IsGroupEmpty

Level 23
Joined
Apr 16, 2012
Messages
4,041
self explanotary pretty much
JASS:
library IsGroupEmpty /*  by edo494 version 1.1
*
*   This function takes group and checks if it is empty.
*
*===========================================================
*
*   ChangeLog:
*
*           1.0 - Intial Release
*
*           1.1 - Updated a little bit
*
*===========================================================
*
*   API:
*
*       function IsGroupEmpty takes group whichgroup returns boolean
*
*===========================================================
*/

private struct IsGroupEmptys extends array
    
    static group gr
    
    static method CallBack takes nothing returns nothing
        call GroupAddUnit(IsGroupEmptys.gr, GetEnumUnit())
    endmethod
    
    static method IsGEm takes group whichgroup returns boolean
        local unit u
        set IsGroupEmptys.gr = CreateGroup()
        call ForGroup(whichgroup, function thistype.CallBack)
        loop
            set u = FirstOfGroup(IsGroupEmptys.gr)
            if not( u == null ) and not IsUnitType(u, UNIT_TYPE_DEAD) then
                set u = null
                call DestroyGroup(IsGroupEmptys.gr)
                return false
            endif
            exitwhen u == null
        endloop
        call DestroyGroup(IsGroupEmptys.gr)
        return true
    endmethod
endstruct

function IsGroupEmpty takes group whichgroup returns boolean
    return IsGroupEmptys.IsGEm(whichgroup)
endfunction

endlibrary

JASS:
scope ATest
    
    private function F_Test takes nothing returns boolean
        local group g = CreateGroup()
        call GroupEnumUnitsOfPlayer(g, Player(0), null)
        if not IsGroupEmpty(g) then
            call BJDebugMsg("Filled")
        else
            call BJDebugMsg("Empty")
        endif

        if not IsGroupEmpty(g) then
            call BJDebugMsg("Filled")
        else
            call BJDebugMsg("Empty")
        endif

        call GroupClear(g)
        if not IsGroupEmpty(g) then
            call BJDebugMsg("Filled")
        else
            call BJDebugMsg("Empty")
        endif
        call DestroyGroup(g)
        set g = null
        return false
    endfunction
    
    
    private module INIT
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterTimerEvent(t, 0., false)
            call TriggerAddCondition(t, Condition(function F_Test))
            set t = null
        endmethod
    endmodule
    
    private struct INITI
        implement INIT
    endstruct
endscope
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
It is a joke, right ?

EDIT :

JASS:
local group g = CreateGroup()
call GroupEnum...

if FirstOfGroup(g) == null
    // the group is empty
else
    // the group contains at least one unit
endif

Now, this method could fail with a group which is kept during time, because of ghost units, but for these ones you could consider to use UnitLL instead of a group (or not)
 
Last edited:
Level 23
Joined
Apr 16, 2012
Messages
4,041
did you read it? I actually do ForGroup which you stated in UnitLL that it doesnt enum those ghost units

I have updated it a little bit

The reason Ive posted it is Im making spell and I needed to check if the group is empty so Ive maid this and though of sharing it.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Yes i've read it.

1) In your sample it's useless since there is no way that the group will contains ghost units because you've just used GroupEnum

2) In the case it could be useful, then it would be better to just not use a group at all (UnitLL, or simply an other unit structure)

3) If i would use a group it would be still better to count the number of units in the group rather than just to know if the group is empty or not.

4) Why the hell you use a struct ?

5) Instead of creating/destroying the group IsGroupEmptys.gr, you could just create once an re-use it.

6) You decide to ignore dead units whithout making it configurable and saying it.

7) CountUnitsInGroup do the same or so except it doesn't ignore dead units.

Now yeah i suppose most of times you don't want to take dead units in consideration, but then your API names are incorrect.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
1. Well, this is not made to filter ghost units, its made to check if the group is empty :D

2. well, how you gonna handle like 15+ units for instance, array them? :D

3. well, checking if first unit is null or checking if someVar == 1 isnt the same basically? :D

4. I dont know :D

5. hmhmh....you've got me :D

6. this is just to try to filter those "ghost units" :D its getting late here so my brain activity is going a little bit down

7. NICE EDITING! :D well yea hmm.....hmm.....hmmm....no comment :D(Youve got me really)

the numberless thingy on bottom:

as I said, it was just a try :D

Nes: what about those ghost units? :D but yes 3 lines beats 29 :D

Well, this is not the best thing ever made but Ive tried but Im not giving up
 
what about those ghost units?

The user should be responsible for maintaining their own groups.

Just because a unit is removed doesn't mean that its pointer is removed from all groups/hashtables/variables it may be stored in.

Now, you could do a CleanGroup function

JASS:
globals
    private group passer
englobals
function CleanGroupEnum takes nothing returns nothing
    if (GetUnitTypeId(GetEnumUnit()) == 0) then
        call GroupRemoveUnit(passer, GetEnumUnit())
    endif
endfunction
function CleanGroup takes group whichGroup returns nothing
    set passer = whichGroup
    call ForGroup(whichGroup, function CleanGroupEnum)
    set passer = null
endfunction

You need to start thinking in terms of modularity. Don't try and bundle a 1000 features together. Only focus on precisely what your lib should do. Don't try to over engineer it ^)^.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Ghost unit : unit removed of the game but not of the group, since units are not automatically removed from of a group when they are removed of the game (by any way, end of decay, use of RemoveUnit, explode ...)

In your sample, there is no way the the group will contain a such unit, since you don't use any wait, and even if you used RemoveUnit, this function is not instant, it waits for the end of the thread, or before a Timer(0) something like that.

Now, to be honest the first time i've read it i don't know if you already decided to ignore dead units, at least i didn't see it.
But again if the group can't have a ghost unit, then just go for a FirstOfGroup/GroupRemoveUnit loop, or if it can then use something else than a group.
With or without UnitLL it's very possible.
 
Top