complete documentation of the network protocol

Mon, 24 Aug 2026 15:48:19 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 24 Aug 2026 15:48:19 +0200
changeset 191
6da16865a270
parent 190
c90386d55cb2
child 192
e57e2874fb2a

complete documentation of the network protocol

resolves #938

PROTOCOL.md file | annotate | diff | comparison | revisions
src/main.c file | annotate | diff | comparison | revisions
src/network.h file | annotate | diff | comparison | revisions
--- a/PROTOCOL.md	Mon Aug 24 14:43:33 2026 +0200
+++ b/PROTOCOL.md	Mon Aug 24 15:48:19 2026 +0200
@@ -84,7 +84,7 @@
 
 ### Starting a New Game
 
-When the server wants to start a new game, they SHALL send a `NETCODE_GAMEINFO`
+When the server wants to start a new game, they SHALL send a `GAMEINFO`
 message. The payload of this message is as follows:
 * one BYTE denoting the color the server wants to play
   (16 or 0x10 = white, 32 or 0x20 = black)
@@ -98,9 +98,9 @@
 
 ### Continuing a Game
 
-When the server wants to continue a game, they SHALL send a `NETCODE_PGNDATA`
+When the server wants to continue a game, they SHALL send a `PGNDATA`
 message. The payload of this message is as follows:
-* the same two BYTEs and three WORDs as in `NETCODE_GAMEINFO`, followed by
+* the same two BYTEs and three WORDs as in `GAMEINFO`, followed by
 * one WORD for the number `n` of moves that will follow
 * the `n` MOVEs that have been played already
 
@@ -125,41 +125,161 @@
 
 ### Make a Move
 
-### Resign
+If the active player wants to make a move, they SHALL send a `MOVE` message
+with one MOVE payload to the waiting player.
+The active player SHALL then wait for an `ACCEPT_MOVE` or `DECLINE_MOVE`
+message.
+
+When the waiting player receives a `MOVE` message, they SHOULD validate the
+move. When validation fails, they SHALL send a `DECLINE_MOVE` message with one
+byte indicating the reason why the move is declined.
+Otherwise, they SHALL send an `ACCEPT_MOVE` message.
+
+When the move is accepted, both players SHALL swap the active / waiting role.
+
+The reasons for declining a move are listed in the following table:
+
+| Reason                | Value | Description                                 |
+|-----------------------|-------|---------------------------------------------|
+| INVALID_MOVE_SYNTAX   | 1     | E.g., indices out of bounds                 | 
+| PIECE_NOT_FOUND       | 2     | The piece is not at the specified position. |
+| NEED_PROMOTION        | 4     | Target piece for promotion is missing.      |
+| PIECE_PINNED          | 5     | Piece cannot move because it is pinned.     |
+| KING_IN_CHECK         | 6     | The move would leave the king in check.     |
+| KING_MOVES_INTO_CHECK | 7     | The king would be moved into check.         |
+| MISSING_CHECK         | 8     | The check-flag was not set.                 |
+| MISSING_CHECKMATE     | 9     | The checkmate-flag is not set.              |
+| INVALID_CHECK         | 10    | The check-flag was incorrectly set.         |
+| INVALID_CHECKMATE     | 11    | The checkmate-flag was incorrectly set.     |
+| RULES_VIOLATED        | 32    | Other rules would be violated by this move. |
+
+### End the Game
+
+The active player, before making a move, SHALL determine if the game has ended.
+The game SHALL be ended if a [checkmate](#checkmate) or [stalemate](#stalemate)
+position has been reached, or the [clock runs out](#clock-timeout).
+
+The game SHOULD be ended if a draw can be [claimed](#claim-a-draw) due to a
+threefold repetition of the same position, insufficient material, or playing
+50 moves without any captures or pawn moves.
+
+The game MAY be ended at any time by any (including the waiting) player by
+[resignation](#resign).
+
+#### Checkmate
+
+Whe the active player determines they were checkmated with the last move,
+they SHALL send a `CHECKMATE` message to the waiting player.
+When receiving such a message, the waiting player SHALL end the game without
+sending any confirmation.
+
+#### Stalemate
 
-### Offer or Claim a Draw
+When the active player determines a stalemate position, they SHALL send a
+`STALEMATE` message to the waiting player.
+The waiting player SHOULD verify this claim.
+When verification fails, they SHALL send a `DECLINE` message, and they SHALL
+send an `ACCEPT` message, otherwise.
+
+Both parties SHALL end the game when the stalemate was agreed on.
+Otherwise, both parties SHOULD continue playing.
+
+#### Clock Timeout
+
+When the clock of the active player times out, they SHALL send a `TIMEOVER`
+message to the waiting player.
+When receiving such a message, the waiting player SHALL end the game without
+sending any confirmation.
+
+#### Claim a Draw
+
+The active player SHOULD claim a draw, when
+* the position is already repeated a third time (threefold repetition rule)
+* there is not enough material for both players on the board (nobody can win)
+* no capture or pawn move was made within the last 50 moves
+
+The draw is claimed by sending a `THREEFOLD`, `NOMATERIAL`, or `50MOVES`
+message, respectively.
+The waiting player SHOULD verify this claim.
+When verification fails, they SHALL send a `DECLINE` message, and they SHALL
+send an `ACCEPT` message, otherwise.
+
+Both parties SHALL end the game when the draw was agreed on.
+Otherwise, both parties SHOULD continue playing.
+
+#### Resign
+
+Both the active and the waiting player MAY send a `RESIGN` message any time.
+When a player receives a `RESIGN` message, they SHALL end the game without
+any further confirmation.
+
+### Offer a Draw
+
+_TODO: draw offers by the active player are bugged - see issue #980_
+
+_TODO: the description is very confusing and should be cleaned up after fixing issue #980_
+
+Both the active and the waiting player MAY send a `REMIS` message any time to
+offer a draw.
+
+When the waiting player receives such an offer, they MAY choose to answer it
+with either an `ACCEPT` or a `DECLINE` message.
+
+When the offer was accepted, both players SHALL end the game.
+Otherwise, they SHALL continue playing.
+When an offer was declined, the requesting player SHOULD NOT send another offer
+for the same position.
+
+When the active player receives such an offer, they MAY ignore it.
+No confirmation is sent.
+Instead, if the player chooses to accept the offer, they SHALL send a `REMIS`
+message on their own.
 
 ### Propose Resignation
 
+The waiting player MAY propose resignation by sending a `TAUNT` message.
+
+The active player MAY ignore such messages completely.
+Implementations MAY choose to display a message to the active player.
+If the active player decides to follow the proposal, they SHOULD send a
+`RESIGN` message, as described [above](#resign).
+
+The waiting player SHOULD NOT use this message excessively or inappropriately.
+It serves to inform the opponent about a decisive position and is intended to
+encourage them to resign a lost game so that both players can make better use
+of their time. 
+
 ## Message Code Table
 
 The following table shows the definitions of the network codes.
 
-| Code Name            | Byte | With Payload |
-|----------------------|------|--------------|
-| NETCODE_ACCEPT       | 0x02 | no           |
-| NETCODE_DECLINE      | 0x04 | no           |
-| NETCODE_DECLINE_MOVE | 0x05 | yes          |
-| NETCODE_GAMEINFO     | 0x10 | yes          |
-| NETCODE_PGNDATA      | 0x11 | yes          |
-| NETCODE_MOVE         | 0x20 | yes          |
-| NETCODE_CHECKMATE    | 0x23 | no           |
-| NETCODE_STALEMATE    | 0x28 | no           |
-| NETCODE_NOMATERIAL   | 0x29 | no           |
-| NETCODE_THREEFOLD    | 0x30 | no           |
-| NETCODE_RESIGN       | 0x41 | no           |
-| NETCODE_REMIS        | 0x42 | no           |
-| NETCODE_TAUNT        | 0x43 | no           |
-| NETCODE_TIMEOVER     | 0x44 | no           |
+| Code Name    | Byte | With Payload |
+|--------------|------|--------------|
+| ACCEPT       | 0x01 | no           |
+| DECLINE      | 0x02 | no           |
+| GAMEINFO     | 0x10 | yes          |
+| PGNDATA      | 0x11 | yes          |
+| MOVE         | 0x20 | yes          |
+| ACCEPT_MOVE  | 0x21 | no           |
+| DECLINE_MOVE | 0x22 | yes          |
+| CHECKMATE    | 0x30 | no           |
+| STALEMATE    | 0x31 | no           |
+| NOMATERIAL   | 0x32 | no           |
+| THREEFOLD    | 0x33 | no           |
+| 50MOVES      | 0x34 | no           |
+| RESIGN       | 0x41 | no           |
+| REMIS        | 0x42 | no           |
+| TAUNT        | 0x43 | no           |
+| TIMEOVER     | 0x44 | no           |
 
 The following codes are reserved for implementation.
 They are not used during transmissions and can be used as return values
 for functions to indicate errors.
 
-| Code Name            | Byte |
-|----------------------|------|
-| NETCODE_AGAIN        | 0x70 | 
-| NETCODE_CONNLOST     | 0x80 |
-| NETCODE_ERROR        | 0xFF |
+| Code Name | Byte |
+|-----------|------|
+| AGAIN     | 0x70 | 
+| CONNLOST  | 0x80 |
+| ERROR     | 0xFF |
 
 
--- a/src/main.c	Mon Aug 24 14:43:33 2026 +0200
+++ b/src/main.c	Mon Aug 24 15:48:19 2026 +0200
@@ -793,14 +793,14 @@
             }
             break;
         /* validate "the game has ended" claims */
+        case NETCODE_CHECKMATE:
+            return 1; /* no need to accept, they say they're toast, OK for us */
         case NETCODE_THREEFOLD:
         case NETCODE_NOMATERIAL:
         case NETCODE_STALEMATE:
-        case NETCODE_CHECKMATE:
             if ((code == NETCODE_THREEFOLD && gamestate->threefold) ||
                 (code == NETCODE_NOMATERIAL && gamestate->nomaterial) ||
-                (code == NETCODE_STALEMATE && gamestate->stalemate) ||
-                (code == NETCODE_CHECKMATE && gamestate->checkmate)) {
+                (code == NETCODE_STALEMATE && gamestate->stalemate)) {
                 /* auto-accept the claim */
                 net_send_code(opponent, NETCODE_ACCEPT);
                 return 1;
@@ -823,6 +823,8 @@
                 bool endgame = true;
                 if (gamestate->checkmate) {
                     net_send_code(opponent, NETCODE_CHECKMATE);
+                    /* checkmate does not need to be accepted */
+                    return 1;
                 } else if (gamestate->stalemate) {
                     net_send_code(opponent, NETCODE_STALEMATE);
                 } else if (gamestate->nomaterial) {
--- a/src/network.h	Mon Aug 24 14:43:33 2026 +0200
+++ b/src/network.h	Mon Aug 24 15:48:19 2026 +0200
@@ -48,6 +48,7 @@
 #define NETCODE_STALEMATE 0x31
 #define NETCODE_NOMATERIAL 0x32
 #define NETCODE_THREEFOLD 0x33
+#define NETCODE_50MOVES 0x34
 #define NETCODE_RESIGN 0x41
 #define NETCODE_REMIS 0x42
 #define NETCODE_TAUNT 0x43

mercurial