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

What does the Hashtable thing do ?

Status
Not open for further replies.
Level 28
Joined
Jan 26, 2007
Messages
4,789
Hmh, you can look at it as a variable, yes.

Are you familiar with arrays?
Because one way one can look at a hashtable, is as a 2D-array.
This means that where a regular array would be something like:
"Hero[1]" (the hero for player 1)​
a 2D-array would be:
"Hero[1][1]" (the first hero for player 1, where:
"Hero[1][2]" would be the second hero for player 1).​

If you understood that, then you're halfway through understanding a hashtable.
However: just a 2D-array isn't enough to justify a hashtable (because a 2D-array can be created with a single array with a little math).
What's so brilliant about a hashtable, is that each array can have up to '231 - 1' slots.
A regular array can only contain 8192 slots (a couple billion less).

So what's the use of 2 billion slots (might even be 4 billion if you count negative integers)?
Well, for one: each object you place on the map has a specific ID (no other object on the map can ever have that same ID).
This ID is usually a very large number (way larger than 8192, which means it's too big for a regular array).
With hashtables, we can do something like this:
"Variable[UNIT_ID][0] = 42"​
This will save the value 42 for the unit with id UNIT_ID. It saves a value for a specific object.

For making things MUI, being able to save things for a specific object is an amazing convenience.

Further reading.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
After you learn what is Hashtable, you will know that this is a method to save data in a structured manner.
You should search "Indexing" too, it's one of method to save data in a structured manner too, but has different approach.

Each of them has their own cons and pros, ultimately it depends on the situation.

Hashtable favours in a situation where you need to save something and be used for future use (does not relate to time) such as when Player enters "-kill", kills a certain unit.

Indexing favours in a situation where the data is related to time such as the trigger is in sequential order.

It's hard to explain and understand too, but once you grab these methods of data storing, you'll be able to produce almost any kinds of trigger, mostly MUI-based trigger.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
In a VARIABLE you can store ONE VALUE.
Ex. tempUnit = Unit

In a VARIABLE ARRAY you can store up to 8192 values
Ex. tempUnit[1] = Unit / tempUnit[2] = Unit / tempUnit[3] = Unit...

In a HASHTABLE you can store millions of values of any kind attached to millions of objects of any kind. As ap0calypse said, it's a 2D array.

You can give them many uses, it depends on what you want.
 
Level 5
Joined
May 12, 2013
Messages
70
Hmh, you can look at it as a variable, yes.

Are you familiar with arrays?
Because one way one can look at a hashtable, is as a 2D-array.
This means that where a regular array would be something like:
"Hero[1]" (the hero for player 1)​
a 2D-array would be:
"Hero[1][1]" (the first hero for player 1, where:
"Hero[1][2]" would be the second hero for player 1).​

If you understood that, then you're halfway through understanding a hashtable.
However: just a 2D-array isn't enough to justify a hashtable (because a 2D-array can be created with a single array with a little math).
What's so brilliant about a hashtable, is that each array can have up to '231 - 1' slots.
A regular array can only contain 8192 slots (a couple billion less).

So what's the use of 2 billion slots (might even be 4 billion if you count negative integers)?
Well, for one: each object you place on the map has a specific ID (no other object on the map can ever have that same ID).
This ID is usually a very large number (way larger than 8192, which means it's too big for a regular array).
With hashtables, we can do something like this:
"Variable[UNIT_ID][0] = 42"​
This will save the value 42 for the unit with id UNIT_ID. It saves a value for a specific object.

For making things MUI, being able to save things for a specific object is an amazing convenience.

Further reading.


I understood it here because you wrote something like
" Variable[UNIT_ID][0] = 42"
But in the Hastables, its written so confusingly, its something like :
" Hashtable - Save 10.0 as 0 of 0 in Hastable "

- What's this "10" here ?
- Whats the 10 as "0" ?
- What's the 0 of "0" ?
- What does this all mean ?
:vw_wtf:

-Why would we need to store the ID of each and every single object in the map ?
-Even if we would need to, we can store it in a variable as well ? Right ?
Its ID is greater than 8192, not its size, because it would only count as 1 object ? right ?

I'm so never gonna get this !

:vw_wtf: :vw_sad:
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Save "Value" as "Index 1" of "Index 2" in "Variable"

so

"Variable"["Index 1"]["Index 2"] = "Value"

so Save 10 as 1 of 5 in Ownage

sets

Ownage[1][5] = 10

Note that unit IDs are MUCH larger than 8192 which is the physical variable limit for normal variables. Hashtables allow indexes up to 2^32, so theyre big enough to save for all units. Lets say you wanted to save an item drop for a unit type

so you can do

Save (Item Id) as (Unit Id) of (0) in (Creep Drop Table)

which is

Creep Drop Table[Unit ID][0] = Item Id

so when you go to drop an item you can do

Create Item(CreepDropTable[Unit Id of Dying Unit][0]
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
@Arhowk: in GUI, the child comes first and then the parent (because it's the reverse order of the JASS native).
Meaning that if you wish to use the unit ID as the parent, then it should be:
"Save (value) as 0 of ID in Hashtable"​
(Instead of "as ID of 0", for the record).

@DJAB: I explain more about parents and children in the last paragraph in the link "Further Reading" (previous post).
You might want to read that little bit, because it's really good if you know how the structure of a hashtable looks like (kind-of like folders/files on your PC).

Why would we need to store the ID of each and every single object in the map?
We're not storing the ID. We're using it in the array.
Think of player numbers: when you use "Hero[1]", you're not saving the player number, right? You're using the player number to store a unit.
So if we store Var[ID][0], we're not storing the ID, we're storing some other value that is specific to the unit with as id "ID" (an integer).

It's the exact same logic behind it, you're just using unit id's here and not player numbers.
(You can also use unit-types, item-types or anything else you like).

Its ID is greater than 8192, not its size, because it would only count as 1 object ? right ?
Not quite sure what you mean here.
Every object just has an integer appointed to it (again, just like players).

Player Red, for example, has the integer '1' appointed to it. We can reference to him as "Player 1".
A unit has the same thing, but it's a really large number (with player numbers we can use a normal array, because it's between 1 and 16, but that doesn't work for units).
Example: Unit Footman 0001 has the integer '11005866' appointed to it. We can reference that unit by using "object 11005866".

Since I'm not sure about the question, I don't know if the answer clears it up. I hope it does :).
 
Level 5
Joined
May 12, 2013
Messages
70
Ok, i think i got it a little, but its still confusing.
It'd be nice if someone can give an example or two of a trigger using hashtables for a purpose. Because i'm confused how or why the hastables would be used !
 
Level 30
Joined
Nov 29, 2012
Messages
6,637
Ok, i think i got it a little, but its still confusing.
It'd be nice if someone can give an example or two of a trigger using hashtables for a purpose. Because i'm confused how or why the hastables would be used !

Its really good that you want to learn! Try this link: Beginner's Guide to Hashtables and it contains some example triggers. Focus your attention to this!
 
They are use normally when using the key of a unit. Its their handle id which is unique to every object in wc3. This allows u to store data with a specific unit rather easy. Also u can do a condition check to see if unit is in hashtable rather than having to loop through all indexes in a unit array. This makes them much faster when retrieving info and less work.
That link hell master provided is a great guide to use.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Lets say you want to make a Wc3 Farm, where you have bulls, cows, and rabbits. They're passive but some of them become ill or mad, and you have to kill them to save the rest, or defeat other animals like bugs and crows (just an Idea, i won't go deep on this in the triggers)

Every time you save an animal it gains some experience, and with level gain it produces more or better milk, Bulls are better paid when you sell them, and rabbits reproduce faster (more food, more product to sell), you can improve rabbits speed, bulls attack, and cows "call for help" range.

For that you need to keep track of EACH COW, EACH BULL, and EACH BUNNY level (Variable 1: Level), also their experience (Variable 2: current experience) and the experience they need for the next level (Variable 3: Experience required to next level).

As other said, every object in the map has an specific Id wich can be used as a "codebar" to identify map elements. It can be known by using some functions (jass) a very large integer. You can use: GetHandleId(Unit) to know the specific unit Id or GetUnitTypeId(Unit) to know the generic Id all the units of that type use.

Now you need to specify some formula for units to get level lets say the max lvl is 5, and they require 100 experience per level. (level 1: 100 / lvl 2: 200, etc.)

Note: "udg_" prefix stands for "user defined global", which are the common variables you use in GUI. It's required in JASS. If you create "Id" variable, it's "udg_Id" in jass. And lets remember our variables:

1 - level
2- exp
3- req exp

  • Trigger 1
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
    • Actions
      • Set UnitVar = (Triggering unit)
      • Custom script: set udg_Id = GetHandleId(udg_UnitVar)
      • -------- Variable 1: Level --------
      • Set Level = 1
      • Hashtable - Save Level as 0 of Id in Hash
      • -------- Saved LEVEL(1) in DataSlot ZERO(0) in the Unit (Id) in the HASHTABLE --------
      • -------- Variable 2: Experience --------
      • Set Exp = 0
      • Hashtable - Save Exp as 1 of Id in Hash
      • -------- Saved Experience(0) in DataSlot ONE(1) in the Unit (Id) in the HASHTABLE --------
      • -------- Variable 3: Required Experience --------
      • Set ReqExp = (Level x 100)
      • Hashtable - Save ReqExp as 2 of Id in Hash
      • -------- Saved ReqExperience(Exp*100) in DataSlot TWO(2) in the Unit (Id) in the HASHTABLE --------
Now, lets say each enemy gives 20 experience divided amongs units in 600 AoE. If one of your units level up, you have to update the level and the required experience.

  • Trigger 2
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Custom script: set bj_wantDestroyGroup = true
      • Set UnitVar = (Triggering unit)
      • Set PointVar = (Position of UnitVar)
      • Set GroupVar = (Units within 600.00 of PointVar)
      • Set ExpGained = (20 / (Number of units in GroupVar))
      • Unit Group - Pick every unit in GroupVar and do (Actions)
        • Loop - Actions
          • Set UnitVar = (Picked unit)
          • Custom script: set udg_Id = GetHandleId(udg_UnitVar)
          • -------- Variable 1: Level --------
          • Set Level = (Load 1 of Id from Hash)
          • -------- Variable 2: Experience --------
          • Set Exp = ((Load 2 of Id from Hash) + ExpGained)
          • Hashtable - Save Exp as 1 of Id in Hash
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Exp Greater than or equal to ReqExp
            • Then - Actions
              • -------- Variable 1: Level --------
              • Set Level = ((Load 1 of Id from Hash) + 1)
              • Hashtable - Save Level as 0 of Id in Hash
              • -------- Variable 3: Required Experience --------
              • Set ReqExp = (Level x 100)
              • Hashtable - Save ReqExp as 2 of Id in Hash
            • Else - Actions
      • Custom script: call RemoveLocation(udg_PointVar)
      • Custom script: call DestroyGroup(udg_GroupVar)
You can see how I set experience = current experience (stored in hashtable) + new experience. Then saving again in the hashtable. Then I check if that experience is higher than the experience required to increase level and if it's, increase the unit level and update the experience required.

Done. There's your farm. Some details as an experience chart, cow price, milk production, bull price, rabbit price, animal reproduction rate, enemy difficulty, etc., can be saved and lodaded exactly in the same way.

Just keep track of what use you give to each slot in the Unit Id. Here i used slot 1 for Level, Slot 2 for experience, slot 3 for required experience. You can use slot 4 for Milk production if it's a cow, Slot 4 for horn length if it's a bull, Slot 4 for meat price if it's a rabbit. Slot 5 for reproduction rate, and so on.

You can even have a Mendel's chart with the dominant and passive gens each animal has, and get units with specific abilities based in how you mix them... just A Hashtable and some math.

I didn't want to to deep in triggers (Like picking units matching conditions, and stuff) just to stablish a possible and easy Hashtable usage. It isn't required to do it exactly as it's, you can do the math directly in the hash without having to use the variables, but I wanted to just to make it easier to read for you. I would also suggest you to use the JASS form of Hash save/Load, since it's faster for the system (BJ avoid) and, at least for me, easier to read, and it just reverses the arguments order, so it's easy to learn.

A = Value: 5
B = Slot: 2
C = Id: 8733894324
D = Hash

In GUI You save: *A* as *B* of *C* in *D*
In Jass you do: *D*, *C*, *B*, *A*
  • Hashtable - Save A as B of C in D
JASS:
call SaveInteger(D, C, B, A)
 
Level 5
Joined
May 12, 2013
Messages
70
@Spartipilo : Thanks a billion. I get it now. That was a great example ! REP+

@Hell Master : Thanks for that guide, its also good, but if i continue to read it all, i would forget what i just learnt.
I think i would mess up with the Hastables and experiment with them, and learn about it from that !

Anyways Thanks all !
 
Level 30
Joined
Nov 29, 2012
Messages
6,637
@Spartipilo : Thanks a billion. I get it now. That was a great example ! REP+

@Hell Master : Thanks for that guide, its also good, but if i continue to read it all, i would forget what i just learnt.
I think i would mess up with the Hastables and experiment with them, and learn about it from that !

Anyways Thanks all !

Hehehe... its okay.:xxd:
 
Status
Not open for further replies.
Top