Make gating mandatory in holdingless Seirawan
authorH.G.Muller <hgm@hgm-xboard.(none)>
Mon, 6 Apr 2020 17:14:30 +0000 (19:14 +0200)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Mon, 6 Apr 2020 17:14:30 +0000 (19:14 +0200)
Moving a piece 'in front of' a gatable piece is made mandatory,
by supplying the missing gating suffix in the move parser. To
achieve this the move type returned by LegalityTast() for a move
with missing suffix is White/BlackPromotion, even when the move is
a castling. The parser then adds the suffix, like it does for any
promotion without a suffix.

moves.c
parser.c

diff --git a/moves.c b/moves.c
index 638a4c0..46763cb 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -1937,8 +1937,24 @@ LegalityTest (Board board, int flags, int rf, int ff, int rt, int ft, int promoC
 
     if(promoChar == 'x') promoChar = NULLCHAR; // [HGM] is this ever the case?
     if(autoProm[piece]) promoChar = NULLCHAR;  // ignore promotion characters on auto-promoting pieces
-    if(gameInfo.variant == VariantSChess && promoChar && promoChar != '=' && board[rf][ff] != WhitePawn && board[rf][ff] != BlackPawn) {
-      if(gameInfo.holdingsSize) {
+    if(gameInfo.variant == VariantSChess) {
+      if(!gameInfo.holdingsSize) {  // holdingless Seirawan
+        if(promoChar == NULLCHAR) { // gating indicator could be missing
+          if(flags & F_WHITE_ON_MOVE) {
+            if(rf == 1) {
+              if(board[0][ff] != DarkSquare) return WhitePromotion; // mandatory gating, report it as promotion
+              if(cl.kind == WhiteQueenSideCastle && board[0][0] != DarkSquare) return WhitePromotion;
+              if(cl.kind == WhiteKingSideCastle && board[0][BOARD_RGHT-1] != DarkSquare) return WhitePromotion;
+            }
+          } else {
+            if(rf == BOARD_HEIGHT-2) {
+              if(board[BOARD_HEIGHT-1][ff] != DarkSquare) return BlackPromotion;
+              if(cl.kind == BlackQueenSideCastle && board[BOARD_HEIGHT-1][0] != DarkSquare) return BlackPromotion;
+              if(cl.kind == BlackKingSideCastle && board[BOARD_HEIGHT-1][BOARD_RGHT-1] != DarkSquare) return BlackPromotion;
+            }
+          }
+        }
+      } else if(promoChar && promoChar != '=' && board[rf][ff] != WhitePawn && board[rf][ff] != BlackPawn) {
         if(board[rf][ff] < BlackPawn) { // white
             if(rf != 0) return IllegalMove; // must be on back rank
             if(!(board[VIRGIN][ff] & VIRGIN_W)) return IllegalMove; // non-virgin
index ff33245..5246944 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -566,6 +566,12 @@ NextUnit (char **p)
                          case VariantShatranj: currentMoveString[4] = PieceToChar(BlackFerz); break;
                          case VariantGreat:    currentMoveString[4] = PieceToChar(BlackMan); break;
                          case VariantShogi:    currentMoveString[4] = '+'; break;
+                         case VariantSChess:   if(!gameInfo.holdingsSize) { // missing auto-gating
+                                                   ChessSquare p = boards[yyboardindex][fromY^1][fromX];
+                                                   if(p == DarkSquare) p = boards[yyboardindex][fromY^1][toX<fromX?BOARD_LEFT:BOARD_RGHT-1];
+                                                   currentMoveString[4] = ToLower(PieceToChar(p));
+                                                   break;
+                                               }
                          default:              currentMoveString[4] = PieceToChar(BlackQueen);
                        }
                      } else if(result == WhiteNonPromotion  || result == BlackNonPromotion) {