ChessMove savedResult[MAX_VARIATIONS];
void PushTail P((int firstMove, int lastMove));
-Boolean PopTail P((void));
+Boolean PopTail P((Boolean annotate));
void CleanupTail P((void));
ChessSquare FIDEArray[2][BOARD_FILES] = {
int count;
int error;
{
-#define BUF_SIZE 8192
+#define BUF_SIZE (16*1024) /* overflowed at 8K with "inchannel 1" on FICS? */
#define STARTED_NONE 0
#define STARTED_MOVES 1
#define STARTED_BOARD 2
return ImpossibleMove;
}
}
-if(appData.debugMode) fprintf(debugFP, "moveType 3 = %d, promochar = %x\n", moveType, promoChar);
+
return moveType;
/* [HGM] <popupFix> in stead of calling FinishMove directly, this
function is made into one that returns an OK move type if FinishMove
/*char*/int promoChar;
{
char *bookHit = 0;
-if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", moveType, promoChar);
+
if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) {
// [HGM] superchess: suppress promotions to non-available piece
int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));
move type in caller when we know the move is a legal promotion */
if(moveType == NormalMove && promoChar)
moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);
-if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", moveType, promoChar);
+
/* [HGM] convert drag-and-drop piece drops to standard form */
- if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {
+ if( (fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) && fromY != DROP_RANK ){
moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;
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
}
/* [HGM] <popupFix> The following if has been moved here from
- UserMoveEvent(). Because it seemed to belon here (why not allow
+ UserMoveEvent(). Because it seemed to belong here (why not allow
piece drops in training games?), and because it can only be
performed after it is known to what we promote. */
if (gameMode == Training) {
}
ModeHighlight();
}
-if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar);
+
/* Relay move to ICS or chess engine */
if (appData.icsActive) {
if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||
/* [AS] Negate score if machine is playing black and reporting absolute scores */
if( cps->scoreIsAbsolute &&
- ((gameMode == MachinePlaysBlack) || (gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b')) )
+ ( gameMode == MachinePlaysBlack ||
+ gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b' ||
+ gameMode == IcsPlayingBlack || // [HGM] also add other situations where engine should report black POV
+ (gameMode == AnalyzeMode || gameMode == AnalyzeFile || gameMode == IcsObserving && appData.icsEngineAnalyze) &&
+ !WhiteOnMove(currentMove)
+ ) )
{
curscore = -curscore;
}
/* Print comments preceding this move */
if (commentList[i] != NULL) {
if (linelen > 0) fprintf(f, "\n");
- fprintf(f, "%s\n", commentList[i]);
+ fprintf(f, "%s", commentList[i]);
linelen = 0;
newblock = TRUE;
}
/* [AS] Add PV info if present */
if( i >= 0 && appData.saveExtendedInfoInPGN && pvInfoList[i].depth > 0 ) {
/* [HGM] add time */
- char buf[MSG_SIZ]; int seconds = 0;
+ char buf[MSG_SIZ]; int seconds;
- if(i >= backwardMostMove) {
- if(WhiteOnMove(i))
- seconds = timeRemaining[0][i] - timeRemaining[0][i+1]
- + GetTimeQuota(i/2) / (1000*WhitePlayer()->timeOdds);
- else
- seconds = timeRemaining[1][i] - timeRemaining[1][i+1]
- + GetTimeQuota(i/2) / (1000*WhitePlayer()->other->timeOdds);
- }
- seconds = (seconds+50)/100; // deci-seconds, rounded to nearest
+ seconds = (pvInfoList[i].time+5)/10; // deci-seconds, rounded to nearest
if( seconds <= 0) buf[0] = 0; else
if( seconds < 30 ) sprintf(buf, " %3.1f%c", seconds/10., 0); else {
time_t tm;
char *fen;
+ if (gameMode == EditPosition) EditPositionDone(TRUE);
if (appData.oldSaveStyle) {
tm = time((time_t *) NULL);
ToStartEvent()
{
if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
- /* to optimze, we temporarily turn off analysis mode while we undo
+ /* to optimize, we temporarily turn off analysis mode while we undo
* all the moves. Otherwise we get analysis output after each undo.
*/
if (first.analysisSupport) {
void
RevertEvent()
{
- if(PopTail()) { // [HGM] vari: restore old game tail
+ if(PopTail(TRUE)) { // [HGM] vari: restore old game tail
return;
}
if (gameMode != IcsExamining) {
{
/* This routine is used only for certain modes */
VariantClass v = gameInfo.variant;
+ ChessMove r = GameUnfinished;
+ char *p = NULL;
+
+ if(gameMode == EditGame) { // [HGM] vari: do not erase result on EditGame
+ r = gameInfo.result;
+ p = gameInfo.resultDetails;
+ gameInfo.resultDetails = NULL;
+ }
ClearGameInfo(&gameInfo);
gameInfo.variant = v;
gameInfo.round = StrSave("-");
gameInfo.white = StrSave("-");
gameInfo.black = StrSave("-");
+ gameInfo.result = r;
+ gameInfo.resultDetails = p;
break;
case EditPosition:
commentList[index] = NULL;
return;
}
- if(*text == '{' || *text == '(' || *text == '[') {
+ if( *text == '{' && strchr(text, '}') || // [HGM] braces: if certainy malformed, put braces
+ *text == '[' && strchr(text, ']') || // otherwise hope the user knows what he is doing
+ *text == '(' && strchr(text, ')')) { // (perhaps check if this parses as comment-only?)
commentList[index] = (char *) malloc(len + 2);
strncpy(commentList[index], text, len);
commentList[index][len] = '\n';
char *p;
commentList[index] = (char *) malloc(len + 6);
strcpy(commentList[index], "{\n");
- strcat(commentList[index], text);
+ strncpy(commentList[index]+2, text, len);
+ commentList[index][len+2] = NULLCHAR;
while(p = strchr(commentList[index], '}')) *p = ')'; // kill all } to make it one comment
- strcat(commentList[index], "\n}");
+ strcat(commentList[index], "\n}\n");
}
}
if (commentList[index] != NULL) {
old = commentList[index];
oldlen = strlen(old);
- commentList[index] = (char *) malloc(oldlen + len + 4); // might waste 2
+ while(commentList[index][oldlen-1] == '\n')
+ commentList[index][--oldlen] = NULLCHAR;
+ commentList[index] = (char *) malloc(oldlen + len + 6); // might waste 4
strcpy(commentList[index], old);
free(old);
- // [HGM] braces: join "{A\n}" + "{B}" as "{A\nB\n}"
+ // [HGM] braces: join "{A\n}\n" + "{\nB}" as "{A\nB\n}"
if(commentList[index][oldlen-1] == '}' && (text[0] == '{' || addBraces)) {
if(addBraces) addBraces = FALSE; else { text++; len--; }
while (*text == '\n') { text++; len--; }
- commentList[index][oldlen-1] = NULLCHAR;
- oldlen--;
+ commentList[index][--oldlen] = NULLCHAR;
}
- strncpy(&commentList[index][oldlen], text, len);
- if(addBraces) strcpy(&commentList[index][oldlen + len], "\n}");
- else strcpy(&commentList[index][oldlen + len], "\n");
+ if(addBraces) strcat(commentList[index], "\n{\n");
+ else strcat(commentList[index], "\n");
+ strcat(commentList[index], text);
+ if(addBraces) strcat(commentList[index], "\n}\n");
+ else strcat(commentList[index], "\n");
} else {
- commentList[index] = (char *) malloc(len + 4); // perhaps wastes 2...
- if(addBraces) commentList[index][0] = '{';
- strcpy(commentList[index] + addBraces, text);
+ commentList[index] = (char *) malloc(len + 6); // perhaps wastes 4...
+ if(addBraces)
+ strcpy(commentList[index], "{\n");
+ else commentList[index][0] = NULLCHAR;
+ strcat(commentList[index], text);
strcat(commentList[index], "\n");
- if(addBraces) strcat(commentList[index], "}");
+ if(addBraces) strcat(commentList[index], "}\n");
}
}
} else {
gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
}
- gameInfo.resultDetails = buf;
+ gameInfo.resultDetails = StrSave(buf);
}
DisplayFatalError(buf, error, 1);
}
} else {
gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;
}
- gameInfo.resultDetails = buf;
+ gameInfo.resultDetails = StrSave(buf);
}
RemoveInputSource(cps->isr);
DisplayFatalError(buf, 0, 1);
*p++ = ' ';
if(q = overrideCastling) { // [HGM] FRC: override castling & e.p fields for non-compliant engines
- while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' ';
+ while(*p++ = *q++); if(q != overrideCastling+1) p[-1] = ' '; else --p;
} else {
if(nrCastlingRights) {
q = p;
if(storedGames == 1) GreyRevert(FALSE);
}
-Boolean
-PopTail()
+Boolean
+PopTail(Boolean annotate)
{
int i, j, nrMoves;
+ char buf[8000], moveBuf[20];
if(appData.icsActive) return FALSE; // only in local mode
if(!storedGames) return FALSE; // sanity
storedGames--;
ToNrEvent(savedFirst[storedGames]); // sets currentMove
nrMoves = savedLast[storedGames] - currentMove;
+ if(annotate) {
+ int cnt = 10;
+ if(!WhiteOnMove(currentMove)) sprintf(buf, "(%d...", currentMove+2>>1);
+ else strcpy(buf, "(");
+ for(i=currentMove; i<forwardMostMove; i++) {
+ if(WhiteOnMove(i))
+ sprintf(moveBuf, " %d. %s", i+2>>1, SavePart(parseList[i]));
+ else sprintf(moveBuf, " %s", SavePart(parseList[i]));
+ strcat(buf, moveBuf);
+ if(!--cnt) { strcat(buf, "\n"); cnt = 10; }
+ }
+ strcat(buf, ")");
+ }
for(i=1; i<nrMoves; i++) { // copy last variation back
CopyBoard(boards[currentMove+i], boards[framePtr+i]);
for(j=0; j<MOVE_LEN; j++)
commentList[currentMove+i] = commentList[framePtr+i];
commentList[framePtr+i] = NULL;
}
+ if(annotate) AppendComment(currentMove+1, buf, FALSE);
framePtr = savedFramePtr[storedGames];
gameInfo.result = savedResult[storedGames];
if(gameInfo.resultDetails != NULL) {