• Check out the results of the Techtree Contest #19!
  • 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.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

Need help with For Each Integer A, Do Actions

Status
Not open for further replies.
Level 8
Joined
Jul 17, 2004
Messages
283
Is there any way to set this up so it's For each (Integer temp_Int) from 2 to 5 AND 8 to 11, do (Actions)?

  • For each (Integer temp_Int) from 1 to 10, do (Actions)
    • Loop - Actions
 
Two approaches.
Inner - Run from 2 to 11 and skip 6 and 7.
Outer - Nest the loop inside another loop. This loop runs twice and uses an array to get the player slots (feeds them as input to the inner loop).

Outer is technically more efficient as it does not iterate through unwanted values but inner is much easier to do. Efficiency is not a concern unless you plan to run this many times a second.

separate it to two separate for each loops maybe?
I think you'll just have to do two separate loops in the same trigger, but not in each other.
This results in very bad procedural coupling. You are basically creating a completely duplicate block of code. Not only does this make maintenances more hard but also wastes space. Both the solutions above will perform similarly but with the advantage that you only have 1 block of code.
 
For a start if you want it to work for 11 then the final number needs to be 11...

Otherwise, put your next part as an "if, then, else" function. Put in an "or multiple conditions". And now is where it gets complicated as you'll need 2 seperate "and multiple conditions" where the first has 2 integer conditions which would be "greater than or equal to 2" and "less than equal to 5". The second and function will have "Greater than or equal to 8" and "less than or equal to 11".

Also another pointer is that you don't need to do it from 1 to whatever if you aren't using 1 for anything surely? Just have the first boundry as 1 to 4 and the second as 7 to 10 and it'll work the same?
 
Well this is what I did. Is this efficient enough? For the event, I am using a Periodic Timer that repeats every 0.03 seconds.

I only want this to run for 2-5 and 8-11.

  • For each (Integer temp_Int) from 1 to 11, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • temp_Int Not equal to 1
          • temp_Int Not equal to 6
          • temp_Int Not equal to 7
        • Then - Actions
          • -------- Actions --------
        • Else - Actions
 
Array list is faster. Use one to define a mapping from 0 to 7 to 2 to 5 and 8 to 11.

The array list will look like...
SlotMap[0] = 2
SlotMap[1] = 3
SlotMap[2] = 4
SlotMap[3] = 5
SlotMap[4] = 8
SlotMap[5] = 9
SlotMap[6] = 10
SlotMap[7] = 11
SlotMapMax = 12

Then all you need to do is loop from 0 to 7 and use that loop integer as the index to SlotMax to get your value. This is probably the most efficient way as it avoids tests.
 
Or you can try the most awesome approach.

Don't use a loop and go through all index 1 by 1.
 
Do the loops number matter? In your first post, you wrote you wanted loop from 2 to 5 and 8 to 11.

8 is greater than 2 by 6 and the number of loops is same (2-5 is 4 loops, just like 8-11).
So you could make stuff like
Code:
For each integer loop_var from 2 to 5 do actions
    Loop (actions)
        Set variable[loop_var] = something
        Set variable[loop_var + 6] = something else
This way, you end up with 2-5 indexes for variable set in the first line, and indexes 8-11 set in the second action.
 
This way, you end up with 2-5 indexes for variable set in the first line, and indexes 8-11 set in the second action.
Would require declaring the code in a function (not supported in GUI, slower in any case due to JASS being rubbish) to avoid procedural coupling.

Don't use a loop and go through all index 1 by 1.
JASS is not a functional language so it does not support map operations.
 
Array list is faster. Use one to define a mapping from 0 to 7 to 2 to 5 and 8 to 11.

The array list will look like...
SlotMap[0] = 2
SlotMap[1] = 3
SlotMap[2] = 4
SlotMap[3] = 5
SlotMap[4] = 8
SlotMap[5] = 9
SlotMap[6] = 10
SlotMap[7] = 11
SlotMapMax = 12

Then all you need to do is loop from 0 to 7 and use that loop integer as the index to SlotMax to get your value. This is probably the most efficient way as it avoids tests.

Like this?

So if we're working with 2-5 and 8-11...

  • Set qq_SlotMap[1] = 2
  • Set qq_SlotMap[2] = 3
  • Set qq_SlotMap[3] = 4
  • Set qq_SlotMap[4] = 5
  • Set qq_SlotMap[5] = 8
  • Set qq_SlotMap[6] = 9
  • Set qq_SlotMap[7] = 10
  • Set qq_SlotMap[8] = 11
  • For each (Integer qq_SlotMap[temp_Int]) from 1 to 8, do (Actions)
    • Loop - Actions
      • -------- Actions --------
temp_Int is just a temporary integer variable I created. It isn't assigned anything.
 
Please post an example? Because I am confused.

And how would that be any better than this:

  • For each (Integer temp_Int) from 2 to 11, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • temp_Int Not equal to 6
          • temp_Int Not equal to 7
        • Then - Actions
          • -------- Actions --------
        • Else - Actions
 
Please post an example? Because I am confused.
Put this somewhere at map initialization.
  • Set qq_SlotMap[0] = 2
  • Set qq_SlotMap[1] = 3
  • Set qq_SlotMap[2] = 4
  • Set qq_SlotMap[3] = 5
  • Set qq_SlotMap[4] = 8
  • Set qq_SlotMap[5] = 9
  • Set qq_SlotMap[6] = 10
  • Set qq_SlotMap[7] = 11
Notice that arrays run from 0 to 8191. Although 8191 should be avoided due to a save/load bug in WC3.

  • For each (Integer temp_Int) from 0 to 7, do (Actions)
    • Loop - Actions
      • -------- Actions --------
This is then used as a look up in your array.

  • -------- Actions --------
  • Do something with integer (qq_SlotMap[temp_Int))
And how would that be any better than this:
Avoids unnescescary tests in exchange for array lookups. In JASS with this scale of numbers it is questionable if it is faster or slower however in GUI since conditional tests are horribly slow due to separate function calls they require it will be noticeably faster.
 
Okay, like this?

  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set SLOTMAP[1] = 2
    • Set SLOTMAP[2] = 3
    • Set SLOTMAP[3] = 4
    • Set SLOTMAP[4] = 5
    • Set SLOTMAP[5] = 8
    • Set SLOTMAP[6] = 9
    • Set SLOTMAP[7] = 10
    • Set SLOTMAP[8] = 11
  • For each (Integer SLOTMAP_TempInt) from 1 to 8, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit[SLOTMAP[SLOTMAP_TempInt]] is dead) Equal to True
        • Then - Actions
          • Set UnitStatus[SLOTMAP[SLOTMAP_TempInt]] = False
        • Else - Actions
          • Set UnitStatus[SLOTMAP[SLOTMAP_TempInt]] = True
The If/Then/Else is supposed to be an example used for the loop.
 
Last edited:
Even if I'm checking with For each (Integer SLOTMAP_TempInt) from 1 to 8, do (Actions)???

Because that's checking between 1-8, and 0 isn't included???

I like to check beginning with 1 for the sake of simplicity on my end. Like if I am storing a unit, I'd rather store the unit on 1 instead of 0. Is there really any down side checking starting at 1 instead of 0?
 
No, you can set it to 0, but all I am asking is...is there anything wrong with me starting with 1 and not using 0?
 
No, you can set it to 0, but all I am asking is...is there anything wrong with me starting with 1 and not using 0?
Logically? No.
Technically? Yes.

It will work but you equivalently waste index 0. This is unlikely to make much of a difference in JASS as arrays expand in powers of two (so the array is probably larger than you need anyway, the difference would be around critical values) but in languages like C, C++ or Java it would waste an extra array element size worth of memory.
 
Logically? No.
Technically? Yes.

It will work but you equivalently waste index 0. This is unlikely to make much of a difference in JASS as arrays expand in powers of two (so the array is probably larger than you need anyway, the difference would be around critical values) but in languages like C, C++ or Java it would waste an extra array element size worth of memory.

What he is trying to say, X-Death, is no. Just use 1 as start value. It works perfectly fine and will not screw up anything.
 
Status
Not open for further replies.
Back
Top