Latest development session involved getting into the saving & loading tutorial — from the outdated Version 1 of the tutorial. Version 2 still isn’t out.
But that’s okay. I’ve been looking forward to seeing if I can start writing my own code in this thing.
Step 1: Refactoring! The tutorial recommends setting up a “constants” file, for all the key things defining the game and what it looks like. (IE, how large is the map? What are the potential room sizes? Where is the message log located on the screen? Etc.) For this, I did copy-paste the tutorial’s file as my starting point, then set about adapting it to what my code actually looked like.
This proved a bit challenging, as the constants it defined were a bit all over the place. This drove me to do some refactoring, to make the code closer to my version of “tidy.” For instance, why was the code responsible for sending data to the message log defining the log’s x/y coordinates every time it was called? There’s a MessageLog object, after all; why not just tell that thing where it lives when you create it, and then not worry about it?
Eventually, I got the code to a point where the “main” file was the only one that cared about the “constants” file, and acted as the traffic cop responsible for sending that data to the parts of the game that needed it. Seems to work pretty well.
Also wound up having to do some debugging to figure out why my “fireball radius” feature (which I’m inordinately proud of) stopped working. Turned out I’d done something foolish to the order in which things got rendered. It was frustrating, but at the same time, I felt very confident when I managed to track-down and correct that problem.
It turns out that saving the game state to a file is piss easy, even easier than the tutorial suggested. The tutorial was telling me to save all these objects individually, but I quickly realized that the only thing I actually needed to save was the “Engine” object. Had a little trouble installing the Python package used to serialize the object, but the problem turned out to be that Python 3 comes with that package pre-installed. Love it when the solution turns out to be “You never actually had that problem in the first place, dumb-ass.”
So, for proof of concept, I had the game save itself after every action. (On the to-do list: confirm that the game is saving itself ONLY after the player acts, and isn’t saving itself every time the mouse twitches. That would be inefficient.) Then, when the game powers-up, it first checks to see if the save file exists; if it does, it loads it instead of creating a new dungeon.
It works! (After I figured out that the data serializer and the file manager have a difference of opinion on whether one should actually specify a “.dat” extension for the savefile.) It works SO well that, if you get killed, the next game will cheerfully reload the dungeon that has become your tomb, with you still laying there surrounded by the monsters that killed you. So, erm, maybe death should delete the save file.
It has the same problem if you win, though; clear the dungeon of monsters, and your next playthrough will load you into the corpse-filled site of your underground rampage, with nothing to do but wander and contemplate the ultimate futility of violence. So I probably do need to define some formal “You won!” condition just so I don’t have to manually delete the save files.
From there, the tutorial would like me to create a “Main” game screen, from which to ask the user if they would like to start a new game or continue an old one, and … goddamn, that’s actually going to take some effort. Looks like the old version of the tutorial actually made you write some dedicated UI code for stuff like that. The new tutorial lacks that feature. So, I think that’s my next task: centralize all the pop-up menu code into some convenient centralized package that I can use to communicate with the player.
Turns out that saving a game is dirt simple, but asking the player if they’d like to save the game is quite challenging. Roguelikes are fuckin’ weird.