• 🏆 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!

Variable doubling each update cycle (SOLVED)

Level 2
Joined
Nov 1, 2023
Messages
8
I'm trying to make a trigger that updates on a regular cycle. Every update cycle, it's supposed to take a variable (the increment), add it to another variable (the old value), and save the result (the new value). However, while most of this seems to work, the updates appear to be updating the increment itself, as well. Specifically, doubling it on every update. The update function is shown below:
  • Events
    • Time - Every 1.00 seconds of game time
  • Conditions
  • Actions
    • Player Group - Pick every player in empirePlayers and do (Actions)
      • Loop - Actions
        • Set CurrentBoard = (Load (Player number of (Picked player)) of (Integer(multiboards)) in empireTables)
        • -------- Update population --------
        • -------- Update Ore --------
        • Set oldValue = (Load (Player number of (Picked player)) of (Integer(currentOre)) from empireTables)
        • Set increment = (Load (Player number of (Picked player)) of (Integer(currentMiners)) from empireTables)
        • Game - Display to (Player group((Picked player))) the text: (Current Miners: + (String((Load (Player number of (Picked player)) of (Integer(currentMiners)) from empireTables))))
        • Set newValue = (oldValue + increment)
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • increment Greater than 0
          • Then - Actions
            • Set localString = (((String(newValue)) + |cff55ff55(+) + ((String(increment)) + )|r))
          • Else - Actions
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • increment Less than 0
              • Then - Actions
                • Set localString = (((String(newValue)) + |cffff5555() + ((String(increment)) + )|r))
              • Else - Actions
                • Set localString = ((String(newValue)) + (+0))
        • Hashtable - Save newValue as (Player number of (Picked player)) of (Integer(currentOre)) in empireTables
        • Multiboard - Set the text for CurrentBoard item in column 1, row 1 to localString
I strongly suspect I've messed up how I'm storing or retrieving from the hashtable, and I am definitely stepping out of my depth in using them here. Am I trying to apply them to the wrong use case, or is there something simple I'm messing up that can be cleanly fixed? Alternatively, have I misdiagnosed the problem, and is there some other area where my trigger's malformed? (The game display line is just for debugging purposes.)

Additionally, if it's important: I am working with classic Warcraft III, not Reforged.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
What's with the Real To Integer conversion for all of your Variables? Integer(multiboards), Integer(currentOre), Integer(currentMiners), etc.

Shouldn't those variables be Integers to begin with? It's not like you can have 2.5 multiboards or something.

Reals suffer from floating point error which means that they aren't guaranteed to be exact, particularly after Arithmetic. So for example, when you convert a Real to an Integer there's a chance that what you expect to be 3.0 -> 3, is actually 2.999999 -> 2 due to imprecision and how Warcraft 3 always rounds down.

If you use Integers instead it should fix the problem since they're always precise. So instead of using the Hashtable - Save/Load Real function, use the Hashtable - Save/Load Integer function and change your variables to Integers. If you MUST use a Real, you can add a small value like +0.001 to the Real during the Integer conversion. This should help offset the imprecision and give you the expected results after the converting and rounding takes place.

I also recommend introducing an Integer variable for (Player number of (Picked player)). It will make the trigger a lot easier to read and would have made it easier to work with had you used it from the start:
  • Loop - Actions
    • Set PN = (Player number of (Picked player))
 
Last edited:
Level 2
Joined
Nov 1, 2023
Messages
8
Ah, yeah. Using a player number variable does sound helpful there. As for the conversions, they're being done from strings, not reals. I'm not sure if that's better or worse, but I'm pretty sure that string characters are at least usually much more constant than floating points. The conversions are just to maintain readability, and make it easier to keep straight which keys point where. Should I hand-define a bunch of integer variables instead?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
Ah, yeah. Using a player number variable does sound helpful there. As for the conversions, they're being done from strings, not reals. I'm not sure if that's better or worse, but I'm pretty sure that string characters are at least usually much more constant than floating points. The conversions are just to maintain readability, and make it easier to keep straight which keys point where. Should I hand-define a bunch of integer variables instead?
Ah, that makes a lot more sense.

You can still try switching to Integers since Strings may be causing the problem - plus it'd be more efficient (not that it's a very big deal).

I often do something like this to declare "constants" for my keys:
  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set KEY_MULTIBOARD = 0
    • Set KEY_ORE = 1
    • Set KEY_MINERS = 2
Other than that, I can't see what would cause the doubling effect you mentioned. I suspect you may have another trigger interfering.
 
Last edited:
Level 2
Joined
Nov 1, 2023
Messages
8
I figured it couldn't be in other triggers because this is the only one that regularly repeats. That said, I tried setting the keys to hard integers and... that worked. I have no idea why a wonky key would cause value doubling of all things, but it appears to work exactly as intended now. Which is very good news to me, since it means I can still avoid putting all of this data in hard variables or arrays, saving me considerable headache.

Anyways, point is that appears to have cleared it right up, so thanks a lot.
 
Top