Starting with SVN revision 1311 of KoLmafia, ASH now supports a new kind of structured data: the record. Here is a little example of how you declare a record and variables of the new type you've created by doing so.
What I've done with the above is declare a new data type which I've named "my_type". Having declared the new type, I can use it (almost) anywhere that I can use a built-in type name. I declared a variable, "rvar", of that type, and I defined a map, "mrvar", which maps keys of type integer to values of type my_type.
The new type, "my_type" is a "composite" type. It contains four fields. "ifield" is an integer. "sfield" is a string. "rfield" is another composite field: an anonymous record containing two integers named "first" and "second". Finally, "mfield" is a map from [int, int] to int.
As you can see, a record can combine data of all the types ASH supports: primitive, aggregate, and composite.
Having defined the new data type and several variables using it, here are some examples of how to access the fields.
As you can see, if you have a variable that is a record, you access the fields of the record by following the variable name with ".<field name>". The resulting value will be of whatever type you declared in the definition of the record. If the value is a map, you can give a list of keys within [], just like any other map. If the value is another record, you can access the fields of the nested record by using another ".<field name>".
If you are familiar with Pascal "records" or C/C++ "structs", this should all be comfortably familiar.
Finally, if you create a map whose values is a record, the file_to_map and map_to_file built-in ASH functions will Do The Right Thing; they will efficiently and reliably save and restore your data.
Code:
record my_type {
int ifield;
string sfield;
record {
int first;
int second;
} rfield;
int [int, int] mfield;
};
my_type rvar;
my_type [int] mrvar;
What I've done with the above is declare a new data type which I've named "my_type". Having declared the new type, I can use it (almost) anywhere that I can use a built-in type name. I declared a variable, "rvar", of that type, and I defined a map, "mrvar", which maps keys of type integer to values of type my_type.
The new type, "my_type" is a "composite" type. It contains four fields. "ifield" is an integer. "sfield" is a string. "rfield" is another composite field: an anonymous record containing two integers named "first" and "second". Finally, "mfield" is a map from [int, int] to int.
As you can see, a record can combine data of all the types ASH supports: primitive, aggregate, and composite.
Having defined the new data type and several variables using it, here are some examples of how to access the fields.
Code:
rvar.ifield = 10;
rvar.sfield = "secret";
rvar.rfield.first = 1000;
rvar.sfield.second = 2000;
rvar.mfield[ 2, 3 ] = 12;
mrvar[ 1 ] = rvar;
foreach key in mrvar
foreach key1, key2 in mrvar[key].mfield
print( "val = " + mrvar[key].mfield[key1,key2] );
As you can see, if you have a variable that is a record, you access the fields of the record by following the variable name with ".<field name>". The resulting value will be of whatever type you declared in the definition of the record. If the value is a map, you can give a list of keys within [], just like any other map. If the value is another record, you can access the fields of the nested record by using another ".<field name>".
If you are familiar with Pascal "records" or C/C++ "structs", this should all be comfortably familiar.

Finally, if you create a map whose values is a record, the file_to_map and map_to_file built-in ASH functions will Do The Right Thing; they will efficiently and reliably save and restore your data.