Remove promotion-piece encoding from ChessMove type
[xboard.git] / backend.c
index b124be6..2a6e2e6 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -158,8 +158,7 @@ void read_from_ics P((InputSourceRef isr, VOIDSTAR closure,
 void ics_printf P((char *format, ...));
 void SendToICS P((char *s));
 void SendToICSDelayed P((char *s, long msdelay));
-void SendMoveToICS P((ChessMove moveType, int fromX, int fromY,
-                     int toX, int toY));
+void SendMoveToICS P((ChessMove moveType, int fromX, int fromY, int toX, int toY, char promoChar));
 void HandleMachineMove P((char *message, ChessProgramState *cps));
 int AutoPlayOneMove P((void));
 int LoadGameOneMove P((ChessMove readAhead));
@@ -895,7 +894,7 @@ InitBackEnd1()
       case VariantGothic:     /* [HGM] should work */
       case VariantCapablanca: /* [HGM] should work */
       case VariantCourier:    /* [HGM] initial forced moves not implemented */
-      case VariantShogi:      /* [HGM] drops not tested for legality */
+      case VariantShogi:      /* [HGM] could still mate with pawn drop */
       case VariantKnightmate: /* [HGM] should work */
       case VariantCylinder:   /* [HGM] untested */
       case VariantFalcon:     /* [HGM] untested */
@@ -4543,9 +4542,10 @@ SendMoveToProgram(moveNum, cps)
 }
 
 void
-SendMoveToICS(moveType, fromX, fromY, toX, toY)
+SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar)
      ChessMove moveType;
      int fromX, fromY, toX, toY;
+     char promoChar;
 {
     char user_move[MSG_SIZ];
 
@@ -4579,20 +4579,8 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY)
       case BlackNonPromotion:
         sprintf(user_move, "%c%c%c%c=\n", AAA + fromX, ONE + fromY, AAA + toX, ONE + toY);
         break;
-      case WhitePromotionQueen:
-      case BlackPromotionQueen:
-      case WhitePromotionRook:
-      case BlackPromotionRook:
-      case WhitePromotionBishop:
-      case BlackPromotionBishop:
-      case WhitePromotionKnight:
-      case BlackPromotionKnight:
-      case WhitePromotionKing:
-      case BlackPromotionKing:
-      case WhitePromotionChancellor:
-      case BlackPromotionChancellor:
-      case WhitePromotionArchbishop:
-      case BlackPromotionArchbishop:
+      case WhitePromotion:
+      case BlackPromotion:
         if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier || gameInfo.variant == VariantMakruk)
             sprintf(user_move, "%c%c%c%c=%c\n",
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
@@ -4604,7 +4592,7 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY)
         else
             sprintf(user_move, "%c%c%c%c=%c\n",
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
-               PieceToChar(PromoPiece(moveType)));
+               promoChar);
        break;
       case WhiteDrop:
       case BlackDrop:
@@ -4793,20 +4781,8 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
     *moveType = yylexstr(moveNum, move, yy_textstr, sizeof yy_textstr);
 
     switch (*moveType) {
-      case WhitePromotionChancellor:
-      case BlackPromotionChancellor:
-      case WhitePromotionArchbishop:
-      case BlackPromotionArchbishop:
-      case WhitePromotionQueen:
-      case BlackPromotionQueen:
-      case WhitePromotionRook:
-      case BlackPromotionRook:
-      case WhitePromotionBishop:
-      case BlackPromotionBishop:
-      case WhitePromotionKnight:
-      case BlackPromotionKnight:
-      case WhitePromotionKing:
-      case BlackPromotionKing:
+      case WhitePromotion:
+      case BlackPromotion:
       case WhiteNonPromotion:
       case BlackNonPromotion:
       case NormalMove:
@@ -5585,7 +5561,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice)
 
     piece = boards[currentMove][fromY][fromX];
     if(gameInfo.variant == VariantShogi) {
-        promotionZoneSize = 3;
+        promotionZoneSize = BOARD_HEIGHT/3;
         highestPromotingPiece = (int)WhiteFerz;
     } else if(gameInfo.variant == VariantMakruk) {
         promotionZoneSize = 3;
@@ -5649,8 +5625,7 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice)
     if(appData.testLegality && !premove) {
        moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
                        fromY, fromX, toY, toX, NULLCHAR);
-       if(moveType != WhitePromotionQueen && moveType  != BlackPromotionQueen &&
-          moveType != WhitePromotionKnight && moveType != BlackPromotionKnight)
+       if(moveType != WhitePromotion && moveType  != BlackPromotion)
            return FALSE;
     }
 
@@ -5803,8 +5778,7 @@ OnlyMove(int *x, int *y, Boolean captures) {
     Disambiguate(boards[currentMove], PosFlags(currentMove), &cl);
     if( cl.kind == NormalMove ||
        cl.kind == AmbiguousMove && captures && cl.captures == 1 ||
-       cl.kind == WhitePromotionQueen || cl.kind == BlackPromotionQueen ||
-       cl.kind == WhitePromotionKnight || cl.kind == BlackPromotionKnight ||
+       cl.kind == WhitePromotion || cl.kind == BlackPromotion ||
        cl.kind == WhiteCapturesEnPassant || cl.kind == BlackCapturesEnPassant) {
       fromX = cl.ff;
       fromY = cl.rf;
@@ -5822,8 +5796,7 @@ OnlyMove(int *x, int *y, Boolean captures) {
     Disambiguate(boards[currentMove], PosFlags(currentMove), &cl);
     if( cl.kind == NormalMove ||
        cl.kind == AmbiguousMove && captures && cl.captures == 1 ||
-       cl.kind == WhitePromotionQueen || cl.kind == BlackPromotionQueen ||
-       cl.kind == WhitePromotionKnight || cl.kind == BlackPromotionKnight ||
+       cl.kind == WhitePromotion || cl.kind == BlackPromotion ||
        cl.kind == WhiteCapturesEnPassant || cl.kind == BlackCapturesEnPassant) {
       fromX = cl.ff;
       fromY = cl.rf;
@@ -5841,11 +5814,10 @@ int lastLoadGameUseList = FALSE;
 char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ];
 ChessMove lastLoadGameStart = (ChessMove) 0;
 
-ChessMove
-UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
+void
+UserMoveEvent(fromX, fromY, toX, toY, promoChar)
      int fromX, fromY, toX, toY;
      int promoChar;
-     Boolean captureOwn;
 {
     ChessMove moveType;
     ChessSquare pdown, pup;
@@ -5870,13 +5842,13 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
       case IcsIdle:
        /* We switched into a game mode where moves are not accepted,
            perhaps while the mouse button was down. */
-        return ImpossibleMove;
+        return;
 
       case MachinePlaysWhite:
        /* User is moving for Black */
        if (WhiteOnMove(currentMove)) {
            DisplayMoveError(_("It is White's turn"));
-            return ImpossibleMove;
+            return;
        }
        break;
 
@@ -5884,7 +5856,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
        /* User is moving for White */
        if (!WhiteOnMove(currentMove)) {
            DisplayMoveError(_("It is Black's turn"));
-            return ImpossibleMove;
+            return;
        }
        break;
 
@@ -5898,13 +5870,13 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
            /* User is moving for Black */
            if (WhiteOnMove(currentMove)) {
                DisplayMoveError(_("It is White's turn"));
-                return ImpossibleMove;
+                return;
            }
        } else {
            /* User is moving for White */
            if (!WhiteOnMove(currentMove)) {
                DisplayMoveError(_("It is Black's turn"));
-                return ImpossibleMove;
+                return;
            }
        }
        break;
@@ -5926,7 +5898,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
                            "fromY %d, toX %d, toY %d\n",
                            fromX, fromY, toX, toY);
            }
-            return ImpossibleMove;
+            return;
        }
        break;
 
@@ -5947,7 +5919,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
                            "fromY %d, toX %d, toY %d\n",
                            fromX, fromY, toX, toY);
            }
-            return ImpossibleMove;
+            return;
        }
        break;
 
@@ -5959,7 +5931,8 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
           click-click move is possible */
        if (toX == -2 || toY == -2) {
            boards[0][fromY][fromX] = EmptySquare;
-           return AmbiguousMove;
+           DrawPosition(FALSE, boards[currentMove]);
+           return;
        } else if (toX >= 0 && toY >= 0) {
            boards[0][toY][toX] = boards[0][fromY][fromX];
            if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings
@@ -5975,28 +5948,27 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
                }
            } else
            boards[0][fromY][fromX] = EmptySquare;
-           return AmbiguousMove;
+           DrawPosition(FALSE, boards[currentMove]);
+           return;
        }
-        return ImpossibleMove;
+        return;
     }
 
-    if(toX < 0 || toY < 0) return ImpossibleMove;
+    if(toX < 0 || toY < 0) return;
     pdown = boards[currentMove][fromY][fromX];
     pup = boards[currentMove][toY][toX];
 
-    /* [HGM] If move started in holdings, it means a drop */
+    /* [HGM] If move started in holdings, it means a drop. Convert to standard form */
     if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { 
-         if( pup != EmptySquare ) return ImpossibleMove;
-         if(appData.testLegality) {
-             /* it would be more logical if LegalityTest() also figured out
-              * which drops are legal. For now we forbid pawns on back rank.
-              * Shogi is on its own here...
-              */
-             if( (pdown == WhitePawn || pdown == BlackPawn) &&
-                 (toY == 0 || toY == BOARD_HEIGHT -1 ) )
-                 return(ImpossibleMove); /* no pawn drops on 1st/8th */
-         }
-         return WhiteDrop; /* Not needed to specify white or black yet */
+         if( pup != EmptySquare ) return;
+         moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
+          if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n", 
+               moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
+          // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
+          if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
+          fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
+          while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; 
+         fromY = DROP_RANK;
     }
 
     /* [HGM] always test for legality, to get promotion info */
@@ -6006,18 +5978,11 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
     if (appData.testLegality) {
        if (moveType == IllegalMove || moveType == ImpossibleMove) {
            DisplayMoveError(_("Illegal move"));
-            return ImpossibleMove;
+            return;
        }
     }
 
-    return moveType;
-    /* [HGM] <popupFix> in stead of calling FinishMove directly, this
-       function is made into one that returns an OK move type if FinishMove
-       should be called. This to give the calling driver routine the
-       opportunity to finish the userMove input with a promotion popup,
-       without bothering the user with this for invalid or illegal moves */
-
-/*    FinishMove(moveType, fromX, fromY, toX, toY, promoChar); */
+    FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
 }
 
 /* Common tail of UserMoveEvent and DropMenuEvent */
@@ -6042,19 +6007,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
     /* [HGM] <popupFix> kludge to avoid having to know the exact promotion
        move type in caller when we know the move is a legal promotion */
     if(moveType == NormalMove && promoChar)
-        moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);
-
-    /* [HGM] convert drag-and-drop piece drops to standard form */
-    if( (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) && fromY != DROP_RANK ){
-         moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
-          if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n", 
-               moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
-          // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
-          if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
-          fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
-          while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++; 
-         fromY = DROP_RANK;
-    }
+        moveType = WhiteOnMove(currentMove) ? WhitePromotion : BlackPromotion;
 
     /* [HGM] <popupFix> The following if has been moved here from
        UserMoveEvent(). Because it seemed to belong here (why not allow
@@ -6142,10 +6095,10 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
       if(userOfferedDraw && (signed char)boards[forwardMostMove][EP_STATUS] <= EP_DRAWS) {
         SendToICS(ics_prefix); // [HGM] drawclaim: send caim and move on one line for FICS
        SendToICS("draw ");
-        SendMoveToICS(moveType, fromX, fromY, toX, toY);
+        SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar);
       }
       // also send plain move, in case ICS does not understand atomic claims
-      SendMoveToICS(moveType, fromX, fromY, toX, toY);
+      SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar);
       ics_user_moved = 1;
     }
   } else {
@@ -6213,28 +6166,6 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
 }
 
 void
-UserMoveEvent(fromX, fromY, toX, toY, promoChar)
-     int fromX, fromY, toX, toY;
-     int promoChar;
-{
-    /* [HGM] This routine was added to allow calling of its two logical
-       parts from other modules in the old way. Before, UserMoveEvent()
-       automatically called FinishMove() if the move was OK, and returned
-       otherwise. I separated the two, in order to make it possible to
-       slip a promotion popup in between. But that it always needs two
-       calls, to the first part, (now called UserMoveTest() ), and to
-       FinishMove if the first part succeeded. Calls that do not need
-       to do anything in between, can call this routine the old way. 
-    */
-    ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar, FALSE);
-if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", moveType, promoChar);
-    if(moveType == AmbiguousMove)
-       DrawPosition(FALSE, boards[currentMove]);
-    else if(moveType != ImpossibleMove && moveType != Comment)
-        FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
-}
-
-void
 Mark(board, flags, kind, rf, ff, rt, ft, closure)
      Board board;
      int flags;
@@ -6708,8 +6639,7 @@ Adjudicate(ChessProgramState *cps)
        ChessProgramState *engineOpponent = (gameMode == TwoMachinesPlay ? cps->other : (cps ? NULL : &first));
        Boolean canAdjudicate = !appData.icsActive;
 
-       // most tests only when we understand the game, i.e. legality-checking on, and (for the time being) no piece drops
-       if(gameInfo.holdingsSize == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {
+       // most tests only when we understand the game, i.e. legality-checking on
            if( appData.testLegality )
            {   /* [HGM] Some more adjudications for obstinate engines */
                int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+1], i;
@@ -6861,7 +6791,6 @@ Adjudicate(ChessProgramState *cps)
                      }
                 } else moveCount = 6;
            }
-       }
          
        if (appData.debugMode) { int i;
            fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",
@@ -7206,9 +7135,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
         /* to make sure an illegal e.p. capture does not slip through,   */
         /* to cause a forfeit on a justified illegal-move complaint      */
         /* of the opponent.                                              */
-        if( gameMode==TwoMachinesPlay && appData.testLegality
-            && fromY != DROP_RANK /* [HGM] temporary; should still add legality test for drops */
-                                                              ) {
+        if( gameMode==TwoMachinesPlay && appData.testLegality ) {
            ChessMove moveType;
            moveType = LegalityTest(boards[forwardMostMove], PosFlags(forwardMostMove),
                              fromY, fromX, toY, toX, promoChar);
@@ -7298,9 +7225,9 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
          if(cps->offeredDraw && (signed char)boards[forwardMostMove][EP_STATUS] <= EP_DRAWS) {
                SendToICS(ics_prefix); // [HGM] drawclaim: send caim and move on one line for FICS
                SendToICS("draw ");
-               SendMoveToICS(moveType, fromX, fromY, toX, toY);
+               SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar);
          }
-         SendMoveToICS(moveType, fromX, fromY, toX, toY);
+         SendMoveToICS(moveType, fromX, fromY, toX, toY, promoChar);
          ics_user_moved = 1;
          if(appData.autoKibitz && !appData.icsEngineAnalyze ) { /* [HGM] kibitz: send most-recent PV info to ICS */
                char buf[3*MSG_SIZ];
@@ -8162,20 +8089,8 @@ ParseGameHistory(game)
     fprintf(debugFP, "board L=%d, R=%d, H=%d, holdings=%d\n", BOARD_LEFT, BOARD_RGHT, BOARD_HEIGHT, gameInfo.holdingsWidth);
     setbuf(debugFP, NULL);
   }
-          case WhitePromotionChancellor:
-          case BlackPromotionChancellor:
-          case WhitePromotionArchbishop:
-          case BlackPromotionArchbishop:
-         case WhitePromotionQueen:
-         case BlackPromotionQueen:
-         case WhitePromotionRook:
-         case BlackPromotionRook:
-         case WhitePromotionBishop:
-         case BlackPromotionBishop:
-         case WhitePromotionKnight:
-         case BlackPromotionKnight:
-         case WhitePromotionKing:
-         case BlackPromotionKing:
+         case WhitePromotion:
+         case BlackPromotion:
          case WhiteNonPromotion:
          case BlackNonPromotion:
          case NormalMove:
@@ -8324,7 +8239,6 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
 
     /* [HGM] compute & store e.p. status and castling rights for new position */
     /* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */
-    { int i;
 
       if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;
       oldEP = (signed char)board[EP_STATUS];
@@ -8333,6 +8247,16 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
       if( board[toY][toX] != EmptySquare ) 
            board[EP_STATUS] = EP_CAPTURE;  
 
+  /* [HGM] In Shatranj and Courier all promotions are to Ferz */
+  if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk)
+       && promoChar != 0) promoChar = PieceToChar(WhiteFerz);
+         
+  if (fromY == DROP_RANK) {
+       /* must be first */
+        piece = board[toY][toX] = (ChessSquare) fromX;
+  } else {
+      int i;
+
       if( board[fromY][fromX] == WhitePawn ) {
            if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
               board[EP_STATUS] = EP_PAWN_MOVE;
@@ -8364,18 +8288,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
              ) board[CASTLING][i] = NoRights; // revoke for moved or captured piece
        }
 
-    }
+     if (fromX == toX && fromY == toY) return;
 
-  /* [HGM] In Shatranj and Courier all promotions are to Ferz */
-  if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier || gameInfo.variant == VariantMakruk)
-       && promoChar != 0) promoChar = PieceToChar(WhiteFerz);
-         
-  if (fromX == toX && fromY == toY) return;
-
-  if (fromY == DROP_RANK) {
-       /* must be first */
-        piece = board[toY][toX] = (ChessSquare) fromX;
-  } else {
      piece = board[fromY][fromX]; /* [HGM] remember, for Shogi promotion */
      king = piece < (int) BlackPawn ? WhiteKing : BlackKing; /* [HGM] Knightmate simplify testing for castling */
      if(gameInfo.variant == VariantKnightmate)
@@ -8521,10 +8435,6 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
        board[toY][toX] = board[fromY][fromX];
        board[fromY][fromX] = EmptySquare;
     }
-
-    /* [HGM] now we promote for Shogi, if needed */
-    if(gameInfo.variant == VariantShogi && promoChar == 'q')
-        board[toY][toX] = (ChessSquare) (PROMOTED piece);
   }
 
     if (gameInfo.holdingsWidth != 0) {
@@ -8600,11 +8510,12 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
        board[toY][toX] = EmptySquare;
       }
     }
-    if(gameInfo.variant == VariantShogi && promoChar != NULLCHAR && promoChar != '=') {
-        /* [HGM] Shogi promotions */
+    if(promoChar == '+') {
+        /* [HGM] Shogi-style promotions, to piece implied by original (Might overwrite orinary Pawn promotion) */
         board[toY][toX] = (ChessSquare) (PROMOTED piece);
+    } else if(!appData.testLegality) { // without legality testing, unconditionally believe promoChar
+        board[toY][toX] = CharToPiece(promoChar);
     }
-
     if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) 
                && promoChar != NULLCHAR && gameInfo.holdingsSize) { 
        // [HGM] superchess: take promotion piece out of holdings
@@ -9638,22 +9549,8 @@ LoadGameOneMove(readAhead)
 
       case WhiteCapturesEnPassant:
       case BlackCapturesEnPassant:
-      case WhitePromotionChancellor:
-      case BlackPromotionChancellor:
-      case WhitePromotionArchbishop:
-      case BlackPromotionArchbishop:
-      case WhitePromotionCentaur:
-      case BlackPromotionCentaur:
-      case WhitePromotionQueen:
-      case BlackPromotionQueen:
-      case WhitePromotionRook:
-      case BlackPromotionRook:
-      case WhitePromotionBishop:
-      case BlackPromotionBishop:
-      case WhitePromotionKnight:
-      case BlackPromotionKnight:
-      case WhitePromotionKing:
-      case BlackPromotionKing:
+      case WhitePromotion:
+      case BlackPromotion:
       case WhiteNonPromotion:
       case BlackNonPromotion:
       case NormalMove: