else SendToProgram(moveList[moveNum], cps);
} else
if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square
- snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", moveList[moveNum][0], moveList[moveNum][1] - '0', // convert to two moves
- moveList[moveNum][5], moveList[moveNum][6] - '0',
- moveList[moveNum][5], moveList[moveNum][6] - '0',
- moveList[moveNum][2], moveList[moveNum][3] - '0');
+ char *m = moveList[moveNum];
+ if((boards[moveNum][m[6]-ONE][m[5]-AAA] < BlackPawn) == (boards[moveNum][m[1]-ONE][m[0]-AAA] < BlackPawn)) // move is kludge to indicate castling
+ snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", m[0], m[1] - '0', // convert to two moves
+ m[2], m[3] - '0',
+ m[5], m[6] - '0',
+ m[2] + (m[0] > m[5] ? 1 : -1), m[3] - '0');
+ else
+ snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", m[0], m[1] - '0', // convert to two moves
+ m[5], m[6] - '0',
+ m[5], m[6] - '0',
+ m[2], m[3] - '0');
SendToProgram(buf, cps);
} else
if(BOARD_HEIGHT > 10) { // [HGM] big: convert ranks to double-digit where needed
if(step && !(toggleFlag && Partner(&promoSweep))) promoSweep -= step;
if(promoSweep == EmptySquare) promoSweep = BlackPawn; // wrap
else if((int)promoSweep == -1) promoSweep = WhiteKing;
- else if(promoSweep == BlackPawn && step < 0) promoSweep = WhitePawn;
- else if(promoSweep == WhiteKing && step > 0) promoSweep = BlackKing;
+ else if(promoSweep == BlackPawn && step < 0 && !toggleFlag) promoSweep = WhitePawn;
+ else if(promoSweep == WhiteKing && step > 0 && !toggleFlag) promoSweep = BlackKing;
if(!step) step = -1;
} while(PieceToChar(promoSweep) == '.' || PieceToChar(promoSweep) == '~' || promoSweep == pawn ||
!toggleFlag && PieceToChar(promoSweep) == '+' || // skip promoted versions of other
case BlackASideCastleFR:
/* End of code added by Tord */
case IllegalMove: /* bug or odd chess variant */
+ if(currentMoveString[1] == '@') { // illegal drop
+ *fromX = WhiteOnMove(moveNum) ?
+ (int) CharToPiece(ToUpper(currentMoveString[0])) :
+ (int) CharToPiece(ToLower(currentMoveString[0]));
+ goto drop;
+ }
*fromX = currentMoveString[0] - AAA;
*fromY = currentMoveString[1] - ONE;
*toX = currentMoveString[2] - AAA;
*fromX = *moveType == WhiteDrop ?
(int) CharToPiece(ToUpper(currentMoveString[0])) :
(int) CharToPiece(ToLower(currentMoveString[0]));
+ drop:
*fromY = DROP_RANK;
*toX = currentMoveString[2] - AAA;
*toY = currentMoveString[3] - ONE;
promotionZoneSize = BOARD_HEIGHT/3;
highestPromotingPiece = (p >= WhiteLion || PieceToChar(piece + 22) == '.') ? WhitePawn : WhiteLion;
} else if(gameInfo.variant == VariantShogi) {
- promotionZoneSize = BOARD_HEIGHT/3;
+ promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8);
highestPromotingPiece = (int)WhiteAlfil;
} else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) {
promotionZoneSize = 3;
x = BOARD_WIDTH - 1 - x;
}
- if(appData.monoMouse && gameMode == EditPosition && clickType == Press && boards[currentMove][y][x] == EmptySquare) {
+ if(appData.monoMouse && gameMode == EditPosition && fromX < 0 && clickType == Press && boards[currentMove][y][x] == EmptySquare) {
static int dummy;
RightClick(clickType, xPix, yPix, &dummy, &dummy);
right = TRUE;
return;
}
}
-
+printf("to click %d,%d\n",x,y);
/* fromX != -1 */
if (clickType == Press && gameMode != EditPosition) {
ChessSquare fromP;
toP = boards[currentMove][y][x];
frc = appData.fischerCastling || gameInfo.variant == VariantSChess;
if( (killX < 0 || x != fromX || y != fromY) && // [HGM] lion: do not interpret igui as deselect!
- legal[y][x] == 0 && // if engine told we can move to here, do it even if own piece
+ marker[y][x] == 0 && // if engine told we can move to here, do it even if own piece
((WhitePawn <= fromP && fromP <= WhiteKing &&
WhitePawn <= toP && toP <= WhiteKing &&
!(fromP == WhiteKing && toP == WhiteRook && frc) &&
else gatingPiece = doubleClick ? fromP : EmptySquare;
fromX = x;
fromY = y; dragging = 1;
- ReportClick("lift", x, y);
+ if(!second) ReportClick("lift", x, y);
MarkTargetSquares(0);
DragPieceBegin(xPix, yPix, FALSE);
if(appData.sweepSelect && CanPromote(piece = boards[currentMove][y][x], y)) {
// ignore clicks on holdings
if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
}
+printf("A type=%d\n",clickType);
- if (clickType == Release && x == fromX && y == fromY && killX < 0) {
+ if(x == fromX && y == fromY && gameMode == EditPosition && SubtractTimeMarks(&lastClickTime, &prevClickTime) < 200) {
+ gatingPiece = boards[currentMove][fromY][fromX]; // prepare to copy rather than move
+ return;
+ }
+
+ if (clickType == Release && x == fromX && y == fromY && killX < 0 && !sweepSelecting) {
DragPieceEnd(xPix, yPix); dragging = 0;
if(clearFlag) {
// a deferred attempt to click-click move an empty square on top of a piece
/* Undo animation damage if any */
DrawPosition(FALSE, NULL);
}
- if (second || sweepSelecting) {
+ if (second) {
/* Second up/down in same square; just abort move */
- if(sweepSelecting) DrawPosition(FALSE, boards[currentMove]);
- second = sweepSelecting = 0;
+ second = 0;
fromX = fromY = -1;
gatingPiece = EmptySquare;
MarkTargetSquares(1);
}
clearFlag = 0;
-
+printf("B\n");
if(gameMode != EditPosition && !appData.testLegality && !legal[y][x] &&
fromX >= BOARD_LEFT && fromX < BOARD_RGHT && (x != killX || y != killY) && !sweepSelecting) {
if(dragging) DragPieceEnd(xPix, yPix), dragging = 0;
DrawPosition(TRUE, NULL);
return; // ignore to-click
}
-
+printf("(%d,%d)-(%d,%d) %d %d\n",fromX,fromY,toX,toY,x,y);
/* we now have a different from- and (possibly off-board) to-square */
/* Completed move */
if(!sweepSelecting) {
if(gatingPiece != EmptySquare && gameInfo.variant == VariantSChess) promoChoice = ToLower(PieceToChar(gatingPiece));
- if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) {
+ if(legal[toY][toX] == 2) promoChoice = ToLower(PieceToChar(defaultPromoChoice)); // highlight-induced promotion
+
+ if (legal[toY][toX] == 2 && !appData.sweepSelect || HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) {
SetHighlights(fromX, fromY, toX, toY);
MarkTargetSquares(1);
if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) {
safeStrCpy(firstLeg, machineMove, 20); // just remember it for processing when second leg arrives
return;
} else if(firstLeg[0]) { // there was a previous leg;
- // only support case where same piece makes two step (and don't even test that!)
+ // only support case where same piece makes two step
char buf[20], *p = machineMove+1, *q = buf+1, f;
safeStrCpy(buf, machineMove, 20);
while(isdigit(*q)) q++; // find start of to-square
safeStrCpy(machineMove, firstLeg, 20);
- while(isdigit(*p)) p++;
+ while(isdigit(*p)) p++; // to-square of first leg (which is now copied to machineMove)
+ if(*p == *buf) // if first-leg to not equal to second-leg from first leg says unmodified (assume it ia King move of castling)
safeStrCpy(p, q, 20); // glue to-square of second leg to from-square of first, to process over-all move
sscanf(buf, "%c%d", &f, &killY); killX = f - AAA; killY -= ONE - '0'; // pass intermediate square to MakeMove in global
firstLeg[0] = NULLCHAR;
if(gameInfo.variant == VariantKnightmate)
king += (int) WhiteUnicorn - (int) WhiteKing;
- if(piece != WhiteKing && piece != BlackKing && pieceDesc[piece] && killX >= 0 && strchr(pieceDesc[piece], 'O') // Betza castling-enabled
- && (piece < BlackPawn ? killed < BlackPawn : killed >= BlackPawn)) { // and captures own
+ if(pieceDesc[piece] && killX >= 0 && strchr(pieceDesc[piece], 'O') // Betza castling-enabled
+ && (piece < BlackPawn ? killed < BlackPawn : killed >= BlackPawn)) { // and tramples own
board[toY][toX] = piece; board[fromY][fromX] = EmptySquare;
board[toY][toX + (killX < fromX ? 1 : -1)] = killed;
board[EP_STATUS] = EP_NONE; // capture was fake!
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX > fromX+1) {
+ for(rookX=fromX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT-1; rookX++); // castle with nearest piece
+ board[fromY][toX-1] = board[fromY][rookX];
+ board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
board[toY][toX] = king;
- for(rookX=BOARD_RGHT-1; board[toY][rookX] == DarkSquare && rookX > toX + 1; rookX--);
- board[toY][toX-1] = board[fromY][rookX];
- board[fromY][rookX] = EmptySquare;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX < fromX-1) {
+ for(rookX=fromX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--); // castle with nearest piece
+ board[fromY][toX+1] = board[fromY][rookX];
+ board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
board[toY][toX] = king;
- for(rookX=BOARD_LEFT; board[toY][rookX] == DarkSquare && rookX < toX - 1; rookX++);
- board[toY][toX+1] = board[fromY][rookX];
- board[fromY][rookX] = EmptySquare;
} else if ((board[fromY][fromX] == WhitePawn && gameInfo.variant != VariantXiangqi ||
board[fromY][fromX] == WhiteLance && gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu)
&& toY >= BOARD_HEIGHT-promoRank && promoChar // defaulting to Q is done elsewhere
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX > fromX+1) {
+ for(rookX=toX+1; board[toY][rookX] == EmptySquare && rookX < BOARD_RGHT - 1; rookX++);
+ board[fromY][toX-1] = board[fromY][rookX];
+ board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
board[toY][toX] = king;
- for(rookX=BOARD_RGHT-1; board[toY][rookX] == DarkSquare && rookX > toX + 1; rookX--);
- board[toY][toX-1] = board[fromY][rookX];
- board[fromY][rookX] = EmptySquare;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX < fromX-1) {
+ for(rookX=toX-1; board[toY][rookX] == EmptySquare && rookX > 0; rookX--);
+ board[fromY][toX+1] = board[fromY][rookX];
+ board[fromY][rookX] = EmptySquare;
board[fromY][fromX] = EmptySquare;
board[toY][toX] = king;
- for(rookX=BOARD_LEFT; board[toY][rookX] == DarkSquare && rookX < toX - 1; rookX++);
- board[toY][toX+1] = board[fromY][rookX];
- board[fromY][rookX] = EmptySquare;
} else if (fromY == 7 && fromX == 3
&& board[fromY][fromX] == BlackKing
&& toY == 7 && toX == 5) {
if (appData.debugMode)
fprintf(debugFP, "Parsed %s into IllegalMove %s\n",
yy_text, currentMoveString);
- fromX = currentMoveString[0] - AAA;
- fromY = currentMoveString[1] - ONE;
+ if(currentMoveString[1] == '@') {
+ fromX = CharToPiece(WhiteOnMove(currentMove) ? ToUpper(currentMoveString[0]) : ToLower(currentMoveString[0]));
+ fromY = DROP_RANK;
+ } else {
+ fromX = currentMoveString[0] - AAA;
+ fromY = currentMoveString[1] - ONE;
+ }
toX = currentMoveString[2] - AAA;
toY = currentMoveString[3] - ONE;
promoChar = currentMoveString[4];
Boolean
ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize)
{
- int i, j, k, w=0, subst=0, shuffle=0;
+ int i, j, k, w=0, subst=0, shuffle=0, wKingRank = -1, bKingRank = -1;
char *p, c;
int emptycount, virgin[BOARD_FILES];
ChessSquare piece;
p++;
}
board[i][(j++)+gameInfo.holdingsWidth] = piece;
+ if(piece == WhiteKing) wKingRank = i;
+ if(piece == BlackKing) bKingRank = i;
} else {
return FALSE;
}
/* [HGM] We NO LONGER ignore the rest of the FEN notation */
/* return the extra info in global variiables */
+ while(*p==' ') p++;
+
+ if(!isdigit(*p) && *p != '-') { // we seem to have castling rights. Make sure they are on the rank the King actually is.
+ if(wKingRank >= 0) for(i=0; i<3; i++) castlingRank[i] = wKingRank;
+ if(bKingRank >= 0) for(i=3; i<6; i++) castlingRank[i] = bKingRank;
+ }
+
/* set defaults in case FEN is incomplete */
board[EP_STATUS] = EP_UNKNOWN;
for(i=0; i<nrCastlingRights; i++ ) {
&& board[castlingRank[5]][initialRights[5]] != BlackKing) board[CASTLING][5] = NoRights;
FENrulePlies = 0;
- while(*p==' ') p++;
if(nrCastlingRights) {
int fischer = 0;
if(gameInfo.variant == VariantSChess) for(i=0; i<BOARD_FILES; i++) virgin[i] = 0;
int c = *p++, whiteKingFile=NoRights, blackKingFile=NoRights;
for(i=BOARD_LEFT; i<BOARD_RGHT; i++) {
- if(board[BOARD_HEIGHT-1][i] == BlackKing) blackKingFile = i;
- if(board[0 ][i] == WhiteKing) whiteKingFile = i;
+ if(board[castlingRank[5]][i] == BlackKing) blackKingFile = i;
+ if(board[castlingRank[2]][i] == WhiteKing) whiteKingFile = i;
}
if(gameInfo.variant == VariantTwoKings || gameInfo.variant == VariantKnightmate)
whiteKingFile = blackKingFile = BOARD_WIDTH >> 1; // for these variant scanning fails
&& board[BOARD_HEIGHT-1][blackKingFile] != BlackKing) blackKingFile = NoRights;
switch(c) {
case'K':
- for(i=BOARD_RGHT-1; board[0][i]!=WhiteRook && i>whiteKingFile; i--);
+ for(i=BOARD_RGHT-1; board[castlingRank[2]][i]!=WhiteRook && i>whiteKingFile; i--);
board[CASTLING][0] = i != whiteKingFile ? i : NoRights;
board[CASTLING][2] = whiteKingFile;
if(board[CASTLING][0] != NoRights) virgin[board[CASTLING][0]] |= VIRGIN_W;
if(whiteKingFile != BOARD_WIDTH>>1|| i != BOARD_RGHT-1) fischer = 1;
break;
case'Q':
- for(i=BOARD_LEFT; i<BOARD_RGHT && board[0][i]!=WhiteRook && i<whiteKingFile; i++);
+ for(i=BOARD_LEFT; i<BOARD_RGHT && board[castlingRank[2]][i]!=WhiteRook && i<whiteKingFile; i++);
board[CASTLING][1] = i != whiteKingFile ? i : NoRights;
board[CASTLING][2] = whiteKingFile;
if(board[CASTLING][1] != NoRights) virgin[board[CASTLING][1]] |= VIRGIN_W;
if(whiteKingFile != BOARD_WIDTH>>1|| i != BOARD_LEFT) fischer = 1;
break;
case'k':
- for(i=BOARD_RGHT-1; board[BOARD_HEIGHT-1][i]!=BlackRook && i>blackKingFile; i--);
+ for(i=BOARD_RGHT-1; board[castlingRank[5]][i]!=BlackRook && i>blackKingFile; i--);
board[CASTLING][3] = i != blackKingFile ? i : NoRights;
board[CASTLING][5] = blackKingFile;
if(board[CASTLING][3] != NoRights) virgin[board[CASTLING][3]] |= VIRGIN_B;
if(blackKingFile != BOARD_WIDTH>>1|| i != BOARD_RGHT-1) fischer = 1;
break;
case'q':
- for(i=BOARD_LEFT; i<BOARD_RGHT && board[BOARD_HEIGHT-1][i]!=BlackRook && i<blackKingFile; i++);
+ for(i=BOARD_LEFT; i<BOARD_RGHT && board[castlingRank[5]][i]!=BlackRook && i<blackKingFile; i++);
board[CASTLING][4] = i != blackKingFile ? i : NoRights;
board[CASTLING][5] = blackKingFile;
if(board[CASTLING][4] != NoRights) virgin[board[CASTLING][4]] |= VIRGIN_B;