Skip to content

Commit

Permalink
Merge pull request #3003 from mattsc/atotb_chase_ai
Browse files Browse the repository at this point in the history
AToTB Chase: add custom AI controlling Muff Toras
  • Loading branch information
mattsc committed May 5, 2018
2 parents 8081114 + fb3697a commit dbddf08
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 1 deletion.
113 changes: 113 additions & 0 deletions data/campaigns/Two_Brothers/lua/muff_toras_move.lua
@@ -0,0 +1,113 @@
local M = wesnoth.map
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local BC = wesnoth.require "ai/lua/battle_calcs.lua"

local muff_toras_move = {}

function muff_toras_move:evaluation()
local muff_toras = wesnoth.get_units { id = 'Muff Toras' }[1]

if muff_toras and (muff_toras.moves > 0) then
return 15000
end

return 0
end

function muff_toras_move:execution()
local muff_toras = wesnoth.get_units { id = 'Muff Toras' }[1]
local units = wesnoth.get_units { side = 3, { 'not', { id = 'Muff Toras' } } }
local enemies = AH.get_attackable_enemies()
local enemy_attack_map = BC.get_attack_map(enemies)

local go_to = AH.find_best_move(muff_toras, function(x, y)
-- Note: we use no_random = false, which adds contribution of up to 0.01.
-- This means all differences between deterministic ratings need to be
-- larger than that

local rating = -10000 -- This is the base rating if no other units are left

-- Main rating is distance from the closest own unit
local min_dist
for _,unit in ipairs(units) do
local dist = M.distance_between(x, y, unit.x, unit.y)
if (not min_dist) or (dist < min_dist) then
min_dist = dist
end
end
if min_dist then rating = -100 * min_dist end

-- Enemy threat is next most important. We could put a scaling factor
-- in front of this, but using 1 seems to work pretty well
local enemy_hp = enemy_attack_map.hitpoints:get(x,y)
if enemy_hp then
rating = rating - enemy_hp
end

-- All else being equal, go with good terrain
local hit_chance = muff_toras:defense(wesnoth.get_terrain(x, y))
rating = rating - hit_chance

-- Finally, we want to run away from enemies if there are no other factors.
-- This mostly kicks in after the other AI units have been killed.
local closest_enemy_dist
for _,enemy in ipairs(enemies) do
local dist = M.distance_between(x, y, enemy.x, enemy.y)
if (not closest_enemy_dist) or (dist < closest_enemy_dist) then
closest_enemy_dist = dist
end
end
rating = rating + closest_enemy_dist

return rating
end)

if ((go_to[1] ~= muff_toras.x) or (go_to[2] ~= muff_toras.y)) then
AH.robust_move_and_attack(ai, muff_toras, go_to)
else
AH.checked_stopunit_moves(ai, muff_toras)
end

-- Test whether an attack without retaliation or with little damage is possible
if (muff_toras.attacks_left <= 0) or (#muff_toras.attacks == 0) then
return
end

local targets = AH.get_attackable_enemies { { "filter_adjacent", { id = muff_toras.id } } }

local max_rating, best_target, best_weapon = -9e99
for _,target in ipairs(targets) do
for n_weapon,weapon in ipairs(muff_toras.attacks) do
local att_stats, def_stats = wesnoth.simulate_combat(muff_toras, n_weapon, target)

local rating = -9e99
-- This is an acceptable attack if:
-- 1. There is no counter attack
-- 2. Probability of death is >=67% for enemy, 0% for attacker (default values)

local enemy_death_chance = 0.67
local muff_toras_death_chance = 0

if (att_stats.hp_chance[muff_toras.hitpoints] == 1)
or (def_stats.hp_chance[0] >= enemy_death_chance) and (att_stats.hp_chance[0] <= muff_toras_death_chance)
then
rating = target.max_hitpoints + def_stats.hp_chance[0] * 100 + att_stats.average_hp - def_stats.average_hp
end

if (rating > max_rating) then
max_rating, best_target, best_weapon = rating, target, n_weapon
end
end
end

if best_target then
AH.checked_attack(ai, muff_toras, best_target, best_weapon)
end
if (not muff_toras) or (not muff_toras.valid) then
return
end

AH.checked_stopunit_attacks(ai, muff_toras)
end

return muff_toras_move
12 changes: 11 additions & 1 deletion data/campaigns/Two_Brothers/scenarios/02_The_Chase.cfg
Expand Up @@ -176,7 +176,7 @@ Besides... I want my brother back."
x,y=9,4

[ai]
leader_ignores_keep=yes
passive_leader=yes
village_value=0

[modify_ai]
Expand Down Expand Up @@ -424,6 +424,16 @@ Besides... I want my brother back."
hidden=no
[/modify_side]

{MODIFY_AI_ADD_CANDIDATE_ACTION 3 main_loop (
[candidate_action]
engine=lua
name=muff_toras_move
id=muff_toras_move
max_score=15000
location="campaigns/Two_Brothers/lua/muff_toras_move.lua"
[/candidate_action]
)}

[remove_shroud]
side=1
x=0-20
Expand Down

0 comments on commit dbddf08

Please sign in to comment.