for the life of me i cant figure out what array this trigger is trying to access and this is for a evolves map
Set Spawns for players
Events
Local Variables
Counter = 1 <Integer>
Counter 2 = 0 <Integer>
Counter 3 = 0 <Integer>
Counter 4 = 0 <Integer>
Conditions
Actions
General - For each integer Counter from 1 to PlayerCount with increment 1, do (Actions)
Actions
General - For each integer Counter 2 from 1 to Levels with increment 1, do (Actions)
Actions
Variable - Set UnitOrder[Counter 3][0] = UnitOrder[Counter 3][Counter 4]
Variable - Set Counter 3 = (Counter 3 + 1)
Variable - Set Counter 4 = (Counter 4 + 1)
You show your local variable, but what is the limit of your global set unit order? It seems that your global must be heavy because of the number of loops you have in your script. As it is the only variable with arrays, it is sure that the problem is here.
If you want some hints, make only 1 local with 4 arrays (much better) and use while loop instead of for each action. For each integer is an action that cannot be nested (1 for each inside 1 for each) if I remember well.
You probably mean to reset "Counter 3" to 0 every time you increment "Counter 4". What is happening is that for each player you are incrementing Counter 3 by "Levels" amount. The result is you are probably overflowing your 2D array "UnitOrder" unless the first dimension is of size Levels*PlayerCount. I doubt the current behaviour is what you are intending to happen.
For more help you need to post the array definitions so we can see their sizes. You also need to post more information on what values are contained by the variables in the system such as "PlayerCount" and "Levels".
Quote:
If you want some hints, make only 1 local with 4 arrays (much better) and use while loop instead of for each action. For each integer is an action that cannot be nested (1 for each inside 1 for each) if I remember well.
It can be nested as much as you want. It is the for loop without a local variable declaration with a special function call to get the value that cannot be nested (eg For picked unit in unit group).
Try resetting counter 3 to 0 every time you increment counter 4. Reasons why it currently does not work were given in my last post, basically counter 3 is growing a lot bigger than 15 (it grows up to 120).
For your question, I made an example of what you wanted with a nice shaped script. As you can see, I added and If condition to be sure to not go through the limit of the array. The 'constant unit order' is a variable who have the value of the first array of your global UnitOrder (which is 15 in your example).
You should avoid using arrays to represent a structure where each member serves a different purpose. I am not too confident about the Galaxy compiler's ability to optimize such arrays into constant address accesses (it might keep them as array accesses using a constant index). The difference here is that constant address accesses such as for non-array globals and locals (well locals are relative to stack frame but still the offset is constant) would execute faster than an array access where first the array index has to be loaded and then the memory accessed.
Your array is also of size 3 yet you use 4 storage locations. Galaxy may allow that however it is probably bad practice to do.
I am also not entirely sure that is what he is after... Why is he setting index 0 at some position to some value? It would be easier if he could describe what he is trying to do. In any case I not sure if 4 counters are necessary.
You seem to have more knowledge than me, but I always though that 1 variable with 4 arrays takes less place than 4 single variable, like 4 drawers with 1 place takes much more place in a bedroom than 1 drawer with 4 places. I always use the 0 array in variable, this is why i have 3 arrays in my function.
You seem to have more knowledge than me, but I always though that 1 variable with 4 arrays takes less place than 4 single variable, like 4 drawers with 1 place takes much more place in a bedroom than 1 drawer with 4 places.
Think of variables as places in a filing cabinet (as in reality they kind of are, memory consists of equal sized units which are addressable) rather than as pieces of furniture or boxes. When you allocate an array of size 3 you are requesting 3 sequential storage locations in the filing cabinet. If you allocate 3 separate variables (no array) then they each request 1 storage location somewhere in the filing cabinet. In both cases the same amount of the filing cabinet is used (3 spaces) with the only difference being the array guarantees those spaces are sequential (and so you can use an index to access them) where as the separate variables could be anywhere (no relationship with each other, although in reality they usually are next to each other for convenience). The result is that 3 variables will use the same space as an array size 3.
The extra names of 3 variables only affects the source code size (map script size) as the compiler translates those names into addresses. If the compiler is good both cases should even produce the same code, however if the compiler is poor the array might perform worse due to it needing to perform an array lookup rather than a static lookup.
Quote:
always use the 0 array in variable, this is why i have 3 arrays in my function.
You only have 1 local array in that function which is of size 3. However you are using 4 indexes of that array (index 0, 1, 2 and 3). This is in theory not legal and in most normal languages will cause a buffer overflow error (C/C++) or array index out of bounds exception (Java). It only works in Galaxy because they added a hacky work around which implicitly adds an extra 1 to the array size (possibly only if required). This is because people had a lot of difficulty grasping the idea of how computer arrays work.
An array of size 3 allocates 3 sequential spaces of the specified type. The array is then represented as an address to first storage space (usually lowest address). The index is then an address offset added to the base address to get the desired element. This means that index 0 is the first element and index 2 (size - 1) is the last element in the array (3 indexes are valid for a size 3 array which are 0, 1 and 2). Trying to access index 3 will compute an address outside the bounds of allocated space, possibly space used by another variable. Galaxy and languages like Java will catch such overflow errors which is why you get "array index out of bound" errors. C and C++ on the other hand will not automatically do so which can result in potential program hacks and crashes.
Array lookups are often implemented as special instructions. For example on the x86 architecture there exist instructions which take multiple address sources (constant, constant offset, one offset register, two offset registers etc) which often have their address computation highly pipe-lined and optimized at the hardware level. A good compiler would see you are using a constant index on a local array and inline it to a stack memory read with an offset (which would also have the offset of the base array added to it). A bad compiler however might load your constant literal into a register and then perform a stack lookup using the register as the offset. The difference here is what could be 1 instruction becomes 2. Things could be even worse if it first has to load the base address of the array into one register, that would make 2 extra instructions per lookup.
Some simpler instructions sets might perform even worse. If they lack such composite address read operations they might have to manually compute the address. This means that an array access becomes and extra addition and a few other instructions over a single variable lookup. Again if the compiler is good it should make no difference however if it is not you can get a performance impact.
From a code maintainability point of view I would not recommend what you are doing. If you named 3/4 separate variables with their purposes then it is easier to understand what the code is doing than if you use an array like you are. Where as the other has human readable names related to the purpose, your array has numbers which can easily be confused resulting in all kinds of potential errors. If you must use that way you should declare named constants for each index which are used to make sure the purpose of each index is clear.
It also is hard to maintain since if you want to remove a variable you would need to change all the constant integers which is a highly error prone process (did you really change them all? You sure you did not miss 1 of possibly dozens scattered around your script?). Using constants mitigates this difficulty to some degree as you now have a single place defining all locations however you still need to manually manage the index allocations. If you use separate variables in this case all the above becomes trivial as you can add and remove them and the compiler will manage the storage and they are human readable so chances of getting the wrong index is near impossible.
for the life of me i cant figure out what array this trigger is trying to access and this is for a evolves map
Set Spawns for players
Events
Local Variables
Counter = 1 <Integer>
Counter 2 = 0 <Integer>
Counter 3 = 0 <Integer>
Counter 4 = 0 <Integer>
Conditions
Actions
General - For each integer Counter from 1 to PlayerCount with increment 1, do (Actions)
Actions
General - For each integer Counter 2 from 1 to Levels with increment 1, do (Actions)
Actions
Variable - Set UnitOrder[Counter 3][0] = UnitOrder[Counter 3][Counter 4]
Variable - Set Counter 3 = (Counter 3 + 1)
Variable - Set Counter 4 = (Counter 4 + 1)
You show your local variable, but what is the limit of your global set unit order? It seems that your global must be heavy because of the number of loops you have in your script. As it is the only variable with arrays, it is sure that the problem is here.
If you want some hints, make only 1 local with 4 arrays (much better) and use while loop instead of for each action. For each integer is an action that cannot be nested (1 for each inside 1 for each) if I remember well.
You probably mean to reset "Counter 3" to 0 every time you increment "Counter 4". What is happening is that for each player you are incrementing Counter 3 by "Levels" amount. The result is you are probably overflowing your 2D array "UnitOrder" unless the first dimension is of size Levels*PlayerCount. I doubt the current behaviour is what you are intending to happen.
For more help you need to post the array definitions so we can see their sizes. You also need to post more information on what values are contained by the variables in the system such as "PlayerCount" and "Levels".
It can be nested as much as you want. It is the for loop without a local variable declaration with a special function call to get the value that cannot be nested (eg For picked unit in unit group).
the reason i use the if statement is because i haven't learned how to use whiles yet so i just used what i knew
UnitOrder = No Game Link <Game Link - Unit[15][8]> ( 15 is the evolve level and 8 is players)
Levels = 0 <Integer>
what would i have to do to that trigger to get it to spawn right? because right now it spawns right for the first player and no one else.
or how would i do it with a while loop to accomplish the same result?
Try resetting counter 3 to 0 every time you increment counter 4. Reasons why it currently does not work were given in my last post, basically counter 3 is growing a lot bigger than 15 (it grows up to 120).
@ImperialGood: Go
Thanks for the reply. I was always scared about for each actions.
@Mitch8778: Go
For your question, I made an example of what you wanted with a nice shaped script. As you can see, I added and If condition to be sure to not go through the limit of the array. The 'constant unit order' is a variable who have the value of the first array of your global UnitOrder (which is 15 in your example).
You should avoid using arrays to represent a structure where each member serves a different purpose. I am not too confident about the Galaxy compiler's ability to optimize such arrays into constant address accesses (it might keep them as array accesses using a constant index). The difference here is that constant address accesses such as for non-array globals and locals (well locals are relative to stack frame but still the offset is constant) would execute faster than an array access where first the array index has to be loaded and then the memory accessed.
Your array is also of size 3 yet you use 4 storage locations. Galaxy may allow that however it is probably bad practice to do.
I am also not entirely sure that is what he is after... Why is he setting index 0 at some position to some value? It would be easier if he could describe what he is trying to do. In any case I not sure if 4 counters are necessary.
@ImperialGood: Go
You seem to have more knowledge than me, but I always though that 1 variable with 4 arrays takes less place than 4 single variable, like 4 drawers with 1 place takes much more place in a bedroom than 1 drawer with 4 places. I always use the 0 array in variable, this is why i have 3 arrays in my function.
Think of variables as places in a filing cabinet (as in reality they kind of are, memory consists of equal sized units which are addressable) rather than as pieces of furniture or boxes. When you allocate an array of size 3 you are requesting 3 sequential storage locations in the filing cabinet. If you allocate 3 separate variables (no array) then they each request 1 storage location somewhere in the filing cabinet. In both cases the same amount of the filing cabinet is used (3 spaces) with the only difference being the array guarantees those spaces are sequential (and so you can use an index to access them) where as the separate variables could be anywhere (no relationship with each other, although in reality they usually are next to each other for convenience). The result is that 3 variables will use the same space as an array size 3.
The extra names of 3 variables only affects the source code size (map script size) as the compiler translates those names into addresses. If the compiler is good both cases should even produce the same code, however if the compiler is poor the array might perform worse due to it needing to perform an array lookup rather than a static lookup.
You only have 1 local array in that function which is of size 3. However you are using 4 indexes of that array (index 0, 1, 2 and 3). This is in theory not legal and in most normal languages will cause a buffer overflow error (C/C
++
) or array index out of bounds exception (Java). It only works in Galaxy because they added a hacky work around which implicitly adds an extra 1 to the array size (possibly only if required). This is because people had a lot of difficulty grasping the idea of how computer arrays work.An array of size 3 allocates 3 sequential spaces of the specified type. The array is then represented as an address to first storage space (usually lowest address). The index is then an address offset added to the base address to get the desired element. This means that index 0 is the first element and index 2 (size - 1) is the last element in the array (3 indexes are valid for a size 3 array which are 0, 1 and 2). Trying to access index 3 will compute an address outside the bounds of allocated space, possibly space used by another variable. Galaxy and languages like Java will catch such overflow errors which is why you get "array index out of bound" errors. C and C
++
on the other hand will not automatically do so which can result in potential program hacks and crashes.Array lookups are often implemented as special instructions. For example on the x86 architecture there exist instructions which take multiple address sources (constant, constant offset, one offset register, two offset registers etc) which often have their address computation highly pipe-lined and optimized at the hardware level. A good compiler would see you are using a constant index on a local array and inline it to a stack memory read with an offset (which would also have the offset of the base array added to it). A bad compiler however might load your constant literal into a register and then perform a stack lookup using the register as the offset. The difference here is what could be 1 instruction becomes 2. Things could be even worse if it first has to load the base address of the array into one register, that would make 2 extra instructions per lookup.
Some simpler instructions sets might perform even worse. If they lack such composite address read operations they might have to manually compute the address. This means that an array access becomes and extra addition and a few other instructions over a single variable lookup. Again if the compiler is good it should make no difference however if it is not you can get a performance impact.
From a code maintainability point of view I would not recommend what you are doing. If you named 3/4 separate variables with their purposes then it is easier to understand what the code is doing than if you use an array like you are. Where as the other has human readable names related to the purpose, your array has numbers which can easily be confused resulting in all kinds of potential errors. If you must use that way you should declare named constants for each index which are used to make sure the purpose of each index is clear.
It also is hard to maintain since if you want to remove a variable you would need to change all the constant integers which is a highly error prone process (did you really change them all? You sure you did not miss 1 of possibly dozens scattered around your script?). Using constants mitigates this difficulty to some degree as you now have a single place defining all locations however you still need to manually manage the index allocations. If you use separate variables in this case all the above becomes trivial as you can add and remove them and the compiler will manage the storage and they are human readable so chances of getting the wrong index is near impossible.