I have some pretty strict rules about runtime data, which are there to facilitate save & restore.
The most important one is that there is never more than one live pointer to any heap-allocated thing. If you seem to need more, then you need to make a collection of objects of that type, give each one a unique ID, and then implement all operations on that type using the collection and the unique ID. This assures that they never get "leaked" when we drop too many pointers, and that no dangling pointers to them can ever be hanging around.
Unique ID's can be dropped resulting in stuff that stays in the collection, but we can always get to it by iterating over the collection (which means we can detect and drop it) and Unique ID's can be hanging around after an item is deleted, but then the collection just returns an error code when you try to do something to it. So you can detect and handle the error locally instead of crashing. At first blush, you'd think that garbage collection should handle this kind of problem for you, but if you're doing save/restore, it most emphatically does not.
Saving the game then becomes mainly a matter of saving all of the managed collections. A big list of actors (items and monsters and the player), a big list of mapdeltas or "digs", a big list of message-history prototypes, a big list of input-history, a big list of pending actions ... plus a few odds & ends like the interface settings, and save is done. In each case, just emit an XML tag to start the list, emit the list in XML format, and emit an XML tag to end the list.
In the middle of saving & restoring the elements in the managed collections, there is one other kind of dynamic data that I save. It's a little hash table, used to store attributes. It's implemented as type "deck", where each entry or "card" has a "suit" or attribute identifier and then a few machine words of information whose meaning depends on the suit. But decks of attributes appear in every type that needs dynamic attributes. Actors, events, in maplevels, etc. I didn't need to write separate save/restore code for all these things' dynamic attributes, I just wrote save/restore code for decks, once, and call it when saving or restoring each kind of thing.
So, anyway, save/restore is one of the main things that drove my runtime representation choices.
Hope that helps,
Bear