From: H.G.Muller Date: Tue, 26 May 2020 17:23:45 +0000 (+0200) Subject: Implement feature dice X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=1744aede9487e7dab6afec43f64e752d3ef32c44;p=xboard.git Implement feature dice An engine can now request XBoard to make a 'dice roll', by sending a command "dice N", where N is the number of faces on the die. XBoard will reply to such a request with "pips K/N", where K is a random number 1...N, and N the N of the request. Multiple dice rolls can be listed in a single dice or pips command, separated by spaces. In Two Machines mode only the requests of the engine that is on move will be honored (as it is assumed that both engines would put in a request for the same dice roll), but the 'pips' reply will then be sent to both engines. (So the opponent can verify whether the opponent did not cheat by specifying wrong N or ignoring K.) When playing against a human the engine can request for both sides to make it easy for the human. The accumulated results of all rolls during the turn will be shown to the user in the title bar of the board window, to also exposes cheating by requesting until you like the result. When the user's roll is displayed, the previous series of rolls (from the engine's turn) is shown behind it in parentheses, to make sure the user gets the chance to see it when the engine moves instantly. A Boolean feature dice is added, to enable the engine to see if it is safe to send the 'dice' command (based on acceptance of the feature), and for the GUI whether it is safe to send the 'pips' to the opponent of the requestor. On rejection of the feature the engine would have to use an alternative way (either generate the randoms by itself, or use 'askuser' to request the user to roll the dice and enter the result, with no guarantees against cheating by the active party). --- diff --git a/backend.c b/backend.c index af59ce3..048fd0a 100644 --- a/backend.c +++ b/backend.c @@ -8938,7 +8938,7 @@ static int savedWhitePlayer, savedBlackPlayer, pairingReceived; static ChessProgramState *stalledEngine; static char stashedInputMove[MSG_SIZ], abortEngineThink, startPieceToChar[MSG_SIZ]; static Boolean prelude; -static char preludeText[MSG_SIZ]; +static char preludeText[MSG_SIZ], diceRoll[MSG_SIZ]; void HandleMachineMove (char *message, ChessProgramState *cps) @@ -9416,6 +9416,31 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h } return; } + if(!strncmp(message, "dice ", 5)) { // [HGM] dice: provide dice rolls + if(gameMode != TwoMachinesPlay || (cps->twoMachinesColor[0] == 'w') == WhiteOnMove(forwardMostMove)) { + static char previousRoll[MSG_SIZ]; + char buf[MSG_SIZ], *p = message + 5; + int n, k, l; + sprintf(buf, "pips"); + while(sscanf(p, "%d", &n) == 1) { + k = (random() + 256*random() & 0xFFFF)*n >> 16; + l = strlen(buf); + snprintf(buf + l, MSG_SIZ - 1 - l, " %d/%d", k+1, n); + while(*++p > ' ') {} + } + l = strlen(diceRoll); + if(l == 0) safeStrCpy(previousRoll, diceRoll+1, MSG_SIZ); // remember series from previous turn + snprintf(diceRoll + l, MSG_SIZ - l, "%s", buf + 4); // accumulate rolls for display + strcat(buf, "\n"); SendToProgram(buf, cps); + if(gameMode != TwoMachinesPlay) { + int human = (gameMode == MachinePlaysWhite) != WhiteOnMove(forwardMostMove); + if(human) snprintf(buf, MSG_SIZ, "Your dice roll:%s (mine %s)", diceRoll, previousRoll); + else snprintf(buf, MSG_SIZ, "My dice roll:%s", diceRoll); + DisplayTitle(buf); + } else if(cps->other->dice) SendToProgram(buf, cps->other); + } + return; + } /* [HGM] Allow engine to set up a position. Don't ask me why one would * want this, I was asked to put it in, and obliged. */ @@ -10852,6 +10877,7 @@ MakeMove (int fromX, int fromY, int toX, int toY, int promoChar) ChessSquare p = boards[forwardMostMove][toY][toX]; // forwardMostMove++; // [HGM] bare: moved downstream + diceRoll[0] = NULLCHAR; // [HGM] dice: consumed by this move if(kill2X >= 0) x = kill2X, y = kill2Y; else if(killX >= 0 && killY >= 0) x = killX, y = killY; // [HGM] lion: make SAN move to intermediate square, if there is one (void) CoordsToAlgebraic(boards[forwardMostMove], @@ -12373,6 +12399,7 @@ Reset (int redraw, int init) second.maybeThinking = FALSE; first.bookSuspend = FALSE; // [HGM] book second.bookSuspend = FALSE; + diceRoll[0] = NULLCHAR; thinkOutput[0] = NULLCHAR; lastHint[0] = NULLCHAR; hintSrc = 0; ClearGameInfo(&gameInfo); @@ -17696,6 +17723,7 @@ ParseFeatures (char *args, ChessProgramState *cps) if (BoolFeature(&p, "exclude", &cps->excludeMoves, cps)) continue; if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue; if (BoolFeature(&p, "name", &cps->sendName, cps)) continue; + if (BoolFeature(&p, "dice", &cps->dice, cps)) continue; // [HGM] dice if (BoolFeature(&p, "pause", &cps->pause, cps)) continue; // [HGM] pause if (IntFeature(&p, "done", &val, cps)) { FeatureDone(cps, val); diff --git a/backend.h b/backend.h index d9392c4..738947d 100644 --- a/backend.h +++ b/backend.h @@ -376,6 +376,7 @@ typedef struct XB_CPS { char *egtFormats; /* [HGM] EGT: supported tablebase formats */ int bookSuspend; /* [HGM] book: go was deferred because of book hit */ int pause; /* [HGM] pause: 1=supports it, 2=actually paused */ + int dice; /* [HGM] dice: engine understands pips command */ int highlight; /* [HGM] engine wants to get lift and put commands */ int nrOptions; /* [HGM] options: remembered option="..." features */ #define MAX_OPTIONS 200