A good start to developing a checkers blockchain is to define the rule set of the game. There are many versions of the rules. Choose a very simple set of basic rules(opens new window) to avoid getting lost in the rules of checkers or the proper implementation of the board state.
Use a ready-made implementation(opens new window) with the additional rule that the board is 8x8, is played on black cells, and black plays first. This code will not need adjustments. Copy this rules file into a new rules folder inside the root folder of your checkers-minimal module. Change its package from checkers to rules. You can do this by command-line:
Index: A string, so it can be identified and retrieved from storage.
Black player: A string, the serialized address.
Red player: A string, the serialized address.
Board proper: A string, the board as it is serialized by the rules file.
Player to play next: A string, specifying whose turn it is.
When you save strings, it makes it easier to understand what comes straight out of storage but at the expense of storage space. As an advanced consideration, you could store the same information in binary.
As ever, taking inspiration from minimal-module-example, this can be described in proto/../types.proto with:
Copy
messageGenesisState{// params defines all the parameters of the module.Params params =1[(gogoproto.nullable)=false];}+messageStoredGame{+string board =1;+string turn =2;+string black =3[(cosmos_proto.scalar)="cosmos.AddressString"];+string red =4[(cosmos_proto.scalar)="cosmos.AddressString"];+} proto alice ... v1 types.proto View source
Since Index is used to store and retrieve the stored game, it does not need to be saved to storage. This saves precious storage space.
Compile it:
Copy
$ make proto-gen
Now that you have the individual stored game structure, you can define how it is kept in storage.
The way that makes sense is to keep a map of games in storage (and controled by the keeper), and rely on the SDK's basic structures to optimize saving and retrieving.
However, the genesis takes a list, and in this list, the games need to be identified by their index.
To achieve that, you create a composed type that is used in the genesis state.
Update your GenesisState in types.proto:
Copy
messageGenesisState{// params defines all the parameters of the module.Params params =1[(gogoproto.nullable)=false];+repeatedIndexedStoredGame indexedStoredGameList =2[(gogoproto.nullable)=false];}messageStoredGame{...}+messageIndexedStoredGame{+string index =1;+StoredGame storedGame =2[(gogoproto.nullable)=false];+} proto alice ... v1 types.proto View source
Just like you did in the previous section, compile the minimal chain, re-initialize, and start it. You need to re-initialize because your genesis has changed once again:
Copy
$ make install
$ make init
$ minid start
Now your minimal chain not only has a checkers module, but also a games storage area. After stopping it with CTRL-C, confirm this by calling up: