Skip to content

Commit

Permalink
Lua AIs: use unit methods instead of wesnoth functions
Browse files Browse the repository at this point in the history
(cherry-picked from commit a686639)
  • Loading branch information
mattsc committed Oct 7, 2018
1 parent 1ab3ec0 commit 25b2024
Show file tree
Hide file tree
Showing 18 changed files with 62 additions and 62 deletions.
10 changes: 5 additions & 5 deletions data/ai/lua/ai_helper.lua
Expand Up @@ -678,7 +678,7 @@ function ai_helper.get_closest_location(hex, location_filter, unit)

if unit then
for _,loc in ipairs(locs) do
local movecost = wesnoth.unit_movement_cost(unit, wesnoth.get_terrain(loc[1], loc[2]))
local movecost = unit:movement(wesnoth.get_terrain(loc[1], loc[2]))
if (movecost <= unit.max_moves) then return loc end
end
else
Expand Down Expand Up @@ -709,7 +709,7 @@ function ai_helper.get_passable_locations(location_filter, unit)
if unit then
local locs = {}
for _,loc in ipairs(all_locs) do
local movecost = wesnoth.unit_movement_cost(unit, wesnoth.get_terrain(loc[1], loc[2]))
local movecost = unit:movement(wesnoth.get_terrain(loc[1], loc[2]))
if (movecost <= unit.max_moves) then table.insert(locs, loc) end
end
return locs
Expand Down Expand Up @@ -1364,7 +1364,7 @@ function ai_helper.find_path_with_shroud(unit, x, y, cfg)
if (u.side ~= viewing_side)
and (not ai_helper.is_visible_unit(viewing_side, u))
then
wesnoth.extract_unit(u)
u:extract()
table.insert(extracted_units, u)
end
end
Expand All @@ -1376,7 +1376,7 @@ function ai_helper.find_path_with_shroud(unit, x, y, cfg)
path, cost = wesnoth.find_path(unit, x, y, cfg_copy)

for _,extracted_unit in ipairs(extracted_units) do
wesnoth.put_unit(extracted_unit)
extracted_unit:to_map()
end
else
path, cost = wesnoth.find_path(unit, x, y, cfg)
Expand Down Expand Up @@ -1665,7 +1665,7 @@ function ai_helper.get_attacks(units, cfg)
for _,target in ipairs(attack_hex_map:get(loc[1], loc[2])) do
local att_stats, def_stats
if cfg.simulate_combat then
local unit_dst = wesnoth.copy_unit(unit)
local unit_dst = unit:clone()
unit_dst.x, unit_dst.y = loc[1], loc[2]

local enemy = all_units[target.i]
Expand Down
22 changes: 11 additions & 11 deletions data/ai/lua/battle_calcs.lua
Expand Up @@ -76,7 +76,7 @@ function battle_calcs.unit_attack_info(unit, cache)

local attack_types = { "arcane", "blade", "cold", "fire", "impact", "pierce" }
for _,attack_type in ipairs(attack_types) do
unit_info.resist_mod[attack_type] = wesnoth.unit_resistance(unit, attack_type) / 100.
unit_info.resist_mod[attack_type] = unit:resistance(attack_type) / 100.
end

if cache then cache[cind] = unit_info end
Expand Down Expand Up @@ -680,8 +680,8 @@ function battle_calcs.battle_outcome(attacker, defender, cfg, cache)
if (def_max_hits > att_strikes) then def_max_hits = att_strikes end

-- Probability of landing a hit
local att_hit_prob = wesnoth.unit_defense(defender, wesnoth.get_terrain(defender.x, defender.y)) / 100.
local def_hit_prob = wesnoth.unit_defense(attacker, wesnoth.get_terrain(dst[1], dst[2])) / 100.
local att_hit_prob = defender:defense(wesnoth.get_terrain(defender.x, defender.y)) / 100.
local def_hit_prob = attacker:defense(wesnoth.get_terrain(dst[1], dst[2])) / 100.

-- Magical: attack and defense, and under all circumstances
if att_attack.magical then att_hit_prob = 0.7 end
Expand Down Expand Up @@ -731,7 +731,7 @@ function battle_calcs.simulate_combat_loc(attacker, dst, defender, weapon)
-- when on terrain of same type as that at @dst, which is of form { x, y }
-- If @weapon is set, use that weapon (Lua index starting at 1), otherwise use best weapon

local attacker_dst = wesnoth.copy_unit(attacker)
local attacker_dst = attacker:clone()
attacker_dst.x, attacker_dst.y = dst[1], dst[2]

if weapon then
Expand Down Expand Up @@ -932,7 +932,7 @@ function battle_calcs.attack_rating(attacker, defender, dst, cfg, cache)
-- We don't need a bonus for good terrain for the attacker, as that is covered in the damage calculation
-- However, we add a small bonus for good terrain defense of the _defender_ on the _attack_ hex
-- This is in order to take good terrain away from defender on next move, all else being equal
local defender_defense = - wesnoth.unit_defense(defender, wesnoth.get_terrain(dst[1], dst[2])) / 100.
local defender_defense = - defender:defense(wesnoth.get_terrain(dst[1], dst[2])) / 100.
defender_value = defender_value + defender_defense * defense_weight

-- Get a very small bonus for hexes in between defender and AI leader
Expand Down Expand Up @@ -1173,7 +1173,7 @@ function battle_calcs.get_attack_map_unit(unit, cfg)
for _,unit in ipairs(all_units) do
if (unit.moves > 0) then
table.insert(units_MP, unit)
wesnoth.extract_unit(unit)
unit:extract()
end
end
end
Expand All @@ -1183,7 +1183,7 @@ function battle_calcs.get_attack_map_unit(unit, cfg)

-- Put the units back out there
if (unit.side ~= wesnoth.current.side) then
for _,uMP in ipairs(units_MP) do wesnoth.put_unit(uMP) end
for _,uMP in ipairs(units_MP) do uMP:to_map() end
end

for _,loc in ipairs(initial_reach) do
Expand Down Expand Up @@ -1312,7 +1312,7 @@ function battle_calcs.best_defense_map(units, cfg)
local defense_map = LS.create()

if cfg.ignore_these_units then
for _,unit in ipairs(cfg.ignore_these_units) do wesnoth.extract_unit(unit) end
for _,unit in ipairs(cfg.ignore_these_units) do unit:extract() end
end

for _,unit in ipairs(units) do
Expand All @@ -1326,7 +1326,7 @@ function battle_calcs.best_defense_map(units, cfg)
if max_moves then unit.moves = old_moves end

for _,loc in ipairs(reach) do
local defense = 100 - wesnoth.unit_defense(unit, wesnoth.get_terrain(loc[1], loc[2]))
local defense = 100 - unit:defense(wesnoth.get_terrain(loc[1], loc[2]))

if (defense > (defense_map:get(loc[1], loc[2]) or -9e99)) then
defense_map:insert(loc[1], loc[2], defense)
Expand All @@ -1335,7 +1335,7 @@ function battle_calcs.best_defense_map(units, cfg)
end

if cfg.ignore_these_units then
for _,unit in ipairs(cfg.ignore_these_units) do wesnoth.put_unit(unit) end
for _,unit in ipairs(cfg.ignore_these_units) do unit:to_map() end
end

return defense_map
Expand Down Expand Up @@ -1534,7 +1534,7 @@ function battle_calcs.get_attack_combos_subset(units, enemy, cfg)
-- Store information about it in 'loc' and add this to 'locs'
-- Want coordinates (dst) and terrain defense (for sorting)
loc.dst = xa * 1000 + ya
loc.hit_prob = wesnoth.unit_defense(unit, wesnoth.get_terrain(xa, ya))
loc.hit_prob = unit:defense(wesnoth.get_terrain(xa, ya))
table.insert(locs, loc)

-- Also mark this hex as usable
Expand Down
4 changes: 2 additions & 2 deletions data/ai/lua/ca_high_xp_attack.lua
Expand Up @@ -82,7 +82,7 @@ function ca_attack_highxp:evaluation(cfg, data)
if (not target_infos[1]) then return 0 end

-- The following location sets are used so that we at most need to call
-- find_reach() and wesnoth.copy_unit() once per unit
-- find_reach() and unit:clone() once per unit
local reaches = LS.create()
local attacker_copies = LS.create()

Expand Down Expand Up @@ -217,7 +217,7 @@ function ca_attack_highxp:evaluation(cfg, data)
if attacker_copies:get(attacker.x, attacker.y) then
attacker_copy = attacker_copies:get(attacker.x, attacker.y)
else
attacker_copy = wesnoth.copy_unit(attacker)
attacker_copy = attacker:clone()
attacker_copies:insert(attacker.x, attacker.y, attacker_copy)
end

Expand Down
18 changes: 9 additions & 9 deletions data/ai/lua/generic_recruit_engine.lua
Expand Up @@ -91,7 +91,7 @@ return {
local best_defense = 100

for i, terrain in ipairs(terrain_archetypes) do
local defense = wesnoth.unit_defense(unit, terrain)
local defense = unit:defense(terrain)
if defense < best_defense then
best_defense = defense
end
Expand Down Expand Up @@ -199,15 +199,15 @@ return {
if wml.get_child(special, 'drains') and drainable(attacker) then
-- TODO: calculate chance to hit
-- currently assumes 50% chance to hit using supplied constant
local attacker_resistance = wesnoth.unit_resistance(attacker, defender_attack.type)
local attacker_resistance = attacker:resistance(defender_attack.type)
drain_recovery = (defender_attack.damage*defender_attack.number*attacker_resistance*attacker_defense/2)/10000
end
end
end
end

defense = defense/100.0
local resistance = wesnoth.unit_resistance(defender, attack.type)
local resistance = defender:resistance(attack.type)
if steadfast and (resistance < 100) then
resistance = 100 - ((100 - resistance) * 2)
if (resistance < 50) then
Expand Down Expand Up @@ -260,8 +260,8 @@ return {
name = "X",
random_gender = false
}
local can_poison = poisonable(unit) and (not wesnoth.unit_ability(unit, 'regenerate'))
local flat_defense = wesnoth.unit_defense(unit, "Gt")
local can_poison = poisonable(unit) and (not unit:ability('regenerate'))
local flat_defense = unit:defense("Gt")
local best_defense = get_best_defense(unit)

local recruit = wesnoth.create_unit {
Expand All @@ -270,10 +270,10 @@ return {
name = "X",
random_gender = false
}
local recruit_flat_defense = wesnoth.unit_defense(recruit, "Gt")
local recruit_flat_defense = recruit:defense("Gt")
local recruit_best_defense = get_best_defense(recruit)

local can_poison_retaliation = poisonable(recruit) and (not wesnoth.unit_ability(recruit, 'regenerate'))
local can_poison_retaliation = poisonable(recruit) and (not recruit:ability('regenerate'))
best_flat_attack, best_flat_damage, flat_poison = get_best_attack(recruit, unit, flat_defense, recruit_best_defense, can_poison)
best_high_defense_attack, best_high_defense_damage, high_defense_poison = get_best_attack(recruit, unit, best_defense, recruit_flat_defense, can_poison)
best_retaliation, best_retaliation_damage, retaliation_poison = get_best_attack(unit, recruit, recruit_flat_defense, best_defense, can_poison_retaliation)
Expand Down Expand Up @@ -767,10 +767,10 @@ return {
if can_slow(recruit_unit) then
unit_score["slows"] = true
end
if wesnoth.match_unit(recruit_unit, { ability = "healing" }) then
if recruit_unit:matches { ability = "healing" } then
unit_score["heals"] = true
end
if wesnoth.match_unit(recruit_unit, { ability = "skirmisher" }) then
if recruit_unit:matches { ability = "skirmisher" } then
unit_score["skirmisher"] = true
end
recruitable_units[recruit_id] = recruit_unit
Expand Down
8 changes: 4 additions & 4 deletions data/ai/lua/generic_rush_engine.lua
Expand Up @@ -199,7 +199,7 @@ return {
for i,loc in ipairs(close_villages) do
local path_village, cost_village = wesnoth.find_path(leader, loc[1], loc[2])
if cost_village <= leader.moves then
local dummy_leader = wesnoth.copy_unit(leader)
local dummy_leader = leader:clone()
dummy_leader.x = loc[1]
dummy_leader.y = loc[2]
local path_keep, cost_keep = wesnoth.find_path(dummy_leader, best_loc[1], best_loc[2])
Expand Down Expand Up @@ -454,14 +454,14 @@ return {
if defender.canrecruit then rating = rating + 1000 end

-- Enemies that can regenerate are not good targets
if wesnoth.unit_ability(defender, 'regenerate') then rating = rating - 1000 end
if defender:ability('regenerate') then rating = rating - 1000 end

-- More priority to enemies on strong terrain
local defender_defense = 100 - wesnoth.unit_defense(defender, wesnoth.get_terrain(defender.x, defender.y))
local defender_defense = 100 - defender:defense(wesnoth.get_terrain(defender.x, defender.y))
rating = rating + defender_defense / 4.

-- For the same attacker/defender pair, go to strongest terrain
local attack_defense = 100 - wesnoth.unit_defense(attacker, wesnoth.get_terrain(a.dst.x, a.dst.y))
local attack_defense = 100 - attacker:defense(wesnoth.get_terrain(a.dst.x, a.dst.y))
rating = rating + attack_defense / 2.
--print('rating', rating)

Expand Down
6 changes: 3 additions & 3 deletions data/ai/lua/retreat.lua
Expand Up @@ -12,7 +12,7 @@ local retreat_functions = {}
function retreat_functions.min_hp(unit)
-- The minimum hp to retreat is a function of level and terrain defense
-- We want to stay longer on good terrain and leave early on very bad terrain
local hp_per_level = wesnoth.unit_defense(unit, wesnoth.get_terrain(unit.x, unit.y))/15
local hp_per_level = unit:defense(wesnoth.get_terrain(unit.x, unit.y))/15
local level = unit.level

-- Leaders are considered to be higher level because of their value
Expand All @@ -38,7 +38,7 @@ function retreat_functions.retreat_injured_units(units)
local regen, non_regen = {}, {}
for i,u in ipairs(units) do
if u.hitpoints < retreat_functions.min_hp(u) then
if wesnoth.unit_ability(u, 'regenerate') then
if u:ability('regenerate') then
table.insert(regen, u)
else
table.insert(non_regen, u)
Expand Down Expand Up @@ -176,7 +176,7 @@ function retreat_functions.get_retreat_injured_units(healees, regenerates)
rating = rating - enemy_count * 100000

-- Penalty based on terrain defense for unit
rating = rating - wesnoth.unit_defense(u, wesnoth.get_terrain(loc[1], loc[2]))/10
rating = rating - u:defense(wesnoth.get_terrain(loc[1], loc[2]))/10

if (loc[1] == u.x) and (loc[2] == u.y) and (not u.status.poisoned) then
if enemy_count == 0 then
Expand Down
8 changes: 4 additions & 4 deletions data/ai/micro_ais/cas/ca_assassin_move.lua
Expand Up @@ -25,7 +25,7 @@ local function custom_cost(x, y, unit, enemy_rating_map, prefer_map)
-- must return values >=1 for the a* search to work.

local terrain = wesnoth.get_terrain(x, y)
local move_cost = wesnoth.unit_movement_cost(unit, terrain)
local move_cost = unit:movement(terrain)

move_cost = move_cost + (enemy_rating_map:get(x, y) or 0)

Expand Down Expand Up @@ -66,7 +66,7 @@ function ca_assassin_move:execution(cfg)
if (not enemy.status.petrified) then
-- Need to "move" enemy next to unit for attack calculation
-- Do this with a unit copy, so that no actual unit has to be moved
local enemy_copy = wesnoth.copy_unit(enemy)
local enemy_copy = enemy:clone()

-- First get the reach of the enemy with full moves though
enemy_copy.moves = enemy_copy.max_moves
Expand Down Expand Up @@ -95,7 +95,7 @@ function ca_assassin_move:execution(cfg)
-- Penalties for damage by enemies
local enemy_rating_map = LS.create()
enemy_damage_map:iter(function(x, y, enemy_damage)
local hit_chance = (wesnoth.unit_defense(unit, wesnoth.get_terrain(x, y))) / 100.
local hit_chance = (unit:defense(wesnoth.get_terrain(x, y))) / 100.

local rating = hit_chance * enemy_damage
rating = rating / unit.max_hitpoints
Expand All @@ -105,7 +105,7 @@ function ca_assassin_move:execution(cfg)
end)

-- Penalties for blocked hexes and ZOC
local is_skirmisher = wesnoth.unit_ability(unit, "skirmisher")
local is_skirmisher = unit:ability("skirmisher")
for _,enemy in ipairs(enemies) do
-- Hexes an enemy is on get a very large penalty
enemy_rating_map:insert(enemy.x, enemy.y, (enemy_rating_map:get(enemy.x, enemy.y) or 0) + 100)
Expand Down
2 changes: 1 addition & 1 deletion data/ai/micro_ais/cas/ca_bottleneck_move.lua
Expand Up @@ -14,7 +14,7 @@ local function bottleneck_is_my_territory(map, enemy_map)
-- If there is no leader, use first unit found
local unit = wesnoth.get_units { side = wesnoth.current.side, canrecruit = 'yes' }[1]
if (not unit) then unit = wesnoth.get_units { side = wesnoth.current.side }[1] end
local dummy_unit = wesnoth.copy_unit(unit)
local dummy_unit = unit:clone()

local territory_map = LS.create()
local width, height = wesnoth.get_map_size()
Expand Down
6 changes: 3 additions & 3 deletions data/ai/micro_ais/cas/ca_fast_attack_utils.lua
Expand Up @@ -164,7 +164,7 @@ function ca_fast_attack_utils.single_unit_info(unit_proxy)
local attack_types = { "arcane", "blade", "cold", "fire", "impact", "pierce" }
single_unit_info.resistances = {}
for _,attack_type in ipairs(attack_types) do
single_unit_info.resistances[attack_type] = wesnoth.unit_resistance(unit_proxy, attack_type) / 100.
single_unit_info.resistances[attack_type] = unit_proxy:resistance(attack_type) / 100.
end

return single_unit_info
Expand All @@ -187,7 +187,7 @@ function ca_fast_attack_utils.get_unit_copy(id, gamedata)

if (not gamedata.unit_copies[id]) then
local unit_proxy = wesnoth.get_units { id = id }[1]
gamedata.unit_copies[id] = wesnoth.copy_unit(unit_proxy)
gamedata.unit_copies[id] = unit_proxy:clone()
end

return gamedata.unit_copies[id]
Expand All @@ -209,7 +209,7 @@ function ca_fast_attack_utils.get_unit_defense(unit_copy, x, y, defense_maps)
if (not defense_maps[unit_copy.id][x]) then defense_maps[unit_copy.id][x] = {} end

if (not defense_maps[unit_copy.id][x][y]) then
local defense = (100. - wesnoth.unit_defense(unit_copy, wesnoth.get_terrain(x, y))) / 100.
local defense = (100. - unit_copy:defense(wesnoth.get_terrain(x, y))) / 100.
defense_maps[unit_copy.id][x][y] = { defense = defense }
end

Expand Down
4 changes: 2 additions & 2 deletions data/ai/micro_ais/cas/ca_fast_move.lua
Expand Up @@ -243,7 +243,7 @@ function ca_fast_move:execution(cfg)
if cfg.dungeon_mode then
table.sort(pre_ratings, function(a,b) return (a.rating > b.rating) end)

wesnoth.extract_unit(unit)
unit:extract()
local old_x, old_y = unit.x, unit.y

local max_rating = -9e99
Expand All @@ -264,7 +264,7 @@ function ca_fast_move:execution(cfg)
end

unit.x, unit.y = old_x, old_y
wesnoth.put_unit(unit)
unit:to_map()
end

if best_hex then
Expand Down
6 changes: 3 additions & 3 deletions data/ai/micro_ais/cas/ca_goto.lua
Expand Up @@ -8,7 +8,7 @@ local M = wesnoth.map

local function custom_cost(x, y, unit, enemy_map, enemy_attack_map, multiplier)
local terrain = wesnoth.get_terrain(x, y)
local move_cost = wesnoth.unit_movement_cost(unit, terrain)
local move_cost = unit:movement(terrain)

move_cost = move_cost + (enemy_map:get(x,y) or 0)
move_cost = move_cost + (enemy_attack_map.units:get(x,y) or 0) * multiplier
Expand Down Expand Up @@ -149,14 +149,14 @@ function ca_goto:execution(cfg, data)
if cfg.ignore_enemy_at_goal then
enemy_at_goal = wesnoth.get_unit(loc[1], loc[2])
if enemy_at_goal and wesnoth.is_enemy(wesnoth.current.side, enemy_at_goal.side) then
wesnoth.extract_unit(enemy_at_goal)
enemy_at_goal:extract()
else
enemy_at_goal = nil
end
end
path, cost = AH.find_path_with_shroud(unit, loc[1], loc[2], { ignore_units = cfg.ignore_units })
if enemy_at_goal then
wesnoth.put_unit(enemy_at_goal)
enemy_at_goal:to_map()
--- Give massive penalty for this goal hex
cost = cost + 100
end
Expand Down

0 comments on commit 25b2024

Please sign in to comment.