fixed syntax error in texi file
[xboard.git] / backend.c
index 7dfb130..0e36ec2 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -2,8 +2,10 @@
  * backend.c -- Common back end for X and Windows NT versions of\r
  * XBoard $Id: backend.c,v 2.6 2003/11/28 09:37:36 mann Exp $\r
  *\r
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
- * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.\r
+ * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
+ * Massachusetts.  Enhancements Copyright\r
+ * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software\r
+ * Foundation, Inc.\r
  *\r
  * The following terms apply to Digital Equipment Corporation's copyright\r
  * interest in XBoard:\r
  * SOFTWARE.\r
  * ------------------------------------------------------------------------\r
  *\r
- * The following terms apply to the enhanced version of XBoard distributed\r
- * by the Free Software Foundation:\r
+ * The following terms apply to the enhanced version of XBoard\r
+ * distributed by the Free Software Foundation:\r
  * ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
+ *\r
+ * GNU XBoard is free software: you can redistribute it and/or modify\r
  * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
  *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
+ * GNU XBoard is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more details.\r
  *\r
  * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * ------------------------------------------------------------------------\r
+ * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
  *\r
- * See the file ChangeLog for a revision history.  */\r
+ *------------------------------------------------------------------------\r
+ ** See the file ChangeLog for a revision history.  */\r
 \r
 /* [AS] Also useful here for debugging */\r
 #ifdef WIN32\r
@@ -68,6 +70,7 @@
 #include <sys/types.h>\r
 #include <sys/stat.h>\r
 #include <math.h>\r
+#include <ctype.h>\r
 \r
 #if STDC_HEADERS\r
 # include <stdlib.h>\r
@@ -208,6 +211,10 @@ void ParseFeatures P((char* args, ChessProgramState *cps));
 void InitBackEnd3 P((void));\r
 void FeatureDone P((ChessProgramState* cps, int val));\r
 void InitChessProgram P((ChessProgramState *cps, int setup));\r
+void OutputKibitz(int window, char *text);\r
+int PerpetualChase(int first, int last);\r
+int EngineOutputIsUp();\r
+void InitDrawingSizes(int x, int y);\r
 \r
 #ifdef WIN32\r
        extern void ConsoleCreate();\r
@@ -226,8 +233,7 @@ extern char installDir[MSG_SIZ];
 extern int tinyLayout, smallLayout;\r
 ChessProgramStats programStats;\r
 static int exiting = 0; /* [HGM] moved to top */\r
-static int setboardSpoiledMachineBlack = 0, errorExitFlag = 0;\r
-extern int startedFromPositionFile;\r
+static int setboardSpoiledMachineBlack = 0 /*, errorExitFlag = 0*/;\r
 int startedFromPositionFile = FALSE; Board filePosition;       /* [HGM] loadPos */\r
 char endingGame = 0;    /* [HGM] crash: flag to prevent recursion of GameEnds() */\r
 int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS     */\r
@@ -288,6 +294,8 @@ static char * safeStrCpy( char * dst, const char * src, size_t count )
     return dst;\r
 }\r
 \r
+#if 0\r
+//[HGM] for future use? Conditioned out for now to suppress warning.\r
 static char * safeStrCat( char * dst, const char * src, size_t count )\r
 {\r
     size_t  dst_len;\r
@@ -304,6 +312,7 @@ static char * safeStrCat( char * dst, const char * src, size_t count )
 \r
     return dst;\r
 }\r
+#endif\r
 \r
 /* Some compiler can't cast u64 to double\r
  * This function do the job for us:\r
@@ -1941,7 +1950,7 @@ VariantSwitch(Board board, VariantClass newVariant)
 {\r
    int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j;\r
    int oldCurrentMove = currentMove, oldForwardMostMove = forwardMostMove, oldBackwardMostMove = backwardMostMove;\r
-   Board tempBoard; int saveCastling[BOARD_SIZE], saveEP;\r
+//   Board tempBoard; int saveCastling[BOARD_SIZE], saveEP;\r
 \r
    startedFromPositionFile = FALSE;\r
    if(gameInfo.variant == newVariant) return;\r
@@ -2357,10 +2366,10 @@ read_from_ics(isr, closure, data, count, error)
                   (StrStr(star_match[0], gameInfo.white) == star_match[0] || \r
                    StrStr(star_match[0], gameInfo.black) == star_match[0]   )) { // kibitz of self or opponent\r
                        suppressKibitz = TRUE;\r
-                       if((StrStr(star_match[0], gameInfo.white) == star_match[0])\r
-                               && (gameMode == IcsPlayingWhite) ||\r
-                          (StrStr(star_match[0], gameInfo.black) == star_match[0])\r
-                               && (gameMode == IcsPlayingBlack)   ) // opponent kibitz\r
+                       if((StrStr(star_match[0], gameInfo.white) == star_match[0]\r
+                               && (gameMode == IcsPlayingWhite)) ||\r
+                          (StrStr(star_match[0], gameInfo.black) == star_match[0]\r
+                               && (gameMode == IcsPlayingBlack))   ) // opponent kibitz\r
                            started = STARTED_CHATTER; // own kibitz we simply discard\r
                        else {\r
                            started = STARTED_COMMENT; // make sure it will be collected in parse[]\r
@@ -2850,7 +2859,7 @@ read_from_ics(isr, closure, data, count, error)
                if(bookHit) { // [HGM] book: simulate book reply\r
                    static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
-                   programStats.depth = programStats.nodes = programStats.time = \r
+                   programStats.nodes = programStats.depth = programStats.time = \r
                    programStats.score = programStats.got_only_move = 0;\r
                    sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -3880,7 +3889,7 @@ ParseBoard12(string)
     if(bookHit) { // [HGM] book: simulate book reply\r
        static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
-       programStats.depth = programStats.nodes = programStats.time = \r
+       programStats.nodes = programStats.depth = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
        sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -4100,7 +4109,7 @@ ProcessICSInitScript(f)
 void\r
 AlphaRank(char *move, int n)\r
 {\r
-    char *p = move, c; int x, y;\r
+//    char *p = move, c; int x, y;\r
 \r
     if (appData.debugMode) {\r
         fprintf(debugFP, "alphaRank(%s,%d)\n", move, n);\r
@@ -4244,6 +4253,7 @@ ParseOneMove(move, moveNum, moveType, fromX, fromY, toX, toY, promoChar)
     }\r
 }\r
 \r
+#if 0\r
 /* [AS] FRC game initialization */\r
 static int FindEmptySquare( Board board, int n )\r
 {\r
@@ -4260,7 +4270,6 @@ static int FindEmptySquare( Board board, int n )
     return i;\r
 }\r
 \r
-#if 0\r
 static void ShuffleFRC( Board board )\r
 {\r
     int i;\r
@@ -4352,7 +4361,7 @@ static void SetupFRC( Board board, int pos_index )
 \r
 int squaresLeft[4];\r
 int piecesLeft[(int)BlackPawn];\r
-long long int seed, nrOfShuffles;\r
+u64 seed, nrOfShuffles;\r
 \r
 void GetPositionNumber()\r
 {      // sets global variable seed\r
@@ -4373,9 +4382,9 @@ int put(Board board, int pieceType, int rank, int n, int shade)
        int i;\r
 \r
        for(i=BOARD_LEFT; i<BOARD_RGHT; i++) {\r
-               if( ((i-BOARD_LEFT)&1)+1 & shade && board[rank][i] == EmptySquare && n-- == 0) {\r
+               if( (((i-BOARD_LEFT)&1)+1) & shade && board[rank][i] == EmptySquare && n-- == 0) {\r
                        board[rank][i] = (ChessSquare) pieceType;\r
-                       squaresLeft[(i-BOARD_LEFT&1) + 1]--;\r
+                       squaresLeft[((i-BOARD_LEFT)&1) + 1]--;\r
                        squaresLeft[ANY]--;\r
                        piecesLeft[pieceType]--; \r
                        return i;\r
@@ -4442,7 +4451,7 @@ void SetUpShuffle(Board board, int number)
            // in variants with super-numerary Kings and Rooks, we leave these for the shuffle\r
        }\r
 \r
-       if((BOARD_RGHT-BOARD_LEFT & 1) == 0)\r
+       if(((BOARD_RGHT-BOARD_LEFT) & 1) == 0)\r
            // only for even boards make effort to put pairs of colorbound pieces on opposite colors\r
            for(p = (int) WhiteKing; p > (int) WhitePawn; p--) {\r
                if(p != (int) WhiteBishop && p != (int) WhiteFerz && p != (int) WhiteAlfil) continue;\r
@@ -4643,10 +4652,10 @@ InitPosition(redraw)
       nrCastlingRights = 6;\r
         castlingRights[0][0] = initialRights[0] = BOARD_RGHT-1;\r
         castlingRights[0][1] = initialRights[1] = BOARD_LEFT;\r
-        castlingRights[0][2] = initialRights[2] = BOARD_WIDTH-1>>1;\r
+        castlingRights[0][2] = initialRights[2] =(BOARD_WIDTH-1)>>1;\r
         castlingRights[0][3] = initialRights[3] = BOARD_RGHT-1;\r
         castlingRights[0][4] = initialRights[4] = BOARD_LEFT;\r
-        castlingRights[0][5] = initialRights[5] = BOARD_WIDTH-1>>1;\r
+        castlingRights[0][5] = initialRights[5] =(BOARD_WIDTH-1)>>1;\r
       break;\r
     case VariantFalcon:\r
       pieces = FalconArray;\r
@@ -5440,7 +5449,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", move
   if(bookHit) { // [HGM] book: simulate book reply\r
        static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
-       programStats.depth = programStats.nodes = programStats.time = \r
+       programStats.nodes = programStats.depth = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
        sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -5473,7 +5482,7 @@ if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", move
 \r
 void SendProgramStatsToFrontend( ChessProgramState * cps, ChessProgramStats * cpstats )\r
 {\r
-    char * hint = lastHint;\r
+//    char * hint = lastHint;\r
     FrontEndProgramStats stats;\r
 \r
     stats.which = cps == &first ? 0 : 1;\r
@@ -5667,8 +5676,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
             sprintf(buf1, _("Illegal move \"%s\" from %s machine"),\r
                    machineMove, cps->which);\r
            DisplayError(buf1, 0);\r
-            sprintf(buf1, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d%c",\r
-                    machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, 0);\r
+            sprintf(buf1, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d",\r
+                    machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, moveType);\r
            if (gameMode == TwoMachinesPlay) {\r
              GameEnds(machineWhite ? BlackWins : WhiteWins,\r
                        buf1, GE_XBOARD);\r
@@ -5713,6 +5722,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                toX--;\r
                currentMoveString[2]--;\r
                break;\r
+            default: ; // nothing to do, but suppresses warning of pedantic compilers\r
            }\r
         }\r
        hintRequested = FALSE;\r
@@ -5735,8 +5745,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                        programStats.depth,\r
                        programStats.score / 100.,\r
                        programStats.time / 100.,\r
-                       (double) programStats.nodes,\r
-                       programStats.nodes / (10*abs(programStats.time) + 1.),\r
+                       u64ToDouble(programStats.nodes),\r
+                       u64ToDouble(programStats.nodes) / (10*abs(programStats.time) + 1.),\r
                        programStats.movelist);\r
                SendToICS(buf);\r
          }\r
@@ -5825,7 +5835,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
            {   /* [HGM] Some more adjudications for obstinate engines */\r
                int NrWN=0, NrBN=0, NrWB=0, NrBB=0, NrWR=0, NrBR=0,\r
                     NrWQ=0, NrBQ=0, NrW=0, bishopsColor = 0,\r
-                    NrPieces=0, NrPawns=0, PawnAdvance=0, i, j, k;\r
+                    NrPieces=0, NrPawns=0, PawnAdvance=0, i, j;\r
                static int moveCount = 6;\r
 \r
                 /* First absolutely insufficient mating material. Count what is on board. */\r
@@ -5871,7 +5881,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                    }\r
                 }\r
 \r
-                if( NrPieces == 2 || gameInfo.variant != VariantXiangqi &&\r
+                if( NrPieces == 2 || gameInfo.variant != VariantXiangqi && \r
+                                    gameInfo.variant != VariantShatranj && // [HGM] baring will remain possible\r
                        (NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 ||\r
                         NrPieces == NrBB+NrWB+2 && bishopsColor != 3)) // [HGM] all Bishops (Ferz!) same color\r
                 {    /* KBK, KNK, KK of KBKB with like Bishops */\r
@@ -5994,6 +6005,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                                                        EP_NONE, castlingRights[m-1]) != MT_CHECK)\r
                                        hisPerpetual = 0; // the opponent did not always check\r
                                }\r
+                               if(appData.debugMode) fprintf(debugFP, "XQ perpetual test, our=%d, his=%d\n",\r
+                                                                       ourPerpetual, hisPerpetual);\r
                                if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit\r
                                    GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, \r
                                           "Xboard adjudication: perpetual checking", GE_XBOARD );\r
@@ -6001,8 +6014,19 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                                }\r
                                if(hisPerpetual && !ourPerpetual)   // he is checking us, but did not repeat yet\r
                                    break; // (or we would have caught him before). Abort repetition-checking loop.\r
-                               // if neither of us is checking all the time, or both are, it is draw\r
-                               // (illegal-chase forfeits not implemented yet!)\r
+                               // Now check for perpetual chases\r
+                               if(!ourPerpetual && !hisPerpetual) { // no perpetual check, test for chase\r
+                                   hisPerpetual = PerpetualChase(k, forwardMostMove);\r
+                                   ourPerpetual = PerpetualChase(k+1, forwardMostMove);\r
+                                   if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit\r
+                                       GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, \r
+                                                     "Xboard adjudication: perpetual chasing", GE_XBOARD );\r
+                                       return;\r
+                                   }\r
+                                   if(hisPerpetual && !ourPerpetual)   // he is chasing us, but did not repeat yet\r
+                                       break; // Abort repetition-checking loop.\r
+                               }\r
+                               // if neither of us is checking or chasing all the time, or both are, it is draw\r
                             }\r
                              GameEnds( GameIsDrawn, "Xboard adjudication: repetition draw", GE_XBOARD );\r
                              return;\r
@@ -6111,7 +6135,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                strcat(bookMove, bookHit);\r
                message = bookMove;\r
                cps = cps->other;\r
-               programStats.depth = programStats.nodes = programStats.time = \r
+               programStats.nodes = programStats.depth = programStats.time = \r
                programStats.score = programStats.got_only_move = 0;\r
                sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -6645,8 +6669,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                if(cps->nps >= 0) { /* [HGM] nps: use engine nodes or time to decrement clock */\r
                        int ticklen;\r
 \r
-                       if(cps->nps == 0) ticklen = 10*time;       // use engine reported time\r
-                       else ticklen = (1000. * nodes) / cps->nps; // convert node count to time\r
+                       if(cps->nps == 0) ticklen = 10*time;                    // use engine reported time\r
+                       else ticklen = (1000. * u64ToDouble(nodes)) / cps->nps; // convert node count to time\r
                        if(WhiteOnMove(forwardMostMove)) \r
                             whiteTimeRemaining = timeRemaining[0][forwardMostMove] - ticklen;\r
                        else blackTimeRemaining = timeRemaining[1][forwardMostMove] - ticklen;\r
@@ -6805,7 +6829,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
         else {\r
            buf1[0] = NULLCHAR;\r
 \r
-           if (sscanf(message, "%d%c %d %d %lu %[^\n]\n",\r
+           if (sscanf(message, "%d%c %d %d " u64Display " %[^\n]\n",\r
                       &plylev, &plyext, &curscore, &time, &nodes, buf1) >= 5) \r
             {\r
                 ChessProgramStats cpstats;\r
@@ -7050,7 +7074,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
     /* [HGM] compute & store e.p. status and castling rights for new position */\r
     /* if we are updating a board for which those exist (i.e. in boards[])    */\r
     if((p = ((int)board - (int)boards[0])/((int)boards[1]-(int)boards[0])) < MAX_MOVES && p > 0)\r
-    { int i, j;\r
+    { int i;\r
 \r
       if(gameInfo.variant == VariantBerolina) berolina = EP_BEROLIN_A;\r
       oldEP = epStatus[p-1];\r
@@ -9501,7 +9525,7 @@ SaveGamePGN(f)
 {\r
     int i, offset, linelen, newblock;\r
     time_t tm;\r
-    char *movetext;\r
+//    char *movetext;\r
     char numtext[32];\r
     int movelen, numlen, blank;\r
     char move_buffer[100]; /* [AS] Buffer for move+PV info */\r
@@ -9610,12 +9634,6 @@ SaveGamePGN(f)
 #else\r
             seconds = (pvInfoList[i].time + 5)/10; // [HGM] PVtime: use engine time\r
 #endif\r
-    if (appData.debugMode,0) {\r
-        fprintf(debugFP, "times = %d %d %d %d, seconds=%d\n",\r
-                timeRemaining[0][i+1], timeRemaining[0][i],\r
-                     timeRemaining[1][i+1], timeRemaining[1][i], seconds\r
-        );\r
-    }\r
 \r
             if( seconds <= 0) buf[0] = 0; else\r
             if( seconds < 30 ) sprintf(buf, " %3.1f%c", seconds/10., 0); else {\r
@@ -10428,7 +10446,7 @@ MachineWhiteEvent()
     if(bookHit) { // [HGM] book: simulate book reply\r
        static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
-       programStats.depth = programStats.nodes = programStats.time = \r
+       programStats.nodes = programStats.depth = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
        sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -10503,7 +10521,7 @@ MachineBlackEvent()
     if(bookHit) { // [HGM] book: simulate book reply\r
        static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
-       programStats.depth = programStats.nodes = programStats.time = \r
+       programStats.nodes = programStats.depth = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
        sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -10649,7 +10667,7 @@ TwoMachinesEvent P((void))
     if(bookHit) { // [HGM] book: simulate book reply\r
        static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
-       programStats.depth = programStats.nodes = programStats.time = \r
+       programStats.nodes = programStats.depth = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
        sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
@@ -12884,6 +12902,11 @@ DisplayBothClocks()
    you have neither ftime nor gettimeofday.\r
 */\r
 \r
+/* VS 2008 requires the #include outside of the function */\r
+#if !HAVE_GETTIMEOFDAY && HAVE_FTIME\r
+#include <sys/timeb.h>\r
+#endif\r
+\r
 /* Get the current time as a TimeMark */\r
 void\r
 GetTimeMark(tm)\r
@@ -12901,7 +12924,7 @@ GetTimeMark(tm)
 #else /*!HAVE_GETTIMEOFDAY*/\r
 #if HAVE_FTIME\r
 \r
-#include <sys/timeb.h>\r
+// include <sys/timeb.h> / moved to just above start of function\r
     struct timeb timeB;\r
 \r
     ftime(&timeB);\r