• 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.

Hashtables vs Variables

Status
Not open for further replies.
Level 2
Joined
Aug 14, 2008
Messages
24
I want to save six integer values for four players sepearately.Should I use a hashtable instead of making arrayed variables?

Also I want to know the benefits of hashtables above variables aside from the obvious double key.
 
Arrays give speed as well. For only a group of players you only need an array.

However, hashtables are able to hold much higher indexes than arrays which are limited to 8192. 8191 if you count the saved-game bug and 8190 if you don't skip the 0 index (structs and unit indexers avoid the 0 index). Hashtables can go as big as integers get, which is 2 ** 32 - 1 (trillions). Oh and they accept negative integers, too, so it's quite a lot more storage capacity.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
Use arrays for small domain problems (such as 6 integers for 4 players as that will only use 24 indicies).

An example of a good hashtable use is storing a value to an ability type, so from an ability type being cast you can get a value. Ability types like all object types have a 32 bit identification value, thus the large range of the hashtable is useful. Equally well, attacking values to handles is another good use as handles have a 32 bit identifier.

Arrays are faster due to how they opperate. It is prety much a bounds check and then a direct memory recall. Where as hashtables have nested bucket arrays (thus need to reduce the hash value to something smaller), then have lists which need to O(n) searched where n is the number of collisions in the bucket and that also means the hashes are stored with every element so that it can be searched accuratly. Do not get me wrong saying hashtables are slow, as they are incomparably faster than doing a linear search on a large pool of data but they are very slow for something simple like 6 integer values per player.
 
Level 5
Joined
Aug 8, 2008
Messages
113
I was going to start a separate thread but saw this one so what are hashtables/indexes/variables/andarrays (I need a simpler explanation than the one given). to record a mui with three units do I use an array or a variable?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
A variable points towards a single address location. This contains a value which can point somwhere else (strings and handles) or contain a direct value (integer, real and boolean). An array is an area of memory which contains multiple locations that can be acessed by an index.

For a more mechanical view...
A variable is nothing more than a 32 bit address which leads to 4 bytes (32 bits) representing a value. An array is a 32 bit address with an offset which leads to 4 bytes (32 bits) representing a value. An array also has an authorised domain which is the array size.

JASS arrays are not proper arrays, they are dynamic arrays meaning that for all purposes you can assume they have 8192 indicies and will not be manipulated as fast as arrays should.

Hashtables use a bucket array and mapping algorthim to try and allocate each given piece of data to a fixed sport using some mapping data so that from the mapping data it be retreived at near O(1) efficiency. The exact way JASS hashtables work is obscured.
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
I'm turning what DSG said towards the practical side (instead of the theoretic side, as that is DSG's strong point).

An array is a variable that can store multiple values.
An example would be the variable "Hero", which stores a unit.
Hero[1] stores the hero of Player 1 (Red)
Hero[2] stores the hero of Player 2 (Blue)
Hero[3] stores the hero of Player 3 (Teal)

As you may begin to see, arrays are widely used for making things MPI (that means Multi-Player Instanceable, or being able to make a system works for ever player).
Any system that uses something of the hero, utilizes that arrayed variable.

Example: if you want to show the movement speed of the hero, you would do:
  • MS
    • Events
      • Player - Player 1 (Red) types a chat message containing -ms as An exact match
      • Player - Player 2 (Blue) types a chat message containing -ms as An exact match
      • Player - Player 3 (Teal) types a chat message containing -ms as An exact match
    • Conditions
    • Actions
      • Game - Display to (Player group((Triggering player))) the text: (Movement Speed: + (String((Current movement speed of Hero[(Player number of (Triggering player))]))))
If Blue said "-ms", then "Hero[(Player number of (Triggering player))]" will turn into "Hero[2]" and will thus show blue's movement speed.

If you know that every player can only have 1 unit either way, and that the cooldown of their spells is greater than the duration of that spell, then making things MUI can be a waste of time (as MPI is good enough).


It IS possible to make things MUI with arrays, but this is more complicated (and limited, but the limit is rather high, so that should not matter), so generally: people use hashtables nowadays.

An array is limited to 8192 indices (from 0 to 8191), meaning that Var[8191] = 5 works, but Var[8192] = 5 would not do anything.

Hashtables are much like dual-arrays (Var[X][Y]), but can take extremely high values and can take any value (real, integer, unit, ...).
Why is this useful? All objects in Warcraft have a special number assigned to them. That number is unique and individual: every unit on the map will have a different number, always.
So when you store the Unit's ID in the first array and use the second array as a quick-slot for specific values, you can make something MUI.

Example:
I cast a spell that should just damage the target after a certain time (a delayed strike).

Var [Unit ID] [0] can hold the timer
Var [Unit ID] [1] can hold the damage
Var [Unit ID] [2] can hold the caster (this is useful when dealing damage)

  • Test trig 1
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Set HandleID = (Key (Target unit of ability being cast))
      • Set Damage = 100.00
      • Set Time = 5.00
      • Hashtable - Save Damage as HandleID of 0 in TestTable
      • Hashtable - Save Time as HandleID of 1 in TestTable
      • Hashtable - Save Handle Of(Triggering unit) as 2 of HandleID in TestTable
      • Unit Group - Add (Target unit of ability being cast) to TestGroup
(You don't particularly need the "Damage" and "Time" variables, you can set them directly in the Hashtable - Save [value]" as well, but if you want to upload your spell, you should create some kind of easy-to-edit system, so using variable like that is the easiest).

As you can see: the HandleID is the ID of the targetted unit. This number is very high and is different for every unit.

Because we need some kind of way to actually do anything with these values.
This is why we create a unit group and we add the unit who's ID we used to store the values in to that group.


Now the loop-trigger would look something like this:
  • Test trig 2
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in TestGroup and do (Actions)
        • Loop - Actions
          • Set HandleID = (Key (Picked unit))
          • Set Time = (Load 1 of HandleID from TestTable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Time Greater than 0.00
            • Then - Actions
              • -------- The spell did not end yet --------
              • -------- We decrease the timer of this unit, because it has to end at some point --------
              • -------- Do not forget this! --------
              • Hashtable - Save (Time - 0.03) as 1 of HandleID in TestTable
            • Else - Actions
              • -------- Ending the spell --------
              • -------- Dealing damage --------
              • Unit - Cause (Load 2 of HandleID in TestTable) to damage (Picked unit), dealing (Load 0 of HandleID from TestTable) damage of attack type Spells and damage type Normal
              • -------- We remove the unit from the group so it won't loop anymore --------
              • Unit Group - Remove (Picked unit) from TestGroup
              • -------- This is necessary to clean up the unused hashtable slots --------
              • Hashtable - Clear all child hashtables of child HandleID in TestTable
I don't know what else I can say here... if anything is not clear, please say so.

Note that this can not be used if the cooldown is lower than the spell duration!
In that case, you can create a dummy unit and set HandleID to Key(last Created Unit), then save both the target and the caster in the hashtable.
Add the dummy unit to the group, loop through it and do anything as you would normally, but whenever you make any unit-related changes (move the unit, damage, ...), then you should use the value you stored in the hashtable as the target.



Anything else?
 
Status
Not open for further replies.
Top