/*
* backend.c -- Common back end for X and Windows NT versions of
- * XBoard $Id: backend.c,v 2.6 2003/11/28 09:37:36 mann Exp $
*
* Copyright 1991 by Digital Equipment Corporation, Maynard,
- * Massachusetts. Enhancements Copyright
- * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software
- * Foundation, Inc.
+ * Massachusetts.
+ *
+ * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
+ * 2007, 2008, 2009 Free Software Foundation, Inc.
+ *
+ * Enhancements Copyright 2005 Alessandro Scotti
*
* The following terms apply to Digital Equipment Corporation's copyright
* interest in XBoard:
VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
int lastIndex = 0; /* [HGM] autoinc: last game/position used in match mode */
int opponentKibitzes;
+int lastSavedGame; /* [HGM] save: ID of game */
/* States for ics_getting_history */
#define H_FALSE 0
#endif
if (appData.noChessProgram) {
- programVersion = (char*) malloc(5 + strlen(PRODUCT) + strlen(VERSION)
- + strlen(PATCHLEVEL));
- sprintf(programVersion, "%s %s.%s", PRODUCT, VERSION, PATCHLEVEL);
+ programVersion = (char*) malloc(5 + strlen(PACKAGE_STRING));
+ sprintf(programVersion, "%s", PACKAGE_STRING);
} else {
#if 0
char *p, *q;
while (*q != ' ' && *q != NULLCHAR) q++;
p = q;
while (p > first.program && *(p-1) != '/' && *(p-1) != '\\') p--; /* [HGM] backslash added */
- programVersion = (char*) malloc(8 + strlen(PRODUCT) + strlen(VERSION)
- + strlen(PATCHLEVEL) + (q - p));
- sprintf(programVersion, "%s %s.%s + ", PRODUCT, VERSION, PATCHLEVEL);
+ programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING + (q - p));
+ sprintf(programVersion, "%s + ", PACKAGE_STRING);
strncat(programVersion, p, q - p);
#else
/* [HGM] tidy: use tidy name, in stead of full pathname (which was probably a bug due to / vs \ ) */
- programVersion = (char*) malloc(8 + strlen(PRODUCT) + strlen(VERSION)
- + strlen(PATCHLEVEL) + strlen(first.tidy));
- sprintf(programVersion, "%s %s.%s + %s", PRODUCT, VERSION, PATCHLEVEL, first.tidy);
+ programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy));
+ sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy);
#endif
}
if (data[i] != NULLCHAR && data[i] != '\r')
buf[buf_len++] = data[i];
if(buf_len >= 5 && buf[buf_len-5]=='\n' && buf[buf_len-4]=='\\' &&
- buf[buf_len-3]==' ' && buf[buf_len-2]==' ' && buf[buf_len-1]==' ')
+ buf[buf_len-3]==' ' && buf[buf_len-2]==' ' && buf[buf_len-1]==' ') {
buf_len -= 5; // [HGM] ICS: join continuation line of Lasker 2.2.3 server with previous
+ buf[buf_len++] = ' '; // replace by space (assumes ICS does not break lines within word)
+ }
}
buf[buf_len] = NULLCHAR;
#endif
}
- if (moveNum > 0 && !gotPremove) {
+ if (moveNum > 0 && !gotPremove && !appData.noGUI) {
/* If move comes from a remote source, animate it. If it
isn't remote, it will have already been animated. */
if (!pausing && !ics_user_moved && prevMove == moveNum - 1) {
/* Display opponents and material strengths */
if (gameInfo.variant != VariantBughouse &&
- gameInfo.variant != VariantCrazyhouse) {
+ gameInfo.variant != VariantCrazyhouse && !appData.noGUI) {
if (tinyLayout || smallLayout) {
if(gameInfo.variant == VariantNormal)
sprintf(str, "%s(%d) %s(%d) {%d %d}",
/* Display the board */
- if (!pausing) {
+ if (!pausing && !appData.noGUI) {
if (appData.premove)
if (!gotPremove ||
/* [HGM] convert drag-and-drop piece drops to standard form */
if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
- fromX = boards[currentMove][fromY][fromX];
+ if(appData.debugMode) fprintf(debugFP, "Drop move %d, curr=%d, x=%d,y=%d, p=%d\n",
+ moveType, currentMove, fromX, fromY, boards[currentMove][fromY][fromX]);
+// fromX = boards[currentMove][fromY][fromX];
+ // holdings might not be sent yet in ICS play; we have to figure out which piece belongs here
+ if(fromX == 0) fromY = BOARD_HEIGHT-1 - fromY; // black holdings upside-down
+ fromX = fromX ? WhitePawn : BlackPawn; // first piece type in selected holdings
+ while(PieceToChar(fromX) == '.' || PieceToNumber(fromX) != fromY && fromX != (int) EmptySquare) fromX++;
fromY = DROP_RANK;
}
if(appData.autoKibitz && !appData.icsEngineAnalyze ) { /* [HGM] kibitz: send most-recent PV info to ICS */
char buf[3*MSG_SIZ];
- sprintf(buf, "kibitz !!! %+.2f/%d (%.2f sec, %.0f nodes, %1.0f knps) PV=%s\n",
+ sprintf(buf, "kibitz !!! %+.2f/%d (%.2f sec, %u nodes, %1.0f knps) PV=%s\n",
programStats.score / 100.,
programStats.depth,
programStats.time / 100.,
- u64ToDouble(programStats.nodes),
- u64ToDouble(programStats.nodes) / (10*abs(programStats.time) + 1.),
+ (unsigned int)programStats.nodes,
+ (unsigned int)programStats.nodes / (10*abs(programStats.time) + 1.),
programStats.movelist);
SendToICS(buf);
}
cps->useSigint = FALSE;
cps->useSigterm = FALSE;
}
+ if (strncmp(message, "feature ", 8) == 0) { // [HGM] moved forward to pre-empt non-compliant commands
+ ParseFeatures(message+8, cps);
+ return; // [HGM] This return was missing, causing option features to be recognized as non-compliant commands!
+ }
/* [HGM] Allow engine to set up a position. Don't ask me why one would
* want this, I was asked to put it in, and obliged.
return;
}
}
- if (strncmp(message, "feature ", 8) == 0) {
- ParseFeatures(message+8, cps);
- }
if (sscanf(message, "pong %d", &cps->lastPong) == 1) {
return;
}
}
+// [HGM] save: calculate checksum of game to make games easily identifiable
+int StringCheckSum(char *s)
+{
+ int i = 0;
+ if(s==NULL) return 0;
+ while(*s) i = i*259 + *s++;
+ return i;
+}
+
+int GameCheckSum()
+{
+ int i, sum=0;
+ for(i=backwardMostMove; i<forwardMostMove; i++) {
+ sum += pvInfoList[i].depth;
+ sum += StringCheckSum(parseList[i]);
+ sum += StringCheckSum(commentList[i]);
+ sum *= 261;
+ }
+ if(i>1 && sum==0) sum++; // make sure never zero for non-empty game
+ return sum + StringCheckSum(commentList[i]);
+} // end of save patch
+
void
GameEnds(result, resultDetails, whosays)
ChessMove result;
DisplayMove(currentMove - 1);
if (forwardMostMove != 0) {
- if (gameMode != PlayFromGameFile && gameMode != EditGame) {
+ if (gameMode != PlayFromGameFile && gameMode != EditGame
+ && lastSavedGame != GameCheckSum() // [HGM] save: suppress duplicates
+ ) {
if (*appData.saveGameFile != NULLCHAR) {
SaveGameToFile(appData.saveGameFile, TRUE);
} else if (appData.autoSaveGames) {
DisplayTitle("");
DisplayMessage("", "");
HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);
+ lastSavedGame = 0; // [HGM] save: make sure next game counts as unsaved
}
void
linelen += numlen;
/* Get move */
- strcpy(move_buffer, parseList[i]); // [HGM] pgn: print move via buffer, so it can be edited
+ strcpy(move_buffer, SavePart(parseList[i])); // [HGM] pgn: print move via buffer, so it can be edited
movelen = strlen(move_buffer); /* [HGM] pgn: line-break point before move */
+#if 0
+ // SavePart already does this!
if( i >= 0 && appData.saveExtendedInfoInPGN && pvInfoList[i].depth > 0 ) {
int p = movelen - 1;
if(move_buffer[p] == ' ') p--;
if(p && move_buffer[p-1] == ' ') move_buffer[movelen=p-1] = 0;
}
}
-
+#endif
/* Print move */
blank = linelen > 0 && movelen > 0;
if (linelen + (blank ? 1 : 0) + movelen > PGN_MAX_LINE) {
}
fclose(f);
+ lastSavedGame = GameCheckSum(); // [HGM] save: remember ID of last saved game to prevent double saving
return TRUE;
}
char *dummy2;
{
if (gameMode == EditPosition) EditPositionDone();
+ lastSavedGame = GameCheckSum(); // [HGM] save: remember ID of last saved game to prevent double saving
if (appData.oldSaveStyle)
return SaveGameOldStyle(f);
else
opt->min = min;
opt->max = max;
opt->type = Spin;
- } else if(p = strstr(opt->name, " -string ")) {
+ } else if((p = strstr(opt->name, " -slider "))) {
+ // for now -slider is a synonym for -spin, to already provide compatibility with future polyglots
+ if((n = sscanf(p, " -slider %d %d %d", &def, &min, &max)) < 3 ) return FALSE;
+ if(max < min) max = min; // enforce consistency
+ if(def < min) def = min;
+ if(def > max) def = max;
+ opt->value = def;
+ opt->min = min;
+ opt->max = max;
+ opt->type = Spin; // Slider;
+ } else if((p = strstr(opt->name, " -string "))) {
opt->textValue = p+9;
opt->type = TextBox;
+ } else if((p = strstr(opt->name, " -file "))) {
+ // for now -file is a synonym for -string, to already provide compatibility with future polyglots
+ opt->textValue = p+7;
+ opt->type = TextBox; // FileName;
+ } else if((p = strstr(opt->name, " -path "))) {
+ // for now -file is a synonym for -string, to already provide compatibility with future polyglots
+ opt->textValue = p+7;
+ opt->type = TextBox; // PathName;
} else if(p = strstr(opt->name, " -check ")) {
if(sscanf(p, " -check %d", &def) < 1) return FALSE;
opt->value = (def != 0);
} else if(p = strstr(opt->name, " -combo ")) {
opt->textValue = (char*) (&cps->comboList[cps->comboCnt]); // cheat with pointer type
cps->comboList[cps->comboCnt++] = q = p+8; // holds possible choices
+ if(*q == '*') cps->comboList[cps->comboCnt-1]++;
opt->value = n = 0;
while(q = StrStr(q, " /// ")) {
n++; *q = 0; // count choices, and null-terminate each of them
DrawPosition(FALSE, boards[currentMove]);
}
}
-}
+}
\ No newline at end of file