Allow two-games-per-opening to work with book
authorH.G. Muller <h.g.muller@hccnet.nl>
Thu, 18 Aug 2011 16:53:09 +0000 (18:53 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Fri, 19 Aug 2011 18:04:32 +0000 (20:04 +0200)
A new option -seedBase is added, and written to the tourney file.
It allows all XBoard instances working on a tourney to generate the same
'random' openings in a deterministic way, based on this one-time seed
and the game number. When -loadGameIndex equals -2, it uses the same seed
for an odd and the following even game.

args.h
backend.c
common.h
winboard/wsettings.c

diff --git a/args.h b/args.h
index 32350ba..bbdaeeb 100644 (file)
--- a/args.h
+++ b/args.h
@@ -577,6 +577,7 @@ ArgDescriptor argDescriptors[] = {
   { "results", ArgString, (void *) &appData.results, FALSE, (ArgIniType) "" },
   { "syncAfterRound", ArgBoolean, (void *) &appData.roundSync, FALSE, (ArgIniType) FALSE },
   { "syncAfterCycle", ArgBoolean, (void *) &appData.cycleSync, FALSE, (ArgIniType) TRUE },
   { "results", ArgString, (void *) &appData.results, FALSE, (ArgIniType) "" },
   { "syncAfterRound", ArgBoolean, (void *) &appData.roundSync, FALSE, (ArgIniType) FALSE },
   { "syncAfterCycle", ArgBoolean, (void *) &appData.cycleSync, FALSE, (ArgIniType) TRUE },
+  { "seedBase", ArgInt, (void *) &appData.seedBase, FALSE, (ArgIniType) 1 },
 
   /* [HGM] board-size, adjudication and misc. options */
   { "oneClickMove", ArgBoolean, (void *) &appData.oneClick, TRUE, (ArgIniType) FALSE },
 
   /* [HGM] board-size, adjudication and misc. options */
   { "oneClickMove", ArgBoolean, (void *) &appData.oneClick, TRUE, (ArgIniType) FALSE },
index 05ce951..26ebe3c 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -981,6 +981,7 @@ InitBackEnd1()
 
     GetTimeMark(&programStartTime);
     srandom((programStartTime.ms + 1000*programStartTime.sec)*0x1001001); // [HGM] book: makes sure random is unpredictabe to msec level
 
     GetTimeMark(&programStartTime);
     srandom((programStartTime.ms + 1000*programStartTime.sec)*0x1001001); // [HGM] book: makes sure random is unpredictabe to msec level
+    appData.seedBase = random() + (random()<<15);
     pauseStart = programStartTime; pauseStart.sec -= 100; // [HGM] matchpause: fake a pause that has long since ended
 
     ClearProgramStats();
     pauseStart = programStartTime; pauseStart.sec -= 100; // [HGM] matchpause: fake a pause that has long since ended
 
     ClearProgramStats();
@@ -9726,6 +9727,7 @@ WriteTourneyFile(char *results, FILE *f)
     if(f == NULL) DisplayError(_("Could not write on tourney file"), 0); else {
        // create a file with tournament description
        fprintf(f, "-participants {%s}\n", appData.participants);
     if(f == NULL) DisplayError(_("Could not write on tourney file"), 0); else {
        // create a file with tournament description
        fprintf(f, "-participants {%s}\n", appData.participants);
+       fprintf(f, "-seedBase %d\n", appData.seedBase);
        fprintf(f, "-tourneyType %d\n", appData.tourneyType);
        fprintf(f, "-tourneyCycles %d\n", appData.tourneyCycles);
        fprintf(f, "-defaultMatchGames %d\n", appData.defaultMatchGames);
        fprintf(f, "-tourneyType %d\n", appData.tourneyType);
        fprintf(f, "-tourneyCycles %d\n", appData.tourneyCycles);
        fprintf(f, "-defaultMatchGames %d\n", appData.defaultMatchGames);
@@ -10026,6 +10028,7 @@ NextMatchGame()
     first.twoMachinesColor =  firstWhite ? "white\n" : "black\n";   // perform actual color assignement
     second.twoMachinesColor = firstWhite ? "black\n" : "white\n";
     appData.noChessProgram = (first.pr == NoProc); // kludge to prevent Reset from starting up chess program
     first.twoMachinesColor =  firstWhite ? "white\n" : "black\n";   // perform actual color assignement
     second.twoMachinesColor = firstWhite ? "black\n" : "white\n";
     appData.noChessProgram = (first.pr == NoProc); // kludge to prevent Reset from starting up chess program
+    if(appData.loadGameIndex == -2) srandom(appData.seedBase + 68163*(nextGame & ~1)); // deterministic seed to force same opening
     Reset(FALSE, first.pr != NoProc);
     appData.noChessProgram = FALSE;
     if(!LoadGameOrPosition(matchGame)) return; // setup game; abort when bad game/pos file
     Reset(FALSE, first.pr != NoProc);
     appData.noChessProgram = FALSE;
     if(!LoadGameOrPosition(matchGame)) return; // setup game; abort when bad game/pos file
index 5f8f5f1..b45fcf1 100644 (file)
--- a/common.h
+++ b/common.h
@@ -669,6 +669,7 @@ typedef struct {
     char *participants;
     int tourneyType;
     int tourneyCycles;
     char *participants;
     int tourneyType;
     int tourneyCycles;
+    int seedBase;
     Boolean roundSync;
     Boolean cycleSync;
 } AppData, *AppDataPtr;
     Boolean roundSync;
     Boolean cycleSync;
 } AppData, *AppDataPtr;
index bfad588..6fc5c40 100644 (file)
@@ -694,6 +694,7 @@ char *tfName;
 int MatchOK()\r
 {\r
     if(autoinc) appData.loadGameIndex = appData.loadPositionIndex = -(twice + 1);\r
 int MatchOK()\r
 {\r
     if(autoinc) appData.loadGameIndex = appData.loadPositionIndex = -(twice + 1);\r
+    if(!appData.loadGameFile[0]) appData.loadGameIndex = -2*twice; // kludge to pass value of "twice" for use in GUI book\r
     if(swiss) { appData.defaultMatchGames = 1; appData.tourneyType = -1; }\r
     if(CreateTourney(tfName) && !matchMode) { // CreateTourney reloads original settings if file already existed\r
        MatchEvent(2);\r
     if(swiss) { appData.defaultMatchGames = 1; appData.tourneyType = -1; }\r
     if(CreateTourney(tfName) && !matchMode) { // CreateTourney reloads original settings if file already existed\r
        MatchEvent(2);\r
@@ -771,7 +772,7 @@ void TourneyPopup(HWND hwnd)
     NamesToList(firstChessProgramNames, engineList, engineMnemonic);\r
     comboCallback = &AddToTourney;\r
     autoinc = appData.loadGameIndex < 0 || appData.loadPositionIndex < 0;\r
     NamesToList(firstChessProgramNames, engineList, engineMnemonic);\r
     comboCallback = &AddToTourney;\r
     autoinc = appData.loadGameIndex < 0 || appData.loadPositionIndex < 0;\r
-    twice = TRUE; swiss = appData.tourneyType < 0;\r
+    twice = FALSE; swiss = appData.tourneyType < 0;\r
     while(engineList[n]) n++; tourneyOptions[3].max = n-1;\r
     snprintf(title, MSG_SIZ, _("Tournament and Match Options"));\r
     ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));\r
     while(engineList[n]) n++; tourneyOptions[3].max = n-1;\r
     snprintf(title, MSG_SIZ, _("Tournament and Match Options"));\r
     ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));\r