• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

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
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
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.
 
Level 13
Joined
Oct 16, 2010
Messages
731
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?
 
Level 8
Joined
Jul 17, 2004
Messages
283
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
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
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.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
Or you can try the most awesome approach.

Don't use a loop and go through all index 1 by 1.
 
Level 25
Joined
Sep 26, 2009
Messages
2,377
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.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
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.
 
Level 8
Joined
Jul 17, 2004
Messages
283
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.
 
Level 8
Joined
Jul 17, 2004
Messages
283
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
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
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.
 
Level 8
Joined
Jul 17, 2004
Messages
283
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:
Level 8
Joined
Jul 17, 2004
Messages
283
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?
 
Level 8
Joined
Jul 17, 2004
Messages
283
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?
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
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.
Top