changes from H.G. Muller; version 4.3.13 v4.3.13
authorH.G. Muller <h.g.muller@hccnet.nl>
Sun, 19 Apr 2009 17:00:52 +0000 (10:00 -0700)
committerArun Persaud <arun@nubati.net>
Sun, 19 Apr 2009 17:32:56 +0000 (10:32 -0700)
194 files changed:
backend.c
backend.h
backendz.h
bitmaps/Thumbs.db [new file with mode: 0644]
bitmaps/a33o.bmp [new file with mode: 0644]
bitmaps/a33s.bmp [new file with mode: 0644]
bitmaps/a33w.bmp [new file with mode: 0644]
bitmaps/a37o.bmp [new file with mode: 0644]
bitmaps/a37s.bmp [new file with mode: 0644]
bitmaps/a37w.bmp [new file with mode: 0644]
bitmaps/a40o.bmp [new file with mode: 0644]
bitmaps/a40s.bmp [new file with mode: 0644]
bitmaps/a40w.bmp [new file with mode: 0644]
bitmaps/a45o.bmp [new file with mode: 0644]
bitmaps/a45s.bmp [new file with mode: 0644]
bitmaps/a45w.bmp [new file with mode: 0644]
bitmaps/a54o.bmp [new file with mode: 0644]
bitmaps/a54s.bmp [new file with mode: 0644]
bitmaps/a54w.bmp [new file with mode: 0644]
bitmaps/a58o.bmp [new file with mode: 0644]
bitmaps/a58s.bmp [new file with mode: 0644]
bitmaps/a58w.bmp [new file with mode: 0644]
bitmaps/a64o.bmp [new file with mode: 0644]
bitmaps/a64s.bmp [new file with mode: 0644]
bitmaps/a64w.bmp [new file with mode: 0644]
bitmaps/as33o.bmp [new file with mode: 0644]
bitmaps/as33s.bmp [new file with mode: 0644]
bitmaps/as33w.bmp [new file with mode: 0644]
bitmaps/as45o.bmp [new file with mode: 0644]
bitmaps/as45s.bmp [new file with mode: 0644]
bitmaps/as45w.bmp [new file with mode: 0644]
bitmaps/as49o.bmp [new file with mode: 0644]
bitmaps/as49s.bmp [new file with mode: 0644]
bitmaps/as49w.bmp [new file with mode: 0644]
bitmaps/as72o.bmp [new file with mode: 0644]
bitmaps/as72s.bmp [new file with mode: 0644]
bitmaps/as72w.bmp [new file with mode: 0644]
bitmaps/bas.gif [new file with mode: 0644]
bitmaps/bcv.gif [new file with mode: 0644]
bitmaps/bitmaps.h
bitmaps/c33o.bmp [new file with mode: 0644]
bitmaps/c33s.bmp [new file with mode: 0644]
bitmaps/c33w.bmp [new file with mode: 0644]
bitmaps/c37o.bmp [new file with mode: 0644]
bitmaps/c37s.bmp [new file with mode: 0644]
bitmaps/c37w.bmp [new file with mode: 0644]
bitmaps/c40o.bmp [new file with mode: 0644]
bitmaps/c40s.bmp [new file with mode: 0644]
bitmaps/c40w.bmp [new file with mode: 0644]
bitmaps/c45o.bmp [new file with mode: 0644]
bitmaps/c45s.bmp [new file with mode: 0644]
bitmaps/c45w.bmp [new file with mode: 0644]
bitmaps/c49s.bmp
bitmaps/c54o.bmp [new file with mode: 0644]
bitmaps/c54s.bmp [new file with mode: 0644]
bitmaps/c54w.bmp [new file with mode: 0644]
bitmaps/c58o.bmp [new file with mode: 0644]
bitmaps/c58s.bmp [new file with mode: 0644]
bitmaps/c58w.bmp [new file with mode: 0644]
bitmaps/c64o.bmp [new file with mode: 0644]
bitmaps/c64s.bmp [new file with mode: 0644]
bitmaps/c64w.bmp [new file with mode: 0644]
bitmaps/c72s.bmp
bitmaps/cv33o.bmp [new file with mode: 0644]
bitmaps/cv33s.bmp [new file with mode: 0644]
bitmaps/cv33w.bmp [new file with mode: 0644]
bitmaps/cv37o.bmp [new file with mode: 0644]
bitmaps/cv37s.bmp [new file with mode: 0644]
bitmaps/cv37w.bmp [new file with mode: 0644]
bitmaps/cv40o.bmp [new file with mode: 0644]
bitmaps/cv40s.bmp [new file with mode: 0644]
bitmaps/cv40w.bmp [new file with mode: 0644]
bitmaps/cv45o.bmp [new file with mode: 0644]
bitmaps/cv45s.bmp [new file with mode: 0644]
bitmaps/cv45w.bmp [new file with mode: 0644]
bitmaps/cv49o.bmp [new file with mode: 0644]
bitmaps/cv49s.bmp [new file with mode: 0644]
bitmaps/cv49w.bmp [new file with mode: 0644]
bitmaps/cv54o.bmp [new file with mode: 0644]
bitmaps/cv54s.bmp [new file with mode: 0644]
bitmaps/cv54w.bmp [new file with mode: 0644]
bitmaps/cv58o.bmp [new file with mode: 0644]
bitmaps/cv58s.bmp [new file with mode: 0644]
bitmaps/cv58w.bmp [new file with mode: 0644]
bitmaps/cv64o.bmp [new file with mode: 0644]
bitmaps/cv64s.bmp [new file with mode: 0644]
bitmaps/cv64w.bmp [new file with mode: 0644]
bitmaps/cv72o.bmp [new file with mode: 0644]
bitmaps/cv72s.bmp [new file with mode: 0644]
bitmaps/cv72w.bmp [new file with mode: 0644]
bitmaps/dk33o.bmp [new file with mode: 0644]
bitmaps/dk33s.bmp [new file with mode: 0644]
bitmaps/dk33w.bmp [new file with mode: 0644]
bitmaps/e33o.bmp [new file with mode: 0644]
bitmaps/e33s.bmp [new file with mode: 0644]
bitmaps/e33w.bmp [new file with mode: 0644]
bitmaps/f33o.bmp [new file with mode: 0644]
bitmaps/f33s.bmp [new file with mode: 0644]
bitmaps/f33w.bmp [new file with mode: 0644]
bitmaps/g33o.bmp [new file with mode: 0644]
bitmaps/g33s.bmp [new file with mode: 0644]
bitmaps/g33w.bmp [new file with mode: 0644]
bitmaps/h33o.bmp [new file with mode: 0644]
bitmaps/h33s.bmp [new file with mode: 0644]
bitmaps/h33w.bmp [new file with mode: 0644]
bitmaps/l33o.bmp [new file with mode: 0644]
bitmaps/l33s.bmp [new file with mode: 0644]
bitmaps/l33w.bmp [new file with mode: 0644]
bitmaps/l37o.bmp [new file with mode: 0644]
bitmaps/l37s.bmp [new file with mode: 0644]
bitmaps/l37w.bmp [new file with mode: 0644]
bitmaps/l40o.bmp [new file with mode: 0644]
bitmaps/l40s.bmp [new file with mode: 0644]
bitmaps/l40w.bmp [new file with mode: 0644]
bitmaps/l45o.bmp [new file with mode: 0644]
bitmaps/l45s.bmp [new file with mode: 0644]
bitmaps/l45w.bmp [new file with mode: 0644]
bitmaps/l54o.bmp [new file with mode: 0644]
bitmaps/l54s.bmp [new file with mode: 0644]
bitmaps/l54w.bmp [new file with mode: 0644]
bitmaps/l58o.bmp [new file with mode: 0644]
bitmaps/l58s.bmp [new file with mode: 0644]
bitmaps/l58w.bmp [new file with mode: 0644]
bitmaps/l64o.bmp [new file with mode: 0644]
bitmaps/l64s.bmp [new file with mode: 0644]
bitmaps/l64w.bmp [new file with mode: 0644]
bitmaps/m33o.bmp [new file with mode: 0644]
bitmaps/m33s.bmp [new file with mode: 0644]
bitmaps/m33w.bmp [new file with mode: 0644]
bitmaps/o33o.bmp [new file with mode: 0644]
bitmaps/o33s.bmp [new file with mode: 0644]
bitmaps/o33w.bmp [new file with mode: 0644]
bitmaps/s49o.bmp [new file with mode: 0644]
bitmaps/s49s.bmp [new file with mode: 0644]
bitmaps/s49w.bmp [new file with mode: 0644]
bitmaps/s72o.bmp [new file with mode: 0644]
bitmaps/s72s.bmp [new file with mode: 0644]
bitmaps/s72w.bmp [new file with mode: 0644]
bitmaps/v33o.bmp [new file with mode: 0644]
bitmaps/v33s.bmp [new file with mode: 0644]
bitmaps/v33w.bmp [new file with mode: 0644]
bitmaps/v49o.bmp [new file with mode: 0644]
bitmaps/v49s.bmp [new file with mode: 0644]
bitmaps/v49w.bmp [new file with mode: 0644]
bitmaps/v54o.bmp [new file with mode: 0644]
bitmaps/v54s.bmp [new file with mode: 0644]
bitmaps/v54w.bmp [new file with mode: 0644]
bitmaps/v72o.bmp [new file with mode: 0644]
bitmaps/v72s.bmp [new file with mode: 0644]
bitmaps/v72w.bmp [new file with mode: 0644]
bitmaps/w33o.bmp [new file with mode: 0644]
bitmaps/w33s.bmp [new file with mode: 0644]
bitmaps/w33w.bmp [new file with mode: 0644]
bitmaps/was.gif [new file with mode: 0644]
bitmaps/wcv.gif [new file with mode: 0644]
bitmaps/wl49o.bmp
bitmaps/wl49s.bmp
bitmaps/wl72o.bmp
bitmaps/wl72s.bmp
common.h
config.h
frontend.h
gamelist.c
lists.c
lists.h
moves.c
moves.h
parser.c
parser.h
parser.l
pgntags.c
uci.c
winboard/defaults.h
winboard/resource.h
winboard/wclipbrd.c
winboard/wclipbrd.h
winboard/wedittags.c
winboard/wedittags.h
winboard/wengineoutput.c
winboard/wevalgraph.c
winboard/wgamelist.c
winboard/wgamelist.h
winboard/whistory.c
winboard/winboard.c
winboard/winboard.h
winboard/winboard.rc
winboard/wlayout.c
winboard/woptions.c
winboard/wplugin.c
winboard/wplugin.h
winboard/wsnap.c
winboard/wsnap.h
zippy.c
zippy.h

index e9e1368..1f0af61 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -214,12 +214,17 @@ int string_to_rating P((char *str));
 void ParseFeatures P((char* args, ChessProgramState *cps));\r
 void InitBackEnd3 P((void));\r
 void FeatureDone P((ChessProgramState* cps, int val));\r
-void InitChessProgram P((ChessProgramState *cps));\r
+void InitChessProgram P((ChessProgramState *cps, int setup));\r
 \r
-void GetInfoFromComment( int, char * );\r
+char *GetInfoFromComment( int, char * ); // [HGM] PV time: returns stripped comment\r
 \r
 extern int tinyLayout, smallLayout;\r
 static ChessProgramStats programStats;\r
+static int exiting = 0; /* [HGM] moved to top */\r
+static int setboardSpoiledMachineBlack = 0, errorExitFlag = 0;\r
+extern int startedFromPositionFile;\r
+int startedFromPositionFile = FALSE; Board filePosition;    /* [HGM] loadPos */\r
+char endingGame = 0; /* [HGM] crash: flag to prevent recursion of GameEnds() */\r
 \r
 /* States for ics_getting_history */\r
 #define H_FALSE 0\r
@@ -292,7 +297,12 @@ static char * safeStrCat( char * dst, const char * src, size_t count )
 }\r
 \r
 /* Fake up flags for now, as we aren't keeping track of castling\r
-   availability yet */\r
+   availability yet. [HGM] Change of logic: the flag now only\r
+   indicates the type of castlings allowed by the rule of the game.\r
+   The actual rights themselves are maintained in the array\r
+   castlingRights, as part of the game history, and are not probed\r
+   by this function.\r
+ */\r
 int\r
 PosFlags(index)\r
 {\r
@@ -310,6 +320,9 @@ PosFlags(index)
   case VariantKriegspiel:\r
     flags |= F_KRIEGSPIEL_CAPTURE;\r
     break;\r
+/*  case VariantCapaRandom: */\r
+  case VariantFischeRandom:\r
+    flags |= F_FRC_TYPE_CASTLING; /* [HGM] enable this through flag */\r
   case VariantNoCastle:\r
     flags &= ~F_ALL_CASTLE_OK;\r
     break;\r
@@ -383,6 +396,7 @@ int have_sent_ICS_logon = 0;
 int movesPerSession;\r
 long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement;\r
 long timeControl_2; /* [AS] Allow separate time controls */\r
+char *fullTimeControlString = NULL; /* [HGM] secondary TC: merge of MPS, TC and inc */\r
 long timeRemaining[2][MAX_MOVES];\r
 int matchGame = 0;\r
 TimeMark programStartTime;\r
@@ -405,10 +419,12 @@ Board boards[MAX_MOVES];
 char  epStatus[MAX_MOVES];\r
 char  castlingRights[MAX_MOVES][BOARD_SIZE]; // stores files for pieces with castling rights or -1\r
 char  castlingRank[BOARD_SIZE]; // and corresponding ranks\r
-char  initialRights[BOARD_SIZE], FENcastlingRights[BOARD_SIZE];\r
+char  initialRights[BOARD_SIZE], FENcastlingRights[BOARD_SIZE], fileRights[BOARD_SIZE];\r
 int   nrCastlingRights; // For TwoKings, or to implement castling-unknown status\r
 int   initialRulePlies, FENrulePlies;\r
 char  FENepStatus;\r
+FILE  *serverMoves = NULL; // next two for broadcasting (/serverMoves option)\r
+int loadFlag = 0; \r
 \r
 ChessSquare  FIDEArray[2][BOARD_SIZE] = {\r
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen,\r
@@ -424,7 +440,6 @@ ChessSquare twoKingsArray[2][BOARD_SIZE] = {
         BlackKing, BlackKing, BlackKnight, BlackRook }\r
 };\r
 \r
-#ifdef FAIRY\r
 ChessSquare  KnightmateArray[2][BOARD_SIZE] = {\r
     { WhiteRook, WhiteMan, WhiteBishop, WhiteQueen,\r
         WhiteUnicorn, WhiteBishop, WhiteMan, WhiteRook },\r
@@ -440,10 +455,10 @@ ChessSquare fairyArray[2][BOARD_SIZE] = { /* [HGM] Queen side differs from King
 };\r
 \r
 ChessSquare ShatranjArray[2][BOARD_SIZE] = { /* [HGM] (movGen knows about Shatranj Q and P) */\r
-    { WhiteRook, WhiteKnight, WhiteAlfil, WhiteFerz,\r
-        WhiteKing, WhiteAlfil, WhiteKnight, WhiteRook },\r
-    { BlackRook, BlackKnight, BlackAlfil, BlackFerz,\r
-        BlackKing, BlackAlfil, BlackKnight, BlackRook }\r
+    { WhiteRook, WhiteKnight, WhiteAlfil, WhiteKing,\r
+        WhiteFerz, WhiteAlfil, WhiteKnight, WhiteRook },\r
+    { BlackRook, BlackKnight, BlackAlfil, BlackKing,\r
+        BlackFerz, BlackAlfil, BlackKnight, BlackRook }\r
 };\r
 \r
 \r
@@ -463,23 +478,34 @@ ChessSquare XiangqiArray[2][BOARD_SIZE] = {
 };\r
 \r
 ChessSquare CapablancaArray[2][BOARD_SIZE] = {\r
-    { WhiteRook, WhiteKnight, WhiteCardinal, WhiteBishop, WhiteQueen, \r
+    { WhiteRook, WhiteKnight, WhiteAngel, WhiteBishop, WhiteQueen, \r
         WhiteKing, WhiteBishop, WhiteMarshall, WhiteKnight, WhiteRook },\r
-    { BlackRook, BlackKnight, BlackCardinal, BlackBishop, BlackQueen, \r
+    { BlackRook, BlackKnight, BlackAngel, BlackBishop, BlackQueen, \r
         BlackKing, BlackBishop, BlackMarshall, BlackKnight, BlackRook }\r
 };\r
 \r
 #ifdef GOTHIC\r
 ChessSquare GothicArray[2][BOARD_SIZE] = {\r
     { WhiteRook, WhiteKnight, WhiteBishop, WhiteQueen, WhiteMarshall, \r
-        WhiteKing, WhiteCardinal, WhiteBishop, WhiteKnight, WhiteRook },\r
+        WhiteKing, WhiteAngel, WhiteBishop, WhiteKnight, WhiteRook },\r
     { BlackRook, BlackKnight, BlackBishop, BlackQueen, BlackMarshall, \r
-        BlackKing, BlackCardinal, BlackBishop, BlackKnight, BlackRook }\r
+        BlackKing, BlackAngel, BlackBishop, BlackKnight, BlackRook }\r
 };\r
 #else // !GOTHIC\r
 #define GothicArray CapablancaArray\r
 #endif // !GOTHIC\r
 \r
+#ifdef FALCON\r
+ChessSquare FalconArray[2][BOARD_SIZE] = {\r
+    { WhiteRook, WhiteKnight, WhiteBishop, WhiteLance, WhiteQueen, \r
+        WhiteKing, WhiteLance, WhiteBishop, WhiteKnight, WhiteRook },\r
+    { BlackRook, BlackKnight, BlackBishop, BlackLance, BlackQueen, \r
+        BlackKing, BlackLance, BlackBishop, BlackKnight, BlackRook }\r
+};\r
+#else // !FALCON\r
+#define FalconArray CapablancaArray\r
+#endif // !FALCON\r
+\r
 #else // !(BOARD_SIZE>=10)\r
 #define XiangqiPosition FIDEArray\r
 #define CapablancaArray FIDEArray\r
@@ -496,7 +522,6 @@ ChessSquare CourierArray[2][BOARD_SIZE] = {
 #else // !(BOARD_SIZE>=12)\r
 #define CourierArray CapablancaArray\r
 #endif // !(BOARD_SIZE>=12)\r
-#endif // FAIRY\r
 \r
 \r
 Board initialPosition;\r
@@ -525,7 +550,7 @@ ClearProgramStats()
     programStats.nr_moves = 0;\r
     programStats.moves_left = 0;\r
     programStats.nodes = 0;\r
-    programStats.time = 100;\r
+    programStats.time = -1;        // [HGM] PGNtime: make invalid to recognize engine output\r
     programStats.score = 0;\r
     programStats.got_only_move = 0;\r
     programStats.got_fail = 0;\r
@@ -666,6 +691,26 @@ InitBackEnd1()
     first.useOOCastle = TRUE; second.useOOCastle = TRUE;\r
     /* End of new features added by Tord. */\r
 \r
+    /* [HGM] time odds: set factor for each machine */\r
+    first.timeOdds  = appData.firstTimeOdds;\r
+    second.timeOdds = appData.secondTimeOdds;\r
+    { int norm = 1;\r
+        if(appData.timeOddsMode) {\r
+            norm = first.timeOdds;\r
+            if(norm > second.timeOdds) norm = second.timeOdds;\r
+        }\r
+        first.timeOdds /= norm;\r
+        second.timeOdds /= norm;\r
+    }\r
+\r
+    /* [HGM] secondary TC: how to handle sessions that do not fit in 'level'*/\r
+    first.accumulateTC = appData.firstAccumulateTC;\r
+    second.accumulateTC = appData.secondAccumulateTC;\r
+    first.maxNrOfSessions = second.maxNrOfSessions = 1;\r
+\r
+    /* [HGM] debug */\r
+    first.debug = second.debug = FALSE;\r
+\r
     first.scoreIsAbsolute = appData.firstScoreIsAbsolute; /* [AS] */\r
     second.scoreIsAbsolute = appData.secondScoreIsAbsolute; /* [AS] */\r
     first.isUCI = appData.firstIsUCI; /* [AS] */\r
@@ -762,8 +807,9 @@ InitBackEnd1()
       case VariantCapablanca: /* [HGM] should work */\r
       case VariantCourier:    /* [HGM] initial forced moves not implemented */\r
       case VariantShogi:      /* [HGM] drops not tested for legality */\r
-      case VariantShowgi:     /* [HGM] not a valid variant */\r
       case VariantKnightmate: /* [HGM] should work */\r
+      case VariantCylinder:   /* [HGM] untested */\r
+      case VariantFalcon:     /* [HGM] untested */\r
       case VariantCrazyhouse: /* holdings not shown, ([HGM] fixed that!)\r
                                 offboard interposition not understood */\r
       case VariantNormal:     /* definitely works! */\r
@@ -827,22 +873,51 @@ int NextTimeControlFromString( char ** str, long * value )
     return result;\r
 }\r
 \r
-int GetTimeControlForWhite()\r
-{\r
-    int result = timeControl;\r
+int NextSessionFromString( char ** str, int *moves, long * tc, long *inc)\r
+{   /* [HGM] routine added to read '+moves/time' for secondary time control */\r
+    int result = -1; long temp, temp2;\r
+\r
+    if(**str != '+') return -1; // old params remain in force!\r
+    (*str)++;\r
+    if( NextTimeControlFromString( str, &temp ) ) return -1;\r
 \r
+    if(**str != '/') {\r
+        /* time only: incremental or sudden-death time control */\r
+        if(**str == '+') { /* increment follows; read it */\r
+            (*str)++;\r
+            if(result = NextIntegerFromString( str, &temp2)) return -1;\r
+            *inc = temp2 * 1000;\r
+        } else *inc = 0;\r
+        *moves = 0; *tc = temp * 1000; \r
+        return 0;\r
+    } else if(temp % 60 != 0) return -1;     /* moves was given as min:sec */\r
+\r
+    (*str)++; /* classical time control */\r
+    result = NextTimeControlFromString( str, &temp2);\r
+    if(result == 0) {\r
+        *moves = temp/60;\r
+        *tc    = temp2 * 1000;\r
+        *inc   = 0;\r
+    }\r
     return result;\r
 }\r
 \r
-int GetTimeControlForBlack()\r
-{\r
-    int result = timeControl;\r
+int GetTimeQuota(int movenr)\r
+{   /* [HGM] get time to add from the multi-session time-control string */\r
+    int moves=1; /* kludge to force reading of first session */\r
+    long time, increment;\r
+    char *s = fullTimeControlString;\r
 \r
-    if( timeControl_2 > 0 ) {\r
-        result = timeControl_2;\r
-    }\r
+    if(appData.debugMode) fprintf(debugFP, "TC string = '%s'\n", fullTimeControlString);\r
+    do {\r
+        if(moves) NextSessionFromString(&s, &moves, &time, &increment);\r
+        if(appData.debugMode) fprintf(debugFP, "mps=%d tc=%d inc=%d\n", moves, (int) time, (int) increment);\r
+        if(movenr == -1) return time;    /* last move before new session     */\r
+        if(!moves) return increment;     /* current session is incremental   */\r
+        if(movenr >= 0) movenr -= moves; /* we already finished this session */\r
+    } while(movenr >= -1);               /* try again for next session       */\r
 \r
-    return result;\r
+    return 0; // no new time quota on this move\r
 }\r
 \r
 int\r
@@ -865,6 +940,19 @@ ParseTimeControl(tc, ti, mps)
 #else\r
     long tc1;\r
     long tc2;\r
+    char buf[MSG_SIZ];\r
+\r
+    if(ti >= 0 && !strchr(tc, '+') && !strchr(tc, '/') ) mps = 0;\r
+    if(ti > 0) {\r
+        if(mps)\r
+             sprintf(buf, "+%d/%s+%d", mps, tc, ti);\r
+        else sprintf(buf, "+%s+%d", tc, ti);\r
+    } else {\r
+        if(mps)\r
+             sprintf(buf, "+%d/%s", mps, tc);\r
+        else sprintf(buf, "+%s", tc);\r
+    }\r
+    fullTimeControlString = StrSave(buf);\r
 \r
     if( NextTimeControlFromString( &tc, &tc1 ) != 0 ) {\r
         return FALSE;\r
@@ -935,7 +1023,10 @@ InitBackEnd3 P((void))
     char buf[MSG_SIZ];\r
     int err;\r
 \r
-    InitChessProgram(&first);\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From InitBackend3\n");\r
+    }\r
+    InitChessProgram(&first, startedFromSetupPosition);\r
 \r
     if (appData.icsActive) {\r
        err = establish();\r
@@ -1038,6 +1129,19 @@ InitBackEnd3 P((void))
            (void) LoadPositionFromFile(appData.loadPositionFile,\r
                                        appData.loadPositionIndex,\r
                                        appData.loadPositionFile);\r
+            /* [HGM] try to make self-starting even after FEN load */\r
+            /* to allow automatic setup of fairy variants with wtm */\r
+            if(initialMode == BeginningOfGame && !blackPlaysFirst) {\r
+                gameMode = BeginningOfGame;\r
+                setboardSpoiledMachineBlack = 1;\r
+            }\r
+            /* [HGM] loadPos: make that every new game uses the setup */\r
+            /* from file as long as we do not switch variant          */\r
+            if(!blackPlaysFirst) { int i;\r
+                startedFromPositionFile = TRUE;\r
+                CopyBoard(filePosition, boards[0]);\r
+                for(i=0; i<BOARD_SIZE; i++) fileRights[i] = castlingRights[0][i];\r
+            }\r
        }\r
        if (initialMode == AnalyzeMode) {\r
          if (appData.noChessProgram) {\r
@@ -1243,7 +1347,7 @@ read_from_player(isr, closure, message, count, error)
        gotEof = 0;\r
        outCount = OutputMaybeTelnet(icsPR, message, count, &outError);\r
        if (outCount < count) {\r
-           DisplayFatalError("Error writing to ICS", outError, 1);\r
+            DisplayFatalError("Error writing to ICS", outError, 1);\r
        }\r
     } else if (count < 0) {\r
        RemoveInputSource(isr);\r
@@ -1507,7 +1611,10 @@ StringToVariant(e)
           v = VariantFairy;\r
           break;\r
         case 44:\r
-          v = VariantShowgi;\r
+          v = VariantCylinder;\r
+         break;\r
+        case 45:\r
+          v = VariantFalcon;\r
          break;\r
 \r
        case -1:\r
@@ -1733,18 +1840,30 @@ CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
 \r
 }\r
 \r
+char startBoard[MSG_SIZ]; /* [HGM] variantswitch */\r
+\r
 void\r
 VariantSwitch(Board board, VariantClass newVariant)\r
 {\r
-   int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j;\r
+   int newHoldingsWidth, newWidth = 8, newHeight = 8, i, j, oldCurrentMove = currentMove;\r
+   Board tempBoard; int saveCastling[BOARD_SIZE], saveEP;\r
+\r
+   startedFromPositionFile = FALSE;\r
    if(gameInfo.variant == newVariant) return;\r
 \r
    /* [HGM] This routine is called each time an assignment is made to\r
     * gameInfo.variant during a game, to make sure the board sizes\r
     * are set to match the new variant. If that means adding or deleting\r
     * holdings, we shift the playing board accordingly\r
+    * This kludge is needed because in ICS observe mode, we get boards\r
+    * of an ongoing game without knowing the variant, and learn about the\r
+    * latter only later. This can be because of the move list we requested,\r
+    * in which case the game history is refilled from the beginning anyway,\r
+    * but also when receiving holdings of a crazyhouse game. In the latter\r
+    * case we want to add those holdings to the already received position.\r
     */\r
 \r
+\r
   if (appData.debugMode) {\r
     fprintf(debugFP, "Switch board from %s to %s\n",\r
                VariantName(gameInfo.variant), VariantName(newVariant));\r
@@ -1753,7 +1872,6 @@ VariantSwitch(Board board, VariantClass newVariant)
     gameInfo.holdingsSize = 5; /* [HGM] prepare holdings */\r
          switch(newVariant) {\r
             case VariantShogi:\r
-            case VariantShowgi:\r
               newWidth = 9;  newHeight = 9;\r
               gameInfo.holdingsSize = 7;\r
             case VariantBughouse:\r
@@ -1790,9 +1908,21 @@ VariantSwitch(Board board, VariantClass newVariant)
         gameInfo.variant = newVariant;\r
         InitDrawingSizes(-2, 0);\r
 \r
-        if(board != boards[0]) InitPosition(FALSE);\r
-\r
-    } else gameInfo.variant = newVariant;\r
+        /* [HGM] The following should definitely be solved in a better way */\r
+#if 0\r
+        CopyBoard(board, tempBoard); /* save position in case it is board[0] */\r
+        for(i=0; i<BOARD_SIZE; i++) saveCastling[i] = castlingRights[0][i];\r
+        saveEP = epStatus[0];\r
+#endif\r
+        InitPosition(FALSE);          /* this sets up board[0], but also other stuff        */\r
+        forwardMostMove = backwardMostMove =\r
+        currentMove = oldCurrentMove; /* InitPos reset this, but we need still to redraw it */\r
+#if 0\r
+        epStatus[0] = saveEP;\r
+        for(i=0; i<BOARD_SIZE; i++) castlingRights[0][i] = saveCastling[i];\r
+        CopyBoard(tempBoard, board); /* restore position received from ICS   */\r
+#endif\r
+    } else { gameInfo.variant = newVariant; InitPosition(FALSE); }\r
 }\r
 \r
 static int loggedOn = FALSE;\r
@@ -1850,6 +1980,10 @@ read_from_ics(isr, closure, data, count, error)
     }\r
 #endif\r
 \r
+    if (appData.debugMode) { int f = forwardMostMove;\r
+        fprintf(debugFP, "ics input %d, castling = %d %d %d %d %d %d\n", f,\r
+                castlingRights[f][0],castlingRights[f][1],castlingRights[f][2],castlingRights[f][3],castlingRights[f][4],castlingRights[f][5]);\r
+    }\r
     if (count > 0) {\r
        /* If last read ended with a partial line that we couldn't parse,\r
           prepend it to the new read and try again. */\r
@@ -3204,7 +3338,62 @@ ParseBoard12(string)
     if (moveNum == 0) {\r
        startedFromSetupPosition =\r
          !CompareBoards(board, initialPosition);\r
-    }\r
+        if(startedFromSetupPosition)\r
+            initialRulePlies = irrev_count; /* [HGM] 50-move counter offset */\r
+    }\r
+    /* [HGM] variantswitch: remember the last initial position parsed, */\r
+    /* because it might have been parsed in the wrong variant, so that */\r
+    /* we can re-parse it once we know the proper variant (which might */\r
+    /* have different piece assignments for the same letters).         */\r
+    if(moveNum == 0) strcpy(startBoard, string);\r
+\r
+    /* [HGM] Set castling rights. Take the outermost Rooks,\r
+       to make it also work for FRC opening positions. Note that board12\r
+       is really defective for later FRC positions, as it has no way to\r
+       indicate which Rook can castle if they are on the same side of King.\r
+       For the initial position we grant rights to the outermost Rooks,\r
+       and remember thos rights, and we then copy them on positions\r
+       later in an FRC game. This means WB might not recognize castlings with\r
+       Rooks that have moved back to their original position as illegal,\r
+       but in ICS mode that is not its job anyway.\r
+    */\r
+    if(moveNum == 0 || gameInfo.variant != VariantFischeRandom)\r
+    { int i, j;\r
+\r
+        for(i=BOARD_LEFT, j= -1; i<BOARD_RGHT; i++)\r
+            if(board[0][i] == WhiteRook) j = i;\r
+        initialRights[0] = castlingRights[moveNum][0] = (castle_ws == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);\r
+        for(i=BOARD_RGHT-1, j= -1; i>=BOARD_LEFT; i--)\r
+            if(board[0][i] == WhiteRook) j = i;\r
+        initialRights[1] = castlingRights[moveNum][1] = (castle_wl == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);\r
+        for(i=BOARD_LEFT, j= -1; i<BOARD_RGHT; i++)\r
+            if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;\r
+        initialRights[3] = castlingRights[moveNum][3] = (castle_bs == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);\r
+        for(i=BOARD_RGHT-1, j= -1; i>=BOARD_LEFT; i--)\r
+            if(board[BOARD_HEIGHT-1][i] == BlackRook) j = i;\r
+        initialRights[4] = castlingRights[moveNum][4] = (castle_bl == 0 && gameInfo.variant != VariantFischeRandom ? -1 : j);\r
+\r
+        for(k=BOARD_LEFT; k<BOARD_RGHT; k++)\r
+            if(board[0][k] == WhiteKing) initialRights[2] = castlingRights[moveNum][2] = k;\r
+        for(k=BOARD_LEFT; k<BOARD_RGHT; k++)\r
+            if(board[BOARD_HEIGHT-1][k] == BlackKing)\r
+                initialRights[5] = castlingRights[moveNum][5] = k;\r
+    } else { int r;\r
+        r = castlingRights[moveNum][0] = initialRights[0];\r
+        if(board[0][r] != WhiteRook) castlingRights[moveNum][0] = -1;\r
+        r = castlingRights[moveNum][1] = initialRights[1];\r
+        if(board[0][r] != WhiteRook) castlingRights[moveNum][1] = -1;\r
+        r = castlingRights[moveNum][3] = initialRights[3];\r
+        if(board[BOARD_HEIGHT-1][r] != BlackRook) castlingRights[moveNum][3] = -1;\r
+        r = castlingRights[moveNum][4] = initialRights[4];\r
+        if(board[BOARD_HEIGHT-1][r] != BlackRook) castlingRights[moveNum][4] = -1;\r
+        /* wildcastle kludge: always assume King has rights */\r
+        r = castlingRights[moveNum][2] = initialRights[2];\r
+        r = castlingRights[moveNum][5] = initialRights[5];\r
+    }\r
+    /* [HGM] e.p. rights. Assume that ICS sends file number here? */\r
+    epStatus[moveNum] = double_push == -1 ? EP_NONE : double_push + BOARD_LEFT;\r
+\r
     \r
     if (ics_getting_history == H_GOT_REQ_HEADER ||\r
        ics_getting_history == H_GOT_UNREQ_HEADER) {\r
@@ -3268,7 +3457,12 @@ ParseBoard12(string)
        to canonical algebraic form. */\r
     if (moveNum > 0) {\r
   if (appData.debugMode) {\r
+    if (appData.debugMode) { int f = forwardMostMove;\r
+        fprintf(debugFP, "parseboard %d, castling = %d %d %d %d %d %d\n", f,\r
+                castlingRights[f][0],castlingRights[f][1],castlingRights[f][2],castlingRights[f][3],castlingRights[f][4],castlingRights[f][5]);\r
+    }\r
     fprintf(debugFP, "accepted move %s from ICS, parse it.\n", move_str);\r
+    fprintf(debugFP, "moveNum = %d\n", moveNum);\r
     fprintf(debugFP, "board = %d-%d x %d\n", BOARD_LEFT, BOARD_RGHT, BOARD_HEIGHT);\r
     setbuf(debugFP, NULL);\r
   }\r
@@ -3472,6 +3666,7 @@ SendMoveToProgram(moveNum, cps)
      ChessProgramState *cps;\r
 {\r
     char buf[MSG_SIZ];\r
+\r
     if (cps->useUsermove) {\r
       SendToProgram("usermove ", cps);\r
     }\r
@@ -3491,14 +3686,17 @@ SendMoveToProgram(moveNum, cps)
        * the engine. It would be nice to have a better way to identify castle \r
        * moves here. */\r
       if(gameInfo.variant == VariantFischeRandom && cps->useOOCastle) {\r
+  if (appData.debugMode) {\r
+    fprintf(debugFP, "Tord's FRC castling code\n");\r
+  }\r
         int fromX = moveList[moveNum][0] - AAA; \r
         int fromY = moveList[moveNum][1] - ONE;\r
         int toX = moveList[moveNum][2] - AAA; \r
         int toY = moveList[moveNum][3] - ONE;\r
-       if((boards[currentMove][fromY][fromX] == WhiteKing \r
-           && boards[currentMove][toY][toX] == WhiteRook)\r
-          || (boards[currentMove][fromY][fromX] == BlackKing \r
-              && boards[currentMove][toY][toX] == BlackRook)) {\r
+        if((boards[moveNum][fromY][fromX] == WhiteKing \r
+            && boards[moveNum][toY][toX] == WhiteRook)\r
+           || (boards[moveNum][fromY][fromX] == BlackKing \r
+               && boards[moveNum][toY][toX] == BlackRook)) {\r
          if(toX > fromX) SendToProgram("O-O\n", cps);\r
          else SendToProgram("O-O-O\n", cps);\r
        }\r
@@ -3507,6 +3705,21 @@ SendMoveToProgram(moveNum, cps)
       else SendToProgram(moveList[moveNum], cps);\r
       /* End of additions by Tord */\r
     }\r
+\r
+    /* [HGM] setting up the opening has brought engine in force mode! */\r
+    /*       Send 'go' if we are in a mode where machine should play. */\r
+    if( (moveNum == 0 && setboardSpoiledMachineBlack && cps == &first) &&\r
+        (gameMode == TwoMachinesPlay   ||\r
+#ifdef ZIPPY\r
+         gameMode == IcsPlayingBlack     || gameMode == IcsPlayingWhite ||\r
+#endif\r
+         gameMode == MachinePlaysBlack || gameMode == MachinePlaysWhite) ) {\r
+        SendToProgram("go\n", cps);\r
+  if (appData.debugMode) {\r
+    fprintf(debugFP, "(extra)\n");\r
+  }\r
+    }\r
+    setboardSpoiledMachineBlack = 0;\r
 }\r
 \r
 void\r
@@ -3552,13 +3765,16 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY)
       case BlackPromotionKnight:\r
       case WhitePromotionKing:\r
       case BlackPromotionKing:\r
-#ifdef FAIRY\r
       case WhitePromotionChancellor:\r
       case BlackPromotionChancellor:\r
       case WhitePromotionArchbishop:\r
       case BlackPromotionArchbishop:\r
-#endif\r
-       sprintf(user_move, "%c%c%c%c=%c\n",\r
+        if(gameInfo.variant == VariantShatranj)\r
+            sprintf(user_move, "%c%c%c%c=%c\n",\r
+                AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
+               PieceToChar(WhiteFerz));\r
+        else\r
+            sprintf(user_move, "%c%c%c%c=%c\n",\r
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
                PieceToChar(PromoPiece(moveType)));\r
        break;\r
@@ -3629,47 +3845,35 @@ AlphaRank(char *move, int n)
     if(move[1]=='*' && \r
        move[2]>='0' && move[2]<='9' &&\r
        move[3]>='a' && move[3]<='x'    ) {\r
-        move[2] = (move[2]-'1')+BOARD_LEFT + AAA;\r
-        move[3] = (move[3]-'a') + ONE;\r
+        move[2] = BOARD_RGHT  -1 - (move[2]-'1') + AAA;\r
+        move[3] = BOARD_HEIGHT-1 - (move[3]-'a') + ONE;\r
     } else\r
     if(move[0]>='0' && move[0]<='9' &&\r
        move[1]>='a' && move[1]<='x' &&\r
        move[2]>='0' && move[2]<='9' &&\r
        move[3]>='a' && move[3]<='x'    ) {\r
         /* input move, Shogi -> normal */\r
-/*\r
-        move[0] = BOARD_RGHT  -1-(move[0]-'1') + AAA;\r
-        move[1] = BOARD_HEIGHT-1-(move[1]-'a') + ONE;\r
-        move[2] = BOARD_RGHT  -1-(move[2]-'1') + AAA;\r
-        move[3] = BOARD_HEIGHT-1-(move[3]-'a') + ONE;\r
-*/\r
-        move[0] = (move[0]-'1')+BOARD_LEFT + AAA;\r
-        move[1] = (move[1]-'a') + ONE;\r
-        move[2] = (move[2]-'1')+BOARD_LEFT + AAA;\r
-        move[3] = (move[3]-'a') + ONE;\r
+        move[0] = BOARD_RGHT  -1 - (move[0]-'1') + AAA;\r
+        move[1] = BOARD_HEIGHT-1 - (move[1]-'a') + ONE;\r
+        move[2] = BOARD_RGHT  -1 - (move[2]-'1') + AAA;\r
+        move[3] = BOARD_HEIGHT-1 - (move[3]-'a') + ONE;\r
     } else\r
     if(move[1]=='@' &&\r
        move[3]>='0' && move[3]<='9' &&\r
        move[2]>='a' && move[2]<='x'    ) {\r
         move[1] = '*';\r
-        move[2] = (move[2]-AAA)-BOARD_LEFT + '1';\r
-        move[3] = (move[3]-ONE) + 'a';\r
+        move[2] = BOARD_RGHT - 1 - (move[2]-AAA) + '1';\r
+        move[3] = BOARD_HEIGHT-1 - (move[3]-ONE) + 'a';\r
     } else\r
     if(\r
        move[0]>='a' && move[0]<='x' &&\r
        move[3]>='0' && move[3]<='9' &&\r
        move[2]>='a' && move[2]<='x'    ) {\r
          /* output move, normal -> Shogi */\r
-/*\r
-        move[0] = BOARD_RGHT  -1-(move[0]-AAA) + '1';\r
-        move[1] = BOARD_HEIGHT-1-(move[1]-ONE) + 'a';\r
-        move[2] = BOARD_RGHT  -1-(move[2]-AAA) + '1';\r
-        move[3] = BOARD_HEIGHT-1-(move[3]-ONE) + 'a';\r
-*/\r
-        move[0] = (move[0]-AAA)-BOARD_LEFT + '1';\r
-        move[1] = (move[1]-ONE) + 'a';\r
-        move[2] = (move[2]-AAA)-BOARD_LEFT + '1';\r
-        move[3] = (move[3]-ONE) + 'a';\r
+        move[0] = BOARD_RGHT - 1 - (move[0]-AAA) + '1';\r
+        move[1] = BOARD_HEIGHT-1 - (move[1]-ONE) + 'a';\r
+        move[2] = BOARD_RGHT - 1 - (move[2]-AAA) + '1';\r
+        move[3] = BOARD_HEIGHT-1 - (move[3]-ONE) + 'a';\r
         if(move[4] == PieceToChar(BlackQueen)) move[4] = '+';\r
     }\r
     if (appData.debugMode) {\r
@@ -3806,9 +4010,15 @@ static void ShuffleFRC( Board board )
     board[0][FindEmptySquare(board, rand() % 6)] = WhiteQueen;\r
     board[0][FindEmptySquare(board, rand() % 5)] = WhiteKnight;\r
     board[0][FindEmptySquare(board, rand() % 4)] = WhiteKnight;\r
-    board[0][FindEmptySquare(board, 0)] = WhiteRook;\r
-    board[0][FindEmptySquare(board, 0)] = WhiteKing;\r
-    board[0][FindEmptySquare(board, 0)] = WhiteRook;\r
+    board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
+    initialRights[1]  = initialRights[4]  =\r
+    castlingRights[0][1] = castlingRights[0][4] = i;\r
+    board[0][ i=FindEmptySquare(board, 0) ] = WhiteKing;\r
+    initialRights[2]  = initialRights[5]  =\r
+    castlingRights[0][2] = castlingRights[0][5] = i;\r
+    board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
+    initialRights[0]  = initialRights[3]  =\r
+    castlingRights[0][0] = castlingRights[0][3] = i;\r
 \r
     for( i=BOARD_LEFT; i<BOARD_RGHT; i++ ) {\r
         board[BOARD_HEIGHT-1][i] = board[0][i] + BlackPawn - WhitePawn;\r
@@ -3851,9 +4061,15 @@ static void SetupFRC( Board board, int pos_index )
     board[0][ FindEmptySquare(board, knights % 16) ] = WhiteKnight;\r
 \r
     /* Place rooks and king */\r
-    board[0][ FindEmptySquare(board, 0) ] = WhiteRook;\r
-    board[0][ FindEmptySquare(board, 0) ] = WhiteKing;\r
-    board[0][ FindEmptySquare(board, 0) ] = WhiteRook;\r
+    board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
+    initialRights[1]  = initialRights[4]  =\r
+    castlingRights[0][1] = castlingRights[0][4] = i;\r
+    board[0][ i=FindEmptySquare(board, 0) ] = WhiteKing;\r
+    initialRights[2]  = initialRights[5]  =\r
+    castlingRights[0][2] = castlingRights[0][5] = i;\r
+    board[0][ i=FindEmptySquare(board, 0) ] = WhiteRook;\r
+    initialRights[0]  = initialRights[3]  =\r
+    castlingRights[0][0] = castlingRights[0][3] = i;\r
 \r
     /* Mirror piece placement for black */\r
     for( i=BOARD_LEFT; i<BOARD_RGHT; i++ ) {\r
@@ -3935,6 +4151,7 @@ InitPosition(redraw)
     case VariantShatranj:\r
       pieces = ShatranjArray;\r
       nrCastlingRights = 0;\r
+      SetCharTable(pieceToChar, "PN.R.QB...Kpn.r.qb...k"); \r
       break;\r
     case VariantTwoKings:\r
       pieces = twoKingsArray;\r
@@ -3943,24 +4160,28 @@ InitPosition(redraw)
       castlingRights[0][7] = initialRights[5] = 5;\r
       castlingRank[6] = 0;\r
       castlingRank[7] = BOARD_HEIGHT-1;\r
-      startedFromSetupPosition = TRUE;\r
       break;\r
     case VariantCapablanca:\r
       pieces = CapablancaArray;\r
       gameInfo.boardWidth = 10;\r
-      SetCharTable(pieceToChar, "PNBRQ.......AC..Kpnbrq.......ac..k"); \r
+      SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack"); \r
       break;\r
     case VariantGothic:\r
       pieces = GothicArray;\r
       gameInfo.boardWidth = 10;\r
-      SetCharTable(pieceToChar, "PNBRQ.......AC..Kpnbrq.......ac..k"); \r
+      SetCharTable(pieceToChar, "PNBRQ..ACKpnbrq..ack"); \r
+      break;\r
+    case VariantFalcon:\r
+      pieces = FalconArray;\r
+      gameInfo.boardWidth = 10;\r
+      SetCharTable(pieceToChar, "PNBRQ.............FKpnbrq.............fk"); \r
       break;\r
     case VariantXiangqi:\r
       pieces = XiangqiArray;\r
       gameInfo.boardWidth  = 9;\r
       gameInfo.boardHeight = 10;\r
       nrCastlingRights = 0;\r
-      SetCharTable(pieceToChar, "PH.R.AKE.C.......ph.r.ake.c......."); \r
+      SetCharTable(pieceToChar, "PH.R.AE..K.C.ph.r.ae..k.c."); \r
       break;\r
     case VariantShogi:\r
       pieces = ShogiArray;\r
@@ -3968,37 +4189,27 @@ InitPosition(redraw)
       gameInfo.boardHeight = 9;\r
       gameInfo.holdingsSize = 7;\r
       nrCastlingRights = 0;\r
-      SetCharTable(pieceToChar, "PNBRLSG...++++++Kpnbrlsg...++++++k"); \r
-      break;\r
-    case VariantShowgi:\r
-      pieces = ShogiArray;\r
-      gameInfo.boardWidth  = 9;\r
-      gameInfo.boardHeight = 9;\r
-      gameInfo.holdingsSize = 7;\r
-      nrCastlingRights = 0;\r
-      for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
-      SetCharTable(pieceToChar, "PNBRQFWEMOUHACG.Kpnbrlsgpnbrls...k"); \r
+      SetCharTable(pieceToChar, "PNBRLS...G.++++++Kpnbrls...g.++++++k"); \r
       break;\r
     case VariantCourier:\r
       pieces = CourierArray;\r
       gameInfo.boardWidth  = 12;\r
       nrCastlingRights = 0;\r
-      SetCharTable(pieceToChar, "PNBR.FWEM.......Kpnbr.fwem.......k"); \r
+      SetCharTable(pieceToChar, "PNBR.FE..WMKpnbr.fe..wmk"); \r
       for(i=0; i<BOARD_SIZE; i++) initialRights[i] = -1;\r
       break;\r
     case VariantKnightmate:\r
       pieces = KnightmateArray;\r
-      SetCharTable(pieceToChar, "P.BRQ...M.K......p.brq...m.k......"); \r
+      SetCharTable(pieceToChar, "P.BRQ.....M.........K.p.brq.....m.........k."); \r
       break;\r
     case VariantFairy:\r
       pieces = fairyArray;\r
-      SetCharTable(pieceToChar, "PNBRQFWEMOUHACGSKpnbrqfwemouhacgsk"); \r
-      startedFromSetupPosition = TRUE;\r
+      SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk"); \r
       break;\r
     case VariantCrazyhouse:\r
     case VariantBughouse:\r
       pieces = FIDEArray;\r
-      SetCharTable(pieceToChar, "PNBRQ......~~~~.Kpnbrq......~~~~.k"); \r
+      SetCharTable(pieceToChar, "PNBRQ.......~~~~Kpnbrq.......~~~~k"); \r
       gameInfo.holdingsSize = 5;\r
       break;\r
     case VariantWildCastle:\r
@@ -4060,9 +4271,8 @@ InitPosition(redraw)
         }\r
         initialPosition[BOARD_HEIGHT-1][j] =  pieces[1][j-gameInfo.holdingsWidth];\r
     }\r
-    if( (gameInfo.variant == VariantShogi\r
-       ||gameInfo.variant == VariantShowgi\r
-                                         ) && !overrule ) {\r
+    if( (gameInfo.variant == VariantShogi) && !overrule ) {\r
+\r
             j=BOARD_LEFT+1;\r
             initialPosition[1][j] = WhiteBishop;\r
             initialPosition[BOARD_HEIGHT-2][j] = BlackRook;\r
@@ -4092,6 +4302,13 @@ InitPosition(redraw)
       else {\r
         SetupFRC( initialPosition, appData.defaultFrcPosition );\r
       }\r
+      startedFromSetupPosition = TRUE;\r
+    } else if(startedFromPositionFile) {\r
+      /* [HGM] loadPos: use PositionFile for every new game */\r
+      CopyBoard(initialPosition, filePosition);\r
+      for(i=0; i<nrCastlingRights; i++)\r
+          castlingRights[0][i] = initialRights[i] = fileRights[i];\r
+      startedFromSetupPosition = TRUE;\r
     }\r
 \r
     CopyBoard(boards[0], initialPosition);\r
@@ -4100,9 +4317,13 @@ InitPosition(redraw)
        oldy != gameInfo.boardHeight ||\r
        oldh != gameInfo.holdingsWidth\r
 #ifdef GOTHIC\r
-       || oldv == VariantGothic ||\r
+       || oldv == VariantGothic ||        // For licensing popups\r
        gameInfo.variant == VariantGothic\r
 #endif\r
+#ifdef FALCON\r
+       || oldv == VariantFalcon ||\r
+       gameInfo.variant == VariantFalcon\r
+#endif\r
                                          )\r
             InitDrawingSizes(-2 ,0);\r
 \r
@@ -4139,6 +4360,15 @@ SendBoard(cps, moveNum)
          if ((int) *bp < (int) BlackPawn) {\r
            sprintf(message, "%c%c%c\n", PieceToChar(*bp), \r
                     AAA + j, ONE + i);\r
+            if(message[0] == '+' || message[0] == '~') {\r
+                sprintf(message, "%c%c%c+\n",\r
+                        PieceToChar((ChessSquare)(DEMOTED *bp)),\r
+                        AAA + j, ONE + i);\r
+            }\r
+            if(appData.alphaRank) {\r
+                message[1] = BOARD_RGHT   - 1 - j + '1';\r
+                message[2] = BOARD_HEIGHT - 1 - i + 'a';\r
+            }\r
            SendToProgram(message, cps);\r
          }\r
        }\r
@@ -4152,6 +4382,15 @@ SendBoard(cps, moveNum)
              && ((int) *bp >= (int) BlackPawn)) {\r
            sprintf(message, "%c%c%c\n", ToUpper(PieceToChar(*bp)),\r
                     AAA + j, ONE + i);\r
+            if(message[0] == '+' || message[0] == '~') {\r
+                sprintf(message, "%c%c%c+\n",\r
+                        PieceToChar((ChessSquare)(DEMOTED *bp)),\r
+                        AAA + j, ONE + i);\r
+            }\r
+            if(appData.alphaRank) {\r
+                message[1] = BOARD_RGHT   - 1 - j + '1';\r
+                message[2] = BOARD_HEIGHT - 1 - i + 'a';\r
+            }\r
            SendToProgram(message, cps);\r
          }\r
        }\r
@@ -4159,6 +4398,7 @@ SendBoard(cps, moveNum)
     \r
       SendToProgram(".\n", cps);\r
     }\r
+    setboardSpoiledMachineBlack = 0; /* [HGM] assume WB 4.2.7 already solves this after sending setboard */\r
 }\r
 \r
 int\r
@@ -4348,7 +4588,11 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar)
             (WhitePawn <= pdown && pdown < BlackPawn &&\r
              WhitePawn <= pup && pup < BlackPawn  ||\r
              BlackPawn <= pdown && pdown < EmptySquare &&\r
-             BlackPawn <= pup && pup < EmptySquare)      )\r
+             BlackPawn <= pup && pup < EmptySquare \r
+            ) && !(gameInfo.variant == VariantFischeRandom &&\r
+                    (pup == WhiteRook && pdown == WhiteKing && fromY == 0 && toY == 0||\r
+                     pup == BlackRook && pdown == BlackKing && fromY == BOARD_HEIGHT-1 && toY == BOARD_HEIGHT-1  ) \r
+        )           )\r
          return ImpossibleMove;\r
 \r
     /* Check if the user is playing in turn.  This is complicated because we\r
@@ -4529,7 +4773,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
     }\r
 \r
     /* [HGM] <popupFix> The following if has been moved here from\r
-       UserMoveEnevt(). Because it seemed to belon here (why not allow\r
+       UserMoveEvent(). Because it seemed to belon here (why not allow\r
        piece drops in training games?), and because it can only be\r
        performed after it is known to what we promote. */\r
     if (gameMode == Training) {\r
@@ -4720,6 +4964,11 @@ HandleMachineMove(message, cps)
     while (*message == '\007') message++;\r
 \r
     /*\r
+     * [HGM] engine debug message: ignore lines starting with '#' character\r
+     */\r
+    if(cps->debug && *message == '#') return;\r
+\r
+    /*\r
      * Look for book output\r
      */\r
     if (cps == &first && bookRequested) {\r
@@ -4811,6 +5060,10 @@ HandleMachineMove(message, cps)
            return;\r
        }\r
 \r
+    if (appData.debugMode) { int f = forwardMostMove;\r
+        fprintf(debugFP, "machine move %d, castling = %d %d %d %d %d %d\n", f,\r
+                castlingRights[f][0],castlingRights[f][1],castlingRights[f][2],castlingRights[f][3],castlingRights[f][4],castlingRights[f][5]);\r
+    }\r
         AlphaRank(machineMove, 4);\r
         if (!ParseOneMove(machineMove, forwardMostMove, &moveType,\r
                               &fromX, &fromY, &toX, &toY, &promoChar)) {\r
@@ -4856,12 +5109,12 @@ HandleMachineMove(message, cps)
            switch(moveType) {\r
              case WhiteASideCastleFR:\r
              case BlackASideCastleFR:\r
-               toY++;\r
+               toX+=2;\r
                currentMoveString[2]++;\r
                break;\r
              case WhiteHSideCastleFR:\r
              case BlackHSideCastleFR:\r
-               toY--;\r
+               toX--;\r
                currentMoveString[2]--;\r
                break;\r
            }\r
@@ -4889,7 +5142,7 @@ HandleMachineMove(message, cps)
         /* [AS] Save move info and clear stats for next move */\r
         pvInfoList[ forwardMostMove ].score = programStats.score;\r
         pvInfoList[ forwardMostMove ].depth = programStats.depth;\r
-        pvInfoList[ forwardMostMove ].time = -1;\r
+        pvInfoList[ forwardMostMove ].time =  programStats.time; // [HGM] PGNtime: take time from engine stats\r
         ClearProgramStats();\r
         thinkOutput[0] = NULLCHAR;\r
         hiddenThinkOutputState = 0;\r
@@ -4955,7 +5208,7 @@ HandleMachineMove(message, cps)
             if( appData.testLegality )\r
             {   /* [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,\r
+                    NrWQ=0, NrBQ=0, bishopsColor = 0,\r
                     NrPieces=0, NrPawns=0, PawnAdvance=0, i, j, k;\r
                 static int moveCount;\r
 \r
@@ -4969,19 +5222,21 @@ HandleMachineMove(message, cps)
                         case WhiteKnight:\r
                              NrWN++; break;\r
                         case WhiteBishop:\r
+                             bishopsColor |= 1 << ((i^j)&1);\r
                              NrWB++; break;\r
                         case BlackKnight:\r
-                             NrWN++; break;\r
+                             NrBN++; break;\r
                         case BlackBishop:\r
+                             bishopsColor |= 1 << ((i^j)&1);\r
                              NrBB++; break;\r
                         case WhiteRook:\r
                              NrWR++; break;\r
                         case BlackRook:\r
                              NrBR++; break;\r
                         case WhiteQueen:\r
-                             NrWR++; break;\r
+                             NrWQ++; break;\r
                         case BlackQueen:\r
-                             NrBR++; break;\r
+                             NrBQ++; break;\r
                         case EmptySquare: \r
                              break;\r
                         case BlackPawn:\r
@@ -4992,8 +5247,9 @@ HandleMachineMove(message, cps)
                     NrPieces += (p != EmptySquare);\r
                 }\r
 \r
-                if( NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 || NrPieces == 2 )\r
-                {    /* KBK, KNK or KK */\r
+                if( NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 || NrPieces == 2\r
+                 || NrPieces == 4 && NrBB+NrWB==2 && bishopsColor != 3)\r
+                {    /* KBK, KNK, KK of KBKB with like Bishops */\r
 \r
                      /* always flag draws, for judging claims */\r
                      epStatus[forwardMostMove] = EP_INSUF_DRAW;\r
@@ -5020,7 +5276,7 @@ HandleMachineMove(message, cps)
                           return;\r
                      }\r
                 } else moveCount = 6;\r
-\r
+#if 0\r
     if (appData.debugMode) { int i;\r
       fprintf(debugFP, "repeat test fmm=%d bmm=%d ep=%d, reps=%d\n",\r
               forwardMostMove, backwardMostMove, epStatus[backwardMostMove],\r
@@ -5029,6 +5285,7 @@ HandleMachineMove(message, cps)
            fprintf(debugFP, "%d ep=%d\n", i, epStatus[i]);\r
 \r
     }\r
+#endif\r
                 /* Check for rep-draws */\r
                 count = 0;\r
                 for(k = forwardMostMove-2;\r
@@ -5037,13 +5294,17 @@ HandleMachineMove(message, cps)
                         epStatus[k+2] <= EP_NONE && epStatus[k+1] <= EP_NONE;\r
                     k-=2)\r
                 {   int rights=0;\r
+#if 0\r
     if (appData.debugMode) {\r
       fprintf(debugFP, " loop\n");\r
     }\r
+#endif\r
                     if(CompareBoards(boards[k], boards[forwardMostMove])) {\r
+#if 0\r
     if (appData.debugMode) {\r
       fprintf(debugFP, "match\n");\r
     }\r
+#endif\r
                         /* compare castling rights */\r
                         if( castlingRights[forwardMostMove][2] != castlingRights[k][2] &&\r
                              (castlingRights[k][0] >= 0 || castlingRights[k][1] >= 0) )\r
@@ -5061,6 +5322,7 @@ HandleMachineMove(message, cps)
                                 castlingRights[forwardMostMove][4] != castlingRights[k][4] )\r
                                    rights++;\r
                         }\r
+#if 0\r
     if (appData.debugMode) {\r
       for(i=0; i<nrCastlingRights; i++)\r
       fprintf(debugFP, " (%d,%d)", castlingRights[forwardMostMove][i], castlingRights[k][i]);\r
@@ -5069,6 +5331,7 @@ HandleMachineMove(message, cps)
     if (appData.debugMode) {\r
       fprintf(debugFP, " %d %d\n", rights, k);\r
     }\r
+#endif\r
                         if( rights == 0 && ++count > appData.drawRepeats-2\r
                             && appData.drawRepeats > 1) {\r
                              /* adjudicate after user-specified nr of repeats */\r
@@ -5097,7 +5360,28 @@ HandleMachineMove(message, cps)
                          ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                          GameEnds( GameIsDrawn, "Xboard adjudication: 50-move rule", GE_XBOARD );\r
                          return;\r
-                 }\r
+                }\r
+\r
+                /* if draw offer is pending, treat it as a draw claim\r
+                 * when draw condition present, to allow engines a way to\r
+                 * claim draws before making their move to avoid a race\r
+                 * condition occurring after their move\r
+                 */\r
+                if( cps->other->offeredDraw || cps->offeredDraw ) {\r
+                         char *p = NULL;\r
+                         if(epStatus[forwardMostMove] == EP_RULE_DRAW)\r
+                             p = "Draw claim: 50-move rule";\r
+                         if(epStatus[forwardMostMove] == EP_REP_DRAW)\r
+                             p = "Draw claim: 3-fold repetition";\r
+                         if(epStatus[forwardMostMove] == EP_INSUF_DRAW)\r
+                             p = "Draw claim: insufficient mating material";\r
+                         if( p != NULL ) {\r
+                             GameEnds( GameIsDrawn, p, GE_XBOARD );\r
+                             ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+                             return;\r
+                         }\r
+                }\r
+\r
             }\r
 \r
 \r
@@ -5112,6 +5396,11 @@ HandleMachineMove(message, cps)
         }\r
 \r
        if (gameMode == TwoMachinesPlay) {\r
+            /* [HGM] relaying draw offers moved to after reception of move */\r
+            /* and interpreting offer as claim if it brings draw condition */\r
+            if (cps->offeredDraw == 1 && cps->other->sendDrawOffers) {\r
+                SendToProgram("draw\n", cps->other);\r
+            }\r
            if (cps->other->sendTime) {\r
                SendTimeRemaining(cps->other,\r
                                  cps->other->twoMachinesColor[0] == 'w');\r
@@ -5574,11 +5863,16 @@ HandleMachineMove(message, cps)
        if (gameMode == TwoMachinesPlay) {\r
            if (cps->other->offeredDraw) {\r
                GameEnds(GameIsDrawn, "Draw agreed", GE_XBOARD);\r
-           } else {\r
+            /* [HGM] in two-machine mode we delay relaying draw offer      */\r
+            /* until after we also have move, to see if it is really claim */\r
+           }\r
+#if 0\r
+              else {\r
                if (cps->other->sendDrawOffers) {\r
                    SendToProgram("draw\n", cps->other);\r
                }\r
            }\r
+#endif\r
        } else if (gameMode == MachinePlaysWhite ||\r
                   gameMode == MachinePlaysBlack) {\r
          if (userOfferedDraw) {\r
@@ -6038,19 +6332,56 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
      int promoChar;\r
      Board board;\r
 {\r
-  ChessSquare captured = board[toY][toX], piece; int p;\r
+  ChessSquare captured = board[toY][toX], piece, king; int p;\r
+\r
+    /* [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
+\r
+      epStatus[p] = EP_NONE;\r
+\r
+      if( board[toY][toX] != EmptySquare ) \r
+           epStatus[p] = EP_CAPTURE;  \r
+\r
+      if( board[fromY][fromX] == WhitePawn ) {\r
+           epStatus[p] = EP_PAWN_MOVE; \r
+           if( toY-fromY==2 &&\r
+               (toX>BOARD_LEFT   && board[toY][toX-1] == BlackPawn ||\r
+                toX<BOARD_RGHT-1 && board[toY][toX+1] == BlackPawn ) )\r
+              epStatus[p] = toX;\r
+      } else \r
+      if( board[fromY][fromX] == BlackPawn ) {\r
+           epStatus[p] = EP_PAWN_MOVE; \r
+           if( toY-fromY== -2 &&\r
+               (toX>BOARD_LEFT   && board[toY][toX-1] == WhitePawn ||\r
+                toX<BOARD_RGHT-1 && board[toY][toX+1] == WhitePawn ) )\r
+              epStatus[p] = toX;\r
+       }\r
+\r
+       for(i=0; i<nrCastlingRights; i++) {\r
+           castlingRights[p][i] = castlingRights[p-1][i];\r
+           if(castlingRights[p][i] == fromX && castlingRank[i] == fromY ||\r
+              castlingRights[p][i] == toX   && castlingRank[i] == toY   \r
+             ) castlingRights[p][i] = -1; // revoke for moved or captured piece\r
+       }\r
+\r
+    }\r
 \r
   /* [HGM] In Shatranj and Courier all promotions are to Ferz */\r
   if((gameInfo.variant==VariantShatranj || gameInfo.variant==VariantCourier)\r
-       && promoChar != 0) promoChar = 'F';\r
+       && promoChar != 0) promoChar = PieceToChar(WhiteFerz);\r
          \r
   if (fromX == toX && fromY == toY) return;\r
 \r
   if (fromY == DROP_RANK) {\r
        /* must be first */\r
-       board[toY][toX] = (ChessSquare) fromX;\r
+        piece = board[toY][toX] = (ChessSquare) fromX;\r
   } else {\r
      piece = board[fromY][fromX]; /* [HGM] remember, for Shogi promotion */\r
+     king = piece < (int) BlackPawn ? WhiteKing : BlackKing; /* [HGM] Knightmate simplify testing for castling */\r
+     if(gameInfo.variant == VariantKnightmate)\r
+         king += (int) WhiteUnicorn - (int) WhiteKing;\r
 \r
     /* Code added by Tord: */\r
     /* FRC castling assumed when king captures friendly rook. */\r
@@ -6074,34 +6405,20 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
       }\r
     /* End of code added by Tord */\r
 \r
-    } else if (initialPosition[fromY][fromX] == WhiteKing\r
-       && board[fromY][fromX] == WhiteKing\r
+    } else if (board[fromY][fromX] == king\r
+        && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */\r
         && toY == fromY && toX > fromX+1) {\r
        board[fromY][fromX] = EmptySquare;\r
-       board[toY][toX] = WhiteKing;\r
+        board[toY][toX] = king;\r
+        board[toY][toX-1] = board[fromY][BOARD_RGHT-1];\r
         board[fromY][BOARD_RGHT-1] = EmptySquare;\r
-        board[toY][toX-1] = WhiteRook;\r
-    } else if (initialPosition[fromY][fromX] == WhiteKing\r
-              && board[fromY][fromX] == WhiteKing\r
+    } else if (board[fromY][fromX] == king\r
+        && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */\r
                && toY == fromY && toX < fromX-1) {\r
        board[fromY][fromX] = EmptySquare;\r
-       board[toY][toX] = WhiteKing;\r
+        board[toY][toX] = king;\r
+        board[toY][toX+1] = board[fromY][BOARD_LEFT];\r
         board[fromY][BOARD_LEFT] = EmptySquare;\r
-        board[toY][toX+1] = WhiteRook;\r
-    } else if (fromY == 0 && fromX == 3\r
-              && board[fromY][fromX] == WhiteKing\r
-              && toY == 0 && toX == 5) {\r
-       board[fromY][fromX] = EmptySquare;\r
-       board[toY][toX] = WhiteKing;\r
-       board[fromY][7] = EmptySquare;\r
-       board[toY][4] = WhiteRook;\r
-    } else if (fromY == 0 && fromX == 3\r
-              && board[fromY][fromX] == WhiteKing\r
-              && toY == 0 && toX == 1) {\r
-       board[fromY][fromX] = EmptySquare;\r
-       board[toY][toX] = WhiteKing;\r
-       board[fromY][0] = EmptySquare;\r
-       board[toY][2] = WhiteRook;\r
     } else if (board[fromY][fromX] == WhitePawn\r
                && toY == BOARD_HEIGHT-1\r
                && gameInfo.variant != VariantXiangqi\r
@@ -6117,26 +6434,27 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
        board[fromY][fromX] = EmptySquare;\r
     } else if ((fromY == BOARD_HEIGHT-4)\r
               && (toX != fromX)\r
+               && gameInfo.variant != VariantXiangqi\r
               && (board[fromY][fromX] == WhitePawn)\r
               && (board[toY][toX] == EmptySquare)) {\r
        board[fromY][fromX] = EmptySquare;\r
        board[toY][toX] = WhitePawn;\r
        captured = board[toY - 1][toX];\r
        board[toY - 1][toX] = EmptySquare;\r
-    } else if (initialPosition[fromY][fromX] == BlackKing\r
-              && board[fromY][fromX] == BlackKing\r
+    } else if (board[fromY][fromX] == king\r
+        && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */\r
                && toY == fromY && toX > fromX+1) {\r
        board[fromY][fromX] = EmptySquare;\r
-       board[toY][toX] = BlackKing;\r
+        board[toY][toX] = king;\r
+        board[toY][toX-1] = board[fromY][BOARD_RGHT-1];\r
         board[fromY][BOARD_RGHT-1] = EmptySquare;\r
-        board[toY][toX-1] = BlackRook;\r
-    } else if (initialPosition[fromY][fromX] == BlackKing\r
-              && board[fromY][fromX] == BlackKing\r
+    } else if (board[fromY][fromX] == king\r
+        && fromX != BOARD_LEFT && fromX != BOARD_RGHT-1 // [HGM] cylinder */\r
                && toY == fromY && toX < fromX-1) {\r
        board[fromY][fromX] = EmptySquare;\r
-       board[toY][toX] = BlackKing;\r
+        board[toY][toX] = king;\r
+        board[toY][toX+1] = board[fromY][BOARD_LEFT];\r
         board[fromY][BOARD_LEFT] = EmptySquare;\r
-        board[toY][toX+1] = BlackRook;\r
     } else if (fromY == 7 && fromX == 3\r
               && board[fromY][fromX] == BlackKing\r
               && toY == 7 && toX == 5) {\r
@@ -6166,6 +6484,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
        board[fromY][fromX] = EmptySquare;\r
     } else if ((fromY == 3)\r
               && (toX != fromX)\r
+               && gameInfo.variant != VariantXiangqi\r
               && (board[fromY][fromX] == BlackPawn)\r
               && (board[toY][toX] == EmptySquare)) {\r
        board[fromY][fromX] = EmptySquare;\r
@@ -6263,6 +6582,48 @@ MakeMove(fromX, fromY, toX, toY, promoChar)
 {\r
     forwardMostMove++;\r
 \r
+    if(serverMoves != NULL) { /* [HGM] write moves on file for broadcasting */\r
+        int timeLeft; static int lastLoadFlag=0; int king, piece;\r
+        piece = boards[forwardMostMove-1][fromY][fromX];\r
+        king = piece < (int) BlackPawn ? WhiteKing : BlackKing;\r
+        if(gameInfo.variant == VariantKnightmate)\r
+            king += (int) WhiteUnicorn - (int) WhiteKing;\r
+        if(forwardMostMove == 1) {\r
+            if(blackPlaysFirst) \r
+                fprintf(serverMoves, "%s;", second.tidy);\r
+            fprintf(serverMoves, "%s;", first.tidy);\r
+            if(!blackPlaysFirst) \r
+                fprintf(serverMoves, "%s;", second.tidy);\r
+        } else fprintf(serverMoves, loadFlag|lastLoadFlag ? ":" : ";");\r
+        lastLoadFlag = loadFlag;\r
+        // print base move\r
+        fprintf(serverMoves, "%c%c:%c%c", AAA+fromX, ONE+fromY, AAA+toX, ONE+toY);\r
+        // print castling suffix\r
+        if( toY == fromY && piece == king ) {\r
+            if(toX-fromX > 1)\r
+                fprintf(serverMoves, ":%c%c:%c%c", AAA+BOARD_RGHT-1, ONE+fromY, AAA+toX-1,ONE+toY);\r
+            if(fromX-toX >1)\r
+                fprintf(serverMoves, ":%c%c:%c%c", AAA+BOARD_LEFT, ONE+fromY, AAA+toX+1,ONE+toY);\r
+        }\r
+        // e.p. suffix\r
+        if( (boards[forwardMostMove-1][fromY][fromX] == WhitePawn ||\r
+             boards[forwardMostMove-1][fromY][fromX] == BlackPawn   ) &&\r
+             boards[forwardMostMove-1][toY][toX] == EmptySquare\r
+             && fromX != toX )\r
+                fprintf(serverMoves, ":%c%c:%c%c", AAA+fromX, ONE+fromY, AAA+toX, ONE+fromY);\r
+        // promotion suffix\r
+        if(promoChar != NULLCHAR)\r
+                fprintf(serverMoves, ":%c:%c%c", promoChar, AAA+toX, ONE+toY);\r
+        if(!loadFlag) {\r
+            fprintf(serverMoves, "/%d/%d",\r
+               pvInfoList[forwardMostMove-1].depth, pvInfoList[forwardMostMove-1].score);\r
+            if(forwardMostMove & 1) timeLeft = whiteTimeRemaining/1000;\r
+            else                    timeLeft = blackTimeRemaining/1000;\r
+            fprintf(serverMoves, "/%d", timeLeft);\r
+        }\r
+        fflush(serverMoves);\r
+    }\r
+\r
     if (forwardMostMove >= MAX_MOVES) {\r
       DisplayFatalError("Game too long; increase MAX_MOVES and recompile",\r
                        0, 1);\r
@@ -6276,40 +6637,6 @@ MakeMove(fromX, fromY, toX, toY, promoChar)
        commentList[forwardMostMove] = NULL;\r
     }\r
     CopyBoard(boards[forwardMostMove], boards[forwardMostMove - 1]);\r
-    /* [HGM] compute & store e.p. status and castling rights for new position */\r
-    { int i, j;\r
-\r
-      epStatus[forwardMostMove] = EP_NONE;\r
-\r
-      if( boards[forwardMostMove][toY][toX] != EmptySquare ) \r
-           epStatus[forwardMostMove] = EP_CAPTURE;  \r
-\r
-      if( boards[forwardMostMove][fromY][fromX] == WhitePawn ) {\r
-           epStatus[forwardMostMove] = EP_PAWN_MOVE; \r
-           if( toY-fromY==2 &&\r
-               (toX>BOARD_LEFT   && boards[forwardMostMove][toY][toX-1] == BlackPawn ||\r
-                toX<BOARD_RGHT-1 && boards[forwardMostMove][toY][toX+1] == BlackPawn ) )\r
-              epStatus[forwardMostMove] = toX;\r
-      } else \r
-      if( boards[forwardMostMove][fromY][fromX] == BlackPawn ) {\r
-           epStatus[forwardMostMove] = EP_PAWN_MOVE; \r
-           if( toY-fromY== -2 &&\r
-               (toX>BOARD_LEFT   && boards[forwardMostMove][toY][toX-1] == WhitePawn ||\r
-                toX<BOARD_RGHT-1 && boards[forwardMostMove][toY][toX+1] == WhitePawn ) )\r
-              epStatus[forwardMostMove] = toX;\r
-       }\r
-\r
-       for(i=0; i<nrCastlingRights; i++) {\r
-           castlingRights[forwardMostMove][i] = castlingRights[forwardMostMove-1][i];\r
-           if(castlingRights[forwardMostMove][i] == fromX && castlingRank[i] == fromY ||\r
-              castlingRights[forwardMostMove][i] == toX   && castlingRank[i] == toY   \r
-             ) castlingRights[forwardMostMove][i] = -1; // revoke for moved or captured piece\r
-\r
-\r
-\r
-       }\r
-\r
-    }\r
     ApplyMove(fromX, fromY, toX, toY, promoChar, boards[forwardMostMove]);\r
     gameInfo.result = GameUnfinished;\r
     if (gameInfo.resultDetails != NULL) {\r
@@ -6372,10 +6699,11 @@ ShowMove(fromX, fromY, toX, toY)
 \r
 \r
 void\r
-InitChessProgram(cps)\r
+InitChessProgram(cps, setup)\r
      ChessProgramState *cps;\r
+     int setup; /* [HGM] needed to setup FRC opening position */\r
 {\r
-    char buf[MSG_SIZ], *b; int overruled;\r
+    char buf[MSG_SIZ], b[MSG_SIZ]; int overruled;\r
     if (appData.noChessProgram) return;\r
     hintRequested = FALSE;\r
     bookRequested = FALSE;\r
@@ -6392,7 +6720,7 @@ InitChessProgram(cps)
        DisplayFatalError(buf, 0, 1);\r
        return;\r
       }\r
-      b = buf;\r
+\r
       /* [HGM] make prefix for non-standard board size. Awkward testing... */\r
       overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
       if( gameInfo.variant == VariantXiangqi )\r
@@ -6401,25 +6729,37 @@ InitChessProgram(cps)
            overruled = gameInfo.boardWidth != 9 || gameInfo.boardHeight != 9 || gameInfo.holdingsSize != 7;\r
       if( gameInfo.variant == VariantBughouse || gameInfo.variant == VariantCrazyhouse )\r
            overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 5;\r
-      if( gameInfo.variant == VariantCapablanca || gameInfo.variant == VariantGothic )\r
+      if( gameInfo.variant == VariantCapablanca || gameInfo.variant == VariantGothic  || gameInfo.variant == VariantFalcon )\r
            overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
       if( gameInfo.variant == VariantCourier )\r
            overruled = gameInfo.boardWidth != 12 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
 \r
       if(overruled) {\r
-           if (cps->protocolVersion != 1 && StrStr(cps->variants, "boardsize") == NULL) {\r
-             sprintf(buf, "Board size %dx%d+%d not supported by %s",\r
-                  gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->tidy);\r
-             DisplayFatalError(buf, 0, 1);\r
-             return;\r
+           sprintf(b, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight, \r
+                               gameInfo.holdingsSize, VariantName(gameInfo.variant)); // cook up sized variant name\r
+           /* [HGM] varsize: try first if this defiant size variant is specifically known */\r
+           if(StrStr(cps->variants, b) == NULL) { \r
+               // specific sized variant not known, check if general sizing allowed\r
+               if (cps->protocolVersion != 1) { // for protocol 1 we cannot check and hope for the best\r
+                   if(StrStr(cps->variants, "boardsize") == NULL) {\r
+                       sprintf(buf, "Board size %dx%d+%d not supported by %s",\r
+                            gameInfo.boardWidth, gameInfo.boardHeight, gameInfo.holdingsSize, cps->tidy);\r
+                       DisplayFatalError(buf, 0, 1);\r
+                       return;\r
+                   }\r
+                   /* [HGM] here we really should compare with the maximum supported board size */\r
+               }\r
            }\r
-           /* [HGM] here we really should compare with the maximum supported board size */\r
-           sprintf(buf, "%dx%d+%d_", gameInfo.boardWidth,\r
-                              gameInfo.boardHeight, gameInfo.holdingsSize );\r
-           while(*b++ != '_');\r
-      }\r
-      sprintf(b, "variant %s\n", VariantName(gameInfo.variant));\r
+      } else sprintf(b, "%s", VariantName(gameInfo.variant));\r
+      sprintf(buf, "variant %s\n", b);\r
       SendToProgram(buf, cps);\r
+      /* [HGM] send opening position in FRC to first engine */\r
+      if(setup /* cps == &first && gameInfo.variant == VariantFischeRandom */) {\r
+          SendToProgram("force\n", cps);\r
+          SendBoard(cps, 0);\r
+          /* engine is now in force mode! Set flag to wake it up after first move. */\r
+          setboardSpoiledMachineBlack = 1;\r
+      }\r
     }\r
     if (cps->sendICS) {\r
       sprintf(buf, "ics %s\n", appData.icsActive ? appData.icsHost : "-");\r
@@ -6554,12 +6894,15 @@ GameEnds(result, resultDetails, whosays)
     int isIcsGame;\r
     char buf[MSG_SIZ];\r
 \r
+    if(endingGame) return; /* [HGM] crash: forbid recursion */\r
+    endingGame = 1;\r
+\r
     if (appData.debugMode) {\r
       fprintf(debugFP, "GameEnds(%d, %s, %d)\n",\r
              result, resultDetails ? resultDetails : "(null)", whosays);\r
     }\r
 \r
-    if (appData.icsActive && whosays == (GE_ENGINE || whosays >= GE_ENGINE1)) {\r
+    if (appData.icsActive && (whosays == GE_ENGINE || whosays >= GE_ENGINE1)) {\r
        /* If we are playing on ICS, the server decides when the\r
           game is over, but the engine can offer to draw, claim \r
           a draw, or resign. \r
@@ -6576,7 +6919,8 @@ GameEnds(result, resultDetails, whosays)
            }\r
         }\r
 #endif\r
-       return;\r
+       endingGame = 0; /* [HGM] crash */\r
+        return;\r
     }\r
 \r
     /* If we're loading the game from a file, stop */\r
@@ -6586,7 +6930,7 @@ GameEnds(result, resultDetails, whosays)
     }\r
 \r
     /* Cancel draw offers */\r
-   first.offeredDraw = second.offeredDraw = 0;\r
+    first.offeredDraw = second.offeredDraw = 0;\r
 \r
     /* If this is an ICS game, only ICS can really say it's done;\r
        if not, anyone can. */\r
@@ -6625,7 +6969,11 @@ GameEnds(result, resultDetails, whosays)
                       result = claimer == 'w' ? BlackWins : WhiteWins;\r
                       resultDetails = buf;\r
                 } else\r
-                if( result == GameIsDrawn && epStatus[forwardMostMove] > EP_DRAWS ) {\r
+                if( result == GameIsDrawn && epStatus[forwardMostMove] > EP_DRAWS\r
+                    && (forwardMostMove <= backwardMostMove ||\r
+                        epStatus[forwardMostMove-1] > EP_DRAWS ||\r
+                        (claimer=='b')==(forwardMostMove&1))\r
+                                                                                  ) {\r
                       /* Draw that was not flagged by Xboard is false */\r
                       sprintf(buf, "False draw claim: '%s'", resultDetails);\r
                       result = claimer == 'w' ? BlackWins : WhiteWins;\r
@@ -6634,6 +6982,12 @@ GameEnds(result, resultDetails, whosays)
                 /* (Claiming a loss is accepted no questions asked!) */\r
         }\r
 \r
+        if(serverMoves != NULL && !loadFlag) { char c = '=';\r
+            if(result==WhiteWins) c = '+';\r
+            if(result==BlackWins) c = '-';\r
+            if(resultDetails != NULL)\r
+                fprintf(serverMoves, ";%c;%s\n", c, resultDetails);\r
+        }\r
     if (appData.debugMode) {\r
       fprintf(debugFP, "GameEnds(%d, %s, %d) after test\n",\r
              result, resultDetails ? resultDetails : "(null)", whosays);\r
@@ -6642,7 +6996,30 @@ GameEnds(result, resultDetails, whosays)
            gameInfo.result = result;\r
            gameInfo.resultDetails = StrSave(resultDetails);\r
 \r
+           /* display last move only if game was not loaded from file */\r
+           if ((whosays != GE_FILE) && (currentMove == forwardMostMove))\r
+               DisplayMove(currentMove - 1);\r
+    \r
+           if (forwardMostMove != 0) {\r
+               if (gameMode != PlayFromGameFile && gameMode != EditGame) {\r
+                   if (*appData.saveGameFile != NULLCHAR) {\r
+                       SaveGameToFile(appData.saveGameFile, TRUE);\r
+                   } else if (appData.autoSaveGames) {\r
+                       AutoSaveGame();\r
+                   }\r
+                   if (*appData.savePositionFile != NULLCHAR) {\r
+                       SavePositionToFile(appData.savePositionFile);\r
+                   }\r
+               }\r
+           }\r
+\r
            /* Tell program how game ended in case it is learning */\r
+            /* [HGM] Moved this to after saving the PGN, just in case */\r
+            /* engine died and we got here through time loss. In that */\r
+            /* case we will get a fatal error writing the pipe, which */\r
+            /* would otherwise lose us the PGN.                       */\r
+            /* [HGM] crash: not needed anymore, but doesn't hurt;     */\r
+            /* output during GameEnds should never be fatal anymore   */\r
            if (gameMode == MachinePlaysWhite ||\r
                gameMode == MachinePlaysBlack ||\r
                gameMode == TwoMachinesPlay ||\r
@@ -6660,23 +7037,6 @@ GameEnds(result, resultDetails, whosays)
                    SendToProgram(buf, &second);\r
                }\r
            }\r
-\r
-           /* display last move only if game was not loaded from file */\r
-           if ((whosays != GE_FILE) && (currentMove == forwardMostMove))\r
-               DisplayMove(currentMove - 1);\r
-    \r
-           if (forwardMostMove != 0) {\r
-               if (gameMode != PlayFromGameFile && gameMode != EditGame) {\r
-                   if (*appData.saveGameFile != NULLCHAR) {\r
-                       SaveGameToFile(appData.saveGameFile, TRUE);\r
-                   } else if (appData.autoSaveGames) {\r
-                       AutoSaveGame();\r
-                   }\r
-                   if (*appData.savePositionFile != NULLCHAR) {\r
-                       SavePositionToFile(appData.savePositionFile);\r
-                   }\r
-               }\r
-           }\r
        }\r
 \r
        if (appData.icsActive) {\r
@@ -6734,7 +7094,8 @@ GameEnds(result, resultDetails, whosays)
     if (appData.noChessProgram) {\r
        gameMode = nextGameMode;\r
        ModeHighlight();\r
-       return;\r
+       endingGame = 0; /* [HGM] crash */\r
+        return;\r
     }\r
 \r
     if (first.reuse) {\r
@@ -6823,6 +7184,7 @@ GameEnds(result, resultDetails, whosays)
             if(appData.matchPause>10000 || appData.matchPause<10)\r
                 appData.matchPause = 10000; /* [HGM] make pause adjustable */\r
             ScheduleDelayedEvent(NextMatchGame, appData.matchPause);\r
+           endingGame = 0; /* [HGM] crash */\r
            return;\r
        } else {\r
            char buf[MSG_SIZ];\r
@@ -6839,6 +7201,7 @@ GameEnds(result, resultDetails, whosays)
       ExitAnalyzeMode();\r
     gameMode = nextGameMode;\r
     ModeHighlight();\r
+    endingGame = 0;  /* [HGM] crash */\r
 }\r
 \r
 /* Assumes program was just initialized (initString sent).\r
@@ -6857,6 +7220,9 @@ FeedMovesToProgram(cps, upto)
     SendToProgram("force\n", cps);\r
     if (startedFromSetupPosition) {\r
        SendBoard(cps, backwardMostMove);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "feedMoves\n");\r
+    }\r
     }\r
     for (i = backwardMostMove; i < upto; i++) {\r
        SendMoveToProgram(i, cps);\r
@@ -6873,7 +7239,10 @@ ResurrectChessProgram()
     if (appData.noChessProgram || first.pr != NoProc) return;\r
     \r
     StartChessProgram(&first);\r
-    InitChessProgram(&first);\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From ResurrectChessProgram\n");\r
+    }\r
+    InitChessProgram(&first, FALSE);\r
     FeedMovesToProgram(&first, currentMove);\r
 \r
     if (!first.sendTime) {\r
@@ -6904,7 +7273,6 @@ Reset(redraw, init)
        fprintf(debugFP, "Reset(%d, %d) from gameMode %d\n",\r
                redraw, init, gameMode);\r
     }\r
-\r
     pausing = pauseExamInvalid = FALSE;\r
     startedFromSetupPosition = blackPlaysFirst = FALSE;\r
     firstMove = TRUE;\r
@@ -6931,6 +7299,19 @@ Reset(redraw, init)
     alarmSounded = FALSE;\r
 \r
     GameEnds((ChessMove) 0, NULL, GE_PLAYER);\r
+    if(appData.serverMovesName != NULL) {\r
+        /* [HGM] prepare to make moves file for broadcasting */\r
+        clock_t t = clock();\r
+        if(serverMoves != NULL) fclose(serverMoves);\r
+        serverMoves = fopen(appData.serverMovesName, "r");\r
+        if(serverMoves != NULL) {\r
+            fclose(serverMoves);\r
+            /* delay 15 sec before overwriting, so all clients can see end */\r
+            while(clock()-t < appData.serverPause*CLOCKS_PER_SEC);\r
+        }\r
+        serverMoves = fopen(appData.serverMovesName, "w");\r
+    }\r
+\r
     ExitAnalyzeMode();\r
     gameMode = BeginningOfGame;\r
     ModeHighlight();\r
@@ -6947,7 +7328,11 @@ Reset(redraw, init)
     if (first.pr == NULL) {\r
        StartChessProgram(&first);\r
     }\r
-    if (init) InitChessProgram(&first);\r
+    if (init) {\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From Reset\n");\r
+    }\r
+InitChessProgram(&first, startedFromSetupPosition);}\r
     DisplayTitle("");\r
     DisplayMessage("", "");\r
     HistorySet(parseList, backwardMostMove, forwardMostMove, currentMove-1);\r
@@ -7014,9 +7399,8 @@ AutoPlayOneMove()
     SendMoveToProgram(currentMove++, &first);\r
     DisplayBothClocks();\r
     DrawPosition(FALSE, boards[currentMove]);\r
-    if (commentList[currentMove] != NULL) {\r
-       DisplayComment(currentMove - 1, commentList[currentMove]);\r
-    }\r
+    // [HGM] PV info: always display, routine tests if empty\r
+    DisplayComment(currentMove - 1, commentList[currentMove]);\r
     return TRUE;\r
 }\r
 \r
@@ -7253,7 +7637,7 @@ LoadGameOneMove(readAhead)
        if (appData.matchMode || (appData.timeDelay == 0 && !pausing)) {\r
            DrawPosition(FALSE, boards[currentMove]);\r
            DisplayBothClocks();\r
-           if (!appData.matchMode && commentList[currentMove] != NULL)\r
+            if (!appData.matchMode) // [HGM] PV info: routine tests if empty\r
              DisplayComment(currentMove - 1, commentList[currentMove]);\r
        }\r
        (void) StopLoadGameTimer();\r
@@ -7464,6 +7848,7 @@ LoadGame(f, gameNumber, title, useList)
     int numPGNTags = 0;\r
     int err;\r
     GameMode oldGameMode;\r
+    VariantClass oldVariant = gameInfo.variant; /* [HGM] PGNvariant */\r
 \r
     if (appData.debugMode) \r
        fprintf(debugFP, "LoadGame(): on entry, gameMode %d\n", gameMode);\r
@@ -7513,7 +7898,6 @@ LoadGame(f, gameNumber, title, useList)
 \r
     yynewfile(f);\r
 \r
-\r
     if (lg && lg->gameInfo.white && lg->gameInfo.black) {\r
        sprintf(buf, "%s vs. %s", lg->gameInfo.white,\r
                lg->gameInfo.black);\r
@@ -7672,6 +8056,16 @@ LoadGame(f, gameNumber, title, useList)
        err = ParsePGNTag(yy_text, &gameInfo);\r
        if (!err) numPGNTags++;\r
 \r
+        /* [HGM] PGNvariant: automatically switch to variant given in PGN tag */\r
+        if(gameInfo.variant != oldVariant) {\r
+            startedFromPositionFile = FALSE; /* [HGM] loadPos: variant switch likely makes position invalid */\r
+           InitPosition(TRUE);\r
+            oldVariant = gameInfo.variant;\r
+           if (appData.debugMode) \r
+             fprintf(debugFP, "New variant %d\n", (int) oldVariant);\r
+        }\r
+\r
+\r
        if (gameInfo.fen != NULL) {\r
          Board initial_position;\r
          startedFromSetupPosition = TRUE;\r
@@ -7804,13 +8198,22 @@ LoadGame(f, gameNumber, title, useList)
     if (first.pr == NoProc) {\r
        StartChessProgram(&first);\r
     }\r
-    InitChessProgram(&first);\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From LoadGame\n");\r
+    }\r
+    InitChessProgram(&first, FALSE);\r
     SendToProgram("force\n", &first);\r
     if (startedFromSetupPosition) {\r
        SendBoard(&first, forwardMostMove);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Load Game\n");\r
+    }\r
        DisplayBothClocks();\r
     }      \r
 \r
+    /* [HGM] server: flag to write setup moves in broadcast file as one */\r
+    loadFlag = appData.suppressLoadMoves;\r
+\r
     while (cm == Comment) {\r
        char *p;\r
        if (appData.debugMode) \r
@@ -7845,10 +8248,9 @@ LoadGame(f, gameNumber, title, useList)
        return TRUE;\r
     }\r
 \r
-    if (commentList[currentMove] != NULL) {\r
-      if (!matchMode && (pausing || appData.timeDelay != 0)) {\r
+    // [HGM] PV info: routine tests if comment empty\r
+    if (!matchMode && (pausing || appData.timeDelay != 0)) {\r
        DisplayComment(currentMove - 1, commentList[currentMove]);\r
-      }\r
     }\r
     if (!matchMode && appData.timeDelay != 0) \r
       DrawPosition(FALSE, boards[currentMove]);\r
@@ -7889,6 +8291,8 @@ LoadGame(f, gameNumber, title, useList)
 \r
     if (appData.debugMode) \r
        fprintf(debugFP, "LoadGame(): on exit, gameMode %d\n", gameMode);\r
+\r
+    loadFlag = 0; /* [HGM] true game starts */\r
     return TRUE;\r
 }\r
 \r
@@ -7960,7 +8364,10 @@ LoadPosition(f, positionNumber, title)
     strcpy(lastLoadPositionTitle, title);\r
     if (first.pr == NoProc) {\r
       StartChessProgram(&first);\r
-      InitChessProgram(&first);\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From LoadPosition\n");\r
+    }\r
+      InitChessProgram(&first, FALSE);\r
     }    \r
     pn = positionNumber;\r
     if (positionNumber < 0) {\r
@@ -7987,6 +8394,7 @@ LoadPosition(f, positionNumber, title)
        DisplayError("Position not found in file", 0);\r
        return FALSE;\r
     }\r
+#if 0\r
     switch (line[0]) {\r
       case '#':  case 'x':\r
       default:\r
@@ -7996,14 +8404,16 @@ LoadPosition(f, positionNumber, title)
       case 'P':  case 'N':  case 'B':  case 'R':  case 'Q':  case 'K':\r
       case '1':  case '2':  case '3':  case '4':  case '5':  case '6':\r
       case '7':  case '8':  case '9':\r
-#ifdef FAIRY\r
       case 'H':  case 'A':  case 'M':  case 'h':  case 'a':  case 'm':\r
       case 'E':  case 'F':  case 'G':  case 'e':  case 'f':  case 'g':\r
       case 'C':  case 'W':             case 'c':  case 'w': \r
-#endif\r
        fenMode = TRUE;\r
        break;\r
     }\r
+#else\r
+    // [HGM] FEN can begin with digit, any piece letter valid in this variant, or a + for Shogi promoted pieces\r
+    fenMode = line[0] >= '0' && line[0] <= '9' || line[0] == '+' || CharToPiece(line[0]) != EmptySquare;\r
+#endif\r
 \r
     if (pn >= 2) {\r
        if (fenMode || line[0] == '#') pn--;\r
@@ -8065,6 +8475,9 @@ LoadPosition(f, positionNumber, title)
        DisplayMessage("", "White to play");\r
     }\r
     SendBoard(&first, forwardMostMove);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Load Position\n");\r
+    }\r
 \r
     if (positionNumber > 1) {\r
        sprintf(line, "%s %d", title, positionNumber);\r
@@ -8324,10 +8737,11 @@ SaveGamePGN(f)
             if(i >= backwardMostMove) {\r
                 /* take the time that changed */\r
                 seconds = timeRemaining[0][i] - timeRemaining[0][i+1];\r
-                if(seconds <= 0)\r
+              if(seconds <= 0)\r
                     seconds = timeRemaining[1][i] - timeRemaining[1][i+1];\r
             }\r
             seconds /= 1000;\r
+            seconds = pvInfoList[i].time/100;\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "times = %d %d %d %d, seconds=%d\n",\r
                 timeRemaining[0][i+1], timeRemaining[0][i],\r
@@ -8855,8 +9269,6 @@ ResetGameEvent()
     }\r
 }\r
 \r
-static int exiting = 0;\r
-\r
 void\r
 ExitEvent(status)\r
      int status;\r
@@ -8879,8 +9291,10 @@ ExitEvent(status)
     if (icsPR != NoProc) {\r
       DestroyChildProcess(icsPR, TRUE);\r
     }\r
+#if 0\r
     /* Save game if resource set and not already saved by GameEnds() */\r
-    if (gameInfo.resultDetails == NULL && forwardMostMove > 0) {\r
+    if ((gameInfo.resultDetails == NULL || errorExitFlag )\r
+                             && forwardMostMove > 0) {\r
       if (*appData.saveGameFile != NULLCHAR) {\r
        SaveGameToFile(appData.saveGameFile, TRUE);\r
       } else if (appData.autoSaveGames) {\r
@@ -8891,6 +9305,17 @@ ExitEvent(status)
       }\r
     }\r
     GameEnds((ChessMove) 0, NULL, GE_PLAYER);\r
+#else\r
+    /* [HGM] crash: leave writing PGN and position entirely to GameEnds() */\r
+    GameEnds(gameInfo.result, gameInfo.resultDetails==NULL ? "aborted" : gameInfo.resultDetails, GE_PLAYER);\r
+#endif\r
+    /* [HGM] crash: the above GameEnds() is a dud if another one was running */\r
+    /* make sure this other one finishes before killing it!                  */\r
+    if(endingGame) { int count = 0;\r
+        if(appData.debugMode) fprintf(debugFP, "ExitEvent() during GameEnds(), wait\n");\r
+        while(endingGame && count++ < 10) DoSleep(1);\r
+        if(appData.debugMode && endingGame) fprintf(debugFP, "GameEnds() seems stuck, proceed exiting\n");\r
+    }\r
 \r
     /* Kill off chess programs */\r
     if (first.pr != NoProc) {\r
@@ -9264,10 +9689,16 @@ TwoMachinesEvent P((void))
        return;\r
     }\r
     DisplayMessage("", "");\r
-    InitChessProgram(&second);\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From TwoMachines\n");\r
+    }\r
+    InitChessProgram(&second, FALSE);\r
     SendToProgram("force\n", &second);\r
     if (startedFromSetupPosition) {\r
        SendBoard(&second, backwardMostMove);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Two Machines\n");\r
+    }\r
     }\r
     for (i = backwardMostMove; i < forwardMostMove; i++) {\r
        SendMoveToProgram(i, &second);\r
@@ -9503,7 +9934,10 @@ void
 EditPositionDone()\r
 {\r
     startedFromSetupPosition = TRUE;\r
-    InitChessProgram(&first);\r
+    if (appData.debugMode) {\r
+       fprintf(debugFP, "From EditPosition\n");\r
+    }\r
+    InitChessProgram(&first, FALSE);\r
     SendToProgram("force\n", &first);\r
     if (blackPlaysFirst) {\r
        strcpy(moveList[0], "");\r
@@ -9514,6 +9948,9 @@ EditPositionDone()
        currentMove = forwardMostMove = backwardMostMove = 0;\r
     }\r
     SendBoard(&first, forwardMostMove);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "EditPosDone\n");\r
+    }\r
     DisplayTitle("");\r
     timeRemaining[0][forwardMostMove] = whiteTimeRemaining;\r
     timeRemaining[1][forwardMostMove] = blackTimeRemaining;\r
@@ -9647,20 +10084,18 @@ EditPositionMenuEvent(selection, x, y)
        break;\r
 \r
       case PromotePiece:\r
-        if(piece >= (int)WhitePawn && piece < (int)WhiteWazir ||\r
-           piece >= (int)BlackPawn && piece < (int)BlackWazir   ) {\r
+        if(piece >= (int)WhitePawn && piece < (int)WhiteMan ||\r
+           piece >= (int)BlackPawn && piece < (int)BlackMan   ) {\r
             selection = (ChessSquare) (PROMOTED piece);\r
-        } else if(piece == EmptySquare) selection = WhiteWazir;\r
+        } else if(piece == EmptySquare) selection = WhiteSilver;\r
         else selection = (ChessSquare)((int)piece - 1);\r
         goto defaultlabel;\r
 \r
       case DemotePiece:\r
-        if(piece >= (int)WhiteUnicorn && piece < (int)WhiteKing ||\r
-           piece >= (int)BlackUnicorn && piece < (int)BlackKing   ) {\r
+        if(piece > (int)WhiteMan && piece <= (int)WhiteKing ||\r
+           piece > (int)BlackMan && piece <= (int)BlackKing   ) {\r
             selection = (ChessSquare) (DEMOTED piece);\r
-        } else if( piece == WhiteKing || piece == BlackKing )\r
-            selection = (ChessSquare)((int)piece - (int)WhiteKing + (int)WhiteMan);\r
-        else if(piece == EmptySquare) selection = BlackWazir;\r
+        } else if(piece == EmptySquare) selection = BlackSilver;\r
         else selection = (ChessSquare)((int)piece + 1);       \r
         goto defaultlabel;\r
 \r
@@ -10011,7 +10446,7 @@ ForwardInner(target)
     DisplayMove(currentMove - 1);\r
     DrawPosition(FALSE, boards[currentMove]);\r
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);\r
-    if (commentList[currentMove] && !matchMode && gameMode != Training) {\r
+    if ( !matchMode && gameMode != Training) { // [HGM] PV info: routine tests if empty\r
        DisplayComment(currentMove - 1, commentList[currentMove]);\r
     }\r
 }\r
@@ -10114,9 +10549,8 @@ BackwardInner(target)
     DisplayMove(currentMove - 1);\r
     DrawPosition(full_redraw, boards[currentMove]);\r
     HistorySet(parseList,backwardMostMove,forwardMostMove,currentMove-1);\r
-    if (commentList[currentMove] != NULL) {\r
-       DisplayComment(currentMove - 1, commentList[currentMove]);\r
-    }\r
+    // [HGM] PV info: routine tests if comment empty\r
+    DisplayComment(currentMove - 1, commentList[currentMove]);\r
 }\r
 \r
 void\r
@@ -10403,6 +10837,7 @@ TidyProgramName(prog, host, buf)
     p = q;\r
     while (p >= prog && *p != '/' && *p != '\\') p--;\r
     p++;\r
+    if(p == prog && *p == '"') p++;\r
     if (q - p >= 4 && StrCaseCmp(q - 4, ".exe") == 0) q -= 4;\r
     memcpy(buf, p, q - p);\r
     buf[q - p] = NULLCHAR;\r
@@ -10563,7 +10998,7 @@ AppendComment(index, text)
     int oldlen, len;\r
     char *old;\r
 \r
-    GetInfoFromComment( index, text );\r
+    text = GetInfoFromComment( index, text ); /* [HGM] PV time: strip PV info from comment */\r
 \r
     CrushCRs(text);\r
     while (*text == '\n') text++;\r
@@ -10601,12 +11036,15 @@ static char * FindStr( char * text, char * sub_text )
 }\r
 \r
 /* [AS] Try to extract PV info from PGN comment */\r
-void GetInfoFromComment( int index, char * text )\r
+/* [HGM] PV time: and then remove it, to prevent it appearing twice */\r
+char *GetInfoFromComment( int index, char * text )\r
 {\r
+    char * sep = text;\r
+\r
     if( text != NULL && index > 0 ) {\r
         int score = 0;\r
         int depth = 0;\r
-        int time = -1;\r
+        int time = -1, sec = 0;\r
         char * s_eval = FindStr( text, "[%eval " );\r
         char * s_emt = FindStr( text, "[%emt " );\r
 \r
@@ -10616,11 +11054,11 @@ void GetInfoFromComment( int index, char * text )
 \r
             if( s_eval != NULL ) {\r
                 if( sscanf( s_eval, "%d,%d%c", &score, &depth, &delim ) != 3 ) {\r
-                    return;\r
+                    return text;\r
                 }\r
 \r
                 if( delim != ']' ) {\r
-                    return;\r
+                    return text;\r
                 }\r
             }\r
 \r
@@ -10629,26 +11067,38 @@ void GetInfoFromComment( int index, char * text )
         }\r
         else {\r
             /* We expect something like: [+|-]nnn.nn/dd */\r
-            char * sep = strchr( text, '/' );\r
             int score_lo = 0;\r
 \r
+            sep = strchr( text, '/' );\r
             if( sep == NULL || sep < (text+4) ) {\r
-                return;\r
+                return text;\r
             }\r
 \r
-            if( sscanf( text, "%d.%d/%d", &score, &score_lo, &depth ) != 3 ) {\r
-                return;\r
+            time = -1; sec = -1;\r
+            if( sscanf( text, "%d.%d/%d %d:%d", &score, &score_lo, &depth, &time, &sec ) != 5 &&\r
+                sscanf( text, "%d.%d/%d %d", &score, &score_lo, &depth, &time ) != 4 &&\r
+                sscanf( text, "%d.%d/%d", &score, &score_lo, &depth ) != 3   ) {\r
+                return text;\r
             }\r
 \r
             if( score_lo < 0 || score_lo >= 100 ) {\r
-                return;\r
+                return text;\r
             }\r
 \r
+            if(sec >= 0) time = 60*time + sec;\r
             score = score >= 0 ? score*100 + score_lo : score*100 - score_lo;\r
+\r
+            /* [HGM] PV time: now locate end of PV info */\r
+            while( *++sep >= '0' && *sep <= '9'); // strip depth\r
+            if(time >= 0)\r
+            while( *++sep >= '0' && *sep <= '9'); // strip time\r
+            if(sec >= 0)\r
+            while( *++sep >= '0' && *sep <= '9'); // strip seconds\r
+            while(*sep == ' ') sep++;\r
         }\r
 \r
         if( depth <= 0 ) {\r
-            return;\r
+            return text;\r
         }\r
 \r
         if( time < 0 ) {\r
@@ -10657,8 +11107,9 @@ void GetInfoFromComment( int index, char * text )
 \r
         pvInfoList[index-1].depth = depth;\r
         pvInfoList[index-1].score = score;\r
-        pvInfoList[index-1].time = time;\r
+        pvInfoList[index-1].time  = time;\r
     }\r
+    return sep;\r
 }\r
 \r
 void\r
@@ -10682,9 +11133,19 @@ SendToProgram(message, cps)
     \r
     count = strlen(message);\r
     outCount = OutputToProcess(cps->pr, message, count, &error);\r
-    if (outCount < count && !exiting) {\r
+    if (outCount < count && !exiting \r
+                         && !endingGame) { /* [HGM] crash: to not hang GameEnds() writing to deceased engines */\r
        sprintf(buf, "Error writing to %s chess program", cps->which);\r
-       DisplayFatalError(buf, error, 1);\r
+        if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */\r
+            if(epStatus[forwardMostMove] <= EP_DRAWS) {\r
+                gameInfo.result = GameIsDrawn; /* [HGM] accept exit as draw claim */\r
+                sprintf(buf, "%s program exits in draw position (%s)", cps->which, cps->program);\r
+            } else {\r
+                gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;\r
+            }\r
+            gameInfo.resultDetails = buf;\r
+        }\r
+        DisplayFatalError(buf, error, 1);\r
     }\r
 }\r
 \r
@@ -10706,6 +11167,15 @@ ReceiveFromProgram(isr, closure, message, count, error)
            sprintf(buf,\r
                    "Error: %s chess program (%s) exited unexpectedly",\r
                    cps->which, cps->program);\r
+        if(gameInfo.resultDetails==NULL) { /* [HGM] crash: if game in progress, give reason for abort */\r
+                if(epStatus[forwardMostMove] <= EP_DRAWS) {\r
+                    gameInfo.result = GameIsDrawn; /* [HGM] accept exit as draw claim */\r
+                    sprintf(buf, "%s program exits in draw position (%s)", cps->which, cps->program);\r
+                } else {\r
+                    gameInfo.result = cps->twoMachinesColor[0]=='w' ? BlackWins : WhiteWins;\r
+                }\r
+                gameInfo.resultDetails = buf;\r
+            }\r
            RemoveInputSource(cps->isr);\r
            DisplayFatalError(buf, 0, 1);\r
        } else {\r
@@ -10722,7 +11192,6 @@ ReceiveFromProgram(isr, closure, message, count, error)
 \r
             DisplayFatalError(buf, error, 1);\r
        }\r
-       GameEnds((ChessMove) 0, NULL, GE_PLAYER);\r
        return;\r
     }\r
     \r
@@ -10749,13 +11218,18 @@ SendTimeControl(cps, mps, tc, inc, sd, st)
      long tc;\r
 {\r
     char buf[MSG_SIZ];\r
-    int seconds = (tc / 1000) % 60;\r
+    int seconds;\r
 \r
     if( timeControl_2 > 0 ) {\r
         if( (gameMode == MachinePlaysBlack) || (gameMode == TwoMachinesPlay && cps->twoMachinesColor[0] == 'b') ) {\r
             tc = timeControl_2;\r
         }\r
     }\r
+    tc  /= cps->timeOdds; /* [HGM] time odds: apply before telling engine */\r
+    inc /= cps->timeOdds;\r
+    st  /= cps->timeOdds;\r
+\r
+    seconds = (tc / 1000) % 60; /* [HGM] displaced to after applying odds */\r
 \r
     if (st > 0) {\r
       /* Set exact time per move, normally using st command */\r
@@ -10796,6 +11270,14 @@ SendTimeControl(cps, mps, tc, inc, sd, st)
     }\r
 }\r
 \r
+ChessProgramState *WhitePlayer()\r
+/* [HGM] return pointer to 'first' or 'second', depending on who plays white */\r
+{\r
+    if(gameMode == TwoMachinesPlay && first.twoMachinesColor[0] == 'b')\r
+        return &second;\r
+    return &first;\r
+}\r
+\r
 void\r
 SendTimeRemaining(cps, machineWhite)\r
      ChessProgramState *cps;\r
@@ -10815,6 +11297,12 @@ SendTimeRemaining(cps, machineWhite)
        time = blackTimeRemaining / 10;\r
        otime = whiteTimeRemaining / 10;\r
     }\r
+    /* [HGM] translate opponent's time by time-odds factor */\r
+    otime = (otime * cps->other->timeOdds) / cps->timeOdds;\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "time odds: %d %d \n", cps->timeOdds, cps->other->timeOdds);\r
+    }\r
+\r
     if (time <= 0) time = 1;\r
     if (otime <= 0) otime = 1;\r
     \r
@@ -10946,6 +11434,8 @@ ParseFeatures(args, cps)
     if (BoolFeature(&p, "ics", &cps->sendICS, cps)) continue;\r
     if (BoolFeature(&p, "name", &cps->sendName, cps)) continue;\r
     if (BoolFeature(&p, "pause", &val, cps)) continue; /* unused at present */\r
+    if (BoolFeature(&p, "debug", &cps->debug, cps)) continue;\r
+    if (IntFeature(&p, "level", &cps->maxNrOfSessions, cps)) continue;\r
     if (IntFeature(&p, "done", &val, cps)) {\r
       FeatureDone(cps, val);\r
       continue;\r
@@ -11192,6 +11682,8 @@ DisplayComment(moveNumber, text)
      char *text;\r
 {\r
     char title[MSG_SIZ];\r
+    char buf[8000]; // comment can be long!\r
+    int score, depth;\r
 \r
     if( appData.autoDisplayComment ) {\r
         if (moveNumber < 0 || parseList[moveNumber][0] == NULLCHAR) {\r
@@ -11201,9 +11693,18 @@ DisplayComment(moveNumber, text)
                    WhiteOnMove(moveNumber) ? " " : ".. ",\r
                    parseList[moveNumber]);\r
         }\r
-\r
+    } else title[0] = 0;\r
+\r
+    // [HGM] PV info: display PV info together with (or as) comment\r
+    if(moveNumber >= 0 && (depth = pvInfoList[moveNumber].depth) > 0) {\r
+        if(text == NULL) text = "";                                           \r
+        score = pvInfoList[moveNumber].score;\r
+        sprintf(buf, "%s%.2f/%d %d\n%s", score>0 ? "+" : "", score/100.,\r
+                              depth, pvInfoList[moveNumber].time, text);\r
+        CommentPopUp(title, buf);\r
+    } else\r
+    if (text != NULL)\r
         CommentPopUp(title, text);\r
-    }\r
 }\r
 \r
 /* This routine sends a ^C interrupt to gnuchess, to awaken it if it\r
@@ -11296,30 +11797,18 @@ CheckTimeControl()
     if (!appData.clockMode || appData.icsActive ||\r
        gameMode == PlayFromGameFile || forwardMostMove == 0) return;\r
 \r
-    if (timeIncrement >= 0) {\r
-       if (WhiteOnMove(forwardMostMove)) {\r
-           blackTimeRemaining += timeIncrement;\r
-       } else {\r
-           whiteTimeRemaining += timeIncrement;\r
-       }\r
-    }\r
     /*\r
-     * add time to clocks when time control is achieved\r
+     * add time to clocks when time control is achieved ([HGM] now also used fot increment)\r
      */\r
-    if (movesPerSession) {\r
-      switch ((forwardMostMove + 1) % (movesPerSession * 2)) {\r
-      case 0:\r
+    if ( !WhiteOnMove(forwardMostMove) )\r
        /* White made time control */\r
-       whiteTimeRemaining += GetTimeControlForWhite();\r
-       break;\r
-      case 1:\r
+        whiteTimeRemaining += GetTimeQuota((forwardMostMove-1)/2)\r
+        /* [HGM] time odds: correct new time quota for time odds! */\r
+                                            / WhitePlayer()->timeOdds;\r
+      else\r
        /* Black made time control */\r
-       blackTimeRemaining += GetTimeControlForBlack();\r
-       break;\r
-      default:\r
-       break;\r
-      }\r
-    }\r
+        blackTimeRemaining += GetTimeQuota((forwardMostMove-1)/2)\r
+                                            / WhitePlayer()->other->timeOdds;\r
 }\r
 \r
 void\r
@@ -11426,9 +11915,9 @@ ResetClocks()
     (void) StopClockTimer();\r
     if (appData.icsActive) {\r
        whiteTimeRemaining = blackTimeRemaining = 0;\r
-    } else {\r
-       whiteTimeRemaining = GetTimeControlForWhite();\r
-        blackTimeRemaining = GetTimeControlForBlack();\r
+    } else { /* [HGM] correct new time quote for time odds */\r
+        whiteTimeRemaining = GetTimeQuota(-1) / WhitePlayer()->timeOdds;\r
+        blackTimeRemaining = GetTimeQuota(-1) / WhitePlayer()->other->timeOdds;\r
     }\r
     if (whiteFlag || blackFlag) {\r
        DisplayTitle("");\r
@@ -11518,12 +12007,17 @@ SwitchClocks()
        lastTickLength = SubtractTimeMarks(&now, &tickStartTM);\r
        if (WhiteOnMove(forwardMostMove)) {\r
            blackTimeRemaining -= lastTickLength;\r
+           /* [HGM] PGNtime: save time for PGN file if engine did not give it */\r
+            if(pvInfoList[forwardMostMove-1].time == -1)\r
+                 pvInfoList[forwardMostMove-1].time = \r
+                      (timeRemaining[1][forwardMostMove-1] - blackTimeRemaining)/10;\r
        } else {\r
            whiteTimeRemaining -= lastTickLength;\r
+           /* [HGM] PGNtime: save time for PGN file if engine did not give it */\r
+            if(pvInfoList[forwardMostMove-1].time == -1)\r
+                 pvInfoList[forwardMostMove-1].time = \r
+                      (timeRemaining[0][forwardMostMove-1] - whiteTimeRemaining)/10;\r
        }\r
-        /* [HGM] save time for PGN file if engine did not give it */\r
-        if(pvInfoList[forwardMostMove-1].time == -1)\r
-             pvInfoList[forwardMostMove-1].time = lastTickLength/100;\r
        flagged = CheckFlags();\r
     }\r
     CheckTimeControl();\r
@@ -11801,84 +12295,50 @@ PositionToFEN(move, useFEN960)
     }\r
     *(p - 1) = ' ';\r
 \r
+    /* [HGM] print Crazyhouse or Shogi holdings */\r
+    if( gameInfo.holdingsWidth ) {\r
+        *(p-1) = '['; /* if we wanted to support BFEN, this could be '/' */\r
+        q = p;\r
+        for(i=0; i<gameInfo.holdingsSize; i++) { /* white holdings */\r
+            piece = boards[move][i][BOARD_WIDTH-1];\r
+            if( piece != EmptySquare )\r
+              for(j=0; j<(int) boards[move][i][BOARD_WIDTH-2]; j++)\r
+                  *p++ = PieceToChar(piece);\r
+        }\r
+        for(i=0; i<gameInfo.holdingsSize; i++) { /* black holdings */\r
+            piece = boards[move][BOARD_HEIGHT-i-1][0];\r
+            if( piece != EmptySquare )\r
+              for(j=0; j<(int) boards[move][BOARD_HEIGHT-i-1][1]; j++)\r
+                  *p++ = PieceToChar(piece);\r
+        }\r
+\r
+        if( q == p ) *p++ = '-';\r
+        *p++ = ']';\r
+        *p++ = ' ';\r
+    }\r
+\r
     /* Active color */\r
     *p++ = whiteToPlay ? 'w' : 'b';\r
     *p++ = ' ';\r
 \r
   if(nrCastlingRights) {\r
-    /* HACK: we don't keep track of castling availability, so fake it! */\r
-    /* Tord! please fix with the aid of castlingRights[move][...] */\r
-\r
-    /* PUSH Fabien & Tord */\r
-\r
-    /* Declare all potential FRC castling rights (conservative) */\r
-    /* outermost rook on each side of the king */\r
-\r
-    if( gameInfo.variant == VariantFischeRandom ) {\r
-       int fk, fr;\r
-\r
-       q = p;\r
+     q = p;\r
+     if(gameInfo.variant == VariantFischeRandom) {\r
+       /* [HGM] write directly from rights */\r
+           if(castlingRights[move][2] >= 0 &&\r
+              castlingRights[move][0] >= 0   )\r
+                *p++ = castlingRights[move][0] + AAA + 'A' - 'a';\r
+           if(castlingRights[move][2] >= 0 &&\r
+              castlingRights[move][1] >= 0   )\r
+                *p++ = castlingRights[move][1] + AAA + 'A' - 'a';\r
+           if(castlingRights[move][5] >= 0 &&\r
+              castlingRights[move][3] >= 0   )\r
+                *p++ = castlingRights[move][3] + AAA;\r
+           if(castlingRights[move][5] >= 0 &&\r
+              castlingRights[move][4] >= 0   )\r
+                *p++ = castlingRights[move][4] + AAA;\r
+     } else {\r
 \r
-       /* White castling rights */\r
-\r
-       for (fk = BOARD_LEFT+1; fk < BOARD_RGHT-1; fk++) {\r
-\r
-          if (boards[move][0][fk] == WhiteKing) {\r
-\r
-             for (fr = BOARD_RGHT-1; fr > fk; fr--) { /* H side */\r
-                if (boards[move][0][fr] == WhiteRook) {\r
-                   *p++ = useFEN960 ? 'A' + fr : 'K';\r
-                   break;\r
-                }\r
-             }\r
-\r
-             for (fr = BOARD_LEFT; fr < fk; fr++) { /* A side */\r
-                if (boards[move][0][fr] == WhiteRook) {\r
-                   *p++ = useFEN960 ? 'A' + fr : 'Q';\r
-                   break;\r
-                }\r
-             }\r
-          }\r
-       }\r
-\r
-       /* Black castling rights */\r
-\r
-       for (fk = BOARD_LEFT+1; fk < BOARD_RGHT-1; fk++) {\r
-\r
-          if (boards[move][BOARD_HEIGHT-1][fk] == BlackKing) {\r
-\r
-             for (fr = BOARD_RGHT-1; fr > fk; fr--) { /* H side */\r
-                if (boards[move][BOARD_HEIGHT-1][fr] == BlackRook) {\r
-                   *p++ = useFEN960 ? 'a' + fr : 'k';\r
-                   break;\r
-                }\r
-             }\r
-\r
-             for (fr = BOARD_LEFT; fr < fk; fr++) { /* A side */\r
-                if (boards[move][BOARD_HEIGHT-1][fr] == BlackRook) {\r
-                   *p++ = useFEN960 ? 'a' + fr : 'q';\r
-                   break;\r
-                }\r
-             }\r
-          }\r
-       }\r
-\r
-       if (q == p) *p++ = '-'; /* No castling rights */\r
-       *p++ = ' ';\r
-    }\r
-    else {\r
-        q = p;\r
-\r
-#ifdef OLDCASTLINGCODE\r
-        if (boards[move][0][BOARD_WIDTH>>1] == WhiteKing) {\r
-            if (boards[move][0][BOARD_RGHT-1] == WhiteRook) *p++ = 'K';\r
-            if (boards[move][0][BOARD_LEFT] == WhiteRook) *p++ = 'Q';\r
-        }\r
-        if (boards[move][BOARD_HEIGHT-1][BOARD_WIDTH>>1] == BlackKing) {\r
-           if (boards[move][BOARD_HEIGHT-1][BOARD_HEIGHT-1] == BlackRook) *p++ = 'k';\r
-            if (boards[move][BOARD_HEIGHT-1][BOARD_LEFT] == BlackRook) *p++ = 'q';\r
-        }          \r
-#else\r
         /* [HGM] write true castling rights */\r
         if( nrCastlingRights == 6 ) {\r
             if(castlingRights[move][0] == BOARD_RGHT-1 &&\r
@@ -11890,12 +12350,9 @@ PositionToFEN(move, useFEN960)
             if(castlingRights[move][4] == BOARD_LEFT &&\r
                castlingRights[move][5] >= 0  ) *p++ = 'q';\r
         }\r
-#endif\r
-        if (q == p) *p++ = '-';\r
-        *p++ = ' ';\r
-    }\r
-\r
-    /* POP Fabien & Tord */\r
+     }\r
+     if (q == p) *p++ = '-'; /* No castling rights */\r
+     *p++ = ' ';\r
   }\r
 \r
   if(gameInfo.variant != VariantShogi    && gameInfo.variant != VariantXiangqi &&\r
@@ -11922,26 +12379,6 @@ PositionToFEN(move, useFEN960)
     *p++ = ' ';\r
   }\r
 \r
-    /* [HGM] print Crazyhouse or Shogi holdings */\r
-    if( gameInfo.holdingsWidth ) {\r
-        q = p;\r
-        for(i=0; i<gameInfo.holdingsSize; i++) { /* white holdings */\r
-            piece = boards[move][i][BOARD_WIDTH-1];\r
-            if( piece != EmptySquare )\r
-              for(j=0; j<(int) boards[move][i][BOARD_WIDTH-2]; j++)\r
-                  *p++ = PieceToChar(piece);\r
-        }\r
-        for(i=0; i<gameInfo.holdingsSize; i++) { /* black holdings */\r
-            piece = boards[move][BOARD_HEIGHT-i-1][0];\r
-            if( piece != EmptySquare )\r
-              for(j=0; j<(int) boards[move][BOARD_HEIGHT-i-1][1]; j++)\r
-                  *p++ = PieceToChar(piece);\r
-        }\r
-\r
-        if( q == p ) *p++ = '-';\r
-        *p++ = ' ';\r
-    }\r
-\r
     /* [HGM] find reversible plies */\r
     {   int i = 0, j=move;\r
 \r
@@ -11990,8 +12427,8 @@ ParseFEN(board, blackPlaysFirst, fen)
     for (i = BOARD_HEIGHT - 1; i >= 0; i--) {\r
        j = 0;\r
        for (;;) {\r
-           if (*p == '/' || *p == ' ') {\r
-               if (*p == '/') p++;\r
+            if (*p == '/' || *p == ' ' || (*p == '[' && i == 0) ) {\r
+                if (*p == '/') p++;\r
                 emptycount = gameInfo.boardWidth - j;\r
                 while (emptycount--)\r
                         board[i][(j++)+gameInfo.holdingsWidth] = EmptySquare;\r
@@ -12032,6 +12469,34 @@ ParseFEN(board, blackPlaysFirst, fen)
     }\r
     while (*p == '/' || *p == ' ') p++;\r
 \r
+    /* [HGM] look for Crazyhouse holdings here */\r
+    while(*p==' ') p++;\r
+    if( gameInfo.holdingsWidth && p[-1] == '/' || *p == '[') {\r
+        if(*p == '[') p++;\r
+        if(*p == '-' ) *p++; /* empty holdings */ else {\r
+            if( !gameInfo.holdingsWidth ) return FALSE; /* no room to put holdings! */\r
+            /* if we would allow FEN reading to set board size, we would   */\r
+            /* have to add holdings and shift the board read so far here   */\r
+            while( (piece = CharToPiece(*p) ) != EmptySquare ) {\r
+                *p++;\r
+                if((int) piece >= (int) BlackPawn ) {\r
+                    i = (int)piece - (int)BlackPawn;\r
+                    if( i >= BOARD_HEIGHT ) return FALSE;\r
+                    board[BOARD_HEIGHT-1-i][0] = piece; /* black holdings */\r
+                    board[BOARD_HEIGHT-1-i][1]++;       /* black counts   */\r
+                } else {\r
+                    i = (int)piece - (int)WhitePawn;\r
+                    if( i >= BOARD_HEIGHT ) return FALSE;\r
+                    board[i][BOARD_WIDTH-1] = piece;    /* white holdings */\r
+                    board[i][BOARD_WIDTH-2]++;          /* black holdings */\r
+                }\r
+            }\r
+        }\r
+        if(*p == ']') *p++;\r
+    }\r
+\r
+    while(*p == ' ') p++;\r
+\r
     /* Active color */\r
     switch (*p++) {\r
       case 'w':\r
@@ -12050,7 +12515,8 @@ ParseFEN(board, blackPlaysFirst, fen)
     /* set defaults in case FEN is incomplete */\r
     FENepStatus = EP_UNKNOWN;\r
     for(i=0; i<nrCastlingRights; i++ ) {\r
-        FENcastlingRights[i] = initialRights[i];\r
+        FENcastlingRights[i] =\r
+            gameInfo.variant == VariantFischeRandom ? -1 : initialRights[i];\r
     }   /* assume possible unless obviously impossible */\r
     if(initialRights[0]>=0 && board[castlingRank[0]][initialRights[0]] != WhiteRook) FENcastlingRights[0] = -1;\r
     if(initialRights[1]>=0 && board[castlingRank[1]][initialRights[1]] != WhiteRook) FENcastlingRights[1] = -1;\r
@@ -12068,27 +12534,71 @@ ParseFEN(board, blackPlaysFirst, fen)
                  FENcastlingRights[i] = -1;\r
           }\r
       }\r
-      while(*p=='K' || *p=='Q' || *p=='k' || *p=='q' || *p=='-') {\r
-        switch(*p++) {\r
+      while(*p=='K' || *p=='Q' || *p=='k' || *p=='q' || *p=='-' ||\r
+             gameInfo.variant == VariantFischeRandom &&\r
+             ( *p >= 'a' && *p < 'a' + gameInfo.boardWidth) ||\r
+             ( *p >= 'A' && *p < 'A' + gameInfo.boardWidth)   ) {\r
+        char c = *p++; int whiteKingFile=-1, blackKingFile=-1;\r
+\r
+        for(i=BOARD_LEFT; i<BOARD_RGHT; i++) {\r
+            if(board[BOARD_HEIGHT-1][i] == BlackKing) blackKingFile = i;\r
+            if(board[0             ][i] == WhiteKing) whiteKingFile = i;\r
+        }\r
+        switch(c) {\r
           case'K':\r
-              FENcastlingRights[0] = BOARD_RGHT-1;\r
-              FENcastlingRights[2] = BOARD_WIDTH>>1;\r
+              for(i=BOARD_RGHT-1; board[0][i]!=WhiteRook && i>whiteKingFile; i--);\r
+              FENcastlingRights[0] = i != whiteKingFile ? i : -1;\r
+              FENcastlingRights[2] = whiteKingFile;\r
               break;\r
           case'Q':\r
-              FENcastlingRights[1] = BOARD_LEFT;\r
-              FENcastlingRights[2] = BOARD_WIDTH>>1;\r
+              for(i=BOARD_LEFT; board[0][i]!=WhiteRook && i<whiteKingFile; i++);\r
+              FENcastlingRights[1] = i != whiteKingFile ? i : -1;\r
+              FENcastlingRights[2] = whiteKingFile;\r
               break;\r
           case'k':\r
-              FENcastlingRights[3] = BOARD_RGHT-1;\r
-              FENcastlingRights[5] = BOARD_WIDTH>>1;\r
+              for(i=BOARD_RGHT-1; board[BOARD_HEIGHT-1][i]!=BlackRook && i>blackKingFile; i--);\r
+              FENcastlingRights[3] = i != blackKingFile ? i : -1;\r
+              FENcastlingRights[5] = blackKingFile;\r
               break;\r
           case'q':\r
-              FENcastlingRights[4] = BOARD_LEFT;\r
-              FENcastlingRights[5] = BOARD_WIDTH>>1;\r
+              for(i=BOARD_LEFT; board[BOARD_HEIGHT-1][i]!=BlackRook && i<blackKingFile; i++);\r
+              FENcastlingRights[4] = i != blackKingFile ? i : -1;\r
+              FENcastlingRights[5] = blackKingFile;\r
+          case '-':\r
               break;\r
-          /* Tord! FRC! */\r
+          default: /* FRC castlings */\r
+              if(c >= 'a') { /* black rights */\r
+                  for(i=BOARD_LEFT; i<BOARD_RGHT; i++)\r
+                    if(board[BOARD_HEIGHT-1][i] == BlackKing) break;\r
+                  if(i == BOARD_RGHT) break;\r
+                  FENcastlingRights[5] = i;\r
+                  c -= AAA;\r
+                  if(board[BOARD_HEIGHT-1][c] <  BlackPawn ||\r
+                     board[BOARD_HEIGHT-1][c] >= BlackKing   ) break;\r
+                  if(c > i)\r
+                      FENcastlingRights[3] = c;\r
+                  else\r
+                      FENcastlingRights[4] = c;\r
+              } else { /* white rights */\r
+                  for(i=BOARD_LEFT; i<BOARD_RGHT; i++)\r
+                    if(board[0][i] == WhiteKing) break;\r
+                  if(i == BOARD_RGHT) break;\r
+                  FENcastlingRights[2] = i;\r
+                  c -= AAA - 'a' + 'A';\r
+                  if(board[0][c] >= WhiteKing) break;\r
+                  if(c > i)\r
+                      FENcastlingRights[0] = c;\r
+                  else\r
+                      FENcastlingRights[1] = c;\r
+              }\r
         }\r
       }\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "FEN castling rights:");\r
+        for(i=0; i<nrCastlingRights; i++)\r
+        fprintf(debugFP, " %d", FENcastlingRights[i]);\r
+        fprintf(debugFP, "\n");\r
+    }\r
 \r
       while(*p==' ') p++;\r
     }\r
@@ -12107,30 +12617,6 @@ ParseFEN(board, blackPlaysFirst, fen)
       }\r
     }\r
 \r
-    /* [HGM] look for Crazyhouse holdings here */\r
-    while(*p==' ') p++;\r
-    if( gameInfo.holdingsWidth ) {\r
-        if(*p == '-' ) *p++; /* empty holdings */ else {\r
-            if( !gameInfo.holdingsWidth ) return FALSE; /* no room to put holdings! */\r
-            /* if we would allow FEN reading to set board size, we would   */\r
-            /* have to add holdings and shift the board read so far here   */\r
-            while( (piece = CharToPiece(*p) ) != EmptySquare ) {\r
-                *p++;\r
-                if((int) piece >= (int) BlackPawn ) {\r
-                    i = (int)piece - (int)BlackPawn;\r
-                    if( i >= BOARD_HEIGHT ) return FALSE;\r
-                    board[BOARD_HEIGHT-1-i][0] = piece; /* black holdings */\r
-                    board[BOARD_HEIGHT-1-i][1]++;       /* black counts   */\r
-                } else {\r
-                    i = (int)piece - (int)WhitePawn;\r
-                    if( i >= BOARD_HEIGHT ) return FALSE;\r
-                    board[i][BOARD_WIDTH-1] = piece;    /* white holdings */\r
-                    board[i][BOARD_WIDTH-2]++;          /* black holdings */\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
 \r
     if(sscanf(p, "%d", &i) == 1) {\r
         FENrulePlies = i; /* 50-move ply counter */\r
index 8ef5bf3..111a3af 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -251,6 +251,12 @@ typedef struct _CPS {
     int scoreIsAbsolute; /* [AS] 0=don't know (standard), 1=score is always from white side */\r
     int isUCI;           /* [AS] 0=no (Winboard), 1=UCI (requires Polyglot) */\r
     int hasOwnBookUCI;   /* [AS] 0=use GUI or Polyglot book, 1=has own book */\r
+\r
+    /* [HGM] time odds */\r
+    int timeOdds;   /* factor through which we divide time for this engine  */\r
+    int debug;      /* [HGM] ignore engine debug lines starting with '#'    */\r
+    int maxNrOfSessions; /* [HGM] secondary TC: max args in 'level' command */\r
+    int accumulateTC; /* [HGM] secondary TC: how to handle extra sessions   */\r
 } ChessProgramState;\r
 \r
 extern ChessProgramState first, second;\r
index 4014e3b..a7592e7 100644 (file)
@@ -1,72 +1,72 @@
-/*
- * backendz.h -- Internal interface exported by XBoard backend.c to zippy.c
- * $Id: backendz.h,v 2.1 2003/10/27 19:21:00 mann Exp $
- *
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
- * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
- *
- * The following terms apply to Digital Equipment Corporation's copyright
- * interest in XBoard:
- * ------------------------------------------------------------------------
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of Digital not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * ------------------------------------------------------------------------
- *
- * The following terms apply to the enhanced version of XBoard distributed
- * by the Free Software Foundation:
- * ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * ------------------------------------------------------------------------
- */
-
-#ifndef _BACKENDZ
-#define _BACKENDZ
-
-#include "common.h"
-#include "frontend.h"
-
-extern long whiteTimeRemaining, blackTimeRemaining;
-extern int forwardMostMove;
-extern char star_match[STAR_MATCH_N][MSG_SIZ];
-extern ProcRef firstProgramPR;
-extern int startedFromSetupPosition;
-extern int firstMove;
-extern GameInfo gameInfo;
-extern void SendToICS P((char *s));
-extern int looking_at P((char *, int *, char *));
-extern void SendToProgram P((char *message, ChessProgramState *cps));
-extern void SendBoard P((ChessProgramState *cps, int moveNum));
-void SendTimeRemaining P((ChessProgramState *cps,
-                         int/*boolean*/ machineWhite));
-
-extern char ics_handle[];
-extern char *ics_prefix;
-
-#endif
+/*\r
+ * backendz.h -- Internal interface exported by XBoard backend.c to zippy.c\r
+ * $Id: backendz.h,v 2.1 2003/10/27 19:21:00 mann Exp $\r
+ *\r
+ * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
+ * Enhancements Copyright 1992-95 Free Software Foundation, Inc.\r
+ *\r
+ * The following terms apply to Digital Equipment Corporation's copyright\r
+ * interest in XBoard:\r
+ * ------------------------------------------------------------------------\r
+ * All Rights Reserved\r
+ *\r
+ * Permission to use, copy, modify, and distribute this software and its\r
+ * documentation for any purpose and without fee is hereby granted,\r
+ * provided that the above copyright notice appear in all copies and that\r
+ * both that copyright notice and this permission notice appear in\r
+ * supporting documentation, and that the name of Digital not be\r
+ * used in advertising or publicity pertaining to distribution of the\r
+ * software without specific, written prior permission.\r
+ *\r
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+ * SOFTWARE.\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * The following terms apply to the enhanced version of XBoard distributed\r
+ * by the Free Software Foundation:\r
+ * ------------------------------------------------------------------------\r
+ * This program 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
+ *\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
+ *\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
+ */\r
+\r
+#ifndef _BACKENDZ\r
+#define _BACKENDZ\r
+\r
+#include "common.h"\r
+#include "frontend.h"\r
+\r
+extern long whiteTimeRemaining, blackTimeRemaining;\r
+extern int forwardMostMove;\r
+extern char star_match[STAR_MATCH_N][MSG_SIZ];\r
+extern ProcRef firstProgramPR;\r
+extern int startedFromSetupPosition;\r
+extern int firstMove;\r
+extern GameInfo gameInfo;\r
+extern void SendToICS P((char *s));\r
+extern int looking_at P((char *, int *, char *));\r
+extern void SendToProgram P((char *message, ChessProgramState *cps));\r
+extern void SendBoard P((ChessProgramState *cps, int moveNum));\r
+void SendTimeRemaining P((ChessProgramState *cps,\r
+                         int/*boolean*/ machineWhite));\r
+\r
+extern char ics_handle[];\r
+extern char *ics_prefix;\r
+\r
+#endif\r
diff --git a/bitmaps/Thumbs.db b/bitmaps/Thumbs.db
new file mode 100644 (file)
index 0000000..401e1e8
Binary files /dev/null and b/bitmaps/Thumbs.db differ
diff --git a/bitmaps/a33o.bmp b/bitmaps/a33o.bmp
new file mode 100644 (file)
index 0000000..fcd6740
Binary files /dev/null and b/bitmaps/a33o.bmp differ
diff --git a/bitmaps/a33s.bmp b/bitmaps/a33s.bmp
new file mode 100644 (file)
index 0000000..2a1bb7d
Binary files /dev/null and b/bitmaps/a33s.bmp differ
diff --git a/bitmaps/a33w.bmp b/bitmaps/a33w.bmp
new file mode 100644 (file)
index 0000000..19598b4
Binary files /dev/null and b/bitmaps/a33w.bmp differ
diff --git a/bitmaps/a37o.bmp b/bitmaps/a37o.bmp
new file mode 100644 (file)
index 0000000..dfdc7ff
Binary files /dev/null and b/bitmaps/a37o.bmp differ
diff --git a/bitmaps/a37s.bmp b/bitmaps/a37s.bmp
new file mode 100644 (file)
index 0000000..ef1b222
Binary files /dev/null and b/bitmaps/a37s.bmp differ
diff --git a/bitmaps/a37w.bmp b/bitmaps/a37w.bmp
new file mode 100644 (file)
index 0000000..e0ed7cd
Binary files /dev/null and b/bitmaps/a37w.bmp differ
diff --git a/bitmaps/a40o.bmp b/bitmaps/a40o.bmp
new file mode 100644 (file)
index 0000000..7545fdd
Binary files /dev/null and b/bitmaps/a40o.bmp differ
diff --git a/bitmaps/a40s.bmp b/bitmaps/a40s.bmp
new file mode 100644 (file)
index 0000000..d2a67d6
Binary files /dev/null and b/bitmaps/a40s.bmp differ
diff --git a/bitmaps/a40w.bmp b/bitmaps/a40w.bmp
new file mode 100644 (file)
index 0000000..668ec31
Binary files /dev/null and b/bitmaps/a40w.bmp differ
diff --git a/bitmaps/a45o.bmp b/bitmaps/a45o.bmp
new file mode 100644 (file)
index 0000000..e6fbc98
Binary files /dev/null and b/bitmaps/a45o.bmp differ
diff --git a/bitmaps/a45s.bmp b/bitmaps/a45s.bmp
new file mode 100644 (file)
index 0000000..b6f36ae
Binary files /dev/null and b/bitmaps/a45s.bmp differ
diff --git a/bitmaps/a45w.bmp b/bitmaps/a45w.bmp
new file mode 100644 (file)
index 0000000..1b84946
Binary files /dev/null and b/bitmaps/a45w.bmp differ
diff --git a/bitmaps/a54o.bmp b/bitmaps/a54o.bmp
new file mode 100644 (file)
index 0000000..5281a27
Binary files /dev/null and b/bitmaps/a54o.bmp differ
diff --git a/bitmaps/a54s.bmp b/bitmaps/a54s.bmp
new file mode 100644 (file)
index 0000000..a7a2339
Binary files /dev/null and b/bitmaps/a54s.bmp differ
diff --git a/bitmaps/a54w.bmp b/bitmaps/a54w.bmp
new file mode 100644 (file)
index 0000000..c0208da
Binary files /dev/null and b/bitmaps/a54w.bmp differ
diff --git a/bitmaps/a58o.bmp b/bitmaps/a58o.bmp
new file mode 100644 (file)
index 0000000..1661057
Binary files /dev/null and b/bitmaps/a58o.bmp differ
diff --git a/bitmaps/a58s.bmp b/bitmaps/a58s.bmp
new file mode 100644 (file)
index 0000000..e42dded
Binary files /dev/null and b/bitmaps/a58s.bmp differ
diff --git a/bitmaps/a58w.bmp b/bitmaps/a58w.bmp
new file mode 100644 (file)
index 0000000..6827e85
Binary files /dev/null and b/bitmaps/a58w.bmp differ
diff --git a/bitmaps/a64o.bmp b/bitmaps/a64o.bmp
new file mode 100644 (file)
index 0000000..4c72b61
Binary files /dev/null and b/bitmaps/a64o.bmp differ
diff --git a/bitmaps/a64s.bmp b/bitmaps/a64s.bmp
new file mode 100644 (file)
index 0000000..d8f467b
Binary files /dev/null and b/bitmaps/a64s.bmp differ
diff --git a/bitmaps/a64w.bmp b/bitmaps/a64w.bmp
new file mode 100644 (file)
index 0000000..a7fe420
Binary files /dev/null and b/bitmaps/a64w.bmp differ
diff --git a/bitmaps/as33o.bmp b/bitmaps/as33o.bmp
new file mode 100644 (file)
index 0000000..bae55ff
Binary files /dev/null and b/bitmaps/as33o.bmp differ
diff --git a/bitmaps/as33s.bmp b/bitmaps/as33s.bmp
new file mode 100644 (file)
index 0000000..7d028dc
Binary files /dev/null and b/bitmaps/as33s.bmp differ
diff --git a/bitmaps/as33w.bmp b/bitmaps/as33w.bmp
new file mode 100644 (file)
index 0000000..1f8a3a9
Binary files /dev/null and b/bitmaps/as33w.bmp differ
diff --git a/bitmaps/as45o.bmp b/bitmaps/as45o.bmp
new file mode 100644 (file)
index 0000000..e01dc8d
Binary files /dev/null and b/bitmaps/as45o.bmp differ
diff --git a/bitmaps/as45s.bmp b/bitmaps/as45s.bmp
new file mode 100644 (file)
index 0000000..f9df7c7
Binary files /dev/null and b/bitmaps/as45s.bmp differ
diff --git a/bitmaps/as45w.bmp b/bitmaps/as45w.bmp
new file mode 100644 (file)
index 0000000..359c061
Binary files /dev/null and b/bitmaps/as45w.bmp differ
diff --git a/bitmaps/as49o.bmp b/bitmaps/as49o.bmp
new file mode 100644 (file)
index 0000000..de6625a
Binary files /dev/null and b/bitmaps/as49o.bmp differ
diff --git a/bitmaps/as49s.bmp b/bitmaps/as49s.bmp
new file mode 100644 (file)
index 0000000..049ad53
Binary files /dev/null and b/bitmaps/as49s.bmp differ
diff --git a/bitmaps/as49w.bmp b/bitmaps/as49w.bmp
new file mode 100644 (file)
index 0000000..cfea22a
Binary files /dev/null and b/bitmaps/as49w.bmp differ
diff --git a/bitmaps/as72o.bmp b/bitmaps/as72o.bmp
new file mode 100644 (file)
index 0000000..fe967e9
Binary files /dev/null and b/bitmaps/as72o.bmp differ
diff --git a/bitmaps/as72s.bmp b/bitmaps/as72s.bmp
new file mode 100644 (file)
index 0000000..d1dcc7f
Binary files /dev/null and b/bitmaps/as72s.bmp differ
diff --git a/bitmaps/as72w.bmp b/bitmaps/as72w.bmp
new file mode 100644 (file)
index 0000000..ad07b7e
Binary files /dev/null and b/bitmaps/as72w.bmp differ
diff --git a/bitmaps/bas.gif b/bitmaps/bas.gif
new file mode 100644 (file)
index 0000000..7376f7e
Binary files /dev/null and b/bitmaps/bas.gif differ
diff --git a/bitmaps/bcv.gif b/bitmaps/bcv.gif
new file mode 100644 (file)
index 0000000..6576cf8
Binary files /dev/null and b/bitmaps/bcv.gif differ
index e3128bd..86a0c08 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * bitmaps.h - Include bitmap files for pieces and icons
- * $Id$
+ * $Id: bitmaps.h,v 2.1 2003/10/27 19:21:01 mann Exp $
  *
  * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
  * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
diff --git a/bitmaps/c33o.bmp b/bitmaps/c33o.bmp
new file mode 100644 (file)
index 0000000..d2fb0ff
Binary files /dev/null and b/bitmaps/c33o.bmp differ
diff --git a/bitmaps/c33s.bmp b/bitmaps/c33s.bmp
new file mode 100644 (file)
index 0000000..895e0a8
Binary files /dev/null and b/bitmaps/c33s.bmp differ
diff --git a/bitmaps/c33w.bmp b/bitmaps/c33w.bmp
new file mode 100644 (file)
index 0000000..057bca0
Binary files /dev/null and b/bitmaps/c33w.bmp differ
diff --git a/bitmaps/c37o.bmp b/bitmaps/c37o.bmp
new file mode 100644 (file)
index 0000000..882afe0
Binary files /dev/null and b/bitmaps/c37o.bmp differ
diff --git a/bitmaps/c37s.bmp b/bitmaps/c37s.bmp
new file mode 100644 (file)
index 0000000..6f3b87b
Binary files /dev/null and b/bitmaps/c37s.bmp differ
diff --git a/bitmaps/c37w.bmp b/bitmaps/c37w.bmp
new file mode 100644 (file)
index 0000000..f7e076d
Binary files /dev/null and b/bitmaps/c37w.bmp differ
diff --git a/bitmaps/c40o.bmp b/bitmaps/c40o.bmp
new file mode 100644 (file)
index 0000000..b5677fc
Binary files /dev/null and b/bitmaps/c40o.bmp differ
diff --git a/bitmaps/c40s.bmp b/bitmaps/c40s.bmp
new file mode 100644 (file)
index 0000000..7af0713
Binary files /dev/null and b/bitmaps/c40s.bmp differ
diff --git a/bitmaps/c40w.bmp b/bitmaps/c40w.bmp
new file mode 100644 (file)
index 0000000..a0b8d15
Binary files /dev/null and b/bitmaps/c40w.bmp differ
diff --git a/bitmaps/c45o.bmp b/bitmaps/c45o.bmp
new file mode 100644 (file)
index 0000000..971b7d0
Binary files /dev/null and b/bitmaps/c45o.bmp differ
diff --git a/bitmaps/c45s.bmp b/bitmaps/c45s.bmp
new file mode 100644 (file)
index 0000000..775ac47
Binary files /dev/null and b/bitmaps/c45s.bmp differ
diff --git a/bitmaps/c45w.bmp b/bitmaps/c45w.bmp
new file mode 100644 (file)
index 0000000..3b9687c
Binary files /dev/null and b/bitmaps/c45w.bmp differ
index 29b6d36..bac2d94 100644 (file)
Binary files a/bitmaps/c49s.bmp and b/bitmaps/c49s.bmp differ
diff --git a/bitmaps/c54o.bmp b/bitmaps/c54o.bmp
new file mode 100644 (file)
index 0000000..6a597db
Binary files /dev/null and b/bitmaps/c54o.bmp differ
diff --git a/bitmaps/c54s.bmp b/bitmaps/c54s.bmp
new file mode 100644 (file)
index 0000000..4571271
Binary files /dev/null and b/bitmaps/c54s.bmp differ
diff --git a/bitmaps/c54w.bmp b/bitmaps/c54w.bmp
new file mode 100644 (file)
index 0000000..61caf6d
Binary files /dev/null and b/bitmaps/c54w.bmp differ
diff --git a/bitmaps/c58o.bmp b/bitmaps/c58o.bmp
new file mode 100644 (file)
index 0000000..15d110e
Binary files /dev/null and b/bitmaps/c58o.bmp differ
diff --git a/bitmaps/c58s.bmp b/bitmaps/c58s.bmp
new file mode 100644 (file)
index 0000000..0bb3cf9
Binary files /dev/null and b/bitmaps/c58s.bmp differ
diff --git a/bitmaps/c58w.bmp b/bitmaps/c58w.bmp
new file mode 100644 (file)
index 0000000..41f05cf
Binary files /dev/null and b/bitmaps/c58w.bmp differ
diff --git a/bitmaps/c64o.bmp b/bitmaps/c64o.bmp
new file mode 100644 (file)
index 0000000..6edd01e
Binary files /dev/null and b/bitmaps/c64o.bmp differ
diff --git a/bitmaps/c64s.bmp b/bitmaps/c64s.bmp
new file mode 100644 (file)
index 0000000..6dac16f
Binary files /dev/null and b/bitmaps/c64s.bmp differ
diff --git a/bitmaps/c64w.bmp b/bitmaps/c64w.bmp
new file mode 100644 (file)
index 0000000..5c3c8ff
Binary files /dev/null and b/bitmaps/c64w.bmp differ
index e34f698..963afdf 100644 (file)
Binary files a/bitmaps/c72s.bmp and b/bitmaps/c72s.bmp differ
diff --git a/bitmaps/cv33o.bmp b/bitmaps/cv33o.bmp
new file mode 100644 (file)
index 0000000..eba036e
Binary files /dev/null and b/bitmaps/cv33o.bmp differ
diff --git a/bitmaps/cv33s.bmp b/bitmaps/cv33s.bmp
new file mode 100644 (file)
index 0000000..31f6a45
Binary files /dev/null and b/bitmaps/cv33s.bmp differ
diff --git a/bitmaps/cv33w.bmp b/bitmaps/cv33w.bmp
new file mode 100644 (file)
index 0000000..7a86530
Binary files /dev/null and b/bitmaps/cv33w.bmp differ
diff --git a/bitmaps/cv37o.bmp b/bitmaps/cv37o.bmp
new file mode 100644 (file)
index 0000000..9075dd6
Binary files /dev/null and b/bitmaps/cv37o.bmp differ
diff --git a/bitmaps/cv37s.bmp b/bitmaps/cv37s.bmp
new file mode 100644 (file)
index 0000000..1b31080
Binary files /dev/null and b/bitmaps/cv37s.bmp differ
diff --git a/bitmaps/cv37w.bmp b/bitmaps/cv37w.bmp
new file mode 100644 (file)
index 0000000..abf95b3
Binary files /dev/null and b/bitmaps/cv37w.bmp differ
diff --git a/bitmaps/cv40o.bmp b/bitmaps/cv40o.bmp
new file mode 100644 (file)
index 0000000..7fe8326
Binary files /dev/null and b/bitmaps/cv40o.bmp differ
diff --git a/bitmaps/cv40s.bmp b/bitmaps/cv40s.bmp
new file mode 100644 (file)
index 0000000..bb2065e
Binary files /dev/null and b/bitmaps/cv40s.bmp differ
diff --git a/bitmaps/cv40w.bmp b/bitmaps/cv40w.bmp
new file mode 100644 (file)
index 0000000..cc195bb
Binary files /dev/null and b/bitmaps/cv40w.bmp differ
diff --git a/bitmaps/cv45o.bmp b/bitmaps/cv45o.bmp
new file mode 100644 (file)
index 0000000..55b4087
Binary files /dev/null and b/bitmaps/cv45o.bmp differ
diff --git a/bitmaps/cv45s.bmp b/bitmaps/cv45s.bmp
new file mode 100644 (file)
index 0000000..22b05b7
Binary files /dev/null and b/bitmaps/cv45s.bmp differ
diff --git a/bitmaps/cv45w.bmp b/bitmaps/cv45w.bmp
new file mode 100644 (file)
index 0000000..250984d
Binary files /dev/null and b/bitmaps/cv45w.bmp differ
diff --git a/bitmaps/cv49o.bmp b/bitmaps/cv49o.bmp
new file mode 100644 (file)
index 0000000..95fd748
Binary files /dev/null and b/bitmaps/cv49o.bmp differ
diff --git a/bitmaps/cv49s.bmp b/bitmaps/cv49s.bmp
new file mode 100644 (file)
index 0000000..5fc24b9
Binary files /dev/null and b/bitmaps/cv49s.bmp differ
diff --git a/bitmaps/cv49w.bmp b/bitmaps/cv49w.bmp
new file mode 100644 (file)
index 0000000..cbf8e92
Binary files /dev/null and b/bitmaps/cv49w.bmp differ
diff --git a/bitmaps/cv54o.bmp b/bitmaps/cv54o.bmp
new file mode 100644 (file)
index 0000000..a74cbbb
Binary files /dev/null and b/bitmaps/cv54o.bmp differ
diff --git a/bitmaps/cv54s.bmp b/bitmaps/cv54s.bmp
new file mode 100644 (file)
index 0000000..9c5bd8b
Binary files /dev/null and b/bitmaps/cv54s.bmp differ
diff --git a/bitmaps/cv54w.bmp b/bitmaps/cv54w.bmp
new file mode 100644 (file)
index 0000000..fff12e3
Binary files /dev/null and b/bitmaps/cv54w.bmp differ
diff --git a/bitmaps/cv58o.bmp b/bitmaps/cv58o.bmp
new file mode 100644 (file)
index 0000000..1622ca5
Binary files /dev/null and b/bitmaps/cv58o.bmp differ
diff --git a/bitmaps/cv58s.bmp b/bitmaps/cv58s.bmp
new file mode 100644 (file)
index 0000000..5b7674d
Binary files /dev/null and b/bitmaps/cv58s.bmp differ
diff --git a/bitmaps/cv58w.bmp b/bitmaps/cv58w.bmp
new file mode 100644 (file)
index 0000000..2f37d5b
Binary files /dev/null and b/bitmaps/cv58w.bmp differ
diff --git a/bitmaps/cv64o.bmp b/bitmaps/cv64o.bmp
new file mode 100644 (file)
index 0000000..522bb6c
Binary files /dev/null and b/bitmaps/cv64o.bmp differ
diff --git a/bitmaps/cv64s.bmp b/bitmaps/cv64s.bmp
new file mode 100644 (file)
index 0000000..1787acd
Binary files /dev/null and b/bitmaps/cv64s.bmp differ
diff --git a/bitmaps/cv64w.bmp b/bitmaps/cv64w.bmp
new file mode 100644 (file)
index 0000000..b3e1bfd
Binary files /dev/null and b/bitmaps/cv64w.bmp differ
diff --git a/bitmaps/cv72o.bmp b/bitmaps/cv72o.bmp
new file mode 100644 (file)
index 0000000..d72c45d
Binary files /dev/null and b/bitmaps/cv72o.bmp differ
diff --git a/bitmaps/cv72s.bmp b/bitmaps/cv72s.bmp
new file mode 100644 (file)
index 0000000..e22fdd5
Binary files /dev/null and b/bitmaps/cv72s.bmp differ
diff --git a/bitmaps/cv72w.bmp b/bitmaps/cv72w.bmp
new file mode 100644 (file)
index 0000000..65e7e1d
Binary files /dev/null and b/bitmaps/cv72w.bmp differ
diff --git a/bitmaps/dk33o.bmp b/bitmaps/dk33o.bmp
new file mode 100644 (file)
index 0000000..9b00f94
Binary files /dev/null and b/bitmaps/dk33o.bmp differ
diff --git a/bitmaps/dk33s.bmp b/bitmaps/dk33s.bmp
new file mode 100644 (file)
index 0000000..f1c8bc9
Binary files /dev/null and b/bitmaps/dk33s.bmp differ
diff --git a/bitmaps/dk33w.bmp b/bitmaps/dk33w.bmp
new file mode 100644 (file)
index 0000000..c77c3b2
Binary files /dev/null and b/bitmaps/dk33w.bmp differ
diff --git a/bitmaps/e33o.bmp b/bitmaps/e33o.bmp
new file mode 100644 (file)
index 0000000..b7f0aac
Binary files /dev/null and b/bitmaps/e33o.bmp differ
diff --git a/bitmaps/e33s.bmp b/bitmaps/e33s.bmp
new file mode 100644 (file)
index 0000000..d132c2d
Binary files /dev/null and b/bitmaps/e33s.bmp differ
diff --git a/bitmaps/e33w.bmp b/bitmaps/e33w.bmp
new file mode 100644 (file)
index 0000000..2ce9548
Binary files /dev/null and b/bitmaps/e33w.bmp differ
diff --git a/bitmaps/f33o.bmp b/bitmaps/f33o.bmp
new file mode 100644 (file)
index 0000000..588010b
Binary files /dev/null and b/bitmaps/f33o.bmp differ
diff --git a/bitmaps/f33s.bmp b/bitmaps/f33s.bmp
new file mode 100644 (file)
index 0000000..6ef112d
Binary files /dev/null and b/bitmaps/f33s.bmp differ
diff --git a/bitmaps/f33w.bmp b/bitmaps/f33w.bmp
new file mode 100644 (file)
index 0000000..b7f7069
Binary files /dev/null and b/bitmaps/f33w.bmp differ
diff --git a/bitmaps/g33o.bmp b/bitmaps/g33o.bmp
new file mode 100644 (file)
index 0000000..6f3cc18
Binary files /dev/null and b/bitmaps/g33o.bmp differ
diff --git a/bitmaps/g33s.bmp b/bitmaps/g33s.bmp
new file mode 100644 (file)
index 0000000..31dd9e8
Binary files /dev/null and b/bitmaps/g33s.bmp differ
diff --git a/bitmaps/g33w.bmp b/bitmaps/g33w.bmp
new file mode 100644 (file)
index 0000000..0c52cea
Binary files /dev/null and b/bitmaps/g33w.bmp differ
diff --git a/bitmaps/h33o.bmp b/bitmaps/h33o.bmp
new file mode 100644 (file)
index 0000000..d811f80
Binary files /dev/null and b/bitmaps/h33o.bmp differ
diff --git a/bitmaps/h33s.bmp b/bitmaps/h33s.bmp
new file mode 100644 (file)
index 0000000..95e5dbe
Binary files /dev/null and b/bitmaps/h33s.bmp differ
diff --git a/bitmaps/h33w.bmp b/bitmaps/h33w.bmp
new file mode 100644 (file)
index 0000000..cebb7a3
Binary files /dev/null and b/bitmaps/h33w.bmp differ
diff --git a/bitmaps/l33o.bmp b/bitmaps/l33o.bmp
new file mode 100644 (file)
index 0000000..510882b
Binary files /dev/null and b/bitmaps/l33o.bmp differ
diff --git a/bitmaps/l33s.bmp b/bitmaps/l33s.bmp
new file mode 100644 (file)
index 0000000..4c1ce81
Binary files /dev/null and b/bitmaps/l33s.bmp differ
diff --git a/bitmaps/l33w.bmp b/bitmaps/l33w.bmp
new file mode 100644 (file)
index 0000000..fff3ec7
Binary files /dev/null and b/bitmaps/l33w.bmp differ
diff --git a/bitmaps/l37o.bmp b/bitmaps/l37o.bmp
new file mode 100644 (file)
index 0000000..473b0f7
Binary files /dev/null and b/bitmaps/l37o.bmp differ
diff --git a/bitmaps/l37s.bmp b/bitmaps/l37s.bmp
new file mode 100644 (file)
index 0000000..5709f68
Binary files /dev/null and b/bitmaps/l37s.bmp differ
diff --git a/bitmaps/l37w.bmp b/bitmaps/l37w.bmp
new file mode 100644 (file)
index 0000000..e9d27fa
Binary files /dev/null and b/bitmaps/l37w.bmp differ
diff --git a/bitmaps/l40o.bmp b/bitmaps/l40o.bmp
new file mode 100644 (file)
index 0000000..c97e0f2
Binary files /dev/null and b/bitmaps/l40o.bmp differ
diff --git a/bitmaps/l40s.bmp b/bitmaps/l40s.bmp
new file mode 100644 (file)
index 0000000..50bc67a
Binary files /dev/null and b/bitmaps/l40s.bmp differ
diff --git a/bitmaps/l40w.bmp b/bitmaps/l40w.bmp
new file mode 100644 (file)
index 0000000..ca11b56
Binary files /dev/null and b/bitmaps/l40w.bmp differ
diff --git a/bitmaps/l45o.bmp b/bitmaps/l45o.bmp
new file mode 100644 (file)
index 0000000..757f9cc
Binary files /dev/null and b/bitmaps/l45o.bmp differ
diff --git a/bitmaps/l45s.bmp b/bitmaps/l45s.bmp
new file mode 100644 (file)
index 0000000..72e451b
Binary files /dev/null and b/bitmaps/l45s.bmp differ
diff --git a/bitmaps/l45w.bmp b/bitmaps/l45w.bmp
new file mode 100644 (file)
index 0000000..9b2050f
Binary files /dev/null and b/bitmaps/l45w.bmp differ
diff --git a/bitmaps/l54o.bmp b/bitmaps/l54o.bmp
new file mode 100644 (file)
index 0000000..4fc6484
Binary files /dev/null and b/bitmaps/l54o.bmp differ
diff --git a/bitmaps/l54s.bmp b/bitmaps/l54s.bmp
new file mode 100644 (file)
index 0000000..7abf49d
Binary files /dev/null and b/bitmaps/l54s.bmp differ
diff --git a/bitmaps/l54w.bmp b/bitmaps/l54w.bmp
new file mode 100644 (file)
index 0000000..2ba36b8
Binary files /dev/null and b/bitmaps/l54w.bmp differ
diff --git a/bitmaps/l58o.bmp b/bitmaps/l58o.bmp
new file mode 100644 (file)
index 0000000..584a038
Binary files /dev/null and b/bitmaps/l58o.bmp differ
diff --git a/bitmaps/l58s.bmp b/bitmaps/l58s.bmp
new file mode 100644 (file)
index 0000000..1c7ba69
Binary files /dev/null and b/bitmaps/l58s.bmp differ
diff --git a/bitmaps/l58w.bmp b/bitmaps/l58w.bmp
new file mode 100644 (file)
index 0000000..2ec0f44
Binary files /dev/null and b/bitmaps/l58w.bmp differ
diff --git a/bitmaps/l64o.bmp b/bitmaps/l64o.bmp
new file mode 100644 (file)
index 0000000..dcd5a4c
Binary files /dev/null and b/bitmaps/l64o.bmp differ
diff --git a/bitmaps/l64s.bmp b/bitmaps/l64s.bmp
new file mode 100644 (file)
index 0000000..0bdc5bb
Binary files /dev/null and b/bitmaps/l64s.bmp differ
diff --git a/bitmaps/l64w.bmp b/bitmaps/l64w.bmp
new file mode 100644 (file)
index 0000000..80342c3
Binary files /dev/null and b/bitmaps/l64w.bmp differ
diff --git a/bitmaps/m33o.bmp b/bitmaps/m33o.bmp
new file mode 100644 (file)
index 0000000..313e998
Binary files /dev/null and b/bitmaps/m33o.bmp differ
diff --git a/bitmaps/m33s.bmp b/bitmaps/m33s.bmp
new file mode 100644 (file)
index 0000000..e2571b6
Binary files /dev/null and b/bitmaps/m33s.bmp differ
diff --git a/bitmaps/m33w.bmp b/bitmaps/m33w.bmp
new file mode 100644 (file)
index 0000000..110f29e
Binary files /dev/null and b/bitmaps/m33w.bmp differ
diff --git a/bitmaps/o33o.bmp b/bitmaps/o33o.bmp
new file mode 100644 (file)
index 0000000..667dc83
Binary files /dev/null and b/bitmaps/o33o.bmp differ
diff --git a/bitmaps/o33s.bmp b/bitmaps/o33s.bmp
new file mode 100644 (file)
index 0000000..a063095
Binary files /dev/null and b/bitmaps/o33s.bmp differ
diff --git a/bitmaps/o33w.bmp b/bitmaps/o33w.bmp
new file mode 100644 (file)
index 0000000..d782bd5
Binary files /dev/null and b/bitmaps/o33w.bmp differ
diff --git a/bitmaps/s49o.bmp b/bitmaps/s49o.bmp
new file mode 100644 (file)
index 0000000..e6755c9
Binary files /dev/null and b/bitmaps/s49o.bmp differ
diff --git a/bitmaps/s49s.bmp b/bitmaps/s49s.bmp
new file mode 100644 (file)
index 0000000..0f0efbb
Binary files /dev/null and b/bitmaps/s49s.bmp differ
diff --git a/bitmaps/s49w.bmp b/bitmaps/s49w.bmp
new file mode 100644 (file)
index 0000000..cc7354a
Binary files /dev/null and b/bitmaps/s49w.bmp differ
diff --git a/bitmaps/s72o.bmp b/bitmaps/s72o.bmp
new file mode 100644 (file)
index 0000000..4df9aa8
Binary files /dev/null and b/bitmaps/s72o.bmp differ
diff --git a/bitmaps/s72s.bmp b/bitmaps/s72s.bmp
new file mode 100644 (file)
index 0000000..d5ed119
Binary files /dev/null and b/bitmaps/s72s.bmp differ
diff --git a/bitmaps/s72w.bmp b/bitmaps/s72w.bmp
new file mode 100644 (file)
index 0000000..e042e37
Binary files /dev/null and b/bitmaps/s72w.bmp differ
diff --git a/bitmaps/v33o.bmp b/bitmaps/v33o.bmp
new file mode 100644 (file)
index 0000000..29edd62
Binary files /dev/null and b/bitmaps/v33o.bmp differ
diff --git a/bitmaps/v33s.bmp b/bitmaps/v33s.bmp
new file mode 100644 (file)
index 0000000..d28863c
Binary files /dev/null and b/bitmaps/v33s.bmp differ
diff --git a/bitmaps/v33w.bmp b/bitmaps/v33w.bmp
new file mode 100644 (file)
index 0000000..718729c
Binary files /dev/null and b/bitmaps/v33w.bmp differ
diff --git a/bitmaps/v49o.bmp b/bitmaps/v49o.bmp
new file mode 100644 (file)
index 0000000..bd2f8a1
Binary files /dev/null and b/bitmaps/v49o.bmp differ
diff --git a/bitmaps/v49s.bmp b/bitmaps/v49s.bmp
new file mode 100644 (file)
index 0000000..9bf4b10
Binary files /dev/null and b/bitmaps/v49s.bmp differ
diff --git a/bitmaps/v49w.bmp b/bitmaps/v49w.bmp
new file mode 100644 (file)
index 0000000..076ea0f
Binary files /dev/null and b/bitmaps/v49w.bmp differ
diff --git a/bitmaps/v54o.bmp b/bitmaps/v54o.bmp
new file mode 100644 (file)
index 0000000..2499562
Binary files /dev/null and b/bitmaps/v54o.bmp differ
diff --git a/bitmaps/v54s.bmp b/bitmaps/v54s.bmp
new file mode 100644 (file)
index 0000000..1c69916
Binary files /dev/null and b/bitmaps/v54s.bmp differ
diff --git a/bitmaps/v54w.bmp b/bitmaps/v54w.bmp
new file mode 100644 (file)
index 0000000..57bf8d6
Binary files /dev/null and b/bitmaps/v54w.bmp differ
diff --git a/bitmaps/v72o.bmp b/bitmaps/v72o.bmp
new file mode 100644 (file)
index 0000000..cd2bbcd
Binary files /dev/null and b/bitmaps/v72o.bmp differ
diff --git a/bitmaps/v72s.bmp b/bitmaps/v72s.bmp
new file mode 100644 (file)
index 0000000..3dd30dc
Binary files /dev/null and b/bitmaps/v72s.bmp differ
diff --git a/bitmaps/v72w.bmp b/bitmaps/v72w.bmp
new file mode 100644 (file)
index 0000000..3797c5a
Binary files /dev/null and b/bitmaps/v72w.bmp differ
diff --git a/bitmaps/w33o.bmp b/bitmaps/w33o.bmp
new file mode 100644 (file)
index 0000000..5de631d
Binary files /dev/null and b/bitmaps/w33o.bmp differ
diff --git a/bitmaps/w33s.bmp b/bitmaps/w33s.bmp
new file mode 100644 (file)
index 0000000..4defb6a
Binary files /dev/null and b/bitmaps/w33s.bmp differ
diff --git a/bitmaps/w33w.bmp b/bitmaps/w33w.bmp
new file mode 100644 (file)
index 0000000..d7a3994
Binary files /dev/null and b/bitmaps/w33w.bmp differ
diff --git a/bitmaps/was.gif b/bitmaps/was.gif
new file mode 100644 (file)
index 0000000..bebbc25
Binary files /dev/null and b/bitmaps/was.gif differ
diff --git a/bitmaps/wcv.gif b/bitmaps/wcv.gif
new file mode 100644 (file)
index 0000000..ff56268
Binary files /dev/null and b/bitmaps/wcv.gif differ
index b405ea9..9e71d68 100644 (file)
Binary files a/bitmaps/wl49o.bmp and b/bitmaps/wl49o.bmp differ
index d1a737a..a24a4f4 100644 (file)
Binary files a/bitmaps/wl49s.bmp and b/bitmaps/wl49s.bmp differ
index e45f0ac..1e07a90 100644 (file)
Binary files a/bitmaps/wl72o.bmp and b/bitmaps/wl72o.bmp differ
index a64f466..4ea254a 100644 (file)
Binary files a/bitmaps/wl72s.bmp and b/bitmaps/wl72s.bmp differ
index 9d3fd41..714a3b2 100644 (file)
--- a/common.h
+++ b/common.h
@@ -172,7 +172,7 @@ int pclose(FILE *);
 #define ZIPPY_GAME_START ""\r
 #define ZIPPY_ADJOURN FALSE\r
 #define ZIPPY_ABORT FALSE\r
-#define ZIPPY_VARIANTS "normal"\r
+#define ZIPPY_VARIANTS "normal,fischerandom,crazyhouse,losers,suicide,3checks,twokings,bughouse,shatranj"\r
 #define ZIPPY_MAX_GAMES 0\r
 #define ZIPPY_REPLAY_TIMEOUT 120\r
 \r
@@ -189,13 +189,13 @@ typedef enum {
     /* only the first N pieces can go into the holdings, and   */\r
     /* promotions in those variants shift P-W to U-S           */\r
     WhitePawn, WhiteKnight, WhiteBishop, WhiteRook, WhiteQueen, \r
-    WhiteFerz, WhiteWazir, WhiteAlfil, WhiteMan, WhiteCannon, WhiteUnicorn,\r
-    WhiteNightrider, WhiteCardinal, WhiteMarshall, WhiteGrasshopper,\r
-    WhiteSilver, WhiteKing,\r
+    WhiteFerz, WhiteAlfil, WhiteAngel, WhiteMarshall, WhiteWazir, WhiteMan, \r
+    WhiteCannon, WhiteNightrider, WhiteCardinal, WhiteDragon, WhiteGrasshopper,\r
+    WhiteSilver, WhiteFalcon, WhiteLance, WhiteCobra, WhiteUnicorn, WhiteKing,\r
     BlackPawn, BlackKnight, BlackBishop, BlackRook, BlackQueen,\r
-    BlackFerz, BlackWazir, BlackAlfil, BlackMan, BlackCannon, BlackUnicorn,\r
-    BlackNightrider, BlackCardinal, BlackMarshall, BlackGrasshopper,\r
-    BlackSilver, BlackKing,\r
+    BlackFerz, BlackAlfil, BlackAngel, BlackMarshall, BlackWazir, BlackMan, \r
+    BlackCannon, BlackNightrider, BlackCardinal, BlackDragon, BlackGrasshopper,\r
+    BlackSilver, BlackFalcon, BlackLance, BlackCobra, BlackUnicorn, BlackKing,\r
     EmptySquare, \r
     ClearBoard, WhitePlay, BlackPlay, PromotePiece, DemotePiece /*for use on EditPosition menus*/\r
   } ChessSquare;\r
@@ -203,8 +203,8 @@ typedef enum {
 /* [HGM] some macros that can be used as prefixes to convert piece types */\r
 #define WHITE_TO_BLACK (int)BlackPawn - (int)WhitePawn + (int)\r
 #define BLACK_TO_WHITE (int)WhitePawn - (int)BlackPawn + (int)\r
-#define PROMOTED       (int)WhiteUnicorn - (int)WhitePawn + (int)\r
-#define DEMOTED        (int)WhitePawn - (int)WhiteUnicorn + (int)\r
+#define PROMOTED       (int)WhiteDragon - (int)WhiteRook + (int)\r
+#define DEMOTED        (int)WhiteRook - (int)WhiteDragon + (int)\r
 #define SHOGI          (int)EmptySquare + (int)\r
 \r
 \r
@@ -274,7 +274,8 @@ typedef enum {
     VariantCapablanca,\r
     VariantKnightmate,\r
     VariantFairy,        \r
-    VariantShowgi,\r
+    VariantCylinder,\r
+    VariantFalcon,\r
     VariantUnknown       /* Catchall for other unknown variants */\r
 } VariantClass;\r
 \r
@@ -309,7 +310,8 @@ typedef enum {
   "capablanca", \\r
   "knightmate", \\r
   "fairy", \\r
-  "showgi", \\r
+  "cylinder", \\r
+  "falcon",\\r
   "unknown" \\r
 }\r
 \r
@@ -543,6 +545,15 @@ typedef struct {
     int zippyMaxGames;\r
     int zippyReplayTimeout; /*seconds*/\r
 #endif\r
+\r
+    char *serverMovesName;\r
+    Boolean suppressLoadMoves;\r
+    int serverPause;\r
+    int firstTimeOdds;\r
+    int secondTimeOdds;\r
+    int timeOddsMode;\r
+    int firstAccumulateTC;\r
+    int secondAccumulateTC;\r
 } AppData, *AppDataPtr;\r
 \r
 /* [AS] PGN tags (for showing in the game list) */\r
index 0e5416c..f0e09d3 100644 (file)
--- a/config.h
+++ b/config.h
@@ -6,9 +6,8 @@
 /* [HGM] Defining FAIRY allows different K- & Q-side piece symbols */\r
 #define FAIRY\r
 \r
-#ifdef FAIRY\r
 #define GOTHIC "Gothic Chess (see www.GothicChess.com) is licensed under U.S. Patent #6,481,716 by Ed Trice"\r
-#endif\r
+#define FALCON "Falcon Chess (see www.chessvariants.com) is licensed under U.S. Patent #5,690,334 by George W. Duke"\r
 \r
 /* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */\r
 /*#undef HAVE_SYS_WAIT_H*/\r
@@ -47,7 +46,7 @@
 \r
 #define LAST_PTY_LETTER 'q'\r
 \r
-#define PATCHLEVEL "12"\r
+#define PATCHLEVEL "13c"\r
 \r
 #define PRODUCT "WinBoard"\r
 \r
index f3556e6..dacd12a 100644 (file)
-/*
- * frontend.h -- Interface exported by all XBoard front ends
- * $Id: frontend.h,v 2.2 2003/11/06 07:22:14 mann Exp $
- *
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
- * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
- *
- * The following terms apply to Digital Equipment Corporation's copyright
- * interest in XBoard:
- * ------------------------------------------------------------------------
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of Digital not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * ------------------------------------------------------------------------
- *
- * The following terms apply to the enhanced version of XBoard distributed
- * by the Free Software Foundation:
- * ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * ------------------------------------------------------------------------
- */
-
-#ifndef _FRONTEND
-#define _FRONTEND
-
-#include <stdio.h>
-
-typedef VOIDSTAR ProcRef;
-#define NoProc ((ProcRef) 0)
-typedef VOIDSTAR InputSourceRef;
-
-void ModeHighlight P((void));
-void SetICSMode P((void));
-void SetGNUMode P((void));
-void SetNCPMode P((void));
-void SetCmailMode P((void));
-void SetTrainingModeOn P((void));
-void SetTrainingModeOff P((void));
-void SetUserThinkingEnables P((void));
-void SetMachineThinkingEnables P((void));
-void DisplayTitle P((String title));
-void DisplayMessage P((String message, String extMessage));
-void DisplayError P((String message, int error));
-void DisplayMoveError P((String message));
-
-/* If status == 0, we are exiting with a benign message, not an error */
-void DisplayFatalError P((String message, int error, int status));
-
-void DisplayInformation P((String message));
-void DisplayNote P((String message));
-void AskQuestion P((String title, String question, String replyPrefix,
-                   ProcRef pr));
-void DisplayIcsInteractionTitle P((String title));
-void DrawPosition P((int fullRedraw, Board board));
-void ResetFrontEnd P((void));
-void CommentPopUp P((String title, String comment));
-void CommentPopDown P((void));
-void EditCommentPopUp P((int index, String title, String text));
-
-void RingBell P((void));
-void PlayIcsWinSound P((void));
-void PlayIcsLossSound P((void));
-void PlayIcsDrawSound P((void));
-void PlayIcsUnfinishedSound P((void));
-void PlayAlarmSound P((void));
-void EchoOn P((void));
-void EchoOff P((void));
-void Raw P((void));
-void Colorize P((ColorClass cc, int continuation));
-
-char *UserName P((void));
-char *HostName P((void));
-
-int ClockTimerRunning P((void));
-int StopClockTimer P((void));
-void StartClockTimer P((long millisec));
-void DisplayWhiteClock P((long timeRemaining, int highlight));
-void DisplayBlackClock P((long timeRemaining, int highlight));
-
-int LoadGameTimerRunning P((void));
-int StopLoadGameTimer P((void));
-void StartLoadGameTimer P((long millisec));
-void AutoSaveGame P((void));
-
-typedef void (*DelayedEventCallback) P((void));
-void ScheduleDelayedEvent P((DelayedEventCallback cb, long millisec));
-DelayedEventCallback GetDelayedEvent P((void));
-void CancelDelayedEvent P((void));
-
-int StartChildProcess P((char *cmdLine, char *dir, ProcRef *pr));
-void DestroyChildProcess P((ProcRef pr, int/*boolean*/ signal));
-void InterruptChildProcess P((ProcRef pr));
-
-int OpenTelnet P((char *host, char *port, ProcRef *pr));
-int OpenTCP P((char *host, char *port, ProcRef *pr));
-int OpenCommPort P((char *name, ProcRef *pr));
-int OpenLoopback P((ProcRef *pr));
-int OpenRcmd P((char *host, char *user, char *cmd, ProcRef *pr));
-
-typedef void (*InputCallback) P((InputSourceRef isr, VOIDSTAR closure,
-                                char *buf, int count, int error));
-/* pr == NoProc means the local keyboard */
-InputSourceRef AddInputSource P((ProcRef pr, int lineByLine,
-                                InputCallback func, VOIDSTAR closure));
-void RemoveInputSource P((InputSourceRef isr));
-
-/* pr == NoProc means the local display */
-int OutputToProcess P((ProcRef pr, char *message, int count, int *outError));
-int OutputToProcessDelayed P((ProcRef pr, char *message, int count,
-                             int *outError, long msdelay));
-
-void CmailSigHandlerCallBack P((InputSourceRef isr, VOIDSTAR closure,
-                               char *buf, int count, int error));
-
-extern ProcRef cmailPR;
-
-/* these are in wgamelist.c */
-void GameListPopUp P((FILE *fp, char *filename));
-void GameListPopDown P((void));
-void GameListHighlight P((int index));
-void GameListDestroy P((void));
-
-/* these are in wedittags.c */
-void EditTagsPopUp P((char *tags));
-void TagsPopUp P((char *tags, char *msg));
-void TagsPopDown P((void));
-
-void ICSInitScript P((void));
-void StartAnalysisClock P((void));
-void AnalysisPopUp P((char *title, char *label));
-void AnalysisPopDown P((void));
-
-void SetHighlights P((int fromX, int fromY, int toX, int toY));
-void ClearHighlights P((void));
-void SetPremoveHighlights P((int fromX, int fromY, int toX, int toY));
-void ClearPremoveHighlights P((void));
-
-void ShutDownFrontEnd P((void));
-void BoardToTop P((void));
-void AnimateMove P((Board board, int fromX, int fromY, int toX, int toY));
-void HistorySet P((char movelist[][2*MOVE_LEN], int first, int last, int current));
-void FreezeUI P((void));
-void ThawUI P((void));
-extern char *programName;
-
-typedef struct FrontEndProgramStats_TAG {
-    int which;
-    int depth;
-    unsigned long nodes;
-    int score;
-    int time;
-    char * pv;
-    char * hint;
-    int an_move_index;
-    int an_move_count;
-} FrontEndProgramStats;
-
-void SetProgramStats P(( FrontEndProgramStats * stats )); /* [AS] */
-
-#endif
+/*\r
+ * frontend.h -- Interface exported by all XBoard front ends\r
+ * $Id: frontend.h,v 2.2 2003/11/06 07:22:14 mann Exp $\r
+ *\r
+ * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
+ * Enhancements Copyright 1992-95 Free Software Foundation, Inc.\r
+ *\r
+ * The following terms apply to Digital Equipment Corporation's copyright\r
+ * interest in XBoard:\r
+ * ------------------------------------------------------------------------\r
+ * All Rights Reserved\r
+ *\r
+ * Permission to use, copy, modify, and distribute this software and its\r
+ * documentation for any purpose and without fee is hereby granted,\r
+ * provided that the above copyright notice appear in all copies and that\r
+ * both that copyright notice and this permission notice appear in\r
+ * supporting documentation, and that the name of Digital not be\r
+ * used in advertising or publicity pertaining to distribution of the\r
+ * software without specific, written prior permission.\r
+ *\r
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+ * SOFTWARE.\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * The following terms apply to the enhanced version of XBoard distributed\r
+ * by the Free Software Foundation:\r
+ * ------------------------------------------------------------------------\r
+ * This program 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
+ *\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
+ *\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
+ */\r
+\r
+#ifndef _FRONTEND\r
+#define _FRONTEND\r
+\r
+#include <stdio.h>\r
+\r
+typedef VOIDSTAR ProcRef;\r
+#define NoProc ((ProcRef) 0)\r
+typedef VOIDSTAR InputSourceRef;\r
+\r
+void ModeHighlight P((void));\r
+void SetICSMode P((void));\r
+void SetGNUMode P((void));\r
+void SetNCPMode P((void));\r
+void SetCmailMode P((void));\r
+void SetTrainingModeOn P((void));\r
+void SetTrainingModeOff P((void));\r
+void SetUserThinkingEnables P((void));\r
+void SetMachineThinkingEnables P((void));\r
+void DisplayTitle P((String title));\r
+void DisplayMessage P((String message, String extMessage));\r
+void DisplayError P((String message, int error));\r
+void DisplayMoveError P((String message));\r
+\r
+/* If status == 0, we are exiting with a benign message, not an error */\r
+void DisplayFatalError P((String message, int error, int status));\r
+\r
+void DisplayInformation P((String message));\r
+void DisplayNote P((String message));\r
+void AskQuestion P((String title, String question, String replyPrefix,\r
+                   ProcRef pr));\r
+void DisplayIcsInteractionTitle P((String title));\r
+void DrawPosition P((int fullRedraw, Board board));\r
+void ResetFrontEnd P((void));\r
+void CommentPopUp P((String title, String comment));\r
+void CommentPopDown P((void));\r
+void EditCommentPopUp P((int index, String title, String text));\r
+\r
+void RingBell P((void));\r
+void PlayIcsWinSound P((void));\r
+void PlayIcsLossSound P((void));\r
+void PlayIcsDrawSound P((void));\r
+void PlayIcsUnfinishedSound P((void));\r
+void PlayAlarmSound P((void));\r
+void EchoOn P((void));\r
+void EchoOff P((void));\r
+void Raw P((void));\r
+void Colorize P((ColorClass cc, int continuation));\r
+\r
+char *UserName P((void));\r
+char *HostName P((void));\r
+\r
+int ClockTimerRunning P((void));\r
+int StopClockTimer P((void));\r
+void StartClockTimer P((long millisec));\r
+void DisplayWhiteClock P((long timeRemaining, int highlight));\r
+void DisplayBlackClock P((long timeRemaining, int highlight));\r
+\r
+int LoadGameTimerRunning P((void));\r
+int StopLoadGameTimer P((void));\r
+void StartLoadGameTimer P((long millisec));\r
+void AutoSaveGame P((void));\r
+\r
+typedef void (*DelayedEventCallback) P((void));\r
+void ScheduleDelayedEvent P((DelayedEventCallback cb, long millisec));\r
+DelayedEventCallback GetDelayedEvent P((void));\r
+void CancelDelayedEvent P((void));\r
+\r
+int StartChildProcess P((char *cmdLine, char *dir, ProcRef *pr));\r
+void DestroyChildProcess P((ProcRef pr, int/*boolean*/ signal));\r
+void InterruptChildProcess P((ProcRef pr));\r
+\r
+int OpenTelnet P((char *host, char *port, ProcRef *pr));\r
+int OpenTCP P((char *host, char *port, ProcRef *pr));\r
+int OpenCommPort P((char *name, ProcRef *pr));\r
+int OpenLoopback P((ProcRef *pr));\r
+int OpenRcmd P((char *host, char *user, char *cmd, ProcRef *pr));\r
+\r
+typedef void (*InputCallback) P((InputSourceRef isr, VOIDSTAR closure,\r
+                                char *buf, int count, int error));\r
+/* pr == NoProc means the local keyboard */\r
+InputSourceRef AddInputSource P((ProcRef pr, int lineByLine,\r
+                                InputCallback func, VOIDSTAR closure));\r
+void RemoveInputSource P((InputSourceRef isr));\r
+\r
+/* pr == NoProc means the local display */\r
+int OutputToProcess P((ProcRef pr, char *message, int count, int *outError));\r
+int OutputToProcessDelayed P((ProcRef pr, char *message, int count,\r
+                             int *outError, long msdelay));\r
+\r
+void CmailSigHandlerCallBack P((InputSourceRef isr, VOIDSTAR closure,\r
+                               char *buf, int count, int error));\r
+\r
+extern ProcRef cmailPR;\r
+\r
+/* these are in wgamelist.c */\r
+void GameListPopUp P((FILE *fp, char *filename));\r
+void GameListPopDown P((void));\r
+void GameListHighlight P((int index));\r
+void GameListDestroy P((void));\r
+\r
+/* these are in wedittags.c */\r
+void EditTagsPopUp P((char *tags));\r
+void TagsPopUp P((char *tags, char *msg));\r
+void TagsPopDown P((void));\r
+\r
+void ICSInitScript P((void));\r
+void StartAnalysisClock P((void));\r
+void AnalysisPopUp P((char *title, char *label));\r
+void AnalysisPopDown P((void));\r
+\r
+void SetHighlights P((int fromX, int fromY, int toX, int toY));\r
+void ClearHighlights P((void));\r
+void SetPremoveHighlights P((int fromX, int fromY, int toX, int toY));\r
+void ClearPremoveHighlights P((void));\r
+\r
+void ShutDownFrontEnd P((void));\r
+void BoardToTop P((void));\r
+void AnimateMove P((Board board, int fromX, int fromY, int toX, int toY));\r
+void HistorySet P((char movelist[][2*MOVE_LEN], int first, int last, int current));\r
+void FreezeUI P((void));\r
+void ThawUI P((void));\r
+extern char *programName;\r
+\r
+typedef struct FrontEndProgramStats_TAG {\r
+    int which;\r
+    int depth;\r
+    unsigned long nodes;\r
+    int score;\r
+    int time;\r
+    char * pv;\r
+    char * hint;\r
+    int an_move_index;\r
+    int an_move_count;\r
+} FrontEndProgramStats;\r
+\r
+void SetProgramStats P(( FrontEndProgramStats * stats )); /* [AS] */\r
+\r
+#endif\r
index 2be1fe8..0d24d1d 100644 (file)
-/*
- * gamelist.c -- Functions to manage a gamelist
- * XBoard $Id: gamelist.c,v 2.1 2003/10/27 19:21:00 mann Exp $
- *
- * Copyright 1995 Free Software Foundation, Inc.
- *
- * ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
- * ------------------------------------------------------------------------
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <errno.h>
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <string.h>
-#else /* not STDC_HEADERS */
-# if HAVE_STRING_H
-#  include <string.h>
-# else /* not HAVE_STRING_H */
-#  include <strings.h>
-# endif /* not HAVE_STRING_H */
-#endif /* not STDC_HEADERS */
-
-#include "common.h"
-#include "frontend.h"
-#include "backend.h"
-#include "parser.h"
-
-
-/* Variables
- */
-List gameList;
-
-
-/* Local function prototypes
- */
-static void GameListDeleteGame P((ListGame *));
-static ListGame *GameListCreate P((void));
-static void GameListFree P((List *));
-static int GameListNewGame P((ListGame **));
-
-/* Delete a ListGame; implies removint it from a list.
- */
-static void GameListDeleteGame(listGame)
-    ListGame *listGame;
-{
-    if (listGame) {
-       if (listGame->gameInfo.event) free(listGame->gameInfo.event);
-       if (listGame->gameInfo.site) free(listGame->gameInfo.site);
-       if (listGame->gameInfo.date) free(listGame->gameInfo.date);
-       if (listGame->gameInfo.round) free(listGame->gameInfo.round);
-       if (listGame->gameInfo.white) free(listGame->gameInfo.white);
-       if (listGame->gameInfo.black) free(listGame->gameInfo.black);
-       if (listGame->gameInfo.fen) free(listGame->gameInfo.fen);
-       if (listGame->gameInfo.resultDetails) free(listGame->gameInfo.resultDetails);
-       if (listGame->gameInfo.timeControl) free(listGame->gameInfo.timeControl);
-       if (listGame->gameInfo.extraTags) free(listGame->gameInfo.extraTags);
-        if (listGame->gameInfo.outOfBook) free(listGame->gameInfo.outOfBook);
-       ListNodeFree((ListNode *) listGame);
-    }
-}
-
-
-/* Free the previous list of games.
- */
-static void GameListFree(gameList)
-    List *gameList;
-{
-    while (!ListEmpty(gameList))
-    {
-       GameListDeleteGame((ListGame *) gameList->head);
-    }
-}
-
-
-
-/* Initialize a new GameInfo structure.
- */
-void GameListInitGameInfo(gameInfo)
-    GameInfo *gameInfo;
-{
-    gameInfo->event = NULL;
-    gameInfo->site = NULL;
-    gameInfo->date = NULL;
-    gameInfo->round = NULL;
-    gameInfo->white = NULL;
-    gameInfo->black = NULL;
-    gameInfo->result = GameUnfinished;
-    gameInfo->fen = NULL;
-    gameInfo->resultDetails = NULL;
-    gameInfo->timeControl = NULL;
-    gameInfo->extraTags = NULL;
-    gameInfo->whiteRating = -1; /* unknown */
-    gameInfo->blackRating = -1; /* unknown */
-    gameInfo->variant = VariantNormal;
-    gameInfo->outOfBook = NULL;
-}
-
-
-/* Create empty ListGame; returns ListGame or NULL, if out of memory.
- *
- * Note, that the ListGame is *not* added to any list
- */
-static ListGame *GameListCreate()
-
-{
-    ListGame *listGame;
-
-    if ((listGame = (ListGame *) ListNodeCreate(sizeof(*listGame)))) {
-       GameListInitGameInfo(&listGame->gameInfo);
-    }
-    return(listGame);
-}
-
-
-/* Creates a new game for the gamelist.
- */
-static int GameListNewGame(listGamePtr)
-     ListGame **listGamePtr;
-{
-    if (!(*listGamePtr = (ListGame *) GameListCreate())) {
-       GameListFree(&gameList);
-       return(ENOMEM);
-    }
-    ListAddTail(&gameList, (ListNode *) *listGamePtr);
-    return(0);
-}
-
-
-/* Build the list of games in the open file f.
- * Returns 0 for success or error number.
- */
-int GameListBuild(f)
-    FILE *f;
-{
-    ChessMove cm, lastStart;
-    int gameNumber;
-    ListGame *currentListGame = NULL;
-    int error;
-    int offset;
-
-    GameListFree(&gameList);
-    yynewfile(f);
-    gameNumber = 0;
-
-    lastStart = (ChessMove) 0;
-    yyskipmoves = FALSE;
-    do {
-        yyboardindex = 0;
-       offset = yyoffset();
-       cm = (ChessMove) yylex();
-       switch (cm) {
-         case GNUChessGame:
-           if ((error = GameListNewGame(&currentListGame))) {
-               rewind(f);
-               yyskipmoves = FALSE;
-               return(error);
-           }
-           currentListGame->number = ++gameNumber;
-           currentListGame->offset = offset;
-           if (currentListGame->gameInfo.event != NULL) {
-               free(currentListGame->gameInfo.event);
-           }
-           currentListGame->gameInfo.event = StrSave(yy_text);
-           lastStart = cm;
-           break;
-         case XBoardGame:
-           lastStart = cm;
-           break;
-         case MoveNumberOne:
-           switch (lastStart) {
-             case GNUChessGame:
-               break;          /*  ignore  */
-             case PGNTag:
-               lastStart = cm;
-               break;          /*  Already started */
-             case (ChessMove) 0:
-             case MoveNumberOne:
-             case XBoardGame:
-               if ((error = GameListNewGame(&currentListGame))) {
-                   rewind(f);
-                   yyskipmoves = FALSE;
-                   return(error);
-               }
-               currentListGame->number = ++gameNumber;
-               currentListGame->offset = offset;
-               lastStart = cm;
-               break;
-             default:
-               break;          /*  impossible  */
-           }
-           break;
-         case PGNTag:
-           lastStart = cm;
-           if ((error = GameListNewGame(&currentListGame))) {
-               rewind(f);
-               yyskipmoves = FALSE;
-               return(error);
-           }
-           currentListGame->number = ++gameNumber;
-           currentListGame->offset = offset;
-           ParsePGNTag(yy_text, &currentListGame->gameInfo);
-           do {
-               yyboardindex = 1;
-               offset = yyoffset();
-               cm = (ChessMove) yylex();
-               if (cm == PGNTag) {
-                   ParsePGNTag(yy_text, &currentListGame->gameInfo);
-               }
-           } while (cm == PGNTag || cm == Comment);
-           break;
-         case NormalMove:
-           /* Allow the first game to start with an unnumbered move */
-           yyskipmoves = TRUE;
-           if (lastStart == (ChessMove) 0) {
-             if ((error = GameListNewGame(&currentListGame))) {
-               rewind(f);
-               yyskipmoves = FALSE;
-               return(error);
-             }
-             currentListGame->number = ++gameNumber;
-             currentListGame->offset = offset;
-             lastStart = MoveNumberOne;
-           }
-           break;
-         default:
-           break;
-       }
-    }
-    while (cm != (ChessMove) 0);
-
-
-    if (appData.debugMode) {
-       for (currentListGame = (ListGame *) gameList.head;
-            currentListGame->node.succ;
-            currentListGame = (ListGame *) currentListGame->node.succ) {
-
-           fprintf(debugFP, "Parsed game number %d, offset %ld:\n",
-                   currentListGame->number, currentListGame->offset);
-           PrintPGNTags(debugFP, &currentListGame->gameInfo);
-       }
-    }
-
-    rewind(f);
-    yyskipmoves = FALSE;
-    return 0;
-}
-
-
-/* Clear an existing GameInfo structure.
- */
-void ClearGameInfo(gameInfo)
-    GameInfo *gameInfo;
-{
-    if (gameInfo->event != NULL) {
-       free(gameInfo->event);
-    }
-    if (gameInfo->site != NULL) {
-       free(gameInfo->site);
-    }
-    if (gameInfo->date != NULL) {
-       free(gameInfo->date);
-    }
-    if (gameInfo->round != NULL) {
-       free(gameInfo->round);
-    }
-    if (gameInfo->white != NULL) {
-       free(gameInfo->white);
-    }
-    if (gameInfo->black != NULL) {
-       free(gameInfo->black);
-    }
-    if (gameInfo->resultDetails != NULL) {
-       free(gameInfo->resultDetails);
-    }
-    if (gameInfo->fen != NULL) {
-       free(gameInfo->fen);
-    }
-    if (gameInfo->timeControl != NULL) {
-       free(gameInfo->timeControl);
-    }
-    if (gameInfo->extraTags != NULL) {
-       free(gameInfo->extraTags);
-    }
-    if (gameInfo->outOfBook != NULL) {
-        free(gameInfo->outOfBook);
-    }
-
-    GameListInitGameInfo(gameInfo);
-}
-
-/* [AS] Replaced by "dynamic" tag selection below */
-char *
-GameListLineOld(number, gameInfo)
-     int number;
-     GameInfo *gameInfo;
-{
-    char *event = (gameInfo->event && strcmp(gameInfo->event, "?") != 0) ?
-                    gameInfo->event : gameInfo->site ? gameInfo->site : "?";
-    char *white = gameInfo->white ? gameInfo->white : "?";
-    char *black = gameInfo->black ? gameInfo->black : "?";
-    char *date = gameInfo->date ? gameInfo->date : "?";
-    int len = 10 + strlen(event) + 2 + strlen(white) + 1 + 
-      strlen(black) + 11 + strlen(date) + 1;
-    char *ret = (char *) malloc(len);
-    sprintf(ret, "%d. %s, %s-%s, %s, %s",
-           number, event, white, black, PGNResult(gameInfo->result), date);
-    return ret;
-}
-
-#define MAX_FIELD_LEN   64  /* To avoid overflowing the buffer */
-
-char * GameListLine( int number, GameInfo * gameInfo )
-{
-    char buffer[1024];
-    char * buf = buffer;
-    char * glt = appData.gameListTags;
-
-    buf += sprintf( buffer, "%d.", number );
-
-    while( *glt != '\0' ) {
-        *buf++ = ' ';
-
-        switch( *glt ) {
-        case GLT_EVENT:
-            strncpy( buf, gameInfo->event ? gameInfo->event : "?", MAX_FIELD_LEN );
-            break;
-        case GLT_SITE:
-            strncpy( buf, gameInfo->site ? gameInfo->site : "?", MAX_FIELD_LEN );
-            break;
-        case GLT_DATE:
-            strncpy( buf, gameInfo->date ? gameInfo->date : "?", MAX_FIELD_LEN );
-            break;
-        case GLT_ROUND:
-            strncpy( buf, gameInfo->round ? gameInfo->round : "?", MAX_FIELD_LEN );
-            break;
-        case GLT_PLAYERS:
-            strncpy( buf, gameInfo->white ? gameInfo->white : "?", MAX_FIELD_LEN );
-            buf[ MAX_FIELD_LEN-1 ] = '\0';
-            buf += strlen( buf );
-            *buf++ = '-';
-            strncpy( buf, gameInfo->black ? gameInfo->black : "?", MAX_FIELD_LEN );
-            break;
-        case GLT_RESULT:
-            strcpy( buf, PGNResult(gameInfo->result) );
-            break;
-        case GLT_WHITE_ELO:
-            if( gameInfo->whiteRating > 0 )
-                sprintf( buf, "%d", gameInfo->whiteRating );
-            else
-                strcpy( buf, "?" );
-            break;
-        case GLT_BLACK_ELO:
-            if( gameInfo->blackRating > 0 )
-                sprintf( buf, "%d", gameInfo->blackRating );
-            else
-                strcpy( buf, "?" );
-            break;
-        case GLT_TIME_CONTROL:
-            strncpy( buf, gameInfo->timeControl ? gameInfo->timeControl : "?", MAX_FIELD_LEN );
-            break;
-        case GLT_VARIANT:
-            break;
-        case GLT_OUT_OF_BOOK:
-            strncpy( buf, gameInfo->outOfBook ? gameInfo->outOfBook : "?", MAX_FIELD_LEN );
-            break;
-        default:
-            break;
-        }
-
-        buf[MAX_FIELD_LEN-1] = '\0';
-
-        buf += strlen( buf );
-
-        glt++;
-
-        if( *glt != '\0' ) {
-            *buf++ = ',';
-        }
-    }
-
-    *buf = '\0';
-
-    return strdup( buffer );
-}
-
-char * GameListLineFull( int number, GameInfo * gameInfo )
-{
-    char * event = gameInfo->event ? gameInfo->event : "?";
-    char * site = gameInfo->site ? gameInfo->site : "?";
-    char * white = gameInfo->white ? gameInfo->white : "?";
-    char * black = gameInfo->black ? gameInfo->black : "?";
-    char * round = gameInfo->round ? gameInfo->round : "?";
-    char * date = gameInfo->date ? gameInfo->date : "?";
-    char * oob = gameInfo->outOfBook ? gameInfo->outOfBook : "";
-
-    int len = 64 + strlen(event) + strlen(site) + strlen(white) + strlen(black) + strlen(date) + strlen(oob);
-
-    char *ret = (char *) malloc(len);
-
-    sprintf(ret, "%d, \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"", number, event, site, round, white, black, PGNResult(gameInfo->result), date, oob );
-
-    return ret;
-}
+/*\r
+ * gamelist.c -- Functions to manage a gamelist\r
+ * XBoard $Id: gamelist.c,v 2.1 2003/10/27 19:21:00 mann Exp $\r
+ *\r
+ * Copyright 1995 Free Software Foundation, Inc.\r
+ *\r
+ * ------------------------------------------------------------------------\r
+ * This program 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
+ *\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
+ *\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 USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+\r
+#include "config.h"\r
+\r
+#include <stdio.h>\r
+#include <errno.h>\r
+#if STDC_HEADERS\r
+# include <stdlib.h>\r
+# include <string.h>\r
+#else /* not STDC_HEADERS */\r
+# if HAVE_STRING_H\r
+#  include <string.h>\r
+# else /* not HAVE_STRING_H */\r
+#  include <strings.h>\r
+# endif /* not HAVE_STRING_H */\r
+#endif /* not STDC_HEADERS */\r
+\r
+#include "common.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+#include "parser.h"\r
+\r
+\r
+/* Variables\r
+ */\r
+List gameList;\r
+\r
+\r
+/* Local function prototypes\r
+ */\r
+static void GameListDeleteGame P((ListGame *));\r
+static ListGame *GameListCreate P((void));\r
+static void GameListFree P((List *));\r
+static int GameListNewGame P((ListGame **));\r
+\r
+/* Delete a ListGame; implies removint it from a list.\r
+ */\r
+static void GameListDeleteGame(listGame)\r
+    ListGame *listGame;\r
+{\r
+    if (listGame) {\r
+       if (listGame->gameInfo.event) free(listGame->gameInfo.event);\r
+       if (listGame->gameInfo.site) free(listGame->gameInfo.site);\r
+       if (listGame->gameInfo.date) free(listGame->gameInfo.date);\r
+       if (listGame->gameInfo.round) free(listGame->gameInfo.round);\r
+       if (listGame->gameInfo.white) free(listGame->gameInfo.white);\r
+       if (listGame->gameInfo.black) free(listGame->gameInfo.black);\r
+       if (listGame->gameInfo.fen) free(listGame->gameInfo.fen);\r
+       if (listGame->gameInfo.resultDetails) free(listGame->gameInfo.resultDetails);\r
+       if (listGame->gameInfo.timeControl) free(listGame->gameInfo.timeControl);\r
+       if (listGame->gameInfo.extraTags) free(listGame->gameInfo.extraTags);\r
+        if (listGame->gameInfo.outOfBook) free(listGame->gameInfo.outOfBook);\r
+       ListNodeFree((ListNode *) listGame);\r
+    }\r
+}\r
+\r
+\r
+/* Free the previous list of games.\r
+ */\r
+static void GameListFree(gameList)\r
+    List *gameList;\r
+{\r
+    while (!ListEmpty(gameList))\r
+    {\r
+       GameListDeleteGame((ListGame *) gameList->head);\r
+    }\r
+}\r
+\r
+\r
+\r
+/* Initialize a new GameInfo structure.\r
+ */\r
+void GameListInitGameInfo(gameInfo)\r
+    GameInfo *gameInfo;\r
+{\r
+    gameInfo->event = NULL;\r
+    gameInfo->site = NULL;\r
+    gameInfo->date = NULL;\r
+    gameInfo->round = NULL;\r
+    gameInfo->white = NULL;\r
+    gameInfo->black = NULL;\r
+    gameInfo->result = GameUnfinished;\r
+    gameInfo->fen = NULL;\r
+    gameInfo->resultDetails = NULL;\r
+    gameInfo->timeControl = NULL;\r
+    gameInfo->extraTags = NULL;\r
+    gameInfo->whiteRating = -1; /* unknown */\r
+    gameInfo->blackRating = -1; /* unknown */\r
+    gameInfo->variant = VariantNormal;\r
+    gameInfo->outOfBook = NULL;\r
+}\r
+\r
+\r
+/* Create empty ListGame; returns ListGame or NULL, if out of memory.\r
+ *\r
+ * Note, that the ListGame is *not* added to any list\r
+ */\r
+static ListGame *GameListCreate()\r
+\r
+{\r
+    ListGame *listGame;\r
+\r
+    if ((listGame = (ListGame *) ListNodeCreate(sizeof(*listGame)))) {\r
+       GameListInitGameInfo(&listGame->gameInfo);\r
+    }\r
+    return(listGame);\r
+}\r
+\r
+\r
+/* Creates a new game for the gamelist.\r
+ */\r
+static int GameListNewGame(listGamePtr)\r
+     ListGame **listGamePtr;\r
+{\r
+    if (!(*listGamePtr = (ListGame *) GameListCreate())) {\r
+       GameListFree(&gameList);\r
+       return(ENOMEM);\r
+    }\r
+    ListAddTail(&gameList, (ListNode *) *listGamePtr);\r
+    return(0);\r
+}\r
+\r
+\r
+/* Build the list of games in the open file f.\r
+ * Returns 0 for success or error number.\r
+ */\r
+int GameListBuild(f)\r
+    FILE *f;\r
+{\r
+    ChessMove cm, lastStart;\r
+    int gameNumber;\r
+    ListGame *currentListGame = NULL;\r
+    int error;\r
+    int offset;\r
+\r
+    GameListFree(&gameList);\r
+    yynewfile(f);\r
+    gameNumber = 0;\r
+\r
+    lastStart = (ChessMove) 0;\r
+    yyskipmoves = FALSE;\r
+    do {\r
+        yyboardindex = 0;\r
+       offset = yyoffset();\r
+       cm = (ChessMove) yylex();\r
+       switch (cm) {\r
+         case GNUChessGame:\r
+           if ((error = GameListNewGame(&currentListGame))) {\r
+               rewind(f);\r
+               yyskipmoves = FALSE;\r
+               return(error);\r
+           }\r
+           currentListGame->number = ++gameNumber;\r
+           currentListGame->offset = offset;\r
+           if (currentListGame->gameInfo.event != NULL) {\r
+               free(currentListGame->gameInfo.event);\r
+           }\r
+           currentListGame->gameInfo.event = StrSave(yy_text);\r
+           lastStart = cm;\r
+           break;\r
+         case XBoardGame:\r
+           lastStart = cm;\r
+           break;\r
+         case MoveNumberOne:\r
+           switch (lastStart) {\r
+             case GNUChessGame:\r
+               break;          /*  ignore  */\r
+             case PGNTag:\r
+               lastStart = cm;\r
+               break;          /*  Already started */\r
+             case (ChessMove) 0:\r
+             case MoveNumberOne:\r
+             case XBoardGame:\r
+               if ((error = GameListNewGame(&currentListGame))) {\r
+                   rewind(f);\r
+                   yyskipmoves = FALSE;\r
+                   return(error);\r
+               }\r
+               currentListGame->number = ++gameNumber;\r
+               currentListGame->offset = offset;\r
+               lastStart = cm;\r
+               break;\r
+             default:\r
+               break;          /*  impossible  */\r
+           }\r
+           break;\r
+         case PGNTag:\r
+           lastStart = cm;\r
+           if ((error = GameListNewGame(&currentListGame))) {\r
+               rewind(f);\r
+               yyskipmoves = FALSE;\r
+               return(error);\r
+           }\r
+           currentListGame->number = ++gameNumber;\r
+           currentListGame->offset = offset;\r
+           ParsePGNTag(yy_text, &currentListGame->gameInfo);\r
+           do {\r
+               yyboardindex = 1;\r
+               offset = yyoffset();\r
+               cm = (ChessMove) yylex();\r
+               if (cm == PGNTag) {\r
+                   ParsePGNTag(yy_text, &currentListGame->gameInfo);\r
+               }\r
+           } while (cm == PGNTag || cm == Comment);\r
+           break;\r
+         case NormalMove:\r
+           /* Allow the first game to start with an unnumbered move */\r
+           yyskipmoves = TRUE;\r
+           if (lastStart == (ChessMove) 0) {\r
+             if ((error = GameListNewGame(&currentListGame))) {\r
+               rewind(f);\r
+               yyskipmoves = FALSE;\r
+               return(error);\r
+             }\r
+             currentListGame->number = ++gameNumber;\r
+             currentListGame->offset = offset;\r
+             lastStart = MoveNumberOne;\r
+           }\r
+           break;\r
+         default:\r
+           break;\r
+       }\r
+    }\r
+    while (cm != (ChessMove) 0);\r
+\r
+\r
+    if (appData.debugMode) {\r
+       for (currentListGame = (ListGame *) gameList.head;\r
+            currentListGame->node.succ;\r
+            currentListGame = (ListGame *) currentListGame->node.succ) {\r
+\r
+           fprintf(debugFP, "Parsed game number %d, offset %ld:\n",\r
+                   currentListGame->number, currentListGame->offset);\r
+           PrintPGNTags(debugFP, &currentListGame->gameInfo);\r
+       }\r
+    }\r
+\r
+    rewind(f);\r
+    yyskipmoves = FALSE;\r
+    return 0;\r
+}\r
+\r
+\r
+/* Clear an existing GameInfo structure.\r
+ */\r
+void ClearGameInfo(gameInfo)\r
+    GameInfo *gameInfo;\r
+{\r
+    if (gameInfo->event != NULL) {\r
+       free(gameInfo->event);\r
+    }\r
+    if (gameInfo->site != NULL) {\r
+       free(gameInfo->site);\r
+    }\r
+    if (gameInfo->date != NULL) {\r
+       free(gameInfo->date);\r
+    }\r
+    if (gameInfo->round != NULL) {\r
+       free(gameInfo->round);\r
+    }\r
+    if (gameInfo->white != NULL) {\r
+       free(gameInfo->white);\r
+    }\r
+    if (gameInfo->black != NULL) {\r
+       free(gameInfo->black);\r
+    }\r
+    if (gameInfo->resultDetails != NULL) {\r
+       free(gameInfo->resultDetails);\r
+    }\r
+    if (gameInfo->fen != NULL) {\r
+       free(gameInfo->fen);\r
+    }\r
+    if (gameInfo->timeControl != NULL) {\r
+       free(gameInfo->timeControl);\r
+    }\r
+    if (gameInfo->extraTags != NULL) {\r
+       free(gameInfo->extraTags);\r
+    }\r
+    if (gameInfo->outOfBook != NULL) {\r
+        free(gameInfo->outOfBook);\r
+    }\r
+\r
+    GameListInitGameInfo(gameInfo);\r
+}\r
+\r
+/* [AS] Replaced by "dynamic" tag selection below */\r
+char *\r
+GameListLineOld(number, gameInfo)\r
+     int number;\r
+     GameInfo *gameInfo;\r
+{\r
+    char *event = (gameInfo->event && strcmp(gameInfo->event, "?") != 0) ?\r
+                    gameInfo->event : gameInfo->site ? gameInfo->site : "?";\r
+    char *white = gameInfo->white ? gameInfo->white : "?";\r
+    char *black = gameInfo->black ? gameInfo->black : "?";\r
+    char *date = gameInfo->date ? gameInfo->date : "?";\r
+    int len = 10 + strlen(event) + 2 + strlen(white) + 1 + \r
+      strlen(black) + 11 + strlen(date) + 1;\r
+    char *ret = (char *) malloc(len);\r
+    sprintf(ret, "%d. %s, %s-%s, %s, %s",\r
+           number, event, white, black, PGNResult(gameInfo->result), date);\r
+    return ret;\r
+}\r
+\r
+#define MAX_FIELD_LEN   64  /* To avoid overflowing the buffer */\r
+\r
+char * GameListLine( int number, GameInfo * gameInfo )\r
+{\r
+    char buffer[1024];\r
+    char * buf = buffer;\r
+    char * glt = appData.gameListTags;\r
+    \r
+    buf += sprintf( buffer, "%d.", number );\r
+\r
+    while( *glt != '\0' ) {\r
+        *buf++ = ' ';\r
+\r
+        switch( *glt ) {\r
+        case GLT_EVENT:\r
+            strncpy( buf, gameInfo->event ? gameInfo->event : "?", MAX_FIELD_LEN );\r
+            break;\r
+        case GLT_SITE:\r
+            strncpy( buf, gameInfo->site ? gameInfo->site : "?", MAX_FIELD_LEN );\r
+            break;\r
+        case GLT_DATE:\r
+            strncpy( buf, gameInfo->date ? gameInfo->date : "?", MAX_FIELD_LEN );\r
+            break;\r
+        case GLT_ROUND:\r
+            strncpy( buf, gameInfo->round ? gameInfo->round : "?", MAX_FIELD_LEN );\r
+            break;\r
+        case GLT_PLAYERS:\r
+            strncpy( buf, gameInfo->white ? gameInfo->white : "?", MAX_FIELD_LEN );\r
+            buf[ MAX_FIELD_LEN-1 ] = '\0';\r
+            buf += strlen( buf );\r
+            *buf++ = '-';\r
+            strncpy( buf, gameInfo->black ? gameInfo->black : "?", MAX_FIELD_LEN );\r
+            break;\r
+        case GLT_RESULT:\r
+            strcpy( buf, PGNResult(gameInfo->result) );\r
+            break;\r
+        case GLT_WHITE_ELO:\r
+            if( gameInfo->whiteRating > 0 )\r
+                sprintf( buf, "%d", gameInfo->whiteRating );\r
+            else\r
+                strcpy( buf, "?" );\r
+            break;\r
+        case GLT_BLACK_ELO:\r
+            if( gameInfo->blackRating > 0 )\r
+                sprintf( buf, "%d", gameInfo->blackRating );\r
+            else\r
+                strcpy( buf, "?" );\r
+            break;\r
+        case GLT_TIME_CONTROL:\r
+            strncpy( buf, gameInfo->timeControl ? gameInfo->timeControl : "?", MAX_FIELD_LEN );\r
+            break;\r
+        case GLT_VARIANT:\r
+            break;\r
+        case GLT_OUT_OF_BOOK:\r
+            strncpy( buf, gameInfo->outOfBook ? gameInfo->outOfBook : "?", MAX_FIELD_LEN );\r
+            break;\r
+        default:\r
+            break;\r
+        }\r
+\r
+        buf[MAX_FIELD_LEN-1] = '\0';\r
+\r
+        buf += strlen( buf );\r
+\r
+        glt++;\r
+\r
+        if( *glt != '\0' ) {\r
+            *buf++ = ',';\r
+        }\r
+    }\r
+\r
+    *buf = '\0';\r
+\r
+    return strdup( buffer );\r
+}\r
+\r
+char * GameListLineFull( int number, GameInfo * gameInfo )\r
+{\r
+    char * event = gameInfo->event ? gameInfo->event : "?";\r
+    char * site = gameInfo->site ? gameInfo->site : "?";\r
+    char * white = gameInfo->white ? gameInfo->white : "?";\r
+    char * black = gameInfo->black ? gameInfo->black : "?";\r
+    char * round = gameInfo->round ? gameInfo->round : "?";\r
+    char * date = gameInfo->date ? gameInfo->date : "?";\r
+    char * oob = gameInfo->outOfBook ? gameInfo->outOfBook : "";\r
+    \r
+    int len = 64 + strlen(event) + strlen(site) + strlen(white) + strlen(black) + strlen(date) + strlen(oob);\r
+\r
+    char *ret = (char *) malloc(len);\r
+\r
+    sprintf(ret, "%d, \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\"", number, event, site, round, white, black, PGNResult(gameInfo->result), date, oob );\r
+\r
+    return ret;\r
+}\r
diff --git a/lists.c b/lists.c
index a9e0d41..8d9bb20 100644 (file)
--- a/lists.c
+++ b/lists.c
-/*
- * lists.c -- Functions to implement a double linked list
- * XBoard $Id: lists.c,v 2.1 2003/10/27 19:21:00 mann Exp $
- *
- * Copyright 1995 Free Software Foundation, Inc.
- *
- * ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
- * ------------------------------------------------------------------------
- *
- * This file could well be a part of backend.c, but I prefer it this
- * way.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#if STDC_HEADERS
-# include <stdlib.h>
-#endif /* not STDC_HEADERS */
-
-#include "common.h"
-#include "lists.h"
-
-
-
-/* Check, if List l is empty; returns TRUE, if it is, FALSE
- * otherwise.
- */
-int ListEmpty(l)
-    List *l;
-{
-    return(l->head == (ListNode *) &l->tail);
-}
-
-
-/* Initialize a list. Must be executed before list is used.
- */
-void ListNew(l)
-    List *l;
-{
-    l->head = (ListNode *) &l->tail;
-    l->tail = NULL;
-    l->tailPred = (ListNode *) l;
-}
-
-
-/* Remove node n from the list it is inside.
- */
-void ListRemove(n)
-    ListNode *n;
-{
-    if (n->succ != NULL) {  /*  Be safe  */
-       n->pred->succ = n->succ;
-       n->succ->pred = n->pred;
-       n->succ = NULL;     /*  Mark node as no longer being member */
-       n->pred = NULL;     /*  of a list.                          */
-    }
-}
-
-
-/* Delete node n.
- */
-void ListNodeFree(n)
-    ListNode *n;
-{
-    if (n) {
-       ListRemove(n);
-       free(n);
-    }
-}
-
-
-/* Create a list node with size s. Returns NULL, if out of memory.
- */
-ListNode *ListNodeCreate(s)
-    size_t s;
-{
-    ListNode *n;
-
-    if ((n = (ListNode*) malloc(s))) {
-       n->succ = NULL; /*  Mark node as not being member of a list.    */
-       n->pred = NULL;
-    }
-    return(n);
-}
-
-
-/* Insert node n into the list of node m after m.
- */
-void ListInsert(m, n)
-    ListNode *m, *n;
-{
-    n->succ = m->succ;
-    n->pred = m;
-    m->succ = n;
-    n->succ->pred = n;
-}
-
-
-/* Add node n to the head of list l.
- */
-void ListAddHead(l, n)
-    List *l;
-    ListNode *n;
-{
-    ListInsert((ListNode *) &l->head, n);
-}
-
-
-/* Add node n to the tail of list l.
- */
-void ListAddTail(l, n)
-    List *l;
-    ListNode *n;
-{
-    ListInsert((ListNode *) l->tailPred, n);
-}
-
-
-/* Return element with number n of list l. (NULL, if n doesn't exist.)
- * Counting starts with 0.
- */
-ListNode *ListElem(l, n)
-    List *l;
-    int n;
-{
-    ListNode *ln;
-
-    for (ln = l->head;  ln->succ;  ln = ln->succ) {
-       if (!n--) {
-           return (ln);
-       }
-    }
-
-    return(NULL);
-}
+/*\r
+ * lists.c -- Functions to implement a double linked list\r
+ * XBoard $Id: lists.c,v 2.1 2003/10/27 19:21:00 mann Exp $\r
+ *\r
+ * Copyright 1995 Free Software Foundation, Inc.\r
+ *\r
+ * ------------------------------------------------------------------------\r
+ * This program 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
+ *\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
+ *\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 USA.\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * This file could well be a part of backend.c, but I prefer it this\r
+ * way.\r
+ */\r
+\r
+#include "config.h"\r
+\r
+#include <stdio.h>\r
+#if STDC_HEADERS\r
+# include <stdlib.h>\r
+#endif /* not STDC_HEADERS */\r
+\r
+#include "common.h"\r
+#include "lists.h"\r
+\r
+\r
+\r
+/* Check, if List l is empty; returns TRUE, if it is, FALSE\r
+ * otherwise.\r
+ */\r
+int ListEmpty(l)\r
+    List *l;\r
+{\r
+    return(l->head == (ListNode *) &l->tail);\r
+}\r
+\r
+\r
+/* Initialize a list. Must be executed before list is used.\r
+ */\r
+void ListNew(l)\r
+    List *l;\r
+{\r
+    l->head = (ListNode *) &l->tail;\r
+    l->tail = NULL;\r
+    l->tailPred = (ListNode *) l;\r
+}\r
+\r
+\r
+/* Remove node n from the list it is inside.\r
+ */\r
+void ListRemove(n)\r
+    ListNode *n;\r
+{\r
+    if (n->succ != NULL) {  /*  Be safe  */\r
+       n->pred->succ = n->succ;\r
+       n->succ->pred = n->pred;\r
+       n->succ = NULL;     /*  Mark node as no longer being member */\r
+       n->pred = NULL;     /*  of a list.                          */\r
+    }\r
+}\r
+\r
+\r
+/* Delete node n.\r
+ */\r
+void ListNodeFree(n)\r
+    ListNode *n;\r
+{\r
+    if (n) {\r
+       ListRemove(n);\r
+       free(n);\r
+    }\r
+}\r
+\r
+\r
+/* Create a list node with size s. Returns NULL, if out of memory.\r
+ */\r
+ListNode *ListNodeCreate(s)\r
+    size_t s;\r
+{\r
+    ListNode *n;\r
+\r
+    if ((n = (ListNode*) malloc(s))) {\r
+       n->succ = NULL; /*  Mark node as not being member of a list.    */\r
+       n->pred = NULL;\r
+    }\r
+    return(n);\r
+}\r
+\r
+\r
+/* Insert node n into the list of node m after m.\r
+ */\r
+void ListInsert(m, n)\r
+    ListNode *m, *n;\r
+{\r
+    n->succ = m->succ;\r
+    n->pred = m;\r
+    m->succ = n;\r
+    n->succ->pred = n;\r
+}\r
+\r
+\r
+/* Add node n to the head of list l.\r
+ */\r
+void ListAddHead(l, n)\r
+    List *l;\r
+    ListNode *n;\r
+{\r
+    ListInsert((ListNode *) &l->head, n);\r
+}\r
+\r
+\r
+/* Add node n to the tail of list l.\r
+ */\r
+void ListAddTail(l, n)\r
+    List *l;\r
+    ListNode *n;\r
+{\r
+    ListInsert((ListNode *) l->tailPred, n);\r
+}\r
+\r
+\r
+/* Return element with number n of list l. (NULL, if n doesn't exist.)\r
+ * Counting starts with 0.\r
+ */\r
+ListNode *ListElem(l, n)\r
+    List *l;\r
+    int n;\r
+{\r
+    ListNode *ln;\r
+\r
+    for (ln = l->head;  ln->succ;  ln = ln->succ) {\r
+       if (!n--) {\r
+           return (ln);\r
+       }\r
+    }\r
+\r
+    return(NULL);\r
+}\r
diff --git a/lists.h b/lists.h
index 31d6f5b..b291894 100644 (file)
--- a/lists.h
+++ b/lists.h
@@ -1,66 +1,66 @@
-/*
- * lists.c -- Includefile of lists.c
- * XBoard $Id: lists.h,v 2.1 2003/10/27 19:21:00 mann Exp $
- *
- * Copyright 1995 Free Software Foundation, Inc.
- *
- * ------------------------------------------------------------------------
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
- * ------------------------------------------------------------------------
- *
- * This file could well be a part of backend.c, but I prefer it this
- * way.
- */
-
-#ifndef _LISTS_H
-#define _LISTS_H
-
-
-/* Type definition: Node of a double linked list.
- */
-typedef struct _ListNode {
-    struct _ListNode *succ;
-    struct _ListNode *pred;
-} ListNode;
-
-
-/* Type definition: Double linked list.
- *
- * The list structure consists of two ListNode's: The pred entry of
- * the head being the succ entry of the tail. Thus a list is empty
- * if and only if it consists of 2 nodes. :-)
- */
-typedef struct {
-    struct _ListNode *head;     /*  The list structure consists of two  */
-    struct _ListNode *tail;     /*  ListNode's: The pred entry of the   */
-    struct _ListNode *tailPred; /*  head being the succ entry of the    */
-} List;                         /*  tail.                               */
-
-
-
-/* Function prototypes
- */
-extern int ListEmpty P((List *));
-void ListNew P((List *));
-void ListRemove P((ListNode *));
-void ListNodeFree P((ListNode *));
-ListNode *ListNodeCreate P((size_t));
-void ListInsert P((ListNode *, ListNode *));
-void ListAddHead P((List *, ListNode *));
-void ListAddTail P((List *, ListNode *));
-ListNode *ListElem P((List *, int));
-
-
-#endif
+/*\r
+ * lists.c -- Includefile of lists.c\r
+ * XBoard $Id: lists.h,v 2.1 2003/10/27 19:21:00 mann Exp $\r
+ *\r
+ * Copyright 1995 Free Software Foundation, Inc.\r
+ *\r
+ * ------------------------------------------------------------------------\r
+ * This program 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
+ *\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
+ *\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 USA.\r
+ * ------------------------------------------------------------------------\r
+ *\r
+ * This file could well be a part of backend.c, but I prefer it this\r
+ * way.\r
+ */\r
+\r
+#ifndef _LISTS_H\r
+#define _LISTS_H\r
+\r
+\r
+/* Type definition: Node of a double linked list.\r
+ */\r
+typedef struct _ListNode {\r
+    struct _ListNode *succ;\r
+    struct _ListNode *pred;\r
+} ListNode;\r
+\r
+\r
+/* Type definition: Double linked list.\r
+ *\r
+ * The list structure consists of two ListNode's: The pred entry of\r
+ * the head being the succ entry of the tail. Thus a list is empty\r
+ * if and only if it consists of 2 nodes. :-)\r
+ */\r
+typedef struct {\r
+    struct _ListNode *head;     /*  The list structure consists of two  */\r
+    struct _ListNode *tail;     /*  ListNode's: The pred entry of the   */\r
+    struct _ListNode *tailPred; /*  head being the succ entry of the    */\r
+} List;                         /*  tail.                               */\r
+\r
+\r
+\r
+/* Function prototypes\r
+ */\r
+extern int ListEmpty P((List *));\r
+void ListNew P((List *));\r
+void ListRemove P((ListNode *));\r
+void ListNodeFree P((ListNode *));\r
+ListNode *ListNodeCreate P((size_t));\r
+void ListInsert P((ListNode *, ListNode *));\r
+void ListAddHead P((List *, ListNode *));\r
+void ListAddTail P((List *, ListNode *));\r
+ListNode *ListElem P((List *, int));\r
+\r
+\r
+#endif\r
diff --git a/moves.c b/moves.c
index deb245f..deac69f 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -196,12 +196,11 @@ ChessMove PromoCharToMoveType(whiteOnMove, promoChar)
 }\r
 \r
 char pieceToChar[] = {\r
-                        'P', 'N', 'B', 'R', 'Q', 'F', \r
-    'W', 'E', 'M', 'O', 'U', 'H', 'A', 'C', 'G', 'S',\r
-    'K',                'p', 'n', 'b', 'r', 'q', 'f', \r
-    'w', 'e', 'm', 'o', 'u', 'h', 'a', 'c', 'g', 's',\r
-    'k', 'x'\r
-  };\r
+                        'P', '