Lua AIs: use unit methods instead of wesnoth functions

(cherry-picked from commit a6866390df)
This commit is contained in:
mattsc 2018-08-27 07:05:43 -07:00
parent 1ab3ec0464
commit 25b2024ee8
18 changed files with 62 additions and 62 deletions

View file

@ -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
@ -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
@ -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
@ -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)
@ -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]

View file

@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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)
@ -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
@ -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

View file

@ -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()
@ -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

View file

@ -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
@ -199,7 +199,7 @@ 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
@ -207,7 +207,7 @@ return {
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
@ -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 {
@ -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)
@ -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

View file

@ -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])
@ -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)

View file

@ -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
@ -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)
@ -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

View file

@ -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)
@ -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
@ -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
@ -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)

View file

@ -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()

View file

@ -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
@ -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]
@ -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

View file

@ -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
@ -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

View file

@ -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
@ -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

View file

@ -38,7 +38,7 @@ function ca_healer_move:evaluation(cfg, data)
-- Potential healees are units without MP that don't already have a healer (also without MP) next to them
-- Also, they cannot be on a village or regenerate
if (healee.moves == 0) then
if (not wesnoth.match_unit(healee, { ability = "regenerates" })) then
if (not healee:matches { ability = "regenerates" }) then
local is_village = wesnoth.get_terrain_info(wesnoth.get_terrain(healee.x, healee.y)).village
if (not is_village) then
local is_healee = true
@ -57,9 +57,9 @@ function ca_healer_move:evaluation(cfg, data)
end
local enemies = AH.get_attackable_enemies()
for _,healee in ipairs(healees_MP) do wesnoth.extract_unit(healee) end
for _,healee in ipairs(healees_MP) do healee:extract() end
local enemy_attack_map = BC.get_attack_map(enemies)
for _,healee in ipairs(healees_MP) do wesnoth.put_unit(healee) end
for _,healee in ipairs(healees_MP) do healee:to_map() end
local avoid_map = LS.of_pairs(ai.aspects.avoid)
@ -106,7 +106,7 @@ function ca_healer_move:evaluation(cfg, data)
local is_village = wesnoth.get_terrain_info(wesnoth.get_terrain(loc[1], loc[2])).village
if is_village then rating = rating + 2 end
local defense = 100 - wesnoth.unit_defense(healer, wesnoth.get_terrain(loc[1], loc[2]))
local defense = 100 - healer:defense(wesnoth.get_terrain(loc[1], loc[2]))
rating = rating + defense / 10.
end

View file

@ -29,7 +29,7 @@ function ca_herding_sheep_move:execution(cfg)
reach_map:iter( function(x, y, v)
for xa, ya in H.adjacent_tiles(x, y) do
local dog = wesnoth.get_unit(xa, ya)
if dog and (wesnoth.match_unit(dog, dogs_filter)) then
if dog and dog:matches(dogs_filter) then
reach_map:remove(x, y)
end
end

View file

@ -57,21 +57,21 @@ function ca_messenger_move:execution(cfg)
local unit_in_way = wesnoth.get_unit(next_hop[1], next_hop[2])
if (unit_in_way == messenger) then unit_in_way = nil end
if unit_in_way then wesnoth.extract_unit(unit_in_way) end
if unit_in_way then unit_in_way:extract() end
wesnoth.put_unit(messenger, next_hop[1], next_hop[2])
local _, cost1 = AH.find_path_with_shroud(messenger, x, y, { ignore_units = 'yes' })
local unit_in_way2 = wesnoth.get_unit(optimum_hop[1], optimum_hop[2])
if (unit_in_way2 == messenger) then unit_in_way2 = nil end
if unit_in_way2 then wesnoth.extract_unit(unit_in_way2) end
if unit_in_way2 then unit_in_way2:extract() end
wesnoth.put_unit(messenger, optimum_hop[1], optimum_hop[2])
local _, cost2 = AH.find_path_with_shroud(messenger, x, y, { ignore_units = 'yes' })
wesnoth.put_unit(messenger, x_current, y_current)
if unit_in_way then wesnoth.put_unit(unit_in_way) end
if unit_in_way2 then wesnoth.put_unit(unit_in_way2) end
if unit_in_way then unit_in_way:to_map() end
if unit_in_way2 then unit_in_way2:to_map() end
-- If cost2 is significantly less, that means that the optimum path might
-- overall be faster even though it is currently blocked

View file

@ -23,7 +23,7 @@ function ca_protect_unit_move:execution(cfg, data)
-- Need to take the protected units off the map, as they don't count into the map scores
-- as long as they can still move
for _,unit in ipairs(protected_units) do wesnoth.extract_unit(unit) end
for _,unit in ipairs(protected_units) do unit:extract() end
local units = wesnoth.get_units { side = wesnoth.current.side }
local enemy_units = AH.get_attackable_enemies()
@ -32,7 +32,7 @@ function ca_protect_unit_move:execution(cfg, data)
local enemy_attack_map = BC.get_attack_map(enemy_units).units -- enemy attack map
-- Now put the protected units back out there
for _,unit in ipairs(protected_units) do wesnoth.put_unit(unit) end
for _,unit in ipairs(protected_units) do unit:to_map() end
-- We move the weakest (fewest HP unit) first
local unit = AH.choose(protected_units, function(u) return - u.hitpoints end)
@ -46,7 +46,7 @@ function ca_protect_unit_move:execution(cfg, data)
local terrain_defense_map = LS.create()
reach_map:iter(function(x, y, data)
terrain_defense_map:insert(x, y, 100 - wesnoth.unit_defense(unit, wesnoth.get_terrain(x, y)))
terrain_defense_map:insert(x, y, 100 - unit:defense(wesnoth.get_terrain(x, y)))
end)
local goal_distance_map = LS.create()

View file

@ -59,7 +59,7 @@ function ca_stationed_guardian:execution(cfg)
if (not AH.is_visible_unit(wesnoth.current.side, unit_in_way))
or (unit_in_way == guardian)
then
local defense = 100 - wesnoth.unit_defense(guardian, wesnoth.get_terrain(xa, ya))
local defense = 100 - guardian:defense(wesnoth.get_terrain(xa, ya))
local nh = AH.next_hop(guardian, xa, ya)
if nh then
if (nh[1] == xa) and (nh[2] == ya) and (defense > best_defense) then

View file

@ -46,7 +46,7 @@ function ca_zone_guardian:execution(cfg)
if (not AH.is_visible_unit(wesnoth.current.side, unit_in_way))
or (unit_in_way == guardian)
then
local defense = 100 - wesnoth.unit_defense(guardian, wesnoth.get_terrain(xa, ya))
local defense = 100 - guardian:defense(wesnoth.get_terrain(xa, ya))
local nh = AH.next_hop(guardian, xa, ya)
if nh then
if (nh[1] == xa) and (nh[2] == ya) and (defense > best_defense) then

View file

@ -22,7 +22,7 @@ function ca_aggressive_attack_no_suicide:evaluation(cfg, data)
local attacker = wesnoth.get_unit(att.src.x, att.src.y)
local defender = wesnoth.get_unit(att.target.x, att.target.y)
local attacker_dst = wesnoth.copy_unit(attacker)
local attacker_dst = attacker:clone()
attacker_dst.x, attacker_dst.y = att.dst.x, att.dst.y
local att_stats, def_stats = wesnoth.simulate_combat(attacker_dst, defender)