#include "config.h"
#include <stdio.h>
-#include <malloc.h>
#if STDC_HEADERS
# include <stdlib.h>
#include "common.h"
#include "frontend.h"
#include "backend.h"
+#include "moves.h"
#include "engineoutput.h"
typedef struct {
static int lastDepth[2] = { -1, -1 };
static int lastForwardMostMove[2] = { -1, -1 };
static int engineState[2] = { -1, -1 };
+static char lastLine[2][MSG_SIZ];
+static char header[MSG_SIZ];
#define MAX_VAR 400
static int scores[MAX_VAR], textEnd[MAX_VAR], curDepth[2], nrVariations[2];
+extern int initialRulePlies;
+
+void MakeEngineOutputTitle()
+{
+ static char buf[MSG_SIZ];
+ static char oldTitle[MSG_SIZ];
+ char *title = "Engine Output";
+ int count, rule = 2*appData.ruleMoves;
+
+ if(!EngineOutputIsUp()) return;
+ // figure out value of 50-move counter
+ count = currentMove;
+ while( (signed char)boards[count][EP_STATUS] <= EP_NONE && count > backwardMostMove ) count--;
+ if( count == backwardMostMove ) count -= initialRulePlies;
+ count = currentMove - count;
+ snprintf(buf, MSG_SIZ, "%s (%d reversible plies)", title, count);
+ if(!rule) rule = 100;
+ if(count >= rule - 40 && !appData.icsActive) title = buf;
+ if(!strcmp(oldTitle, title)) return;
+ safeStrCpy(oldTitle, title, MSG_SIZ);
+ SetEngineOutputTitle(title);
+}
+
// back end, due to front-end wrapper for SetWindowText, and new SetIcon arguments
void SetEngineState( int which, int state, char * state_data )
{
{
EngineOutputData ed;
int clearMemo = FALSE;
- int which;
- int depth;
+ int which, depth, multi;
if( stats == 0 ) {
SetEngineState( 0, STATE_IDLE, "" );
ed.name = second.tidy;
}
+ if( ed.pv != 0 && ed.pv[0] == ' ' ) {
+ if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */
+ ed.pv = "";
+ }
+ }
+
/* Clear memo if needed */
- if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) {
+ if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1 && ed.pv[0]) ) { // no reason to clear if we won't add line
clearMemo = TRUE;
}
clearMemo = TRUE;
}
- if( clearMemo ) { DoClearMemo(which); nrVariations[which] = 0; }
+ if( clearMemo ) {
+ DoClearMemo(which); nrVariations[which] = 0;
+ header[0] = NULLCHAR;
+ if(gameMode == AnalyzeMode && (multi = MultiPV(&first)) >= 0) {
+ snprintf(header, MSG_SIZ, "\t%s viewpoint\t\tfewer / Multi-PV setting = %d / more\n",
+ appData.whitePOV || appData.scoreWhite ? "white" : "mover", first.option[multi].value);
+ InsertIntoMemo( which, header, 0);
+ } else
+ if(appData.ponderNextMove && lastLine[which][0]) {
+ InsertIntoMemo( which, lastLine[which], 0 );
+ InsertIntoMemo( which, "\n", 0 );
+ }
+ }
/* Update */
lastDepth[which] = depth == 1 && ed.nodes == 0 ? 0 : depth; // [HGM] info-line kudge
lastForwardMostMove[which] = forwardMostMove;
- if( ed.pv != 0 && ed.pv[0] == ' ' ) {
- if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */
- ed.pv = "";
- }
- }
-
UpdateControls( &ed );
}
scores[n] = newScore;
}
nrVariations[n] += 2;
- return offs;
+ return offs + (gameMode == AnalyzeMode)*strlen(header);
}
// int isPondering = FALSE;
char s_label[MAX_NAME_LENGTH + 32];
-
+ int h;
char * name = ed->name;
/* Label */
strncpy( mov, ed->hint, sizeof(mov) );
mov[ sizeof(mov)-1 ] = '\0';
- sprintf( buf, "[%d] %d/%d: %s [%02d:%02d:%02d]", ed->depth, ed->an_move_index,
+ snprintf( buf, sizeof(buf)/sizeof(buf[0]), "[%d] %d/%d: %s [%02d:%02d:%02d]", ed->depth, ed->an_move_index,
ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );
}
unsigned long nps_100 = ed->nodes / ed->time;
if( nps_100 < 100000 ) {
- sprintf( s_label, "NPS: %lu", nps_100 * 100 );
+ snprintf( s_label, sizeof(s_label)/sizeof(s_label[0]), "NPS: %lu", nps_100 * 100 );
}
else {
- sprintf( s_label, "NPS: %.1fk", nps_100 / 10.0 );
+ snprintf( s_label, sizeof(s_label)/sizeof(s_label[0]), "NPS: %.1fk", nps_100 / 10.0 );
}
}
/* Nodes */
if( ed->nodes < 1000000 ) {
- sprintf( s_nodes, u64Display, ed->nodes );
+ snprintf( s_nodes, sizeof(s_nodes)/sizeof(s_nodes[0]), u64Display, ed->nodes );
}
else {
- sprintf( s_nodes, "%.1fM", u64ToDouble(ed->nodes) / 1000000.0 );
+ snprintf( s_nodes, sizeof(s_nodes)/sizeof(s_nodes[0]), "%.1fM", u64ToDouble(ed->nodes) / 1000000.0 );
}
/* Score */
- if( ed->score > 0 ) {
- sprintf( s_score, "+%.2f", ed->score / 100.0 );
+ h = ((gameMode == AnalyzeMode && appData.whitePOV || appData.scoreWhite) && !WhiteOnMove(currentMove) ? -1 : 1) * ed->score;
+ if( h > 0 ) {
+ snprintf( s_score, sizeof(s_score)/sizeof(s_score[0]), "+%.2f", h / 100.0 );
}
else {
- sprintf( s_score, "%.2f", ed->score / 100.0 );
+ snprintf( s_score, sizeof(s_score)/sizeof(s_score[0]), "%.2f", h / 100.0 );
}
/* Time */
- sprintf( s_time, "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );
+ snprintf( s_time, sizeof(s_time)/sizeof(s_time[0]), "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );
/* Put all together... */
- if(ed->nodes == 0 && ed->score == 0 && ed->time == 0) sprintf( buf, "%3d\t", ed->depth ); else
- sprintf( buf, "%3d\t%s\t%s\t%s\t", ed->depth, s_score, s_nodes, s_time );
+ if(ed->nodes == 0 && ed->score == 0 && ed->time == 0)
+ snprintf( buf, sizeof(buf)/sizeof(buf[0]), "%3d\t", ed->depth );
+ else
+ snprintf( buf, sizeof(buf)/sizeof(buf[0]), "%3d\t%s\t%s\t%s\t", ed->depth, s_score, s_nodes, s_time );
/* Add PV */
buflen = strlen(buf);
/* Update memo */
InsertIntoMemo( ed->which, buf, InsertionPoint(strlen(buf), ed) );
+ strncpy(lastLine[ed->which], buf, MSG_SIZ);
}
/* Colors */
}
opponentKibitzes = TRUE; // this causes split window DisplayMode in ICS modes.
VerifyDisplayMode();
+ strncpy(text+strlen(text)-1, "\r\n",sizeof(text+strlen(text)-1)); // to not lose line breaks on copying
if(gameMode == IcsObserving) {
DoSetWindowText(0, nLabel, gameInfo.white);
SetIcon( 0, nColorIcon, nColorWhite);