Use -keepAlive option to determine connection health
[xboard.git] / backend.c
index 31427c3..1e0bf93 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -187,6 +187,7 @@ void DisplayMove P((int moveNumber));
 
 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));
@@ -242,6 +243,7 @@ char endingGame = 0;    /* [HGM] crash: flag to prevent recursion of GameEnds()
 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 */
@@ -1097,6 +1099,8 @@ InitBackEnd3 P((void))
          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 {
@@ -1417,6 +1421,8 @@ read_from_player(isr, closure, message, count, error)
 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);
 }
@@ -2071,6 +2077,8 @@ read_from_ics(isr, closure, data, count, error)
     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: ");
@@ -3700,6 +3708,11 @@ ParseBoard12(string)
         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;
@@ -13895,10 +13908,12 @@ ParseFEN(board, blackPlaysFirst, fen)
     }   /* 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++;
@@ -13919,9 +13934,15 @@ ParseFEN(board, blackPlaysFirst, fen)
             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;
@@ -13931,7 +13952,7 @@ ParseFEN(board, blackPlaysFirst, fen)
               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;
@@ -13968,6 +13989,8 @@ ParseFEN(board, blackPlaysFirst, fen)
               }
         }
       }
+      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++)