The ASH functions map_to_file and file_to_map have an optional third argument which specifies that the file format is "compact". Since that is the default, and I expect everybody wants that behavior, you may not even know what this means. Currently, it has an effect only for maps of records.
For a record, it puts all the fields for a record on the same line of a data file, rather than initializing them one field per line.
For example, here is a script which has a map of records and wants to save/restore it from a file in the data directory.
yields this:
These are the two files generated by map_to_file.
Compact (arec1.txt):
Non-compact (arec2.txt):
The compact version has one record per line with all the fields in order, whereas the non-compact version sets one field at a time by name.
What if you have a map of maps? Which is to say, effectively a multi-dimensional map.
Maps only have a non-compact representation. Whether or not you say "compact" in map_to_file or file_to_map, you will get multiple lines of data. The first field will be the index of the outer map, the second field will be the index of the nested map, and the third field will be the data. (That is for a two-dimensional map; things are more complicated for more dimensions, but they should work.)
What if you have a map of arrays?
Currently, they behave like maps and only have a non-compact representation. However, since we know what all the "keys" are - they are simply integers from 0 - <N> - we could have a compact representation which doesn't save the keys.
I have implemented a "compact" file representation for arrays. This script:
Yields this:
Here are the two files generated by map_to_file.
Compact (amaps2.txt):
Non-compact (amaps1.txt):
Which is completely analogous to compact & non-compact records.
It also means that if you read questslog.txt as a file with a "compact" array (which it is, effectively), you can write out a file in the same format.
I like this, but it is not completely backwards compatible: if you had a map whose values are arrays (not maps) and saved it with map_to_file, you previously always got the "non-compact" version - even if you didn't say you wanted that. Especially if you didn't bother saying that, since the default two-argument version of map_to_file and file_to_map assumed "compact".
The solution for scripts is simple: if you had a map of arrays (again, not maps) which you saved to a file, add the optional third parameter to map_to_file and file_to_map where you saved & restored it to be "false" (boolean, not as a string).
I may just submit this, but I thought I'd throw it out for comments first. For a while.
For a record, it puts all the fields for a record on the same line of a data file, rather than initializing them one field per line.
For example, here is a script which has a map of records and wants to save/restore it from a file in the data directory.
Code:
record test {
int a;
string b;
location c;
};
test [int] map;
map[0] = new test( 1, "abc", $location[ none ] );
map[1] = new test( 2, "def", $location[ The Spooky Forest ] );
map[2] = new test( 3, "ghi", $location[ Barf Mountain ] );
void print_map( string title, test [int] map )
{
print( title );
foreach index, val in map {
print( "map[" + index + "] = (" + val.a + "," + val.b + ", " + val.c + ")" );
}
print( "" );
}
print_map( "Original map", map );
map_to_file( map, "arec1.txt", true );
test [int] map1;
file_to_map( "arec1.txt", map1, true );
print_map( "Compact file", map1 );
map_to_file( map, "arec2.txt", false );
test [int] map2;
file_to_map( "arec2.txt", map2, false );
print_map( "Non-compact file", map2 );
Code:
[color=green]> arecs.ash[/color]
Original map
map[0] = (1,abc, none)
map[1] = (2,def, The Spooky Forest)
map[2] = (3,ghi, Barf Mountain)
Compact file
map[0] = (1,abc, none)
map[1] = (2,def, The Spooky Forest)
map[2] = (3,ghi, Barf Mountain)
Non-compact file
map[0] = (1,abc, none)
map[1] = (2,def, The Spooky Forest)
map[2] = (3,ghi, Barf Mountain)
Compact (arec1.txt):
Code:
0 1 abc none
1 2 def The Spooky Forest
2 3 ghi Barf Mountain
Non-compact (arec2.txt):
Code:
0 a 1
0 b abc
0 c none
1 a 2
1 b def
1 c The Spooky Forest
2 a 3
2 b ghi
2 c Barf Mountain
What if you have a map of maps? Which is to say, effectively a multi-dimensional map.
Maps only have a non-compact representation. Whether or not you say "compact" in map_to_file or file_to_map, you will get multiple lines of data. The first field will be the index of the outer map, the second field will be the index of the nested map, and the third field will be the data. (That is for a two-dimensional map; things are more complicated for more dimensions, but they should work.)
What if you have a map of arrays?
Currently, they behave like maps and only have a non-compact representation. However, since we know what all the "keys" are - they are simply integers from 0 - <N> - we could have a compact representation which doesn't save the keys.
I have implemented a "compact" file representation for arrays. This script:
Code:
typedef string[3] type_v;
typedef string type_k;
type_v [type_k] map;
map[ "first" ] = string[3] { "a", "b", "c" };
map[ "second" ] = string[3] { "b", "c", "a" };
map[ "third" ] = string[3] { "c", "a", "b" };
// Not compact
map_to_file( map, "amaps1.txt", false );
type_v [type_k] amap1;
file_to_map( "amaps1.txt", amap1, false );
// Compact
map_to_file( map, "amaps2.txt", true );
type_v [type_k] amap2;
file_to_map( "amaps2.txt", amap2, true );
void print_map( string title, type_v [type_k] map )
{
print( title );
foreach key, val in map {
foreach index, str in val {
print( "map[" + key + "][" + index + "] = " + str );
}
}
print( "" );
}
print_map( "Original map", map );
print_map( "Non-compact map", amap1 );
print_map( "Compact map", amap2 );
Code:
[color=green]> amaps.ash[/color]
Original map
map[first][0] = a
map[first][1] = b
map[first][2] = c
map[second][0] = b
map[second][1] = c
map[second][2] = a
map[third][0] = c
map[third][1] = a
map[third][2] = b
Non-compact map
map[first][0] = a
map[first][1] = b
map[first][2] = c
map[second][0] = b
map[second][1] = c
map[second][2] = a
map[third][0] = c
map[third][1] = a
map[third][2] = b
Compact map
map[first][0] = a
map[first][1] = b
map[first][2] = c
map[second][0] = b
map[second][1] = c
map[second][2] = a
map[third][0] = c
map[third][1] = a
map[third][2] = b
Compact (amaps2.txt):
Code:
first a b c
second b c a
third c a b
Non-compact (amaps1.txt):
Code:
first 0 a
first 1 b
first 2 c
second 0 b
second 1 c
second 2 a
third 0 c
third 1 a
third 2 b
It also means that if you read questslog.txt as a file with a "compact" array (which it is, effectively), you can write out a file in the same format.
I like this, but it is not completely backwards compatible: if you had a map whose values are arrays (not maps) and saved it with map_to_file, you previously always got the "non-compact" version - even if you didn't say you wanted that. Especially if you didn't bother saying that, since the default two-argument version of map_to_file and file_to_map assumed "compact".
The solution for scripts is simple: if you had a map of arrays (again, not maps) which you saved to a file, add the optional third parameter to map_to_file and file_to_map where you saved & restored it to be "false" (boolean, not as a string).
I may just submit this, but I thought I'd throw it out for comments first. For a while.
