Showing posts with label Serialisation. Show all posts
Showing posts with label Serialisation. Show all posts

Wednesday, 8 July 2009

Refactoring for Persistance

Saving and Loading Games would be nice, but before I even attempt to implement that, I need to do a codebase-wide refactor. Currently I have numerous global variables that I have used to store various state data, e.g. the number of turns that have passed, the current level depth, and so on. I really need to store all these in a "game-state" object that is instantiated on starting a game (and this is one of the nice things about C# - that everthing is an object). If I do this, it will make saving and loading a heck of a lot easier to implement. In fact, it would make it decidedly trivial.

Additionally, this gets rid of all those nasty global variables that currently litter my code, and in itself this is a good thing, as they are (and I agree with this) "considered harmful".

(N.B. when I talk about saving and loading, I don't mean in the style of the old Kharne, where you could freely reload saved games, but rather in the traditional roguelike sense of "saving a game and then restarting it within the framework of permadeath")

Wednesday, 4 June 2008

Thoughts on Serialisation

I'm finding out that implementing Serialisation (i.e. writing the state of the game out to disk) is a pain. Not only because pre .NET Delphi (I'm using Delphi 7) doesn't support inherent serialisation natively, in the way Java does, but because it requires a great deal of clarity of thought when it comes to designing and writing data structures and classes with serialisation in mind.

Let's look at what serialisation is required for Kharne:
  • Storing '@' information, such as current location, stats, inventory and current effects that he/she(/it) is subject to. The player is represented by a specific instance of the TCreature Class.
  • Storing the dungeon information. Ironically, I'm finding that this is the simplest to serialise, since the Dungeon class (cunningly called TDungeon) is basically just a multi-dimensional array of integers and booleans.
  • Storing the monster information. Monsters (also instances of the TCreature class) are stored in a TObjectList, and there are soft references to them in the dungeon class (by soft, I mean absolute ID addressing, not pointer referencing).
  • Storing the item information. Items are stored in a TObjectList, and there are soft references to them in the dungeon class. However, there is an added difficulty in that Items themselves are effectively compound objects (consisting of a base TItem and optionally one or more TItemEnchantment classes to represent magical properties of the item).
  • Storing the high-score table and any bones files.

The old Kharne did all this successfully enough, but with one major drawback: the save files lacked any soft of compression and were stupidly big (20 Mb!). This was due to the crude method I previously used for handling saves files (basically, standard Pascal WriteLn/ReadLn). This bloat is unacceptable however in the new Kharne. Fortunately, if I switch to using a more modern implementation, i.e. streaming (which Delphi supports extremely well using both TFileStream and TMemoryStream) and also use one of the many compression libraries, the save files can be reduced to an acceptible size.

Now, there are plug-in Delphi libraries available that implement serialisation but I'm not convinced that using them would be any easier than using the above methodology. I will have to do further investigation on these.