# include "zippy.h"
#endif
#include "backendz.h"
+#include "evalgraph.h"
#include "gettext.h"
#ifdef ENABLE_NLS
ChessSquare pieceSweep = EmptySquare;
ChessSquare promoSweep = EmptySquare, defaultPromoChoice;
int promoDefaultAltered;
+int keepInfo = 0; /* [HGM] to protect PGN tags in auto-step game analysis */
/* States for ics_getting_history */
#define H_FALSE 0
{
int outError, outCount;
static int gotEof = 0;
+ static FILE *ini;
/* Pass data read from player on to ICS */
if (count > 0) {
if (outCount < count) {
DisplayFatalError(_("Error writing to ICS"), outError, 1);
}
+ if(have_sent_ICS_logon == 2) {
+ if(ini = fopen(appData.icsLogon, "w")) { // save first two lines (presumably username & password) on init script file
+ fprintf(ini, "%s", message);
+ have_sent_ICS_logon = 3;
+ } else
+ have_sent_ICS_logon = 1;
+ } else if(have_sent_ICS_logon == 3) {
+ fprintf(ini, "%s", message);
+ fclose(ini);
+ have_sent_ICS_logon = 1;
+ }
} else if (count < 0) {
RemoveInputSource(isr);
DisplayFatalError(_("Error reading from keyboard"), error, 1);
}
void
+PlotSingleSeekAd (int i)
+{
+ PlotSeekAd(i);
+}
+
+void
AddAd (char *handle, char *rating, int base, int inc, char rated, char *type, int nr, Boolean plot)
{
char buf[MSG_SIZ], *ext = "";
seekNrList[nrOfSeekAds] = nr;
zList[nrOfSeekAds] = 0;
seekAdList[nrOfSeekAds++] = StrSave(buf);
- if(plot) PlotSeekAd(nrOfSeekAds-1);
+ if(plot) PlotSingleSeekAd(nrOfSeekAds-1);
}
}
for(i=0; i<4000; i+= 100) if(i>=minRating && i<maxRating) {
int yy =((double)i - minRating)/(maxRating - minRating)*(h-vMargin-squareSize/8-1) + vMargin;
yy = h-1-yy;
- DrawSeekAxis(hMargin+5*(i%500==0), yy, hMargin-5, yy); // rating ticks
+ DrawSeekAxis(hMargin-5, yy, hMargin+5*(i%500==0), yy); // rating ticks
if(i%500 == 0) {
char buf[MSG_SIZ];
snprintf(buf, MSG_SIZ, "%d", i);
continue;
}
- if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) {
- ICSInitScript();
- have_sent_ICS_logon = 1;
+ if (looking_at(buf, &i, "login:")) {
+ if (!have_sent_ICS_logon) {
+ if(ICSInitScript())
+ have_sent_ICS_logon = 1;
+ else // no init script was found
+ have_sent_ICS_logon = (appData.autoCreateLogon ? 2 : 1); // flag that we should capture username + password
+ } else { // we have sent (or created) the InitScript, but apparently the ICS rejected it
+ have_sent_ICS_logon = (appData.autoCreateLogon ? 2 : 1); // request creation of a new script
+ }
continue;
}
}
}
- if(doubleClick) { // [HGM] exclude: move entered with double-click on from square is for exclusion, not playing
+ if(doubleClick && gameMode == AnalyzeMode) { // [HGM] exclude: move entered with double-click on from square is for exclusion, not playing
if(ExcludeOneMove(fromY, fromX, toY, toX, promoChar, '*')) // toggle
ClearPremoveHighlights(); // was included
else ClearHighlights(), SetPremoveHighlights(ff, rf, ft, rt); // exclusion indicated by premove highlights
return;
}
doubleClick = FALSE;
+ if(gameMode == AnalyzeMode && pausing && first.excludeMoves) { // use pause state to exclude moves
+ doubleClick = TRUE; gatingPiece = boards[currentMove][y][x];
+ }
fromX = x; fromY = y; toX = toY = -1;
if(!appData.oneClick || !OnlyMove(&x, &y, FALSE) ||
// even if only move, we treat as normal when this would trigger a promotion popup, to allow sweep selection
ClearHighlights();
}
} else {
+#if 0
+// [HGM] this must be done after the move is made, as with arrow it could lead to a board redraw with piece still on from square
/* Finish drag move */
if (appData.highlightLastMove) {
SetHighlights(fromX, fromY, toX, toY);
} else {
ClearHighlights();
}
+#endif
DragPieceEnd(xPix, yPix); dragging = 0;
/* Don't animate move and drag both */
appData.animate = FALSE;
}
- MarkTargetSquares(1);
// moves into holding are invalid for now (except in EditPosition, adapting to-square)
if(x >= 0 && x < BOARD_LEFT || x >= BOARD_RGHT) {
}
ClearHighlights();
fromX = fromY = -1;
+ MarkTargetSquares(1);
DrawPosition(TRUE, boards[currentMove]);
return;
}
if (HasPromotionChoice(fromX, fromY, toX, toY, &promoChoice, appData.sweepSelect)) {
SetHighlights(fromX, fromY, toX, toY);
+ MarkTargetSquares(1);
if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat || gameInfo.variant == VariantGrand) {
// [HGM] super: promotion to captured piece selected from holdings
ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];
if(saveAnimate && !appData.animate && currentMove != oldMove && // drag-move was performed
Explode(boards[currentMove-1], fromX, fromY, toX, toY))
DrawPosition(TRUE, boards[currentMove]);
+ MarkTargetSquares(1);
fromX = fromY = -1;
}
appData.animate = saveAnimate;
) {
/* white pawn promotion */
board[toY][toX] = CharToPiece(ToUpper(promoChar));
- if(gameInfo.variant==VariantBughouse ||
- gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */
+ if((gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse)
+ && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */
board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]);
board[fromY][fromX] = EmptySquare;
} else if ((fromY >= BOARD_HEIGHT>>1)
) {
/* black pawn promotion */
board[toY][toX] = CharToPiece(ToLower(promoChar));
- if(gameInfo.variant==VariantBughouse ||
- gameInfo.variant==VariantCrazyhouse) /* [HGM] use shadow piece */
+ if((gameInfo.variant==VariantBughouse || gameInfo.variant==VariantCrazyhouse)
+ && PieceToChar(PROMOTED board[toY][toX]) == '~') /* [HGM] use shadow piece (if available) */
board[toY][toX] = (ChessSquare) (PROMOTED board[toY][toX]);
board[fromY][fromX] = EmptySquare;
} else if ((fromY < BOARD_HEIGHT>>1)
AnimateMove(boards[forwardMostMove - 1],
fromX, fromY, toX, toY);
}
- if (appData.highlightLastMove) {
- SetHighlights(fromX, fromY, toX, toY);
- }
}
currentMove = forwardMostMove;
}
if (instant) return;
DisplayMove(currentMove - 1);
+ if (!pausing || gameMode == PlayFromGameFile || gameMode == AnalyzeFile) {
+ if (appData.highlightLastMove) { // [HGM] moved to after DrawPosition, as with arrow it could redraw old board
+ SetHighlights(fromX, fromY, toX, toY);
+ }
+ }
DrawPosition(FALSE, boards[currentMove]);
DisplayBothClocks();
HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);
char buf[MSG_SIZ];
extern char *icsNames;
if(!s || !*s) return 0;
- NamesToList(n == 10 ? icsNames : firstChessProgramNames, command, mnemonic, "all");
+ NamesToList(n >= 10 ? icsNames : firstChessProgramNames, command, mnemonic, "all");
for(i=1; mnemonic[i]; i++) if(!strcmp(s, mnemonic[i])) break;
if(!mnemonic[i]) return 0;
+ if(n == 11) return 1; // just testing if there was a match
snprintf(buf, MSG_SIZ, "-%s %s", n == 10 ? "icshost" : "fcp", command[i]);
if(n == 1) SwapEngines(n);
ParseArgsFromString(buf);
if (*appData.savePositionFile != NULLCHAR) {
SavePositionToFile(appData.savePositionFile);
}
+ AddGameToBook(FALSE); // Only does something during Monte-Carlo book building
}
}
}
}
+void
+AnalyzeNextGame()
+{
+ ReloadGame(1); // next game
+}
int
AutoPlayOneMove ()
}
if (currentMove >= forwardMostMove) {
- if(gameMode == AnalyzeFile) { ExitAnalyzeMode(); SendToProgram("force\n", &first); }
+ if(gameMode == AnalyzeFile) {
+ if(appData.loadGameIndex == -1) {
+ GameEnds(EndOfFile, NULL, GE_FILE);
+ ScheduleDelayedEvent(AnalyzeNextGame, 10);
+ } else {
+ ExitAnalyzeMode(); SendToProgram("force\n", &first);
+ }
+ }
// gameMode = EndOfGame;
// ModeHighlight();
}
GameInfo dummyInfo;
+static int creatingBook;
int
GameContainsPosition (FILE *f, ListGame *lg)
gn = 1;
}
else {
+ if(gameMode == AnalyzeFile && appData.loadGameIndex == -1)
+ appData.loadGameIndex = 0; // [HGM] suppress error message if we reach file end after auto-stepping analysis
+ else
DisplayError(_("Game number out of range"), 0);
return FALSE;
}
cm = (ChessMove) Myylex();
}
+ if(!creatingBook) {
if (first.pr == NoProc) {
StartChessProgram(&first);
}
}
DisplayBothClocks();
}
+ }
/* [HGM] server: flag to write setup moves in broadcast file as one */
loadFlag = appData.suppressLoadMoves;
if (oldGameMode == AnalyzeFile ||
oldGameMode == AnalyzeMode) {
+ appData.loadGameIndex = -1; // [HGM] order auto-stepping through games
+ keepInfo = 1;
AnalyzeFileEvent();
+ keepInfo = 0;
}
+ if(creatingBook) return TRUE;
if (!matchMode && pos > 0) {
ToNrEvent(pos); // [HGM] no autoplay if selected on position
} else
WhiteOnMove(forwardMostMove))) {
StopClocks();
}
+ case AnalyzeMode:
pausing = TRUE;
ModeHighlight();
break;
}
}
+/* Toggle ShowThinking */
void
+ToggleShowThinking()
+{
+ appData.showThinking = !appData.showThinking;
+ ShowThinkingEvent();
+}
+
+int
AnalyzeModeEvent ()
{
- if (gameMode == AnalyzeMode) { ToggleSecond(); return; }
+ char buf[MSG_SIZ];
+
+ if (!first.analysisSupport) {
+ snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
+ DisplayError(buf, 0);
+ return 0;
+ }
+ /* [DM] icsEngineAnalyze [HGM] This is horrible code; reverse the gameMode and isEngineAnalyze tests! */
+ if (appData.icsActive) {
+ if (gameMode != IcsObserving) {
+ snprintf(buf, MSG_SIZ, _("You are not observing a game"));
+ DisplayError(buf, 0);
+ /* secure check */
+ if (appData.icsEngineAnalyze) {
+ if (appData.debugMode)
+ fprintf(debugFP, _("Found unexpected active ICS engine analyze \n"));
+ ExitAnalyzeMode();
+ ModeHighlight();
+ }
+ return 0;
+ }
+ /* if enable, user wants to disable icsEngineAnalyze */
+ if (appData.icsEngineAnalyze) {
+ ExitAnalyzeMode();
+ ModeHighlight();
+ return 0;
+ }
+ appData.icsEngineAnalyze = TRUE;
+ if (appData.debugMode)
+ fprintf(debugFP, _("ICS engine analyze starting... \n"));
+ }
+
+ if (gameMode == AnalyzeMode) { ToggleSecond(); return 0; }
if (appData.noChessProgram || gameMode == AnalyzeMode)
- return;
+ return 0;
if (gameMode != AnalyzeFile) {
if (!appData.icsEngineAnalyze) {
EditGameEvent();
- if (gameMode != EditGame) return;
+ if (gameMode != EditGame) return 0;
}
+ if (!appData.showThinking) ToggleShowThinking();
ResurrectChessProgram();
SendToProgram("analyze\n", &first);
first.analyzing = TRUE;
StartAnalysisClock();
GetTimeMark(&lastNodeCountTime);
lastNodeCount = 0;
+ return 1;
}
void
if (appData.noChessProgram || gameMode == AnalyzeFile)
return;
+ if (!first.analysisSupport) {
+ char buf[MSG_SIZ];
+ snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
+ DisplayError(buf, 0);
+ return;
+ }
+
if (gameMode != AnalyzeMode) {
EditGameEvent();
if (gameMode != EditGame) return;
+ if (!appData.showThinking) ToggleShowThinking();
ResurrectChessProgram();
SendToProgram("analyze\n", &first);
first.analyzing = TRUE;
GetTimeMark(&lastNodeCountTime);
lastNodeCount = 0;
if(appData.timeDelay > 0) StartLoadGameTimer((long)(1000.0f * appData.timeDelay));
+ AnalysisPeriodicEvent(1);
}
void
}
void
+CreateBookEvent ()
+{
+ ListGame * lg = (ListGame *) gameList.head;
+ FILE *f;
+ int nItem;
+ static int secondTime = FALSE;
+
+ if( !(f = GameFile()) || ((ListGame *) gameList.tailPred)->number <= 0 ) {
+ DisplayError(_("Game list not loaded or empty"), 0);
+ return;
+ }
+
+ if(!secondTime && (f = fopen(appData.polyglotBook, "r"))) {
+ fclose(f);
+ secondTime++;
+ DisplayNote(_("Book file exists! Try again for overwrite."));
+ return;
+ }
+
+ creatingBook = TRUE;
+ secondTime = FALSE;
+
+ /* Get list size */
+ for (nItem = 1; nItem <= ((ListGame *) gameList.tailPred)->number; nItem++){
+ LoadGame(f, nItem, "", TRUE);
+ AddGameToBook(TRUE);
+ lg = (ListGame *) lg->node.succ;
+ }
+
+ creatingBook = FALSE;
+ FlushBook();
+}
+
+void
BookEvent ()
{
if (appData.noChessProgram) return;
ChessMove r = GameUnfinished;
char *p = NULL;
+ if(keepInfo) return;
+
if(gameMode == EditGame) { // [HGM] vari: do not erase result on EditGame
r = gameInfo.result;
p = gameInfo.resultDetails;
ToNrEvent(currentMove+1);
}
+void
+LoadTheme ()
+{
+ char *p, *q, buf[MSG_SIZ];
+ if(engineLine && engineLine[0]) { // a theme was selected from the listbox
+ snprintf(buf, MSG_SIZ, "-theme %s", engineLine);
+ ParseArgsFromString(buf);
+ ActivateTheme(TRUE); // also redo colors
+ return;
+ }
+ p = nickName;
+ if(*p && !strchr(p, '"')) // theme name specified and well-formed; add settings to theme list
+ {
+ int len;
+ q = appData.themeNames;
+ snprintf(buf, MSG_SIZ, "\"%s\"", nickName);
+ if(appData.useBitmaps) {
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt true -lbtf \"%s\" -dbtf \"%s\" -lbtm %d -dbtm %d",
+ appData.liteBackTextureFile, appData.darkBackTextureFile,
+ appData.liteBackTextureMode,
+ appData.darkBackTextureMode );
+ } else {
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ubt false -lsc %s -dsc %s",
+ Col2Text(2), // lightSquareColor
+ Col2Text(3) ); // darkSquareColor
+ }
+ if(appData.useBorder) {
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ub true -border \"%s\"",
+ appData.border);
+ } else {
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -ub false");
+ }
+ if(appData.useFont) {
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -upf true -pf \"%s\" -fptc \"%s\" -fpfcw %s -fpbcb %s",
+ appData.renderPiecesWithFont,
+ appData.fontToPieceTable,
+ Col2Text(9), // appData.fontBackColorWhite
+ Col2Text(10) ); // appData.fontForeColorBlack
+ } else {
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -upf false -pid \"%s\"",
+ appData.pieceDirectory);
+ if(!appData.pieceDirectory[0])
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -wpc %s -bpc %s",
+ Col2Text(0), // whitePieceColor
+ Col2Text(1) ); // blackPieceColor
+ }
+ snprintf(buf+strlen(buf), MSG_SIZ-strlen(buf), " -hsc %s -phc %s\n",
+ Col2Text(4), // highlightSquareColor
+ Col2Text(5) ); // premoveHighlightColor
+ appData.themeNames = malloc(len = strlen(q) + strlen(buf) + 1);
+ if(insert != q) insert[-1] = NULLCHAR;
+ snprintf(appData.themeNames, len, "%s\n%s%s", q, buf, insert);
+ if(q) free(q);
+ }
+ ActivateTheme(FALSE);
+}