Micro AIs: use the new functions for storing information in units
… such that it is done in a consistent way and this information can be removed on MAI deletion.
This commit is contained in:
parent
a4ee966d06
commit
49cc3bc7f9
9 changed files with 105 additions and 74 deletions
|
@ -1,6 +1,7 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local LS = wesnoth.require "lua/location_set.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
local ca_big_animals = {}
|
||||
|
||||
|
@ -33,15 +34,18 @@ function ca_big_animals:execution(ai, cfg)
|
|||
--AH.put_labels(avoid)
|
||||
|
||||
for i,unit in ipairs(units) do
|
||||
local goal = MAIUV.get_mai_unit_variables(unit, cfg.ai_id)
|
||||
|
||||
-- Unit gets a new goal if none exist or on any move with 10% random chance
|
||||
local r = math.random(10)
|
||||
if (not unit.variables.goal_x) or (r == 1) then
|
||||
if (not goal.goal_x) or (r == 1) then
|
||||
local locs = AH.get_passable_locations(cfg.filter_location or {})
|
||||
local rand = math.random(#locs)
|
||||
--print(type, ': #locs', #locs, rand)
|
||||
unit.variables.goal_x, unit.variables.goal_y = locs[rand][1], locs[rand][2]
|
||||
goal.goal_x, goal.goal_y = locs[rand][1], locs[rand][2]
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, goal)
|
||||
end
|
||||
--print('Big animal goto: ', type, unit.variables.goal_x, unit.variables.goal_y, r)
|
||||
--print('Big animal goto: ', unit.id, goal.goal_x, goal.goal_y, r)
|
||||
|
||||
-- hexes the unit can reach
|
||||
local reach_map = AH.get_reachable_unocc(unit)
|
||||
|
@ -57,7 +61,7 @@ function ca_big_animals:execution(ai, cfg)
|
|||
local max_rating, best_hex = -9e99, {}
|
||||
reach_map:iter( function(x, y, v)
|
||||
-- Distance from goal is first rating
|
||||
local rating = - H.distance_between(x, y, unit.variables.goal_x, unit.variables.goal_y)
|
||||
local rating = - H.distance_between(x, y, goal.goal_x, goal.goal_y)
|
||||
|
||||
-- Proximity to an enemy unit is a plus
|
||||
local enemy_hp = 500
|
||||
|
@ -87,14 +91,12 @@ function ca_big_animals:execution(ai, cfg)
|
|||
else -- If animal did not move, we need to stop it (also delete the goal)
|
||||
AH.checked_stopunit_moves(ai, unit)
|
||||
if (not unit) or (not unit.valid) then return end
|
||||
unit.variables.goal_x = nil
|
||||
unit.variables.goal_y = nil
|
||||
MAIUV.delete_mai_unit_variables(unit, cfg.ai_id)
|
||||
end
|
||||
|
||||
-- Or if this gets the unit to the goal, we also delete the goal
|
||||
if (unit.x == unit.variables.goal_x) and (unit.y == unit.variables.goal_y) then
|
||||
unit.variables.goal_x = nil
|
||||
unit.variables.goal_y = nil
|
||||
if (unit.x == goal.goal_x) and (unit.y == goal.goal_y) then
|
||||
MAIUV.delete_mai_unit_variables(unit, cfg.ai_id)
|
||||
end
|
||||
|
||||
-- Finally, if the unit ended up next to enemies, attack the weakest of those
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local LS = wesnoth.require "lua/location_set.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
local ca_hang_out = {}
|
||||
|
||||
|
@ -23,7 +24,7 @@ function ca_hang_out:evaluation(ai, cfg, self)
|
|||
-- Need to unmark all units also
|
||||
local units = wesnoth.get_units { side = wesnoth.current.side, { "and", cfg.filter } }
|
||||
for i,u in ipairs(units) do
|
||||
u.variables.mai_hangout_moved = nil
|
||||
MAIUV.delete_mai_unit_variables(u, cfg.ai_id)
|
||||
end
|
||||
|
||||
return 0
|
||||
|
@ -85,7 +86,7 @@ function ca_hang_out:execution(ai, cfg, self)
|
|||
local best_hex, best_unit, max_rating = {}, {}, -9e99
|
||||
for i,u in ipairs(units) do
|
||||
-- Only consider units that have not been marked yet
|
||||
if (not u.variables.mai_hangout_moved) then
|
||||
if (not MAIUV.get_mai_unit_variables(u, cfg.ai_id, "moved")) then
|
||||
local best_hex_unit, max_rating_unit = {}, -9e99
|
||||
|
||||
-- Check out all unoccupied hexes the unit can reach
|
||||
|
@ -128,12 +129,14 @@ function ca_hang_out:execution(ai, cfg, self)
|
|||
for i,u in ipairs(units) do
|
||||
AH.checked_stopunit_moves(ai, u)
|
||||
-- Also remove the markers
|
||||
if u and u.valid then u.variables.mai_hangout_moved = nil end
|
||||
if u and u.valid then MAIUV.delete_mai_unit_variables(u, cfg.ai_id) end
|
||||
end
|
||||
else
|
||||
-- Otherwise move unit and mark as having been used
|
||||
AH.checked_move(ai, best_unit, best_hex[1], best_hex[2])
|
||||
if best_unit and best_unit.valid then best_unit.variables.mai_hangout_moved = true end
|
||||
if best_unit and best_unit.valid then
|
||||
MAIUV.set_mai_unit_variables(best_unit, cfg.ai_id, { moved = true })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local W = H.set_wml_action_metatable {}
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
local ca_hunter = {}
|
||||
|
||||
|
@ -64,17 +65,19 @@ function ca_hunter:execution(ai, cfg)
|
|||
)[1]
|
||||
|
||||
-- If hunting_status is not set for the unit -> default behavior -> hunting
|
||||
if (not unit.variables.hunting_status) then
|
||||
local hunter_vars = MAIUV.get_mai_unit_variables(unit, cfg.ai_id)
|
||||
if (not hunter_vars.hunting_status) then
|
||||
-- Unit gets a new goal if none exist or on any move with 10% random chance
|
||||
local r = math.random(10)
|
||||
if (not unit.variables.goal_x) or (r <= 1) then
|
||||
if (not hunter_vars.goal_x) or (r <= 1) then
|
||||
-- 'locs' includes border hexes, but that does not matter here
|
||||
locs = AH.get_passable_locations((cfg.filter_location or {}), unit)
|
||||
local rand = math.random(#locs)
|
||||
--print('#locs', #locs, rand)
|
||||
unit.variables.goal_x, unit.variables.goal_y = locs[rand][1], locs[rand][2]
|
||||
hunter_vars.goal_x, hunter_vars.goal_y = locs[rand][1], locs[rand][2]
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
end
|
||||
--print('Hunter goto: ', unit.variables.goal_x, unit.variables.goal_y, r)
|
||||
--print('Hunter goto: ', hunter_vars.goal_x, hunter_vars.goal_y, r)
|
||||
|
||||
-- Hexes the unit can reach
|
||||
local reach_map = AH.get_reachable_unocc(unit)
|
||||
|
@ -83,7 +86,7 @@ function ca_hunter:execution(ai, cfg)
|
|||
local max_rating, best_hex = -9e99, {}
|
||||
reach_map:iter( function(x, y, v)
|
||||
-- Distance from goal is first rating
|
||||
local rating = - H.distance_between(x, y, unit.variables.goal_x, unit.variables.goal_y)
|
||||
local rating = - H.distance_between(x, y, hunter_vars.goal_x, hunter_vars.goal_y)
|
||||
|
||||
-- Proximity to an enemy unit is a plus
|
||||
local enemy_hp = 500
|
||||
|
@ -109,12 +112,14 @@ function ca_hunter:execution(ai, cfg)
|
|||
else -- If hunter did not move, we need to stop it (also delete the goal)
|
||||
AH.checked_stopunit_moves(ai, unit)
|
||||
if (not unit) or (not unit.valid) then return end
|
||||
unit.variables.goal_x, unit.variables.goal_y = nil, nil
|
||||
hunter_vars.goal_x, hunter_vars.goal_y = nil, nil
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
end
|
||||
|
||||
-- Or if this gets the unit to the goal, we also delete the goal
|
||||
if (unit.x == unit.variables.goal_x) and (unit.y == unit.variables.goal_y) then
|
||||
unit.variables.goal_x, unit.variables.goal_y = nil, nil
|
||||
if (unit.x == hunter_vars.goal_x) and (unit.y == hunter_vars.goal_y) then
|
||||
hunter_vars.goal_x, hunter_vars.goal_y = nil, nil
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
end
|
||||
|
||||
-- Finally, if the unit ended up next to enemies, attack the weakest of those
|
||||
|
@ -122,8 +127,9 @@ function ca_hunter:execution(ai, cfg)
|
|||
|
||||
-- If the enemy was killed, hunter returns home
|
||||
if unit.valid and (attack_status == 'killed') then
|
||||
unit.variables.goal_x, unit.variables.goal_y = nil, nil
|
||||
unit.variables.hunting_status = 'return'
|
||||
hunter_vars.goal_x, hunter_vars.goal_y = nil, nil
|
||||
hunter_vars.hunting_status = 'return'
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
if cfg.show_messages then
|
||||
W.message { speaker = unit.id, message = 'Now that I have eaten, I will go back home.' }
|
||||
end
|
||||
|
@ -134,7 +140,7 @@ function ca_hunter:execution(ai, cfg)
|
|||
end
|
||||
|
||||
-- If we got here, this means the unit is either returning, or resting
|
||||
if (unit.variables.hunting_status == 'return') then
|
||||
if (hunter_vars.hunting_status == 'return') then
|
||||
goto_x, goto_y = wesnoth.find_vacant_tile(cfg.home_x, cfg.home_y)
|
||||
--print('Go home:', home_x, home_y, goto_x, goto_y)
|
||||
|
||||
|
@ -163,10 +169,11 @@ function ca_hunter:execution(ai, cfg)
|
|||
|
||||
-- If the unit got home, start the resting counter
|
||||
if (unit.x == cfg.home_x) and (unit.y == cfg.home_y) then
|
||||
unit.variables.hunting_status = 'resting'
|
||||
unit.variables.resting_until = wesnoth.current.turn + (cfg.rest_turns or 3)
|
||||
hunter_vars.hunting_status = 'resting'
|
||||
hunter_vars.resting_until = wesnoth.current.turn + (cfg.rest_turns or 3)
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
if cfg.show_messages then
|
||||
W.message { speaker = unit.id, message = 'I made it home - resting now until the end of Turn ' .. unit.variables.resting_until .. ' or until fully healed.' }
|
||||
W.message { speaker = unit.id, message = 'I made it home - resting now until the end of Turn ' .. hunter_vars.resting_until .. ' or until fully healed.' }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -175,7 +182,7 @@ function ca_hunter:execution(ai, cfg)
|
|||
end
|
||||
|
||||
-- If we got here, the only remaining action is resting
|
||||
if (unit.variables.hunting_status == 'resting') then
|
||||
if (hunter_vars.hunting_status == 'resting') then
|
||||
-- So all we need to do is take moves away from the unit
|
||||
AH.checked_stopunit_moves(ai, unit)
|
||||
if (not unit) or (not unit.valid) then return end
|
||||
|
@ -185,9 +192,10 @@ function ca_hunter:execution(ai, cfg)
|
|||
if (not unit) or (not unit.valid) then return end
|
||||
|
||||
-- If this is the last turn of resting, we also remove the status and turn variable
|
||||
if (unit.hitpoints >= unit.max_hitpoints) and (unit.variables.resting_until <= wesnoth.current.turn) then
|
||||
unit.variables.hunting_status = nil
|
||||
unit.variables.resting_until = nil
|
||||
if (unit.hitpoints >= unit.max_hitpoints) and (hunter_vars.resting_until <= wesnoth.current.turn) then
|
||||
hunter_vars.hunting_status = nil
|
||||
hunter_vars.resting_until = nil
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
if cfg.show_messages then
|
||||
W.message { speaker = unit.id, message = 'I am done resting. It is time to go hunting again next turn.' }
|
||||
end
|
||||
|
@ -196,7 +204,8 @@ function ca_hunter:execution(ai, cfg)
|
|||
end
|
||||
|
||||
-- In principle we should never get here, but just in case: reset variable, so that unit goes hunting on next turn
|
||||
unit.variables.hunting_status = nil
|
||||
hunter_vars.hunting_status = nil
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, hunter_vars)
|
||||
end
|
||||
|
||||
return ca_hunter
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local LS = wesnoth.require "lua/location_set.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
local ca_messenger_escort_move = {}
|
||||
|
||||
|
@ -58,7 +59,8 @@ function ca_messenger_escort_move:execution(ai, cfg)
|
|||
local max_messenger_rating = -9e99
|
||||
for _,m in ipairs(messengers) do
|
||||
local messenger_rating = 1. / (H.distance_between(x, y, m.x, m.y) + 2.)
|
||||
messenger_rating = messenger_rating * 10. * (1. + m.variables.wp_rating * 2.)
|
||||
local wp_rating = MAIUV.get_mai_unit_variables(m, cfg.ai_id, "wp_rating")
|
||||
messenger_rating = messenger_rating * 10. * (1. + wp_rating * 2.)
|
||||
|
||||
if (messenger_rating > max_messenger_rating) then
|
||||
max_messenger_rating = messenger_rating
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
return function(cfg)
|
||||
-- Calculate next waypoint and rating for all messengers
|
||||
|
@ -26,7 +27,7 @@ return function(cfg)
|
|||
for i, m in ipairs(messengers) do
|
||||
-- To avoid code duplication and ensure consistency, we store some pieces of
|
||||
-- information in the messenger units, even though it could be calculated each time it is needed
|
||||
local wp_i = m.variables.wp_i or 1
|
||||
local wp_i = MAIUV.get_mai_unit_variables(m, cfg.ai_id, "wp_i") or 1
|
||||
local wp_x, wp_y = waypoint_x[wp_i], waypoint_y[wp_i]
|
||||
|
||||
-- If this messenger is within 3 hexes of the next waypoint, we go on to the one after that
|
||||
|
@ -34,8 +35,6 @@ return function(cfg)
|
|||
local dist_wp = H.distance_between(m.x, m.y, wp_x, wp_y)
|
||||
if (dist_wp <= 3) and (wp_i < #waypoint_x) then wp_i = wp_i + 1 end
|
||||
|
||||
m.variables.wp_i, m.variables.wp_x, m.variables.wp_y = wp_i, wp_x, wp_y
|
||||
|
||||
-- Also store the rating for each messenger
|
||||
-- For now, this is simply a "forward rating"
|
||||
local rating = wp_i - dist_wp / 1000.
|
||||
|
@ -47,7 +46,7 @@ return function(cfg)
|
|||
rating = #waypoint_x - rating
|
||||
end
|
||||
|
||||
m.variables.wp_rating = rating
|
||||
MAIUV.set_mai_unit_variables(m, cfg.ai_id, { wp_i = wp_i, wp_x = wp_x, wp_y = wp_y, wp_rating = rating })
|
||||
|
||||
-- Find the messenger with the highest rating that has MP left
|
||||
if (m.moves > 0) and (rating > max_rating) then
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
local ca_patrol = {}
|
||||
|
||||
|
@ -28,10 +29,12 @@ function ca_patrol:execution(ai, cfg)
|
|||
|
||||
local n_wp = #cfg.waypoint_x -- just for convenience
|
||||
|
||||
local patrol_vars = MAIUV.get_mai_unit_variables(patrol, cfg.ai_id)
|
||||
|
||||
-- Set up waypoints, taking into account whether 'reverse' is set
|
||||
-- This works even the first time, when patrol.variables.patrol_reverse is not set yet
|
||||
-- This works even the first time, when patrol_vars.patrol_reverse is not set yet
|
||||
local waypoints = {}
|
||||
if patrol.variables.patrol_reverse then
|
||||
if patrol_vars.patrol_reverse then
|
||||
for i = 1,n_wp do
|
||||
waypoints[i] = { tonumber(cfg.waypoint_x[n_wp-i+1]), tonumber(cfg.waypoint_y[n_wp-i+1]) }
|
||||
end
|
||||
|
@ -43,10 +46,11 @@ function ca_patrol:execution(ai, cfg)
|
|||
|
||||
-- If not set, set next location (first move)
|
||||
-- This needs to be in WML format, so that it persists over save/load cycles
|
||||
if (not patrol.variables.patrol_x) then
|
||||
patrol.variables.patrol_x = waypoints[1][1]
|
||||
patrol.variables.patrol_y = waypoints[1][2]
|
||||
patrol.variables.patrol_reverse = false
|
||||
if (not patrol_vars.patrol_x) then
|
||||
patrol_vars.patrol_x = waypoints[1][1]
|
||||
patrol_vars.patrol_y = waypoints[1][2]
|
||||
patrol_vars.patrol_reverse = false
|
||||
MAIUV.set_mai_unit_variables(patrol, cfg.ai_id, patrol_vars)
|
||||
end
|
||||
|
||||
while patrol.moves > 0 do
|
||||
|
@ -61,8 +65,8 @@ function ca_patrol:execution(ai, cfg)
|
|||
|
||||
-- Also check whether we're next to any unit (enemy or ally) which is on the next waypoint
|
||||
local unit_on_wp = wesnoth.get_units {
|
||||
x = patrol.variables.patrol_x,
|
||||
y = patrol.variables.patrol_y,
|
||||
x = patrol_vars.patrol_x,
|
||||
y = patrol_vars.patrol_y,
|
||||
{ "filter_adjacent", { id = patrol.id } }
|
||||
}[1]
|
||||
|
||||
|
@ -75,28 +79,32 @@ function ca_patrol:execution(ai, cfg)
|
|||
-- Move him to the first one (or reverse route), if he's on the last waypoint
|
||||
-- Unless cfg.one_time_only is set
|
||||
if cfg.one_time_only then
|
||||
patrol.variables.patrol_x = waypoints[n_wp][1]
|
||||
patrol.variables.patrol_y = waypoints[n_wp][2]
|
||||
patrol_vars.patrol_x = waypoints[n_wp][1]
|
||||
patrol_vars.patrol_y = waypoints[n_wp][2]
|
||||
MAIUV.set_mai_unit_variables(patrol, cfg.ai_id, patrol_vars)
|
||||
else
|
||||
-- Go back to first WP or reverse direction
|
||||
if cfg.out_and_back then
|
||||
patrol.variables.patrol_x = waypoints[n_wp-1][1]
|
||||
patrol.variables.patrol_y = waypoints[n_wp-1][2]
|
||||
|
||||
patrol_vars.patrol_x = waypoints[n_wp-1][1]
|
||||
patrol_vars.patrol_y = waypoints[n_wp-1][2]
|
||||
-- We also need to reverse the waypoints right here, as this might not be the end of the move
|
||||
patrol.variables.patrol_reverse = not patrol.variables.patrol_reverse
|
||||
patrol_vars.patrol_reverse = not patrol_vars.patrol_reverse
|
||||
MAIUV.set_mai_unit_variables(patrol, cfg.ai_id, patrol_vars)
|
||||
|
||||
local tmp_wp = {}
|
||||
for i,wp in ipairs(waypoints) do tmp_wp[n_wp-i+1] = wp end
|
||||
waypoints = tmp_wp
|
||||
else
|
||||
patrol.variables.patrol_x = waypoints[1][1]
|
||||
patrol.variables.patrol_y = waypoints[1][2]
|
||||
patrol_vars.patrol_x = waypoints[1][1]
|
||||
patrol_vars.patrol_y = waypoints[1][2]
|
||||
MAIUV.set_mai_unit_variables(patrol, cfg.ai_id, patrol_vars)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- ... else move him on the next waypoint
|
||||
patrol.variables.patrol_x = waypoints[i+1][1]
|
||||
patrol.variables.patrol_y = waypoints[i+1][2]
|
||||
patrol_vars.patrol_x = waypoints[i+1][1]
|
||||
patrol_vars.patrol_y = waypoints[i+1][2]
|
||||
MAIUV.set_mai_unit_variables(patrol, cfg.ai_id, patrol_vars)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -107,7 +115,7 @@ function ca_patrol:execution(ai, cfg)
|
|||
then
|
||||
AH.checked_stopunit_moves(ai, patrol)
|
||||
else -- otherwise move toward next WP
|
||||
local x, y = wesnoth.find_vacant_tile(patrol.variables.patrol_x, patrol.variables.patrol_y, patrol)
|
||||
local x, y = wesnoth.find_vacant_tile(patrol_vars.patrol_x, patrol_vars.patrol_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])
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local W = H.set_wml_action_metatable {}
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
local LS = wesnoth.require "lua/location_set.lua"
|
||||
local WMPF = wesnoth.require "ai/micro_ais/cas/ca_wolves_multipacks_functions.lua"
|
||||
|
||||
|
@ -8,7 +9,6 @@ local ca_wolves_multipacks_attack = {}
|
|||
|
||||
function ca_wolves_multipacks_attack:evaluation(ai, cfg)
|
||||
local unit_type = cfg.type or "Wolf"
|
||||
|
||||
-- If wolves have attacks left, call this CA
|
||||
-- It will generally be disabled by being black-listed, so as to avoid
|
||||
-- having to do the full attack evaluation for every single move
|
||||
|
@ -26,7 +26,6 @@ function ca_wolves_multipacks_attack:execution(ai, cfg)
|
|||
-- and I want all wolves in a pack to move first, before going on to the next pack
|
||||
-- which makes this slightly more complicated than it would be otherwise
|
||||
for pack_number,pack in pairs(packs) do
|
||||
|
||||
local keep_attacking_this_pack = true -- whether there might be attacks left
|
||||
local pack_attacked = false -- whether an attack by the pack has happened
|
||||
|
||||
|
@ -97,10 +96,13 @@ function ca_wolves_multipacks_attack:execution(ai, cfg)
|
|||
-- the same target for all wolves of the pack)
|
||||
for x, y in H.adjacent_tiles(target.x, target.y) do
|
||||
local adj_unit = wesnoth.get_unit(x, y)
|
||||
if adj_unit and (adj_unit.variables.pack == pack_number)
|
||||
and (adj_unit.side == wesnoth.current.side) and (adj_unit.attacks_left == 0)
|
||||
then
|
||||
rating = rating + 10 -- very strongly favors this target
|
||||
if adj_unit then
|
||||
local pack = MAIUV.get_mai_unit_variables(adj_unit, cfg.ai_id, "pack")
|
||||
if (pack == pack_number) and (adj_unit.side == wesnoth.current.side)
|
||||
and (adj_unit.attacks_left == 0)
|
||||
then
|
||||
rating = rating + 10 -- very strongly favors this target
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local W = H.set_wml_action_metatable {}
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
|
||||
local wolves_multipacks_functions = {}
|
||||
|
||||
|
@ -25,9 +26,10 @@ function wolves_multipacks_functions.assign_packs(cfg)
|
|||
local packs = {}
|
||||
-- Find wolves that already have a pack number assigned
|
||||
for i,w in ipairs(wolves) do
|
||||
if w.variables.pack then
|
||||
if (not packs[w.variables.pack]) then packs[w.variables.pack] = {} end
|
||||
table.insert(packs[w.variables.pack], { x = w.x, y = w.y, id = w.id })
|
||||
local pack = MAIUV.get_mai_unit_variables(w, cfg.ai_id, "pack")
|
||||
if pack then
|
||||
if (not packs[pack]) then packs[pack] = {} end
|
||||
table.insert(packs[pack], { x = w.x, y = w.y, id = w.id })
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,7 +39,7 @@ function wolves_multipacks_functions.assign_packs(cfg)
|
|||
--print(' have pack:', k, ' #members:', #p)
|
||||
if (#p == 1) then
|
||||
local wolf = wesnoth.get_unit(p[1].x, p[1].y)
|
||||
wolf.variables.pack, wolf.variables.goal_x, wolf.variables.goal_y = nil, nil, nil
|
||||
MAIUV.delete_mai_unit_variables(wolf, cfg.ai_id)
|
||||
packs[k] = nil
|
||||
end
|
||||
end
|
||||
|
@ -47,10 +49,11 @@ function wolves_multipacks_functions.assign_packs(cfg)
|
|||
-- Wolves that are not in a pack (new ones or those removed above)
|
||||
local nopack_wolves = {}
|
||||
for i,w in ipairs(wolves) do
|
||||
if (not w.variables.pack) then
|
||||
local pack = MAIUV.get_mai_unit_variables(w, cfg.ai_id, "pack")
|
||||
if (not pack) then
|
||||
table.insert(nopack_wolves, w)
|
||||
-- Also erase any goal one of these might have
|
||||
w.variables.pack, w.variables.goal_x, w.variables.goal_y = nil, nil, nil
|
||||
MAIUV.delete_mai_unit_variables(w, cfg.ai_id)
|
||||
end
|
||||
end
|
||||
--print('#nopack_wolves:', #nopack_wolves)
|
||||
|
@ -70,7 +73,7 @@ function wolves_multipacks_functions.assign_packs(cfg)
|
|||
end
|
||||
if (min_dist < 9e99) then
|
||||
table.insert(packs[k], { x = best_wolf.x, y = best_wolf.y, id = best_wolf.id })
|
||||
best_wolf.variables.pack = k
|
||||
MAIUV.set_mai_unit_variables(best_wolf, cfg.ai_id, { pack = k })
|
||||
table.remove(nopack_wolves, best_ind)
|
||||
end
|
||||
end
|
||||
|
@ -93,7 +96,7 @@ function wolves_multipacks_functions.assign_packs(cfg)
|
|||
packs[new_pack] = {}
|
||||
for i,w in ipairs(nopack_wolves) do
|
||||
table.insert(packs[new_pack], { x = w.x, y = w.y, id = w.id })
|
||||
w.variables.pack = new_pack
|
||||
MAIUV.set_mai_unit_variables(w, cfg.ai_id, { pack = new_pack })
|
||||
end
|
||||
break
|
||||
end
|
||||
|
@ -121,7 +124,7 @@ function wolves_multipacks_functions.assign_packs(cfg)
|
|||
-- Need to count down for table.remove to work correctly
|
||||
for i = pack_size,1,-1 do
|
||||
table.insert(packs[new_pack], { x = best_wolves[i].x, y = best_wolves[i].y, id = best_wolves[i].id })
|
||||
best_wolves[i].variables.pack = new_pack
|
||||
MAIUV.set_mai_unit_variables(best_wolves[i], cfg.ai_id, { pack = new_pack })
|
||||
end
|
||||
end
|
||||
--print('After grouping remaining single wolves')
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
local H = wesnoth.require "lua/helper.lua"
|
||||
local W = H.set_wml_action_metatable {}
|
||||
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
||||
local MAIUV = wesnoth.dofile "ai/micro_ais/micro_ai_unit_variables.lua"
|
||||
local LS = wesnoth.require "lua/location_set.lua"
|
||||
local WMPF = wesnoth.require "ai/micro_ais/cas/ca_wolves_multipacks_functions.lua"
|
||||
|
||||
|
@ -27,9 +28,11 @@ function ca_wolves_multipacks_wander:execution(ai, cfg)
|
|||
local wolf = wesnoth.get_unit(loc.x, loc.y)
|
||||
--print(k, i, wolf.id)
|
||||
table.insert(wolves, wolf)
|
||||
|
||||
-- If any of the wolves in the pack has a goal set, we use that one
|
||||
if wolf.variables.goal_x then
|
||||
goal = { wolf.variables.goal_x, wolf.variables.goal_y }
|
||||
local wolf_goal = MAIUV.get_mai_unit_variables(wolf, cfg.ai_id)
|
||||
if wolf_goal.goal_x then
|
||||
goal = { wolf_goal.goal_x, wolf_goal.goal_y }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -61,7 +64,7 @@ function ca_wolves_multipacks_wander:execution(ai, cfg)
|
|||
|
||||
-- This goal is saved with every wolf of the pack
|
||||
for i,w in ipairs(wolves) do
|
||||
w.variables.goal_x, w.variables.goal_y = goal[1], goal[2]
|
||||
MAIUV.insert_mai_unit_variables(w, cfg.ai_id, { goal_x = goal[1], goal_y = goal[2] })
|
||||
end
|
||||
|
||||
-- The pack wanders with only 2 considerations
|
||||
|
|
Loading…
Add table
Reference in a new issue