changes by H.G. Muller; version 4.3.4
[xboard.git] / moves.c
diff --git a/moves.c b/moves.c
index 57e350e..2070ef3 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -119,13 +119,13 @@ ChessSquare PromoPiece(moveType)
        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 WhiteCardinal;\r
       case BlackPromotionArchbishop:\r
-        return BlackFairyBishop;\r
+        return BlackCardinal;\r
 #endif\r
     }\r
 }\r
@@ -196,15 +196,15 @@ ChessMove PromoCharToMoveType(whiteOnMove, promoChar)
 }\r
 \r
 char pieceToChar[] = {\r
-    'P', 'N', 'B', 'R', \r
+              'P', 'N', 'B', 'R', 'Q', \r
 #ifdef FAIRY\r
-    'A', 'C', 'F', 'H', 'E', 'W', 'D', 'O', 'G', 'M',\r
+    'F', 'W', 'E', 'H', 'A', 'C', 'G', 'O', 'M', 'U', \r
 #endif\r
-    'Q', 'K', 'p', 'n', 'b', 'r', \r
+    'K',      'p', 'n', 'b', 'r', 'q', \r
 #ifdef FAIRY            \r
-    'a', 'c', 'f', 'h', 'e', 'w', 'd', 'o', 'g', 'm',\r
+    'f', 'w', 'e', 'h', 'a', 'c', 'g', 'o', 'm', 'u',\r
 #endif\r
-    'q', 'k', 'x'\r
+    'k', 'x'\r
   };\r
 \r
 char PieceToChar(p)\r
@@ -215,7 +215,13 @@ char PieceToChar(p)
 \r
 ChessSquare CharToPiece(c)\r
      int c;\r
-{    switch (c) {\r
+{\r
+     int i;\r
+     for(i=0; i< (int) EmptySquare; i++)\r
+          if(pieceToChar[i] == c) return (ChessSquare) i;\r
+     return EmptySquare;\r
+/* [HGM] code marked for deletion\r
+     switch (c) {\r
       default:\r
       case 'x':        return EmptySquare;\r
       case 'P':        return WhitePawn;\r
@@ -233,28 +239,29 @@ ChessSquare CharToPiece(c)
 #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
+      case 'F': return WhiteFerz;\r
+      case 'H': return WhiteNightrider;\r
+      case 'E': return WhiteAlfil;\r
+      case 'W': return WhiteWazir;\r
+      case 'U': return WhiteUnicorn;\r
+      case 'O': return WhiteCannon;\r
+      case 'G': return WhiteGrasshopper;\r
+      case 'M': return WhiteMan;\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
+      case 'f': return BlackFerz;\r
+      case 'h': return BlackNightrider;\r
+      case 'e': return BlackAlfil;\r
+      case 'w': return BlackWazir;\r
+      case 'u': return BlackUnicorn;\r
+      case 'o': return BlackCannon;\r
+      case 'g': return BlackGrasshopper;\r
+      case 'm': return BlackMan;\r
                 \r
 #endif\r
     }\r
+*/\r
 }\r
 \r
 void CopyBoard(to, from)\r
@@ -300,15 +307,24 @@ 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(gameInfo.variant == VariantCrazyhouse &&\r
+              ( (int) piece > (int) WhiteQueen && (int) piece < (int) WhiteKing\r
+             || (int) piece > (int) BlackQueen && (int) piece < (int) BlackKing ))\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
@@ -325,7 +341,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
@@ -341,12 +357,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 +371,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
@@ -376,7 +393,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
@@ -392,12 +409,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 +423,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 +434,10 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              }             \r
              break;\r
 \r
+#ifdef FAIRY\r
+            case WhiteUnicorn:\r
+            case BlackUnicorn:\r
+#endif\r
            case WhiteKnight:\r
            case BlackKnight:\r
             mounted:\r
@@ -424,22 +446,46 @@ 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
+\r
 #ifdef FAIRY\r
-            case WhiteFairyMarshall:\r
-            case BlackFairyMarshall:\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, \r
+                              rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : 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, \r
+                              rf == 1 ? BlackPromotionQueen : 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,35 +498,82 @@ 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, \r
+                              rf == BOARD_HEIGHT-2 ? WhitePromotionQueen : 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, \r
+                              rf == 1 ? BlackPromotionQueen : 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
+            /* Shogi Dragon Horse has to continue with Wazir after Bishop */\r
+            case SHOGI WhiteCardinal:\r
+            case SHOGI BlackCardinal:\r
+              m++;\r
+\r
+            /* Capablanca Archbishop continues as Knight                  */\r
             case WhiteCardinal:\r
             case BlackCardinal:\r
               m++;\r
+\r
+            /* Shogi Bishops are ordinary Bishops */\r
+            case SHOGI WhiteBishop:\r
+            case SHOGI BlackBishop:\r
 #endif\r
            case WhiteBishop:\r
            case BlackBishop:\r
@@ -489,19 +582,56 @@ 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 WhiteMarshall:\r
+            case SHOGI BlackMarshall:\r
+              m++;\r
+\r
+            /* Capablanca Chancellor sets flag to continue as Knight      */\r
             case WhiteMarshall:\r
             case BlackMarshall:\r
               m++;\r
+\r
+            /* Shogi Rooks are ordinary Rooks */\r
+            case SHOGI WhiteRook:\r
+            case SHOGI BlackRook:\r
 #endif\r
            case WhiteRook:\r
            case BlackRook:\r
@@ -510,13 +640,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 walking;\r
              break;\r
 \r
            case WhiteQueen:\r
@@ -527,7 +658,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
@@ -537,31 +668,55 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
              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) break;\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
+            case WhiteMan:\r
+            case BlackMan:\r
+            case SHOGI WhiteKing:\r
+            case SHOGI BlackKing:\r
 #endif\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
@@ -602,7 +757,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
@@ -648,79 +803,79 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
     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] == WhiteKing &&\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
              !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
+                     0, ff, 0, ff + ((gameInfo.boardWidth+2)>>2), closure);\r
        }\r
        if ((flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_WHITE_QCASTLE_OK) &&\r
            board[0][ff] == WhiteKing &&\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 + 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
              !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), 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 - 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, BOARD_LEFT+3,      FALSE) &&\r
              !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, 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
@@ -731,9 +886,9 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
 \r
     if ((flags & F_WHITE_ON_MOVE) != 0) {\r
 \r
-       for (ff = 1; ff < BOARD_WIDTH-1; ff++) {\r
+       for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) {\r
           if (board[0][ff] == WhiteKing) {\r
-             for (ft = 0; ft < BOARD_WIDTH; ft++) {\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
@@ -745,9 +900,9 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
 \r
     } else {\r
 \r
-       for (ff = 1; ff < BOARD_WIDTH-1; ff++) {\r
+       for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) {\r
           if (board[BOARD_HEIGHT-1][ff] == BlackKing) {\r
-             for (ft = 0; ft < BOARD_WIDTH; ft++) {\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
@@ -805,6 +960,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 +980,9 @@ 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
              GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, -1,\r
                             CheckTestCallback, (VOIDSTAR) &cl);\r
              goto undo_move;  /* 2-level break */\r
@@ -858,6 +1018,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
@@ -921,7 +1084,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 ?\r
+                         MT_CHECKMATE : MT_STALEMATE;\r
     }\r
 }\r
 \r
@@ -1063,11 +1227,12 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
        /* 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
        *outp = NULLCHAR;\r
+        AlphaRank(out, 5);\r
        return (flags & F_WHITE_ON_MOVE) ? WhiteDrop : BlackDrop;\r
     }\r
 \r
@@ -1086,7 +1251,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,7 +1261,7 @@ 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
@@ -1107,7 +1272,8 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
            *outp++ = ToUpper(promoChar);\r
        }\r
        *outp = NULLCHAR;\r
-       return kind;\r
+        AlphaRank(out, 10);\r
+        return kind;\r
 \r
        \r
       case WhiteKing:\r
@@ -1125,9 +1291,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
@@ -1175,7 +1341,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
        *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,21 +1352,20 @@ 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
+        AlphaRank(out, 10);\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
+      case WhiteNightrider:\r
+      case BlackNightrider:\r
+      case WhiteGrasshopper:\r
+      case BlackGrasshopper:\r
 #endif\r
       case EmptySquare:\r
        /* Moving a nonexistent piece */\r
@@ -1219,12 +1384,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
@@ -1235,6 +1400,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
     }\r
     *outp = NULLCHAR;\r
 \r
+    AlphaRank(out, 0);\r
     return IllegalMove;\r
 }\r
 \r