AI retreat_injured CA: improve retreat threshold calculation
The main problem was that the previous calculation was based on the 'caution' aspect. While that is not technically wrong, caution is also used for other purposes and there are mainline (and presumably UMC) scenarios that use large values for caution. In those cases, units retreated that were barely injured. This, again, might even be desirable for some use cases, but it needs to be decoupled from the other uses of caution. Thus, the new 'retreat_factor' aspect is used now. In addition, the calculation is now based on a unit's maximum hitpoints, rather than its level.
This commit is contained in:
parent
efe5a4d497
commit
903e03d68a
2 changed files with 25 additions and 20 deletions
|
@ -12,7 +12,7 @@ function ca_retreat_injured:evaluation(cfg, data, filter_own)
|
|||
local start_time, ca_name = wesnoth.get_time_stamp() / 1000., 'retreat_injured'
|
||||
if AH.print_eval() then AH.print_ts(' - Evaluating retreat_injured CA:') end
|
||||
|
||||
if (ai.aspects.caution <= 0) then
|
||||
if (ai.aspects.retreat_factor <= 0) then
|
||||
if AH.print_eval() then AH.done_eval_messages(start_time, ca_name) end
|
||||
return 0
|
||||
end
|
||||
|
|
|
@ -7,40 +7,45 @@ local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
|||
local BC = wesnoth.require "ai/lua/battle_calcs.lua"
|
||||
local LS = wesnoth.require "location_set"
|
||||
|
||||
local function print_dbg(...)
|
||||
local show_debug_info = false -- manually set to true/false depending on whether output is desired
|
||||
if wesnoth.game_config.debug and show_debug_info then
|
||||
std_print('Retreat debug: ', ...)
|
||||
end
|
||||
end
|
||||
|
||||
local retreat_functions = {}
|
||||
|
||||
function retreat_functions.min_hp(unit)
|
||||
-- The minimum hp to retreat is a function of level and terrain defense
|
||||
-- We want to stay longer on good terrain and leave early on very bad terrain
|
||||
-- The minimum hp to retreat is a function of hitpoints and terrain defense
|
||||
-- We want to stay longer on good terrain and leave early on bad terrain
|
||||
-- It can be influenced by the 'retreat_factor' AI aspect
|
||||
|
||||
-- Take caution into account here. We want the multiplier to be:
|
||||
-- 1 for default caution (0.25)
|
||||
-- 0 for minimal caution <= 0
|
||||
-- 2 for caution = 1
|
||||
local caution_factor = ai.aspects.caution
|
||||
if (caution_factor < 0) then caution_factor = 0 end
|
||||
caution_factor = math.sqrt(caution_factor) * 2
|
||||
local retreat_factor = ai.aspects.retreat_factor
|
||||
|
||||
local hp_per_level = (100 - unit:defense_on(wesnoth.get_terrain(unit.x, unit.y)))/15 * caution_factor
|
||||
local level = unit.level
|
||||
-- Leaders are more valuable and should retreat earlier
|
||||
if unit.canrecruit then retreat_factor = retreat_factor * 1.5 end
|
||||
|
||||
-- Leaders are considered to be higher level because of their value
|
||||
if unit.canrecruit then level = level+2 end
|
||||
-- Higher retreat willingness on bad terrain
|
||||
local retreat_factor = retreat_factor * (100 - unit:defense_on(wesnoth.get_terrain(unit.x, unit.y))) / 50
|
||||
|
||||
local min_hp = hp_per_level*(level+2)
|
||||
local min_hp = retreat_factor * unit.max_hitpoints
|
||||
|
||||
-- Account for poison damage on next turn
|
||||
if unit.status.poisoned then min_hp = min_hp + wesnoth.game_config.poison_amount end
|
||||
|
||||
-- Make sure that units are actually injured (only relevant for low-HP units)
|
||||
-- Want this to be roughly half the units HP at caution=0, close to full HP at caution=1
|
||||
local hp_factor = 0.5 + 0.25 * caution_factor
|
||||
if (hp_factor > 1) then hp_factor = 1 end
|
||||
local max_min_hp = (unit.max_hitpoints - 4) * hp_factor
|
||||
-- Large values of retreat_factor could cause fully healthy units to retreat.
|
||||
-- We require a unit to be down more than 10 HP, or half its HP for units with less than 20 max_HP.
|
||||
local max_hp = unit.max_hitpoints
|
||||
local max_min_hp = math.max(max_hp - 10, max_hp / 2)
|
||||
if (min_hp > max_min_hp) then
|
||||
min_hp = max_min_hp
|
||||
end
|
||||
|
||||
local retreat_str = ''
|
||||
if (unit.hitpoints < min_hp) then retreat_str = ' --> retreat' end
|
||||
print_dbg(string.format('%20s %3d/%-3d HP threshold: %5.1f HP%s', unit.id, unit.hitpoints, unit.max_hitpoints, min_hp, retreat_str))
|
||||
|
||||
return min_hp
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue