• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] 2d simple jass array?

Status
Not open for further replies.
Level 3
Joined
Mar 20, 2008
Messages
27
Just as the title says is it possible to make a 2d array in the simple jass ?
For the first instance i need it to make a quest array for all the players, and secondly i need it for an item table :) Thanks in advance :)
 
Level 9
Joined
Mar 25, 2005
Messages
252
It is pretty simple. For example, if you want to have a 2d array where one index is a player's id, you can do:
JASS:
function Set2D takes integer playerId, integer secondIndex, <type> value returns nothing
    set udg_myVar[playerId + 16 * secondIndex] = value
endfunction
function Get2D takes integer playerId, integer secondIndex returns <type>
    return udg_myVar[playerId + 16 * secondIndex]
endfunction
Here the 16 comes from the fact that player ids range from 0 to 15 (to my recollection).

If you want to understand why this works, you can stare at the results of the [playerId + 16 * secondIndex] function and see how it doesn't generate overlapping indexes i.e. numbers in the third column occur only once for the given values:
playerIdsecondIndexplayerId + 16 * secondIndex
000
0116
0232
0348
0464
0580
0696
07112
08128
09144
0......
101
1117
1233
1349
1465
1581
1697
17113
18129
19145
1......
202
2118
2234
2350
2466
2582
2698
27114
28130
29146
2......
.........
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
It is pretty simple. For example, if you want to have a 2d array where one index is a player's id, you can do:
JASS:
function Set2D takes integer playerId, integer secondIndex, <type> value returns nothing
    set udg_myVar[playerId + 16 * secondIndex] = value
endfunction
function Get2D takes integer playerId, integer secondIndex returns <type>
    return udg_myVar[playerId + 16 * secondIndex]
endfunction
Here the 16 comes from the fact that player ids range from 0 to 15 (to my recollection).

If you want to understand why this works, you can stare at the results of the [playerId + 16 * secondIndex] function and see how it doesn't generate overlapping indexes i.e. numbers in the third column occur only once for the given values:
playerIdsecondIndexplayerId + 16 * secondIndex
000
0116
0232
0348
0464
0580
0696
07112
08128
09144
0......
101
1117
1233
1349
1465
1581
1697
17113
18129
19145
1......
202
2118
2234
2350
2466
2582
2698
27114
28130
29146
2......
.........

This is a 2d array; the variable still carry 1 index whatever its value is.

Int[j] is not Int2[i + 16*j]
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
looks like a 2d array too me, takes 2 integers. its a pew-newgen 2d array :D
How :confused:? I don't understand. 2d arrays must have 2 indexes, its what I used in other programing language to make a matrix.

In the table you created an equation inside the [] that will result in different number when you change the 2 variables it consists of but it is a single array still.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
How :confused:? I don't understand. 2d arrays must have 2 indexes, its what I used in other programing language to make a matrix.

In the table you created an equation inside the [] that will result in different number when you change the 2 variables it consists of but it is a single array still.

That's how a 2D array works under the surface.
You don't just tell your compiler to put something at [4][3] and it magically stores it somewhere.
A 2D array is a normal array just with some calculations (the above) that tell it where to store/get things.

I am pretty sure, though, they usually do it in blocks and not spread like that (as in i * Max + j).
This makes more sense as it allocates a block for each 'i'.

And in case you don't see how that makes a 2D array, say you want a 4x4 array, the first index is [0][0] which will turn into 0*4+0 = 0.
The second index is [0][1] which will turn into 0*4+1 = 1.
The last index is [3][3] which will turn into 3*4+3 = 15.

And so on and on.

The exact same thing happens for any dimension above one, but it gets more and more messy.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
That's how a 2D array works under the surface.
You don't just tell your compiler to put something at [4][3] and it magically stores it somewhere.
A 2D array is a normal array just with some calculations (the above) that tell it where to store/get things.

I am pretty sure, though, they usually do it in blocks and not spread like that (as in i * Max + j).
This makes more sense as it allocates a block for each 'i'.

And in case you don't see how that makes a 2D array, say you want a 4x4 array, the first index is [0][0] which will turn into 0*4+0 = 0.
The second index is [0][1] which will turn into 0*4+1 = 1.
The last index is [3][3] which will turn into 3*4+3 = 15.

And so on and on.

The exact same thing happens for any dimension above one, but it gets more and more messy.
And this applies to any array in any programing language or in JASS scripting only ?
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Yes.

In some low-level programming languages you get much more power over arrays. For example: in C arrays can be used as pointers. A pointer *points* to a memory adress in your RAM memory. Arrays effectively are pointers to an adress. The calculation is very simple:

Say "array" points to adress 1000. Say it's an array of "integers", this means every integer is 4 bytes large.
array[0] points to 1000 + 0*4 = 1000
array[1] points to 1000 + 1*4 = 1004
array[2] points to 1000 + 2*4 = 1008
etcetera.

If it would be an array of long integers (8 bytes - this type doesn't exist in warcraft), then it would be very similar:
array[0] points to 1000 + 0*8 = 1000
array[1] points to 1000 + 1*8 = 1008

A 2D array can be seen as an "array of arrays"". So if you have an array of long integers (8 bytes) of maximum size 4x4, you get:
array[0,0] points to 1000 + (0*4*8) + (0*8) = 1000
array[0,1] points to 1000 + (0*4*8) + (1*8) = 1008
array[0,2] points to 1000 + (0*4*8) + (2*8) = 1016
array[0,3] points to 1000 + (0*4*8) + (3*8) = 1024
array[1,0] points to 1000 + (1*4*8) + (0*8) = 1032
As you can see, the 2D array is just like the 1D array a pointer to a memory adress, where the index specifies an offset from that adress. In the case of multiple indices, each index specifies their own offset from the starting adress.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Yes.

In some low-level programming languages you get much more power over arrays. For example: in C arrays can be used as pointers. A pointer *points* to a memory adress in your RAM memory. Arrays effectively are pointers to an adress. The calculation is very simple:

Say "array" points to adress 1000. Say it's an array of "integers", this means every integer is 4 bytes large.
array[0] points to 1000 + 0*4 = 1000
array[1] points to 1000 + 1*4 = 1004
array[2] points to 1000 + 2*4 = 1008
etcetera.

If it would be an array of long integers (8 bytes - this type doesn't exist in warcraft), then it would be very similar:
array[0] points to 1000 + 0*8 = 1000
array[1] points to 1000 + 1*8 = 1008

A 2D array can be seen as an "array of arrays"". So if you have an array of long integers (8 bytes) of maximum size 4x4, you get:
array[0,0] points to 1000 + (0*4*8) + (0*8) = 1000
array[0,1] points to 1000 + (0*4*8) + (1*8) = 1008
array[0,2] points to 1000 + (0*4*8) + (2*8) = 1016
array[0,3] points to 1000 + (0*4*8) + (3*8) = 1024
array[1,0] points to 1000 + (1*4*8) + (0*8) = 1032
As you can see, the 2D array is just like the 1D array a pointer to a memory adress, where the index specifies an offset from that adress. In the case of multiple indices, each index specifies their own offset from the starting adress.
I can't say that I comletely understand but do you know of any site that can illustrate this more precisly.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
array[0,0] points to 1000 + (0*4*8) + (0*8) = 1000
array[0,1] points to 1000 + (0*4*8) + (1*8) = 1008
array[0,2] points to 1000 + (0*4*8) + (2*8) = 1016
array[0,3] points to 1000 + (0*4*8) + (3*8) = 1024
array[1,0] points to 1000 + (1*4*8) + (0*8) = 1032

I understand now how they point to a specific address but the number 4,8 I don't know why we use those specific numbers ?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
You use the size of the data type you are storing in the array because Eleandor is talking about the actual bytes that the array is stored in.

A normal integer is 4 bytes long, so it makes sense that every index takes 4 bytes.
A short integer is 2 bytes long, so it makes sense that every index takes 2 bytes.

Same goes for any size.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
You use the size of the data type you are storing in the array because Eleandor is talking about the actual bytes that the array is stored in.

A normal integer is 4 bytes long, so it makes sense that every index takes 4 bytes.
A short integer is 2 bytes long, so it makes sense that every index takes 2 bytes.

Same goes for any size.
Normal integers like 1,2,3,4 .... they are as binary stored in those bytes ?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Say you have a character variable (a character is a...well, a character, for example 'a', '1', etc).
A character takes 1 byte, this means that it looks like this when it is equal to zero:
(b = binary, 0x = hex, d = decimel)

00000000b
0x00
0d

Now say you make it equal to 4, it will look like this

00000100b
0x04
4d

It always takes exactly one byte so it can be between -127 and 127 (forget unsigned integers for now)

01111111b
0x7F
127d

Now say you have an array of characters {0,1,2,3,4,5,6} at the address 1000, it would look like this (hex for short text)

Code:
Address: 1000 1001 1002 1003 1004 1005 1006
Offset:  00   01   02   03   04   05   06
Value:   00   01   02   03   04   05   06

The same thing applies for integers or any data type, just they are bigger.
A Warcraft integer is 4 bytes, which is

00000000000000000000000000000000b
0x00000000

Meaning that if you have the same array but with integers, it will look like this
Code:
Address: 1000 1004 1008 1012 1016 1020 1024
Offset:  00   04   08   0C   10   14   18
Value:   00   01   02   03   04   05   06
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
128 will be

10000000b
0x 80
128d

Isn't that supposed to count as 1 byte also ?

You can only put 128-255 if the variable is unsigned (it has no minus).
This is because if it is signed, the last bit is there to determine the sign, 1 for minus and 0 for plus (although there are also those who do 0 for minus and 1 for plus).

Signed:
10000000b = -0

Unsigned:
10000000b = 128
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,223
You can get limateless 2D arrays. Whereby you can pass any number, even negatives as indexes as get as specific storage location. However this is a process of hashing and is a lot, lot and lot slower than normal 2D arrays as they require multiple comparisons and loops to find the right place in the array (as well as other operations). Welcome to HashTables which take 2 integers and return a unique value (storage location).

Thus for speed you are forced to go with fixed size arrays in JASS. In other languages however you can use dynamic sized 2D arrays which are basically arrays of arrays. Speed wise I am not certain, but they may be faster or slower depending on caching and opperations like array bond checks. They however are more memory intensive as they have pointers to other parts in the memory which hold the data rather than directly storing the data.

Basically you difine an array of a certain size of arrays. You then can create an array of values in that array slot of any size. This works because the first array refers to another arrays and so does not store the data in a continous and mathimatically logical way. As you have probably figured, this means that the arrays can end up anywhere in memory and so the additional memory reading can cause slowdowns if not cached. This however is a prety decent way to do 2D arrays as it still keeps direct efficency and allows some degree of size varience.

For example using this method 0 might refer to an array of size 16 of value.
1 on the other hand might refer to an array of size 1024.
2 may refer to an array of size 10.
Using this system 0:11, 1:959 and 2:5 are all valid storage locations. However 0:16 exceeds the array size.

This can be used to store data more dynamically than other methods. It saves on storage space if there are a couple of indexes which need a large number of second index space as you can difine only the space needed and do not have to have to allocate space that will never be used. It also allows the extension of the array easier. If you want to expand index 0 from size 16 to size 32, using the other mathimatical method of 2D arrays it would require the rebuilding of the whole array which can be many 1000 entries, each needing to be moved to new locations which takes time while with the nested arrays you simply rebuild the second level array which requires the duplication of only 16 entries.

As you can see this is also a completly viable way and would be great for some spells in WC3. Sadly blizzard did not allow you to difine arrays on the fly in JASS like JAVA, C++ and other languages do so you are stuck with mathimatical 2D arrays of fixed indexes or HashTable emulated 2D arrays.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,223
Not entirly true. Hashes are designed to store stuff with 2 indexes thus it to the triggerer appears as a 2 level array system lol.

Yes though, for speed based 2D work it is totally wrong to use hashes, as they are designed for coping with a huge range of numbers, not lots of numbers.
If only Blizzard allowed for lower level array manipulation, then this would not be a problem.

You could then do something like "set array[1][2] = 1" easilly as array[1] has the value of another array which you can then directly pass another index into.
 
Status
Not open for further replies.
Top