fix wrong game state when the waiting player resigns default tip

Fri, 22 May 2026 18:34:02 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 22 May 2026 18:34:02 +0200
changeset 126
d58b2abdd330
parent 125
e195652038e0

fix wrong game state when the waiting player resigns

fixes #844

src/chess/game-info.h file | annotate | diff | comparison | revisions
src/chess/pgn.c file | annotate | diff | comparison | revisions
src/game.c file | annotate | diff | comparison | revisions
--- a/src/chess/game-info.h	Wed May 20 15:52:17 2026 +0200
+++ b/src/chess/game-info.h	Fri May 22 18:34:02 2026 +0200
@@ -100,7 +100,8 @@
     bool checkmate;
     bool stalemate;
     bool remis;
-    bool resign;
+    bool wresign;
+    bool bresign;
     /** this flag is only supposed to be set when the opponent disconnects */
     bool ragequit;
     bool review;
@@ -108,8 +109,8 @@
 
 
 #define is_game_running(gamestate) !((gamestate)->checkmate || \
-    (gamestate)->resign || (gamestate)->stalemate || (gamestate)->remis || \
-    (gamestate)->review)
+    (gamestate)->wresign || (gamestate)->bresign || \
+    (gamestate)->stalemate || (gamestate)->remis || (gamestate)->review)
 
 #define last_move(gamestate) \
     ((gamestate)->moves[(gamestate)->movecount-1])
--- a/src/chess/pgn.c	Wed May 20 15:52:17 2026 +0200
+++ b/src/chess/pgn.c	Fri May 22 18:34:02 2026 +0200
@@ -41,7 +41,8 @@
     pgn_error_missing_brace,
     pgn_error_missing_dot,
     pgn_error_move_syntax,
-    pgn_error_move_semantics
+    pgn_error_move_semantics,
+    pgn_error_result_syntax,
 };
 
 static const char* pgn_error_strings[] = {
@@ -51,7 +52,8 @@
     "Tags must be enclosed in square brackets: '[Key \"Value\"]'.",
     "Move numbers must be terminated with a dot (e.g. '13.' - not '13').",
     "Move is syntactically incorrect.",
-    "Move is not valid according to chess rules."
+    "Move is not valid according to chess rules.",
+    "Result syntax is incorrect. Expected 1-0, 0-1, 1/2-1/2, or *.",
 };
 
 const char* pgn_error_str(int code) {
@@ -97,7 +99,9 @@
             return pgn_error_missing_bracket;
         }
 
+        // TODO: read clock info
         if (strcmp("Result", tagkey) == 0) {
+            // TODO: why are we parsing this? it is never used!
             memcpy(result, tagvalue, 8);
         }
     }
@@ -153,8 +157,20 @@
         }
         if (c == '1' || c == '0') {
             c = fgetc(stream);
+            // TODO: #842 - allow games to be continued if possible
             if (c == '-') {
-                gamestate->resign = !gamestate->checkmate;
+                if (!gamestate->checkmate) {
+                    // TODO: maybe we should not parse this here;
+                    //       there is an unused result string from the STR
+                    c = fgetc(stream);
+                    if (c == '1') {
+                        gamestate->wresign = true;
+                    } else if (c == '0') {
+                        gamestate->bresign = true;
+                    } else {
+                        return pgn_error_result_syntax;
+                    }
+                }
                 break;
             } else if (c == '/') {
                 gamestate->remis = !gamestate->stalemate;
@@ -248,7 +264,11 @@
     char *result;
     if (gamestate->stalemate || gamestate->remis) {
         result = "1/2-1/2";
-    } else if (gamestate->checkmate || gamestate->resign) {
+    } else if (gamestate->wresign) {
+        result = "0-1";
+    } else if (gamestate->bresign) {
+        result = "1-0";
+    } else if (gamestate->checkmate) {
         if (gamestate->movecount > 0) {
             result = (last_move(gamestate).piece & COLOR_MASK) == WHITE ?
                 "1-0" : "0-1";
@@ -259,6 +279,8 @@
         result = "*";
     }
     fprintf(stream, "[Result \"%s\"]\n\n", result);
+
+    // TODO: add optional clock info
     
     /* moves */
     size_t moveblkcap = 4096;
--- a/src/game.c	Wed May 20 15:52:17 2026 +0200
+++ b/src/game.c	Fri May 22 18:34:02 2026 +0200
@@ -224,7 +224,11 @@
         
         if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) {
             if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) {
-                gamestate->resign = true;
+                if (curcolor == WHITE) {
+                    gamestate->wresign = true;
+                } else {
+                    gamestate->bresign = true;
+                }
                 return 1;
             } else if (strncmp(movestr, "remis", MOVESTR_BUFLEN) == 0) {
                 gamestate->remis = true;
@@ -311,7 +315,11 @@
                 resign_suggested = true;
                 break;
             case NETCODE_RESIGN:
-                gamestate->resign = true;
+                if (mycolor == WHITE) {
+                    gamestate->bresign = true;
+                } else {
+                    gamestate->wresign = true;
+                }
                 return 1;
             case NETCODE_CONNLOST:
                 gamestate->ragequit = true;
@@ -332,7 +340,11 @@
             bool was_premove = use_premove;
             use_premove = false;
             if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) {
-                gamestate->resign = true;
+                if (mycolor == WHITE) {
+                    gamestate->wresign = true;
+                } else {
+                    gamestate->bresign = true;
+                }
                 net_send_code(opponent, NETCODE_RESIGN);
                 return 1;
             } else if (strncmp(movestr, "savepgn", MOVESTR_BUFLEN) == 0) {
@@ -436,7 +448,11 @@
         /* allow the player to prepare a move */
         if (asyncgetnstr(movestr, &bufpos, MOVESTR_BUFLEN)) {
             if (strncmp(movestr, "resign", MOVESTR_BUFLEN) == 0) {
-                gamestate->resign = true;
+                if (mycolor == WHITE) {
+                    gamestate->wresign = true;
+                } else {
+                    gamestate->bresign = true;
+                }
                 net_send_code(opponent, NETCODE_RESIGN);
                 return 1;
             } else if (strncmp(movestr, "taunt", MOVESTR_BUFLEN) == 0) {
@@ -470,7 +486,11 @@
             timecontrol(gamestate, gameinfo);
             return 1;
         case NETCODE_RESIGN:
-            gamestate->resign = true;
+            if (mycolor == WHITE) {
+                gamestate->bresign = true;
+            } else {
+                gamestate->wresign = true;
+            }
             return 1;
         case NETCODE_CONNLOST:
             gamestate->ragequit = true;
@@ -547,16 +567,17 @@
             timecontrol(&viewedstate, gameinfo);
 
             move(getmaxy(stdscr)-5, 0);
-            const char *curcolorstr =
-                gamestate->movecount % 2 == 0 ? "White" : "Black";
-            if (gamestate->resign) {
-                printw("%s resigned.\n", curcolorstr);
+            if (gamestate->wresign) {
+                addstr("White resigned.\n");
+            } else if (gamestate->bresign) {
+                addstr("Black resigned.\n");
             } else if (gamestate->remis) {
                 addstr("The game ended remis.\n");
             } else if (gamestate->stalemate) {
                 addstr("The game ended in a stalemate.\n");
             } else if (gamestate->checkmate) {
-                printw("%s has lost the game.\n", curcolorstr);
+                printw("%s was checkmated.\n",
+                    gamestate->movecount % 2 == 0 ? "White" : "Black");
             } else if (gamestate->ragequit) {
                 printw("Your opponent disconnected.\n");
             }

mercurial