[JASS] Count players and set food cap problem

Status
Not open for further replies.
Level 11
Joined
Sep 14, 2009
Messages
284
Hello. I'm making a map for 6 players, and depending on the number of players, each player may pick a certain number of heroes. To limit the heroes, i modify the food cap for each player.

Here is how it's supposed to work:
6 Players = 1 Food Cap
5 Players = 1 Food Cap (+1 Food Cap for 1 Random Player)
4 Players = 1 Food Cap (+1 Food Cap for 2 Random Players)
3 Players = 2 Food Cap
2 Players = 3 Food Cap
1 Player = 6 Food Cap

So it's pretty obvious that when there are 5 or 4 players, it get's more complicated.

I could easily use "ForcePickRandomPlayer", but I want to try and make it free from non-natives.
It's the last loop I have problem with. And it's not finished.
Here is the code so far:

JASS:
function CountPlayers_Actions takes nothing returns nothing
    local integer i = 0
    local integer playercount = 0
    local integer r = 0
    local force f = CreateForce()
    loop
        exitwhen i > 5
        if GetPlayerController(Player(i)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
            call ForceAddPlayer(f, (Player(i)))
            set playercount = playercount + 1
        endif
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if IsPlayerInForce(Player(i), f) == true then
            if playercount >= 6 then
                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 1)
            else
                if playercount == 5 then
                    call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 1)
                    set r = 1
                else
                    if playercount == 4 then
                        call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 1)
                        set r = 2
                    else
                        if playercount == 3 then
                            call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
                        else
                            if playercount == 2 then
                                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 3)
                            else
                                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 6)
                            endif
                        endif
                    endif
                endif
            endif
        endif
        set i = i + 1
    endloop
    set i = 0
    //This is the part I have problem with, setting the extra food cap for the 5 or 4 player case
    loop
        exitwhen i > r
        if IsPlayerInForce(Player(i), f) == true then
            call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
            call ForceRemovePlayer(f, Player(i))
            
        else
            set i = i + 1
        endif
    endloop
    call DestroyForce(f)
    set f = null
endfunction

//===========================================================================
function InitTrig_CountPlayers takes nothing returns nothing
    set gg_trg_CountPlayers = CreateTrigger()
    call TriggerAddAction(gg_trg_CountPlayers, function CountPlayers_Actions)
endfunction
 
here solution for you:
JASS:
function SetFoodCap takes integer food returns nothing //call this at start with food 1
    call SetPlayerState(Player(0), PLAYER_STATE_RESOURCE_FOOD_CAP, food)
    call SetPlayerState(Player(1), PLAYER_STATE_RESOURCE_FOOD_CAP, food)
    call SetPlayerState(Player(2), PLAYER_STATE_RESOURCE_FOOD_CAP, food)
    call SetPlayerState(Player(3), PLAYER_STATE_RESOURCE_FOOD_CAP, food)
    call SetPlayerState(Player(4), PLAYER_STATE_RESOURCE_FOOD_CAP, food)
    call SetPlayerState(Player(5), PLAYER_STATE_RESOURCE_FOOD_CAP, food)    
endfunction
//=========================================================
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local integer i = 0
    local integer playercount = 0
    local integer array playerList
    local integer x=0
    
    loop
        exitwhen i > 5
        if GetPlayerController(Player(i)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
            set playercount = playercount + 1
            set playerList[playercount] = i
        endif
        set i = i + 1
    endloop
    
    if playercount == 1 then
        call SetFoodCap(6)     
    elseif playercount == 2 then
        call SetFoodCap(3)
    elseif playercount == 3 then
        call SetFoodCap(2)
    
    elseif playercount == 4 then //2 random players 2food:
        set x = GetRandomInt(0, playercount)
        call SetPlayerState(Player(playerList[x]), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
        set playerList[x] = playerList[playercount]
        set playercount=playercount-1
        
        set x = GetRandomInt(0, playercount)
        call SetPlayerState(Player(playerList[x]), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
        set playerList[x] = playerList[playercount]
        set playercount=playercount-1
        
    elseif playercount == 5 then //1 random player 2food:
        set x = GetRandomInt(0, playercount)
        call SetPlayerState(Player(playerList[x]), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
        set playerList[x] = playerList[playercount]
        set playercount=playercount-1
        
    endif

endfunction

zibi
 
Level 11
Joined
Sep 14, 2009
Messages
284
Too Many if's.

What do you mean to many? Is it bad to use many ifs? I see no problem with it.

Anyways I solved the problem.

Here is the final code:

JASS:
function CountPlayers_Actions takes nothing returns nothing
    local integer i = 0
    local integer playercount = 0
    local integer r = 0
    local force f = CreateForce()
    loop
        exitwhen i > 5
        if GetPlayerController(Player(i)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
            call ForceAddPlayer(f, (Player(i)))
            set playercount = playercount + 1
        endif
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if IsPlayerInForce(Player(i), f) == true then
            if playercount >= 6 then
                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 1)
                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 3)
            else
                if playercount == 5 then
                    call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 1)
                    call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 3)
                    set r = 1
                else
                    if playercount == 4 then
                        call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 1)
                        call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 3)
                        set r = 2
                    else
                        if playercount == 3 then
                            call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
                            call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 6)
                        else
                            if playercount == 2 then
                                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 3)
                                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 9)
                            else
                                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 6)
                                call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 18)
                            endif
                        endif
                    endif
                endif
            endif
        endif
        set i = i + 1
    endloop
    set i = 0
    if playercount == 5 or playercount == 4 then
        loop
            exitwhen i > r
                if IsPlayerInForce(Player(i), f) == true then
                    call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
                    call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, 6)
                    call ForceRemovePlayer(f, Player(i))
                    set i = i + 1
                endif
        endloop
    endif
    call DestroyForce(f)
    set f = null
endfunction

//===========================================================================
function InitTrig_CountPlayers takes nothing returns nothing
    set gg_trg_CountPlayers = CreateTrigger()
    call TriggerAddAction(gg_trg_CountPlayers, function CountPlayers_Actions)
endfunction
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,272
I think this version would be better. It certainly looks neater and more maintainable. Notice the lack of case statement style "if then" blocks.
JASS:
function CountPlayers_Actions takes nothing returns nothing
    // some constants for conveinence
    local integer foodcap = 6

    local integer i = 0
    local integer playercount = 0
    local integer r
    local integer amount
    local integer give
    local player p
    local player array players

    // enumerate and count active players
    loop
        exitwhen i > 5
        set p = Player(i)
        if GetPlayerController(p) == MAP_CONTROL_USER and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING then
            set players[playercount] = p
            set playercount = playercount + 1
        endif
        set i = i + 1
    endloop

    // food remainder (inlined simplified modulo)
    set r = foodcap - (foodcap / playercount) * playercount

    // base amount per player
    set amount = foodcap / playercount

    set i = 0
    loop
        exitwhen i >= playercount
        set p = players[i]
        
        // determine amount to give
        set give = amount
        if GetRandomInt(1, playercount - i) <= r then
            // lucky player also gets part of remainder
            set give = give + 1
            set r = r - 1
        endif

        // distribute properties
        call SetPlayerState(p, PLAYER_STATE_RESOURCE_FOOD_CAP, give)
        call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, give * 3)

        // local variable bugfix (technically not required for player)
        set players[i] = null

        set i = i + 1
    endloop

    // local variable bugfix (technically not required for player)
    set p = null
endfunction

//===========================================================================
function InitTrig_CountPlayers takes nothing returns nothing
    set gg_trg_CountPlayers = CreateTrigger()
    call TriggerAddAction(gg_trg_CountPlayers, function CountPlayers_Actions)
endfunction
 
Level 11
Joined
Sep 14, 2009
Messages
284
Some people are not worthy to help them because they treat helper's work like a thin air.

Not sure if you mean me here or someone else. But in any case I went through your code and there's a slight problem with it if the empty player slot is not necessarily 5 or 6, but might as well be 2, 3 or 4 etc.

@Dr Super Good
I have made my code alot simpler since last post, but even then your version still looks way better. I will look through it and consider using it later. Thanks.

EDIT:
I went through your code now, and it seems you forget one important thing just like ZiBi. Just becuase there are (for example) 4 active players, doesn't mean they are necessarily in slot 1-4. Thus, if player slot 3 and 5 are the empty ones etc, the values get messed up if I use your code.

Anyways, here is my final solution:

JASS:
function CountPlayers_Actions takes nothing returns nothing
    local integer i = 0
    local integer playercount = 0
    local integer r = 0
    local force f = CreateForce()
    local integer food = 0
    local integer lumber = 0
    local player array p
    local boolean array inForce
    loop
        exitwhen i > 5
        set p[i] = Player(i)
        if GetPlayerController(p[i]) == MAP_CONTROL_USER and GetPlayerSlotState(p[i]) == PLAYER_SLOT_STATE_PLAYING then
            call ForceAddPlayer(f, (p[i]))
            set playercount = playercount + 1
        endif
        set inForce[i] = IsPlayerInForce(p[i], f)
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if inForce[i] == true then
            if playercount >= 6 then
                set food = 1
                set lumber = 3
            else
                if playercount == 5 then
                    set food = 1
                    set lumber = 3
                    set r = 1
                else
                    if playercount == 4 then
                        set food = 1
                        set lumber = 3
                        set r = 2
                    else
                        if playercount == 3 then
                            set food = 2
                            set lumber = 6
                        else
                            if playercount == 2 then
                                set food = 3
                                set lumber = 9
                            else
                                set food = 6
                                set lumber = 18
                            endif
                        endif
                    endif
                endif
            endif
            call SetPlayerState(p[i], PLAYER_STATE_RESOURCE_FOOD_CAP, food)
            call SetPlayerState(p[i], PLAYER_STATE_RESOURCE_LUMBER, lumber)
        endif
        set i = i + 1
    endloop
    set i = 0
    if playercount == 5 or playercount == 4 then
        loop
            exitwhen i > r
                if inForce[i] == true then
                    call SetPlayerState(p[i], PLAYER_STATE_RESOURCE_FOOD_CAP, 2)
                    call SetPlayerState(p[i], PLAYER_STATE_RESOURCE_LUMBER, 6)
                    call ForceRemovePlayer(f, p[i])
                    set i = i + 1
                endif
        endloop
    endif
    set i = 0
    loop
        exitwhen i > 5
        set p[i] = null
        set i = i + 1
    endloop
    call DestroyForce(f)
    set f = null
endfunction

//===========================================================================
function InitTrig_CountPlayers takes nothing returns nothing
    set gg_trg_CountPlayers = CreateTrigger()
    call TriggerAddAction(gg_trg_CountPlayers, function CountPlayers_Actions)
endfunction
 
Last edited:
Status
Not open for further replies.
Top