Micro AIs: use AI id instead of CA id as identifier

… for determining whether AI/CA ids are unique.  Also pass AI id to
eval/exec functions, instead of CA id.  This is also a step toward
fixing the bug with MAI variables remaining stored in units after an
MAI is removed.
In principle, the ca_id= key in the [micro_ai] tag should now be
renamed to ai_id, but that would break backward compatibility without
any benefit to the user, so we deal with it internally behind the
scenes instead.
This commit is contained in:
mattsc 2014-03-31 08:12:33 -07:00
parent 96e84f24c5
commit 24881edfb3
4 changed files with 135 additions and 82 deletions

View file

@ -22,7 +22,7 @@ function ca_goto:evaluation(ai, cfg, self)
-- which case we do not do anything
if cfg.release_all_units_at_goal then
for rel in H.child_range(self.data, "goto_release_all") do
if (rel.id == cfg.ca_id) then
if (rel.id == cfg.ai_id) then
return 0
end
end
@ -65,7 +65,7 @@ function ca_goto:evaluation(ai, cfg, self)
if cfg.release_unit_at_goal then
for i_unit=#units,1,-1 do
for rel in H.child_range(self.data, "goto_release_unit") do
if (rel.id == cfg.ca_id .. '_' .. units[i_unit].id) then
if (rel.id == cfg.ai_id .. '_' .. units[i_unit].id) then
table.remove(units, i_unit)
break
end
@ -227,12 +227,12 @@ function ca_goto:execution(ai, cfg, self)
-- 2. Keys cannot contain certain characters -> everything potentially user-defined needs to be in values
if unit_at_goal then
if cfg.release_unit_at_goal then
table.insert(self.data, { "goto_release_unit" , { id = cfg.ca_id .. '_' .. best_unit.id } } )
table.insert(self.data, { "goto_release_unit" , { id = cfg.ai_id .. '_' .. best_unit.id } } )
end
if cfg.release_all_units_at_goal then
--print("Releasing all units")
table.insert(self.data, { "goto_release_all", { id = cfg.ca_id } } )
table.insert(self.data, { "goto_release_all", { id = cfg.ai_id } } )
end
end
end

View file

@ -8,8 +8,8 @@ function ca_hang_out:evaluation(ai, cfg, self)
cfg = cfg or {}
-- Return 0 if the mobilize condition has previously been met
for mobilze in H.child_range(self.data, "hangout_mobilize_units") do
if (mobilze.id == cfg.ca_id) then
for mobilize in H.child_range(self.data, "hangout_mobilize_units") do
if (mobilize.id == cfg.ai_id) then
return 0
end
end
@ -18,7 +18,7 @@ function ca_hang_out:evaluation(ai, cfg, self)
if (cfg.mobilize_condition and wesnoth.eval_conditional(cfg.mobilize_condition))
or (cfg.mobilize_on_gold_less_than and (wesnoth.sides[wesnoth.current.side].gold < cfg.mobilize_on_gold_less_than))
then
table.insert(self.data, { "hangout_mobilize_units" , { id = cfg.ca_id } } )
table.insert(self.data, { "hangout_mobilize_units" , { id = cfg.ai_id } } )
-- Need to unmark all units also
local units = wesnoth.get_units { side = wesnoth.current.side, { "and", cfg.filter } }

View file

@ -5,40 +5,48 @@ local AH = wesnoth.require("ai/lua/ai_helper.lua")
local micro_ai_helper = {}
function micro_ai_helper.add_CAs(side, CA_parms, CA_cfg)
-- Add the candidate actions defined in 'CA_parms' to the AI of 'side'
-- CA_parms is an array of tables, one for each CA to be added (CA setup parameters)
-- CA_cfg is a table with the parameters passed to the eval/exec functions
-- Add the candidate actions defined in @CA_parms to the AI of @side
-- @CA_parms is an array of tables, one for each CA to be added (CA setup parameters)
-- and also contains one key: ai_id
-- @CA_cfg is a table with the parameters passed to the eval/exec functions
--
-- Required keys for CA_parms:
-- - ca_id: is used for CA id/name and the eval/exec function names
-- Required keys for each table of @CA_parms:
-- - ca_id: is used for CA id/name
-- - location: the path+file name for the external CA file
-- - score: the evaluation score
for i,parms in ipairs(CA_parms) do
-- Make sure the id/name of each CA are unique.
-- We do this by seeing if a CA by that name exists already.
-- If not, we use the passed id in parms.ca_id
-- If yes, we add a number to the end of parms.ca_id until we find an id that does not exist yet
local ca_id, id_found = parms.ca_id, true
-- We need to make sure that the id/name of each CA are unique.
-- We do this by checking if CAs starting with ai_id exist already
-- If yes, we add numbers to the end of ai_id until we find an id that does not exist yet
local n = 1
while id_found do -- This is really just a precaution
id_found = false
local ai_id, id_found = CA_parms.ai_id, true
for ai_tag in H.child_range(wesnoth.sides[side].__cfg, 'ai') do
for stage in H.child_range(ai_tag, 'stage') do
for ca in H.child_range(stage, 'candidate_action') do
if (ca.name == ca_id) then id_found = true end
--print('---> found CA:', ca.name, id_found)
local n = 1
while id_found do -- This is really just a precaution
id_found = false
for ai_tag in H.child_range(wesnoth.sides[side].__cfg, 'ai') do
for stage in H.child_range(ai_tag, 'stage') do
for ca in H.child_range(stage, 'candidate_action') do
if string.find(ca.name, ai_id .. '_') then
id_found = true
--print('---> found CA:', ca.name, ai_id, id_found, string.find(ca.name, ai_id))
break
end
end
end
if (id_found) then ca_id = parms.ca_id .. n end
n = n+1
end
-- Always pass the ca_id and ca_score to the eval/exec functions
CA_cfg.ca_id = ca_id
if (id_found) then ai_id = CA_parms.ai_id .. n end
n = n + 1
end
-- Now add the CAs
for i,parms in ipairs(CA_parms) do
local ca_id = ai_id .. '_' .. parms.ca_id
-- Always pass the ai_id and ca_score to the eval/exec functions
CA_cfg.ai_id = ai_id
CA_cfg.ca_score = parms.score
local CA = {
@ -63,13 +71,13 @@ function micro_ai_helper.add_CAs(side, CA_parms, CA_cfg)
end
function micro_ai_helper.delete_CAs(side, CA_parms)
-- Delete the candidate actions defined in 'CA_parms' from the AI of 'side'
-- CA_parms is an array of tables, one for each CA to be removed
-- Delete the candidate actions defined in @CA_parms from the AI of @side
-- @CA_parms is an array of tables, one for each CA to be removed
-- We can simply pass the one used for add_CAs(), although only the
-- CA_parms.ca_id field is needed
for i,parms in ipairs(CA_parms) do
local ca_id = parms.ca_id
local ca_id = CA_parms.ai_id .. '_' .. parms.ca_id
W.modify_ai {
side = side,
@ -126,15 +134,12 @@ function micro_ai_helper.delete_aspects(side, aspect_parms)
end
function micro_ai_helper.micro_ai_setup(cfg, CA_parms, required_keys, optional_keys)
-- If cfg.ca_id is set, it gets added to the ca_id= key of all CAs
-- If cfg.ca_id is set, it gets used as the ai_id= key
-- This allows for selective removal of CAs
if cfg.ca_id then
for i,parms in ipairs(CA_parms) do
-- Need to save eval_id first though
parms.eval_id = parms.ca_id
parms.ca_id = parms.ca_id .. '_' .. cfg.ca_id
end
end
-- Note: the ca_id key of the [micro_ai] tag should really be renamed to ai_id,
-- but that would mean breaking backward compatibility, so we'll just deal with it internally instead
CA_parms.ai_id = cfg.ca_id or CA_parms.ai_id
-- If action=delete, we do that and are done
if (cfg.action == 'delete') then

View file

@ -64,14 +64,15 @@ function wesnoth.wml_actions.micro_ai(cfg)
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
CA_parms = {
{ ca_id = 'mai_healer_initialize', location = CA_path .. 'ca_healer_initialize.lua', score = 999990 },
{ ca_id = 'mai_healer_move', location = CA_path .. 'ca_healer_move.lua', score = 105000 },
ai_id = 'mai_healer',
{ ca_id = 'initialize', location = CA_path .. 'ca_healer_initialize.lua', score = 999990 },
{ ca_id = 'move', location = CA_path .. 'ca_healer_move.lua', score = 105000 },
}
-- The healers_can_attack CA is only added to the table if aggression ~= 0
-- But: make sure we always try removal
if (cfg.action == 'delete') or (tonumber(cfg.aggression) ~= 0) then
table.insert(CA_parms, { ca_id = 'mai_healer_may_attack', location = CA_path .. 'ca_healer_may_attack.lua', score = 99990 })
table.insert(CA_parms, { ca_id = 'may_attack', location = CA_path .. 'ca_healer_may_attack.lua', score = 99990 })
end
--------- Bottleneck Defense Micro AI -----------------------------------
@ -80,8 +81,9 @@ function wesnoth.wml_actions.micro_ai(cfg)
optional_keys = { "healer_x", "healer_y", "leadership_x", "leadership_y", "active_side_leader" }
local score = cfg.ca_score or 300000
CA_parms = {
{ ca_id = 'mai_bottleneck_move', location = CA_path .. 'ca_bottleneck_move.lua', score = score },
{ ca_id = 'mai_bottleneck_attack', location = CA_path .. 'ca_bottleneck_attack.lua', score = score - 1 }
ai_id = 'mai_bottleneck',
{ ca_id = 'move', location = CA_path .. 'ca_bottleneck_move.lua', score = score },
{ ca_id = 'attack', location = CA_path .. 'ca_bottleneck_attack.lua', score = score - 1 }
}
--------- Messenger Escort Micro AI ------------------------------------
@ -93,25 +95,30 @@ function wesnoth.wml_actions.micro_ai(cfg)
optional_keys = { "id", "enemy_death_chance", "filter", "filter_second", "invert_order", "messenger_death_chance" }
local score = cfg.ca_score or 300000
CA_parms = {
{ ca_id = 'mai_messenger_attack', location = CA_path .. 'ca_messenger_attack.lua', score = score },
{ ca_id = 'mai_messenger_move', location = CA_path .. 'ca_messenger_move.lua', score = score - 1 },
{ ca_id = 'mai_messenger_escort_move', location = CA_path .. 'ca_messenger_escort_move.lua', score = score - 2 }
ai_id = 'mai_messenger',
{ ca_id = 'attack', location = CA_path .. 'ca_messenger_attack.lua', score = score },
{ ca_id = 'move', location = CA_path .. 'ca_messenger_move.lua', score = score - 1 },
{ ca_id = 'escort_move', location = CA_path .. 'ca_messenger_escort_move.lua', score = score - 2 }
}
--------- Lurkers Micro AI ------------------------------------
elseif (cfg.ai_type == 'lurkers') then
required_keys = { "filter", "filter_location" }
optional_keys = { "stationary", "filter_location_wander" }
CA_parms = { { ca_id = 'mai_lurkers', location = CA_path .. 'ca_lurkers.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_lurkers',
{ ca_id = 'move', location = CA_path .. 'ca_lurkers.lua', score = cfg.ca_score or 300000 }
}
--------- Protect Unit Micro AI ------------------------------------
elseif (cfg.ai_type == 'protect_unit') then
required_keys = { "id", "goal_x", "goal_y" }
-- Scores for this AI need to be hard-coded, it does not work otherwise
CA_parms = {
{ ca_id = 'mai_protect_unit_finish', location = CA_path .. 'ca_protect_unit_finish.lua', score = 300000 },
{ ca_id = 'mai_protect_unit_attack', location = CA_path .. 'ca_protect_unit_attack.lua', score = 95000 },
{ ca_id = 'mai_protect_unit_move', location = CA_path .. 'ca_protect_unit_move.lua', score = 94999 }
ai_id = 'mai_protect_unit',
{ ca_id = 'finish', location = CA_path .. 'ca_protect_unit_finish.lua', score = 300000 },
{ ca_id = 'attack', location = CA_path .. 'ca_protect_unit_attack.lua', score = 95000 },
{ ca_id = 'move', location = CA_path .. 'ca_protect_unit_move.lua', score = 94999 }
}
-- [unit] tags need to be dealt with separately
@ -195,7 +202,10 @@ function wesnoth.wml_actions.micro_ai(cfg)
end
required_keys = { "distance", "station_x", "station_y", "guard_x", "guard_y" }
optional_keys = { "id", "filter" }
CA_parms = { { ca_id = 'mai_stationed_guardian', location = CA_path .. 'ca_stationed_guardian.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_stationed_guardian',
{ ca_id = 'move', location = CA_path .. 'ca_stationed_guardian.lua', score = cfg.ca_score or 300000 }
}
elseif (cfg.ai_type == 'zone_guardian') then
if (cfg.action ~= 'delete') and (not cfg.id) and (not H.get_child(cfg, "filter")) then
@ -203,7 +213,10 @@ function wesnoth.wml_actions.micro_ai(cfg)
end
required_keys = { "filter_location" }
optional_keys = { "id", "filter", "filter_location_enemy", "station_x", "station_y" }
CA_parms = { { ca_id = 'mai_zone_guardian', location = CA_path .. 'ca_zone_guardian.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_zone_guardian',
{ ca_id = 'move', location = CA_path .. 'ca_zone_guardian.lua', score = cfg.ca_score or 300000 }
}
elseif (cfg.ai_type == 'return_guardian') then
if (cfg.action ~= 'delete') and (not cfg.id) and (not H.get_child(cfg, "filter")) then
@ -211,7 +224,10 @@ function wesnoth.wml_actions.micro_ai(cfg)
end
required_keys = { "return_x", "return_y" }
optional_keys = { "id", "filter" }
CA_parms = { { ca_id = 'mai_return_guardian', location = CA_path .. 'ca_return_guardian.lua', score = cfg.ca_score or 100010 } }
CA_parms = {
ai_id = 'mai_return_guardian',
{ ca_id = 'move', location = CA_path .. 'ca_return_guardian.lua', score = cfg.ca_score or 100010 }
}
elseif (cfg.ai_type == 'coward') then
if (cfg.action ~= 'delete') and (not cfg.id) and (not H.get_child(cfg, "filter")) then
@ -219,21 +235,28 @@ function wesnoth.wml_actions.micro_ai(cfg)
end
required_keys = { "distance" }
optional_keys = { "id", "filter", "filter_second", "seek_x", "seek_y","avoid_x","avoid_y" }
CA_parms = { { ca_id = 'mai_coward', location = CA_path .. 'ca_coward.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_coward',
{ ca_id = 'move', location = CA_path .. 'ca_coward.lua', score = cfg.ca_score or 300000 }
}
--------- Micro AI Animals ------------------------------------
elseif (cfg.ai_type == 'big_animals') then
required_keys = { "filter"}
optional_keys = { "avoid_unit", "filter_location", "filter_location_wander" }
CA_parms = { { ca_id = "mai_big_animals", location = CA_path .. 'ca_big_animals.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_big_animals',
{ ca_id = "move", location = CA_path .. 'ca_big_animals.lua', score = cfg.ca_score or 300000 }
}
elseif (cfg.ai_type == 'wolves') then
required_keys = { "filter", "filter_second" }
optional_keys = { "attack_only_prey", "avoid_type" }
local score = cfg.ca_score or 90000
CA_parms = {
{ ca_id = "mai_wolves_move", location = CA_path .. 'ca_wolves_move.lua', score = score },
{ ca_id = "mai_wolves_wander", location = CA_path .. 'ca_wolves_wander.lua', score = score - 1 }
ai_id = 'mai_wolves',
{ ca_id = "move", location = CA_path .. 'ca_wolves_move.lua', score = score },
{ ca_id = "wander", location = CA_path .. 'ca_wolves_wander.lua', score = score - 1 }
}
if cfg.attack_only_prey then
@ -283,12 +306,13 @@ function wesnoth.wml_actions.micro_ai(cfg)
optional_keys = { "attention_distance", "attack_distance" }
local score = cfg.ca_score or 300000
CA_parms = {
{ ca_id = "mai_herding_attack_close_enemy", location = CA_path .. 'ca_herding_attack_close_enemy.lua', score = score },
{ ca_id = "mai_herding_sheep_runs_enemy", location = CA_path .. 'ca_herding_sheep_runs_enemy.lua', score = score - 1 },
{ ca_id = "mai_herding_sheep_runs_dog", location = CA_path .. 'ca_herding_sheep_runs_dog.lua', score = score - 2 },
{ ca_id = "mai_herding_herd_sheep", location = CA_path .. 'ca_herding_herd_sheep.lua', score = score - 3 },
{ ca_id = "mai_herding_sheep_move", location = CA_path .. 'ca_herding_sheep_move.lua', score = score - 4 },
{ ca_id = "mai_herding_dog_move", location = CA_path .. 'ca_herding_dog_move.lua', score = score - 5 }
ai_id = 'mai_herding',
{ ca_id = "attack_close_enemy", location = CA_path .. 'ca_herding_attack_close_enemy.lua', score = score },
{ ca_id = "sheep_runs_enemy", location = CA_path .. 'ca_herding_sheep_runs_enemy.lua', score = score - 1 },
{ ca_id = "sheep_runs_dog", location = CA_path .. 'ca_herding_sheep_runs_dog.lua', score = score - 2 },
{ ca_id = "herd_sheep", location = CA_path .. 'ca_herding_herd_sheep.lua', score = score - 3 },
{ ca_id = "sheep_move", location = CA_path .. 'ca_herding_sheep_move.lua', score = score - 4 },
{ ca_id = "dog_move", location = CA_path .. 'ca_herding_dog_move.lua', score = score - 5 }
}
elseif (cfg.ai_type == 'forest_animals') then
@ -297,26 +321,29 @@ function wesnoth.wml_actions.micro_ai(cfg)
}
local score = cfg.ca_score or 300000
CA_parms = {
{ ca_id = "mai_forest_animals_new_rabbit", location = CA_path .. 'ca_forest_animals_new_rabbit.lua', score = score },
{ ca_id = "mai_forest_animals_tusker_attack", location = CA_path .. 'ca_forest_animals_tusker_attack.lua', score = score - 1 },
{ ca_id = "mai_forest_animals_move", location = CA_path .. 'ca_forest_animals_move.lua', score = score - 2 },
{ ca_id = "mai_forest_animals_tusklet_move", location = CA_path .. 'ca_forest_animals_tusklet_move.lua', score = score - 3 }
ai_id = 'mai_forest_animals',
{ ca_id = "new_rabbit", location = CA_path .. 'ca_forest_animals_new_rabbit.lua', score = score },
{ ca_id = "tusker_attack", location = CA_path .. 'ca_forest_animals_tusker_attack.lua', score = score - 1 },
{ ca_id = "move", location = CA_path .. 'ca_forest_animals_move.lua', score = score - 2 },
{ ca_id = "tusklet_move", location = CA_path .. 'ca_forest_animals_tusklet_move.lua', score = score - 3 }
}
elseif (cfg.ai_type == 'swarm') then
optional_keys = { "scatter_distance", "vision_distance", "enemy_distance" }
local score = cfg.ca_score or 300000
CA_parms = {
{ ca_id = "mai_swarm_scatter", location = CA_path .. 'ca_swarm_scatter.lua', score = score },
{ ca_id = "mai_swarm_move", location = CA_path .. 'ca_swarm_move.lua', score = score - 1 }
ai_id = 'mai_swarm',
{ ca_id = "scatter", location = CA_path .. 'ca_swarm_scatter.lua', score = score },
{ ca_id = "move", location = CA_path .. 'ca_swarm_move.lua', score = score - 1 }
}
elseif (cfg.ai_type == 'wolves_multipacks') then
optional_keys = { "type", "pack_size", "show_pack_number" }
local score = cfg.ca_score or 300000
CA_parms = {
{ ca_id = "mai_wolves_multipacks_attack", location = CA_path .. 'ca_wolves_multipacks_attack.lua', score = score },
{ ca_id = "mai_wolves_multipacks_wander", location = CA_path .. 'ca_wolves_multipacks_wander.lua', score = score - 1 }
ai_id = 'mai_wolves_multipacks',
{ ca_id = "attack", location = CA_path .. 'ca_wolves_multipacks_attack.lua', score = score },
{ ca_id = "wander", location = CA_path .. 'ca_wolves_multipacks_wander.lua', score = score - 1 }
}
elseif (cfg.ai_type == 'hunter') then
@ -325,7 +352,10 @@ function wesnoth.wml_actions.micro_ai(cfg)
end
required_keys = { "home_x", "home_y" }
optional_keys = { "id", "filter", "filter_location", "rest_turns", "show_messages" }
CA_parms = { { ca_id = "mai_hunter", location = CA_path .. 'ca_hunter.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_hunter',
{ ca_id = "move", location = CA_path .. 'ca_hunter.lua', score = cfg.ca_score or 300000 }
}
--------- Patrol Micro AI ------------------------------------
elseif (cfg.ai_type == 'patrol') then
@ -334,17 +364,26 @@ function wesnoth.wml_actions.micro_ai(cfg)
end
required_keys = { "waypoint_x", "waypoint_y" }
optional_keys = { "id", "filter", "attack", "one_time_only", "out_and_back" }
CA_parms = { { ca_id = "mai_patrol", location = CA_path .. 'ca_patrol.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_patrol',
{ ca_id = "move", location = CA_path .. 'ca_patrol.lua', score = cfg.ca_score or 300000 }
}
--------- Recruiting Micro AI ------------------------------------
elseif (cfg.ai_type == 'recruit_rushers') or (cfg.ai_type == 'recruit_random')then
if (cfg.ai_type == 'recruit_rushers') then
optional_keys = { "randomness" }
CA_parms = { { ca_id = "mai_rusher_recruit", location = CA_path .. 'ca_recruit_rushers.lua', score = cfg.ca_score or 180000 } }
CA_parms = {
ai_id = 'mai_rusher_recruit',
{ ca_id = "move", location = CA_path .. 'ca_recruit_rushers.lua', score = cfg.ca_score or 180000 }
}
else
optional_keys = { "skip_low_gold_recruiting", "type", "prob" }
CA_parms = { { ca_id = "mai_random_recruit", location = CA_path .. 'ca_recruit_random.lua', score = cfg.ca_score or 180000 } }
CA_parms = {
ai_id = 'mai_random_recruit',
{ ca_id = "move", location = CA_path .. 'ca_recruit_random.lua', score = cfg.ca_score or 180000 }
}
-- The 'probability' tags need to be handled separately here
cfg.type, cfg.prob = {}, {}
@ -391,17 +430,26 @@ function wesnoth.wml_actions.micro_ai(cfg)
"avoid_enemies", "filter", "ignore_units", "ignore_enemy_at_goal",
"release_all_units_at_goal", "release_unit_at_goal", "unique_goals", "use_straight_line"
}
CA_parms = { { ca_id = 'mai_goto', location = CA_path .. 'ca_goto.lua', score = cfg.ca_score or 300000 } }
CA_parms = {
ai_id = 'mai_goto',
{ ca_id = 'move', location = CA_path .. 'ca_goto.lua', score = cfg.ca_score or 300000 }
}
--------- Hang Out Micro AI ------------------------------------
elseif (cfg.ai_type == 'hang_out') then
optional_keys = { "filter", "filter_location", "avoid", "mobilize_condition", "mobilize_on_gold_less_than" }
CA_parms = { { ca_id = 'mai_hang_out', location = CA_path .. 'ca_hang_out.lua', score = cfg.ca_score or 170000 } }
CA_parms = {
ai_id = 'mai_hang_out',
{ ca_id = 'move', location = CA_path .. 'ca_hang_out.lua', score = cfg.ca_score or 170000 }
}
--------- Simple Attack Micro AI ---------------------------
elseif (cfg.ai_type == 'simple_attack') then
optional_keys = { "filter", "filter_second", "weapon" }
CA_parms = { { ca_id = 'mai_simple_attack', location = CA_path .. 'ca_simple_attack.lua', score = cfg.ca_score or 110000 } }
CA_parms = {
ai_id = 'mai_simple_attack',
{ ca_id = 'move', location = CA_path .. 'ca_simple_attack.lua', score = cfg.ca_score or 110000 }
}
-- If we got here, none of the valid ai_types was specified
else