* Massachusetts.
*
* Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
*
* Enhancements Copyright 2005 Alessandro Scotti
*
int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */
static int initPing = -1;
int border; /* [HGM] width of board rim, needed to size seek graph */
+char bestMove[MSG_SIZ];
+int solvingTime, totalTime;
/* States for ics_getting_history */
#define H_FALSE 0
case WhitePromotion:
case BlackPromotion:
if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
- gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
+ gameInfo.variant == VariantMakruk)
snprintf(user_move, MSG_SIZ, "%c%c%c%c=%c\n",
AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
PieceToChar(WhiteFerz));
SendToICS(ics_type == ICS_ICC ? "tag result Game in progress\n" : "commit\n");
}
-int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
+int killX = -1, killY = -1, kill2X = -1, kill2Y = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
int legNr = 1;
void
-CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7])
+CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[9])
{
if (rf == DROP_RANK) {
if(ff == EmptySquare) sprintf(move, "@@@@\n"); else // [HGM] pass
if (promoChar == 'x' || promoChar == NULLCHAR) {
sprintf(move, "%c%c%c%c\n",
AAA + ff, ONE + rf, AAA + ft, ONE + rt);
- if(killX >= 0 && killY >= 0) sprintf(move+4, ";%c%c\n", AAA + killX, ONE + killY);
+ if(killX >= 0 && killY >= 0) {
+ sprintf(move+4, ";%c%c\n", AAA + killX, ONE + killY);
+ if(kill2X >= 0 && kill2Y >= 0) sprintf(move+7, "%c%c\n", AAA + killX, ONE + killY);
+ }
} else {
sprintf(move, "%c%c%c%c%c\n",
AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar);
{
int n = 0;
if(!*escapes) return strlen(s);
- while(*s) n += (*s != ':' && !strchr(escapes, *s)), s++;
+ while(*s) n += (*s != '/' && !strchr(escapes, *s)), s++;
return n;
}
/* [HGM] moved here from winboard.c because of its general usefulness */
/* Basically a safe strcpy that uses the last character as King */
{
- int result = FALSE; int NrPieces;
+ int result = FALSE; int NrPieces, offs;
if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare
&& NrPieces >= 12 && !(NrPieces&1)) {
int i, j = 0; /* [HGM] Accept even length from 12 to 88 */
for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';
- for( i=0; i<NrPieces/2-1; i++ ) {
+ for( i=offs=0; i<NrPieces/2-1; i++ ) {
char *p;
- if(map[j] == ':' && *escapes) i = CHUPROMOTED WhitePawn, j++;
- table[i] = map[j++];
- if(p = strchr(escapes, map[j])) j++, table[i] += 64*(p - escapes + 1);
+ if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
+ table[i + offs] = map[j++];
+ if(p = strchr(escapes, map[j])) j++, table[i + offs] += 64*(p - escapes + 1);
}
table[(int) WhiteKing] = map[j++];
- for( i=0; i<NrPieces/2-1; i++ ) {
+ for( i=offs=0; i<NrPieces/2-1; i++ ) {
char *p;
- if(map[j] == ':' && *escapes) i = CHUPROMOTED WhitePawn, j++;
- table[WHITE_TO_BLACK i] = map[j++];
- if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i] += 64*(p - escapes + 1);
+ if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
+ table[WHITE_TO_BLACK i + offs] = map[j++];
+ if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i + offs] += 64*(p - escapes + 1);
}
table[(int) BlackKing] = map[j++];
gameInfo.boardWidth = 12;
gameInfo.boardHeight = 12;
nrCastlingRights = 0;
- SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN:+.++.++++++++++.+++++K"
- "p.brqsexogcathd.vmlifn:+.++.++++++++++.+++++k", SUFFIXES);
+ SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN/+.++.++++++++++.+++++K"
+ "p.brqsexogcathd.vmlifn/+.++.++++++++++.+++++k", SUFFIXES);
break;
case VariantCourier:
pieces = CourierArray;
if ((int) *bp < (int) BlackPawn) {
if(j == BOARD_RGHT+1)
snprintf(message, MSG_SIZ, "%c@%d\n", PieceToChar(*bp), bp[-1]);
- else snprintf(message, MSG_SIZ, "%c%c%c\n", PieceToChar(*bp), AAA + j, ONE + i);
+ else snprintf(message, MSG_SIZ, "%c%c%d\n", PieceToChar(*bp), AAA + j, ONE + i - '0');
if(message[0] == '+' || message[0] == '~') {
- snprintf(message, MSG_SIZ,"%c%c%c+\n",
+ snprintf(message, MSG_SIZ,"%c%c%d+\n",
PieceToChar((ChessSquare)(DEMOTED *bp)),
- AAA + j, ONE + i);
+ AAA + j, ONE + i - '0');
}
if(cps->alphaRank) { /* [HGM] shogi: translate coords */
message[1] = BOARD_RGHT - 1 - j + '1';
&& ((int) *bp >= (int) BlackPawn)) {
if(j == BOARD_LEFT-2)
snprintf(message, MSG_SIZ, "%c@%d\n", ToUpper(PieceToChar(*bp)), bp[1]);
- else snprintf(message,MSG_SIZ, "%c%c%c\n", ToUpper(PieceToChar(*bp)),
- AAA + j, ONE + i);
+ else snprintf(message,MSG_SIZ, "%c%c%d\n", ToUpper(PieceToChar(*bp)),
+ AAA + j, ONE + i - '0');
if(message[0] == '+' || message[0] == '~') {
- snprintf(message, MSG_SIZ,"%c%c%c+\n",
+ snprintf(message, MSG_SIZ,"%c%c%d+\n",
PieceToChar((ChessSquare)(DEMOTED *bp)),
- AAA + j, ONE + i);
+ AAA + j, ONE + i - '0');
}
if(cps->alphaRank) { /* [HGM] shogi: translate coords */
message[1] = BOARD_RGHT - 1 - j + '1';
{
ChessSquare result;
if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
- gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
+ gameInfo.variant == VariantMakruk)
result = WhiteFerz; // no choice
+ else if(gameInfo.variant == VariantASEAN)
+ result = WhiteRook; // no choice
else if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway)
result= WhiteKing; // in Suicide Q is the last thing we want
else if(gameInfo.variant == VariantSpartan)
// we either have a choice what to promote to, or (in Shogi) whether to promote
if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
- gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) {
+ gameInfo.variant == VariantMakruk) {
ChessSquare p=BlackFerz; // no choice
while(p < EmptySquare) { //but make sure we use piece that exists
*promoChoice = PieceToChar(p++);
if(IS_SHOGI(gameInfo.variant) || gameInfo.variant == VariantXiangqi ||
gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat ||
gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
- gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) return FALSE;
+ gameInfo.variant == VariantMakruk) return FALSE;
return (piece == BlackPawn && y <= zone ||
piece == WhitePawn && y >= BOARD_HEIGHT-1-zone ||
piece == BlackLance && y <= zone ||
if(marker[y][x] == 5) { // [HGM] lion: this was the release of a to-click or drag on a cyan square
dragging *= 2; // flag button-less dragging if we are dragging
MarkTargetSquares(1);
- if(x == killX && y == killY) killX = killY = -1; else {
+ if(x == killX && y == killY) killX = kill2X, killY = kill2Y, kill2X = kill2Y = -1; // cancel last kill
+ else {
+ kill2X = killX; kill2Y = killY;
killX = x; killY = y; //remeber this square as intermediate
ReportClick("put", x, y); // and inform engine
ReportClick("lift", x, y);
// most tests only when we understand the game, i.e. legality-checking on
if( appData.testLegality )
{ /* [HGM] Some more adjudications for obstinate engines */
- int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+1], i;
+ int nrW, nrB, bishopColor, staleW, staleB, nr[EmptySquare+2], i;
static int moveCount = 6;
ChessMove result;
char *reason = NULL;
if(cps->alphaRank) AlphaRank(machineMove, 4);
// [HGM] lion: (some very limited) support for Alien protocol
- killX = killY = -1;
+ killX = killY = kill2X = kill2Y = -1;
if(machineMove[strlen(machineMove)-1] == ',') { // move ends in coma: non-final leg of composite move
safeStrCpy(firstLeg, machineMove, 20); // just remember it for processing when second leg arrives
return;
snprintf(buf1, MSG_SIZ*10, _("Illegal move \"%s\" from %s machine"),
machineMove, _(cps->which));
DisplayMoveError(buf1);
- snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c via %c%c) res=%d",
- machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, killX+AAA, killY+ONE, moveType);
+ snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c via %c%c, %c%c) res=%d",
+ machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, killX+AAA, killY+ONE, kill2X+AAA, kill2Y+ONE, moveType);
if (gameMode == TwoMachinesPlay) {
GameEnds(machineWhite ? BlackWins : WhiteWins,
buf1, GE_XBOARD);
free(fen);
GameEnds(GameUnfinished, NULL, GE_XBOARD);
}
+ if(appData.epd) {
+ if(solvingTime >= 0) {
+ snprintf(buf1, MSG_SIZ, "%d. %4.2fs\n", matchGame, solvingTime/100.);
+ totalTime += solvingTime; first.matchWins++;
+ } else {
+ snprintf(buf1, MSG_SIZ, "%d. wrong (%s)\n", matchGame, parseList[backwardMostMove]);
+ second.matchWins++;
+ }
+ OutputKibitz(2, buf1);
+ GameEnds(GameUnfinished, NULL, GE_XBOARD);
+ }
/* [AS] Adjudicate game if needed (note: remember that forwardMostMove now points past the last move) */
if( gameMode == TwoMachinesPlay && appData.adjudicateLossThreshold != 0 && forwardMostMove >= adjudicateLossPlies ) {
}
if(sscanf(message, "piece %s %s", buf2, buf1) == 2) {
ChessSquare piece = WhitePawn;
- char *p=buf2, *q, *s = SUFFIXES, ID = *p;
+ char *p=message+6, *q, *s = SUFFIXES, ID = *p;
if(*p == '+') piece = CHUPROMOTED WhitePawn, ID = *++p;
if(q = strchr(s, p[1])) ID += 64*(q - s + 1), p++;
- piece += CharToPiece(ID) - WhitePawn;
+ piece += CharToPiece(ID & 255) - WhitePawn;
if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR
/* always accept definition of */ && piece != WhiteFalcon && piece != BlackFalcon
/* wild-card pieces. */ && piece != WhiteCobra && piece != BlackCobra
if(piece < EmptySquare) {
pieceDefs = TRUE;
ASSIGN(pieceDesc[piece], buf1);
- if(isupper(*p) && p[1] == '&') { ASSIGN(pieceDesc[WHITE_TO_BLACK piece], buf1); }
+ if((ID & 32) == 0 && p[1] == '&') { ASSIGN(pieceDesc[WHITE_TO_BLACK piece], buf1); }
}
return;
}
return;
}
if(!strncmp(message, "highlight ", 10)) {
- if((appData.testLegality || *engineVariant) && appData.markers) return;
+ if(appData.testLegality && !*engineVariant && appData.markers) return;
MarkByFEN(message+10); // [HGM] alien: allow engine to mark board squares
return;
}
buf1[0] = NULLCHAR;
if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",
&plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) {
+ char score_buf[MSG_SIZ];
if(nodes>>32 == u64Const(0xFFFFFFFF)) // [HGM] negative node count read
nodes += u64Const(0x100000000);
if(appData.pvSAN[cps==&second]) pv = PvToSAN(buf1);
+ if(*bestMove) { // rememer time best EPD move was first found
+ int ff1, tf1, fr1, tr1, ff2, tf2, fr2, tr2; char pp1, pp2;
+ ChessMove mt;
+ int ok = ParseOneMove(bestMove, forwardMostMove, &mt, &ff1, &fr1, &tf1, &tr1, &pp1);
+ ok &= ParseOneMove(pv, forwardMostMove, &mt, &ff2, &fr2, &tf2, &tr2, &pp2);
+ solvingTime = (ok && ff1==ff2 && fr1==fr2 && tf1==tf2 && tr1==tr2 && pp1==pp2 ? time : -1);
+ }
+
if(serverMoves && (time > 100 || time == 0 && plylev > 7)) {
char buf[MSG_SIZ];
FILE *f;
[AS] Protect the thinkOutput buffer from overflow... this
is only useful if buf1 hasn't overflowed first!
*/
- snprintf(thinkOutput, sizeof(thinkOutput)/sizeof(thinkOutput[0]), "[%d]%c%+.2f %s%s",
+ if(curscore >= MATE_SCORE)
+ snprintf(score_buf, MSG_SIZ, "#%d", curscore - MATE_SCORE);
+ else if(curscore <= -MATE_SCORE)
+ snprintf(score_buf, MSG_SIZ, "#%d", curscore + MATE_SCORE);
+ else
+ snprintf(score_buf, MSG_SIZ, "%+.2f", ((double) curscore) / 100.0);
+ snprintf(thinkOutput, sizeof(thinkOutput)/sizeof(thinkOutput[0]), "[%d]%c%s %s%s",
plylev,
(gameMode == TwoMachinesPlay ?
ToUpper(cps->twoMachinesColor[0]) : ' '),
- ((double) curscore) / 100.0,
+ score_buf,
prefixHint ? lastHint : "",
prefixHint ? " " : "" );
void
ApplyMove (int fromX, int fromY, int toX, int toY, int promoChar, Board board)
{
- ChessSquare captured = board[toY][toX], piece, pawn, king, killed; int p, rookX, oldEP, epRank, berolina = 0;
+ ChessSquare captured = board[toY][toX], piece, pawn, king, killed, killed2; 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 */
// ChessSquare victim;
int i;
- if( killX >= 0 && killY >= 0 ) // [HGM] lion: Lion trampled over something
+ 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( kill2X >= 0 && kill2Y >= 0)
+ killed2 = board[kill2Y][kill2X], board[kill2Y][kill2X] = EmptySquare;
+ }
if( board[toY][toX] != EmptySquare ) {
board[EP_STATUS] = EP_CAPTURE;
}
/* End of code added by Tord */
+ } else if (pieceDesc[piece] && piece == king && !strchr(pieceDesc[piece], 'O') && strchr(pieceDesc[piece], 'i')) {
+ board[fromY][fromX] = EmptySquare; // never castle if King has virgin moves defined on it other than castling
+ board[toY][toX] = piece;
} else if (board[fromY][fromX] == king
&& fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */
&& toY == fromY && toX > fromX+1) {
&& gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway
&& gameInfo.variant != VariantSuicide // [HGM] losers: except in losers, of course...
&& result != GameIsDrawn)
- { int i, j, k=0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
+ { int i, j, k=0, oppoKings = 0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);
for(j=BOARD_LEFT; j<BOARD_RGHT; j++) for(i=0; i<BOARD_HEIGHT; i++) {
int p = (signed char)boards[forwardMostMove][i][j] - color;
if(p >= 0 && p <= (int)WhiteKing) k++;
+ oppoKings += (p + color == WhiteKing + BlackPawn - color);
}
if (appData.debugMode) {
fprintf(debugFP, "GE(%d, %s, %d) bare king k=%d color=%d\n",
result, resultDetails ? resultDetails : "(null)", whosays, k, color);
}
- if(k <= 1) {
+ if(k <= 1 && oppoKings > 0) { // the latter needed in Atomic, where bare K wins if opponent King already destroyed
result = GameIsDrawn;
snprintf(buf, MSG_SIZ, "%s but bare king", resultDetails);
resultDetails = buf;
case BlackASideCastleFR:
/* POP Fabien */
if (appData.debugMode)
- fprintf(debugFP, "Parsed %s into %s\n", yy_text, currentMoveString);
+ fprintf(debugFP, "Parsed %s into %s virgin=%x,%x\n", yy_text, currentMoveString, boards[forwardMostMove][TOUCHED_W], boards[forwardMostMove][TOUCHED_B]);
fromX = currentMoveString[0] - AAA;
fromY = currentMoveString[1] - ONE;
toX = currentMoveString[2] - AAA;
}
if (fenMode) {
+ char *p;
if (!ParseFEN(initial_position, &blackPlaysFirst, line, TRUE)) {
DisplayError(_("Bad FEN position in file"), 0);
return FALSE;
}
+ if((p = strstr(line, ";")) && (p = strstr(p+1, "bm "))) { // EPD with best move
+ sscanf(p+3, "%s", bestMove);
+ } else *bestMove = NULLCHAR;
} else {
(void) fgets(line, MSG_SIZ, f);
(void) fgets(line, MSG_SIZ, f);
PositionToFEN (int move, char *overrideCastling, int moveCounts)
{
int i, j, fromX, fromY, toX, toY;
- int whiteToPlay;
+ int whiteToPlay, haveRights = nrCastlingRights;
char buf[MSG_SIZ];
char *p, *q;
int emptycount;
*p++ = whiteToPlay ? 'w' : 'b';
*p++ = ' ';
+ if(pieceDesc[WhiteKing] && strchr(pieceDesc[WhiteKing], 'i') && !strchr(pieceDesc[WhiteKing], 'O')) { // redefined without castling
+ haveRights = 0; q = p;
+ for(i=BOARD_RGHT-1; i>=BOARD_LEFT; i--) {
+ piece = boards[move][0][i];
+ if(piece >= WhitePawn && piece <= WhiteKing && pieceDesc[piece] && strchr(pieceDesc[piece], 'i')) { // piece with initial move
+ if(!(boards[move][TOUCHED_W] & 1<<i)) *p++ = 'A' + i; // print file ID if it has not moved
+ }
+ }
+ for(i=BOARD_RGHT-1; i>=BOARD_LEFT; i--) {
+ piece = boards[move][BOARD_HEIGHT-1][i];
+ if(piece >= BlackPawn && piece <= BlackKing && pieceDesc[piece] && strchr(pieceDesc[piece], 'i')) { // piece with initial move
+ if(!(boards[move][TOUCHED_B] & 1<<i)) *p++ = 'a' + i; // print file ID if it has not moved
+ }
+ }
+ if(p == q) *p++ = '-';
+ *p++ = ' ';
+ }
+
if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines
while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; else --p;
} else {
- if(nrCastlingRights) {
+ if(haveRights) {
int handW=0, handB=0;
if(gameInfo.variant == VariantSChess) { // for S-Chess, all virgin backrank pieces must be listed
for(i=0; i<BOARD_HEIGHT; i++) handW += boards[move][i][BOARD_RGHT]; // count white held pieces
/* [HGM] write true castling rights */
if( nrCastlingRights == 6 ) {
int q, k=0;
- if(boards[move][CASTLING][0] == BOARD_RGHT-1 &&
+ if(boards[move][CASTLING][0] != NoRights &&
boards[move][CASTLING][2] != NoRights ) k = 1, *p++ = 'K';
- q = (boards[move][CASTLING][1] == BOARD_LEFT &&
+ q = (boards[move][CASTLING][1] != NoRights &&
boards[move][CASTLING][2] != NoRights );
if(handW) { // for S-Chess with pieces in hand, list virgin pieces between K and Q
for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--)
}
if(q) *p++ = 'Q';
k = 0;
- if(boards[move][CASTLING][3] == BOARD_RGHT-1 &&
+ if(boards[move][CASTLING][3] != NoRights &&
boards[move][CASTLING][5] != NoRights ) k = 1, *p++ = 'k';
- q = (boards[move][CASTLING][4] == BOARD_LEFT &&
+ q = (boards[move][CASTLING][4] != NoRights &&
boards[move][CASTLING][5] != NoRights );
if(handB) {
for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--)
int i, j, k, w=0, subst=0, shuffle=0, wKingRank = -1, bKingRank = -1;
char *p, c;
int emptycount, virgin[BOARD_FILES];
- ChessSquare piece;
+ ChessSquare piece, king = (gameInfo.variant == VariantKnightmate ? WhiteUnicorn : WhiteKing);
p = fen;
p++;
}
board[i][(j++)+gameInfo.holdingsWidth] = piece;
- if(piece == WhiteKing) wKingRank = i;
- if(piece == BlackKing) bKingRank = i;
+ if(piece == king) wKingRank = i;
+ if(piece == WHITE_TO_BLACK king) bKingRank = i;
} else {
return FALSE;
}
/* set defaults in case FEN is incomplete */
board[EP_STATUS] = EP_UNKNOWN;
+ board[TOUCHED_W] = board[TOUCHED_B] = 0;
for(i=0; i<nrCastlingRights; i++ ) {
board[CASTLING][i] =
appData.fischerCastling ? NoRights : initialRights[i];
&& board[castlingRank[5]][initialRights[5]] != BlackKing) board[CASTLING][5] = NoRights;
FENrulePlies = 0;
+ if(pieceDesc[WhiteKing] && strchr(pieceDesc[WhiteKing], 'i') && !strchr(pieceDesc[WhiteKing], 'O')) { // redefined without castling
+ char *q = p;
+ int w=0, b=0;
+ while(isalpha(*p)) {
+ if(isupper(*p)) w |= 1 << (*p++ - 'A');
+ if(islower(*p)) b |= 1 << (*p++ - 'a');
+ }
+ if(*p == '-') p++;
+ if(p != q) {
+ board[TOUCHED_W] = ~w;
+ board[TOUCHED_B] = ~b;
+ while(*p == ' ') p++;
+ }
+ } else
+
if(nrCastlingRights) {
int fischer = 0;
if(gameInfo.variant == VariantSChess) for(i=0; i<BOARD_FILES; i++) virgin[i] = 0;
}
if(gameInfo.variant == VariantTwoKings || gameInfo.variant == VariantKnightmate)
whiteKingFile = blackKingFile = BOARD_WIDTH >> 1; // for these variant scanning fails
- if(whiteKingFile == NoRights || board[0][whiteKingFile] != WhiteUnicorn
- && board[0][whiteKingFile] != WhiteKing) whiteKingFile = NoRights;
- if(blackKingFile == NoRights || board[BOARD_HEIGHT-1][blackKingFile] != BlackUnicorn
- && board[BOARD_HEIGHT-1][blackKingFile] != BlackKing) blackKingFile = NoRights;
+ if(whiteKingFile == NoRights || board[castlingRank[2]][whiteKingFile] != WhiteUnicorn
+ && board[castlingRank[2]][whiteKingFile] != WhiteKing) whiteKingFile = NoRights;
+ if(blackKingFile == NoRights || board[castlingRank[5]][blackKingFile] != BlackUnicorn
+ && board[castlingRank[5]][blackKingFile] != BlackKing) blackKingFile = NoRights;
switch(c) {
case'K':
for(i=BOARD_RGHT-1; board[castlingRank[2]][i]!=WhiteRook && i>whiteKingFile; i--);