Sharing Score and other variables between games?

I understand TADS 3 has a file I/O system much like Inform 6/7 do, but how would I go about saving certain variables (such as score, number of moves, Etc.) to a file? I know this was possible with Inform and the Glulx file I/O layer, but from what I’ve seen the syntax is rather unorthodox; TADS seems to be a bit more straightforward in the case of file creation.

1 Like

Have you read the File section in the System Manual yet?

Yes I have. I’ve managed to create files, but loading data into variables and saving variables to the file… I still have no idea how to get that working.

This is working for me (with limitations):

InitObject
  execute() {
    local customFile = File.openTextFile('custom.txt', FileAccessRead);
    Compiler.compile('function() {' + customFile.readFile + ';}')();
  }
;

With custom.txt containing normal TADS code. The caveat being that only the first line is parsed. I haven’t looked into fixing that yet, but you can get around it by putting all your code on one line, with the use of semicolons.
Hope this helps! I’ll post results when I find out how to parse the whole file, and not just the first line.

edit:
OK, this probably won’t help you with writing thigs to the file, but at least the other half is covered :slight_smile:

Btw., what’s the reason for wanting to track the score and movements outside of the standard save file functionality?

I’ve never had cause to look into how to use it, but would this be a situation where you use the ByteArray objects?

I plan on releasing a series of games in an episodic manner, and having access to score and other variables is an interesting mechanic that I’ve not seen before, except perhaps in the Level 9 games, so I plan on taking advantage of it as much as possible.

I’ve only skimmed the File doc in the system manual but it seems like the Data format type would be suited for basic stat tracking?

I tried the data format, but for some reason I couldn’t get the variable stored in the file to transfer over to the current game state. Writing the file with the information worked fine, but I’m not sure how to move the data from the file to the variable.

Here’s one example of how you could do it:


...
someFunction() {
  try {
      storeDataToDataFile(['TEST1','TEST2']);
      local result = readDataFileToArray();
      result.forEach({data: "data read: <<data>>"});
  } catch(Exception e) {
      "Failure during open/read/write operation: <<e.exceptionMessage>>";
  }
}

function storeDataToDataFile(dataArray) {
    local file = File.openDataFile('test.data', FileAccessWrite);
    foreach(local data in dataArray){
        file.writeFile(data);
    }
    file.closeFile();
}

function readDataFileToArray() {
    local result = [];
    local file = File.openDataFile('test.data', FileAccessRead);
    local x;
    while((x = file.readFile()) != nil) {
         result += x;
    }
    file.closeFile();
    return result;
}

2 Likes

As you can see by the example you just keep reading the data file with readFile() until you get nil back, then all data has been read.

Then if I understand it correctly, I should be able to reassign the items in the array to the variables I wrote to the file, once the data elements have been stored in the array, so array[1] could become the score variable, Etc. Thanks a ton.

That’s right! One drawback is of course that the values will be stored in plain sight and can be altered outside (too easily). Therefore it might be a better idea to store the values as bytes using the raw-format. If you are only using integers between 0-65535 the following solution will work for you but if you are planning to mix strings and numbers you will probably need to read up a lot in the sections: File, ByteArray and BytePacking in the system manual.

If you just wish another range for the numbers, replace ‘S’ and ‘S*’ (in packBytes and unpackBytes respectively) with one of the type codes available in the the top of the chapter of Byte Packing.


someFunction() {
  try {
      local filename = 'test.bin';
      storeUIntToRawFile(filename, [200,300, 500, 7000]);
      local result = readRawFileToArray(filename);
      result.forEach({data: "data read: <<data>>\n"});      
  } catch(FileException e) {
      "Failure during open/read/write operation: <<e.exceptionMessage>>";
  }
}

function storeUIntToRawFile(filename, dataArray) {
    local file = File.openRawFile(filename, FileAccessWrite);
    dataArray.forEach(function(value) {
        file.packBytes('S', value);
    });
    file.closeFile();
}


function readRawFileToArray(filename) {
    local file = File.openRawFile(filename, FileAccessRead);
    local byteArray = file.unpackBytes('S*');
    file.closeFile();
    return byteArray;
}

2 Likes

This will work just as well, if not more. Thanks a ton.