Allow -timeIncrement to be a float
[xboard.git] / backend.c
index 67a1c1a..471a065 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -449,7 +449,11 @@ int adjudicateLossPlies = 6;
 char white_holding[64], black_holding[64];
 TimeMark lastNodeCountTime;
 long lastNodeCount=0;
+
 int have_sent_ICS_logon = 0;
+int sending_ICS_login    = 0;
+int sending_ICS_password = 0;
+
 int movesPerSession;
 int suddenDeath, whiteStartMove, blackStartMove; /* [HGM] for implementation of 'any per time' sessions, as in first part of byoyomi TC */
 long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement, lastWhite, lastBlack;
@@ -1023,6 +1027,13 @@ int NextSessionFromString( char ** str, int *moves, long * tc, long *inc, int *i
             if(**str == '!') type = *(*str)++; // Bronstein TC
             if(result = NextIntegerFromString( str, &temp2)) return -1;
             *inc = temp2 * 1000;
+            if(**str == '.') { // read fraction of increment
+                char *start = ++(*str);
+                if(result = NextIntegerFromString( str, &temp2)) return -1;
+                temp2 *= 1000;
+                while(start++ < *str) temp2 /= 10;
+                *inc += temp2;
+            }
         } else *inc = 0;
         *moves = 0; *tc = temp * 1000; *incType = type;
         return 0;
@@ -1065,7 +1076,7 @@ int GetTimeQuota(int movenr, int lastUsed, char *tcString)
 int
 ParseTimeControl(tc, ti, mps)
      char *tc;
-     int ti;
+     float ti;
      int mps;
 {
   long tc1;
@@ -1080,9 +1091,9 @@ ParseTimeControl(tc, ti, mps)
   if(ti > 0) {
 
     if(mps)
-      snprintf(buf, MSG_SIZ, ":%d/%s+%d", mps, mytc, ti);
+      snprintf(buf, MSG_SIZ, ":%d/%s+%g", mps, mytc, ti);
     else 
-      snprintf(buf, MSG_SIZ, ":%s+%d", mytc, ti);
+      snprintf(buf, MSG_SIZ, ":%s+%g", mytc, ti);
   } else {
     if(mps)
       snprintf(buf, MSG_SIZ, ":%d/%s", mps, mytc);
@@ -3108,10 +3119,17 @@ read_from_ics(isr, closure, data, count, error)
            if (!have_sent_ICS_logon && looking_at(buf, &i, "login:")) {
                ICSInitScript();
                have_sent_ICS_logon = 1;
+               sending_ICS_password = 0; // in case we come back to login
+               sending_ICS_login = 1; 
                continue;
            }
-
-           if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ &&
+           /* need to shadow the password */
+           if (!sending_ICS_password && looking_at(buf, &i, "password:")) {
+             sending_ICS_password = 1;
+             continue;
+           }
+             
+           if (ics_getting_history != H_GETTING_MOVES /*smpos kludge*/ && 
                (looking_at(buf, &i, "\n<12> ") ||
                 looking_at(buf, &i, "<12> "))) {
                loggedOn = TRUE;
@@ -3538,7 +3556,7 @@ read_from_ics(isr, closure, data, count, error)
                /*           [4] is " *" or empty (don't care). */
                int gamenum = atoi(star_match[0]);
                char *whitename, *blackname, *why, *endtoken;
-               ChessMove endtype = (ChessMove) 0;
+               ChessMove endtype = EndOfFile;
 
                if (tkind == 0) {
                  whitename = star_match[1];
@@ -4899,7 +4917,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
 
       case AmbiguousMove:
       case ImpossibleMove:
-      case (ChessMove) 0:      /* end of file */
+      case EndOfFile:
       case ElapsedTime:
       case Comment:
       case PGNTag:
@@ -5875,7 +5893,7 @@ FILE *lastLoadGameFP = NULL, *lastLoadPositionFP = NULL;
 int lastLoadGameNumber = 0, lastLoadPositionNumber = 0;
 int lastLoadGameUseList = FALSE;
 char lastLoadGameTitle[MSG_SIZ], lastLoadPositionTitle[MSG_SIZ];
-ChessMove lastLoadGameStart = (ChessMove) 0;
+ChessMove lastLoadGameStart = EndOfFile;
 
 void
 UserMoveEvent(fromX, fromY, toX, toY, promoChar)
@@ -6803,7 +6821,7 @@ Adjudicate(ChessProgramState *cps)
                    case EP_WINS:
                        result = WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins; break;
                    default:
-                       result = (ChessMove) 0;
+                       result = EndOfFile;
                }
                 if(canAdjudicate && appData.checkMates && result) { // [HGM] mates: adjudicate finished games if requested
                    if(engineOpponent)
@@ -8208,7 +8226,7 @@ ParseGameHistory(game)
   }
            DisplayError(buf, 0);
            return;
-         case (ChessMove) 0:   /* end of file */
+         case EndOfFile:
            if (boardIndex < backwardMostMove) {
                /* Oops, gap.  How did that happen? */
                DisplayError(_("Gap in move list"), 0);
@@ -9466,7 +9484,7 @@ Reset(redraw, init)
     gotPremove = FALSE;
     alarmSounded = FALSE;
 
-    GameEnds((ChessMove) 0, NULL, GE_PLAYER);
+    GameEnds(EndOfFile, NULL, GE_PLAYER);
     if(appData.serverMovesName != NULL) {
         /* [HGM] prepare to make moves file for broadcasting */
         clock_t t = clock();
@@ -9591,7 +9609,7 @@ LoadGameOneMove(readAhead)
     }
 
     yyboardindex = forwardMostMove;
-    if (readAhead != (ChessMove)0) {
+    if (readAhead != EndOfFile) {
       moveType = readAhead;
     } else {
       if (gameFileFP == NULL)
@@ -9679,7 +9697,7 @@ LoadGameOneMove(readAhead)
        }
        break;
 
-      case (ChessMove) 0:      /* end of file */
+      case EndOfFile:
        if (appData.debugMode)
          fprintf(debugFP, "Parser hit end of file\n");
        switch (MateTest(boards[currentMove], PosFlags(currentMove)) ) {
@@ -9707,7 +9725,7 @@ LoadGameOneMove(readAhead)
            if (appData.debugMode)
              fprintf(debugFP, "Parser ignoring: '%s' (%d)\n",
                      yy_text, (int) moveType);
-           return LoadGameOneMove((ChessMove)0); /* tail recursion */
+           return LoadGameOneMove(EndOfFile); /* tail recursion */
        }
        /* else fall thru */
 
@@ -9742,7 +9760,7 @@ LoadGameOneMove(readAhead)
        if (appData.debugMode)
          fprintf(debugFP, "Parser ignoring: '%s' (%d)\n",
                  yy_text, (int) moveType);
-       return LoadGameOneMove((ChessMove)0); /* tail recursion */
+       return LoadGameOneMove(EndOfFile); /* tail recursion */
 
       case IllegalMove:
        if (appData.testLegality) {
@@ -10088,12 +10106,12 @@ LoadGame(f, gameNumber, title, useList)
      * 5-4-02: Let's try being more lenient and allowing a game to
      * start with an unnumbered move.  Does that break anything?
      */
-    cm = lastLoadGameStart = (ChessMove) 0;
+    cm = lastLoadGameStart = EndOfFile;
     while (gn > 0) {
        yyboardindex = forwardMostMove;
        cm = (ChessMove) yylex();
        switch (cm) {
-         case (ChessMove) 0:
+         case EndOfFile:
            if (cmailMsgLoaded) {
                nCmailGames = CMAIL_MAX_GAMES - gn;
            } else {
@@ -10115,7 +10133,7 @@ LoadGame(f, gameNumber, title, useList)
              case PGNTag:
                break;
              case MoveNumberOne:
-             case (ChessMove) 0:
+             case EndOfFile:
                gn--;           /* count this game */
                lastLoadGameStart = cm;
                break;
@@ -10130,7 +10148,7 @@ LoadGame(f, gameNumber, title, useList)
              case GNUChessGame:
              case PGNTag:
              case MoveNumberOne:
-             case (ChessMove) 0:
+             case EndOfFile:
                gn--;           /* count this game */
                lastLoadGameStart = cm;
                break;
@@ -10165,7 +10183,7 @@ LoadGame(f, gameNumber, title, useList)
          case NormalMove:
            /* Only a NormalMove can be at the start of a game
             * without a position diagram. */
-           if (lastLoadGameStart == (ChessMove) 0) {
+           if (lastLoadGameStart == EndOfFile ) {
              gn--;
              lastLoadGameStart = MoveNumberOne;
            }
@@ -10185,10 +10203,10 @@ LoadGame(f, gameNumber, title, useList)
            yyboardindex = forwardMostMove;
            cm = (ChessMove) yylex();
 
-           if (cm == (ChessMove) 0 ||
+           if (cm == EndOfFile ||
                cm == GNUChessGame || cm == XBoardGame) {
                /* Empty game; pretend end-of-file and handle later */
-               cm = (ChessMove) 0;
+               cm = EndOfFile;
                break;
            }
 
@@ -10372,7 +10390,7 @@ LoadGame(f, gameNumber, title, useList)
        cm = (ChessMove) yylex();
     }
 
-    if ((cm == (ChessMove) 0 && lastLoadGameStart != (ChessMove) 0) ||
+    if ((cm == EndOfFile && lastLoadGameStart != EndOfFile ) ||
        cm == WhiteWins || cm == BlackWins ||
        cm == GameIsDrawn || cm == GameUnfinished) {
        DisplayMessage("", _("No moves in game"));
@@ -10409,7 +10427,7 @@ LoadGame(f, gameNumber, title, useList)
        LoadGameOneMove(cm);
 
     /* load the remaining moves from the file */
-    while (LoadGameOneMove((ChessMove)0)) {
+    while (LoadGameOneMove(EndOfFile)) {
       timeRemaining[0][forwardMostMove] = whiteTimeRemaining;
       timeRemaining[1][forwardMostMove] = blackTimeRemaining;
     }
@@ -11992,7 +12010,7 @@ EditGameEvent()
        SendToProgram("force\n", &first);
        break;
       case TwoMachinesPlay:
-       GameEnds((ChessMove) 0, NULL, GE_PLAYER);
+       GameEnds(EndOfFile, NULL, GE_PLAYER);
        ResurrectChessProgram();
        SetUserThinkingEnables();
        break;
@@ -13528,9 +13546,9 @@ SendTimeControl(cps, mps, tc, inc, sd, st)
        /* Note old gnuchess bug -- minutes:seconds used to not work.
           Fixed in later versions, but still avoid :seconds
           when seconds is 0. */
-       snprintf(buf, MSG_SIZ, "level %d %ld %d\n", mps, tc/60000, inc/1000);
+       snprintf(buf, MSG_SIZ, "level %d %ld %g\n", mps, tc/60000, inc/1000);
       } else {
-       snprintf(buf, MSG_SIZ, "level %d %ld:%02d %d\n", mps, tc/60000,
+       snprintf(buf, MSG_SIZ, "level %d %ld:%02d %g\n", mps, tc/60000,
                 seconds, inc/1000);
       }
     }
@@ -14864,12 +14882,12 @@ ParseFEN(board, blackPlaysFirst, fen)
     while(*p==' ') p++;
     if( gameInfo.holdingsWidth && p[-1] == '/' || *p == '[') {
         if(*p == '[') p++;
-        if(*p == '-' ) *p++; /* empty holdings */ else {
+        if(*p == '-' ) p++; /* empty holdings */ else {
             if( !gameInfo.holdingsWidth ) return FALSE; /* no room to put holdings! */
             /* if we would allow FEN reading to set board size, we would   */
             /* have to add holdings and shift the board read so far here   */
             while( (piece = CharToPiece(*p) ) != EmptySquare ) {
-                *p++;
+                p++;
                 if((int) piece >= (int) BlackPawn ) {
                     i = (int)piece - (int)BlackPawn;
                    i = PieceToNumber((ChessSquare)i);
@@ -14885,7 +14903,7 @@ ParseFEN(board, blackPlaysFirst, fen)
                 }
             }
         }
-        if(*p == ']') *p++;
+        if(*p == ']') p++;
     }
 
     while(*p == ' ') p++;
@@ -15020,7 +15038,7 @@ ParseFEN(board, blackPlaysFirst, fen)
          char c = *p++ - AAA;
 
          if(c < BOARD_LEFT || c >= BOARD_RGHT) return TRUE;
-         if(*p >= '0' && *p <='9') *p++;
+         if(*p >= '0' && *p <='9') p++;
          board[EP_STATUS] = c;
       }
     }
@@ -15219,11 +15237,11 @@ PopTail(Boolean annotate)
        if(annotate) {
                int cnt = 10;
                if(!WhiteOnMove(currentMove))
-                 snprintf(buf, sizeof(buf)/sizeof(buf[0]),"(%d...", currentMove+2>>1);
+                 snprintf(buf, sizeof(buf)/sizeof(buf[0]),"(%d...", (currentMove+2)>>1);
                else safeStrCpy(buf, "(", sizeof(buf)/sizeof(buf[0]));
                for(i=currentMove; i<forwardMostMove; i++) {
                        if(WhiteOnMove(i))
-                         snprintf(moveBuf, sizeof(moveBuf)/sizeof(moveBuf[0]), " %d. %s", i+2>>1, SavePart(parseList[i]));
+                         snprintf(moveBuf, sizeof(moveBuf)/sizeof(moveBuf[0]), " %d. %s", (i+2)>>1, SavePart(parseList[i]));
                        else snprintf(moveBuf, sizeof(moveBuf)/sizeof(moveBuf[0])," %s", SavePart(parseList[i]));
                        strcat(buf, moveBuf);
                        if(commentList[i]) { strcat(buf, " "); strcat(buf, commentList[i]); }