Lua AIs: replace tabs with spaces

(cherry-picked from commit 45a3bf9363)
This commit is contained in:
mattsc 2018-09-02 15:08:24 -07:00
parent ed406495d7
commit c52ce11e49
4 changed files with 174 additions and 174 deletions

View file

@ -7,200 +7,200 @@ local CS_leader_score
-- Note that leader_target is also needed by the recruiting CA, so it must be stored in 'data'
local function get_reachable_enemy_leaders(unit)
-- We're cheating a little here and also find hidden enemy leaders. That's
-- because a human player could make a pretty good educated guess as to where
-- the enemy leaders are likely to be while the AI does not know how to do that.
local potential_enemy_leaders = AH.get_live_units { canrecruit = 'yes',
{ "filter_side", { { "enemy_of", {side = wesnoth.current.side} } } }
}
local enemy_leaders = {}
for j,e in ipairs(potential_enemy_leaders) do
local path, cost = wesnoth.find_path(unit, e.x, e.y, { ignore_units = true, viewing_side = 0 })
if cost < AH.no_path then
table.insert(enemy_leaders, e)
end
end
-- We're cheating a little here and also find hidden enemy leaders. That's
-- because a human player could make a pretty good educated guess as to where
-- the enemy leaders are likely to be while the AI does not know how to do that.
local potential_enemy_leaders = AH.get_live_units { canrecruit = 'yes',
{ "filter_side", { { "enemy_of", {side = wesnoth.current.side} } } }
}
local enemy_leaders = {}
for j,e in ipairs(potential_enemy_leaders) do
local path, cost = wesnoth.find_path(unit, e.x, e.y, { ignore_units = true, viewing_side = 0 })
if cost < AH.no_path then
table.insert(enemy_leaders, e)
end
end
return enemy_leaders
return enemy_leaders
end
local ca_castle_switch = {}
function ca_castle_switch:evaluation(cfg, data)
local start_time, ca_name = wesnoth.get_time_stamp() / 1000., 'castle_switch'
if AH.print_eval() then AH.print_ts(' - Evaluating castle_switch CA:') end
local start_time, ca_name = wesnoth.get_time_stamp() / 1000., 'castle_switch'
if AH.print_eval() then AH.print_ts(' - Evaluating castle_switch CA:') end
if ai.aspects.passive_leader then
-- Turn off this CA if the leader is passive
return 0
end
if ai.aspects.passive_leader then
-- Turn off this CA if the leader is passive
return 0
end
local leader = wesnoth.get_units {
side = wesnoth.current.side,
canrecruit = 'yes',
formula = '(movement_left = total_movement) and (hitpoints = max_hitpoints)'
}[1]
if not leader then
-- CA is irrelevant if no leader or the leader may have moved from another CA
data.leader_target = nil
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return 0
end
local leader = wesnoth.get_units {
side = wesnoth.current.side,
canrecruit = 'yes',
formula = '(movement_left = total_movement) and (hitpoints = max_hitpoints)'
}[1]
if not leader then
-- CA is irrelevant if no leader or the leader may have moved from another CA
data.leader_target = nil
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return 0
end
local cheapest_unit_cost = AH.get_cheapest_recruit_cost()
local cheapest_unit_cost = AH.get_cheapest_recruit_cost()
if data.leader_target and wesnoth.sides[wesnoth.current.side].gold >= cheapest_unit_cost then
-- make sure move is still valid
local next_hop = AH.next_hop(leader, data.leader_target[1], data.leader_target[2])
if next_hop and next_hop[1] == data.leader_target[1]
and next_hop[2] == data.leader_target[2] then
return CS_leader_score
end
end
if data.leader_target and wesnoth.sides[wesnoth.current.side].gold >= cheapest_unit_cost then
-- make sure move is still valid
local next_hop = AH.next_hop(leader, data.leader_target[1], data.leader_target[2])
if next_hop and next_hop[1] == data.leader_target[1]
and next_hop[2] == data.leader_target[2] then
return CS_leader_score
end
end
local width,height,border = wesnoth.get_map_size()
local keeps = wesnoth.get_locations {
terrain = 'K*,K*^*,*^K*', -- Keeps
x = '1-'..width,
y = '1-'..height,
{ "not", { {"filter", {}} }}, -- That have no unit
{ "not", { radius = 6, {"filter", { canrecruit = 'yes',
{ "filter_side", { { "enemy_of", {side = wesnoth.current.side} } } }
}} }}, -- That are not too close to an enemy leader
{ "not", {
x = leader.x, y = leader.y, terrain = 'K*,K*^*,*^K*',
radius = 3,
{ "filter_radius", { terrain = 'C*,K*,C*^*,K*^*,*^K*,*^C*' } }
}}, -- That are not close and connected to a keep the leader is on
{ "filter_adjacent_location", {
terrain = 'C*,K*,C*^*,K*^*,*^K*,*^C*'
}} -- That are not one-hex keeps
}
if #keeps < 1 then
-- Skip if there aren't extra keeps to evaluate
-- In this situation we'd only switch keeps if we were running away
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return 0
end
local width,height,border = wesnoth.get_map_size()
local keeps = wesnoth.get_locations {
terrain = 'K*,K*^*,*^K*', -- Keeps
x = '1-'..width,
y = '1-'..height,
{ "not", { {"filter", {}} }}, -- That have no unit
{ "not", { radius = 6, {"filter", { canrecruit = 'yes',
{ "filter_side", { { "enemy_of", {side = wesnoth.current.side} } } }
}} }}, -- That are not too close to an enemy leader
{ "not", {
x = leader.x, y = leader.y, terrain = 'K*,K*^*,*^K*',
radius = 3,
{ "filter_radius", { terrain = 'C*,K*,C*^*,K*^*,*^K*,*^C*' } }
}}, -- That are not close and connected to a keep the leader is on
{ "filter_adjacent_location", {
terrain = 'C*,K*,C*^*,K*^*,*^K*,*^C*'
}} -- That are not one-hex keeps
}
if #keeps < 1 then
-- Skip if there aren't extra keeps to evaluate
-- In this situation we'd only switch keeps if we were running away
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return 0
end
local enemy_leaders = get_reachable_enemy_leaders(leader)
local enemy_leaders = get_reachable_enemy_leaders(leader)
-- Look for the best keep
local best_score, best_loc, best_turns = 0, {}, 3
for i,loc in ipairs(keeps) do
-- Only consider keeps within 2 turns movement
local path, cost = wesnoth.find_path(leader, loc[1], loc[2])
local score = 0
-- Prefer closer keeps to enemy
local turns = math.ceil(cost/leader.max_moves)
if turns <= 2 then
score = 1/turns
for j,e in ipairs(enemy_leaders) do
score = score + 1 / M.distance_between(loc[1], loc[2], e.x, e.y)
end
-- Look for the best keep
local best_score, best_loc, best_turns = 0, {}, 3
for i,loc in ipairs(keeps) do
-- Only consider keeps within 2 turns movement
local path, cost = wesnoth.find_path(leader, loc[1], loc[2])
local score = 0
-- Prefer closer keeps to enemy
local turns = math.ceil(cost/leader.max_moves)
if turns <= 2 then
score = 1/turns
for j,e in ipairs(enemy_leaders) do
score = score + 1 / M.distance_between(loc[1], loc[2], e.x, e.y)
end
if score > best_score then
best_score = score
best_loc = loc
best_turns = turns
end
end
end
if score > best_score then
best_score = score
best_loc = loc
best_turns = turns
end
end
end
-- If we're on a keep,
-- don't move to another keep unless it's much better when uncaptured villages are present
if best_score > 0 and wesnoth.get_terrain_info(wesnoth.get_terrain(leader.x, leader.y)).keep then
local close_unowned_village = (wesnoth.get_villages {
{ "and", {
x = leader.x,
y = leader.y,
radius = leader.max_moves
}},
owner_side = 0
})[1]
if close_unowned_village then
local score = 1/best_turns
for j,e in ipairs(enemy_leaders) do
-- count all distances as three less than they actually are
score = score + 1 / (M.distance_between(leader.x, leader.y, e.x, e.y) - 3)
end
-- If we're on a keep,
-- don't move to another keep unless it's much better when uncaptured villages are present
if best_score > 0 and wesnoth.get_terrain_info(wesnoth.get_terrain(leader.x, leader.y)).keep then
local close_unowned_village = (wesnoth.get_villages {
{ "and", {
x = leader.x,
y = leader.y,
radius = leader.max_moves
}},
owner_side = 0
})[1]
if close_unowned_village then
local score = 1/best_turns
for j,e in ipairs(enemy_leaders) do
-- count all distances as three less than they actually are
score = score + 1 / (M.distance_between(leader.x, leader.y, e.x, e.y) - 3)
end
if score > best_score then
best_score = 0
end
end
end
if score > best_score then
best_score = 0
end
end
end
if best_score > 0 then
local next_hop = AH.next_hop(leader, best_loc[1], best_loc[2])
if best_score > 0 then
local next_hop = AH.next_hop(leader, best_loc[1], best_loc[2])
if next_hop and ((next_hop[1] ~= leader.x) or (next_hop[2] ~= leader.y)) then
-- See if there is a nearby village that can be captured without delaying progress
local close_villages = wesnoth.get_villages( {
{ "and", { x = next_hop[1], y = next_hop[2], radius = leader.max_moves }},
owner_side = 0 })
for i,loc in ipairs(close_villages) do
local path_village, cost_village = wesnoth.find_path(leader, loc[1], loc[2])
if cost_village <= leader.moves then
local dummy_leader = leader:clone()
dummy_leader.x = loc[1]
dummy_leader.y = loc[2]
local path_keep, cost_keep = wesnoth.find_path(dummy_leader, best_loc[1], best_loc[2])
local turns_from_keep = math.ceil(cost_keep/leader.max_moves)
if turns_from_keep < best_turns
or (turns_from_keep == 1 and wesnoth.sides[wesnoth.current.side].gold < cheapest_unit_cost)
then
-- There is, go there instead
next_hop = loc
break
end
end
end
end
if next_hop and ((next_hop[1] ~= leader.x) or (next_hop[2] ~= leader.y)) then
-- See if there is a nearby village that can be captured without delaying progress
local close_villages = wesnoth.get_villages( {
{ "and", { x = next_hop[1], y = next_hop[2], radius = leader.max_moves }},
owner_side = 0 })
for i,loc in ipairs(close_villages) do
local path_village, cost_village = wesnoth.find_path(leader, loc[1], loc[2])
if cost_village <= leader.moves then
local dummy_leader = leader:clone()
dummy_leader.x = loc[1]
dummy_leader.y = loc[2]
local path_keep, cost_keep = wesnoth.find_path(dummy_leader, best_loc[1], best_loc[2])
local turns_from_keep = math.ceil(cost_keep/leader.max_moves)
if turns_from_keep < best_turns
or (turns_from_keep == 1 and wesnoth.sides[wesnoth.current.side].gold < cheapest_unit_cost)
then
-- There is, go there instead
next_hop = loc
break
end
end
end
end
data.leader_target = next_hop
data.leader_target = next_hop
-- if we're on a keep, wait until there are no movable units on the castle before moving off
CS_leader_score = 290000
if wesnoth.get_terrain_info(wesnoth.get_terrain(leader.x, leader.y)).keep then
local castle = wesnoth.get_locations {
x = "1-"..width, y = "1-"..height,
{ "and", {
x = leader.x, y = leader.y, radius = 200,
{ "filter_radius", { terrain = 'C*,K*,C*^*,K*^*,*^K*,*^C*' } }
}}
}
local should_wait = false
for i,loc in ipairs(castle) do
local unit = wesnoth.get_unit(loc[1], loc[2])
if (not AH.is_visible_unit(wesnoth.current.side, unit)) then
should_wait = false
break
elseif unit.moves > 0 then
should_wait = true
end
end
if should_wait then
CS_leader_score = 15000
end
end
-- if we're on a keep, wait until there are no movable units on the castle before moving off
CS_leader_score = 290000
if wesnoth.get_terrain_info(wesnoth.get_terrain(leader.x, leader.y)).keep then
local castle = wesnoth.get_locations {
x = "1-"..width, y = "1-"..height,
{ "and", {
x = leader.x, y = leader.y, radius = 200,
{ "filter_radius", { terrain = 'C*,K*,C*^*,K*^*,*^K*,*^C*' } }
}}
}
local should_wait = false
for i,loc in ipairs(castle) do
local unit = wesnoth.get_unit(loc[1], loc[2])
if (not AH.is_visible_unit(wesnoth.current.side, unit)) then
should_wait = false
break
elseif unit.moves > 0 then
should_wait = true
end
end
if should_wait then
CS_leader_score = 15000
end
end
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return CS_leader_score
end
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return CS_leader_score
end
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return 0
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
return 0
end
function ca_castle_switch:execution(cfg, data)
local leader = wesnoth.get_units { side = wesnoth.current.side, canrecruit = 'yes' }[1]
local leader = wesnoth.get_units { side = wesnoth.current.side, canrecruit = 'yes' }[1]
if AH.print_exec() then AH.print_ts(' Executing castle_switch CA') end
if AH.show_messages() then wesnoth.wml_actions.message { speaker = leader.id, message = 'Switching castles' } end
if AH.print_exec() then AH.print_ts(' Executing castle_switch CA') end
if AH.show_messages() then wesnoth.wml_actions.message { speaker = leader.id, message = 'Switching castles' } end
AH.checked_move(ai, leader, data.leader_target[1], data.leader_target[2])
data.leader_target = nil
AH.checked_move(ai, leader, data.leader_target[1], data.leader_target[2])
data.leader_target = nil
end
return ca_castle_switch

View file

@ -155,7 +155,7 @@ function ca_forest_animals_move:execution(cfg)
-- If this is a rabbit ending on a hole -> disappears
if (unit.type == rabbit_type) and hole_map:get(farthest_hex[1], farthest_hex[2]) then
wesnoth.invoke_synced_command("rabbit_despawn", { x = farthest_hex[1], y = farthest_hex[2]})
wesnoth.invoke_synced_command("rabbit_despawn", { x = farthest_hex[1], y = farthest_hex[2]})
end
end

View file

@ -56,7 +56,7 @@ function ca_forest_animals_new_rabbit:execution(cfg)
x, y = wesnoth.find_vacant_tile(holes[i].x, holes[i].y)
end
wesnoth.invoke_synced_command("rabbit_spawn", { rabbit_type = cfg.rabbit_type, x = x, y = y})
wesnoth.invoke_synced_command("rabbit_spawn", { rabbit_type = cfg.rabbit_type, x = x, y = y})
end
if wesnoth.sides[wesnoth.current.side].shroud then

View file

@ -110,12 +110,12 @@ function ca_transport:execution()
-- Also unload units
table.sort(best_adj_tiles, function(a, b) return a[3] > b[3] end)
local command_data = { x = best_unit.x, y = best_unit.y }
for i = 1, math.min(#best_adj_tiles, 3) do
table.insert(command_data, T.dst { x = best_adj_tiles[i][1], y = best_adj_tiles[i][2]} )
end
local command_data = { x = best_unit.x, y = best_unit.y }
for i = 1, math.min(#best_adj_tiles, 3) do
table.insert(command_data, T.dst { x = best_adj_tiles[i][1], y = best_adj_tiles[i][2]} )
end
wesnoth.invoke_synced_command("ship_unload", command_data)
wesnoth.invoke_synced_command("ship_unload", command_data)
return
end