bug-xboard
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Add an option to notify the user when a draw is eligible


From: Asher Gordon
Subject: [PATCH] Add an option to notify the user when a draw is eligible
Date: Wed, 09 Sep 2020 01:31:51 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux)

Hello,

I've written a patch to add an option to notify the user when a draw is
eligible. This can be useful, for example, when playing on an ICS and
you want to claim a draw. (I asked on FICS, and MoosMutz said that he
didn't think that this would be cheating. Although someone else then
said that he would consider it cheating. But then, he implied that he
thought that time increments shouldn't be allowed either, so...)

Here is the patch below. I haven't tested it much, so beware. Also, I
didn't include the full changes to po/xboard.pot and po/*.po, because
they are very large. But after applying my patch, you should be able to
do 'cd po && make update-po' to get the appropriate changes.
From 04be330e3b1302b4860eb18fd80efd5f9e45662a Mon Sep 17 00:00:00 2001
From: Asher Gordon <AsDaGo@posteo.net>
Date: Wed, 9 Sep 2020 01:20:08 -0400
Subject: [PATCH] Add an option to notify the user when a draw is eligible

---
 args.h        |  1 +
 backend.c     | 58 ++++++++++++++++++++++++++++++++++-----------------
 common.h      |  1 +
 dialogs.c     |  1 +
 po/xboard.pot |  6 +++++-
 xboard.texi   |  4 ++++
 6 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/args.h b/args.h
index f23f1ab0..7265a176 100644
--- a/args.h
+++ b/args.h
@@ -658,6 +658,7 @@ ArgDescriptor argDescriptors[] = {
   { "trivialDraws", ArgBoolean, (void *) &appData.trivialDraws, TRUE, 
(ArgIniType) FALSE },
   { "ruleMoves", ArgInt, (void *) &appData.ruleMoves, TRUE, (ArgIniType) 51 },
   { "repeatsToDraw", ArgInt, (void *) &appData.drawRepeats, TRUE, (ArgIniType) 
6 },
+  { "notifyDraws", ArgBoolean, (void *) &appData.notifyDraws, TRUE, 
(ArgIniType) TRUE },
   { "backgroundObserve", ArgBoolean, (void *) &appData.bgObserve, TRUE, 
(ArgIniType) FALSE },
   { "dualBoard", ArgBoolean, (void *) &appData.dualBoard, TRUE, (ArgIniType) 
FALSE },
   { "autoKibitz", ArgTrue, (void *) &appData.autoKibitz, FALSE, INVALID },
diff --git a/backend.c b/backend.c
index 776f7516..d3761ef4 100644
--- a/backend.c
+++ b/backend.c
@@ -299,6 +299,7 @@ static int initPing = -1;
 int border;       /* [HGM] width of board rim, needed to size seek graph  */
 char bestMove[MSG_SIZ], avoidMove[MSG_SIZ];
 int solvingTime, totalTime;
+char *eligibleDraw;
 
 /* States for ics_getting_history */
 #define H_FALSE 0
@@ -8281,6 +8282,8 @@ Adjudicate (ChessProgramState *cps)
        int k, drop, count = 0; static int bare = 1;
        ChessProgramState *engineOpponent = (gameMode == TwoMachinesPlay ? 
cps->other : (cps ? NULL : &first));
        Boolean canAdjudicate = !appData.icsActive;
+        char *reason;
+        int ret;
 
        // most tests only when we understand the game, i.e. legality-checking 
on
            if( appData.testLegality )
@@ -8288,7 +8291,8 @@ Adjudicate (ChessProgramState *cps)
                int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+2], i;
                static int moveCount = 6;
                ChessMove result;
-               char *reason = NULL;
+
+                reason = NULL;
 
                 /* Count what is on board. */
                Count(boards[forwardMostMove], nr, &nrW, &nrB, &staleW, 
&staleB, &bishopColor);
@@ -8556,27 +8560,34 @@ Adjudicate (ChessProgramState *cps)
                          return 1;
                 }
 
+                /* Check for draws. */
+                reason = NULL;
+                if((signed char)boards[forwardMostMove][EP_STATUS] == 
EP_RULE_DRAW)
+                    reason = "50-move rule";
+                if((signed char)boards[forwardMostMove][EP_STATUS] == 
EP_REP_DRAW)
+                    reason = "3-fold repetition";
+                if((signed char)boards[forwardMostMove][EP_STATUS] == 
EP_INSUF_DRAW)
+                    reason = "insufficient mating material";
+
                 /* if draw offer is pending, treat it as a draw claim
                  * when draw condition present, to allow engines a way to
                  * claim draws before making their move to avoid a race
                  * condition occurring after their move
                  */
-               if((gameMode == TwoMachinesPlay ? second.offeredDraw : 
userOfferedDraw) || first.offeredDraw ) {
-                         char *p = NULL;
-                         if((signed char)boards[forwardMostMove][EP_STATUS] == 
EP_RULE_DRAW)
-                             p = "Draw claim: 50-move rule";
-                         if((signed char)boards[forwardMostMove][EP_STATUS] == 
EP_REP_DRAW)
-                             p = "Draw claim: 3-fold repetition";
-                         if((signed char)boards[forwardMostMove][EP_STATUS] == 
EP_INSUF_DRAW)
-                             p = "Draw claim: insufficient mating material";
-                         if( p != NULL && canAdjudicate) {
-                            if(engineOpponent) {
-                              SendToProgram("force\n", engineOpponent); // 
suppress reply
-                              SendMoveToProgram(forwardMostMove-1, 
engineOpponent); /* make sure opponent gets to see move */
-                            }
-                             GameEnds( GameIsDrawn, p, GE_XBOARD );
-                             return 1;
-                         }
+                if(((gameMode == TwoMachinesPlay ? second.offeredDraw : 
userOfferedDraw) || first.offeredDraw) && reason != NULL && canAdjudicate) {
+                    char buf[64];
+                    if(engineOpponent) {
+                      SendToProgram("force\n", engineOpponent); // suppress 
reply
+                      SendMoveToProgram(forwardMostMove-1, engineOpponent); /* 
make sure opponent gets to see move */
+                    }
+                    ret = snprintf(buf, sizeof(buf), "Draw claim: %s", reason);
+                    GameEnds( GameIsDrawn, buf, GE_XBOARD );
+                    return 1;
+                }
+
+                if(appData.notifyDraws && reason != NULL) {
+                    /* Let the user know that a draw is eligible. */
+                    eligibleDraw = reason;
                 }
 
                if( canAdjudicate && appData.adjudicateDrawMoves > 0 && 
forwardMostMove > (2*appData.adjudicateDrawMoves) ) {
@@ -17538,6 +17549,7 @@ DisplayMove (int moveNumber)
     char message[MSG_SIZ];
     char res[MSG_SIZ];
     char cpThinkOutput[MSG_SIZ];
+    char extMessage[MSG_SIZ];
 
     if(appData.noGUI) return; // [HGM] fast: suppress display of moves
 
@@ -17579,13 +17591,21 @@ DisplayMove (int moveNumber)
        res[0] = NULLCHAR;
     }
 
+    if (eligibleDraw == NULL) {
+        strncpy(extMessage, cpThinkOutput, MSG_SIZ - 1);
+        extMessage[MSG_SIZ - 1] = NULLCHAR;
+    } else {
+        snprintf(extMessage, MSG_SIZ, "Draw eligible: %s  %s", eligibleDraw, 
cpThinkOutput);
+        eligibleDraw = NULL;
+    }
+
     if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) {
-       DisplayMessage(res, cpThinkOutput);
+       DisplayMessage(res, extMessage);
     } else {
       snprintf(message, MSG_SIZ, "%d.%s%s%s", moveNumber / 2 + 1,
                WhiteOnMove(moveNumber) ? " " : ".. ",
                parseList[moveNumber], res);
-       DisplayMessage(message, cpThinkOutput);
+       DisplayMessage(message, extMessage);
     }
 }
 
diff --git a/common.h b/common.h
index 9a4c2c4a..9424e6fe 100644
--- a/common.h
+++ b/common.h
@@ -720,6 +720,7 @@ typedef struct {
     Boolean trivialDraws;
     int ruleMoves;
     int drawRepeats;
+    Boolean notifyDraws;
 
 #if ZIPPY
     char *zippyLines;
diff --git a/dialogs.c b/dialogs.c
index af11b492..f384cad4 100644
--- a/dialogs.c
+++ b/dialogs.c
@@ -419,6 +419,7 @@ static Option generalOptions[] = {
 { 0,  0, 0, NULL, (void*) &appData.hideThinkingFromHuman, "", NULL, CheckBox, 
N_("Hide Thinking from Human") },
 { 0,  0, 0, NULL, (void*) &appData.highlightLastMove, "", NULL, CheckBox, 
N_("Highlight Last Move") },
 { 0,  0, 0, NULL, (void*) &appData.highlightMoveWithArrow, "", NULL, CheckBox, 
N_("Highlight with Arrow") },
+{ 0,  0, 0, NULL, (void*) &appData.notifyDraws, "", NULL, CheckBox, N_("Notify 
Eligible Draws") },
 { 0,  0, 0, NULL, (void*) &appData.oneClick, "", NULL, CheckBox, N_("One-Click 
Moving") },
 { 0,  0, 0, NULL, (void*) &appData.periodicUpdates, "", NULL, CheckBox, 
N_("Periodic Updates (in Analysis Mode)") },
 { 0, SAME_ROW, 0, NULL, NULL, NULL, NULL, Break, "" },
diff --git a/po/xboard.pot b/po/xboard.pot
index d683c4b6..3bcdb1f1 100644
--- a/po/xboard.pot
+++ b/po/xboard.pot
@@ -1012,7 +1012,11 @@ msgstr ""
 msgid "Highlight with Arrow"
 msgstr ""
 
-#: dialogs.c:422 menus.c:764
+#: dialogs.c:422
+msgid "Notify Eligible Draws"
+msgstr ""
+
+#: dialogs.c:423 menus.c:764
 msgid "One-Click Moving"
 msgstr ""
 
diff --git a/xboard.texi b/xboard.texi
index 81c46ae0..f18c110d 100644
--- a/xboard.texi
+++ b/xboard.texi
@@ -1550,6 +1550,10 @@ be unmade are highlighted.
 Causes the highlighting described in Highlight Last Move to be done
 by drawing an arrow between the highlighted squares,
 so that it is visible even when the width of the grid lines is set to zero.
+@item Notify Eligible Draws
+@cindex Notify Eligible Draws, Menu Item
+Display a message when a draw is eligible to be claimed, either by the
+50-move rule, 3-fold repetition, or insufficient mating material.
 @item One-Click Moving
 @cindex One-Click Moving, Menu Item
 If this option is on, XBoard does not wait for you to click both the
-- 
2.28.0

Unfortunately, I cannot update the translations since I only know
English.

Thanks,
Asher

-- 
The marvels of today's modern technology include the development of a
soda can, when discarded will last forever ... and a $7,000 car which
when properly cared for will rust out in two or three years.
                               --------
I prefer to send and receive mail encrypted. Please send me your
public key, and if you do not have my public key, please let me
know. Thanks.

GPG fingerprint: 38F3 975C D173 4037 B397  8095 D4C9 C4FC 5460 8E68

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]