ShowThinkingEvent(); // [HGM] thinking: make sure post/nopost state is set according to options\r
\r
GetTimeMark(&programStartTime);\r
+ srand(programStartTime.ms); // [HGM] book: makes sure random is unpredictabe to msec level\r
\r
ClearProgramStats();\r
programStats.ok_to_send = 1;\r
first.useFEN960 = FALSE; second.useFEN960 = FALSE;\r
first.useOOCastle = TRUE; second.useOOCastle = TRUE;\r
/* End of new features added by Tord. */\r
+ first.fenOverride = appData.fenOverride1;\r
+ second.fenOverride = appData.fenOverride2;\r
\r
/* [HGM] time odds: set factor for each machine */\r
first.timeOdds = appData.firstTimeOdds;\r
}\r
}\r
\r
-#if 0\r
-/* [AS] FRC game initialization */\r
-static int FindEmptySquare( Board board, int n )\r
-{\r
- int i = 0;\r
-\r
- while( 1 ) {\r
- while( board[0][i] != EmptySquare ) i++;\r
- if( n == 0 )\r
- break;\r
- n--;\r
- i++;\r
- }\r
-\r
- return i;\r
-}\r
-\r
-static void ShuffleFRC( Board board )\r
-{\r
- int i;\r
-\r
- srand( time(0) );\r
- \r
- for( i=0; i<8; i++ ) {\r
- board[0][i] = EmptySquare;\r
- }\r
-\r
- board[0][(rand() % 4)*2 ] = WhiteBishop; /* On dark square */\r
- board[0][(rand() % 4)*2+1] = WhiteBishop; /* On lite square */\r
- board[0][FindEmptySquare(board, rand() % 6)] = WhiteQueen;\r
- board[0][FindEmptySquare(board, rand() % 5)] = WhiteKnight;\r
- board[0][FindEmptySquare(board, rand() % 4)] = WhiteKnight;\r
- board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
- initialRights[1] = initialRights[4] =\r
- castlingRights[0][1] = castlingRights[0][4] = i;\r
- board[0][ i=FindEmptySquare(board, 0) ] = WhiteKing;\r
- initialRights[2] = initialRights[5] =\r
- castlingRights[0][2] = castlingRights[0][5] = i;\r
- board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
- initialRights[0] = initialRights[3] =\r
- castlingRights[0][0] = castlingRights[0][3] = i;\r
-\r
- for( i=BOARD_LEFT; i<BOARD_RGHT; i++ ) {\r
- board[BOARD_HEIGHT-1][i] = board[0][i] + BlackPawn - WhitePawn;\r
- }\r
-}\r
-\r
-static unsigned char FRC_KnightTable[10] = {\r
- 0x00, 0x01, 0x02, 0x03, 0x11, 0x12, 0x13, 0x22, 0x23, 0x33\r
-};\r
-\r
-static void SetupFRC( Board board, int pos_index )\r
-{\r
- int i;\r
- unsigned char knights;\r
-\r
- /* Bring the position index into a safe range (just in case...) */\r
- if( pos_index < 0 ) pos_index = 0;\r
-\r
- pos_index %= 960;\r
-\r
- /* Clear the board */\r
- for( i=0; i<8; i++ ) {\r
- board[0][i] = EmptySquare;\r
- }\r
-\r
- /* Place bishops and queen */\r
- board[0][ (pos_index % 4)*2 + 1 ] = WhiteBishop; /* On lite square */\r
- pos_index /= 4;\r
- \r
- board[0][ (pos_index % 4)*2 ] = WhiteBishop; /* On dark square */\r
- pos_index /= 4;\r
-\r
- board[0][ FindEmptySquare(board, pos_index % 6) ] = WhiteQueen;\r
- pos_index /= 6;\r
-\r
- /* Place knigths */\r
- knights = FRC_KnightTable[ pos_index ];\r
-\r
- board[0][ FindEmptySquare(board, knights / 16) ] = WhiteKnight;\r
- board[0][ FindEmptySquare(board, knights % 16) ] = WhiteKnight;\r
-\r
- /* Place rooks and king */\r
- board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
- initialRights[1] = initialRights[4] =\r
- castlingRights[0][1] = castlingRights[0][4] = i;\r
- board[0][ i=FindEmptySquare(board, 0) ] = WhiteKing;\r
- initialRights[2] = initialRights[5] =\r
- castlingRights[0][2] = castlingRights[0][5] = i;\r
- board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
- initialRights[0] = initialRights[3] =\r
- castlingRights[0][0] = castlingRights[0][3] = i;\r
-\r
- /* Mirror piece placement for black */\r
- for( i=BOARD_LEFT; i<BOARD_RGHT; i++ ) {\r
- board[BOARD_HEIGHT-1][i] = board[0][i] + BlackPawn - WhitePawn;\r
- }\r
-}\r
-#else\r
-// [HGM] shuffle: a more general way to suffle opening setups, applicable to arbitrry variants.\r
+// [HGM] shuffle: a general way to suffle opening setups, applicable to arbitrary variants.\r
// All positions will have equal probability, but the current method will not provide a unique\r
// numbering scheme for arrays that contain 3 or more pieces of the same kind.\r
#define DARK 1\r
\r
int squaresLeft[4];\r
int piecesLeft[(int)BlackPawn];\r
-u64 seed, nrOfShuffles;\r
+int seed, nrOfShuffles;\r
\r
void GetPositionNumber()\r
{ // sets global variable seed\r
\r
seed = appData.defaultFrcPosition;\r
if(seed < 0) { // randomize based on time for negative FRC position numbers\r
- srandom(time(0)); \r
for(i=0; i<50; i++) seed += random();\r
seed = random() ^ random() >> 8 ^ random() << 8;\r
if(seed<0) seed = -seed;\r
if(number >= 0) appData.defaultFrcPosition %= nrOfShuffles; // normalize\r
}\r
\r
-#endif\r
-\r
int 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
char message[MSG_SIZ];\r
\r
if (cps->useSetboard) {\r
- char* fen = PositionToFEN(moveNum, cps->useFEN960);\r
+ char* fen = PositionToFEN(moveNum, cps->fenOverride);\r
sprintf(message, "setboard %s\n", fen);\r
SendToProgram(message, cps);\r
free(fen);\r
machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);\r
GameEnds(machineWhite ? BlackWins : WhiteWins,\r
buf1, GE_XBOARD);\r
+ return;\r
} else if(gameInfo.variant != VariantFischeRandom && gameInfo.variant != VariantCapaRandom)\r
/* [HGM] Kludge to handle engines that send FRC-style castling\r
when they shouldn't (like TSCP-Gothic) */\r
int k, count = 0, epFile = epStatus[forwardMostMove]; static int bare = 1;\r
if(gameInfo.holdingsSize == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {\r
\r
- if(appData.testLegality)\r
- // don't wait for engine to announce game end if we can judge ourselves\r
- switch (MateTest(boards[forwardMostMove],\r
- PosFlags(forwardMostMove), epFile,\r
- castlingRights[forwardMostMove]) ) {\r
- case MT_NONE:\r
- case MT_CHECK:\r
- default:\r
- break;\r
- case MT_STALEMATE:\r
- epStatus[forwardMostMove] = EP_STALEMATE;\r
- if(appData.checkMates) {\r
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
- if(gameInfo.variant == VariantLosers || gameInfo.variant == VariantSuicide\r
- || gameInfo.variant == VariantGiveaway) // [HGM] losers:\r
- GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, // stalemated side wins!\r
- "Xboard adjudication: Stalemate", GE_XBOARD );\r
- else\r
- GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate", GE_XBOARD );\r
- return;\r
- }\r
- break;\r
- case MT_CHECKMATE:\r
- epStatus[forwardMostMove] = EP_CHECKMATE;\r
- if(appData.checkMates) {\r
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
- GameEnds( WhiteOnMove(forwardMostMove) != (gameInfo.variant == VariantLosers) // [HGM] losers:\r
- ? BlackWins : WhiteWins, // reverse the result ( A!=1 is !A for a boolean)\r
- "Xboard adjudication: Checkmate", GE_XBOARD );\r
- return;\r
- }\r
- break;\r
- }\r
-\r
if( appData.testLegality )\r
{ /* [HGM] Some more adjudications for obstinate engines */\r
int NrWN=0, NrBN=0, NrWB=0, NrBB=0, NrWR=0, NrBR=0,\r
NrPieces=0, NrPawns=0, PawnAdvance=0, i, j;\r
static int moveCount = 6;\r
\r
- /* First absolutely insufficient mating material. Count what is on board. */\r
+ /* Count what is on board. */\r
for(i=0; i<BOARD_HEIGHT; i++) for(j=BOARD_LEFT; j<BOARD_RGHT; j++)\r
{ ChessSquare p = boards[forwardMostMove][i][j];\r
int m=i;\r
}\r
}\r
\r
+ /* Some material-based adjudications that have to be made before stalemate test */\r
if(gameInfo.variant == VariantAtomic && NrK < 2) {\r
// [HGM] atomic: stm must have lost his King on previous move, as destroying own K is illegal\r
epStatus[forwardMostMove] = EP_CHECKMATE; // make claimable as if stm is checkmated\r
} else bare = 1;\r
\r
\r
+ // don't wait for engine to announce game end if we can judge ourselves\r
+ switch (MateTest(boards[forwardMostMove],\r
+ PosFlags(forwardMostMove), epFile,\r
+ castlingRights[forwardMostMove]) ) {\r
+ case MT_NONE:\r
+ case MT_CHECK:\r
+ default:\r
+ break;\r
+ case MT_STALEMATE:\r
+ if(epStatus[forwardMostMove] != EP_CHECKMATE) // [HGM] spare win through baring or K-capt\r
+ epStatus[forwardMostMove] = EP_STALEMATE;\r
+ if(appData.checkMates) {\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+ if(gameInfo.variant == VariantLosers || gameInfo.variant == VariantSuicide\r
+ || gameInfo.variant == VariantGiveaway) // [HGM] losers:\r
+ GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, // stalemated side wins!\r
+ "Xboard adjudication: Stalemate", GE_XBOARD );\r
+ else\r
+ GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate", GE_XBOARD );\r
+ return;\r
+ }\r
+ break;\r
+ case MT_CHECKMATE:\r
+ epStatus[forwardMostMove] = EP_CHECKMATE;\r
+ if(appData.checkMates) {\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+ GameEnds( WhiteOnMove(forwardMostMove) != (gameInfo.variant == VariantLosers) // [HGM] losers:\r
+ ? BlackWins : WhiteWins, // reverse the result ( A!=1 is !A for a boolean)\r
+ "Xboard adjudication: Checkmate", GE_XBOARD );\r
+ return;\r
+ }\r
+ break;\r
+ }\r
+\r
+ /* Next absolutely insufficient mating material. */\r
if( NrPieces == 2 || gameInfo.variant != VariantXiangqi && \r
gameInfo.variant != VariantShatranj && // [HGM] baring will remain possible\r
(NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 ||\r
PrintPGNTags(f, &gameInfo);\r
\r
if (backwardMostMove > 0 || startedFromSetupPosition) {\r
- char *fen = PositionToFEN(backwardMostMove, 1);\r
+ char *fen = PositionToFEN(backwardMostMove, NULL);\r
fprintf(f, "[FEN \"%s\"]\n[SetUp \"1\"]\n", fen);\r
fprintf(f, "\n{--------------\n");\r
PrintPosition(f, backwardMostMove);\r
PrintPosition(f, currentMove);\r
fprintf(f, "--------------]\n");\r
} else {\r
- fen = PositionToFEN(currentMove, 1);\r
+ fen = PositionToFEN(currentMove, NULL);\r
fprintf(f, "%s\n", fen);\r
free(fen);\r
}\r
\r
\r
char *\r
-PositionToFEN(move, useFEN960)\r
+PositionToFEN(move, overrideCastling)\r
int move;\r
- int useFEN960;\r
+ char *overrideCastling;\r
{\r
int i, j, fromX, fromY, toX, toY;\r
int whiteToPlay;\r
*p++ = whiteToPlay ? 'w' : 'b';\r
*p++ = ' ';\r
\r
+ if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines\r
+ while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' ';\r
+ } else {\r
if(nrCastlingRights) {\r
q = p;\r
if(gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom) {\r
}\r
*p++ = ' ';\r
}\r
+ }\r
\r
/* [HGM] find reversible plies */\r
{ int i = 0, j=move;\r