I've finished a rough breakdown of how the game will be put together. This is really the last step in the high-level design phase; from here the designs get much more detailed and cryptic.
This is the infamous Block Diagram that kicks off most software projects:
Each of these modules gets summarized below, though each will require a detailed low-level specification.
Application Resources
Contains a selection of pre-designed playing boards and the descriptions of all the possible cards for this application’s included ‘decks’. This content will be designed separately, compressed and attached to the application either as an external banshee database or as java app resources.
Card Database
Responsible for informing the Game Rules Engine all about a particular modifier card. The GRE doesn’t read the application resources directly, because the card may not exist there.
One of the goals of this game is to be able to interoperate with other versions of the application. Picture the Danger Catalog with three different games in it, each separately purchased for $4.99 (maybe with a discount if you’ve already bought one of them). You buy game A (with a certain list of cards encoded in it), and your friend buys game B (with a different list of cards). Yet you want to be able to play against each other.
When asked to resolve the meaning of a card, the database first consults its cache of card information; if that turns up the data it needs, then its job is done.
If the card isn’t in-cache, the database consults the application resources to see if it has some data about the card locally. If so, it decodes the resource and shoves the result into its cache, then returns the result.
If that fails, then the card must’ve been introduced by a peer. The database turns to the network to ask about the card, and updates its cache when it gets a response. (When the GRE asks for data about a card, it also specifies which peer probably triggered that query-usually the player whose turn just ended.)
The card database is also used by the local display, which needs to describe cards to the local player; in this capacity it caches text and icons. These also are served from cache.
Finally, the current game state also interacts with the card database, in order to advise it that particular cards are currently active and should not be thrown out of the cache.
Persistent Card Storage
When the card database receives data about a new card from a peer, it records that data persistently as well as in its local cache.
This persistent storage is required when loading a previously networked game-and is particularly essential on the Hiptop, where even switching away from the game requires that all in-memory caches be discarded to save memory.
Network Connections
The networking model here is driven by what the Danger Hiptop supports-that is, peer-to-peer networking is preferred over client/server architectures.
Typically the rules engine receives updates over the network from other players who have just completed a turn. There are many complications here in the realms of picking players and setting up a game, handling disconnections and so on.
It is anticipated that the desktop game-which has lower-latency networking-will probably be primarily a real-time turn-based game. The cell phone game, however, is likely going to be used often as a correspondence game-make your move, then close your phone and go do something else, expecting to get notified when it’s your turn again. The game must support both models.
The actual network protocol should be generic enough to support cell phone users playing against desktop users. Certainly the other content-cards, rules, game board dimensions, etc-will be compatible.
Game Rules Engine
The most complex part of the game: this is the logic engine that takes a description of a player’s turn and applies it to a Current Game State in order to determine the result. The GRE is responsible for accumulating actions performed by the user locally and eventually transmitting them to all peers when this player’s turn is completed.
Note that the GRE does not typically transmit the entire resulting game state-just the actions performed by the local user. The assumption is that the remote player’s receiving GRE will enact those same actions and end up with an identical game state. To verify this, the local GRE will checksum its initial and final game states and transmit those checksums as well; if the receiving player’s GRE ends up with a different checksum (or if it fails to perform the turn at all, perhaps because it lost the local save game), then the GRE will indeed transmit the entire game state to the recipient.
Current Game State
A static structure that encompasses the entire present state of a game, including board terrains, player creatures, active modifiers and so on.
The Game State can be initialized by the GRE for a new game or can be loaded from a serialized state; thereafter it is modified by the GRE as turns proceed. The Game State informs the local display as it changes, and makes different actions available to the local user.
Local User Input
Manages the input devices for the local player. These are quite different between the desktop and cell phone variants, and so each flavor requires a separate specification.
Serialization
Encodes a game state as a relatively compact chunk of data, which can be saved persistently for later. The serialized game state does not encode the cache of the card database; the database is responsible for maintaining any persistent storage that it needs.
Local Display
Works very closely with the local user input module, presenting the game on the local monitor or cell phone. As with the input module, the display’s form factor is clearly radically different between the cell phone and desktop device, and these will therefore require separate specifications.
I've also got short summary of how the game sequencing should work. This is less fancy stuff--but it's something that I typically slap on at the last minute and therefore botch horribly. "Sequencing" means, at least in this sense, all the messy menuing stuff that lets the user start a game, pause a game, load and save games, switch away, advance levels and generally just do everything else in the application except simply play the game. Because Hero has a lot of potential to be played as a correspondence-style game, I wanted to make sure I got this part right.
Game Sequencing
The application maintains a persistent store of ongoing games; any one of which can be active at once. The active game is the one that is currently being displayed. This active game, if there is one, can be either paused or running.
The application has a main menu which-among other things-lists all ongoing games. For each such ongoing game, the application indicates whether it is the local player’s turn or whether the game is still waiting for a remote opponent to move.
When the game is first run, there is no active game and the user is presented with this main menu. Thereafter, the user can return to that main menu at any time-doing so again means there is no longer an active game. The game that was previously active will appear in the list of games as one among several, with the current selection focus on that game-such that triggering it will return the user to play.
While playing a game, it’s possible that the user will switch away to another process. On the cell phone this is a particularly common activity, but even on the desktop the action must be streamlined to account for a play-by-correspondence feel. Switching away from the application does not clear the active game; it simply switches the active game from the running state to the paused state.
As long as the application is running, it is possible that it will receive input from a peer indicating that the state of the game has changed. If this change affects the active game, and if the active game is running rather than paused, then the change is made immediately to the active game and the turn is played out visually on the local display. In all other cases, the new turn data is cashiered away along with the target game-so that when the user next resumes the updated game (or un-pauses the active game), the opponent’s turn can be visually seen.
While switched away, the desktop application uses a bubble notice near the taskbar to indicate that a game state has changed; the cell phone application uses a notification over the clock area for the same purpose.
The splash screen for the game indicates a brief summary of whether there are any games in progress for which it is the local player’s turn.
Lost Connections
Cell phone connections are particularly vulnerable to being dropped, and desktop connections will be dropped if either player closes the game. The active game is not impacted by these lost connections; instead, if it is the local player’s turn he can continue without even being notified of the problem.
When the local player completes his turn, the application attempts to send the summary of his actions to all peers. If any peer fails to acknowledge that the turn was received within a reasonable period of time, the local application attempts to re-send it-and will continue trying, until it either succeeds or receives a game update from another peer.
Remember that more than two players may be involved: if player A completes his turn, that data will be transmitted to B and C. Assuming B receives the data and it is B’s turn to play, that player will probably make his own turn and proceed to transmit that update to A and C-even if C never got A’s transmission. In this case, A will receive B’s transmission and update his own game state, discarding the data that it failed to send to C.
This process is safe because C, when it finally discovers that it is out of date, will simply get a transmission of the full game-state rather than an incremental update-and the game continues normally.
So long as the application is running, it periodically (~N seconds) looks through all the ongoing games-even the active one-searching for games in which it is not the local player’s turn. For those games, the application makes a quick call to all its peers asking for the current game’s status; the peers reply simply with a checksum of the current game state. In this way, if one peer temporarily loses its connection and misses some content, it will catch up quickly once it reattaches to its peers.