Page 1 of 1

Array of Array's

Posted: Sun, 17. Dec 06, 02:00
by Draslin
Um, the MSCI is a little sparse on array details. Is it possible to make an array of arrays? Is there antying specific I need to be aware while using one?

Posted: Sun, 17. Dec 06, 02:10
by moggy2
array of arrays is fine.

Posted: Sun, 17. Dec 06, 02:30

there is a way to use 2 dimesional arrays

Code: Select all

001   $tmp.array =  array alloc: size=0
002   append ware to array $tmp.array
003   append 100 to array $tmp.array
004   $wanted.ware =  array alloc: size=0
005   append $tmp.array to array $wanted.ware
007 $tmp.a = $wanted.ware[0][0]
008 $tmp.b = $wanted.ware[0][1]
Line 7 returns ware
Line 8 returns 100

you could also use the other way
for example
$wanted.ware[0][0]=another ware
but the arrays have to be defined bevor you could use them

Posted: Sun, 17. Dec 06, 05:44
by euclid
Another way to do it is to allocate an array of size 0 and append arrays to it. What you get has the structure:


so the elements of the array are arrays.

Cheers Euclid

Posted: Sun, 17. Dec 06, 11:29
by Cycrow
an array can hold any objects you wish, which includes other arrays.

in one of my scripts, i have an array of numbers, but one of them is another array.

Posted: Sun, 17. Dec 06, 11:50
by Red Spot
thing I often do is the following;

make an array of specific sized arrays, like an array containing nothing but other arrays of the same size, makes grouping information very easy and generally easy to find back.

example would be MDS (MD Suppliers)
it has suppliers that are stored in a general plugin array wich has an array that contains the plugin info and iirc 2 arrays
the 1st array contains arrays with the info about the suppliers their hombase and homesector, the second has a list of fighters equipped with MDs
basicly meaning I have all info from the plugin contained in 1 main plugin ... (meaning I only need to create 1 "tag" (global/local var))


Posted: Sun, 4. Feb 07, 03:43
by Gazz
I was toying with arrays and it's somewhat tricky to understand in X3. There are no "clean" two dimensional arrays.
(I'm not a number! I AM A FREE ARRAY!)

Code: Select all

001   $MainArr =  array alloc: size=9
002   $SubArr =  array alloc: size=5
004   $MainArr[1] = $SubArr
005   $MainArr[7] = $SubArr
007   $MainArr[1][2] = 17
008   $MainArr[7][2] = 77
010   $Test1 = $MainArr[1][2]
011   $Test2 = $MainArr[1][2]
012   $test = 'result = ' + $Test1 + '    ' + $Test2
013   send incoming message $test to player: display it=[TRUE]
Returns: Result = 77 77

Code: Select all

001   $MainArr =  array alloc: size=9
003   $SubArr =  array alloc: size=5
004   $MainArr[1] = $SubArr
005   $SubArr =  array alloc: size=5
006   $MainArr[7] = $SubArr
008   $MainArr[1][2] = 17
009   $MainArr[7][2] = 77
010   $Test1 = $MainArr[1][2]
011   $Test2 = $MainArr[7][2]
013   $test = 'result = ' + $Test1 + '     ' + $Test2
014   send incoming message $test to player: display it=[TRUE]
Returns: Result = 17 77

Arrays like the subarray in the first example are like "named" entities - or objects.
Allocating a NEW array like in 2nd example line 005 forgot the old pointer to the still existing (and stored away) $Subarr and created a different subarray with it's pointer put into $Subarr again.
A small but decisive difference.

A construct like that can be passed as a data type argument or as a global variable since it is technically only a one dimensional array containing single elements of "stuff".
That the stuff is a collection of unique and distinct other arrays is an entirely different matter.

ACCESSING this construct with $Test2 = $MainArr[7][2] is an interesting shortcut since it accesses 2 entirely different objects.

This test result was so pretty I decided to post it. =)

Just like everyone else I can only guess at the proper cleanup procedure.
Assuming there is no garbage collection, one would have to iterate through all subarrays and resize them to zero.
Then resize the main array to zero.

Since there is no remove array command I can only guess that some minor residue from the header will remain.

Code: Select all

$Subarr = Null 
is probably wishful thinking since that only assigns Null to the variable that stored the pointer instead of doing anything to the array itself.

Given that, it might be wise to not casually clean out subarrays to create new ones at leisure but reuse the existing ones.
Depending on the script there could be a lot of these subarrays being created and discarded. Eventually they would bloat the savegame to epic proportions.

What I wanted to use the array for won't cause trouble like that becasue creation of a subarray would only be triggered rarely and by direct player action but if it was an automatic function I would probably test it for uncontrolled savegame growth.

Posted: Sun, 4. Feb 07, 20:56
by Gazz
Another thing I did wrong at first:

Once you SET a global array, you never need to set it again.
This is not a database entry where you have to update, unlock or whatever.

A script only needs to GET the pointer to the global array once.
Then it can freely edit any values and the changes take effect immediately.

2 scripts accessing it "simultaneously" would access the exact same object so a basic lock/unlock procedure for "records" is required.

Posted: Tue, 20. Mar 07, 15:14
by Draslin
I'm still trying to work out how array's work. Based on what I've seen already on this topic. I should think this would work. And give me the expected output of "Array Dump = A B C D || A B C D || A B C D || A B C D ||"

Instead I get "Array Dump = nullnullnullnull |||||||||" I'm missing something.

The If index, is just part of a switch. I pass a variable to the script to determine what chunk of the code I want to execute for testing.

Code: Select all

 if $Index == 8
050    $ArrayColumn =  array alloc: size=4
051    $ArrayRows =  array alloc: size=4
052    $ArrayColumn[0] = $ArrayRows
053    $ArrayRows =  array alloc: size=4
054    $ArrayColumn[1] = $ArrayRows
055    $ArrayRows =  array alloc: size=4
056    $ArrayColumn[2] = $ArrayRows
057    $ArrayRows =  array alloc: size=4
058    $ArrayColumn[3] = $ArrayRows
060    $Loop = 0
062    while $Loop < 4
063     $ArrayColumn[$Loop][0] = 'A '
064     $ArrayColumn[$Loop][1] = 'B '
065     $ArrayColumn[$Loop][2] = 'C '
066     $ArrayColumn[$Loop][3] = 'D '
067     inc $Loop = 
068    end
070    $Loop = 0
071    $Loop2 = 0
072    $Log = 'Array Dump = '
073    while $Loop < 4
074     $ArrayBuffer = $ArrayColumn[$Loop][$Loop2]
075     while $Loop2 < 4
076      $ArrayBuffer = $ArrayColumn[$Loop][$Loop2]
077      $Log = $Log + $ArrayBuffer
078      inc $Loop2 = 
079     end
080     $Log = $Log + '||'
081     inc $Loop = 
082    end
083    send incoming message $Log to player: display it=[TRUE]
084   end

Posted: Tue, 20. Mar 07, 15:54
by Draslin
Until such time as someone explains to me what I'm doing wrong. (everything!? :-) ) I'm going to move forward with a workaround. I'll simply create a one dimensional array with what would have been my sub array's concatenated end to end. Each entry was going to be a uniform length so I should be able to get away with multiplying my index by the intended length of the sub array.

I'm optimistic.

.... so I'll be back here in about five minutes.

Posted: Tue, 20. Mar 07, 16:17
by Draslin
Oh one last thing, the output I got from the above 2d array was not "nullnullnullnull |||||||||" but actually I got "A B C D |||||||||"

Posted: Tue, 20. Mar 07, 16:34
by Cycrow
there is an easier way to output the contents of an array.

if u just send the whole array to the logbook, it will displays its whole contents, upto a certain amount.


Code: Select all

write to player logbook $ArrayColumn
should get something like

Code: Select all

ARRAY ( ARRAY ( 'A', 'B', 'C', 'D' ), ARRAY ( 'A', 'B', 'C', 'D' ), ARRAY ( 'A', 'B', 'C', 'D' ), ARRAY ( 'A', 'B', 'C', 'D' ) )
but anyways, the mistake u are making is in the displaying of the array. Your not resetting the loop count for each inner loop.

Code: Select all

070    $Loop = 0 
071    $Log = 'Array Dump = ' 
072    while $Loop < 4 
073     $loop2 = 0
074     while $Loop2 < 4 
076      $ArrayBuffer = $ArrayColumn[$Loop][$Loop2] 
077      $Log = $Log + $ArrayBuffer 
078      inc $Loop2 = 
079     end 
080     $Log = $Log + '||' 
081     inc $Loop = 
082    end

Posted: Tue, 20. Mar 07, 16:39
by Draslin
Ah, thank you much.

There is always a little mistake like that in my code, that I can't ever see until after my brain has imploded trying to figure it out.