#include <sys/types.h>\r
#include <sys/stat.h>\r
#include <math.h>\r
+#include <ctype.h>\r
\r
#if STDC_HEADERS\r
# include <stdlib.h>\r
void InitBackEnd3 P((void));\r
void FeatureDone P((ChessProgramState* cps, int val));\r
void InitChessProgram P((ChessProgramState *cps, int setup));\r
+void OutputKibitz(int window, char *text);\r
+int PerpetualChase(int first, int last);\r
+int EngineOutputIsUp();\r
+void InitDrawingSizes(int x, int y);\r
\r
#ifdef WIN32\r
extern void ConsoleCreate();\r
extern int tinyLayout, smallLayout;\r
ChessProgramStats programStats;\r
static int exiting = 0; /* [HGM] moved to top */\r
-static int setboardSpoiledMachineBlack = 0, errorExitFlag = 0;\r
-extern int startedFromPositionFile;\r
+static int setboardSpoiledMachineBlack = 0 /*, errorExitFlag = 0*/;\r
int startedFromPositionFile = FALSE; Board filePosition; /* [HGM] loadPos */\r
char endingGame = 0; /* [HGM] crash: flag to prevent recursion of GameEnds() */\r
int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS */\r
return dst;\r
}\r
\r
+#if 0\r
+//[HGM] for future use? Conditioned out for now to suppress warning.\r
static char * safeStrCat( char * dst, const char * src, size_t count )\r
{\r
size_t dst_len;\r
\r
return dst;\r
}\r
+#endif\r
\r
/* Some compiler can't cast u64 to double\r
* This function do the job for us:\r
flags &= ~F_ALL_CASTLE_OK;\r
case VariantGiveaway: // [HGM] moved this case label one down: seems Giveaway does have castling on ICC!\r
flags |= F_IGNORE_CHECK;\r
+ case VariantLosers:\r
+ flags |= F_MANDATORY_CAPTURE; //[HGM] losers: sets flag so TestLegality rejects non-capts if capts exist\r
break;\r
case VariantAtomic:\r
flags |= F_IGNORE_CHECK | F_ATOMIC_CAPTURE;\r
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
int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j;\r
int oldCurrentMove = currentMove, oldForwardMostMove = forwardMostMove, oldBackwardMostMove = backwardMostMove;\r
- Board tempBoard; int saveCastling[BOARD_SIZE], saveEP;\r
+// Board tempBoard; int saveCastling[BOARD_SIZE], saveEP;\r
\r
startedFromPositionFile = FALSE;\r
if(gameInfo.variant == newVariant) return;\r
(StrStr(star_match[0], gameInfo.white) == star_match[0] || \r
StrStr(star_match[0], gameInfo.black) == star_match[0] )) { // kibitz of self or opponent\r
suppressKibitz = TRUE;\r
- if((StrStr(star_match[0], gameInfo.white) == star_match[0])\r
- && (gameMode == IcsPlayingWhite) ||\r
- (StrStr(star_match[0], gameInfo.black) == star_match[0])\r
- && (gameMode == IcsPlayingBlack) ) // opponent kibitz\r
+ if((StrStr(star_match[0], gameInfo.white) == star_match[0]\r
+ && (gameMode == IcsPlayingWhite)) ||\r
+ (StrStr(star_match[0], gameInfo.black) == star_match[0]\r
+ && (gameMode == IcsPlayingBlack)) ) // opponent kibitz\r
started = STARTED_CHATTER; // own kibitz we simply discard\r
else {\r
started = STARTED_COMMENT; // make sure it will be collected in parse[]\r
if(bookHit) { // [HGM] book: simulate book reply\r
static char bookMove[MSG_SIZ]; // a bit generous?\r
\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
if(bookHit) { // [HGM] book: simulate book reply\r
static char bookMove[MSG_SIZ]; // a bit generous?\r
\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
void\r
AlphaRank(char *move, int n)\r
{\r
- char *p = move, c; int x, y;\r
+// char *p = move, c; int x, y;\r
\r
if (appData.debugMode) {\r
fprintf(debugFP, "alphaRank(%s,%d)\n", move, n);\r
}\r
}\r
\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
-#if 0\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
-long long int 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
int i;\r
\r
for(i=BOARD_LEFT; i<BOARD_RGHT; i++) {\r
- if( ((i-BOARD_LEFT)&1)+1 & shade && board[rank][i] == EmptySquare && n-- == 0) {\r
+ if( (((i-BOARD_LEFT)&1)+1) & shade && board[rank][i] == EmptySquare && n-- == 0) {\r
board[rank][i] = (ChessSquare) pieceType;\r
- squaresLeft[(i-BOARD_LEFT&1) + 1]--;\r
+ squaresLeft[((i-BOARD_LEFT)&1) + 1]--;\r
squaresLeft[ANY]--;\r
piecesLeft[pieceType]--; \r
return i;\r
// in variants with super-numerary Kings and Rooks, we leave these for the shuffle\r
}\r
\r
- if((BOARD_RGHT-BOARD_LEFT & 1) == 0)\r
+ if(((BOARD_RGHT-BOARD_LEFT) & 1) == 0)\r
// only for even boards make effort to put pairs of colorbound pieces on opposite colors\r
for(p = (int) WhiteKing; p > (int) WhitePawn; p--) {\r
if(p != (int) WhiteBishop && p != (int) WhiteFerz && p != (int) WhiteAlfil) continue;\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
break;\r
case VariantTwoKings:\r
pieces = twoKingsArray;\r
- nrCastlingRights = 8; /* add rights for second King */\r
- castlingRights[0][6] = initialRights[2] = 5;\r
- castlingRights[0][7] = initialRights[5] = 5;\r
- castlingRank[6] = 0;\r
- castlingRank[7] = BOARD_HEIGHT-1;\r
break;\r
case VariantCapaRandom:\r
shuffleOpenings = TRUE;\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>>1;\r
+ castlingRights[0][2] = initialRights[2] =(BOARD_WIDTH-1)>>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>>1;\r
+ castlingRights[0][5] = initialRights[5] =(BOARD_WIDTH-1)>>1;\r
break;\r
case VariantFalcon:\r
pieces = FalconArray;\r
\r
if(gameInfo.variant == VariantSuper) Prelude(initialPosition);\r
if(gameInfo.variant == VariantGreat) { // promotion commoners\r
- initialPosition[PieceToNumber(WhiteMan)][BOARD_RGHT-1] = WhiteMan;\r
- initialPosition[PieceToNumber(WhiteMan)][BOARD_RGHT-2] = 9;\r
+ initialPosition[PieceToNumber(WhiteMan)][BOARD_WIDTH-1] = WhiteMan;\r
+ initialPosition[PieceToNumber(WhiteMan)][BOARD_WIDTH-2] = 9;\r
initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan;\r
initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9;\r
}\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
if(bookHit) { // [HGM] book: simulate book reply\r
static char bookMove[MSG_SIZ]; // a bit generous?\r
\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
\r
void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cpstats )\r
{\r
- char * hint = lastHint;\r
+// char * hint = lastHint;\r
FrontEndProgramStats stats;\r
\r
stats.which = cps == &first ? 0 : 1;\r
sprintf(buf1, _("Illegal move \"%s\" from %s machine"),\r
machineMove, cps->which);\r
DisplayError(buf1, 0);\r
- sprintf(buf1, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d%c",\r
- machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);\r
+ sprintf(buf1, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d",\r
+ machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, moveType);\r
if (gameMode == TwoMachinesPlay) {\r
GameEnds(machineWhite ? BlackWins : WhiteWins,\r
buf1, GE_XBOARD);\r
toX--;\r
currentMoveString[2]--;\r
break;\r
+ default: ; // nothing to do, but suppresses warning of pedantic compilers\r
}\r
}\r
hintRequested = FALSE;\r
programStats.depth,\r
programStats.score / 100.,\r
programStats.time / 100.,\r
- (double) programStats.nodes,\r
- programStats.nodes / (10*abs(programStats.time) + 1.),\r
+ u64ToDouble(programStats.nodes),\r
+ u64ToDouble(programStats.nodes) / (10*abs(programStats.time) + 1.),\r
programStats.movelist);\r
SendToICS(buf);\r
}\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( GameIsDrawn, "Xboard adjudication: Stalemate",\r
- GE_XBOARD );\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
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) ? BlackWins : WhiteWins, \r
- "Xboard adjudication: Checkmate", \r
- GE_XBOARD );\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
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
- NrWQ=0, NrBQ=0, NrW=0, bishopsColor = 0,\r
- NrPieces=0, NrPawns=0, PawnAdvance=0, i, j, k;\r
+ NrWQ=0, NrBQ=0, NrW=0, NrK=0, bishopsColor = 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
\r
switch((int) p)\r
{ /* count B,N,R and other of each side */\r
+ case WhiteKing:\r
+ case BlackKing:\r
+ NrK++; break; // [HGM] atomic: count Kings\r
case WhiteKnight:\r
NrWN++; break;\r
case WhiteBishop:\r
}\r
}\r
\r
- if( NrPieces == 2 || gameInfo.variant != VariantXiangqi &&\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
+ if(appData.checkMates) {\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets move\r
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+ GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins, \r
+ "Xboard adjudication: King destroyed", GE_XBOARD );\r
+ return;\r
+ }\r
+ }\r
+\r
+ /* Bare King in Shatranj (loses) or Losers (wins) */\r
+ if( NrW == 1 || NrPieces - NrW == 1) {\r
+ if( gameInfo.variant == VariantLosers) { // [HGM] losers: bare King wins (stm must have it first)\r
+ epStatus[forwardMostMove] = EP_STALEMATE; // kludge to make position claimable as win\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) ? WhiteWins : BlackWins, \r
+ "Xboard adjudication: Bare king", GE_XBOARD );\r
+ return;\r
+ }\r
+ } else\r
+ if( gameInfo.variant == VariantShatranj && --bare < 0)\r
+ { /* bare King */\r
+ epStatus[forwardMostMove] = EP_CHECKMATE; // make claimable as win for stm\r
+ if(appData.checkMates) {\r
+ /* but only adjudicate if adjudication enabled */\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); // make sure opponent gets move\r
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+ GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn, \r
+ "Xboard adjudication: Bare king", GE_XBOARD );\r
+ return;\r
+ }\r
+ }\r
+ } else bare = 1;\r
+\r
+\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
NrPieces == NrBB+NrWB+2 && bishopsColor != 3)) // [HGM] all Bishops (Ferz!) same color\r
{ /* KBK, KNK, KK of KBKB with like Bishops */\r
}\r
}\r
\r
- /* Shatranj baring rule */\r
- if( gameInfo.variant == VariantShatranj && (NrW == 1 || NrPieces - NrW == 1) )\r
- { /* bare King */\r
-\r
- if(--bare < 0 && appData.checkMates) {\r
- /* but only adjudicate them if adjudication enabled */\r
- SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
- GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn, \r
- "Xboard adjudication: Bare king", GE_XBOARD );\r
- return;\r
- }\r
- } else bare = 1;\r
-\r
/* Then some trivial draws (only adjudicate, cannot be claimed) */\r
if(NrPieces == 4 && \r
( NrWR == 1 && NrBR == 1 /* KRKR */\r
EP_NONE, castlingRights[m-1]) != MT_CHECK)\r
hisPerpetual = 0; // the opponent did not always check\r
}\r
+ if(appData.debugMode) fprintf(debugFP, "XQ perpetual test, our=%d, his=%d\n",\r
+ ourPerpetual, hisPerpetual);\r
if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit\r
GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, \r
"Xboard adjudication: perpetual checking", GE_XBOARD );\r
}\r
if(hisPerpetual && !ourPerpetual) // he is checking us, but did not repeat yet\r
break; // (or we would have caught him before). Abort repetition-checking loop.\r
- // if neither of us is checking all the time, or both are, it is draw\r
- // (illegal-chase forfeits not implemented yet!)\r
+ // Now check for perpetual chases\r
+ if(!ourPerpetual && !hisPerpetual) { // no perpetual check, test for chase\r
+ hisPerpetual = PerpetualChase(k, forwardMostMove);\r
+ ourPerpetual = PerpetualChase(k+1, forwardMostMove);\r
+ if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit\r
+ GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, \r
+ "Xboard adjudication: perpetual chasing", GE_XBOARD );\r
+ return;\r
+ }\r
+ if(hisPerpetual && !ourPerpetual) // he is chasing us, but did not repeat yet\r
+ break; // Abort repetition-checking loop.\r
+ }\r
+ // if neither of us is checking or chasing all the time, or both are, it is draw\r
}\r
GameEnds( GameIsDrawn, "Xboard adjudication: repetition draw", GE_XBOARD );\r
return;\r
strcat(bookMove, bookHit);\r
message = bookMove;\r
cps = cps->other;\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
if(cps->nps >= 0) { /* [HGM] nps: use engine nodes or time to decrement clock */\r
int ticklen;\r
\r
- if(cps->nps == 0) ticklen = 10*time; // use engine reported time\r
- else ticklen = (1000. * nodes) / cps->nps; // convert node count to time\r
+ if(cps->nps == 0) ticklen = 10*time; // use engine reported time\r
+ else ticklen = (1000. * u64ToDouble(nodes)) / cps->nps; // convert node count to time\r
if(WhiteOnMove(forwardMostMove)) \r
whiteTimeRemaining = timeRemaining[0][forwardMostMove] - ticklen;\r
else blackTimeRemaining = timeRemaining[1][forwardMostMove] - ticklen;\r
else {\r
buf1[0] = NULLCHAR;\r
\r
- if (sscanf(message, "%d%c %d %d %lu %[^\n]\n",\r
+ if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",\r
&plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) \r
{\r
ChessProgramStats cpstats;\r
/* [HGM] compute & store e.p. status and castling rights for new position */\r
/* if we are updating a board for which those exist (i.e. in boards[]) */\r
if((p = ((int)board - (int)boards[0])/((int)boards[1]-(int)boards[0])) < MAX_MOVES && p > 0)\r
- { int i, j;\r
+ { int i;\r
\r
if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;\r
oldEP = epStatus[p-1];\r
if(gameMode == TwoMachinesPlay && appData.testClaims) {\r
if(appData.testLegality && whosays >= GE_ENGINE1 ) {\r
char claimer;\r
+ ChessMove trueResult = (ChessMove) -1;\r
\r
claimer = whosays == GE_ENGINE1 ? /* color of claimer */\r
first.twoMachinesColor[0] :\r
second.twoMachinesColor[0] ;\r
- if( (gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) &&\r
- (result == WhiteWins && claimer == 'w' ||\r
- result == BlackWins && claimer == 'b' ) ) {\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "result=%d sp=%d move=%d\n",\r
- result, epStatus[forwardMostMove], forwardMostMove);\r
+\r
+ // [HGM] losers: because the logic is becoming a bit hairy, determine true result first\r
+ if(epStatus[forwardMostMove] == EP_CHECKMATE) {\r
+ /* [HGM] verify: engine mate claims accepted if they were flagged */\r
+ trueResult = WhiteOnMove(forwardMostMove) != (gameInfo.variant == VariantLosers)\r
+ ? BlackWins : WhiteWins; // [HGM] losers: reverse the result in VariantLosers!\r
+ } else\r
+ if(epStatus[forwardMostMove] == EP_STALEMATE) {\r
+ trueResult = GameIsDrawn; // default; in variants where stalemate loses, Status is CHECKMATE\r
+ if(gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuicide || \r
+ gameInfo.variant == VariantLosers) // [HGM] losers: in giveaway variants stalemate wins\r
+ trueResult = WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins;\r
}\r
- /* [HGM] verify: engine mate claims accepted if they were flagged */\r
- if(epStatus[forwardMostMove] != EP_CHECKMATE &&\r
- result != (WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins)) {\r
+\r
+ // now verify win claims, but not in drop games, as we don't understand those yet\r
+ if( (gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper\r
+ || gameInfo.variant == VariantGreat) &&\r
+ (result == WhiteWins && claimer == 'w' ||\r
+ result == BlackWins && claimer == 'b' ) ) { // case to verify: engine claims own win\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "result=%d sp=%d move=%d\n",\r
+ result, epStatus[forwardMostMove], forwardMostMove);\r
+ }\r
+ if(result != trueResult) {\r
sprintf(buf, "False win claim: '%s'", resultDetails);\r
result = claimer == 'w' ? BlackWins : WhiteWins;\r
resultDetails = buf;\r
}\r
/* [HGM] bare: don't allow bare King to win */\r
if((gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
- && result != GameIsDrawn)\r
+ && gameInfo.variant != VariantLosers && gameInfo.variant != VariantGiveaway \r
+ && gameInfo.variant != VariantSuicide // [HGM] losers: except in losers, of course...\r
+ && result != GameIsDrawn)\r
{ int i, j, k=0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);\r
for(j=BOARD_LEFT; j<BOARD_RGHT; j++) for(i=0; i<BOARD_HEIGHT; i++) {\r
int p = (int)boards[forwardMostMove][i][j] - color;\r
{\r
int i, offset, linelen, newblock;\r
time_t tm;\r
- char *movetext;\r
+// char *movetext;\r
char numtext[32];\r
int movelen, numlen, blank;\r
char move_buffer[100]; /* [AS] Buffer for move+PV info */\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
#else\r
seconds = (pvInfoList[i].time + 5)/10; // [HGM] PVtime: use engine time\r
#endif\r
- if (appData.debugMode,0) {\r
- fprintf(debugFP, "times = %d %d %d %d, seconds=%d\n",\r
- timeRemaining[0][i+1], timeRemaining[0][i],\r
- timeRemaining[1][i+1], timeRemaining[1][i], seconds\r
- );\r
- }\r
\r
if( seconds <= 0) buf[0] = 0; else\r
if( seconds < 30 ) sprintf(buf, " %3.1f%c", seconds/10., 0); else {\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
if(bookHit) { // [HGM] book: simulate book reply\r
static char bookMove[MSG_SIZ]; // a bit generous?\r
\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
if(bookHit) { // [HGM] book: simulate book reply\r
static char bookMove[MSG_SIZ]; // a bit generous?\r
\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
if(bookHit) { // [HGM] book: simulate book reply\r
static char bookMove[MSG_SIZ]; // a bit generous?\r
\r
- programStats.depth = programStats.nodes = programStats.time = \r
+ programStats.nodes = programStats.depth = programStats.time = \r
programStats.score = programStats.got_only_move = 0;\r
sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
\r
} else return FALSE;\r
*p = 0; // terminate option name\r
// now look if the command-line options define a setting for this engine option.\r
- p = strstr(cps->optionSettings, opt->name);\r
- if(p == cps->optionSettings || p[-1] == ',') {\r
+ if(cps->optionSettings && cps->optionSettings[0])\r
+ p = strstr(cps->optionSettings, opt->name); else p = NULL;\r
+ if(p && (p == cps->optionSettings || p[-1] == ',')) {\r
sprintf(buf, "option %s", p);\r
if(p = strstr(buf, ",")) *p = 0;\r
strcat(buf, "\n");\r
you have neither ftime nor gettimeofday.\r
*/\r
\r
+/* VS 2008 requires the #include outside of the function */\r
+#if !HAVE_GETTIMEOFDAY && HAVE_FTIME\r
+#include <sys/timeb.h>\r
+#endif\r
+\r
/* Get the current time as a TimeMark */\r
void\r
GetTimeMark(tm)\r
#else /*!HAVE_GETTIMEOFDAY*/\r
#if HAVE_FTIME\r
\r
-#include <sys/timeb.h>\r
+// include <sys/timeb.h> / moved to just above start of function\r
struct timeb timeB;\r
\r
ftime(&timeB);\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