extern char installDir[MSG_SIZ];
VariantClass startVariant; /* [HGM] nicks: initial variant */
Boolean abortMatch;
-int deadRanks;
+int deadRanks, handSize, handOffsets;
extern int tinyLayout, smallLayout;
ChessProgramStats programStats;
if( (int)lowestPiece >= BlackPawn ) {
holdingsColumn = 0;
countsColumn = 1;
- holdingsStartRow = BOARD_HEIGHT-1;
+ holdingsStartRow = handSize-1;
direction = -1;
} else {
holdingsColumn = BOARD_WIDTH-1;
direction = 1;
}
- for(i=0; i<BOARD_HEIGHT; i++) { /* clear holdings */
+ for(i=0; i<BOARD_RANKS-1; i++) { /* clear holdings */
board[i][holdingsColumn] = EmptySquare;
board[i][countsColumn] = (ChessSquare) 0;
}
parse, currentMove);
if (sscanf(parse, " game %d", &gamenum) == 1) {
if(gamenum == ics_gamenum) { // [HGM] bughouse: old code if part of foreground game
+ new_piece[0] = NULLCHAR;
+ sscanf(parse, "game %d white [%s black [%s <- %s",
+ &gamenum, white_holding, black_holding,
+ new_piece);
+ white_holding[strlen(white_holding)-1] = NULLCHAR;
+ black_holding[strlen(black_holding)-1] = NULLCHAR;
if (gameInfo.variant == VariantNormal) {
/* [HGM] We seem to switch variant during a game!
* Presumably no holdings were displayed, so we have
switch(gameInfo.boardWidth) { // base guess on board width
case 9: newVariant = VariantShogi; break;
case 10: newVariant = VariantGreat; break;
- default: newVariant = VariantCrazyhouse; break;
+ default: newVariant = VariantCrazyhouse;
+ if(strchr(white_holding, 'E') || strchr(black_holding, 'E') ||
+ strchr(white_holding, 'H') || strchr(black_holding, 'H') )
+ newVariant = VariantSChess;
}
VariantSwitch(boards[currentMove], newVariant); /* temp guess */
/* Get a move list just to see the header, which
SendToICS(str);
}
}
- new_piece[0] = NULLCHAR;
- sscanf(parse, "game %d white [%s black [%s <- %s",
- &gamenum, white_holding, black_holding,
- new_piece);
- white_holding[strlen(white_holding)-1] = NULLCHAR;
- black_holding[strlen(black_holding)-1] = NULLCHAR;
/* [HGM] copy holdings to board holdings area */
CopyHoldings(boards[forwardMostMove], white_holding, WhitePawn);
CopyHoldings(boards[forwardMostMove], black_holding, BlackPawn);
boards[moveNum][EP_STATUS] = EP_NONE;
if(str[0] == 'P') boards[moveNum][EP_STATUS] = EP_PAWN_MOVE;
if(strchr(move_str, 'x')) boards[moveNum][EP_STATUS] = EP_CAPTURE;
- if(double_push != -1) boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT;
+ if(double_push != -1) {
+ int dir = WhiteOnMove(moveNum) ? 1 : -1, last = BOARD_HEIGHT-1;
+ boards[moveNum][EP_FILE] = // also set new e.p. variables
+ boards[moveNum][EP_STATUS] = double_push + BOARD_LEFT;
+ boards[moveNum][EP_RANK] = (last + 3*dir)/2;
+ boards[moveNum][LAST_TO] = 128*(last + dir) + boards[moveNum][EP_FILE];
+ } else boards[moveNum][EP_FILE] = boards[moveNum][EP_RANK] = 100;
if (ics_getting_history == H_GOT_REQ_HEADER ||
&& gameInfo.variant != VariantGrand&& gameInfo.variant != VariantSChess) // inherit info that ICS does not give from previous board
for(k=0; k<ranks; k++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++) {
ChessSquare old, new = boards[moveNum][k][j];
- if(fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
+ if(new == EmptySquare || fromY == DROP_RANK && k==toY && j==toX) continue; // dropped pieces always stand for themselves
old = (k==toY && j==toX) ? boards[moveNum-1][fromY][fromX] : boards[moveNum-1][k][j]; // trace back mover
if(old == new) continue;
if(old == PROMOTED(new)) boards[moveNum][k][j] = old;// prevent promoted pieces to revert to primordial ones
if(old < WhiteCannon || old >= BlackPawn && old < BlackCannon)
boards[moveNum][k][j] = PROMOTED(old); // choose correct type of Gold in promotion
else boards[moveNum][k][j] = old; // preserve type of Gold
- } else if((old == WhitePawn || old == BlackPawn) && new != EmptySquare) // Pawn promotions (but not e.p.capture!)
+ } else if(old == WhitePawn || old == BlackPawn) // Pawn promotions (but not e.p.capture!)
boards[moveNum][k][j] = PROMOTED(new); // use non-primordial representation of chosen piece
}
} else {
j = seed%4; seed /= 4;
p = board[0][BOARD_LEFT+j]; board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p);
board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;
- board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;
+ board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++;
j = seed%3 + (seed%3 >= j); seed /= 3;
p = board[0][BOARD_LEFT+j]; board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p);
board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;
- board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;
+ board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++;
j = seed%3; seed /= 3;
p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p);
board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;
- board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;
+ board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++;
j = seed%2 + (seed%2 >= j); seed /= 2;
p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p);
board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;
- board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;
+ board[handSize-1-k][0] = WHITE_TO_BLACK p; board[handSize-1-k][1]++;
j = seed%4; seed /= 4; put(board, exoPieces[3], 0, j, ANY);
j = seed%3; seed /= 3; put(board, exoPieces[2], 0, j, ANY);
j = seed%2; seed /= 2; put(board, exoPieces[1], 0, j, ANY);
}
if(appData.holdingsSize >= 0) {
i = appData.holdingsSize;
- if(i > gameInfo.boardHeight) i = gameInfo.boardHeight;
+// if(i > gameInfo.boardHeight) i = gameInfo.boardHeight;
gameInfo.holdingsSize = i;
}
if(gameInfo.holdingsSize) gameInfo.holdingsWidth = 2;
if(BOARD_HEIGHT > BOARD_RANKS || BOARD_WIDTH > BOARD_FILES)
DisplayFatalError(_("Recompile to support this BOARD_RANKS or BOARD_FILES!"), 0, 2);
+ if(!handSize) handSize = BOARD_HEIGHT;
pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */
if(pawnRow < 1) pawnRow = 1;
if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN ||
if(gameInfo.variant == VariantGreat) { // promotion commoners
initialPosition[PieceToNumber(WhiteMan)][BOARD_WIDTH-1] = WhiteMan;
initialPosition[PieceToNumber(WhiteMan)][BOARD_WIDTH-2] = 9;
- initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan;
- initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9;
+ initialPosition[handSize-1-PieceToNumber(WhiteMan)][0] = BlackMan;
+ initialPosition[handSize-1-PieceToNumber(WhiteMan)][1] = 9;
}
if( gameInfo.variant == VariantSChess ) {
initialPosition[1][0] = BlackMarshall;
initialPosition[1][1] = initialPosition[2][1] =
initialPosition[6][BOARD_WIDTH-2] = initialPosition[5][BOARD_WIDTH-2] = 1;
}
+ initialPosition[CHECK_COUNT] = (gameInfo.variant == Variant3Check ? 0x303 : 0);
if (appData.debugMode) {
fprintf(debugFP, "shuffleOpenings = %d\n", shuffleOpenings);
}
piece = boards[currentMove][fromY][fromX];
if(gameInfo.variant == VariantChu) {
- promotionZoneSize = BOARD_HEIGHT/3;
+ promotionZoneSize = (BOARD_HEIGHT - deadRanks)/3;
if(legal[toY][toX] == 6) return FALSE; // no promotion if highlights deny it
highestPromotingPiece = (PieceToChar(piece) == '+' || PieceToChar(CHUPROMOTED(piece)) != '+') ? WhitePawn : WhiteKing;
} else if(gameInfo.variant == VariantShogi) {
- promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8);
+ promotionZoneSize = (BOARD_HEIGHT- deadRanks)/3 +(BOARD_HEIGHT == 8);
highestPromotingPiece = (int)WhiteAlfil;
+ if(PieceToChar(piece) != '+' || PieceToChar(CHUPROMOTED(piece)) == '+') highestPromotingPiece = piece;
} else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) {
promotionZoneSize = 3;
}
if(fromY < promotionZoneSize && gameInfo.variant == VariantChuChess) return FALSE;
highestPromotingPiece = WHITE_TO_BLACK highestPromotingPiece;
} else {
- if( toY < BOARD_HEIGHT - promotionZoneSize &&
- fromY < BOARD_HEIGHT - promotionZoneSize) return FALSE;
- if(fromY >= BOARD_HEIGHT - promotionZoneSize && gameInfo.variant == VariantChuChess)
+ if( toY < BOARD_HEIGHT - deadRanks - promotionZoneSize &&
+ fromY < BOARD_HEIGHT - deadRanks - promotionZoneSize) return FALSE;
+ if(fromY >= BOARD_HEIGHT - deadRanks - promotionZoneSize && gameInfo.variant == VariantChuChess)
return FALSE;
}
return FALSE;
}
} else {
- if(toY == BOARD_HEIGHT-1 && piece == WhitePawn ||
- toY == BOARD_HEIGHT-1 && piece == WhiteQueen ||
- toY >= BOARD_HEIGHT-2 && piece == WhiteKnight) {
+ if(toY == BOARD_HEIGHT-deadRanks-1 && piece == WhitePawn ||
+ toY == BOARD_HEIGHT-deadRanks-1 && piece == WhiteQueen ||
+ toY >= BOARD_HEIGHT-deadRanks-2 && piece == WhiteKnight) {
*promoChoice = '+';
return FALSE;
}
int
PieceForSquare (int x, int y)
{
- if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT)
- return -1;
- else
+ if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) return -1;
+ if(x == BOARD_RGHT+1 && handOffsets & 1) y += handSize - BOARD_HEIGHT;
+ if(x == BOARD_LEFT-2 && !(handOffsets & 2)) y += handSize - BOARD_HEIGHT;
return boards[currentMove][y][x];
}
+ChessSquare
+More (Board board, int col, int start, int end)
+{
+ int k;
+ for(k=start; k<end; k++) if(board[k][col]) return (col == 1 ? WhiteMonarch : BlackMonarch); // arrow image
+ return EmptySquare;
+}
+
+void
+DrawPosition (int repaint, Board board)
+{
+ Board compactedBoard;
+ if(handSize > BOARD_HEIGHT && board) {
+ int k;
+ CopyBoard(compactedBoard, board);
+ if(handOffsets & 1) {
+ for(k=0; k<BOARD_HEIGHT; k++) {
+ compactedBoard[k][BOARD_WIDTH-1] = board[k+handSize-BOARD_HEIGHT][BOARD_WIDTH-1];
+ compactedBoard[k][BOARD_WIDTH-2] = board[k+handSize-BOARD_HEIGHT][BOARD_WIDTH-2];
+ }
+ compactedBoard[0][BOARD_WIDTH-1] = More(board, BOARD_WIDTH-2, 0, handSize-BOARD_HEIGHT+1);
+ } else compactedBoard[BOARD_HEIGHT-1][BOARD_WIDTH-1] = More(board, BOARD_WIDTH-2, BOARD_HEIGHT-1, handSize);
+ if(!(handOffsets & 2)) {
+ for(k=0; k<BOARD_HEIGHT; k++) {
+ compactedBoard[k][0] = board[k+handSize-BOARD_HEIGHT][0];
+ compactedBoard[k][1] = board[k+handSize-BOARD_HEIGHT][1];
+ }
+ compactedBoard[0][0] = More(board, 1, 0, handSize-BOARD_HEIGHT+1);
+ } else compactedBoard[BOARD_HEIGHT-1][0] = More(board, 1, BOARD_HEIGHT-1, handSize);
+ DrawPositionX(TRUE, compactedBoard);
+ } else DrawPositionX(repaint, board);
+}
+
int
OKToStartUserMove (int x, int y)
{
if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n",
moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
// holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
- if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
+ if(fromX == 0) fromY = handSize-1 - fromY; // black holdings upside-down
fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
while(PieceToChar(fromX) == '.' || PieceToChar(fromX) == '+' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++;
fromY = DROP_RANK;
if(WhiteOnMove(currentMove)) {
if(!boards[currentMove][k][BOARD_WIDTH-2]) return 0;
} else {
- if(!boards[currentMove][BOARD_HEIGHT-1-k][1]) return 0;
+ if(!boards[currentMove][handSize-1-k][1]) return 0;
}
}
if(PosFlags(0) & F_MANDATORY_CAPTURE) {
for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) if(marker[y][x]>1) capt++;
if(capt)
- for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) if(marker[y][x] == 1) marker[y][x] = 0;
+ for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) if(marker[y][x] == 1) marker[y][x] = legal[y][x] = 0;
}
}
DrawPosition(FALSE, NULL);
(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
gameInfo.variant == VariantMakruk) && !*engineVariant) return FALSE;
return (piece == BlackPawn && y <= zone ||
- piece == WhitePawn && y >= BOARD_HEIGHT-1-zone ||
+ piece == WhitePawn && y >= BOARD_HEIGHT-1-deadRanks-zone ||
piece == BlackLance && y <= zone ||
- piece == WhiteLance && y >= BOARD_HEIGHT-1-zone );
+ piece == WhiteLance && y >= BOARD_HEIGHT-1-deadRanks-zone );
}
void
Boolean right; // instructs front-end to use button-1 events as if they were button 3
Boolean deferChoice;
+int createX = -1, createY = -1; // square where we last created a piece in EditPosition mode
void
LeftClick (ClickType clickType, int xPix, int yPix)
x = BOARD_WIDTH - 1 - x;
}
- if(appData.monoMouse && gameMode == EditPosition && fromX < 0 && clickType == Press && boards[currentMove][y][x] == EmptySquare) {
+ // map clicks in offsetted holdings back to true coords (or switch the offset)
+ if(x == BOARD_RGHT+1) {
+ if(handOffsets & 1) {
+ if(y == 0) { handOffsets &= ~1; DrawPosition(TRUE, boards[currentMove]); return; }
+ y += handSize - BOARD_HEIGHT;
+ } else if(y == BOARD_HEIGHT-1) { handOffsets |= 1; DrawPosition(TRUE, boards[currentMove]); return; }
+ }
+ if(x == BOARD_LEFT-2) {
+ if(!(handOffsets & 2)) {
+ if(y == 0) { handOffsets |= 2; DrawPosition(TRUE, boards[currentMove]); return; }
+ y += handSize - BOARD_HEIGHT;
+ } else if(y == BOARD_HEIGHT-1) { handOffsets &= ~2; DrawPosition(TRUE, boards[currentMove]); return; }
+ }
+
+ if(appData.monoMouse && gameMode == EditPosition && fromX < 0 && clickType == Press &&
+ (boards[currentMove][y][x] == EmptySquare || x == createX && y == createY) ) {
static int dummy;
RightClick(clickType, xPix, yPix, &dummy, &dummy);
right = TRUE;
return;
}
+ createX = createY = -1;
+
if(SeekGraphClick(clickType, xPix, yPix, 0)) return;
prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
if(x == BOARD_LEFT-2 && piece >= BlackPawn) {
n = PieceToNumber(piece - (int)BlackPawn);
if(n >= gameInfo.holdingsSize) { n = 0; piece = BlackPawn; }
- boards[currentMove][BOARD_HEIGHT-1 - n][0] = piece;
- boards[currentMove][BOARD_HEIGHT-1 - n][1]++;
+ boards[currentMove][handSize-1 - n][0] = piece;
+ boards[currentMove][handSize-1 - n][1]++;
} else
if(x == BOARD_RGHT+1 && piece < BlackPawn) {
n = PieceToNumber(piece);
if (xSqr == BOARD_LEFT-1 || xSqr == BOARD_RGHT) return -1;
if (xSqr < 0 || ySqr < 0) return -1;
if(appData.pieceMenu) { whichMenu = 0; break; } // edit-position menu
+ if(flipView) xSqr = BOARD_WIDTH - 1 - xSqr; else ySqr = BOARD_HEIGHT - 1 - ySqr;
+ if(xSqr == createX && ySqr == createY && xSqr != BOARD_LEFT-2 && xSqr != BOARD_RGHT+1) {
+ ChessSquare p = boards[currentMove][ySqr][xSqr];
+ do { if(++p == EmptySquare) p = WhitePawn; } while(PieceToChar(p) == '.');
+ boards[currentMove][ySqr][xSqr] = p; DrawPosition(FALSE, boards[currentMove]);
+ return -2;
+ }
pieceSweep = shiftKey ? BlackPawn : WhitePawn; // [HGM] sweep: prepare selecting piece by mouse sweep
- toX = xSqr; toY = ySqr; lastX = x, lastY = y;
- if(flipView) toX = BOARD_WIDTH - 1 - toX; else toY = BOARD_HEIGHT - 1 - toY;
+ createX = toX = xSqr; createY = toY = ySqr; lastX = x, lastY = y;
NextPiece(0);
return 2; // grab
case IcsObserving:
while(message[s] && message[s++] != ' ');
if(BOARD_HEIGHT != h || BOARD_WIDTH != w + 4*(hand != 0) || gameInfo.holdingsSize != hand ||
dummy == 4 && gameInfo.variant != StringToVariant(varName) ) { // engine wants to change board format or variant
- if(hand <= h) deadRanks = 0; else deadRanks = hand - h, h = hand; // adapt board to over-sized holdings
+// if(hand <= h) deadRanks = 0; else deadRanks = hand - h, h = hand; // adapt board to over-sized holdings
+ if(hand > h) handSize = hand; else handSize = h;
appData.NrFiles = w; appData.NrRanks = h; appData.holdingsSize = hand;
if(dummy == 4) gameInfo.variant = StringToVariant(varName); // parent variant
InitPosition(1); // calls InitDrawingSizes to let new parameters take effect
ParseGameHistory (char *game)
{
ChessMove moveType;
- int fromX, fromY, toX, toY, boardIndex;
+ int fromX, fromY, toX, toY, boardIndex, mask;
char promoChar;
char *p, *q;
char buf[MSG_SIZ];
strcat(moveList[boardIndex], "\n");
boardIndex++;
ApplyMove(fromX, fromY, toX, toY, promoChar, boards[boardIndex]);
+ mask = (WhiteOnMove(boardIndex) ? 0xFF : 0xFF00);
switch (MateTest(boards[boardIndex], PosFlags(boardIndex)) ) {
case MT_NONE:
case MT_STALEMATE:
default:
break;
case MT_CHECK:
- if(!IS_SHOGI(gameInfo.variant))
- strcat(parseList[boardIndex - 1], "+");
- break;
+ if(boards[boardIndex][CHECK_COUNT]) boards[boardIndex][CHECK_COUNT] -= mask & 0x101;
+ if(!boards[boardIndex][CHECK_COUNT] || boards[boardIndex][CHECK_COUNT] & mask) {
+ if(!IS_SHOGI(gameInfo.variant)) strcat(parseList[boardIndex - 1], "+");
+ break;
+ }
case MT_CHECKMATE:
case MT_STAINMATE:
strcat(parseList[boardIndex - 1], "#");
/* we can always do that 'in place', now pointers to these rights are passed to ApplyMove */
if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;
- oldEP = (signed char)board[EP_STATUS]; epRank = board[EP_RANK]; epFile = board[EP_FILE]; lastFile = board[LAST_FILE],lastRank = board[LAST_RANK];
+ oldEP = (signed char)board[EP_STATUS]; epRank = board[EP_RANK]; epFile = board[EP_FILE]; lastFile = board[LAST_TO] & 255,lastRank = board[LAST_TO] >> 8;
board[EP_STATUS] = EP_NONE;
- board[EP_FILE] = board[EP_RANK] = board[LAST_FILE] = board[LAST_RANK] = 100;
+ board[EP_FILE] = board[EP_RANK] = 100, board[LAST_TO] = 0x4040;
if (fromY == DROP_RANK) {
/* must be first */
if(toX<BOARD_RGHT-1 && board[toY][toX+1] == BlackPawn &&
gameInfo.variant != VariantBerolina || toX > fromX)
board[EP_STATUS] = toX;
- board[LAST_FILE] = toX; board[LAST_RANK] = toY;
+ board[LAST_TO] = toX + 256*toY;
}
} else
if( pawn == BlackPawn ) {
if(toX<BOARD_RGHT-1 && board[toY][toX+1] == WhitePawn &&
gameInfo.variant != VariantBerolina || toX > fromX)
board[EP_STATUS] = toX;
- board[LAST_FILE] = toX; board[LAST_RANK] = toY;
+ board[LAST_TO] = toX + 256*toY;
}
}
p -= (int)BlackPawn;
p = PieceToNumber((ChessSquare)p);
if(p >= gameInfo.holdingsSize) p = 0;
- if(--board[BOARD_HEIGHT-1-p][1] <= 0)
- board[BOARD_HEIGHT-1-p][0] = EmptySquare;
- if((int)board[BOARD_HEIGHT-1-p][1] < 0)
- board[BOARD_HEIGHT-1-p][1] = 0;
+ if(--board[handSize-1-p][1] <= 0)
+ board[handSize-1-p][0] = EmptySquare;
+ if((int)board[handSize-1-p][1] < 0)
+ board[handSize-1-p][1] = 0;
}
}
if (captured != EmptySquare && gameInfo.holdingsSize > 0
}
p = PieceToNumber((ChessSquare)p);
if(p >= gameInfo.holdingsSize) { p = 0; captured = WhitePawn; }
- board[BOARD_HEIGHT-1-p][1]++;
- board[BOARD_HEIGHT-1-p][0] = WHITE_TO_BLACK captured;
+ board[handSize-1-p][1]++;
+ board[handSize-1-p][0] = WHITE_TO_BLACK captured;
}
}
} else if (gameInfo.variant == VariantAtomic) {
if(!--board[k][BOARD_WIDTH-2])
board[k][BOARD_WIDTH-1] = EmptySquare;
} else {
- if(!--board[BOARD_HEIGHT-1-k][1])
- board[BOARD_HEIGHT-1-k][0] = EmptySquare;
+ if(!--board[handSize-1-k][1])
+ board[handSize-1-k][0] = EmptySquare;
}
}
}
void
MakeMove (int fromX, int fromY, int toX, int toY, int promoChar)
{
- int x = toX, y = toY;
+ int x = toX, y = toY, mask;
char *s = parseList[forwardMostMove];
ChessSquare p = boards[forwardMostMove][toY][toX];
// forwardMostMove++; // [HGM] bare: moved downstream
}
CoordsToComputerAlgebraic(fromY, fromX, toY, toX, promoChar,
moveList[forwardMostMove - 1]);
+ mask = (WhiteOnMove(forwardMostMove) ? 0xFF : 0xFF00);
switch (MateTest(boards[forwardMostMove], PosFlags(forwardMostMove)) ) {
case MT_NONE:
case MT_STALEMATE:
default:
break;
case MT_CHECK:
- if(!IS_SHOGI(gameInfo.variant))
- strcat(parseList[forwardMostMove - 1], "+");
- break;
+ if(boards[forwardMostMove][CHECK_COUNT]) boards[forwardMostMove][CHECK_COUNT] -= mask & 0x101;
+ if(!boards[forwardMostMove][CHECK_COUNT] || boards[forwardMostMove][CHECK_COUNT] & mask) {
+ if(!IS_SHOGI(gameInfo.variant)) strcat(parseList[forwardMostMove - 1], "+");
+ break;
+ }
case MT_CHECKMATE:
case MT_STAINMATE:
strcat(parseList[forwardMostMove - 1], "#");
if(n == 1) SwapEngines(n);
ParseArgsFromString(buf);
if(n == 1) SwapEngines(n);
+ if(n < 2) { ASSIGN(currentEngine[n], command[i]); }
if(n == 0 && *appData.secondChessProgram == NULLCHAR) {
SwapEngines(1); // set second same as first if not yet set (to suppress WB startup dialog)
ParseArgsFromString(buf);
if(mnemonic[n]) { // if somehow the engine with the selected nickname is no longer found in the list, we skip
ReplaceEngine(&first, 0);
FloatToFront(&appData.recentEngineList, command[n]);
+ ASSIGN(currentEngine[0], command[n]);
}
}
}
pieceDefs = FALSE; // [HGM] gen: reset engine-defined piece moves
deadRanks = 0; // assume entire board is used
+ handSize = 0;
for(i=0; i<EmptySquare; i++) { FREE(pieceDesc[i]); pieceDesc[i] = NULL; }
CleanupTail(); // [HGM] vari: delete any stored variations
CommentPopDown(); // [HGM] make sure no comments to the previous game keep hanging on
}
void
-ToggleSecond ()
+StartSecond ()
{
- if(second.analyzing) {
- SendToProgram("exit\n", &second);
- second.analyzing = FALSE;
- } else {
- if (second.pr == NoProc) StartChessProgram(&second);
+ if(WaitForEngine(&second, StartSecond)) return;
InitChessProgram(&second, FALSE);
FeedMovesToProgram(&second, currentMove);
SendToProgram("analyze\n", &second);
second.analyzing = TRUE;
+ ThawUI();
+}
+
+void
+ToggleSecond ()
+{
+ if(second.analyzing) {
+ SendToProgram("exit\n", &second);
+ second.analyzing = FALSE;
+ } else {
+ StartSecond();
}
}
} else {
if(x < BOARD_LEFT || x >= BOARD_RGHT) {
if(x == BOARD_LEFT-2) {
- if(y < BOARD_HEIGHT-1-gameInfo.holdingsSize) break;
+ if(y < handSize-1-gameInfo.holdingsSize) break;
boards[0][y][1] = 0;
} else
if(x == BOARD_RGHT+1) {
if(x == BOARD_LEFT-2 && selection >= BlackPawn) {
n = PieceToNumber(selection - BlackPawn);
if(n >= gameInfo.holdingsSize) { n = 0; selection = BlackPawn; }
- boards[0][BOARD_HEIGHT-1-n][0] = selection;
- boards[0][BOARD_HEIGHT-1-n][1]++;
+ boards[0][handSize-1-n][0] = selection;
+ boards[0][handSize-1-n][1]++;
} else
if(x == BOARD_RGHT+1 && selection < BlackPawn) {
n = PieceToNumber(selection);
opt->type = SaveButton;
} else return FALSE;
*p = 0; // terminate option name
+ *(int*) (opt->name + MSG_SIZ - 104) = opt->value; // hide default values somewhere
+ if(opt->target == &opt->textValue) strncpy(opt->name + MSG_SIZ - 100, opt->textValue, 99);
// now look if the command-line options define a setting for this engine option.
if(cps->optionSettings && cps->optionSettings[0])
p = strstr(cps->optionSettings, opt->name); else p = NULL;
if(!strcmp(((char**)opt->textValue)[n], q+1)) opt->value = n;
break;
case TextBox:
+ case FileName:
+ case PathName:
safeStrCpy(opt->textValue, q+1, MSG_SIZ - (opt->textValue - opt->name));
break;
case Spin:
strcat(buf, "\n");
SendToProgram(buf, cps);
}
- *(int*) (opt->name + MSG_SIZ - 104) = opt->value; // hide default values somewhere
- if(opt->target == &opt->textValue) strncpy(opt->name + MSG_SIZ - 100, opt->textValue, 99);
return TRUE;
}
DelayedEventCallback cb = GetDelayedEvent();
if ((cb == InitBackEnd3 && cps == &first) ||
(cb == SettingsMenuIfReady && cps == &second) ||
- (cb == LoadEngine) ||
+ (cb == LoadEngine) || (cb == StartSecond) ||
(cb == TwoMachinesEventIfReady)) {
CancelDelayedEvent();
ScheduleDelayedEvent(cb, val ? 1 : 3600000);
*p++ = PieceToChar(piece);
}
for(i=0; i<gameInfo.holdingsSize; i++) { /* black holdings */
- piece = boards[move][BOARD_HEIGHT-i-1][0];
+ piece = boards[move][handSize-i-1][0];
if( piece != EmptySquare )
- for(j=0; j<(int) boards[move][BOARD_HEIGHT-i-1][1]; j++)
+ for(j=0; j<(int) boards[move][handSize-i-1][1]; j++)
*p++ = PieceToChar(piece);
}
fromY = moveList[move - 1][1] - ONE;
toX = moveList[move - 1][2] - AAA;
toY = moveList[move - 1][3] - ONE;
- if (fromY == (whiteToPlay ? BOARD_HEIGHT-2 : 1) &&
- toY == (whiteToPlay ? BOARD_HEIGHT-4 : 3) &&
- boards[move][toY][toX] == (whiteToPlay ? BlackPawn : WhitePawn) &&
- fromX == toX) {
+ if ((whiteToPlay ? toY < fromY - 1 : toY > fromY + 1) &&
+ boards[move][toY][toX] == (whiteToPlay ? BlackPawn : WhitePawn) ) {
/* 2-square pawn move just happened */
- *p++ = toX + AAA;
- *p++ = whiteToPlay ? '6'+BOARD_HEIGHT-8 : '3';
+ *p++ = (3*toX + 5*fromX + 4)/8 + AAA;
+ *p++ = (3*toY + 5*fromY + 4)/8 + ONE;
+ if(gameInfo.variant == VariantBerolina) {
+ *p++ = toX + AAA;
+ *p++ = toY + ONE;
+ }
} else {
*p++ = '-';
}
}
}
+ i = boards[move][CHECK_COUNT];
+ if(i) {
+ sprintf(p, "%d+%d ", i&255, i>>8);
+ while(*p) p++;
+ }
+
if(moveCounts)
{ int i = 0, j=move;
/* [HGM] by default clear Crazyhouse holdings, if present */
if(gameInfo.holdingsWidth) {
- for(i=0; i<BOARD_HEIGHT; i++) {
+ for(i=0; i<handSize; i++) {
board[i][0] = EmptySquare; /* black holdings */
board[i][BOARD_WIDTH-1] = EmptySquare; /* white holdings */
board[i][1] = (ChessSquare) 0; /* black counts */
i = (int)piece - (int)BlackPawn;
i = PieceToNumber((ChessSquare)i);
if( i >= gameInfo.holdingsSize ) return FALSE;
- board[BOARD_HEIGHT-1-i][0] = piece; /* black holdings */
- board[BOARD_HEIGHT-1-i][1]++; /* black counts */
+ board[handSize-1-i][0] = piece; /* black holdings */
+ board[handSize-1-i][1]++; /* black counts */
bcnt++;
} else {
i = (int)piece - (int)WhitePawn;
if(board[BOARD_HEIGHT-1][j] == ClearBoard) {
if(!bcnt) return FALSE;
if(n >= bcnt) n = rand() % bcnt; // use same randomization for black and white if possible
- for(k=0, m=n; k<gameInfo.holdingsSize; k++) if((n -= board[BOARD_HEIGHT-1-k][1]) < 0) {
- board[BOARD_HEIGHT-1][j] = board[BOARD_HEIGHT-1-k][0]; bcnt--;
- if(--board[BOARD_HEIGHT-1-k][1] == 0) board[BOARD_HEIGHT-1-k][0] = EmptySquare;
+ for(k=0, m=n; k<gameInfo.holdingsSize; k++) if((n -= board[handSize-1-k][1]) < 0) {
+ board[BOARD_HEIGHT-1][j] = board[handSize-1-k][0]; bcnt--;
+ if(--board[handSize-1-k][1] == 0) board[handSize-1-k][0] = EmptySquare;
break;
}
}
if(*p=='-') {
p++; board[EP_STATUS] = EP_NONE;
} else {
- char c = *p++ - AAA;
-
- if(c < BOARD_LEFT || c >= BOARD_RGHT) return TRUE;
- if(*p >= '0' && *p <='9') p++;
- board[EP_STATUS] = c;
+ int d, r, c = *p - AAA;
+
+ if(c >= BOARD_LEFT && c < BOARD_RGHT) {
+ p++;
+ board[EP_STATUS] = board[EP_FILE] = c; r = 0;
+ if(*p >= '0' && *p <='9') r = board[EP_RANK] = *p++ - ONE;
+ d = (r < BOARD_HEIGHT << 1 ? 1 : -1); // assume double-push (P next to e.p. square nearer center)
+ if(board[r+d][c] == EmptySquare) d *= 2; // but if no Pawn there, triple push
+ board[LAST_TO] = 256*(r + d) + c;
+ c = *p++ - AAA;
+ if(c >= BOARD_LEFT && c < BOARD_RGHT) { // mover explicitly mentioned
+ if(*p >= '0' && *p <='9') r = board[EP_RANK] = *p++ - ONE;
+ board[LAST_TO] = 256*r + c;
+ if(!(board[EP_RANK]-r & 1)) board[EP_RANK] |= 128;
+ }
+ }
}
}
+ while(*p == ' ') p++;
+
+ board[CHECK_COUNT] = 0; // [HGM] 3check: check-count field
+ if(sscanf(p, "%d+%d", &i, &j) == 2) {
+ board[CHECK_COUNT] = i + 256*j;
+ while(*p && *p != ' ') p++;
+ }
- if(sscanf(p, "%d", &i) == 1) {
+ c = sscanf(p, "%d%*d +%d+%d", &i, &j, &k);
+ if(c > 0) {
FENrulePlies = i; /* 50-move ply counter */
/* (The move number is still ignored) */
+ if(c == 3 && !board[CHECK_COUNT]) board[CHECK_COUNT] = (3 - j) + 256*(3 - k); // SCIDB-style check count
}
return TRUE;