N-dimensional arrays

GameMaker unfortunately does not natively support arrays with more than two dimensions, contrary to most other programming languages. This tutorial will show you how to create three-dimensional arrays, and ultimately, n-dimensional.

We will be doing this using a method that is also used for RGB color encoding. The ‘R’, ‘G’ and ‘B’ values are the red, green and blue components of a color, with values ranging 0 to 255, which is then ‘compiled’ into a single number using this formula:

C = R + G * (R_max + 1) + B * (G_max + 1) * (R_max + 1);

R_max and G_max are the maximal values of R and G, which in this case is 255. We multiply by ‘max+1′ to make sure that two different colors have a unique ‘C’. If we just used R_max, the colors (255, 0, 0) and (0, 1, 0) would both result in a C value of 255, after which it would be impossible to say which one of the two this C was originally.

Either way, GameMaker’s built-in function make_color_rgb(red, green, blue) will probably look a lot like this:

return (argument0 + argument1 * 256 + argument2 * 65536);

(Note that \(256^2=65536\))

Of course we can also reverse this process: R = C mod 256;, G = (C div 256) mod 256; and B = C div 65536. For those of you unfamiliar with GameMaker’s operators: mod is normal modulo, and div is integer division.

We can also use this technique for arrays. We take indices A, B and C, turn them into a number using the formula A + B*Amax + C*Amax*Bmax, and use that as an index for a one-dimensional array. However, there is one problem here: GameMaker has a limit for array indices, they cannot go exceed 32000, so the maximal value of Amax*Bmax*Cmax is 32000, meaning that the maximal value for A, B and C equals \(32000^{1/3}\), which equals the disappointing value of 31.75.

So if you are fine with an array of the size 31 * 31 * 31, great. But I think we can do better: we have two-dimensional arrays after all. The most obvious thing to do would be to store the value of A in the first index, and B and C in the second. The second index would then be calculated by B + C * Bmax. The maximal values of B and C are then equal to \(32000^{1/2}\), which results in a higher, but still disappointing value of 178.89. Our array would then be 32000 * 178 * 178, which seems a little bit unfair.

So, we’ll have to find a way to spread A, B and C out over the two indices, in such a way that all indices have the same maximal value.

As I mentioned before, RGB encoding can also be used backwards, split one number up into three. And this also works for one-into-two:

index1 = N div Max;
index2 = N mod Max;

In this example, Max is the maximal value one of the two final indices can be, which is naturally 32000 in our case. Consequently, the maximal value of an individual index in our three-dimensional array would be \((32000 * 32000)^{1/3}\) which can be rounded down to 1007.

Calculating your indices would go like this:

var index, index1, index2;
A = 12;
B = 34;
C = 56;
A_max = 20;
B_max = 40;
C_max = 60;

index = A + B*A_max + C*B_max*A_max;
index1 = index mod 32000;
index2 = index div 32000;
array[index1,index2] = 0;

You can continue doing this for four-dimensional arrays:

var index, index1, index2;
A = 12;
B = 34;
C = 56;
D = 12; 
A_max = 20;
B_max = 40;
C_max = 60;
D_max = 20; 

index = A + B*A_max + C*B_max*A_max + D*C_max*B_max*A_max;
index1 = index mod 32000;
index2 = index div 32000;
array[index1,index2] = 0;

All that is required is that you keep index (the product of all maximal values) under 32000 * 32000. You can even calculate the maximal value of each of your starting indices:

(max_final_index_1 * max_final_index_2) ^ (1 / starting_indices)
= (32000 * 32000) ^ (1/n)
= 32000^(2/n)

Notice that when you set n to 1, you get a number that is larger than 32000. This means you can actually make a one-dimensional array that exceeds the built-in limit of 32000, and instead has a ceiling of 32000^2 = 1,024,000,000!

Leave a Reply

Name and website fields are completely optional.