char p;\r
ChessSquare piece;\r
\r
- if(gameInfo.holdingsWidth < 1) return;\r
+ if(gameInfo.holdingsWidth < 2) return;\r
\r
if( (int)lowestPiece >= BlackPawn ) {\r
holdingsColumn = 0;\r
countsColumn = 1;\r
holdingsStartRow = BOARD_HEIGHT-1;\r
- direction = 1;\r
+ direction = -1;\r
} else {\r
holdingsColumn = BOARD_WIDTH-1;\r
countsColumn = BOARD_WIDTH-2;\r
while( (p=*holdings++) != NULLCHAR ) {\r
piece = CharToPiece( ToUpper(p) );\r
if(piece == EmptySquare) continue;\r
- j = (int) piece - (int) WhitePawn;\r
+ /*j = (int) piece - (int) WhitePawn;*/\r
+ j = PieceToNumber(piece);\r
if(j >= gameInfo.holdingsSize) continue; /* ignore pieces that do not fit */\r
if(j < 0) continue; /* should not happen */\r
- piece = (ChessSquare) ( (int)piece + (int)lowestPiece );\r
- board[holdingsStartRow+i*direction][holdingsColumn] = piece;\r
- board[holdingsStartRow+i*direction][countsColumn]++;\r
+ piece = (ChessSquare) ( j + (int)lowestPiece );\r
+ board[holdingsStartRow+j*direction][holdingsColumn] = piece;\r
+ board[holdingsStartRow+j*direction][countsColumn]++;\r
}\r
\r
}\r
sprintf(str, "ICS %s %s match", star_match[0], star_match[1]);\r
gameInfo.event = StrSave(str);\r
gameInfo.variant = StringToVariant(gameInfo.event);\r
+ Reset(TRUE,TRUE); /* [HGM] possibly change board or holdings size */\r
continue;\r
}\r
\r
if (sscanf(parse, " game %d", &gamenum) == 1 &&\r
gamenum == ics_gamenum) {\r
if (gameInfo.variant == VariantNormal) {\r
+ /* [HGM] We seem to switch variant during a game!\r
+ * Presumably no holdings were displayed, so we have\r
+ * to move the position two files to the right to\r
+ * create room for them!\r
+ */\r
+ int i, j;\r
+ if(gameInfo.holdingsWidth == 0) /* to be sure */\r
+ for(i=0; i<BOARD_HEIGHT; i++)\r
+ for(j=BOARD_RGHT-1; j>=0; j--)\r
+ boards[currentMove][i][j+2] = boards[currentMove][i][j];\r
+\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "Switch board to Crazy\n");\r
+ setbuf(debugFP, NULL);\r
+ }\r
gameInfo.variant = VariantCrazyhouse; /*temp guess*/\r
+ gameInfo.boardWidth = 8; /* [HGM] guess board size as well */\r
+ gameInfo.boardHeight = 8;\r
+ gameInfo.holdingsSize = 5;\r
+ gameInfo.holdingsWidth = 2;\r
+ InitDrawingSizes(-2, 0);\r
/* Get a move list just to see the header, which\r
will tell us whether this is really bug or zh */\r
if (ics_getting_history == H_FALSE) {\r
new_piece);\r
white_holding[strlen(white_holding)-1] = NULLCHAR;\r
black_holding[strlen(black_holding)-1] = NULLCHAR;\r
+ /* [HGM] copy holdings to board holdings area */\r
+ CopyHoldings(boards[currentMove], white_holding, WhitePawn);\r
+ CopyHoldings(boards[currentMove], black_holding, BlackPawn);\r
#if ZIPPY\r
if (appData.zippyPlay && first.initDone) {\r
ZippyHoldings(white_holding, black_holding,\r
gameInfo.black, black_holding);\r
}\r
\r
- /* [HGM] copy holdings to board holdings area */\r
- CopyHoldings(boards[currentMove], white_holding, WhitePawn);\r
- CopyHoldings(boards[currentMove], black_holding, BlackPawn);\r
DrawPosition(FALSE, NULL);\r
DisplayTitle(str);\r
}\r
movesPerSession = 0;\r
gameInfo.timeControl = TimeControlTagValue();\r
gameInfo.variant = StringToVariant(gameInfo.event);\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "ParseBoard says variant = '%s'\n", gameInfo.event);\r
+ fprintf(debugFP, "recognized as %s\n", VariantName(gameInfo.variant));\r
+ setbuf(debugFP, NULL);\r
+ }\r
+\r
gameInfo.holdingsSize = 5; /* [HGM] prepare holdings */\r
+ gameInfo.boardWidth = gameInfo.boardHeight = 8;\r
switch(gameInfo.variant) {\r
case VariantShogi:\r
case VariantShowgi:\r
- gameInfo.boardWidth = gameInfo.boardHeight = 9;\r
- gameInfo.holdingsSize += 2;\r
+ gameInfo.boardWidth = 9; gameInfo.boardHeight = 9;\r
+ gameInfo.holdingsSize = 7;\r
case VariantBughouse:\r
case VariantCrazyhouse:\r
- gameInfo.boardWidth = gameInfo.boardHeight = 8;\r
gameInfo.holdingsWidth = 2; break;\r
default:\r
- gameInfo.boardWidth = gameInfo.boardHeight = 8;\r
- gameInfo.holdingsWidth = 0;\r
+ gameInfo.holdingsWidth = gameInfo.holdingsSize = 0;\r
}\r
+ InitDrawingSizes(-2, 0);\r
gameInfo.outOfBook = NULL;\r
\r
/* Do we have the ratings? */\r
}\r
\r
/* Parse the board */\r
- for (k = 0; k < 8; k++)\r
+ for (k = 0; k < 8; k++) {\r
for (j = 0; j < 8; j++)\r
- board[k][j] = CharToPiece(board_chars[(7-k)*9 + j]);\r
+ board[k][j+gameInfo.holdingsWidth] = CharToPiece(board_chars[(7-k)*9 + j]);\r
+ if(gameInfo.holdingsWidth > 1) {\r
+ board[k][0] = board[k][BOARD_WIDTH-1] = EmptySquare;\r
+ board[k][1] = board[k][BOARD_WIDTH-2] = (ChessSquare) 0;;\r
+ }\r
+ }\r
CopyBoard(boards[moveNum], board);\r
if (moveNum == 0) {\r
startedFromSetupPosition =\r
/* Put the move on the move list, first converting\r
to canonical algebraic form. */\r
if (moveNum > 0) {\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "accepted move %s from ICS, parse it.\n", move_str);\r
+ fprintf(debugFP, "board = %d-d x%d\n", BOARD_LEFT, BOARD_RGHT, BOARD_HEIGHT);\r
+ setbuf(debugFP, NULL);\r
+ }\r
if (moveNum <= backwardMostMove) {\r
/* We don't know what the board looked like before\r
this move. Punt. */\r
default:\r
break;\r
case MT_CHECK:\r
- strcat(parseList[moveNum - 1], "+");\r
+ if(gameInfo.variant != VariantShogi)\r
+ strcat(parseList[moveNum - 1], "+");\r
break;\r
case MT_CHECKMATE:\r
strcat(parseList[moveNum - 1], "#");\r
moveList[moveNum - 1][0] = NULLCHAR;\r
fromX = fromY = toX = toY = -1;\r
}\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "Move parsed to '%s'\n", parseList[moveNum - 1]);\r
+ setbuf(debugFP, NULL);\r
+ }\r
\r
#if ZIPPY\r
/* Send move to chess program (BEFORE animating it). */\r
sprintf(buf, "%s\n", parseList[moveNum]);\r
}\r
/* [HGM] decrement all digits to code ranks starting from 0 */\r
- if(BOARD_HEIGHT>8) {\r
+ if(BOARD_HEIGHT>9) {\r
char *p = buf;\r
while(*p) { if(*p < 'A') (*p)--; p++; }\r
}\r
}\r
}\r
\r
+BOOL SetCharTable( char *table, const char * map )\r
+/* [HGM] moved here from winboard.c because of its general usefulness */\r
+/* Basically a safe strcpy that uses the last character as King */\r
+{\r
+ BOOL result = FALSE; int NrPieces;\r
+\r
+ if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare \r
+ && NrPieces >= 12 && !(NrPieces&1)) {\r
+ int i; /* [HGM] Accept even length from 12 to 34 */\r
+\r
+ for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';\r
+ for( i=0; i<NrPieces/2-1; i++ ) {\r
+ table[i] = map[i];\r
+ table[i + (int)BlackPawn - (int) WhitePawn] = map[i+NrPieces/2];\r
+ }\r
+ table[(int) WhiteKing] = map[NrPieces/2-1];\r
+ table[(int) BlackKing] = map[NrPieces-1];\r
+\r
+ result = TRUE;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
void\r
InitPosition(redraw)\r
int redraw;\r
int i, j, pawnRow, overrule,\r
oldx = gameInfo.boardWidth,\r
oldy = gameInfo.boardHeight,\r
- oldh = gameInfo.holdingsWidth;\r
+ oldh = gameInfo.holdingsWidth,\r
+ oldv = gameInfo.variant;\r
\r
currentMove = forwardMostMove = backwardMostMove = 0;\r
\r
for( j=0; j<BOARD_SIZE; j++ ) castlingRights[i][j] = -1;\r
}\r
\r
- /* [HGM] Build normal castling rights */\r
- for( j=0; j<BOARD_SIZE; j++ ) initialRights[j] = -1;\r
- nrCastlingRights = 6;\r
- castlingRights[0][0] = initialRights[0] = BOARD_RGHT-1;\r
- castlingRights[0][1] = initialRights[1] = BOARD_LEFT;\r
- castlingRights[0][2] = initialRights[2] = BOARD_WIDTH>>1;\r
- castlingRights[0][3] = initialRights[3] = BOARD_RGHT-1;\r
- castlingRights[0][4] = initialRights[4] = BOARD_LEFT;\r
- castlingRights[0][5] = initialRights[5] = BOARD_WIDTH>>1;\r
-\r
- castlingRank[0] = castlingRank[1] = castlingRank[2] = 0;\r
- castlingRank[3] = castlingRank[4] = castlingRank[5] = BOARD_HEIGHT-1;\r
-\r
initialRulePlies = 0; /* 50-move counter start */\r
}\r
\r
gameInfo.boardWidth = 8;\r
gameInfo.boardHeight = 8;\r
gameInfo.holdingsSize = 0;\r
+ nrCastlingRights = -1; /* [HGM] Kludge to indicate default should be used */\r
+ for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1; /* but no rights yet */\r
+ SetCharTable(pieceToChar, "PNBRQ...........Kpnbrq...........k"); \r
\r
switch (gameInfo.variant) {\r
default:\r
case VariantShatranj:\r
pieces = ShatranjArray;\r
nrCastlingRights = 0;\r
- for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
break;\r
case VariantTwoKings:\r
pieces = twoKingsArray;\r
case VariantCapablanca:\r
pieces = CapablancaArray;\r
gameInfo.boardWidth = 10;\r
+ SetCharTable(pieceToChar, "PNBRQ.......AC..Kpnbrq.......ac..k"); \r
break;\r
case VariantGothic:\r
pieces = GothicArray;\r
gameInfo.boardWidth = 10;\r
+ SetCharTable(pieceToChar, "PNBRQ.......AC..Kpnbrq.......ac..k"); \r
break;\r
case VariantXiangqi:\r
pieces = XiangqiArray;\r
gameInfo.boardWidth = 9;\r
gameInfo.boardHeight = 10;\r
nrCastlingRights = 0;\r
- for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
- strcpy(pieceToChar, "PN.R.MKE...C....pn.r.mke...c...."); \r
+ SetCharTable(pieceToChar, "PH.R.AKE.C.......ph.r.ake.c......."); \r
break;\r
case VariantShogi:\r
pieces = ShogiArray;\r
gameInfo.boardHeight = 9;\r
gameInfo.holdingsSize = 7;\r
nrCastlingRights = 0;\r
- for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
- strcpy(pieceToChar, "PNBRLSGPNBRLS..Kpnbrlsgpnbrls..k"); \r
+ SetCharTable(pieceToChar, "PNBRLSG.........Kpnbrlsg.........k"); \r
break;\r
case VariantShowgi:\r
pieces = ShogiArray;\r
gameInfo.holdingsSize = 7;\r
nrCastlingRights = 0;\r
for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
- strcpy(pieceToChar, "PNBRQFWEHACGOUMKpnbrlsgpnbrls..k"); \r
+ SetCharTable(pieceToChar, "PNBRQFWEMOUHACG.Kpnbrlsgpnbrls...k"); \r
break;\r
case VariantCourier:\r
pieces = CourierArray;\r
gameInfo.boardWidth = 12;\r
nrCastlingRights = 0;\r
+ SetCharTable(pieceToChar, "PNBR.FWEM.......Kpnbr.fwem.......k"); \r
for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
break;\r
case VariantKnightmate:\r
pieces = KnightmateArray;\r
- strcpy(pieceToChar, "PNBRQFWEHACGOMK.pnbrqfwehacgomK."); \r
+ strcpy(pieceToChar, "P.BRQ...M.K......p.brq...m.k......"); \r
break;\r
case VariantFairy:\r
pieces = fairyArray;\r
- strcpy(pieceToChar, "PNBRQFWEHACGOMUKpnbrqfwehacgomuk"); \r
+ SetCharTable(pieceToChar, "PNBRQFWEMOUHACGSKpnbrqfwemouhacgsk"); \r
startedFromSetupPosition = TRUE;\r
break;\r
case VariantCrazyhouse:\r
case VariantBughouse:\r
pieces = FIDEArray;\r
gameInfo.holdingsSize = 5;\r
- strcpy(pieceToChar, "PNBRQ...NBRQ...Kpnbrq...nbrq...k"); \r
break;\r
case VariantWildCastle:\r
pieces = FIDEArray;\r
gameInfo.boardWidth = appData.NrFiles;\r
}\r
if(appData.NrRanks >= 0) {\r
- if(gameInfo.boardHeight != appData.NrRanks) overrule++;\r
gameInfo.boardHeight = appData.NrRanks;\r
}\r
if(appData.holdingsSize >= 0) {\r
if(BOARD_HEIGHT > BOARD_SIZE || BOARD_WIDTH > BOARD_SIZE)\r
DisplayFatalError("Recompile to support this BOARD_SIZE!", 0, 2);\r
\r
- pawnRow = gameInfo.boardHeight - 7; /* seems to work in all variants */\r
+ pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */\r
+ if(pawnRow < 1) pawnRow = 1;\r
\r
/* User pieceToChar list overrules defaults */\r
if(appData.pieceToCharTable != NULL)\r
- strcpy(pieceToChar, appData.pieceToCharTable);\r
+ SetCharTable(pieceToChar, appData.pieceToCharTable);\r
\r
for( j=0; j<BOARD_WIDTH; j++ ) { ChessSquare s = EmptySquare;\r
\r
initialPosition[BOARD_HEIGHT-2][j] = BlackBishop;\r
}\r
\r
+ if( nrCastlingRights == -1) {\r
+ /* [HGM] Build normal castling rights (must be done after board sizing!) */\r
+ /* This sets default castling rights from none to normal corners */\r
+ /* Variants with other castling rights must set them themselves above */\r
+ nrCastlingRights = 6;\r
+ \r
+ castlingRights[0][0] = initialRights[0] = BOARD_RGHT-1;\r
+ castlingRights[0][1] = initialRights[1] = BOARD_LEFT;\r
+ castlingRights[0][2] = initialRights[2] = BOARD_WIDTH>>1;\r
+ castlingRights[0][3] = initialRights[3] = BOARD_RGHT-1;\r
+ castlingRights[0][4] = initialRights[4] = BOARD_LEFT;\r
+ castlingRights[0][5] = initialRights[5] = BOARD_WIDTH>>1;\r
+\r
+ castlingRank[0] = castlingRank[1] = castlingRank[2] = 0;\r
+ castlingRank[3] = castlingRank[4] = castlingRank[5] = BOARD_HEIGHT-1;\r
+ }\r
+\r
if(gameInfo.variant == VariantFischeRandom) {\r
if( appData.defaultFrcPosition < 0 ) {\r
ShuffleFRC( initialPosition );\r
\r
if(oldx != gameInfo.boardWidth ||\r
oldy != gameInfo.boardHeight ||\r
- oldh != gameInfo.holdingsWidth )\r
- InitDrawingSizes(-1 ,0);\r
+ oldh != gameInfo.holdingsWidth\r
+#ifdef GOTHIC\r
+ || oldv == VariantGothic ||\r
+ gameInfo.variant == VariantGothic\r
+#endif\r
+ )\r
+ InitDrawingSizes(-2 ,0);\r
\r
if (redraw)\r
DrawPosition(TRUE, boards[currentMove]);\r
piece = boards[currentMove][fromY][fromX];\r
if(gameInfo.variant == VariantShogi) {\r
promotionZoneSize = 3;\r
- highestPromotingPiece = (int)WhiteFerz; /* Silver */\r
+ highestPromotingPiece = (int)WhiteKing;\r
+ /* [HGM] Should be Silver = Ferz, really, but legality testing is off,\r
+ and if in normal chess we then allow promotion to King, why not\r
+ allow promotion of other piece in Shogi? */\r
}\r
if((int)piece >= BlackPawn) {\r
if(toY >= promotionZoneSize && fromY >= promotionZoneSize)\r
int promoChar;\r
{\r
ChessMove moveType;\r
+ ChessSquare pdown, pup;\r
\r
if (fromX < 0 || fromY < 0) return ImpossibleMove;\r
if ((fromX == toX) && (fromY == toY)) {\r
return ImpossibleMove;\r
}\r
- /* [HGM] suppress all moves into holdings area and guard band */\r
- if( toX < BOARD_LEFT || toX >= BOARD_RGHT ) return ImpossibleMove;\r
- \r
+\r
/* Check if the user is playing in turn. This is complicated because we\r
let the user "pick up" a piece before it is his turn. So the piece he\r
tried to pick up may have been captured by the time he puts it down!\r
break;\r
\r
case EditPosition:\r
+ /* EditPosition, empty square, or different color piece;\r
+ click-click move is possible */\r
if (toX == -2 || toY == -2) {\r
boards[0][fromY][fromX] = EmptySquare;\r
DrawPosition(FALSE, boards[currentMove]);\r
return ImpossibleMove;\r
}\r
\r
- if (toX < 0 || toY < 0) return ImpossibleMove;\r
+ /* [HGM] suppress all moves into holdings area and guard band */\r
+ if( toX < BOARD_LEFT || toX >= BOARD_RGHT || toY < 0 )\r
+ return ImpossibleMove;\r
+\r
+ /* [HGM] <sameColor> moved to here from winboard.c */\r
+ /* note: EditPosition already filtered out and performed! */\r
+ pdown = boards[currentMove][fromY][fromX];\r
+ pup = boards[currentMove][toY][toX];\r
+ if ( \r
+ (WhitePawn <= pdown && pdown < BlackPawn &&\r
+ WhitePawn <= pup && pup < BlackPawn) ||\r
+ (BlackPawn <= pdown && pdown < EmptySquare &&\r
+ BlackPawn <= pup && pup < EmptySquare) )\r
+ return ImpossibleMove;\r
\r
/* [HGM] If move started in holdings, it means a drop */\r
- if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {\r
- if( boards[currentMove][toY][toX] != EmptySquare ) return ImpossibleMove;\r
+ if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) { \r
+ if( pup != EmptySquare ) return ImpossibleMove;\r
+ if(appData.testLegality) {\r
+ /* it would be more logical if LegalityTest() also figured out\r
+ * which drops are legal. For now we forbid pawns on back rank.\r
+ * Shogi is on its own here...\r
+ */\r
+ if( (pdown == WhitePawn || pdown == BlackPawn) &&\r
+ (toY == 0 || toY == BOARD_HEIGHT -1 ) )\r
+ return(ImpossibleMove); /* no pawn drops on 1st/8th */\r
+ }\r
return WhiteDrop; /* Not needed to specify white or black yet */\r
}\r
\r
userOfferedDraw = FALSE;\r
\r
- if (appData.testLegality) {\r
- moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),\r
- EP_UNKNOWN, castlingRights[currentMove],\r
+ /* [HGM] always test for legality, to get promotion info */\r
+ moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),\r
+ epStatus[currentMove], castlingRights[currentMove],\r
fromY, fromX, toY, toX, promoChar);\r
+\r
+ /* [HGM] but possibly ignore an IllegalMove result */\r
+ if (appData.testLegality) {\r
if (moveType == IllegalMove || moveType == ImpossibleMove) {\r
DisplayMoveError("Illegal move");\r
return ImpossibleMove;\r
}\r
- } else {\r
- moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);\r
}\r
\r
return moveType;\r
/* to make sure an illegal e.p. capture does not slip through, */\r
/* to cause a forfeit on a justified illegal-move complaint */\r
/* of the opponent. */\r
- if(gameMode==TwoMachinesPlay && appData.testLegality &&\r
- fromY != DROP_RANK && /* [HGM] temporary; should still add legality test for drops */\r
- LegalityTest(boards[forwardMostMove], PosFlags(forwardMostMove),\r
+ if( gameMode==TwoMachinesPlay && appData.testLegality\r
+ && fromY != DROP_RANK /* [HGM] temporary; should still add legality test for drops */\r
+ ) {\r
+ ChessMove moveType;\r
+ moveType = LegalityTest(boards[forwardMostMove], PosFlags(forwardMostMove),\r
epStatus[forwardMostMove], castlingRights[forwardMostMove],\r
- fromY, fromX, toY, toX, promoChar) == IllegalMove)\r
- {\r
+ fromY, fromX, toY, toX, promoChar);\r
if (appData.debugMode) {\r
int i;\r
for(i=0; i< nrCastlingRights; i++) fprintf(debugFP, "(%d,%d) ",\r
castlingRights[forwardMostMove][i], castlingRank[i]);\r
fprintf(debugFP, "castling rights\n");\r
}\r
- sprintf(buf1, "Xboard: Forfeit due to illegal move: %s (%c%c%c%c)%c",\r
- machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);\r
- GameEnds(machineWhite ? BlackWins : WhiteWins,\r
- buf1, GE_XBOARD);\r
+ if(moveType == IllegalMove) {\r
+ sprintf(buf1, "Xboard: Forfeit due to illegal move: %s (%c%c%c%c)%c",\r
+ machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);\r
+ GameEnds(machineWhite ? BlackWins : WhiteWins,\r
+ buf1, GE_XBOARD);\r
+ } else if(gameInfo.variant != VariantFischeRandom)\r
+ /* [HGM] Kludge to handle engines that send FRC-style castling\r
+ when they shouldn't (like TSCP-Gothic) */\r
+ switch(moveType) {\r
+ case WhiteASideCastleFR:\r
+ case BlackASideCastleFR:\r
+ toY++;\r
+ currentMoveString[2]++;\r
+ break;\r
+ case WhiteHSideCastleFR:\r
+ case BlackHSideCastleFR:\r
+ toY--;\r
+ currentMoveString[2]--;\r
+ break;\r
}\r
+ }\r
hintRequested = FALSE;\r
lastHint[0] = NULLCHAR;\r
bookRequested = FALSE;\r
cps->useSigterm = FALSE;\r
}\r
\r
+ /* [HGM] Allow engine to set up a position. Don't ask me why one would\r
+ * want this, I was asked to put it in, and obliged.\r
+ */\r
+ if (!strncmp(message, "setboard ", 9)) {\r
+ Board initial_position; int i;\r
+\r
+ GameEnds(GameIsDrawn, "Engine aborts game", GE_XBOARD);\r
+\r
+ if (!ParseFEN(initial_position, &blackPlaysFirst, message + 9)) {\r
+ DisplayError("Bad FEN received from engine", 0);\r
+ return ;\r
+ } else {\r
+ Reset(FALSE, FALSE);\r
+ CopyBoard(boards[0], initial_position);\r
+ initialRulePlies = FENrulePlies;\r
+ epStatus[0] = FENepStatus;\r
+ for( i=0; i<nrCastlingRights; i++ )\r
+ castlingRights[0][i] = FENcastlingRights[i];\r
+ if(blackPlaysFirst) gameMode = MachinePlaysWhite;\r
+ else gameMode = MachinePlaysBlack; \r
+ DrawPosition(FALSE, boards[currentMove]);\r
+ }\r
+ return;\r
+ }\r
+\r
/*\r
* Look for communication commands\r
*/\r
default:\r
break;\r
case MT_CHECK:\r
- strcat(parseList[boardIndex - 1], "+");\r
+ if(gameInfo.variant != VariantShogi)\r
+ strcat(parseList[boardIndex - 1], "+");\r
break;\r
case MT_CHECKMATE:\r
strcat(parseList[boardIndex - 1], "#");\r
int promoChar;\r
Board board;\r
{\r
- ChessSquare captured = board[toY][toX], piece; int p;\r
+ ChessSquare captured = board[toY][toX], piece; int p;\r
\r
- /* [HGM] In Shatranj and Courier all promotions are to Ferz */\r
- if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier)\r
+ /* [HGM] In Shatranj and Courier all promotions are to Ferz */\r
+ if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier)\r
&& promoChar != 0) promoChar = 'F';\r
\r
- if (fromY == DROP_RANK) {\r
+ if (fromX == toX && fromY == toY) return;\r
+\r
+ if (fromY == DROP_RANK) {\r
/* must be first */\r
board[toY][toX] = (ChessSquare) fromX;\r
- } else if (fromX == toX && fromY == toY) {\r
- return;\r
- }\r
+ } else {\r
+ piece = board[fromY][fromX]; /* [HGM] remember, for Shogi promotion */\r
\r
- piece = board[fromY][fromX];\r
- \r
/* Code added by Tord: */\r
/* FRC castling assumed when king captures friendly rook. */\r
- else if (board[fromY][fromX] == WhiteKing &&\r
+ if (board[fromY][fromX] == WhiteKing &&\r
board[toY][toX] == WhiteRook) {\r
board[fromY][fromX] = EmptySquare;\r
board[toY][toX] = EmptySquare;\r
board[toY][2] = WhiteRook;\r
} else if (board[fromY][fromX] == WhitePawn\r
&& toY == BOARD_HEIGHT-1\r
-#ifdef FAIRY\r
&& gameInfo.variant != VariantXiangqi\r
-#endif\r
) {\r
/* white pawn promotion */\r
board[toY][toX] = CharToPiece(ToUpper(promoChar));\r
if (board[toY][toX] == EmptySquare) {\r
board[toY][toX] = WhiteQueen;\r
}\r
- if(gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */\r
- board[toY][toX] += (int) WhiteAlfil - (int) WhitePawn;\r
+ if(gameInfo.variant==VariantBughouse ||\r
+ gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */\r
+ board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]);\r
board[fromY][fromX] = EmptySquare;\r
} else if ((fromY == BOARD_HEIGHT-4)\r
&& (toX != fromX)\r
board[toY][2] = BlackRook;\r
} else if (board[fromY][fromX] == BlackPawn\r
&& toY == 0\r
-#ifdef FAIRY\r
&& gameInfo.variant != VariantXiangqi\r
-#endif\r
) {\r
/* black pawn promotion */\r
board[0][toX] = CharToPiece(ToLower(promoChar));\r
if (board[0][toX] == EmptySquare) {\r
board[0][toX] = BlackQueen;\r
}\r
- if(gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */\r
- board[toY][toX] += (int) WhiteAlfil - (int) WhitePawn;\r
+ if(gameInfo.variant==VariantBughouse ||\r
+ gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */\r
+ board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]);\r
board[fromY][fromX] = EmptySquare;\r
} else if ((fromY == 3)\r
&& (toX != fromX)\r
board[toY][toX] = board[fromY][fromX];\r
board[fromY][fromX] = EmptySquare;\r
}\r
+\r
+ /* [HGM] now we promote for Shogi, if needed */\r
+ if(gameInfo.variant == VariantShogi && promoChar == 'q')\r
+ board[toY][toX] = (ChessSquare) (PROMOTED piece);\r
+ }\r
+\r
if (gameInfo.holdingsWidth != 0) {\r
\r
/* !!A lot more code needs to be written to support holdings */\r
captured = (ChessSquare) (DEMOTED captured);\r
p = DEMOTED p;\r
}\r
+ p = PieceToNumber((ChessSquare)p);\r
if(p >= gameInfo.holdingsSize) { p = 0; captured = BlackPawn; }\r
board[p][BOARD_WIDTH-2]++;\r
board[p][BOARD_WIDTH-1] =\r
captured = (ChessSquare) (DEMOTED captured);\r
p = DEMOTED p;\r
}\r
+ p = PieceToNumber((ChessSquare)p);\r
if(p >= gameInfo.holdingsSize) { p = 0; captured = WhitePawn; }\r
board[BOARD_HEIGHT-1-p][1]++;\r
board[BOARD_HEIGHT-1-p][0] =\r
board[toY][toX] = EmptySquare;\r
}\r
}\r
- if(gameInfo.variant == VariantShogi && promoChar != NULLCHAR) {\r
+ if(gameInfo.variant == VariantShogi && promoChar != NULLCHAR && promoChar != '=') {\r
/* [HGM] Shogi promotions */\r
board[toY][toX] = (ChessSquare) (PROMOTED piece);\r
}\r
default:\r
break;\r
case MT_CHECK:\r
- strcat(parseList[forwardMostMove - 1], "+");\r
+ if(gameInfo.variant != VariantShogi)\r
+ strcat(parseList[forwardMostMove - 1], "+");\r
break;\r
case MT_CHECKMATE:\r
strcat(parseList[forwardMostMove - 1], "#");\r
break;\r
}\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "move: %s, parse: %s (%c)\n", moveList[forwardMostMove-1], parseList[forwardMostMove-1], moveList[forwardMostMove-1][4]);\r
+ }\r
+\r
}\r
\r
/* Updates currentMove if not pausing */\r
|| gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8\r
) {\r
char *v = VariantName(gameInfo.variant);\r
- if (StrStr(cps->variants, v) == NULL) {\r
+ if (cps->protocolVersion != 1 && StrStr(cps->variants, v) == NULL) {\r
+ /* [HGM] in protocol 1 we have to assume all variants valid */\r
sprintf(buf, "Variant %s not supported by %s", v, cps->tidy);\r
DisplayFatalError(buf, 0, 1);\r
return;\r
overruled = gameInfo.boardWidth != 12 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
\r
if(overruled) {\r
-#if 0\r
- // doesn't work in protocol 1\r
- if (StrStr(cps->variants, "boardsize") == NULL,) {\r
+ if (cps->protocolVersion != 1 && StrStr(cps->variants, "boardsize") == NULL) {\r
sprintf(buf, "Board size %dx%d+%d not supported by %s",\r
gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->tidy);\r
DisplayFatalError(buf, 0, 1);\r
return;\r
}\r
-#endif\r
+ /* [HGM] here we really should compare with the maximum supported board size */\r
sprintf(buf, "%dx%d+%d_", gameInfo.boardWidth,\r
gameInfo.boardHeight, gameInfo.holdingsSize );\r
while(*b++ != '_');\r
\r
case WhiteCapturesEnPassant:\r
case BlackCapturesEnPassant:\r
-#ifdef FAIRY\r
case WhitePromotionChancellor:\r
case BlackPromotionChancellor:\r
case WhitePromotionArchbishop:\r
case BlackPromotionArchbishop:\r
-#endif\r
case WhitePromotionQueen:\r
case BlackPromotionQueen:\r
case WhitePromotionRook:\r
int x, y;\r
{\r
char buf[MSG_SIZ];\r
+ ChessSquare piece = boards[0][y][x];\r
\r
if (gameMode != EditPosition && gameMode != IcsExamining) return;\r
\r
}\r
break;\r
\r
+ case PromotePiece:\r
+ if(piece >= (int)WhitePawn && piece < (int)WhiteWazir ||\r
+ piece >= (int)BlackPawn && piece < (int)BlackWazir ) {\r
+ selection = (ChessSquare) (PROMOTED piece);\r
+ } else if(piece == EmptySquare) selection = WhiteWazir;\r
+ else selection = (ChessSquare)((int)piece - 1);\r
+ goto defaultlabel;\r
+\r
+ case DemotePiece:\r
+ if(piece >= (int)WhiteUnicorn && piece < (int)WhiteKing ||\r
+ piece >= (int)BlackUnicorn && piece < (int)BlackKing ) {\r
+ selection = (ChessSquare) (DEMOTED piece);\r
+ } else if( piece == WhiteKing || piece == BlackKing )\r
+ selection = (ChessSquare)((int)piece - (int)WhiteKing + (int)WhiteMan);\r
+ else if(piece == EmptySquare) selection = BlackWazir;\r
+ else selection = (ChessSquare)((int)piece + 1); \r
+ goto defaultlabel;\r
+\r
+ case WhiteQueen:\r
+ case BlackQueen:\r
+ if(gameInfo.variant == VariantShatranj ||\r
+ gameInfo.variant == VariantXiangqi ||\r
+ gameInfo.variant == VariantCourier )\r
+ selection = (ChessSquare)((int)selection - (int)WhiteQueen + (int)WhiteFerz);\r
+ goto defaultlabel;\r
+\r
+ case WhiteKing:\r
+ case BlackKing:\r
+ if(gameInfo.variant == VariantXiangqi)\r
+ selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteWazir);\r
+ if(gameInfo.variant == VariantKnightmate)\r
+ selection = (ChessSquare)((int)selection - (int)WhiteKing + (int)WhiteUnicorn);\r
default:\r
+ defaultlabel:\r
if (gameMode == IcsExamining) {\r
sprintf(buf, "%s%c@%c%c\n", ics_prefix,\r
PieceToChar(selection), AAA + x, ONE + y);\r
return nextTickLength;\r
}\r
\r
+/* Adjust clock one minute up or down */\r
+void\r
+AdjustClock(Boolean which, int dir)\r
+{\r
+ if(which) blackTimeRemaining += 60000*dir;\r
+ else whiteTimeRemaining += 60000*dir;\r
+ DisplayBothClocks();\r
+}\r
+\r
/* Stop clocks and reset to a fresh time control */\r
void\r
ResetClocks() \r
for (j = BOARD_LEFT; j < BOARD_RGHT; j++) {\r
if (boards[move][i][j] == EmptySquare) {\r
emptycount++;\r
- } else {\r
+ } else { ChessSquare piece = boards[move][i][j];\r
if (emptycount > 0) {\r
if(emptycount<10) /* [HGM] can be >= 10 */\r
*p++ = '0' + emptycount;\r
else { *p++ = '0' + emptycount/10; *p++ = '0' + emptycount%10; }\r
emptycount = 0;\r
}\r
- *p++ = PieceToChar(boards[move][i][j]);\r
- if(gameInfo.variant == VariantCrazyhouse) {\r
+ if(gameInfo.variant == VariantShogi) {\r
+ /* [HGM] write Shogi promoted pieces as +<unpromoted> */\r
+ if( (int)piece > (int) WhiteCannon && (int)piece < (int) WhiteKing ||\r
+ (int)piece > (int) BlackCannon && (int)piece < (int) BlackKing ) {\r
+ *p++ = '+';\r
+ piece = (ChessSquare)(DEMOTED piece);\r
+ }\r
+ } \r
+ *p++ = PieceToChar(piece);\r
+ if(gameInfo.variant == VariantCrazyhouse || gameInfo.variant == VariantBughouse) {\r
/* [HGM] flag Crazyhouse promoted pieces */\r
- if( (int)boards[move][i][j] > (int) WhiteQueen && (int)boards[move][i][j] < (int) WhiteKing ||\r
- (int)boards[move][i][j] > (int) BlackQueen && (int)boards[move][i][j] < (int) BlackKing ) {\r
- p[-1] = PieceToChar((ChessSquare)((int)boards[move][i][j]-(int)WhiteAlfil+(int)WhitePawn));\r
+ if( (int)piece > (int) WhiteQueen && (int)piece < (int) WhiteKing ||\r
+ (int)piece > (int) BlackQueen && (int)piece < (int) BlackKing ) {\r
+ p[-1] = PieceToChar((ChessSquare)(DEMOTED piece));\r
*p++ = '~';\r
}\r
}\r
if (j + emptycount > gameInfo.boardWidth) return FALSE;\r
while (emptycount--)\r
board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;\r
- } else if (isalpha(*p)) {\r
+ } else if (*p == '+' || isalpha(*p)) {\r
if (j >= gameInfo.boardWidth) return FALSE;\r
- piece = CharToPiece(*p++);\r
+ if(*p=='+') { piece = (ChessSquare) (PROMOTED CharToPiece(*++p) ); p++; }\r
+ else piece = CharToPiece(*p++);\r
if(*p == '~') { /* [HGM] make it a promoted piece for Crazyhouse */\r
- piece = (ChessSquare) ((int)piece + (int)WhiteAlfil - (int)WhitePawn);\r
+ piece = (ChessSquare) (PROMOTED piece);\r
p++;\r
}\r
board[i][(j++)+gameInfo.holdingsWidth] = piece;\r