* backend.c -- Common back end for X and Windows NT versions of\r
* XBoard $Id: backend.c,v 2.6 2003/11/28 09:37:36 mann Exp $\r
*\r
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
- * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.\r
+ * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
+ * Massachusetts. Enhancements Copyright\r
+ * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software\r
+ * Foundation, Inc.\r
*\r
* The following terms apply to Digital Equipment Corporation's copyright\r
* interest in XBoard:\r
* SOFTWARE.\r
* ------------------------------------------------------------------------\r
*\r
- * The following terms apply to the enhanced version of XBoard distributed\r
- * by the Free Software Foundation:\r
+ * The following terms apply to the enhanced version of XBoard\r
+ * distributed by the Free Software Foundation:\r
* ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
+ *\r
+ * GNU XBoard is free software: you can redistribute it and/or modify\r
* it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
*\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
+ * GNU XBoard is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
*\r
* You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * ------------------------------------------------------------------------\r
+ * along with this program. If not, see http://www.gnu.org/licenses/. *\r
*\r
- * See the file ChangeLog for a revision history. */\r
+ *------------------------------------------------------------------------\r
+ ** See the file ChangeLog for a revision history. */\r
\r
/* [AS] Also useful here for debugging */\r
#ifdef WIN32\r
\r
#else\r
\r
-#define DoSleep( n )\r
-typedef int BOOL;\r
+#define DoSleep( n ) if( (n) >= 0) sleep(n)\r
\r
#endif\r
\r
#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
# include "zippy.h"\r
#endif\r
#include "backendz.h"\r
+#include "gettext.h" \r
+ \r
+#ifdef ENABLE_NLS \r
+# define _(s) gettext (s) \r
+# define N_(s) gettext_noop (s) \r
+#else \r
+# define _(s) (s) \r
+# define N_(s) s \r
+#endif \r
+\r
\r
/* A point in time */\r
typedef struct {\r
int ms; /* Assuming this is >= 16 bits */\r
} TimeMark;\r
\r
-/* Search stats from chessprogram */\r
-typedef struct {\r
- char movelist[2*MSG_SIZ]; /* Last PV we were sent */\r
- int depth; /* Current search depth */\r
- int nr_moves; /* Total nr of root moves */\r
- int moves_left; /* Moves remaining to be searched */\r
- char move_name[MOVE_LEN]; /* Current move being searched, if provided */\r
- unsigned long nodes; /* # of nodes searched */\r
- int time; /* Search time (centiseconds) */\r
- int score; /* Score (centipawns) */\r
- int got_only_move; /* If last msg was "(only move)" */\r
- int got_fail; /* 0 - nothing, 1 - got "--", 2 - got "++" */\r
- int ok_to_send; /* handshaking between send & recv */\r
- int line_is_book; /* 1 if movelist is book moves */\r
- int seen_stat; /* 1 if we've seen the stat01: line */\r
-} ChessProgramStats;\r
-\r
int establish P((void));\r
void read_from_player P((InputSourceRef isr, VOIDSTAR closure,\r
char *buf, int count, int error));\r
Board board));\r
void MakeMove P((int fromX, int fromY, int toX, int toY, int promoChar));\r
void ShowMove P((int fromX, int fromY, int toX, int toY));\r
-void FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
+int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,\r
/*char*/int promoChar));\r
void BackwardInner P((int target));\r
void ForwardInner P((int target));\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
+#endif\r
+\r
+ChessProgramState *WhitePlayer();\r
+void InsertIntoMemo P((int which, char *text)); // [HGM] kibitz: in engineo.c\r
+int VerifyDisplayMode P(());\r
\r
char *GetInfoFromComment( int, char * ); // [HGM] PV time: returns stripped comment\r
+void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); // [HGM] moved here from winboard.c\r
+char *ProbeBook P((int moveNr, char *book)); // [HGM] book: returns a book move\r
+char *SendMoveToBookUser P((int nr, ChessProgramState *cps, int initial)); // [HGM] book\r
+extern char installDir[MSG_SIZ];\r
\r
extern int tinyLayout, smallLayout;\r
-static ChessProgramStats programStats;\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
VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */\r
+int lastIndex = 0; /* [HGM] autoinc: last game/position used in match mode */\r
+int opponentKibitzes;\r
\r
/* States for ics_getting_history */\r
#define H_FALSE 0\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
+\r
+ * We use the highest bit for cast, this only\r
+ * works if the highest bit is not\r
+ * in use (This should not happen)\r
+ *\r
+ * We used this for all compiler\r
+ */\r
+double\r
+u64ToDouble(u64 value)\r
+{\r
+ double r;\r
+ u64 tmp = value & u64Const(0x7fffffffffffffff);\r
+ r = (double)(s64)tmp;\r
+ if (value & u64Const(0x8000000000000000))\r
+ r += 9.2233720368547758080e18; /* 2^63 */\r
+ return r;\r
+}\r
\r
/* Fake up flags for now, as we aren't keeping track of castling\r
availability yet. [HGM] Change of logic: the flag now only\r
if ((index % 2) == 0) flags |= F_WHITE_ON_MOVE;\r
switch (gameInfo.variant) {\r
case VariantSuicide:\r
- case VariantGiveaway:\r
- flags |= F_IGNORE_CHECK;\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
break;\r
case VariantAtomic:\r
flags |= F_IGNORE_CHECK | F_ATOMIC_CAPTURE;\r
Boolean alarmSounded;\r
/* end premove variables */\r
\r
-#define ICS_GENERIC 0\r
-#define ICS_ICC 1\r
-#define ICS_FICS 2\r
-#define ICS_CHESSNET 3 /* not really supported */\r
-int ics_type = ICS_GENERIC;\r
char *ics_prefix = "$";\r
+int ics_type = ICS_GENERIC;\r
\r
int currentMove = 0, forwardMostMove = 0, backwardMostMove = 0;\r
int pauseExamForwardMostMove = 0;\r
BlackKing, BlackBishop, BlackMarshall, BlackKnight, BlackRook }\r
};\r
\r
+ChessSquare GreatArray[2][BOARD_SIZE] = {\r
+ { WhiteDragon, WhiteKnight, WhiteAlfil, WhiteGrasshopper, WhiteKing, \r
+ WhiteSilver, WhiteCardinal, WhiteAlfil, WhiteKnight, WhiteDragon },\r
+ { BlackDragon, BlackKnight, BlackAlfil, BlackGrasshopper, BlackKing, \r
+ BlackSilver, BlackCardinal, BlackAlfil, BlackKnight, BlackDragon },\r
+};\r
+\r
ChessSquare JanusArray[2][BOARD_SIZE] = {\r
{ WhiteRook, WhiteAngel, WhiteKnight, WhiteBishop, WhiteKing, \r
WhiteQueen, WhiteBishop, WhiteKnight, WhiteAngel, WhiteRook },\r
#define XiangqiPosition FIDEArray\r
#define CapablancaArray FIDEArray\r
#define GothicArray FIDEArray\r
+#define GreatArray FIDEArray\r
#endif // !(BOARD_SIZE>=10)\r
\r
#if (BOARD_SIZE>=12)\r
{\r
int matched, min, sec;\r
\r
+ ShowThinkingEvent(); // [HGM] thinking: make sure post/nopost state is set according to options\r
+\r
GetTimeMark(&programStartTime);\r
\r
ClearProgramStats();\r
if (!ParseTimeControl(appData.timeControl, appData.timeIncrement,\r
appData.movesPerSession)) {\r
char buf[MSG_SIZ];\r
- sprintf(buf, "bad timeControl option %s", appData.timeControl);\r
+ sprintf(buf, _("bad timeControl option %s"), appData.timeControl);\r
DisplayFatalError(buf, 0, 2);\r
}\r
\r
searchTime = min * 60 + sec;\r
} else {\r
char buf[MSG_SIZ];\r
- sprintf(buf, "bad searchTime option %s", appData.searchTime);\r
+ sprintf(buf, _("bad searchTime option %s"), appData.searchTime);\r
DisplayFatalError(buf, 0, 2);\r
}\r
}\r
first.debug = second.debug = FALSE;\r
first.supportsNPS = second.supportsNPS = UNKNOWN;\r
\r
+ /* [HGM] options */\r
+ first.optionSettings = appData.firstOptions;\r
+ second.optionSettings = appData.secondOptions;\r
+\r
first.scoreIsAbsolute = appData.firstScoreIsAbsolute; /* [AS] */\r
second.scoreIsAbsolute = appData.secondScoreIsAbsolute; /* [AS] */\r
first.isUCI = appData.firstIsUCI; /* [AS] */\r
if (appData.firstProtocolVersion > PROTOVER ||\r
appData.firstProtocolVersion < 1) {\r
char buf[MSG_SIZ];\r
- sprintf(buf, "protocol version %d not supported",\r
+ sprintf(buf, _("protocol version %d not supported"),\r
appData.firstProtocolVersion);\r
DisplayFatalError(buf, 0, 2);\r
} else {\r
if (appData.secondProtocolVersion > PROTOVER ||\r
appData.secondProtocolVersion < 1) {\r
char buf[MSG_SIZ];\r
- sprintf(buf, "protocol version %d not supported",\r
+ sprintf(buf, _("protocol version %d not supported"),\r
appData.secondProtocolVersion);\r
DisplayFatalError(buf, 0, 2);\r
} else {\r
+ strlen(PATCHLEVEL));\r
sprintf(programVersion, "%s %s.%s", PRODUCT, VERSION, PATCHLEVEL);\r
} else {\r
+#if 0\r
char *p, *q;\r
q = first.program;\r
while (*q != ' ' && *q != NULLCHAR) q++;\r
p = q;\r
- while (p > first.program && *(p-1) != '/') p--;\r
+ while (p > first.program && *(p-1) != '/' && *(p-1) != '\\') p--; /* [HGM] bckslash added */\r
programVersion = (char*) malloc(8 + strlen(PRODUCT) + strlen(VERSION)\r
+ strlen(PATCHLEVEL) + (q - p));\r
sprintf(programVersion, "%s %s.%s + ", PRODUCT, VERSION, PATCHLEVEL);\r
strncat(programVersion, p, q - p);\r
+#else\r
+ /* [HGM] tidy: use tidy name, in stead of full pathname (which was probably a bug due to / vs \ ) */\r
+ programVersion = (char*) malloc(8 + strlen(PRODUCT) + strlen(VERSION)\r
+ + strlen(PATCHLEVEL) + strlen(first.tidy));\r
+ sprintf(programVersion, "%s %s.%s + %s", PRODUCT, VERSION, PATCHLEVEL, first.tidy);\r
+#endif\r
}\r
\r
if (!appData.icsActive) {\r
case VariantBughouse: /* need four players and two boards */\r
case VariantKriegspiel: /* need to hide pieces and move details */\r
/* case VariantFischeRandom: (Fabien: moved below) */\r
- sprintf(buf, "Variant %s supported only in ICS mode", appData.variant);\r
+ sprintf(buf, _("Variant %s supported only in ICS mode"), appData.variant);\r
DisplayFatalError(buf, 0, 2);\r
return;\r
\r
case Variant35:\r
case Variant36:\r
default:\r
- sprintf(buf, "Unknown variant name %s", appData.variant);\r
+ sprintf(buf, _("Unknown variant name %s"), appData.variant);\r
DisplayFatalError(buf, 0, 2);\r
return;\r
\r
case VariantShatranj: /* should work except for all win conditions */\r
case VariantBerolina: /* might work if TestLegality is off */\r
case VariantCapaRandom: /* should work */\r
+ case VariantJanus: /* should work */\r
+ case VariantSuper: /* experimental */\r
+ case VariantGreat: /* experimental, requires legality testing to be off */\r
break;\r
}\r
}\r
+\r
+ InitEngineUCI( installDir, &first ); // [HGM] moved here from winboard.c, to make available in xboard\r
+ InitEngineUCI( installDir, &second );\r
}\r
\r
int NextIntegerFromString( char ** str, long * value )\r
} else if (appData.matchMode) {\r
appData.matchGames = 1;\r
}\r
+ if(appData.matchMode && appData.sameColorGames > 0) /* [HGM] alternate: overrule matchGames */\r
+ appData.matchGames = appData.sameColorGames;\r
+ if(appData.rewindIndex > 1) { /* [HGM] autoinc: rewind implies auto-increment and overrules given index */\r
+ if(appData.loadPositionIndex >= 0) appData.loadPositionIndex = -1;\r
+ if(appData.loadGameIndex >= 0) appData.loadGameIndex = -1;\r
+ }\r
Reset(TRUE, FALSE);\r
if (appData.noChessProgram || first.protocolVersion == 1) {\r
InitBackEnd3();\r
} else {\r
/* kludge: allow timeout for initial "feature" commands */\r
FreezeUI();\r
- DisplayMessage("", "Starting chess program");\r
+ DisplayMessage("", _("Starting chess program"));\r
ScheduleDelayedEvent(InitBackEnd3, FEATURE_TIMEOUT);\r
}\r
}\r
\r
InitChessProgram(&first, startedFromSetupPosition);\r
\r
+\r
if (appData.icsActive) {\r
+#ifdef WIN32\r
+ /* [DM] Make a console window if needed [HGM] merged ifs */\r
+ ConsoleCreate(); \r
+#endif\r
err = establish();\r
if (err != 0) {\r
if (*appData.icsCommPort != NULLCHAR) {\r
- sprintf(buf, "Could not open comm port %s", \r
+ sprintf(buf, _("Could not open comm port %s"), \r
appData.icsCommPort);\r
} else {\r
- sprintf(buf, "Could not connect to host %s, port %s", \r
+ sprintf(buf, _("Could not connect to host %s, port %s"), \r
appData.icsHost, appData.icsPort);\r
}\r
DisplayFatalError(buf, err, 1);\r
} else if (StrCaseCmp(appData.initialMode, "Training") == 0) {\r
initialMode = Training;\r
} else {\r
- sprintf(buf, "Unknown initialMode %s", appData.initialMode);\r
+ sprintf(buf, _("Unknown initialMode %s"), appData.initialMode);\r
DisplayFatalError(buf, 0, 2);\r
return;\r
}\r
if (appData.matchMode) {\r
/* Set up machine vs. machine match */\r
if (appData.noChessProgram) {\r
- DisplayFatalError("Can't have a match with no chess programs",\r
+ DisplayFatalError(_("Can't have a match with no chess programs"),\r
0, 2);\r
return;\r
}\r
matchMode = TRUE;\r
matchGame = 1;\r
if (*appData.loadGameFile != NULLCHAR) {\r
+ int index = appData.loadGameIndex; // [HGM] autoinc\r
+ if(index<0) lastIndex = index = 1;\r
if (!LoadGameFromFile(appData.loadGameFile,\r
- appData.loadGameIndex,\r
+ index,\r
appData.loadGameFile, FALSE)) {\r
- DisplayFatalError("Bad game file", 0, 1);\r
+ DisplayFatalError(_("Bad game file"), 0, 1);\r
return;\r
}\r
} else if (*appData.loadPositionFile != NULLCHAR) {\r
+ int index = appData.loadPositionIndex; // [HGM] autoinc\r
+ if(index<0) lastIndex = index = 1;\r
if (!LoadPositionFromFile(appData.loadPositionFile,\r
- appData.loadPositionIndex,\r
+ index,\r
appData.loadPositionFile)) {\r
- DisplayFatalError("Bad position file", 0, 1);\r
+ DisplayFatalError(_("Bad position file"), 0, 1);\r
return;\r
}\r
}\r
/* Set up other modes */\r
if (initialMode == AnalyzeFile) {\r
if (*appData.loadGameFile == NULLCHAR) {\r
- DisplayFatalError("AnalyzeFile mode requires a game file", 0, 1);\r
+ DisplayFatalError(_("AnalyzeFile mode requires a game file"), 0, 1);\r
return;\r
}\r
}\r
}\r
if (initialMode == AnalyzeMode) {\r
if (appData.noChessProgram) {\r
- DisplayFatalError("Analysis mode requires a chess engine", 0, 2);\r
+ DisplayFatalError(_("Analysis mode requires a chess engine"), 0, 2);\r
return;\r
}\r
if (appData.icsActive) {\r
- DisplayFatalError("Analysis mode does not work with ICS mode",0,2);\r
+ DisplayFatalError(_("Analysis mode does not work with ICS mode"),0,2);\r
return;\r
}\r
AnalyzeModeEvent();\r
} else if (initialMode == AnalyzeFile) {\r
- ShowThinkingEvent(TRUE);\r
+ appData.showThinking = TRUE; // [HGM] thinking: moved out of ShowThinkingEvent\r
+ ShowThinkingEvent();\r
AnalyzeFileEvent();\r
AnalysisPeriodicEvent(1);\r
} else if (initialMode == MachinePlaysWhite) {\r
if (appData.noChessProgram) {\r
- DisplayFatalError("MachineWhite mode requires a chess engine",\r
+ DisplayFatalError(_("MachineWhite mode requires a chess engine"),\r
0, 2);\r
return;\r
}\r
if (appData.icsActive) {\r
- DisplayFatalError("MachineWhite mode does not work with ICS mode",\r
+ DisplayFatalError(_("MachineWhite mode does not work with ICS mode"),\r
0, 2);\r
return;\r
}\r
MachineWhiteEvent();\r
} else if (initialMode == MachinePlaysBlack) {\r
if (appData.noChessProgram) {\r
- DisplayFatalError("MachineBlack mode requires a chess engine",\r
+ DisplayFatalError(_("MachineBlack mode requires a chess engine"),\r
0, 2);\r
return;\r
}\r
if (appData.icsActive) {\r
- DisplayFatalError("MachineBlack mode does not work with ICS mode",\r
+ DisplayFatalError(_("MachineBlack mode does not work with ICS mode"),\r
0, 2);\r
return;\r
}\r
MachineBlackEvent();\r
} else if (initialMode == TwoMachinesPlay) {\r
if (appData.noChessProgram) {\r
- DisplayFatalError("TwoMachines mode requires a chess engine",\r
+ DisplayFatalError(_("TwoMachines mode requires a chess engine"),\r
0, 2);\r
return;\r
}\r
if (appData.icsActive) {\r
- DisplayFatalError("TwoMachines mode does not work with ICS mode",\r
+ DisplayFatalError(_("TwoMachines mode does not work with ICS mode"),\r
0, 2);\r
return;\r
}\r
EditPositionEvent();\r
} else if (initialMode == Training) {\r
if (*appData.loadGameFile == NULLCHAR) {\r
- DisplayFatalError("Training mode requires a game file", 0, 2);\r
+ DisplayFatalError(_("Training mode requires a game file"), 0, 2);\r
return;\r
}\r
TrainingEvent();\r
gotEof = 0;\r
outCount = OutputMaybeTelnet(icsPR, message, count, &outError);\r
if (outCount < count) {\r
- DisplayFatalError("Error writing to ICS", outError, 1);\r
+ DisplayFatalError(_("Error writing to ICS"), outError, 1);\r
}\r
} else if (count < 0) {\r
RemoveInputSource(isr);\r
- DisplayFatalError("Error reading from keyboard", error, 1);\r
+ DisplayFatalError(_("Error reading from keyboard"), error, 1);\r
} else if (gotEof++ > 0) {\r
RemoveInputSource(isr);\r
- DisplayFatalError("Got end of file from keyboard", 0, 0);\r
+ DisplayFatalError(_("Got end of file from keyboard"), 0, 0);\r
}\r
}\r
\r
count = strlen(s);\r
outCount = OutputMaybeTelnet(icsPR, s, count, &outError);\r
if (outCount < count) {\r
- DisplayFatalError("Error writing to ICS", outError, 1);\r
+ DisplayFatalError(_("Error writing to ICS"), outError, 1);\r
}\r
}\r
\r
outCount = OutputToProcessDelayed(icsPR, s, count, &outError,\r
msdelay);\r
if (outCount < count) {\r
- DisplayFatalError("Error writing to ICS", outError, 1);\r
+ DisplayFatalError(_("Error writing to ICS"), outError, 1);\r
}\r
}\r
\r
\r
if (!found) {\r
if ((StrCaseStr(e, "fischer") && StrCaseStr(e, "random"))\r
- || StrCaseStr(e, "wild/fr")) {\r
+ || StrCaseStr(e, "wild/fr") \r
+ || StrCaseStr(e, "frc") || StrCaseStr(e, "960")) {\r
v = VariantFischeRandom;\r
} else if ((i = 4, p = StrCaseStr(e, "wild")) ||\r
(i = 1, p = StrCaseStr(e, "w"))) {\r
case 48:\r
v = VariantJanus;\r
break;\r
+ case 49:\r
+ v = VariantSuper;\r
+ break;\r
+ case 50:\r
+ v = VariantGreat;\r
+ break;\r
case -1:\r
/* Found "wild" or "w" in the string but no number;\r
must assume it's normal chess. */\r
v = VariantNormal;\r
break;\r
default:\r
- sprintf(buf, "Unknown wild type %d", wnum);\r
+ sprintf(buf, _("Unknown wild type %d"), wnum);\r
DisplayError(buf, 0);\r
v = VariantUnknown;\r
break;\r
}\r
}\r
if (appData.debugMode) {\r
- fprintf(debugFP, "recognized '%s' (%d) as variant %s\n",\r
+ fprintf(debugFP, _("recognized '%s' (%d) as variant %s\n"),\r
e, wnum, VariantName(v));\r
}\r
return v;\r
int error, outCount;\r
outCount = OutputToProcess(NoProc, data, length, &error);\r
if (outCount < length) {\r
- DisplayFatalError("Error writing to display", error, 1);\r
+ DisplayFatalError(_("Error writing to display"), error, 1);\r
}\r
}\r
\r
msg[2] = option;\r
outCount = OutputToProcess(icsPR, (char *)msg, 3, &outError);\r
if (outCount < 3) {\r
- DisplayFatalError("Error writing to ICS", outError, 1);\r
+ DisplayFatalError(_("Error writing to ICS"), outError, 1);\r
}\r
}\r
\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) ( j + (int)lowestPiece );\r
+ piece = (ChessSquare) ( (int)piece + (int)lowestPiece );\r
board[holdingsStartRow+j*direction][holdingsColumn] = piece;\r
board[holdingsStartRow+j*direction][countsColumn]++;\r
}\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
/*----------------------------*/\r
\r
ColorClass curColor = ColorNormal;\r
+int suppressKibitz = 0;\r
\r
void\r
read_from_ics(isr, closure, data, count, error)\r
int buf_len;\r
int next_out;\r
int tkind;\r
+ int backup; /* [DM] For zippy color lines */\r
char *p;\r
\r
-#ifdef WIN32\r
if (appData.debugMode) {\r
if (!error) {\r
fprintf(debugFP, "<ICS: ");\r
fprintf(debugFP, "\n");\r
}\r
}\r
-#endif\r
\r
if (appData.debugMode) { int f = forwardMostMove;\r
fprintf(debugFP, "ics input %d, castling = %d %d %d %d %d %d\n", f,\r
for (i = 0; i < count; i++) {\r
if (data[i] != NULLCHAR && data[i] != '\r')\r
buf[buf_len++] = data[i];\r
+ if(buf_len >= 5 && buf[buf_len-5]=='\n' && buf[buf_len-4]=='\\' && \r
+ buf[buf_len-3]==' ' && buf[buf_len-2]==' ' && buf[buf_len-1]==' ') \r
+ buf_len -= 5; // [HGM] ICS: join continuation line of Lasker 2.2.3 server with previous\r
}\r
\r
buf[buf_len] = NULLCHAR;\r
parse[parse_pos++] = buf[i];\r
if (buf[i] == '\n') {\r
parse[parse_pos] = NULLCHAR;\r
- AppendComment(forwardMostMove, StripHighlight(parse));\r
+ if(!suppressKibitz) // [HGM] kibitz\r
+ AppendComment(forwardMostMove, StripHighlight(parse));\r
+ else { // [HGM kibitz: divert memorized engine kibitz to engine-output window\r
+ int nrDigit = 0, nrAlph = 0, i;\r
+ if(parse_pos > MSG_SIZ - 30) // defuse unreasonably long input\r
+ { parse_pos = MSG_SIZ-30; parse[parse_pos - 1] = '\n'; }\r
+ parse[parse_pos] = NULLCHAR;\r
+ // try to be smart: if it does not look like search info, it should go to\r
+ // ICS interaction window after all, not to engine-output window.\r
+ for(i=0; i<parse_pos; i++) { // count letters and digits\r
+ nrDigit += (parse[i] >= '0' && parse[i] <= '9');\r
+ nrAlph += (parse[i] >= 'a' && parse[i] <= 'z');\r
+ nrAlph += (parse[i] >= 'A' && parse[i] <= 'Z');\r
+ }\r
+ if(nrAlph < 9*nrDigit) { // if more than 10% digit we assume search info\r
+ OutputKibitz(suppressKibitz, parse);\r
+ } else {\r
+ char tmp[MSG_SIZ];\r
+ sprintf(tmp, _("your opponent kibitzes: %s"), parse);\r
+ SendToPlayer(tmp, strlen(tmp));\r
+ }\r
+ }\r
started = STARTED_NONE;\r
} else {\r
/* Don't match patterns against characters in chatter */\r
}\r
\r
oldi = i;\r
+ // [HGM] kibitz: try to recognize opponent engine-score kibitzes, to divert them to engine-output window\r
+ if (appData.autoKibitz && started == STARTED_NONE && \r
+ !appData.icsEngineAnalyze && // [HGM] [DM] ICS analyze\r
+ (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || gameMode == IcsObserving)) {\r
+ if(looking_at(buf, &i, "* kibitzes: ") &&\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
+ started = STARTED_CHATTER; // own kibitz we simply discard\r
+ else {\r
+ started = STARTED_COMMENT; // make sure it will be collected in parse[]\r
+ parse_pos = 0; parse[0] = NULLCHAR;\r
+ savingComment = TRUE;\r
+ suppressKibitz = gameMode != IcsObserving ? 2 :\r
+ (StrStr(star_match[0], gameInfo.white) == NULL) + 1;\r
+ } \r
+ continue;\r
+ } else\r
+ if(looking_at(buf, &i, "kibitzed to")) { // suppress the acknowledgements of our own autoKibitz\r
+ started = STARTED_CHATTER;\r
+ suppressKibitz = TRUE;\r
+ }\r
+ } // [HGM] kibitz: end of patch\r
+\r
if (appData.zippyTalk || appData.zippyPlay) {\r
+ /* [DM] Backup address for color zippy lines */\r
+ backup = i;\r
#if ZIPPY\r
- if (ZippyControl(buf, &i) ||\r
- ZippyConverse(buf, &i) ||\r
- (appData.zippyPlay && ZippyMatch(buf, &i))) {\r
- loggedOn = TRUE;\r
- continue;\r
+ #ifdef WIN32\r
+ if (loggedOn == TRUE)\r
+ if (ZippyControl(buf, &backup) || ZippyConverse(buf, &backup) ||\r
+ (appData.zippyPlay && ZippyMatch(buf, &backup)));\r
+ #else\r
+ if (ZippyControl(buf, &i) ||\r
+ ZippyConverse(buf, &i) ||\r
+ (appData.zippyPlay && ZippyMatch(buf, &i))) {\r
+ loggedOn = TRUE;\r
+ if (!appData.colorize) continue;\r
}\r
+ #endif\r
#endif\r
- } else {\r
- if (/* Don't color "message" or "messages" output */\r
+ } // [DM] 'else { ' deleted\r
+ if (/* Don't color "message" or "messages" output */\r
(tkind = 5, looking_at(buf, &i, "*. * (*:*): ")) ||\r
looking_at(buf, &i, "*. * at *:*: ") ||\r
looking_at(buf, &i, "--* (*:*): ") ||\r
curColor = ColorSeek;\r
}\r
continue;\r
- }\r
}\r
\r
if (looking_at(buf, &i, "\\ ")) {\r
case H_GOT_UNWANTED_HEADER:\r
case H_GETTING_MOVES:\r
/* Should not happen */\r
- DisplayError("Error gathering move list: two headers", 0);\r
+ DisplayError(_("Error gathering move list: two headers"), 0);\r
ics_getting_history = H_FALSE;\r
break;\r
}\r
gameInfo.whiteRating = string_to_rating(star_match[1]);\r
gameInfo.blackRating = string_to_rating(star_match[3]);\r
if (appData.debugMode)\r
- fprintf(debugFP, "Ratings from header: W %d, B %d\n", \r
+ fprintf(debugFP, _("Ratings from header: W %d, B %d\n"), \r
gameInfo.whiteRating, gameInfo.blackRating);\r
}\r
continue;\r
break;\r
case H_GETTING_MOVES:\r
/* Should not happen */\r
- DisplayError("Error gathering move list: nested", 0);\r
+ DisplayError(_("Error gathering move list: nested"), 0);\r
ics_getting_history = H_FALSE;\r
break;\r
case H_GOT_REQ_HEADER:\r
\r
if (looking_at(buf, &i, "% ") ||\r
((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE)\r
- && looking_at(buf, &i, "}*"))) {\r
+ && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book\r
savingComment = FALSE;\r
switch (started) {\r
case STARTED_MOVES:\r
}\r
SendTimeRemaining(&first, TRUE);\r
}\r
+#if 0\r
if (first.useColors) {\r
SendToProgram("white\ngo\n", &first);\r
} else {\r
SendToProgram("go\n", &first);\r
}\r
+#else\r
+ if (first.useColors) {\r
+ SendToProgram("white\n", &first); // [HGM] book: made sending of "go\n" book dependent\r
+ }\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: probe book for initial pos\r
+#endif\r
first.maybeThinking = TRUE;\r
} else {\r
if (first.usePlayother) {\r
}\r
SendTimeRemaining(&first, FALSE);\r
}\r
+#if 0\r
if (first.useColors) {\r
SendToProgram("black\ngo\n", &first);\r
} else {\r
SendToProgram("go\n", &first);\r
}\r
+#else\r
+ if (first.useColors) {\r
+ SendToProgram("black\n", &first);\r
+ }\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE);\r
+#endif\r
first.maybeThinking = TRUE;\r
} else {\r
if (first.usePlayother) {\r
default:\r
break;\r
}\r
+ if(bookHit) { // [HGM] book: simulate book reply\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ programStats.nodes = programStats.depth = programStats.time = \r
+ programStats.score = programStats.got_only_move = 0;\r
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ HandleMachineMove(bookMove, &first);\r
+ }\r
continue;\r
}\r
\r
if (forwardMostMove > backwardMostMove) {\r
currentMove = --forwardMostMove;\r
DisplayMove(currentMove - 1); /* before DMError */\r
- DisplayMoveError("Illegal move (rejected by ICS)");\r
+ DisplayMoveError(_("Illegal move (rejected by ICS)"));\r
DrawPosition(FALSE, boards[currentMove]);\r
SwitchClocks();\r
DisplayBothClocks();\r
if (gameMode == IcsObserving &&\r
atoi(star_match[0]) == ics_gamenum)\r
{\r
+ /* icsEngineAnalyze */\r
+ if (appData.icsEngineAnalyze) {\r
+ ExitAnalyzeMode();\r
+ ModeHighlight();\r
+ }\r
StopClocks();\r
gameMode = IcsIdle;\r
ics_gamenum = -1;\r
i++; /* skip unparsed character and loop back */\r
}\r
\r
- if (started != STARTED_MOVES && started != STARTED_BOARD &&\r
+ if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz suppress printing in ICS interaction window\r
started != STARTED_HOLDINGS && i > next_out) {\r
SendToPlayer(&buf[next_out], i - next_out);\r
next_out = i;\r
}\r
+ suppressKibitz = FALSE; // [HGM] kibitz: has done its duty in if-statement above\r
\r
leftover_len = buf_len - leftover_start;\r
/* if buffer ends with something we couldn't parse,\r
\r
} else if (count == 0) {\r
RemoveInputSource(isr);\r
- DisplayFatalError("Connection closed by ICS", 0, 0);\r
+ DisplayFatalError(_("Connection closed by ICS"), 0, 0);\r
} else {\r
- DisplayFatalError("Error reading from ICS", error, 1);\r
+ DisplayFatalError(_("Error reading from ICS"), error, 1);\r
}\r
}\r
\r
* Additional trailing fields may be added in the future. \r
*/\r
\r
-#define PATTERN "%72c%c%d%d%d%d%d%d%d%s%s%d%d%d%d%d%d%d%d%s%s%s%d%d"\r
+#define PATTERN "%c%d%d%d%d%d%d%d%s%s%d%d%d%d%d%d%d%d%s%s%s%d%d"\r
\r
#define RELATION_OBSERVING_PLAYED 0\r
#define RELATION_OBSERVING_STATIC -2 /* examined, oldmoves, or smoves */\r
char *string;\r
{ \r
GameMode newGameMode;\r
- int gamenum, newGame, newMove, relation, basetime, increment, ics_flip = 0;\r
- int j, k, n, moveNum, white_stren, black_stren, white_time, black_time;\r
+ int gamenum, newGame, newMove, relation, basetime, increment, ics_flip = 0, i;\r
+ int j, k, n, moveNum, white_stren, black_stren, white_time, black_time, takeback;\r
int double_push, castle_ws, castle_wl, castle_bs, castle_bl, irrev_count;\r
- char to_play, board_chars[72];\r
+ char to_play, board_chars[200];\r
char move_str[500], str[500], elapsed_time[500];\r
char black[32], white[32];\r
Board board;\r
ChessMove moveType;\r
int fromX, fromY, toX, toY;\r
char promoChar;\r
+ int ranks=1, files=0; /* [HGM] ICS80: allow variable board size */\r
+ char *bookHit = NULL; // [HGM] book\r
\r
fromX = fromY = toX = toY = -1;\r
\r
newGame = FALSE;\r
\r
if (appData.debugMode)\r
- fprintf(debugFP, "Parsing board: %s\n", string);\r
+ fprintf(debugFP, _("Parsing board: %s\n"), string);\r
\r
move_str[0] = NULLCHAR;\r
elapsed_time[0] = NULLCHAR;\r
- n = sscanf(string, PATTERN, board_chars, &to_play, &double_push,\r
+ { /* [HGM] figure out how many ranks and files the board has, for ICS extension used by Capablanca server */\r
+ int i = 0, j;\r
+ while(i < 199 && (string[i] != ' ' || string[i+2] != ' ')) {\r
+ if(string[i] == ' ') { ranks++; files = 0; }\r
+ else files++;\r
+ i++;\r
+ }\r
+ for(j = 0; j <i; j++) board_chars[j] = string[j];\r
+ board_chars[i] = '\0';\r
+ string += i + 1;\r
+ }\r
+ n = sscanf(string, PATTERN, &to_play, &double_push,\r
&castle_ws, &castle_wl, &castle_bs, &castle_bl, &irrev_count,\r
&gamenum, white, black, &relation, &basetime, &increment,\r
&white_stren, &black_stren, &white_time, &black_time,\r
&moveNum, str, elapsed_time, move_str, &ics_flip,\r
&ticking);\r
\r
- if (n < 22) {\r
- sprintf(str, "Failed to parse board string:\n\"%s\"", string);\r
+ if (n < 21) {\r
+ sprintf(str, _("Failed to parse board string:\n\"%s\""), string);\r
DisplayError(str, 0);\r
return;\r
}\r
moveNum = (moveNum - 1) * 2;\r
if (to_play == 'B') moveNum++;\r
if (moveNum >= MAX_MOVES) {\r
- DisplayFatalError("Game too long; increase MAX_MOVES and recompile",\r
+ DisplayFatalError(_("Game too long; increase MAX_MOVES and recompile"),\r
0, 1);\r
return;\r
}\r
return;\r
case H_GETTING_MOVES:\r
/* Should not happen */\r
- DisplayError("Error gathering move list: extra board", 0);\r
+ DisplayError(_("Error gathering move list: extra board"), 0);\r
ics_getting_history = H_FALSE;\r
return;\r
}\r
}\r
}\r
\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "load %dx%d board\n", files, ranks);\r
+ }\r
/* Parse the board */\r
- for (k = 0; k < 8; k++) {\r
- for (j = 0; j < 8; j++)\r
- board[k][j+gameInfo.holdingsWidth] = CharToPiece(board_chars[(7-k)*9 + j]);\r
+ for (k = 0; k < ranks; k++) {\r
+ for (j = 0; j < files; j++)\r
+ board[k][j+gameInfo.holdingsWidth] = CharToPiece(board_chars[(ranks-1-k)*(files+1) + 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
but in ICS mode that is not its job anyway.\r
*/\r
if(moveNum == 0 || gameInfo.variant != VariantFischeRandom)\r
- { int i, j;\r
+ { int i, j; ChessSquare wKing = WhiteKing, bKing = BlackKing;\r
\r
for(i=BOARD_LEFT, j= -1; i<BOARD_RGHT; i++)\r
if(board[0][i] == WhiteRook) j = i;\r
if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;\r
initialRights[4] = castlingRights[moveNum][4] = (castle_bl == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);\r
\r
+ if(gameInfo.variant == VariantKnightmate) { wKing = WhiteUnicorn; bKing = BlackUnicorn; }\r
for(k=BOARD_LEFT; k<BOARD_RGHT; k++)\r
- if(board[0][k] == WhiteKing) initialRights[2] = castlingRights[moveNum][2] = k;\r
+ if(board[0][k] == wKing) initialRights[2] = castlingRights[moveNum][2] = k;\r
for(k=BOARD_LEFT; k<BOARD_RGHT; k++)\r
- if(board[BOARD_HEIGHT-1][k] == BlackKing)\r
+ if(board[BOARD_HEIGHT-1][k] == bKing)\r
initialRights[5] = castlingRights[moveNum][5] = k;\r
} else { int r;\r
r = castlingRights[moveNum][0] = initialRights[0];\r
\r
/* Update currentMove and known move number limits */\r
newMove = newGame || moveNum > forwardMostMove;\r
+\r
+ /* [DM] If we found takebacks during icsEngineAnalyze try send to engine */\r
+ if (!newGame && appData.icsEngineAnalyze && moveNum < forwardMostMove) {\r
+ takeback = forwardMostMove - moveNum;\r
+ for (i = 0; i < takeback; i++) {\r
+ if (appData.debugMode) fprintf(debugFP, "take back move\n");\r
+ SendToProgram("undo\n", &first);\r
+ }\r
+ }\r
+\r
if (newGame) {\r
forwardMostMove = backwardMostMove = currentMove = moveNum;\r
if (gameMode == IcsExamining && moveNum == 0) {\r
strcat(parseList[moveNum - 1], " ");\r
strcat(parseList[moveNum - 1], elapsed_time);\r
moveList[moveNum - 1][0] = NULLCHAR;\r
- } else if (ParseOneMove(move_str, moveNum - 1, &moveType,\r
- &fromX, &fromY, &toX, &toY, &promoChar)) {\r
+ } else if (strcmp(move_str, "none") == 0) {\r
+ // [HGM] long SAN: swapped order; test for 'none' before parsing move\r
+ /* Again, we don't know what the board looked like;\r
+ this is really the start of the game. */\r
+ parseList[moveNum - 1][0] = NULLCHAR;\r
+ moveList[moveNum - 1][0] = NULLCHAR;\r
+ backwardMostMove = moveNum;\r
+ startedFromSetupPosition = TRUE;\r
+ fromX = fromY = toX = toY = -1;\r
+ } else {\r
+ // [HGM] long SAN: if legality-testing is off, disambiguation might not work or give wrong move. \r
+ // So we parse the long-algebraic move string in stead of the SAN move\r
+ int valid; char buf[MSG_SIZ], *prom;\r
+\r
+ // str looks something like "Q/a1-a2"; kill the slash\r
+ if(str[1] == '/') \r
+ sprintf(buf, "%c%s", str[0], str+2);\r
+ else strcpy(buf, str); // might be castling\r
+ if((prom = strstr(move_str, "=")) && !strstr(buf, "=")) \r
+ strcat(buf, prom); // long move lacks promo specification!\r
+ if(!appData.testLegality) {\r
+ if(appData.debugMode) \r
+ fprintf(debugFP, "replaced ICS move '%s' by '%s'\n", move_str, buf);\r
+ strcpy(move_str, buf);\r
+ }\r
+ valid = ParseOneMove(move_str, moveNum - 1, &moveType,\r
+ &fromX, &fromY, &toX, &toY, &promoChar)\r
+ || ParseOneMove(buf, moveNum - 1, &moveType,\r
+ &fromX, &fromY, &toX, &toY, &promoChar);\r
+ // end of long SAN patch\r
+ if (valid) {\r
(void) CoordsToAlgebraic(boards[moveNum - 1],\r
PosFlags(moveNum - 1), EP_UNKNOWN,\r
fromY, fromX, toY, toX, promoChar,\r
/* currentMoveString is set as a side-effect of ParseOneMove */\r
strcpy(moveList[moveNum - 1], currentMoveString);\r
strcat(moveList[moveNum - 1], "\n");\r
- } else if (strcmp(move_str, "none") == 0) {\r
- /* Again, we don't know what the board looked like;\r
- this is really the start of the game. */\r
- parseList[moveNum - 1][0] = NULLCHAR;\r
- moveList[moveNum - 1][0] = NULLCHAR;\r
- backwardMostMove = moveNum;\r
- startedFromSetupPosition = TRUE;\r
- fromX = fromY = toX = toY = -1;\r
- } else {\r
+ } else {\r
/* Move from ICS was illegal!? Punt. */\r
if (appData.debugMode) {\r
fprintf(debugFP, "Illegal move from ICS '%s'\n", move_str);\r
strcat(parseList[moveNum - 1], elapsed_time);\r
moveList[moveNum - 1][0] = NULLCHAR;\r
fromX = fromY = toX = toY = -1;\r
+ }\r
}\r
if (appData.debugMode) {\r
fprintf(debugFP, "Move parsed to '%s'\n", parseList[moveNum - 1]);\r
if ((gameMode == IcsPlayingWhite && WhiteOnMove(moveNum)) ||\r
(gameMode == IcsPlayingBlack && !WhiteOnMove(moveNum))) {\r
if (moveList[moveNum - 1][0] == NULLCHAR) {\r
- sprintf(str, "Couldn't parse move \"%s\" from ICS",\r
+ sprintf(str, _("Couldn't parse move \"%s\" from ICS"),\r
move_str);\r
DisplayError(str, 0);\r
} else {\r
if (first.sendTime) {\r
SendTimeRemaining(&first, gameMode == IcsPlayingWhite);\r
}\r
- SendMoveToProgram(moveNum - 1, &first);\r
- if (firstMove) {\r
+ bookHit = SendMoveToBookUser(moveNum - 1, &first, FALSE); // [HGM] book\r
+ if (firstMove && !bookHit) {\r
firstMove = FALSE;\r
if (first.useColors) {\r
SendToProgram(gameMode == IcsPlayingWhite ?\r
}\r
} else if (gameMode == IcsObserving || gameMode == IcsExamining) {\r
if (moveList[moveNum - 1][0] == NULLCHAR) {\r
- sprintf(str, "Couldn't parse move \"%s\" from ICS", move_str);\r
+ sprintf(str, _("Couldn't parse move \"%s\" from ICS"), move_str);\r
DisplayError(str, 0);\r
} else {\r
if(gameInfo.variant == currentlyInitializedVariant) // [HGM] refrain sending moves engine can't understand!\r
}\r
\r
HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);\r
+#if ZIPPY\r
+ if(bookHit) { // [HGM] book: simulate book reply\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ programStats.nodes = programStats.depth = programStats.time = \r
+ programStats.score = programStats.got_only_move = 0;\r
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ HandleMachineMove(bookMove, &first);\r
+ }\r
+#endif\r
}\r
\r
void\r
}\r
SendToProgram(buf, cps);\r
} else {\r
+ if(cps->alphaRank) { /* [HGM] shogi: temporarily convert to shogi coordinates before sending */\r
+ AlphaRank(moveList[moveNum], 4);\r
+ SendToProgram(moveList[moveNum], cps);\r
+ AlphaRank(moveList[moveNum], 4); // and back\r
+ } else\r
/* Added by Tord: Send castle moves in "O-O" in FRC games if required by\r
* the engine. It would be nice to have a better way to identify castle \r
* moves here. */\r
if((gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom)\r
&& cps->useOOCastle) {\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "Tord's FRC castling code\n");\r
- }\r
int fromX = moveList[moveNum][0] - AAA; \r
int fromY = moveList[moveNum][1] - ONE;\r
int toX = moveList[moveNum][2] - AAA; \r
\r
switch (moveType) {\r
default:\r
- sprintf(user_move, "say Internal error; bad moveType %d (%d,%d-%d,%d)",\r
+ sprintf(user_move, _("say Internal error; bad moveType %d (%d,%d-%d,%d)"),\r
(int)moveType, fromX, fromY, toX, toY);\r
DisplayError(user_move + strlen("say "), 0);\r
break;\r
case BlackPromotionChancellor:\r
case WhitePromotionArchbishop:\r
case BlackPromotionArchbishop:\r
- if(gameInfo.variant == VariantShatranj)\r
+ if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
sprintf(user_move, "%c%c%c%c=%c\n",\r
AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
PieceToChar(WhiteFerz));\r
+ else if(gameInfo.variant == VariantGreat)\r
+ sprintf(user_move, "%c%c%c%c=%c\n",\r
+ AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
+ PieceToChar(WhiteMan));\r
else\r
sprintf(user_move, "%c%c%c%c=%c\n",\r
AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
AAA + ff, ONE + rf, AAA + ft, ONE + rt, promoChar);\r
}\r
}\r
- AlphaRank(move, 4);\r
}\r
\r
void\r
void\r
AlphaRank(char *move, int n)\r
{\r
- char *p = move, c; int x, y;\r
-\r
- if( !appData.alphaRank ) return;\r
+// char *p = move, c; int x, y;\r
\r
if (appData.debugMode) {\r
fprintf(debugFP, "alphaRank(%s,%d)\n", move, n);\r
if(move[1]=='*' && \r
move[2]>='0' && move[2]<='9' &&\r
move[3]>='a' && move[3]<='x' ) {\r
+ move[1] = '@';\r
move[2] = BOARD_RGHT -1 - (move[2]-'1') + AAA;\r
move[3] = BOARD_HEIGHT-1 - (move[3]-'a') + ONE;\r
} else\r
}\r
}\r
\r
+#if 0\r
/* [AS] FRC game initialization */\r
static int FindEmptySquare( Board board, int n )\r
{\r
return i;\r
}\r
\r
-#if 0\r
static void ShuffleFRC( Board board )\r
{\r
int i;\r
\r
int squaresLeft[4];\r
int piecesLeft[(int)BlackPawn];\r
-long long int seed, nrOfShuffles;\r
+u64 seed, nrOfShuffles;\r
+\r
+void GetPositionNumber()\r
+{ // sets global variable seed\r
+ int i;\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
+ }\r
+}\r
\r
int put(Board board, int pieceType, int rank, int n, int shade)\r
// put the piece on the (n-1)-th empty squares of the given shade\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
{\r
int i, p, first=1;\r
\r
- seed = number, nrOfShuffles = 1;\r
- if(number < 0) { \r
- srand(time(0)); \r
- for(i=0; i<50; i++) seed += rand();\r
- seed = rand() ^ rand()<<16; \r
- }\r
+ GetPositionNumber(); nrOfShuffles = 1;\r
\r
squaresLeft[DARK] = (BOARD_RGHT - BOARD_LEFT + 1)/2;\r
squaresLeft[ANY] = BOARD_RGHT - BOARD_LEFT;\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
\r
#endif\r
\r
-BOOL SetCharTable( char *table, const char * map )\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
{\r
- BOOL result = FALSE; int NrPieces;\r
+ int result = FALSE; int NrPieces;\r
\r
if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare \r
&& NrPieces >= 12 && !(NrPieces&1)) {\r
return result;\r
}\r
\r
+void Prelude(Board board)\r
+{ // [HGM] superchess: random selection of exo-pieces\r
+ int i, j, k; ChessSquare p; \r
+ static ChessSquare exoPieces[4] = { WhiteAngel, WhiteMarshall, WhiteSilver, WhiteLance };\r
+\r
+ GetPositionNumber(); // use FRC position number\r
+\r
+ if(appData.pieceToCharTable != NULL) { // select pieces to participate from given char table\r
+ SetCharTable(pieceToChar, appData.pieceToCharTable);\r
+ for(i=(int)WhiteQueen+1, j=0; i<(int)WhiteKing && j<4; i++) \r
+ if(PieceToChar((ChessSquare)i) != '.') exoPieces[j++] = (ChessSquare) i;\r
+ }\r
+\r
+ j = seed%4; seed /= 4; \r
+ p = board[0][BOARD_LEFT+j]; board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p);\r
+ board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;\r
+ board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;\r
+ j = seed%3 + (seed%3 >= j); seed /= 3; \r
+ p = board[0][BOARD_LEFT+j]; board[0][BOARD_LEFT+j] = EmptySquare; k = PieceToNumber(p);\r
+ board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;\r
+ board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;\r
+ j = seed%3; seed /= 3; \r
+ p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p);\r
+ board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;\r
+ board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;\r
+ j = seed%2 + (seed%2 >= j); seed /= 2; \r
+ p = board[0][BOARD_LEFT+j+5]; board[0][BOARD_LEFT+j+5] = EmptySquare; k = PieceToNumber(p);\r
+ board[k][BOARD_WIDTH-1] = p; board[k][BOARD_WIDTH-2]++;\r
+ board[BOARD_HEIGHT-1-k][0] = WHITE_TO_BLACK p; board[BOARD_HEIGHT-1-k][1]++;\r
+ j = seed%4; seed /= 4; put(board, exoPieces[3], 0, j, ANY);\r
+ j = seed%3; seed /= 3; put(board, exoPieces[2], 0, j, ANY);\r
+ j = seed%2; seed /= 2; put(board, exoPieces[1], 0, j, ANY);\r
+ put(board, exoPieces[0], 0, 0, ANY);\r
+ for(i=BOARD_LEFT; i<BOARD_RGHT; i++) board[BOARD_HEIGHT-1][i] = WHITE_TO_BLACK board[0][i];\r
+}\r
+\r
void\r
InitPosition(redraw)\r
int redraw;\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
pieces = fairyArray;\r
SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk"); \r
break;\r
+ case VariantGreat:\r
+ pieces = GreatArray;\r
+ gameInfo.boardWidth = 10;\r
+ SetCharTable(pieceToChar, "PN....E...S..HWGMKpn....e...s..hwgmk");\r
+ gameInfo.holdingsSize = 8;\r
+ break;\r
+ case VariantSuper:\r
+ pieces = FIDEArray;\r
+ SetCharTable(pieceToChar, "PNBRQ..SE.......V.AKpnbrq..se.......v.ak");\r
+ gameInfo.holdingsSize = 8;\r
+ startedFromSetupPosition = TRUE;\r
+ break;\r
case VariantCrazyhouse:\r
case VariantBughouse:\r
pieces = FIDEArray;\r
}\r
if(gameInfo.holdingsSize) gameInfo.holdingsWidth = 2;\r
if(BOARD_HEIGHT > BOARD_SIZE || BOARD_WIDTH > BOARD_SIZE)\r
- DisplayFatalError("Recompile to support this BOARD_SIZE!", 0, 2);\r
+ DisplayFatalError(_("Recompile to support this BOARD_SIZE!"), 0, 2);\r
\r
pawnRow = gameInfo.boardHeight - 7; /* seems to work in all common variants */\r
if(pawnRow < 1) pawnRow = 1;\r
castlingRights[0][5] = initialRights[5] = BOARD_WIDTH>>1;\r
}\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[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan;\r
+ initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9;\r
+ }\r
#if 0\r
if(gameInfo.variant == VariantFischeRandom) {\r
if( appData.defaultFrcPosition < 0 ) {\r
PieceToChar((ChessSquare)(DEMOTED *bp)),\r
AAA + j, ONE + i);\r
}\r
- if(appData.alphaRank) {\r
+ if(cps->alphaRank) { /* [HGM] shogi: translate coords */\r
message[1] = BOARD_RGHT - 1 - j + '1';\r
message[2] = BOARD_HEIGHT - 1 - i + 'a';\r
}\r
PieceToChar((ChessSquare)(DEMOTED *bp)),\r
AAA + j, ONE + i);\r
}\r
- if(appData.alphaRank) {\r
+ if(cps->alphaRank) { /* [HGM] shogi: translate coords */\r
message[1] = BOARD_RGHT - 1 - j + '1';\r
message[2] = BOARD_HEIGHT - 1 - i + 'a';\r
}\r
case IcsPlayingBlack:\r
if (appData.zippyPlay) return FALSE;\r
if (white_piece) {\r
- DisplayMoveError("You are playing Black");\r
+ DisplayMoveError(_("You are playing Black"));\r
return FALSE;\r
}\r
break;\r
case IcsPlayingWhite:\r
if (appData.zippyPlay) return FALSE;\r
if (!white_piece) {\r
- DisplayMoveError("You are playing White");\r
+ DisplayMoveError(_("You are playing White"));\r
return FALSE;\r
}\r
break;\r
\r
case EditGame:\r
if (!white_piece && WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is White's turn");\r
+ DisplayMoveError(_("It is White's turn"));\r
return FALSE;\r
} \r
if (white_piece && !WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is Black's turn");\r
+ DisplayMoveError(_("It is Black's turn"));\r
return FALSE;\r
} \r
if (cmailMsgLoaded && (currentMove < cmailOldMove)) {\r
if (appData.icsActive) return FALSE;\r
if (!appData.noChessProgram) {\r
if (!white_piece) {\r
- DisplayMoveError("You are playing White");\r
+ DisplayMoveError(_("You are playing White"));\r
return FALSE;\r
}\r
}\r
\r
case Training:\r
if (!white_piece && WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is White's turn");\r
+ DisplayMoveError(_("It is White's turn"));\r
return FALSE;\r
} \r
if (white_piece && !WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is Black's turn");\r
+ DisplayMoveError(_("It is Black's turn"));\r
return FALSE;\r
} \r
break;\r
}\r
if (currentMove != forwardMostMove && gameMode != AnalyzeMode\r
&& gameMode != AnalyzeFile && gameMode != Training) {\r
- DisplayMoveError("Displayed position is not current");\r
+ DisplayMoveError(_("Displayed position is not current"));\r
return FALSE;\r
}\r
return TRUE;\r
case MachinePlaysWhite:\r
/* User is moving for Black */\r
if (WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is White's turn");\r
+ DisplayMoveError(_("It is White's turn"));\r
return ImpossibleMove;\r
}\r
break;\r
case MachinePlaysBlack:\r
/* User is moving for White */\r
if (!WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is Black's turn");\r
+ DisplayMoveError(_("It is Black's turn"));\r
return ImpossibleMove;\r
}\r
break;\r
(int) boards[currentMove][fromY][fromX] < (int) EmptySquare) {\r
/* User is moving for Black */\r
if (WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is White's turn");\r
+ DisplayMoveError(_("It is White's turn"));\r
return ImpossibleMove;\r
}\r
} else {\r
/* User is moving for White */\r
if (!WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is Black's turn");\r
+ DisplayMoveError(_("It is Black's turn"));\r
return ImpossibleMove;\r
}\r
}\r
/* User is moving for Black */\r
if (WhiteOnMove(currentMove)) {\r
if (!appData.premove) {\r
- DisplayMoveError("It is White's turn");\r
+ DisplayMoveError(_("It is White's turn"));\r
} else if (toX >= 0 && toY >= 0) {\r
premoveToX = toX;\r
premoveToY = toY;\r
/* User is moving for White */\r
if (!WhiteOnMove(currentMove)) {\r
if (!appData.premove) {\r
- DisplayMoveError("It is Black's turn");\r
+ DisplayMoveError(_("It is Black's turn"));\r
} else if (toX >= 0 && toY >= 0) {\r
premoveToX = toX;\r
premoveToY = toY;\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 AmbiguousMove;\r
} else if (toX >= 0 && toY >= 0) {\r
boards[0][toY][toX] = boards[0][fromY][fromX];\r
boards[0][fromY][fromX] = EmptySquare;\r
- DrawPosition(FALSE, boards[currentMove]);\r
+ return AmbiguousMove;\r
}\r
return ImpossibleMove;\r
}\r
/* [HGM] but possibly ignore an IllegalMove result */\r
if (appData.testLegality) {\r
if (moveType == IllegalMove || moveType == ImpossibleMove) {\r
- DisplayMoveError("Illegal move");\r
+ DisplayMoveError(_("Illegal move"));\r
return ImpossibleMove;\r
}\r
}\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 3 = %d, promochar = %x\n", moveType, promoChar);\r
return moveType;\r
/* [HGM] <popupFix> in stead of calling FinishMove directly, this\r
function is made into one that returns an OK move type if FinishMove\r
}\r
\r
/* Common tail of UserMoveEvent and DropMenuEvent */\r
-void\r
+int\r
FinishMove(moveType, fromX, fromY, toX, toY, promoChar)\r
ChessMove moveType;\r
int fromX, fromY, toX, toY;\r
/*char*/int promoChar;\r
{\r
- /* [HGM] <popupFix> kludge to avoid having know the exact promotion\r
+ char *bookHit = 0;\r
+if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", moveType, promoChar);\r
+ if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) { \r
+ // [HGM] superchess: suppress promotions to non-available piece\r
+ int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));\r
+ if(WhiteOnMove(currentMove)) {\r
+ if(!boards[currentMove][k][BOARD_WIDTH-2]) return 0;\r
+ } else {\r
+ if(!boards[currentMove][BOARD_HEIGHT-1-k][1]) return 0;\r
+ }\r
+ }\r
+\r
+ /* [HGM] <popupFix> kludge to avoid having to know the exact promotion\r
move type in caller when we know the move is a legal promotion */\r
- if(moveType == NormalMove)\r
+ if(moveType == NormalMove && promoChar)\r
moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", moveType, promoChar);\r
/* [HGM] convert drag-and-drop piece drops to standard form */\r
if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {\r
moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;\r
gameMode = PlayFromGameFile;\r
ModeHighlight();\r
SetTrainingModeOff();\r
- DisplayInformation("End of game");\r
+ DisplayInformation(_("End of game"));\r
}\r
} else {\r
- DisplayError("Incorrect move", 0);\r
+ DisplayError(_("Incorrect move"), 0);\r
}\r
- return;\r
+ return 1;\r
}\r
\r
/* Ok, now we know that the move is good, so we can kill\r
\r
MakeMove(fromX, fromY, toX, toY, promoChar); /*updates forwardMostMove*/\r
\r
+ if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) \r
+ && promoChar != NULLCHAR && gameInfo.holdingsSize) { \r
+ // [HGM] superchess: take promotion piece out of holdings\r
+ int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));\r
+ if(WhiteOnMove(forwardMostMove-1)) {\r
+ if(!--boards[forwardMostMove][k][BOARD_WIDTH-2])\r
+ boards[forwardMostMove][k][BOARD_WIDTH-1] = EmptySquare;\r
+ } else {\r
+ if(!--boards[forwardMostMove][BOARD_HEIGHT-1-k][1])\r
+ boards[forwardMostMove][BOARD_HEIGHT-1-k][0] = EmptySquare;\r
+ }\r
+ }\r
+\r
if (gameMode == BeginningOfGame) {\r
if (appData.noChessProgram) {\r
gameMode = EditGame;\r
} else {\r
char buf[MSG_SIZ];\r
gameMode = MachinePlaysBlack;\r
+ StartClocks();\r
SetGameInfo();\r
sprintf(buf, "%s vs. %s", gameInfo.white, gameInfo.black);\r
DisplayTitle(buf);\r
}\r
ModeHighlight();\r
}\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar);\r
/* Relay move to ICS or chess engine */\r
if (appData.icsActive) {\r
if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||\r
gameMode == MachinePlaysBlack)) {\r
SendTimeRemaining(&first, gameMode != MachinePlaysBlack);\r
}\r
- SendMoveToProgram(forwardMostMove-1, &first);\r
if (gameMode != EditGame && gameMode != PlayFromGameFile) {\r
- first.maybeThinking = TRUE;\r
- }\r
+ // [HGM] book: if program might be playing, let it use book\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, FALSE);\r
+ first.maybeThinking = TRUE;\r
+ } else SendMoveToProgram(forwardMostMove-1, &first);\r
if (currentMove == cmailOldMove + 1) {\r
cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE;\r
}\r
default:\r
break;\r
}\r
+\r
+ if(bookHit) { // [HGM] book: simulate book reply\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ programStats.nodes = programStats.depth = programStats.time = \r
+ programStats.score = programStats.got_only_move = 0;\r
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ HandleMachineMove(bookMove, &first);\r
+ }\r
+ return 1;\r
}\r
\r
void\r
to do anything in between, can call this routine the old way. \r
*/\r
ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar);\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", moveType, promoChar);\r
if(moveType != ImpossibleMove)\r
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);\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
SetProgramStats( &stats );\r
}\r
\r
+char *SendMoveToBookUser(int moveNr, ChessProgramState *cps, int initial)\r
+{ // [HGM] book: this routine intercepts moves to simulate book replies\r
+ char *bookHit = NULL;\r
+\r
+ //first determine if the incoming move brings opponent into his book\r
+ if(appData.usePolyglotBook && (cps == &first ? !appData.firstHasOwnBookUCI : !appData.secondHasOwnBookUCI))\r
+ bookHit = ProbeBook(moveNr+1, appData.polyglotBook); // returns move\r
+ if(appData.debugMode) fprintf(debugFP, "book hit = %s\n", bookHit ? bookHit : "(NULL)");\r
+ if(bookHit != NULL && !cps->bookSuspend) {\r
+ // make sure opponent is not going to reply after receiving move to book position\r
+ SendToProgram("force\n", cps);\r
+ cps->bookSuspend = TRUE; // flag indicating it has to be restarted\r
+ }\r
+ if(!initial) SendMoveToProgram(moveNr, cps); // with hit on initial position there is no move\r
+ // now arrange restart after book miss\r
+ if(bookHit) {\r
+ // after a book hit we never send 'go', and the code after the call to this routine\r
+ // has '&& !bookHit' added to suppress potential sending there (based on 'firstMove').\r
+ char buf[MSG_SIZ];\r
+ if (cps->useUsermove) sprintf(buf, "usermove "); // sorry, no SAN yet :(\r
+ sprintf(buf, "%s\n", bookHit); // force book move into program supposed to play it\r
+ SendToProgram(buf, cps);\r
+ if(!initial) firstMove = FALSE; // normally we would clear the firstMove condition after return & sending 'go'\r
+ } else if(initial) { // 'go' was needed irrespective of firstMove, and it has to be done in this routine\r
+ SendToProgram("go\n", cps);\r
+ cps->bookSuspend = FALSE; // after a 'go' we are never suspended\r
+ } else { // 'go' might be sent based on 'firstMove' after this routine returns\r
+ if(cps->bookSuspend && !firstMove) // 'go' needed, and it will not be done after we return\r
+ SendToProgram("go\n", cps); \r
+ cps->bookSuspend = FALSE; // anyhow, we will not be suspended after a miss\r
+ }\r
+ return bookHit; // notify caller of hit, so it can take action to send move to opponent\r
+}\r
+\r
+char *savedMessage;\r
+ChessProgramState *savedState;\r
+void DeferredBookMove(void)\r
+{\r
+ if(savedState->lastPing != savedState->lastPong)\r
+ ScheduleDelayedEvent(DeferredBookMove, 10);\r
+ else\r
+ HandleMachineMove(savedMessage, savedState);\r
+}\r
+\r
void\r
HandleMachineMove(message, cps)\r
char *message;\r
char promoChar;\r
char *p;\r
int machineWhite;\r
+ char *bookHit;\r
\r
+FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book hit\r
/*\r
* Kludge to ignore BEL characters\r
*/\r
fprintf(debugFP, "machine move %d, castling = %d %d %d %d %d %d\n", f,\r
castlingRights[f][0],castlingRights[f][1],castlingRights[f][2],castlingRights[f][3],castlingRights[f][4],castlingRights[f][5]);\r
}\r
- AlphaRank(machineMove, 4);\r
+ if(cps->alphaRank) AlphaRank(machineMove, 4);\r
if (!ParseOneMove(machineMove, forwardMostMove, &moveType,\r
&fromX, &fromY, &toX, &toY, &promoChar)) {\r
/* Machine move could not be parsed; ignore it. */\r
- sprintf(buf1, "Illegal move \"%s\" from %s machine",\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
first.initDone) {\r
SendMoveToICS(moveType, fromX, fromY, toX, toY);\r
ics_user_moved = 1;\r
- if(appData.autoKibitz) { /* [HGM] kibitz: send most-recent PV info to ICS */\r
+ if(appData.autoKibitz && !appData.icsEngineAnalyze ) { /* [HGM] kibitz: send most-recent PV info to ICS */\r
char buf[3*MSG_SIZ];\r
\r
sprintf(buf, "kibitz %d/%+.2f (%.2f sec, %.0f nodes, %1.0f knps) PV = %s\n",\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
}\r
}\r
\r
-#ifdef ADJUDICATE // [HGM] some adjudications useful with buggy engines\r
-\r
- if( gameMode == TwoMachinesPlay && gameInfo.holdingsSize == 0) {\r
- int count = 0, epFile = epStatus[forwardMostMove];\r
+ if( gameMode == TwoMachinesPlay ) {\r
+ // [HGM] some adjudications useful with buggy engines\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 && appData.checkMates) \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
default:\r
break;\r
case MT_STALEMATE:\r
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
- GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate",\r
- GE_XBOARD );\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
+ GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate",\r
+ GE_XBOARD );\r
+ }\r
break;\r
case MT_CHECKMATE:\r
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
- GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins, \r
- "Xboard adjudication: Checkmate", \r
- GE_XBOARD );\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) ? BlackWins : WhiteWins, \r
+ "Xboard adjudication: Checkmate", \r
+ GE_XBOARD );\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
- NrWQ=0, NrBQ=0, bishopsColor = 0,\r
- NrPieces=0, NrPawns=0, PawnAdvance=0, i, j, k;\r
- static int moveCount;\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;\r
+ static int moveCount = 6;\r
\r
/* First absolutely insufficient mating material. 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
+ 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
- switch((int) p)\r
- { /* count B,N,R and other of each side */\r
+ switch((int) p)\r
+ { /* count B,N,R and other of each side */\r
case WhiteKnight:\r
NrWN++; break;\r
case WhiteBishop:\r
+ case WhiteFerz: // [HGM] shatranj: kludge to mke it work in shatranj\r
bishopsColor |= 1 << ((i^j)&1);\r
NrWB++; break;\r
case BlackKnight:\r
NrBN++; break;\r
case BlackBishop:\r
+ case BlackFerz: // [HGM] shatranj: kludge to mke it work in shatranj\r
bishopsColor |= 1 << ((i^j)&1);\r
NrBB++; break;\r
case WhiteRook:\r
PawnAdvance += m; NrPawns++;\r
}\r
NrPieces += (p != EmptySquare);\r
+ NrW += ((int)p < (int)BlackPawn);\r
+ if(gameInfo.variant == VariantXiangqi && \r
+ (p == WhiteFerz || p == WhiteAlfil || p == BlackFerz || p == BlackAlfil)) {\r
+ NrPieces--; // [HGM] XQ: do not count purely defensive pieces\r
+ NrW -= ((int)p < (int)BlackPawn);\r
+ }\r
}\r
\r
- if( NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 || NrPieces == 2\r
- || NrPieces == 4 && NrBB+NrWB==2 && bishopsColor != 3)\r
+ if( NrPieces == 2 || gameInfo.variant != VariantXiangqi &&\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
/* always flag draws, for judging claims */\r
\r
if(appData.materialDraws) {\r
/* but only adjudicate them if adjudication enabled */\r
+ SendToProgram("force\n", cps->other); // suppress reply\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see last move */\r
ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
GameEnds( GameIsDrawn, "Xboard adjudication: Insufficient mating material", GE_XBOARD );\r
return;\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 : NrPiece - NrW > 1 ? BlackWins : GameIsDrawn, \r
+ GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn, \r
"Xboard adjudication: Bare king", GE_XBOARD );\r
return;\r
}\r
) ) {\r
if(--moveCount < 0 && appData.trivialDraws)\r
{ /* if the first 3 moves do not show a tactical win, declare draw */\r
+ SendToProgram("force\n", cps->other); // suppress reply\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: Trivial draw", GE_XBOARD );\r
return;\r
}\r
} else moveCount = 6;\r
-#if 0\r
+ }\r
+ }\r
+#if 1\r
if (appData.debugMode) { int i;\r
fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",\r
forwardMostMove, backwardMostMove, epStatus[backwardMostMove],\r
if( rights == 0 && ++count > appData.drawRepeats-2\r
&& appData.drawRepeats > 1) {\r
/* adjudicate after user-specified nr of repeats */\r
+ SendToProgram("force\n", cps->other); // suppress reply\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 == VariantXiangqi && appData.testLegality) { \r
+ // [HGM] xiangqi: check for forbidden perpetuals\r
+ int m, ourPerpetual = 1, hisPerpetual = 1;\r
+ for(m=forwardMostMove; m>k; m-=2) {\r
+ if(MateTest(boards[m], PosFlags(m), \r
+ EP_NONE, castlingRights[m]) != MT_CHECK)\r
+ ourPerpetual = 0; // the current mover did not always check\r
+ if(MateTest(boards[m-1], PosFlags(m-1), \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
+ return;\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
+ // 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
}\r
epStatus[forwardMostMove] = EP_RULE_DRAW;\r
/* this is used to judge if draw claims are legal */\r
if(appData.ruleMoves > 0 && count >= 2*appData.ruleMoves) {\r
+ SendToProgram("force\n", cps->other); // suppress reply\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: 50-move rule", GE_XBOARD );\r
return;\r
if(epStatus[forwardMostMove] == EP_INSUF_DRAW)\r
p = "Draw claim: insufficient mating material";\r
if( p != NULL ) {\r
+ SendToProgram("force\n", cps->other); // suppress reply\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
GameEnds( GameIsDrawn, p, GE_XBOARD );\r
ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
return;\r
}\r
}\r
\r
- }\r
-\r
\r
- }\r
-#endif\r
- if( appData.adjudicateDrawMoves > 0 && forwardMostMove > (2*appData.adjudicateDrawMoves) ) {\r
- ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+ if( appData.adjudicateDrawMoves > 0 && forwardMostMove > (2*appData.adjudicateDrawMoves) ) {\r
+ SendToProgram("force\n", cps->other); // suppress reply\r
+ SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
+ ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
\r
- GameEnds( GameIsDrawn, "Xboard adjudication: long game", GE_XBOARD );\r
+ GameEnds( GameIsDrawn, "Xboard adjudication: long game", GE_XBOARD );\r
\r
- return;\r
+ return;\r
+ }\r
}\r
\r
+ bookHit = NULL;\r
if (gameMode == TwoMachinesPlay) {\r
/* [HGM] relaying draw offers moved to after reception of move */\r
/* and interpreting offer as claim if it brings draw condition */\r
SendTimeRemaining(cps->other,\r
cps->other->twoMachinesColor[0] == 'w');\r
}\r
- SendMoveToProgram(forwardMostMove-1, cps->other);\r
- if (firstMove) {\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, cps->other, FALSE);\r
+ if (firstMove && !bookHit) {\r
firstMove = FALSE;\r
if (cps->other->useColors) {\r
SendToProgram(cps->other->twoMachinesColor, cps->other);\r
if (gameMode != TwoMachinesPlay)\r
SetUserThinkingEnables();\r
\r
+ // [HGM] book: after book hit opponent has received move and is now in force mode\r
+ // force the book reply into it, and then fake that it outputted this move by jumping\r
+ // back to the beginning of HandleMachineMove, with cps toggled and message set to this move\r
+ if(bookHit) {\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ message = bookMove;\r
+ cps = cps->other;\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->lastPing != cps->lastPong) {\r
+ savedMessage = message; // args for deferred call\r
+ savedState = cps;\r
+ ScheduleDelayedEvent(DeferredBookMove, 10);\r
+ return;\r
+ }\r
+ goto FakeBookMove;\r
+ }\r
+\r
return;\r
}\r
\r
GameEnds(GameUnfinished, "Engine aborts game", GE_XBOARD);\r
\r
if (!ParseFEN(initial_position, &blackPlaysFirst, message + 9)) {\r
- DisplayError("Bad FEN received from engine", 0);\r
+ DisplayError(_("Bad FEN received from engine"), 0);\r
return ;\r
} else {\r
Reset(FALSE, FALSE);\r
cps->analysisSupport = FALSE;\r
cps->analyzing = FALSE;\r
Reset(FALSE, TRUE);\r
- sprintf(buf2, "%s does not support analysis", cps->tidy);\r
+ sprintf(buf2, _("%s does not support analysis"), cps->tidy);\r
DisplayError(buf2, 0);\r
return;\r
}\r
DisplayMove(currentMove-1); /* before DisplayMoveError */\r
SwitchClocks();\r
DisplayBothClocks();\r
- sprintf(buf1, "Illegal move \"%s\" (rejected by %s chess program)",\r
+ sprintf(buf1, _("Illegal move \"%s\" (rejected by %s chess program)"),\r
parseList[currentMove], cps->which);\r
DisplayMoveError(buf1);\r
DrawPosition(FALSE, boards[currentMove]);\r
|| (StrStr(message, "Permission denied") != NULL)) {\r
\r
cps->maybeThinking = FALSE;\r
- sprintf(buf1, "Failed to start %s chess program %s on %s: %s\n",\r
+ sprintf(buf1, _("Failed to start %s chess program %s on %s: %s\n"),\r
cps->which, cps->program, cps->host, message);\r
RemoveInputSource(cps->isr);\r
DisplayFatalError(buf1, 0, 1);\r
(void) CoordsToAlgebraic(boards[forwardMostMove],\r
PosFlags(forwardMostMove), EP_UNKNOWN,\r
fromY, fromX, toY, toX, promoChar, buf1);\r
- sprintf(buf2, "Hint: %s", buf1);\r
+ sprintf(buf2, _("Hint: %s"), buf1);\r
DisplayInformation(buf2);\r
} else {\r
/* Hint move could not be parsed!? */\r
sprintf(buf2,\r
- "Illegal hint move \"%s\"\nfrom %s chess program",\r
+ _("Illegal hint move \"%s\"\nfrom %s chess program"),\r
buf1, cps->which);\r
DisplayError(buf2, 0);\r
}\r
} else if (gameMode == MachinePlaysWhite ||\r
gameMode == MachinePlaysBlack) {\r
if (userOfferedDraw) {\r
- DisplayInformation("Machine accepts your draw offer");\r
+ DisplayInformation(_("Machine accepts your draw offer"));\r
GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD);\r
} else {\r
- DisplayInformation("Machine offers a draw\nSelect Action / Draw to agree");\r
+ DisplayInformation(_("Machine offers a draw\nSelect Action / Draw to agree"));\r
}\r
}\r
}\r
/*\r
* Look for thinking output\r
*/\r
- if ( appData.showThinking) {\r
+ if ( appData.showThinking // [HGM] thinking: test all options that cause this output\r
+ || !appData.hideThinkingFromHuman || appData.adjudicateLossThreshold != 0 || EngineOutputIsUp()\r
+ ) {\r
int plylev, mvleft, mvtot, curscore, time;\r
char mvname[MOVE_LEN];\r
- unsigned long nodes;\r
+ u64 nodes; // [DM]\r
char plyext;\r
int ignore = FALSE;\r
int prefixHint = FALSE;\r
break;\r
case AnalyzeMode:\r
case AnalyzeFile:\r
+ break;\r
+ case IcsObserving: /* [DM] icsEngineAnalyze */\r
+ if (!appData.icsEngineAnalyze) ignore = TRUE;\r
break;\r
case TwoMachinesPlay:\r
if ((cps->twoMachinesColor[0] == 'w') != WhiteOnMove(forwardMostMove)) {\r
\r
if (!ignore) {\r
buf1[0] = NULLCHAR;\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
if (plyext != ' ' && plyext != '\t') {\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
strcat( thinkOutput, buf1 );\r
}\r
\r
- if (currentMove == forwardMostMove || gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
+ if (currentMove == forwardMostMove || gameMode == AnalyzeMode\r
+ || gameMode == AnalyzeFile || appData.icsEngineAnalyze) {\r
DisplayMove(currentMove - 1);\r
DisplayAnalysis();\r
}\r
\r
SendProgramStatsToFrontend( cps, &programStats );\r
\r
- if (currentMove == forwardMostMove || gameMode==AnalyzeMode || gameMode == AnalyzeFile) {\r
+ if (currentMove == forwardMostMove || gameMode==AnalyzeMode || \r
+ gameMode == AnalyzeFile || appData.icsEngineAnalyze) {\r
DisplayMove(currentMove - 1);\r
DisplayAnalysis();\r
}\r
return;\r
- } else if (sscanf(message,"stat01: %d %lu %d %d %d %s",\r
+ } else if (sscanf(message,"stat01: %d " u64Display " %d %d %d %s",\r
&time, &nodes, &plylev, &mvleft,\r
&mvtot, mvname) >= 5) {\r
/* The stat01: line is from Crafty (9.29+) in response\r
strcat(programStats.movelist, p);\r
}\r
\r
- if (currentMove == forwardMostMove || gameMode==AnalyzeMode || gameMode == AnalyzeFile) {\r
+ if (currentMove == forwardMostMove || gameMode==AnalyzeMode ||\r
+ gameMode == AnalyzeFile || appData.icsEngineAnalyze) {\r
DisplayMove(currentMove - 1);\r
DisplayAnalysis();\r
}\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
break;\r
case AmbiguousMove:\r
/* bug? */\r
- sprintf(buf, "Ambiguous move in ICS output: \"%s\"", yy_text);\r
+ sprintf(buf, _("Ambiguous move in ICS output: \"%s\""), yy_text);\r
if (appData.debugMode) {\r
fprintf(debugFP, "Ambiguous move from ICS: '%s'\n", yy_text);\r
fprintf(debugFP, "board L=%d, R=%d, H=%d, holdings=%d\n", BOARD_LEFT, BOARD_RGHT, BOARD_HEIGHT, gameInfo.holdingsWidth);\r
return;\r
case ImpossibleMove:\r
/* bug? */\r
- sprintf(buf, "Illegal move in ICS output: \"%s\"", yy_text);\r
+ sprintf(buf, _("Illegal move in ICS output: \"%s\""), yy_text);\r
if (appData.debugMode) {\r
fprintf(debugFP, "Impossible move from ICS: '%s'\n", yy_text);\r
fprintf(debugFP, "board L=%d, R=%d, H=%d, holdings=%d\n", BOARD_LEFT, BOARD_RGHT, BOARD_HEIGHT, gameInfo.holdingsWidth);\r
case (ChessMove) 0: /* end of file */\r
if (boardIndex < backwardMostMove) {\r
/* Oops, gap. How did that happen? */\r
- DisplayError("Gap in move list", 0);\r
+ DisplayError(_("Gap in move list"), 0);\r
return;\r
}\r
backwardMostMove = blackPlaysFirst ? 1 : 0;\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
epStatus[p] = EP_CAPTURE; \r
\r
if( board[fromY][fromX] == WhitePawn ) {\r
- epStatus[p] = EP_PAWN_MOVE; \r
- if( toY-fromY==2)\r
+ if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers\r
+ epStatus[p] = EP_PAWN_MOVE;\r
+ if( toY-fromY==2) {\r
if(toX>BOARD_LEFT && board[toY][toX-1] == BlackPawn &&\r
gameInfo.variant != VariantBerolina || toX < fromX)\r
epStatus[p] = toX | berolina;\r
if(toX<BOARD_RGHT-1 && board[toY][toX+1] == BlackPawn &&\r
gameInfo.variant != VariantBerolina || toX > fromX) \r
epStatus[p] = toX;\r
+ }\r
} else \r
if( board[fromY][fromX] == BlackPawn ) {\r
- epStatus[p] = EP_PAWN_MOVE; \r
- if( toY-fromY== -2)\r
+ if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers\r
+ epStatus[p] = EP_PAWN_MOVE; \r
+ if( toY-fromY== -2) {\r
if(toX>BOARD_LEFT && board[toY][toX-1] == WhitePawn &&\r
gameInfo.variant != VariantBerolina || toX < fromX)\r
epStatus[p] = toX | berolina;\r
if(toX<BOARD_RGHT-1 && board[toY][toX+1] == WhitePawn &&\r
gameInfo.variant != VariantBerolina || toX > fromX) \r
epStatus[p] = toX;\r
+ }\r
}\r
\r
for(i=0; i<nrCastlingRights; i++) {\r
}\r
if (captured != EmptySquare && gameInfo.holdingsSize > 0\r
&& gameInfo.variant != VariantBughouse ) {\r
- /* Add to holdings, if holdings exist */\r
+ /* [HGM] holdings: Add to holdings, if holdings exist */\r
+ if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { \r
+ // [HGM] superchess: suppress flipping color of captured pieces by reverse pre-flip\r
+ captured = (int) captured >= (int) BlackPawn ? BLACK_TO_WHITE captured : WHITE_TO_BLACK captured;\r
+ }\r
p = (int) captured;\r
if (p >= (int) BlackPawn) {\r
p -= (int)BlackPawn;\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
- BLACK_TO_WHITE captured;\r
+ board[p][BOARD_WIDTH-1] = BLACK_TO_WHITE captured;\r
} else {\r
p -= (int)WhitePawn;\r
if(gameInfo.variant == VariantShogi && DEMOTED p >= 0) {\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
- WHITE_TO_BLACK captured;\r
+ board[BOARD_HEIGHT-1-p][0] = WHITE_TO_BLACK captured;\r
}\r
}\r
\r
int fromX, fromY, toX, toY;\r
int promoChar;\r
{\r
- forwardMostMove++;\r
+// forwardMostMove++; // [HGM] bare: moved downstream\r
\r
- if(serverMoves != NULL) { /* [HGM] write moves on file for broadcasting */\r
+ if(serverMoves != NULL) { /* [HGM] write moves on file for broadcasting (should be separate routine, really) */\r
int timeLeft; static int lastLoadFlag=0; int king, piece;\r
- piece = boards[forwardMostMove-1][fromY][fromX];\r
+ piece = boards[forwardMostMove][fromY][fromX];\r
king = piece < (int) BlackPawn ? WhiteKing : BlackKing;\r
if(gameInfo.variant == VariantKnightmate)\r
king += (int) WhiteUnicorn - (int) WhiteKing;\r
- if(forwardMostMove == 1) {\r
+ if(forwardMostMove == 0) {\r
if(blackPlaysFirst) \r
fprintf(serverMoves, "%s;", second.tidy);\r
fprintf(serverMoves, "%s;", first.tidy);\r
fprintf(serverMoves, ":%c%c:%c%c", AAA+BOARD_LEFT, ONE+fromY, AAA+toX+1,ONE+toY);\r
}\r
// e.p. suffix\r
- if( (boards[forwardMostMove-1][fromY][fromX] == WhitePawn ||\r
- boards[forwardMostMove-1][fromY][fromX] == BlackPawn ) &&\r
- boards[forwardMostMove-1][toY][toX] == EmptySquare\r
+ if( (boards[forwardMostMove][fromY][fromX] == WhitePawn ||\r
+ boards[forwardMostMove][fromY][fromX] == BlackPawn ) &&\r
+ boards[forwardMostMove][toY][toX] == EmptySquare\r
&& fromX != toX )\r
fprintf(serverMoves, ":%c%c:%c%c", AAA+fromX, ONE+fromY, AAA+toX, ONE+fromY);\r
// promotion suffix\r
fprintf(serverMoves, ":%c:%c%c", promoChar, AAA+toX, ONE+toY);\r
if(!loadFlag) {\r
fprintf(serverMoves, "/%d/%d",\r
- pvInfoList[forwardMostMove-1].depth, pvInfoList[forwardMostMove-1].score);\r
- if(forwardMostMove & 1) timeLeft = whiteTimeRemaining/1000;\r
- else timeLeft = blackTimeRemaining/1000;\r
+ pvInfoList[forwardMostMove].depth, pvInfoList[forwardMostMove].score);\r
+ if(forwardMostMove+1 & 1) timeLeft = whiteTimeRemaining/1000;\r
+ else timeLeft = blackTimeRemaining/1000;\r
fprintf(serverMoves, "/%d", timeLeft);\r
}\r
fflush(serverMoves);\r
}\r
\r
- if (forwardMostMove >= MAX_MOVES) {\r
- DisplayFatalError("Game too long; increase MAX_MOVES and recompile",\r
+ if (forwardMostMove+1 >= MAX_MOVES) {\r
+ DisplayFatalError(_("Game too long; increase MAX_MOVES and recompile"),\r
0, 1);\r
return;\r
}\r
SwitchClocks();\r
- timeRemaining[0][forwardMostMove] = whiteTimeRemaining;\r
- timeRemaining[1][forwardMostMove] = blackTimeRemaining;\r
- if (commentList[forwardMostMove] != NULL) {\r
- free(commentList[forwardMostMove]);\r
- commentList[forwardMostMove] = NULL;\r
- }\r
- CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]);\r
- ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove]);\r
+ timeRemaining[0][forwardMostMove+1] = whiteTimeRemaining;\r
+ timeRemaining[1][forwardMostMove+1] = blackTimeRemaining;\r
+ if (commentList[forwardMostMove+1] != NULL) {\r
+ free(commentList[forwardMostMove+1]);\r
+ commentList[forwardMostMove+1] = NULL;\r
+ }\r
+ CopyBoard(boards[forwardMostMove+1], boards[forwardMostMove]);\r
+ ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove+1]);\r
+ forwardMostMove++; // [HGM] bare: moved to after ApplyMove, to make sure clock interrupt finds complete board\r
gameInfo.result = GameUnfinished;\r
if (gameInfo.resultDetails != NULL) {\r
free(gameInfo.resultDetails);\r
{\r
int instant = (gameMode == PlayFromGameFile) ?\r
(matchMode || (appData.timeDelay == 0 && !pausing)) : pausing;\r
+ if(appData.noGUI) return;\r
if (!pausing || gameMode == PlayFromGameFile || gameMode == AnalyzeFile) {\r
if (!instant) {\r
if (forwardMostMove == currentMove + 1) {\r
HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);\r
}\r
\r
+void SendEgtPath(ChessProgramState *cps)\r
+{ /* [HGM] EGT: match formats given in feature with those given by user, and send info for each match */\r
+ char buf[MSG_SIZ], name[MSG_SIZ], *p;\r
+\r
+ if((p = cps->egtFormats) == NULL || appData.egtFormats == NULL) return;\r
+\r
+ while(*p) {\r
+ char c, *q = name+1, *r, *s;\r
+\r
+ name[0] = ','; // extract next format name from feature and copy with prefixed ','\r
+ while(*p && *p != ',') *q++ = *p++;\r
+ *q++ = ':'; *q = 0;\r
+ if( appData.defaultPathEGTB && appData.defaultPathEGTB[0] && \r
+ strcmp(name, ",nalimov:") == 0 ) {\r
+ // take nalimov path from the menu-changeable option first, if it is defined\r
+ sprintf(buf, "egtpath nalimov %s\n", appData.defaultPathEGTB);\r
+ SendToProgram(buf,cps); // send egtbpath command for nalimov\r
+ } else\r
+ if( (s = StrStr(appData.egtFormats, name+1)) == appData.egtFormats ||\r
+ (s = StrStr(appData.egtFormats, name)) != NULL) {\r
+ // format name occurs amongst user-supplied formats, at beginning or immediately after comma\r
+ s = r = StrStr(s, ":") + 1; // beginning of path info\r
+ while(*r && *r != ',') r++; // path info is everything upto next ';' or end of string\r
+ c = *r; *r = 0; // temporarily null-terminate path info\r
+ *--q = 0; // strip of trailig ':' from name\r
+ sprintf(buf, "egtbpath %s %s\n", name+1, s);\r
+ *r = c;\r
+ SendToProgram(buf,cps); // send egtbpath command for this format\r
+ }\r
+ if(*p == ',') p++; // read away comma to position for next format name\r
+ }\r
+}\r
\r
void\r
InitChessProgram(cps, setup)\r
if (appData.noChessProgram) return;\r
hintRequested = FALSE;\r
bookRequested = FALSE;\r
+\r
+ /* [HGM] some new WB protocol commands to configure engine are sent now, if engine supports them */\r
+ /* moved to before sending initstring in 4.3.15, so Polyglot can delay UCI 'isready' to recepton of 'new' */\r
+ if(cps->memSize) { /* [HGM] memory */\r
+ sprintf(buf, "memory %d\n", appData.defaultHashSize + appData.defaultCacheSizeEGTB);\r
+ SendToProgram(buf, cps);\r
+ }\r
+ SendEgtPath(cps); /* [HGM] EGT */\r
+ if(cps->maxCores) { /* [HGM] SMP: (protocol specified must be last settings command before new!) */\r
+ sprintf(buf, "cores %d\n", appData.smpCores);\r
+ SendToProgram(buf, cps);\r
+ }\r
+\r
SendToProgram(cps->initString, cps);\r
if (gameInfo.variant != VariantNormal &&\r
gameInfo.variant != VariantLoadable\r
char *v = VariantName(gameInfo.variant);\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
+ sprintf(buf, _("Variant %s not supported by %s"), v, cps->tidy);\r
DisplayFatalError(buf, 0, 1);\r
return;\r
}\r
overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
if( gameInfo.variant == VariantCourier )\r
overruled = gameInfo.boardWidth != 12 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
+ if( gameInfo.variant == VariantSuper )\r
+ overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;\r
+ if( gameInfo.variant == VariantGreat )\r
+ overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;\r
\r
if(overruled) {\r
sprintf(b, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight, \r
timeIncrement, appData.searchDepth,\r
searchTime);\r
}\r
- if (appData.showThinking) {\r
+ if (appData.showThinking \r
+ // [HGM] thinking: four options require thinking output to be sent\r
+ || !appData.hideThinkingFromHuman || appData.adjudicateLossThreshold != 0 || EngineOutputIsUp()\r
+ ) {\r
SendToProgram("post\n", cps);\r
}\r
SendToProgram("hard\n", cps);\r
}\r
\r
if (err != 0) {\r
- sprintf(buf, "Startup failure on '%s'", cps->program);\r
+ sprintf(buf, _("Startup failure on '%s'"), cps->program);\r
DisplayFatalError(buf, err, 1);\r
cps->pr = NoProc;\r
cps->isr = NULL;\r
cps->isr = AddInputSource(cps->pr, TRUE, ReceiveFromProgram, cps);\r
if (cps->protocolVersion > 1) {\r
sprintf(buf, "xboard\nprotover %d\n", cps->protocolVersion);\r
+ cps->nrOptions = 0; // [HGM] options: clear all engine-specific options\r
+ cps->comboCnt = 0; // and values of combo boxes\r
SendToProgram(buf, cps);\r
} else {\r
SendToProgram("xboard\n", cps);\r
TwoMachinesEventIfReady P((void))\r
{\r
if (first.lastPing != first.lastPong) {\r
- DisplayMessage("", "Waiting for first chess program");\r
- ScheduleDelayedEvent(TwoMachinesEventIfReady, 1000);\r
+ DisplayMessage("", _("Waiting for first chess program"));\r
+ ScheduleDelayedEvent(TwoMachinesEventIfReady, 10); // [HGM] fast: lowered from 1000\r
return;\r
}\r
if (second.lastPing != second.lastPong) {\r
- DisplayMessage("", "Waiting for second chess program");\r
- ScheduleDelayedEvent(TwoMachinesEventIfReady, 1000);\r
+ DisplayMessage("", _("Waiting for second chess program"));\r
+ ScheduleDelayedEvent(TwoMachinesEventIfReady, 10); // [HGM] fast: lowered from 1000\r
return;\r
}\r
ThawUI();\r
void\r
NextMatchGame P((void))\r
{\r
+ int index; /* [HGM] autoinc: step lod index during match */\r
Reset(FALSE, TRUE);\r
if (*appData.loadGameFile != NULLCHAR) {\r
+ index = appData.loadGameIndex;\r
+ if(index < 0) { // [HGM] autoinc\r
+ lastIndex = index = (index == -2 && first.twoMachinesColor[0] == 'b') ? lastIndex : lastIndex+1;\r
+ if(appData.rewindIndex > 0 && index > appData.rewindIndex) lastIndex = index = 1;\r
+ } \r
LoadGameFromFile(appData.loadGameFile,\r
- appData.loadGameIndex,\r
+ index,\r
appData.loadGameFile, FALSE);\r
} else if (*appData.loadPositionFile != NULLCHAR) {\r
+ index = appData.loadPositionIndex;\r
+ if(index < 0) { // [HGM] autoinc\r
+ lastIndex = index = (index == -2 && first.twoMachinesColor[0] == 'b') ? lastIndex : lastIndex+1;\r
+ if(appData.rewindIndex > 0 && index > appData.rewindIndex) lastIndex = index = 1;\r
+ } \r
LoadPositionFromFile(appData.loadPositionFile,\r
- appData.loadPositionIndex,\r
+ index,\r
appData.loadPositionFile);\r
}\r
TwoMachinesEventIfReady();\r
if (!isIcsGame || whosays == GE_ICS) {\r
/* OK -- not an ICS game, or ICS said it was done */\r
StopClocks();\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "GameEnds(%d, %s, %d) clock stopped\n",\r
- result, resultDetails ? resultDetails : "(null)", whosays);\r
- }\r
if (!isIcsGame && !appData.noChessProgram) \r
SetUserThinkingEnables();\r
\r
/* [HGM] if a machine claims the game end we verify this claim */\r
- if( appData.testLegality && gameMode == TwoMachinesPlay &&\r
- appData.testClaims && whosays >= GE_ENGINE1 ) {\r
+ if(gameMode == TwoMachinesPlay && appData.testClaims) {\r
+ if(appData.testLegality && whosays >= GE_ENGINE1 ) {\r
char claimer;\r
\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "GameEnds(%d, %s, %d) test claims\n",\r
- result, resultDetails ? resultDetails : "(null)", whosays);\r
- }\r
claimer = whosays == GE_ENGINE1 ? /* color of claimer */\r
first.twoMachinesColor[0] :\r
second.twoMachinesColor[0] ;\r
- if( gameInfo.holdingsWidth == 0 &&\r
+ if( (gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) &&\r
(result == WhiteWins && claimer == 'w' ||\r
result == BlackWins && claimer == 'b' ) ) {\r
- /* Xboard immediately adjudicates all mates, so win claims must be false */\r
- sprintf(buf, "False win claim: '%s'", resultDetails);\r
- result = claimer == 'w' ? BlackWins : WhiteWins;\r
- resultDetails = buf;\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "result=%d sp=%d move=%d\n",\r
+ result, epStatus[forwardMostMove], forwardMostMove);\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
+ sprintf(buf, "False win claim: '%s'", resultDetails);\r
+ result = claimer == 'w' ? BlackWins : WhiteWins;\r
+ resultDetails = buf;\r
+ }\r
} else\r
if( result == GameIsDrawn && epStatus[forwardMostMove] > EP_DRAWS\r
&& (forwardMostMove <= backwardMostMove ||\r
epStatus[forwardMostMove-1] > EP_DRAWS ||\r
(claimer=='b')==(forwardMostMove&1))\r
) {\r
- /* Draw that was not flagged by Xboard is false */\r
+ /* [HGM] verify: draws that were not flagged are false claims */\r
sprintf(buf, "False draw claim: '%s'", resultDetails);\r
result = claimer == 'w' ? BlackWins : WhiteWins;\r
resultDetails = buf;\r
}\r
/* (Claiming a loss is accepted no questions asked!) */\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
+ { 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
+ if(p >= 0 && p <= (int)WhiteKing) k++;\r
+ }\r
+ if (appData.debugMode) {\r
+ fprintf(debugFP, "GE(%d, %s, %d) bare king k=%d color=%d\n",\r
+ result, resultDetails ? resultDetails : "(null)", whosays, k, color);\r
+ }\r
+ if(k <= 1) {\r
+ result = GameIsDrawn;\r
+ sprintf(buf, "%s but bare king", resultDetails);\r
+ resultDetails = buf;\r
+ }\r
+ }\r
}\r
\r
+\r
if(serverMoves != NULL && !loadFlag) { char c = '=';\r
if(result==WhiteWins) c = '+';\r
if(result==BlackWins) c = '-';\r
if(resultDetails != NULL)\r
fprintf(serverMoves, ";%c;%s\n", c, resultDetails);\r
}\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "GameEnds(%d, %s, %d) after test\n",\r
- result, resultDetails ? resultDetails : "(null)", whosays);\r
- }\r
- if (resultDetails != NULL) {\r
+ if (resultDetails != NULL) {\r
gameInfo.result = result;\r
gameInfo.resultDetails = StrSave(resultDetails);\r
\r
}\r
if (matchGame < appData.matchGames) {\r
char *tmp;\r
- tmp = first.twoMachinesColor;\r
- first.twoMachinesColor = second.twoMachinesColor;\r
- second.twoMachinesColor = tmp;\r
+ if(appData.sameColorGames <= 1) { /* [HGM] alternate: suppress color swap */\r
+ tmp = first.twoMachinesColor;\r
+ first.twoMachinesColor = second.twoMachinesColor;\r
+ second.twoMachinesColor = tmp;\r
+ }\r
gameMode = nextGameMode;\r
matchGame++;\r
if(appData.matchPause>10000 || appData.matchPause<10)\r
} else {\r
char buf[MSG_SIZ];\r
gameMode = nextGameMode;\r
- sprintf(buf, "Match %s vs. %s: final score %d-%d-%d",\r
+ sprintf(buf, _("Match %s vs. %s: final score %d-%d-%d"),\r
first.tidy, second.tidy,\r
first.matchWins, second.matchWins,\r
appData.matchGames - (first.matchWins + second.matchWins));\r
timeRemaining[1][currentMove] = blackTimeRemaining;\r
}\r
\r
- if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) &&\r
- first.analysisSupport) {\r
+ if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile ||\r
+ appData.icsEngineAnalyze) && first.analysisSupport) {\r
SendToProgram("analyze\n", &first);\r
first.analyzing = TRUE;\r
}\r
hintRequested = bookRequested = FALSE;\r
first.maybeThinking = FALSE;\r
second.maybeThinking = FALSE;\r
+ first.bookSuspend = FALSE; // [HGM] book\r
+ second.bookSuspend = FALSE;\r
thinkOutput[0] = NULLCHAR;\r
lastHint[0] = NULLCHAR;\r
ClearGameInfo(&gameInfo);\r
ics_gamenum = -1;\r
white_holding[0] = black_holding[0] = NULLCHAR;\r
ClearProgramStats();\r
+ opponentKibitzes = FALSE; // [HGM] kibitz: do not reserve space in engine-output window in zippy mode\r
\r
ResetFrontEnd();\r
ClearHighlights();\r
case BlackPromotionChancellor:\r
case WhitePromotionArchbishop:\r
case BlackPromotionArchbishop:\r
+ case WhitePromotionCentaur:\r
+ case BlackPromotionCentaur:\r
case WhitePromotionQueen:\r
case BlackPromotionQueen:\r
case WhitePromotionRook:\r
if (appData.testLegality) {\r
if (appData.debugMode)\r
fprintf(debugFP, "Parsed IllegalMove: %s\n", yy_text);\r
- sprintf(move, "Illegal move: %d.%s%s",\r
+ sprintf(move, _("Illegal move: %d.%s%s"),\r
(forwardMostMove / 2) + 1,\r
WhiteOnMove(forwardMostMove) ? " " : ".. ", yy_text);\r
DisplayError(move, 0);\r
case AmbiguousMove:\r
if (appData.debugMode)\r
fprintf(debugFP, "Parsed AmbiguousMove: %s\n", yy_text);\r
- sprintf(move, "Ambiguous move: %d.%s%s",\r
+ sprintf(move, _("Ambiguous move: %d.%s%s"),\r
(forwardMostMove / 2) + 1,\r
WhiteOnMove(forwardMostMove) ? " " : ".. ", yy_text);\r
DisplayError(move, 0);\r
default:\r
case ImpossibleMove:\r
if (appData.debugMode)\r
- fprintf(debugFP, "Parsed ImpossibleMove: %s\n", yy_text);\r
- sprintf(move, "Illegal move: %d.%s%s",\r
+ fprintf(debugFP, "Parsed ImpossibleMove (type = %d): %s\n", moveType, yy_text);\r
+ sprintf(move, _("Illegal move: %d.%s%s"),\r
(forwardMostMove / 2) + 1,\r
WhiteOnMove(forwardMostMove) ? " " : ".. ", yy_text);\r
DisplayError(move, 0);\r
} else {\r
f = fopen(filename, "rb");\r
if (f == NULL) {\r
- sprintf(buf, "Can't open \"%s\"", filename);\r
+ sprintf(buf, _("Can't open \"%s\""), filename);\r
DisplayError(buf, errno);\r
return FALSE;\r
}\r
if (useList && n == 0) {\r
int error = GameListBuild(f);\r
if (error) {\r
- DisplayError("Cannot build game list", error);\r
+ DisplayError(_("Cannot build game list"), error);\r
} else if (!ListEmpty(&gameList) &&\r
((ListGame *) gameList.tailPred)->number > 1) {\r
GameListPopUp(f, title);\r
int retVal;\r
\r
if (gameNumber > nCmailGames) {\r
- DisplayError("No more games in this message", 0);\r
+ DisplayError(_("No more games in this message"), 0);\r
return FALSE;\r
}\r
if (f == lastLoadGameFP) {\r
{\r
int gameNumber = lastLoadGameNumber + offset;\r
if (lastLoadGameFP == NULL) {\r
- DisplayError("No game has been loaded yet", 0);\r
+ DisplayError(_("No game has been loaded yet"), 0);\r
return FALSE;\r
}\r
if (gameNumber <= 0) {\r
- DisplayError("Can't back up any further", 0);\r
+ DisplayError(_("Can't back up any further"), 0);\r
return FALSE;\r
}\r
if (cmailMsgLoaded) {\r
gn = 1;\r
}\r
else {\r
- DisplayError("Game number out of range", 0);\r
+ DisplayError(_("Game number out of range"), 0);\r
return FALSE;\r
}\r
} else {\r
gameNumber == 1) {\r
gn = 1;\r
} else {\r
- DisplayError("Can't seek on game file", 0);\r
+ DisplayError(_("Can't seek on game file"), 0);\r
return FALSE;\r
}\r
}\r
nCmailGames = CMAIL_MAX_GAMES - gn;\r
} else {\r
Reset(TRUE, TRUE);\r
- DisplayError("Game not found in file", 0);\r
+ DisplayError(_("Game not found in file"), 0);\r
}\r
return FALSE;\r
\r
startedFromSetupPosition = TRUE;\r
if (!ParseFEN(initial_position, &blackPlaysFirst, gameInfo.fen)) {\r
Reset(TRUE, TRUE);\r
- DisplayError("Bad FEN position in file", 0);\r
+ DisplayError(_("Bad FEN position in file"), 0);\r
return FALSE;\r
}\r
CopyBoard(boards[0], initial_position);\r
- /* [HGM] copy FEN attributes as well */\r
- { int i;\r
- initialRulePlies = FENrulePlies;\r
- epStatus[0] = FENepStatus;\r
- for( i=0; i< nrCastlingRights; i++ )\r
- initialRights[i] = castlingRights[0][i] = FENcastlingRights[i];\r
- }\r
if (blackPlaysFirst) {\r
currentMove = forwardMostMove = backwardMostMove = 1;\r
CopyBoard(boards[1], initial_position);\r
} else {\r
currentMove = forwardMostMove = backwardMostMove = 0;\r
}\r
+ /* [HGM] copy FEN attributes as well. Bugfix 4.3.14m and 4.3.15e: moved to after 'blackPlaysFirst' */\r
+ { int i;\r
+ initialRulePlies = FENrulePlies;\r
+ epStatus[forwardMostMove] = FENepStatus;\r
+ for( i=0; i< nrCastlingRights; i++ )\r
+ initialRights[i] = castlingRights[forwardMostMove][i] = FENcastlingRights[i];\r
+ }\r
yyboardindex = forwardMostMove;\r
free(gameInfo.fen);\r
gameInfo.fen = NULL;\r
if ((cm == (ChessMove) 0 && lastLoadGameStart != (ChessMove) 0) ||\r
cm == WhiteWins || cm == BlackWins ||\r
cm == GameIsDrawn || cm == GameUnfinished) {\r
- DisplayMessage("", "No moves in game");\r
+ DisplayMessage("", _("No moves in game"));\r
if (cmailMsgLoaded) {\r
if (appData.debugMode)\r
fprintf(debugFP, "Setting flipView to %d.\n", FALSE);\r
{\r
int positionNumber = lastLoadPositionNumber + offset;\r
if (lastLoadPositionFP == NULL) {\r
- DisplayError("No position has been loaded yet", 0);\r
+ DisplayError(_("No position has been loaded yet"), 0);\r
return FALSE;\r
}\r
if (positionNumber <= 0) {\r
- DisplayError("Can't back up any further", 0);\r
+ DisplayError(_("Can't back up any further"), 0);\r
return FALSE;\r
}\r
return LoadPosition(lastLoadPositionFP, positionNumber,\r
} else {\r
f = fopen(filename, "rb");\r
if (f == NULL) {\r
- sprintf(buf, "Can't open \"%s\"", filename);\r
+ sprintf(buf, _("Can't open \"%s\""), filename);\r
DisplayError(buf, errno);\r
return FALSE;\r
} else {\r
if (positionNumber < 0) {\r
/* Negative position number means to seek to that byte offset */\r
if (fseek(f, -positionNumber, 0) == -1) {\r
- DisplayError("Can't seek on position file", 0);\r
+ DisplayError(_("Can't seek on position file"), 0);\r
return FALSE;\r
};\r
pn = 1;\r
positionNumber == 1) {\r
pn = 1;\r
} else {\r
- DisplayError("Can't seek on position file", 0);\r
+ DisplayError(_("Can't seek on position file"), 0);\r
return FALSE;\r
}\r
}\r
}\r
/* See if this file is FEN or old-style xboard */\r
if (fgets(line, MSG_SIZ, f) == NULL) {\r
- DisplayError("Position not found in file", 0);\r
+ DisplayError(_("Position not found in file"), 0);\r
return FALSE;\r
}\r
#if 0\r
if (pn >= 2) {\r
if (fenMode || line[0] == '#') pn--;\r
while (pn > 0) {\r
- /* skip postions before number pn */\r
+ /* skip positions before number pn */\r
if (fgets(line, MSG_SIZ, f) == NULL) {\r
Reset(TRUE, TRUE);\r
- DisplayError("Position not found in file", 0);\r
+ DisplayError(_("Position not found in file"), 0);\r
return FALSE;\r
}\r
if (fenMode || line[0] == '#') pn--;\r
\r
if (fenMode) {\r
if (!ParseFEN(initial_position, &blackPlaysFirst, line)) {\r
- DisplayError("Bad FEN position in file", 0);\r
+ DisplayError(_("Bad FEN position in file"), 0);\r
return FALSE;\r
}\r
} else {\r
\r
SendToProgram("force\n", &first);\r
CopyBoard(boards[0], initial_position);\r
- /* [HGM] copy FEN attributes as well */\r
- { int i;\r
- initialRulePlies = FENrulePlies;\r
- epStatus[0] = FENepStatus;\r
- for( i=0; i< nrCastlingRights; i++ )\r
- castlingRights[0][i] = FENcastlingRights[i];\r
- }\r
if (blackPlaysFirst) {\r
currentMove = forwardMostMove = backwardMostMove = 1;\r
strcpy(moveList[0], "");\r
strcpy(parseList[0], "");\r
CopyBoard(boards[1], initial_position);\r
- DisplayMessage("", "Black to play");\r
+ DisplayMessage("", _("Black to play"));\r
} else {\r
currentMove = forwardMostMove = backwardMostMove = 0;\r
- DisplayMessage("", "White to play");\r
+ DisplayMessage("", _("White to play"));\r
}\r
+ /* [HGM] copy FEN attributes as well */\r
+ { int i;\r
+ initialRulePlies = FENrulePlies;\r
+ epStatus[forwardMostMove] = FENepStatus;\r
+ for( i=0; i< nrCastlingRights; i++ )\r
+ castlingRights[forwardMostMove][i] = FENcastlingRights[i];\r
+ }\r
SendBoard(&first, forwardMostMove);\r
if (appData.debugMode) {\r
+int i, j;\r
+ for(i=0;i<2;i++){for(j=0;j<6;j++)fprintf(debugFP, " %d", castlingRights[i][j]);fprintf(debugFP,"\n");}\r
+ for(j=0;j<6;j++)fprintf(debugFP, " %d", initialRights[j]);fprintf(debugFP,"\n");\r
fprintf(debugFP, "Load Position\n");\r
}\r
\r
} else {\r
f = fopen(filename, append ? "a" : "w");\r
if (f == NULL) {\r
- sprintf(buf, "Can't open \"%s\"", filename);\r
+ sprintf(buf, _("Can't open \"%s\""), filename);\r
DisplayError(buf, errno);\r
return FALSE;\r
} else {\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
linelen += numlen;\r
\r
/* Get move */\r
- movetext = SavePart(parseList[i]);\r
+ movelen = strlen(parseList[i]); /* [HGM] pgn: line-break point before move */\r
+\r
+ /* Print move */\r
+ blank = linelen > 0 && movelen > 0;\r
+ if (linelen + (blank ? 1 : 0) + movelen > PGN_MAX_LINE) {\r
+ fprintf(f, "\n");\r
+ linelen = 0;\r
+ blank = 0;\r
+ }\r
+ if (blank) {\r
+ fprintf(f, " ");\r
+ linelen++;\r
+ }\r
+ fprintf(f, parseList[i]);\r
+ linelen += movelen;\r
\r
/* [AS] Add PV info if present */\r
if( i >= 0 && appData.saveExtendedInfoInPGN && pvInfoList[i].depth > 0 ) {\r
\r
#if 0\r
if(i >= backwardMostMove) {\r
- /* take the time that changed */\r
- seconds = timeRemaining[0][i] - timeRemaining[0][i+1];\r
- if(seconds <= 0)\r
- seconds = timeRemaining[1][i] - timeRemaining[1][i+1];\r
+ if(WhiteOnMove(i))\r
+ seconds = timeRemaining[0][i] - timeRemaining[0][i+1]\r
+ + GetTimeQuota(i/2) / WhitePlayer()->timeOdds;\r
+ else\r
+ seconds = timeRemaining[1][i] - timeRemaining[1][i+1]\r
+ + GetTimeQuota(i/2) / WhitePlayer()->other->timeOdds;\r
}\r
- seconds /= 1000;\r
+ seconds = (seconds+50)/100; // deci-seconds, rounded to nearest\r
+#else\r
+ seconds = (pvInfoList[i].time + 5)/10; // [HGM] PVtime: use engine time\r
#endif\r
- seconds = pvInfoList[i].time/100; // [HGM] PVtime: use engine time\r
- if (appData.debugMode) {\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 < 60 ) sprintf(buf, " %d%c", seconds, 0);\r
- else sprintf(buf, " %d:%02d%c", seconds/60, seconds%60, 0);\r
+ if( seconds <= 0) buf[0] = 0; else\r
+ if( seconds < 30 ) sprintf(buf, " %3.1f%c", seconds/10., 0); else {\r
+ seconds = (seconds + 4)/10; // round to full seconds\r
+ if( seconds < 60 ) sprintf(buf, " %d%c", seconds, 0); else\r
+ sprintf(buf, " %d:%02d%c", seconds/60, seconds%60, 0);\r
+ }\r
\r
- sprintf( move_buffer, "%s {%s%.2f/%d%s}", \r
- movetext, \r
+ sprintf( move_buffer, "{%s%.2f/%d%s}", \r
pvInfoList[i].score >= 0 ? "+" : "",\r
pvInfoList[i].score / 100.0,\r
pvInfoList[i].depth,\r
- buf );\r
- movetext = move_buffer;\r
- }\r
+ buf );\r
\r
- movelen = strlen(movetext);\r
+ movelen = strlen(move_buffer); /* [HGM] pgn: line-break point after move */\r
\r
- /* Print move */\r
- blank = linelen > 0 && movelen > 0;\r
- if (linelen + (blank ? 1 : 0) + movelen > PGN_MAX_LINE) {\r
- fprintf(f, "\n");\r
- linelen = 0;\r
- blank = 0;\r
- }\r
- if (blank) {\r
- fprintf(f, " ");\r
- linelen++;\r
- }\r
- fprintf(f, movetext);\r
- linelen += movelen;\r
+ /* Print score/depth */\r
+ blank = linelen > 0 && movelen > 0;\r
+ if (linelen + (blank ? 1 : 0) + movelen > PGN_MAX_LINE) {\r
+ fprintf(f, "\n");\r
+ linelen = 0;\r
+ blank = 0;\r
+ }\r
+ if (blank) {\r
+ fprintf(f, " ");\r
+ linelen++;\r
+ }\r
+ fprintf(f, move_buffer);\r
+ linelen += movelen;\r
+ }\r
\r
i++;\r
}\r
} else {\r
f = fopen(filename, "a");\r
if (f == NULL) {\r
- sprintf(buf, "Can't open \"%s\"", filename);\r
+ sprintf(buf, _("Can't open \"%s\""), filename);\r
DisplayError(buf, errno);\r
return FALSE;\r
} else {\r
}\r
\r
if (cmailOldMove == -1) {\r
- DisplayError("You have edited the game history.\nUse Reload Same Game and make your move again.", 0);\r
+ DisplayError(_("You have edited the game history.\nUse Reload Same Game and make your move again."), 0);\r
return FALSE;\r
}\r
\r
if (currentMove > cmailOldMove + 1) {\r
- DisplayError("You have entered too many moves.\nBack up to the correct position and try again.", 0);\r
+ DisplayError(_("You have entered too many moves.\nBack up to the correct position and try again."), 0);\r
return FALSE;\r
}\r
\r
if (currentMove < cmailOldMove) {\r
- DisplayError("Displayed position is not current.\nStep forward to the correct position and try again.", 0);\r
+ DisplayError(_("Displayed position is not current.\nStep forward to the correct position and try again."), 0);\r
return FALSE;\r
}\r
\r
cmailMoveRegistered[lastLoadGameNumber - 1] = TRUE;\r
nCmailMovesRegistered ++;\r
} else if (nCmailGames == 1) {\r
- DisplayError("You have not made a move yet", 0);\r
+ DisplayError(_("You have not made a move yet"), 0);\r
return FALSE;\r
}\r
\r
char *arcDir;\r
\r
if (! cmailMsgLoaded) {\r
- DisplayError("The cmail message is not loaded.\nUse Reload CMail Message and make your move again.", 0);\r
+ DisplayError(_("The cmail message is not loaded.\nUse Reload CMail Message and make your move again."), 0);\r
return;\r
}\r
\r
if (nCmailGames == nCmailResults) {\r
- DisplayError("No unfinished games", 0);\r
+ DisplayError(_("No unfinished games"), 0);\r
return;\r
}\r
\r
#if CMAIL_PROHIBIT_REMAIL\r
if (cmailMailedMove) {\r
- sprintf(msg, "You have already mailed a move.\nWait until a move arrives from your opponent.\nTo resend the same move, type\n\"cmail -remail -game %s\"\non the command line.", appData.cmailGameName);\r
+ sprintf(msg, _("You have already mailed a move.\nWait until a move arrives from your opponent.\nTo resend the same move, type\n\"cmail -remail -game %s\"\non the command line."), appData.cmailGameName);\r
DisplayError(msg, 0);\r
return;\r
}\r
|| (nCmailMovesRegistered + nCmailResults == nCmailGames)) {\r
sprintf(string, partCommandString,\r
appData.debugMode ? " -v" : "", appData.cmailGameName);\r
- commandOutput = popen(string, "rb");\r
+ commandOutput = popen(string, "r");\r
\r
if (commandOutput == NULL) {\r
- DisplayError("Failed to invoke cmail", 0);\r
+ DisplayError(_("Failed to invoke cmail"), 0);\r
} else {\r
for (nBuffers = 0; (! feof(commandOutput)); nBuffers ++) {\r
nBytes = fread(buffer, 1, MSG_SIZ - 1, commandOutput);\r
if (!cmailMsgLoaded) return "";\r
\r
if (cmailMailedMove) {\r
- sprintf(cmailMsg, "Waiting for reply from opponent\n");\r
+ sprintf(cmailMsg, _("Waiting for reply from opponent\n"));\r
} else {\r
/* Create a list of games left */\r
sprintf(string, "[");\r
switch (nCmailGames) {\r
case 1:\r
sprintf(cmailMsg,\r
- "Still need to make move for game\n");\r
+ _("Still need to make move for game\n"));\r
break;\r
\r
case 2:\r
sprintf(cmailMsg,\r
- "Still need to make moves for both games\n");\r
+ _("Still need to make moves for both games\n"));\r
break;\r
\r
default:\r
sprintf(cmailMsg,\r
- "Still need to make moves for all %d games\n",\r
+ _("Still need to make moves for all %d games\n"),\r
nCmailGames);\r
break;\r
}\r
switch (nCmailGames - nCmailMovesRegistered - nCmailResults) {\r
case 1:\r
sprintf(cmailMsg,\r
- "Still need to make a move for game %s\n",\r
+ _("Still need to make a move for game %s\n"),\r
string);\r
break;\r
\r
case 0:\r
if (nCmailResults == nCmailGames) {\r
- sprintf(cmailMsg, "No unfinished games\n");\r
+ sprintf(cmailMsg, _("No unfinished games\n"));\r
} else {\r
- sprintf(cmailMsg, "Ready to send mail\n");\r
+ sprintf(cmailMsg, _("Ready to send mail\n"));\r
}\r
break;\r
\r
default:\r
sprintf(cmailMsg,\r
- "Still need to make moves for games %s\n",\r
+ _("Still need to make moves for games %s\n"),\r
string);\r
}\r
}\r
GameEnds((ChessMove) 0, NULL, GE_PLAYER);\r
#else\r
/* [HGM] crash: leave writing PGN and position entirely to GameEnds() */\r
- GameEnds(gameInfo.result, gameInfo.resultDetails==NULL ? "aborted" : gameInfo.resultDetails, GE_PLAYER);\r
+ GameEnds(gameInfo.result, gameInfo.resultDetails==NULL ? "xboard exit" : gameInfo.resultDetails, GE_PLAYER);\r
#endif\r
/* [HGM] crash: the above GameEnds() is a dud if another one was running */\r
/* make sure this other one finishes before killing it! */\r
char title[MSG_SIZ];\r
\r
if (currentMove < 1 || parseList[currentMove - 1][0] == NULLCHAR) {\r
- strcpy(title, "Edit comment");\r
+ strcpy(title, _("Edit comment"));\r
} else {\r
- sprintf(title, "Edit comment on %d.%s%s", (currentMove - 1) / 2 + 1,\r
+ sprintf(title, _("Edit comment on %d.%s%s"), (currentMove - 1) / 2 + 1,\r
WhiteOnMove(currentMove - 1) ? " " : ".. ",\r
parseList[currentMove - 1]);\r
}\r
return;\r
\r
if (gameMode != AnalyzeFile) {\r
- EditGameEvent();\r
- if (gameMode != EditGame) return;\r
+ if (!appData.icsEngineAnalyze) {\r
+ EditGameEvent();\r
+ if (gameMode != EditGame) return;\r
+ }\r
ResurrectChessProgram();\r
SendToProgram("analyze\n", &first);\r
first.analyzing = TRUE;\r
/*first.maybeThinking = TRUE;*/\r
first.maybeThinking = FALSE; /* avoid killing GNU Chess */\r
- AnalysisPopUp("Analysis",\r
- "Starting analysis mode...\nIf this message stays up, your chess program does not support analysis.");\r
+ AnalysisPopUp(_("Analysis"),\r
+ _("Starting analysis mode...\nIf this message stays up, your chess program does not support analysis."));\r
}\r
- gameMode = AnalyzeMode;\r
+ if (!appData.icsEngineAnalyze) gameMode = AnalyzeMode;\r
pausing = FALSE;\r
ModeHighlight();\r
SetGameInfo();\r
first.analyzing = TRUE;\r
/*first.maybeThinking = TRUE;*/\r
first.maybeThinking = FALSE; /* avoid killing GNU Chess */\r
- AnalysisPopUp("Analysis",\r
- "Starting analysis mode...\nIf this message stays up, your chess program does not support analysis.");\r
+ AnalysisPopUp(_("Analysis"),\r
+ _("Starting analysis mode...\nIf this message stays up, your chess program does not support analysis."));\r
}\r
gameMode = AnalyzeFile;\r
pausing = FALSE;\r
MachineWhiteEvent()\r
{\r
char buf[MSG_SIZ];\r
+ char *bookHit = NULL;\r
\r
if (appData.noChessProgram || (gameMode == MachinePlaysWhite))\r
return;\r
EditPositionDone();\r
\r
if (!WhiteOnMove(currentMove)) {\r
- DisplayError("It is not White's turn", 0);\r
+ DisplayError(_("It is not White's turn"), 0);\r
return;\r
}\r
\r
TruncateGame();\r
\r
ResurrectChessProgram(); /* in case it isn't running */\r
+ if(gameMode == BeginningOfGame) { /* [HGM] time odds: to get right odds in human mode */\r
+ gameMode = MachinePlaysWhite;\r
+ ResetClocks();\r
+ } else\r
gameMode = MachinePlaysWhite;\r
pausing = FALSE;\r
ModeHighlight();\r
SendTimeRemaining(&first, TRUE);\r
}\r
if (first.useColors) {\r
- SendToProgram("white\ngo\n", &first);\r
- } else {\r
- SendToProgram("go\n", &first);\r
+ SendToProgram("white\n", &first); // [HGM] book: send 'go' separately\r
}\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move\r
SetMachineThinkingEnables();\r
first.maybeThinking = TRUE;\r
StartClocks();\r
if (appData.autoFlipView && !flipView) {\r
flipView = !flipView;\r
DrawPosition(FALSE, NULL);\r
+ DisplayBothClocks(); // [HGM] logo: clocks might have to be exchanged;\r
+ }\r
+\r
+ if(bookHit) { // [HGM] book: simulate book reply\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ programStats.nodes = programStats.depth = programStats.time = \r
+ programStats.score = programStats.got_only_move = 0;\r
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ HandleMachineMove(bookMove, &first);\r
}\r
}\r
\r
MachineBlackEvent()\r
{\r
char buf[MSG_SIZ];\r
+ char *bookHit = NULL;\r
\r
if (appData.noChessProgram || (gameMode == MachinePlaysBlack))\r
return;\r
EditPositionDone();\r
\r
if (WhiteOnMove(currentMove)) {\r
- DisplayError("It is not Black's turn", 0);\r
+ DisplayError(_("It is not Black's turn"), 0);\r
return;\r
}\r
\r
SendTimeRemaining(&first, FALSE);\r
}\r
if (first.useColors) {\r
- SendToProgram("black\ngo\n", &first);\r
- } else {\r
- SendToProgram("go\n", &first);\r
+ SendToProgram("black\n", &first); // [HGM] book: 'go' sent separately\r
}\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move\r
SetMachineThinkingEnables();\r
first.maybeThinking = TRUE;\r
StartClocks();\r
if (appData.autoFlipView && flipView) {\r
flipView = !flipView;\r
DrawPosition(FALSE, NULL);\r
+ DisplayBothClocks(); // [HGM] logo: clocks might have to be exchanged;\r
+ }\r
+ if(bookHit) { // [HGM] book: simulate book reply\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ programStats.nodes = programStats.depth = programStats.time = \r
+ programStats.score = programStats.got_only_move = 0;\r
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ HandleMachineMove(bookMove, &first);\r
}\r
}\r
\r
int i;\r
char buf[MSG_SIZ];\r
ChessProgramState *onmove;\r
+ char *bookHit = NULL;\r
\r
if (appData.noChessProgram) return;\r
\r
case MachinePlaysWhite:\r
case MachinePlaysBlack:\r
if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) {\r
- DisplayError("Wait until your turn,\nor select Move Now", 0);\r
+ DisplayError(_("Wait until your turn,\nor select Move Now"), 0);\r
return;\r
}\r
/* fall through */\r
} else {\r
/* kludge: allow timeout for initial "feature" command */\r
FreezeUI();\r
- DisplayMessage("", "Starting second chess program");\r
+ DisplayMessage("", _("Starting second chess program"));\r
ScheduleDelayedEvent(TwoMachinesEventIfReady, FEATURE_TIMEOUT);\r
}\r
return;\r
SendToProgram(buf, &second);\r
}\r
\r
+ ResetClocks();\r
if (!first.sendTime || !second.sendTime) {\r
- ResetClocks();\r
timeRemaining[0][forwardMostMove] = whiteTimeRemaining;\r
timeRemaining[1][forwardMostMove] = blackTimeRemaining;\r
}\r
if (onmove->useColors) {\r
SendToProgram(onmove->twoMachinesColor, onmove);\r
}\r
- SendToProgram("go\n", onmove);\r
+ bookHit = SendMoveToBookUser(forwardMostMove-1, onmove, TRUE); // [HGM] book: send go or retrieve book move\r
+// SendToProgram("go\n", onmove);\r
onmove->maybeThinking = TRUE;\r
SetMachineThinkingEnables();\r
\r
StartClocks();\r
+\r
+ if(bookHit) { // [HGM] book: simulate book reply\r
+ static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+ programStats.nodes = programStats.depth = programStats.time = \r
+ programStats.score = programStats.got_only_move = 0;\r
+ sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+ strcpy(bookMove, "move ");\r
+ strcat(bookMove, bookHit);\r
+ HandleMachineMove(bookMove, &first);\r
+ }\r
}\r
\r
void\r
if (gameMode == Training) {\r
SetTrainingModeOff();\r
gameMode = PlayFromGameFile;\r
- DisplayMessage("", "Training mode off");\r
+ DisplayMessage("", _("Training mode off"));\r
} else {\r
gameMode = Training;\r
animateTraining = appData.animate;\r
/* make sure we are not already at the end of the game */\r
if (currentMove < forwardMostMove) {\r
SetTrainingModeOn();\r
- DisplayMessage("", "Training mode on");\r
+ DisplayMessage("", _("Training mode on"));\r
} else {\r
gameMode = PlayFromGameFile;\r
- DisplayError("Already at end of game", 0);\r
+ DisplayError(_("Already at end of game"), 0);\r
}\r
}\r
ModeHighlight();\r
break;\r
case IcsPlayingBlack:\r
case IcsPlayingWhite:\r
- DisplayError("Warning: You are still playing a game", 0);\r
+ DisplayError(_("Warning: You are still playing a game"), 0);\r
break;\r
case IcsObserving:\r
- DisplayError("Warning: You are still observing a game", 0);\r
+ DisplayError(_("Warning: You are still observing a game"), 0);\r
break;\r
case IcsExamining:\r
- DisplayError("Warning: You are still examining a game", 0);\r
+ DisplayError(_("Warning: You are still examining a game"), 0);\r
break;\r
case IcsIdle:\r
break;\r
void\r
ExitAnalyzeMode()\r
{\r
+ /* [DM] icsEngineAnalyze - possible call from other functions */\r
+ if (appData.icsEngineAnalyze) {\r
+ appData.icsEngineAnalyze = FALSE;\r
+\r
+ DisplayMessage("",_("Close ICS engine analyze..."));\r
+ }\r
if (first.analysisSupport && first.analyzing) {\r
SendToProgram("exit\n", &first);\r
first.analyzing = FALSE;\r
strcpy(parseList[0], "");\r
currentMove = forwardMostMove = backwardMostMove = 1;\r
CopyBoard(boards[1], boards[0]);\r
+ /* [HGM] copy rights as well, as this code is also used after pasting a FEN */\r
+ { int i;\r
+ epStatus[1] = epStatus[0];\r
+ for(i=0; i<nrCastlingRights; i++) castlingRights[1][i] = castlingRights[0][i];\r
+ }\r
} else {\r
currentMove = forwardMostMove = backwardMostMove = 0;\r
}\r
SendToICS(ics_prefix);\r
SendToICS("clearboard\n");\r
} else {\r
- for (x = 0; x < BOARD_WIDTH; x++) {\r
+ for (x = 0; x < BOARD_WIDTH; x++) { ChessSquare p = EmptySquare;\r
+ if(x == BOARD_LEFT-1 || x == BOARD_RGHT) p = (ChessSquare) 0; /* [HGM] holdings */\r
for (y = 0; y < BOARD_HEIGHT; y++) {\r
if (gameMode == IcsExamining) {\r
if (boards[currentMove][y][x] != EmptySquare) {\r
SendToICS(buf);\r
}\r
} else {\r
- boards[0][y][x] = EmptySquare;\r
+ boards[0][y][x] = p;\r
}\r
}\r
}\r
case IcsPlayingWhite:\r
case MachinePlaysBlack:\r
if (!WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is Black's turn");\r
+ DisplayMoveError(_("It is Black's turn"));\r
return;\r
}\r
moveType = WhiteDrop;\r
case IcsPlayingBlack:\r
case MachinePlaysWhite:\r
if (WhiteOnMove(currentMove)) {\r
- DisplayMoveError("It is White's turn");\r
+ DisplayMoveError(_("It is White's turn"));\r
return;\r
}\r
moveType = BlackDrop;\r
+ (int) BlackPawn - (int) WhitePawn);\r
}\r
if (boards[currentMove][y][x] != EmptySquare) {\r
- DisplayMoveError("That square is occupied");\r
+ DisplayMoveError(_("That square is occupied"));\r
return;\r
}\r
\r
GameEnds(GameIsDrawn, "Draw agreed", GE_PLAYER);\r
cmailMoveType[lastLoadGameNumber - 1] = CMAIL_ACCEPT;\r
} else {\r
- DisplayError("There is no pending offer on this move", 0);\r
+ DisplayError(_("There is no pending offer on this move"), 0);\r
cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE;\r
}\r
} else {\r
DisplayComment(cmailOldMove - 1, "Draw declined");\r
#endif /*NOTDEF*/\r
} else {\r
- DisplayError("There is no pending offer on this move", 0);\r
+ DisplayError(_("There is no pending offer on this move"), 0);\r
}\r
} else {\r
/* Not used for offers from chess program */\r
else\r
GameEnds(BlackWins, "Black wins on time", GE_PLAYER);\r
} else {\r
- DisplayError("Your opponent is not out of time", 0);\r
+ DisplayError(_("Your opponent is not out of time"), 0);\r
}\r
break;\r
case MachinePlaysBlack:\r
else\r
GameEnds(WhiteWins, "White wins on time", GE_PLAYER);\r
} else {\r
- DisplayError("Your opponent is not out of time", 0);\r
+ DisplayError(_("Your opponent is not out of time"), 0);\r
}\r
break;\r
}\r
DisplayComment(currentMove - 1, offer);\r
cmailMoveType[lastLoadGameNumber - 1] = CMAIL_DRAW;\r
} else {\r
- DisplayError("You must make your move before offering a draw", 0);\r
+ DisplayError(_("You must make your move before offering a draw"), 0);\r
cmailMoveType[lastLoadGameNumber - 1] = CMAIL_MOVE;\r
}\r
} else if (first.offeredDraw) {\r
RevertEvent()\r
{\r
if (gameMode != IcsExamining) {\r
- DisplayError("You are not examining a game", 0);\r
+ DisplayError(_("You are not examining a game"), 0);\r
return;\r
}\r
if (pausing) {\r
- DisplayError("You can't revert while pausing", 0);\r
+ DisplayError(_("You can't revert while pausing"), 0);\r
return;\r
}\r
SendToICS(ics_prefix);\r
case MachinePlaysWhite:\r
case MachinePlaysBlack:\r
if (WhiteOnMove(forwardMostMove) == (gameMode == MachinePlaysWhite)) {\r
- DisplayError("Wait until your turn,\nor select Move Now", 0);\r
+ DisplayError(_("Wait until your turn,\nor select Move Now"), 0);\r
return;\r
}\r
if (forwardMostMove < 2) return;\r
switch (gameMode) {\r
case MachinePlaysWhite:\r
if (!WhiteOnMove(forwardMostMove)) {\r
- DisplayError("It is your turn", 0);\r
+ DisplayError(_("It is your turn"), 0);\r
return;\r
}\r
cps = &first;\r
break;\r
case MachinePlaysBlack:\r
if (WhiteOnMove(forwardMostMove)) {\r
- DisplayError("It is your turn", 0);\r
+ DisplayError(_("It is your turn"), 0);\r
return;\r
}\r
cps = &first;\r
switch (gameMode) {\r
case MachinePlaysWhite:\r
if (WhiteOnMove(forwardMostMove)) {\r
- DisplayError("Wait until your turn", 0);\r
+ DisplayError(_("Wait until your turn"), 0);\r
return;\r
}\r
break;\r
case BeginningOfGame:\r
case MachinePlaysBlack:\r
if (!WhiteOnMove(forwardMostMove)) {\r
- DisplayError("Wait until your turn", 0);\r
+ DisplayError(_("Wait until your turn"), 0);\r
return;\r
}\r
break;\r
default:\r
- DisplayError("No hint available", 0);\r
+ DisplayError(_("No hint available"), 0);\r
return;\r
}\r
SendToProgram("hint\n", &first);\r
switch (gameMode) {\r
case MachinePlaysWhite:\r
if (WhiteOnMove(forwardMostMove)) {\r
- DisplayError("Wait until your turn", 0);\r
+ DisplayError(_("Wait until your turn"), 0);\r
return;\r
}\r
break;\r
case BeginningOfGame:\r
case MachinePlaysBlack:\r
if (!WhiteOnMove(forwardMostMove)) {\r
- DisplayError("Wait until your turn", 0);\r
+ DisplayError(_("Wait until your turn"), 0);\r
return;\r
}\r
break;\r
if( text != NULL && index > 0 ) {\r
int score = 0;\r
int depth = 0;\r
- int time = -1, sec = 0;\r
+ int time = -1, sec = 0, deci;\r
char * s_eval = FindStr( text, "[%eval " );\r
char * s_emt = FindStr( text, "[%emt " );\r
\r
return text;\r
}\r
\r
- time = -1; sec = -1;\r
+ time = -1; sec = -1; deci = -1;\r
if( sscanf( text, "%d.%d/%d %d:%d", &score, &score_lo, &depth, &time, &sec ) != 5 &&\r
+ sscanf( text, "%d.%d/%d %d.%d", &score, &score_lo, &depth, &time, &deci ) != 5 &&\r
sscanf( text, "%d.%d/%d %d", &score, &score_lo, &depth, &time ) != 4 &&\r
sscanf( text, "%d.%d/%d", &score, &score_lo, &depth ) != 3 ) {\r
return text;\r
return text;\r
}\r
\r
- if(sec >= 0) time = 60*time + sec;\r
+ if(sec >= 0) time = 600*time + 10*sec; else\r
+ if(deci >= 0) time = 10*time + deci; else time *= 10; // deci-sec\r
+\r
score = score >= 0 ? score*100 + score_lo : score*100 - score_lo;\r
\r
/* [HGM] PV time: now locate end of PV info */\r
while( *++sep >= '0' && *sep <= '9'); // strip time\r
if(sec >= 0)\r
while( *++sep >= '0' && *sep <= '9'); // strip seconds\r
+ if(deci >= 0)\r
+ while( *++sep >= '0' && *sep <= '9'); // strip fractional seconds\r
while(*sep == ' ') sep++;\r
}\r
\r
\r
pvInfoList[index-1].depth = depth;\r
pvInfoList[index-1].score = score;\r
- pvInfoList[index-1].time = time;\r
+ pvInfoList[index-1].time = 10*time; // centi-sec\r
}\r
return sep;\r
}\r
outCount = OutputToProcess(cps->pr, message, count, &error);\r
if (outCount < count && !exiting \r
&& !endingGame) { /* [HGM] crash: to not hang GameEnds() writing to deceased engines */\r
- sprintf(buf, "Error writing to %s chess program", cps->which);\r
+ sprintf(buf, _("Error writing to %s chess program"), cps->which);\r
if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */\r
if(epStatus[forwardMostMove] <= EP_DRAWS) {\r
gameInfo.result = GameIsDrawn; /* [HGM] accept exit as draw claim */\r
if (count <= 0) {\r
if (count == 0) {\r
sprintf(buf,\r
- "Error: %s chess program (%s) exited unexpectedly",\r
+ _("Error: %s chess program (%s) exited unexpectedly"),\r
cps->which, cps->program);\r
if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */\r
if(epStatus[forwardMostMove] <= EP_DRAWS) {\r
gameInfo.result = GameIsDrawn; /* [HGM] accept exit as draw claim */\r
- sprintf(buf, "%s program exits in draw position (%s)", cps->which, cps->program);\r
+ sprintf(buf, _("%s program exits in draw position (%s)"), cps->which, cps->program);\r
} else {\r
gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;\r
}\r
DisplayFatalError(buf, 0, 1);\r
} else {\r
sprintf(buf,\r
- "Error reading from %s chess program (%s)",\r
+ _("Error reading from %s chess program (%s)"),\r
cps->which, cps->program);\r
RemoveInputSource(cps->isr);\r
\r
sscanf(message, "resign%c", &c)!=1 && sscanf(message, "feature %c", &c)!=1 &&\r
sscanf(message, "error %c", &c)!=1 && sscanf(message, "illegal %c", &c)!=1 &&\r
sscanf(message, "tell%c", &c)!=1 && sscanf(message, "0-1 %c", &c)!=1 &&\r
- sscanf(message, "askuser%c", &c)!=1 && sscanf(message, "1-0 %c", &c)!=1 && \r
- sscanf(message, "1/2-1/2 %c", &c)!=1 && start != '#')\r
+ sscanf(message, "1-0 %c", &c)!=1 && sscanf(message, "1/2-1/2 %c", &c)!=1 && start != '#')\r
{ quote = "# "; print = (appData.engineComments == 2); }\r
message[0] = start; // restore original message\r
}\r
message);\r
}\r
}\r
+\r
+ /* [DM] if icsEngineAnalyze is active we block all whisper and kibitz output, because nobody want to see this */\r
+ if (appData.icsEngineAnalyze) {\r
+ if (strstr(message, "whisper") != NULL ||\r
+ strstr(message, "kibitz") != NULL || \r
+ strstr(message, "tellics") != NULL) return;\r
+ }\r
+\r
HandleMachineMove(message, cps);\r
}\r
\r
ChessProgramState *WhitePlayer()\r
/* [HGM] return pointer to 'first' or 'second', depending on who plays white */\r
{\r
- if(gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'b')\r
+ if(gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'b' || \r
+ gameMode == BeginningOfGame || gameMode == MachinePlaysBlack)\r
return &second;\r
return &first;\r
}\r
return FALSE;\r
}\r
\r
+int \r
+ParseOption(Option *opt, ChessProgramState *cps)\r
+// [HGM] options: process the string that defines an engine option, and determine\r
+// name, type, default value, and allowed value range\r
+{\r
+ char *p, *q, buf[MSG_SIZ];\r
+ int n, min = (-1)<<31, max = 1<<31, def;\r
+\r
+ if(p = strstr(opt->name, " -spin ")) {\r
+ if((n = sscanf(p, " -spin %d %d %d", &def, &min, &max)) < 3 ) return FALSE;\r
+ if(max < min) max = min; // enforce consistency\r
+ if(def < min) def = min;\r
+ if(def > max) def = max;\r
+ opt->value = def;\r
+ opt->min = min;\r
+ opt->max = max;\r
+ opt->type = Spin;\r
+ } else if(p = strstr(opt->name, " -string ")) {\r
+ opt->textValue = p+9;\r
+ opt->type = TextBox;\r
+ } else if(p = strstr(opt->name, " -check ")) {\r
+ if(sscanf(p, " -check %d", &def) < 1) return FALSE;\r
+ opt->value = (def != 0);\r
+ opt->type = CheckBox;\r
+ } else if(p = strstr(opt->name, " -combo ")) {\r
+ opt->textValue = (char*) (&cps->comboList[cps->comboCnt]); // cheat with pointer type\r
+ cps->comboList[cps->comboCnt++] = q = p+8; // holds possible choices\r
+ opt->value = n = 0;\r
+ while(q = StrStr(q, " /// ")) {\r
+ n++; *q = 0; // count choices, and null-terminate each of them\r
+ q += 5;\r
+ if(*q == '*') { // remember default, which is marked with * prefix\r
+ q++;\r
+ opt->value = n;\r
+ }\r
+ cps->comboList[cps->comboCnt++] = q;\r
+ }\r
+ cps->comboList[cps->comboCnt++] = NULL;\r
+ opt->max = n + 1;\r
+ opt->type = ComboBox;\r
+ } else if(p = strstr(opt->name, " -button")) {\r
+ opt->type = Button;\r
+ } else if(p = strstr(opt->name, " -save")) {\r
+ opt->type = SaveButton;\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
+ sprintf(buf, "option %s", p);\r
+ if(p = strstr(buf, ",")) *p = 0;\r
+ strcat(buf, "\n");\r
+ SendToProgram(buf, cps);\r
+ }\r
+ return TRUE;\r
+}\r
+\r
void\r
FeatureDone(cps, val)\r
ChessProgramState* cps;\r
if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue;\r
if (BoolFeature(&p, "name", &cps->sendName, cps)) continue;\r
if (BoolFeature(&p, "pause", &val, cps)) continue; /* unused at present */\r
- if (BoolFeature(&p, "debug", &cps->debug, cps)) continue;\r
- if (BoolFeature(&p, "nps", &cps->supportsNPS, cps)) continue;\r
- if (IntFeature(&p, "level", &cps->maxNrOfSessions, cps)) continue;\r
if (IntFeature(&p, "done", &val, cps)) {\r
FeatureDone(cps, val);\r
continue;\r
if (BoolFeature(&p, "oocastle", &cps->useOOCastle, cps)) continue;\r
/* End of additions by Tord */\r
\r
+ /* [HGM] added features: */\r
+ if (BoolFeature(&p, "debug", &cps->debug, cps)) continue;\r
+ if (BoolFeature(&p, "nps", &cps->supportsNPS, cps)) continue;\r
+ if (IntFeature(&p, "level", &cps->maxNrOfSessions, cps)) continue;\r
+ if (BoolFeature(&p, "memory", &cps->memSize, cps)) continue;\r
+ if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue;\r
+ if (StringFeature(&p, "egt", &cps->egtFormats, cps)) continue;\r
+ if (StringFeature(&p, "option", &(cps->option[cps->nrOptions].name), cps)) {\r
+ ParseOption(&(cps->option[cps->nrOptions++]), cps); // [HGM] options: add option feature\r
+ if(cps->nrOptions >= MAX_OPTIONS) {\r
+ cps->nrOptions--;\r
+ sprintf(buf, "%s engine has too many options\n", cps->which);\r
+ DisplayError(buf, 0);\r
+ }\r
+ continue;\r
+ }\r
+ if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue;\r
+ /* End of additions by HGM */\r
+\r
/* unknown feature: complain and skip */\r
q = p;\r
while (*q && *q != '=') q++;\r
}\r
\r
void\r
-ShowThinkingEvent(newState)\r
- int newState;\r
+NewSettingEvent(option, command, value)\r
+ char *command;\r
+ int option, value;\r
{\r
- if (newState == appData.showThinking) return;\r
+ char buf[MSG_SIZ];\r
+\r
if (gameMode == EditPosition) EditPositionDone();\r
- if (newState) {\r
+ sprintf(buf, "%s%s %d\n", (option ? "option ": ""), command, value);\r
+ SendToProgram(buf, &first);\r
+ if (gameMode == TwoMachinesPlay) {\r
+ SendToProgram(buf, &second);\r
+ }\r
+}\r
+\r
+void\r
+ShowThinkingEvent()\r
+// [HGM] thinking: this routine is now also called from "Options -> Engine..." popup\r
+{\r
+ static int oldState = 2; // kludge alert! Neither true nor fals, so first time oldState is always updated\r
+ int newState = appData.showThinking\r
+ // [HGM] thinking: other features now need thinking output as well\r
+ || !appData.hideThinkingFromHuman || appData.adjudicateLossThreshold != 0 || EngineOutputIsUp();\r
+ \r
+ if (oldState == newState) return;\r
+ oldState = newState;\r
+ if (gameMode == EditPosition) EditPositionDone();\r
+ if (oldState) {\r
SendToProgram("post\n", &first);\r
if (gameMode == TwoMachinesPlay) {\r
SendToProgram("post\n", &second);\r
SendToProgram("nopost\n", &second);\r
}\r
}\r
- appData.showThinking = newState;\r
+// appData.showThinking = newState; // [HGM] thinking: responsible option should already have be changed when calling this routine!\r
}\r
\r
void\r
char res[MSG_SIZ];\r
char cpThinkOutput[MSG_SIZ];\r
\r
+ if(appData.noGUI) return; // [HGM] fast: suppress display of moves\r
+ \r
if (moveNumber == forwardMostMove - 1 || \r
gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
\r
} else {\r
res[0] = NULLCHAR;\r
}\r
- \r
+\r
if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) {\r
DisplayMessage(res, cpThinkOutput);\r
} else {\r
{\r
char buf[MSG_SIZ];\r
\r
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
+ if (gameMode == AnalyzeMode || gameMode == AnalyzeFile \r
+ || appData.icsEngineAnalyze) {\r
sprintf(buf, "Analysis (%s)", first.tidy);\r
AnalysisPopUp(buf, text);\r
}\r
} else {\r
safeStrCpy( lst, programStats.movelist, sizeof(lst));\r
\r
- nps = (((double)programStats.nodes) /\r
- (((double)programStats.time)/100.0));\r
+ nps = (u64ToDouble(programStats.nodes) /\r
+ ((double)programStats.time /100.0));\r
\r
cs = programStats.time % 100;\r
s = programStats.time / 100;\r
\r
if (programStats.moves_left > 0 && appData.periodicUpdates) {\r
if (programStats.move_name[0] != NULLCHAR) {\r
- sprintf(buf, "depth=%d %d/%d(%s) %+.2f %s%s\nNodes: %lu NPS: %d\nTime: %02d:%02d:%02d.%02d",\r
+ sprintf(buf, "depth=%d %d/%d(%s) %+.2f %s%s\nNodes: " u64Display " NPS: %d\nTime: %02d:%02d:%02d.%02d",\r
programStats.depth,\r
programStats.nr_moves-programStats.moves_left,\r
programStats.nr_moves, programStats.move_name,\r
((float)programStats.score)/100.0, lst,\r
only_one_move(lst)?\r
xtra[programStats.got_fail] : "",\r
- programStats.nodes, (int)nps, h, m, s, cs);\r
+ (u64)programStats.nodes, (int)nps, h, m, s, cs);\r
} else {\r
- sprintf(buf, "depth=%d %d/%d %+.2f %s%s\nNodes: %lu NPS: %d\nTime: %02d:%02d:%02d.%02d",\r
+ sprintf(buf, "depth=%d %d/%d %+.2f %s%s\nNodes: " u64Display " NPS: %d\nTime: %02d:%02d:%02d.%02d",\r
programStats.depth,\r
programStats.nr_moves-programStats.moves_left,\r
programStats.nr_moves, ((float)programStats.score)/100.0,\r
lst,\r
only_one_move(lst)?\r
xtra[programStats.got_fail] : "",\r
- programStats.nodes, (int)nps, h, m, s, cs);\r
+ (u64)programStats.nodes, (int)nps, h, m, s, cs);\r
}\r
} else {\r
- sprintf(buf, "depth=%d %+.2f %s%s\nNodes: %lu NPS: %d\nTime: %02d:%02d:%02d.%02d",\r
+ sprintf(buf, "depth=%d %+.2f %s%s\nNodes: " u64Display " NPS: %d\nTime: %02d:%02d:%02d.%02d",\r
programStats.depth,\r
((float)programStats.score)/100.0,\r
lst,\r
only_one_move(lst)?\r
xtra[programStats.got_fail] : "",\r
- programStats.nodes, (int)nps, h, m, s, cs);\r
+ (u64)programStats.nodes, (int)nps, h, m, s, cs);\r
}\r
}\r
DisplayAnalysisText(buf);\r
if(text == NULL) text = ""; \r
score = pvInfoList[moveNumber].score;\r
sprintf(buf, "%s%.2f/%d %d\n%s", score>0 ? "+" : "", score/100.,\r
- depth, pvInfoList[moveNumber].time, text);\r
+ depth, (pvInfoList[moveNumber].time+50)/100, text);\r
CommentPopUp(title, buf);\r
} else\r
if (text != NULL)\r
}\r
} else {\r
if (blackFlag) {\r
- if(gameMode != TwoMachinesPlay) DisplayTitle("Both flags fell");\r
+ if(gameMode != TwoMachinesPlay) DisplayTitle(_("Both flags fell"));\r
} else {\r
- if(gameMode != TwoMachinesPlay) DisplayTitle("White's flag fell");\r
+ if(gameMode != TwoMachinesPlay) DisplayTitle(_("White's flag fell"));\r
if (appData.autoCallFlag) {\r
GameEnds(BlackWins, "Black wins on time", GE_XBOARD);\r
return TRUE;\r
}\r
} else {\r
if (whiteFlag) {\r
- if(gameMode != TwoMachinesPlay) DisplayTitle("Both flags fell");\r
+ if(gameMode != TwoMachinesPlay) DisplayTitle(_("Both flags fell"));\r
} else {\r
- if(gameMode != TwoMachinesPlay) DisplayTitle("Black's flag fell");\r
+ if(gameMode != TwoMachinesPlay) DisplayTitle(_("Black's flag fell"));\r
if (appData.autoCallFlag) {\r
GameEnds(WhiteWins, "White wins on time", GE_XBOARD);\r
return TRUE;\r
gameMode == PlayFromGameFile || forwardMostMove == 0) return;\r
\r
/*\r
- * add time to clocks when time control is achieved ([HGM] now also used fot increment)\r
+ * add time to clocks when time control is achieved ([HGM] now also used for increment)\r
*/\r
if ( !WhiteOnMove(forwardMostMove) )\r
/* White made time control */\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
if(blackNPS >= 0) lastTickLength = 0;\r
blackTimeRemaining -= lastTickLength;\r
/* [HGM] PGNtime: save time for PGN file if engine did not give it */\r
- if(pvInfoList[forwardMostMove-1].time == -1)\r
- pvInfoList[forwardMostMove-1].time = \r
+// if(pvInfoList[forwardMostMove-1].time == -1)\r
+ pvInfoList[forwardMostMove-1].time = // use GUI time\r
(timeRemaining[1][forwardMostMove-1] - blackTimeRemaining)/10;\r
} else {\r
if(whiteNPS >= 0) lastTickLength = 0;\r
whiteTimeRemaining -= lastTickLength;\r
/* [HGM] PGNtime: save time for PGN file if engine did not give it */\r
- if(pvInfoList[forwardMostMove-1].time == -1)\r
+// if(pvInfoList[forwardMostMove-1].time == -1)\r
pvInfoList[forwardMostMove-1].time = \r
(timeRemaining[0][forwardMostMove-1] - whiteTimeRemaining)/10;\r
}\r
*p++;\r
if((int) piece >= (int) BlackPawn ) {\r
i = (int)piece - (int)BlackPawn;\r
- if( i >= BOARD_HEIGHT ) return FALSE;\r
+ i = PieceToNumber((ChessSquare)i);\r
+ if( i >= gameInfo.holdingsSize ) return FALSE;\r
board[BOARD_HEIGHT-1-i][0] = piece; /* black holdings */\r
board[BOARD_HEIGHT-1-i][1]++; /* black counts */\r
} else {\r
i = (int)piece - (int)WhitePawn;\r
- if( i >= BOARD_HEIGHT ) return FALSE;\r
+ i = PieceToNumber((ChessSquare)i);\r
+ if( i >= gameInfo.holdingsSize ) return FALSE;\r
board[i][BOARD_WIDTH-1] = piece; /* white holdings */\r
board[i][BOARD_WIDTH-2]++; /* black holdings */\r
}\r
Board initial_position;\r
\r
if (!ParseFEN(initial_position, &blackPlaysFirst, fen)) {\r
- DisplayError("Bad FEN position in clipboard", 0);\r
+ DisplayError(_("Bad FEN position in clipboard"), 0);\r
return ;\r
} else {\r
int savedBlackPlaysFirst = blackPlaysFirst;\r