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
case BlackASideCastleFR:
/* End of code added by Tord */
case IllegalMove: /* bug or odd chess variant */
+ if(currentMoveString[1] == '@') goto drop; // illegal drop
*fromX = currentMoveString[0] - AAA;
*fromY = currentMoveString[1] - ONE;
*toX = currentMoveString[2] - AAA;
case WhiteDrop:
case BlackDrop:
+ drop:
*fromX = *moveType == WhiteDrop ?
(int) CharToPiece(ToUpper(currentMoveString[0])) :
(int) CharToPiece(ToLower(currentMoveString[0]));
int p = piece >= BlackPawn ? BLACK_TO_WHITE piece : piece;
promotionZoneSize = BOARD_HEIGHT/3;
highestPromotingPiece = (p >= WhiteLion || PieceToChar(piece + 22) == '.') ? WhitePawn : WhiteLion;
- } else if(gameInfo.variant == VariantShogi || gameInfo.variant == VariantChuChess) {
+ } else if(gameInfo.variant == VariantShogi) {
promotionZoneSize = BOARD_HEIGHT/3;
highestPromotingPiece = (int)WhiteAlfil;
} else if(gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess) {
/* EditPosition, empty square, or different color piece;
click-click move is possible */
if (toX == -2 || toY == -2) {
- boards[0][fromY][fromX] = EmptySquare;
+ boards[0][fromY][fromX] = (boards[0][fromY][fromX] == EmptySquare ? DarkSquare : EmptySquare);
DrawPosition(FALSE, boards[currentMove]);
return;
} else if (toX >= 0 && toY >= 0) {
gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) return FALSE;
return (piece == BlackPawn && y <= zone ||
piece == WhitePawn && y >= BOARD_HEIGHT-1-zone ||
- piece == BlackLance && y == 1 ||
- piece == WhiteLance && y == BOARD_HEIGHT-2 );
+ piece == BlackLance && y <= zone ||
+ piece == WhiteLance && y >= BOARD_HEIGHT-1-zone );
}
void
SendToProgram(buf, &first);
}
+Boolean right; // instructs front-end to use button-1 events as if they were button 3
+
void
LeftClick (ClickType clickType, int xPix, int yPix)
{
ChessSquare piece;
static TimeMark lastClickTime, prevClickTime;
- if(SeekGraphClick(clickType, xPix, yPix, 0)) return;
-
- prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
-
- if (clickType == Press) ErrorPopDown();
- lastClickType = clickType, lastLeftX = xPix, lastLeftY = yPix; // [HGM] alien: remember state
-
x = EventToSquare(xPix, BOARD_WIDTH);
y = EventToSquare(yPix, BOARD_HEIGHT);
if (!flipView && y >= 0) {
x = BOARD_WIDTH - 1 - x;
}
+ 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;
+ }
+
+ if(SeekGraphClick(clickType, xPix, yPix, 0)) return;
+
+ prevClickTime = lastClickTime; GetTimeMark(&lastClickTime);
+
+ if (clickType == Press) ErrorPopDown();
+ lastClickType = clickType, lastLeftX = xPix, lastLeftY = yPix; // [HGM] alien: remember state
+
if(promoSweep != EmptySquare) { // up-click during sweep-select of promo-piece
defaultPromoChoice = promoSweep;
promoSweep = EmptySquare; // terminate sweep
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
((WhitePawn <= fromP && fromP <= WhiteKing &&
WhitePawn <= toP && toP <= WhiteKing &&
!(fromP == WhiteKing && toP == WhiteRook && frc) &&
// ignore clicks on holdings
if(x < BOARD_LEFT || x >= BOARD_RGHT) return;
}
+printf("A type=%d\n",clickType);
+
+ 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) {
DragPieceEnd(xPix, yPix); dragging = 0;
}
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) {
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;
void
ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
{
- ChessSquare captured = board[toY][toX], piece, king; int p, rookX, oldEP = EP_NONE, berolina = 0;
+ ChessSquare captured = board[toY][toX], piece, pawn, king, killed; int p, rookX, oldEP, epRank, berolina = 0;
int promoRank = gameInfo.variant == VariantMakruk || gameInfo.variant == VariantGrand || gameInfo.variant == VariantChuChess ? 3 : 1;
/* [HGM] compute & store e.p. status and castling rights for new position */
/* 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];
+ oldEP = (signed char)board[EP_FILE]; epRank = board[EP_RANK];
board[EP_STATUS] = EP_NONE;
board[EP_FILE] = board[EP_RANK] = 100;
if( killX >= 0 && killY >= 0 ) // [HGM] lion: Lion trampled over something
// victim = board[killY][killX],
+ killed = board[killY][killX],
board[killY][killX] = EmptySquare,
board[EP_STATUS] = EP_CAPTURE;
}
}
- if( board[fromY][fromX] == WhiteLance || board[fromY][fromX] == BlackLance ) {
- if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantShogi )
- board[EP_STATUS] = EP_PAWN_MOVE; // Lance is Pawn-like in most variants
- } else
- if( board[fromY][fromX] == WhitePawn ) {
+ pawn = board[fromY][fromX];
+ if( pawn == WhiteLance || pawn == BlackLance ) {
+ if( gameInfo.variant != VariantSuper && gameInfo.variant != VariantChu ) {
+ if(gameInfo.variant == VariantSpartan) board[EP_STATUS] = EP_PAWN_MOVE; // in Spartan no e.p. rights must be set
+ else pawn += WhitePawn - WhiteLance; // Lance is Pawn-like in most variants, so let Pawn code treat it by this kludge
+ }
+ }
+ if( pawn == WhitePawn ) {
if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
board[EP_STATUS] = EP_PAWN_MOVE;
- if( toY-fromY==2) {
- board[EP_FILE] = (fromX + toX)/2; board[EP_RANK] = (fromY + toY)/2;
+ if( toY-fromY>=2) {
+ board[EP_FILE] = (fromX + toX)/2; board[EP_RANK] = toY - 1 | 128*(toY - fromY > 2);
if(toX>BOARD_LEFT && board[toY][toX-1] == BlackPawn &&
gameInfo.variant != VariantBerolina || toX < fromX)
board[EP_STATUS] = toX | berolina;
board[EP_STATUS] = toX;
}
} else
- if( board[fromY][fromX] == BlackPawn ) {
+ if( pawn == BlackPawn ) {
if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers
board[EP_STATUS] = EP_PAWN_MOVE;
- if( toY-fromY== -2) {
- board[EP_FILE] = (fromX + toX)/2; board[EP_RANK] = (fromY + toY)/2;
+ if( toY-fromY<= -2) {
+ board[EP_FILE] = (fromX + toX)/2; board[EP_RANK] = toY + 1 | 128*(fromY - toY > 2);
if(toX>BOARD_LEFT && board[toY][toX-1] == WhitePawn &&
gameInfo.variant != VariantBerolina || toX < fromX)
board[EP_STATUS] = toX | berolina;
if(gameInfo.variant == VariantKnightmate)
king += (int) WhiteUnicorn - (int) WhiteKing;
+ 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
/* Code added by Tord: */
/* FRC castling assumed when king captures friendly rook. [HGM] or RxK for S-Chess */
if (board[fromY][fromX] == WhiteKing && board[toY][toX] == WhiteRook ||
} 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
&& (toX != fromX)
&& gameInfo.variant != VariantXiangqi
&& gameInfo.variant != VariantBerolina
- && (board[fromY][fromX] == WhitePawn)
+ && (pawn == WhitePawn)
&& (board[toY][toX] == EmptySquare)) {
board[fromY][fromX] = EmptySquare;
- board[toY][toX] = WhitePawn;
- captured = board[toY - 1][toX];
- board[toY - 1][toX] = EmptySquare;
+ board[toY][toX] = piece;
+ if(toY == epRank - 128 + 1)
+ captured = board[toY - 2][toX], board[toY - 2][toX] = EmptySquare;
+ else
+ captured = board[toY - 1][toX], board[toY - 1][toX] = EmptySquare;
} else if ((fromY == BOARD_HEIGHT-4)
&& (toX == fromX)
&& gameInfo.variant == VariantBerolina
} 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) {
&& (toX != fromX)
&& gameInfo.variant != VariantXiangqi
&& gameInfo.variant != VariantBerolina
- && (board[fromY][fromX] == BlackPawn)
+ && (pawn == BlackPawn)
&& (board[toY][toX] == EmptySquare)) {
board[fromY][fromX] = EmptySquare;
- board[toY][toX] = BlackPawn;
- captured = board[toY + 1][toX];
- board[toY + 1][toX] = EmptySquare;
+ board[toY][toX] = piece;
+ if(toY == epRank - 128 - 1)
+ captured = board[toY + 2][toX], board[toY + 2][toX] = EmptySquare;
+ else
+ captured = board[toY + 1][toX], board[toY + 1][toX] = EmptySquare;
} else if ((fromY == 3)
&& (toX == fromX)
&& gameInfo.variant == VariantBerolina
AAA + x, ONE + y);
SendToICS(buf);
}
- } else {
+ } else if(boards[0][y][x] != DarkSquare) {
if(boards[0][y][x] != p) nonEmpty++;
boards[0][y][x] = p;
}