• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Group swap

Status
Not open for further replies.
Level 18
Joined
Nov 21, 2012
Messages
835
Regarding vJass Optimization: Using a First of Group Loop for Enumeration tutorial, I'm not sure I understand swaping group method
This is a example script from above tutorial
JASS:
scope test
    globals
        private group iterator=CreateGroup()
        private group swap=CreateGroup()
        private group temp
    endglobals
    
    private function fgSwap takes nothing returns nothing
        local unit FoG
        loop
            set FoG=FirstOfGroup(iterator)
            exitwhen FoG==null
            //
            call GroupAddUnit(swap,FoG)
            call GroupRemoveUnit(iterator,FoG)
        endloop
        set temp=iterator
        set iterator=swap
        set swap=temp
    endfunction
endscope

I'm embarrassed with group "temp". Is this needed? Would not be enough to do after endloop:
JASS:
// set temp=iterator //"iterator" is empty, what for we set "temp" as empty group?
set iterator=swap
// set swap=temp // can't we just call GroupClear(swap) ?
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Handle variables are pointers to objects. In this case you have two objects (two groups created by CreateGroup) and three group pointers.

I will call the objects Group1 and Group2

At first iterator points towards Group1 and swap towards Group2.
Group1 is cleared during the loop and instead the units are added to Group2.

After the loop we still have iterator->Group1 and swap->Group2. But now Group1 is empty and Group2 contains our units.

If we would now do
set iterator = swap, both variables would point to Group2. We have a leak, because we cannot access Group1 anymore.
If we would now use GroupClear(swap) we would clear Group2, so after that both iterator and swap would point to the now empty Group2.

By using temp we have the following.
At first we have: iterator->Group1 and swap->Group2.
After set temp=iteratortemp->Group1, iterator->Group1 and swap->Group2.
set iterator=swaptemp->Group1, iterator->Group2 and swap->Group2.
set swap=temptemp->Group1, iterator->Group2 and swap->Group1.

So now have still access to both groups and we swapped them correctly (iterator now points to the second group and swap to the first group)
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
ZiBitheWand3r3r must have been confused because the first part where the FirstOfGroup loop seems like it already is swapping the group's contents with each other when what it truly is trying to exhibit is the enumeration of the units within the group "iterator". The actual object/handle pointer swapping is on the last three lines.
 
Level 18
Joined
Nov 21, 2012
Messages
835
Thanks for detailed explanation, Jampion,
I messed up in my head groups itself and variables.
So the main reason these 3 lines exist is to avoid leak by setting empty Group1 to variable "swap" ?

chobibo, thanks but I was confused by variable "temp"

edit:
Let's say I need a function that removes dead/removed units from a group. Will this be correct guys?
JASS:
globals// for "swap group" method using FoG
    group iteratorGroup=CreateGroup()
    group swapGroup=CreateGroup()
    group tempGroup
endglobals

function GroupRemoveDeadUnits takes group g returns nothing
    local unit FoG=null
    loop
        set FoG=FirstOfGroup(g)
        exitwhen FoG==null
        //
        if UnitAlive(FoG) then // do not add dead or removed units
            call GroupAddUnit(swapGroup,FoG)
        endif
        call GroupRemoveUnit(g,FoG)
    endloop
    set tempGroup=g
    set g=swapGroup
    set swapGroup=tempGroup
endfunction
 
Last edited:
From what I understand, that will result into a different group handle containing all members. In this case, adding them back to the first group from the swapper group is a must.

JASS:
loop
        set FoG=FirstOfGroup(g)
        exitwhen FoG==null
        //
        if UnitAlive(FoG) then // do not add dead or removed units
            call GroupAddUnit(swapGroup,FoG)
        endif
        call GroupRemoveUnit(g,FoG)
endloop
// Another loop for adding the members back
loop
    set FoG = First off too(swapGroup)
    exitwhen FoG == null

    call GroupAddUnit(g, FoG)
    call Grouper move unit(swapGroup, FoG)
endloop

Since the function merely clears out the units that are not alive, it should make sense for it to receive back its' list of living units, and not to get another group in exchange.
 
Level 18
Joined
Nov 21, 2012
Messages
835
It won't change UnitGroup's handle id by adding/removing units from unit group, right?
If so, why you're saying that
that will result into a different group handle containing all members
UnitGroup as an object does not containts info about group memebrs (units) if I understand it right. Im really confused by your comment MyPad.
 
Last edited:
I think it pretty much does what it should do, but maybe it's not what one might expect. Yes, the method literally swaps groups, hence also the names. It for most cases makes sense for globals, not for local params that are cleaned on function end. (as it also probably rarely makes sense overall to use a hold-value method for locals)

In your case, if you want to make it with a local, we require to return the local again, so still access it properly. Try to change ..
JASS:
function GroupRemoveDeadUnits takes group g returns nothing
    local unit FoG=null
    loop
        set FoG=FirstOfGroup(g)
        exitwhen FoG==null
        //
        if UnitAlive(FoG) then // do not add dead or removed units
            call GroupAddUnit(swapGroup,FoG)
        endif
        call GroupRemoveUnit(g,FoG)
    endloop
    set tempGroup=g
    set g=swapGroup
    set swapGroup=tempGroup
endfunction
-->
JASS:
function GroupRemoveDeadUnits takes group g returns group
    local unit FoG=null
    loop
        set FoG=FirstOfGroup(g)
        exitwhen FoG==null
        if UnitAlive(FoG) then // do not add dead or removed units
            call GroupAddUnit(swapGroup,FoG)
        endif
        call GroupRemoveUnit(g,FoG)
    endloop
    set tempGroup=g
    set g=swapGroup
    set swapGroup=tempGroup
    return g
endfunction
.. then also after the function has ended you have wanted values if you use it like:

JASS:
 local group g = ...
set g = GroupRemoveDeadUnits(g)

If the group cleaning from invalid units is your actual goal, then this thread by @Aniki might interest you, too, as he explains and provides some code for this problem.
 
Status
Not open for further replies.
Top