Micro AIs: add check for valid stopunit execution and error message

This now checks whether the stopunit execution intended to be done with
ai.stopunit_all, ai.stopunit_attacks or ai.stopunit_moves is possible
and displays an error message if it is not.
This commit is contained in:
mattsc 2014-02-27 10:53:26 -08:00
parent f0506b2d31
commit 835194eee4
17 changed files with 57 additions and 24 deletions

View file

@ -173,6 +173,39 @@ function ai_helper.checked_move(ai, unit, x, y)
ai_helper.checked_move_core(ai, unit, x, y, 'ai.move')
end
function ai_helper.checked_stopunit_all(ai, unit)
local check = ai.check_stopunit(unit)
if (not check.ok) then
ai_helper.checked_action_error('ai.stopunit_all', check.status)
return
end
ai.stopunit_all(unit)
end
function ai_helper.checked_stopunit_attacks(ai, unit)
local check = ai.check_stopunit(unit)
if (not check.ok) then
ai_helper.checked_action_error('ai.stopunit_attacks', check.status)
return
end
ai.stopunit_attacks(unit)
end
function ai_helper.checked_stopunit_moves(ai, unit)
local check = ai.check_stopunit(unit)
if (not check.ok) then
ai_helper.checked_action_error('ai.stopunit_moves', check.status)
return
end
ai.stopunit_moves(unit)
end
----- General functionality and maths helper functions ------
function ai_helper.filter(input, condition)
@ -1073,7 +1106,7 @@ function ai_helper.movefull_stopunit(ai, unit, x, y)
if next_hop and ((next_hop[1] ~= unit.x) or (next_hop[2] ~= unit.y)) then
ai_helper.checked_move_full(ai, unit, next_hop[1], next_hop[2])
else
ai.stopunit_moves(unit)
ai_helper.checked_stopunit_moves(ai, unit)
end
end
@ -1102,7 +1135,7 @@ function ai_helper.movefull_outofway_stopunit(ai, unit, x, y, cfg)
if next_hop and ((next_hop[1] ~= unit.x) or (next_hop[2] ~= unit.y)) then
ai_helper.checked_move_full(ai, unit, next_hop[1], next_hop[2])
else
ai.stopunit_moves(unit)
ai_helper.checked_stopunit_moves(ai, unit)
end
end

View file

@ -84,7 +84,7 @@ function ca_big_animals:execution(ai, cfg)
if (best_hex[1] ~= unit.x) or (best_hex[2] ~= unit.y) then
AH.checked_move(ai, unit, best_hex[1], best_hex[2]) -- partial move only
else -- If animal did not move, we need to stop it (also delete the goal)
ai.stopunit_moves(unit)
AH.checked_stopunit_moves(ai, unit)
unit.variables.goal_x = nil
unit.variables.goal_y = nil
end

View file

@ -72,7 +72,7 @@ function ca_bottleneck_attack:execution(ai, cfg, self)
if self.data.bottleneck_attacks_done then
local units = wesnoth.get_units { side = wesnoth.current.side, formula = '$this_unit.attacks_left > 0' }
for i,u in ipairs(units) do
ai.stopunit_attacks(u)
AH.checked_stopunit_attacks(ai, u)
end
else
AH.checked_attack(ai, self.data.attacker, self.data.target, self.data.weapon)

View file

@ -491,7 +491,7 @@ function ca_bottleneck_move:execution(ai, cfg, self)
}
end
for i,u in ipairs(units) do
ai.stopunit_moves(u)
AH.checked_stopunit_moves(ai, u)
end
else
--print("Moving unit:",self.data.unit.id, self.data.unit.x, self.data.unit.y, " ->", best_hex[1], best_hex[2], " -- turn:", wesnoth.current.turn)

View file

@ -45,7 +45,7 @@ function ca_coward:execution(ai, cfg)
-- if no enemies are within reach: keep unit from doing anything and exit
if not enemies[1] then
ai.stopunit_all(unit)
AH.checked_stopunit_all(ai, unit)
return
end
@ -119,7 +119,7 @@ function ca_coward:execution(ai, cfg)
-- Get unit again, just in case it was killed by a moveto event
local unit = wesnoth.get_units{ id = cfg.id }[1]
if unit then ai.stopunit_all(unit) end
if unit then AH.checked_stopunit_all(ai, unit) end
end
return ca_coward

View file

@ -163,7 +163,7 @@ function ca_forest_animals_move:execution(ai, cfg)
-- Finally, take moves away, as only partial move might have been done
-- Also attacks, as these units never attack
if unit and unit.valid then ai.stopunit_all(unit) end
if unit and unit.valid then AH.checked_stopunit_all(ai, unit) end
-- Need this ^ test here because bunnies might have disappeared
end
end

View file

@ -61,7 +61,7 @@ function ca_forest_animals_tusker_attack:execution(ai, cfg)
if (dist == 1) then
AH.checked_attack(ai, attacker, target)
else
ai.stopunit_attacks(attacker)
AH.checked_stopunit_attacks(ai, attacker)
end
end

View file

@ -41,7 +41,7 @@ function ca_forest_animals_tusklet_move:execution(ai, cfg)
AH.movefull_stopunit(ai, tusklet, best_hex)
-- Also make sure tusklets never attack
ai.stopunit_all(tusklet)
AH.checked_stopunit_all(ai, tusklet)
end
end

View file

@ -204,7 +204,7 @@ function ca_goto:execution(ai, cfg, self)
if closest_hex then
AH.checked_move_full(ai, best_unit, closest_hex[1], closest_hex[2])
else
ai.stopunit_moves(best_unit)
AH.checked_stopunit_moves(ai, best_unit)
end
-- If release_unit_at_goal= or release_all_units_at_goal= key is set:

View file

@ -126,7 +126,7 @@ function ca_hang_out:execution(ai, cfg, self)
-- respective best locations already, we take moves away from all units
if (max_rating == -9e99) then
for i,u in ipairs(units) do
ai.stopunit_moves(u)
AH.checked_stopunit_moves(ai, u)
-- Also remove the markers
u.variables.mai_hangout_moved = nil
end

View file

@ -83,7 +83,7 @@ function ca_herding_herd_sheep:execution(ai, cfg)
-- If it's already in the best position, we just take moves away from it
-- (to avoid black-listing of CA, in the worst case)
if (best_hex[1] == best_dog.x) and (best_hex[2] == best_dog.y) then
ai.stopunit_moves(best_dog)
AH.checked_stopunit_moves(ai, best_dog)
else
--print('Dog moving to herd sheep')
AH.checked_move(ai, best_dog, best_hex[1], best_hex[2]) -- partial move only

View file

@ -115,7 +115,7 @@ function ca_hunter:execution(ai, cfg)
if (best_hex[1] ~= unit.x) or (best_hex[2] ~= unit.y) then
AH.checked_move(ai, unit, best_hex[1], best_hex[2]) -- partial move only
else -- If hunter did not move, we need to stop it (also delete the goal)
ai.stopunit_moves(unit)
AH.checked_stopunit_moves(ai, unit)
unit.variables.goal_x, unit.variables.goal_y = nil, nil
end
@ -181,7 +181,7 @@ function ca_hunter:execution(ai, cfg)
-- If we got here, the only remaining action is resting
if (unit.variables.hunting_status == 'resting') then
-- So all we need to do is take moves away from the unit
ai.stopunit_moves(unit)
AH.checked_stopunit_moves(ai, unit)
-- However, we do also attack the weakest adjacent enemy, if still possible
hunter_attack_weakest_adj_enemy(ai, unit)

View file

@ -93,7 +93,7 @@ function ca_lurkers:execution(ai, cfg)
end
-- If the unit has moves or attacks left at this point, take them away
if me and me.valid then ai.stopunit_all(me) end
if me and me.valid then AH.checked_stopunit_all(ai, me) end
end
return ca_lurkers

View file

@ -60,7 +60,7 @@ function ca_messenger_move:execution(ai, cfg, self)
if next_hop and ((next_hop[1] ~= messenger.x) or (next_hop[2] ~= messenger.y)) then
AH.checked_move(ai, messenger, next_hop[1], next_hop[2])
else
ai.stopunit_moves(messenger)
AH.checked_stopunit_moves(ai, messenger)
end
-- We also test whether an attack without retaliation or with little damage is possible
@ -118,7 +118,7 @@ function ca_messenger_move:execution(ai, cfg, self)
end
-- Finally, make sure unit is really done after this
ai.stopunit_attacks(messenger)
AH.checked_stopunit_attacks(ai, messenger)
end
return ca_messenger_move

View file

@ -114,14 +114,14 @@ function ca_patrol:execution(ai, cfg, self)
if cfg.one_time_only and
(patrol.x == waypoints[n_wp][1]) and (patrol.y == waypoints[n_wp][2])
then
ai.stopunit_moves(patrol)
AH.checked_stopunit_moves(ai, patrol)
else -- otherwise move toward next WP
local x, y = wesnoth.find_vacant_tile(self.data[patrol.id..'_x'], self.data[patrol.id..'_y'], patrol)
local nh = AH.next_hop(patrol, x, y)
if nh and ((nh[1] ~= patrol.x) or (nh[2] ~= patrol.y)) then
AH.checked_move(ai, patrol, nh[1], nh[2])
else
ai.stopunit_moves(patrol)
AH.checked_stopunit_moves(ai, patrol)
end
end
end
@ -154,7 +154,7 @@ function ca_patrol:execution(ai, cfg, self)
end
-- Check that patrol is not killed
if patrol and patrol.valid then ai.stopunit_all(patrol) end
if patrol and patrol.valid then AH.checked_stopunit_all(ai, patrol) end
end
return ca_patrol

View file

@ -44,7 +44,7 @@ function ca_stationed_guardian:execution(ai, cfg)
-- if no enemies are within 'distance': keep unit from doing anything and exit
if not enemies[1] then
--print("No enemies close -> sleeping:",unit.id)
ai.stopunit_moves(unit)
AH.checked_stopunit_moves(ai, unit)
return
end
@ -127,7 +127,7 @@ function ca_stationed_guardian:execution(ai, cfg)
-- Get unit again, just in case something was done to it in a 'moveto' or 'attack' event
local unit = wesnoth.get_units{ id = cfg.id }[1]
if unit then ai.stopunit_moves(unit) end
if unit then AH.checked_stopunit_moves(ai, unit) end
-- If there are attacks left and unit ended up next to an enemy, we'll leave this to RCA AI
end

View file

@ -156,7 +156,7 @@ function ca_zone_guardian:execution(ai, cfg)
-- Get unit again, just in case something was done to it in a 'moveto' or 'attack' event
local unit = wesnoth.get_units{ id = cfg.id }[1]
if unit then ai.stopunit_moves(unit) end
if unit then AH.checked_stopunit_moves(ai, unit) end
-- If there are attacks left and unit ended up next to an enemy, we'll leave this to RCA AI
end