From ddd7e25026fb286d8d727a32664412026e2d5095 Mon Sep 17 00:00:00 2001
From: Bart Massey <bart@cs.pdx.edu>
Date: Thu, 9 Apr 2009 01:44:10 -0700
Subject: [PATCH] added support for MiniChess 2007 variant

---
 backend.c |  108 +++++++++++++++++++++++++++++++++++++++----------------------
 backend.h |    1 +
 common.h  |    3 ++
 moves.c   |   76 +++++++++++++++++++++++++-----------------
 moves.h   |    1 +
 xboard.c  |   86 +++++++++++++++++++++++++-----------------------
 6 files changed, 163 insertions(+), 112 deletions(-)

diff --git a/backend.c b/backend.c
index 8b4c47e..89610da 100644
--- a/backend.c
+++ b/backend.c
@@ -203,6 +203,7 @@ void InitBackEnd3 P((void));
 void FeatureDone P((ChessProgramState* cps, int val));
 void InitChessProgram P((ChessProgramState *cps));
 
+int boardRows = BOARD_SIZE, boardCols = BOARD_SIZE;
 extern int tinyLayout, smallLayout;
 static ChessProgramStats programStats;
 
@@ -250,7 +251,7 @@ static ChessProgramStats programStats;
 int
 PosFlags(index)
 {
-  int flags = F_ALL_CASTLE_OK;
+  int flags = F_ALL_CASTLE_OK | F_DOUBLE_PAWN_MOVES;
   if ((index % 2) == 0) flags |= F_WHITE_ON_MOVE;
   switch (gameInfo.variant) {
   case VariantSuicide:
@@ -267,6 +268,9 @@ PosFlags(index)
   case VariantNoCastle:
     flags &= ~F_ALL_CASTLE_OK;
     break;
+  case VariantMiniChess:
+    flags |= F_IGNORE_CHECK;
+    flags &= ~(F_ALL_CASTLE_OK | F_DOUBLE_PAWN_MOVES);
   default:
     break;
   }
@@ -377,6 +381,14 @@ Board twoKingsPosition = {
     { BlackRook, BlackKnight, BlackBishop, BlackQueen,
 	BlackKing, BlackKing, BlackKnight, BlackRook }
 };
+Board miniChessPosition = {
+    { WhiteKing, WhiteQueen, WhiteBishop, WhiteKnight, WhiteRook },
+    { WhitePawn, WhitePawn, WhitePawn, WhitePawn, WhitePawn },
+    { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare },
+    { EmptySquare, EmptySquare, EmptySquare, EmptySquare, EmptySquare },
+    { BlackPawn, BlackPawn, BlackPawn, BlackPawn, BlackPawn },
+    { BlackRook, BlackKnight, BlackBishop, BlackQueen, BlackKing }
+};
 
 
 /* Convert str to a rating. Checks for special cases of "----",
@@ -413,6 +425,12 @@ InitBackEnd1()
 {
     int matched, min, sec;
 
+    if (!strcmp(appData.variant, "minichess")) {
+      boardRows = 6;
+      boardCols = 5;
+      appData.alwaysPromoteToQueen = TRUE;
+    }
+
     GetTimeMark(&programStartTime);
 
     ClearProgramStats();
@@ -621,6 +639,7 @@ InitBackEnd1()
       case VariantAtomic:     /* should work except for win condition */
       case Variant3Check:     /* should work except for win condition */
       case VariantShatranj:   /* might work if TestLegality is off */
+      case VariantMiniChess:  /* should work */
 	break;
       }
     }
@@ -1227,6 +1246,9 @@ StringToVariant(e)
 	case 36:
 	  v = Variant36;
 	  break;
+	case 37:
+	  v = VariantMiniChess;
+	  break;
 
 	case -1:
 	  /* Found "wild" or "w" in the string but no number;
@@ -2789,9 +2811,10 @@ ParseBoard12(string)
     }
     
     /* Parse the board */
-    for (k = 0; k < 8; k++)
-      for (j = 0; j < 8; j++)
-	board[k][j] = CharToPiece(board_chars[(7-k)*9 + j]);
+    for (k = 0; k < boardRows; k++)
+      for (j = 0; j < boardCols; j++)
+	board[k][j] = CharToPiece(board_chars[(boardRows - k - 1) *
+					      (boardCols + 1) + j]);
     CopyBoard(boards[moveNum], board);
     if (moveNum == 0) {
 	startedFromSetupPosition =
@@ -3262,6 +3285,11 @@ InitPosition(redraw)
       CopyBoard(boards[0], initialPosition);
       /* !!shuffle according to FR rules */
       break;
+    case VariantMiniChess:
+      /* XXX can't yet dynamically switch board size */
+      if (boardRows != 6 || boardCols != 5)
+	gameInfo.variant = VariantNormal;
+      CopyBoard(boards[0], miniChessPosition);
     }
     if (redraw)
       DrawPosition(FALSE, boards[currentMove]);
@@ -3290,9 +3318,9 @@ SendBoard(cps, moveNum)
 
       SendToProgram("edit\n", cps);
       SendToProgram("#\n", cps);
-      for (i = BOARD_SIZE - 1; i >= 0; i--) {
+      for (i = boardRows - 1; i >= 0; i--) {
 	bp = &boards[moveNum][i][0];
-	for (j = 0; j < BOARD_SIZE; j++, bp++) {
+	for (j = 0; j < boardCols; j++, bp++) {
 	  if ((int) *bp < (int) BlackPawn) {
 	    sprintf(message, "%c%c%c\n", PieceToChar(*bp), 
 		    'a' + j, '1' + i);
@@ -3302,9 +3330,9 @@ SendBoard(cps, moveNum)
       }
     
       SendToProgram("c\n", cps);
-      for (i = BOARD_SIZE - 1; i >= 0; i--) {
+      for (i = boardRows - 1; i >= 0; i--) {
 	bp = &boards[moveNum][i][0];
-	for (j = 0; j < BOARD_SIZE; j++, bp++) {
+	for (j = 0; j < boardCols; j++, bp++) {
 	  if (((int) *bp != (int) EmptySquare)
 	      && ((int) *bp >= (int) BlackPawn)) {
 	    sprintf(message, "%c%c%c\n", ToUpper(PieceToChar(*bp)),
@@ -3324,7 +3352,8 @@ IsPromotion(fromX, fromY, toX, toY)
 {
     return gameMode != EditPosition &&
       fromX >=0 && fromY >= 0 && toX >= 0 && toY >= 0 &&
-	((boards[currentMove][fromY][fromX] == WhitePawn && toY == 7) ||
+	((boards[currentMove][fromY][fromX] == WhitePawn &&
+	  toY == boardRows - 1) ||
 	 (boards[currentMove][fromY][fromX] == BlackPawn && toY == 0));
 }
 
@@ -3334,7 +3363,7 @@ PieceForSquare (x, y)
      int x;
      int y;
 {
-  if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE)
+  if (x < 0 || x >= boardCols || y < 0 || y >= boardRows)
      return -1;
   else
      return boards[currentMove][y][x];
@@ -4692,14 +4721,14 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
 	board[fromY][0] = EmptySquare;
 	board[toY][2] = WhiteRook;
     } else if (board[fromY][fromX] == WhitePawn
-	       && toY == 7) {
+	       && toY == boardRows - 1) {
 	/* white pawn promotion */
-	board[7][toX] = CharToPiece(ToUpper(promoChar));
-	if (board[7][toX] == EmptySquare) {
-	    board[7][toX] = WhiteQueen;
+	board[boardRows - 1][toX] = CharToPiece(ToUpper(promoChar));
+	if (board[boardRows - 1][toX] == EmptySquare) {
+	    board[boardRows - 1][toX] = WhiteQueen;
 	}
 	board[fromY][fromX] = EmptySquare;
-    } else if ((fromY == 4)
+    } else if ((fromY == boardRows - 4)
 	       && (toX != fromX)
 	       && (board[fromY][fromX] == WhitePawn)
 	       && (board[toY][toX] == EmptySquare)) {
@@ -4707,30 +4736,30 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
 	board[toY][toX] = WhitePawn;
 	captured = board[toY - 1][toX];
 	board[toY - 1][toX] = EmptySquare;
-    } else if (fromY == 7 && fromX == 4
+    } else if (fromY == boardRows - 1 && fromX == 4
 	       && board[fromY][fromX] == BlackKing
-	       && toY == 7 && toX == 6) {
+	       && toY == boardRows - 1 && toX == 6) {
 	board[fromY][fromX] = EmptySquare;
 	board[toY][toX] = BlackKing;
 	board[fromY][7] = EmptySquare;
 	board[toY][5] = BlackRook;
-    } else if (fromY == 7 && fromX == 4
+    } else if (fromY == boardRows - 1 && fromX == 4
 	       && board[fromY][fromX] == BlackKing
-	       && toY == 7 && toX == 2) {
+	       && toY == boardRows - 1 && toX == 2) {
 	board[fromY][fromX] = EmptySquare;
 	board[toY][toX] = BlackKing;
 	board[fromY][0] = EmptySquare;
 	board[toY][3] = BlackRook;
-    } else if (fromY == 7 && fromX == 3
+    } else if (fromY == boardRows - 1 && fromX == 3
 	       && board[fromY][fromX] == BlackKing
-	       && toY == 7 && toX == 5) {
+	       && toY == boardRows - 1 && toX == 5) {
 	board[fromY][fromX] = EmptySquare;
 	board[toY][toX] = BlackKing;
 	board[fromY][7] = EmptySquare;
 	board[toY][4] = BlackRook;
-    } else if (fromY == 7 && fromX == 3
+    } else if (fromY == boardRows - 1 && fromX == 3
 	       && board[fromY][fromX] == BlackKing
-	       && toY == 7 && toX == 1) {
+	       && toY == boardRows - 1 && toX == 1) {
 	board[fromY][fromX] = EmptySquare;
 	board[toY][toX] = BlackKing;
 	board[fromY][0] = EmptySquare;
@@ -4776,7 +4805,8 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
 	int y, x;
 	for (y = toY-1; y <= toY+1; y++) {
 	  for (x = toX-1; x <= toX+1; x++) {
-	    if (y >= 0 && y <= 7 && x >= 0 && x <= 7 &&
+	    if (y >= 0 && y <= boardRows - 1 &&
+		x >= 0 && x <= boardCols - 1 &&
 		board[y][x] != WhitePawn && board[y][x] != BlackPawn) {
 	      board[y][x] = EmptySquare;
 	    }
@@ -6131,8 +6161,8 @@ LoadGame(f, gameNumber, title, useList)
 
 	if (!startedFromSetupPosition) {
 	    p = yy_text;
-	    for (i = BOARD_SIZE - 1; i >= 0; i--)
-	      for (j = 0; j < BOARD_SIZE; p++)
+	    for (i = boardRows - 1; i >= 0; i--)
+	      for (j = 0; j < boardCols; p++)
 		switch (*p) {
 		  case '[':
 		  case '-':
@@ -6395,9 +6425,9 @@ LoadPosition(f, positionNumber, title)
 	(void) fgets(line, MSG_SIZ, f);
 	(void) fgets(line, MSG_SIZ, f);
     
-	for (i = BOARD_SIZE - 1; i >= 0; i--) {
+	for (i = boardRows - 1; i >= 0; i--) {
 	    (void) fgets(line, MSG_SIZ, f);
-	    for (p = line, j = 0; j < BOARD_SIZE; p++) {
+	    for (p = line, j = 0; j < boardCols; p++) {
 		if (*p == ' ')
 		  continue;
 		initial_position[i][j++] = CharToPiece(*p);
@@ -7839,8 +7869,8 @@ EditPositionMenuEvent(selection, x, y)
 	    SendToICS(ics_prefix);
 	    SendToICS("clearboard\n");
 	} else {
-	    for (x = 0; x < BOARD_SIZE; x++) {
-		for (y = 0; y < BOARD_SIZE; y++) {
+	    for (x = 0; x < boardCols; x++) {
+		for (y = 0; y < boardRows; y++) {
 		    if (gameMode == IcsExamining) {
 			if (boards[currentMove][y][x] != EmptySquare) {
 			    sprintf(buf, "%sx@%c%c\n", ics_prefix,
@@ -8553,11 +8583,11 @@ PrintPosition(fp, move)
 {
     int i, j;
     
-    for (i = BOARD_SIZE - 1; i >= 0; i--) {
-	for (j = 0; j < BOARD_SIZE; j++) {
+    for (i = boardRows - 1; i >= 0; i--) {
+	for (j = 0; j < boardCols; j++) {
 	    char c = PieceToChar(boards[move][i][j]);
 	    fputc(c == 'x' ? '.' : c, fp);
-	    fputc(j == BOARD_SIZE - 1 ? '\n' : ' ', fp);
+	    fputc(j == boardRows - 1 ? '\n' : ' ', fp);
 	}
     }
     if ((gameMode == EditPosition) ? !blackPlaysFirst : (move % 2 == 0))
@@ -9831,9 +9861,9 @@ PositionToFEN(move)
     p = buf;
 
     /* Piece placement data */
-    for (i = BOARD_SIZE - 1; i >= 0; i--) {
+    for (i = boardRows - 1; i >= 0; i--) {
 	emptycount = 0;
-	for (j = 0; j < BOARD_SIZE; j++) {
+	for (j = 0; j < boardCols; j++) {
 	    if (boards[move][i][j] == EmptySquare) {
 		emptycount++;
 	    } else {
@@ -9912,20 +9942,20 @@ ParseFEN(board, blackPlaysFirst, fen)
     p = fen;
 
     /* Piece placement data */
-    for (i = BOARD_SIZE - 1; i >= 0; i--) {
+    for (i = boardRows - 1; i >= 0; i--) {
 	j = 0;
 	for (;;) {
 	    if (*p == '/' || *p == ' ') {
 		if (*p == '/') p++;
-		emptycount = BOARD_SIZE - j;
+		emptycount = boardCols - j;
 		while (emptycount--) board[i][j++] = EmptySquare;
 		break;
 	    } else if (isdigit(*p)) {
 		emptycount = *p++ - '0';
-		if (j + emptycount > BOARD_SIZE) return FALSE;
+		if (j + emptycount > boardCols) return FALSE;
 		while (emptycount--) board[i][j++] = EmptySquare;
 	    } else if (isalpha(*p)) {
-		if (j >= BOARD_SIZE) return FALSE;
+		if (j >= boardCols) return FALSE;
 		board[i][j++] = CharToPiece(*p++);
 	    } else {
 		return FALSE;
diff --git a/backend.h b/backend.h
index dff919c..6f37ac1 100644
--- a/backend.h
+++ b/backend.h
@@ -198,6 +198,7 @@ char *GameListLine P((int, GameInfo *));
 extern char* StripHighlight P((char *));  /* returns static data */
 extern char* StripHighlightAndTitle P((char *));  /* returns static data */
 
+extern int boardRows, boardCols;
 
 typedef struct _CPS {
     char *which;
diff --git a/common.h b/common.h
index 556e542..5130154 100644
--- a/common.h
+++ b/common.h
@@ -227,6 +227,7 @@ typedef enum {
     Variant34,           /* Temporary name for possible future ICC wild 34 */
     Variant35,           /* Temporary name for possible future ICC wild 35 */
     Variant36,           /* Temporary name for possible future ICC wild 36 */
+    VariantMiniChess,    /* Simplified on a 5x6 board */
     VariantUnknown       /* Catchall for other unknown variants */
 } VariantClass;
 
@@ -254,6 +255,7 @@ typedef enum {
   "wild34", \
   "wild35", \
   "wild36", \
+  "minichess", \
   "unknown" \
 }
 
@@ -425,6 +427,7 @@ typedef struct {
     int zippyMaxGames;
     int zippyReplayTimeout; /*seconds*/
 #endif
+    int boardRows, boardCols;
 } AppData, *AppDataPtr;
 
 extern AppData appData;
diff --git a/moves.c b/moves.c
index a77b23b..a1ade78 100644
--- a/moves.c
+++ b/moves.c
@@ -204,8 +204,8 @@ void CopyBoard(to, from)
 {
     int i, j;
     
-    for (i = 0; i < BOARD_SIZE; i++)
-      for (j = 0; j < BOARD_SIZE; j++)
+    for (i = 0; i < boardRows; i++)
+      for (j = 0; j < boardCols; j++)
 	to[i][j] = from[i][j];
 }
 
@@ -214,8 +214,8 @@ int CompareBoards(board1, board2)
 {
     int i, j;
     
-    for (i = 0; i < BOARD_SIZE; i++)
-      for (j = 0; j < BOARD_SIZE; j++) {
+    for (i = 0; i < boardRows; i++)
+      for (j = 0; j < boardCols; j++) {
 	  if (board1[i][j] != board2[i][j])
 	    return FALSE;
     }
@@ -241,8 +241,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
     int rf, ff;
     int i, j, d, s, fs, rs, rt, ft;
 
-    for (rf = 0; rf <= 7; rf++) 
-      for (ff = 0; ff <= 7; ff++) {
+    for (rf = 0; rf < boardRows; rf++)
+      for (ff = 0; ff < boardCols; ff++) {
 	  if (flags & F_WHITE_ON_MOVE) {
 	      if (!WhitePiece(board[rf][ff])) continue;
 	  } else {
@@ -255,31 +255,35 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 	      break;
 
 	    case WhitePawn:
-	      if (rf < 7 && board[rf + 1][ff] == EmptySquare) {
+	      if (rf < boardRows - 1 && board[rf + 1][ff] == EmptySquare) {
 		  callback(board, flags,
-			   rf == 6 ? WhitePromotionQueen : NormalMove,
+			   rf == boardRows - 2 ?
+			     WhitePromotionQueen : NormalMove,
 			   rf, ff, rf + 1, ff, closure);
 	      }
-	      if (rf == 1 && board[2][ff] == EmptySquare &&
+	      if ((flags & F_DOUBLE_PAWN_MOVES) &&
+		  rf == 1 && board[2][ff] == EmptySquare &&
 		  board[3][ff] == EmptySquare) {
 		  callback(board, flags, NormalMove,
 			   rf, ff, 3, ff, closure);
 	      }
 	      for (s = -1; s <= 1; s += 2) {
-		  if (rf < 7 && ff + s >= 0 && ff + s <= 7 &&
+		  if (rf < boardRows - 1 &&
+		      ff + s >= 0 && ff + s <= boardCols - 1 &&
 		      ((flags & F_KRIEGSPIEL_CAPTURE) ||
 		       BlackPiece(board[rf + 1][ff + s]))) {
 		      callback(board, flags, 
-			       rf == 6 ? WhitePromotionQueen : NormalMove,
+			       rf == boardRows - 2 ?
+			         WhitePromotionQueen : NormalMove,
 			       rf, ff, rf + 1, ff + s, closure);
 		  }
-		  if (rf == 4) {
-		      if (ff + s >= 0 && ff + s <= 7 &&
+		  if ((flags & F_DOUBLE_PAWN_MOVES) && rf == boardRows - 4) {
+		      if (ff + s >= 0 && ff + s <= boardRows - 1 &&
 			  (epfile == ff + s || epfile == EP_UNKNOWN) &&
-			  board[4][ff + s] == BlackPawn &&
-			  board[5][ff + s] == EmptySquare) {
+			  board[boardRows - 4][ff + s] == BlackPawn &&
+			  board[boardRows - 3][ff + s] == EmptySquare) {
 			  callback(board, flags, WhiteCapturesEnPassant,
-				   rf, ff, 5, ff + s, closure);
+				   rf, ff, boardRows - 3, ff + s, closure);
 		      }
 		  }
 	      }		    
@@ -291,21 +295,23 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 			   rf == 1 ? BlackPromotionQueen : NormalMove,
 			   rf, ff, rf - 1, ff, closure);
 	      }
-	      if (rf == 6 && board[5][ff] == EmptySquare &&
-		  board[4][ff] == EmptySquare) {
+	      if ((flags & F_DOUBLE_PAWN_MOVES) &&
+		  rf == boardRows - 2 &&
+		  board[boardRows - 3][ff] == EmptySquare &&
+		  board[boardRows - 4][ff] == EmptySquare) {
 		  callback(board, flags, NormalMove,
-			   rf, ff, 4, ff, closure);
+			   rf, ff, boardRows - 4, ff, closure);
 	      }
 	      for (s = -1; s <= 1; s += 2) {
-		  if (rf > 0 && ff + s >= 0 && ff + s <= 7 &&
+		  if (rf > 0 && ff + s >= 0 && ff + s <= boardCols - 1 &&
 		      ((flags & F_KRIEGSPIEL_CAPTURE) ||
 		       WhitePiece(board[rf - 1][ff + s]))) {
 		      callback(board, flags, 
 			       rf == 1 ? BlackPromotionQueen : NormalMove,
 			       rf, ff, rf - 1, ff + s, closure);
 		  }
-		  if (rf == 3) {
-		      if (ff + s >= 0 && ff + s <= 7 &&
+		  if ((flags & F_DOUBLE_PAWN_MOVES) && rf == 3) {
+		      if (ff + s >= 0 && ff + s <= boardCols - 1 &&
 			  (epfile == ff + s || epfile == EP_UNKNOWN) &&
 			  board[3][ff + s] == WhitePawn &&
 			  board[2][ff + s] == EmptySquare) {
@@ -323,7 +329,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 		  for (s = 1; s <= 2; s++) {
 		      rt = rf + i*s;
 		      ft = ff + j*(3-s);
-		      if (rt < 0 || rt > 7 || ft < 0 || ft > 7) continue;
+		      if (rt < 0 || rt > boardRows - 1 ||
+			  ft < 0 || ft > boardCols - 1) continue;
 		      if (SameColor(board[rf][ff], board[rt][ft])) continue;
 		      callback(board, flags, NormalMove,
 			       rf, ff, rt, ft, closure);
@@ -337,7 +344,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 		  for (i = 1;; i++) {
 		      rt = rf + (i * rs);
 		      ft = ff + (i * fs);
-		      if (rt < 0 || rt > 7 || ft < 0 || ft > 7) break;
+		      if (rt < 0 || rt > boardRows - 1 ||
+			  ft < 0 || ft > boardCols - 1) break;
 		      if (SameColor(board[rf][ff], board[rt][ft])) break;
 		      callback(board, flags, NormalMove,
 			       rf, ff, rt, ft, closure);
@@ -352,7 +360,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 		  for (i = 1;; i++) {
 		      rt = rf + (i * s) * d;
 		      ft = ff + (i * s) * (1 - d);
-		      if (rt < 0 || rt > 7 || ft < 0 || ft > 7) break;
+		      if (rt < 0 || rt > boardRows - 1 ||
+			  ft < 0 || ft > boardCols - 1) break;
 		      if (SameColor(board[rf][ff], board[rt][ft])) break;
 		      callback(board, flags, NormalMove,
 			       rf, ff, rt, ft, closure);
@@ -368,7 +377,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 		    for (i = 1;; i++) {
 			rt = rf + (i * rs);
 			ft = ff + (i * fs);
-			if (rt < 0 || rt > 7 || ft < 0 || ft > 7) break;
+			if (rt < 0 || rt > boardRows - 1 ||
+			    ft < 0 || ft > boardCols - 1) break;
 			if (SameColor(board[rf][ff], board[rt][ft])) break;
 			callback(board, flags, NormalMove,
 				 rf, ff, rt, ft, closure);
@@ -384,7 +394,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
 		    if (i == 0 && j == 0) continue;
 		    rt = rf + i;
 		    ft = ff + j;
-		    if (rt < 0 || rt > 7 || ft < 0 || ft > 7) continue;
+		    if (rt < 0 || rt > boardRows - 1 ||
+			ft < 0 || ft > boardCols - 1) continue;
 		    if (SameColor(board[rf][ff], board[rt][ft])) continue;
 		    callback(board, flags, NormalMove,
 			     rf, ff, rt, ft, closure);
@@ -425,7 +436,7 @@ void GenLegalCallback(board, flags, kind, rf, ff, rt, ft, closure)
 	if (board[rf][ff] == king) return;
 	for (r = rt-1; r <= rt+1; r++) {
 	  for (f = ft-1; f <= ft+1; f++) {
-	    if (r >= 0 && r <= 7 && f >= 0 && f <= 7 &&
+	    if (r >= 0 && r <= boardRows - 1 && f >= 0 && f <= boardCols - 1 &&
 		board[r][f] == king) return;
 	  }
 	}
@@ -441,7 +452,10 @@ void GenLegalCallback(board, flags, kind, rf, ff, rt, ft, closure)
    moves that would destroy your own king.  The CASTLE_OK flags are
    true if castling is not yet ruled out by a move of the king or
    rook.  Return TRUE if the player on move is currently in check and
-   F_IGNORE_CHECK is not set.  */
+   F_IGNORE_CHECK is not set.
+
+   XXX This routine works properly only for castling on 8x8 boards.
+ */
 int GenLegal(board, flags, epfile, callback, closure)
      Board board;
      int flags;
@@ -584,8 +598,8 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant)
        order a1, a2, a3, ... b1, b2, ..., h8 to find the first king,
        and we test only whether that one is in check. */
     cl.check = 0;
-    for (cl.fking = 0; cl.fking <= 7; cl.fking++)
-	for (cl.rking = 0; cl.rking <= 7; cl.rking++) {
+    for (cl.fking = 0; cl.fking <= boardCols - 1; cl.fking++)
+	for (cl.rking = 0; cl.rking <= boardRows - 1; cl.rking++) {
 	  if (board[cl.rking][cl.fking] == king) {
 	      GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, -1,
 			     CheckTestCallback, (VOIDSTAR) &cl);
diff --git a/moves.h b/moves.h
index c0c6b75..6f7dee5 100644
--- a/moves.h
+++ b/moves.h
@@ -71,6 +71,7 @@ typedef void (*MoveCallback) P((Board board, int flags, ChessMove kind,
 #define F_ATOMIC_CAPTURE 128    /* capturing piece explodes, destroying itself
 				   and all non-pawns on adjacent squares; 
 				   destroying your own king is illegal */
+#define F_DOUBLE_PAWN_MOVES 256 /* pawns can move two spaces first time */
 
 /* Special epfile values */
 #define EP_NONE -1
diff --git a/xboard.c b/xboard.c
index aa11b92..d75c05b 100644
--- a/xboard.c
+++ b/xboard.c
@@ -428,7 +428,6 @@ Widget shellWidget, layoutWidget, formWidget, boardWidget, messageWidget,
   menuBarWidget, buttonBarWidget, editShell, errorShell, analysisShell,
   ICSInputShell, fileNameShell, askQuestionShell;
 XSegment gridSegments[(BOARD_SIZE + 1) * 2];
-XSegment jailGridSegments[(BOARD_SIZE + 3) * 2];
 Font clockFontID, coordFontID;
 XFontStruct *clockFontStruct, *coordFontStruct;
 XtAppContext appContext;
@@ -1837,7 +1836,7 @@ main(argc, argv)
     int i, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
     XSetWindowAttributes window_attributes;
     Arg args[16];
-    Dimension timerWidth, boardWidth, w, h, sep, bor, wr, hr;
+    Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
     XrmValue vFrom, vTo;
     XtGeometryResult gres;
     char *p;
@@ -1972,21 +1971,22 @@ main(argc, argv)
 	}
     }
 		
-    boardWidth = lineGap + BOARD_SIZE * (squareSize + lineGap);
+    boardWidth = lineGap + boardCols * (squareSize + lineGap);
+    boardHeight = lineGap + boardRows * (squareSize + lineGap);
     if (appData.showJail == 1) {
 	/* Jail on top and bottom */
 	XtSetArg(boardArgs[1], XtNwidth, boardWidth);
 	XtSetArg(boardArgs[2], XtNheight,
-		 boardWidth + 2*(lineGap + squareSize));
+		 boardHeight + 2*(lineGap + squareSize));
     } else if (appData.showJail == 2) {
 	/* Jail on sides */
 	XtSetArg(boardArgs[1], XtNwidth,
 		 boardWidth + 2*(lineGap + squareSize));
-	XtSetArg(boardArgs[2], XtNheight, boardWidth);
+	XtSetArg(boardArgs[2], XtNheight, boardHeight);
     } else {
 	/* No jail */
 	XtSetArg(boardArgs[1], XtNwidth, boardWidth);
-	XtSetArg(boardArgs[2], XtNheight, boardWidth);
+	XtSetArg(boardArgs[2], XtNheight, boardHeight);
     }
 
     /*
@@ -3411,18 +3411,20 @@ void CreateGrid()
     int i;
     
     if (lineGap == 0) return;
-    for (i = 0; i < BOARD_SIZE + 1; i++) {
+    for (i = 0; i < boardRows + 1; i++) {
 	gridSegments[i].x1 = 0;
 	gridSegments[i].x2 =
-	  lineGap + BOARD_SIZE * (squareSize + lineGap);
+	  lineGap + boardCols * (squareSize + lineGap);
 	gridSegments[i].y1 = gridSegments[i].y2
 	  = lineGap / 2 + (i * (squareSize + lineGap));
+    }
 
-	gridSegments[i + BOARD_SIZE + 1].y1 = 0;
-	gridSegments[i + BOARD_SIZE + 1].y2 =
-	  BOARD_SIZE * (squareSize + lineGap);
-	gridSegments[i + BOARD_SIZE + 1].x1 =
-	  gridSegments[i + BOARD_SIZE + 1].x2
+    for (i = 0; i < boardCols + 1; i++) {
+	gridSegments[i + boardRows + 1].y1 = 0;
+	gridSegments[i + boardRows + 1].y2 =
+	  boardRows * (squareSize + lineGap);
+	gridSegments[i + boardRows + 1].x1 =
+	  gridSegments[i + boardRows + 1].x2
 	    = lineGap / 2 + (i * (squareSize + lineGap));
     }
 }
@@ -3659,15 +3661,15 @@ void PieceMenuPopup(w, event, params, num_params)
 	return;
     }
     
-    if (((pmFromX = EventToSquare(event->xbutton.x, BOARD_SIZE)) < 0) ||
-	((pmFromY = EventToSquare(event->xbutton.y, BOARD_SIZE)) < 0)) {
+    if (((pmFromX = EventToSquare(event->xbutton.x, boardCols)) < 0) ||
+	((pmFromY = EventToSquare(event->xbutton.y, boardRows)) < 0)) {
 	pmFromX = pmFromY = -1;
 	return;
     }
     if (flipView)
-      pmFromX = BOARD_SIZE - 1 - pmFromX;
+      pmFromX = boardCols - 1 - pmFromX;
     else
-      pmFromY = BOARD_SIZE - 1 - pmFromY;
+      pmFromY = boardRows - 1 - pmFromY;
     
     XtPopupSpringLoaded(XtNameToWidget(boardWidget, whichMenu));
 }
@@ -3752,12 +3754,12 @@ static void drawHighlight(file, rank, gc)
     if (lineGap == 0 || appData.blindfold) return;
     
     if (flipView) {
-	x = lineGap/2 + ((BOARD_SIZE-1)-file) * 
+	x = lineGap/2 + ((boardCols-1)-file) *
 	  (squareSize + lineGap);
 	y = lineGap/2 + rank * (squareSize + lineGap);
     } else {
 	x = lineGap/2 + file * (squareSize + lineGap);
-	y = lineGap/2 + ((BOARD_SIZE-1)-rank) * 
+	y = lineGap/2 + ((boardRows-1)-rank) *
 	  (squareSize + lineGap);
     }
     
@@ -4020,12 +4022,12 @@ void DrawSquare(row, column, piece, do_flash)
     flash_delay = 500 / appData.flashRate;
 	
     if (flipView) {
-	x = lineGap + ((BOARD_SIZE-1)-column) * 
+	x = lineGap + ((boardCols-1)-column) *
 	  (squareSize + lineGap);
 	y = lineGap + row * (squareSize + lineGap);
     } else {
 	x = lineGap + column * (squareSize + lineGap);
-	y = lineGap + ((BOARD_SIZE-1)-row) * 
+	y = lineGap + ((boardRows-1)-row) *
 	  (squareSize + lineGap);
     }
     
@@ -4051,7 +4053,7 @@ void DrawSquare(row, column, piece, do_flash)
     }
 	
     string[1] = NULLCHAR;
-    if (appData.showCoords && row == (flipView ? 7 : 0)) {
+    if (appData.showCoords && row == (flipView ? boardRows - 1 : 0)) {
 	string[0] = 'a' + column;
 	XTextExtents(coordFontStruct, string, 1, &direction, 
 		     &font_ascent, &font_descent, &overall);
@@ -4065,7 +4067,7 @@ void DrawSquare(row, column, piece, do_flash)
 			y + squareSize - font_descent - 1, string, 1);
 	}
     }
-    if (appData.showCoords && column == (flipView ? 7 : 0)) {
+    if (appData.showCoords && column == (flipView ? boardCols - 1 : 0)) {
 	string[0] = '1' + row;
 	XTextExtents(coordFontStruct, string, 1, &direction, 
 		     &font_ascent, &font_descent, &overall);
@@ -4115,8 +4117,8 @@ static int too_many_diffs(b1, b2)
     int i, j;
     int c = 0;
   
-    for (i=0; i<BOARD_SIZE; ++i) {
-	for (j=0; j<BOARD_SIZE; ++j) {
+    for (i=0; i<boardRows; ++i) {
+	for (j=0; j<boardCols; ++j) {
 	    if (b1[i][j] != b2[i][j]) {
 		if (++c > 4)	/* Castling causes 4 diffs */
 		  return 1;
@@ -4225,8 +4227,8 @@ void XDrawPosition(w, repaint, board)
 	/* First pass -- Draw (newly) empty squares and repair damage. 
 	   This prevents you from having a piece show up twice while it 
 	   is flashing on its new square */
-	for (i = 0; i < BOARD_SIZE; i++)
-	  for (j = 0; j < BOARD_SIZE; j++)
+	for (i = 0; i < boardRows; i++)
+	  for (j = 0; j < boardCols; j++)
 	    if ((board[i][j] != lastBoard[i][j] && board[i][j] == EmptySquare)
 		|| damage[i][j]) {
 		DrawSquare(i, j, board[i][j], 0);
@@ -4234,18 +4236,18 @@ void XDrawPosition(w, repaint, board)
 	    }
 
 	/* Second pass -- Draw piece(s) in new position and flash them */
-	for (i = 0; i < BOARD_SIZE; i++)
-	  for (j = 0; j < BOARD_SIZE; j++)
+	for (i = 0; i < boardRows; i++)
+	  for (j = 0; j < boardCols; j++)
 	    if (board[i][j] != lastBoard[i][j]) {
 		DrawSquare(i, j, board[i][j], do_flash);	  
 	    }
     } else {
 	if (lineGap > 0)
 	  XDrawSegments(xDisplay, xBoardWindow, lineGC,
-			gridSegments, (BOARD_SIZE + 1) * 2);
+			gridSegments, boardRows + boardCols + 2);
 	
-	for (i = 0; i < BOARD_SIZE; i++)
-	  for (j = 0; j < BOARD_SIZE; j++) {
+	for (i = 0; i < boardRows; i++)
+	  for (j = 0; j < boardCols; j++) {
 	      DrawSquare(i, j, board[i][j], 0);
 	      damage[i][j] = False;
 	  }
@@ -4318,13 +4320,13 @@ void HandleUserMove(w, event, prms, nprms)
 	}
     }
     
-    x = EventToSquare(event->xbutton.x, BOARD_SIZE);
-    y = EventToSquare(event->xbutton.y, BOARD_SIZE);
+    x = EventToSquare(event->xbutton.x, boardCols);
+    y = EventToSquare(event->xbutton.y, boardRows);
     if (!flipView && y >= 0) {
-	y = BOARD_SIZE - 1 - y;
+	y = boardRows - 1 - y;
     }
     if (flipView && x >= 0) {
-	x = BOARD_SIZE - 1 - x;
+	x = boardCols - 1 - x;
     }
 
     if (fromX == -1) {
@@ -7962,11 +7964,11 @@ ScreenSquare(column, row, pt, color)
      int column; int row; XPoint * pt; int * color;
 {
   if (flipView) {
-    pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);
+    pt->x = lineGap + ((boardCols-1)-column) * (squareSize + lineGap);
     pt->y = lineGap + row * (squareSize + lineGap);
   } else {
     pt->x = lineGap + column * (squareSize + lineGap);
-    pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);
+    pt->y = lineGap + ((boardRows-1)-row) * (squareSize + lineGap);
   }
   *color = ((column + row) % 2) == 1;
 }
@@ -7977,12 +7979,12 @@ static void
 BoardSquare(x, y, column, row)
      int x; int y; int * column; int * row;
 {
-  *column = EventToSquare(x, BOARD_SIZE);
+  *column = EventToSquare(x, boardCols);
   if (flipView && *column >= 0)
-    *column = BOARD_SIZE - 1 - *column;
-  *row = EventToSquare(y, BOARD_SIZE);
+    *column = boardCols - 1 - *column;
+  *row = EventToSquare(y, boardRows);
   if (!flipView && *row >= 0)
-    *row = BOARD_SIZE - 1 - *row;
+    *row = boardRows - 1 - *row;
 }
 
 /*   Utilities	*/
-- 
1.6.2.1

