void BackwardInner P((int target));
void ForwardInner P((int target));
void GameEnds P((ChessMove result, char *resultDetails, int whosays));
-void EditPositionDone P((void));
+void EditPositionDone P((Boolean fakeRights));
void PrintOpponents P((FILE *fp));
void PrintPosition P((FILE *fp, int move));
void StartChessProgram P((ChessProgramState *cps));
void ParseGameHistory P((char *game));
void ParseBoard12 P((char *string));
+void KeepAlive P((void));
void StartClocks P((void));
void SwitchClocks P((void));
void StopClocks P((void));
int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS */
VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */
int lastIndex = 0; /* [HGM] autoinc: last game/position used in match mode */
+Boolean connectionAlive;/* [HGM] alive: ICS connection status from probing */
int opponentKibitzes;
int lastSavedGame; /* [HGM] save: ID of game */
char chatPartner[MAX_CHAT][MSG_SIZ]; /* [HGM] chat: list of chatting partners */
/* [HGM] time odds: set factor for each machine */
first.timeOdds = appData.firstTimeOdds;
second.timeOdds = appData.secondTimeOdds;
- { int norm = 1;
+ { float norm = 1;
if(appData.timeOddsMode) {
norm = first.timeOdds;
if(norm > second.timeOdds) norm = second.timeOdds;
AddInputSource(icsPR, FALSE, read_from_ics, &telnetISR);
fromUserISR =
AddInputSource(NoProc, FALSE, read_from_player, &fromUserISR);
+ if(appData.keepAlive) // [HGM] alive: schedule sending of dummy 'date' command
+ ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
} else if (appData.noChessProgram) {
SetNCPMode();
} else {
void
KeepAlive()
{ // [HGM] alive: periodically send dummy (date) command to ICS to prevent time-out
+ if(!connectionAlive) DisplayFatalError("No response from ICS", 0, 1);
+ connectionAlive = FALSE; // only sticks if no response to 'date' command.
SendToICS("date\n");
if(appData.keepAlive) ScheduleDelayedEvent(KeepAlive, appData.keepAlive*60*1000);
}
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
char talker[MSG_SIZ]; // [HGM] chat
int channel;
+ connectionAlive = TRUE; // [HGM] alive: I think, therefore I am...
+
if (appData.debugMode) {
if (!error) {
fprintf(debugFP, "<ICS: ");
strncmp(why, "Continuing ", 11) == 0) {
gs_gamenum = gamenum;
strcpy(gs_kind, strchr(why, ' ') + 1);
+ VariantSwitch(boards[currentMove], StringToVariant(gs_kind)); // [HGM] variantswitch: even before we get first board
#if ZIPPY
if (appData.zippyPlay) {
ZippyGameStart(whitename, blackname);
for(k=BOARD_LEFT; k<BOARD_RGHT; k++)
if(board[BOARD_HEIGHT-1][k] == bKing)
initialRights[5] = castlingRights[moveNum][5] = k;
+ if(gameInfo.variant == VariantTwoKings) {
+ // In TwoKings looking for a King does not work, so always give castling rights to a King on e1/e8
+ if(board[0][4] == wKing) initialRights[2] = castlingRights[moveNum][2] = 4;
+ if(board[BOARD_HEIGHT-1][4] == bKing) initialRights[5] = castlingRights[moveNum][5] = 4;
+ }
} else { int r;
r = castlingRights[moveNum][0] = initialRights[0];
if(board[0][r] != WhiteRook) castlingRights[moveNum][0] = -1;
if (appData.testLegality) {
return (*moveType != IllegalMove);
} else {
- return !(fromX == fromY && toX == toY);
+ return !(*fromX == *toX && *fromY == *toY);
}
case WhiteDrop:
break;
case VariantFairy:
pieces = fairyArray;
- SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");
+ SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVLSUKpnbrqfeacwmohijgdvlsuk");
break;
case VariantGreat:
pieces = GreatArray;
moveType = PromoCharToMoveType(WhiteOnMove(currentMove), 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]);
} else moveCount = 6;
}
}
-
- 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]);
-
- }
/* Check for rep-draws */
count = 0;
/* [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;
}
/* [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 {
int dummy;
char *dummy2;
{
- if (gameMode == EditPosition) EditPositionDone();
+ if (gameMode == EditPosition) EditPositionDone(TRUE);
lastSavedGame = GameCheckSum(); // [HGM] save: remember ID of last saved game to prevent double saving
if (appData.oldSaveStyle)
return SaveGameOldStyle(f);
{
time_t tm;
char *fen;
-
+
+ if (gameMode == EditPosition) EditPositionDone(TRUE);
if (appData.oldSaveStyle) {
tm = time((time_t *) NULL);
EditGameEvent();
if (gameMode == EditPosition)
- EditPositionDone();
+ EditPositionDone(TRUE);
if (!WhiteOnMove(currentMove)) {
DisplayError(_("It is not White's turn"), 0);
EditGameEvent();
if (gameMode == EditPosition)
- EditPositionDone();
+ EditPositionDone(TRUE);
if (WhiteOnMove(currentMove)) {
DisplayError(_("It is not Black's turn"), 0);
if (gameMode != EditGame) return;
break;
case EditPosition:
- EditPositionDone();
+ EditPositionDone(TRUE);
break;
case AnalyzeMode:
case AnalyzeFile:
break;
case EditPosition:
- EditPositionDone();
+ EditPositionDone(TRUE);
break;
case AnalyzeMode:
}
break;
case EditPosition:
- EditPositionDone();
+ EditPositionDone(TRUE);
break;
case AnalyzeMode:
case AnalyzeFile:
}
void
-EditPositionDone()
+EditPositionDone(Boolean fakeRights)
{
int king = gameInfo.variant == VariantKnightmate ? WhiteUnicorn : WhiteKing;
startedFromSetupPosition = TRUE;
InitChessProgram(&first, FALSE);
- castlingRights[0][2] = castlingRights[0][5] = BOARD_WIDTH>>1;
- if(boards[0][0][BOARD_WIDTH>>1] == king) {
- castlingRights[0][1] = boards[0][0][BOARD_LEFT] == WhiteRook ? 0 : -1;
- castlingRights[0][0] = boards[0][0][BOARD_RGHT-1] == WhiteRook ? BOARD_RGHT-1 : -1;
- } else castlingRights[0][2] = -1;
- if(boards[0][BOARD_HEIGHT-1][BOARD_WIDTH>>1] == WHITE_TO_BLACK king) {
- castlingRights[0][4] = boards[0][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook ? 0 : -1;
- castlingRights[0][3] = boards[0][BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook ? BOARD_RGHT-1 : -1;
- } else castlingRights[0][5] = -1;
+ if(fakeRights)
+ { /* don't do this if we just pasted FEN */
+ castlingRights[0][2] = castlingRights[0][5] = BOARD_WIDTH>>1;
+ if(boards[0][0][BOARD_WIDTH>>1] == king)
+ {
+ castlingRights[0][1] = boards[0][0][BOARD_LEFT] == WhiteRook ? 0 : -1;
+ castlingRights[0][0] = boards[0][0][BOARD_RGHT-1] == WhiteRook ? BOARD_RGHT-1 : -1;
+ }
+ else
+ castlingRights[0][2] = -1;
+ if(boards[0][BOARD_HEIGHT-1][BOARD_WIDTH>>1] == WHITE_TO_BLACK king)
+ {
+ castlingRights[0][4] = boards[0][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook ? 0 : -1;
+ castlingRights[0][3] = boards[0][BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook ? BOARD_RGHT-1 : -1;
+ }
+ else
+ castlingRights[0][5] = -1;
+ }
SendToProgram("force\n", &first);
if (blackPlaysFirst) {
strcpy(moveList[0], "");
}
break;
case EditPosition:
- EditPositionDone();
+ EditPositionDone(TRUE);
break;
case TwoMachinesPlay:
return;
/* [HGM] translate opponent's time by time-odds factor */
otime = (otime * cps->other->timeOdds) / cps->timeOdds;
if (appData.debugMode) {
- fprintf(debugFP, "time odds: %d %d \n", cps->timeOdds, cps->other->timeOdds);
+ fprintf(debugFP, "time odds: %f %f \n", cps->timeOdds, cps->other->timeOdds);
}
if (time <= 0) time = 1;
int newState;
{
if (newState == appData.ponderNextMove) return;
- if (gameMode == EditPosition) EditPositionDone();
+ if (gameMode == EditPosition) EditPositionDone(TRUE);
if (newState) {
SendToProgram("hard\n", &first);
if (gameMode == TwoMachinesPlay) {
{
char buf[MSG_SIZ];
- if (gameMode == EditPosition) EditPositionDone();
+ if (gameMode == EditPosition) EditPositionDone(TRUE);
sprintf(buf, "%s%s %d\n", (option ? "option ": ""), command, value);
SendToProgram(buf, &first);
if (gameMode == TwoMachinesPlay) {
if (oldState == newState) return;
oldState = newState;
- if (gameMode == EditPosition) EditPositionDone();
+ if (gameMode == EditPosition) EditPositionDone(TRUE);
if (oldState) {
SendToProgram("post\n", &first);
if (gameMode == TwoMachinesPlay) {
*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;
} /* assume possible unless obviously impossible */
if(initialRights[0]>=0 && board[castlingRank[0]][initialRights[0]] != WhiteRook) FENcastlingRights[0] = -1;
if(initialRights[1]>=0 && board[castlingRank[1]][initialRights[1]] != WhiteRook) FENcastlingRights[1] = -1;
- if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1;
+ if(initialRights[2]>=0 && board[castlingRank[2]][initialRights[2]] != WhiteUnicorn
+ && board[castlingRank[2]][initialRights[2]] != WhiteKing) FENcastlingRights[2] = -1;
if(initialRights[3]>=0 && board[castlingRank[3]][initialRights[3]] != BlackRook) FENcastlingRights[3] = -1;
if(initialRights[4]>=0 && board[castlingRank[4]][initialRights[4]] != BlackRook) FENcastlingRights[4] = -1;
- if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1;
+ if(initialRights[5]>=0 && board[castlingRank[5]][initialRights[5]] != BlackUnicorn
+ && board[castlingRank[5]][initialRights[5]] != BlackKing) FENcastlingRights[5] = -1;
FENrulePlies = 0;
while(*p==' ') p++;
if(board[BOARD_HEIGHT-1][i] == BlackKing) blackKingFile = i;
if(board[0 ][i] == WhiteKing) whiteKingFile = i;
}
+ if(gameInfo.variant == VariantTwoKings || gameInfo.variant == VariantKnightmate)
+ whiteKingFile = blackKingFile = BOARD_WIDTH >> 1; // scanning fails in these variants
+ if(whiteKingFile<0 || board[0][whiteKingFile]!=WhiteUnicorn
+ && board[0][whiteKingFile]!=WhiteKing) whiteKingFile = -1;
+ if(blackKingFile<0 || board[BOARD_HEIGHT-1][blackKingFile]!=BlackUnicorn
+ && board[BOARD_HEIGHT-1][blackKingFile]!=BlackKing) blackKingFile = -1;
switch(c) {
case'K':
- for(i=BOARD_RGHT-1; board[0][i]!=WhiteRook && i>whiteKingFile; i--);
+ for(i=BOARD_RGHT-1; i>whiteKingFile && board[0][i]!=WhiteRook; i--);
FENcastlingRights[0] = i != whiteKingFile ? i : -1;
FENcastlingRights[2] = whiteKingFile;
break;
FENcastlingRights[2] = whiteKingFile;
break;
case'k':
- for(i=BOARD_RGHT-1; board[BOARD_HEIGHT-1][i]!=BlackRook && i>blackKingFile; i--);
+ for(i=BOARD_RGHT-1; i>blackKingFile && board[BOARD_HEIGHT-1][i]!=BlackRook; i--);
FENcastlingRights[3] = i != blackKingFile ? i : -1;
FENcastlingRights[5] = blackKingFile;
break;
}
}
}
+ for(i=0; i<nrCastlingRights; i++)
+ if(FENcastlingRights[i] >= 0) initialRights[i] = FENcastlingRights[i];
if (appData.debugMode) {
fprintf(debugFP, "FEN castling rights:");
for(i=0; i<nrCastlingRights; i++)
for( i=0; i<nrCastlingRights; i++ )
castlingRights[0][i] = FENcastlingRights[i];
}
- EditPositionDone();
+ EditPositionDone(FALSE);
DisplayBothClocks();
DrawPosition(FALSE, boards[currentMove]);
}