Skip to content

Commit

Permalink
Merge branch 'master' of github.com:wesnoth/wesnoth
Browse files Browse the repository at this point in the history
  • Loading branch information
AI0867 committed Mar 30, 2014
2 parents cad98a3 + e9d42a9 commit 0170b53
Show file tree
Hide file tree
Showing 36 changed files with 1,213 additions and 1,348 deletions.
5 changes: 4 additions & 1 deletion changelog
Expand Up @@ -13,7 +13,7 @@ Version 1.13.0-dev:
* C++ Engine:
* Purge "human_ai" controller type. This is a fixup of bugfix #18829 below.
* Language and i18n:
* Updated translations: German, Greek, Scottish Gaelic, Slovak
* Updated translations: German, Greek, Hungarian, Scottish Gaelic, Slovak
* Lua API:
* Fix bug #21761: wesnoth.synchronize_choice will now give a warning when
the table returned by the user-specified function is not completely valid,
Expand Down Expand Up @@ -50,6 +50,9 @@ Version 1.13.0-dev:
* Fix bug #21257: Lagging animations with skip AI animations and fog/shroud.
* Improved unicode handling on windows for characters outside the Basic
Multilingual Plane.
* Fix bug #3856: The turn dialog used in hotseat MP play now applies
a blindfold for the duration of the dialog.
* Petrified units are no longer displayed in the "Damage versus" tooltip.

Version 1.11.11:
* Add-ons server:
Expand Down
3 changes: 2 additions & 1 deletion data/ai/lua/ai_helper.lua
Expand Up @@ -485,14 +485,15 @@ function ai_helper.get_closest_location(hex, location_filter, unit)
if (radius == 0) then
loc_filter = {
{ "and", { x = hex[1], y = hex[2], radius = radius } },
{ "and", location_filter }
}
else
loc_filter = {
{ "and", { x = hex[1], y = hex[2], radius = radius } },
{ "not", { x = hex[1], y = hex[2], radius = radius - 1 } },
{ "and", location_filter }
}
end
for k,v in pairs(location_filter) do loc_filter[k] = v end

local locs = wesnoth.get_locations(loc_filter)

Expand Down
39 changes: 13 additions & 26 deletions data/ai/micro_ais/cas/ca_coward.lua
Expand Up @@ -4,35 +4,25 @@ local AH = wesnoth.require "ai/lua/ai_helper.lua"
local ca_coward = {}

function ca_coward:evaluation(ai, cfg)
local unit
if cfg.filter then
unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", cfg.filter },
formula = '$this_unit.moves > 0' }
)[1]
else
unit = wesnoth.get_units({ id = cfg.id, formula = '$this_unit.moves > 0' })[1]
end
local filter = cfg.filter or { id = cfg.id }
local unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", filter },
formula = '$this_unit.moves > 0' }
)[1]

-- Check if unit exists as sticky BCAs are not always removed successfully
if unit then return cfg.ca_score end
return 0
end

-- cfg parameters: id, distance, seek_x, seek_y, avoid_x, avoid_y
function ca_coward:execution(ai, cfg)
--print("Coward exec " .. cfg.id)
local unit
if cfg.filter then
unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", cfg.filter },
formula = '$this_unit.moves > 0' }
)[1]
else
unit = wesnoth.get_units({ id = cfg.id, formula = '$this_unit.moves > 0' })[1]
end
local filter = cfg.filter or { id = cfg.id }
local unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", filter },
formula = '$this_unit.moves > 0' }
)[1]

local reach = wesnoth.find_reach(unit)

Expand Down Expand Up @@ -112,10 +102,7 @@ function ca_coward:execution(ai, cfg)
end
--items.place_image(mx, my, "items/ring-gold.png")

-- (mx,my) is the position to move to
if (mx ~= unit.x or my ~= unit.y) then
AH.movefull_stopunit(ai, unit, mx, my)
end
AH.movefull_stopunit(ai, unit, mx, my)
if (not unit) or (not unit.valid) then return end

AH.checked_stopunit_all(ai, unit)
Expand Down
2 changes: 1 addition & 1 deletion data/ai/micro_ais/cas/ca_goto.lua
Expand Up @@ -157,7 +157,7 @@ function ca_goto:execution(ai, cfg, self)
-- Add a small penalty for occupied hexes
-- (this mean occupied by an allied unit, as enemies make the hex unreachable)
local unit_in_way = wesnoth.get_unit(l[1], l[2])
if unit_in_way and ((unit_in_way.x ~= u.x) or (unit_in_way.y ~= u.y)) then
if unit_in_way and (unit_in_way ~= u) then
rating = rating - 0.01
end

Expand Down
2 changes: 1 addition & 1 deletion data/ai/micro_ais/cas/ca_healer_move.lua
Expand Up @@ -87,7 +87,7 @@ function ca_healer_move:evaluation(ai, cfg, self)
-- Also, hex must be unoccupied by another unit, of course
local unit_in_way = wesnoth.get_unit(r[1], r[2])
if (not avoid_map:get(r[1], r[2])) then
if (not unit_in_way) or ((unit_in_way.x == h.x) and (unit_in_way.y == h.y)) then
if (not unit_in_way) or (unit_in_way == h) then
for k,u in ipairs(healees) do
if (H.distance_between(u.x, u.y, r[1], r[2]) == 1) then
-- !!!!!!! These ratings have to be positive or the method doesn't work !!!!!!!!!
Expand Down
33 changes: 12 additions & 21 deletions data/ai/micro_ais/cas/ca_hunter.lua
Expand Up @@ -39,16 +39,12 @@ local function hunter_attack_weakest_adj_enemy(ai, unit)
end

function ca_hunter:evaluation(ai, cfg)
local unit
if cfg.filter then
unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", cfg.filter },
formula = '$this_unit.moves > 0' }
)[1]
else
unit = wesnoth.get_units({ id = cfg.id, formula = '$this_unit.moves > 0' })[1]
end
local filter = cfg.filter or { id = cfg.id }
local unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", filter },
formula = '$this_unit.moves > 0' }
)[1]

if unit then return cfg.ca_score end
return 0
Expand All @@ -60,17 +56,12 @@ function ca_hunter:execution(ai, cfg)
-- hunting_ground, then retreats to
-- position given by 'home_x,home_y' for 'rest_turns' turns, or until fully healed

local unit
if cfg.filter then
unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", cfg.filter },
formula = '$this_unit.moves > 0' }
)[1]
else
unit = wesnoth.get_units({ id = cfg.id, formula = '$this_unit.moves > 0' })[1]
end
--print('Hunter: ', unit.id)
local filter = cfg.filter or { id = cfg.id }
local unit = wesnoth.get_units({
side = wesnoth.current.side,
{ "and", filter },
formula = '$this_unit.moves > 0' }
)[1]

-- If hunting_status is not set for the unit -> default behavior -> hunting
if (not unit.variables.hunting_status) then
Expand Down
19 changes: 10 additions & 9 deletions data/ai/micro_ais/cas/ca_messenger_attack.lua
Expand Up @@ -53,7 +53,7 @@ local function messenger_find_enemies_in_way(unit, goal_x, goal_y)
return
end

local function messenger_find_clearing_attack(unit, goal_x, goal_y)
local function messenger_find_clearing_attack(unit, goal_x, goal_y, cfg)
-- Check if an enemy is in the way of the messenger
-- If so, find attack that would "clear" that enemy out of the way
-- unit: proxy table for the messenger unit
Expand All @@ -68,8 +68,12 @@ local function messenger_find_clearing_attack(unit, goal_x, goal_y)
--print('Finding attacks on',enemy_in_way.name,enemy_in_way.id)

-- Find all units that can attack this enemy
local my_units = wesnoth.get_units{ side = wesnoth.current.side, formula = '$this_unit.attacks_left > 0',
{ "not", { id = unit.id } }
local filter = cfg.filter or { id = cfg.id }
local my_units = wesnoth.get_units {
side = wesnoth.current.side,
formula = '$this_unit.attacks_left > 0',
{ "not", filter },
{ "and", cfg.filter_second }
}

-- Eliminate units without attacks
Expand Down Expand Up @@ -131,17 +135,14 @@ local function messenger_find_clearing_attack(unit, goal_x, goal_y)
end

function ca_messenger_attack:evaluation(ai, cfg, self)
-- Attack units in the path of the messenger
-- id: id of the messenger unit
-- Attack units in the path of the messengers
-- goal_x, goal_y: coordinates of the goal toward which the messenger moves

local messenger = wesnoth.get_units{ side = wesnoth.current.side, id = cfg.id }[1]
local messenger, x, y = messenger_next_waypoint(cfg)
if (not messenger) then return 0 end

local x, y = messenger_next_waypoint(messenger, cfg, self)

-- See if there's an enemy in the way that should be attacked
local attack = messenger_find_clearing_attack(messenger, x, y)
local attack = messenger_find_clearing_attack(messenger, x, y, cfg)

if attack then
self.data.best_attack = attack
Expand Down
113 changes: 72 additions & 41 deletions data/ai/micro_ais/cas/ca_messenger_escort_move.lua
@@ -1,61 +1,92 @@
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 ca_messenger_escort_move = {}

local messenger_next_waypoint = wesnoth.require "ai/micro_ais/cas/ca_messenger_f_next_waypoint.lua"

function ca_messenger_escort_move:evaluation(ai, cfg)
-- Move escort units close to messenger, and in between messenger and enemies
-- The messenger has moved at this time, so we don't need to exclude him
-- But we check that he exist (not for this scenario, but for others)
local messenger = wesnoth.get_units{ side = wesnoth.current.side, id = cfg.id }[1]
if (not messenger) then return 0 end
-- Move escort units close to messengers, and in between messengers and enemies
-- The messengers have moved at this time, so we don't need to exclude them,
-- but we check that there are messengers left

local my_units = wesnoth.get_units{ side = wesnoth.current.side, formula = '$this_unit.moves > 0' }
local my_units = wesnoth.get_units {
side = wesnoth.current.side,
formula = '$this_unit.moves > 0',
{ "and", cfg.filter_second }
}
if (not my_units[1]) then return 0 end

if my_units[1] then
return cfg.ca_score
end
return 0
local _, _, _, messengers = messenger_next_waypoint(cfg)
if (not messengers) or (not messengers[1]) then return 0 end

return cfg.ca_score
end

function ca_messenger_escort_move:execution(ai, cfg)
local messenger = wesnoth.get_units{ id = cfg.id }[1]
local my_units = wesnoth.get_units{ side = wesnoth.current.side, formula = '$this_unit.moves > 0' }

-- Simply move units one at a time
local next_unit = my_units[1]
local reach = LS.of_pairs(wesnoth.find_reach(next_unit))
local my_units = wesnoth.get_units {
side = wesnoth.current.side,
formula = '$this_unit.moves > 0',
{ "and", cfg.filter_second }
}

-- Distance from messenger for each hex the unit can reach
local dist_messenger = AH.distance_map({messenger}, reach)
local _, _, _, messengers = messenger_next_waypoint(cfg)

local enemies = wesnoth.get_units {
{ "filter_side", {{"enemy_of", {side = wesnoth.current.side} }} }
}

-- Rating (in the end, we pick the _minimum _rating):
-- 1. Minimize distance from enemies
local rating = AH.distance_map(enemies, reach)
-- 2. This one favors hexes in between messenger and enemies
rating:union_merge(dist_messenger, function(x, y, v1, v2)
return v1 + v2*#enemies
end)
-- 3. Strongly prefer hexes close to the messenger
rating:union_merge(dist_messenger, function(x, y, v1, v2)
return v1 + v2^2
end)
--AH.put_labels(rating)

-- Now find hex with minimum value that is unoccupied
min_rating, best_hex = 9e99, {}
rating:iter(function(x, y, r)
local unit_in_way = wesnoth.get_units{ x = x, y = y, { "not", { id = next_unit.id } } }[1]
if (not unit_in_way) and (r < min_rating) then
min_rating, best_hex = r, { x, y }
end
end)
-- and move the unit there
AH.movefull_stopunit(ai, next_unit, best_hex)
local base_rating_map = LS.create()
local max_rating, best_unit, best_hex = -9e99
for _,unit in ipairs(my_units) do
-- Only considering hexes unoccupied by other units is good enough for this
local reach_map = AH.get_reachable_unocc(unit)

-- Minor rating for the fastest and strongest unit to go first
local unit_rating = unit.max_moves / 100. + unit.hitpoints / 1000.

reach_map:iter( function(x, y, v)
-- base rating only needs to be calculated once for each hex
local base_rating = base_rating_map:get(x, y)

if (not base_rating) then
base_rating = 0

-- Distance from messenger is most important; only closest messenger counts for this
-- Give somewhat of a bonus for the messenger that has moved the most through the waypoints
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.)

if (messenger_rating > max_messenger_rating) then
max_messenger_rating = messenger_rating
end
end
base_rating = base_rating + max_messenger_rating

-- Distance from (sum of) enemies is important too
-- This favors placing escort units between the messenger and close enemies
for _,e in ipairs(enemies) do
base_rating = base_rating + 1. / (H.distance_between(x, y, e.x, e.y) + 2.)
end

base_rating_map:insert(x, y, base_rating)
end

local rating = base_rating + unit_rating

if (rating > max_rating) then
max_rating = rating
best_unit, best_hex = unit, { x, y }
end
end)
end
--AH.put_labels(base_rating_map)

-- This will always find at least the hex the unit is on -> no check necessary
AH.movefull_stopunit(ai, best_unit, best_hex)
end

return ca_messenger_escort_move

0 comments on commit 0170b53

Please sign in to comment.