updated INSTALL, NEWS and other files for new release
[xboard.git] / moves.c
diff --git a/moves.c b/moves.c
index 57e350e..eb0701c 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -117,144 +117,100 @@ ChessSquare PromoPiece(moveType)
        return WhiteKing;\r
       case BlackPromotionKing:\r
        return BlackKing;\r
-#ifdef FAIRY\r
       case WhitePromotionChancellor:\r
-        return WhiteFairyRook;\r
+        return WhiteMarshall;\r
       case BlackPromotionChancellor:\r
-        return BlackFairyRook;\r
+        return BlackMarshall;\r
       case WhitePromotionArchbishop:\r
-        return WhiteFairyBishop;\r
+        return WhiteAngel;\r
       case BlackPromotionArchbishop:\r
-        return BlackFairyBishop;\r
-#endif\r
-    }\r
-}\r
-\r
-ChessMove PromoCharToMoveType(whiteOnMove, promoChar)\r
-     int whiteOnMove;\r
-     int promoChar;\r
-{\r
-    if (whiteOnMove) {\r
-       switch (promoChar) {\r
-         case 'n':\r
-         case 'N':\r
-           return WhitePromotionKnight;\r
-         case 'b':\r
-         case 'B':\r
-           return WhitePromotionBishop;\r
-         case 'r':\r
-         case 'R':\r
-           return WhitePromotionRook;\r
-#ifdef FAIRY\r
-          case 'a':\r
-          case 'A':\r
-            return WhitePromotionArchbishop;\r
-          case 'c':\r
-          case 'C':\r
-            return WhitePromotionChancellor;\r
-#endif\r
-         case 'q':\r
-         case 'Q':\r
-           return WhitePromotionQueen;\r
-         case 'k':\r
-         case 'K':\r
-           return WhitePromotionKing;\r
-         case NULLCHAR:\r
-         default:\r
-           return NormalMove;\r
-       }\r
-    } else {\r
-       switch (promoChar) {\r
-         case 'n':\r
-         case 'N':\r
-           return BlackPromotionKnight;\r
-         case 'b':\r
-         case 'B':\r
-           return BlackPromotionBishop;\r
-         case 'r':\r
-         case 'R':\r
-           return BlackPromotionRook;\r
-#ifdef FAIRY\r
-          case 'a':\r
-          case 'A':\r
-            return BlackPromotionArchbishop;\r
-          case 'c':\r
-          case 'C':\r
-            return BlackPromotionChancellor;\r
-#endif\r
-         case 'q':\r
-         case 'Q':\r
-           return BlackPromotionQueen;\r
-         case 'k':\r
-         case 'K':\r
-           return BlackPromotionKing;\r
-         case NULLCHAR:\r
-         default:\r
-           return NormalMove;\r
-       }\r
+        return BlackAngel;\r
+      case WhitePromotionCentaur:\r
+        return WhiteSilver;\r
+      case BlackPromotionCentaur:\r
+        return BlackSilver;\r
     }\r
 }\r
 \r
 char pieceToChar[] = {\r
-    'P', 'N', 'B', 'R', \r
-#ifdef FAIRY\r
-    'A', 'C', 'F', 'H', 'E', 'W', 'D', 'O', 'G', 'M',\r
-#endif\r
-    'Q', 'K', 'p', 'n', 'b', 'r', \r
-#ifdef FAIRY            \r
-    'a', 'c', 'f', 'h', 'e', 'w', 'd', 'o', 'g', 'm',\r
-#endif\r
-    'q', 'k', 'x'\r
-  };\r
+                        'P', 'N', 'B', 'R', 'Q', 'F', 'E', 'A', 'C', 'W', 'M', \r
+                        'O', 'H', 'I', 'J', 'G', 'D', 'V', 'L', 's', 'U', 'K',\r
+                        'p', 'n', 'b', 'r', 'q', 'f', 'e', 'a', 'c', 'w', 'm', \r
+                        'o', 'h', 'i', 'j', 'g', 'd', 'v', 'l', 's', 'u', 'k', \r
+                        'x' };\r
 \r
 char PieceToChar(p)\r
      ChessSquare p;\r
 {\r
+    if((int)p < 0 || (int)p >= (int)EmptySquare) return('x'); /* [HGM] for safety */\r
     return pieceToChar[(int) p];\r
 }\r
 \r
+int PieceToNumber(p)  /* [HGM] holdings: count piece type, ignoring non-participating piece types */\r
+     ChessSquare p;\r
+{\r
+    int i=0;\r
+    ChessSquare start = (int)p >= (int)BlackPawn ? BlackPawn : WhitePawn;\r
+\r
+    while(start++ != p) if(pieceToChar[(int)start-1] != '.') i++;\r
+    return i;\r
+}\r
+\r
 ChessSquare CharToPiece(c)\r
      int c;\r
-{    switch (c) {\r
-      default:\r
-      case 'x':        return EmptySquare;\r
-      case 'P':        return WhitePawn;\r
-      case 'R':        return WhiteRook;\r
-      case 'N':        return WhiteKnight;\r
-      case 'B':        return WhiteBishop;\r
-      case 'Q':        return WhiteQueen;\r
-      case 'K':        return WhiteKing;\r
-      case 'p':        return BlackPawn;\r
-      case 'r':        return BlackRook;\r
-      case 'n':        return BlackKnight;\r
-      case 'b':        return BlackBishop;\r
-      case 'q':        return BlackQueen;\r
-      case 'k':        return BlackKing;\r
-#ifdef FAIRY\r
-      case 'A': return WhiteCardinal;\r
-      case 'C': return WhiteMarshall;\r
-      case 'F': return WhiteFairyPawn;\r
-      case 'H': return WhiteFairyKnight;\r
-      case 'E': return WhiteFairyBishop;\r
-      case 'W': return WhiteFairyRook;\r
-      case 'D': return WhiteFairyCardinal;\r
-      case 'O': return WhiteFairyMarshall;\r
-      case 'G': return WhiteFairyQueen;\r
-      case 'M': return WhiteFairyKing;\r
-                \r
-      case 'a': return BlackCardinal;\r
-      case 'c': return BlackMarshall;\r
-      case 'f': return BlackFairyPawn;\r
-      case 'h': return BlackFairyKnight;\r
-      case 'e': return BlackFairyBishop;\r
-      case 'w': return BlackFairyRook;\r
-      case 'd': return BlackFairyCardinal;\r
-      case 'o': return BlackFairyMarshall;\r
-      case 'g': return BlackFairyQueen;\r
-      case 'm': return BlackFairyKing;\r
-                \r
-#endif\r
-    }\r
+{\r
+     int i;\r
+     for(i=0; i< (int) EmptySquare; i++)\r
+          if(pieceToChar[i] == c) return (ChessSquare) i;\r
+     return EmptySquare;\r
+}\r
+\r
+ChessMove PromoCharToMoveType(whiteOnMove, promoChar)\r
+     int whiteOnMove;\r
+     int promoChar;\r
+{      /* [HGM] made dependent on CharToPiece to alow alternate piece letters */\r
+       ChessSquare piece = CharToPiece(whiteOnMove ? ToUpper(promoChar) : ToLower(promoChar) );\r
+\r
+
+       if(promoChar == NULLCHAR) return NormalMove;\r
+\r
+       switch(piece) {\r
+               case WhiteQueen:\r
+                       return WhitePromotionQueen;\r
+               case WhiteRook:\r
+                       return WhitePromotionRook;\r
+               case WhiteBishop:\r
+                       return WhitePromotionBishop;\r
+               case WhiteKnight:\r
+                       return WhitePromotionKnight;\r
+               case WhiteKing:\r
+                       return WhitePromotionKing;\r
+               case WhiteAngel:\r
+                       return WhitePromotionArchbishop;\r
+               case WhiteMarshall:\r
+                       return WhitePromotionChancellor;\r
+               case WhiteSilver:\r
+                       return WhitePromotionCentaur;\r
+               case BlackQueen:\r
+                       return BlackPromotionQueen;\r
+               case BlackRook:\r
+                       return BlackPromotionRook;\r
+               case BlackBishop:\r
+                       return BlackPromotionBishop;\r
+               case BlackKnight:\r
+                       return BlackPromotionKnight;\r
+               case BlackKing:\r
+                       return BlackPromotionKing;\r
+               case BlackAngel:\r
+                       return BlackPromotionArchbishop;\r
+               case BlackMarshall:\r
+                       return BlackPromotionChancellor;\r
+               case BlackSilver:\r
+                       return BlackPromotionCentaur;\r
+               default:\r
+                       // not all promotion implemented yet! Take Queen for those we don't know.\r
+                       return (whiteOnMove ? WhitePromotionQueen : BlackPromotionQueen);\r
+       }\r
 }\r
 \r
 void CopyBoard(to, from)\r
@@ -300,21 +256,27 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
     int i, j, d, s, fs, rs, rt, ft, m;\r
 \r
     for (rf = 0; rf < BOARD_HEIGHT; rf++) \r
-      for (ff = 0; ff < BOARD_WIDTH; ff++) {\r
+      for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) {\r
+          ChessSquare piece;\r
+\r
          if (flags & F_WHITE_ON_MOVE) {\r
              if (!WhitePiece(board[rf][ff])) continue;\r
          } else {\r
              if (!BlackPiece(board[rf][ff])) continue;\r
          }\r
-          m = 0;\r
-         switch (board[rf][ff]) {\r
-           case EmptySquare:\r
+          m = 0; piece = board[rf][ff];\r
+          if(PieceToChar(piece) == '~') \r
+                 piece = (ChessSquare) ( DEMOTED piece );\r
+          if(gameInfo.variant == VariantShogi)\r
+                 piece = (ChessSquare) ( SHOGI piece );\r
+\r
+          switch (piece) {\r
+            /* case EmptySquare: [HGM] this is nonsense, and conflicts with Shogi cases */\r
            default:\r
              /* can't happen ([HGM] except for faries...) */\r
              break;\r
 \r
-           case WhitePawn:\r
-#ifdef FAIRY\r
+             case WhitePawn:\r
               if(gameInfo.variant == VariantXiangqi) {\r
                   /* [HGM] capture and move straight ahead in Xiangqi */\r
                   if (rf < BOARD_HEIGHT-1 &&\r
@@ -325,7 +287,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                   /* and move sideways when across the river */\r
                   for (s = -1; s <= 1; s += 2) {\r
                       if (rf >= BOARD_HEIGHT>>1 &&\r
-                          ff + s >= 0 && ff + s < BOARD_WIDTH &&\r
+                          ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
                           !WhitePiece(board[rf][ff+s]) ) {\r
                            callback(board, flags, NormalMove,\r
                                     rf, ff, rf, ff+s, closure);\r
@@ -333,7 +295,6 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                   }\r
                   break;\r
               }\r
-#endif\r
               if (rf < BOARD_HEIGHT-1 && board[rf + 1][ff] == EmptySquare) {\r
                  callback(board, flags,\r
                           rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : NormalMove,\r
@@ -341,12 +302,13 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              }\r
              if (rf == 1 && board[2][ff] == EmptySquare &&\r
                   gameInfo.variant != VariantShatranj && /* [HGM] */\r
+                  gameInfo.variant != VariantCourier  && /* [HGM] */\r
                   board[3][ff] == EmptySquare ) {\r
                       callback(board, flags, NormalMove,\r
                                rf, ff, 3, ff, closure);\r
              }\r
              for (s = -1; s <= 1; s += 2) {\r
-                 if (rf < BOARD_HEIGHT-1 && ff + s >= 0 && ff + s < BOARD_WIDTH &&\r
+                  if (rf < BOARD_HEIGHT-1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
                      ((flags & F_KRIEGSPIEL_CAPTURE) ||\r
                       BlackPiece(board[rf + 1][ff + s]))) {\r
                      callback(board, flags, \r
@@ -354,7 +316,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                               rf, ff, rf + 1, ff + s, closure);\r
                  }\r
                  if (rf == BOARD_HEIGHT-4) {\r
-                     if (ff + s >= 0 && ff + s < BOARD_WIDTH &&\r
+                      if (ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
                          (epfile == ff + s || epfile == EP_UNKNOWN) &&\r
                           board[BOARD_HEIGHT-4][ff + s] == BlackPawn &&\r
                           board[BOARD_HEIGHT-3][ff + s] == EmptySquare) {\r
@@ -366,7 +328,6 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              break;\r
 \r
            case BlackPawn:\r
-#ifdef FAIRY\r
               if(gameInfo.variant == VariantXiangqi) {\r
                   /* [HGM] capture straight ahead in Xiangqi */\r
                   if (rf > 0 && !SameColor(board[rf][ff], board[rf - 1][ff]) ) {\r
@@ -376,7 +337,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                   /* and move sideways when across the river */\r
                   for (s = -1; s <= 1; s += 2) {\r
                       if (rf < BOARD_HEIGHT>>1 &&\r
-                          ff + s >= 0 && ff + s < BOARD_WIDTH &&\r
+                          ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
                           !BlackPiece(board[rf][ff+s]) ) {\r
                            callback(board, flags, NormalMove,\r
                                     rf, ff, rf, ff+s, closure);\r
@@ -384,7 +345,6 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                   }\r
                   break;\r
               }\r
-#endif\r
              if (rf > 0 && board[rf - 1][ff] == EmptySquare) {\r
                  callback(board, flags, \r
                           rf == 1 ? BlackPromotionQueen : NormalMove,\r
@@ -392,12 +352,13 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              }\r
              if (rf == BOARD_HEIGHT-2 && board[BOARD_HEIGHT-3][ff] == EmptySquare &&\r
                   gameInfo.variant != VariantShatranj && /* [HGM] */\r
+                  gameInfo.variant != VariantCourier  && /* [HGM] */\r
                  board[BOARD_HEIGHT-4][ff] == EmptySquare) {\r
                  callback(board, flags, NormalMove,\r
                           rf, ff, BOARD_HEIGHT-4, ff, closure);\r
              }\r
              for (s = -1; s <= 1; s += 2) {\r
-                 if (rf > 0 && ff + s >= 0 && ff + s < BOARD_WIDTH &&\r
+                  if (rf > 0 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
                      ((flags & F_KRIEGSPIEL_CAPTURE) ||\r
                       WhitePiece(board[rf - 1][ff + s]))) {\r
                      callback(board, flags, \r
@@ -405,7 +366,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                               rf, ff, rf - 1, ff + s, closure);\r
                  }\r
                  if (rf == 3) {\r
-                      if (ff + s >= 0 && ff + s < BOARD_WIDTH &&\r
+                      if (ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
                          (epfile == ff + s || epfile == EP_UNKNOWN) &&\r
                          board[3][ff + s] == WhitePawn &&\r
                          board[2][ff + s] == EmptySquare) {\r
@@ -416,6 +377,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              }             \r
              break;\r
 \r
+            case WhiteUnicorn:\r
+            case BlackUnicorn:\r
            case WhiteKnight:\r
            case BlackKnight:\r
             mounted:\r
@@ -424,22 +387,43 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                  for (s = 1; s <= 2; s++) {\r
                      rt = rf + i*s;\r
                      ft = ff + j*(3-s);\r
-                     if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) continue;\r
-                     if (SameColor(board[rf][ff], board[rt][ft])) continue;\r
+                      if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)\r
+                          && ( gameInfo.variant != VariantXiangqi || board[rf+i*(s-1)][ff+j*(2-s)] == EmptySquare)\r
+                          && !SameColor(board[rf][ff], board[rt][ft]))\r
                      callback(board, flags, NormalMove,\r
                               rf, ff, rt, ft, closure);\r
                  }\r
              break;\r
-#ifdef FAIRY\r
-            case WhiteFairyMarshall:\r
-            case BlackFairyMarshall:\r
+\r
+            case SHOGI WhiteKnight:\r
+             for (s = -1; s <= 1; s += 2) {\r
+                  if (rf < BOARD_HEIGHT-2 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
+                      !SameColor(board[rf][ff], board[rf + 2][ff + s])) {\r
+                      callback(board, flags, NormalMove,\r
+                               rf, ff, rf + 2, ff + s, closure);\r
+                 }\r
+              }\r
+             break;\r
+\r
+            case SHOGI BlackKnight:\r
+             for (s = -1; s <= 1; s += 2) {\r
+                  if (rf > 1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
+                      !SameColor(board[rf][ff], board[rf - 2][ff + s])) {\r
+                      callback(board, flags, NormalMove,\r
+                               rf, ff, rf - 2, ff + s, closure);\r
+                 }\r
+             }             \r
+             break;\r
+\r
+            case WhiteCannon:\r
+            case BlackCannon:\r
               for (d = 0; d <= 1; d++)\r
                 for (s = -1; s <= 1; s += 2) {\r
                   m = 0;\r
                  for (i = 1;; i++) {\r
                      rt = rf + (i * s) * d;\r
                      ft = ff + (i * s) * (1 - d);\r
-                     if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break;\r
+                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;\r
                       if (m == 0 && board[rt][ft] == EmptySquare)\r
                                  callback(board, flags, NormalMove,\r
                                           rf, ff, rt, ft, closure);\r
@@ -452,36 +436,80 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                 }\r
              break;\r
 \r
-            case WhiteFairyRook:\r
-            case BlackFairyRook:\r
+            /* Gold General (and all its promoted versions) . First do the */\r
+            /* diagonal forward steps, then proceed as normal Wazir        */\r
+            case SHOGI WhiteWazir:\r
+            case SHOGI (PROMOTED WhitePawn):\r
+            case SHOGI (PROMOTED WhiteKnight):\r
+            case SHOGI (PROMOTED WhiteQueen):\r
+            case SHOGI (PROMOTED WhiteFerz):\r
+             for (s = -1; s <= 1; s += 2) {\r
+                  if (rf < BOARD_HEIGHT-1 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
+                      !SameColor(board[rf][ff], board[rf + 1][ff + s])) {\r
+                      callback(board, flags, NormalMove,\r
+                              rf, ff, rf + 1, ff + s, closure);\r
+                 }\r
+              }\r
+              goto finishGold;\r
+\r
+            case SHOGI BlackWazir:\r
+            case SHOGI (PROMOTED BlackPawn):\r
+            case SHOGI (PROMOTED BlackKnight):\r
+            case SHOGI (PROMOTED BlackQueen):\r
+            case SHOGI (PROMOTED BlackFerz):\r
+             for (s = -1; s <= 1; s += 2) {\r
+                  if (rf > 0 && ff + s >= BOARD_LEFT && ff + s < BOARD_RGHT &&\r
+                      !SameColor(board[rf][ff], board[rf - 1][ff + s])) {\r
+                      callback(board, flags, NormalMove,\r
+                              rf, ff, rf - 1, ff + s, closure);\r
+                 }\r
+             }             \r
+\r
+            case WhiteWazir:\r
+            case BlackWazir:\r
+            finishGold:\r
               for (d = 0; d <= 1; d++)\r
-                for (s = -1; s <= 1; s += 2)\r
+                for (s = -1; s <= 1; s += 2) {\r
                       rt = rf + s * d;\r
                       ft = ff + s * (1 - d);\r
-                      if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH)\r
-                          && !SameColor(board[rf][ff], board[rt][ft]))\r
+                      if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)\r
+                          && !SameColor(board[rf][ff], board[rt][ft]) &&\r
+                          (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) )\r
                                callback(board, flags, NormalMove,\r
                                         rf, ff, rt, ft, closure);\r
+                      }\r
              break;\r
 \r
-           case WhiteFairyBishop:\r
-           case BlackFairyBishop:\r
+            case WhiteAlfil:\r
+            case BlackAlfil:\r
                 /* [HGM] support Shatranj pieces */\r
                 for (rs = -1; rs <= 1; rs += 2) \r
                   for (fs = -1; fs <= 1; fs += 2) {\r
                       rt = rf + 2 * rs;\r
                       ft = ff + 2 * fs;\r
-                      if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH)\r
+                      if (!(rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT)\r
+                          && ( gameInfo.variant != VariantXiangqi ||\r
+                               board[rf+rs][ff+fs] == EmptySquare && (2*rf < BOARD_HEIGHT) == (2*rt < BOARD_HEIGHT) )\r
+                         \r
                           && !SameColor(board[rf][ff], board[rt][ft]))\r
                                callback(board, flags, NormalMove,\r
                                         rf, ff, rt, ft, closure);\r
                  }\r
                 break;\r
 \r
-            case WhiteCardinal:\r
-            case BlackCardinal:\r
+            /* Shogi Dragon Horse has to continue with Wazir after Bishop */\r
+            case SHOGI WhiteCardinal:\r
+            case SHOGI BlackCardinal:\r
               m++;\r
-#endif\r
+\r
+            /* Capablanca Archbishop continues as Knight                  */\r
+            case WhiteAngel:\r
+            case BlackAngel:\r
+              m++;\r
+\r
+            /* Shogi Bishops are ordinary Bishops */\r
+            case SHOGI WhiteBishop:\r
+            case SHOGI BlackBishop:\r
            case WhiteBishop:\r
            case BlackBishop:\r
              for (rs = -1; rs <= 1; rs += 2) \r
@@ -489,20 +517,55 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                  for (i = 1;; i++) {\r
                      rt = rf + (i * rs);\r
                      ft = ff + (i * fs);\r
-                     if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break;\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
-                if(m) goto mounted;\r
+                if(m==1) goto mounted;\r
+                if(m==2) goto finishGold;\r
+                /* Bishop falls through */\r
              break;\r
 \r
-#ifdef FAIRY\r
+            /* Shogi Lance is unlike anything, and asymmetric at that */\r
+            case SHOGI WhiteQueen:\r
+              for(i = 1;; i++) {\r
+                      rt = rf + i;\r
+                      ft = ff;\r
+                      if (rt >= BOARD_HEIGHT) 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
+              break;\r
+\r
+            case SHOGI BlackQueen:\r
+              for(i = 1;; i++) {\r
+                      rt = rf - i;\r
+                      ft = ff;\r
+                      if (rt < 0) 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
+              break;\r
+\r
+            /* Shogi Dragon King has to continue as Ferz after Rook moves */\r
+            case SHOGI WhiteDragon:\r
+            case SHOGI BlackDragon:\r
+              m++;\r
+\r
+            /* Capablanca Chancellor sets flag to continue as Knight      */\r
             case WhiteMarshall:\r
             case BlackMarshall:\r
               m++;\r
-#endif\r
+\r
+            /* Shogi Rooks are ordinary Rooks */\r
+            case SHOGI WhiteRook:\r
+            case SHOGI BlackRook:\r
            case WhiteRook:\r
            case BlackRook:\r
               for (d = 0; d <= 1; d++)\r
@@ -510,13 +573,14 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                  for (i = 1;; i++) {\r
                      rt = rf + (i * s) * d;\r
                      ft = ff + (i * s) * (1 - d);\r
-                     if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break;\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
-                if(m) goto mounted;\r
+                if(m==1) goto mounted;\r
+                if(m==2) goto finishGold;\r
              break;\r
 \r
            case WhiteQueen:\r
@@ -527,7 +591,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                    for (i = 1;; i++) {\r
                        rt = rf + (i * rs);\r
                        ft = ff + (i * fs);\r
-                       if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break;\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
@@ -536,37 +600,81 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                }\r
              break;\r
 \r
-#ifdef FAIRY\r
-            case WhiteFairyPawn:\r
-            case BlackFairyPawn:\r
+            /* Shogi Pawn and Silver General: first the Pawn move,    */\r
+            /* then the General continues like a Ferz                 */\r
+            case SHOGI WhitePawn:\r
+            case SHOGI WhiteFerz:\r
+                  if (rf < BOARD_HEIGHT-1 &&\r
+                           !SameColor(board[rf][ff], board[rf + 1][ff]) ) \r
+                           callback(board, flags, NormalMove,\r
+                                    rf, ff, rf + 1, ff, closure);\r
+              if(piece != SHOGI WhitePawn) goto finishSilver;\r
+              break;\r
+\r
+            case SHOGI BlackPawn:\r
+            case SHOGI BlackFerz:\r
+                  if (rf > 0 &&\r
+                           !SameColor(board[rf][ff], board[rf - 1][ff]) ) \r
+                           callback(board, flags, NormalMove,\r
+                                    rf, ff, rf - 1, ff, closure);\r
+              if(piece == SHOGI BlackPawn) break;\r
+\r
+            case WhiteFerz:\r
+            case BlackFerz:\r
+            finishSilver:\r
                 /* [HGM] support Shatranj pieces */\r
                 for (rs = -1; rs <= 1; rs += 2) \r
                   for (fs = -1; fs <= 1; fs += 2) {\r
                       rt = rf + rs;\r
                       ft = ff + fs;\r
-                     if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) break;\r
-                      if (!SameColor(board[rf][ff], board[rt][ft]))\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
                                         rf, ff, rt, ft, closure);\r
                  }\r
                 break;\r
 \r
-            case WhiteFairyKing:\r
-            case BlackFairyKing:\r
-#endif\r
+           case WhiteSilver:\r
+           case BlackSilver:\r
+               m++; // [HGM] superchess: use for Centaur\r
+            case WhiteMan:\r
+            case BlackMan:\r
+            case SHOGI WhiteKing:\r
+            case SHOGI BlackKing:\r
            case WhiteKing:\r
            case BlackKing:\r
+            walking:\r
              for (i = -1; i <= 1; i++)\r
                for (j = -1; j <= 1; j++) {\r
                    if (i == 0 && j == 0) continue;\r
                    rt = rf + i;\r
                    ft = ff + j;\r
-                   if (rt < 0 || rt >= BOARD_HEIGHT || ft < 0 || ft >= BOARD_WIDTH) continue;\r
+                    if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;\r
                    if (SameColor(board[rf][ff], board[rt][ft])) continue;\r
                    callback(board, flags, NormalMove,\r
                             rf, ff, rt, ft, closure);\r
                }\r
+               if(m==1) goto mounted;\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
@@ -602,7 +710,7 @@ void GenLegalCallback(board, flags, kind, rf, ff, rt, ft, closure)
        if (board[rf][ff] == king) return;\r
        for (r = rt-1; r <= rt+1; r++) {\r
          for (f = ft-1; f <= ft+1; f++) {\r
-           if (r >= 0 && r < BOARD_HEIGHT && f >= 0 && f < BOARD_WIDTH &&\r
+            if (r >= 0 && r < BOARD_HEIGHT && f >= BOARD_LEFT && f < BOARD_RGHT &&\r
                board[r][f] == king) return;\r
          }\r
        }\r
@@ -634,8 +742,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
@@ -645,120 +754,156 @@ 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 + 1] == EmptySquare &&\r
-           board[0][ff + 2] == EmptySquare &&\r
-           board[0][BOARD_WIDTH-3] == EmptySquare &&\r
-           board[0][BOARD_WIDTH-2] == EmptySquare &&\r
-           board[0][BOARD_WIDTH-1] == WhiteRook &&\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
+            board[0][BOARD_RGHT-2] == EmptySquare &&\r
+            board[0][BOARD_RGHT-1] == WhiteRook &&\r
             castlingRights[0] >= 0 && /* [HGM] check rights */\r
             ( castlingRights[2] == ff || castlingRights[6] == ff ) &&\r
             (ignoreCheck ||                             \r
             (!CheckTest(board, flags, 0, ff, 0, ff + 1, FALSE) &&\r
-             !CheckTest(board, flags, 0, ff, 0, BOARD_WIDTH-3, FALSE) &&\r
+              !CheckTest(board, flags, 0, ff, 0, BOARD_RGHT-3, FALSE) &&\r
+              (gameInfo.variant != VariantJanus || !CheckTest(board, flags, 0, ff, 0, BOARD_RGHT-2, FALSE)) &&\r
              !CheckTest(board, flags, 0, ff, 0, ff + 2, FALSE)))) {\r
 \r
            callback(board, flags,\r
-                    ff==4 ? WhiteKingSideCastle : WhiteKingSideCastleWild,\r
-                    0, ff, 0, ff + ((BOARD_WIDTH+2)>>2), closure);\r
+                     ff==BOARD_WIDTH>>1 ? WhiteKingSideCastle : WhiteKingSideCastleWild,\r
+                     0, ff, 0, ff + ((gameInfo.boardWidth+2)>>2) + (gameInfo.variant == VariantJanus), closure);\r
        }\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][2] == EmptySquare &&\r
-           board[0][1] == EmptySquare &&\r
-            board[0][0] == WhiteRook &&\r
+            board[0][BOARD_LEFT+2] == EmptySquare &&\r
+            board[0][BOARD_LEFT+1] == EmptySquare &&\r
+            board[0][BOARD_LEFT+0] == WhiteRook &&\r
             castlingRights[1] >= 0 && /* [HGM] check rights */\r
             ( castlingRights[2] == ff || castlingRights[6] == ff ) &&\r
            (ignoreCheck ||\r
             (!CheckTest(board, flags, 0, ff, 0, ff - 1, FALSE) &&\r
-             !CheckTest(board, flags, 0, ff, 0, 3,      FALSE) &&\r
+              !CheckTest(board, flags, 0, ff, 0, BOARD_LEFT+3, FALSE) &&\r
              !CheckTest(board, flags, 0, ff, 0, ff - 2, FALSE)))) {\r
 \r
            callback(board, flags,\r
                     ff==BOARD_WIDTH>>1 ? WhiteQueenSideCastle : WhiteQueenSideCastleWild,\r
-                    0, ff, 0, ff - ((BOARD_WIDTH+2)>>2), closure);\r
+                     0, ff, 0, ff - ((gameInfo.boardWidth+2)>>2), closure);\r
        }\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_WIDTH-3] == EmptySquare &&\r
-           board[BOARD_HEIGHT-1][BOARD_WIDTH-2] == EmptySquare &&\r
-           board[BOARD_HEIGHT-1][BOARD_WIDTH-1] == BlackRook &&\r
+            board[BOARD_HEIGHT-1][BOARD_RGHT-3] == EmptySquare &&\r
+            board[BOARD_HEIGHT-1][BOARD_RGHT-2] == EmptySquare &&\r
+            board[BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook &&\r
             castlingRights[3] >= 0 && /* [HGM] check rights */\r
             ( castlingRights[5] == ff || castlingRights[7] == ff ) &&\r
            (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_WIDTH-3, FALSE) &&\r
+              !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_RGHT-3, FALSE) &&\r
+              (gameInfo.variant != VariantJanus || !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_RGHT-2, 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 ? BlackKingSideCastle : BlackKingSideCastleWild,\r
-                    BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + ((BOARD_WIDTH+2)>>2), closure);\r
+                     BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + ((gameInfo.boardWidth+2)>>2) + (gameInfo.variant == VariantJanus), closure);\r
        }\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][2] == EmptySquare &&\r
-           board[BOARD_HEIGHT-1][1] == EmptySquare &&\r
-           board[BOARD_HEIGHT-1][0] == BlackRook &&\r
+            board[BOARD_HEIGHT-1][BOARD_LEFT+2] == EmptySquare &&\r
+            board[BOARD_HEIGHT-1][BOARD_LEFT+1] == EmptySquare &&\r
+            board[BOARD_HEIGHT-1][BOARD_LEFT+0] == BlackRook &&\r
             castlingRights[4] >= 0 && /* [HGM] check rights */\r
             ( castlingRights[5] == ff || castlingRights[7] == ff ) &&\r
            (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, 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, BOARD_LEFT+3, 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
-                    BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - ((BOARD_WIDTH+2)>>2), closure);\r
+                     BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - ((gameInfo.boardWidth+2)>>2), closure);\r
        }\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
+    /* [HGM] test if the Rooks we find have castling rights */\r
 \r
-    if ((flags & F_WHITE_ON_MOVE) != 0) {\r
-\r
-       for (ff = 1; ff < BOARD_WIDTH-1; ff++) {\r
-          if (board[0][ff] == WhiteKing) {\r
-             for (ft = 0; ft < BOARD_WIDTH; 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 && board[0][ff] == WhiteKing) {\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 && board[0][ft] == WhiteRook)\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
+            if(ft >= 0 && board[0][ft] == WhiteRook)\r
+                callback(board, flags, WhiteASideCastleFR, 0, ff, 0, ft, closure);\r
+        }\r
     } else {\r
-\r
-       for (ff = 1; ff < BOARD_WIDTH-1; ff++) {\r
-          if (board[BOARD_HEIGHT-1][ff] == BlackKing) {\r
-             for (ft = 0; ft < BOARD_WIDTH; 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 && board[BOARD_HEIGHT-1][ff] == BlackKing) {\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 && board[BOARD_HEIGHT-1][ft] == BlackRook)\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
+            if(ft >= 0 && board[BOARD_HEIGHT-1][ft] == BlackRook)\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
@@ -805,6 +950,11 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant)
     ChessSquare captured = EmptySquare;\r
     /*  Suppress warnings on uninitialized variables    */\r
 \r
+    if(gameInfo.variant == VariantXiangqi)\r
+        king = flags & F_WHITE_ON_MOVE ? WhiteWazir : BlackWazir;\r
+    if(gameInfo.variant == VariantKnightmate)\r
+        king = flags & F_WHITE_ON_MOVE ? WhiteUnicorn : BlackUnicorn;\r
+\r
     if (rf >= 0) {\r
        if (enPassant) {\r
            captured = board[rf][ft];\r
@@ -820,9 +970,20 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant)
        order a1, a2, a3, ... b1, b2, ..., h8 to find the first king,\r
        and we test only whether that one is in check. */\r
     cl.check = 0;\r
-    for (cl.fking = 0; cl.fking < BOARD_WIDTH; cl.fking++)\r
+    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 (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
@@ -858,6 +1019,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 (rf == cl->rf && ff == cl->ff && rt == cl->rt && ft == cl->ft)\r
       cl->kind = kind;\r
 }\r
@@ -868,15 +1032,63 @@ 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
     cl.ft = ft;\r
     cl.kind = IllegalMove;\r
     GenLegal(board, flags, epfile, castlingRights, LegalityTestCallback, (VOIDSTAR) &cl);\r
+\r
+    if(gameInfo.variant == VariantShogi) {\r
+        /* [HGM] Shogi promotions. '=' means defer */\r
+        if(rf != DROP_RANK && cl.kind == NormalMove) {\r
+            ChessSquare piece = board[rf][ff];\r
+\r
+            if(promoChar == PieceToChar(BlackQueen)) promoChar = NULLCHAR; /* [HGM] Kludge */\r
+            if(promoChar != NULLCHAR && promoChar != 'x' &&\r
+               promoChar != '+' && promoChar != '=' &&\r
+               ToUpper(PieceToChar(PROMOTED piece)) != ToUpper(promoChar) )\r
+                    cl.kind = IllegalMove;\r
+            else if(flags & F_WHITE_ON_MOVE) {\r
+                if( (int) piece < (int) WhiteWazir &&\r
+                     (rf > BOARD_HEIGHT-4 || rt > BOARD_HEIGHT-4) ) {\r
+                    if( (piece == WhitePawn || piece == WhiteQueen) && rt > BOARD_HEIGHT-2 ||\r
+                         piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */\r
+                             cl.kind = promoChar == '=' ? IllegalMove : WhitePromotionKnight;\r
+                    else /* promotion optional, default is promote */\r
+                             cl.kind = promoChar == '=' ? NormalMove  : WhitePromotionQueen;\r
+                   \r
+                } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?\r
+                                            NormalMove : IllegalMove;\r
+            } else {\r
+                if( (int) piece < (int) BlackWazir && (rf < 3 || rt < 3) ) {\r
+                    if( (piece == BlackPawn || piece == BlackQueen) && rt < 1 ||\r
+                         piece == BlackKnight && rt < 2 ) /* promotion obligatory */\r
+                             cl.kind = promoChar == '=' ? IllegalMove : BlackPromotionKnight;\r
+                    else /* promotion optional, default is promote */\r
+                             cl.kind = promoChar == '=' ? NormalMove  : BlackPromotionQueen;\r
+\r
+                } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?\r
+                                            NormalMove : IllegalMove;\r
+            }\r
+        }\r
+    } else\r
     if (promoChar != NULLCHAR && promoChar != 'x') {\r
+       if(promoChar == '=') cl.kind = IllegalMove; else // [HGM] shogi: no deferred promotion outside Shogi\r
        if (cl.kind == WhitePromotionQueen || cl.kind == BlackPromotionQueen) {\r
            cl.kind = \r
              PromoCharToMoveType((flags & F_WHITE_ON_MOVE) != 0, promoChar);\r
@@ -884,6 +1096,7 @@ ChessMove LegalityTest(board, flags, epfile, castlingRights, rf, ff, rt, ft, pro
            cl.kind = IllegalMove;\r
        }\r
     }\r
+    /* [HGM] For promotions, 'ToQueen' = optional, 'ToKnight' = mandatory */\r
     return cl.kind;\r
 }\r
 \r
@@ -921,7 +1134,8 @@ int MateTest(board, flags, epfile, castlingRights)
     if (cl.count > 0) {\r
        return inCheck ? MT_CHECK : MT_NONE;\r
     } else {\r
-       return inCheck ? MT_CHECKMATE : MT_STALEMATE;\r
+        return inCheck || gameInfo.variant == VariantXiangqi || gameInfo.variant == VariantShatranj ?\r
+                         MT_CHECKMATE : MT_STALEMATE;\r
     }\r
 }\r
 \r
@@ -939,14 +1153,17 @@ 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
        (cl->ftIn == -1 || cl->ftIn == ft)) {\r
 \r
        cl->count++;\r
-       cl->piece = board[rf][ff];\r
+        cl->piece = board[rf][ff];\r
        cl->rf = rf;\r
        cl->ff = ff;\r
        cl->rt = rt;\r
@@ -960,10 +1177,15 @@ void Disambiguate(board, flags, epfile, closure)
      int flags, epfile;\r
      DisambiguateClosure *closure;\r
 {\r
-    int illegal = 0;\r
+    int illegal = 0; char c = closure->promoCharIn;\r
     closure->count = 0;\r
     closure->rf = closure->ff = closure->rt = closure->ft = 0;\r
     closure->kind = ImpossibleMove;\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,\r
+                             closure->promoCharIn, closure->promoCharIn >= ' ' ? closure->promoCharIn : '-');\r
+    }\r
     GenLegal(board, flags, epfile, initialRights, DisambiguateCallback, (VOIDSTAR) closure);\r
     if (closure->count == 0) {\r
        /* See if it's an illegal move due to check */\r
@@ -972,9 +1194,62 @@ void Disambiguate(board, flags, epfile, closure)
                 (VOIDSTAR) closure);   \r
        if (closure->count == 0) {\r
            /* No, it's not even that */\r
+    if (appData.debugMode) { int i, j;\r
+       for(i=BOARD_HEIGHT-1; i>=0; i--) {\r
+               for(j=0; j<BOARD_WIDTH; j++)\r
+                       fprintf(debugFP, "%3d", (int) board[i][j]);\r
+               fprintf(debugFP, "\n");\r
+       }\r
+    }\r
            return;\r
        }\r
     }\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
+#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,\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,\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
+                         piece == WhiteKnight && closure->rt > BOARD_HEIGHT-3) /* promotion mandatory */\r
+                             closure->kind = c == '=' ? IllegalMove : WhitePromotionKnight;\r
+                    else /* promotion optional, default is promote */\r
+                             closure->kind = c == '=' ? NormalMove  : WhitePromotionQueen;\r
+                   \r
+                } else closure->kind = (c == NULLCHAR || c == 'x' || c == '=') ?\r
+                                            NormalMove : IllegalMove;\r
+            } else {\r
+                if( (int) piece < (int) BlackWazir && (closure->rf < 3 || closure->rt < 3) ) {\r
+                    if( (piece == BlackPawn || piece == BlackQueen) && closure->rt < 1 ||\r
+                         piece == BlackKnight && closure->rt < 2 ) /* promotion obligatory */\r
+                             closure->kind = c == '=' ? IllegalMove : BlackPromotionKnight;\r
+                    else /* promotion optional, default is promote */\r
+                             closure->kind = c == '=' ? NormalMove  : BlackPromotionQueen;\r
+\r
+                } else closure->kind = (c == NULLCHAR || c == 'x' || c == '=') ?\r
+                                            NormalMove : IllegalMove;\r
+            }\r
+        }\r
+    } else\r
     if (closure->promoCharIn != NULLCHAR && closure->promoCharIn != 'x') {\r
        if (closure->kind == WhitePromotionQueen\r
            || closure->kind == BlackPromotionQueen) {\r
@@ -985,7 +1260,17 @@ void Disambiguate(board, flags, epfile, closure)
            closure->kind = IllegalMove;\r
        }\r
     }\r
-    closure->promoChar = ToLower(PieceToChar(PromoPiece(closure->kind)));\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,\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(closure->promoCharIn);\r
+    else closure->promoChar = '=';\r
     if (closure->promoChar == 'x') closure->promoChar = NULLCHAR;\r
     if (closure->count > 1) {\r
        closure->kind = AmbiguousMove;\r
@@ -997,6 +1282,14 @@ void Disambiguate(board, flags, epfile, closure)
        */\r
        closure->kind = IllegalMove;\r
     }\r
+    if(closure->kind == IllegalMove)\r
+    /* [HGM] might be a variant we don't understand, pass on promotion info */\r
+        closure->promoChar = ToLower(closure->promoCharIn);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Disambiguate out: %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
+        closure->piece,closure->ff,closure->rf,closure->ft,closure->rt,closure->promoChar,\r
+       closure->promoChar >= ' ' ? closure->promoChar:'-');\r
+    }\r
 }\r
 \r
 \r
@@ -1026,7 +1319,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
@@ -1056,14 +1352,14 @@ 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
        /* Bughouse piece drop */\r
        *outp++ = ToUpper(PieceToChar((ChessSquare) ff));\r
        *outp++ = '@';\r
-       *outp++ = ft + 'a';\r
+        *outp++ = ft + AAA;\r
         if(rt+ONE <= '9')\r
            *outp++ = rt + ONE;\r
         else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }\r
@@ -1073,6 +1369,10 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
 \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 (%d,%d)-(%d,%d) %c\n", (int)piece,ff,rf,ft,rt,promoChar >= ' ' ? promoChar : '-');\r
     switch (piece) {\r
       case WhitePawn:\r
       case BlackPawn:\r
@@ -1086,7 +1386,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
            kind = IllegalMove;\r
        }\r
        /* Pawn move */\r
-       *outp++ = ff + 'a';\r
+        *outp++ = ff + AAA;\r
         if (ff == ft && board[rt][ft] == EmptySquare) { /* [HGM] Xiangqi has straight noncapts! */\r
            /* Non-capture; use style "e5" */\r
             if(rt+ONE <= '9')\r
@@ -1096,18 +1396,26 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
            /* Capture; use style "exd5" */\r
             if(gameInfo.variant != VariantXiangqi || board[rt][ft] != EmptySquare )\r
             *outp++ = 'x';  /* [HGM] Xiangqi has sideway noncaptures across river! */\r
-           *outp++ = ft + 'a';\r
+            *outp++ = ft + AAA;\r
             if(rt+ONE <= '9')\r
                *outp++ = rt + ONE;\r
             else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }\r
        }\r
        /* Use promotion suffix style "=Q" */\r
-       if (promoChar != NULLCHAR && promoChar != 'x') {\r
-           *outp++ = '=';\r
-           *outp++ = ToUpper(promoChar);\r
-       }\r
        *outp = NULLCHAR;\r
-       return kind;\r
+  if (appData.debugMode)\r
+          fprintf(debugFP, "movetype=%d, promochar=%d=%c\n", (int)kind, promoChar, promoChar >= ' ' ? promoChar : '-');\r
+        if (promoChar != NULLCHAR) {\r
+            if(gameInfo.variant == VariantShogi) {\r
+                /* [HGM] ... but not in Shogi! */\r
+                *outp++ = promoChar == '=' ? '=' : '+';\r
+            } else {\r
+                *outp++ = '=';\r
+                *outp++ = ToUpper(promoChar);\r
+            }\r
+            *outp = NULLCHAR;\r
+       }\r
+        return kind;\r
 \r
        \r
       case WhiteKing:\r
@@ -1125,9 +1433,9 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
        /* Use style "O-O" (oh-oh) for PGN compatibility */\r
        else if (rf == rt &&\r
            rf == ((piece == WhiteKing) ? 0 : BOARD_HEIGHT-1) &&\r
-           ((ff == BOARD_WIDTH>>1 && (ft == 2 || ft == BOARD_WIDTH-2)) ||\r
-            (ff == (BOARD_WIDTH-1)>>1 && (ft == 1 || ft == BOARD_WIDTH-3)))) {\r
-           if(ft==1 || ft==BOARD_WIDTH-2)\r
+            ((ff == BOARD_WIDTH>>1 && (ft == BOARD_LEFT+2 || ft == BOARD_RGHT-2)) ||\r
+             (ff == (BOARD_WIDTH-1)>>1 && (ft == BOARD_LEFT+1 || ft == BOARD_RGHT-3)))) {\r
+            if(ft==BOARD_LEFT+1 || ft==BOARD_RGHT-2)\r
                strcpy(out, "O-O");\r
             else\r
                strcpy(out, "O-O-O");\r
@@ -1172,10 +1480,16 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
           else "N1f3" or "N5xf7",\r
           else "Ng1f3" or "Ng5xf7".\r
        */\r
-       *outp++ = ToUpper(PieceToChar(piece));\r
-       \r
+        c = PieceToChar(piece) ;\r
+        if( c == '~' || c == '+') {\r
+           /* [HGM] print nonexistent piece as its demoted version */\r
+           piece = (ChessSquare) (DEMOTED piece);\r
+        }\r
+        if(c=='+') *outp++ = c;\r
+        *outp++ = ToUpper(PieceToChar(piece));\r
+\r
        if (cl.file || (cl.either && !cl.rank)) {\r
-           *outp++ = ff + 'a';\r
+            *outp++ = ff + AAA;\r
        }\r
        if (cl.rank) {\r
             if(rf+ONE <= '9')\r
@@ -1186,22 +1500,57 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
        if(board[rt][ft] != EmptySquare)\r
          *outp++ = 'x';\r
 \r
-       *outp++ = ft + 'a';\r
+        *outp++ = ft + AAA;\r
         if(rt+ONE <= '9')\r
            *outp++ = rt + ONE;\r
         else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }\r
        *outp = NULLCHAR;\r
-       return cl.kind;\r
+        if (gameInfo.variant == VariantShogi) {\r
+            /* [HGM] in Shogi non-pawns can promote */\r
+            if(flags & F_WHITE_ON_MOVE) {\r
+                if( (int) cl.piece < (int) WhiteWazir &&\r
+                     (rf > BOARD_HEIGHT-4 || rt > BOARD_HEIGHT-4) ) {\r
+                    if( (piece == WhitePawn || piece == WhiteQueen) && rt > BOARD_HEIGHT-2 ||\r
+                         piece == WhiteKnight && rt > BOARD_HEIGHT-3) /* promotion mandatory */\r
+                             cl.kind = promoChar == '=' ? IllegalMove : WhitePromotionKnight;\r
+                    else cl.kind =  WhitePromotionQueen; /* promotion optional */\r
+                   \r
+                } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?\r
+                                            NormalMove : IllegalMove;\r
+            } else {\r
+                if( (int) cl.piece < (int) BlackWazir && (rf < 3 || rt < 3) ) {\r
+                    if( (piece == BlackPawn || piece == BlackQueen) && rt < 1 ||\r
+                         piece == BlackKnight && rt < 2 ) /* promotion obligatory */\r
+                             cl.kind = promoChar == '=' ? IllegalMove : BlackPromotionKnight;\r
+                    else cl.kind =  BlackPromotionQueen; /* promotion optional */\r
+                } else cl.kind = (promoChar == NULLCHAR || promoChar == 'x' || promoChar == '=') ?\r
+                                            NormalMove : IllegalMove;\r
+            }\r
+            if(cl.kind == WhitePromotionQueen || cl.kind == BlackPromotionQueen) {\r
+                /* for optional promotions append '+' or '=' */\r
+                if(promoChar == '=') {\r
+                    *outp++ = '=';\r
+                    cl.kind = NormalMove;\r
+                } else *outp++ = '+';\r
+                *outp = NULLCHAR;\r
+            } else if(cl.kind == IllegalMove) {\r
+                /* Illegal move specifies any given promotion */\r
+                if(promoChar != NULLCHAR && promoChar != 'x') {\r
+                    *outp++ = '=';\r
+                    *outp++ = ToUpper(promoChar);\r
+                    *outp = NULLCHAR;\r
+                }\r
+            }\r
+        }\r
+        return cl.kind;\r
        \r
-#ifdef FAIRY\r
-      /* [HGM] Always long notation for fairies, don't know how they move */\r
-      case WhiteFairyRook:\r
-      case BlackFairyRook:\r
-      case WhiteFairyKnight:\r
-      case BlackFairyKnight:\r
-      case WhiteFairyQueen:\r
-      case BlackFairyQueen:\r
-#endif\r
+      /* [HGM] Always long notation for fairies we don't know */\r
+      case WhiteFalcon:\r
+      case BlackFalcon:\r
+      case WhiteLance:\r
+      case BlackLance:\r
+      case WhiteGrasshopper:\r
+      case BlackGrasshopper:\r
       case EmptySquare:\r
        /* Moving a nonexistent piece */\r
        break;\r
@@ -1219,12 +1568,12 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
     if (piece != EmptySquare && piece != WhitePawn && piece != BlackPawn) {\r
        *outp++ = ToUpper(PieceToChar(piece));\r
     }\r
-    *outp++ = ff + 'a';\r
+    *outp++ = ff + AAA;\r
     if(rf+ONE <= '9')\r
        *outp++ = rf + ONE;\r
     else { *outp++ = (rf+ONE-'0')/10 + '0';*outp++ = (rf+ONE-'0')%10 + '0'; }\r
     if (board[rt][ft] != EmptySquare) *outp++ = 'x';\r
-    *outp++ = ft + 'a';\r
+    *outp++ = ft + AAA;\r
     if(rt+ONE <= '9')\r
        *outp++ = rt + ONE;\r
     else { *outp++ = (rt+ONE-'0')/10 + '0';*outp++ = (rt+ONE-'0')%10 + '0'; }\r