Order of AI moves
Moderator: Forum Moderators
Forum rules
- Please use [code] BBCode tags in your posts for embedding WML snippets.
- To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Order of AI moves
Hi,
I have an AI side with nine units.
I would like to make a specific unit out of the nine be the last one to move, always. How can it be done?
I have an AI side with nine units.
I would like to make a specific unit out of the nine be the last one to move, always. How can it be done?
- Lord-Knightmare
- Discord Moderator
- Posts: 2361
- Joined: May 24th, 2010, 5:26 pm
- Location: Somewhere in the depths of Irdya, gathering my army to eventually destroy the known world.
- Contact:
Re: Order of AI moves
Maybe assign the CA score of that said unit with the lowest value? like 50? That unit will be at the bottom of the move list then.
Creator of "War of Legends"
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
Re: Order of AI moves
That doesn't work. It executed the move CA which is at 20,000 instead.
Here is the example that I'm working with. I want Peasant_4 to be the last one to move.
(The mod should be call Bug_Tester for the path to work)
Here is the example that I'm working with. I want Peasant_4 to be the last one to move.
(The mod should be call Bug_Tester for the path to work)
Code: Select all
[campaign]
id=Tester
rank=1
icon="units/human-magi/red-mage-attack-magic-2.png~RC(magenta>red)"
image="story/landscape-coast.jpg~SCALE(360,270)"
name= _ "Tester ai order"
abbrev= _ "TEST"
first_scenario=The_Scenario
define=CAMPAIGN_TESTER
[/campaign]
#ifdef CAMPAIGN_TESTER
[lua]
code= <<
local helper = wesnoth.require "lua/helper.lua"
local LS = wesnoth.require "location_set"
local utils = wesnoth.require "wml-utils"
>>
[/lua]
[scenario]
name= _ "The Scenario"
id=The_Scenario
map_data="Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Gg
Gg, Gg, Xu, 2 Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, 1 Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, 3 Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg"
{DEFAULT_MUSIC_PLAYLIST}
{DEFAULT_SCHEDULE}
next_scenario=null
victory_when_enemies_defeated=no
turns = -1
[side]
side=1
type=Peasant
id=Harry
team_name=allies
user_team_name=allies
suppress_end_turn_confirmation = yes
controller=human
recruit=
gold=500
[/side]
[side]
side=2
controller=ai
no_leader=yes
team_name=badguys
user_team_name=badguys
recruit=
gold=500
[ai]
{MODIFY_AI_ADD_CANDIDATE_ACTION 1 main_loop (
[candidate_action]
engine=lua
name=return_guardian_bob
id=return_guardian_bob
max_score=20010
location="~add-ons/Bug_Tester/return_guardian.lua"
[args]
id=Peasant_4
return_x=9
return_y=3
[/args]
# In the older syntax, the above would have looked like this:
#eval_parms="id = 'Peasant_4', return_x = 9, return_y = 3"
#exec_parms="id = 'Peasant_4', return_x = 9, return_y = 3"
[/candidate_action]
)}
[/ai]
[/side]
[side]
side=3
controller=ai
no_leader=yes
team_name=allies
user_team_name=allies
[ai]
ai_algorithm=idle_ai
[/ai]
recruit=
gold=500
[/side]
[event]
name=prestart
#define MY_UNIT SIDE TYPE X Y WML
[label]
x={X}
y={Y}
text={WML}
[/label]
[unit]
side={SIDE}
type={TYPE}
x={X}
y={Y}
random_traits=no
random_gender=no
generate_name=no
name={WML}
id={WML}
[/unit]
#enddef
{MY_UNIT 2 Peasant 3 4 Peasant_1}
{MY_UNIT 2 Peasant 5 4 Peasant_2}
{MY_UNIT 2 Peasant 7 4 Peasant_3}
{MY_UNIT 2 Peasant 9 4 Peasant_4}
{MY_UNIT 2 Peasant 11 4 Peasant_5}
{MY_UNIT 2 Peasant 13 4 Peasant_6}
{MY_UNIT 2 Peasant 15 4 Peasant_7}
{MY_UNIT 2 Peasant 17 4 Peasant_8}
{MY_UNIT 2 Peasant 19 4 Peasant_9}
[/event]
[/scenario]
#endif
Code: Select all
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local function get_guardian(cfg)
local filter = cfg.filter or { id = cfg.id }
local guardian = AH.get_units_with_moves {
side = wesnoth.current.side,
{ "and", filter }
}[1]
return guardian
end
local ca_return_guardian = {}
-- params for eval_parms (ai, cfg, self)
function ca_return_guardian:evaluation(cfg, data, filter_own)
std_print("evaluation")
local guardian = get_guardian(cfg)
if guardian then
-- local filter = cfg.filter or { id = cfg.id }
-- local other_units = AH.get_units_with_moves {
-- side = wesnoth.current.side,
-- { "not", filter }
-- }[1]
--
-- if other_units then
-- std_print("Return is 15000")
-- return 15000
-- end
if (guardian.x == cfg.return_x) and (guardian.y == cfg.return_y) then
std_print("Return is 19990")
return 19990
else
std_print("Return is 20010")
return 20010
end
end
std_print("Return is 0")
return 0
end
-- params for exec_parms (ai, cfg, self)
function ca_return_guardian:execution(cfg, data, filter_own)
std_print("excution")
local guardian = get_guardian(cfg)
-- local filter = cfg.filter or { id = cfg.id }
-- local other_units = AH.get_units_with_moves {
-- side = wesnoth.current.side,
-- { "not", filter }
-- }[1]
--
-- if other_units then
-- std_print("Exceution return")
-- return
-- end
-- In case the return hex is occupied:
local x, y = cfg.return_x, cfg.return_y
if (guardian.x ~= x) or (guardian.y ~= y) then
x, y = wesnoth.find_vacant_tile(x, y, guardian)
end
local next_hop = AH.next_hop(guardian, x, y)
if (not next_hop) then next_hop = { guardian.x, guardian.y } end
if ((next_hop[1] ~= guardian.x) or (next_hop[2] ~= guardian.y)) then
ai.move_full(guardian, next_hop[1], next_hop[2])
else
ai.stopunit_moves(guardian)
end
end
return ca_return_guardian
Re: Order of AI moves
The solution is hiding somewhere in the hang out micro ai (or maybe the healer micro ai). I need to take away the moves and give them back when other_units returns nil. I still haven't figured out how to do it.
Edit: Holy cr*p it worked!
I'll post the working version soon.
Edit: Holy cr*p it worked!
I'll post the working version soon.
Re: Order of AI moves
Here is a working version. Peasant_4 will always be the last one to move/attack.
I don't know if what I'm doing would invalidate the game state.
There could be other problems with it. There might be an infinite loop happening somewhere :/
It still needs a lot of work to get it right.
It wouldn't be a bad idea if mainline had a micro_ai with a similar concept.
Edit: It appears I need to freeze all and thaw all whenever the execution happens because otherwise it would miss some.
I also needed to restore the resting status of the unit. Without it the frozen units healed 2 HP when the moves and attacks_left were given back.
For the [micro_ai] version, you can see it in my Wild_Frontiers repo.
ca_wf_move_last.lua
mai definition
usage
There are other micro_ais worth checking too
I don't know if what I'm doing would invalidate the game state.
There could be other problems with it. There might be an infinite loop happening somewhere :/
It still needs a lot of work to get it right.
It wouldn't be a bad idea if mainline had a micro_ai with a similar concept.
Code: Select all
[campaign]
id=Tester
rank=1
icon="units/human-magi/red-mage-attack-magic-2.png~RC(magenta>red)"
image="story/landscape-coast.jpg~SCALE(360,270)"
name= _ "Tester ai order"
abbrev= _ "TEST"
first_scenario=The_Scenario
define=CAMPAIGN_TESTER
[/campaign]
#ifdef CAMPAIGN_TESTER
[lua]
code= <<
local helper = wesnoth.require "lua/helper.lua"
local LS = wesnoth.require "location_set"
local utils = wesnoth.require "wml-utils"
>>
[/lua]
[scenario]
name= _ "The Scenario"
id=The_Scenario
map_data="Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Gg
Gg, Gg, Xu, 2 Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg, Xu, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, 1 Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, 3 Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg
Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg, Gg"
{DEFAULT_MUSIC_PLAYLIST}
{DEFAULT_SCHEDULE}
next_scenario=null
victory_when_enemies_defeated=no
turns = -1
[side]
side=1
type=Peasant
id=Harry
team_name=allies
user_team_name=allies
suppress_end_turn_confirmation = yes
controller=human
recruit=
gold=500
[status]
invulnerable=yes
[/status]
[/side]
[side]
side=2
controller=ai
no_leader=yes
team_name=badguys
user_team_name=badguys
recruit=
gold=500
[ai]
{MODIFY_AI_ADD_CANDIDATE_ACTION 1 main_loop (
[candidate_action]
engine=lua
name=move_last_bob
id=move_last_bob
max_score=300000
location="~add-ons/Bug_Tester/move_last.lua"
[args]
ai_id=dummy_move_last
id=Peasant_4
[/args]
# In the older syntax, the above would have looked like this:
#eval_parms="ai_id = 'dummy_move_last', id = 'Peasant_4'"
#exec_parms="ai_id = 'dummy_move_last', id = 'Peasant_4'"
[/candidate_action]
)}
[/ai]
[/side]
[side]
side=3
controller=ai
no_leader=yes
team_name=allies
user_team_name=allies
[ai]
ai_algorithm=idle_ai
[/ai]
recruit=
gold=500
[/side]
[event]
name=prestart
#define MY_UNIT SIDE TYPE X Y WML
[label]
x={X}
y={Y}
text={WML}
[/label]
[unit]
side={SIDE}
type={TYPE}
x={X}
y={Y}
random_traits=no
random_gender=no
generate_name=no
name={WML}
id={WML}
[/unit]
#enddef
{MY_UNIT 2 Peasant 3 4 Peasant_1}
{MY_UNIT 2 Peasant 5 4 Peasant_2}
{MY_UNIT 2 Peasant 7 4 Peasant_3}
{MY_UNIT 2 Peasant 9 4 Peasant_4}
{MY_UNIT 2 Peasant 11 4 Peasant_5}
{MY_UNIT 2 Peasant 13 4 Peasant_6}
{MY_UNIT 2 Peasant 15 4 Peasant_7}
{MY_UNIT 2 Peasant 17 4 Peasant_8}
{MY_UNIT 2 Peasant 19 4 Peasant_9}
[/event]
[/scenario]
#endif
Code: Select all
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local MAIUV = wesnoth.require "ai/micro_ais/micro_ai_unit_variables.lua"
local function get_last_unit(cfg)
local filter = cfg.filter or { id = cfg.id }
local last_unit = AH.get_units_with_moves {
side = wesnoth.current.side,
{ "and", filter }
}[1]
return last_unit
end
local function get_last_unit_frozen(cfg)
local filter = cfg.filter or { id = cfg.id }
local all_units = wesnoth.get_units {
side = wesnoth.current.side,
{ "and", filter }
}
local units = {}
for _,unit in ipairs(all_units) do
if MAIUV.get_mai_unit_variables(unit, cfg.ai_id, "frozen") then
table.insert(units, unit)
end
end
return units[1]
end
local function get_other_unit(cfg)
local filter = cfg.filter or { id = cfg.id }
local other_unit = AH.get_units_with_moves {
side = wesnoth.current.side,
{ "not", filter }
}[1]
return other_unit
end
local ca_move_last = {}
-- params for eval_parms (ai, cfg, self)
function ca_move_last:evaluation(cfg, data, filter_own)
std_print("evaluation")
local last_unit_frozen = get_last_unit_frozen(cfg)
local last_unit = get_last_unit(cfg)
local filter = cfg.filter or { id = cfg.id }
local other_unit = get_other_unit(cfg)
if not other_unit then
if last_unit_frozen then
std_print("evaluation: return 300000 not other_units")
return 300000
end
end
local last_unit = get_last_unit(cfg)
if last_unit then
std_print("evaluation: return 300000 last_unit")
return 300000
end
std_print("evaluation: return 0 no last_unit end of function")
return 0
end
-- params for exec_parms (ai, cfg, self)
function ca_move_last:execution(cfg, data, filter_own)
std_print("execution")
local last_unit = get_last_unit(cfg)
local other_unit = get_other_unit(cfg)
if other_unit and last_unit then
MAIUV.set_mai_unit_variables(last_unit, cfg.ai_id, { frozen = true, moves = last_unit.moves, attacks_left = last_unit.attacks_left })
AH.checked_stopunit_all(ai, last_unit)
std_print("execution: Freezing last_unit and return")
return
end
last_unit = get_last_unit_frozen(cfg)
if last_unit then
last_unit.moves = MAIUV.get_mai_unit_variables(last_unit, cfg.ai_id, "moves" )
last_unit.attacks_left = MAIUV.get_mai_unit_variables(last_unit, cfg.ai_id, "attacks_left" )
MAIUV.delete_mai_unit_variables(last_unit, cfg.ai_id)
end
std_print("execution: fallthru last_unit to other CAs")
end
return ca_move_last
I also needed to restore the resting status of the unit. Without it the frozen units healed 2 HP when the moves and attacks_left were given back.
For the [micro_ai] version, you can see it in my Wild_Frontiers repo.
ca_wf_move_last.lua
mai definition
usage
There are other micro_ais worth checking too
- Celtic_Minstrel
- Developer
- Posts: 2214
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Order of AI moves
I think you can do this without any Lua code. Just include two copies of the standard movement CA, one with a
[filter_own][not]id=Peasant_4
that has the standard score, and one with a [filter_own]id=Peasant_4
that has a lower score than any other CA.Re: Order of AI moves
I'm still trying to get the micro_ai version to work right, but I'm having issues with the rest healing.
The healing is happening in a strange way.
Here's the setup, I have 9 peasants. They all start with their hitpoints set to 8.
The paths for Peasants 2 and 8 are blocked, so they shouldn't be able to move at all.
Peasants 4 and 6 are controlled by the move_last micro_ai.
Now what I can't understand or fix is that on turn 3 Peasants 2,8 and 4,6 start to rest heal by 2 points.
Why didn't peasants 2,8 rest heal on turn 2?
Why are peasants 4,6 rest healing even though they have moved and their resting flag should be false?
I'm testing this on 1.14.
Anyone knows what's going on here? (Keep moving your peasant back if you want to test it )
And a final question, the last_move micro ai seems to be getting blacklisted. Is there a way to force change the gamestate without having to move the units or take away their attacks?
The healing is happening in a strange way.
Here's the setup, I have 9 peasants. They all start with their hitpoints set to 8.
The paths for Peasants 2 and 8 are blocked, so they shouldn't be able to move at all.
Peasants 4 and 6 are controlled by the move_last micro_ai.
Now what I can't understand or fix is that on turn 3 Peasants 2,8 and 4,6 start to rest heal by 2 points.
Why didn't peasants 2,8 rest heal on turn 2?
Why are peasants 4,6 rest healing even though they have moved and their resting flag should be false?
I'm testing this on 1.14.
Anyone knows what's going on here? (Keep moving your peasant back if you want to test it )
And a final question, the last_move micro ai seems to be getting blacklisted. Is there a way to force change the gamestate without having to move the units or take away their attacks?
Thanks. I'll give it a try later. Will it work on 1.14?Celtic_Minstrel wrote: ↑January 20th, 2022, 12:32 am I think you can do this without any Lua code. Just include two copies of the standard movement CA, one with a[filter_own][not]id=Peasant_4
that has the standard score, and one with a[filter_own]id=Peasant_4
that has a lower score than any other CA.
- Attachments
-
- Bug_Tester.zip
- (3.04 KiB) Downloaded 41 times
Re: Order of AI moves
There is no "built-in" way of doing this, but you can make it happen by taking the moves (or attacks) away and then giving them back:
Code: Select all
function utils.force_gamestate_change(ai)
-- Can be done using any unit of the AI side; works even if the unit already has 0 moves
local unit = wesnoth.units.find_on_map { side = wesnoth.current.side }[1]
local cfg_reset_moves = { id = unit.id, moves = unit.moves }
ai.stopunit_moves(unit)
wesnoth.sync.invoke_command('reset_moves', cfg_reset_moves)
end
Code: Select all
function wesnoth.custom_synced_commands.reset_moves(cfg)
local unit = wesnoth.units.find_on_map { id = cfg.id }[1]
unit.moves = cfg.moves
end
No, this was introduced in 1.15.3.
SP campaigns: Galuldur's First Journey (1.12 & 1.14) & Grnk the Mighty (1.10 & 1.12)
AI experiments: Micro AIs (wiki, forum thread, known/fixed bugs), Fred, AI-demos add-on
AI experiments: Micro AIs (wiki, forum thread, known/fixed bugs), Fred, AI-demos add-on
Re: Order of AI moves
Hi mattsc, it's good to see you again!
Thanks, that was super helpful! It's good to know that this method "works even if the unit already has 0 moves".
I didn't know that before.
For my case, blacklisting would be the safest bet, but I will try to refactor the code to use the force_gamestate_change in another version. I would have to be real careful with the evaluation to avoid an infinite loop.
I solved in a rudimentary way the rest healing problem by saving the last_x and last_y and setting the resting flag to false if they have changed. It's not perfect, it doesn't take into account attacks_left.
I still don't get why they flipped to resting=true by default for the micro_ai units.
I mean I checked. They start off resting=false, then the unit moves, and it flips to resting=true which doesn't make sense :/
Edit:
The code with the last_x,last_y fix ca_wf_move_last.lua
Thanks, that was super helpful! It's good to know that this method "works even if the unit already has 0 moves".
I didn't know that before.
For my case, blacklisting would be the safest bet, but I will try to refactor the code to use the force_gamestate_change in another version. I would have to be real careful with the evaluation to avoid an infinite loop.
I solved in a rudimentary way the rest healing problem by saving the last_x and last_y and setting the resting flag to false if they have changed. It's not perfect, it doesn't take into account attacks_left.
I still don't get why they flipped to resting=true by default for the micro_ai units.
I mean I checked. They start off resting=false, then the unit moves, and it flips to resting=true which doesn't make sense :/
Edit:
The code with the last_x,last_y fix ca_wf_move_last.lua
Re: Order of AI moves
hmm, force_gamestate_change didn't work. The ca still got blacklisted.
I added the following to the definition file micro_ai.lua. (adapted for 1.14)
and called utils.force_gamestate_change(ai) at the end of execution()
In the game inspector, it said enabled=no for the move last ca.
Edit:
Unfortunately, this part turned out not to be correct about "works even if the unit already has 0 moves"
It needs the unit to have moves for it to work.
Replacing wesnoth.get_units with
I added the following to the definition file micro_ai.lua. (adapted for 1.14)
Code: Select all
-- force_gamestate_change by mattsc
local utils = wesnoth.require "wml-utils"
function utils.force_gamestate_change(ai)
-- Can be done using any unit of the AI side; works even if the unit already has 0 moves
local unit = wesnoth.get_units { side = wesnoth.current.side }[1]
local cfg_reset_moves = { id = unit.id, moves = unit.moves }
ai.stopunit_moves(unit)
std_print("force_gamestate_change on " .. cfg_reset_moves.id)
wesnoth.invoke_synced_command('reset_moves', cfg_reset_moves)
end
-- reset_moves by mattsc
function wesnoth.custom_synced_commands.reset_moves(cfg)
local unit = wesnoth.get_units { id = cfg.id }[1]
unit.moves = cfg.moves
std_print("synced command on " .. cfg.id)
end
In the game inspector, it said enabled=no for the move last ca.
Edit:
Unfortunately, this part turned out not to be correct about "works even if the unit already has 0 moves"
Code: Select all
-- Can be done using any unit of the AI side; works even if the unit already has 0 moves
local unit = wesnoth.get_units { side = wesnoth.current.side }[1]
Replacing wesnoth.get_units with
local unit = AH.get_units_with_moves { side = wesnoth.current.side }[1]
gets it back to track and won't blacklist the CA anymore. (warning: It will go into an infinite loop in this example)Re: Order of AI moves
Ok, guys here it is.
move_last micro_ai with forced gamestate change and no blacklisting or infinite loop. This includes the resting hack (still no clue why that happens, maybe ai.stopunit_all sets it?)
Thanks to mattsc for the force gamestate trick.
move_last micro_ai with forced gamestate change and no blacklisting or infinite loop. This includes the resting hack (still no clue why that happens, maybe ai.stopunit_all sets it?)
Thanks to mattsc for the force gamestate trick.
- Attachments
-
- Bug_Tester.zip
- (3.74 KiB) Downloaded 37 times
Re: Order of AI moves
Glad you got it to work. As for the gamestate changed comment, looks like I actually changed (fixed) that myself about three years ago and then forgot about it. I copied the code I posted up there out of an existing AI that I apparently wrote before that. Sorry for that.
I don't know anything about the resting behavior, somebody else will have to comment on that.
I don't know anything about the resting behavior, somebody else will have to comment on that.
SP campaigns: Galuldur's First Journey (1.12 & 1.14) & Grnk the Mighty (1.10 & 1.12)
AI experiments: Micro AIs (wiki, forum thread, known/fixed bugs), Fred, AI-demos add-on
AI experiments: Micro AIs (wiki, forum thread, known/fixed bugs), Fred, AI-demos add-on