changes from H.G. Muller; version 4.3.13
[xboard.git] / moves.c
diff --git a/moves.c b/moves.c
index 9aff915..deac69f 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -196,12 +196,11 @@ ChessMove PromoCharToMoveType(whiteOnMove, promoChar)
 }\r
 \r
 char pieceToChar[] = {\r
-                        'P', 'N', 'B', 'R', 'Q', 'F', \r
-    'W', 'E', 'M', 'O', 'U', 'H', 'A', 'C', 'G', 'S',\r
-    'K',                'p', 'n', 'b', 'r', 'q', 'f', \r
-    'w', 'e', 'm', 'o', 'u', 'h', 'a', 'c', 'g', 's',\r
-    'k', 'x'\r
-  };\r
+                        'P', 'N', 'B', 'R', 'Q', 'F', 'E', 'A', 'C', 'W', 'M', \r
+                        'O', 'H', 'I', 'J', 'G', 'D', 'V', 'S', 'L', 'U', 'K',\r
+                        'p', 'n', 'b', 'r', 'q', 'f', 'e', 'a', 'c', 'w', 'm', \r
+                        'o', 'h', 'i', 'j', 'g', 'd', 'v', 's', 'l', 'u', 'k', \r
+                        'x' };\r
 \r
 char PieceToChar(p)\r
      ChessSquare p;\r
@@ -210,7 +209,7 @@ char PieceToChar(p)
     return pieceToChar[(int) p];\r
 }\r
 \r
-int PieceToNumber(p)\r
+int PieceToNumber(p)  /* [HGM] holdings: count piece type, ignoring non-participating piece types */\r
      ChessSquare p;\r
 {\r
     int i=0;\r
@@ -281,9 +280,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              if (!BlackPiece(board[rf][ff])) continue;\r
          }\r
           m = 0; piece = board[rf][ff];\r
-          if(gameInfo.variant == VariantCrazyhouse &&\r
-              ( (int) piece > (int) WhiteQueen && (int) piece < (int) WhiteKing\r
-             || (int) piece > (int) BlackQueen && (int) piece < (int) BlackKing ))\r
+          if(PieceToChar(piece) == '~') \r
                  piece = (ChessSquare) ( DEMOTED piece );\r
           if(gameInfo.variant == VariantShogi)\r
                  piece = (ChessSquare) ( SHOGI piece );\r
@@ -294,7 +291,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              /* can't happen ([HGM] except for faries...) */\r
              break;\r
 \r
-           case WhitePawn:\r
+             case WhitePawn:\r
               if(gameInfo.variant == VariantXiangqi) {\r
                   /* [HGM] capture and move straight ahead in Xiangqi */\r
                   if (rf < BOARD_HEIGHT-1 &&\r
@@ -521,8 +518,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
               m++;\r
 \r
             /* Capablanca Archbishop continues as Knight                  */\r
-            case WhiteCardinal:\r
-            case BlackCardinal:\r
+            case WhiteAngel:\r
+            case BlackAngel:\r
               m++;\r
 \r
             /* Shogi Bishops are ordinary Bishops */\r
@@ -572,8 +569,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
               break;\r
 \r
             /* Shogi Dragon King has to continue as Ferz after Rook moves */\r
-            case SHOGI WhiteMarshall:\r
-            case SHOGI BlackMarshall:\r
+            case SHOGI WhiteDragon:\r
+            case SHOGI BlackDragon:\r
               m++;\r
 \r
             /* Capablanca Chancellor sets flag to continue as Knight      */\r
@@ -645,7 +642,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                   for (fs = -1; fs <= 1; fs += 2) {\r
                       rt = rf + rs;\r
                       ft = ff + fs;\r
-                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;\r
+                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;\r
                       if (!SameColor(board[rf][ff], board[rt][ft]) &&\r
                           (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) )\r
                                callback(board, flags, NormalMove,\r
@@ -671,6 +668,24 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                             rf, ff, rt, ft, closure);\r
                }\r
              break;\r
+\r
+           case WhiteNightrider:\r
+           case BlackNightrider:\r
+             for (i = -1; i <= 1; i += 2)\r
+               for (j = -1; j <= 1; j += 2)\r
+                 for (s = 1; s <= 2; s++) {  int k;\r
+                    for(k=1;; k++) {\r
+                     rt = rf + k*i*s;\r
+                     ft = ff + k*j*(3-s);\r
+                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;\r
+                     if (SameColor(board[rf][ff], board[rt][ft])) break;\r
+                     callback(board, flags, NormalMove,\r
+                              rf, ff, rt, ft, closure);\r
+                     if (board[rt][ft] != EmptySquare) break;\r
+                    }\r
+                 }\r
+             break;\r
+\r
          }\r
       }\r
 }\r
@@ -738,8 +753,9 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
      VOIDSTAR closure;\r
 {\r
     GenLegalClosure cl;\r
-    int ff, ft;\r
+    int ff, ft, k, left, right;\r
     int ignoreCheck = (flags & F_IGNORE_CHECK) != 0;\r
+    ChessSquare wKing = WhiteKing, bKing = BlackKing;\r
 \r
     cl.cb = callback;\r
     cl.cl = closure;\r
@@ -749,10 +765,14 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        CheckTest(board, flags, -1, -1, -1, -1, FALSE)) return TRUE;\r
 \r
     /* Generate castling moves */\r
+    if(gameInfo.variant == VariantKnightmate) { /* [HGM] Knightmate */\r
+        wKing = WhiteUnicorn; bKing = BlackUnicorn;\r
+    }\r
+\r
     for (ff = BOARD_WIDTH>>1; ff >= (BOARD_WIDTH-1)>>1; ff-- /*ics wild 1*/) {\r
        if ((flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_WHITE_KCASTLE_OK) &&\r
-            board[0][ff] == WhiteKing &&\r
+            board[0][ff] == wKing &&\r
             board[0][ff + 1] == EmptySquare &&\r
             board[0][ff + 2] == EmptySquare &&\r
             board[0][BOARD_RGHT-3] == EmptySquare &&\r
@@ -771,7 +791,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
        if ((flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_WHITE_QCASTLE_OK) &&\r
-           board[0][ff] == WhiteKing &&\r
+            board[0][ff] == wKing &&\r
            board[0][ff - 1] == EmptySquare &&\r
            board[0][ff - 2] == EmptySquare &&\r
             board[0][BOARD_LEFT+2] == EmptySquare &&\r
@@ -790,7 +810,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
        if (!(flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_BLACK_KCASTLE_OK) &&\r
-           board[BOARD_HEIGHT-1][ff] == BlackKing &&\r
+            board[BOARD_HEIGHT-1][ff] == bKing &&\r
            board[BOARD_HEIGHT-1][ff + 1] == EmptySquare &&\r
            board[BOARD_HEIGHT-1][ff + 2] == EmptySquare &&\r
             board[BOARD_HEIGHT-1][BOARD_RGHT-3] == EmptySquare &&\r
@@ -809,7 +829,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
        if (!(flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_BLACK_QCASTLE_OK) &&\r
-           board[BOARD_HEIGHT-1][ff] == BlackKing &&\r
+            board[BOARD_HEIGHT-1][ff] == bKing &&\r
            board[BOARD_HEIGHT-1][ff - 1] == EmptySquare &&\r
            board[BOARD_HEIGHT-1][ff - 2] == EmptySquare &&\r
             board[BOARD_HEIGHT-1][BOARD_LEFT+2] == EmptySquare &&\r
@@ -820,7 +840,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
            (ignoreCheck ||\r
             (!CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE) &&\r
               !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_LEFT+3,      FALSE) &&\r
-             !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE)))) {\r
+              !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 2, FALSE)))) {\r
 \r
            callback(board, flags,\r
                     ff==BOARD_WIDTH>>1 ? BlackQueenSideCastle : BlackQueenSideCastleWild,\r
@@ -828,41 +848,73 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
     }\r
 \r
-    /* PUSH Fabien */\r
+  if(gameInfo.variant == VariantFischeRandom) {\r
 \r
     /* generate all potential FRC castling moves (KxR), ignoring flags */\r
-    /* [HGM] Tord! Help requested! */\r
-\r
-    if ((flags & F_WHITE_ON_MOVE) != 0) {\r
+    /* [HGM] test if the Rooks we find have castling rights */\r
 \r
-       for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) {\r
-          if (board[0][ff] == WhiteKing) {\r
-             for (ft = BOARD_LEFT+0; ft < BOARD_RGHT; ft++) {\r
-                if (board[0][ft] == WhiteRook) {\r
-                   callback(board, flags, \r
-                            (ft > ff) ? WhiteHSideCastleFR : WhiteASideCastleFR,\r
-                            0, ff, 0, ft, closure);\r
-                }\r
-             }\r
-          }\r
-       }\r
 \r
+    if ((flags & F_WHITE_ON_MOVE) != 0) {\r
+        ff = castlingRights[2]; /* King file if we have any rights */\r
+        if(ff > 0) {\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "FRC castling, %d %d %d %d %d %d\n",\r
+                castlingRights[0],castlingRights[1],ff,castlingRights[3],castlingRights[4],castlingRights[5]);\r
+    }\r
+            ft = castlingRights[0]; /* Rook file if we have H-side rights */\r
+            left  = ff+1;\r
+            right = BOARD_RGHT-2;\r
+            if(ff == BOARD_RGHT-2) left = right = ff-1;    /* special case */\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[0][k] != EmptySquare) ft = -1;\r
+            for(k=left; k<right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = -1;\r
+            if(ft >= 0)\r
+                callback(board, flags, WhiteHSideCastleFR, 0, ff, 0, ft, closure);\r
+\r
+            ft = castlingRights[1]; /* Rook file if we have A-side rights */\r
+            left  = BOARD_LEFT+2;\r
+            right = ff-1;\r
+            if(ff <= BOARD_LEFT+2) { left = ff+1; right = BOARD_LEFT+3; }\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[0][k] != EmptySquare) ft = -1;\r
+            if(ff > BOARD_LEFT+2) \r
+            for(k=left+1; k<=right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = -1;\r
+\r
+            if(ft >= 0)\r
+                callback(board, flags, WhiteASideCastleFR, 0, ff, 0, ft, closure);\r
+        }\r
     } else {\r
-\r
-       for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) {\r
-          if (board[BOARD_HEIGHT-1][ff] == BlackKing) {\r
-             for (ft = BOARD_LEFT+0; ft < BOARD_RGHT; ft++) {\r
-                if (board[BOARD_HEIGHT-1][ft] == BlackRook) {\r
-                   callback(board, flags, \r
-                            (ft > ff) ? BlackHSideCastleFR : BlackASideCastleFR,\r
-                            BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);\r
-                }\r
-             }\r
-          }\r
-       }\r
+        ff = castlingRights[5]; /* King file if we have any rights */\r
+        if(ff > 0) {\r
+            ft = castlingRights[3]; /* Rook file if we have H-side rights */\r
+            left  = ff+1;\r
+            right = BOARD_RGHT-2;\r
+            if(ff == BOARD_RGHT-2) left = right = ff-1;    /* special case */\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = -1;\r
+            for(k=left; k<right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = -1;\r
+            if(ft >= 0)\r
+                callback(board, flags, BlackHSideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);\r
+\r
+            ft = castlingRights[4]; /* Rook file if we have A-side rights */\r
+            left  = BOARD_LEFT+2;\r
+            right = ff-1;\r
+            if(ff <= BOARD_LEFT+2) { left = ff+1; right = BOARD_LEFT+3; }\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = -1;\r
+            if(ff > BOARD_LEFT+2) \r
+            for(k=left+1; k<=right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = -1;\r
+\r
+            if(ft >= 0)\r
+                callback(board, flags, BlackASideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);\r
+        }\r
     }\r
 \r
-    /* POP Fabien */\r
+  }\r
 \r
     return FALSE;\r
 }\r
@@ -932,6 +984,17 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant)
     for (cl.fking = BOARD_LEFT+0; cl.fking < BOARD_RGHT; cl.fking++)\r
        for (cl.rking = 0; cl.rking < BOARD_HEIGHT; cl.rking++) {\r
           if (board[cl.rking][cl.fking] == king) {\r
+              if(gameInfo.variant == VariantXiangqi) {\r
+                  /* [HGM] In Xiangqi opposing Kings means check as well */\r
+                  int i, dir;\r
+                  dir = (king >= BlackPawn) ? -1 : 1;\r
+                  for( i=cl.rking+dir; i>=0 && i<BOARD_HEIGHT &&\r
+                                board[i][cl.fking] == EmptySquare; i+=dir );\r
+                  if(i>=0 && i<BOARD_HEIGHT &&\r
+                      board[i][cl.fking] == (dir>0 ? BlackWazir : WhiteWazir) )\r
+                          cl.check++;\r
+              }\r
+\r
              GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, -1,\r
                             CheckTestCallback, (VOIDSTAR) &cl);\r
              goto undo_move;  /* 2-level break */\r
@@ -967,9 +1030,9 @@ void LegalityTestCallback(board, flags, kind, rf, ff, rt, ft, closure)
 {\r
     register LegalityTestClosure *cl = (LegalityTestClosure *) closure;\r
 \r
-    if (appData.debugMode) {\r
-        fprintf(debugFP, "Legality test: %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);\r
-    }\r
+//    if (appData.debugMode) {\r
+//        fprintf(debugFP, "Legality test: %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);\r
+//    }\r
     if (rf == cl->rf && ff == cl->ff && rt == cl->rt && ft == cl->ft)\r
       cl->kind = kind;\r
 }\r
@@ -980,8 +1043,20 @@ ChessMove LegalityTest(board, flags, epfile, castlingRights, rf, ff, rt, ft, pro
      int rf, ff, rt, ft, promoChar;\r
      char castlingRights[];\r
 {\r
-    LegalityTestClosure cl;\r
+    LegalityTestClosure cl; ChessSquare piece = board[rf][ff];\r
     \r
+    if (appData.debugMode) {\r
+        int i;\r
+        for(i=0; i<6; i++) fprintf(debugFP, "%d ", castlingRights[i]);\r
+        fprintf(debugFP, "Legality test? %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);\r
+    }\r
+    /* [HGM] Lance, Cobra and Falcon are wildcard pieces; consider all their moves legal */\r
+    /* (perhaps we should disallow moves that obviously leave us in check?)              */\r
+    if(piece == WhiteFalcon || piece == BlackFalcon ||\r
+       piece == WhiteCobra  || piece == BlackCobra  ||\r
+       piece == WhiteLance  || piece == BlackLance)\r
+        return NormalMove;\r
+\r
     cl.rf = rf;\r
     cl.ff = ff;\r
     cl.rt = rt;\r
@@ -1088,7 +1163,10 @@ void DisambiguateCallback(board, flags, kind, rf, ff, rt, ft, closure)
 {\r
     register DisambiguateClosure *cl = (DisambiguateClosure *) closure;\r
 \r
-    if ((cl->pieceIn == EmptySquare || cl->pieceIn == board[rf][ff]) &&\r
+    if ((cl->pieceIn == EmptySquare || cl->pieceIn == board[rf][ff]\r
+         || PieceToChar(board[rf][ff]) == '~'\r
+              && cl->pieceIn == (ChessSquare)(DEMOTED board[rf][ff])\r
+                                                                      ) &&\r
        (cl->rfIn == -1 || cl->rfIn == rf) &&\r
        (cl->ffIn == -1 || cl->ffIn == ff) &&\r
        (cl->rtIn == -1 || cl->rtIn == rt) &&\r
@@ -1127,25 +1205,31 @@ void Disambiguate(board, flags, epfile, closure)
 \r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate in:  %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                             closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                             closure->promoCharIn,closure->promoCharIn);\r
     }\r
     if(gameInfo.variant == VariantShogi) {\r
         /* [HGM] Shogi promotions. '=' means defer */\r
         if(closure->rfIn != DROP_RANK && closure->kind == NormalMove) {\r
             ChessSquare piece = closure->piece;\r
-\r
+#if 0\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate A:   %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                          closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                          closure->promoCharIn,closure->promoCharIn);\r
     }\r
+#endif\r
             if(c != NULLCHAR && c != 'x' && c != '+' && c != '=' &&\r
                ToUpper(PieceToChar(PROMOTED piece)) != ToUpper(c) ) \r
                     closure->kind = IllegalMove;\r
             else if(flags & F_WHITE_ON_MOVE) {\r
+#if 0\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate B:   %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                          closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                          closure->promoCharIn,closure->promoCharIn);\r
     }\r
+#endif\r
                 if( (int) piece < (int) WhiteWazir &&\r
                      (closure->rf > BOARD_HEIGHT-4 || closure->rt > BOARD_HEIGHT-4) ) {\r
                     if( (piece == WhitePawn || piece == WhiteQueen) && closure->rt > BOARD_HEIGHT-2 ||\r
@@ -1179,10 +1263,13 @@ void Disambiguate(board, flags, epfile, closure)
            closure->kind = IllegalMove;\r
        }\r
     }\r
+#if 0\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate C:   %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                          closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                          closure->promoCharIn,closure->promoCharIn);\r
     }\r
+#endif\r
     /* [HGM] returns 'q' for optional promotion, 'n' for mandatory */\r
     if(closure->promoCharIn != '=')\r
         closure->promoChar = ToLower(PieceToChar(PromoPiece(closure->kind)));\r
@@ -1234,7 +1321,10 @@ void CoordsToAlgebraicCallback(board, flags, kind, rf, ff, rt, ft, closure)
       (CoordsToAlgebraicClosure *) closure;\r
 \r
     if (rt == cl->rt && ft == cl->ft &&\r
-       board[rf][ff] == cl->piece) {\r
+        (board[rf][ff] == cl->piece\r
+         || PieceToChar(board[rf][ff]) == '~' &&\r
+            (ChessSquare) (DEMOTED board[rf][ff]) == cl->piece)\r
+                                     ) {\r
        if (rf == cl->rf) {\r
            if (ff == cl->ff) {\r
                cl->kind = kind; /* this is the move we want */\r
@@ -1264,7 +1354,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
 {\r
     ChessSquare piece;\r
     ChessMove kind;\r
-    char *outp = out;\r
+    char *outp = out, c;\r
     CoordsToAlgebraicClosure cl;\r
     \r
     if (rf == DROP_RANK) {\r
@@ -1276,20 +1366,18 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
            *outp++ = rt + ONE;\r
         else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }\r
        *outp = NULLCHAR;\r
-        AlphaRank(out, 5);\r
        return (flags & F_WHITE_ON_MOVE) ? WhiteDrop : BlackDrop;\r
     }\r
 \r
     if (promoChar == 'x') promoChar = NULLCHAR;\r
     piece = board[rf][ff];\r
+    if(PieceToChar(piece)=='~') piece = (ChessSquare)(DEMOTED piece);\r
 \r
   if (appData.debugMode)\r
-          fprintf(debugFP, "CoordsToAlgebraic, piece=%d\n", (int)piece);\r
+          fprintf(debugFP, "CoordsToAlgebraic, piece=%d (%d,%d)-(%d,%d) %c\n", (int)piece,ff,rf,ft,rt,promoChar );\r
     switch (piece) {\r
       case WhitePawn:\r
       case BlackPawn:\r
-  if (appData.debugMode)\r
-          fprintf(debugFP, "CoordsToAlgebraic, Pawn\n");\r
         kind = LegalityTest(board, flags, epfile, initialRights, rf, ff, rt, ft, promoChar);\r
        if (kind == IllegalMove && !(flags&F_IGNORE_CHECK)) {\r
            /* Keep short notation if move is illegal only because it\r
@@ -1317,6 +1405,8 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
        }\r
        /* Use promotion suffix style "=Q" */\r
        *outp = NULLCHAR;\r
+  if (appData.debugMode)\r
+          fprintf(debugFP, "movetype=%d, promochar=%d=%c\n", (int)kind, promoChar, promoChar);\r
         if (promoChar != NULLCHAR) {\r
             if(gameInfo.variant == VariantShogi) {\r
                 /* [HGM] ... but not in Shogi! */\r
@@ -1327,7 +1417,6 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
             }\r
             *outp = NULLCHAR;\r
        }\r
-        AlphaRank(out, 10);\r
         return kind;\r
 \r
        \r
@@ -1393,13 +1482,14 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
           else "N1f3" or "N5xf7",\r
           else "Ng1f3" or "Ng5xf7".\r
        */\r
-        if(PieceToChar(piece) == '.') {\r
+        c = PieceToChar(piece) ;\r
+        if( c == '~' || c == '+') {\r
            /* [HGM] print nonexistent piece as its demoted version */\r
            piece = (ChessSquare) (DEMOTED piece);\r
-           if( gameInfo.variant == VariantShogi )\r
-                *outp++ = '+';\r
         }\r
+        if(c=='+') *outp++ = c;\r
         *outp++ = ToUpper(PieceToChar(piece));\r
+\r
        if (cl.file || (cl.either && !cl.rank)) {\r
             *outp++ = ff + AAA;\r
        }\r
@@ -1454,12 +1544,15 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
                 }\r
             }\r
         }\r
-        AlphaRank(out, 10);\r
         return cl.kind;\r
        \r
       /* [HGM] Always long notation for fairies we don't know */\r
-      case WhiteNightrider:\r
-      case BlackNightrider:\r
+      case WhiteFalcon:\r
+      case BlackFalcon:\r
+      case WhiteSilver:\r
+      case BlackSilver:\r
+      case WhiteLance:\r
+      case BlackLance:\r
       case WhiteGrasshopper:\r
       case BlackGrasshopper:\r
       case EmptySquare:\r
@@ -1495,7 +1588,6 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
     }\r
     *outp = NULLCHAR;\r
 \r
-    AlphaRank(out, 0);\r
     return IllegalMove;\r
 }\r
 \r