Setting the stage
During the main gameplay loop, the Gambit chessboard switches between two major states: the player move and the enemy move. The enemy move is straightforward enough – the state of the board is sent out, and a move from an external source is sent in. There is little wiggle room so the implementation is quite simple. The player move is a different story however. Gambit allows the user to play as if it was a normal chessboard, which comes with its own limitations. In order to implement this functionality, a finite state machine was created in order to track the player’s moves which is the topic of this blogpost.
The problem(s)
The main problem stems from the way that player input is received. In this case, the only source of player input are the reed switches scattered on the board. Those reed switches only know one thing each: if there is a magnet on top of them or not. They cannot be used directly to describe a complex action like moving a chess piece, especially since some moves require more than one pieces to be picked up and moved (eg. captures). There is one aspect of the reed switches we can exploit though: given a previous state of the board, every possible move has its own unique sequence of specific reed switches being switched on and off*. It makes sense if you thing about it – if at the start of the game the board detected a reed switch going off at e2, and then turning on at e4, then clearly the player must have moved a pawn from e2 to e4. Now if we could just monitor the player actions step by step – in this case 1. pick up pawn from e2, 2. put down pawn on e4, we can determine when the move is complete and effectively abstract the player’s atomic actions into a full chess move to update the board state and send it off for the next round. That is where the finite state machine comes in.
*there is one caveat to that statement: the board is unable to distinguish between promoting pawns to different pieces, but that problem can most likely be solved through other means, like the accompanying app.
The solution
The basic idea is that the state machine will be able to determine what the player is doing at any given moment. Are they holding a piece? Are they preparing to capture? Did they complete a move? Or are they just idling. A simple movement of a piece is simple enough but it soon gets more complicated with more advanced moves. A capture for example requires a sequence of atomic moves that’s longer by one. First you pick up your piece that’s doing the capturing, then you pick up the enemy piece that’s about to be captured, and finally you place down your piece on the captured piece’s spot. An even more complex move is castling. This requires a total of four steps: picking up the king, picking up the rook, placing the king and placing the rook. This is further exacerbated by the uniqueness of the castling move where the pieces do actions they wouldn’t be able to do otherwise. All in all, the FSM has to handle all those cases.
Robustness
One of the most important aspects of the FSM is robustness. Players might come with their own habits when it comes to moving pieces: for example some people might prefer to pick up the enemy piece before picking up your own piece during captures. Furthermore player might make mistakes and want to put their piece back down (perhaps not allowed in professional competitions, but very much common in casual matches). Worst of all, the players can perform an illegal move, which cannot be parsed and therefore needs to be retracted. It is paramount that all those situations are fully recoverable, otherwise having to restart the whole game after every mistake would be incredibly annoying. As such the FSM needs to also account for this, increasing complexity further.
Keeping it grounded
There are limits to this of course. There are millions of way a player can make a mistake and at some point it starts to be impossible to keep track of. There is no way to gracefully recover once a cat stepped over the board and knocked off all the pieces. As such, the FSM should support at least one degree of error (i.e. if there is just one mistake on the board), which should handle the majority of situations. In deeper troubles, the FSM goes to an error state that is not directly recoverable. From this point on, there are several possibilities, but those haven’t been implemented yet. The simplest one is to end the game, but this could be seen as lazy. Perhaps a more elegant solution would be to use the accompanying app to display the last valid state of the board and ask the player to restore it. This problem will be handled at a later time.
Either way, after much consideration the FSM has been created like so:

Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.