Micro AIs: Distinguish attribute and tag parameters and copy all of the latter

(Though currently only Protect Unit and Random Recruiting actually honour multiples of any tag.)
This commit is contained in:
Celtic Minstrel 2016-03-28 12:54:25 -04:00
parent dd02202fc8
commit 32c3abbbaf
10 changed files with 44 additions and 34 deletions

View file

@ -2,8 +2,8 @@ local H = wesnoth.require "lua/helper.lua"
local MAIH = wesnoth.require("ai/micro_ais/micro_ai_helper.lua")
function wesnoth.micro_ais.big_animals(cfg)
local required_keys = { "filter"}
local optional_keys = { "avoid_unit", "filter_location", "filter_location_wander" }
local required_keys = { "[filter]"}
local optional_keys = { "[avoid_unit]", "[filter_location]", "[filter_location_wander]" }
local CA_parms = {
ai_id = 'mai_big_animals',
{ ca_id = "move", location = 'ca_big_animals.lua', score = cfg.ca_score or 300000 }
@ -12,7 +12,7 @@ function wesnoth.micro_ais.big_animals(cfg)
end
function wesnoth.micro_ais.wolves(cfg)
local required_keys = { "filter", "filter_second" }
local required_keys = { "[filter]", "[filter_second]" }
local optional_keys = { "attack_only_prey", "avoid_type" }
local score = cfg.ca_score or 90000
local CA_parms = {
@ -66,7 +66,7 @@ function wesnoth.micro_ais.wolves(cfg)
end
function wesnoth.micro_ais.herding(cfg)
local required_keys = { "filter_location", "filter", "filter_second", "herd_x", "herd_y" }
local required_keys = { "[filter_location]", "[filter]", "[filter_second]", "herd_x", "herd_y" }
local optional_keys = { "attention_distance", "attack_distance" }
local score = cfg.ca_score or 300000
local CA_parms = {
@ -84,7 +84,7 @@ end
function wesnoth.micro_ais.forest_animals(cfg)
local optional_keys = { "rabbit_type", "rabbit_number", "rabbit_enemy_distance", "rabbit_hole_img",
"tusker_type", "tusklet_type", "deer_type", "filter_location"
"tusker_type", "tusklet_type", "deer_type", "[filter_location]"
}
local score = cfg.ca_score or 300000
local CA_parms = {
@ -124,7 +124,7 @@ function wesnoth.micro_ais.hunter(cfg)
H.wml_error("Hunter [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "home_x", "home_y" }
local optional_keys = { "id", "filter", "filter_location", "rest_turns", "show_messages" }
local optional_keys = { "id", "[filter]", "[filter_location]", "rest_turns", "show_messages" }
local CA_parms = {
ai_id = 'mai_hunter',
{ ca_id = "move", location = 'ca_hunter.lua', score = cfg.ca_score or 300000 }

View file

@ -5,7 +5,7 @@ function wesnoth.micro_ais.messenger_escort(cfg)
H.wml_error("Messenger [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "waypoint_x", "waypoint_y" }
local optional_keys = { "id", "enemy_death_chance", "filter", "filter_second", "invert_order", "messenger_death_chance" }
local optional_keys = { "id", "enemy_death_chance", "[filter]", "[filter_second]", "invert_order", "messenger_death_chance" }
local score = cfg.ca_score or 300000
local CA_parms = {
ai_id = 'mai_messenger',

View file

@ -3,8 +3,8 @@ local W = H.set_wml_action_metatable {}
function wesnoth.micro_ais.fast_ai(cfg)
local optional_keys = {
"attack_hidden_enemies", "avoid", "dungeon_mode",
"filter", "filter_second", "include_occupied_attack_hexes",
"attack_hidden_enemies", "[avoid]", "dungeon_mode",
"[filter]", "[filter_second]", "include_occupied_attack_hexes",
"leader_additional_threat", "leader_attack_max_units", "leader_weight", "move_cost_factor",
"weak_units_first", "skip_combat_ca", "skip_move_ca", "threatened_leader_fights"
}

View file

@ -5,7 +5,7 @@ function wesnoth.micro_ais.stationed_guardian(cfg)
H.wml_error("Stationed Guardian [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "distance", "station_x", "station_y" }
local optional_keys = { "id", "filter", "guard_x", "guard_y" }
local optional_keys = { "id", "[filter]", "guard_x", "guard_y" }
local CA_parms = {
ai_id = 'mai_stationed_guardian',
{ ca_id = 'move', location = 'ca_stationed_guardian.lua', score = cfg.ca_score or 300000 }
@ -17,8 +17,8 @@ function wesnoth.micro_ais.zone_guardian(cfg)
if (cfg.action ~= 'delete') and (not cfg.id) and (not H.get_child(cfg, "filter")) then
H.wml_error("Zone Guardian [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "filter_location" }
local optional_keys = { "id", "filter", "filter_location_enemy", "station_x", "station_y" }
local required_keys = { "[filter_location]" }
local optional_keys = { "id", "[filter]", "[filter_location_enemy]", "station_x", "station_y" }
local CA_parms = {
ai_id = 'mai_zone_guardian',
{ ca_id = 'move', location = 'ca_zone_guardian.lua', score = cfg.ca_score or 300000 }
@ -31,7 +31,7 @@ function wesnoth.micro_ais.return_guardian(cfg)
H.wml_error("Return Guardian [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "return_x", "return_y" }
local optional_keys = { "id", "filter" }
local optional_keys = { "id", "[filter]" }
local CA_parms = {
ai_id = 'mai_return_guardian',
{ ca_id = 'move', location = 'ca_return_guardian.lua', score = cfg.ca_score or 100010 }
@ -44,7 +44,7 @@ function wesnoth.micro_ais.coward(cfg)
H.wml_error("Coward [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "distance" }
local optional_keys = { "attack_if_trapped", "id", "filter", "filter_second", "seek_x", "seek_y","avoid_x","avoid_y" }
local optional_keys = { "attack_if_trapped", "id", "[filter]", "[filter_second]", "seek_x", "seek_y","avoid_x","avoid_y" }
local CA_parms = {
ai_id = 'mai_coward',
{ ca_id = 'move', location = 'ca_coward.lua', score = cfg.ca_score or 300000 }

View file

@ -1,6 +1,6 @@
function wesnoth.micro_ais.healer_support(cfg)
local optional_keys = { "aggression", "injured_units_only", "max_threats", "filter", "filter_second" }
local optional_keys = { "aggression", "injured_units_only", "max_threats", "[filter]", "[filter_second]" }
-- Scores for this AI need to be hard-coded, it does not work otherwise
local CA_parms = {
ai_id = 'mai_healer',

View file

@ -1,7 +1,7 @@
function wesnoth.micro_ais.lurkers(cfg)
local required_keys = { "filter", "filter_location" }
local optional_keys = { "stationary", "filter_location_wander" }
local required_keys = { "[filter]", "[filter_location]" }
local optional_keys = { "stationary", "[filter_location_wander]" }
local CA_parms = {
ai_id = 'mai_lurkers',
{ ca_id = 'move', location = 'ca_lurkers.lua', score = cfg.ca_score or 300000 }
@ -11,9 +11,9 @@ end
-- goto is a keyword, so need to use index operator directly
wesnoth.micro_ais["goto"] = function(cfg)
local required_keys = { "filter_location" }
local required_keys = { "[filter_location]" }
local optional_keys = {
"avoid_enemies", "filter", "ignore_units", "ignore_enemy_at_goal",
"avoid_enemies", "[filter]", "ignore_units", "ignore_enemy_at_goal",
"release_all_units_at_goal", "release_unit_at_goal", "unique_goals", "use_straight_line"
}
local CA_parms = {
@ -24,7 +24,7 @@ wesnoth.micro_ais["goto"] = function(cfg)
end
function wesnoth.micro_ais.hang_out(cfg)
local optional_keys = { "filter", "filter_location", "avoid", "mobilize_condition", "mobilize_on_gold_less_than" }
local optional_keys = { "[filter]", "[filter_location]", "[avoid]", "[mobilize_condition]", "mobilize_on_gold_less_than" }
local CA_parms = {
ai_id = 'mai_hang_out',
{ ca_id = 'move', location = 'ca_hang_out.lua', score = cfg.ca_score or 170000 }

View file

@ -5,7 +5,7 @@ function wesnoth.micro_ais.patrol(cfg)
H.wml_error("Patrol [micro_ai] tag requires either id= key or [filter] tag")
end
local required_keys = { "waypoint_x", "waypoint_y" }
local optional_keys = { "id", "filter", "attack", "one_time_only", "out_and_back" }
local optional_keys = { "id", "[filter]", "attack", "one_time_only", "out_and_back" }
local CA_parms = {
ai_id = 'mai_patrol',
{ ca_id = "move", location = 'ca_patrol.lua', score = cfg.ca_score or 300000 }

View file

@ -24,9 +24,6 @@ function wesnoth.micro_ais.protect_unit(cfg)
end
table.insert(unit_ids, u.id)
end
if #unit_ids == 0 then
H.wml_error("Protect Unit Micro AI is missing required [unit] tag")
end
-- Optional key disable_move_leader_to_keep: needs to be dealt with
-- separately as it affects a default CA
@ -74,5 +71,5 @@ function wesnoth.micro_ais.protect_unit(cfg)
else
MAIH.add_aspects(cfg.side, aspect_parms)
end
return {}, {}, CA_parms
return {"[unit]"}, {}, CA_parms
end

View file

@ -39,7 +39,7 @@ function wesnoth.micro_ais.recruit_rushers(cfg)
end
function wesnoth.micro_ais.recruit_random(cfg)
local optional_keys = { "skip_low_gold_recruiting", "type", "probability" }
local optional_keys = { "skip_low_gold_recruiting", "[probability]" }
local CA_parms = {
ai_id = 'mai_random_recruit',
{ ca_id = "move", location = 'ca_recruit_random.lua', score = cfg.ca_score or 180000 }

View file

@ -174,19 +174,32 @@ function micro_ai_helper.micro_ai_setup(cfg, CA_parms, required_keys, optional_k
-- Required keys
for _,v in pairs(required_keys) do
local child = H.get_child(cfg, v)
if (not cfg[v]) and (not child) then
H.wml_error("[micro_ai] tag (" .. cfg.ai_type .. ") is missing required parameter: " .. v)
if v:match('%[[a-zA-Z0-9_]+%]') then
v = v:sub(2,-2)
if not H.get_child(cfg, v) then
H.wml_error("[micro_ai] tag (" .. cfg.ai_type .. ") is missing required parameter: [" .. v .. "]")
end
for child in H.child_range(cfg, v) do
table.insert(CA_cfg, T[v](child))
end
else
if not cfg[v] then
H.wml_error("[micro_ai] tag (" .. cfg.ai_type .. ") is missing required parameter: " .. v .."=")
end
CA_cfg[v] = cfg[v]
end
CA_cfg[v] = cfg[v]
if child then table.insert(CA_cfg, T[v](child)) end
end
-- Optional keys
for _,v in pairs(optional_keys) do
CA_cfg[v] = cfg[v]
local child = H.get_child(cfg, v)
if child then table.insert(CA_cfg, T[v](child)) end
if v:match('%[[a-zA-Z0-9_]+%]') then
v = v:sub(2,-2)
for child in H.child_range(cfg, v) do
table.insert(CA_cfg, T[v](child))
end
else
CA_cfg[v] = cfg[v]
end
end
-- Finally, set up the candidate actions themselves