[SOLVED]Parsing from an 2D array into a script

C

Cooltrain

Guest
Hey All,

So I've been doing some work on a command system for my game (and future games). Everything is handled inside a command object which pauses the game when opened, it uses a standard pause system of deactivating all instances, taking a screenshot of the view and drawing it to a surface. This means that any commands that apply to another instance won't take effect because that instance won't exists while paused. I've had the idea to store the commands that are run into a 2D array and once the game is unpaused, to loop through the list and parse each one to my command script (which contains all of the possible commands and there actions). I just need some help with doing this.

Commands use the following layout: command,value
Once a command is entered the command section is stored into splits[0] and the value in splits[1]. I then

Obj_command Create
Code:
globalvar commandList;
commandList=0;
pos=0;
Obj_command Step
Code:
pos = array_height_2d( commandList );
commandList[pos,0] = splits[0]//Command
commandList[pos,1] = splits[1]//Value

for (i = 0; i < pos; i += 1){
  if (pause == false){
  scr_commandList(commandList[i,0], commandList[i,1]) //run command
  }
  }
I need to run through all of the avaliable commands once the game is resumed and then remove or maybe reset a value in the commandList array so its not read again ?

Thanks in advance.
 
R

rui.rosario

Guest
I need to run through all of the avaliable commands once the game is resumed and then remove or maybe reset a value in the commandList array so its not read again ?
I'm assuming your question is how to remove / reset the value? The simplest way would be to use a ds_list which allows removal of values based on index or even clearing of the complete list.

If you want to keep arrays, then either create a new one to replace the one with the already executed commands, or fill the array with invalid values (undefined or noone for example) and instead of getting the height as the position you'd have to search for the next position with undefined/noone or the end of the array (if no more undefined/noone values exist).
 
Last edited by a moderator:
C

Cooltrain

Guest
I'm assuming your question is how to remove / reset the value? The simplest way would be to use a ds_list which allows removal of values based on index or event clearing of the complete list.
I've never used ds_lists or maps before so i'm not too sure how they work. After reading about them it seems like i should use a ds_map to hold both values. I need to:
  • Add the command to the ds_map when its entered.
  • When the game is unpaused loop through the ds_map.
  • Parse the values one by one from the ds_map into the script.
  • Remove each entry in the ds_map after its been run.
As I've not used these before any advice would be a great help. So far I think this should be adding each entry ?

Create Event Command object

Code:
commandList=ds_map_create();
Step Event Command object

This is run every time a new command is entered, both splits are overridden with new data.

Code:
ds_map_add(commandList,splits[0],splits[1]);
splits0 is the command, splits1 is the value. Splits0 is only ever a string, whereas splits1 can be both real or string.

How would i go about looping through a map/list in such a way and running each one to a script with two arguments ?

Thanks for the help so far.
 
R

rui.rosario

Guest
How would i go about looping through a map/list in such a way and running each one to a script with two arguments ?
Take a look at the functions: ds_map_find_first, ds_map_find_next (the first one has an example of how to iterate)

For lists, simply get the size and iterate each index from 0 to size - 1.

So far I think this should be adding each entry ?
Yes, it is adding, but beware of something:

If you have two equal commands one after the other, then the second one will override the first, so my advice would be to use a list
 

Surgeon_

Symbian Curator
Maps are not ordered so the only way to loop through them is to use the following commands:
Code:
ds_map_find_first();
ds_map_find_next();
ds_map_find_last();
But it's also slower and more inconvenient to program than looping through other data structures or arrays. And if you need your commands to be read in the order in which they were inputted, you're out of luck.

So I recommend going back to your original idea with 2D arrays and just delete the array after you've looped through it. You can delete an array by assigning a numerical value to it, like this:
Code:
commandList=0;
And if you want to go the route of data structures, use grids.

EDIT: And in the case of arrays you'll probably want to use is_array() to prevent trying to loop through a non-indexed variable.
 
R

rui.rosario

Guest
And if you want to go the route of data structures, use grids.
Grids have to be resized if you reach the grid's maximum, so lists with index x being the command and x + 1 the argument would probable be the best
 

Surgeon_

Symbian Curator
Grids have to be resized if you reach the grid's maximum, so lists with index x being the command and x + 1 the argument would probable be the best
That's a good idea, but I personally think his original idea with 2D arrays is still better than other solutions. But it's not like you'll see any lag from any of the approaches since those are all trivial operations by today's standards, so it's mostly up to the programmer's preference.
 
R

rui.rosario

Guest
That's a good idea, but I personally think his original idea with 2D arrays is still better than other solutions. But it's not like you'll see any lag from any of the approaches since those are all trivial operations by today's standards, so it's mostly up to the programmer's preference.
Yes, but arrays are more difficult to handle if you just want to delete several sparse indexes
 

Surgeon_

Symbian Curator
Yes, but arrays are more difficult to handle if you just want to delete several sparse indexes
The idea here is obviously to loop through the whole array, process everything, and then delete everything. And even if it wasn't the case, it'd be better to find a way to flag a row/column (or a ds_list entry) as "empty" (by setting its value to noone or undefined for example) and just skip it in the loop - better than resizing the structure all the time, granted you do a lot of reading and writing.
 
R

rui.rosario

Guest
The idea here is obviously to loop through the whole array, process everything, and then delete everything. And even if it wasn't the case, it'd be better to find a way to flag a row/column (or a ds_list entry) as "empty" (by setting its value to noone or undefined for example) and just skip it in the loop - better than resizing the structure all the time, granted you do a lot of reading and writing.
From
I need to run through all of the avaliable commands once the game is resumed and then remove or maybe reset a value in the commandList array so its not read again ?
I assume there may be the case where it is just one value that needs to be deleted.

But I also agree with the flag as empty, as stated (but maybe not that clearly) in:
If you want to keep arrays, then either create a new one to replace the one with the already executed commands, or fill the array with invalid values (undefined or noone for example) and instead of getting the height as the position you'd have to search for the next position with undefined/noone or the end of the array (if no more undefined/noone values exist).
 

Surgeon_

Symbian Curator
From the code above the part you quoted, I assume he wants the all or nothing approach, seeing as he is looping from 0 to height-1. Anyway, we've stated many options here, so let's wait and see which route he's taken.
In reality I just need to get off the forums and go study math...
 
C

Cooltrain

Guest
The idea here is obviously to loop through the whole array, process everything, and then delete everything.
I'm now bouncing back and forth trying different recommendations. But the main problem i was having with this was that for some odd reason i would have to enter each command twice, the first time i would enter the command the trigger for the loop just doesn't run, and after entering another command the first one that was entered will run. Its triggered when pause is false and i've checked that its going to false when the window closes. I've also checked that the command is stored inside the array.

Every time Enter is pressed inside obj_command step

Code:
pos = array_height_2d(commandList);
commandList[pos, 0] = splits[0] //Command
 commandList[pos, 1] = splits[1] //Value

Bottom of the obj_command

Code:
if pause==false{
for (i = 0; i < pos; i += 1) {
           
             show_debug_message("==Start ENDSTEP " + string(i) + " ==");
             show_debug_message(commandList[i,0]);
             show_debug_message(commandList[i,1]);
             show_debug_message("==Finish ENDSTEP " + string(i) + " ==");
           
             scr_commandList(commandList[i, 0], commandList[i, 1]);
             commandList="";
   }
}
seeing as he is looping from 0 to height-1
So i should be adding ?
Code:
for (i = 0; i < pos-1; i += 1) {
 
R

rui.rosario

Guest
I'm now bouncing back and forth trying different recommendations. But the main problem i was having with this was that for some odd reason i would have to enter each command twice, the first time i would enter the command the trigger for the loop just doesn't run, and after entering another command the first one that was entered will run. Its triggered when pause is false and i've checked that its going to false when the window closes. I've also checked that the command is stored inside the array.

Every time Enter is pressed inside obj_command step

Code:
pos = array_height_2d(commandList);
commandList[pos, 0] = splits[0] //Command
commandList[pos, 1] = splits[1] //Value

Bottom of the obj_command

Code:
if pause==false{
for (i = 0; i < pos; i += 1) {
          
             show_debug_message("==Start ENDSTEP " + string(i) + " ==");
             show_debug_message(commandList[i,0]);
             show_debug_message(commandList[i,1]);
             show_debug_message("==Finish ENDSTEP " + string(i) + " ==");
          
             scr_commandList(commandList[i, 0], commandList[i, 1]);
             commandList="";
   }
}


So i should be adding ?
Code:
for (i = 0; i < pos-1; i += 1) {
Set the array to "" after the loop, otherwise it'll delete the array after the first iteration (although I don't think that would quite do the behaviour you described).

Concerning the loop, if pos is 5 and you have 5 elements in the array, then you want for (i = 0; i < pos; i++), if you have 6 elements you should include pos (<=). You would only want < pos - 1 if you didn't want to process the last element.
i.e., the correct usage to iterate everything is for (i = 0; i < pos; i++) since the last index is pos - 1
 
C

Cooltrain

Guest
Set the array to "" after the loop, otherwise it'll delete the array after the first iteration
Ugh, yes of course, silly mistake.

if you have 6 elements you should include pos (<=).
Why if if it had 6 ? The goal was the every command is put into the array, meaning you could put in any amount, and then they are run once the game is unpaused (the typing/command window has closed).

The current behavior after fixing that silly mistake is that, the array is now being reset every time the game is running, but its not running the loop at all. Even though pause is false, it just doesnt seem to run, and i've got no clue why. This might be connected to why the first command that is entered isn't run until there is another command. But now it just doesn't do anything.
 
R

rui.rosario

Guest
Why if if it had 6 ? The goal was the every command is put into the array, meaning you could put in any amount, and then they are run once the game is unpaused (the typing/command window has closed).
It was an example xD I was trying to explain that:
- if pos is the number of elements, you go from 0 while i < pos
- if pos is the index of the last element, you go from 0 while i <= pos

The current behavior after fixing that silly mistake is that, the array is now being reset every time the game is running, but its not running the loop at all. Even though pause is false, it just doesnt seem to run, and i've got no clue why. This might be connected to why the first command that is entered isn't run until there is another command. But now it just doesn't do anything.
Are you sure your pos variable is correctly set?

By being reset every time you mean even when pause is not false?
 
C

Cooltrain

Guest
It was an example xD I was trying to explain that:
- if pos is the number of elements, you go from 0 while i < pos
- if pos is the index of the last element, you go from 0 while i <= pos
Oh haha, i see XD. Thanks for clarifying.

By being reset every time you mean even when pause is not false?
It's constantly being reset while pause is false.


Are you sure your pos variable is correctly set?
After watching in the debugger, the first time a command is entered pos stays at 0, and then second time a command is entered pos goes to 1.
If i now close the command window (which unpauses the game) then the new following error:

Code:
trying to index variable that is not an array
at gml_Object_obj_command_StepNormalEvent_1 (line 75) -              scr_commandList(commandList[i, 0], commandList[i, 1]);
The area from the error has already been posted above, but ill just quote it
Code:
if pause==false{
for (i = 0; i < pos; i += 1) {  
             scr_commandList(commandList[i, 0], commandList[i, 1]);    
   }
    commandList="";
    show_debug_message("Cleared commandList");

}
 
R

rui.rosario

Guest
It's constantly being reset while pause is false.
That's expected, since your code is saying to reset after processing all elements in the for loop.

After watching in the debugger, the first time a command is entered pos stays at 0, and then second time a command is entered pos goes to 1.
Then you either missed incrementing the pos variable after adding a new entry or you should change the for to <= pos (I recommend the first).

If i now close the command window (which unpauses the game) then the new following error:
That's because your variable is no longer an array, because you reset it. After resetting the array you need to make sure the variable is an array again.
 
C

Cooltrain

Guest
That's because your variable is no longer an array, because you reset it. After resetting the array you need to make sure the variable is an array again.
But its been set the same way from the create event, how would i do that here ?
 
R

rui.rosario

Guest
Ohh wait, I think I know why: You reset the array, but did you reset the pos variable?
 
C

Cooltrain

Guest
Ohh wait, I think I know why: You reset the array, but did you reset the pos variable?
Wow, holy crap... that did it. By adding a reset for pos inside the pause statement the system works...
It stores all the commands and then when it resumes runs the script that applies them all to the instances.

Thank you, so so much for all your help.
 
Top