HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Module help

11-01-2009, 01:20 PM#1
Cheezeman
Hello.
I'm making a map in which I have a strategic point in the middle. To caputre it you have to have the more units than anyone else close to it.
Since I'm a fan of modularity I decided to make a function that retrived which player has the most units in a radius of a point. This is how it looks like:
Collapse JASS:
library PersonalLibrary
    globals
        private integer array Count
    endglobals
    
    private function Increase takes nothing returns nothing
        set Count[GetPlayerId(GetOwningPlayer(GetEnumUnit()))] = Count[GetPlayerId(GetOwningPlayer(GetEnumUnit()))] + 1
    endfunction

    function GetPlayerWithMostUnitsInRange takes real x, real y, real radius, boolexpr filter returns player
        local group g = CreateGroup()
        local integer i = 0
        local integer temp_count
        local player p = Player(0)
        call GroupEnumUnitsInRange( g, x, y, radius, filter )
        call ForGroup( g, function Increase )
        
        set temp_count = Count[0]
        loop
            exitwhen i > 11
            
            if Count[i] > temp_count then
                set temp_count = Count[i]
                set p = Player(i)
            endif
            
            set i = i + 1
            exitwhen i > 11
        endloop
        
        set i = 0
        loop
            exitwhen i > 11
            
            set Count[i] = 0
            
            set i = i + 1
            exitwhen i > 11
        endloop
        
        call DestroyGroup(g)
        set g = null
        return p
    endfunction
endlibrary

Right now, it works without bugs but it has an obvious flaw: If two players (or more) have an equal amount of units close to the point, the player with the smallest number will be returned (if player 1 has three units and player 2 also does, player 1 will be returned).
To solve this dispute I'd like to return Neutral Passive if two or more players have equal amount of units.
Problem is I don't know how.
I tried some if's but it always returns Neutral Passive
Help?
11-01-2009, 02:22 PM#2
Anitarf
Collapse JASS:
library GetPlayerWithMostUnitsInRange
    globals
        private integer array Count
        private group g = CreateGroup()
    endglobals

    private function Increase takes nothing returns nothing
        local integer i=GetPlayerId(GetOwningPlayer(GetEnumUnit()))
        set Count[i] = Count[i] + 1
    endfunction

    function GetPlayerWithMostUnitsInRange takes real x, real y, real radius, boolexpr filter returns player
        local integer i = 0
        local integer tempCount = 0
        local player tempPlayer
        call GroupEnumUnitsInRange( g, x, y, radius, filter )
        call ForGroup( g, function Increase )
        
        loop
            if Count[i]>tempCount then
                set tempCount = Count[i]
                set tempPlayer = Player(i)
            elseif Count[i]==tempCount then
                set tempPlayer = Player(15)
            endif
            set Count[i] = 0
            
            set i = i + 1
            exitwhen i > 11
        endloop

        return tempPlayer
    endfunction
endlibrary
11-01-2009, 02:41 PM#3
Cheezeman
Strange. I just tried the same thing but it always returned neutral passive no matter what.
And I mean exactly the same thing.
Thanks, I guess :/
11-02-2009, 05:31 PM#4
Vexorian
Yes, Anitarf's code looks strange somehow...

The way I would do it is to keep the best and the second-best player. Then if both have the same amount of units, return Neutral passive.
Collapse JASS:
    function GetPlayerWithMostUnitsInRange takes real x, real y, real radius, boolexpr filter returns player
        local integer i = 0
        local integer tempCount1 = -1 //to force it to work
        local integer tempCount2 = -1
        local player tempPlayer1 = Player(15)
        local player tempPlayer2 = Player(15)
        call GroupEnumUnitsInRange( g, x, y, radius, filter )
        call ForGroup( g, function Increase )
        
        loop
            if Count[i]>tempCount1 then
                set tempCount2 = tempCount1
                set tempPlayer2 = tempPlayer1
                set tempCount1 = Count[i]
                set tempPlayer1 = Player(i)              
            elseif Count[i]>tempCount2 then
                set tempPlayer2 = Player(15)
                set tempCount2 = Count[i]
            endif
            set Count[i] = 0           
            set i = i + 1
            exitwhen i > 11
        endloop
        if(tempCount2 == tempCount2) then
            return Player(15)
        endif

        return tempPlayer
    endfunction
11-02-2009, 05:42 PM#5
Anachron
Haven't tested, but should work
Collapse JASS:
library GetPlayerWithMostUnitsInRange
    globals
        private integer array Count
    endglobals

    private function Increase takes nothing returns nothing
        local integer i=GetPlayerId(GetOwningPlayer(GetEnumUnit()))
        set Count[i] = Count[i] + 1
    endfunction
    
    function GetLeadingPlayerRange takes real x, real y, real r, boolexpr filter returns player
        local integer i = 0
        local player p = Player(PLAYER_NEUTRAL_PASSIVE)
        local player w = null
        local group    g = null
        local integer s = 0
        
        loop
            exitwhen i >= 15
            
            set Count[i] = 0
            set g = CreateGroup()
            call GroupEnumUnitsInRange(g, x, y, r, filter)
            call ForGroup(g, function Increase)
            call DestroyGroup(g)
            set g = null
            
            if Count[i] > s then
                set w = Player(i)
                set s = Count[i]
            elseif w != p then
                set w = p
                set i = 14
            endif
            
            set i = i + 1
        endloop
    
        return w
    endfunction
endlibrary
11-02-2009, 05:49 PM#6
Anitarf
Quote:
Originally Posted by Vexorian
Yes, Anitarf's code looks strange somehow...
It loops through the players, if a player beats the top score he becomes the new top player, if on the other hand he ties the top score the neutral player becomes the top player. I think the logic of that is fairly straightforward, it doesn't seem strange to me.

Edit: Anachron, that's just depressing.
11-02-2009, 05:54 PM#7
Vexorian
don't use DestroyGroup.

I now think Anitarf's should work really well. Hmnn, are you sure you really did try it and always returned Neutral Passive?
11-02-2009, 06:02 PM#8
Anitarf
Quote:
Originally Posted by Vexorian
I now think Anitarf's should work really well. Hmnn, are you sure you really did try it and always returned Neutral Passive?
Nah, he didn't say he tried it, he said he wrote the same thing himself, only I'm guessing it wasn't exactly the same. One possible difference that comes to mind is using endif+if instead of elseif, that would cause it to malfunction like he has described.
11-02-2009, 08:29 PM#9
Cheezeman
No I used an elseif, and it looked exactly the same (ok not 'exactly' since my tempPlayer was named p and my tempCount was called temp_count, but those are just names). But the problem may have been in my code which uses the module.
However I noticed that if two players on the same team have equal units, no one captures the point, which is kind of stupid since capturing the point is beneficial to the whole team. I havn't worked on solving it yet (no time). I'll just double-post here if I need help with it (do hope moderators approve of this liberty)
11-02-2009, 08:50 PM#10
Anitarf
elseif Count[i]==tempCount and IsPlayerEnemy(tempPlayer, Player(i)) then
This way, if two players on the same team are tied, the one with the lower player id wins.