release of version 4.4.2
[xboard.git] / backend.c
index 342b6f8..b9348a9 100755 (executable)
--- a/backend.c
+++ b/backend.c
@@ -168,7 +168,7 @@ int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
 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));
@@ -2042,7 +2042,7 @@ read_from_ics(isr, closure, data, count, error)
      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
@@ -3134,6 +3134,7 @@ read_from_ics(isr, closure, data, count, error)
                    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);
@@ -5345,7 +5346,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
         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]);
@@ -6223,15 +6224,6 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
                 } 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;
@@ -6932,7 +6924,12 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
 
                 /* [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;
                 }
@@ -9949,17 +9946,9 @@ SaveGamePGN(f)
         /* [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 {
@@ -10088,7 +10077,7 @@ SaveGame(f, dummy, dummy2)
      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);
@@ -10128,7 +10117,8 @@ SavePosition(f, dummy, dummy2)
 {
     time_t tm;
     char *fen;
-    
+
+    if (gameMode == EditPosition) EditPositionDone(TRUE);
     if (appData.oldSaveStyle) {
        tm = time((time_t *) NULL);
     
@@ -10706,7 +10696,7 @@ MachineWhiteEvent()
        EditGameEvent();
 
     if (gameMode == EditPosition) 
-        EditPositionDone();
+        EditPositionDone(TRUE);
 
     if (!WhiteOnMove(currentMove)) {
        DisplayError(_("It is not White's turn"), 0);
@@ -10787,7 +10777,7 @@ MachineBlackEvent()
         EditGameEvent();
 
     if (gameMode == EditPosition) 
-        EditPositionDone();
+        EditPositionDone(TRUE);
 
     if (WhiteOnMove(currentMove)) {
        DisplayError(_("It is not Black's turn"), 0);
@@ -10894,7 +10884,7 @@ TwoMachinesEvent P((void))
        if (gameMode != EditGame) return;
        break;
       case EditPosition:
-       EditPositionDone();
+       EditPositionDone(TRUE);
        break;
       case AnalyzeMode:
       case AnalyzeFile:
@@ -11032,7 +11022,7 @@ IcsClientEvent()
        break;
 
       case EditPosition:
-       EditPositionDone();
+       EditPositionDone(TRUE);
        break;
 
       case AnalyzeMode:
@@ -11073,7 +11063,7 @@ EditGameEvent()
        }
        break;
       case EditPosition:
-       EditPositionDone();
+       EditPositionDone(TRUE);
        break;
       case AnalyzeMode:
       case AnalyzeFile:
@@ -11180,21 +11170,30 @@ ExitAnalyzeMode()
 }
 
 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], "");
@@ -12026,7 +12025,7 @@ BookEvent()
        }
        break;
       case EditPosition:
-       EditPositionDone();
+       EditPositionDone(TRUE);
        break;
       case TwoMachinesPlay:
        return;
@@ -12890,7 +12889,7 @@ PonderNextMoveEvent(newState)
      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) {
@@ -12913,7 +12912,7 @@ NewSettingEvent(option, command, value)
 {
     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) {
@@ -12932,7 +12931,7 @@ ShowThinkingEvent()
     
     if (oldState == newState) return;
     oldState = newState;
-    if (gameMode == EditPosition) EditPositionDone();
+    if (gameMode == EditPosition) EditPositionDone(TRUE);
     if (oldState) {
        SendToProgram("post\n", &first);
        if (gameMode == TwoMachinesPlay) {
@@ -13684,7 +13683,7 @@ PositionToFEN(move, overrideCastling)
     *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;
@@ -14023,7 +14022,7 @@ EditPositionPasteFEN(char *fen)
               for( i=0; i<nrCastlingRights; i++ )
                   castlingRights[0][i] = FENcastlingRights[i];
           }
-      EditPositionDone();
+      EditPositionDone(FALSE);
       DisplayBothClocks();
       DrawPosition(FALSE, boards[currentMove]);
     }