Sorting values.
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.
Sorting values.
Hello,
I am working on some hand-tailored AI scripts and I am currently trying to figure out how to sort a series of values. Let's say that I have 6 units and I want to have an array of their hp values sorted from max to min. How can I do this?
Thanks in advance.
EDIT:
On the same token, what would be the cleanest way (I can imagine the crude way) to sort six hexes based on how many enemies surround it?
I am working on some hand-tailored AI scripts and I am currently trying to figure out how to sort a series of values. Let's say that I have 6 units and I want to have an array of their hp values sorted from max to min. How can I do this?
Thanks in advance.
EDIT:
On the same token, what would be the cleanest way (I can imagine the crude way) to sort six hexes based on how many enemies surround it?
Re: Sorting values.
You probably want table.sort in the Lua standard library.
Re: Sorting values.
Ok, so let's say my table is named "Dudes".
Should I do it more or less like that?
[lua]
Dudes = table.sort (Dudes)
[/lua]
I am really lacking examples from the tutorials.
Should I do it more or less like that?
[lua]
Dudes = table.sort (Dudes)
[/lua]
I am really lacking examples from the tutorials.
Re: Sorting values.
No, it's an in-place sort, so it doesn't return anything; it just modifies the array that is passed as an argument. So you would just write:
Code: Select all
table.sort (Dudes)
Code: Select all
-- get the units
local Dudes = wesnoth.units.find_on_map { side = 1 }
-- sort the units (by hp)
local function compare_hp(a, b)
if a.hitpoints > b.hitpoints then
return true
else
return false
end
end
table.sort(Dudes, compare_hp)
-- display the units
for i, Dude in ipairs(Dudes) do
print(Dude.type .. ': ' .. Dude.name .. ': ' .. Dude.hitpoints .. ' hp')
end
Re: Sorting values.
Ok, so I suppose I can't do it the way I was guessing?
I.e., create list of hitpoint values using WML, then pass this list to lua?
I.e., create list of hitpoint values using WML, then pass this list to lua?
Re: Sorting values.
I'm not sure what you mean... you can sort a list of anything, including hitpoint values (numbers). For example, you might have 6 units with hitpoints {32, 36, 23, 35, 41, 42} and then after sorting that becomes {42, 41, 36, 35, 32, 23}. But that might not be very useful - that doesn't tell you which unit has 42 hp, which unit has 41 hp, etc. In most cases it would be more useful to sort a list of units.
Re: Sorting values.
Ok, so my first concern is noobish - how do I integrate it into my [scenario][/scenario].
Technically I could identify units by their hp, i.e., "send the one with 23 hp here, then the one with 32 hp here".
So if I make a list using WML, i.e., store units, and then just put their $unit.hp into a list using just WML, not lua...
... then do I just make [lua][/lua] bracket to make the sorting operation from above?
Technically I could identify units by their hp, i.e., "send the one with 23 hp here, then the one with 32 hp here".
So if I make a list using WML, i.e., store units, and then just put their $unit.hp into a list using just WML, not lua...
... then do I just make [lua][/lua] bracket to make the sorting operation from above?
-
- Posts: 1456
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
Re: Sorting values.
This is untested, and I'm just plugging gnombat's sort algo in w/o really thinking about it (looks fine), but it should give you the basics:
Code: Select all
[lua]
code = <<
local ul = wml.array_access.get "unit_list" -- get the WML array 'unit_list' and put it in lua table 'ul'
-- sort the units (by hp)
local function compare_hp(a, b)
if a.hitpoints > b.hitpoints then
return true
else
return false
end
end
table.sort(ul, compare_hp)
wml.array_access.set("unit_list", ul) -- put lua table 'ul' in WML array 'unit_list'
>>
[/lua]
Speak softly, and carry Doombringer.
-
- Posts: 1456
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
Re: Sorting values.
BTW, this assumes you just store the units into unit_list, and forget aboutwhite_haired_uncle wrote: ↑September 2nd, 2024, 1:51 pm This is untested, and I'm just plugging gnombat's sort algo in w/o really thinking about it (looks fine), but it should give you the basics:
Code: Select all
[lua] code = << local ul = wml.array_access.get "unit_list" -- get the WML array 'unit_list' and put it in lua table 'ul' -- sort the units (by hp) local function compare_hp(a, b) if a.hitpoints > b.hitpoints then return true else return false end end table.sort(ul, compare_hp) wml.array_access.set("unit_list", ul) -- put lua table 'ul' in WML array 'unit_list' >> [/lua]
So if I make a list using WML, i.e., store units, and then just put their $unit.hp into a list using just WML, not lua...
Speak softly, and carry Doombringer.
Re: Sorting values.
I planned on storing only hp due to my limited understanding of the lua. WML was my only point of reference, but now you have given me something to tinker with top-down. Particularly, I'm reading on wml.array_access.set now. Thanks.
-
- Posts: 1456
- Joined: August 26th, 2018, 11:46 pm
- Location: A country place, far outside the Wire
Re: Sorting values.
You could store only hp, but if you store it as "hp" make sure to change the sort to use a.hp > b.hp and not a.hitpoints > b.hitpoints.
I don't think that makes any sense, but you could do it. If you're just getting started, just use the list of units from [store_unit], let lua sort it, and go from there.
I don't think that makes any sense, but you could do it. If you're just getting started, just use the list of units from [store_unit], let lua sort it, and go from there.
Speak softly, and carry Doombringer.
- Celtic_Minstrel
- Developer
- Posts: 2371
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Sorting values.
This is excessively verbose, just write it like this:white_haired_uncle wrote: ↑September 2nd, 2024, 1:51 pmCode: Select all
[lua] code = << local ul = wml.array_access.get "unit_list" -- get the WML array 'unit_list' and put it in lua table 'ul' -- sort the units (by hp) local function compare_hp(a, b) if a.hitpoints > b.hitpoints then return true else return false end end table.sort(ul, compare_hp) wml.array_access.set("unit_list", ul) -- put lua table 'ul' in WML array 'unit_list' >> [/lua]
Code: Select all
table.sort(ul, function(a,b) return a.hitpoints > b.hitpoints end)
Re: Sorting values.
table.sort is not a stable sort, and I'm not sure whether they exact outcome is guaranteed to be Platform Independent, if is it's using stable sort where elements might compare as equal, might result in oos.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
Re: Sorting values.
If it were necessary to perform the sort in multiplayer, this would prevent oos, wouldn't it?
Code: Select all
local function compare_hp(a, b)
if a.hitpoints > b.hitpoints then
return true
elseif a.hitpoints < b.hitpoints then
return false
elseif a.id < b.id then
return true
else
return false
end
end
Re: Sorting values.
hmm I don't know actually, in particular about whether the Id is guaranteed to be the same on all clients, I know for sure that there were issues in the past where the I'd was _not_ the same on all clients, but I don't remember them well enough to say for sure whether they have been fixed.gnombat wrote: ↑September 2nd, 2024, 7:51 pmIf it were necessary to perform the sort in multiplayer, this would prevent oos, wouldn't it?
Code: Select all
local function compare_hp(a, b) if a.hitpoints > b.hitpoints then return true elseif a.hitpoints < b.hitpoints then return false elseif a.id < b.id then return true else return false end end
I do know however that many codes still refer to units by locations (for example the "rename" commandwhich actually complicates things since moves can be undone and then the location is no longer valid) Instead of the units id for these reasons
Also I want to point out that oos are also an issue in single player, for example when someone uses the "replay turn" button that was added to the menu in 1.18
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.