TRoW S15: add new attack and retreat AI candidate actions

The attack CA is very aggressive and almost exclusively tries to deal
maximum damage, but will not execute an attack if therre's a chance of
dying for the attacker.  The retreat CA is the same as that used in the
Experimental AI.
This commit is contained in:
mattsc 2013-12-26 11:48:18 -08:00
parent 74929fb284
commit 99bd9dce7b
3 changed files with 162 additions and 13 deletions

View file

@ -0,0 +1,67 @@
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local ca_aggressive_attack_no_suicide = {}
function ca_aggressive_attack_no_suicide:evaluation(ai, cfg, self)
local units = wesnoth.get_units {
side = wesnoth.current.side,
formula = '$this_unit.attacks_left > 0'
}
--print('#units', #units)
if (not units[1]) then return 0 end
-- Get all possible attacks
local attacks = AH.get_attacks(units, { include_occupied = true })
--print('#attacks', #attacks)
if (not attacks[1]) then return 0 end
-- Now find the best of the possible attacks
local max_rating, best_attack = -9e99, {}
for i, att in ipairs(attacks) do
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)
attacker_dst.x, attacker_dst.y = att.dst.x, att.dst.y
local att_stats, def_stats = wesnoth.simulate_combat(attacker_dst, defender)
if (att_stats.hp_chance[0] == 0) then
local rating = def_stats.hp_chance[0] * 100
local attacker_damage = attacker.hitpoints - att_stats.average_hp
local defender_damage = defender.hitpoints - def_stats.average_hp
rating = rating + defender_damage
rating = rating - attacker_damage / 10.
-- Also, take strongest unit first
rating = rating + attacker.hitpoints / 10.
--print('rating:', rating, attacker.id, defender.id)
if (rating > max_rating) then
max_rating = rating
best_attack = att
end
end
end
if (max_rating > -9e99) then
self.data.attack = best_attack
return 100000
end
return 0
end
function ca_aggressive_attack_no_suicide:execution(ai, cfg, self)
local attacker = wesnoth.get_unit(self.data.attack.src.x, self.data.attack.src.y)
local defender = wesnoth.get_unit(self.data.attack.target.x, self.data.attack.target.y)
AH.movefull_outofway_stopunit(ai, attacker, self.data.attack.dst.x, self.data.attack.dst.y)
ai.attack(attacker, defender)
self.data.attack = nil
end
return ca_aggressive_attack_no_suicide

View file

@ -0,0 +1,31 @@
local R = wesnoth.require "ai/lua/retreat.lua"
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local retreat = {}
function retreat:evaluation(ai, cfg, self)
local units = wesnoth.get_units {
side = wesnoth.current.side,
formula = '$this_unit.moves > 0'
}
--print('#units', #units)
if (not units[1]) then return 0 end
local unit, dst, enemy_threat = R.retreat_injured_units(units)
if unit then
self.data.retreat_unit = unit
self.data.retreat_dst = dst
return 101000
end
return 0
end
function retreat:execution(ai, cfg, self)
AH.movefull_outofway_stopunit(ai, self.data.retreat_unit, self.data.retreat_dst[1], self.data.retreat_dst[2])
self.data.retreat_unit, self.data.retreat_dst = nil, nil
end
return retreat

View file

@ -52,10 +52,27 @@
recruit=Elvish Archer, Elvish Fighter, Elvish Scout, Elvish Shaman, Elvish Hero, Elvish Marksman, Elvish Druid
[ai]
{NO_SCOUTS}
recruitment_ignore_bad_movement=yes
recruitment_pattern=scout,fighter,archer,fighter, archer, healer
aggression=1.0
caution=0.0
recruitment_pattern=fighter,archer,fighter,archer,healer
{MODIFY_AI_ADD_CANDIDATE_ACTION 2 main_loop (
[candidate_action]
engine=lua
name=retreat
id=retreat
max_score=101000
location="campaigns/The_Rise_Of_Wesnoth/ai/ca_retreat.lua"
[/candidate_action]
)}
{MODIFY_AI_ADD_CANDIDATE_ACTION 2 main_loop (
[candidate_action]
engine=lua
name=aggressive_attack_no_suicide
id=aggressive_attack_no_suicide
max_score=100000
location="campaigns/The_Rise_Of_Wesnoth/ai/ca_aggressive_attack_no_suicide.lua"
[/candidate_action]
)}
{MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop combat}
[/ai]
{FLAG_VARIANT wood-elvish}
[/side]
@ -79,10 +96,27 @@
recruit=Dwarvish Fighter, Dwarvish Thunderer, Dwarvish Guardsman, Dwarvish Steelclad, Dwarvish Thunderguard
[ai]
{NO_SCOUTS}
recruitment_ignore_bad_movement=yes
recruitment_pattern=fighter,fighter,fighter,mixed fighter
aggression=1.0
caution=0.0
recruitment_pattern=fighter,archer,fighter,archer,healer
{MODIFY_AI_ADD_CANDIDATE_ACTION 2 main_loop (
[candidate_action]
engine=lua
name=retreat
id=retreat
max_score=101000
location="campaigns/The_Rise_Of_Wesnoth/ai/ca_retreat.lua"
[/candidate_action]
)}
{MODIFY_AI_ADD_CANDIDATE_ACTION 2 main_loop (
[candidate_action]
engine=lua
name=aggressive_attack_no_suicide
id=aggressive_attack_no_suicide
max_score=100000
location="campaigns/The_Rise_Of_Wesnoth/ai/ca_aggressive_attack_no_suicide.lua"
[/candidate_action]
)}
{MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop combat}
[/ai]
{FLAG_VARIANT knalgan}
[/side]
@ -105,10 +139,27 @@
recruit=Elvish Archer, Elvish Fighter, Elvish Scout, Elvish Shaman
[ai]
{NO_SCOUTS}
recruitment_ignore_bad_movement=yes
recruitment_pattern=scout,fighter,archer,fighter, archer, healer
aggression=1.0
caution=0.0
recruitment_pattern=fighter,archer,fighter,archer,healer
{MODIFY_AI_ADD_CANDIDATE_ACTION 2 main_loop (
[candidate_action]
engine=lua
name=retreat
id=retreat
max_score=101000
location="campaigns/The_Rise_Of_Wesnoth/ai/ca_retreat.lua"
[/candidate_action]
)}
{MODIFY_AI_ADD_CANDIDATE_ACTION 2 main_loop (
[candidate_action]
engine=lua
name=aggressive_attack_no_suicide
id=aggressive_attack_no_suicide
max_score=100000
location="campaigns/The_Rise_Of_Wesnoth/ai/ca_aggressive_attack_no_suicide.lua"
[/candidate_action]
)}
{MODIFY_AI_DELETE_CANDIDATE_ACTION 2 main_loop combat}
[/ai]
{FLAG_VARIANT long}
[/side]
@ -465,7 +516,7 @@ _"Notes:"+"</big></span>"
{NEW_GOLD_CARRYOVER $anl_carryover}
next_scenario=16_The_Kalian
[/endlevel]
{CLEAR_VARIABLE anl_carryover}
[/event]
[/scenario]