• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Looping through 2d arrays

Status
Not open for further replies.
I'm having some problems with a system i made for keeping track of so called "public relations" or "public unrest" between nations in my map. The concept is that nations will get reduced income if they are allied to a player who have historically been an enemy. The relations between nations improve the longer they stay allied, but gets worse when they are at war.

There are only two functions called from this library; "ModifyRelations" and "SetRelations".
The first is used to increase/reduce the relation value between two countries by a certain ammount, while the other is called periodically to increase/reduce the value depending on wether the nations are allied or not. This adds to a variable that will then help set the income reduction for the given player.
Basically, the SetRelations loop through all players, passing their index to another function that compares him with players in the second dimension of the "RELATIONS" array (which is a 2d array).

The problem is that it somehow doesn't read past the line where it calls the "RelationsCallback", and instead calls it over and over again, reducing the relation value of every nation down until it reaches 0. Nothing below the function call appears to be read.

Why is this happening?


JASS:
library PublicRelations initializer Init

globals
    integer array RELATIONS[12][12]
    real array TAX_FACTOR[12]
    private integer MAXY = 12
endglobals

function ModifyRelations takes integer playerindex, integer targetindex, integer reduction returns nothing
    if reduction < 0 then
      if RELATIONS[playerindex][targetindex]-reduction < -50 then
        set RELATIONS[playerindex][targetindex] = -50
      else
        set RELATIONS[playerindex][targetindex] = RELATIONS[playerindex][targetindex]-reduction
      endif
    endif

    if reduction > 0 then
      if RELATIONS[playerindex][targetindex]+reduction > 50 then
        set RELATIONS[playerindex][targetindex] = 50
      else
        set RELATIONS[playerindex][targetindex] = RELATIONS[playerindex][targetindex]+reduction
      endif
    endif

endfunction

private function RelationsCallback takes integer p returns integer
local integer i = 0
local integer unrest = 0

  loop
    exitwhen i == 11

    if ( IsPlayerEnemy(Player(p), Player(i)) ) then
      if RELATIONS[i]-2 < -50 then
        set RELATIONS[i] = -50
      else
        set RELATIONS[i] = RELATIONS[i]-2
      endif
    endif

    if ( GetPlayerAlliance(Player(p), Player(i), ALLIANCE_SHARED_VISION) == true ) then
      if RELATIONS[i]+1 > 50 then
        set RELATIONS[i] = 50
      else
        set RELATIONS[i] = RELATIONS[i]+1
      endif
    endif
    
    
    if ( GetPlayerAlliance(Player(p), Player(i), ALLIANCE_SHARED_VISION) == true ) then
      if (RELATIONS[i] < -40) then
        set unrest = unrest +15
      else
         if (RELATIONS[i] < -30) then
           set unrest = unrest +10
         else
            if (RELATIONS[i] < -20) then
              set unrest = unrest +5
         endif
       endif
      endif
    endif
    
    call BJDebugMsg("made it here, relations:"+I2S(RELATIONS[i]))
    call BJDebugMsg(I2S(i))
    set i = i+1
  endloop
  
  return unrest
endfunction

function SetRelations takes nothing returns nothing
  local integer i = 0
  local integer f
  local real inc

  loop
      exitwhen i == 11
    set f = RelationsCallback(i)
    
    if (f>10) then
      set inc = 1-(f*0.02)
    endif
    if (inc<0.10) then
      set inc = 0.10
    endif
    call BJDebugMsg("INC: "+R2S(inc))
    
    set TAX_FACTOR[i] = inc
    //I will add some extra conditions to the below line; don't worry about it. 
    call DisplayTextToPlayer(Player(i), 0., 0., "[WARNING]: Your population is displeased with you choice of alliance, your tax rates are cut by "+R2S(f*0.02)+" Percent!")
    set i = i+1
  endloop

endfunction

// 0 = USSR
// 1 = USA A
// 2 = null
// 3 = China
// 4 = null
// 5 = Britain A
// 6 = Italy
// 7 = null
// 8 = Germany
// 9 = USA P
// 10 = Finland
// 11 = Japan

private function Init takes nothing returns nothing
//Initialization values

//USSR
local integer i = 12
local integer p = 0
set RELATIONS[1] = -8
set RELATIONS[2] = 0
set RELATIONS[3] = 5
set RELATIONS[4] = 0
set RELATIONS[5] = 0
set RELATIONS[6] = -5
set RELATIONS[7] = 0
set RELATIONS[8] = -50
set RELATIONS[9] = -8
set RELATIONS[10] = -30
set RELATIONS[11] = -30

//USA A
set p = 1
set RELATIONS[0] = -8
set RELATIONS[2] = 0
set RELATIONS[3] = 15
set RELATIONS[4] = 50
set RELATIONS[5] = 50
set RELATIONS[6] = -10
set RELATIONS[7] = 0
set RELATIONS[8] = -50
set RELATIONS[9] = 50
set RELATIONS[10] = 0
set RELATIONS[11] = -40

//China
set p = 3
set RELATIONS[0] = 5
set RELATIONS[1] = 15
set RELATIONS[2] = 0
set RELATIONS[4] = 10
set RELATIONS[5] = 10
set RELATIONS[6] = -10
set RELATIONS[7] = 0
set RELATIONS[8] = -50
set RELATIONS[9] = 15
set RELATIONS[10] = 0
set RELATIONS[11] = -50

//Britain E
set p = 4
set RELATIONS[0] = 0
set RELATIONS[1] = 50
set RELATIONS[2] = 0
set RELATIONS[3] = 10
set RELATIONS[5] = 50
set RELATIONS[6] = -40
set RELATIONS[7] = 0
set RELATIONS[8] = -50
set RELATIONS[9] = 50
set RELATIONS[10] = 0
set RELATIONS[11] = -40

//Britain A
set p = 5
set RELATIONS[0] = 0
set RELATIONS[1] = 50
set RELATIONS[2] = 0
set RELATIONS[3] = 10
set RELATIONS[4] = 50
set RELATIONS[6] = -40
set RELATIONS[7] = 0
set RELATIONS[8] = -50
set RELATIONS[9] = 50
set RELATIONS[10] = 0
set RELATIONS[11] = -40

//Italy
set p = 6
set RELATIONS[0] = -30
set RELATIONS[1] = -15
set RELATIONS[2] = 0
set RELATIONS[3] = 0
set RELATIONS[4] = 0
set RELATIONS[5] = 0
set RELATIONS[7] = 0
set RELATIONS[8] = 50
set RELATIONS[9] = -15
set RELATIONS[10] = 10
set RELATIONS[11] = 0

//Germany
set p = 8
set RELATIONS[0] = -50
set RELATIONS[1] = -30
set RELATIONS[2] = 0
set RELATIONS[3] = 0
set RELATIONS[4] = -50
set RELATIONS[5] = -50
set RELATIONS[6] = 50
set RELATIONS[7] = 0
set RELATIONS[9] = -30
set RELATIONS[10] = 50
set RELATIONS[11] = 30

//USA P
set p = 9
set RELATIONS[0] = -8
set RELATIONS[1] = 50
set RELATIONS[2] = 0
set RELATIONS[3] = 15
set RELATIONS[4] = 50
set RELATIONS[5] = 50
set RELATIONS[6] = -10
set RELATIONS[7] = 0
set RELATIONS[8] = -50
set RELATIONS[10] = 0
set RELATIONS[11] = -40

//Finland
set p = 10
set RELATIONS[0] = -50
set RELATIONS[1] = 0
set RELATIONS[2] = 0
set RELATIONS[3] = 0
set RELATIONS[4] = 20
set RELATIONS[5] = 20
set RELATIONS[6] = 20
set RELATIONS[7] = 0
set RELATIONS[8] = 50
set RELATIONS[9] = 0
set RELATIONS[11] = 10

//Japan
set p = 11
set RELATIONS[0] = -30
set RELATIONS[1] = -40
set RELATIONS[2] = 0
set RELATIONS[3] = -50
set RELATIONS[4] = 0
set RELATIONS[5] = 0
set RELATIONS[6] = 0
set RELATIONS[7] = 0
set RELATIONS[8] = 50
set RELATIONS[9] = -40
set RELATIONS[10] = 0


loop
  set TAX_FACTOR[i] = 1.
    exitwhen i == 0
  set i = i-1
endloop

endfunction

endlibrary
 
I'm pretty sure that player indexes starts at 0 and ends at 11? Otherwise you'd have 13 player indexes?

EDIT: By the way, i realize now what you mean. A question about this though; if i place the "exitwhen" line at the bottom of the loop, will it call the above lines first then, before it checks the exit condition?
 
I'm pretty sure that player indexes starts at 0 and ends at 11? Otherwise you'd have 13 player indexes?

EDIT: By the way, i realize now what you mean. A question about this though; if i place the "exitwhen" line at the bottom of the loop, will it call the above lines first then, before it checks the exit condition?

yes, the exitwhen is only evaluated when the engine reaches that line...
 
then use a loop inside a loop, where's the problem on that?

JASS:
/*
Example... just an example...

*/
local integer i = 0
local integer x = 0
loop
    exitwhen i > 11
    set x = 0
    loop
         exitwhen x > 11
         //You checks here
         //example, hypothetical function
         if not IsPlayerAlly(Player(i), Player(x)) then
         endif
         
    endloop
    set i = i + 1
endloop
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,287
A 2D array in WC3 is basically an array broken up into rows/columns via maths. Thus why a maximum size parameter is needed.

If vJASS was properly made, it would permit the virtual type cast from a 2D array into a 1D array with a predicted maximum of D1*D2. You could then loop through all indicies in the 2D array via a simple loop from 0 to D1*D2. D1 and D2 are the sizes of the demensions.

Adiktuz, a loop inside a loop may be how to do it in languages like java where 2D arrays are an array of arrays (data stored discontiniously), but in WC3 where it is a mapped 1D array it is just plain stupid and unefficient.

The basic principle behind 2D arrays via mapping a 1D array is a formula like Y*maxX+X with certain restrictions on the domain of Y and X. With more complicated maths it is even possible to do N demensional arrays but that becomes ever slower (and thus why arrays of arrays method is used in reality in programming as that can get a result from an N demensional array with N array lookups unlike mapped 1D arrays which need N-1 variable look ups and N-1 multiplication and N addition).
 
Status
Not open for further replies.
Top