#if STDC_HEADERS
# include <stdlib.h>
# include <string.h>
+# include <stdarg.h>
#else /* not STDC_HEADERS */
# if HAVE_STRING_H
# include <string.h>
char *buf, int count, int error));
void read_from_ics P((InputSourceRef isr, VOIDSTAR closure,
char *buf, int count, int error));
+void ics_printf P((char *format, ...));
void SendToICS P((char *s));
void SendToICSDelayed P((char *s, long msdelay));
void SendMoveToICS P((ChessMove moveType, int fromX, int fromY,
void ResurrectChessProgram P((void));
void DisplayComment P((int moveNumber, char *text));
void DisplayMove P((int moveNumber));
-void DisplayAnalysis P((void));
void ParseGameHistory P((char *game));
void ParseBoard12 P((char *string));
void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); // [HGM] moved here from winboard.c
char *ProbeBook P((int moveNr, char *book)); // [HGM] book: returns a book move
char *SendMoveToBookUser P((int nr, ChessProgramState *cps, int initial)); // [HGM] book
+void ics_update_width P((int new_width));
extern char installDir[MSG_SIZ];
extern int tinyLayout, smallLayout;
return dst;
}
-#if 0
-//[HGM] for future use? Conditioned out for now to suppress warning.
-static char * safeStrCat( char * dst, const char * src, size_t count )
-{
- size_t dst_len;
-
- assert( dst != NULL );
- assert( src != NULL );
- assert( count > 0 );
-
- dst_len = strlen(dst);
-
- assert( count > dst_len ); /* Buffer size must be greater than current length */
-
- safeStrCpy( dst + dst_len, src, count - dst_len );
-
- return dst;
-}
-#endif
-
/* Some compiler can't cast u64 to double
* This function do the job for us:
FILE *serverMoves = NULL; // next two for broadcasting (/serverMoves option)
int loadFlag = 0;
int shuffleOpenings;
+int mute; // mute all sounds
ChessSquare FIDEArray[2][BOARD_SIZE] = {
{ WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,
programVersion = (char*) malloc(5 + strlen(PACKAGE_STRING));
sprintf(programVersion, "%s", PACKAGE_STRING);
} else {
-#if 0
- char *p, *q;
- q = first.program;
- while (*q != ' ' && *q != NULLCHAR) q++;
- p = q;
- while (p > first.program && *(p-1) != '/' && *(p-1) != '\\') p--; /* [HGM] backslash added */
- 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(PACKAGE_STRING) + strlen(first.tidy));
- sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy);
-#endif
+ /* [HGM] tidy: use tidy name, in stead of full pathname (which was probably a bug due to / vs \ ) */
+ programVersion = (char*) malloc(8 + strlen(PACKAGE_STRING) + strlen(first.tidy));
+ sprintf(programVersion, "%s + %s", PACKAGE_STRING, first.tidy);
}
if (!appData.icsActive) {
int ti;
int mps;
{
-#if 0
- int matched, min, sec;
-
- matched = sscanf(tc, "%d:%d", &min, &sec);
- if (matched == 1) {
- timeControl = min * 60 * 1000;
- } else if (matched == 2) {
- timeControl = (min * 60 + sec) * 1000;
- } else {
- return FALSE;
- }
-#else
- long tc1;
- long tc2;
- char buf[MSG_SIZ];
-
- if(ti >= 0 && !strchr(tc, '+') && !strchr(tc, '/') ) mps = 0;
- if(ti > 0) {
- if(mps)
- sprintf(buf, "+%d/%s+%d", mps, tc, ti);
- else sprintf(buf, "+%s+%d", tc, ti);
- } else {
- if(mps)
+ long tc1;
+ long tc2;
+ char buf[MSG_SIZ];
+
+ if(ti >= 0 && !strchr(tc, '+') && !strchr(tc, '/') ) mps = 0;
+ if(ti > 0) {
+ if(mps)
+ sprintf(buf, "+%d/%s+%d", mps, tc, ti);
+ else sprintf(buf, "+%s+%d", tc, ti);
+ } else {
+ if(mps)
sprintf(buf, "+%d/%s", mps, tc);
- else sprintf(buf, "+%s", tc);
- }
- fullTimeControlString = StrSave(buf);
-
- if( NextTimeControlFromString( &tc, &tc1 ) != 0 ) {
- return FALSE;
- }
-
- if( *tc == '/' ) {
- /* Parse second time control */
- tc++;
-
- if( NextTimeControlFromString( &tc, &tc2 ) != 0 ) {
- return FALSE;
- }
-
- if( tc2 == 0 ) {
- return FALSE;
- }
-
- timeControl_2 = tc2 * 1000;
- }
- else {
- timeControl_2 = 0;
- }
-
- if( tc1 == 0 ) {
- return FALSE;
+ else sprintf(buf, "+%s", tc);
+ }
+ fullTimeControlString = StrSave(buf);
+
+ if( NextTimeControlFromString( &tc, &tc1 ) != 0 ) {
+ return FALSE;
+ }
+
+ if( *tc == '/' ) {
+ /* Parse second time control */
+ tc++;
+
+ if( NextTimeControlFromString( &tc, &tc2 ) != 0 ) {
+ return FALSE;
}
-
- timeControl = tc1 * 1000;
-#endif
-
- if (ti >= 0) {
- timeIncrement = ti * 1000; /* convert to ms */
- movesPerSession = 0;
- } else {
- timeIncrement = 0;
- movesPerSession = mps;
+
+ if( tc2 == 0 ) {
+ return FALSE;
}
- return TRUE;
+
+ timeControl_2 = tc2 * 1000;
+ }
+ else {
+ timeControl_2 = 0;
+ }
+
+ if( tc1 == 0 ) {
+ return FALSE;
+ }
+
+ timeControl = tc1 * 1000;
+
+ if (ti >= 0) {
+ timeIncrement = ti * 1000; /* convert to ms */
+ movesPerSession = 0;
+ } else {
+ timeIncrement = 0;
+ movesPerSession = mps;
+ }
+ return TRUE;
}
void
if(appData.keepAlive) ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
}
+/* added routine for printf style output to ics */
+void ics_printf(char *format, ...)
+{
+ char buffer[MSG_SIZ];
+ va_list args;
+
+ va_start(args, format);
+ vsnprintf(buffer, sizeof(buffer), format, args);
+ buffer[sizeof(buffer)-1] = '\0';
+ SendToICS(buffer);
+ va_end(args);
+}
+
void
SendToICS(s)
char *s;
while( *e++ != '_');
}
+ if(StrCaseStr(e, "misc/")) { // [HGM] on FICS, misc/shogi is not shogi
+ v = VariantNormal;
+ found = TRUE;
+ } else
for (i=0; i<sizeof(variantNames)/sizeof(char*); i++) {
if (StrCaseStr(e, variantNames[i])) {
v = (VariantClass) i;
VariantSwitch(Board board, VariantClass newVariant)
{
int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j;
- int oldCurrentMove = currentMove, oldForwardMostMove = forwardMostMove, oldBackwardMostMove = backwardMostMove;
-// Board tempBoard; int saveCastling[BOARD_SIZE], saveEP;
startedFromPositionFile = FALSE;
if(gameInfo.variant == newVariant) return;
* case we want to add those holdings to the already received position.
*/
-
- if (appData.debugMode) {
- fprintf(debugFP, "Switch board from %s to %s\n",
- VariantName(gameInfo.variant), VariantName(newVariant));
- setbuf(debugFP, NULL);
- }
- shuffleOpenings = 0; /* [HGM] shuffle */
- gameInfo.holdingsSize = 5; /* [HGM] prepare holdings */
- switch(newVariant) {
- case VariantShogi:
- newWidth = 9; newHeight = 9;
- gameInfo.holdingsSize = 7;
- case VariantBughouse:
- case VariantCrazyhouse:
- newHoldingsWidth = 2; break;
- default:
- newHoldingsWidth = gameInfo.holdingsSize = 0;
- }
-
- if(newWidth != gameInfo.boardWidth ||
- newHeight != gameInfo.boardHeight ||
- newHoldingsWidth != gameInfo.holdingsWidth ) {
-
- /* shift position to new playing area, if needed */
- if(newHoldingsWidth > gameInfo.holdingsWidth) {
- for(i=0; i<BOARD_HEIGHT; i++)
- for(j=BOARD_RGHT-1; j>=BOARD_LEFT; j--)
- board[i][j+newHoldingsWidth-gameInfo.holdingsWidth] =
- board[i][j];
- for(i=0; i<newHeight; i++) {
- board[i][0] = board[i][newWidth+2*newHoldingsWidth-1] = EmptySquare;
- board[i][1] = board[i][newWidth+2*newHoldingsWidth-2] = (ChessSquare) 0;
- }
- } else if(newHoldingsWidth < gameInfo.holdingsWidth) {
- for(i=0; i<BOARD_HEIGHT; i++)
- for(j=BOARD_LEFT; j<BOARD_RGHT; j++)
- board[i][j+newHoldingsWidth-gameInfo.holdingsWidth] =
- board[i][j];
- }
-
- gameInfo.boardWidth = newWidth;
- gameInfo.boardHeight = newHeight;
- gameInfo.holdingsWidth = newHoldingsWidth;
- gameInfo.variant = newVariant;
- InitDrawingSizes(-2, 0);
-
- /* [HGM] The following should definitely be solved in a better way */
-#if 0
- CopyBoard(board, tempBoard); /* save position in case it is board[0] */
- for(i=0; i<BOARD_SIZE; i++) saveCastling[i] = castlingRights[0][i];
- saveEP = epStatus[0];
-#endif
- InitPosition(FALSE); /* this sets up board[0], but also other stuff */
-#if 0
- epStatus[0] = saveEP;
- for(i=0; i<BOARD_SIZE; i++) castlingRights[0][i] = saveCastling[i];
- CopyBoard(tempBoard, board); /* restore position received from ICS */
-#endif
- } else { gameInfo.variant = newVariant; InitPosition(FALSE); }
-
- forwardMostMove = oldForwardMostMove;
- backwardMostMove = oldBackwardMostMove;
- currentMove = oldCurrentMove; /* InitPos reset these, but we need still to redraw the position */
+
+ if (appData.debugMode) {
+ fprintf(debugFP, "Switch board from %s to %s\n",
+ VariantName(gameInfo.variant), VariantName(newVariant));
+ setbuf(debugFP, NULL);
+ }
+ shuffleOpenings = 0; /* [HGM] shuffle */
+ gameInfo.holdingsSize = 5; /* [HGM] prepare holdings */
+ switch(newVariant)
+ {
+ case VariantShogi:
+ newWidth = 9; newHeight = 9;
+ gameInfo.holdingsSize = 7;
+ case VariantBughouse:
+ case VariantCrazyhouse:
+ newHoldingsWidth = 2; break;
+ case VariantGreat:
+ newWidth = 10;
+ case VariantSuper:
+ newHoldingsWidth = 2;
+ gameInfo.holdingsSize = 8;
+ return;
+ case VariantGothic:
+ case VariantCapablanca:
+ case VariantCapaRandom:
+ newWidth = 10;
+ default:
+ newHoldingsWidth = gameInfo.holdingsSize = 0;
+ };
+
+ if(newWidth != gameInfo.boardWidth ||
+ newHeight != gameInfo.boardHeight ||
+ newHoldingsWidth != gameInfo.holdingsWidth ) {
+
+ /* shift position to new playing area, if needed */
+ if(newHoldingsWidth > gameInfo.holdingsWidth) {
+ for(i=0; i<BOARD_HEIGHT; i++)
+ for(j=BOARD_RGHT-1; j>=BOARD_LEFT; j--)
+ board[i][j+newHoldingsWidth-gameInfo.holdingsWidth] =
+ board[i][j];
+ for(i=0; i<newHeight; i++) {
+ board[i][0] = board[i][newWidth+2*newHoldingsWidth-1] = EmptySquare;
+ board[i][1] = board[i][newWidth+2*newHoldingsWidth-2] = (ChessSquare) 0;
+ }
+ } else if(newHoldingsWidth < gameInfo.holdingsWidth) {
+ for(i=0; i<BOARD_HEIGHT; i++)
+ for(j=BOARD_LEFT; j<BOARD_RGHT; j++)
+ board[i][j+newHoldingsWidth-gameInfo.holdingsWidth] =
+ board[i][j];
+ }
+ gameInfo.boardWidth = newWidth;
+ gameInfo.boardHeight = newHeight;
+ gameInfo.holdingsWidth = newHoldingsWidth;
+ gameInfo.variant = newVariant;
+ InitDrawingSizes(-2, 0);
+ InitPosition(FALSE); /* this sets up board[0], but also other stuff */
+ } else { gameInfo.variant = newVariant; InitPosition(FALSE); }
+
+ DrawPosition(TRUE, boards[currentMove]);
}
static int loggedOn = FALSE;
int backup; /* [DM] For zippy color lines */
char *p;
char talker[MSG_SIZ]; // [HGM] chat
+ int channel;
if (appData.debugMode) {
if (!error) {
for (i = 0; i < count; i++) {
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]=='\\' &&
+ if(!appData.noJoin && 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_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)
+ if(buf_len == 0 || buf[buf_len-1] != ' ')
+ buf[buf_len++] = ' '; // add space (assumes ICS does not break lines within word)
}
}
sprintf(str,
"/set-quietly interface %s\n/set-quietly style 12\n",
programVersion);
-
+ if (!appData.noJoin)
+ strcat(str, "/set-quietly wrap 0\n");
} else if (ics_type == ICS_CHESSNET) {
sprintf(str, "/style 12\n");
} else {
#ifdef WIN32
strcat(str, "$iset nohighlight 1\n");
#endif
+ if (!appData.noJoin)
+ strcat(str, "$iset nowrap 1\n");
strcat(str, "$iset lock 1\n$style 12\n");
}
SendToICS(str);
+ NotifyFrontendLogin();
intfSet = TRUE;
}
//if(appData.debugMode) fprintf(debugFP, "hunt for tell, buf = %s\n", buf+i);
// [HGM] chat: intercept tells by users for which we have an open chat window
+ channel = -1;
if(started == STARTED_NONE && (looking_at(buf, &i, "* tells you:") || looking_at(buf, &i, "* says:") ||
- looking_at(buf, &i, "* whispers:"))) {
+ looking_at(buf, &i, "* whispers:") ||
+ looking_at(buf, &i, "*(*):") && (sscanf(star_match[1], "%d", &channel),1) ||
+ looking_at(buf, &i, "*(*)(*):") && sscanf(star_match[2], "%d", &channel) == 1 )) {
int p;
sscanf(star_match[0], "%[^(]", talker+1); // strip (C) or (U) off ICS handle
chattingPartner = -1;
- if(buf[i-3] == 'r') // whisper; look if there is a WHISPER chatbox
- for(p=0; p<MAX_CHAT; p++) if(!strcmp("WHISPER", chatPartner[p])) {
+
+ if(channel >= 0) // channel broadcast; look if there is a chatbox for this channel
+ for(p=0; p<MAX_CHAT; p++) {
+ if(channel == atoi(chatPartner[p])) {
talker[0] = '['; strcat(talker, "]");
chattingPartner = p; break;
+ }
+ } else
+ if(buf[i-3] == 'r') // whisper; look if there is a WHISPER chatbox
+ for(p=0; p<MAX_CHAT; p++) {
+ if(!strcmp("WHISPER", chatPartner[p])) {
+ talker[0] = '['; strcat(talker, "]");
+ chattingPartner = p; break;
+ }
}
if(chattingPartner<0) // if not, look if there is a chatbox for this indivdual
- for(p=0; p<MAX_CHAT; p++) if(!strcasecmp(talker+1, chatPartner[p])) {
+ for(p=0; p<MAX_CHAT; p++) if(!StrCaseCmp(talker+1, chatPartner[p])) {
talker[0] = 0;
chattingPartner = p; break;
}
}
SendTimeRemaining(&first, TRUE);
}
-#if 0
- if (first.useColors) {
- SendToProgram("white\ngo\n", &first);
- } else {
- SendToProgram("go\n", &first);
- }
-#else
if (first.useColors) {
SendToProgram("white\n", &first); // [HGM] book: made sending of "go\n" book dependent
}
bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: probe book for initial pos
-#endif
first.maybeThinking = TRUE;
} else {
if (first.usePlayother) {
}
SendTimeRemaining(&first, FALSE);
}
-#if 0
- if (first.useColors) {
- SendToProgram("black\ngo\n", &first);
- } else {
- SendToProgram("go\n", &first);
- }
-#else
if (first.useColors) {
SendToProgram("black\n", &first);
}
bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE);
-#endif
first.maybeThinking = TRUE;
} else {
if (first.usePlayother) {
fprintf(debugFP, "Illegal move from ICS '%s'\n", move_str);
fprintf(debugFP, "board L=%d, R=%d, H=%d, holdings=%d\n", BOARD_LEFT, BOARD_RGHT, BOARD_HEIGHT, gameInfo.holdingsWidth);
}
-#if 0
- if (appData.testLegality && appData.debugMode) {
- sprintf(str, "Illegal move \"%s\" from ICS", move_str);
- DisplayError(str, 0);
- }
-#endif
strcpy(parseList[moveNum - 1], move_str);
strcat(parseList[moveNum - 1], " ");
strcat(parseList[moveNum - 1], elapsed_time);
programStats.ok_to_send = 0;
}
+void ics_update_width(new_width)
+ int new_width;
+{
+ ics_printf("set width %d\n", new_width);
+}
+
void
SendMoveToProgram(moveNum, cps)
int moveNum;
oldh = gameInfo.holdingsWidth,
oldv = gameInfo.variant;
- currentMove = forwardMostMove = backwardMostMove = 0;
if(appData.icsActive) shuffleOpenings = FALSE; // [HGM] shuffle: in ICS mode, only shuffle on ICS request
/* [AS] Initialize pv info list [HGM] and game status */
initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan;
initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9;
}
-#if 0
- if(gameInfo.variant == VariantFischeRandom) {
- if( appData.defaultFrcPosition < 0 ) {
- ShuffleFRC( initialPosition );
- }
- else {
- SetupFRC( initialPosition, appData.defaultFrcPosition );
- }
- startedFromSetupPosition = TRUE;
- } else
-#else
if (appData.debugMode) {
fprintf(debugFP, "shuffleOpenings = %d\n", shuffleOpenings);
}
SetUpShuffle(initialPosition, appData.defaultFrcPosition);
startedFromSetupPosition = TRUE;
}
-#endif
if(startedFromPositionFile) {
/* [HGM] loadPos: use PositionFile for every new game */
CopyBoard(initialPosition, filePosition);
char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ];
ChessMove lastLoadGameStart = (ChessMove) 0;
-
ChessMove
-UserMoveTest(fromX, fromY, toX, toY, promoChar)
+UserMoveTest(fromX, fromY, toX, toY, promoChar, captureOwn)
int fromX, fromY, toX, toY;
int promoChar;
+ Boolean captureOwn;
{
ChessMove moveType;
ChessSquare pdown, pup;
if (fromX < 0 || fromY < 0) return ImpossibleMove;
- if ((fromX == toX) && (fromY == toY)) {
- return ImpossibleMove;
- }
/* [HGM] suppress all moves into holdings area and guard band */
if( toX < BOARD_LEFT || toX >= BOARD_RGHT || toY < 0 )
return ImpossibleMove;
/* [HGM] <sameColor> moved to here from winboard.c */
- /* note: this code seems to exist for filtering out some obviously illegal premoves */
+ /* note: capture of own piece can be legal as drag-drop premove. For click-click it is selection of new piece. */
pdown = boards[currentMove][fromY][fromX];
pup = boards[currentMove][toY][toX];
- if ( gameMode != EditPosition &&
+ if ( gameMode != EditPosition && !captureOwn &&
(WhitePawn <= pdown && pdown < BlackPawn &&
WhitePawn <= pup && pup < BlackPawn ||
BlackPawn <= pdown && pdown < EmptySquare &&
BlackPawn <= pup && pup < EmptySquare
) && !((gameInfo.variant == VariantFischeRandom || gameInfo.variant == VariantCapaRandom) &&
(pup == WhiteRook && pdown == WhiteKing && fromY == 0 && toY == 0||
- pup == BlackRook && pdown == BlackKing && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 )
+ pup == BlackRook && pdown == BlackKing && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 ||
+ pup == WhiteKing && pdown == WhiteRook && fromY == 0 && toY == 0|| // also allow RxK
+ pup == BlackKing && pdown == BlackRook && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1 )
) )
- return ImpossibleMove;
+ return Comment;
/* Check if the user is playing in turn. This is complicated because we
let the user "pick up" a piece before it is his turn. So the piece he
moveType = LegalityTest(boards[currentMove], PosFlags(currentMove),
epStatus[currentMove], castlingRights[currentMove],
fromY, fromX, toY, toX, promoChar);
-
/* [HGM] but possibly ignore an IllegalMove result */
if (appData.testLegality) {
if (moveType == IllegalMove || moveType == ImpossibleMove) {
FinishMove if the first part succeeded. Calls that do not need
to do anything in between, can call this routine the old way.
*/
- ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar);
+ ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar, FALSE);
if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", moveType, promoChar);
- if(moveType != ImpossibleMove)
+ if(moveType == AmbiguousMove)
+ DrawPosition(FALSE, boards[currentMove]);
+ else if(moveType != ImpossibleMove && moveType != Comment)
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
}
} else moveCount = 6;
}
}
-#if 1
- if (appData.debugMode) { int i;
- fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",
- forwardMostMove, backwardMostMove, epStatus[backwardMostMove],
- appData.drawRepeats);
- for( i=forwardMostMove; i>=backwardMostMove; i-- )
- fprintf(debugFP, "%d ep=%d\n", i, epStatus[i]);
+
+ if (appData.debugMode) { int i;
+ fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",
+ forwardMostMove, backwardMostMove, epStatus[backwardMostMove],
+ appData.drawRepeats);
+ for( i=forwardMostMove; i>=backwardMostMove; i-- )
+ fprintf(debugFP, "%d ep=%d\n", i, epStatus[i]);
+
+ }
- }
-#endif
/* Check for rep-draws */
count = 0;
for(k = forwardMostMove-2;
epStatus[k+2] <= EP_NONE && epStatus[k+1] <= EP_NONE;
k-=2)
{ int rights=0;
-#if 0
- if (appData.debugMode) {
- fprintf(debugFP, " loop\n");
- }
-#endif
if(CompareBoards(boards[k], boards[forwardMostMove])) {
-#if 0
- if (appData.debugMode) {
- fprintf(debugFP, "match\n");
- }
-#endif
/* compare castling rights */
if( castlingRights[forwardMostMove][2] != castlingRights[k][2] &&
(castlingRights[k][0] >= 0 || castlingRights[k][1] >= 0) )
castlingRights[forwardMostMove][4] != castlingRights[k][4] )
rights++;
}
-#if 0
- if (appData.debugMode) {
- for(i=0; i<nrCastlingRights; i++)
- fprintf(debugFP, " (%d,%d)", castlingRights[forwardMostMove][i], castlingRights[k][i]);
- }
-
- if (appData.debugMode) {
- fprintf(debugFP, " %d %d\n", rights, k);
- }
-#endif
if( rights == 0 && ++count > appData.drawRepeats-2
&& appData.drawRepeats > 1) {
/* adjudicate after user-specified nr of repeats */
if (gameMode == BeginningOfGame || gameMode == EndOfGame ||
gameMode == IcsIdle) return;
if (forwardMostMove <= backwardMostMove) return;
-#if 0
- /* Following removed: it caused a bug where a real illegal move
- message in analyze mored would be ignored. */
- if (cps == &first && programStats.ok_to_send == 0) {
- /* Bogus message from Crafty responding to "." This filtering
- can miss some of the bad messages, but fortunately the bug
- is fixed in current Crafty versions, so it doesn't matter. */
- return;
- }
-#endif
if (pausing) PauseEvent();
+ if(appData.forceIllegal) {
+ // [HGM] illegal: machine refused move; force position after move into it
+ SendToProgram("force\n", cps);
+ if(!cps->useSetboard) { // hideous kludge on kludge, because SendBoard sucks.
+ // we have a real problem now, as SendBoard will use the a2a3 kludge
+ // when black is to move, while there might be nothing on a2 or black
+ // might already have the move. So send the board as if white has the move.
+ // But first we must change the stm of the engine, as it refused the last move
+ SendBoard(cps, 0); // always kludgeless, as white is to move on boards[0]
+ if(WhiteOnMove(forwardMostMove)) {
+ SendToProgram("a7a6\n", cps); // for the engine black still had the move
+ SendBoard(cps, forwardMostMove); // kludgeless board
+ } else {
+ SendToProgram("a2a3\n", cps); // for the engine white still had the move
+ CopyBoard(boards[forwardMostMove+1], boards[forwardMostMove]);
+ SendBoard(cps, forwardMostMove+1); // kludgeless board
+ }
+ } else SendBoard(cps, forwardMostMove); // FEN case, also sets stm properly
+ if(gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||
+ gameMode == TwoMachinesPlay)
+ SendToProgram("go\n", cps);
+ return;
+ } else
if (gameMode == PlayFromGameFile) {
/* Stop reading this game file */
gameMode = EditGame;
/* [HGM] in two-machine mode we delay relaying draw offer */
/* until after we also have move, to see if it is really claim */
}
-#if 0
- else {
- if (cps->other->sendDrawOffers) {
- SendToProgram("draw\n", cps->other);
- }
- }
-#endif
} else if (gameMode == MachinePlaysWhite ||
gameMode == MachinePlaysBlack) {
if (userOfferedDraw) {
if (currentMove == forwardMostMove || gameMode == AnalyzeMode
|| gameMode == AnalyzeFile || appData.icsEngineAnalyze) {
DisplayMove(currentMove - 1);
- DisplayAnalysis();
}
return;
if (currentMove == forwardMostMove || gameMode==AnalyzeMode ||
gameMode == AnalyzeFile || appData.icsEngineAnalyze) {
DisplayMove(currentMove - 1);
- DisplayAnalysis();
}
return;
} else if (sscanf(message,"stat01: %d " u64Display " %d %d %d %s",
SendProgramStatsToFrontend( cps, &programStats );
- DisplayAnalysis();
return;
} else if (strncmp(message,"++",2) == 0) {
if (currentMove == forwardMostMove || gameMode==AnalyzeMode ||
gameMode == AnalyzeFile || appData.icsEngineAnalyze) {
DisplayMove(currentMove - 1);
- DisplayAnalysis();
}
return;
}
0, 1);
return;
}
- SwitchClocks();
- timeRemaining[0][forwardMostMove+1] = whiteTimeRemaining;
- timeRemaining[1][forwardMostMove+1] = blackTimeRemaining;
if (commentList[forwardMostMove+1] != NULL) {
free(commentList[forwardMostMove+1]);
commentList[forwardMostMove+1] = NULL;
ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove+1],
castlingRights[forwardMostMove+1], &epStatus[forwardMostMove+1]);
forwardMostMove++; // [HGM] bare: moved to after ApplyMove, to make sure clock interrupt finds complete board
+ SwitchClocks(); // uses forwardMostMove, so must be done after incrementing it !
+ timeRemaining[0][forwardMostMove] = whiteTimeRemaining;
+ timeRemaining[1][forwardMostMove] = blackTimeRemaining;
gameInfo.result = GameUnfinished;
if (gameInfo.resultDetails != NULL) {
free(gameInfo.resultDetails);
while(*r && *r != ',') r++; // path info is everything upto next ';' or end of string
c = *r; *r = 0; // temporarily null-terminate path info
*--q = 0; // strip of trailig ':' from name
- sprintf(buf, "egtbpath %s %s\n", name+1, s);
+ sprintf(buf, "egtpath %s %s\n", name+1, s);
*r = c;
SendToProgram(buf,cps); // send egtbpath command for this format
}
gameMode = BeginningOfGame;
ModeHighlight();
if(appData.icsActive) gameInfo.variant = VariantNormal;
+ currentMove = forwardMostMove = backwardMostMove = 0;
InitPosition(redraw);
for (i = 0; i < MAX_MOVES; i++) {
if (commentList[i] != NULL) {
DisplayError(_("Position not found in file"), 0);
return FALSE;
}
-#if 0
- switch (line[0]) {
- case '#': case 'x':
- default:
- fenMode = FALSE;
- break;
- case 'p': case 'n': case 'b': case 'r': case 'q': case 'k':
- case 'P': case 'N': case 'B': case 'R': case 'Q': case 'K':
- case '1': case '2': case '3': case '4': case '5': case '6':
- case '7': case '8': case '9':
- case 'H': case 'A': case 'M': case 'h': case 'a': case 'm':
- case 'E': case 'F': case 'G': case 'e': case 'f': case 'g':
- case 'C': case 'W': case 'c': case 'w':
- fenMode = TRUE;
- break;
- }
-#else
// [HGM] FEN can begin with digit, any piece letter valid in this variant, or a + for Shogi promoted pieces
fenMode = line[0] >= '0' && line[0] <= '9' || line[0] == '+' || CharToPiece(line[0]) != EmptySquare;
-#endif
if (pn >= 2) {
if (fenMode || line[0] == '#') pn--;
fprintf(f, " ");
linelen++;
}
- fprintf(f, numtext);
+ fprintf(f, "%s", numtext);
linelen += numlen;
/* Get move */
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(move_buffer[p] == ')') { // [HGM] pgn: strip off ICS time if we have extended info
- while(p && move_buffer[--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) {
fprintf(f, " ");
linelen++;
}
- fprintf(f, move_buffer);
+ fprintf(f, "%s", move_buffer);
linelen += movelen;
/* [AS] Add PV info if present */
/* [HGM] add time */
char buf[MSG_SIZ]; int seconds = 0;
-#if 1
if(i >= backwardMostMove) {
if(WhiteOnMove(i))
seconds = timeRemaining[0][i] - timeRemaining[0][i+1]
+ GetTimeQuota(i/2) / (1000*WhitePlayer()->other->timeOdds);
}
seconds = (seconds+50)/100; // deci-seconds, rounded to nearest
-#else
- seconds = (pvInfoList[i].time + 5)/10; // [HGM] PVtime: use engine time
-#endif
if( seconds <= 0) buf[0] = 0; else
if( seconds < 30 ) sprintf(buf, " %3.1f%c", seconds/10., 0); else {
fprintf(f, " ");
linelen++;
}
- fprintf(f, move_buffer);
+ fprintf(f, "%s", move_buffer);
linelen += movelen;
}
if (icsPR != NoProc) {
DestroyChildProcess(icsPR, TRUE);
}
-#if 0
- /* Save game if resource set and not already saved by GameEnds() */
- if ((gameInfo.resultDetails == NULL || errorExitFlag )
- && forwardMostMove > 0) {
- if (*appData.saveGameFile != NULLCHAR) {
- SaveGameToFile(appData.saveGameFile, TRUE);
- } else if (appData.autoSaveGames) {
- AutoSaveGame();
- }
- if (*appData.savePositionFile != NULLCHAR) {
- SavePositionToFile(appData.savePositionFile);
- }
- }
- GameEnds((ChessMove) 0, NULL, GE_PLAYER);
-#else
+
/* [HGM] crash: leave writing PGN and position entirely to GameEnds() */
GameEnds(gameInfo.result, gameInfo.resultDetails==NULL ? "xboard exit" : gameInfo.resultDetails, GE_PLAYER);
-#endif
+
/* [HGM] crash: the above GameEnds() is a dud if another one was running */
/* make sure this other one finishes before killing it! */
if(endingGame) { int count = 0;
first.analyzing = TRUE;
/*first.maybeThinking = TRUE;*/
first.maybeThinking = FALSE; /* avoid killing GNU Chess */
- AnalysisPopUp(_("Analysis"),
- _("Starting analysis mode...\nIf this message stays up, your chess program does not support analysis."));
+ EngineOutputPopUp();
}
if (!appData.icsEngineAnalyze) gameMode = AnalyzeMode;
pausing = FALSE;
first.analyzing = TRUE;
/*first.maybeThinking = TRUE;*/
first.maybeThinking = FALSE; /* avoid killing GNU Chess */
- AnalysisPopUp(_("Analysis"),
- _("Starting analysis mode...\nIf this message stays up, your chess program does not support analysis."));
+ EngineOutputPopUp();
}
gameMode = AnalyzeFile;
pausing = FALSE;
SetMachineThinkingEnables();
first.maybeThinking = TRUE;
StartClocks();
+ firstMove = FALSE;
if (appData.autoFlipView && !flipView) {
flipView = !flipView;
SendToProgram("exit\n", &first);
first.analyzing = FALSE;
}
- AnalysisPopDown();
thinkOutput[0] = NULLCHAR;
}
sscanf(message, "resign%c", &c)!=1 && sscanf(message, "feature %c", &c)!=1 &&
sscanf(message, "error %c", &c)!=1 && sscanf(message, "illegal %c", &c)!=1 &&
sscanf(message, "tell%c", &c)!=1 && sscanf(message, "0-1 %c", &c)!=1 &&
- sscanf(message, "1-0 %c", &c)!=1 && sscanf(message, "1/2-1/2 %c", &c)!=1 && start != '#')
+ sscanf(message, "1-0 %c", &c)!=1 && sscanf(message, "1/2-1/2 %c", &c)!=1 &&
+ sscanf(message, "pong %c", &c)!=1 && start != '#')
{ quote = "# "; print = (appData.engineComments == 2); }
message[0] = start; // restore original message
}
appData.periodicUpdates=newState;
/* Display type changes, so update it now */
- DisplayAnalysis();
+// DisplayAnalysis();
/* Get the ball rolling again... */
if (newState) {
}
void
-DisplayAnalysisText(text)
- char *text;
-{
- char buf[MSG_SIZ];
-
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
- || appData.icsEngineAnalyze) {
- sprintf(buf, "Analysis (%s)", first.tidy);
- AnalysisPopUp(buf, text);
- }
-}
-
-static int
-only_one_move(str)
- char *str;
-{
- while (*str && isspace(*str)) ++str;
- while (*str && !isspace(*str)) ++str;
- if (!*str) return 1;
- while (*str && isspace(*str)) ++str;
- if (!*str) return 1;
- return 0;
-}
-
-void
-DisplayAnalysis()
-{
- char buf[MSG_SIZ];
- char lst[MSG_SIZ / 2];
- double nps;
- static char *xtra[] = { "", " (--)", " (++)" };
- int h, m, s, cs;
-
- if (programStats.time == 0) {
- programStats.time = 1;
- }
-
- if (programStats.got_only_move) {
- safeStrCpy(buf, programStats.movelist, sizeof(buf));
- } else {
- safeStrCpy( lst, programStats.movelist, sizeof(lst));
-
- nps = (u64ToDouble(programStats.nodes) /
- ((double)programStats.time /100.0));
-
- cs = programStats.time % 100;
- s = programStats.time / 100;
- h = (s / (60*60));
- s = s - h*60*60;
- m = (s/60);
- s = s - m*60;
-
- if (programStats.moves_left > 0 && appData.periodicUpdates) {
- if (programStats.move_name[0] != NULLCHAR) {
- sprintf(buf, "depth=%d %d/%d(%s) %+.2f %s%s\nNodes: " u64Display " NPS: %d\nTime: %02d:%02d:%02d.%02d",
- programStats.depth,
- programStats.nr_moves-programStats.moves_left,
- programStats.nr_moves, programStats.move_name,
- ((float)programStats.score)/100.0, lst,
- only_one_move(lst)?
- xtra[programStats.got_fail] : "",
- (u64)programStats.nodes, (int)nps, h, m, s, cs);
- } else {
- sprintf(buf, "depth=%d %d/%d %+.2f %s%s\nNodes: " u64Display " NPS: %d\nTime: %02d:%02d:%02d.%02d",
- programStats.depth,
- programStats.nr_moves-programStats.moves_left,
- programStats.nr_moves, ((float)programStats.score)/100.0,
- lst,
- only_one_move(lst)?
- xtra[programStats.got_fail] : "",
- (u64)programStats.nodes, (int)nps, h, m, s, cs);
- }
- } else {
- sprintf(buf, "depth=%d %+.2f %s%s\nNodes: " u64Display " NPS: %d\nTime: %02d:%02d:%02d.%02d",
- programStats.depth,
- ((float)programStats.score)/100.0,
- lst,
- only_one_move(lst)?
- xtra[programStats.got_fail] : "",
- (u64)programStats.nodes, (int)nps, h, m, s, cs);
- }
- }
- DisplayAnalysisText(buf);
-}
-
-void
DisplayComment(moveNumber, text)
int moveNumber;
char *text;
} else {
*p++ = '-';
}
+ } else if(move == backwardMostMove) {
+ // [HGM] perhaps we should always do it like this, and forget the above?
+ if(epStatus[move] >= 0) {
+ *p++ = epStatus[move] + AAA;
+ *p++ = whiteToPlay ? '6'+BOARD_HEIGHT-8 : '3';
+ } else {
+ *p++ = '-';
+ }
} else {
*p++ = '-';
}