Extend legality testing to drop moves
[xboard.git] / parser.l
old mode 100755 (executable)
new mode 100644 (file)
index 7e77c88..9590fe2
--- a/parser.l
+++ b/parser.l
@@ -232,7 +232,7 @@ extern void CopyBoard P((Board to, Board from));
        currentMoveString[2] - AAA >= BOARD_RGHT   ||\r
        currentMoveString[0] - AAA <  BOARD_LEFT   ||\r
        currentMoveString[2] - AAA <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
     piece = boards[yyboardindex]\r
       [currentMoveString[1] - ONE][currentMoveString[0] - AAA];\r
@@ -244,8 +244,6 @@ extern void CopyBoard P((Board to, Board from));
 \r
     result = LegalityTest(boards[yyboardindex],\r
                          PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: might think we can e.p.!\r
-                         EP_UNKNOWN,\r
-                          initialRights, /* [HGM] assume all castlings allowed */\r
                           currentMoveString[1] - ONE,\r
                           currentMoveString[0] - AAA,\r
                           currentMoveString[3] - ONE,\r
@@ -302,34 +300,91 @@ extern void CopyBoard P((Board to, Board from));
        currentMoveString[2] - AAA >= BOARD_RGHT   ||\r
        currentMoveString[0] - AAA <  BOARD_LEFT   ||\r
        currentMoveString[2] - AAA <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
     result = LegalityTest(boards[yyboardindex],\r
                          PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: might think we can e.p.!\r
-                         EP_UNKNOWN,\r
-                          initialRights, /* [HGM] assume all castlings allowed */\r
                           currentMoveString[1] - ONE,\r
                           currentMoveString[0] - AAA,\r
                           currentMoveString[3] - ONE,\r
                           currentMoveString[2] - AAA,\r
                          currentMoveString[4]);\r
 \r
+    if (currentMoveString[4] == NULLCHAR) {
+      if(result == WhitePromotionKnight || result == BlackPromotionKnight ||
+         result == WhitePromotionQueen  || result == BlackPromotionQueen) {
+        if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
+            currentMoveString[4] = PieceToChar(BlackFerz);
+        else if(gameInfo.variant == VariantGreat)
+            currentMoveString[4] = PieceToChar(BlackMan);
+        else
+            currentMoveString[4] = PieceToChar(BlackQueen);
+       currentMoveString[5] = NULLCHAR;
+      }
+    } else if(appData.testLegality && // strip off unnecessary and false promo characters
+       !(result == WhitePromotionQueen  || result == BlackPromotionQueen ||
+         result == WhiteNonPromotion    || result == BlackNonPromotion)) currentMoveString[4] = NULLCHAR;
+
+    return (int) result;
+}
+
+[A-L][0-9][xX:-]?[A-L][0-9]      {
+    /*
+     * Simple algebraic move, in capitals
+     * [HGM] Engine moves are received in this format, with lower-case promoChar!
+     */
+    int skip = 0;
+    ChessMove result;
+
+    if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
+
+    /* remove the [xX:-] */
+    if ((yytext[2] == 'x') || (yytext[2] == 'X') ||
+       (yytext[2] == '-') || (yytext[2] == ':')) skip = 1;
+
+    currentMoveString[0] = yytext[0]+32;
+    currentMoveString[1] = yytext[1];
+    currentMoveString[2] = yytext[2+skip]+32;
+    currentMoveString[3] = yytext[3+skip];
+    currentMoveString[4] = NULLCHAR;
+
+    /* [HGM] do not allow values beyond board size */
+    if(currentMoveString[1] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[1] - ONE <  0            ||
+       currentMoveString[0] - AAA >= BOARD_RGHT   ||
+       currentMoveString[3] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[3] - ONE <  0            ||
+       currentMoveString[2] - AAA >= BOARD_RGHT   ||
+       currentMoveString[0] - AAA <  BOARD_LEFT   ||
+       currentMoveString[2] - AAA <  BOARD_LEFT     )
+      return ImpossibleMove;
+
+    result = LegalityTest(boards[yyboardindex],
+                         PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: might think we can e.p.!
+                          currentMoveString[1] - ONE,
+                          currentMoveString[0] - AAA,
+                          currentMoveString[3] - ONE,
+                          currentMoveString[2] - AAA,
+                         currentMoveString[4]);
+
     if (currentMoveString[4] == NULLCHAR &&\r
         (result == WhitePromotionKnight || result == BlackPromotionKnight ||\r
          result == WhitePromotionQueen  || result == BlackPromotionQueen)) {\r
-        if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
+        if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)\r
             currentMoveString[4] = PieceToChar(BlackFerz);\r
         else if(gameInfo.variant == VariantGreat)\r
             currentMoveString[4] = PieceToChar(BlackMan);\r
         else\r
             currentMoveString[4] = PieceToChar(BlackQueen);\r
        currentMoveString[5] = NULLCHAR;\r
-    }\r
+    } else if(appData.testLegality && // strip off unnecessary and false promo characters
+       !(result == WhitePromotionQueen  || result == BlackPromotionQueen ||
+         result == WhiteNonPromotion    || result == BlackNonPromotion)) currentMoveString[4] = NULLCHAR;
 \r
     return (int) result;\r
 }\r
 \r
-[a-l][0-9]((=?\(?[A-Z]\)?)|=)?       {\r
+[a-l][0-9]((=?\(?[A-Za-z]\)?)|=)?       {\r
     /*\r
      * Pawn move, possibly with promotion\r
      */\r
@@ -347,21 +402,20 @@ extern void CopyBoard P((Board to, Board from));
     cl.ffIn = yytext[0] - AAA;\r
     cl.rtIn = yytext[1] - ONE;\r
     cl.ftIn = yytext[0] - AAA;\r
-    c = cl.promoCharIn = yytext[2+skip];\r
+    c = cl.promoCharIn = ToLower(yytext[2+skip]);\r
 \r
     /* [HGM] do not allow values beyond board size */\r
     if(cl.rtIn >= BOARD_HEIGHT ||\r
        cl.rtIn <  0            ||\r
        cl.ffIn >= BOARD_RGHT   ||\r
        cl.ftIn <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
     if(c != '=' && c != '+' && c != NULLCHAR && CharToPiece(c) == EmptySquare)\r
       return IllegalMove;\r
 \r
 \r
-    Disambiguate(boards[yyboardindex],\r
-                PosFlags(yyboardindex), EP_UNKNOWN, &cl);\r
+    Disambiguate(boards[yyboardindex], PosFlags(yyboardindex), &cl);\r
 \r
     currentMoveString[0] = cl.ff + AAA;\r
     currentMoveString[1] = cl.rf + ONE;\r
@@ -410,13 +464,12 @@ extern void CopyBoard P((Board to, Board from));
        cl.ffIn <  BOARD_LEFT  ||\r
        cl.ftIn >= BOARD_RGHT  ||\r
        cl.ftIn <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
     if(c != '=' && c != '+' && c != NULLCHAR && CharToPiece(c) == EmptySquare)\r
       return IllegalMove;\r
 \r
-    Disambiguate(boards[yyboardindex],\r
-                PosFlags(yyboardindex), EP_UNKNOWN, &cl);\r
+    Disambiguate(boards[yyboardindex], PosFlags(yyboardindex), &cl);\r
 \r
     currentMoveString[0] = cl.ff + AAA;\r
     currentMoveString[1] = cl.rf + ONE;\r
@@ -461,7 +514,7 @@ extern void CopyBoard P((Board to, Board from));
        currentMoveString[2] - AAA >= BOARD_RGHT   ||\r
        currentMoveString[0] - AAA <  BOARD_LEFT   ||\r
        currentMoveString[2] - AAA <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
     if (gameInfo.variant == VariantXiangqi && /* [HGM] In Xiangqi rank stays same */\r
          currentMoveString[0] != currentMoveString[2] ) {\r
@@ -492,8 +545,6 @@ extern void CopyBoard P((Board to, Board from));
 \r
     result = LegalityTest(boards[yyboardindex],\r
                          PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: might think we can e.p.!\r
-                         EP_UNKNOWN,\r
-                          initialRights, /* [HGM] assume all castlings allowed */\r
                           currentMoveString[1] - ONE,\r
                           currentMoveString[0] - AAA,\r
                           currentMoveString[3] - ONE,\r
@@ -505,7 +556,7 @@ extern void CopyBoard P((Board to, Board from));
          result == WhitePromotionKnight || result == BlackPromotionKnight)) {\r
         currentMoveString[4] = PieceToChar(BlackQueen);\r
        // [HGM] shatranj: take care of variants without Queen\r
-       if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
+       if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)\r
             currentMoveString[4] = PieceToChar(BlackFerz);\r
        if(gameInfo.variant == VariantGreat)\r
             currentMoveString[4] = PieceToChar(BlackMan);\r
@@ -533,8 +584,6 @@ extern void CopyBoard P((Board to, Board from));
 \r
     result = LegalityTest(boards[yyboardindex],\r
                          PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: might think we can e.p.!\r
-                         EP_UNKNOWN,\r
-                          initialRights, /* [HGM] assume all castlings allowed */\r
                           currentMoveString[1] - ONE,\r
                           currentMoveString[0] - AAA,\r
                           currentMoveString[3] - ONE,\r
@@ -589,10 +638,9 @@ extern void CopyBoard P((Board to, Board from));
        cl.rtIn <  0            ||\r
        cl.ftIn >= BOARD_RGHT   ||\r
        cl.ftIn <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
-    Disambiguate(boards[yyboardindex],\r
-                PosFlags(yyboardindex), EP_UNKNOWN, &cl);\r
+    Disambiguate(boards[yyboardindex], PosFlags(yyboardindex), &cl);\r
 \r
     currentMoveString[0] = cl.ff + AAA;\r
     currentMoveString[1] = cl.rf + ONE;\r
@@ -650,10 +698,9 @@ extern void CopyBoard P((Board to, Board from));
        cl.rtIn <  0            ||\r
        cl.ftIn >= BOARD_RGHT   ||\r
        cl.ftIn <  BOARD_LEFT     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
-    Disambiguate(boards[yyboardindex],\r
-                PosFlags(yyboardindex), EP_UNKNOWN, &cl);\r
+    Disambiguate(boards[yyboardindex], PosFlags(yyboardindex), &cl);\r
 \r
     currentMoveString[0] = cl.ff + AAA;\r
     currentMoveString[1] = cl.rf + ONE;\r
@@ -698,7 +745,7 @@ extern void CopyBoard P((Board to, Board from));
             ft = BOARD_LEFT+2;\r
        }\r
     }\r
-    if(gameInfo.variant == VariantFischeRandom) {\r
+    if(PosFlags(0) & F_FRC_TYPE_CASTLING) {
         if (WhiteOnMove(yyboardindex)) {\r
             ff = initialRights[2];\r
             ft = initialRights[1];\r
@@ -718,8 +765,6 @@ extern void CopyBoard P((Board to, Board from));
     }\r
     return (int) LegalityTest(boards[yyboardindex],\r
                              PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: e.p.!\r
-                             EP_UNKNOWN,\r
-                              castlingRights[yyboardindex], /* [HGM] use true castling rights */\r
                              rf, ff, rt, ft, NULLCHAR);\r
 }\r
 \r
@@ -755,7 +800,7 @@ extern void CopyBoard P((Board to, Board from));
             ft = BOARD_RGHT-2;\r
        }\r
     }\r
-    if(gameInfo.variant == VariantFischeRandom) {\r
+    if(PosFlags(0) & F_FRC_TYPE_CASTLING) {
         if (WhiteOnMove(yyboardindex)) {\r
             ff = initialRights[2];\r
             ft = initialRights[0];\r
@@ -775,13 +820,11 @@ extern void CopyBoard P((Board to, Board from));
 \r
     return (int) LegalityTest(boards[yyboardindex],\r
                              PosFlags(yyboardindex)&~F_MANDATORY_CAPTURE, // [HGM] losers: e.p.!\r
-                             EP_UNKNOWN,\r
-                              castlingRights[yyboardindex], /* [HGM] use true castling rights */\r
                              rf, ff, rt, ft, NULLCHAR);\r
 }\r
 \r
 [A-Z][@*][a-l][0-9] {\r
-    /* Bughouse piece drop.  No legality checking for now. */\r
+    /* Bughouse piece drop. */\r
     currentMoveString[1] = '@';\r
     currentMoveString[2] = yytext[2];\r
     currentMoveString[3] = yytext[3];\r
@@ -793,15 +836,15 @@ extern void CopyBoard P((Board to, Board from));
     /* [HGM] do not allow values beyond board size */\r
     if(currentMoveString[3] - ONE >= BOARD_HEIGHT ||\r
        currentMoveString[2] - AAA >= BOARD_WIDTH     )\r
-      return 0;\r
+      return ImpossibleMove;\r
 \r
     if (WhiteOnMove(yyboardindex)) {\r
        currentMoveString[0] = ToUpper(yytext[0]);\r
-       return (int) WhiteDrop;\r
     } else {\r
        currentMoveString[0] = ToLower(yytext[0]);\r
-       return (int) BlackDrop;\r
     }\r
+    return LegalityTest(boards[yyboardindex], PosFlags(yyboardindex), DROP_RANK, // [HGM] does drops now too
+                        CharToPiece(currentMoveString[0]), currentMoveString[3] - ONE, currentMoveString[2] - AAA, NULLCHAR);
 }\r
 \r
 [Rr]esign(s|ed)?  {\r
@@ -849,11 +892,11 @@ extern void CopyBoard P((Board to, Board from));
     return (int) GameIsDrawn;\r
 }\r
 \r
-(([Ww](hite)?)|([Bb](lack)?))" "([Mm]ate(s|ed)?)|([Ww][io]n(s)?.*)  {\r
+(([Ww](hite)?)|([Bb](lack)?))" "(([Mm]ates)|([Ww][io]n(s)?)) { \r
     return (int) (ToUpper(yytext[0]) == 'W' ? WhiteWins : BlackWins);\r
 }\r
 \r
-(([Ww](hite)?)|([Bb](lack)?))" "([Mm]ate(s|ed)?)|([Ll]os[tes]+.*)  {\r
+(([Ww](hite)?)|([Bb](lack)?))" "(([Mm]ated)|([Ll]os[tes]+)) { \r
     return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins);\r
 }\r
 \r
@@ -1101,10 +1144,10 @@ int yywrap()
 \r
 /* Parse a move from the given string s */\r
 /* ^ at start of pattern WON'T work here unless using flex */\r
-ChessMove yylexstr(boardIndex, s)\r
-     int boardIndex;\r
-     char *s;\r
-{\r
+ChessMove yylexstr(boardIndex, s, text, len)\r
+     int boardIndex, len;\r
+     char *s, *text;\r
+{
     ChessMove ret;\r
     char *oldStringToLex;\r
 #ifdef FLEX_SCANNER\r
@@ -1120,7 +1163,9 @@ ChessMove yylexstr(boardIndex, s)
     yy_switch_to_buffer(buffer);\r
 #endif /*FLEX_SCANNER*/\r
 \r
-    ret = (ChessMove) yylex();\r
+    ret = (ChessMove) yylex();
+     strncpy(text, yy_text, len-1); // [HGM] vari: yy_text is not available to caller after buffer switch ?!?
+     text[len-1] = NULLCHAR;\r
 \r
 #ifdef FLEX_SCANNER\r
     if (oldBuffer != NULL) \r