GameMaker Saving DS_LIST with nested DS_MAP?

I'm relatively new to GMS2 and looking for advice on saving DS_LISTS that have ds_maps inside of them to an ini file.

Adding the map to the list..
Code:
global.troops = ds_list_create();

entry = ds_map_create();
ds_map_add(entry, "type", "Knight");
ds_map_add(entry, "hp", 100);
ds_list_add(global.troops, entry);
saving the file..
Code:
filename = "settingfile.ini";
ini_open(filename);

temp_list = ds_list_create();
length = ds_list_size(global.troops);

for(i = 0; i < length; i++) {
    temp_var = ds_list_find_value(global.troops, i);
    ds_list_add(temp_list, temp_var);
}

temp_list_str = ds_list_write(temp_list);
ini_write_string("Save", "troops", temp_list_str);
ds_list_destroy(temp_list);

ini_close();
load file..
Code:
global.troops = ds_list_create();

filename = "settingfile.ini";
if(file_exists(filename)) {
ini_open(filename);

temp_list = ds_list_create();
temp_list_str = ini_read_string("Save", "troops", "");
 
ds_list_read(temp_list, temp_list_str);
 
length = ds_list_size(temp_list);
 
for(i = 0; i < length; i++) {
        val = ds_list_find_value(temp_list, i);
        ds_list_add(global.troops, val);
}
 
    ds_list_destroy(temp_list);
}

ini_close();
Now every attempt I've made at loading the variables, doesn't seem to work. How would I go about reading the ds_list/ds_map from the ini file? I know how to load basic variables with ini_read_string() etc. But I can't seem to read the ds_list! Can't get my head around it, can someone give me advice? Am I going about this the wrong way? Thank you!
 
Last edited:

chamaeleon

Member
I'm relatively new to GMS2 and looking for advice on saving DS_LISTS that have ds_maps inside of them to an ini file.

Adding the map to the list..
Code:
global.troops = ds_list_create();

entry = ds_map_create();
ds_map_add(entry, "type", "Knight");
ds_map_add(entry, "hp", 100);
ds_list_add(global.troops, entry);
saving the file..
Code:
filename = "settingfile.ini";
ini_open(filename);

temp_list = ds_list_create();
length = ds_list_size(global.troops);

for(i = 0; i < length; i++) {
    temp_var = ds_list_find_value(global.troops, i);
    ds_list_add(temp_list, temp_var);
}

temp_list_str = ds_list_write(temp_list);
ini_write_string("Save", "troops", temp_list_str);
ds_list_destroy(temp_list);

ini_close();
load file..
Code:
global.troops = ds_list_create();

filename = "settingfile.ini";
if(file_exists(filename)) {
ini_open(filename);

temp_list = ds_list_create();
temp_list_str = ini_read_string("Save", "troops", "");
 
ds_list_read(temp_list, temp_list_str);
 
length = ds_list_size(temp_list);
 
for(i = 0; i < length; i++) {
        val = ds_list_find_value(temp_list, i);
        ds_list_add(global.troops, val);
}
 
    ds_list_destroy(temp_list);
}

ini_close();
Now every attempt I've made at loading the variables, doesn't seem to work. How would I go about reading the ds_list/ds_map from the ini file? I know how to load basic variables with ini_read_string() etc. But I can't seem to read the ds_list! Can't get my head around it, can someone give me advice? Am I going about this the wrong way? Thank you!
A fundamental problem you have is that you assume the list knows that a particular stored entry in it is a map instead of a number. But it can only know that if you use the ds_list_mark_as_map and ds_list_mark_as_list functions after you add such things to the list. The "drawback" doing this though, is that now that the list you added the map to becomes the owner of the map, and you can no longer destroy it at your leisure, and you cannot destroy the container list without either ds_list_delete() or ds_list_replace() the value containing a map or list with something that is not a data structure (doesn't matter what, maybe the number 0, or empty string, whatever), before you ds_list_destroy() the list.

Take some time to understand the implications of dealing with ids for things, and that an id is just a number with no inherent meaning unless you call a function with it as an argument.

Code:
var l = ds_list_create(); // => l = 0
var m = ds_map_create(); => m = 0
Some possibilities showing the issue that ds_list_mark_as_map, ds_list_mark_as_list, ds_map_add_map and ds_map_add_list tries to work around
Code:
ds_list_destroy(l); // program will run fine, doesn't care where 0 came from
ds_list_destroy(m); // program will run fine, doesn't care where 0 came from
ds_map_destroy(l); // program will run fine, doesn't care where 0 came from
ds_map_destroy(m); // program will run fine, doesn't care where 0 came from
ds_list_destroy(0); // program will run fine, doesn't care where 0 came from
ds_map_destroy(0); // program will run fine, doesn't care where 0 came from
Code:
ds_list_add(l, m);
var s = ds_list_write(l); // "Programmer wants me to write out the number 0 stored in the first position. No problem!"
ds_list_mark_as_map(l, 0);
var s = ds_list_write(l); // "Programmer wants me to write out the map stored in the first position. No problem!"
 

Neptune

Member
Code:
var list = ds_list_create();
var map = ds_map_create();

ds_list_add(list,ds_map_write(map));

var save str = ds_list_write(list);
Gotta write your data structures to a string (a huge strand of misc characters that represent your data structure, and can be 'read' back into a DS when you load).
Otherwise your list is just containing a reference to a map (some integer value).
Or some marking technique like suggested (I have no idea about doing that).
 
O

OccultOne

Guest
ds_list_write is likely your best bet, though if you need a bit more control, or need to do something funky with the data as you save, perhaps iterating through the Maps and Lists?


Iterating through a list is simple.
for(var i=0;i<ds_list_size(List);i++) {}


Code:
// Store the first Key in the Map
var _Key = ds_map_find_first(Map);
// Store the index if you need it (Optional)
var i = 0;
// While the Key is not Undefined (You're still iterating through the Map)
while(!is_undefined(_Key)){
// Get the Value at this mapping.
var _MapValue = Map[? _Key];
// Do something with it.

// Get the next key in the Map
_Key = ds_map_find_next(Map, _Key);
 i++;
}
 
Top