Start implementing EPD test suites
[xboard.git] / backend.c
index d6b293b..f1dcf5d 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5,7 +5,7 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
  *
  * Enhancements Copyright 2005 Alessandro Scotti
  *
@@ -296,6 +296,8 @@ int promoDefaultAltered;
 int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */
 static int initPing = -1;
 int border;       /* [HGM] width of board rim, needed to size seek graph  */
+char bestMove[MSG_SIZ];
+int solvingTime, totalTime;
 
 /* States for ics_getting_history */
 #define H_FALSE 0
@@ -5228,7 +5230,7 @@ SendMoveToICS (ChessMove moveType, int fromX, int fromY, int toX, int toY, char
       case WhitePromotion:
       case BlackPromotion:
         if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-           gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
+           gameInfo.variant == VariantMakruk)
          snprintf(user_move, MSG_SIZ, "%c%c%c%c=%c\n",
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
                PieceToChar(WhiteFerz));
@@ -5334,7 +5336,7 @@ UploadGameEvent ()
     SendToICS(ics_type == ICS_ICC ? "tag result Game in progress\n" : "commit\n");
 }
 
-int killX = -1, killY = -1, kill2X, kill2Y; // [HGM] lion: used for passing e.p. capture square to MakeMove
+int killX = -1, killY = -1, kill2X = -1, kill2Y = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
 int legNr = 1;
 
 void
@@ -6556,8 +6558,10 @@ DefaultPromoChoice (int white)
 {
     ChessSquare result;
     if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-       gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
+       gameInfo.variant == VariantMakruk)
        result = WhiteFerz; // no choice
+    else if(gameInfo.variant == VariantASEAN)
+       result = WhiteRook; // no choice
     else if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway)
        result= WhiteKing; // in Suicide Q is the last thing we want
     else if(gameInfo.variant == VariantSpartan)
@@ -6649,7 +6653,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i
 
     // we either have a choice what to promote to, or (in Shogi) whether to promote
     if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-       gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) {
+       gameInfo.variant == VariantMakruk) {
        ChessSquare p=BlackFerz;  // no choice
        while(p < EmptySquare) {  //but make sure we use piece that exists
            *promoChoice = PieceToChar(p++);
@@ -7361,7 +7365,7 @@ CanPromote (ChessSquare piece, int y)
        if(IS_SHOGI(gameInfo.variant)          || gameInfo.variant == VariantXiangqi ||
           gameInfo.variant == VariantSuper    || gameInfo.variant == VariantGreat   ||
           gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-         gameInfo.variant == VariantMakruk   || gameInfo.variant == VariantASEAN) return FALSE;
+         gameInfo.variant == VariantMakruk) return FALSE;
        return (piece == BlackPawn && y <= zone ||
                piece == WhitePawn && y >= BOARD_HEIGHT-1-zone ||
                piece == BlackLance && y <= zone ||
@@ -8791,6 +8795,17 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
            free(fen);
            GameEnds(GameUnfinished, NULL, GE_XBOARD);
         }
+        if(appData.epd) {
+           if(solvingTime >= 0) {
+              snprintf(buf1, MSG_SIZ, "%d. %4.2fs\n", matchGame, solvingTime/100.);
+              totalTime += solvingTime; first.matchWins++;
+           } else {
+              snprintf(buf1, MSG_SIZ, "%d. wrong (%s)\n", matchGame, parseList[backwardMostMove]);
+              second.matchWins++;
+           }
+           OutputKibitz(2, buf1);
+           GameEnds(GameUnfinished, NULL, GE_XBOARD);
+        }
 
         /* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
         if( gameMode == TwoMachinesPlay && appData.adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
@@ -9540,6 +9555,14 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
 
                if(appData.pvSAN[cps==&second]) pv = PvToSAN(buf1);
 
+               if(*bestMove) { // rememer time best EPD move was first found
+                   int ff1, tf1, fr1, tr1, ff2, tf2, fr2, tr2; char pp1, pp2;
+                   ChessMove mt;
+                   int ok = ParseOneMove(bestMove, forwardMostMove, &mt, &ff1, &fr1, &tf1, &tr1, &pp1);
+                   ok    &= ParseOneMove(pv, forwardMostMove, &mt, &ff2, &fr2, &tf2, &tr2, &pp2);
+                   solvingTime = (ok && ff1==ff2 && fr1==fr2 && tf1==tf2 && tr1==tr2 && pp1==pp2 ? time : -1);
+               }
+
                if(serverMoves && (time > 100 || time == 0 && plylev > 7)) {
                        char buf[MSG_SIZ];
                        FILE *f;
@@ -13310,10 +13333,14 @@ LoadPosition (FILE *f, int positionNumber, char *title)
     }
 
     if (fenMode) {
+       char *p;
        if (!ParseFEN(initial_position, &blackPlaysFirst, line, TRUE)) {
            DisplayError(_("Bad FEN position in file"), 0);
            return FALSE;
        }
+       if((p = strstr(line, ";")) && (p = strstr(p+1, "bm "))) { // EPD with best move
+           sscanf(p+3, "%s", bestMove);
+       } else *bestMove = NULLCHAR;
     } else {
        (void) fgets(line, MSG_SIZ, f);
        (void) fgets(line, MSG_SIZ, f);