Filters

# Keep Track Of How Many Moves Have Been Played

Make sure you have everything you need before proceeding:

In this section, you will:

  • Implement a count of game moves.
  • Extend your unit tests.

Previously, you added a winner and a deadline to games, with a view to implementing a forfeit mechanism for games that have become stale.

# Some initial thoughts

When the forfeit is implemented, it would be interesting to be able to differentiate games that have never been played on from games that have.

To be specific:

  1. If no moves are ever played, there is no point in recording a winner and a forfeiter. There is no point in keeping a track of the game.
  2. If the black player moved once but the red player never showed up, it is the same situation. After all, a malicious player could create many games that go stale just to tarnish the reputation of another player.
  3. If both players have played at least once, then this can be considered a proper game, where a forfeit is one of the legitimate outcomes.

# New information

To achieve this, the easiest way is to add a new MoveCount to the StoredGame. In proto/checkers/stored_game.proto:

Copy message StoredGame { ... + uint64 moveCount = 8; } proto checkers stored_game.proto View source

Run Protobuf to recompile the relevant Go files:

MoveCount should start at 0 and increment by 1 on each move.

  1. Adjust it first in the handler when creating the game:

    Copy storedGame := types.StoredGame{ ... + MoveCount: 0, } x checkers keeper msg_server_create_game.go View source
  2. Before saving to the storage, adjust it in the handler when playing a move:

    Copy ... storedGame.Deadline = types.FormatDeadline(types.GetNextDeadline(ctx)) + storedGame.MoveCount++ storedGame.Turn = rules.PieceStrings[game.Turn] ... x checkers keeper msg_server_play_move.go View source

This value is not emitted in events, because (as it stands) it will be only used internally for checks.

# Unit tests

You have to fix the existing tests by adding MoveCount: 0 (opens new window) (or more (opens new window)) when testing a retrieved StoredGame.

# Interact via the CLI

There is not much to test here. Remember that you added a new field, but if your blockchain state already contains games then they are missing that field, so the default value of the underlying type will be applied:

Although this game was already played on, the default uint value is applied:

Copy ... + moveCount: 0 ...

In effect, your blockchain state is broken. Eventually examine the section on migrations to see how to update your blockchain state to avoid such a breaking change.

Restart your chain with --reset-once, create a new game, then:

This contains:

Copy ... + moveCount: 1 ...
synopsis

To summarize, this section has explored:

  • How to implement a new moveCount field and increment it on play.
  • How to test your code to ensure that it functions as desired.
  • How, if your blockchain contains preexisting games, that the blockchain state is now effectively broken, since the move count field of those games is 0 by default (which can be corrected through migration).