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', 'N', 'B', 'R', 'Q', 'F', 'E', 'A', 'C', 'W', 'M', \r
+                        'O', 'H', 'I', 'J', 'G', 'D', 'V', 'S', 'L', 'U', 'K',\r
+                        'p', 'n', 'b', 'r', 'q', 'f', 'e', 'a', 'c', 'w', 'm', \r
+                        'o', 'h', 'i', 'j', 'g', 'd', 'v', 's', 'l', 'u', 'k', \r
+                        'x' };\r
 \r
 char PieceToChar(p)\r
      ChessSquare p;\r
@@ -210,7 +209,7 @@ char PieceToChar(p)
     return pieceToChar[(int) p];\r
 }\r
 \r
-int PieceToNumber(p)\r
+int PieceToNumber(p)  /* [HGM] holdings: count piece type, ignoring non-participating piece types */\r
      ChessSquare p;\r
 {\r
     int i=0;\r
@@ -519,8 +518,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
               m++;\r
 \r
             /* Capablanca Archbishop continues as Knight                  */\r
-            case WhiteCardinal:\r
-            case BlackCardinal:\r
+            case WhiteAngel:\r
+            case BlackAngel:\r
               m++;\r
 \r
             /* Shogi Bishops are ordinary Bishops */\r
@@ -570,8 +569,8 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
               break;\r
 \r
             /* Shogi Dragon King has to continue as Ferz after Rook moves */\r
-            case SHOGI WhiteMarshall:\r
-            case SHOGI BlackMarshall:\r
+            case SHOGI WhiteDragon:\r
+            case SHOGI BlackDragon:\r
               m++;\r
 \r
             /* Capablanca Chancellor sets flag to continue as Knight      */\r
@@ -643,7 +642,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                   for (fs = -1; fs <= 1; fs += 2) {\r
                       rt = rf + rs;\r
                       ft = ff + fs;\r
-                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;\r
+                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) continue;\r
                       if (!SameColor(board[rf][ff], board[rt][ft]) &&\r
                           (gameInfo.variant != VariantXiangqi || InPalace(rt, ft) ) )\r
                                callback(board, flags, NormalMove,\r
@@ -669,6 +668,24 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                             rf, ff, rt, ft, closure);\r
                }\r
              break;\r
+\r
+           case WhiteNightrider:\r
+           case BlackNightrider:\r
+             for (i = -1; i <= 1; i += 2)\r
+               for (j = -1; j <= 1; j += 2)\r
+                 for (s = 1; s <= 2; s++) {  int k;\r
+                    for(k=1;; k++) {\r
+                     rt = rf + k*i*s;\r
+                     ft = ff + k*j*(3-s);\r
+                      if (rt < 0 || rt >= BOARD_HEIGHT || ft < BOARD_LEFT || ft >= BOARD_RGHT) break;\r
+                     if (SameColor(board[rf][ff], board[rt][ft])) break;\r
+                     callback(board, flags, NormalMove,\r
+                              rf, ff, rt, ft, closure);\r
+                     if (board[rt][ft] != EmptySquare) break;\r
+                    }\r
+                 }\r
+             break;\r
+\r
          }\r
       }\r
 }\r
@@ -736,8 +753,9 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
      VOIDSTAR closure;\r
 {\r
     GenLegalClosure cl;\r
-    int ff, ft;\r
+    int ff, ft, k, left, right;\r
     int ignoreCheck = (flags & F_IGNORE_CHECK) != 0;\r
+    ChessSquare wKing = WhiteKing, bKing = BlackKing;\r
 \r
     cl.cb = callback;\r
     cl.cl = closure;\r
@@ -747,10 +765,14 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        CheckTest(board, flags, -1, -1, -1, -1, FALSE)) return TRUE;\r
 \r
     /* Generate castling moves */\r
+    if(gameInfo.variant == VariantKnightmate) { /* [HGM] Knightmate */\r
+        wKing = WhiteUnicorn; bKing = BlackUnicorn;\r
+    }\r
+\r
     for (ff = BOARD_WIDTH>>1; ff >= (BOARD_WIDTH-1)>>1; ff-- /*ics wild 1*/) {\r
        if ((flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_WHITE_KCASTLE_OK) &&\r
-            board[0][ff] == WhiteKing &&\r
+            board[0][ff] == wKing &&\r
             board[0][ff + 1] == EmptySquare &&\r
             board[0][ff + 2] == EmptySquare &&\r
             board[0][BOARD_RGHT-3] == EmptySquare &&\r
@@ -769,7 +791,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
        if ((flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_WHITE_QCASTLE_OK) &&\r
-           board[0][ff] == WhiteKing &&\r
+            board[0][ff] == wKing &&\r
            board[0][ff - 1] == EmptySquare &&\r
            board[0][ff - 2] == EmptySquare &&\r
             board[0][BOARD_LEFT+2] == EmptySquare &&\r
@@ -788,7 +810,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
        if (!(flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_BLACK_KCASTLE_OK) &&\r
-           board[BOARD_HEIGHT-1][ff] == BlackKing &&\r
+            board[BOARD_HEIGHT-1][ff] == bKing &&\r
            board[BOARD_HEIGHT-1][ff + 1] == EmptySquare &&\r
            board[BOARD_HEIGHT-1][ff + 2] == EmptySquare &&\r
             board[BOARD_HEIGHT-1][BOARD_RGHT-3] == EmptySquare &&\r
@@ -807,7 +829,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
        if (!(flags & F_WHITE_ON_MOVE) &&\r
            (flags & F_BLACK_QCASTLE_OK) &&\r
-           board[BOARD_HEIGHT-1][ff] == BlackKing &&\r
+            board[BOARD_HEIGHT-1][ff] == bKing &&\r
            board[BOARD_HEIGHT-1][ff - 1] == EmptySquare &&\r
            board[BOARD_HEIGHT-1][ff - 2] == EmptySquare &&\r
             board[BOARD_HEIGHT-1][BOARD_LEFT+2] == EmptySquare &&\r
@@ -818,7 +840,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
            (ignoreCheck ||\r
             (!CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE) &&\r
               !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, BOARD_LEFT+3,      FALSE) &&\r
-             !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE)))) {\r
+              !CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 2, FALSE)))) {\r
 \r
            callback(board, flags,\r
                     ff==BOARD_WIDTH>>1 ? BlackQueenSideCastle : BlackQueenSideCastleWild,\r
@@ -826,41 +848,73 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure)
        }\r
     }\r
 \r
-    /* PUSH Fabien */\r
+  if(gameInfo.variant == VariantFischeRandom) {\r
 \r
     /* generate all potential FRC castling moves (KxR), ignoring flags */\r
-    /* [HGM] Tord! Help requested! */\r
-\r
-    if ((flags & F_WHITE_ON_MOVE) != 0) {\r
+    /* [HGM] test if the Rooks we find have castling rights */\r
 \r
-       for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) {\r
-          if (board[0][ff] == WhiteKing) {\r
-             for (ft = BOARD_LEFT+0; ft < BOARD_RGHT; ft++) {\r
-                if (board[0][ft] == WhiteRook) {\r
-                   callback(board, flags, \r
-                            (ft > ff) ? WhiteHSideCastleFR : WhiteASideCastleFR,\r
-                            0, ff, 0, ft, closure);\r
-                }\r
-             }\r
-          }\r
-       }\r
 \r
+    if ((flags & F_WHITE_ON_MOVE) != 0) {\r
+        ff = castlingRights[2]; /* King file if we have any rights */\r
+        if(ff > 0) {\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "FRC castling, %d %d %d %d %d %d\n",\r
+                castlingRights[0],castlingRights[1],ff,castlingRights[3],castlingRights[4],castlingRights[5]);\r
+    }\r
+            ft = castlingRights[0]; /* Rook file if we have H-side rights */\r
+            left  = ff+1;\r
+            right = BOARD_RGHT-2;\r
+            if(ff == BOARD_RGHT-2) left = right = ff-1;    /* special case */\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[0][k] != EmptySquare) ft = -1;\r
+            for(k=left; k<right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = -1;\r
+            if(ft >= 0)\r
+                callback(board, flags, WhiteHSideCastleFR, 0, ff, 0, ft, closure);\r
+\r
+            ft = castlingRights[1]; /* Rook file if we have A-side rights */\r
+            left  = BOARD_LEFT+2;\r
+            right = ff-1;\r
+            if(ff <= BOARD_LEFT+2) { left = ff+1; right = BOARD_LEFT+3; }\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[0][k] != EmptySquare) ft = -1;\r
+            if(ff > BOARD_LEFT+2) \r
+            for(k=left+1; k<=right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = -1;\r
+\r
+            if(ft >= 0)\r
+                callback(board, flags, WhiteASideCastleFR, 0, ff, 0, ft, closure);\r
+        }\r
     } else {\r
-\r
-       for (ff = BOARD_LEFT+1; ff < BOARD_RGHT-1; ff++) {\r
-          if (board[BOARD_HEIGHT-1][ff] == BlackKing) {\r
-             for (ft = BOARD_LEFT+0; ft < BOARD_RGHT; ft++) {\r
-                if (board[BOARD_HEIGHT-1][ft] == BlackRook) {\r
-                   callback(board, flags, \r
-                            (ft > ff) ? BlackHSideCastleFR : BlackASideCastleFR,\r
-                            BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);\r
-                }\r
-             }\r
-          }\r
-       }\r
+        ff = castlingRights[5]; /* King file if we have any rights */\r
+        if(ff > 0) {\r
+            ft = castlingRights[3]; /* Rook file if we have H-side rights */\r
+            left  = ff+1;\r
+            right = BOARD_RGHT-2;\r
+            if(ff == BOARD_RGHT-2) left = right = ff-1;    /* special case */\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = -1;\r
+            for(k=left; k<right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = -1;\r
+            if(ft >= 0)\r
+                callback(board, flags, BlackHSideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);\r
+\r
+            ft = castlingRights[4]; /* Rook file if we have A-side rights */\r
+            left  = BOARD_LEFT+2;\r
+            right = ff-1;\r
+            if(ff <= BOARD_LEFT+2) { left = ff+1; right = BOARD_LEFT+3; }\r
+            for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */\r
+                if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = -1;\r
+            if(ff > BOARD_LEFT+2) \r
+            for(k=left+1; k<=right && ft >= 0; k++) /* then if not checked */\r
+                if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = -1;\r
+\r
+            if(ft >= 0)\r
+                callback(board, flags, BlackASideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure);\r
+        }\r
     }\r
 \r
-    /* POP Fabien */\r
+  }\r
 \r
     return FALSE;\r
 }\r
@@ -976,9 +1030,9 @@ void LegalityTestCallback(board, flags, kind, rf, ff, rt, ft, closure)
 {\r
     register LegalityTestClosure *cl = (LegalityTestClosure *) closure;\r
 \r
-    if (appData.debugMode) {\r
-        fprintf(debugFP, "Legality test: %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);\r
-    }\r
+//    if (appData.debugMode) {\r
+//        fprintf(debugFP, "Legality test: %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);\r
+//    }\r
     if (rf == cl->rf && ff == cl->ff && rt == cl->rt && ft == cl->ft)\r
       cl->kind = kind;\r
 }\r
@@ -989,8 +1043,20 @@ ChessMove LegalityTest(board, flags, epfile, castlingRights, rf, ff, rt, ft, pro
      int rf, ff, rt, ft, promoChar;\r
      char castlingRights[];\r
 {\r
-    LegalityTestClosure cl;\r
+    LegalityTestClosure cl; ChessSquare piece = board[rf][ff];\r
     \r
+    if (appData.debugMode) {\r
+        int i;\r
+        for(i=0; i<6; i++) fprintf(debugFP, "%d ", castlingRights[i]);\r
+        fprintf(debugFP, "Legality test? %c%c%c%c\n", ff+AAA, rf+ONE, ft+AAA, rt+ONE);\r
+    }\r
+    /* [HGM] Lance, Cobra and Falcon are wildcard pieces; consider all their moves legal */\r
+    /* (perhaps we should disallow moves that obviously leave us in check?)              */\r
+    if(piece == WhiteFalcon || piece == BlackFalcon ||\r
+       piece == WhiteCobra  || piece == BlackCobra  ||\r
+       piece == WhiteLance  || piece == BlackLance)\r
+        return NormalMove;\r
+\r
     cl.rf = rf;\r
     cl.ff = ff;\r
     cl.rt = rt;\r
@@ -1139,25 +1205,31 @@ void Disambiguate(board, flags, epfile, closure)
 \r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate in:  %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                             closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                             closure->promoCharIn,closure->promoCharIn);\r
     }\r
     if(gameInfo.variant == VariantShogi) {\r
         /* [HGM] Shogi promotions. '=' means defer */\r
         if(closure->rfIn != DROP_RANK && closure->kind == NormalMove) {\r
             ChessSquare piece = closure->piece;\r
-\r
+#if 0\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate A:   %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                          closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                          closure->promoCharIn,closure->promoCharIn);\r
     }\r
+#endif\r
             if(c != NULLCHAR && c != 'x' && c != '+' && c != '=' &&\r
                ToUpper(PieceToChar(PROMOTED piece)) != ToUpper(c) ) \r
                     closure->kind = IllegalMove;\r
             else if(flags & F_WHITE_ON_MOVE) {\r
+#if 0\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate B:   %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                          closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                          closure->promoCharIn,closure->promoCharIn);\r
     }\r
+#endif\r
                 if( (int) piece < (int) WhiteWazir &&\r
                      (closure->rf > BOARD_HEIGHT-4 || closure->rt > BOARD_HEIGHT-4) ) {\r
                     if( (piece == WhitePawn || piece == WhiteQueen) && closure->rt > BOARD_HEIGHT-2 ||\r
@@ -1191,10 +1263,13 @@ void Disambiguate(board, flags, epfile, closure)
            closure->kind = IllegalMove;\r
        }\r
     }\r
+#if 0\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate C:   %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
-        closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,closure->promoCharIn,closure->promoCharIn);\r
+                          closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,\r
+                          closure->promoCharIn,closure->promoCharIn);\r
     }\r
+#endif\r
     /* [HGM] returns 'q' for optional promotion, 'n' for mandatory */\r
     if(closure->promoCharIn != '=')\r
         closure->promoChar = ToLower(PieceToChar(PromoPiece(closure->kind)));\r
@@ -1299,7 +1374,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
     if(PieceToChar(piece)=='~') piece = (ChessSquare)(DEMOTED piece);\r
 \r
   if (appData.debugMode)\r
-          fprintf(debugFP, "CoordsToAlgebraic, piece=%d\n", (int)piece);\r
+          fprintf(debugFP, "CoordsToAlgebraic, piece=%d (%d,%d)-(%d,%d) %c\n", (int)piece,ff,rf,ft,rt,promoChar );\r
     switch (piece) {\r
       case WhitePawn:\r
       case BlackPawn:\r
@@ -1330,6 +1405,8 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
        }\r
        /* Use promotion suffix style "=Q" */\r
        *outp = NULLCHAR;\r
+  if (appData.debugMode)\r
+          fprintf(debugFP, "movetype=%d, promochar=%d=%c\n", (int)kind, promoChar, promoChar);\r
         if (promoChar != NULLCHAR) {\r
             if(gameInfo.variant == VariantShogi) {\r
                 /* [HGM] ... but not in Shogi! */\r
@@ -1470,8 +1547,12 @@ ChessMove CoordsToAlgebraic(board, flags, epfile,
         return cl.kind;\r
        \r
       /* [HGM] Always long notation for fairies we don't know */\r
-      case WhiteNightrider:\r
-      case BlackNightrider:\r
+      case WhiteFalcon:\r
+      case BlackFalcon:\r
+      case WhiteSilver:\r
+      case BlackSilver:\r
+      case WhiteLance:\r
+      case BlackLance:\r
       case WhiteGrasshopper:\r
       case BlackGrasshopper:\r
       case EmptySquare:\r
diff --git a/moves.h b/moves.h
index cc70260..f50ea08 100644 (file)
--- a/moves.h
+++ b/moves.h
@@ -73,6 +73,7 @@ typedef void (*MoveCallback) P((Board board, int flags, ChessMove kind,
 #define F_ATOMIC_CAPTURE 128    /* capturing piece explodes, destroying itself\r
                                   and all non-pawns on adjacent squares; \r
                                   destroying your own king is illegal */\r
+#define F_FRC_TYPE_CASTLING 256 /* generate castlings as captures of own Rook */\r
 \r
 /* Special epfile values. [HGM] positive values are non-reversible moves! */\r
 #define EP_NONE (-4)           /* [HGM] Tricky! order matters:            */\r
index 49ebb34..58282bd 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -9,8 +9,7 @@
 #define YY_FLEX_MINOR_VERSION 5
 
 #include <stdio.h>
-// #include <unistd.h>
-
+#include <errno.h>
 
 /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
 #ifdef c_plusplus
@@ -23,6 +22,9 @@
 #ifdef __cplusplus
 
 #include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
 
 /* Use prototypes in function declarations. */
 #define YY_USE_PROTOS
@@ -62,6 +64,7 @@
 #define YY_PROTO(proto) ()
 #endif
 
+
 /* Returned upon end-of-file. */
 #define YY_NULL 0
 
@@ -286,7 +289,7 @@ static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
 
 #define YY_NUM_RULES 42
 #define YY_END_OF_BUFFER 43
-static yyconst short int yy_acclist[661] =
+static yyconst short int yy_acclist[650] =
     {   0,
        43,   41,   42,   41,   42,   41,   42,   40,   41,   42,
        41,   42,   25,   41,   42,   41,   42,   40,   41,   42,
@@ -294,155 +297,152 @@ static yyconst short int yy_acclist[661] =
        40,   41,   42,   40,   41,   42,   40,   41,   42,   40,
        41,   42,   40,   41,   42,   40,   41,   42,   40,   41,
        42,   40,   41,   42,   40,   41,   42,   40,   41,   42,
-       40,   41,   42,   40,   41,   42,   40,   41,   42,   41,
+       40,   41,   42,   41,   42,   40,   41,   42,   40,   41,
        42,   40,   41,   42,   40,   41,   42,   40,   41,   42,
        40,   41,   42,   40,   41,   42,   40,   41,   42,   40,
-       41,   42,   40,   41,   42,   40,   41,   42,   41,   42,
+       41,   42,   40,   41,   42,   40,   41,   42,   40,   41,
 
+       42,   40,   41,   42,   40,   41,   42,   40,   41,   42,
+       40,   41,   42,   40,   41,   42,   41,   42,   41,   42,
+       40,   41,   42,   40,   41,   42,   40,   41,   42,16410,
+       40,   41,   42,16410,   41,   42,   40,   41,   42,   40,
        41,   42,   40,   41,   42,   40,   41,   42,   40,   41,
-       42,16410,   40,   41,   42,16410,   41,   42,   40,   41,
        42,   40,   41,   42,   40,   41,   42,   40,   41,   42,
        40,   41,   42,   40,   41,   42,   40,   41,   42,   40,
        41,   42,   40,   41,   42,   40,   41,   42,   40,   41,
        42,   40,   41,   42,   40,   41,   42,   40,   41,   42,
        40,   41,   42,   40,   41,   42,   40,   41,   42,   40,
-       41,   42,   40,   41,   42,   40,   41,   42,   40,   41,
-       42,   40,   41,   42,   41,   42,   33,   40,   17,   40,
-        9,   40,   40,   40,16410, 8218,   40,   35,   40,   40,
 
+       41,   42,   40,   41,   42,   40,   41,   42,   40,   41,
+       42,   40,   41,   42,   40,   41,   42,   40,   41,   42,
+       41,   42,   33,   40,   17,   40,    9,   40,   40,   40,
+    16410, 8218,   40,   35,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,    9,   40,   40,   40,   40,
+       40,   40,   36,   40,    3,   40,   40,    4,   40,   40,
+       40,   40,   40,   40,    9,   40,   40,   40,   34,   40,
+       40,    9,   40,   40,   40,16410, 8218,   40,   40,   40,
        40,   40,   40,   40,   40,   40,   40,   40,   40,    9,
-       40,   40,   40,   40,   40,   40,   36,   40,    3,   40,
-       40,   40,    4,   40,   40,    3,   40,   40,    4,   40,
-       40,   40,   40,    9,   40,   34,   40,   40,    9,   40,
-       40,   40,16410, 8218,   40,   40,   40,   40,   40,   40,
-       40,   40,   40,   40,   40,   40,    9,   40,   40,   40,
-       40,   40,   40,   40,    3,   40,   40,   40,    4,   40,
-       40,    3,   40,   40,    4,   40,   40,   40,   40,    9,
+       40,   40,   40,   40,   40,   40,   40,    3,   40,   40,
+
+        4,   40,   40,   40,   40,   40,   40,    9,   40,   40,
        40,   15,    9,   40,   23,   40,   23,    8,   40, 8218,
        22,   40,   22,   24,   40,   40,   40,    6,   40,   40,
-
        40,   40,   40,   40,   40,    9,   40,   40,   40,   40,
-       40,   20,   40,    4,   40,   40,    3,   40,   40,    3,
-       40,    4,    5,   40,    4,   40,   40,    4,   40,   40,
-       40,    3,   40,    4,    4,   40,    5,    6,   40,    4,
-       40,   40,    9,   40,   34,   39,    9,   40,   23,   40,
-        8,   40,   22,   40,   35,   40,   40,   40,    6,   40,
-       40,   40,   40,   40,   40,   40,    9,   40,   40,   40,
-       40,   40,   20,   40,    4,   40,   40,    3,   40,   40,
-        3,   40,    5,   40,    4,   40,   40,    4,   40,   40,
-       40,    3,   40,    4,   40,    5,    6,   40,    4,   40,
-
-       40,    9,   40,   38,   38,   37,   25,   25,   40,    6,
-       40,    7,   40,    6,   10,   40,   40,   40,   40,   19,
-       40,   40,   21,   40,   16,   40,   40,   40,   40,   40,
-       20,   20,   40,   20,   40,   36,    3,    3,    2,   40,
-        5,    4,    5,   40,   40,    4,    4,   40,    2,    7,
-       40,    5,    6,    5,    6,   40,    5,   40,   40,   40,
-       25,   39,   40,    6,   40,    7,   40,   40,   40,   40,
-       40,   19,   40,   40,   21,   40,   16,   40,   40,   40,
-       40,   40,   20,   40,   20,   20,   40,    2,   40,    5,
-       40,   40,    4,   40,    2,    7,   40,    5,    6,   40,
-
-        5,   40,   40,   40,    7,    1,   40,   40,   40,   19,
-       40,   40,   40,   21,   21,   40,   21,   40,   40,   40,
-       40,   30,   36,    2,    2,   40,    5,    4,    5,    5,
-       40,    2,    7,   39,    1,   40,   40,   40,   19,   40,
-       40,   40,   21,   40,   21,   21,   40,   40,   40,   40,
-       20,   39,    2,   40,    5,   40,   27,   38,   23,   23,
-       22,   22,   24,   24,   20,   21,    1,    1,   40,   40,
+       20,   40,    4,   40,   40,    3,    3,   40,    3,   40,
+       40,    4,    5,   40,    4,    4,   40,   40,   40,   40,
+        9,   40,   40,   34,   39,    9,   40,   23,   40,    8,
+       40,   22,   40,   35,   40,   40,   40,    6,   40,   40,
+       40,   40,   40,   40,   40,    9,   40,   40,   40,   40,
+       20,   40,    4,   40,   40,    3,   40,    3,   40,   40,
+
+        5,   40,    4,   40,   40,   40,   40,    9,   40,   40,
+       38,   38,   37,   25,   25,    6,   40,   10,    6,   40,
+        7,   40,    6,   40,    6,   40,   40,   40,   19,   40,
+       40,   21,   40,   16,   40,   40,   40,   40,   40,   20,
+       20,   40,   20,   40,   36,    3,    3,    2,   40,    5,
+        4,    5,    5,   40,   40,    4,    4,   40,   40,   25,
+       39,   40,    6,   40,    7,   40,   40,   40,   40,   40,
+       19,   40,   40,   21,   40,   16,   40,   40,   40,   40,
+       40,   20,   40,   20,   20,   40,    2,   40,    5,   40,
+       40,    4,   40,   40,    7,    7,    1,   40,   40,   40,
+
+       19,   40,   40,   40,   21,   21,   40,   21,   40,   40,
+       40,   40,   30,   36,    2,    2,    2,   40,    5,    5,
+        5,   40,   39,    1,   40,   40,   40,   19,   40,   40,
+       40,   21,   40,   21,   21,   40,   40,   40,   40,   20,
+       39,    2,   40,    5,   40,   27,   38,    1,   23,   23,
+       22,   22,   24,   24,    1,    1,   40,   20,   21,   40,
        40,   40,   11,   40,   40,   28,   36,   30,    2,    2,
-        5,   27,   34,   39,   39,    1,   40,   40,   40,   40,
-       21,   39,   11,   40,   40,   20,   39,   18,   24,   20,
-
-       21,    1,    1,   19,   40,   40,   40,   11,   40,   40,
-       40,   40,   21,   39,   40,   11,   40,   40,   12,   40,
-       40,   40,   40,   12,   40,   40,   14,   40,   40,   40,
-       14,   40,   40,   40,   39,   40,   40,   40,   40,   39,
-       39,   40,   40,   31,   40,   39,   39,   31,   40,   13,
-       31,   32,   32,   35,   39,   39,   31,   39,   34,   29
+       27,   34,   39,   39,    1,   40,   40,   40,   40,   21,
+       39,   11,   40,   40,   20,   39,   18,    1,   24,    1,
+       20,   21,   19,   40,   40,   40,   11,   40,   40,   40,
+
+       40,   21,   39,   40,   11,   40,   40,   12,   40,   40,
+       40,   40,   12,   40,   40,   14,   40,   40,   40,   14,
+       40,   40,   40,   39,   40,   40,   40,   40,   39,   39,
+       40,   40,   31,   40,   39,   39,   31,   40,   13,   31,
+       32,   32,   35,   39,   39,   31,   39,   34,   29
     } ;
 
-static yyconst short int yy_accept[712] =
+static yyconst short int yy_accept[698] =
     {   0,
         1,    1,    1,    2,    4,    6,    8,   11,   13,   16,
        18,   21,   25,   29,   31,   34,   37,   40,   43,   46,
-       49,   52,   55,   58,   61,   64,   67,   70,   72,   75,
-       78,   81,   84,   87,   90,   93,   96,   99,  101,  103,
-      106,  109,  113,  117,  119,  122,  125,  128,  131,  134,
+       49,   52,   55,   58,   61,   64,   66,   69,   72,   75,
+       78,   81,   84,   87,   90,   93,   96,   99,  102,  105,
+      108,  111,  114,  117,  119,  121,  124,  127,  131,  135,
       137,  140,  143,  146,  149,  152,  155,  158,  161,  164,
-      167,  170,  173,  176,  179,  182,  185,  187,  187,  188,
-      189,  189,  189,  189,  189,  190,  190,  190,  191,  191,
-      193,  193,  193,  193,  194,  194,  194,  196,  196,  198,
-      198,  199,  199,  200,  200,  201,  201,  201,  202,  203,
-
-      204,  205,  206,  207,  208,  209,  210,  212,  213,  214,
-      215,  216,  217,  217,  217,  217,  217,  218,  219,  221,
-      221,  222,  223,  225,  226,  228,  228,  229,  231,  232,
-      233,  234,  236,  236,  236,  236,  237,  237,  238,  238,
-      239,  241,  241,  242,  244,  244,  246,  246,  247,  248,
-      248,  249,  250,  251,  252,  253,  254,  255,  256,  257,
-      259,  260,  261,  262,  263,  264,  265,  267,  267,  268,
-      269,  271,  272,  274,  274,  275,  277,  278,  279,  280,
-      282,  282,  282,  282,  282,  282,  282,  282,  282,  282,
-      282,  282,  283,  283,  283,  283,  285,  287,  288,  290,
-
-      291,  291,  291,  291,  293,  294,  295,  295,  295,  295,
-      295,  296,  296,  297,  297,  298,  298,  298,  300,  301,
-      302,  303,  304,  305,  306,  308,  309,  310,  311,  312,
-      314,  314,  314,  314,  314,  316,  316,  317,  317,  317,
-      319,  320,  322,  323,  325,  325,  325,  327,  328,  330,
-      331,  331,  332,  334,  335,  337,  340,  342,  343,  345,
-      346,  346,  346,  346,  346,  347,  349,  351,  353,  355,
-      355,  356,  356,  357,  358,  358,  359,  361,  362,  363,
-      364,  365,  366,  367,  369,  370,  371,  372,  373,  375,
-      377,  378,  378,  380,  381,  383,  385,  387,  388,  390,
-
-      391,  391,  392,  394,  396,  399,  401,  402,  404,  404,
-      404,  405,  406,  406,  406,  407,  407,  407,  408,  408,
-      409,  409,  409,  409,  410,  410,  410,  410,  410,  410,
-      410,  410,  410,  410,  410,  410,  412,  412,  412,  414,
-      415,  416,  417,  417,  418,  419,  420,  422,  422,  423,
-      425,  427,  428,  429,  430,  431,  432,  434,  436,  436,
-      436,  436,  436,  437,  438,  438,  439,  441,  442,  443,
-      443,  443,  443,  445,  446,  447,  447,  449,  449,  452,
-      454,  457,  459,  460,  461,  461,  462,  462,  462,  462,
-      462,  463,  463,  464,  464,  464,  466,  468,  469,  469,
-
-      470,  471,  472,  474,  475,  477,  479,  480,  481,  482,
-      483,  485,  486,  488,  490,  492,  493,  495,  498,  501,
-      503,  504,  505,  505,  505,  505,  505,  505,  505,  505,
-      505,  505,  505,  505,  505,  505,  505,  505,  505,  505,
-      506,  508,  509,  510,  510,  512,  512,  513,  514,  515,
-      517,  519,  520,  521,  522,  522,  522,  524,  524,  524,
-      525,  525,  525,  527,  528,  528,  529,  530,  530,  532,
-      532,  534,  534,  534,  534,  534,  534,  534,  535,  535,
-      535,  537,  538,  539,  541,  542,  543,  545,  546,  548,
-      549,  550,  551,  553,  555,  557,  557,  557,  559,  559,
-
-      559,  560,  560,  561,  561,  562,  562,  563,  563,  564,
-      564,  565,  565,  565,  565,  565,  567,  567,  568,  568,
-      568,  570,  571,  571,  571,  571,  571,  571,  572,  573,
-      575,  576,  578,  578,  579,  580,  581,  582,  582,  582,
-      584,  584,  584,  585,  586,  586,  586,  588,  589,  590,
-      591,  593,  595,  596,  598,  598,  599,  599,  599,  599,
-      600,  600,  600,  600,  602,  602,  603,  604,  604,  605,
-      605,  605,  605,  605,  606,  607,  608,  610,  611,  611,
-      611,  611,  611,  611,  612,  613,  615,  616,  618,  619,
-      619,  619,  619,  619,  619,  619,  620,  620,  620,  620,
-
-      620,  621,  622,  622,  622,  622,  622,  623,  624,  624,
-      624,  624,  624,  625,  625,  625,  625,  626,  627,  629,
-      629,  629,  629,  629,  630,  630,  631,  633,  633,  633,
-      633,  633,  634,  635,  635,  635,  635,  635,  636,  637,
-      638,  638,  638,  638,  638,  638,  639,  640,  640,  640,
-      640,  640,  641,  642,  643,  644,  644,  644,  644,  644,
-      644,  646,  646,  646,  646,  646,  647,  648,  650,  650,
-      650,  651,  651,  652,  652,  653,  653,  653,  655,  655,
-      656,  657,  657,  657,  657,  657,  659,  659,  659,  659,
-      659,  659,  659,  659,  659,  659,  659,  659,  659,  659,
-
-      659,  659,  659,  659,  659,  659,  659,  659,  660,  661,
-      661
+      167,  170,  173,  176,  179,  182,  185,  188,  191,  194,
+      197,  200,  203,  206,  209,  212,  215,  218,  221,  223,
+      223,  224,  225,  225,  225,  225,  225,  226,  226,  226,
+      226,  227,  227,  229,  229,  229,  229,  230,  230,  230,
+
+      232,  232,  234,  234,  235,  235,  236,  236,  237,  237,
+      238,  238,  239,  240,  241,  242,  243,  244,  245,  246,
+      248,  249,  250,  251,  252,  253,  253,  253,  253,  253,
+      254,  255,  257,  257,  258,  260,  261,  262,  263,  264,
+      265,  267,  268,  269,  269,  269,  269,  270,  270,  271,
+      271,  272,  274,  274,  275,  277,  277,  279,  279,  280,
+      281,  281,  282,  283,  284,  285,  286,  287,  288,  289,
+      290,  292,  293,  294,  295,  296,  297,  298,  300,  300,
+      301,  303,  304,  305,  306,  307,  308,  310,  311,  312,
+      312,  312,  312,  312,  312,  312,  312,  312,  312,  312,
+
+      312,  313,  313,  313,  313,  313,  313,  315,  317,  318,
+      320,  321,  321,  321,  321,  323,  324,  325,  325,  326,
+      326,  327,  327,  328,  328,  330,  330,  330,  330,  330,
+      331,  332,  333,  334,  335,  336,  338,  339,  340,  341,
+      343,  343,  343,  343,  343,  345,  345,  346,  346,  347,
+      349,  351,  352,  353,  353,  355,  356,  358,  359,  360,
+      361,  363,  364,  365,  365,  365,  365,  365,  366,  368,
+      370,  372,  374,  374,  375,  375,  376,  377,  377,  378,
+      380,  381,  382,  383,  384,  385,  386,  388,  389,  390,
+      391,  393,  395,  396,  396,  398,  400,  401,  403,  405,
+
+      406,  407,  408,  410,  411,  411,  411,  412,  413,  413,
+      413,  414,  414,  414,  415,  415,  416,  416,  417,  417,
+      417,  417,  418,  418,  418,  418,  418,  418,  418,  418,
+      419,  421,  421,  423,  424,  425,  425,  426,  427,  427,
+      427,  427,  427,  428,  429,  431,  431,  432,  434,  436,
+      437,  438,  439,  440,  441,  443,  445,  445,  445,  445,
+      445,  446,  447,  447,  448,  450,  451,  452,  452,  452,
+      453,  455,  456,  457,  457,  459,  460,  460,  461,  461,
+      461,  461,  461,  462,  462,  463,  463,  463,  465,  467,
+      468,  468,  469,  470,  471,  473,  474,  476,  478,  479,
+
+      480,  481,  482,  484,  485,  487,  489,  491,  492,  494,
+      495,  495,  495,  495,  495,  496,  496,  496,  496,  496,
+      496,  496,  496,  496,  496,  497,  499,  499,  499,  499,
+      499,  500,  501,  501,  503,  503,  504,  505,  506,  508,
+      510,  511,  512,  513,  513,  513,  515,  515,  515,  516,
+      516,  517,  519,  520,  520,  521,  521,  523,  523,  523,
+      523,  523,  523,  523,  523,  524,  524,  524,  526,  527,
+      528,  530,  531,  532,  534,  535,  537,  538,  539,  540,
+      542,  544,  546,  546,  546,  548,  548,  549,  549,  550,
+      550,  551,  551,  552,  552,  553,  553,  554,  554,  555,
+
+      555,  555,  555,  556,  558,  558,  558,  560,  560,  561,
+      561,  561,  561,  561,  561,  562,  563,  565,  566,  568,
+      568,  569,  570,  571,  571,  571,  573,  573,  573,  574,
+      575,  575,  575,  577,  578,  579,  580,  582,  584,  585,
+      587,  587,  588,  588,  588,  589,  589,  590,  591,  591,
+      591,  591,  593,  593,  593,  594,  594,  594,  594,  594,
+      595,  596,  597,  599,  600,  600,  600,  600,  600,  600,
+      601,  602,  604,  605,  607,  608,  608,  608,  608,  608,
+      608,  608,  609,  609,  609,  609,  609,  610,  611,  611,
+      611,  611,  611,  612,  613,  613,  613,  613,  613,  614,
+
+      614,  614,  614,  615,  616,  618,  618,  618,  618,  618,
+      619,  619,  620,  622,  622,  622,  622,  622,  623,  624,
+      624,  624,  624,  624,  625,  626,  627,  627,  627,  627,
+      627,  627,  628,  629,  629,  629,  629,  629,  630,  631,
+      632,  633,  633,  633,  633,  633,  633,  635,  635,  635,
+      635,  635,  636,  637,  639,  639,  639,  640,  640,  641,
+      641,  642,  642,  642,  644,  644,  645,  646,  646,  646,
+      646,  646,  648,  648,  648,  648,  648,  648,  648,  648,
+      648,  648,  648,  648,  648,  648,  648,  648,  648,  648,
+      648,  648,  648,  648,  649,  650,  650
+
     } ;
 
 static yyconst int yy_ec[256] =
@@ -452,15 +452,15 @@ static yyconst int yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    4,    1,    5,    6,    7,    8,    1,    9,   10,
        11,   12,   13,    1,   14,   15,   16,   17,   18,   19,
-       20,   20,   20,   20,   20,   20,   21,   22,   23,    1,
-       24,    1,    1,   25,   26,   27,   28,   29,   30,   31,
-       32,   33,   34,   34,   35,   36,   37,   38,   39,   40,
-       41,   42,   43,   34,   44,   34,   45,   46,   34,   34,
-       47,    1,   48,    1,   49,    1,   50,   51,   52,   53,
-
-       54,   55,   56,   57,   58,   34,   59,   60,   61,   62,
-       63,   64,   41,   65,   66,   67,   68,   34,   69,   46,
-       70,   34,   71,    1,   72,    1,    1,    1,    1,    1,
+       20,   20,   20,   20,   20,   20,   20,   21,   22,    1,
+       23,    1,    1,   24,   25,   26,   27,   28,   29,   30,
+       31,   32,   33,   33,   34,   35,   36,   37,   38,   34,
+       34,   39,   40,   33,   41,   33,   42,   43,   33,   33,
+       44,    1,   45,    1,   46,    1,   47,   48,   49,   50,
+
+       51,   52,   53,   54,   55,   56,   57,   58,   59,   60,
+       61,   62,   63,   64,   65,   66,   67,   68,   69,   70,
+       71,   68,   72,    1,   73,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -477,694 +477,707 @@ static yyconst int yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst int yy_meta[73] =
+static yyconst int yy_meta[74] =
     {   0,
         1,    2,    3,    2,    1,    1,    1,    1,    4,    5,
-        6,    1,    1,    7,    1,    1,    4,    8,    8,    8,
-        4,    9,    1,   10,    1,    4,   11,    4,    4,    4,
-        4,    4,    4,    4,   11,    4,    4,   11,   12,   12,
-       11,   11,    4,    4,    4,    7,    1,    1,    1,   13,
-       14,   13,   13,   15,   13,   13,   13,    4,   11,    4,
-        4,   11,   12,   12,   11,    4,    4,    4,    4,    4,
-        1,    1
+        6,    1,    7,    8,    1,    1,    9,    9,    9,    9,
+       10,    1,   11,    1,   12,   12,   12,   12,   12,   12,
+       12,   12,   13,   12,   13,   13,   12,   12,   12,   13,
+       13,   12,   14,    1,    1,    1,   15,   15,   15,   15,
+       16,   15,   15,   15,   15,   15,   15,   15,   17,   18,
+       18,   18,   18,   18,   17,   17,   17,   17,   17,   19,
+       17,    1,    1
     } ;
 
-static yyconst short int yy_base[787] =
+static yyconst short int yy_base[784] =
     {   0,
-        0,   72, 2588, 4394,  119,  129,    0,  141, 2583,  139,
-      150,  171,  238, 2583,  257, 2527, 2518,  117,  159, 2518,
-     2530,  190,  142,  233,  191, 2512,  239,  317,  376,  420,
-      125,  205,  193,  114,  243,  120,  204,  331, 2574,  174,
-      353,  476,  258,  260,  543,  244,  282,  346,  311,  334,
-      256,  312,  365,  595,  331,  351,  354,  644,  688,  242,
-      348,  327,  365,  386,  303,  392,  552, 2521,  432,    0,
-     2566,  258,  557,  282, 4394, 2562,  393,  320, 2556, 2554,
-     2552,  342,  442, 2551,  457,  364,  605, 2550,    0, 2562,
-     4394,  576,  530,  617,  732,  625,  661,  449, 2514, 2509,
-
-     2512, 2517, 2492, 2493, 2490, 2517, 2515,  463,  572, 2503,
-     2494, 2489, 2502,  789,  372,  861, 4394,  669,  924,  705,
-      713,  468,  980,  765, 1032,  773,  789, 1076,  481,  637,
-     2486, 2485,  390, 2475,  830, 2542, 2541,  383, 2540,  617,
-      593,  546,  858,  874,  406,  579,  432,  865, 1120, 1005,
-      505,  683,  726,  727,  621,  872,  870,  876,  603,  873,
-      905,  665,  891,  884,  882,  973, 1168, 1013, 1049,  936,
-     1225, 1057, 1277, 1093, 1101, 1321,  641,  983,  928,  930,
-      896, 2478,  538,  543,  612, 2531,  622, 1030, 1221, 2528,
-     2466, 4394, 2532, 2531, 2529, 2518, 2527, 2526,    0, 4394,
-
-     2525, 2524, 2523, 2521, 2520,  443, 2465, 2459, 2471, 2466,
-      668,  709,  594, 1218,  732,  753,  756, 1365, 2467, 2466,
-     2446,  803,  906, 2460, 2498,    0, 2453, 2449, 2441, 1422,
-      689, 1069,  172, 1494,  790, 1251, 1294, 1302, 1415, 2496,
-      838,  976, 1288, 1557, 1413, 1449,  678,  629,  910, 1338,
-     1346,  992, 1105, 1502, 1057, 1609, 1182, 1100, 2492, 4394,
-     1510,  996, 2501,  191, 2501, 1172,  960,  962, 1158,  831,
-     2499, 1132, 1237,  889, 1482, 1300, 1653, 1176, 1228, 1010,
-     1273, 1315, 1175, 1190,    0, 1204, 1531, 1071, 1710, 1774,
-     1550, 1582, 1242, 1443, 1551, 1830, 1272, 1239, 1121, 1493,
-
-     1590, 1606, 1659, 1141, 1882, 1673, 1721, 1427, 1504, 2447,
-     4394,  843, 1025, 2489, 4394, 1727, 2487, 2485, 2423, 2422,
-     2475, 2474, 2473, 2473, 1010, 2472,  539, 2471, 1290, 1541,
-      610, 2421, 2421, 2414, 2414,    0,  939, 1197,    0, 4394,
-     4394, 1699, 1710, 1344, 2420, 2419,  885,  879, 1130, 1939,
-        0, 2438, 2420, 2421, 2420,    0, 2011, 2083,  733,  949,
-     1131, 1410, 2468, 2461, 1365, 4394, 2146, 1356, 1154,  689,
-     1752, 1796, 1157,  715, 2417, 2406,    0, 1386,    0, 1564,
-     2202, 1802, 1633, 2406, 1857, 2464, 1571, 1672, 2417, 2403,
-     2462, 1187, 1451, 1003,  894, 1295, 1470, 1718, 1855, 1823,
-
-     1555, 1665, 1782, 1796, 2267, 1574, 1588, 1826, 1647, 1674,
-     2339, 2460, 2411, 2475, 1840, 1858, 1608,    0, 2531, 1905,
-     1956, 1857, 1728, 2409, 2451, 1639, 2450, 2385, 2445, 2383,
-     2443, 2381, 2434, 1281, 2399, 2395, 2395, 2390, 1389, 4394,
-     2587, 2443, 1146, 1916, 2442, 1281, 2415, 2390,    0, 2652,
-     2724, 2378, 2378, 2428, 1322, 1883, 4394, 2426, 1966, 1457,
-     2002, 2076, 2419, 1428,  952, 4394, 2375, 2364,    0, 2410,
-     1544, 1774, 2396, 1877, 2392, 2347, 2341, 1521, 1030, 1255,
-     2787, 1676, 1881, 1788, 1891, 1861, 2852, 2402, 2924, 1963,
-     1841, 1944, 2402, 1691, 1649, 1816, 1235, 4394, 1979, 2393,
-
-     2392, 2330, 2329, 2389, 2388, 2326, 2325, 2385, 2381, 2319,
-     2318, 2366, 2362, 2315, 2323, 1377, 2320, 1778, 2004, 2102,
-     2355, 2310, 2348, 2304, 2287, 2326, 2288, 2289, 2264, 1524,
-     2279, 4394, 1980, 4394, 2317, 4394, 4394, 2312, 2053, 2319,
-     2268, 2261, 2315, 1999, 1555,  548, 1908, 1982, 1951, 1786,
-     2301, 2043, 2029, 2297, 2054, 4394, 2243, 2158, 2289, 2284,
-     2219, 2205, 2209, 4394, 2198, 2239, 4394, 2235, 2228, 2174,
-     2228, 2182, 2157, 2174, 2105, 2086,    0, 2061, 2130, 2120,
-     2054, 1040,  358, 2032, 2091, 2073, 2093, 1970, 2136, 2120,
-     1988, 2029, 1542, 1985, 1941, 1941, 1923,  884, 1858, 1831,
-
-     2996, 1815, 1772, 1768, 1617,  651, 3068, 2150, 2149, 1757,
-     1745, 1725, 4394, 1623, 1924, 2045, 3140, 2054,    0, 1631,
-     1594, 1302, 1202, 3212, 2158, 2066, 2040, 2177, 1577, 1531,
-     2110, 1524, 1496, 1455, 1427, 1308, 1895, 2162, 1448, 1422,
-     2179, 1319, 1298, 2163, 2154, 1285, 1115, 1083, 1117, 1726,
-     1576, 2196, 2198, 1062,  984, 2193, 2056,  930, 2153, 2166,
-        0,  902,  804,  803, 1618, 2210, 2238,    0, 2213,  583,
-     4394,  497, 2199,  486, 4394,  426,  460, 4394, 2116, 2203,
-     2254, 2231,  392,  317, 1804, 2255, 2281,  239, 2027,  829,
-     2006, 2117, 2293, 2295, 2298, 2299, 2303, 2317, 2321, 2322,
-
-     2323, 2365, 2366, 2369, 2370, 2371, 2233,  154, 4394, 4394,
-     3281, 3296, 3311, 3326, 3341, 3353, 3368, 3383, 3397, 3412,
-     3427, 3442, 3457, 3472, 3487, 3502, 3517, 3532, 3547, 3562,
-     3577, 3592, 3607, 3622, 3633, 3648, 3663, 3678, 3693, 3708,
-     3723, 3738, 3753, 3768, 3783, 3792, 3807, 3822, 3837, 3852,
-     3867, 3882, 3897, 3908, 3923, 3938, 3953, 3968, 3983, 3998,
-     4013, 4028, 4043, 4058, 4073, 4088, 4103, 4118, 4133, 4148,
-     4163, 4174, 4188, 4203, 4218, 4233, 4244, 4258, 4273, 4288,
-     4303, 4318, 4333, 4348, 4363, 4378
+        0,   73, 2729, 4517,  122,  131,    0,  142, 2724,  140,
+      151,  171,  162, 2724,  231,  159, 2672, 2661,  119, 2660,
+     2673,  143, 2668, 2652,  211,  301,  361,  212,  209,  279,
+      243,  284,  301,  286,  221,  303,  309,  329, 2670,  239,
+     2665, 2649,  338,  403, 2710,  149,  380,  475,  348,  190,
+      538,  240, 2659, 2648,  236, 2650, 2663,  157, 2658, 2642,
+      379,  600,  314,  353,  377,  395,  401,  413,  382,  408,
+      513,  424,  516,  423,  562,  448,  544,  607,  612, 2654,
+      468,    0, 2696,  309,  617,  174, 4517, 2692,  672,  246,
+      353, 2686, 2686, 2680,  517,  661, 2680,  576,  280,  655,
+
+     2679,    0, 2692, 4517,    0,  696,    0,  741,    0,  580,
+      644,  586,  622, 2645, 2640, 2592, 2592,  692, 2617, 2616,
+      714, 2606,  680,  720, 2592, 2606,  811,  537,  884, 4517,
+      911,  961,    0,  986, 1035,  687,  753,  757, 2584, 2588,
+     2587, 2582, 2591,  318, 2568,  825, 2636, 2635,  430, 2634,
+      747,  820,  253,  830, 1085,  160,  563,  455, 1148, 1193,
+     2633,  784,  843,  850,  760,  603,  692,  844,  854, 2596,
+      657,  858,  893,  862,  893,  658, 1217, 1267, 2629, 1292,
+     1342,  913,  926, 1157,  831,  894,  915,  918,  895,  845,
+     2568,  464,  487,  538, 2620,  556, 1162, 1073, 2619, 2556,
+
+     4517, 1146, 1209, 2624, 2623, 2622, 2611, 2620, 2619,    0,
+     4517, 2618, 2616, 2615, 2614, 2613,  384, 1029, 1062, 1078,
+     1367, 1147, 1145, 1167, 1412, 2558, 2551, 2564, 2559, 1240,
+     1422, 2540,  756,  651, 2557, 2593, 2551, 2547, 1214, 1482,
+      722, 1208,  761, 1555, 1619,    0, 1624,    0, 2594, 2592,
+     2591, 1174, 1426, 1490, 1673, 2591, 2589,  560, 2550, 2549,
+     2583, 2530, 4517, 1499, 1039, 2591,  725, 2587,  928,  845,
+      592,  917,  642, 2585, 1156, 1503, 1716, 2584, 1516, 1761,
+     1531, 1564, 1470, 1565, 1464, 1429, 1580, 1490, 1566, 1598,
+     1831, 1896, 1901, 2583, 1582, 2573, 1613, 1950, 1587, 1676,
+
+     1588, 1614, 1581, 1149, 1539, 2528, 4517,  775,  799, 2562,
+     4517, 1709, 2557, 2556, 2493, 2492, 1202, 1709, 2546, 2545,
+     2544, 2544,  615, 2543,  744, 2542, 1099, 1674,  832, 4517,
+     2535, 1719, 2534, 2533, 1955, 1622, 4517, 1410, 2490, 2490,
+     2487, 2487, 2494, 2493,  778,  892,  920, 2013,    0, 2511,
+     2495, 2496, 2495,    0, 2086, 2159,  940, 1210, 1233, 1309,
+     2540, 2533, 1434, 4517, 1776, 1424, 2529,  910, 1615, 1616,
+     2528, 1173, 4517, 2476,    0, 2476, 1842, 2532, 1727, 1735,
+     2488, 2473, 2530, 1003, 1736,  904,  599, 1216, 1523, 2186,
+     2528, 1847, 1726, 1767, 1880, 1771, 2244, 1522, 1813, 1849,
+
+     1848, 1862, 2317, 2527, 2390, 2029, 1869, 1879, 1713, 2021,
+     1747, 2479, 2517, 1595, 2500, 1809, 2511, 2443, 2504, 2441,
+     2500, 2433, 2460, 1869, 4517, 2454, 2427, 2423, 2423, 2418,
+     2468, 1049, 2006, 2467, 1075, 2440, 2410,    0, 2497, 2570,
+     2400, 2394, 2448, 1341, 1756, 4517, 2446, 1803, 1343, 1491,
+     1768, 2439, 2438, 1416, 4517, 2386,    0, 2425, 1871, 2421,
+     1240, 2416, 2373, 2366, 1454, 1718, 1473, 2635, 1888, 2044,
+     1889, 2042, 2023, 2678, 2425, 1990, 1886, 2052, 2063, 2425,
+     1870, 1899, 1958, 1000, 4517, 2095, 1777, 2416, 2415, 2351,
+     2350, 2411, 2410, 2347, 2346, 2407, 2406, 2343, 2342, 2393,
+
+     2388, 1840, 2017, 2382, 2320, 2326, 2011, 2298, 2303, 2338,
+     2296, 2275, 2316, 2293, 2302, 2270, 2018, 2264, 4517, 2117,
+     4517, 2296, 4517, 2290, 2119, 2300, 2251, 2231, 2282, 1960,
+     1445,  289, 2107, 2108, 2114, 2068, 2281, 2125, 2131, 2280,
+     2139, 4517, 2227, 2176, 2262, 2267, 2258, 4517, 2187, 2173,
+     2177, 4517, 2166, 2214, 2211, 2157, 2198, 2148, 2103, 2111,
+     2085, 2098,    0, 2077, 2196, 2071, 2002,  827, 1575, 2168,
+     2135, 2063, 2170, 2136, 2164, 2203, 2000, 2014, 1683, 1939,
+     1931, 2030, 1944, 1630, 1954, 1906, 2751, 1919, 1917, 1913,
+     1385, 1565, 2824, 2249, 2204, 1850, 1863, 1832, 4517, 1806,
+
+     1637, 1912, 2897, 1920,    0, 1775, 1762, 1585,  945, 2970,
+     2096, 1949, 2188, 2207, 1772, 1743, 2250, 1745, 1677, 1563,
+     1551, 1686,  681, 2260, 1568, 1502, 2258, 1408, 1406, 2243,
+     2170, 1358, 1313, 1240, 1258, 1751, 1127, 2261, 2312, 1072,
+      926, 2279, 2133,  809, 1969, 2073,    0,  855,  705,  711,
+     1429, 2317, 2305,    0, 2284,  631, 4517,  546, 2094,  480,
+     4517,  413,  392, 4517, 1794, 2351, 2357, 2298,  325,  206,
+     1884, 2303, 2352,  203, 1915,  365, 2138, 2221, 2364, 2365,
+     2369, 2370, 2371, 2372, 2373, 2427, 2444, 2451, 2452, 2453,
+     2454, 2456, 2296,  179, 4517, 4517, 3040, 3059, 3072, 3086,
+
+     3105, 3124, 3140, 3159, 3178, 3196, 1267, 1342, 1671, 3214,
+     3233, 1702, 3252, 3271, 3290, 3309, 3328, 3347, 3366, 3385,
+     3404, 3416, 3435, 3454, 3473, 3492, 3511, 3519, 1896, 3529,
+     3545, 3564, 3580, 3599, 3618, 3637, 3656, 3675, 3694, 3713,
+     3732, 3744, 3763, 3782, 3801, 3820, 3839, 3858, 3877, 3893,
+     3908, 3924, 3943, 3962, 3981, 3997, 4016, 4035, 4054, 4073,
+     4092, 4111, 4130, 4149, 4168, 4187, 4206, 4225, 4244, 4259,
+     4278, 4297, 4316, 4331, 4345, 4364, 4383, 4402, 4421, 4440,
+     4459, 4478, 4497
     } ;
 
-static yyconst short int yy_def[787] =
+static yyconst short int yy_def[784] =
     {   0,
-      710,  710,  710,  710,  710,  710,  711,  712,  710,  710,
-      711,  710,   12,  713,  711,  711,  711,  711,   15,  711,
-      711,   15,  711,  711,   15,  711,  711,  714,  711,   15,
-       29,   29,   29,   29,   29,   29,  711,  715,  710,  716,
-      716,  710,   42,  713,  716,  716,  716,  716,   45,  716,
-      716,   45,  716,  716,   45,  716,  716,  716,   45,   58,
-       58,   58,   58,   58,   58,  716,  715,  710,  710,  711,
-      717,  718,  717,  710,  710,  710,  710,  711,  710,  711,
-      710,  719,  719,  711,  719,  710,   12,  710,  711,  713,
-      710,  710,  711,  710,  711,  710,  710,   95,  711,  711,
-
-      711,  711,  711,  711,  711,  711,  711,  711,   95,  711,
-      711,  711,  720,  714,  720,  721,  710,  711,  711,  710,
-      711,  711,  711,  711,  119,  710,  711,  123,   95,  711,
-      711,  711,  715,  722,  715,  710,  723,  716,  710,  716,
-      716,  710,  716,   42,  710,  716,  724,  716,  148,  710,
-      149,  716,  716,  716,  716,  716,  716,  716,  716,  716,
-      716,  149,  716,  716,  716,  148,  148,  710,  148,  716,
-      716,  148,  167,  710,  148,  171,  149,  716,  716,  716,
-      715,  710,  717,  725,  725,  726,  727,  717,  717,  728,
-      729,  710,  710,  710,  710,  711,  711,  710,  711,  710,
-
-      710,  710,  710,  711,  710,  710,  710,  710,  710,  710,
-      711,  710,   95,  710,  711,  710,  710,  711,  711,  711,
-      711,  711,  711,  711,  711,  218,  711,  711,  711,  730,
-      731,  732,  733,  734,  123,  710,  711,  710,  710,  711,
-      711,  711,  735,  711,  710,  710,  711,  711,  123,  711,
-      710,  711,  711,  735,  123,  244,  711,  711,  711,  710,
-      715,  710,  736,  710,  737,  716,  716,  716,  716,  738,
-      736,  739,  716,  149,  710,  716,  149,  716,  716,  716,
-      716,  716,  716,  716,  277,  716,  716,  716,  740,  716,
-      716,  710,  716,  716,  716,  290,  716,  716,  290,  291,
-
-      710,  716,  716,  290,  296,  716,  716,  716,  715,  710,
-      710,  741,  741,  742,  710,  743,  744,  744,  745,  745,
-      710,  710,  710,  711,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  711,  746,  710,  711,  710,
-      710,  711,  710,  711,  711,  711,  711,  710,  711,  747,
-      711,  711,  711,  711,  711,  748,  749,  749,  750,  750,
-      751,  752,  753,  710,  710,  710,  711,  754,  710,  710,
-      710,  710,  711,  711,  710,  710,  711,  710,  367,  754,
-      367,  711,  711,  711,  715,  710,  710,  710,  710,  710,
-      755,  710,  716,  756,  756,  716,  716,  291,  710,  716,
-
-      716,  716,  716,  716,  757,  716,  716,  716,  716,  716,
-      758,  748,  758,  716,  716,  716,  716,  414,  414,  716,
-      716,  716,  715,  710,  759,  760,  761,  762,  763,  764,
-      765,  766,  710,  710,  710,  710,  710,  710,  710,  710,
-      711,  711,  711,  710,  711,  710,  711,  711,  767,  768,
-      768,  711,  711,  711,  769,  770,  710,  771,  710,  772,
-      710,  710,  711,  710,  710,  710,  710,  710,  711,  710,
-      772,  715,  710,  710,  710,  710,  710,  773,  774,  774,
-      414,  716,  716,  716,  716,  716,  775,  767,  775,  716,
-      716,  716,  776,  716,  716,  715,  710,  710,  760,  761,
-
-      761,  762,  762,  763,  763,  764,  764,  765,  765,  766,
-      766,  710,  710,  710,  710,  710,  710,  777,  710,  710,
-      711,  711,  778,  710,  710,  710,  710,  711,  711,  711,
-      711,  710,  710,  710,  710,  710,  710,  710,  715,  710,
-      710,  710,  773,  773,  774,  774,  716,  716,  716,  716,
-      779,  716,  716,  776,  715,  710,  710,  760,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  778,  778,  710,
-      710,  710,  710,  711,  711,  711,  711,  711,  715,  710,
-      710,  774,  774,  716,  716,  779,  716,  716,  716,  715,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-
-      780,  711,  710,  710,  774,  774,  781,  716,  715,  710,
-      710,  710,  710,  710,  782,  782,  780,  617,  711,  710,
-      710,  774,  774,  781,  782,  624,  716,  715,  710,  710,
-      782,  617,  617,  710,  710,  774,  774,  783,  624,  624,
-      715,  710,  710,  782,  782,  617,  617,  710,  710,  774,
-      774,  783,  783,  624,  624,  715,  710,  710,  782,  782,
-      617,  784,  710,  785,  774,  783,  783,  624,  715,  710,
-      710,  710,  782,  784,  710,  710,  785,  710,  774,  783,
-      783,  715,  710,  710,  774,  783,  715,  710,  774,  715,
-      786,  786,  786,  786,  786,  786,  786,  786,  786,  786,
-
-      786,  786,  786,  786,  786,  786,  786,  710,  710,    0,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710
+      696,  696,  696,  696,  696,  696,  697,  698,  696,  699,
+      697,  696,   12,  700,  697,   15,   15,   15,   15,   15,
+       15,   15,   15,   15,   15,  701,  697,   27,   27,   27,
+       27,   27,   27,   27,   27,   27,   27,   27,  697,  697,
+      697,  697,  697,  702,  696,  703,  703,  696,   48,  700,
+      703,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,  703,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   62,   62,  703,  703,  703,  703,  703,  702,  696,
+      696,  697,  704,  705,  704,  696,  696,  696,  696,  696,
+      697,  696,  697,  696,  706,  706,  697,  706,  696,   12,
+
+      696,  697,  700,  696,  707,  697,  708,  697,  709,  108,
+      696,  108,  108,  697,  697,  697,  697,  108,  106,  697,
+      108,  697,  108,  108,  697,  710,  701,  710,  711,  696,
+      697,  696,  712,  697,  697,  697,  697,  697,  697,  697,
+      697,  697,  697,  702,  713,  702,  696,  714,  703,  696,
+      703,  703,  696,  703,  696,  696,  703,  715,  703,  159,
+      709,  160,  160,  160,  703,  703,  703,  703,  160,  159,
+      703,  160,  703,  160,  160,  703,  159,  696,  712,  159,
+      696,  703,  703,  703,  703,  703,  703,  703,  703,  702,
+      696,  716,  717,  717,  718,  719,  716,  716,  720,  721,
+
+      696,  722,  722,  696,  696,  696,  697,  697,  696,  697,
+      696,  696,  696,  696,  697,  696,  696,  696,  697,  696,
+      697,  722,  697,  696,  697,  696,  696,  696,  696,  697,
+      697,  697,  697,  697,  697,  697,  697,  697,  697,  723,
+      724,  725,  726,  727,  697,  728,  697,  729,  728,  697,
+      247,  697,  730,  730,  697,  254,  697,  697,  697,  697,
+      697,  697,  696,  702,  696,  731,  696,  732,  733,  733,
+      733,  733,  734,  731,  735,  733,  733,  222,  733,  277,
+      733,  733,  733,  733,  733,  733,  733,  733,  733,  733,
+      736,  733,  277,  729,  733,  293,  733,  292,  733,  733,
+
+      733,  733,  733,  733,  702,  696,  696,  737,  737,  738,
+      696,  739,  740,  740,  741,  741,  696,  742,  696,  696,
+      696,  697,  696,  696,  696,  696,  696,  696,  696,  696,
+      697,  742,  697,  696,  697,  332,  696,  697,  696,  696,
+      696,  696,  697,  697,  697,  696,  697,  743,  697,  697,
+      697,  697,  697,  744,  745,  745,  746,  746,  747,  748,
+      749,  696,  696,  696,  750,  751,  696,  696,  751,  751,
+      697,  697,  696,  696,  697,  697,  702,  696,  696,  696,
+      696,  696,  752,  696,  733,  753,  753,  733,  733,  293,
+      336,  733,  733,  733,  733,  733,  754,  733,  733,  733,
+
+      733,  733,  755,  744,  755,  756,  733,  733,  733,  733,
+      702,  696,  757,  758,  696,  696,  759,  760,  761,  762,
+      763,  764,  696,  696,  696,  697,  696,  696,  696,  696,
+      697,  697,  696,  697,  696,  697,  697,  765,  766,  766,
+      697,  697,  697,  767,  768,  696,  769,  696,  770,  770,
+      770,  697,  696,  696,  696,  696,  697,  696,  702,  696,
+      696,  696,  696,  696,  771,  772,  772,  733,  733,  733,
+      733,  733,  733,  754,  765,  474,  733,  733,  733,  773,
+      733,  733,  702,  696,  696,  758,  774,  759,  759,  760,
+      760,  761,  761,  762,  762,  763,  763,  764,  764,  696,
+
+      696,  774,  774,  697,  696,  696,  696,  696,  697,  775,
+      696,  696,  696,  696,  697,  697,  697,  697,  696,  696,
+      696,  696,  696,  696,  702,  696,  696,  696,  771,  771,
+      772,  772,  733,  733,  733,  733,  776,  733,  733,  773,
+      702,  696,  696,  758,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  775,  775,  696,  696,  696,  696,  697,
+      697,  697,  697,  697,  702,  696,  696,  772,  772,  733,
+      733,  776,  733,  733,  733,  702,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  777,  697,  696,  696,
+      772,  772,  778,  733,  702,  696,  696,  696,  696,  696,
+
+      779,  779,  777,  603,  697,  696,  696,  772,  772,  778,
+      779,  610,  733,  702,  696,  696,  779,  603,  603,  696,
+      696,  772,  772,  780,  610,  610,  702,  696,  696,  779,
+      779,  603,  603,  696,  696,  772,  772,  780,  780,  610,
+      610,  702,  696,  696,  779,  779,  603,  781,  696,  782,
+      772,  780,  780,  610,  702,  696,  696,  696,  779,  781,
+      696,  696,  782,  696,  772,  780,  780,  702,  696,  696,
+      772,  780,  702,  696,  772,  702,  783,  783,  783,  783,
+      783,  783,  783,  783,  783,  783,  783,  783,  783,  783,
+      783,  783,  783,  696,  696,    0,  696,  696,  696,  696,
+
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696
     } ;
 
-static yyconst short int yy_nxt[4467] =
+static yyconst short int yy_nxt[4591] =
     {   0,
         4,    4,    4,    5,    4,    4,    6,    4,    7,    8,
         4,    9,   10,    7,    4,    4,   11,   12,   13,   13,
-       13,    4,   14,    4,    4,    7,   15,   16,   17,    7,
-        7,   18,    7,    7,   19,   20,   21,   22,   23,   24,
-       22,   25,   26,    7,   27,    7,   28,    4,    4,   29,
-       30,   31,   32,   33,   34,   35,   36,    7,   19,   20,
-       21,   22,   37,   24,   25,   26,    7,    7,   27,    7,
-       38,    4,    4,    4,    4,    5,    4,   39,    6,   39,
-        7,    8,    4,    9,   10,   40,    4,    4,   41,   42,
-       43,   43,   43,    4,   44,    4,    4,   40,   45,   46,
-
-       47,   40,   40,   48,   40,   40,   49,   50,   51,   52,
-       53,   54,   52,   55,   56,   40,   57,   40,   28,    4,
-        4,   58,   59,   60,   61,   62,   63,   64,   65,   40,
-       49,   50,   51,   52,   66,   54,   55,   56,   40,   40,
-       57,   40,   67,    4,   68,   69,   69,   69,   69,   69,
-       72,   75,   76,   77,  102,  106,  709,   73,   73,   73,
-       73,   73,  710,   78,  122,   79,   80,  123,   68,  123,
-      122,   81,   82,   82,   83,  123,  362,  123,  103,   70,
-      107,  130,   70,  710,   84,   85,   86,   87,   87,   87,
-       87,   87,   88,  710,  710,  139,   70,   89,   70,   70,
-
-       70,   70,   70,   70,   70,   89,   70,   70,   89,   89,
-       89,   89,   89,   70,   70,   70,   70,  131,   70,  363,
-       89,   89,   89,   89,   89,   89,   89,   89,   70,   89,
-       70,   70,   89,   89,   89,   89,   70,   70,   70,   70,
-       70,   82,   92,  122,  109,  123,  389,  123,   94,   70,
-       70,   70,   70,  710,  390,  122,  123,   97,  123,  710,
-       92,   82,   91,  147,   70,  139,  132,  186,  187,  101,
-       93,  138,   94,  710,   95,   95,   95,  139,   96,  139,
-      102,   97,  108,  108,  108,  108,  108,  108,  108,  108,
-       70,  190,  662,  122,  171,  111,  112,  123,  178,  123,
-
-      153,  112,   93,  139,  103,  158,   98,   98,   98,   98,
-       98,   98,   98,   98,  710,  710,   99,  113,  114,  114,
-      114,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      115,  113,  113,  134,  710,  710,  196,  197,  113,  113,
-      113,  113,   70,   82,   82,   82,  154,  135,  135,  135,
-      135,  135,  191,  170,   70,  139,   77,   92,  171,   70,
-       91,   70,   70,  113,  117,  113,  140,  139,   79,  141,
-      138,  138,  139,   70,  142,  139,  688,  170,  159,  171,
-      205,  171,  206,  155,  162,  231,  139,  113,  113,  118,
-      138,   70,  134,  119,  119,  119,  157,  120,  170,  171,
-
-       70,  171,  136,  160,  139,  179,  193,  156,  194,  265,
-      164,  165,  154,  139,  195,  170,  165,  163,  171,  117,
-      171,  121,  205,  155,  606,  122,  123,  122,  122,  122,
-      122,  122,  122,  124,  271,  272,  170,  125,  125,  125,
-      171,  126,  171,   82,   82,   82,  330,  156,   69,   69,
-       69,   69,   69,  556,  180,  201,  331,  202,   82,   82,
-       82,  136,  678,  203,  331,  127,  218,  218,  218,  128,
-      129,  128,  129,  129,  129,  129,  129,   82,   82,   83,
-      226,  226,  226,  684,   70,  244,  244,  244,  675,  143,
-       85,   86,  144,  144,  144,  144,  144,  145,  256,  256,
-
-      256,  138,  146,  138,  138,  138,  138,  138,  138,  138,
-      146,  138,  138,  146,  146,  146,  146,  146,  138,  138,
-      138,  138,  277,  277,  277,  146,  146,  146,  146,  146,
-      146,  146,  146,  138,  146,  138,  138,  146,  146,  146,
-      146,  138,  138,  138,  138,  138,   92,  184,  311,  265,
-       91,   70,  186,  312,  134,  205,  148,  206,   94,  683,
-      149,  149,  149,  198,  150,  181,  184,   97,  135,  135,
-      135,  135,  135,  188,  188,  188,  188,  188,  189,  211,
-      211,  211,  211,  211,  211,  211,  211,   70,  148,  218,
-      218,  218,  151,  151,  151,  151,  151,  151,  151,  151,
-
-      139,   70,  152,   70,  207,  583,  208,   70,   82,  268,
-       94,   70,  209,  433,  139,  710,  139,  210,   70,   97,
-      710,  186,  312,  136,  139,   70,  710,  434,  207,   70,
-      208,  314,  315,  266,  267,  671,  209,  227,  139,   70,
-      210,  284,  139,  376,  161,  161,  161,  161,  161,  161,
-      161,  161,   70,   91,  244,  244,  244,  166,  305,  305,
-      305,  167,  167,  167,  281,  168,  212,  212,  212,  212,
-      212,  212,  212,  212,  216,  216,  216,  216,  216,  216,
-      216,  216,  277,  277,  277,  336,  336,  336,  375,  169,
-      220,   70,  377,  170,  171,  170,  170,  170,  170,  170,
-
-      170,  172,  360,  376,  139,  173,  173,  173,  623,  174,
-      217,  217,  217,  217,  217,  217,  217,  217,  235,  235,
-      235,  235,  235,  235,  235,  235,  337,  337,  337,  468,
-      286,  248,  278,  175,   70,   70,  117,  176,  177,  176,
-      177,  177,  177,  177,  177,  213,  360,  139,  139,  339,
-      339,  339,  466,  214,  243,  243,  243,  243,  243,  243,
-      243,  243,  123,  123,  123,  123,  123,  123,  123,  123,
-      340,  340,  340,  341,  341,  341,  280,  213,  469,  279,
-      117,  215,  215,  215,  215,  215,  215,  215,  215,  113,
-      114,  114,  114,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  678,  348,   70,   70,   70,
-      113,  113,  113,  113,  249,  249,  249,  249,  249,  249,
-      249,  249,  254,  254,  254,  254,  254,  254,  254,  254,
-      349,  691,  134,  271,  272,  113,  117,  113,  255,  255,
-      255,  255,  255,  255,  255,  255,  135,  135,  135,  135,
-      135,  261,  314,  315,  349,  367,  367,  367,  676,  113,
-      113,  113,  232,  232,  232,  233,   70,  113,  113,  113,
-      113,  113,  113,   70,  269,  113,  113,   82,   70,  139,
-       70,   70,  113,  113,   70,  113,  139,  138,  444,  710,
-       70,  139,   70,  139,  139,  139,   91,  139,  134,   70,
-
-      136,  136,  138,  139,  675,  139,  446,  113,  117,  309,
-      139,  268,  139,   70,  273,  273,  273,  273,  273,  273,
-      273,  273,  285,  285,  285,  524,  139,  336,  336,  336,
-      446,  113,  113,  236,  138,  282,   70,  237,   70,  281,
-      287,  288,  283,  289,   70,  238,  445,  239,  524,  139,
-      240,  139,  343,  296,  296,  296,  480,  139,  240,  350,
-      343,  240,  455,  325,  240,  240,  468,  136,   70,  237,
-       70,  350,  350,  241,  242,  241,  241,  241,  241,  241,
-      241,  139,  240,  139,  343,  240,  366,  672,  240,  245,
-      308,   70,  268,  367,  367,  367,  117,  244,  244,  244,
-
-      296,  296,  296,  246,  139,   91,  247,  386,  265,  379,
-      379,  379,  387,  388,  247,  537,  265,  247,   70,  427,
-      247,  247,  290,  290,  290,  290,  290,  290,  290,  290,
-      247,  139,   91,  248,  314,  315,  279,  668,  247,  184,
-      311,  247,   91,  605,  247,  250,  188,  188,  188,  188,
-      188,  189,  479,  251,  216,  216,  216,  216,  216,  216,
-      216,  216,  243,  243,  243,  243,  243,  243,  243,  243,
-      232,  232,  232,  233,  381,  381,  381,  250,  403,   70,
-      428,  252,  253,  252,  252,  252,  252,  252,  252,  213,
-      545,  668,  139,  256,  256,  256,  265,  214,  171,  171,
-
-      171,  171,  171,  171,  171,  171,  299,  299,  299,  299,
-      299,  299,  299,  299,  376,  366,  117,  339,  339,  339,
-      663,  213,  379,  379,  379,  215,  257,  215,  215,  258,
-      215,  215,  215,  274,   91,  362,  662,  410,  396,  396,
-      396,  275,  254,  254,  254,  254,  254,  254,  254,  254,
-      304,  304,  304,  304,  304,  304,  304,  304,  419,  419,
-      419,  329,  447,  377,  375,  274,   70,  467,  661,  276,
-      276,  276,  276,  276,  276,  276,  276,  236,  363,  139,
-       70,  291,  522,   70,   70,  393,  448,  394,  478,  292,
-      478,  239,  375,  139,  293,  395,  139,  139,   70,  339,
-
-      339,  339,  293,  407,   91,  293,  522,  370,  293,  293,
-      374,  139,   70,  291,  440,  440,  440,  294,  295,  294,
-      294,  294,  294,  294,  294,  139,  293,  401,  406,  293,
-      184,  311,  293,   70,  245,  248,   70,  316,  316,  316,
-      316,  316,  296,  296,  296,   70,  139,   70,  246,  139,
-       70,  297,  366,  376,  396,  396,  396,   91,  139,  297,
-      139,  408,  297,  139,  637,  297,  297,  338,  338,  338,
-      338,  338,  338,  338,  338,  297,  348,  364,  298,  402,
-       70,   70,  375,  297,  512,  364,  297,  556,  364,  297,
-      300,  364,  364,  139,  139,  557,  513,  245,  301,  429,
-
-      404,  364,  417,   70,   91,  368,  368,  368,   70,  364,
-       91,  246,  364,  526,  661,  364,  139,  397,  397,  397,
-      546,  139,  300,   70,  404,  298,  302,  303,  302,  302,
-      302,  302,  302,  302,  274,  455,  139,  527,  305,  305,
-      305,  370,  275,  241,  241,  241,  241,  241,  241,  241,
-      241,  365,  365,  365,  365,  365,  365,  365,  365,  636,
-      430,  441,  441,  441,  658,  371,  274,  650,  405,  532,
-      276,  306,  276,  276,  307,  276,  276,  276,  342,  372,
-      405,  405,  460,  460,  460,  657,  343,  252,  252,  252,
-      252,  252,  252,  252,  252,  378,  378,  378,  378,  378,
-
-      378,  378,  378,  471,  471,  471,  518,  518,  518,  465,
-      342,  456,  456,  456,  344,  344,  344,  344,  344,  344,
-      344,  344,  356,  356,  236,  356,  356,  356,  356,  356,
-      563,  356,  356,  356,  356,   70,  356,  356,  467,  369,
-      422,  364,  564,  356,  356,  356,  356,  369,  139,  364,
-      369,   70,  364,  369,  369,  364,  364,  457,  245,   70,
-      414,  414,  414,  369,  139,  364,  461,  268,  356,  356,
-      356,  369,  139,  364,  369,  369,  364,  369,   70,  364,
-      462,  465,  655,  369,  654,  265,  369,  358,  649,  369,
-      369,  139,  356,  356,  113,  232,  232,  232,  233,  369,
-
-      113,  113,  113,  113,  113,  113,  134,  369,  113,  113,
-      369,  245,  134,  369,  648,  113,  113,  423,  113,  380,
-      380,  380,  544,  392,  544,  246,  385,  385,  385,  385,
-      385,  338,  338,  338,  338,  338,  338,  338,  338,   70,
-      113,  117,  302,  302,  302,  302,  302,  302,  302,  302,
-      431,  431,  139,  461,  331,  370,  647,   91,   70,   70,
-      646,  366,  331,   70,  113,  113,  371,  462,  414,  414,
-      414,  139,  139,  371,   77,  136,  139,  576,   91,  665,
-      372,  136,   70,  373,  473,  265,   79,  372,  643,  577,
-      409,  373,   81,  265,  373,  139,   70,  373,  373,  294,
-
-      294,  294,  294,  294,  294,  294,  294,  373,  582,  139,
-      374,  432,  432,  482,   70,  373,   70,  465,  373,   91,
-       91,  373,  342,  418,  418,  418,  268,  139,  642,  139,
-      343,  365,  365,  365,  365,  365,  365,  365,  365,  378,
-      378,  378,  378,  378,  378,  378,  378,  468,  184,  498,
-      441,  441,  441,  499,  342,   70,  635,   70,  344,  382,
-      344,  344,  383,  344,  344,  344,  398,   70,  139,  366,
-      139,  622,  679,   70,  399,  474,  418,  418,  418,   92,
-      139,   70,   70,  375,   70,  475,  139,   86,  634,  630,
-      397,  397,  397,   88,  139,  139,  469,  139,  398,   70,
-
-      491,  536,  400,  400,  400,  400,  400,  400,  400,  400,
-      356,  356,  139,  356,  356,  356,  356,  356,  357,  356,
-      356,  356,  356,  483,  356,  356,  298,  492,   91,   70,
-      134,  412,  356,  356,  356,  376,  184,  311,  397,  397,
-      397,  496,  139,  426,  426,  426,  426,  426,  344,  344,
-      344,  344,  344,  344,  344,  344,  356,  356,  356,  439,
-      439,  439,  439,  439,  439,  439,  439,  400,  400,  400,
-      400,  400,  400,  400,  400,  413,  134,  613,  464,  664,
-      356,  356,   70,  245,  417,  444,  464,  519,  539,  464,
-       70,  444,  464,  464,   70,  139,   70,  246,  629,  136,
-
-      297,  520,  464,  139,   70,  371,   91,  139,  297,  139,
-      464,  297,  467,  464,  297,  297,  464,  139,  134,  441,
-      441,  441,  464,  556,  297,  621,  620,  298,  485,  555,
-      464,   70,  297,  464,   70,  297,  464,  464,  297,  371,
-      481,  481,  481,  484,  139,  540,  464,  139,   70,   70,
-      467,  585,  486,  372,  464,  374,  415,  464,  265,  134,
-      464,  139,  139,  689,  415,   70,   70,  415,  619,   70,
-      415,  415,  468,  472,  472,  472,  472,  472,  139,  139,
-      415,  490,  139,  416,  456,  456,  456,  136,  415,   70,
-      201,  415,  202,  416,  415,  398,  615,   91,  203,   70,
-
-      615,  553,  139,  399,  439,  439,  439,  439,  439,  439,
-      439,  439,  139,   70,  550,  467,   70,  548,  567,  268,
-      549,  495,  481,  481,  481,  523,  139,  398,  136,  139,
-      457,  400,  420,  400,  400,  421,  400,  400,  400,  449,
-      449,  548,  449,  449,  449,  449,  449,   92,  449,  449,
-      449,  449,   70,  449,  449,  631,  651,  524,  416,   70,
-      449,  449,  449,  449,   70,  139,  525,  533,  533,  533,
-      468,   70,  139,  481,  481,  481,  614,  139,   70,  631,
-      524,  533,  533,  533,  139,  449,  449,  449,  184,  311,
-       70,  139,  451,  584,  612,  558,  558,  558,  558,  558,
-
-      544,  392,  544,  139,  451,  451,  613,  596,  693,  449,
-      449,  356,  356,  534,  356,  356,  356,  356,  356,  495,
-      356,  356,  356,  356,  552,  356,  356,  534,  535,   91,
-      566,  158,  356,  356,  356,  356,  535,   70,  566,  535,
-       70,  566,  535,  535,  566,  566,  611,  560,   70,  610,
-      139,   70,  535,  139,  566,  134,  134,  356,  356,  356,
-      535,  139,  566,  535,  139,  566,  535,  590,  566,  579,
-      579,  579,  579,  579,  607,  392,  631,  260,  589,  632,
-      664,  356,  356,  356,  356,  461,  356,  356,  356,  356,
-      356,  639,  356,  356,  356,  356,  587,  356,  356,   70,
-
-      631,   70,  535,  633,  356,  356,  356,  356,  588,  670,
-      535,  519,  139,  535,  139,  640,  535,  535,   91,  693,
-      604,  671,  134,  603,  136,  136,  535,  602,  566,  356,
-      356,  356,  134,  609,  535,  644,  566,  535,  577,  566,
-      535,  631,  566,  566,   70,  588,  579,  579,  579,  579,
-      579,  134,  566,  356,  356,  461,  607,  139,   70,  645,
-      566,  638,  628,  566,  392,  631,  566,  184,  498,  462,
-      601,  139,  463,  685,  558,  558,  558,  558,  558,  134,
-      463,  134,  673,  463,  631,  631,  463,  463,  260,  631,
-      641,  136,  656,  653,  631,  134,  463,  631,  392,  659,
-
-      392,  540,  608,  627,  463,  392,  669,  463,  631,  631,
-      463,  371,  392,  631,  660,  134,  601,  653,  631,  673,
-      136,  631,  600,  666,  599,  372,  682,  653,  373,  653,
-      631,  598,  686,  134,  653,  693,  373,  597,  569,  373,
-      392,  653,  373,  373,  687,  569,  680,  667,  136,  567,
-      136,  653,  373,  653,  631,  374,  392,  392,  653,  596,
-      373,  564,  595,  373,  136,  653,  373,  449,  449,  653,
-      449,  449,  449,  449,  449,  450,  449,  449,  449,  449,
-      594,  449,  449,  134,  136,  653,  653,  593,  488,  449,
-      449,  449,  592,  653,  690,  693,  591,  693,  681,  392,
-
-      693,  693,  136,  392,  708,  693,  694,  686,  695,  653,
-      653,  696,  697,  449,  449,  449,  698,  392,  581,  693,
-      489,  580,  262,  693,  693,  693,  537,  536,  578,  575,
-      699,  574,  489,  489,  700,  701,  702,  449,  449,  356,
-      356,  573,  356,  356,  356,  356,  356,  357,  356,  356,
-      356,  356,  136,  356,  356,  572,  571,  570,  569,  105,
-      412,  356,  356,  356,  260,  567,  260,  693,  693,  260,
-      260,  693,  693,  693,  260,  565,  562,  561,  703,  704,
-      560,  559,  705,  706,  707,  356,  356,  356,  260,  511,
-      511,  509,  260,  260,  260,  509,  507,  507,  505,  505,
-
-      503,  503,  501,  501,  392,  551,  542,  541,  205,  356,
-      356,  356,  356,  198,  356,  356,  356,  356,  356,  357,
-      356,  356,  356,  356,  466,  356,  356,  538,  465,  536,
-      459,   92,  412,  356,  356,  356,  260,  260,  531,  530,
-      260,  260,  260,  529,  528,  444,   92,  517,  516,  515,
-      514,  434,  511,  509,  507,  505,  503,  356,  356,  356,
-      501,  187,  497,  493,  392,  477,  476,   74,  199,  470,
-      370,  366,  459,  454,  453,  452,  199,  443,  442,  438,
-      437,  356,  356,   70,  461,  436,  435,  205,  205,  199,
-      198,  198,  198,  320,  320,  318,  139,  318,  462,  187,
-
-      424,  494,  264,  392,  264,  384,  366,  355,  354,  494,
-      353,  352,  494,  351,  347,  494,  494,  346,  345,  335,
-      334,  333,  332,  329,  329,  494,  328,  327,  326,  325,
-      325,  324,  323,  494,  322,  321,  494,  320,  318,  494,
-      371,  311,  310,  265,  264,  262,  260,  199,  259,  117,
-      230,  229,  228,  199,  372,  225,  224,  415,  223,  222,
-      222,  221,  220,  219,   91,  415,  205,  204,  415,  198,
-      199,  415,  415,  198,  192,  184,  182,  137,  110,  105,
-      104,  415,  101,  100,  416,   91,   74,  710,  710,  415,
-      710,  710,  415,  710,  710,  415,  519,  710,  710,  710,
-
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      520,  710,  710,  521,  710,  710,  710,  710,  710,  710,
-      710,  521,  710,  710,  521,  710,  710,  521,  521,  710,
-      710,  710,  710,  710,  710,  710,  710,  521,  710,  710,
-      710,  710,  710,  710,  710,  521,  710,  710,  521,  710,
-      710,  521,  449,  449,  710,  449,  449,  449,  449,  449,
-      710,  449,  449,  449,  449,  710,  449,  449,  710,  710,
-      710,  710,  710,  449,  449,  449,  449,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  449,  449,
-
-      449,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  449,  449,  449,  449,  710,  449,  449,  449,
-      449,  449,  710,  449,  449,  449,  449,  710,  449,  449,
-      710,  710,  710,  710,  710,  449,  449,  449,  449,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      449,  449,  449,  710,  710,  710,  710,  451,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  451,
-      451,  710,  710,  710,  449,  449,  519,  710,  710,  710,
-
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      520,  710,  710,  547,  710,  710,  710,  710,  710,  710,
-      710,  547,  710,  710,  547,  710,  710,  547,  547,  710,
-      710,  710,  710,  710,  710,  710,  710,  547,  710,  710,
-      710,  710,  710,  710,  710,  547,  710,  710,  547,  710,
-      710,  547,  449,  449,  710,  449,  449,  449,  449,  449,
-      450,  449,  449,  449,  449,  710,  449,  449,  710,  710,
-      710,  710,  710,  488,  449,  449,  449,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  449,  449,
-
-      449,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  449,  449,  449,  449,  710,  449,  449,  449,
-      449,  449,  450,  449,  449,  449,  449,  710,  449,  449,
-      710,  710,  710,  710,  710,  488,  449,  449,  449,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      449,  449,  449,  710,  710,  710,  710,  489,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  489,
-      489,  710,  710,  710,  449,  449,  616,  616,  710,  616,
-
-      616,  616,  616,  616,  710,  616,  616,  616,  616,  710,
-      616,  616,  710,  710,  710,  710,  710,  616,  616,  616,
-      616,  710,  710,  710,  710,  710,  710,  618,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  616,  616,  616,  710,  710,  710,  710,  710,
-      710,  618,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  616,  616,  616,  616,
-      710,  616,  616,  616,  616,  616,  617,  616,  616,  616,
-      616,  710,  616,  616,  710,  710,  710,  710,  710,  625,
-      616,  616,  616,  710,  710,  710,  710,  710,  710,  626,
+        4,   14,    4,    4,   15,   16,   17,   18,   15,   15,
+       19,   15,   15,   15,   20,   21,   15,   22,   23,   24,
+       15,   25,   15,   26,    4,    4,   27,   28,   29,   30,
+       31,   32,   33,   34,   35,   36,   37,   38,   39,    7,
+       40,    7,    7,   41,   42,    7,    7,    7,   43,    7,
+        7,   44,    4,    4,    4,    4,    5,    4,   45,    6,
+       45,    7,    8,    4,    9,   10,   46,    4,    4,   47,
+       48,   49,   49,    4,   50,    4,    4,   51,   52,   53,
+
+       54,   51,   51,   55,   51,   51,   51,   56,   57,   51,
+       58,   59,   60,   51,   61,   51,   26,    4,    4,   62,
+       63,   64,   65,   66,   67,   68,   69,   70,   71,   72,
+       73,   74,   46,   75,   46,   46,   76,   77,   46,   46,
+       46,   78,   46,   46,   79,    4,   80,   81,   81,   81,
+       81,   84,   87,   88,   90,  115,  119,   82,   85,   85,
+       85,   85,  111,  268,   91,   95,   92,   93,   80,  150,
+      170,   94,   95,   95,   96,   82,  216,  696,  116,   82,
+      120,  695,  696,  199,   97,   98,   99,  100,  100,  100,
+      100,  101,  104,  158,  171,  102,  102,  102,  102,  102,
+
+      102,  102,  102,   82,  102,   82,   82,  102,  102,  102,
+       82,   82,  102,   82,  111,  111,  112,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,   82,
+      102,  102,  102,  102,  102,   82,   82,   82,   82,   82,
+       82,   82,  105,  111,  106,  200,  107,  108,  108,  108,
+      108,  109,  140,  648,  105,  136,  268,  135,  135,  204,
+      135,  205,  138,  674,  123,  124,  206,  136,  136,  137,
+      209,  125,  166,  106,  135,  135,  135,  110,  110,  110,
+      110,  110,  110,  110,  110,  110,  110,  110,  110,  136,
+      136,  104,  135,  135,  135,  167,  216,  163,  217,  141,
+
+      106,  126,  127,  127,  127,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  128,  126,  126,  111,  195,  196,
+      145,  126,  126,  126,  126,  136,  136,  135,  135,  135,
+      136,  136,  136,  136,  135,  135,  135,  115,  135,  135,
+      135,  111,  114,  569,  126,  130,  126,  136,  136,  136,
+      136,   95,  135,  135,  135,  136,  136,  135,  135,  135,
+      116,  149,  181,  696,  135,  135,  135,  677,  150,  207,
+      208,  183,  126,  126,  131,  136,  136,  132,  132,  132,
+      132,  133,  111,   90,  542,  135,  135,  328,   82,  117,
+      147,  143,  125,  151,  664,   92,  152,  329,  125,  182,
+
+      153,  181,  181,  134,  329,  145,  184,  135,  135,  136,
+      136,  136,  136,  136,  136,  136,  136,  136,  136,  146,
+      146,  146,  146,  182,  182,  181,  181,  181,  182,  182,
+      134,   82,  174,  175,  181,  181,  181,  147,   82,  176,
+      165,  182,  182,  150,  181,  181,  181,  182,  182,  166,
+      150,  181,  181,  181,  182,  182,   82,  274,  275,  182,
+      182,  181,  181,  181,  181,  181,  181,  670,  150,  185,
+      182,  182,  167,  193,  307,  147,   95,   95,   96,  181,
+      181,  181,  661,   82,   81,   81,   81,   81,  154,   98,
+       99,  155,  155,  155,  155,  156,  195,  308,  188,  157,
+
+      157,  157,  157,  157,  157,  157,  157,  149,  157,  149,
+      149,  157,  157,  157,  149,  149,  157,  149,   95,   95,
+       95,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  157,  157,  149,  157,  157,  157,  157,  157,  149,
+      149,  149,  149,  149,  149,  149,   82,  195,  308,  105,
+      241,  159,   82,  107,  160,  160,  160,  160,  161,  182,
+      182,  105,  182,  182,  150,  310,  311,  181,  181,  181,
+       82,   82,  181,  181,  374,  186,  168,   95,   95,   95,
+      159,  130,  150,  150,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  225,  225,  225,  225,
+
+       82,  104,  225,  225,  225,  225,  669,  159,   82,  173,
+      111,   82,  150,  177,  145,   82,  178,  178,  178,  178,
+      179,  375,  187,  150,  417,  190,  193,  150,  146,  146,
+      146,  146,  230,  197,  197,  197,  197,  198,  225,  225,
+      225,  225,  180,  284,  274,  275,  181,  181,  182,  182,
+      182,  182,  182,  182,  182,  182,  182,  182,   95,  467,
+      189,  176,   95,   95,   95,   82,   82,  176,   82,  180,
+      696,  226,  231,  227,  212,  696,  213,  150,  150,  228,
+      657,  214,  229,  104,  147,  109,  418,  107,  202,  202,
+      202,  202,  109,  226,  271,  227,  225,  225,  225,  225,
+
+       82,  348,  228,  255,  255,  255,  255,  229,  225,  225,
+      225,  225,  150,  664,  109,  348,  348,  291,  203,  203,
+      203,  203,  203,  203,  203,  203,  203,  203,  203,  203,
+      225,  225,  225,  225,  239,  358,  225,  225,  225,  225,
+      637,  109,  219,  219,  219,  219,  219,  219,  219,  219,
+      219,  219,  219,  219,  221,   82,  662,  235,  284,  346,
+      216,  222,  217,  269,  270,  360,  130,  150,   82,  255,
+      255,  255,  255,  255,  255,  255,  255,  381,  237,  240,
+      150,  433,  347,  221,  310,  311,  382,  223,  223,  223,
+      223,  223,  223,  223,  223,  223,  223,  223,  223,  259,
+
+      280,  280,  280,  280,  347,  361,  283,  260,  310,  311,
+      221,  126,  127,  127,  127,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  145,   82,  104,
+      591,  126,  126,  126,  126,  423,  271,  434,   82,   82,
+      150,  146,  146,  146,  146,  264,  272,  145,  323,  424,
+      150,  150,   82,   82,  126,  130,  126,  661,  305,  280,
+      280,  280,  280,  658,  150,  150,  280,  280,  280,  280,
+      280,  280,  280,  280,  280,  280,  280,  280,  280,  280,
+      280,  280,  126,  126,  126,  242,  242,  242,  243,  281,
+      126,  126,  126,  126,  126,  126,  286,  147,  126,  126,
+
+      282,   82,   82,   82,  126,  126,  104,  126,  285,  280,
+      280,  280,  280,  150,  150,  150,  290,  147,  435,  286,
+      327,   82,  288,   82,  374,   82,   82,  126,  130,  298,
+      298,  298,  298,  150,   82,  150,   82,  150,  150,  289,
+      435,  385,  298,  298,  298,  298,  150,  104,  150,  304,
+      466,  436,  291,  358,  303,  126,  126,  245,  245,  245,
+      245,  245,  245,  245,  245,  245,  245,  245,  245,   82,
+      246,  373,  301,  437,  247,  271,  654,   82,   82,   82,
+       82,  248,  288,  249,  130,  250,  250,  250,  250,  250,
+      250,  250,  250,  250,  250,  250,  250,  250,  250,  250,
+
+      250,  250,  250,  251,  465,  623,  465,  252,  252,  252,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,   82,
+       82,   82,   82,   82,   82,   82,   82,   82,   82,   82,
+      247,   82,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  254,  330,  330,  330,  330,  542,
+      378,  255,  255,  255,  255,  379,  380,  256,  543,  257,
+      257,  257,  257,  257,  257,  257,  257,  257,  257,  257,
+      257,  257,  257,  257,  257,  257,  257,  257,  331,  331,
+      331,  331,  193,  307,  509,  258,   95,   95,   95,  312,
+      312,  312,  312,   82,  332,  332,  332,  332,  149,   98,
+
+      654,  155,  155,  155,  155,  150,  513,  509,  419,  157,
+      157,  157,  157,  157,  157,  157,  157,  149,  157,  149,
+      149,  157,  157,  157,  149,  149,  157,  149,  514,  104,
+      651,  157,  157,  157,  157,  157,  157,  157,  157,  157,
+      157,  157,  157,  149,  157,  157,  157,  157,  157,  149,
+      149,  149,  149,  149,  149,  149,   82,   82,  104,  222,
+      696,  333,  333,  333,  333,   82,  222,  696,  150,  150,
+      420,  193,  307,  298,  298,  298,  298,  150,  197,  197,
+      197,  197,  198,  334,  334,  334,  334,  456,  222,  696,
+      365,  365,  365,  365,  276,  276,  276,  276,  276,  276,
+
+      276,  276,  276,  276,  276,  276,  277,  302,  386,  242,
+      242,  242,  243,  278,  402,  222,  696,  387,  415,  415,
+      415,  415,  222,  444,   82,  318,  318,  318,  318,  222,
+      333,  333,  333,  333,  457,  277,  150,  360,  337,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  222,  130,  212,  130,  213,  333,  333,  333,  333,
+      214,  649,  277,  292,  292,  292,  292,  292,  292,  292,
+      292,  292,  292,  292,  292,   82,  246,  361,  222,  353,
+      293,  218,  218,  149,  149,  149,  149,  294,  343,  249,
+      648,  295,  295,  295,  295,  295,  295,  295,  295,  295,
+
+      295,  295,  295,  295,  295,  295,  295,  295,  295,  296,
+      445,  445,  445,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  149,  149,  149,  149,  149,
+      149,  149,  149,  149,  149,  149,  293,  149,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+       82,  254,  450,  446,  444,  149,  220,  220,  298,  298,
+      298,  298,  150,  647,  256,  451,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  519,  647,  104,  149,  149,
+      149,  149,  300,  149,  149,  149,  149,  149,  149,  149,
+
+      149,  149,  149,  149,  149,  149,  149,  149,  149,  149,
+      149,  149,  149,  223,  223,  223,  223,  223,  223,  223,
+      223,  223,  223,  223,  223,  335,  426,  426,  426,  426,
+      456,  104,  336,  369,  337,  254,  608,   82,  333,  333,
+      333,  333,  366,  366,  366,  366,  370,  104,  256,  150,
+      449,  449,  449,  449,  335,  530,  384,  530,  338,  338,
+      338,  338,  338,  338,  338,  338,  338,  338,  338,  338,
+      344,  644,   82,  643,  454,  104,  368,  455,   82,  398,
+      665,  335,  354,  354,  150,  354,  354,  354,  354,  354,
+      150,  354,  354,  354,  354,  568,  354,  354,   82,  696,
+
+      696,  145,  354,  354,  354,  354,  696,  696,  696,  696,
+      150,   82,  696,  696,  397,  377,  377,  377,  377,  388,
+      388,  388,  388,  150,   82,  354,  354,  354,  397,  397,
+       82,   82,  389,  389,  389,  389,  150,  532,  395,   82,
+      696,  145,  150,  150,  400,  425,  356,  389,  389,  389,
+      389,  150,  411,  354,  354,  126,  242,  242,  242,  243,
+      641,  126,  126,  126,  126,  126,  126,  104,  346,  126,
+      126,  147,   82,   82,   82,  126,  126,  104,  126,  393,
+      389,  389,  389,  389,  150,  150,  150,  104,   82,   82,
+       82,  396,  364,  399,  410,   82,   82,  373,  126,  130,
+
+      150,  150,  150,  640,  193,  485,   82,  150,  150,  486,
+      635,  147,  394,  396,  389,  389,  389,  389,  150,  609,
+      634,   82,   82,  401,  696,  369,  126,  126,  254,  406,
+      406,  406,  406,  150,  150,  696,  393,  696,  696,  622,
+      592,  256,  696,  257,  257,  257,  257,  257,  257,  257,
+      257,  257,  257,  257,  257,  257,  257,  257,  257,  257,
+      257,  257,  394,  402,  696,  696,  696,  617,  511,  258,
+      252,  252,  252,  252,  252,  252,  252,  252,  252,  252,
+      252,  252,  369,  421,   82,  224,  224,  329,  104,  617,
+      374,  696,  421,  511,  329,  370,  150,  371,  371,  371,
+
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  253,  253,  193,  307,
+      104,   82,  336,  372,   82,  414,  414,  414,  414,  336,
+       90,  337,  336,  150,   82,  633,  150,  409,  461,  336,
+      460,  696,   92,  636,   82,  422,  150,   94,  462,  145,
+       99,  336,  271,  104,  422,  101,  150,  445,  445,  445,
+      483,  336,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  390,   82,  531,  450,  336,   82,
+      632,  391,  469,  337,   82,  450,  502,  150,  336,   82,
+      696,  150,   82,   82,   82,   82,  104,  629,  451,  503,
+
+      446,  650,  472,  390,  520,  520,  520,  392,  392,  392,
+      392,  392,  392,  392,  392,  392,  392,  392,  392,  147,
+      628,   82,  621,  470,  473,  487,  487,  487,  487,  620,
+      390,  354,  354,  150,  354,  354,  354,  354,  354,  355,
+      354,  354,  354,  354,  145,  354,  354,  521,  671,  696,
+      271,  404,  354,  354,  354,   82,   82,   82,  459,  459,
+      459,  459,  696,  468,  468,  468,  468,  150,  150,  150,
+       82,  616,  500,  145,  354,  354,  354,   82,   82,  455,
+      523,  599,  150,  433,  501,  525,  104,   82,   82,  150,
+      150,  111,  433,  456,   82,  405,   82,   82,  478,  150,
+
+      150,  477,  354,  354,   82,  254,  150,   82,  150,  150,
+      363,  363,  479,  615,  147,  542,  150,  104,  256,  150,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  471,
+      482,  675,  617,  526,  618,  538,  300,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  369,
+      145,  530,  384,  530,  617,  650,  619,  607,  606,  605,
+      601,  541,  370,  625,  407,  407,  407,  407,  407,  407,
+      407,  407,  407,  407,  407,  407,  407,  407,  407,  407,
+      407,  407,  407,  601,  600,  626,  582,  659,  597,  617,
+
+      408,  338,  338,  338,  338,  338,  338,  338,  338,  338,
+      338,  338,  338,  438,  438,  510,  438,  438,  438,  438,
+      438,  617,  438,  438,  438,  438,  502,  438,  438,   82,
+      147,   82,  547,  438,  438,  438,  438,   82,  450,  696,
+      476,  150,  149,  150,  511,  149,  149,  149,  149,  150,
+       82,  451,   82,  512,  476,  476,  438,  438,  438,  596,
+       82,  551,  150,  440,  150,  384,  111,  590,  562,  511,
+      535,   82,  150,  536,  589,  552,   82,  440,  440,  534,
+      598,  271,  563,  150,  438,  438,  354,  354,  150,  354,
+      354,  354,  354,  354,  599,  354,  354,  354,  354,  624,
+
+      354,  354,  534,  617,  193,  307,  354,  354,  354,  354,
+      539,  544,  544,  544,  544,   82,   82,  548,  520,  520,
+      520,  145,   82,  659,  617,  617,  617,  150,  150,  354,
+      354,  354,  571,   82,  150,  565,  565,  565,  565,   82,
+      679,  145,  588,   82,   82,  150,  617,  563,  617,  587,
+      587,  150,  576,  570,  185,  150,  150,  354,  354,  354,
+      354,  521,  354,  354,  354,  354,  354,  586,  354,  354,
+      354,  354,   82,  354,  354,  573,   82,  575,   82,  354,
+      354,  354,  354,  656,  150,  193,  485,  585,  150,  574,
+      150,  147,  544,  544,  544,  544,   82,  657,  145,  593,
+
+      617,  584,  354,  354,  354,  145,  145,  593,  150,  145,
+      263,  147,  565,  565,  565,  565,  595,  614,  583,  574,
+      627,  555,  617,  679,  555,  582,  552,  581,  646,  594,
+      354,  354,  392,  392,  392,  392,  392,  392,  392,  392,
+      392,  392,  392,  392,  438,  438,  580,  438,  438,  438,
+      438,  438,  439,  438,  438,  438,  438,   82,  438,  438,
+      145,  579,  384,  384,  475,  438,  438,  438,  526,  150,
+      578,  642,  548,  617,  630,  147,  147,  577,  645,  147,
+      617,  145,  384,  384,  384,  567,  145,  438,  438,  438,
+      639,  639,  655,  263,  476,  617,  631,  668,  679,  613,
+
+      145,  566,  617,  265,  455,  384,  523,  384,  476,  476,
+      564,  673,  639,  639,  384,  438,  438,  354,  354,  384,
+      354,  354,  354,  354,  354,  355,  354,  354,  354,  354,
+      147,  354,  354,  639,  561,  639,  652,  404,  354,  354,
+      354,  560,  639,  559,  558,  557,  556,  639,  555,  139,
+      553,  147,  666,  384,  145,  639,  147,  639,  653,  384,
+      354,  354,  354,  667,  639,  676,  679,  679,  694,  639,
+      147,  679,  679,  679,  679,  679,  550,  680,  681,  672,
+      549,  639,  682,  683,  684,  685,  686,  639,  354,  354,
+      354,  354,  548,  354,  354,  354,  354,  354,  355,  354,
+
+      354,  354,  354,  639,  354,  354,  547,  672,  546,  639,
+      404,  354,  354,  354,  499,  499,  497,  497,  495,  495,
+      493,  493,  491,  491,  147,  489,  489,  384,  537,  679,
+      528,  527,  216,  354,  354,  354,  263,  263,  209,  373,
+      687,  263,  263,  263,  263,  263,  679,  524,  455,  523,
+      448,  111,  518,  679,  679,  679,  679,  688,  679,  517,
+      516,  354,  354,  502,  689,  690,  691,  692,  515,  693,
+      433,  111,  508,  507,  506,  505,  503,  424,  504,  504,
+      504,  504,  504,  504,  504,  504,  504,  504,  504,  504,
+      504,  504,  504,  504,  504,  504,  504,  438,  438,  263,
+
+      438,  438,  438,  438,  438,  499,  438,  438,  438,  438,
+      497,  438,  438,  495,  493,  491,  263,  438,  438,  438,
+      438,  489,  425,  263,  263,  263,  263,  196,  263,  484,
+      480,  268,  384,  464,  463,   86,  210,  458,  455,  373,
+      438,  438,  438,  364,  448,  443,  442,  441,  210,  432,
+      431,  430,  429,  428,  427,  337,  425,  337,  216,  216,
+      210,  209,  209,  209,  316,  316,  314,  314,  438,  438,
+      438,  438,  196,  438,  438,  438,  438,  438,  412,  438,
+      438,  438,  438,  364,  438,  438,  268,  268,  267,  384,
+      438,  438,  438,  438,  267,  353,  376,  344,  343,  373,
+
+      254,  364,  364,  246,  352,  351,  350,  349,  345,  342,
+      341,  340,  339,  438,  438,  438,  327,  327,  326,  325,
+      440,  324,  323,  323,  322,  321,  320,  319,  316,  314,
+      307,  306,  268,  287,  440,  440,  268,  268,  267,  265,
+      263,  438,  438,   82,  502,  262,  237,  210,  261,  235,
+      130,  240,  238,  210,  236,  150,  234,  503,  233,  533,
+      533,  533,  533,  533,  533,  533,  533,  533,  533,  533,
+      533,  533,  533,  533,  533,  533,  533,  533,  438,  438,
+      233,  438,  438,  438,  438,  438,  439,  438,  438,  438,
+      438,  232,  438,  438,  104,  216,  215,  209,  475,  438,
+
+      438,  438,  210,  209,  201,  193,  191,  173,  172,  169,
+      168,  165,  164,  148,  122,  142,  139,  122,  121,  118,
+      117,  438,  438,  438,  114,  113,  104,   86,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  438,
+      438,  602,  602,  696,  602,  602,  602,  602,  602,  696,
+      602,  602,  602,  602,  696,  602,  602,  696,  696,  696,
+      696,  602,  602,  602,  602,  696,  696,  696,  696,  696,
+      696,  604,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  602,  602,  602,  696,  696,  696,
+
+      696,  696,  696,  604,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  602,  602,  602,  602,  696,  602,  602,  602,
+      602,  602,  603,  602,  602,  602,  602,  696,  602,  602,
+      696,  696,  696,  696,  611,  602,  602,  602,  696,  696,
+      696,  696,  696,  696,  612,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  602,  602,  602,
+      696,  696,  696,  696,  696,  696,  612,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  602,  602,  602,  602,  696,
+
+      602,  602,  602,  602,  602,  696,  602,  602,  602,  602,
+      696,  602,  602,  696,  696,  696,  696,  602,  602,  602,
+      602,  696,  696,  696,  696,  696,  696,  604,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      602,  602,  602,  696,  696,  696,  696,  696,  696,  604,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  602,  602,
+      602,  602,  696,  602,  602,  602,  602,  602,  603,  602,
+      602,  602,  602,  696,  602,  602,  696,  696,  696,  696,
+      611,  602,  602,  602,  696,  696,  696,  696,  696,  696,
+
+      612,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  602,  602,  602,  696,  696,  696,  696,
+      696,  696,  612,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  602,  602,   82,  696,  696,  696,   82,   82,  696,
+      696,   82,   82,   82,   82,   82,   82,   82,   82,   83,
+       83,   83,   83,   83,  696,   83,   83,   83,   83,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   89,   89,
+      696,  696,  696,   89,   89,   89,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+
+      103,  103,  103,  103,  103,  129,  129,  129,  129,  129,
+      129,  129,  129,  129,  129,  129,  129,  129,  129,  129,
+      129,  129,  129,  129,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  144,  144,  144,  144,  144,  144,  144,
+      144,  144,  144,  149,  696,  696,  696,  149,  149,  149,
+      696,  149,  149,  149,  149,  149,  149,  149,  149,  192,
+      192,  192,  192,  192,  696,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  192,  192,  192,  192,  194,  194,
+      194,  194,  194,  194,  194,  194,  194,  194,  194,  194,
+      194,  194,  194,  194,  194,  194,  194,  211,  211,  696,
+
+      696,  696,  696,  696,  696,  696,  696,  211,  696,  696,
+      211,  211,  696,  211,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  244,  244,  244,  244,  244,  244,  244,
+      244,  244,  244,  244,  244,  244,  244,  244,  244,  244,
+      244,  244,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  266,  266,  266,  266,  266,  266,  266,  266,  266,
+      266,  266,  266,  266,  266,  266,  266,  266,  266,  266,
+      273,  273,  273,  273,  273,  273,  273,  273,  273,  273,
+
+      273,  273,  273,  273,  273,  273,  273,  273,  273,  192,
+      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  192,  192,  192,  192,  194,  194,
+      194,  194,  194,  194,  194,  194,  194,  194,  194,  194,
+      194,  194,  194,  194,  194,  194,  194,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  195,  195,  195,  195,
+      195,  195,  195,  195,  195,  195,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  313,  313,  696,  313,  313,
+      313,  313,  313,  313,  313,  313,  313,  313,  313,  313,
 
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  616,  616,  616,  710,  710,  710,
-      710,  710,  710,  626,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  616,  616,
-      616,  616,  710,  616,  616,  616,  616,  616,  710,  616,
-      616,  616,  616,  710,  616,  616,  710,  710,  710,  710,
-      710,  616,  616,  616,  616,  710,  710,  710,  710,  710,
-      710,  618,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  616,  616,  616,  710,
-      710,  710,  710,  710,  710,  618,  710,  710,  710,  710,
+      313,  313,  313,  313,  315,  315,  696,  315,  315,  315,
+      315,  315,  315,  315,  315,  315,  315,  315,  315,  315,
+      315,  315,  315,  317,  696,  317,  696,  696,  696,  317,
+      317,  317,  696,  696,  317,  355,  355,  696,  355,  355,
+      355,  355,  355,  355,  355,  355,  355,  355,  355,  355,
+      355,  355,  355,  355,  357,  357,  357,  357,  357,  357,
+      357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
+      357,  357,  357,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  359,  359,  359,  359,  359,  359,  359,  359,
 
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      616,  616,  616,  616,  710,  616,  616,  616,  616,  616,
-      617,  616,  616,  616,  616,  710,  616,  616,  710,  710,
-      710,  710,  710,  625,  616,  616,  616,  710,  710,  710,
-      710,  710,  710,  626,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  616,  616,
-      616,  710,  710,  710,  710,  710,  710,  626,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  616,  616,   70,  710,  710,   70,   70,  710,
-      710,   70,   70,   70,   70,   70,   71,   71,   71,   71,
-
-       71,  710,   71,   71,   71,   71,   71,   71,   71,   71,
-       71,   90,   90,   90,   90,   90,   90,   90,   90,   90,
-       90,   90,   90,   90,   90,   90,  116,  116,  116,  116,
-      116,  116,  116,  116,  116,  116,  116,  116,  116,  116,
-      116,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  138,  710,  710,  138,
-      138,  138,  710,  138,  138,  138,  138,  138,  183,  183,
-      183,  183,  183,  710,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  185,  185,  185,  185,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  200,  200,
-
-      710,  710,  710,  710,  710,  710,  710,  200,  200,  200,
-      200,  200,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  234,  234,  234,
-      234,  234,  234,  234,  234,  234,  234,  234,  234,  234,
-      234,  234,  134,  134,  134,  134,  134,  134,  134,  134,
-      134,  134,  134,  134,  134,  134,  134,  263,  263,  263,
-      263,  263,  263,  263,  263,  263,  263,  263,  263,  263,
-      263,  263,  270,  270,  270,  270,  270,  270,  270,  270,
-      270,  270,  270,  270,  270,  270,  270,  185,  185,  185,
-      185,  185,  185,  185,  185,  185,  185,  185,  185,  185,
-
-      185,  185,  186,  186,  186,  186,  186,  186,  186,  186,
-      186,  186,  186,  186,  186,  186,  186,  313,  313,  313,
+      359,  359,  359,  359,  359,  359,  359,  359,  359,  359,
+      359,  244,  244,  244,  244,  244,  244,  244,  244,  244,
+      244,  244,  244,  244,  244,  244,  244,  244,  244,  244,
+      362,  362,  362,  367,  696,  696,  696,  367,  696,  367,
+      367,  367,  367,  696,  367,  266,  266,  266,  266,  266,
+      266,  266,  266,  266,  266,  266,  266,  266,  266,  266,
+      266,  266,  266,  266,  383,  383,  383,  383,  383,  383,
+      383,  383,  383,  383,  383,  383,  383,  383,  383,  383,
+      383,  383,  383,  149,  696,  696,  696,  149,  149,  149,
+      696,  149,  149,  149,  149,  149,  149,  149,  149,  273,
+
+      273,  273,  273,  273,  273,  273,  273,  273,  273,  273,
+      273,  273,  273,  273,  273,  273,  273,  273,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  403,  403,  696,
+      403,  403,  403,  403,  403,  403,  403,  403,  403,  403,
+      403,  403,  403,  403,  403,  403,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309,  309,  309,  309,  309,  413,  413,  413,  413,  696,
+      413,  413,  413,  413,  413,  413,  413,  413,  413,  413,
+      413,  413,  413,  413,  192,  192,  192,  192,  192,  192,
+
+      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
+      192,  192,  192,  313,  313,  696,  313,  313,  313,  313,
       313,  313,  313,  313,  313,  313,  313,  313,  313,  313,
-      313,  313,  317,  317,  710,  317,  317,  317,  317,  317,
-      317,  317,  317,  317,  317,  317,  317,  319,  319,  710,
-      319,  319,  319,  319,  319,  319,  319,  319,  319,  319,
-      319,  319,  357,  357,  710,  357,  357,  357,  357,  357,
-      357,  357,  357,  357,  357,  357,  357,  359,  359,  359,
+      313,  313,  315,  315,  696,  315,  315,  315,  315,  315,
+      315,  315,  315,  315,  315,  315,  315,  315,  315,  315,
+      315,  416,  696,  416,  416,  696,  696,  416,  416,  416,
+      696,  696,  416,  439,  439,  696,  439,  439,  439,  439,
+      439,  439,  439,  439,  439,  439,  439,  439,  439,  439,
+      439,  439,  354,  354,  696,  354,  354,  354,  354,  354,
+      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
+
+      354,  355,  355,  696,  355,  355,  355,  355,  355,  355,
+      355,  355,  355,  355,  355,  355,  355,  355,  355,  355,
+      357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
+      357,  357,  357,  357,  357,  357,  357,  357,  357,  359,
       359,  359,  359,  359,  359,  359,  359,  359,  359,  359,
-      359,  359,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  361,  361,  361,
-      361,  361,  361,  361,  361,  361,  361,  361,  361,  361,
-      361,  361,  234,  234,  234,  234,  234,  234,  234,  234,
-      234,  234,  234,  234,  234,  234,  234,  369,  710,  710,
-      369,  710,  369,  369,  710,  710,  369,  369,  263,  263,
-      263,  263,  263,  263,  263,  263,  263,  263,  263,  263,
-      263,  263,  263,  391,  391,  391,  391,  391,  391,  391,
-      391,  391,  391,  391,  391,  391,  391,  391,  270,  270,
-      270,  270,  270,  270,  270,  270,  270,  270,  270,  270,
-      270,  270,  270,   90,   90,   90,   90,   90,   90,   90,
-
-       90,   90,   90,   90,   90,   90,   90,   90,  411,  411,
-      710,  411,  411,  411,  411,  411,  411,  411,  411,  411,
-      411,  411,  411,  313,  313,  313,  313,  313,  313,  313,
-      313,  313,  313,  313,  313,  313,  313,  313,  425,  425,
-      425,  425,  710,  425,  425,  425,  425,  425,  425,  425,
-      425,  425,  425,  183,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  183,  183,  183,  183,  183,  317,  317,
-      710,  317,  317,  317,  317,  317,  317,  317,  317,  317,
-      317,  317,  317,  319,  319,  710,  319,  319,  319,  319,
-      319,  319,  319,  319,  319,  319,  319,  319,  439,  710,
-
-      439,  710,  710,  710,  439,  439,  439,  450,  450,  710,
-      450,  450,  450,  450,  450,  450,  450,  450,  450,  450,
-      450,  450,  356,  356,  710,  356,  356,  356,  356,  356,
-      356,  356,  356,  356,  356,  356,  356,  357,  357,  710,
+      359,  359,  359,  359,  359,  359,  359,  359,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  452,  452,  696,  696,
+
+      452,  452,  696,  452,  452,  452,  452,  452,  452,  452,
+      452,  452,  453,  696,  696,  696,  696,  696,  453,  453,
+      453,  453,  696,  453,  383,  383,  383,  383,  383,  383,
+      383,  383,  383,  383,  383,  383,  383,  383,  383,  383,
+      383,  383,  383,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  474,  474,  696,  474,  474,  474,  474,  474,
+      474,  474,  474,  474,  474,  474,  474,  474,  474,  474,
+      474,  403,  403,  696,  403,  403,  403,  403,  403,  403,
+      403,  403,  403,  403,  403,  403,  403,  403,  403,  403,
+
+      481,  481,  696,  696,  481,  481,  481,  481,  481,  481,
+      481,  481,  481,  481,  481,  481,  413,  413,  413,  413,
+      696,  413,  413,  413,  413,  413,  413,  413,  413,  413,
+      413,  413,  413,  413,  413,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  488,  488,  696,  488,  488,  488,
+      488,  488,  488,  488,  488,  488,  488,  488,  488,  488,
+      488,  488,  488,  490,  490,  696,  490,  490,  490,  490,
+      490,  490,  490,  490,  490,  490,  490,  490,  490,  490,
+      490,  490,  492,  492,  696,  492,  492,  492,  492,  492,
+
+      492,  492,  492,  492,  492,  492,  492,  492,  492,  492,
+      492,  494,  494,  696,  494,  494,  494,  494,  494,  494,
+      494,  494,  494,  494,  494,  494,  494,  494,  494,  494,
+      496,  496,  696,  496,  496,  496,  496,  496,  496,  496,
+      496,  496,  496,  496,  496,  496,  496,  496,  496,  498,
+      498,  696,  498,  498,  498,  498,  498,  498,  498,  498,
+      498,  498,  498,  498,  498,  498,  498,  498,  438,  438,
+      696,  438,  438,  438,  438,  438,  438,  438,  438,  438,
+      438,  438,  438,  438,  438,  438,  438,  439,  439,  696,
+      439,  439,  439,  439,  439,  439,  439,  439,  439,  439,
+
+      439,  439,  439,  439,  439,  439,  357,  357,  357,  357,
       357,  357,  357,  357,  357,  357,  357,  357,  357,  357,
-      357,  357,  359,  359,  359,  359,  359,  359,  359,  359,
-      359,  359,  359,  359,  359,  359,  359,  361,  361,  361,
-      361,  361,  361,  361,  361,  361,  361,  361,  361,  361,
-      361,  361,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  458,  458,  458,
-
-      458,  458,  458,  458,  458,  458,  458,  458,  458,  458,
-      458,  458,  464,  710,  710,  710,  710,  464,  464,  710,
-      710,  464,  464,  391,  391,  391,  391,  391,  391,  391,
-      391,  391,  391,  391,  391,  391,  391,  391,   90,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,   90,   90,
-       90,   90,   90,  487,  487,  710,  487,  487,  487,  487,
-      487,  487,  487,  487,  487,  487,  487,  487,  411,  411,
-      710,  411,  411,  411,  411,  411,  411,  411,  411,  411,
-      411,  411,  411,  425,  425,  425,  425,  710,  425,  425,
-      425,  425,  425,  425,  425,  425,  425,  425,  183,  183,
-
-      183,  183,  183,  183,  183,  183,  183,  183,  183,  183,
-      183,  183,  183,  500,  500,  710,  500,  500,  500,  500,
-      500,  500,  500,  500,  500,  500,  500,  500,  502,  502,
-      710,  502,  502,  502,  502,  502,  502,  502,  502,  502,
-      502,  502,  502,  504,  504,  710,  504,  504,  504,  504,
-      504,  504,  504,  504,  504,  504,  504,  504,  506,  506,
-      710,  506,  506,  506,  506,  506,  506,  506,  506,  506,
-      506,  506,  506,  508,  508,  710,  508,  508,  508,  508,
-      508,  508,  508,  508,  508,  508,  508,  508,  510,  510,
-      710,  510,  510,  510,  510,  510,  510,  510,  510,  510,
-
-      510,  510,  510,  449,  449,  710,  449,  449,  449,  449,
-      449,  449,  449,  449,  449,  449,  449,  449,  450,  450,
-      710,  450,  450,  450,  450,  450,  450,  450,  450,  450,
-      450,  450,  450,  359,  359,  359,  359,  359,  359,  359,
-      359,  359,  359,  359,  359,  359,  359,  359,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  458,  458,  458,  458,  458,  458,  458,
-      458,  458,  458,  458,  458,  458,  458,  458,  535,  710,
-      710,  710,  710,  535,  535,  710,  710,  535,  543,  543,
-      543,  543,  543,  543,  543,  543,  543,  543,  543,  543,
-
-      543,  543,  543,   90,   90,   90,   90,   90,   90,   90,
-       90,   90,   90,   90,   90,   90,   90,   90,  487,  487,
-      710,  487,  487,  487,  487,  487,  487,  487,  487,  487,
-      487,  487,  487,  554,  554,  554,  554,  554,  554,  554,
-      554,  554,  554,  554,  554,  554,  554,  554,  566,  710,
-      710,  710,  710,  566,  566,  710,  710,  566,  568,  568,
-      710,  568,  568,  568,  568,  568,  568,  568,  568,  568,
-      568,  568,  568,  586,  586,  586,  586,  586,  586,  586,
-      586,  586,  586,  586,  586,  586,  586,  586,  617,  617,
-      710,  617,  617,  617,  617,  617,  617,  617,  617,  617,
-
-      617,  617,  617,  624,  624,  710,  624,  624,  624,  624,
-      624,  624,  624,  624,  624,  624,  624,  624,  616,  616,
-      710,  616,  616,  616,  616,  616,  616,  616,  616,  616,
-      616,  616,  616,  652,  652,  652,  652,  652,  652,  652,
-      652,  652,  652,  652,  652,  652,  652,  652,  674,  674,
-      674,  674,  674,  674,  674,  674,  674,  674,  674,  674,
-      674,  674,  674,  677,  677,  677,  677,  677,  677,  677,
-      677,  677,  677,  677,  677,  677,  677,  677,  692,  692,
-      692,  692,  692,  692,  692,  692,  692,  692,  692,  692,
-      692,  692,  692,    3,  710,  710,  710,  710,  710,  710,
-
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710
+      357,  357,  357,  357,  357,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  126,  126,  126,  126,  126,  126,
+      126,  126,  126,  126,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  447,  447,  447,  447,  447,  447,  447,
+      447,  447,  447,  522,  696,  696,  696,  696,  696,  522,
+      522,  522,  522,  522,  522,  522,  522,  522,  529,  529,
+      529,  529,  529,  529,  529,  529,  529,  529,  529,  529,
+      529,  529,  529,  529,  529,  529,  529,  103,  103,  103,
+
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  540,  540,  540,  540,
+      540,  540,  540,  540,  540,  540,  540,  540,  540,  540,
+      540,  540,  540,  540,  540,  545,  696,  696,  696,  696,
+      696,  545,  545,  545,  545,  554,  554,  696,  554,  554,
+      554,  554,  554,  554,  554,  554,  554,  554,  554,  554,
+      554,  554,  554,  554,  572,  572,  572,  572,  572,  572,
+      572,  572,  572,  572,  572,  572,  572,  572,  572,  572,
+      572,  572,  572,  603,  603,  696,  603,  603,  603,  603,
+      603,  603,  603,  603,  603,  603,  603,  603,  603,  603,
+
+      603,  603,  610,  610,  696,  610,  610,  610,  610,  610,
+      610,  610,  610,  610,  610,  610,  610,  610,  610,  610,
+      610,  602,  602,  696,  602,  602,  602,  602,  602,  602,
+      602,  602,  602,  602,  602,  602,  602,  602,  602,  602,
+      638,  638,  638,  638,  638,  638,  638,  638,  638,  638,
+      638,  638,  638,  638,  638,  638,  638,  638,  638,  660,
+      660,  660,  660,  660,  660,  660,  660,  660,  660,  660,
+      660,  660,  660,  660,  660,  660,  660,  660,  663,  663,
+      663,  663,  663,  663,  663,  663,  663,  663,  663,  663,
+      663,  663,  663,  663,  663,  663,  663,  678,  678,  678,
+
+      678,  678,  678,  678,  678,  678,  678,  678,  678,  678,
+      678,  678,  678,  678,  678,  678,    3,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696
     } ;
 
-static yyconst short int yy_chk[4467] =
+static yyconst short int yy_chk[4591] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -1173,7 +1186,7 @@ static yyconst short int yy_chk[4467] =
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    2,    2,    2,    2,    2,    2,    2,    2,
+        1,    1,    1,    2,    2,    2,    2,    2,    2,    2,
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
 
@@ -1181,482 +1194,495 @@ static yyconst short int yy_chk[4467] =
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
         2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-        2,    2,    2,    2,    5,    6,    6,    6,    6,    6,
-        8,   10,   10,   11,   18,   23,  708,    8,    8,    8,
-        8,    8,   19,   11,   34,   11,   11,   34,    5,   34,
-       36,   11,   12,   12,   12,   36,  233,   31,   18,   12,
-       23,   31,   40,   19,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   22,   25,   40,   12,   12,   12,   12,
+        2,    2,    2,    2,    2,    2,    5,    6,    6,    6,
+        6,    8,   10,   10,   11,   19,   22,   46,    8,    8,
+        8,    8,   16,  156,   11,   13,   11,   11,    5,   46,
+       58,   11,   12,   12,   12,   13,  156,   13,   19,   12,
+       22,  694,   13,   86,   12,   12,   12,   12,   12,   12,
+       12,   12,   50,   50,   58,   12,   12,   12,   12,   12,
 
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   37,   19,  233,
+       12,   12,   12,   12,   25,   28,   16,   12,   12,   12,
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   13,   27,   33,   25,   33,  264,   33,   24,   22,
-       25,   13,   46,   13,  264,   32,   32,   24,   32,   13,
-       15,   43,   44,   44,   51,   46,   37,   72,   72,   32,
-       15,   43,   15,   43,   15,   15,   15,   51,   15,   43,
-       35,   15,   24,   24,   24,   24,   24,   24,   24,   24,
-       47,   74,  688,   35,   60,   27,   27,   35,   60,   35,
-
-       46,   27,   15,   47,   35,   51,   15,   15,   15,   15,
-       15,   15,   15,   15,   49,   52,   15,   28,   28,   28,
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   38,   55,   49,   78,   78,   28,   28,
-       28,   28,   50,   82,   82,   82,   47,   38,   38,   38,
-       38,   38,   74,   65,   48,   50,   41,   57,   65,   56,
-      583,   41,   57,   28,   28,   28,   41,   48,   41,   41,
-       49,   52,   56,   53,   41,   57,  684,   62,   53,   62,
-       86,   62,   86,   48,   55,  115,   53,   28,   28,   29,
-       55,  138,  133,   29,   29,   29,   50,   29,   61,   61,
-
-       66,   61,   38,   53,  138,   66,   77,   48,   77,  145,
-       57,   57,   61,   66,   77,   63,   57,   56,   63,  115,
-       63,   29,  145,   64,  583,   29,   29,   29,   29,   29,
-       29,   29,   29,   30,  147,  147,   64,   30,   30,   30,
-       64,   30,   64,   83,   83,   83,  206,   64,   69,   69,
-       69,   69,   69,  683,   66,   83,  206,   83,   85,   85,
-       85,  133,  677,   83,  206,   30,   98,   98,   98,   30,
-       30,   30,   30,   30,   30,   30,   30,   42,   42,   42,
-      108,  108,  108,  676,   42,  122,  122,  122,  674,   42,
-       42,   42,   42,   42,   42,   42,   42,   42,  129,  129,
-
-      129,   42,   42,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,  151,  151,  151,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
-       42,   42,   42,   42,   42,   42,   45,  183,  183,  142,
-      546,   45,  184,  184,   67,  327,   45,  327,   45,  672,
-       45,   45,   45,  142,   45,   67,   73,   45,   67,   67,
-       67,   67,   67,   73,   73,   73,   73,   73,   73,   93,
-       93,   93,   93,   93,   93,   93,   93,  146,   45,  109,
-      109,  109,   45,   45,   45,   45,   45,   45,   45,   45,
-
-      146,  141,   45,   54,   92,  546,   92,  213,   87,  141,
-       54,  159,   92,  331,  141,  213,   54,   92,   87,   54,
-       87,  185,  185,   67,  159,  140,   87,  331,   92,  155,
-       92,  187,  187,  140,  140,  670,   92,  109,  140,  213,
-       92,  159,  155,  248,   54,   54,   54,   54,   54,   54,
-       54,   54,   58,  606,  130,  130,  130,   58,  177,  177,
-      177,   58,   58,   58,  155,   58,   94,   94,   94,   94,
-       94,   94,   94,   94,   96,   96,   96,   96,   96,   96,
-       96,   96,  162,  162,  162,  211,  211,  211,  247,   58,
-      130,  152,  248,   58,   58,   58,   58,   58,   58,   58,
-
-       58,   59,  231,  370,  152,   59,   59,   59,  606,   59,
-       97,   97,   97,   97,   97,   97,   97,   97,  118,  118,
-      118,  118,  118,  118,  118,  118,  212,  212,  212,  374,
-      162,  247,  152,   59,  153,  154,  231,   59,   59,   59,
-       59,   59,   59,   59,   59,   95,  359,  153,  154,  215,
-      215,  215,  370,   95,  120,  120,  120,  120,  120,  120,
-      120,  120,  121,  121,  121,  121,  121,  121,  121,  121,
-      216,  216,  216,  217,  217,  217,  154,   95,  374,  153,
-      359,   95,   95,   95,   95,   95,   95,   95,   95,  114,
-      114,  114,  114,  114,  114,  114,  114,  114,  114,  114,
-
-      114,  114,  114,  114,  114,  664,  222,  235,  235,  235,
-      114,  114,  114,  114,  124,  124,  124,  124,  124,  124,
-      124,  124,  126,  126,  126,  126,  126,  126,  126,  126,
-      222,  690,  135,  270,  270,  114,  114,  114,  127,  127,
-      127,  127,  127,  127,  127,  127,  135,  135,  135,  135,
-      135,  135,  312,  312,  222,  241,  241,  241,  663,  114,
-      114,  116,  116,  116,  116,  116,  143,  116,  116,  116,
-      116,  116,  116,  148,  143,  116,  116,  144,  157,  143,
-      156,  160,  116,  116,  158,  116,  148,  144,  347,  144,
-      165,  157,  164,  156,  160,  144,  395,  158,  181,  163,
-
-      690,  135,  274,  165,  662,  164,  348,  116,  116,  181,
-      274,  160,  163,  161,  148,  148,  148,  148,  148,  148,
-      148,  148,  161,  161,  161,  598,  161,  249,  249,  249,
-      348,  116,  116,  119,  274,  157,  179,  119,  180,  156,
-      163,  164,  158,  165,  170,  119,  347,  119,  598,  179,
-      119,  180,  337,  170,  170,  170,  395,  170,  119,  223,
-      337,  119,  360,  267,  119,  119,  465,  181,  267,  119,
-      268,  223,  223,  119,  119,  119,  119,  119,  119,  119,
-      119,  267,  119,  268,  337,  119,  242,  658,  119,  123,
-      179,  178,  180,  242,  242,  242,  360,  123,  123,  123,
-
-      178,  178,  178,  123,  178,  394,  123,  262,  150,  252,
-      252,  252,  262,  262,  123,  465,  168,  123,  280,  325,
-      123,  123,  166,  166,  166,  166,  166,  166,  166,  166,
-      123,  280,  479,  123,  313,  313,  178,  655,  123,  188,
-      188,  123,  582,  582,  123,  125,  188,  188,  188,  188,
-      188,  188,  394,  125,  150,  150,  150,  150,  150,  150,
-      150,  150,  168,  168,  168,  168,  168,  168,  168,  168,
-      232,  232,  232,  232,  255,  255,  255,  125,  280,  288,
-      325,  125,  125,  125,  125,  125,  125,  125,  125,  128,
-      479,  654,  288,  128,  128,  128,  174,  128,  169,  169,
-
-      169,  169,  169,  169,  169,  169,  172,  172,  172,  172,
-      172,  172,  172,  172,  258,  253,  232,  258,  258,  258,
-      649,  128,  253,  253,  253,  128,  128,  128,  128,  128,
-      128,  128,  128,  149,  272,  361,  648,  288,  299,  299,
-      299,  149,  174,  174,  174,  174,  174,  174,  174,  174,
-      175,  175,  175,  175,  175,  175,  175,  175,  304,  304,
-      304,  269,  349,  258,  369,  149,  269,  373,  647,  149,
-      149,  149,  149,  149,  149,  149,  149,  167,  361,  269,
-      266,  167,  443,  283,  278,  266,  349,  272,  392,  167,
-      392,  167,  257,  266,  167,  272,  283,  278,  284,  257,
-
-      257,  257,  167,  284,  623,  167,  443,  369,  167,  167,
-      373,  284,  286,  167,  338,  338,  338,  167,  167,  167,
-      167,  167,  167,  167,  167,  286,  167,  278,  283,  167,
-      189,  189,  167,  171,  171,  257,  279,  189,  189,  189,
-      189,  189,  171,  171,  171,  273,  171,  298,  171,  279,
-      293,  171,  293,  298,  273,  273,  273,  480,  273,  171,
-      298,  286,  171,  293,  623,  171,  171,  214,  214,  214,
-      214,  214,  214,  214,  214,  171,  281,  236,  171,  279,
-      297,  281,  297,  171,  434,  236,  171,  497,  236,  171,
-      173,  236,  236,  297,  281,  497,  434,  243,  173,  329,
-
-      281,  236,  298,  396,  622,  243,  243,  243,  276,  236,
-      636,  243,  236,  446,  646,  236,  396,  276,  276,  276,
-      480,  276,  173,  282,  281,  297,  173,  173,  173,  173,
-      173,  173,  173,  173,  176,  455,  282,  446,  176,  176,
-      176,  243,  176,  237,  237,  237,  237,  237,  237,  237,
-      237,  238,  238,  238,  238,  238,  238,  238,  238,  622,
-      329,  344,  344,  344,  643,  368,  176,  636,  282,  455,
-      176,  176,  176,  176,  176,  176,  176,  176,  218,  368,
-      282,  282,  365,  365,  365,  642,  218,  250,  250,  250,
-      250,  250,  250,  250,  250,  251,  251,  251,  251,  251,
-
-      251,  251,  251,  378,  378,  378,  439,  439,  439,  368,
-      218,  362,  362,  362,  218,  218,  218,  218,  218,  218,
-      218,  218,  230,  230,  239,  230,  230,  230,  230,  230,
-      516,  230,  230,  230,  230,  308,  230,  230,  464,  245,
-      308,  239,  516,  230,  230,  230,  230,  245,  308,  239,
-      245,  294,  239,  245,  245,  239,  239,  362,  246,  393,
-      294,  294,  294,  245,  294,  239,  460,  393,  230,  230,
-      230,  245,  393,  239,  245,  246,  239,  245,  397,  239,
-      460,  464,  640,  246,  639,  275,  246,  230,  635,  246,
-      246,  397,  230,  230,  234,  234,  234,  234,  234,  246,
-
-      234,  234,  234,  234,  234,  234,  309,  246,  234,  234,
-      246,  254,  261,  246,  634,  234,  234,  309,  234,  254,
-      254,  254,  478,  478,  478,  254,  261,  261,  261,  261,
-      261,  275,  275,  275,  275,  275,  275,  275,  275,  287,
-      234,  234,  300,  300,  300,  300,  300,  300,  300,  300,
-      330,  593,  287,  471,  330,  254,  633,  545,  291,  295,
-      632,  295,  330,  401,  234,  234,  244,  471,  295,  295,
-      295,  291,  295,  380,  387,  309,  401,  530,  651,  651,
-      244,  261,  406,  244,  387,  292,  387,  380,  630,  530,
-      287,  244,  387,  301,  244,  406,  407,  244,  244,  291,
-
-      291,  291,  291,  291,  291,  291,  291,  244,  545,  407,
-      244,  330,  593,  401,  302,  244,  417,  380,  244,  605,
-      665,  244,  256,  302,  302,  302,  407,  302,  629,  417,
-      256,  292,  292,  292,  292,  292,  292,  292,  292,  301,
-      301,  301,  301,  301,  301,  301,  301,  383,  426,  426,
-      383,  383,  383,  426,  256,  409,  621,  495,  256,  256,
-      256,  256,  256,  256,  256,  256,  277,  303,  409,  303,
-      495,  605,  665,  402,  277,  388,  303,  303,  303,  482,
-      303,  306,  410,  306,  482,  388,  402,  388,  620,  614,
-      306,  306,  306,  388,  306,  410,  383,  482,  277,  494,
-
-      409,  494,  277,  277,  277,  277,  277,  277,  277,  277,
-      289,  289,  494,  289,  289,  289,  289,  289,  289,  289,
-      289,  289,  289,  402,  289,  289,  306,  410,  650,  307,
-      423,  289,  289,  289,  289,  307,  316,  316,  307,  307,
-      307,  423,  307,  316,  316,  316,  316,  316,  342,  342,
-      342,  342,  342,  342,  342,  342,  289,  289,  289,  343,
-      343,  343,  343,  343,  343,  343,  343,  398,  398,  398,
-      398,  398,  398,  398,  398,  289,  472,  612,  371,  650,
-      289,  289,  290,  290,  307,  403,  371,  518,  472,  371,
-      403,  484,  371,  371,  550,  290,  484,  290,  611,  423,
-
-      290,  518,  371,  403,  404,  372,  685,  550,  290,  484,
-      371,  290,  382,  371,  290,  290,  371,  404,  496,  382,
-      382,  382,  372,  610,  290,  604,  603,  290,  404,  496,
-      372,  400,  290,  372,  408,  290,  372,  372,  290,  296,
-      400,  400,  400,  403,  400,  472,  372,  408,  415,  491,
-      415,  550,  404,  296,  372,  382,  296,  372,  399,  385,
-      372,  415,  491,  685,  296,  422,  416,  296,  602,  486,
-      296,  296,  416,  385,  385,  385,  385,  385,  422,  416,
-      296,  408,  486,  296,  456,  456,  456,  496,  296,  483,
-      474,  296,  474,  415,  296,  305,  600,  637,  474,  485,
-
-      599,  491,  483,  305,  399,  399,  399,  399,  399,  399,
-      399,  399,  485,  420,  486,  420,  547,  483,  547,  422,
-      485,  416,  420,  420,  420,  444,  420,  305,  385,  547,
-      456,  305,  305,  305,  305,  305,  305,  305,  305,  350,
-      350,  483,  350,  350,  350,  350,  350,  492,  350,  350,
-      350,  350,  492,  350,  350,  615,  637,  444,  420,  549,
-      350,  350,  350,  350,  421,  492,  444,  459,  459,  459,
-      421,  490,  549,  421,  421,  421,  597,  421,  588,  615,
-      444,  533,  533,  533,  490,  350,  350,  350,  499,  499,
-      548,  588,  350,  549,  596,  499,  499,  499,  499,  499,
-
-      544,  544,  544,  548,  350,  350,  596,  595,  691,  350,
-      350,  357,  357,  459,  357,  357,  357,  357,  357,  421,
-      357,  357,  357,  357,  490,  357,  357,  533,  461,  689,
-      519,  548,  357,  357,  357,  357,  461,  553,  519,  461,
-      584,  519,  461,  461,  519,  519,  594,  592,  627,  591,
-      553,  552,  461,  584,  519,  539,  555,  357,  357,  357,
-      461,  627,  519,  461,  552,  519,  461,  555,  519,  539,
-      539,  539,  539,  539,  584,  586,  616,  691,  553,  618,
-      689,  357,  357,  358,  358,  462,  358,  358,  358,  358,
-      358,  626,  358,  358,  358,  358,  552,  358,  358,  585,
-
-      616,  587,  462,  618,  358,  358,  358,  358,  552,  657,
-      462,  520,  585,  462,  587,  626,  462,  462,  679,  692,
-      581,  657,  590,  580,  539,  555,  462,  578,  520,  358,
-      358,  358,  579,  590,  462,  631,  520,  462,  576,  520,
-      462,  631,  520,  520,  589,  587,  579,  579,  579,  579,
-      579,  609,  520,  358,  358,  367,  585,  589,  608,  631,
-      520,  625,  609,  520,  638,  631,  520,  558,  558,  367,
-      575,  608,  367,  679,  558,  558,  558,  558,  558,  628,
-      367,  641,  659,  367,  659,  645,  367,  367,  692,  625,
-      628,  590,  641,  638,  644,  656,  367,  660,  652,  644,
-
-      653,  579,  589,  608,  367,  680,  656,  367,  659,  645,
-      367,  381,  666,  625,  645,  669,  574,  638,  644,  660,
-      609,  660,  573,  653,  572,  381,  669,  652,  381,  653,
-      673,  571,  680,  682,  680,  707,  381,  570,  569,  381,
-      667,  666,  381,  381,  682,  568,  666,  653,  628,  566,
-      641,  652,  381,  653,  673,  381,  681,  686,  680,  565,
-      381,  563,  562,  381,  656,  666,  381,  405,  405,  667,
-      405,  405,  405,  405,  405,  405,  405,  405,  405,  405,
-      561,  405,  405,  687,  669,  681,  686,  560,  405,  405,
-      405,  405,  559,  667,  687,  693,  557,  694,  667,  554,
-
-      695,  696,  682,  551,  707,  697,  693,  681,  694,  681,
-      686,  695,  696,  405,  405,  405,  697,  543,  542,  698,
-      405,  541,  540,  699,  700,  701,  538,  535,  531,  529,
-      698,  528,  405,  405,  699,  700,  701,  405,  405,  411,
-      411,  527,  411,  411,  411,  411,  411,  411,  411,  411,
-      411,  411,  687,  411,  411,  526,  525,  524,  523,  522,
-      411,  411,  411,  411,  693,  521,  694,  702,  703,  695,
-      696,  704,  705,  706,  697,  517,  515,  514,  702,  703,
-      513,  512,  704,  705,  706,  411,  411,  411,  698,  511,
-      510,  509,  699,  700,  701,  508,  507,  506,  505,  504,
-
-      503,  502,  501,  500,  493,  488,  477,  476,  475,  411,
-      411,  413,  413,  473,  413,  413,  413,  413,  413,  413,
-      413,  413,  413,  413,  470,  413,  413,  468,  467,  463,
-      458,  454,  413,  413,  413,  413,  702,  703,  453,  452,
-      704,  705,  706,  448,  447,  445,  442,  438,  437,  436,
-      435,  433,  432,  431,  430,  429,  428,  413,  413,  413,
-      427,  425,  424,  412,  391,  390,  389,  386,  384,  376,
-      375,  364,  363,  355,  354,  353,  352,  346,  345,  335,
-      334,  413,  413,  414,  414,  333,  332,  328,  326,  324,
-      323,  322,  321,  320,  319,  318,  414,  317,  414,  314,
-
-      310,  414,  271,  265,  263,  259,  240,  229,  228,  414,
-      227,  225,  414,  224,  221,  414,  414,  220,  219,  210,
-      209,  208,  207,  205,  204,  414,  203,  202,  201,  198,
-      197,  196,  195,  414,  194,  193,  414,  191,  190,  414,
-      419,  186,  182,  139,  137,  136,  134,  132,  131,  113,
-      112,  111,  110,  107,  419,  106,  105,  419,  104,  103,
-      102,  101,  100,   99,   90,  419,   88,   84,  419,   81,
-       80,  419,  419,   79,   76,   71,   68,   39,   26,   21,
-       20,  419,   17,   16,  419,   14,    9,    3,    0,  419,
-        0,    0,  419,    0,    0,  419,  441,    0,    0,    0,
-
+       12,   12,   15,   52,   15,   86,   15,   15,   15,   15,
+       15,   15,   40,  674,   15,   29,  153,   29,   29,   90,
+       28,   90,   29,  670,   25,   25,   90,   35,   35,   28,
+      153,   25,   55,   15,   35,   35,   35,   15,   15,   15,
+       15,   15,   15,   15,   15,   15,   15,   15,   15,   31,
+       31,  532,   31,   31,   31,   55,   99,   52,   99,   40,
+
+       15,   26,   26,   26,   26,   26,   26,   26,   26,   26,
+       26,   26,   26,   26,   26,   26,   26,   63,   84,   84,
+      144,   26,   26,   26,   26,   30,   30,   30,   30,   30,
+       32,   32,   34,   34,   32,   32,   32,   33,   34,   34,
+       34,   43,   30,  532,   26,   26,   26,   33,   33,   36,
+       36,   49,   33,   33,   33,   37,   37,   36,   36,   36,
+       33,   49,   63,   49,   37,   37,   37,  676,   49,   91,
+       91,   63,   26,   26,   27,   38,   38,   27,   27,   27,
+       27,   27,   61,   47,  669,   38,   38,  217,   47,   38,
+      144,   43,   43,   47,  663,   47,   47,  217,   43,   64,
+
+       47,   64,   64,   27,  217,   44,   64,   27,   27,   27,
+       27,   27,   27,   27,   27,   27,   27,   27,   27,   44,
+       44,   44,   44,   65,   65,   65,   65,   65,   69,   69,
+       27,   74,   61,   61,   69,   69,   69,  676,  149,   61,
+       65,   66,   66,   74,   66,   66,   66,   67,   67,   68,
+      149,   67,   67,   67,   70,   70,   76,  158,  158,   68,
+       68,   70,   70,   70,   68,   68,   68,  662,   76,   74,
+       72,   72,   68,  192,  192,   44,   48,   48,   48,   72,
+       72,   72,  660,   48,   81,   81,   81,   81,   48,   48,
+       48,   48,   48,   48,   48,   48,  193,  193,   76,   48,
+
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   95,   95,
+       95,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   51,  194,  194,   51,
+      128,   51,   77,   51,   51,   51,   51,   51,   51,   71,
+       71,   51,   73,   73,   77,  196,  196,   71,   71,   71,
+       75,  157,   73,   73,  258,   75,   73,   98,   98,   98,
+       51,  128,   75,  157,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,  110,  110,  110,  110,
+
+      271,  387,  112,  112,  112,  112,  658,   51,   62,   77,
+       78,  166,  271,   62,   79,   78,   62,   62,   62,   62,
+       62,  258,   75,  166,  323,   79,   85,   78,   79,   79,
+       79,   79,  112,   85,   85,   85,   85,   85,  113,  113,
+      113,  113,   62,  166,  273,  273,   62,   62,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,  100,  387,
+       78,   78,   96,   96,   96,  171,  176,   78,  100,   62,
+      100,  111,  113,  111,   96,  100,   96,  171,  176,  111,
+      656,   96,  111,  623,   79,   89,  323,   89,   89,   89,
+       89,   89,   89,  111,  171,  111,  123,  123,  123,  123,
+
+      167,  234,  111,  136,  136,  136,  136,  111,  118,  118,
+      118,  118,  167,  650,   89,  234,  234,  176,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+      121,  121,  121,  121,  123,  241,  124,  124,  124,  124,
+      623,   89,  106,  106,  106,  106,  106,  106,  106,  106,
+      106,  106,  106,  106,  108,  151,  649,  118,  167,  233,
+      325,  108,  325,  151,  151,  243,  241,  151,  165,  137,
+      137,  137,  137,  138,  138,  138,  138,  267,  121,  124,
+      165,  345,  233,  108,  308,  308,  267,  108,  108,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  137,
+
+      162,  162,  162,  162,  233,  243,  165,  138,  309,  309,
+      108,  127,  127,  127,  127,  127,  127,  127,  127,  127,
+      127,  127,  127,  127,  127,  127,  127,  146,  152,  568,
+      568,  127,  127,  127,  127,  329,  152,  345,  154,  185,
+      152,  146,  146,  146,  146,  146,  154,  190,  270,  329,
+      154,  185,  168,  270,  127,  127,  127,  648,  190,  163,
+      163,  163,  163,  644,  168,  270,  164,  164,  164,  164,
+      169,  169,  169,  169,  172,  172,  172,  172,  174,  174,
+      174,  174,  127,  127,  129,  129,  129,  129,  129,  163,
+      129,  129,  129,  129,  129,  129,  185,  146,  129,  129,
+
+      164,  173,  186,  189,  129,  129,  386,  129,  168,  175,
+      175,  175,  175,  173,  186,  189,  174,  190,  346,  169,
+      272,  182,  172,  187,  368,  272,  188,  129,  129,  182,
+      182,  182,  182,  182,  183,  187,  269,  272,  188,  173,
+      346,  269,  183,  183,  183,  183,  183,  609,  269,  189,
+      386,  347,  175,  357,  186,  129,  129,  131,  131,  131,
+      131,  131,  131,  131,  131,  131,  131,  131,  131,  132,
+      132,  368,  183,  347,  132,  187,  641,  132,  132,  132,
+      132,  132,  188,  132,  357,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+
+      132,  132,  132,  132,  384,  609,  384,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      132,  132,  134,  134,  134,  134,  134,  134,  134,  134,
+      134,  134,  134,  134,  135,  218,  218,  218,  218,  484,
+      265,  135,  135,  135,  135,  265,  265,  135,  484,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  219,  219,
+      219,  219,  198,  198,  432,  135,  155,  155,  155,  198,
+      198,  198,  198,  155,  220,  220,  220,  220,  155,  155,
+
+      640,  155,  155,  155,  155,  155,  435,  432,  327,  155,
+      155,  155,  155,  155,  155,  155,  155,  155,  155,  155,
+      155,  155,  155,  155,  155,  155,  155,  155,  435,  637,
+      637,  155,  155,  155,  155,  155,  155,  155,  155,  155,
+      155,  155,  155,  155,  155,  155,  155,  155,  155,  155,
+      155,  155,  155,  155,  155,  155,  159,  304,  275,  202,
+      222,  223,  223,  223,  223,  184,  202,  222,  159,  304,
+      327,  197,  197,  184,  184,  184,  184,  184,  197,  197,
+      197,  197,  197,  224,  224,  224,  224,  372,  202,  222,
+      252,  252,  252,  252,  159,  159,  159,  159,  159,  159,
+
+      159,  159,  159,  159,  159,  159,  160,  184,  275,  242,
+      242,  242,  242,  160,  304,  202,  222,  275,  317,  317,
+      317,  317,  203,  358,  388,  203,  203,  203,  203,  203,
+      239,  239,  239,  239,  372,  160,  388,  359,  388,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
+      160,  203,  242,  461,  358,  461,  230,  230,  230,  230,
+      461,  635,  160,  177,  177,  177,  177,  177,  177,  177,
+      177,  177,  177,  177,  177,  178,  178,  359,  203,  239,
+      178,  707,  707,  178,  178,  178,  178,  178,  230,  178,
+      634,  178,  178,  178,  178,  178,  178,  178,  178,  178,
+
+      178,  178,  178,  178,  178,  178,  178,  178,  178,  178,
+      360,  360,  360,  178,  178,  178,  178,  178,  178,  178,
+      178,  178,  178,  178,  178,  178,  178,  178,  178,  178,
+      178,  178,  178,  178,  178,  178,  178,  178,  180,  180,
+      180,  180,  180,  180,  180,  180,  180,  180,  180,  180,
+      181,  181,  449,  360,  444,  181,  708,  708,  181,  181,
+      181,  181,  181,  633,  181,  449,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  181,  181,  444,  632,  591,  181,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  181,
+      181,  181,  181,  221,  221,  221,  221,  221,  221,  221,
+      221,  221,  221,  221,  221,  225,  338,  338,  338,  338,
+      454,  651,  225,  366,  225,  253,  591,  286,  231,  231,
+      231,  231,  253,  253,  253,  253,  366,  531,  253,  286,
+      363,  363,  363,  363,  225,  465,  465,  465,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      231,  629,  285,  628,  366,  467,  253,  454,  283,  286,
+      651,  225,  240,  240,  285,  240,  240,  240,  240,  240,
+      283,  240,  240,  240,  240,  531,  240,  240,  288,  254,
+
+      450,  264,  240,  240,  240,  240,  254,  254,  254,  254,
+      288,  276,  254,  450,  285,  264,  264,  264,  264,  276,
+      276,  276,  276,  276,  279,  240,  240,  240,  285,  285,
+      398,  389,  279,  279,  279,  279,  279,  467,  283,  281,
+      254,  305,  398,  389,  288,  389,  240,  281,  281,  281,
+      281,  281,  305,  240,  240,  244,  244,  244,  244,  244,
+      626,  244,  244,  244,  244,  244,  244,  592,  284,  244,
+      244,  264,  282,  284,  289,  244,  244,  569,  244,  281,
+      282,  282,  282,  282,  282,  284,  289,  608,  287,  303,
+      295,  284,  295,  287,  303,  299,  301,  299,  244,  244,
+
+      287,  303,  295,  625,  414,  414,  290,  299,  301,  414,
+      621,  305,  282,  284,  290,  290,  290,  290,  290,  592,
+      620,  297,  302,  289,  369,  370,  244,  244,  245,  297,
+      297,  297,  297,  297,  302,  336,  301,  369,  370,  608,
+      569,  245,  336,  245,  245,  245,  245,  245,  245,  245,
+      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,
+      245,  245,  302,  290,  336,  369,  370,  601,  584,  245,
+      247,  247,  247,  247,  247,  247,  247,  247,  247,  247,
+      247,  247,  255,  328,  300,  709,  709,  328,  622,  601,
+      300,  336,  579,  584,  328,  255,  300,  255,  255,  255,
+
+      255,  255,  255,  255,  255,  255,  255,  255,  255,  255,
+      255,  255,  255,  255,  255,  255,  712,  712,  312,  312,
+      466,  409,  318,  255,  277,  312,  312,  312,  312,  318,
+      379,  318,  332,  409,  393,  619,  277,  300,  380,  332,
+      379,  332,  379,  622,  385,  328,  393,  379,  380,  411,
+      380,  318,  385,  636,  579,  380,  385,  445,  445,  445,
+      411,  332,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  280,  394,  466,  451,  318,  396,
+      618,  280,  393,  280,  365,  365,  487,  394,  332,  365,
+      451,  396,  365,  365,  365,  365,  665,  616,  365,  487,
+
+      445,  636,  396,  280,  448,  448,  448,  280,  280,  280,
+      280,  280,  280,  280,  280,  280,  280,  280,  280,  411,
+      615,  399,  607,  394,  396,  416,  416,  416,  416,  606,
+      280,  291,  291,  399,  291,  291,  291,  291,  291,  291,
+      291,  291,  291,  291,  377,  291,  291,  448,  665,  502,
+      399,  291,  291,  291,  291,  392,  401,  400,  377,  377,
+      377,  377,  502,  392,  392,  392,  392,  392,  401,  400,
+      402,  600,  424,  459,  291,  291,  291,  407,  481,  407,
+      481,  598,  402,  395,  424,  459,  671,  408,  395,  407,
+      481,  469,  471,  408,  477,  291,  469,  471,  401,  408,
+
+      395,  400,  291,  291,  292,  292,  477,  482,  469,  471,
+      729,  729,  402,  597,  377,  596,  292,  675,  292,  482,
+      292,  292,  292,  292,  292,  292,  292,  292,  292,  292,
+      292,  292,  292,  292,  292,  292,  292,  292,  292,  395,
+      408,  671,  602,  459,  604,  477,  292,  293,  293,  293,
+      293,  293,  293,  293,  293,  293,  293,  293,  293,  298,
+      483,  530,  530,  530,  602,  675,  604,  590,  589,  588,
+      586,  483,  298,  612,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  585,  583,  612,  581,  645,  580,  645,
+
+      298,  335,  335,  335,  335,  335,  335,  335,  335,  335,
+      335,  335,  335,  348,  348,  433,  348,  348,  348,  348,
+      348,  645,  348,  348,  348,  348,  503,  348,  348,  410,
+      483,  473,  578,  348,  348,  348,  348,  406,  406,  503,
+      476,  410,  406,  473,  433,  406,  406,  406,  406,  406,
+      472,  406,  470,  433,  476,  476,  348,  348,  348,  577,
+      478,  507,  472,  348,  470,  572,  479,  567,  517,  433,
+      472,  479,  478,  473,  566,  507,  536,  348,  348,  470,
+      582,  410,  517,  479,  348,  348,  355,  355,  536,  355,
+      355,  355,  355,  355,  582,  355,  355,  355,  355,  611,
+
+      355,  355,  470,  646,  486,  486,  355,  355,  355,  355,
+      478,  486,  486,  486,  486,  533,  534,  533,  520,  520,
+      520,  525,  535,  646,  659,  646,  611,  533,  534,  355,
+      355,  355,  536,  538,  535,  525,  525,  525,  525,  539,
+      677,  541,  564,  571,  574,  538,  659,  562,  611,  561,
+      560,  539,  541,  535,  534,  571,  574,  355,  355,  356,
+      356,  520,  356,  356,  356,  356,  356,  559,  356,  356,
+      356,  356,  575,  356,  356,  538,  570,  539,  573,  356,
+      356,  356,  356,  643,  575,  544,  544,  558,  570,  538,
+      573,  525,  544,  544,  544,  544,  613,  643,  565,  571,
+
+      631,  557,  356,  356,  356,  576,  595,  570,  613,  614,
+      677,  541,  565,  565,  565,  565,  576,  595,  556,  573,
+      614,  555,  631,  678,  554,  553,  551,  550,  631,  575,
+      356,  356,  390,  390,  390,  390,  390,  390,  390,  390,
+      390,  390,  390,  390,  397,  397,  549,  397,  397,  397,
+      397,  397,  397,  397,  397,  397,  397,  594,  397,  397,
+      627,  547,  624,  638,  397,  397,  397,  397,  565,  594,
+      546,  627,  545,  630,  617,  576,  595,  543,  630,  614,
+      617,  642,  540,  537,  529,  528,  655,  397,  397,  397,
+      624,  638,  642,  678,  397,  630,  617,  655,  693,  594,
+
+      668,  527,  617,  526,  524,  672,  522,  653,  397,  397,
+      518,  668,  624,  638,  639,  397,  397,  403,  403,  652,
+      403,  403,  403,  403,  403,  403,  403,  403,  403,  403,
+      627,  403,  403,  672,  516,  653,  639,  403,  403,  403,
+      403,  515,  639,  514,  513,  512,  511,  652,  510,  509,
+      508,  642,  652,  666,  673,  672,  655,  653,  639,  667,
+      403,  403,  403,  653,  639,  673,  679,  680,  693,  652,
+      668,  681,  682,  683,  684,  685,  506,  679,  680,  666,
+      505,  666,  681,  682,  683,  684,  685,  667,  403,  403,
+      405,  405,  504,  405,  405,  405,  405,  405,  405,  405,
+
+      405,  405,  405,  666,  405,  405,  501,  667,  500,  667,
+      405,  405,  405,  405,  499,  498,  497,  496,  495,  494,
+      493,  492,  491,  490,  673,  489,  488,  480,  475,  686,
+      464,  463,  462,  405,  405,  405,  679,  680,  460,  458,
+      686,  681,  682,  683,  684,  685,  687,  456,  453,  452,
+      447,  443,  442,  688,  689,  690,  691,  687,  692,  441,
+      437,  405,  405,  426,  688,  689,  690,  691,  436,  692,
+      434,  431,  430,  429,  428,  427,  426,  423,  426,  426,
+      426,  426,  426,  426,  426,  426,  426,  426,  426,  426,
+      426,  426,  426,  426,  426,  426,  426,  439,  439,  686,
+
+      439,  439,  439,  439,  439,  422,  439,  439,  439,  439,
+      421,  439,  439,  420,  419,  418,  687,  439,  439,  439,
+      439,  417,  415,  688,  689,  690,  691,  413,  692,  412,
+      404,  391,  383,  382,  381,  378,  376,  374,  371,  367,
+      439,  439,  439,  362,  361,  353,  352,  351,  350,  344,
+      343,  342,  341,  340,  339,  334,  333,  331,  326,  324,
+      322,  321,  320,  319,  316,  315,  314,  313,  439,  439,
+      440,  440,  310,  440,  440,  440,  440,  440,  306,  440,
+      440,  440,  440,  296,  440,  440,  294,  278,  274,  268,
+      440,  440,  440,  440,  266,  262,  261,  260,  259,  257,
+
+      256,  251,  250,  249,  238,  237,  236,  235,  232,  229,
+      228,  227,  226,  440,  440,  440,  216,  215,  214,  213,
+      440,  212,  209,  208,  207,  206,  205,  204,  200,  199,
+      195,  191,  179,  170,  440,  440,  161,  150,  148,  147,
+      145,  440,  440,  468,  468,  143,  142,  141,  140,  139,
+      126,  125,  122,  120,  119,  468,  117,  468,  116,  468,
+      468,  468,  468,  468,  468,  468,  468,  468,  468,  468,
+      468,  468,  468,  468,  468,  468,  468,  468,  474,  474,
+      115,  474,  474,  474,  474,  474,  474,  474,  474,  474,
+      474,  114,  474,  474,  103,  101,   97,   94,  474,  474,
+
+      474,  474,   93,   92,   88,   83,   80,   60,   59,   57,
+       56,   54,   53,   45,   42,   41,   39,   24,   23,   21,
+       20,  474,  474,  474,   18,   17,   14,    9,    3,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      441,    0,    0,  441,    0,    0,    0,    0,    0,    0,
-        0,  441,    0,    0,  441,    0,    0,  441,  441,    0,
-        0,    0,    0,    0,    0,    0,    0,  441,    0,    0,
-        0,    0,    0,    0,    0,  441,    0,    0,  441,    0,
-        0,  441,  450,  450,    0,  450,  450,  450,  450,  450,
-        0,  450,  450,  450,  450,    0,  450,  450,    0,    0,
-        0,    0,    0,  450,  450,  450,  450,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  450,  450,
-
-      450,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  450,  450,  451,  451,    0,  451,  451,  451,
-      451,  451,    0,  451,  451,  451,  451,    0,  451,  451,
-        0,    0,    0,    0,    0,  451,  451,  451,  451,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  474,
+      474,  587,  587,    0,  587,  587,  587,  587,  587,    0,
+      587,  587,  587,  587,    0,  587,  587,    0,    0,    0,
+        0,  587,  587,  587,  587,    0,    0,    0,    0,    0,
+        0,  587,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,  587,  587,  587,    0,    0,    0,
+
+        0,    0,    0,  587,    0,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  587,  587,  593,  593,    0,  593,  593,  593,
+      593,  593,  593,  593,  593,  593,  593,    0,  593,  593,
+        0,    0,    0,    0,  593,  593,  593,  593,    0,    0,
+        0,    0,    0,    0,  593,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  593,  593,  593,
+        0,    0,    0,    0,    0,    0,  593,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      451,  451,  451,    0,    0,    0,    0,  451,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  451,
-      451,    0,    0,    0,  451,  451,  481,    0,    0,    0,
+        0,    0,    0,    0,    0,  593,  593,  603,  603,    0,
 
+      603,  603,  603,  603,  603,    0,  603,  603,  603,  603,
+        0,  603,  603,    0,    0,    0,    0,  603,  603,  603,
+      603,    0,    0,    0,    0,    0,    0,  603,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      481,    0,    0,  481,    0,    0,    0,    0,    0,    0,
-        0,  481,    0,    0,  481,    0,    0,  481,  481,    0,
-        0,    0,    0,    0,    0,    0,    0,  481,    0,    0,
-        0,    0,    0,    0,    0,  481,    0,    0,  481,    0,
-        0,  481,  487,  487,    0,  487,  487,  487,  487,  487,
-      487,  487,  487,  487,  487,    0,  487,  487,    0,    0,
-        0,    0,    0,  487,  487,  487,  487,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  487,  487,
-
-      487,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      603,  603,  603,    0,    0,    0,    0,    0,    0,  603,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  487,  487,  489,  489,    0,  489,  489,  489,
-      489,  489,  489,  489,  489,  489,  489,    0,  489,  489,
-        0,    0,    0,    0,    0,  489,  489,  489,  489,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  603,  603,
+      610,  610,    0,  610,  610,  610,  610,  610,  610,  610,
+      610,  610,  610,    0,  610,  610,    0,    0,    0,    0,
+      610,  610,  610,  610,    0,    0,    0,    0,    0,    0,
+
+      610,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  610,  610,  610,    0,    0,    0,    0,
+        0,    0,  610,    0,    0,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      489,  489,  489,    0,    0,    0,    0,  489,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,  489,
-      489,    0,    0,    0,  489,  489,  601,  601,    0,  601,
-
-      601,  601,  601,  601,    0,  601,  601,  601,  601,    0,
-      601,  601,    0,    0,    0,    0,    0,  601,  601,  601,
-      601,    0,    0,    0,    0,    0,    0,  601,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  601,  601,  601,    0,    0,    0,    0,    0,
-        0,  601,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,  601,  601,  607,  607,
-        0,  607,  607,  607,  607,  607,  607,  607,  607,  607,
-      607,    0,  607,  607,    0,    0,    0,    0,    0,  607,
-      607,  607,  607,    0,    0,    0,    0,    0,    0,  607,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,  607,  607,  607,    0,    0,    0,
-        0,    0,    0,  607,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  607,  607,
-      617,  617,    0,  617,  617,  617,  617,  617,    0,  617,
-      617,  617,  617,    0,  617,  617,    0,    0,    0,    0,
-        0,  617,  617,  617,  617,    0,    0,    0,    0,    0,
-        0,  617,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,  617,  617,  617,    0,
-        0,    0,    0,    0,    0,  617,    0,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-      617,  617,  624,  624,    0,  624,  624,  624,  624,  624,
-      624,  624,  624,  624,  624,    0,  624,  624,    0,    0,
-        0,    0,    0,  624,  624,  624,  624,    0,    0,    0,
-        0,    0,    0,  624,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,  624,  624,
-      624,    0,    0,    0,    0,    0,    0,  624,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,  624,  624,  711,    0,    0,  711,  711,    0,
-        0,  711,  711,  711,  711,  711,  712,  712,  712,  712,
-
-      712,    0,  712,  712,  712,  712,  712,  712,  712,  712,
-      712,  713,  713,  713,  713,  713,  713,  713,  713,  713,
-      713,  713,  713,  713,  713,  713,  714,  714,  714,  714,
+        0,  610,  610,  697,    0,    0,    0,  697,  697,    0,
+        0,  697,  697,  697,  697,  697,  697,  697,  697,  698,
+      698,  698,  698,  698,    0,  698,  698,  698,  698,  698,
+      698,  698,  698,  698,  698,  698,  698,  698,  699,  699,
+        0,    0,    0,  699,  699,  699,  700,  700,  700,  700,
+      700,  700,  700,  700,  700,  700,  700,  700,  700,  700,
+
+      700,  700,  700,  700,  700,  701,  701,  701,  701,  701,
+      701,  701,  701,  701,  701,  701,  701,  701,  701,  701,
+      701,  701,  701,  701,  702,  702,  702,  702,  702,  702,
+      702,  702,  702,  702,  702,  702,  702,  702,  702,  702,
+      702,  702,  702,  703,    0,    0,    0,  703,  703,  703,
+        0,  703,  703,  703,  703,  703,  703,  703,  703,  704,
+      704,  704,  704,  704,    0,  704,  704,  704,  704,  704,
+      704,  704,  704,  704,  704,  704,  704,  704,  705,  705,
+      705,  705,  705,  705,  705,  705,  705,  705,  705,  705,
+      705,  705,  705,  705,  705,  705,  705,  706,  706,    0,
+
+        0,    0,    0,    0,    0,    0,    0,  706,    0,    0,
+      706,  706,    0,  706,  710,  710,  710,  710,  710,  710,
+      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
+      710,  710,  710,  711,  711,  711,  711,  711,  711,  711,
+      711,  711,  711,  711,  711,  711,  711,  711,  711,  711,
+      711,  711,  713,  713,  713,  713,  713,  713,  713,  713,
+      713,  713,  713,  713,  713,  713,  713,  713,  713,  713,
+      713,  714,  714,  714,  714,  714,  714,  714,  714,  714,
       714,  714,  714,  714,  714,  714,  714,  714,  714,  714,
-      714,  715,  715,  715,  715,  715,  715,  715,  715,  715,
-      715,  715,  715,  715,  715,  715,  716,    0,    0,  716,
-      716,  716,    0,  716,  716,  716,  716,  716,  717,  717,
-      717,  717,  717,    0,  717,  717,  717,  717,  717,  717,
-      717,  717,  717,  718,  718,  718,  718,  718,  718,  718,
-      718,  718,  718,  718,  718,  718,  718,  718,  719,  719,
-
-        0,    0,    0,    0,    0,    0,    0,  719,  719,  719,
-      719,  719,  720,  720,  720,  720,  720,  720,  720,  720,
-      720,  720,  720,  720,  720,  720,  720,  721,  721,  721,
+      715,  715,  715,  715,  715,  715,  715,  715,  715,  715,
+
+      715,  715,  715,  715,  715,  715,  715,  715,  715,  716,
+      716,  716,  716,  716,  716,  716,  716,  716,  716,  716,
+      716,  716,  716,  716,  716,  716,  716,  716,  717,  717,
+      717,  717,  717,  717,  717,  717,  717,  717,  717,  717,
+      717,  717,  717,  717,  717,  717,  717,  718,  718,  718,
+      718,  718,  718,  718,  718,  718,  718,  718,  718,  718,
+      718,  718,  718,  718,  718,  718,  719,  719,  719,  719,
+      719,  719,  719,  719,  719,  719,  719,  719,  719,  719,
+      719,  719,  719,  719,  719,  720,  720,    0,  720,  720,
+      720,  720,  720,  720,  720,  720,  720,  720,  720,  720,
+
+      720,  720,  720,  720,  721,  721,    0,  721,  721,  721,
       721,  721,  721,  721,  721,  721,  721,  721,  721,  721,
-      721,  721,  722,  722,  722,  722,  722,  722,  722,  722,
-      722,  722,  722,  722,  722,  722,  722,  723,  723,  723,
+      721,  721,  721,  722,    0,  722,    0,    0,    0,  722,
+      722,  722,    0,    0,  722,  723,  723,    0,  723,  723,
       723,  723,  723,  723,  723,  723,  723,  723,  723,  723,
-      723,  723,  724,  724,  724,  724,  724,  724,  724,  724,
-      724,  724,  724,  724,  724,  724,  724,  725,  725,  725,
+      723,  723,  723,  723,  724,  724,  724,  724,  724,  724,
+      724,  724,  724,  724,  724,  724,  724,  724,  724,  724,
+      724,  724,  724,  725,  725,  725,  725,  725,  725,  725,
       725,  725,  725,  725,  725,  725,  725,  725,  725,  725,
-
       725,  725,  726,  726,  726,  726,  726,  726,  726,  726,
-      726,  726,  726,  726,  726,  726,  726,  727,  727,  727,
+
+      726,  726,  726,  726,  726,  726,  726,  726,  726,  726,
+      726,  727,  727,  727,  727,  727,  727,  727,  727,  727,
       727,  727,  727,  727,  727,  727,  727,  727,  727,  727,
-      727,  727,  728,  728,    0,  728,  728,  728,  728,  728,
-      728,  728,  728,  728,  728,  728,  728,  729,  729,    0,
-      729,  729,  729,  729,  729,  729,  729,  729,  729,  729,
-      729,  729,  730,  730,    0,  730,  730,  730,  730,  730,
-      730,  730,  730,  730,  730,  730,  730,  731,  731,  731,
+      728,  728,  728,  730,    0,    0,    0,  730,    0,  730,
+      730,  730,  730,    0,  730,  731,  731,  731,  731,  731,
       731,  731,  731,  731,  731,  731,  731,  731,  731,  731,
-      731,  731,  732,  732,  732,  732,  732,  732,  732,  732,
-
-      732,  732,  732,  732,  732,  732,  732,  733,  733,  733,
-      733,  733,  733,  733,  733,  733,  733,  733,  733,  733,
-      733,  733,  734,  734,  734,  734,  734,  734,  734,  734,
-      734,  734,  734,  734,  734,  734,  734,  735,    0,    0,
-      735,    0,  735,  735,    0,    0,  735,  735,  736,  736,
+      731,  731,  731,  731,  732,  732,  732,  732,  732,  732,
+      732,  732,  732,  732,  732,  732,  732,  732,  732,  732,
+      732,  732,  732,  733,    0,    0,    0,  733,  733,  733,
+        0,  733,  733,  733,  733,  733,  733,  733,  733,  734,
+
+      734,  734,  734,  734,  734,  734,  734,  734,  734,  734,
+      734,  734,  734,  734,  734,  734,  734,  734,  735,  735,
+      735,  735,  735,  735,  735,  735,  735,  735,  735,  735,
+      735,  735,  735,  735,  735,  735,  735,  736,  736,    0,
       736,  736,  736,  736,  736,  736,  736,  736,  736,  736,
-      736,  736,  736,  737,  737,  737,  737,  737,  737,  737,
-      737,  737,  737,  737,  737,  737,  737,  737,  738,  738,
+      736,  736,  736,  736,  736,  736,  737,  737,  737,  737,
+      737,  737,  737,  737,  737,  737,  737,  737,  737,  737,
+      737,  737,  737,  737,  737,  738,  738,  738,  738,    0,
       738,  738,  738,  738,  738,  738,  738,  738,  738,  738,
-      738,  738,  738,  739,  739,  739,  739,  739,  739,  739,
-
-      739,  739,  739,  739,  739,  739,  739,  739,  740,  740,
-        0,  740,  740,  740,  740,  740,  740,  740,  740,  740,
-      740,  740,  740,  741,  741,  741,  741,  741,  741,  741,
-      741,  741,  741,  741,  741,  741,  741,  741,  742,  742,
-      742,  742,    0,  742,  742,  742,  742,  742,  742,  742,
-      742,  742,  742,  743,  743,  743,  743,  743,  743,  743,
-      743,  743,  743,  743,  743,  743,  743,  743,  744,  744,
-        0,  744,  744,  744,  744,  744,  744,  744,  744,  744,
-      744,  744,  744,  745,  745,    0,  745,  745,  745,  745,
-      745,  745,  745,  745,  745,  745,  745,  745,  746,    0,
-
-      746,    0,    0,    0,  746,  746,  746,  747,  747,    0,
+      738,  738,  738,  738,  739,  739,  739,  739,  739,  739,
+
+      739,  739,  739,  739,  739,  739,  739,  739,  739,  739,
+      739,  739,  739,  740,  740,    0,  740,  740,  740,  740,
+      740,  740,  740,  740,  740,  740,  740,  740,  740,  740,
+      740,  740,  741,  741,    0,  741,  741,  741,  741,  741,
+      741,  741,  741,  741,  741,  741,  741,  741,  741,  741,
+      741,  742,    0,  742,  742,    0,    0,  742,  742,  742,
+        0,    0,  742,  743,  743,    0,  743,  743,  743,  743,
+      743,  743,  743,  743,  743,  743,  743,  743,  743,  743,
+      743,  743,  744,  744,    0,  744,  744,  744,  744,  744,
+      744,  744,  744,  744,  744,  744,  744,  744,  744,  744,
+
+      744,  745,  745,    0,  745,  745,  745,  745,  745,  745,
+      745,  745,  745,  745,  745,  745,  745,  745,  745,  745,
+      746,  746,  746,  746,  746,  746,  746,  746,  746,  746,
+      746,  746,  746,  746,  746,  746,  746,  746,  746,  747,
       747,  747,  747,  747,  747,  747,  747,  747,  747,  747,
-      747,  747,  748,  748,    0,  748,  748,  748,  748,  748,
-      748,  748,  748,  748,  748,  748,  748,  749,  749,    0,
+      747,  747,  747,  747,  747,  747,  747,  747,  748,  748,
+      748,  748,  748,  748,  748,  748,  748,  748,  748,  748,
+      748,  748,  748,  748,  748,  748,  748,  749,  749,  749,
       749,  749,  749,  749,  749,  749,  749,  749,  749,  749,
-      749,  749,  750,  750,  750,  750,  750,  750,  750,  750,
-      750,  750,  750,  750,  750,  750,  750,  751,  751,  751,
-      751,  751,  751,  751,  751,  751,  751,  751,  751,  751,
-      751,  751,  752,  752,  752,  752,  752,  752,  752,  752,
-      752,  752,  752,  752,  752,  752,  752,  753,  753,  753,
+      749,  749,  749,  749,  749,  749,  750,  750,    0,    0,
 
+      750,  750,    0,  750,  750,  750,  750,  750,  750,  750,
+      750,  750,  751,    0,    0,    0,    0,    0,  751,  751,
+      751,  751,    0,  751,  752,  752,  752,  752,  752,  752,
+      752,  752,  752,  752,  752,  752,  752,  752,  752,  752,
+      752,  752,  752,  753,  753,  753,  753,  753,  753,  753,
       753,  753,  753,  753,  753,  753,  753,  753,  753,  753,
-      753,  753,  754,    0,    0,    0,    0,  754,  754,    0,
-        0,  754,  754,  755,  755,  755,  755,  755,  755,  755,
-      755,  755,  755,  755,  755,  755,  755,  755,  756,  756,
-      756,  756,  756,  756,  756,  756,  756,  756,  756,  756,
-      756,  756,  756,  757,  757,    0,  757,  757,  757,  757,
-      757,  757,  757,  757,  757,  757,  757,  757,  758,  758,
-        0,  758,  758,  758,  758,  758,  758,  758,  758,  758,
-      758,  758,  758,  759,  759,  759,  759,    0,  759,  759,
-      759,  759,  759,  759,  759,  759,  759,  759,  760,  760,
-
+      753,  753,  754,  754,    0,  754,  754,  754,  754,  754,
+      754,  754,  754,  754,  754,  754,  754,  754,  754,  754,
+      754,  755,  755,    0,  755,  755,  755,  755,  755,  755,
+      755,  755,  755,  755,  755,  755,  755,  755,  755,  755,
+
+      756,  756,    0,    0,  756,  756,  756,  756,  756,  756,
+      756,  756,  756,  756,  756,  756,  757,  757,  757,  757,
+        0,  757,  757,  757,  757,  757,  757,  757,  757,  757,
+      757,  757,  757,  757,  757,  758,  758,  758,  758,  758,
+      758,  758,  758,  758,  758,  758,  758,  758,  758,  758,
+      758,  758,  758,  758,  759,  759,    0,  759,  759,  759,
+      759,  759,  759,  759,  759,  759,  759,  759,  759,  759,
+      759,  759,  759,  760,  760,    0,  760,  760,  760,  760,
       760,  760,  760,  760,  760,  760,  760,  760,  760,  760,
-      760,  760,  760,  761,  761,    0,  761,  761,  761,  761,
-      761,  761,  761,  761,  761,  761,  761,  761,  762,  762,
-        0,  762,  762,  762,  762,  762,  762,  762,  762,  762,
-      762,  762,  762,  763,  763,    0,  763,  763,  763,  763,
-      763,  763,  763,  763,  763,  763,  763,  763,  764,  764,
-        0,  764,  764,  764,  764,  764,  764,  764,  764,  764,
-      764,  764,  764,  765,  765,    0,  765,  765,  765,  765,
-      765,  765,  765,  765,  765,  765,  765,  765,  766,  766,
-        0,  766,  766,  766,  766,  766,  766,  766,  766,  766,
-
-      766,  766,  766,  767,  767,    0,  767,  767,  767,  767,
-      767,  767,  767,  767,  767,  767,  767,  767,  768,  768,
-        0,  768,  768,  768,  768,  768,  768,  768,  768,  768,
-      768,  768,  768,  769,  769,  769,  769,  769,  769,  769,
-      769,  769,  769,  769,  769,  769,  769,  769,  770,  770,
-      770,  770,  770,  770,  770,  770,  770,  770,  770,  770,
-      770,  770,  770,  771,  771,  771,  771,  771,  771,  771,
-      771,  771,  771,  771,  771,  771,  771,  771,  772,    0,
-        0,    0,    0,  772,  772,    0,    0,  772,  773,  773,
+      760,  760,  761,  761,    0,  761,  761,  761,  761,  761,
+
+      761,  761,  761,  761,  761,  761,  761,  761,  761,  761,
+      761,  762,  762,    0,  762,  762,  762,  762,  762,  762,
+      762,  762,  762,  762,  762,  762,  762,  762,  762,  762,
+      763,  763,    0,  763,  763,  763,  763,  763,  763,  763,
+      763,  763,  763,  763,  763,  763,  763,  763,  763,  764,
+      764,    0,  764,  764,  764,  764,  764,  764,  764,  764,
+      764,  764,  764,  764,  764,  764,  764,  764,  765,  765,
+        0,  765,  765,  765,  765,  765,  765,  765,  765,  765,
+      765,  765,  765,  765,  765,  765,  765,  766,  766,    0,
+      766,  766,  766,  766,  766,  766,  766,  766,  766,  766,
+
+      766,  766,  766,  766,  766,  766,  767,  767,  767,  767,
+      767,  767,  767,  767,  767,  767,  767,  767,  767,  767,
+      767,  767,  767,  767,  767,  768,  768,  768,  768,  768,
+      768,  768,  768,  768,  768,  768,  768,  768,  768,  768,
+      768,  768,  768,  768,  769,  769,  769,  769,  769,  769,
+      769,  769,  769,  769,  769,  769,  769,  769,  769,  769,
+      769,  769,  769,  770,    0,    0,    0,    0,    0,  770,
+      770,  770,  770,  770,  770,  770,  770,  770,  771,  771,
+      771,  771,  771,  771,  771,  771,  771,  771,  771,  771,
+      771,  771,  771,  771,  771,  771,  771,  772,  772,  772,
+
+      772,  772,  772,  772,  772,  772,  772,  772,  772,  772,
+      772,  772,  772,  772,  772,  772,  773,  773,  773,  773,
       773,  773,  773,  773,  773,  773,  773,  773,  773,  773,
-
-      773,  773,  773,  774,  774,  774,  774,  774,  774,  774,
-      774,  774,  774,  774,  774,  774,  774,  774,  775,  775,
-        0,  775,  775,  775,  775,  775,  775,  775,  775,  775,
-      775,  775,  775,  776,  776,  776,  776,  776,  776,  776,
-      776,  776,  776,  776,  776,  776,  776,  776,  777,    0,
-        0,    0,    0,  777,  777,    0,    0,  777,  778,  778,
-        0,  778,  778,  778,  778,  778,  778,  778,  778,  778,
-      778,  778,  778,  779,  779,  779,  779,  779,  779,  779,
-      779,  779,  779,  779,  779,  779,  779,  779,  780,  780,
-        0,  780,  780,  780,  780,  780,  780,  780,  780,  780,
-
-      780,  780,  780,  781,  781,    0,  781,  781,  781,  781,
+      773,  773,  773,  773,  773,  774,    0,    0,    0,    0,
+        0,  774,  774,  774,  774,  775,  775,    0,  775,  775,
+      775,  775,  775,  775,  775,  775,  775,  775,  775,  775,
+      775,  775,  775,  775,  776,  776,  776,  776,  776,  776,
+      776,  776,  776,  776,  776,  776,  776,  776,  776,  776,
+      776,  776,  776,  777,  777,    0,  777,  777,  777,  777,
+      777,  777,  777,  777,  777,  777,  777,  777,  777,  777,
+
+      777,  777,  778,  778,    0,  778,  778,  778,  778,  778,
+      778,  778,  778,  778,  778,  778,  778,  778,  778,  778,
+      778,  779,  779,    0,  779,  779,  779,  779,  779,  779,
+      779,  779,  779,  779,  779,  779,  779,  779,  779,  779,
+      780,  780,  780,  780,  780,  780,  780,  780,  780,  780,
+      780,  780,  780,  780,  780,  780,  780,  780,  780,  781,
+      781,  781,  781,  781,  781,  781,  781,  781,  781,  781,
       781,  781,  781,  781,  781,  781,  781,  781,  782,  782,
-        0,  782,  782,  782,  782,  782,  782,  782,  782,  782,
-      782,  782,  782,  783,  783,  783,  783,  783,  783,  783,
-      783,  783,  783,  783,  783,  783,  783,  783,  784,  784,
-      784,  784,  784,  784,  784,  784,  784,  784,  784,  784,
-      784,  784,  784,  785,  785,  785,  785,  785,  785,  785,
-      785,  785,  785,  785,  785,  785,  785,  785,  786,  786,
-      786,  786,  786,  786,  786,  786,  786,  786,  786,  786,
-      786,  786,  786,  710,  710,  710,  710,  710,  710,  710,
-
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710,  710,  710,  710,  710,
-      710,  710,  710,  710,  710,  710
+      782,  782,  782,  782,  782,  782,  782,  782,  782,  782,
+      782,  782,  782,  782,  782,  782,  782,  783,  783,  783,
+
+      783,  783,  783,  783,  783,  783,  783,  783,  783,  783,
+      783,  783,  783,  783,  783,  783,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696,
+      696,  696,  696,  696,  696,  696,  696,  696,  696,  696
     } ;
 
 static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
@@ -1681,9 +1707,7 @@ goto find_rule; \
 #define YY_MORE_ADJ 0
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
-#line 1 "../parser.l"
 #define INITIAL 0
-#line 8 "../parser.l"
 /*
  * parser.l -- lex parser of algebraic chess moves for XBoard
  * $Id: parser.l,v 2.1 2003/10/27 19:21:00 mann Exp $
@@ -1735,6 +1759,16 @@ char *yytext;
 /* This parser handles all forms of promotion.
  * The parser resolves ambiguous moves by searching and check-testing.
  * It also parses comments of the form [anything] or (anything).
+ *
+ * [HGM] Parser extensively modified for bigger boards, Shogi-like syntax,
+ * and unknow pieces. All pieces are now mandatory upper case, but can be
+ * any letter A-Z. Files must be lower case (as before), but can run upto 'l'.
+ * Ranks can be 0-9. The parser returns 0 for off-board files and ranks.
+ * For an unknown piece (as mover or promotion piece) it returns
+ * IllegalMove, like it does when the piece doesn't match.
+ * Promotions can now also be appended Shogi-style, a bare '=' or '+',
+ * and this is then returned as promotion character. The piece indicator
+ * can be prefixed by a '+' to indicate it is a promoted piece.
  */
 
 #include "config.h"
@@ -1831,7 +1865,6 @@ int yyback P((int *, int));
 int yywrap P((void));
 extern void CopyBoard P((Board to, Board from));
 
-#line 1835 "lex.yy.c"
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -1931,9 +1964,20 @@ YY_MALLOC_DECL
                        YY_FATAL_ERROR( "input in flex scanner failed" ); \
                result = n; \
                } \
-       else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
-                 && ferror( yyin ) ) \
-               YY_FATAL_ERROR( "input in flex scanner failed" );
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }
 #endif
 
 /* No semi-colon after return; correct usage is to write "yyterminate();" -
@@ -1982,13 +2026,11 @@ YY_MALLOC_DECL
 YY_DECL
        {
        register yy_state_type yy_current_state;
-       register char *yy_cp = NULL, *yy_bp = NULL;
+       register char *yy_cp, *yy_bp;
        register int yy_act;
 
-#line 156 "../parser.l"
 
 
-#line 1992 "lex.yy.c"
 
        if ( yy_init )
                {
@@ -2037,14 +2079,14 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 711 )
+                               if ( yy_current_state >= 697 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        *yy_state_ptr++ = yy_current_state;
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 4394 );
+               while ( yy_base[yy_current_state] != 4517 );
 
 yy_find_action:
                yy_current_state = *--yy_state_ptr;
@@ -2095,55 +2137,83 @@ do_action:      /* This label is used only to access EOF actions. */
        { /* beginning of action switch */
 case 1:
 YY_RULE_SETUP
-#line 158 "../parser.l"
 {
     /*
      * Fully-qualified algebraic move, possibly with promotion
      */
-    int skip1 = 0, skip2 = 0;
+    int skip1 = 0, skip2 = 0, skip3 = 0, promoted = 0;
     ChessSquare piece;
     ChessMove result;
-
+    char c;
+    
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
-    /* remove the / */
-    if (yytext[1] == '/') skip1 = 1;
+    if (yytext[0] == '+') skip1 = skip3 = promoted = 1; /* [HGM] Shogi promoted */
 
+    /* remove the / */
+    if (yytext[1+skip1] == '/')  skip1++; 
+    
     /* remove the [xX:-] */
     if ((yytext[3+skip1] == 'x') || (yytext[3+skip1] == 'X') ||
-       (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1;
-
+        (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1;
+    
     currentMoveString[0] = yytext[1+skip1];
     currentMoveString[1] = yytext[2+skip1];
     currentMoveString[2] = yytext[3+skip1+skip2];
     currentMoveString[3] = yytext[4+skip1+skip2];
     currentMoveString[4] = NULLCHAR;
+    
+    if (appData.debugMode) {
+        fprintf(debugFP, "Parser Qa1b2: yyleng=%d\n",
+        yyleng);
+    }
 
-    if (yyleng-skip1-skip2 > 5) {
-       if (yytext[yyleng-1] == ')') {
-           currentMoveString[4] = ToLower(yytext[yyleng-2]);
+    if (yyleng-skip1-skip2 > 5) { char c;
+        if (yytext[yyleng-1] == ')') {
+            c = currentMoveString[4] = ToLower(yytext[yyleng-2]);
        } else {
-           currentMoveString[4] = ToLower(yytext[yyleng-1]);
+            c = currentMoveString[4] = ToLower(yytext[yyleng-1]);
        }
        currentMoveString[5] = NULLCHAR;
+        if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare)
+            return IllegalMove; /* [HGM] promotion to invalid piece */
+    }
+
+    if (appData.debugMode) {
+        fprintf(debugFP, "parser: %s\n", currentMoveString);
     }
+    /* [HGM] do not allow values beyond board size */
+    if(currentMoveString[1] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[1] - ONE <  0            ||
+       currentMoveString[0] - AAA >= BOARD_RGHT   ||
+       currentMoveString[3] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[3] - ONE <  0            ||
+       currentMoveString[2] - AAA >= BOARD_RGHT   ||
+       currentMoveString[0] - AAA <  BOARD_LEFT   ||
+       currentMoveString[2] - AAA <  BOARD_LEFT     )
+      return 0;
 
     piece = boards[yyboardindex]
-      [currentMoveString[1] - '1'][currentMoveString[0] - 'a'];
-    if (ToLower(yytext[0]) != ToLower(PieceToChar(piece)))
+      [currentMoveString[1] - ONE][currentMoveString[0] - AAA];
+    if(promoted) piece = (ChessSquare) (DEMOTED piece);
+    c = PieceToChar(piece);
+    if(c == '~') c = PieceToChar((ChessSquare) (DEMOTED piece));
+    if (ToLower(yytext[skip3]) != ToLower(c))
       return (int) IllegalMove;
 
     result = LegalityTest(boards[yyboardindex],
                          PosFlags(yyboardindex), EP_UNKNOWN,
-                         currentMoveString[1] - '1',
-                         currentMoveString[0] - 'a',
-                         currentMoveString[3] - '1',
-                         currentMoveString[2] - 'a',
+                          initialRights, /* [HGM] assume all castlings allowed */
+                          currentMoveString[1] - ONE,
+                          currentMoveString[0] - AAA,
+                          currentMoveString[3] - ONE,
+                          currentMoveString[2] - AAA,
                          currentMoveString[4]);
 
     if (currentMoveString[4] == NULLCHAR &&
-       (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
-       currentMoveString[4] = 'q';
+        (result == WhitePromotionKnight || result == BlackPromotionKnight ||
+         result == WhitePromotionQueen  || result == BlackPromotionQueen)) {
+        currentMoveString[4] = PieceToChar(BlackQueen);
        currentMoveString[5] = NULLCHAR;
     }
 
@@ -2152,10 +2222,10 @@ YY_RULE_SETUP
        YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 212 "../parser.l"
 {
     /*
      * Simple algebraic move, possibly with promotion
+     * [HGM] Engine moves are received in this format, with lower-case promoChar!
      */
     int skip = 0;
     ChessMove result;
@@ -2172,26 +2242,44 @@ YY_RULE_SETUP
     currentMoveString[3] = yytext[3+skip];
     currentMoveString[4] = NULLCHAR;
 
-    if (yyleng-skip > 4) {
+    if (yyleng-skip > 4) { char c;
        if (yytext[yyleng-1] == ')') {
-           currentMoveString[4] = ToLower(yytext[yyleng-2]);
+            c = currentMoveString[4] = ToLower(yytext[yyleng-2]);
        } else {
-           currentMoveString[4] = ToLower(yytext[yyleng-1]);
+            c = currentMoveString[4] = ToLower(yytext[yyleng-1]);
        }
        currentMoveString[5] = NULLCHAR;
+        if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare)
+            return IllegalMove;
     }
 
+    /* [HGM] do not allow values beyond board size */
+    if(currentMoveString[1] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[1] - ONE <  0            ||
+       currentMoveString[0] - AAA >= BOARD_RGHT   ||
+       currentMoveString[3] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[3] - ONE <  0            ||
+       currentMoveString[2] - AAA >= BOARD_RGHT   ||
+       currentMoveString[0] - AAA <  BOARD_LEFT   ||
+       currentMoveString[2] - AAA <  BOARD_LEFT     )
+      return 0;
+
     result = LegalityTest(boards[yyboardindex],
                          PosFlags(yyboardindex), EP_UNKNOWN,
-                         currentMoveString[1] - '1',
-                         currentMoveString[0] - 'a',
-                         currentMoveString[3] - '1',
-                         currentMoveString[2] - 'a',
+                          initialRights, /* [HGM] assume all castlings allowed */
+                          currentMoveString[1] - ONE,
+                          currentMoveString[0] - AAA,
+                          currentMoveString[3] - ONE,
+                          currentMoveString[2] - AAA,
                          currentMoveString[4]);
 
     if (currentMoveString[4] == NULLCHAR &&
-       (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
-       currentMoveString[4] = 'q';
+        (result == WhitePromotionKnight || result == BlackPromotionKnight ||
+         result == WhitePromotionQueen  || result == BlackPromotionQueen)) {
+        if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)
+            currentMoveString[4] = PieceToChar(BlackFerz);
+        else
+            currentMoveString[4] = PieceToChar(BlackQueen);
        currentMoveString[5] = NULLCHAR;
     }
 
@@ -2200,33 +2288,44 @@ YY_RULE_SETUP
        YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 257 "../parser.l"
 {
     /*
      * Pawn move, possibly with promotion
      */
     DisambiguateClosure cl;
-    int skip = 0;
+    int skip = 0; char c;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
     /* remove the =() */
-    if (yytext[2] == '=') skip++;
+    if (yytext[2] == '=' && yytext[3] != NULLCHAR) skip++;
     if (yytext[2+skip] == '(') skip++;
 
     cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn;
     cl.rfIn = -1;
-    cl.ffIn = yytext[0] - 'a';
-    cl.rtIn = yytext[1] - '1';
-    cl.ftIn = yytext[0] - 'a';
-    cl.promoCharIn = yytext[2+skip];
+    cl.ffIn = yytext[0] - AAA;
+    cl.rtIn = yytext[1] - ONE;
+    cl.ftIn = yytext[0] - AAA;
+    c = cl.promoCharIn = yytext[2+skip];
+
+    /* [HGM] do not allow values beyond board size */
+    if(cl.rtIn >= BOARD_HEIGHT ||
+       cl.rtIn <  0            ||
+       cl.ffIn >= BOARD_RGHT   ||
+       cl.ftIn <  BOARD_LEFT     )
+      return 0;
+
+    if(c != '=' && c != '+' && c != NULLCHAR && CharToPiece(c) == EmptySquare)
+      return IllegalMove;
+
+
     Disambiguate(boards[yyboardindex],
                 PosFlags(yyboardindex), EP_UNKNOWN, &cl);
 
-    currentMoveString[0] = cl.ff + 'a';
-    currentMoveString[1] = cl.rf + '1';
-    currentMoveString[2] = cl.ft + 'a';
-    currentMoveString[3] = cl.rt + '1';
+    currentMoveString[0] = cl.ff + AAA;
+    currentMoveString[1] = cl.rf + ONE;
+    currentMoveString[2] = cl.ft + AAA;
+    currentMoveString[3] = cl.rt + ONE;
     currentMoveString[4] = cl.promoChar;
     currentMoveString[5] = NULLCHAR;
 
@@ -2235,13 +2334,12 @@ YY_RULE_SETUP
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 290 "../parser.l"
 {
     /*
      * Pawn capture, possibly with promotion, possibly ambiguous
      */
     DisambiguateClosure cl;
-    int skip1 = 0, skip2 = 0;
+    int skip1 = 0, skip2 = 0; char c;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
@@ -2257,22 +2355,33 @@ YY_RULE_SETUP
     /* remove the [xX:-] and =() */
     if ((yytext[1] == 'x') || (yytext[1] == 'X')
        || (yytext[1] == ':') || (yytext[1] == '-')) skip1 = 1;
-    if (yytext[2+skip1] == '=') skip2++;
+    if (yytext[2+skip1] == '=' && yytext[3+skip1] != NULLCHAR) skip2++;
     if (yytext[2+skip1+skip2] == '(') skip2++;
 
     cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn;
     cl.rfIn = -1;
-    cl.ffIn = yytext[0] - 'a';
+    cl.ffIn = yytext[0] - AAA;
     cl.rtIn = -1;
-    cl.ftIn = yytext[1+skip1] - 'a';
-    cl.promoCharIn = yytext[2+skip1+skip2];
+    cl.ftIn = yytext[1+skip1] - AAA;
+    c = cl.promoCharIn = yytext[2+skip1+skip2];
+
+    /* [HGM] do not allow values beyond board size */
+    if(cl.ffIn >= BOARD_RGHT  ||
+       cl.ffIn <  BOARD_LEFT  ||
+       cl.ftIn >= BOARD_RGHT  ||
+       cl.ftIn <  BOARD_LEFT     )
+      return 0;
+
+    if(c != '=' && c != '+' && c != NULLCHAR && CharToPiece(c) == EmptySquare)
+      return IllegalMove;
+
     Disambiguate(boards[yyboardindex],
                 PosFlags(yyboardindex), EP_UNKNOWN, &cl);
 
-    currentMoveString[0] = cl.ff + 'a';
-    currentMoveString[1] = cl.rf + '1';
-    currentMoveString[2] = cl.ft + 'a';
-    currentMoveString[3] = cl.rt + '1';
+    currentMoveString[0] = cl.ff + AAA;
+    currentMoveString[1] = cl.rf + ONE;
+    currentMoveString[2] = cl.ft + AAA;
+    currentMoveString[3] = cl.rt + ONE;
     currentMoveString[4] = cl.promoChar;
     currentMoveString[5] = NULLCHAR;
 
@@ -2281,13 +2390,12 @@ YY_RULE_SETUP
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 333 "../parser.l"
 {
     /*
      * unambiguously abbreviated Pawn capture, possibly with promotion
      */
     int skip = 0;
-    ChessMove result;
+    ChessMove result; char c;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
@@ -2307,34 +2415,53 @@ YY_RULE_SETUP
     currentMoveString[0] = yytext[0];
     currentMoveString[2] = yytext[1+skip];
     currentMoveString[3] = yytext[2+skip];
+
+    /* [HGM] do not allow values beyond board size */
+    if(currentMoveString[0] - AAA >= BOARD_RGHT   ||
+       currentMoveString[3] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[3] - ONE <  0            ||
+       currentMoveString[2] - AAA >= BOARD_RGHT   ||
+       currentMoveString[0] - AAA <  BOARD_LEFT   ||
+       currentMoveString[2] - AAA <  BOARD_LEFT     )
+      return 0;
+
+    if (gameInfo.variant == VariantXiangqi && /* [HGM] In Xiangqi rank stays same */
+         currentMoveString[0] != currentMoveString[2] ) {
+        if (yytext[2+skip] == ONE) return (int) ImpossibleMove;
+        currentMoveString[1] = yytext[2+skip];
+    } else 
     if (WhiteOnMove(yyboardindex)) {
-       if (yytext[2+skip] == '1') return (int) ImpossibleMove;
+        if (yytext[2+skip] == ONE) return (int) ImpossibleMove;
        currentMoveString[1] = yytext[2+skip] - 1;
     } else {
-       if (yytext[2+skip] == '8') return (int) ImpossibleMove;
-       currentMoveString[1] = yytext[2+skip] + 1;
+        currentMoveString[1] = currentMoveString[3] + 1;
+        if (currentMoveString[3] == ONE+BOARD_HEIGHT-1) return (int) ImpossibleMove;
     }
     if (yyleng-skip > 3) {
        if (yytext[yyleng-1] == ')')
-         currentMoveString[4] = ToLower(yytext[yyleng-2]);
+          c = currentMoveString[4] = ToLower(yytext[yyleng-2]);
        else
-         currentMoveString[4] = ToLower(yytext[yyleng-1]);
+          c = currentMoveString[4] = ToLower(yytext[yyleng-1]);
        currentMoveString[5] = NULLCHAR;
+        if(c != '=' && c != '+' && CharToPiece(c) == EmptySquare)
+            return IllegalMove;
     } else {
        currentMoveString[4] = NULLCHAR;
     }
 
     result = LegalityTest(boards[yyboardindex],
                          PosFlags(yyboardindex), EP_UNKNOWN,
-                         currentMoveString[1] - '1',
-                         currentMoveString[0] - 'a',
-                         currentMoveString[3] - '1',
-                         currentMoveString[2] - 'a',
+                          initialRights, /* [HGM] assume all castlings allowed */
+                          currentMoveString[1] - ONE,
+                          currentMoveString[0] - AAA,
+                          currentMoveString[3] - ONE,
+                          currentMoveString[2] - AAA,
                          currentMoveString[4]);
 
     if (currentMoveString[4] == NULLCHAR &&
-       (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
-       currentMoveString[4] = 'q';
+        (result == WhitePromotionQueen  || result == BlackPromotionQueen ||
+         result == WhitePromotionKnight || result == BlackPromotionKnight)) {
+        currentMoveString[4] = PieceToChar(BlackQueen);
        currentMoveString[5] = NULLCHAR;
     }
 
@@ -2359,10 +2486,11 @@ YY_RULE_SETUP
 
     result = LegalityTest(boards[yyboardindex],
                          PosFlags(yyboardindex), EP_UNKNOWN,
-                         currentMoveString[1] - '1',
-                         currentMoveString[0] - 'a',
-                         currentMoveString[3] - '1',
-                         currentMoveString[2] - 'a',
+                          initialRights, /* [HGM] assume all castlings allowed */
+                          currentMoveString[1] - ONE,
+                          currentMoveString[0] - AAA,
+                          currentMoveString[3] - ONE,
+                          currentMoveString[2] - AAA,
                          currentMoveString[4]);
 
     if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant)
@@ -2373,37 +2501,57 @@ YY_RULE_SETUP
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 422 "../parser.l"
 {
     /*
      * piece move, possibly ambiguous
      */
     DisambiguateClosure cl;
-    int skip = 0;
+    int skip = 0, skip2 = 0, promoted = 0;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
+    if(yytext[0] == '+') promoted = skip = skip2 = 1;
+
     /* remove the [xX:-] */
-    if ((yytext[1] == 'x') || (yytext[1] == 'X')
-       || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1;
+    if ((yytext[1+skip] == 'x') || (yytext[1+skip] == 'X')
+        || (yytext[1+skip] == ':') || (yytext[1+skip] == '-')) skip++;
 
     if (WhiteOnMove(yyboardindex)) {
-       cl.pieceIn = CharToPiece(ToUpper(yytext[0]));
+        cl.pieceIn = CharToPiece(ToUpper(yytext[skip2]));
     } else {
-       cl.pieceIn = CharToPiece(ToLower(yytext[0]));
+        cl.pieceIn = CharToPiece(ToLower(yytext[skip2]));
     }
+    if(promoted) cl.pieceIn = (ChessSquare) (PROMOTED cl.pieceIn);
+
     cl.rfIn = -1;
     cl.ffIn = -1;
-    cl.rtIn = yytext[2+skip] - '1';
-    cl.ftIn = yytext[1+skip] - 'a';
+    cl.rtIn = yytext[2+skip] - ONE;
+    cl.ftIn = yytext[1+skip] - AAA;
     cl.promoCharIn = NULLCHAR;
+
+    if(yyleng-skip > 3) /* [HGM] can have Shogi-style promotion */
+        cl.promoCharIn = yytext[yyleng-1];
+
+    if (appData.debugMode) {
+        fprintf(debugFP, "Parser Qa1: yyleng=%d,  %d(%d,%d)-(%d,%d) = %d (%c)\n",
+        yyleng,
+        cl.pieceIn,cl.ffIn,cl.rfIn,cl.ftIn,cl.rtIn,cl.promoCharIn,cl.promoCharIn?cl.promoCharIn:' ');
+    }
+
+    /* [HGM] but do not allow values beyond board size */
+    if(cl.rtIn >= BOARD_HEIGHT ||
+       cl.rtIn <  0            ||
+       cl.ftIn >= BOARD_RGHT   ||
+       cl.ftIn <  BOARD_LEFT     )
+      return 0;
+
     Disambiguate(boards[yyboardindex],
                 PosFlags(yyboardindex), EP_UNKNOWN, &cl);
 
-    currentMoveString[0] = cl.ff + 'a';
-    currentMoveString[1] = cl.rf + '1';
-    currentMoveString[2] = cl.ft + 'a';
-    currentMoveString[3] = cl.rt + '1';
+    currentMoveString[0] = cl.ff + AAA;
+    currentMoveString[1] = cl.rf + ONE;
+    currentMoveString[2] = cl.ft + AAA;
+    currentMoveString[3] = cl.rt + ONE;
     currentMoveString[4] = cl.promoChar;
     currentMoveString[5] = NULLCHAR;
 
@@ -2412,42 +2560,61 @@ YY_RULE_SETUP
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 458 "../parser.l"
 {
     /*
      * piece move with rank or file disambiguator
      */
     DisambiguateClosure cl;
-    int skip = 0;
+    int skip = 0, skip2 = 0; int promoted=0;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
+    if(yytext[0]=='+') promoted = skip = skip2 = 1;
+
     /* remove the [xX:-] */
-    if ((yytext[2] == 'x') || (yytext[2] == 'X')
-       || (yytext[2] == ':') || (yytext[2] == '-')) skip = 1;
+    if ((yytext[2+skip] == 'x') || (yytext[2+skip] == 'X')
+        || (yytext[2+skip] == ':') || (yytext[2+skip] == '-')) skip++;
 
     if (WhiteOnMove(yyboardindex)) {
-       cl.pieceIn = CharToPiece(ToUpper(yytext[0]));
+        cl.pieceIn = CharToPiece(ToUpper(yytext[skip2]));
     } else {
-       cl.pieceIn = CharToPiece(ToLower(yytext[0]));
+        cl.pieceIn = CharToPiece(ToLower(yytext[skip2]));
     }
-    if (isalpha(yytext[1])) {
+    if(promoted) cl.pieceIn = (ChessSquare) (PROMOTED cl.pieceIn);
+
+    if (isalpha(yytext[1+skip2])) {
        cl.rfIn = -1;
-       cl.ffIn = yytext[1] - 'a';
+        cl.ffIn = yytext[1+skip2] - AAA;
+       
+        if(cl.ffIn >= BOARD_RGHT ||
+           cl.ffIn <  BOARD_LEFT   ) return 0;
     } else {
-       cl.rfIn = yytext[1] - '1';
+        cl.rfIn = yytext[1+skip2] - ONE;
        cl.ffIn = -1;
+        if(cl.rfIn >= BOARD_HEIGHT ||
+           cl.rfIn <  0) return 0;
     }
-    cl.rtIn = yytext[3+skip] - '1';
-    cl.ftIn = yytext[2+skip] - 'a';
+    cl.rtIn = yytext[3+skip] - ONE;
+    cl.ftIn = yytext[2+skip] - AAA;
     cl.promoCharIn = NULLCHAR;
+
+    if(yyleng-skip > 4) /* [HGM] can have Shogi-style promotion */
+        cl.promoCharIn = yytext[yyleng-1];
+
+    /* [HGM] do not allow values beyond board size */
+    if(cl.rtIn >= BOARD_HEIGHT ||
+       cl.rtIn <  0            ||
+       cl.ftIn >= BOARD_RGHT   ||
+       cl.ftIn <  BOARD_LEFT     )
+      return 0;
+
     Disambiguate(boards[yyboardindex],
                 PosFlags(yyboardindex), EP_UNKNOWN, &cl);
 
-    currentMoveString[0] = cl.ff + 'a';
-    currentMoveString[1] = cl.rf + '1';
-    currentMoveString[2] = cl.ft + 'a';
-    currentMoveString[3] = cl.rt + '1';
+    currentMoveString[0] = cl.ff + AAA;
+    currentMoveString[1] = cl.rf + ONE;
+    currentMoveString[2] = cl.ft + AAA;
+    currentMoveString[3] = cl.rt + ONE;
     currentMoveString[4] = cl.promoChar;
     currentMoveString[5] = NULLCHAR;
 
@@ -2456,101 +2623,135 @@ YY_RULE_SETUP
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 499 "../parser.l"
 {
     int rf, ff, rt, ft;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
+    /* [HGM] all squares referenced to board edges in stead of absolute */
     if (WhiteOnMove(yyboardindex)) {
-       if (boards[yyboardindex][0][3] == WhiteKing) {
+        if (boards[yyboardindex][0][(BOARD_WIDTH-1)>>1] == WhiteKing) {
            /* ICS wild castling */
-           strcpy(currentMoveString, "d1f1");
            rf = 0;
-           ff = 3;
+            ff = (BOARD_WIDTH-1)>>1;
            rt = 0;
-           ft = 5;
+            ft = BOARD_RGHT-3;
        } else {
-           strcpy(currentMoveString, "e1c1");
            rf = 0;
-           ff = 4;
+            ff = BOARD_WIDTH>>1;
            rt = 0;
-           ft = 2;
+            ft = BOARD_LEFT+2;
        }
-    } else{
-       if (boards[yyboardindex][7][3] == BlackKing) {
+    } else{ 
+        if (boards[yyboardindex][BOARD_HEIGHT-1][(BOARD_WIDTH-1)>>1] == BlackKing) {
            /* ICS wild castling */
-           strcpy(currentMoveString, "d8f8");
-           rf = 7;
-           ff = 3;
-           rt = 7;
-           ft = 5;
+            rf = BOARD_HEIGHT-1;
+            ff = (BOARD_WIDTH-1)>>1;
+            rt = BOARD_HEIGHT-1;
+            ft = BOARD_RGHT-3;
        } else {
-           strcpy(currentMoveString, "e8c8");
-           rf = 7;
-           ff = 4;
-           rt = 7;
-           ft = 2;
+            rf = BOARD_HEIGHT-1;
+            ff = BOARD_WIDTH>>1;
+            rt = BOARD_HEIGHT-1;
+            ft = BOARD_LEFT+2;
        }
     }
+    if(gameInfo.variant == VariantFischeRandom) {
+        if (WhiteOnMove(yyboardindex)) {
+            ff = initialRights[2];
+            ft = initialRights[1];
+        } else {
+            ff = initialRights[5];
+            ft = initialRights[4];
+        }
+        fprintf(debugFP, "Parser FRC long %d %d\n", ff, ft);
+        if(ff < 0 || ft < 0) return 0;
+    }
+    sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);
+    if (appData.debugMode) {
+        fprintf(debugFP, "long castling %d %d\n", ff, ft);
+    }
     return (int) LegalityTest(boards[yyboardindex],
                              PosFlags(yyboardindex), EP_UNKNOWN,
+                              castlingRights[yyboardindex], /* [HGM] use true castling rights */
                              rf, ff, rt, ft, NULLCHAR);
 }
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 540 "../parser.l"
 {
     int rf, ff, rt, ft;
 
     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
 
     if (WhiteOnMove(yyboardindex)) {
-       if (boards[yyboardindex][0][3] == WhiteKing) {
+        if (boards[yyboardindex][0][(BOARD_WIDTH-1)>>1] == WhiteKing) {
            /* ICS wild castling */
-           strcpy(currentMoveString, "d1b1");
            rf = 0;
-           ff = 3;
+            ff = (BOARD_WIDTH-1)>>1;
            rt = 0;
-           ft = 1;
+            ft = BOARD_LEFT+1;
        } else {
-           strcpy(currentMoveString, "e1g1");
            rf = 0;
-           ff = 4;
+            ff = BOARD_WIDTH>>1;
            rt = 0;
-           ft = 6;
+            ft = BOARD_RGHT-2;
        }
     } else {
-       if (boards[yyboardindex][7][3] == BlackKing) {
+        if (boards[yyboardindex][BOARD_HEIGHT-1][(BOARD_WIDTH-1)>>1] == BlackKing) {
            /* ICS wild castling */
-           strcpy(currentMoveString, "d8b8");
-           rf = 7;
-           ff = 3;
-           rt = 7;
-           ft = 1;
+            rf = BOARD_HEIGHT-1;
+            ff = (BOARD_WIDTH-1)>>1;
+            rt = BOARD_HEIGHT-1;
+            ft = BOARD_LEFT+1;
        } else {
-           strcpy(currentMoveString, "e8g8");
-           rf = 7;
-           ff = 4;
-           rt = 7;
-           ft = 6;
+            rf = BOARD_HEIGHT-1;
+            ff = BOARD_WIDTH>>1;
+            rt = BOARD_HEIGHT-1;
+            ft = BOARD_RGHT-2;
        }
     }
+    if(gameInfo.variant == VariantFischeRandom) {
+        if (WhiteOnMove(yyboardindex)) {
+            ff = initialRights[2];
+            ft = initialRights[0];
+        } else {
+            ff = initialRights[5];
+            ft = initialRights[3];
+        }
+    if (appData.debugMode) {
+        fprintf(debugFP, "Parser FRC short %d %d\n", ff, ft);
+    }
+        if(ff < 0 || ft < 0) return 0;
+    }
+    sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);
+    if (appData.debugMode) {
+        fprintf(debugFP, "short castling %d %d\n", ff, ft);
+    }
+
     return (int) LegalityTest(boards[yyboardindex],
-                             PosFlags(yyboardindex), EP_UNKNOWN,
+                              PosFlags(yyboardindex), EP_UNKNOWN,
+                              castlingRights[yyboardindex], /* [HGM] use true castling rights */
                              rf, ff, rt, ft, NULLCHAR);
 }
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 581 "../parser.l"
 {
     /* Bughouse piece drop.  No legality checking for now. */
     currentMoveString[1] = '@';
     currentMoveString[2] = yytext[2];
     currentMoveString[3] = yytext[3];
     currentMoveString[4] = NULLCHAR;
+
+    if (appData.debugMode) {
+        fprintf(debugFP, "Drop: %s\n", currentMoveString);
+    }
+    /* [HGM] do not allow values beyond board size */
+    if(currentMoveString[3] - ONE >= BOARD_HEIGHT ||
+       currentMoveString[2] - AAA >= BOARD_WIDTH     )
+      return 0;
+
     if (WhiteOnMove(yyboardindex)) {
        currentMoveString[0] = ToUpper(yytext[0]);
        return (int) WhiteDrop;
@@ -2562,7 +2763,6 @@ YY_RULE_SETUP
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 596 "../parser.l"
 {
     if (WhiteOnMove(yyboardindex))
       return (int) BlackWins;
@@ -2572,35 +2772,30 @@ YY_RULE_SETUP
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 603 "../parser.l"
 {
     return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins);
 }
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 607 "../parser.l"
 {
     return (int) GameUnfinished;
 }
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 611 "../parser.l"
 {
     return (int) GameIsDrawn;
 }
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 615 "../parser.l"
 {
     return (int) GameIsDrawn;
 }
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 619 "../parser.l"
 {
     if (WhiteOnMove(yyboardindex))
       return (int) BlackWins;
@@ -2610,7 +2805,6 @@ YY_RULE_SETUP
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 626 "../parser.l"
 {
     if (WhiteOnMove(yyboardindex))
       return (int) BlackWins;
@@ -2620,63 +2814,54 @@ YY_RULE_SETUP
        YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 633 "../parser.l"
 {
     return (int) GameIsDrawn;
 }
        YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 637 "../parser.l"
 {
     return (int) GameIsDrawn;
 }
        YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 641 "../parser.l"
 {
     return (int) (ToUpper(yytext[0]) == 'W' ? WhiteWins : BlackWins);
 }
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 645 "../parser.l"
 {
     return (int) (ToUpper(yytext[0]) == 'W' ? BlackWins : WhiteWins);
 }
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 649 "../parser.l"
-{
+{ 
     return (int) WhiteWins;
 }
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 653 "../parser.l"
-{
+{ 
     return (int) BlackWins;
 }
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 657 "../parser.l"
 {
     return (int) GameIsDrawn;
 }
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 661 "../parser.l"
 {
     return (int) GameUnfinished;
 }
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 665 "../parser.l"
 {
     /* move numbers */
     if ((yyleng == 1) && (yytext[0] == '1'))
@@ -2685,15 +2870,13 @@ YY_RULE_SETUP
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 671 "../parser.l"
 {
-    /* elapsed time indication, e.g. (0:12) or {10:21.071} */
+    /* elapsed time indication, e.g. (0:12) or {10:21.071} */ 
     return (int) ElapsedTime;
 }
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 676 "../parser.l"
 {
     /* position diagram enclosed in [-- --] */
     return (int) PositionDiagram;
@@ -2704,7 +2887,6 @@ case 29:
 yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 681 "../parser.l"
 {
     /* position diagram enclosed in {-- --} */
     return (int) PositionDiagram;
@@ -2712,14 +2894,12 @@ YY_RULE_SETUP
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 686 "../parser.l"
 {
     return (int) PGNTag;
-}
+}    
        YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 690 "../parser.l"
 {
     return (int) GNUChessGame;
 }
@@ -2729,23 +2909,20 @@ case 32:
 yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 694 "../parser.l"
 {
     return (int) XBoardGame;
 }
        YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 698 "../parser.l"
 {                              /* numeric annotation glyph */
     return (int) NAG;
 }
        YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 702 "../parser.l"
 {                              /* anything in {} */
-    return (int) Comment;
+    return (int) Comment; 
 }
        YY_BREAK
 case 35:
@@ -2753,59 +2930,50 @@ case 35:
 yy_c_buf_p = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 706 "../parser.l"
 {                                          /* ; to end of line */
     return (int) Comment;
 }
        YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 710 "../parser.l"
 {                              /* anything in [] */
-    return (int) Comment;
+    return (int) Comment; 
 }
        YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 714 "../parser.l"
 {              /* nested () */
-    return (int) Comment;
+    return (int) Comment; 
 }
        YY_BREAK
 case 38:
 YY_RULE_SETUP
-#line 718 "../parser.l"
 {                              /* >=2 chars in () */
-    return (int) Comment;
-}
+    return (int) Comment; 
+}       
        YY_BREAK
 case 39:
 YY_RULE_SETUP
-#line 722 "../parser.l"
 {
         /* Skip mail headers */
 }
        YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 726 "../parser.l"
 {
         /* Skip random words */
 }
        YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 730 "../parser.l"
 {
         /* Skip everything else */
 }
        YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 734 "../parser.l"
 ECHO;
        YY_BREAK
-#line 2809 "lex.yy.c"
                        case YY_STATE_EOF(INITIAL):
                                yyterminate();
 
@@ -3095,7 +3263,7 @@ static yy_state_type yy_get_previous_state()
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 711 )
+                       if ( yy_current_state >= 697 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -3125,11 +3293,11 @@ yy_state_type yy_current_state;
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 711 )
+               if ( yy_current_state >= 697 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 710);
+       yy_is_jam = (yy_current_state == 696);
        if ( ! yy_is_jam )
                *yy_state_ptr++ = yy_current_state;
 
@@ -3182,7 +3350,6 @@ register char *yy_bp;
 #endif /* ifndef YY_NO_UNPUT */
 
 
-#ifndef YY_NO_INPUT
 #ifdef __cplusplus
 static int yyinput()
 #else
@@ -3255,7 +3422,7 @@ static int input()
 
        return c;
        }
-#endif /* YY_NO_INPUT */
+
 
 #ifdef YY_USE_PROTOS
 void yyrestart( FILE *input_file )
@@ -3366,6 +3533,15 @@ YY_BUFFER_STATE b;
        }
 
 
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+#endif
 
 #ifdef YY_USE_PROTOS
 void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
@@ -3683,7 +3859,6 @@ int main()
        return 0;
        }
 #endif
-#line 734 "../parser.l"
 
 
 
@@ -3695,7 +3870,7 @@ static FILE *lexFP;
 static int input()
 {
     int ret;
-
+    
     if (StringToLex != NULL) {
        ret = *StringToLex;
        if (ret == NULLCHAR)
@@ -3706,9 +3881,9 @@ static int input()
        ret = unputBuffer[--unputCount];
     } else {
        ret = fgetc(lexFP);
-    }
+    }    
 
-    if (ret == EOF)
+    if (ret == EOF) 
       return 0;
     else
       return ret;
@@ -3726,7 +3901,7 @@ int yyoffset()
     }
     return(offset);
 }
-
 static void output(ch)
      int ch;
 {
@@ -3798,7 +3973,7 @@ void my_yy_input(buf, result, max_size)
            *result = count;
        }
        return;
-    }
+    }    
 }
 
 static YY_BUFFER_STATE my_file_buffer = NULL;
@@ -3852,7 +4027,7 @@ ChessMove yylexstr(boardIndex, s)
 #ifdef FLEX_SCANNER
     YY_BUFFER_STATE buffer, oldBuffer;
 #endif
-
+    
     yyboardindex = boardIndex;
     oldStringToLex = StringToLex;
     StringToLex = s;
@@ -3865,7 +4040,7 @@ ChessMove yylexstr(boardIndex, s)
     ret = (ChessMove) yylex();
 
 #ifdef FLEX_SCANNER
-    if (oldBuffer != NULL)
+    if (oldBuffer != NULL) 
       yy_switch_to_buffer(oldBuffer);
     yy_delete_buffer(buffer);
 #endif /*FLEX_SCANNER*/
index 7718604..66fe833 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -58,3 +58,4 @@ extern char *yy_text;  /* Needed because yytext can be either a char[]
                          or a (non-constant) char* */\r
 extern int yyoffset P((void));\r
 extern char initialRights[BOARD_SIZE];\r
+extern char castlingRights[MAX_MOVES][BOARD_SIZE];\r
index 46de027..41feced 100644 (file)
--- a/parser.l
+++ b/parser.l
@@ -191,6 +191,11 @@ extern void CopyBoard P((Board to, Board from));
     currentMoveString[3] = yytext[4+skip1+skip2];\r
     currentMoveString[4] = NULLCHAR;\r
     \r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Parser Qa1b2: yyleng=%d\n",\r
+        yyleng);\r
+    }\r
+\r
     if (yyleng-skip1-skip2 > 5) { char c;\r
         if (yytext[yyleng-1] == ')') {\r
             c = currentMoveString[4] = ToLower(yytext[yyleng-2]);\r
@@ -297,7 +302,10 @@ extern void CopyBoard P((Board to, Board from));
     if (currentMoveString[4] == NULLCHAR &&\r
         (result == WhitePromotionKnight || result == BlackPromotionKnight ||\r
          result == WhitePromotionQueen  || result == BlackPromotionQueen)) {\r
-        currentMoveString[4] = PieceToChar(BlackQueen);\r
+        if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
+            currentMoveString[4] = PieceToChar(BlackFerz);\r
+        else\r
+            currentMoveString[4] = PieceToChar(BlackQueen);\r
        currentMoveString[5] = NULLCHAR;\r
     }\r
 \r
@@ -543,6 +551,12 @@ extern void CopyBoard P((Board to, Board from));
     if(yyleng-skip > 3) /* [HGM] can have Shogi-style promotion */\r
         cl.promoCharIn = yytext[yyleng-1];\r
 \r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Parser Qa1: yyleng=%d,  %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
+        yyleng,\r
+        cl.pieceIn,cl.ffIn,cl.rfIn,cl.ftIn,cl.rtIn,cl.promoCharIn,cl.promoCharIn?cl.promoCharIn:' ');\r
+    }\r
+\r
     /* [HGM] but do not allow values beyond board size */\r
     if(cl.rtIn >= BOARD_HEIGHT ||\r
        cl.rtIn <  0            ||\r
@@ -557,7 +571,7 @@ extern void CopyBoard P((Board to, Board from));
     currentMoveString[1] = cl.rf + ONE;\r
     currentMoveString[2] = cl.ft + AAA;\r
     currentMoveString[3] = cl.rt + ONE;\r
-    currentMoveS\0tring[4] = cl.promoChar;\r
+    currentMoveString[4] = cl.promoChar;\r
     currentMoveString[5] = NULLCHAR;\r
 \r
     return (int) cl.kind;\r
@@ -637,33 +651,44 @@ extern void CopyBoard P((Board to, Board from));
             ff = (BOARD_WIDTH-1)>>1;\r
            rt = 0;\r
             ft = BOARD_RGHT-3;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        } else {\r
            rf = 0;\r
             ff = BOARD_WIDTH>>1;\r
            rt = 0;\r
             ft = BOARD_LEFT+2;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        }\r
     } else{ \r
-        if (boards[yyboardindex][BOARD_HEIGHT-1][3] == BlackKing) {\r
+        if (boards[yyboardindex][BOARD_HEIGHT-1][(BOARD_WIDTH-1)>>1] == BlackKing) {\r
            /* ICS wild castling */\r
             rf = BOARD_HEIGHT-1;\r
             ff = (BOARD_WIDTH-1)>>1;\r
             rt = BOARD_HEIGHT-1;\r
             ft = BOARD_RGHT-3;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        } else {\r
             rf = BOARD_HEIGHT-1;\r
             ff = BOARD_WIDTH>>1;\r
             rt = BOARD_HEIGHT-1;\r
             ft = BOARD_LEFT+2;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        }\r
     }\r
+    if(gameInfo.variant == VariantFischeRandom) {\r
+        if (WhiteOnMove(yyboardindex)) {\r
+            ff = initialRights[2];\r
+            ft = initialRights[1];\r
+        } else {\r
+            ff = initialRights[5];\r
+            ft = initialRights[4];\r
+        }\r
+        fprintf(debugFP, "Parser FRC long %d %d\n", ff, ft);\r
+        if(ff < 0 || ft < 0) return 0;\r
+    }\r
+    sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "long castling %d %d\n", ff, ft);\r
+    }\r
     return (int) LegalityTest(boards[yyboardindex],\r
                              PosFlags(yyboardindex), EP_UNKNOWN,\r
-                              initialRights, /* [HGM] assume all castlings allowed */\r
+                              castlingRights[yyboardindex], /* [HGM] use true castling rights */\r
                              rf, ff, rt, ft, NULLCHAR);\r
 }\r
 \r
@@ -679,13 +704,11 @@ extern void CopyBoard P((Board to, Board from));
             ff = (BOARD_WIDTH-1)>>1;\r
            rt = 0;\r
             ft = BOARD_LEFT+1;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        } else {\r
            rf = 0;\r
             ff = BOARD_WIDTH>>1;\r
            rt = 0;\r
             ft = BOARD_RGHT-2;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        }\r
     } else {\r
         if (boards[yyboardindex][BOARD_HEIGHT-1][(BOARD_WIDTH-1)>>1] == BlackKing) {\r
@@ -694,18 +717,34 @@ extern void CopyBoard P((Board to, Board from));
             ff = (BOARD_WIDTH-1)>>1;\r
             rt = BOARD_HEIGHT-1;\r
             ft = BOARD_LEFT+1;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        } else {\r
             rf = BOARD_HEIGHT-1;\r
             ff = BOARD_WIDTH>>1;\r
             rt = BOARD_HEIGHT-1;\r
             ft = BOARD_RGHT-2;\r
-            sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
        }\r
     }\r
+    if(gameInfo.variant == VariantFischeRandom) {\r
+        if (WhiteOnMove(yyboardindex)) {\r
+            ff = initialRights[2];\r
+            ft = initialRights[0];\r
+        } else {\r
+            ff = initialRights[5];\r
+            ft = initialRights[3];\r
+        }\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "Parser FRC short %d %d\n", ff, ft);\r
+    }\r
+        if(ff < 0 || ft < 0) return 0;\r
+    }\r
+    sprintf(currentMoveString, "%c%c%c%c",ff+AAA,rf+ONE,ft+AAA,rt+ONE);\r
+    if (appData.debugMode) {\r
+        fprintf(debugFP, "short castling %d %d\n", ff, ft);\r
+    }\r
+\r
     return (int) LegalityTest(boards[yyboardindex],\r
-                             PosFlags(yyboardindex), EP_UNKNOWN,\r
-                              initialRights, /* [HGM] assume all castlings allowed */\r
+                              PosFlags(yyboardindex), EP_UNKNOWN,\r
+                              castlingRights[yyboardindex], /* [HGM] use true castling rights */\r
                              rf, ff, rt, ft, NULLCHAR);\r
 }\r
 \r
index 6317c8b..f21bccc 100644 (file)
--- a/pgntags.c
+++ b/pgntags.c
-/*
- * pgntags.c -- Functions to manage PGN tags
- * XBoard $Id: pgntags.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>
-#include <errno.h>
-#include <ctype.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"
-
-static char *PGNTagsStatic P((GameInfo *));
-
-
-
-/* Parse PGN tags; returns 0 for success or error number
- */
-int ParsePGNTag(tag, gameInfo)
-    char *tag;
-    GameInfo *gameInfo;
-{
-    char *name, *value, *p, *oldTags;
-    int len;
-    int success;
-
-    name = tag;
-    while (!isalpha(*name) && !isdigit(*name)) {
-       name++;
-    }
-    p = name;
-    while (*p != ' ' && *p != '\t' && *p != '\n') {
-       p++;
-    }
-    *p = NULLCHAR;
-    value = strchr(p + 1, '"') + 1;
-    p = strrchr(value, '"');
-    *p = NULLCHAR;
-
-    if (StrCaseCmp(name, "Event") == 0) {
-       success = StrSavePtr(value, &gameInfo->event) != NULL;
-    } else if (StrCaseCmp(name, "Site") == 0) {
-       success = StrSavePtr(value, &gameInfo->site) != NULL;
-    } else if (StrCaseCmp(name, "Date") == 0) {
-       success = StrSavePtr(value, &gameInfo->date) != NULL;
-    } else if (StrCaseCmp(name, "Round") == 0) {
-       success = StrSavePtr(value, &gameInfo->round) != NULL;
-    } else if (StrCaseCmp(name, "White") == 0) {
-       success = StrSavePtr(value, &gameInfo->white) != NULL;
-    } else if (StrCaseCmp(name, "Black") == 0) {
-       success = StrSavePtr(value, &gameInfo->black) != NULL;
-    }
-    /* Fold together the various ways of denoting White/Black rating */
-    else if ((StrCaseCmp(name, "WhiteElo")==0) ||
-            (StrCaseCmp(name, "WhiteUSCF")==0) ) {
-      success = TRUE;
-      gameInfo->whiteRating = atoi( value );
-    } else if ((StrCaseCmp(name, "BlackElo")==0) ||
-              (StrCaseCmp(name, "BlackUSCF")==0)) {
-      success = TRUE;
-      gameInfo->blackRating = atoi( value );
-    }
-    else if (StrCaseCmp(name, "Result") == 0) {
-       if (strcmp(value, "1-0") == 0)
-           gameInfo->result = WhiteWins;
-       else if (strcmp(value, "0-1") == 0)
-           gameInfo->result = BlackWins;
-       else if (strcmp(value, "1/2-1/2") == 0)
-           gameInfo->result = GameIsDrawn;
-       else
-           gameInfo->result = GameUnfinished;
-       success = TRUE;
-    } else if (StrCaseCmp(name, "FEN") == 0) {
-       success = StrSavePtr(value, &gameInfo->fen) != NULL;
-    } else if (StrCaseCmp(name, "SetUp") == 0) {
-       /* ignore on input; presence of FEN governs */
-       success = TRUE;
-    } else if (StrCaseCmp(name, "Variant") == 0) {
-        /* xboard-defined extension */
-        gameInfo->variant = StringToVariant(value);
-       success = TRUE;
-    } else if (StrCaseCmp(name, PGN_OUT_OF_BOOK) == 0) {
-        /* [AS] Out of book annotation */
-        success = StrSavePtr(value, &gameInfo->outOfBook) != NULL;
-    } else {
-       if (gameInfo->extraTags == NULL) {
-           oldTags = "";
-       } else {
-           oldTags = gameInfo->extraTags;
-       }
-       /* Buffer size includes 7 bytes of space for [ ""]\n\0 */
-       len = strlen(oldTags) + strlen(value) + strlen(name) + 7;
-       if ((p = (char *) malloc(len))  !=  NULL) {
-           sprintf(p, "%s[%s \"%s\"]\n", oldTags, name, value);
-           if (gameInfo->extraTags != NULL) free(gameInfo->extraTags);
-           gameInfo->extraTags = p;
-           success = TRUE;
-       } else {
-           success = FALSE;
-       }
-    }
-    return(success ? 0 : ENOMEM);
-}
-
-
-
-/* Return a static buffer with a game's data.
- */
-static char *PGNTagsStatic(gameInfo)
-    GameInfo *gameInfo;
-{
-    static char buf[8192];
-    char buf1[MSG_SIZ];
-
-    buf[0] = NULLCHAR;
-
-    sprintf(buf1, "[Event \"%s\"]\n",
-           gameInfo->event ? gameInfo->event : "?");
-    strcat(buf, buf1);
-    sprintf(buf1, "[Site \"%s\"]\n",
-           gameInfo->site ? gameInfo->site : "?");
-    strcat(buf, buf1);
-    sprintf(buf1, "[Date \"%s\"]\n",
-           gameInfo->date ? gameInfo->date : "?");
-    strcat(buf, buf1);
-    sprintf(buf1, "[Round \"%s\"]\n",
-           gameInfo->round ? gameInfo->round : "-");
-    strcat(buf, buf1);
-    sprintf(buf1, "[White \"%s\"]\n",
-           gameInfo->white ? gameInfo->white : "?");
-    strcat(buf, buf1);
-    sprintf(buf1, "[Black \"%s\"]\n",
-           gameInfo->black ? gameInfo->black : "?");
-    strcat(buf, buf1);
-    sprintf(buf1, "[Result \"%s\"]\n", PGNResult(gameInfo->result));
-    strcat(buf, buf1);
-    if (gameInfo->whiteRating >= 0 ) {
-       sprintf(buf1, "[WhiteElo \"%d\"]\n", gameInfo->whiteRating );
-       strcat(buf, buf1);
-    }
-    if ( gameInfo->blackRating >= 0 ) {
-       sprintf(buf1, "[BlackElo \"%d\"]\n", gameInfo->blackRating );
-       strcat(buf, buf1);
-    }    
-    if (gameInfo->timeControl != NULL) {
-       sprintf(buf1, "[TimeControl \"%s\"]\n", gameInfo->timeControl);
-       strcat(buf, buf1);
-    }
-    if (gameInfo->variant != VariantNormal) {
-        sprintf(buf1, "[Variant \"%s\"]\n", VariantName(gameInfo->variant));
-       strcat(buf, buf1);
-    }
-    if (gameInfo->extraTags != NULL) {
-       strcat(buf, gameInfo->extraTags);
-    }
-    return buf;
-}
-
-
-/* Print game info
- */
-void PrintPGNTags(fp, gameInfo)
-     FILE *fp;
-     GameInfo *gameInfo;
-{
-    fprintf(fp, "%s", PGNTagsStatic(gameInfo));
-}
-
-
-/* Return a non-static buffer with a games info.
- */
-char *PGNTags(gameInfo)
-    GameInfo *gameInfo;
-{
-    return StrSave(PGNTagsStatic(gameInfo));
-}
-
-
-/* Returns pointer to a static string with a result.
- */
-char *PGNResult(result)
-     ChessMove result;
-{
-    switch (result) {
-      case GameUnfinished:
-      default:
-       return "*";
-      case WhiteWins:
-       return "1-0";
-      case BlackWins:
-       return "0-1";
-      case GameIsDrawn:
-       return "1/2-1/2";
-    }
-}  
-
-/* Returns 0 for success, nonzero for error */
-int
-ReplaceTags(tags, gameInfo)
-     char *tags;
-     GameInfo *gameInfo;
-{
-    ChessMove moveType;
-    int err;
-
-    ClearGameInfo(gameInfo);
-    yynewstr(tags);
-    for (;;) {
-       yyboardindex = 0;
-       moveType = (ChessMove) yylex();
-       if (moveType == (ChessMove) 0) {
-           break;
-       } else if (moveType == PGNTag) {
-           err = ParsePGNTag(yy_text, gameInfo);
-           if (err != 0) return err;
-       } 
-    }
-    /* just one problem...if there is a result in the new tags,
-     * DisplayMove() won't ever show it because ClearGameInfo() set
-     * gameInfo->resultDetails to NULL. So we must plug something in if there
-     * is a result.
-     */
-    if (gameInfo->result != GameUnfinished) {
-      if (gameInfo->resultDetails) free(gameInfo->resultDetails);
-      gameInfo->resultDetails = strdup("");
-    }
-    return 0;
-}
+/*\r
+ * pgntags.c -- Functions to manage PGN tags\r
+ * XBoard $Id: pgntags.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
+#include <errno.h>\r
+#include <ctype.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
+static char *PGNTagsStatic P((GameInfo *));\r
+\r
+\r
+\r
+/* Parse PGN tags; returns 0 for success or error number\r
+ */\r
+int ParsePGNTag(tag, gameInfo)\r
+    char *tag;\r
+    GameInfo *gameInfo;\r
+{\r
+    char *name, *value, *p, *oldTags;\r
+    int len;\r
+    int success;\r
+\r
+    name = tag;\r
+    while (!isalpha(*name) && !isdigit(*name)) {\r
+       name++;\r
+    }\r
+    p = name;\r
+    while (*p != ' ' && *p != '\t' && *p != '\n') {\r
+       p++;\r
+    }\r
+    *p = NULLCHAR;\r
+    value = strchr(p + 1, '"') + 1;\r
+    p = strrchr(value, '"');\r
+    *p = NULLCHAR;\r
+\r
+    if (StrCaseCmp(name, "Event") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->event) != NULL;\r
+    } else if (StrCaseCmp(name, "Site") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->site) != NULL;\r
+    } else if (StrCaseCmp(name, "Date") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->date) != NULL;\r
+    } else if (StrCaseCmp(name, "Round") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->round) != NULL;\r
+    } else if (StrCaseCmp(name, "White") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->white) != NULL;\r
+    } else if (StrCaseCmp(name, "Black") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->black) != NULL;\r
+    }\r
+    /* Fold together the various ways of denoting White/Black rating */\r
+    else if ((StrCaseCmp(name, "WhiteElo")==0) ||\r
+            (StrCaseCmp(name, "WhiteUSCF")==0) ) {\r
+      success = TRUE;\r
+      gameInfo->whiteRating = atoi( value );\r
+    } else if ((StrCaseCmp(name, "BlackElo")==0) ||\r
+              (StrCaseCmp(name, "BlackUSCF")==0)) {\r
+      success = TRUE;\r
+      gameInfo->blackRating = atoi( value );\r
+    }\r
+    else if (StrCaseCmp(name, "Result") == 0) {\r
+       if (strcmp(value, "1-0") == 0)\r
+           gameInfo->result = WhiteWins;\r
+       else if (strcmp(value, "0-1") == 0)\r
+           gameInfo->result = BlackWins;\r
+       else if (strcmp(value, "1/2-1/2") == 0)\r
+           gameInfo->result = GameIsDrawn;\r
+       else\r
+           gameInfo->result = GameUnfinished;\r
+       success = TRUE;\r
+    } else if (StrCaseCmp(name, "FEN") == 0) {\r
+       success = StrSavePtr(value, &gameInfo->fen) != NULL;\r
+    } else if (StrCaseCmp(name, "SetUp") == 0) {\r
+       /* ignore on input; presence of FEN governs */\r
+       success = TRUE;\r
+    } else if (StrCaseCmp(name, "Variant") == 0) {\r
+        /* xboard-defined extension */\r
+        gameInfo->variant = StringToVariant(value);\r
+       success = TRUE;\r
+    } else if (StrCaseCmp(name, PGN_OUT_OF_BOOK) == 0) {\r
+        /* [AS] Out of book annotation */\r
+        success = StrSavePtr(value, &gameInfo->outOfBook) != NULL;\r
+    } else {\r
+       if (gameInfo->extraTags == NULL) {\r
+           oldTags = "";\r
+       } else {\r
+           oldTags = gameInfo->extraTags;\r
+       }\r
+       /* Buffer size includes 7 bytes of space for [ ""]\n\0 */\r
+       len = strlen(oldTags) + strlen(value) + strlen(name) + 7;\r
+       if ((p = (char *) malloc(len))  !=  NULL) {\r
+           sprintf(p, "%s[%s \"%s\"]\n", oldTags, name, value);\r
+           if (gameInfo->extraTags != NULL) free(gameInfo->extraTags);\r
+           gameInfo->extraTags = p;\r
+           success = TRUE;\r
+       } else {\r
+           success = FALSE;\r
+       }\r
+    }\r
+    return(success ? 0 : ENOMEM);\r
+}\r
+\r
+\r
+\r
+/* Return a static buffer with a game's data.\r
+ */\r
+static char *PGNTagsStatic(gameInfo)\r
+    GameInfo *gameInfo;\r
+{\r
+    static char buf[8192];\r
+    char buf1[MSG_SIZ];\r
+\r
+    buf[0] = NULLCHAR;\r
+\r
+    sprintf(buf1, "[Event \"%s\"]\n",\r
+           gameInfo->event ? gameInfo->event : "?");\r
+    strcat(buf, buf1);\r
+    sprintf(buf1, "[Site \"%s\"]\n",\r
+           gameInfo->site ? gameInfo->site : "?");\r
+    strcat(buf, buf1);\r
+    sprintf(buf1, "[Date \"%s\"]\n",\r
+           gameInfo->date ? gameInfo->date : "?");\r
+    strcat(buf, buf1);\r
+    sprintf(buf1, "[Round \"%s\"]\n",\r
+           gameInfo->round ? gameInfo->round : "-");\r
+    strcat(buf, buf1);\r
+    sprintf(buf1, "[White \"%s\"]\n",\r
+           gameInfo->white ? gameInfo->white : "?");\r
+    strcat(buf, buf1);\r
+    sprintf(buf1, "[Black \"%s\"]\n",\r
+           gameInfo->black ? gameInfo->black : "?");\r
+    strcat(buf, buf1);\r
+    sprintf(buf1, "[Result \"%s\"]\n", PGNResult(gameInfo->result));\r
+    strcat(buf, buf1);\r
\r
+    if (gameInfo->whiteRating >= 0 ) {\r
+       sprintf(buf1, "[WhiteElo \"%d\"]\n", gameInfo->whiteRating );\r
+       strcat(buf, buf1);\r
+    }\r
+    if ( gameInfo->blackRating >= 0 ) {\r
+       sprintf(buf1, "[BlackElo \"%d\"]\n", gameInfo->blackRating );\r
+       strcat(buf, buf1);\r
+    }    \r
+    if (gameInfo->timeControl != NULL) {\r
+       sprintf(buf1, "[TimeControl \"%s\"]\n", gameInfo->timeControl);\r
+       strcat(buf, buf1);\r
+    }\r
+    if (gameInfo->variant != VariantNormal) {\r
+        sprintf(buf1, "[Variant \"%s\"]\n", VariantName(gameInfo->variant));\r
+       strcat(buf, buf1);\r
+    }\r
+    if (gameInfo->extraTags != NULL) {\r
+       strcat(buf, gameInfo->extraTags);\r
+    }\r
+    return buf;\r
+}\r
+\r
+\r
\r
+/* Print game info\r
+ */\r
+void PrintPGNTags(fp, gameInfo)\r
+     FILE *fp;\r
+     GameInfo *gameInfo;\r
+{\r
+    fprintf(fp, "%s", PGNTagsStatic(gameInfo));\r
+}\r
+\r
+\r
+/* Return a non-static buffer with a games info.\r
+ */\r
+char *PGNTags(gameInfo)\r
+    GameInfo *gameInfo;\r
+{\r
+    return StrSave(PGNTagsStatic(gameInfo));\r
+}\r
+\r
+\r
+/* Returns pointer to a static string with a result.\r
+ */\r
+char *PGNResult(result)\r
+     ChessMove result;\r
+{\r
+    switch (result) {\r
+      case GameUnfinished:\r
+      default:\r
+       return "*";\r
+      case WhiteWins:\r
+       return "1-0";\r
+      case BlackWins:\r
+       return "0-1";\r
+      case GameIsDrawn:\r
+       return "1/2-1/2";\r
+    }\r
+}  \r
+\r
+/* Returns 0 for success, nonzero for error */\r
+int\r
+ReplaceTags(tags, gameInfo)\r
+     char *tags;\r
+     GameInfo *gameInfo;\r
+{\r
+    ChessMove moveType;\r
+    int err;\r
+\r
+    ClearGameInfo(gameInfo);\r
+    yynewstr(tags);\r
+    for (;;) {\r
+       yyboardindex = 0;\r
+       moveType = (ChessMove) yylex();\r
+       if (moveType == (ChessMove) 0) {\r
+           break;\r
+       } else if (moveType == PGNTag) {\r
+           err = ParsePGNTag(yy_text, gameInfo);\r
+           if (err != 0) return err;\r
+       } \r
+    }\r
+    /* just one problem...if there is a result in the new tags,\r
+     * DisplayMove() won't ever show it because ClearGameInfo() set\r
+     * gameInfo->resultDetails to NULL. So we must plug something in if there\r
+     * is a result.\r
+     */\r
+    if (gameInfo->result != GameUnfinished) {\r
+      if (gameInfo->resultDetails) free(gameInfo->resultDetails);\r
+      gameInfo->resultDetails = strdup("");\r
+    }\r
+    return 0;\r
+}\r
diff --git a/uci.c b/uci.c
index fdf7e6c..5af3ce6 100644 (file)
--- a/uci.c
+++ b/uci.c
-/*
- * UCI support thru Polyglot
- *
- * Author: Alessandro Scotti (Jan 2006)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#include "config.h"
-
-#include <windows.h> /* required for all Windows applications */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-
-#include "common.h"
-#include "winboard.h"
-#include "frontend.h"
-#include "backend.h"
-
-#define INIFILE_PREFIX      "polyglot_"
-#define INIFILE_SUFFIX_1ST  "1st"
-#define INIFILE_SUFFIX_2ND  "2nd"
-#define INIFILE_EXT         ".ini"
-
-static const char * GetIniFilename( ChessProgramState * cps )
-{
-    return cps == &first ? INIFILE_PREFIX INIFILE_SUFFIX_1ST INIFILE_EXT : INIFILE_PREFIX INIFILE_SUFFIX_2ND INIFILE_EXT;
- }
-
-void InitEngineUCI( const char * iniDir, ChessProgramState * cps )
-{
-    if( cps->isUCI ) {
-        const char * iniFileName = GetIniFilename( cps );
-        char polyglotIniFile[ MAX_PATH ];
-        FILE * f;
-
-        /* Build name of initialization file */
-        if( strchr( iniDir, ' ' ) != NULL ) {
-            char iniDirShort[ MAX_PATH ];
-
-            GetShortPathName( iniDir, iniDirShort, sizeof(iniDirShort) );
-
-            strcpy( polyglotIniFile, iniDirShort );
-        }
-        else {
-            strcpy( polyglotIniFile, iniDir );
-        }
-
-        strcat( polyglotIniFile, "\\" );
-        strcat( polyglotIniFile, iniFileName );
-
-        /* Create initialization file */
-        f = fopen( polyglotIniFile, "w" );
-
-        if( f != NULL ) {
-            fprintf( f, "[Polyglot]\n" );
-
-            if( cps->dir != 0 && strlen(cps->dir) > 0 ) {
-                fprintf( f, "EngineDir = %s\n", cps->dir );
-            }
-
-            if( cps->program != 0 && strlen(cps->program) > 0 ) {
-                fprintf( f, "EngineCommand = %s\n", cps->program );
-            }
-
-            fprintf( f, "Book = %s\n", appData.usePolyglotBook ? "true" : "false" );
-            fprintf( f, "BookFile = %s\n", appData.polyglotBook );
-
-            fprintf( f, "[Engine]\n" );
-            fprintf( f, "Hash = %d\n", appData.defaultHashSize );
-
-            fprintf( f, "NalimovPath = %s\n", appData.defaultPathEGTB );
-            fprintf( f, "NalimovCache = %d\n", appData.defaultCacheSizeEGTB );
-
-            fprintf( f, "OwnBook = %s\n", cps->hasOwnBookUCI ? "true" : "false" );
-
-            fclose( f );
-
-            /* Replace program with properly configured Polyglot */
-            cps->dir = appData.polyglotDir;
-            cps->program = (char *) malloc( strlen(polyglotIniFile) + 32 );
-            strcpy( cps->program, "polyglot " );
-            strcat( cps->program, polyglotIniFile );
-        }
-    }
-}
+/*\r
+ * UCI support thru Polyglot\r
+ *\r
+ * Author: Alessandro Scotti (Jan 2006)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#include "config.h"\r
+\r
+#include <windows.h> /* required for all Windows applications */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+\r
+#include "common.h"\r
+#include "winboard.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+\r
+#define INIFILE_PREFIX      "polyglot_"\r
+#define INIFILE_SUFFIX_1ST  "1st"\r
+#define INIFILE_SUFFIX_2ND  "2nd"\r
+#define INIFILE_EXT         ".ini"\r
+\r
+static const char * GetIniFilename( ChessProgramState * cps )\r
+{\r
+    return cps == &first ? INIFILE_PREFIX INIFILE_SUFFIX_1ST INIFILE_EXT : INIFILE_PREFIX INIFILE_SUFFIX_2ND INIFILE_EXT;\r
+ }\r
+\r
+void InitEngineUCI( const char * iniDir, ChessProgramState * cps )\r
+{\r
+    if( cps->isUCI ) {\r
+        const char * iniFileName = GetIniFilename( cps );\r
+        char polyglotIniFile[ MAX_PATH ];\r
+        FILE * f;\r
+\r
+        /* Build name of initialization file */\r
+        if( strchr( iniDir, ' ' ) != NULL ) {\r
+            char iniDirShort[ MAX_PATH ];\r
+\r
+            GetShortPathName( iniDir, iniDirShort, sizeof(iniDirShort) );\r
+\r
+            strcpy( polyglotIniFile, iniDirShort );\r
+        }\r
+        else {\r
+            strcpy( polyglotIniFile, iniDir );\r
+        }\r
+        \r
+        strcat( polyglotIniFile, "\\" );\r
+        strcat( polyglotIniFile, iniFileName );\r
+\r
+        /* Create initialization file */\r
+        f = fopen( polyglotIniFile, "w" );\r
+\r
+        if( f != NULL ) {\r
+            fprintf( f, "[Polyglot]\n" );\r
+\r
+            if( cps->dir != 0 && strlen(cps->dir) > 0 ) {\r
+                fprintf( f, "EngineDir = %s\n", cps->dir );\r
+            }\r
+\r
+            if( cps->program != 0 && strlen(cps->program) > 0 ) {\r
+                fprintf( f, "EngineCommand = %s\n", cps->program );\r
+            }\r
+\r
+            fprintf( f, "Book = %s\n", appData.usePolyglotBook ? "true" : "false" );\r
+            fprintf( f, "BookFile = %s\n", appData.polyglotBook );\r
+        \r
+            fprintf( f, "[Engine]\n" );\r
+            fprintf( f, "Hash = %d\n", appData.defaultHashSize );\r
+\r
+            fprintf( f, "NalimovPath = %s\n", appData.defaultPathEGTB );\r
+            fprintf( f, "NalimovCache = %d\n", appData.defaultCacheSizeEGTB );\r
+\r
+            fprintf( f, "OwnBook = %s\n", cps->hasOwnBookUCI ? "true" : "false" );\r
+\r
+            fclose( f );\r
+\r
+            /* Replace program with properly configured Polyglot */\r
+            cps->dir = appData.polyglotDir;\r
+            cps->program = (char *) malloc( strlen(polyglotIniFile) + 32 );\r
+            strcpy( cps->program, "polyglot " );\r
+            strcat( cps->program, polyglotIniFile );\r
+        }\r
+    }\r
+}\r
index c90fd9e..901bd5d 100644 (file)
 #define EDITTAGS_FONT_COLOSSAL "Courier New:8.0"\r
 #define EDITTAGS_FONT_TITANIC  "Courier New:8.0"\r
 \r
-#define MOVEHISTORY_FONT_ALL    "MS Sans Serif:8.0"
-
+#define MOVEHISTORY_FONT_ALL    "MS Sans Serif:8.0"\r
+\r
 #define COLOR_SHOUT            "#209000"\r
 #define COLOR_SSHOUT         "b #289808"\r
 #define COLOR_CHANNEL1         "#2020E0"\r
index 32e7081..4b08076 100644 (file)
 #define OPT_VariantAtomic               1513\r
 #define OPT_VariantNormal               1514\r
 #define OPT_VariantFairy                1515\r
+#define OPT_VariantFRC                  1516\r
+#define OPT_VariantCylinder             1517\r
+#define OPT_VariantFalcon               1518\r
+#define OPT_VariantCRC                  1519\r
 #define IDC_Files                       1550\r
 #define IDC_Ranks                       1551\r
 #define IDC_Holdings                    1552\r
index d04ce9a..55b9dfd 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * wclipbrd.c -- Clipboard routines for WinBoard\r
- * $Id: wclipbrd.c,v 2.1 2003/10/27 19:21:02 mann Exp $
+ * $Id: wclipbrd.c,v 2.1 2003/10/27 19:21:02 mann Exp $\r
  *\r
  * Copyright 2000 Free Software Foundation, Inc.\r
  *\r
@@ -47,7 +47,7 @@ CopyFENToClipboard()
 {\r
   char *fen = NULL;\r
 \r
-  fen = PositionToFEN(currentMove,1);
+  fen = PositionToFEN(currentMove,1);\r
   if (!fen) {\r
     DisplayError("Unable to convert position to FEN.", 0);\r
     return;\r
@@ -57,38 +57,38 @@ CopyFENToClipboard()
   free(fen);\r
 }\r
 \r
-/* [AS] */
-HGLOBAL ExportGameListAsText();
-
-VOID CopyGameListToClipboard()
-{
-    HGLOBAL hMem = ExportGameListAsText();
-
-    if( hMem != NULL ) {
-        /* Assign memory block to clipboard */
-        BOOL ok = OpenClipboard( hwndMain );
-
-        if( ok ) {
-            ok = EmptyClipboard();
-
-            if( ok ) {
-                if( hMem != SetClipboardData( CF_TEXT, hMem ) ) {
-                    ok = FALSE;
-                }
-            }
-
-            CloseClipboard();
-
-            if( ! ok ) {
-                GlobalFree( hMem );
-            }
-        }
-
-        if( ! ok ) {
-            DisplayError( "Cannot copy list to clipboard.", 0 );
-        }
-    }
-}
+/* [AS] */\r
+HGLOBAL ExportGameListAsText();\r
+\r
+VOID CopyGameListToClipboard()\r
+{\r
+    HGLOBAL hMem = ExportGameListAsText();\r
+    \r
+    if( hMem != NULL ) {\r
+        /* Assign memory block to clipboard */\r
+        BOOL ok = OpenClipboard( hwndMain );\r
+\r
+        if( ok ) {\r
+            ok = EmptyClipboard();\r
+\r
+            if( ok ) {\r
+                if( hMem != SetClipboardData( CF_TEXT, hMem ) ) {\r
+                    ok = FALSE;\r
+                }\r
+            }\r
+\r
+            CloseClipboard();\r
+\r
+            if( ! ok ) {\r
+                GlobalFree( hMem );\r
+            }\r
+        }\r
+\r
+        if( ! ok ) {\r
+            DisplayError( "Cannot copy list to clipboard.", 0 );\r
+        }\r
+    }\r
+}\r
 \r
 VOID\r
 CopyGameToClipboard()\r
@@ -226,16 +226,16 @@ CopyTextToClipboard(char *text)
   return TRUE;\r
 }\r
 \r
-/* [AS] Reworked paste functions so they can work with strings too */
-
-VOID PasteFENFromString( char * fen )
-{
-  if (appData.debugMode) {
-    fprintf(debugFP, "PasteFenFromString(): fen '%s'\n", fen);
-  }
-  EditPositionPasteFEN(fen); /* call into backend */
-  free(fen);
-}
+/* [AS] Reworked paste functions so they can work with strings too */\r
+\r
+VOID PasteFENFromString( char * fen )\r
+{\r
+  if (appData.debugMode) {\r
+    fprintf(debugFP, "PasteFenFromString(): fen '%s'\n", fen);\r
+  }\r
+  EditPositionPasteFEN(fen); /* call into backend */\r
+  free(fen);\r
+}\r
 \r
 \r
 VOID\r
@@ -246,10 +246,10 @@ PasteFENFromClipboard()
       DisplayError("Unable to paste FEN from clipboard.", 0);\r
       return;\r
   }\r
-  PasteFENFromString( fen );
+  PasteFENFromString( fen );\r
 }\r
 \r
-VOID PasteGameFromString( char * buf )
+VOID PasteGameFromString( char * buf )\r
 {\r
   FILE *f;\r
   size_t len;\r
@@ -259,55 +259,55 @@ VOID PasteGameFromString( char * buf )
   f = fopen(pasteTemp, "w");\r
   if (!f) {\r
     DisplayError("Unable to create temporary file.", 0);\r
-    free(buf); /* [AS] */
+    free(buf); /* [AS] */\r
     return;\r
   }\r
   len = fwrite(buf, sizeof(char), strlen(buf), f);\r
   fclose(f);\r
   if (len != strlen(buf)) {\r
     DisplayError("Error writing to temporary file.", 0);\r
-    free(buf); /* [AS] */
+    free(buf); /* [AS] */\r
     return;\r
   }\r
   LoadGameFromFile(pasteTemp, 0, "Clipboard", TRUE);\r
-  free( buf ); /* [AS] */
-}
-
-
-VOID
-PasteGameFromClipboard()
-{
-  /* Write the clipboard to a temp file, then let LoadGameFromFile()
-   * do all the work.  */
-  char *buf;
-  if (!PasteTextFromClipboard(&buf)) {
-    return;
-  }
-  PasteGameFromString( buf );
+  free( buf ); /* [AS] */\r
+}\r
+\r
+\r
+VOID\r
+PasteGameFromClipboard()\r
+{\r
+  /* Write the clipboard to a temp file, then let LoadGameFromFile()\r
+   * do all the work.  */\r
+  char *buf;\r
+  if (!PasteTextFromClipboard(&buf)) {\r
+    return;\r
+  }\r
+  PasteGameFromString( buf );\r
 }\r
 \r
-/* [AS] Try to detect whether the clipboard contains FEN or PGN data */
-VOID PasteGameOrFENFromClipboard()
-{
-  char *buf;
-  char *tmp;
-
-  if (!PasteTextFromClipboard(&buf)) {
-    return;
-  }
-
-  tmp = buf;
-  while( *tmp == ' ' || *tmp == '\t' || *tmp == '\r' || *tmp == '\n' ) {
-      tmp++;
-  }
-
-  if( *tmp == '[' ) {
-      PasteGameFromString( buf );
-  }
-  else {
-      PasteFENFromString( buf );
-  }
-}
+/* [AS] Try to detect whether the clipboard contains FEN or PGN data */\r
+VOID PasteGameOrFENFromClipboard()\r
+{\r
+  char *buf;\r
+  char *tmp;\r
+\r
+  if (!PasteTextFromClipboard(&buf)) {\r
+    return;\r
+  }\r
+\r
+  tmp = buf;\r
+  while( *tmp == ' ' || *tmp == '\t' || *tmp == '\r' || *tmp == '\n' ) {\r
+      tmp++;\r
+  }\r
+\r
+  if( *tmp == '[' ) {\r
+      PasteGameFromString( buf );\r
+  }\r
+  else {\r
+      PasteFENFromString( buf );\r
+  }\r
+}\r
 \r
 int \r
 PasteTextFromClipboard(char **text)\r
index 791dc74..b2ea95b 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * wclipbrd.c -- Clipboard routines for WinBoard\r
- * $Id: wclipbrd.h,v 2.1 2003/10/27 19:21:02 mann Exp $
+ * $Id: wclipbrd.h,v 2.1 2003/10/27 19:21:02 mann Exp $\r
  *\r
  * Copyright 2000 Free Software Foundation, Inc.\r
  *\r
@@ -23,7 +23,7 @@
 \r
 VOID CopyFENToClipboard();\r
 VOID CopyGameToClipboard();\r
-VOID CopyGameListToClipboard();
+VOID CopyGameListToClipboard();\r
 int CopyTextToClipboard(char *text);\r
 \r
 VOID PasteFENFromClipboard();\r
@@ -31,5 +31,5 @@ VOID PasteGameFromClipboard();
 int PasteTextFromClipboard(char **text);\r
 \r
 VOID DeleteClipboardTempFiles();\r
-
-VOID PasteGameOrFENFromClipboard(); /* [AS] */
+\r
+VOID PasteGameOrFENFromClipboard(); /* [AS] */\r
index 935e761..83cd607 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * wedittags.c -- EditTags window for WinBoard\r
- * $Id: wedittags.c,v 2.1 2003/10/27 19:21:02 mann Exp $
+ * $Id: wedittags.c,v 2.1 2003/10/27 19:21:02 mann Exp $\r
  *\r
  * Copyright 1995 Free Software Foundation, Inc.\r
  *\r
index 9b3626a..0851d39 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * wedittags.h -- EditTags window for WinBoard\r
- * $Id: wedittags.h,v 2.1 2003/10/27 19:21:02 mann Exp $
+ * $Id: wedittags.h,v 2.1 2003/10/27 19:21:02 mann Exp $\r
  *\r
  * Copyright 1995 Free Software Foundation, Inc.\r
  *\r
index 0eb7536..86715e3 100644 (file)
-/*
- * Engine output (PV)
- *
- * Author: Alessandro Scotti (Dec 2005)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#include "config.h"
-
-#include <windows.h> /* required for all Windows applications */
-#include <richedit.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <commdlg.h>
-#include <dlgs.h>
-
-#include "common.h"
-#include "winboard.h"
-#include "frontend.h"
-#include "backend.h"
-
-#include "wsnap.h"
-
-VOID EngineOutputPopUp();
-VOID EngineOutputPopDown();
-BOOL EngineOutputIsUp();
-
-#define SHOW_PONDERING
-
-/* Imports from backend.c */
-char * SavePart(char *str);
-
-/* Imports from winboard.c */
-extern HWND engineOutputDialog;
-extern BOOLEAN engineOutputDialogUp;
-
-extern HINSTANCE hInst;
-extern HWND hwndMain;
-
-extern WindowPlacement wpEngineOutput;
-
-/* Module variables */
-#define H_MARGIN            2
-#define V_MARGIN            2
-#define LABEL_V_DISTANCE    1   /* Distance between label and memo */
-#define SPLITTER_SIZE       4   /* Distance between first memo and second label */
-
-#define ICON_SIZE           14
-
-#define STATE_UNKNOWN   -1
-#define STATE_THINKING   0
-#define STATE_IDLE       1
-#define STATE_PONDERING  2
-#define STATE_ANALYZING  3
-
-static int  windowMode = 1;
-
-static BOOL needInit = TRUE;
-
-static HICON hiColorBlack = NULL;
-static HICON hiColorWhite = NULL;
-static HICON hiColorUnknown = NULL;
-static HICON hiClear = NULL;
-static HICON hiPondering = NULL;
-static HICON hiThinking = NULL;
-static HICON hiAnalyzing = NULL;
-
-static int  lastDepth[2] = { -1, -1 };
-static int  lastForwardMostMove[2] = { -1, -1 };
-static int  engineState[2] = { -1, -1 };
-
-typedef struct {
-    HWND hColorIcon;
-    HWND hLabel;
-    HWND hStateIcon;
-    HWND hStateData;
-    HWND hLabelNPS;
-    HWND hMemo;
-    char * name;
-    int which;
-    int depth;
-    unsigned long nodes;
-    int score;
-    int time;
-    char * pv;
-    char * hint;
-    int an_move_index;
-    int an_move_count;
-} EngineOutputData;
-
-static HICON LoadIconEx( int id )
-{
-    return LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, ICON_SIZE, ICON_SIZE, 0 );
-}
-
-static VOID InitializeEngineOutput()
-{
-    if( needInit ) {
-        hiColorBlack = LoadIconEx( IDI_BLACK_14 );
-        hiColorWhite = LoadIconEx( IDI_WHITE_14 );
-        hiColorUnknown = LoadIconEx( IDI_UNKNOWN_14 );
-        hiClear = LoadIconEx( IDI_TRANS_14 );
-        hiPondering = LoadIconEx( IDI_PONDER_14 );
-        hiThinking = LoadIconEx( IDI_CLOCK_14 );
-        hiAnalyzing = LoadIconEx( IDI_ANALYZE2_14 );
-        needInit = FALSE;
-    }
-}
-
-static VOID SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )
-{
-    HWND hControl = GetDlgItem( hDlg, id );
-
-    SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );
-}
-
-#define HIDDEN_X    20000
-#define HIDDEN_Y    20000
-
-static VOID HideControl( HWND hDlg, int id )
-{
-    HWND hControl = GetDlgItem( hDlg, id );
-    RECT rc;
-
-    GetWindowRect( hControl, &rc );
-
-    /*
-        Avoid hiding an already hidden control, because that causes many
-        unnecessary WM_ERASEBKGND messages!
-    */
-    if( rc.left != HIDDEN_X || rc.top != HIDDEN_Y ) {
-    SetControlPos( hDlg, id, 20000, 20000, 100, 100 );
-    }
-}
-
-static int GetControlWidth( HWND hDlg, int id )
-{
-    RECT rc;
-
-    GetWindowRect( GetDlgItem( hDlg, id ), &rc );
-
-    return rc.right - rc.left;
-}
-
-static int GetControlHeight( HWND hDlg, int id )
-{
-    RECT rc;
-
-    GetWindowRect( GetDlgItem( hDlg, id ), &rc );
-
-    return rc.bottom - rc.top;
-}
-
-static int GetHeaderHeight()
-{
-    int result = GetControlHeight( engineOutputDialog, IDC_EngineLabel1 );
-
-    if( result < ICON_SIZE ) result = ICON_SIZE;
-
-    return result;
-}
-
-#define ENGINE_COLOR_WHITE      'w'
-#define ENGINE_COLOR_BLACK      'b'
-#define ENGINE_COLOR_UNKNOWN    ' '
-
-char GetEngineColor( int which )
-{
-    char result = ENGINE_COLOR_UNKNOWN;
-
-    if( which == 0 || which == 1 ) {
-        ChessProgramState * cps;
-
-        switch (gameMode) {
-        case MachinePlaysBlack:
-        case IcsPlayingBlack:
-            result = ENGINE_COLOR_BLACK;
-            break;
-        case MachinePlaysWhite:
-        case IcsPlayingWhite:
-            result = ENGINE_COLOR_WHITE;
-            break;
-        case AnalyzeMode:
-        case AnalyzeFile:
-            result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
-            break;
-        case TwoMachinesPlay:
-            cps = (which == 0) ? &first : &second;
-            result = cps->twoMachinesColor[0];
-            result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
-            break;
-        }
-    }
-
-    return result;
-}
-
-char GetActiveEngineColor()
-{
-    char result = ENGINE_COLOR_UNKNOWN;
-
-    if( gameMode == TwoMachinesPlay ) {
-        result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
-    }
-
-    return result;
-}
-
-static int IsEnginePondering( int which )
-{
-    int result = FALSE;
-
-    switch (gameMode) {
-    case MachinePlaysBlack:
-    case IcsPlayingBlack:
-        if( WhiteOnMove(forwardMostMove) ) result = TRUE;
-        break;
-    case MachinePlaysWhite:
-    case IcsPlayingWhite:
-        if( ! WhiteOnMove(forwardMostMove) ) result = TRUE;
-        break;
-    case TwoMachinesPlay:
-        if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) {
-            if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE;
-        }
-        break;
-    }
-
-    return result;
-}
-
-static VOID PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData )
-{
-    int label_x = x + ICON_SIZE + H_MARGIN;
-    int label_h = GetControlHeight( hDlg, IDC_EngineLabel1 );
-    int label_y = y + ICON_SIZE - label_h;
-    int nps_w = GetControlWidth( hDlg, IDC_Engine1_NPS );
-    int nps_x = clientWidth - H_MARGIN - nps_w;
-    int state_data_w = GetControlWidth( hDlg, IDC_StateData1 );
-    int state_data_x = nps_x - H_MARGIN - state_data_w;
-    int state_icon_x = state_data_x - ICON_SIZE - 2;
-    int max_w = clientWidth - 2*H_MARGIN;
-    int memo_y = y + ICON_SIZE + LABEL_V_DISTANCE;
-
-    SetControlPos( hDlg, idColor, x, y, ICON_SIZE, ICON_SIZE );
-    SetControlPos( hDlg, idEngineLabel, label_x, label_y, state_icon_x - label_x, label_h );
-    SetControlPos( hDlg, idStateIcon, state_icon_x, y, ICON_SIZE, ICON_SIZE );
-    SetControlPos( hDlg, idStateData, state_data_x, label_y, state_data_w, label_h );
-    SetControlPos( hDlg, idNPS, nps_x, label_y, nps_w, label_h );
-    SetControlPos( hDlg, idMemo, x, memo_y, max_w, memoHeight );
-}
-
-static VOID ResizeWindowControls( HWND hDlg, int mode )
-{
-    RECT rc;
-    int headerHeight = GetHeaderHeight();
-    int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 );
-    int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN;
-    int labelDeltaY = ICON_SIZE - labelHeight;
-    int clientWidth;
-    int clientHeight;
-    int maxControlWidth;
-    int npsWidth;
-
-    /* Initialize variables */
-    GetClientRect( hDlg, &rc );
-
-    clientWidth = rc.right - rc.left;
-    clientHeight = rc.bottom - rc.top;
-
-    maxControlWidth = clientWidth - 2*H_MARGIN;
-
-    npsWidth = GetControlWidth( hDlg, IDC_Engine1_NPS );
-
-    /* Resize controls */
-    if( mode == 0 ) {
-        /* One engine */
-        PositionControlSet( hDlg, H_MARGIN, V_MARGIN,
-            clientWidth,
-            clientHeight - V_MARGIN - LABEL_V_DISTANCE - headerHeight- V_MARGIN,
-            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );
-
-        /* Hide controls for the second engine */
-        HideControl( hDlg, IDC_Color2 );
-        HideControl( hDlg, IDC_EngineLabel2 );
-        HideControl( hDlg, IDC_StateIcon2 );
-        HideControl( hDlg, IDC_StateData2 );
-        HideControl( hDlg, IDC_Engine2_NPS );
-        HideControl( hDlg, IDC_EngineMemo2 );
-        SendDlgItemMessage( hDlg, IDC_EngineMemo2, WM_SETTEXT, 0, (LPARAM) "" );
-        /* TODO: we should also hide/disable them!!! what about tab stops?!?! */
-    }
-    else {
-        /* Two engines */
-        int memo_h = (clientHeight - headerHeight*2 - V_MARGIN*2 - LABEL_V_DISTANCE*2 - SPLITTER_SIZE) / 2;
-        int header1_y = V_MARGIN;
-        int header2_y = V_MARGIN + headerHeight + LABEL_V_DISTANCE + memo_h + SPLITTER_SIZE;
-
-        PositionControlSet( hDlg, H_MARGIN, header1_y, clientWidth, memo_h,
-            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );
-
-        PositionControlSet( hDlg, H_MARGIN, header2_y, clientWidth, memo_h,
-            IDC_Color2, IDC_EngineLabel2, IDC_Engine2_NPS, IDC_EngineMemo2, IDC_StateIcon2, IDC_StateData2 );
-    }
-
-    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );
-    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );
-}
-
-static VOID SetDisplayMode( int mode )
-{
-    if( windowMode != mode ) {
-        windowMode = mode;
-
-        ResizeWindowControls( engineOutputDialog, mode );
-    }
-}
-
-static VOID VerifyDisplayMode()
-{
-    int mode;
-
-    /* Get proper mode for current game */
-    switch( gameMode ) {
-    case AnalyzeMode:
-    case AnalyzeFile:
-    case MachinePlaysWhite:
-    case MachinePlaysBlack:
-    case IcsPlayingWhite:
-    case IcsPlayingBlack:
-        mode = 0;
-        break;
-    case TwoMachinesPlay:
-        mode = 1;
-        break;
-    default:
-        /* Do not change */
-        return;
-    }
-
-    SetDisplayMode( mode );
-}
-
-static VOID InsertIntoMemo( HWND hMemo, char * text )
-{
-    SendMessage( hMemo, EM_SETSEL, 0, 0 );
-
-    SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );
-}
-
-static VOID SetIcon( HWND hControl, HICON hIcon )
-{
-    if( hIcon != NULL ) {
-        SendMessage( hControl, STM_SETICON, (WPARAM) hIcon, 0 );
-    }
-}
-
-static VOID SetEngineColorIcon( HWND hControl, int which )
-{
-    char color = GetEngineColor(which);
-    HICON hicon = NULL;
-
-    if( color == ENGINE_COLOR_BLACK )
-        hicon = hiColorBlack;
-    else if( color == ENGINE_COLOR_WHITE )
-        hicon = hiColorWhite;
-    else
-        hicon = hiColorUnknown;
-
-    SetIcon( hControl, hicon );
-}
-
-static SetEngineState( int which, int state, char * state_data )
-{
-    int x_which = 1 - which;
-    HWND hStateIcon = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateIcon1 : IDC_StateIcon2 );
-    HWND hStateData = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateData1 : IDC_StateData2 );
-
-    if( engineState[ which ] != state ) {
-        engineState[ which ] = state;
-
-        switch( state ) {
-        case STATE_THINKING:
-            SetIcon( hStateIcon, hiThinking );
-            if( engineState[ x_which ] == STATE_THINKING ) {
-                SetEngineState( x_which, STATE_IDLE, "" );
-            }
-            break;
-        case STATE_PONDERING:
-            SetIcon( hStateIcon, hiPondering );
-            break;
-        case STATE_ANALYZING:
-            SetIcon( hStateIcon, hiAnalyzing );
-            break;
-        default:
-            SetIcon( hStateIcon, hiClear );
-            break;
-        }
-    }
-
-    if( state_data != 0 ) {
-        SetWindowText( hStateData, state_data );
-    }
-}
-
-#define MAX_NAME_LENGTH 32
-
-static VOID UpdateControls( EngineOutputData * ed )
-{
-    BOOL isPondering = FALSE;
-
-    char s_label[MAX_NAME_LENGTH + 32];
-
-    char * name = ed->name;
-
-    /* Label */
-    if( name == 0 || *name == '\0' ) {
-        name = "?";
-    }
-
-    strncpy( s_label, name, MAX_NAME_LENGTH );
-    s_label[ MAX_NAME_LENGTH-1 ] = '\0';
-
-#ifdef SHOW_PONDERING
-    if( IsEnginePondering( ed->which ) ) {
-            char buf[8];
-
-            buf[0] = '\0';
-
-            if( ed->hint != 0 && *ed->hint != '\0' ) {
-                strncpy( buf, ed->hint, sizeof(buf) );
-                buf[sizeof(buf)-1] = '\0';
-            }
-            else if( ed->pv != 0 && *ed->pv != '\0' ) {
-                char * sep = strchr( ed->pv, ' ' );
-                int buflen = sizeof(buf);
-
-                if( sep != NULL ) {
-                    buflen = sep - ed->pv + 1;
-                    if( buflen > sizeof(buf) ) buflen = sizeof(buf);
-                }
-
-                strncpy( buf, ed->pv, buflen );
-                buf[ buflen-1 ] = '\0';
-            }
-
-            SetEngineState( ed->which, STATE_PONDERING, buf );
-        }
-    else if( gameMode == TwoMachinesPlay ) {
-            SetEngineState( ed->which, STATE_THINKING, "" );
-        }
-    else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile ) {
-        char buf[64];
-        int time_secs = ed->time / 100;
-        int time_mins = time_secs / 60;
-
-        buf[0] = '\0';
-
-        if( ed->an_move_index != 0 && ed->an_move_count != 0 && *ed->hint != '\0' ) {
-            char mov[16];
-
-            strncpy( mov, ed->hint, sizeof(mov) );
-            mov[ sizeof(mov)-1 ] = '\0';
-
-            sprintf( buf, "%d/%d: %s [%02d:%02d:%02d]", ed->an_move_index, ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );
-        }
-
-        SetEngineState( ed->which, STATE_ANALYZING, buf );
-    }
-    else {
-        SetEngineState( ed->which, STATE_IDLE, "" );
-    }
-#endif
-
-    SetWindowText( ed->hLabel, s_label );
-
-    s_label[0] = '\0';
-
-    if( ed->time > 0 && ed->nodes > 0 ) {
-        unsigned long nps_100 = ed->nodes / ed->time;
-
-        if( nps_100 < 100000 ) {
-            sprintf( s_label, "NPS: %lu", nps_100 * 100 );
-        }
-        else {
-            sprintf( s_label, "NPS: %.1fk", nps_100 / 10.0 );
-        }
-    }
-
-    SetWindowText( ed->hLabelNPS, s_label );
-
-    /* Memo */
-    if( ed->pv != 0 && *ed->pv != '\0' ) {
-        char s_nodes[24];
-        char s_score[16];
-        char s_time[24];
-        char buf[256];
-        int buflen;
-        int time_secs = ed->time / 100;
-        int time_cent = ed->time % 100;
-
-        /* Nodes */
-        if( ed->nodes < 1000000 ) {
-            sprintf( s_nodes, "%lu", ed->nodes );
-        }
-        else {
-            sprintf( s_nodes, "%.1fM", ed->nodes / 1000000.0 );
-        }
-
-        /* Score */
-        if( ed->score > 0 ) {
-            sprintf( s_score, "+%.2f", ed->score / 100.0 );
-        }
-        else {
-            sprintf( s_score, "%.2f", ed->score / 100.0 );
-        }
-
-        /* Time */
-        sprintf( s_time, "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );
-
-        /* Put all together... */
-        sprintf( buf, "%3d\t%s\t%s\t%s\t", ed->depth, s_score, s_nodes, s_time );
-
-        /* Add PV */
-        buflen = strlen(buf);
-
-        strncpy( buf + buflen, ed->pv, sizeof(buf) - buflen );
-
-        buf[ sizeof(buf) - 3 ] = '\0';
-
-        strcat( buf + buflen, "\r\n" );
-
-        /* Update memo */
-        InsertIntoMemo( ed->hMemo, buf );
-    }
-
-    /* Colors */
-    SetEngineColorIcon( ed->hColorIcon, ed->which );
-}
-
-LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
-{
-    static SnapData sd;
-
-    switch (message) {
-    case WM_INITDIALOG:
-        if( engineOutputDialog == NULL ) {
-            engineOutputDialog = hDlg;
-
-            RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */
-
-            ResizeWindowControls( hDlg, windowMode );
-
-            SetEngineState( 0, STATE_IDLE, "" );
-            SetEngineState( 1, STATE_IDLE, "" );
-        }
-
-        return FALSE;
-
-    case WM_COMMAND:
-        switch (LOWORD(wParam)) {
-        case IDOK:
-          EndDialog(hDlg, TRUE);
-          return TRUE;
-
-        case IDCANCEL:
-          EndDialog(hDlg, FALSE);
-          return TRUE;
-
-        default:
-          break;
-        }
-
-        break;
-
-    case WM_GETMINMAXINFO:
-        {
-            MINMAXINFO * mmi = (MINMAXINFO *) lParam;
-
-            mmi->ptMinTrackSize.x = 100;
-            mmi->ptMinTrackSize.y = 160;
-        }
-        break;
-
-    case WM_CLOSE:
-        EngineOutputPopDown();
-        break;
-
-    case WM_SIZE:
-        ResizeWindowControls( hDlg, windowMode );
-        break;
-
-    case WM_ENTERSIZEMOVE:
-        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
-
-    case WM_SIZING:
-        return OnSizing( &sd, hDlg, wParam, lParam );
-
-    case WM_MOVING:
-        return OnMoving( &sd, hDlg, wParam, lParam );
-
-    case WM_EXITSIZEMOVE:
-        return OnExitSizeMove( &sd, hDlg, wParam, lParam );
-    }
-
-    return FALSE;
-}
-
-VOID EngineOutputPopUp()
-{
-  FARPROC lpProc;
-
-  if( needInit ) {
-      InitializeEngineOutput();
-  }
-
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED);
-
-  if( engineOutputDialog ) {
-    SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 );
-
-    if( ! engineOutputDialogUp ) {
-        ShowWindow(engineOutputDialog, SW_SHOW);
-    }
-  }
-  else {
-    lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst );
-
-    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */
-    CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc );
-
-    FreeProcInstance(lpProc);
-  }
-
-  engineOutputDialogUp = TRUE;
-}
-
-VOID EngineOutputPopDown()
-{
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED);
-
-  if( engineOutputDialog ) {
-      ShowWindow(engineOutputDialog, SW_HIDE);
-  }
-
-  engineOutputDialogUp = FALSE;
-}
-
-BOOL EngineOutputIsUp()
-{
-    return engineOutputDialogUp;
-}
-
-VOID EngineOutputUpdate( FrontEndProgramStats * stats )
-{
-    EngineOutputData ed;
-    BOOL clearMemo = FALSE;
-    int which;
-    int depth;
-
-    if( stats == 0 ) {
-        SetEngineState( 0, STATE_IDLE, "" );
-        SetEngineState( 1, STATE_IDLE, "" );
-        return;
-    }
-
-    which = stats->which;
-    depth = stats->depth;
-
-    if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) {
-        return;
-    }
-
-    if( engineOutputDialog == NULL ) {
-        return;
-    }
-
-    VerifyDisplayMode();
-
-    ed.which = which;
-    ed.depth = depth;
-    ed.nodes = stats->nodes;
-    ed.score = stats->score;
-    ed.time = stats->time;
-    ed.pv = stats->pv;
-    ed.hint = stats->hint;
-    ed.an_move_index = stats->an_move_index;
-    ed.an_move_count = stats->an_move_count;
-
-    /* Get target control */
-    if( which == 0 ) {
-        ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color1 );
-        ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 );
-        ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon1 );
-        ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData1 );
-        ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS );
-        ed.hMemo  = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 );
-        ed.name = first.tidy;
-    }
-    else {
-        ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color2 );
-        ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 );
-        ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon2 );
-        ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData2 );
-        ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS );
-        ed.hMemo  = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 );
-        ed.name = second.tidy;
-    }
-
-    /* Clear memo if needed */
-    if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) {
-        clearMemo = TRUE;
-    }
-
-    if( lastForwardMostMove[which] != forwardMostMove ) {
-        clearMemo = TRUE;
-    }
-
-    if( clearMemo ) {
-        SendMessage( ed.hMemo, WM_SETTEXT, 0, (LPARAM) "" );
-    }
-
-    /* Update */
-    lastDepth[which] = depth;
-    lastForwardMostMove[which] = forwardMostMove;
-
-    if( ed.pv != 0 && ed.pv[0] == ' ' ) {
-        if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */
-            ed.pv = "";
-        }
-    }
-
-    UpdateControls( &ed );
-}
+/*\r
+ * Engine output (PV)\r
+ *\r
+ * Author: Alessandro Scotti (Dec 2005)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#include "config.h"\r
+\r
+#include <windows.h> /* required for all Windows applications */\r
+#include <richedit.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <commdlg.h>\r
+#include <dlgs.h>\r
+\r
+#include "common.h"\r
+#include "winboard.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+\r
+#include "wsnap.h"\r
+\r
+VOID EngineOutputPopUp();\r
+VOID EngineOutputPopDown();\r
+BOOL EngineOutputIsUp();\r
+\r
+#define SHOW_PONDERING\r
+\r
+/* Imports from backend.c */\r
+char * SavePart(char *str);\r
+\r
+/* Imports from winboard.c */\r
+extern HWND engineOutputDialog;\r
+extern BOOLEAN engineOutputDialogUp;\r
+\r
+extern HINSTANCE hInst;\r
+extern HWND hwndMain;\r
+\r
+extern WindowPlacement wpEngineOutput;\r
+\r
+/* Module variables */\r
+#define H_MARGIN            2\r
+#define V_MARGIN            2\r
+#define LABEL_V_DISTANCE    1   /* Distance between label and memo */\r
+#define SPLITTER_SIZE       4   /* Distance between first memo and second label */\r
+\r
+#define ICON_SIZE           14\r
+\r
+#define STATE_UNKNOWN   -1\r
+#define STATE_THINKING   0\r
+#define STATE_IDLE       1\r
+#define STATE_PONDERING  2\r
+#define STATE_ANALYZING  3\r
+\r
+static int  windowMode = 1;\r
+\r
+static BOOL needInit = TRUE;\r
+\r
+static HICON hiColorBlack = NULL;\r
+static HICON hiColorWhite = NULL;\r
+static HICON hiColorUnknown = NULL;\r
+static HICON hiClear = NULL;\r
+static HICON hiPondering = NULL;\r
+static HICON hiThinking = NULL;\r
+static HICON hiAnalyzing = NULL;\r
+\r
+static int  lastDepth[2] = { -1, -1 };\r
+static int  lastForwardMostMove[2] = { -1, -1 };\r
+static int  engineState[2] = { -1, -1 };\r
+\r
+typedef struct {\r
+    HWND hColorIcon;\r
+    HWND hLabel;\r
+    HWND hStateIcon;\r
+    HWND hStateData;\r
+    HWND hLabelNPS;\r
+    HWND hMemo;\r
+    char * name;\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
+} EngineOutputData;\r
+\r
+static HICON LoadIconEx( int id )\r
+{\r
+    return LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, ICON_SIZE, ICON_SIZE, 0 );\r
+}\r
+\r
+static VOID InitializeEngineOutput()\r
+{\r
+    if( needInit ) {\r
+        hiColorBlack = LoadIconEx( IDI_BLACK_14 );\r
+        hiColorWhite = LoadIconEx( IDI_WHITE_14 );\r
+        hiColorUnknown = LoadIconEx( IDI_UNKNOWN_14 );\r
+        hiClear = LoadIconEx( IDI_TRANS_14 );\r
+        hiPondering = LoadIconEx( IDI_PONDER_14 );\r
+        hiThinking = LoadIconEx( IDI_CLOCK_14 );\r
+        hiAnalyzing = LoadIconEx( IDI_ANALYZE2_14 );\r
+        needInit = FALSE;\r
+    }\r
+}\r
+\r
+static VOID SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )\r
+{\r
+    HWND hControl = GetDlgItem( hDlg, id );\r
+\r
+    SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );\r
+}\r
+\r
+#define HIDDEN_X    20000\r
+#define HIDDEN_Y    20000\r
+\r
+static VOID HideControl( HWND hDlg, int id )\r
+{\r
+    HWND hControl = GetDlgItem( hDlg, id );\r
+    RECT rc;\r
+\r
+    GetWindowRect( hControl, &rc );\r
+\r
+    /* \r
+        Avoid hiding an already hidden control, because that causes many\r
+        unnecessary WM_ERASEBKGND messages!\r
+    */\r
+    if( rc.left != HIDDEN_X || rc.top != HIDDEN_Y ) {\r
+        SetControlPos( hDlg, id, 20000, 20000, 100, 100 );\r
+    }\r
+}\r
+\r
+static int GetControlWidth( HWND hDlg, int id )\r
+{\r
+    RECT rc;\r
+\r
+    GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
+\r
+    return rc.right - rc.left;\r
+}\r
+\r
+static int GetControlHeight( HWND hDlg, int id )\r
+{\r
+    RECT rc;\r
+\r
+    GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
+\r
+    return rc.bottom - rc.top;\r
+}\r
+\r
+static int GetHeaderHeight()\r
+{\r
+    int result = GetControlHeight( engineOutputDialog, IDC_EngineLabel1 );\r
+\r
+    if( result < ICON_SIZE ) result = ICON_SIZE;\r
+\r
+    return result;\r
+}\r
+\r
+#define ENGINE_COLOR_WHITE      'w'\r
+#define ENGINE_COLOR_BLACK      'b'\r
+#define ENGINE_COLOR_UNKNOWN    ' '\r
+\r
+char GetEngineColor( int which )\r
+{\r
+    char result = ENGINE_COLOR_UNKNOWN;\r
+\r
+    if( which == 0 || which == 1 ) {\r
+        ChessProgramState * cps;\r
+\r
+        switch (gameMode) {\r
+        case MachinePlaysBlack:\r
+        case IcsPlayingBlack:\r
+            result = ENGINE_COLOR_BLACK;\r
+            break;\r
+        case MachinePlaysWhite:\r
+        case IcsPlayingWhite:\r
+            result = ENGINE_COLOR_WHITE;\r
+            break;\r
+        case AnalyzeMode:\r
+        case AnalyzeFile:\r
+            result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;\r
+            break;\r
+        case TwoMachinesPlay:\r
+            cps = (which == 0) ? &first : &second;\r
+            result = cps->twoMachinesColor[0];\r
+            result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;\r
+            break;\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+char GetActiveEngineColor()\r
+{\r
+    char result = ENGINE_COLOR_UNKNOWN;\r
+\r
+    if( gameMode == TwoMachinesPlay ) {\r
+        result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static int IsEnginePondering( int which )\r
+{\r
+    int result = FALSE;\r
+\r
+    switch (gameMode) {\r
+    case MachinePlaysBlack:\r
+    case IcsPlayingBlack:\r
+        if( WhiteOnMove(forwardMostMove) ) result = TRUE;\r
+        break;\r
+    case MachinePlaysWhite:\r
+    case IcsPlayingWhite:\r
+        if( ! WhiteOnMove(forwardMostMove) ) result = TRUE;\r
+        break;\r
+    case TwoMachinesPlay:\r
+        if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) {\r
+            if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE;\r
+        }\r
+        break;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static VOID PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData )\r
+{\r
+    int label_x = x + ICON_SIZE + H_MARGIN;\r
+    int label_h = GetControlHeight( hDlg, IDC_EngineLabel1 );\r
+    int label_y = y + ICON_SIZE - label_h;\r
+    int nps_w = GetControlWidth( hDlg, IDC_Engine1_NPS );\r
+    int nps_x = clientWidth - H_MARGIN - nps_w;\r
+    int state_data_w = GetControlWidth( hDlg, IDC_StateData1 );\r
+    int state_data_x = nps_x - H_MARGIN - state_data_w;\r
+    int state_icon_x = state_data_x - ICON_SIZE - 2;\r
+    int max_w = clientWidth - 2*H_MARGIN;\r
+    int memo_y = y + ICON_SIZE + LABEL_V_DISTANCE;\r
+\r
+    SetControlPos( hDlg, idColor, x, y, ICON_SIZE, ICON_SIZE );\r
+    SetControlPos( hDlg, idEngineLabel, label_x, label_y, state_icon_x - label_x, label_h );\r
+    SetControlPos( hDlg, idStateIcon, state_icon_x, y, ICON_SIZE, ICON_SIZE );\r
+    SetControlPos( hDlg, idStateData, state_data_x, label_y, state_data_w, label_h );\r
+    SetControlPos( hDlg, idNPS, nps_x, label_y, nps_w, label_h );\r
+    SetControlPos( hDlg, idMemo, x, memo_y, max_w, memoHeight );\r
+}\r
+\r
+static VOID ResizeWindowControls( HWND hDlg, int mode )\r
+{\r
+    RECT rc;\r
+    int headerHeight = GetHeaderHeight();\r
+    int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 );\r
+    int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN;\r
+    int labelDeltaY = ICON_SIZE - labelHeight;\r
+    int clientWidth;\r
+    int clientHeight;\r
+    int maxControlWidth;\r
+    int npsWidth;\r
+\r
+    /* Initialize variables */\r
+    GetClientRect( hDlg, &rc );\r
+\r
+    clientWidth = rc.right - rc.left;\r
+    clientHeight = rc.bottom - rc.top;\r
+\r
+    maxControlWidth = clientWidth - 2*H_MARGIN;\r
+\r
+    npsWidth = GetControlWidth( hDlg, IDC_Engine1_NPS );\r
+\r
+    /* Resize controls */\r
+    if( mode == 0 ) {\r
+        /* One engine */\r
+        PositionControlSet( hDlg, H_MARGIN, V_MARGIN, \r
+            clientWidth, \r
+            clientHeight - V_MARGIN - LABEL_V_DISTANCE - headerHeight- V_MARGIN,\r
+            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );\r
+\r
+        /* Hide controls for the second engine */\r
+        HideControl( hDlg, IDC_Color2 );\r
+        HideControl( hDlg, IDC_EngineLabel2 );\r
+        HideControl( hDlg, IDC_StateIcon2 );\r
+        HideControl( hDlg, IDC_StateData2 );\r
+        HideControl( hDlg, IDC_Engine2_NPS );\r
+        HideControl( hDlg, IDC_EngineMemo2 );\r
+        SendDlgItemMessage( hDlg, IDC_EngineMemo2, WM_SETTEXT, 0, (LPARAM) "" );\r
+        /* TODO: we should also hide/disable them!!! what about tab stops?!?! */\r
+    }\r
+    else {\r
+        /* Two engines */\r
+        int memo_h = (clientHeight - headerHeight*2 - V_MARGIN*2 - LABEL_V_DISTANCE*2 - SPLITTER_SIZE) / 2;\r
+        int header1_y = V_MARGIN;\r
+        int header2_y = V_MARGIN + headerHeight + LABEL_V_DISTANCE + memo_h + SPLITTER_SIZE;\r
+\r
+        PositionControlSet( hDlg, H_MARGIN, header1_y, clientWidth, memo_h,\r
+            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );\r
+\r
+        PositionControlSet( hDlg, H_MARGIN, header2_y, clientWidth, memo_h,\r
+            IDC_Color2, IDC_EngineLabel2, IDC_Engine2_NPS, IDC_EngineMemo2, IDC_StateIcon2, IDC_StateData2 );\r
+    }\r
+\r
+    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );\r
+    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );\r
+}\r
+\r
+static VOID SetDisplayMode( int mode )\r
+{\r
+    if( windowMode != mode ) {\r
+        windowMode = mode;\r
+\r
+        ResizeWindowControls( engineOutputDialog, mode );\r
+    }\r
+}\r
+\r
+static VOID VerifyDisplayMode()\r
+{\r
+    int mode;\r
+\r
+    /* Get proper mode for current game */\r
+    switch( gameMode ) {\r
+    case AnalyzeMode:\r
+    case AnalyzeFile:\r
+    case MachinePlaysWhite:\r
+    case MachinePlaysBlack:\r
+    case IcsPlayingWhite:\r
+    case IcsPlayingBlack:\r
+        mode = 0;\r
+        break;\r
+    case TwoMachinesPlay:\r
+        mode = 1;\r
+        break;\r
+    default:\r
+        /* Do not change */\r
+        return;\r
+    }\r
+\r
+    SetDisplayMode( mode );\r
+}\r
+\r
+static VOID InsertIntoMemo( HWND hMemo, char * text )\r
+{\r
+    SendMessage( hMemo, EM_SETSEL, 0, 0 );\r
+\r
+    SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
+}\r
+\r
+static VOID SetIcon( HWND hControl, HICON hIcon )\r
+{\r
+    if( hIcon != NULL ) {\r
+        SendMessage( hControl, STM_SETICON, (WPARAM) hIcon, 0 );\r
+    }\r
+}\r
+\r
+static VOID SetEngineColorIcon( HWND hControl, int which )\r
+{\r
+    char color = GetEngineColor(which);\r
+    HICON hicon = NULL;\r
+\r
+    if( color == ENGINE_COLOR_BLACK )\r
+        hicon = hiColorBlack;\r
+    else if( color == ENGINE_COLOR_WHITE )\r
+        hicon = hiColorWhite;\r
+    else\r
+        hicon = hiColorUnknown;\r
+\r
+    SetIcon( hControl, hicon );\r
+}\r
+\r
+static SetEngineState( int which, int state, char * state_data )\r
+{\r
+    int x_which = 1 - which;\r
+    HWND hStateIcon = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateIcon1 : IDC_StateIcon2 );\r
+    HWND hStateData = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateData1 : IDC_StateData2 );\r
+\r
+    if( engineState[ which ] != state ) {\r
+        engineState[ which ] = state;\r
+\r
+        switch( state ) {\r
+        case STATE_THINKING:\r
+            SetIcon( hStateIcon, hiThinking );\r
+            if( engineState[ x_which ] == STATE_THINKING ) {\r
+                SetEngineState( x_which, STATE_IDLE, "" );\r
+            }\r
+            break;\r
+        case STATE_PONDERING:\r
+            SetIcon( hStateIcon, hiPondering );\r
+            break;\r
+        case STATE_ANALYZING:\r
+            SetIcon( hStateIcon, hiAnalyzing );\r
+            break;\r
+        default:\r
+            SetIcon( hStateIcon, hiClear );\r
+            break;\r
+        }\r
+    }\r
+\r
+    if( state_data != 0 ) {\r
+        SetWindowText( hStateData, state_data );\r
+    }\r
+}\r
+\r
+#define MAX_NAME_LENGTH 32\r
+\r
+static VOID UpdateControls( EngineOutputData * ed )\r
+{\r
+    BOOL isPondering = FALSE;\r
+\r
+    char s_label[MAX_NAME_LENGTH + 32];\r
+    \r
+    char * name = ed->name;\r
+\r
+    /* Label */\r
+    if( name == 0 || *name == '\0' ) {\r
+        name = "?";\r
+    }\r
+\r
+    strncpy( s_label, name, MAX_NAME_LENGTH );\r
+    s_label[ MAX_NAME_LENGTH-1 ] = '\0';\r
+\r
+#ifdef SHOW_PONDERING\r
+    if( IsEnginePondering( ed->which ) ) {\r
+        char buf[8];\r
+\r
+        buf[0] = '\0';\r
+\r
+        if( ed->hint != 0 && *ed->hint != '\0' ) {\r
+            strncpy( buf, ed->hint, sizeof(buf) );\r
+            buf[sizeof(buf)-1] = '\0';\r
+        }\r
+        else if( ed->pv != 0 && *ed->pv != '\0' ) {\r
+            char * sep = strchr( ed->pv, ' ' );\r
+            int buflen = sizeof(buf);\r
+\r
+            if( sep != NULL ) {\r
+                buflen = sep - ed->pv + 1;\r
+                if( buflen > sizeof(buf) ) buflen = sizeof(buf);\r
+            }\r
+\r
+            strncpy( buf, ed->pv, buflen );\r
+            buf[ buflen-1 ] = '\0';\r
+        }\r
+\r
+        SetEngineState( ed->which, STATE_PONDERING, buf );\r
+    }\r
+    else if( gameMode == TwoMachinesPlay ) {\r
+        SetEngineState( ed->which, STATE_THINKING, "" );\r
+    }\r
+    else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile ) {\r
+        char buf[64];\r
+        int time_secs = ed->time / 100;\r
+        int time_mins = time_secs / 60;\r
+\r
+        buf[0] = '\0';\r
+\r
+        if( ed->an_move_index != 0 && ed->an_move_count != 0 && *ed->hint != '\0' ) {\r
+            char mov[16];\r
+\r
+            strncpy( mov, ed->hint, sizeof(mov) );\r
+            mov[ sizeof(mov)-1 ] = '\0';\r
+\r
+            sprintf( buf, "%d/%d: %s [%02d:%02d:%02d]", ed->an_move_index, ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );\r
+        }\r
+\r
+        SetEngineState( ed->which, STATE_ANALYZING, buf );\r
+    }\r
+    else {\r
+        SetEngineState( ed->which, STATE_IDLE, "" );\r
+    }\r
+#endif\r
+\r
+    SetWindowText( ed->hLabel, s_label );\r
+\r
+    s_label[0] = '\0';\r
+\r
+    if( ed->time > 0 && ed->nodes > 0 ) {\r
+        unsigned long nps_100 = ed->nodes / ed->time;\r
+\r
+        if( nps_100 < 100000 ) {\r
+            sprintf( s_label, "NPS: %lu", nps_100 * 100 );\r
+        }\r
+        else {\r
+            sprintf( s_label, "NPS: %.1fk", nps_100 / 10.0 );\r
+        }\r
+    }\r
+\r
+    SetWindowText( ed->hLabelNPS, s_label );\r
+\r
+    /* Memo */\r
+    if( ed->pv != 0 && *ed->pv != '\0' ) {\r
+        char s_nodes[24];\r
+        char s_score[16];\r
+        char s_time[24];\r
+        char buf[256];\r
+        int buflen;\r
+        int time_secs = ed->time / 100;\r
+        int time_cent = ed->time % 100;\r
+\r
+        /* Nodes */\r
+        if( ed->nodes < 1000000 ) {\r
+            sprintf( s_nodes, "%lu", ed->nodes );\r
+        }\r
+        else {\r
+            sprintf( s_nodes, "%.1fM", ed->nodes / 1000000.0 );\r
+        }\r
+\r
+        /* Score */\r
+        if( ed->score > 0 ) {\r
+            sprintf( s_score, "+%.2f", ed->score / 100.0 );\r
+        }\r
+        else {\r
+            sprintf( s_score, "%.2f", ed->score / 100.0 );\r
+        }\r
+\r
+        /* Time */\r
+        sprintf( s_time, "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );\r
+\r
+        /* Put all together... */\r
+        sprintf( buf, "%3d\t%s\t%s\t%s\t", ed->depth, s_score, s_nodes, s_time );\r
+\r
+        /* Add PV */\r
+        buflen = strlen(buf);\r
+\r
+        strncpy( buf + buflen, ed->pv, sizeof(buf) - buflen );\r
+\r
+        buf[ sizeof(buf) - 3 ] = '\0';\r
+\r
+        strcat( buf + buflen, "\r\n" );\r
+\r
+        /* Update memo */\r
+        InsertIntoMemo( ed->hMemo, buf );\r
+    }\r
+\r
+    /* Colors */\r
+    SetEngineColorIcon( ed->hColorIcon, ed->which );\r
+}\r
+\r
+LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )\r
+{\r
+    static SnapData sd;\r
+\r
+    switch (message) {\r
+    case WM_INITDIALOG:\r
+        if( engineOutputDialog == NULL ) {\r
+            engineOutputDialog = hDlg;\r
+\r
+            RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */\r
+\r
+            ResizeWindowControls( hDlg, windowMode );\r
+\r
+            SetEngineState( 0, STATE_IDLE, "" );\r
+            SetEngineState( 1, STATE_IDLE, "" );\r
+        }\r
+\r
+        return FALSE;\r
+\r
+    case WM_COMMAND:\r
+        switch (LOWORD(wParam)) {\r
+        case IDOK:\r
+          EndDialog(hDlg, TRUE);\r
+          return TRUE;\r
+\r
+        case IDCANCEL:\r
+          EndDialog(hDlg, FALSE);\r
+          return TRUE;\r
+\r
+        default:\r
+          break;\r
+        }\r
+\r
+        break;\r
+\r
+    case WM_GETMINMAXINFO:\r
+        {\r
+            MINMAXINFO * mmi = (MINMAXINFO *) lParam;\r
+        \r
+            mmi->ptMinTrackSize.x = 100;\r
+            mmi->ptMinTrackSize.y = 160;\r
+        }\r
+        break;\r
+\r
+    case WM_CLOSE:\r
+        EngineOutputPopDown();\r
+        break;\r
+\r
+    case WM_SIZE:\r
+        ResizeWindowControls( hDlg, windowMode );\r
+        break;\r
+\r
+    case WM_ENTERSIZEMOVE:\r
+        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_SIZING:\r
+        return OnSizing( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_MOVING:\r
+        return OnMoving( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_EXITSIZEMOVE:\r
+        return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+VOID EngineOutputPopUp()\r
+{\r
+  FARPROC lpProc;\r
+\r
+  if( needInit ) {\r
+      InitializeEngineOutput();\r
+  }\r
+  \r
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED);\r
+\r
+  if( engineOutputDialog ) {\r
+    SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 );\r
+\r
+    if( ! engineOutputDialogUp ) {\r
+        ShowWindow(engineOutputDialog, SW_SHOW);\r
+    }\r
+  }\r
+  else {\r
+    lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst );\r
+\r
+    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */\r
+    CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc );\r
+\r
+    FreeProcInstance(lpProc);\r
+  }\r
+\r
+  engineOutputDialogUp = TRUE;\r
+}\r
+\r
+VOID EngineOutputPopDown()\r
+{\r
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED);\r
+\r
+  if( engineOutputDialog ) {\r
+      ShowWindow(engineOutputDialog, SW_HIDE);\r
+  }\r
+\r
+  engineOutputDialogUp = FALSE;\r
+}\r
+\r
+BOOL EngineOutputIsUp()\r
+{\r
+    return engineOutputDialogUp;\r
+}\r
+\r
+VOID EngineOutputUpdate( FrontEndProgramStats * stats )\r
+{\r
+    EngineOutputData ed;\r
+    BOOL clearMemo = FALSE;\r
+    int which;\r
+    int depth;\r
+\r
+    if( stats == 0 ) {\r
+        SetEngineState( 0, STATE_IDLE, "" );\r
+        SetEngineState( 1, STATE_IDLE, "" );\r
+        return;\r
+    }\r
+\r
+    which = stats->which;\r
+    depth = stats->depth;\r
+\r
+    if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) {\r
+        return;\r
+    }\r
+\r
+    if( engineOutputDialog == NULL ) {\r
+        return;\r
+    }\r
+\r
+    VerifyDisplayMode();\r
+\r
+    ed.which = which;\r
+    ed.depth = depth;\r
+    ed.nodes = stats->nodes;\r
+    ed.score = stats->score;\r
+    ed.time = stats->time;\r
+    ed.pv = stats->pv;\r
+    ed.hint = stats->hint;\r
+    ed.an_move_index = stats->an_move_index;\r
+    ed.an_move_count = stats->an_move_count;\r
+\r
+    /* Get target control */\r
+    if( which == 0 ) {\r
+        ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color1 );\r
+        ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 );\r
+        ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon1 );\r
+        ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData1 );\r
+        ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS );\r
+        ed.hMemo  = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 );\r
+        ed.name = first.tidy;\r
+    }\r
+    else {\r
+        ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color2 );\r
+        ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 );\r
+        ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon2 );\r
+        ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData2 );\r
+        ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS );\r
+        ed.hMemo  = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 );\r
+        ed.name = second.tidy;\r
+    }\r
+\r
+    /* Clear memo if needed */\r
+    if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) {\r
+        clearMemo = TRUE;\r
+    }\r
+\r
+    if( lastForwardMostMove[which] != forwardMostMove ) {\r
+        clearMemo = TRUE;\r
+    }\r
+\r
+    if( clearMemo ) {\r
+        SendMessage( ed.hMemo, WM_SETTEXT, 0, (LPARAM) "" );\r
+    }\r
+\r
+    /* Update */\r
+    lastDepth[which] = depth;\r
+    lastForwardMostMove[which] = forwardMostMove;\r
+\r
+    if( ed.pv != 0 && ed.pv[0] == ' ' ) {\r
+        if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */\r
+            ed.pv = "";\r
+        }\r
+    }\r
+\r
+    UpdateControls( &ed );\r
+}\r
index 2896a23..997bd17 100644 (file)
-/*
- * Evaluation graph
- *
- * Author: Alessandro Scotti (Dec 2005)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#include "config.h"
-
-#include <windows.h> /* required for all Windows applications */
-#include <richedit.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <commdlg.h>
-#include <dlgs.h>
-
-#include "common.h"
-#include "winboard.h"
-#include "frontend.h"
-#include "backend.h"
-
-#include "wsnap.h"
-
-VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
-VOID EvalGraphPopUp();
-VOID EvalGraphPopDown();
-BOOL EvalGraphIsUp();
-
-#define WM_REFRESH_GRAPH    (WM_USER + 1)
-
-/* Imports from backend.c */
-char * SavePart(char *str);
-
-/* Imports from winboard.c */
-extern HWND evalGraphDialog;
-extern BOOLEAN evalGraphDialogUp;
-
-extern HINSTANCE hInst;
-extern HWND hwndMain;
-
-extern WindowPlacement wpEvalGraph;
-
-/* Module globals */
-static ChessProgramStats_Move * currPvInfo;
-static int currFirst = 0;
-static int currLast = 0;
-static int currCurrent = -1;
-
-static COLORREF crWhite = RGB( 0xFF, 0xFF, 0xB0 );
-static COLORREF crBlack = RGB( 0xAD, 0x5D, 0x3D );
-
-static HDC hdcPB = NULL;
-static HBITMAP hbmPB = NULL;
-static int nWidthPB = 0;
-static int nHeightPB = 0;
-static HPEN hpenDotted = NULL;
-static HPEN hpenBlueDotted = NULL;
-static HPEN hpenBold[2] = { NULL, NULL };
-static HBRUSH hbrHist[2] = { NULL, NULL };
-
-static int MarginX = 18;
-static int MarginW = 4;
-static int MarginH = 4;
-
-#define MIN_HIST_WIDTH  4
-#define MAX_HIST_WIDTH  10
-
-static int GetPvScore( int index )
-{
-    int score = currPvInfo[ index ].score;
-
-    if( index & 1 ) score = -score; /* Flip score for black */
-
-    return score;
-}
-
-static VOID DrawLine( int x1, int y1, int x2, int y2 )
-{
-    MoveToEx( hdcPB, x1, y1, NULL );
-
-    LineTo( hdcPB, x2, y2 );
-}
-
-static VOID DrawLineEx( int x1, int y1, int x2, int y2 )
-{
-    POINT stPT;
-
-    MoveToEx( hdcPB, x1, y1, &stPT );
-
-    LineTo( hdcPB, x2, y2 );
-
-    MoveToEx( hdcPB, stPT.x, stPT.y, NULL );
-}
-
-static HBRUSH CreateBrush( UINT style, COLORREF color )
-{
-    LOGBRUSH stLB;
-
-    stLB.lbStyle = style;
-    stLB.lbColor = color;
-    stLB.lbHatch = 0;
-
-    return CreateBrushIndirect( &stLB );
-}
-
-/*
-    For a centipawn value, this function returns the height of the corresponding
-    histogram, centered on the reference axis.
-
-    Note: height can be negative!
-*/
-static int GetValueY( int value )
-{
-    if( value < -700 ) value = -700;
-    if( value > +700 ) value = +700;
-
-    return (nHeightPB / 2) - (int)(value * (nHeightPB - 2*MarginH) / 1400.0);
-}
-
-static VOID DrawAxisSegmentHoriz( int value, BOOL drawValue )
-{
-    int y = GetValueY( value*100 );
-
-    SelectObject( hdcPB, GetStockObject(BLACK_PEN) );
-    DrawLine( MarginX, y, MarginX + MarginW, y );
-    SelectObject( hdcPB, hpenDotted );
-    DrawLine( MarginX + MarginW, y, nWidthPB - MarginW, y );
-
-    if( drawValue ) {
-        SIZE stSize;
-        char buf[8];
-        int cbBuf;
-
-        if( value > 0 ) {
-            buf[0] = '+';
-            itoa( value, buf+1, 10 );
-        }
-        else {
-            itoa( value, buf, 10 );
-        }
-
-        cbBuf = strlen( buf );
-
-        GetTextExtentPoint32( hdcPB, buf, cbBuf, &stSize );
-
-        TextOut( hdcPB, MarginX - stSize.cx - 2, y - stSize.cy / 2, buf, cbBuf );
-    }
-}
-
-static VOID DrawAxis()
-{
-    int cy = nHeightPB / 2;
-
-    SelectObject( hdcPB, GetStockObject(NULL_BRUSH) );
-
-    SetBkMode( hdcPB, TRANSPARENT );
-
-    DrawAxisSegmentHoriz( +5, TRUE );
-    DrawAxisSegmentHoriz( +3, FALSE );
-    DrawAxisSegmentHoriz( +1, FALSE );
-    DrawAxisSegmentHoriz(  0, TRUE );
-    DrawAxisSegmentHoriz( -1, FALSE );
-    DrawAxisSegmentHoriz( -3, FALSE );
-    DrawAxisSegmentHoriz( -5, TRUE );
-
-    SelectObject( hdcPB, GetStockObject(BLACK_PEN) );
-
-    DrawLine( MarginX + MarginW, cy, nWidthPB - MarginW, cy );
-    DrawLine( MarginX + MarginW, MarginH, MarginX + MarginW, nHeightPB - MarginH );
-}
-
-static VOID DrawHistogram( int x, int y, int width, int value, int side )
-{
-    RECT rc;
-
-    if( value > -25 && value < +25 ) return;
-
-    rc.left = x;
-    rc.right = rc.left + width + 1;
-
-    if( value > 0 ) {
-        rc.top = GetValueY( value );
-        rc.bottom = y+1;
-    }
-    else {
-        rc.top = y;
-        rc.bottom = GetValueY( value ) + 1;
-    }
-
-
-    if( width == MIN_HIST_WIDTH ) {
-        rc.right--;
-        FillRect( hdcPB, &rc, hbrHist[side] );
-    }
-    else {
-        SelectObject( hdcPB, hbrHist[side] );
-        Rectangle( hdcPB, rc.left, rc.top, rc.right, rc.bottom );
-    }
-}
-
-static VOID DrawSeparator( int index, int x )
-{
-    if( index > 0 ) {
-        if( index == currCurrent ) {
-            HPEN hp = SelectObject( hdcPB, hpenBlueDotted );
-            DrawLineEx( x, MarginH, x, nHeightPB - MarginH );
-            SelectObject( hdcPB, hp );
-        }
-        else if( (index % 20) == 0 ) {
-            HPEN hp = SelectObject( hdcPB, hpenDotted );
-            DrawLineEx( x, MarginH, x, nHeightPB - MarginH );
-            SelectObject( hdcPB, hp );
-        }
-    }
-}
-
-/* Actually draw histogram as a diagram, cause there's too much data */
-static VOID DrawHistogramAsDiagram( int cy, int paint_width, int hist_count )
-{
-    double step;
-    int i;
-
-    /* Rescale the graph every few moves (as opposed to every move) */
-    hist_count -= hist_count % 8;
-    hist_count += 8;
-    hist_count /= 2;
-
-    step = (double) paint_width / (hist_count + 1);
-
-    for( i=0; i<2; i++ ) {
-        int index = currFirst;
-        int side = (currCurrent + i + 1) & 1; /* Draw current side last */
-        double x = MarginX + MarginW;
-
-        if( (index & 1) != side ) {
-            x += step / 2;
-            index++;
-        }
-
-        SelectObject( hdcPB, hpenBold[side] );
-
-        MoveToEx( hdcPB, (int) x, cy, NULL );
-
-        index += 2;
-
-        while( index < currLast ) {
-            x += step;
-
-            DrawSeparator( index, (int) x );
-
-            /* Extend line up to current point */
-            if( currPvInfo[index].depth > 0 ) {
-                LineTo( hdcPB, (int) x, GetValueY( GetPvScore(index) ) );
-            }
-
-            index += 2;
-        }
-    }
-}
-
-static VOID DrawHistogramFull( int cy, int hist_width, int hist_count )
-{
-    int i;
-
-    SelectObject( hdcPB, GetStockObject(BLACK_PEN) );
-
-    for( i=0; i<hist_count; i++ ) {
-        int index = currFirst + i;
-        int x = MarginX + MarginW + index * hist_width;
-
-        /* Draw a separator every 10 moves */
-        DrawSeparator( index, x );
-
-        /* Draw histogram */
-        if( currPvInfo[i].depth > 0 ) {
-            DrawHistogram( x, cy, hist_width, GetPvScore(index), index & 1 );
-        }
-    }
-}
-
-typedef struct {
-    int cy;
-    int hist_width;
-    int hist_count;
-    int paint_width;
-} VisualizationData;
-
-static BOOL InitVisualization( VisualizationData * vd )
-{
-    BOOL result = FALSE;
-
-    vd->cy = nHeightPB / 2;
-    vd->hist_width = MIN_HIST_WIDTH;
-    vd->hist_count = currLast - currFirst;
-    vd->paint_width = nWidthPB - MarginX - 2*MarginW;
-
-    if( vd->hist_count > 0 ) {
-        result = TRUE;
-
-        /* Compute width */
-        vd->hist_width = vd->paint_width / vd->hist_count;
-
-        if( vd->hist_width > MAX_HIST_WIDTH ) vd->hist_width = MAX_HIST_WIDTH;
-
-        vd->hist_width -= vd->hist_width % 2;
-    }
-
-    return result;
-}
-
-static VOID DrawHistograms()
-{
-    VisualizationData vd;
-
-    if( InitVisualization( &vd ) ) {
-        if( vd.hist_width < MIN_HIST_WIDTH ) {
-            DrawHistogramAsDiagram( vd.cy, vd.paint_width, vd.hist_count );
-        }
-        else {
-            DrawHistogramFull( vd.cy, vd.hist_width, vd.hist_count );
-        }
-    }
-}
-
-static int GetMoveIndexFromPoint( int x, int y )
-{
-    int result = -1;
-    int start_x = MarginX + MarginW;
-    VisualizationData vd;
-
-    if( x >= start_x && InitVisualization( &vd ) ) {
-        /* Almost an hack here... we duplicate some of the paint logic */
-        if( vd.hist_width < MIN_HIST_WIDTH ) {
-            double step;
-
-            vd.hist_count -= vd.hist_count % 8;
-            vd.hist_count += 8;
-            vd.hist_count /= 2;
-
-            step = (double) vd.paint_width / (vd.hist_count + 1);
-            step /= 2;
-
-            result = (int) (0.5 + (double) (x - start_x) / step);
-        }
-        else {
-            result = (x - start_x) / vd.hist_width;
-        }
-    }
-
-    if( result >= currLast ) {
-        result = -1;
-    }
-
-    return result;
-}
-
-static VOID DrawBackground()
-{
-    HBRUSH hbr;
-    RECT rc;
-
-    hbr = CreateBrush( BS_SOLID, GetSysColor( COLOR_3DFACE ) );
-
-    rc.left = 0;
-    rc.top = 0;
-    rc.right = nWidthPB;
-    rc.bottom = nHeightPB;
-
-    FillRect( hdcPB, &rc, hbr );
-
-    DeleteObject( hbr );
-}
-
-static VOID PaintEvalGraph( HWND hWnd, HDC hDC )
-{
-    RECT rcClient;
-    int width;
-    int height;
-
-    /* Get client area */
-    GetClientRect( hWnd, &rcClient );
-
-    width = rcClient.right - rcClient.left;
-    height = rcClient.bottom - rcClient.top;
-
-    /* Create or recreate paint box if needed */
-    if( hbmPB == NULL || width != nWidthPB || height != nHeightPB ) {
-        if( hpenDotted == NULL ) {
-            hpenDotted = CreatePen( PS_DOT, 0, RGB(0xA0,0xA0,0xA0) );
-            hpenBlueDotted = CreatePen( PS_DOT, 0, RGB(0x00,0x00,0xFF) );
-            hpenBold[0] = CreatePen( PS_SOLID, 2, crWhite );
-            hpenBold[1] = CreatePen( PS_SOLID, 2, crBlack );
-            hbrHist[0] = CreateBrush( BS_SOLID, crWhite );
-            hbrHist[1] = CreateBrush( BS_SOLID, crBlack );
-        }
-
-        if( hdcPB != NULL ) {
-            DeleteDC( hdcPB );
-            hdcPB = NULL;
-        }
-
-        if( hbmPB != NULL ) {
-            DeleteObject( hbmPB );
-            hbmPB = NULL;
-        }
-
-        hdcPB = CreateCompatibleDC( hDC );
-
-        nWidthPB = width;
-        nHeightPB = height;
-        hbmPB = CreateCompatibleBitmap( hDC, nWidthPB, nHeightPB );
-
-        SelectObject( hdcPB, hbmPB );
-    }
-
-    /* Draw */
-    DrawBackground();
-    DrawAxis();
-    DrawHistograms();
-
-    /* Copy bitmap into destination DC */
-    BitBlt( hDC, 0, 0, width, height, hdcPB, 0, 0, SRCCOPY );
-}
-
-LRESULT CALLBACK EvalGraphProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
-{
-    static SnapData sd;
-
-    PAINTSTRUCT stPS;
-    HDC hDC;
-
-    switch (message) {
-    case WM_INITDIALOG:
-        if( evalGraphDialog == NULL ) {
-            evalGraphDialog = hDlg;
-
-            RestoreWindowPlacement( hDlg, &wpEvalGraph ); /* Restore window placement */
-        }
-
-        return FALSE;
-
-    case WM_COMMAND:
-        switch (LOWORD(wParam)) {
-        case IDOK:
-          EndDialog(hDlg, TRUE);
-          return TRUE;
-
-        case IDCANCEL:
-          EndDialog(hDlg, FALSE);
-          return TRUE;
-
-        default:
-          break;
-        }
-
-        break;
-
-    case WM_ERASEBKGND:
-        return TRUE;
-
-    case WM_PAINT:
-        hDC = BeginPaint( hDlg, &stPS );
-        PaintEvalGraph( hDlg, hDC );
-        EndPaint( hDlg, &stPS );
-        break;
-
-    case WM_REFRESH_GRAPH:
-        hDC = GetDC( hDlg );
-        PaintEvalGraph( hDlg, hDC );
-        ReleaseDC( hDlg, hDC );
-        break;
-
-    case WM_LBUTTONDBLCLK:
-        if( wParam == 0 || wParam == MK_LBUTTON ) {
-            int index = GetMoveIndexFromPoint( LOWORD(lParam), HIWORD(lParam) );
-
-            if( index >= 0 && index < currLast ) {
-                ToNrEvent( index + 1 );
-            }
-        }
-        return TRUE;
-
-    case WM_SIZE:
-        InvalidateRect( hDlg, NULL, FALSE );
-        break;
-
-    case WM_GETMINMAXINFO:
-        {
-            MINMAXINFO * mmi = (MINMAXINFO *) lParam;
-
-            mmi->ptMinTrackSize.x = 100;
-            mmi->ptMinTrackSize.y = 100;
-        }
-        break;
-
-    /* Support for captionless window */
-#if 0
-    case WM_NCLBUTTONDBLCLK:
-        if( wParam == HTCAPTION ) {
-            int index;
-            POINT mouse_xy;
-            POINTS pts = MAKEPOINTS(lParam);
-
-            mouse_xy.x = pts.x;
-            mouse_xy.y = pts.y;
-            ScreenToClient( hDlg, &mouse_xy );
-
-            index = GetMoveIndexFromPoint( mouse_xy.x, mouse_xy.y );
-
-            if( index >= 0 && index < currLast ) {
-                ToNrEvent( index + 1 );
-            }
-        }
-        break;
-
-    case WM_NCHITTEST:
-        {
-            LRESULT res = DefWindowProc( hDlg, message, wParam, lParam );
-
-            if( res == HTCLIENT ) res = HTCAPTION;
-
-            SetWindowLong( hDlg, DWL_MSGRESULT, res );
-
-            return TRUE;
-        }
-        break;
-#endif
-
-    case WM_CLOSE:
-        EvalGraphPopDown();
-        break;
-
-    case WM_ENTERSIZEMOVE:
-        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
-
-    case WM_SIZING:
-        return OnSizing( &sd, hDlg, wParam, lParam );
-
-    case WM_MOVING:
-        return OnMoving( &sd, hDlg, wParam, lParam );
-
-    case WM_EXITSIZEMOVE:
-        return OnExitSizeMove( &sd, hDlg, wParam, lParam );
-    }
-
-    return FALSE;
-}
-
-VOID EvalGraphPopUp()
-{
-  FARPROC lpProc;
-
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEvalGraph, MF_CHECKED);
-
-  if( evalGraphDialog ) {
-    SendMessage( evalGraphDialog, WM_INITDIALOG, 0, 0 );
-
-    if( ! evalGraphDialogUp ) {
-        ShowWindow(evalGraphDialog, SW_SHOW);
-    }
-  }
-  else {
-    crWhite = appData.evalHistColorWhite;
-    crBlack = appData.evalHistColorBlack;
-
-    lpProc = MakeProcInstance( (FARPROC) EvalGraphProc, hInst );
-
-    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */
-    CreateDialog( hInst, MAKEINTRESOURCE(DLG_EvalGraph), hwndMain, (DLGPROC)lpProc );
-
-    FreeProcInstance(lpProc);
-  }
-
-  evalGraphDialogUp = TRUE;
-}
-
-VOID EvalGraphPopDown()
-{
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEvalGraph, MF_UNCHECKED);
-
-  if( evalGraphDialog ) {
-      ShowWindow(evalGraphDialog, SW_HIDE);
-  }
-
-  evalGraphDialogUp = FALSE;
-}
-
-VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo )
-{
-    /* [AS] Danger! For now we rely on the pvInfo parameter being a static variable! */
-
-    currFirst = first;
-    currLast = last;
-    currCurrent = current;
-    currPvInfo = pvInfo;
-
-    if( evalGraphDialog ) {
-        SendMessage( evalGraphDialog, WM_REFRESH_GRAPH, 0, 0 );
-    }
-}
-
-BOOL EvalGraphIsUp()
-{
-    return evalGraphDialogUp;
-}
+/*\r
+ * Evaluation graph\r
+ *\r
+ * Author: Alessandro Scotti (Dec 2005)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#include "config.h"\r
+\r
+#include <windows.h> /* required for all Windows applications */\r
+#include <richedit.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <commdlg.h>\r
+#include <dlgs.h>\r
+\r
+#include "common.h"\r
+#include "winboard.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+\r
+#include "wsnap.h"\r
+\r
+VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );\r
+VOID EvalGraphPopUp();\r
+VOID EvalGraphPopDown();\r
+BOOL EvalGraphIsUp();\r
+\r
+#define WM_REFRESH_GRAPH    (WM_USER + 1)\r
+\r
+/* Imports from backend.c */\r
+char * SavePart(char *str);\r
+\r
+/* Imports from winboard.c */\r
+extern HWND evalGraphDialog;\r
+extern BOOLEAN evalGraphDialogUp;\r
+\r
+extern HINSTANCE hInst;\r
+extern HWND hwndMain;\r
+\r
+extern WindowPlacement wpEvalGraph;\r
+\r
+/* Module globals */\r
+static ChessProgramStats_Move * currPvInfo;\r
+static int currFirst = 0;\r
+static int currLast = 0;\r
+static int currCurrent = -1;\r
+\r
+static COLORREF crWhite = RGB( 0xFF, 0xFF, 0xB0 );\r
+static COLORREF crBlack = RGB( 0xAD, 0x5D, 0x3D );\r
+\r
+static HDC hdcPB = NULL;\r
+static HBITMAP hbmPB = NULL;\r
+static int nWidthPB = 0;\r
+static int nHeightPB = 0;\r
+static HPEN hpenDotted = NULL;\r
+static HPEN hpenBlueDotted = NULL;\r
+static HPEN hpenBold[2] = { NULL, NULL };\r
+static HBRUSH hbrHist[2] = { NULL, NULL };\r
+\r
+static int MarginX = 18;\r
+static int MarginW = 4;\r
+static int MarginH = 4;\r
+\r
+#define MIN_HIST_WIDTH  4\r
+#define MAX_HIST_WIDTH  10\r
+\r
+static int GetPvScore( int index )\r
+{\r
+    int score = currPvInfo[ index ].score;\r
+\r
+    if( index & 1 ) score = -score; /* Flip score for black */\r
+\r
+    return score;\r
+}\r
+\r
+static VOID DrawLine( int x1, int y1, int x2, int y2 )\r
+{\r
+    MoveToEx( hdcPB, x1, y1, NULL );\r
+\r
+    LineTo( hdcPB, x2, y2 );\r
+}\r
+\r
+static VOID DrawLineEx( int x1, int y1, int x2, int y2 )\r
+{\r
+    POINT stPT;\r
+\r
+    MoveToEx( hdcPB, x1, y1, &stPT );\r
+\r
+    LineTo( hdcPB, x2, y2 );\r
+\r
+    MoveToEx( hdcPB, stPT.x, stPT.y, NULL );\r
+}\r
+\r
+static HBRUSH CreateBrush( UINT style, COLORREF color )\r
+{\r
+    LOGBRUSH stLB;\r
+\r
+    stLB.lbStyle = style;\r
+    stLB.lbColor = color;\r
+    stLB.lbHatch = 0;\r
+\r
+    return CreateBrushIndirect( &stLB );\r
+}\r
+\r
+/*\r
+    For a centipawn value, this function returns the height of the corresponding\r
+    histogram, centered on the reference axis.\r
+\r
+    Note: height can be negative!\r
+*/\r
+static int GetValueY( int value )\r
+{\r
+    if( value < -700 ) value = -700;\r
+    if( value > +700 ) value = +700;\r
+\r
+    return (nHeightPB / 2) - (int)(value * (nHeightPB - 2*MarginH) / 1400.0);\r
+}\r
+\r
+static VOID DrawAxisSegmentHoriz( int value, BOOL drawValue )\r
+{\r
+    int y = GetValueY( value*100 );\r
+\r
+    SelectObject( hdcPB, GetStockObject(BLACK_PEN) );\r
+    DrawLine( MarginX, y, MarginX + MarginW, y );\r
+    SelectObject( hdcPB, hpenDotted );\r
+    DrawLine( MarginX + MarginW, y, nWidthPB - MarginW, y );\r
+\r
+    if( drawValue ) {\r
+        SIZE stSize;\r
+        char buf[8];\r
+        int cbBuf;\r
+\r
+        if( value > 0 ) {\r
+            buf[0] = '+';\r
+            itoa( value, buf+1, 10 );\r
+        }\r
+        else {\r
+            itoa( value, buf, 10 );\r
+        }\r
+\r
+        cbBuf = strlen( buf );\r
+\r
+        GetTextExtentPoint32( hdcPB, buf, cbBuf, &stSize );\r
+\r
+        TextOut( hdcPB, MarginX - stSize.cx - 2, y - stSize.cy / 2, buf, cbBuf );\r
+    }\r
+}\r
+\r
+static VOID DrawAxis()\r
+{\r
+    int cy = nHeightPB / 2;\r
+    \r
+    SelectObject( hdcPB, GetStockObject(NULL_BRUSH) );\r
+\r
+    SetBkMode( hdcPB, TRANSPARENT );\r
+\r
+    DrawAxisSegmentHoriz( +5, TRUE );\r
+    DrawAxisSegmentHoriz( +3, FALSE );\r
+    DrawAxisSegmentHoriz( +1, FALSE );\r
+    DrawAxisSegmentHoriz(  0, TRUE );\r
+    DrawAxisSegmentHoriz( -1, FALSE );\r
+    DrawAxisSegmentHoriz( -3, FALSE );\r
+    DrawAxisSegmentHoriz( -5, TRUE );\r
+\r
+    SelectObject( hdcPB, GetStockObject(BLACK_PEN) );\r
+\r
+    DrawLine( MarginX + MarginW, cy, nWidthPB - MarginW, cy );\r
+    DrawLine( MarginX + MarginW, MarginH, MarginX + MarginW, nHeightPB - MarginH );\r
+}\r
+\r
+static VOID DrawHistogram( int x, int y, int width, int value, int side )\r
+{\r
+    RECT rc;\r
+\r
+    if( value > -25 && value < +25 ) return;\r
+\r
+    rc.left = x;\r
+    rc.right = rc.left + width + 1;\r
+\r
+    if( value > 0 ) {\r
+        rc.top = GetValueY( value );\r
+        rc.bottom = y+1;\r
+    }\r
+    else {\r
+        rc.top = y;\r
+        rc.bottom = GetValueY( value ) + 1;\r
+    }\r
+\r
+\r
+    if( width == MIN_HIST_WIDTH ) {\r
+        rc.right--;\r
+        FillRect( hdcPB, &rc, hbrHist[side] );\r
+    }\r
+    else {\r
+        SelectObject( hdcPB, hbrHist[side] );\r
+        Rectangle( hdcPB, rc.left, rc.top, rc.right, rc.bottom );\r
+    }\r
+}\r
+\r
+static VOID DrawSeparator( int index, int x )\r
+{\r
+    if( index > 0 ) {\r
+        if( index == currCurrent ) {\r
+            HPEN hp = SelectObject( hdcPB, hpenBlueDotted );\r
+            DrawLineEx( x, MarginH, x, nHeightPB - MarginH );\r
+            SelectObject( hdcPB, hp );\r
+        }\r
+        else if( (index % 20) == 0 ) {\r
+            HPEN hp = SelectObject( hdcPB, hpenDotted );\r
+            DrawLineEx( x, MarginH, x, nHeightPB - MarginH );\r
+            SelectObject( hdcPB, hp );\r
+        }\r
+    }\r
+}\r
+\r
+/* Actually draw histogram as a diagram, cause there's too much data */\r
+static VOID DrawHistogramAsDiagram( int cy, int paint_width, int hist_count )\r
+{\r
+    double step;\r
+    int i;\r
+\r
+    /* Rescale the graph every few moves (as opposed to every move) */\r
+    hist_count -= hist_count % 8;\r
+    hist_count += 8;\r
+    hist_count /= 2;\r
+\r
+    step = (double) paint_width / (hist_count + 1);\r
+\r
+    for( i=0; i<2; i++ ) {\r
+        int index = currFirst;\r
+        int side = (currCurrent + i + 1) & 1; /* Draw current side last */\r
+        double x = MarginX + MarginW;\r
+\r
+        if( (index & 1) != side ) {\r
+            x += step / 2;\r
+            index++;\r
+        }\r
+\r
+        SelectObject( hdcPB, hpenBold[side] );\r
+\r
+        MoveToEx( hdcPB, (int) x, cy, NULL );\r
+\r
+        index += 2;\r
+\r
+        while( index < currLast ) {\r
+            x += step;\r
+\r
+            DrawSeparator( index, (int) x );\r
+\r
+            /* Extend line up to current point */\r
+            if( currPvInfo[index].depth > 0 ) {\r
+                LineTo( hdcPB, (int) x, GetValueY( GetPvScore(index) ) );\r
+            }\r
+\r
+            index += 2;\r
+        }\r
+    }\r
+}\r
+\r
+static VOID DrawHistogramFull( int cy, int hist_width, int hist_count )\r
+{\r
+    int i;\r
+\r
+    SelectObject( hdcPB, GetStockObject(BLACK_PEN) );\r
+\r
+    for( i=0; i<hist_count; i++ ) {\r
+        int index = currFirst + i;\r
+        int x = MarginX + MarginW + index * hist_width;\r
+\r
+        /* Draw a separator every 10 moves */\r
+        DrawSeparator( index, x );\r
+\r
+        /* Draw histogram */\r
+        if( currPvInfo[i].depth > 0 ) {\r
+            DrawHistogram( x, cy, hist_width, GetPvScore(index), index & 1 );\r
+        }\r
+    }\r
+}\r
+\r
+typedef struct {\r
+    int cy;\r
+    int hist_width;\r
+    int hist_count;\r
+    int paint_width;\r
+} VisualizationData;\r
+\r
+static BOOL InitVisualization( VisualizationData * vd )\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    vd->cy = nHeightPB / 2;\r
+    vd->hist_width = MIN_HIST_WIDTH;\r
+    vd->hist_count = currLast - currFirst;\r
+    vd->paint_width = nWidthPB - MarginX - 2*MarginW;\r
+\r
+    if( vd->hist_count > 0 ) {\r
+        result = TRUE;\r
+\r
+        /* Compute width */\r
+        vd->hist_width = vd->paint_width / vd->hist_count;\r
+\r
+        if( vd->hist_width > MAX_HIST_WIDTH ) vd->hist_width = MAX_HIST_WIDTH;\r
+\r
+        vd->hist_width -= vd->hist_width % 2;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static VOID DrawHistograms()\r
+{\r
+    VisualizationData vd;\r
+\r
+    if( InitVisualization( &vd ) ) {\r
+        if( vd.hist_width < MIN_HIST_WIDTH ) {\r
+            DrawHistogramAsDiagram( vd.cy, vd.paint_width, vd.hist_count );\r
+        }\r
+        else {\r
+            DrawHistogramFull( vd.cy, vd.hist_width, vd.hist_count );\r
+        }\r
+    }\r
+}\r
+\r
+static int GetMoveIndexFromPoint( int x, int y )\r
+{\r
+    int result = -1;\r
+    int start_x = MarginX + MarginW;\r
+    VisualizationData vd;\r
+\r
+    if( x >= start_x && InitVisualization( &vd ) ) {\r
+        /* Almost an hack here... we duplicate some of the paint logic */\r
+        if( vd.hist_width < MIN_HIST_WIDTH ) {\r
+            double step;\r
+\r
+            vd.hist_count -= vd.hist_count % 8;\r
+            vd.hist_count += 8;\r
+            vd.hist_count /= 2;\r
+\r
+            step = (double) vd.paint_width / (vd.hist_count + 1);\r
+            step /= 2;\r
+\r
+            result = (int) (0.5 + (double) (x - start_x) / step);\r
+        }\r
+        else {\r
+            result = (x - start_x) / vd.hist_width;\r
+        }\r
+    }\r
+\r
+    if( result >= currLast ) {\r
+        result = -1;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static VOID DrawBackground()\r
+{\r
+    HBRUSH hbr;\r
+    RECT rc;\r
+\r
+    hbr = CreateBrush( BS_SOLID, GetSysColor( COLOR_3DFACE ) );\r
+\r
+    rc.left = 0;\r
+    rc.top = 0;\r
+    rc.right = nWidthPB;\r
+    rc.bottom = nHeightPB;\r
+\r
+    FillRect( hdcPB, &rc, hbr );\r
+\r
+    DeleteObject( hbr );\r
+}\r
+\r
+static VOID PaintEvalGraph( HWND hWnd, HDC hDC )\r
+{\r
+    RECT rcClient;\r
+    int width;\r
+    int height;\r
+\r
+    /* Get client area */\r
+    GetClientRect( hWnd, &rcClient );\r
+\r
+    width = rcClient.right - rcClient.left;\r
+    height = rcClient.bottom - rcClient.top;\r
+\r
+    /* Create or recreate paint box if needed */\r
+    if( hbmPB == NULL || width != nWidthPB || height != nHeightPB ) {\r
+        if( hpenDotted == NULL ) {\r
+            hpenDotted = CreatePen( PS_DOT, 0, RGB(0xA0,0xA0,0xA0) );\r
+            hpenBlueDotted = CreatePen( PS_DOT, 0, RGB(0x00,0x00,0xFF) );\r
+            hpenBold[0] = CreatePen( PS_SOLID, 2, crWhite );\r
+            hpenBold[1] = CreatePen( PS_SOLID, 2, crBlack );\r
+            hbrHist[0] = CreateBrush( BS_SOLID, crWhite );\r
+            hbrHist[1] = CreateBrush( BS_SOLID, crBlack );\r
+        }\r
+\r
+        if( hdcPB != NULL ) {\r
+            DeleteDC( hdcPB );\r
+            hdcPB = NULL;\r
+        }\r
+\r
+        if( hbmPB != NULL ) {\r
+            DeleteObject( hbmPB );\r
+            hbmPB = NULL;\r
+        }\r
+\r
+        hdcPB = CreateCompatibleDC( hDC );\r
+\r
+        nWidthPB = width;\r
+        nHeightPB = height;\r
+        hbmPB = CreateCompatibleBitmap( hDC, nWidthPB, nHeightPB );\r
+\r
+        SelectObject( hdcPB, hbmPB );\r
+    }\r
+\r
+    /* Draw */\r
+    DrawBackground();\r
+    DrawAxis();\r
+    DrawHistograms();\r
+\r
+    /* Copy bitmap into destination DC */\r
+    BitBlt( hDC, 0, 0, width, height, hdcPB, 0, 0, SRCCOPY );\r
+}\r
+\r
+LRESULT CALLBACK EvalGraphProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )\r
+{\r
+    static SnapData sd;\r
+\r
+    PAINTSTRUCT stPS;\r
+    HDC hDC;\r
+\r
+    switch (message) {\r
+    case WM_INITDIALOG:\r
+        if( evalGraphDialog == NULL ) {\r
+            evalGraphDialog = hDlg;\r
+\r
+            RestoreWindowPlacement( hDlg, &wpEvalGraph ); /* Restore window placement */\r
+        }\r
+\r
+        return FALSE;\r
+\r
+    case WM_COMMAND:\r
+        switch (LOWORD(wParam)) {\r
+        case IDOK:\r
+          EndDialog(hDlg, TRUE);\r
+          return TRUE;\r
+\r
+        case IDCANCEL:\r
+          EndDialog(hDlg, FALSE);\r
+          return TRUE;\r
+\r
+        default:\r
+          break;\r
+        }\r
+\r
+        break;\r
+\r
+    case WM_ERASEBKGND:\r
+        return TRUE;\r
+\r
+    case WM_PAINT:\r
+        hDC = BeginPaint( hDlg, &stPS );\r
+        PaintEvalGraph( hDlg, hDC );\r
+        EndPaint( hDlg, &stPS );\r
+        break;\r
+\r
+    case WM_REFRESH_GRAPH:\r
+        hDC = GetDC( hDlg );\r
+        PaintEvalGraph( hDlg, hDC );\r
+        ReleaseDC( hDlg, hDC );\r
+        break;\r
+\r
+    case WM_LBUTTONDBLCLK:\r
+        if( wParam == 0 || wParam == MK_LBUTTON ) {\r
+            int index = GetMoveIndexFromPoint( LOWORD(lParam), HIWORD(lParam) );\r
+\r
+            if( index >= 0 && index < currLast ) {\r
+                ToNrEvent( index + 1 );\r
+            }\r
+        }\r
+        return TRUE;\r
+\r
+    case WM_SIZE:\r
+        InvalidateRect( hDlg, NULL, FALSE );\r
+        break;\r
+\r
+    case WM_GETMINMAXINFO:\r
+        {\r
+            MINMAXINFO * mmi = (MINMAXINFO *) lParam;\r
+        \r
+            mmi->ptMinTrackSize.x = 100;\r
+            mmi->ptMinTrackSize.y = 100;\r
+        }\r
+        break;\r
+\r
+    /* Support for captionless window */\r
+#if 0\r
+    case WM_NCLBUTTONDBLCLK:\r
+        if( wParam == HTCAPTION ) {\r
+            int index;\r
+            POINT mouse_xy;\r
+            POINTS pts = MAKEPOINTS(lParam);\r
+\r
+            mouse_xy.x = pts.x;\r
+            mouse_xy.y = pts.y;\r
+            ScreenToClient( hDlg, &mouse_xy );\r
+\r
+            index = GetMoveIndexFromPoint( mouse_xy.x, mouse_xy.y );\r
+\r
+            if( index >= 0 && index < currLast ) {\r
+                ToNrEvent( index + 1 );\r
+            }\r
+        }\r
+        break;\r
+\r
+    case WM_NCHITTEST:\r
+        {\r
+            LRESULT res = DefWindowProc( hDlg, message, wParam, lParam );\r
+\r
+            if( res == HTCLIENT ) res = HTCAPTION;\r
+\r
+            SetWindowLong( hDlg, DWL_MSGRESULT, res );\r
+\r
+            return TRUE;\r
+        }\r
+        break;\r
+#endif\r
+\r
+    case WM_CLOSE:\r
+        EvalGraphPopDown();\r
+        break;\r
+\r
+    case WM_ENTERSIZEMOVE:\r
+        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_SIZING:\r
+        return OnSizing( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_MOVING:\r
+        return OnMoving( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_EXITSIZEMOVE:\r
+        return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+VOID EvalGraphPopUp()\r
+{\r
+  FARPROC lpProc;\r
+  \r
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEvalGraph, MF_CHECKED);\r
+\r
+  if( evalGraphDialog ) {\r
+    SendMessage( evalGraphDialog, WM_INITDIALOG, 0, 0 );\r
+\r
+    if( ! evalGraphDialogUp ) {\r
+        ShowWindow(evalGraphDialog, SW_SHOW);\r
+    }\r
+  }\r
+  else {\r
+    crWhite = appData.evalHistColorWhite;\r
+    crBlack = appData.evalHistColorBlack;\r
+\r
+    lpProc = MakeProcInstance( (FARPROC) EvalGraphProc, hInst );\r
+\r
+    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */\r
+    CreateDialog( hInst, MAKEINTRESOURCE(DLG_EvalGraph), hwndMain, (DLGPROC)lpProc );\r
+\r
+    FreeProcInstance(lpProc);\r
+  }\r
+\r
+  evalGraphDialogUp = TRUE;\r
+}\r
+\r
+VOID EvalGraphPopDown()\r
+{\r
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEvalGraph, MF_UNCHECKED);\r
+\r
+  if( evalGraphDialog ) {\r
+      ShowWindow(evalGraphDialog, SW_HIDE);\r
+  }\r
+\r
+  evalGraphDialogUp = FALSE;\r
+}\r
+\r
+VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo )\r
+{\r
+    /* [AS] Danger! For now we rely on the pvInfo parameter being a static variable! */\r
+\r
+    currFirst = first;\r
+    currLast = last;\r
+    currCurrent = current;\r
+    currPvInfo = pvInfo;\r
+\r
+    if( evalGraphDialog ) {\r
+        SendMessage( evalGraphDialog, WM_REFRESH_GRAPH, 0, 0 );\r
+    }\r
+}\r
+\r
+BOOL EvalGraphIsUp()\r
+{\r
+    return evalGraphDialogUp;\r
+}\r
index 5fa191c..e1bf978 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * wgamelist.c -- Game list window for WinBoard\r
- * $Id: wgamelist.c,v 2.1 2003/10/27 19:21:02 mann Exp $
+ * $Id: wgamelist.c,v 2.1 2003/10/27 19:21:02 mann Exp $\r
  *\r
  * Copyright 1995 Free Software Foundation, Inc.\r
  *\r
@@ -36,8 +36,8 @@
 #include "frontend.h"\r
 #include "backend.h"\r
 \r
-#include "wsnap.h"
-
+#include "wsnap.h"\r
+\r
 /* Module globals */\r
 HWND gameListDialog = NULL;\r
 BOOLEAN gameListUp = FALSE;\r
@@ -49,185 +49,185 @@ int gameListX, gameListY, gameListW, gameListH;
 extern HINSTANCE hInst;\r
 extern HWND hwndMain;\r
 \r
-struct GameListStats
-{
-    int white_wins;
-    int black_wins;
-    int drawn;
-    int unfinished;
-};
-
-/* [AS] Wildcard pattern matching */
-static BOOL HasPattern( const char * text, const char * pattern )
-{
-    while( *pattern != '\0' ) {
-        if( *pattern == '*' ) {
-            while( *pattern == '*' ) {
-                pattern++;
-            }
-
-            if( *pattern == '\0' ) {
-                return TRUE;
-            }
-
-            while( *text != '\0' ) {
-                if( HasPattern( text, pattern ) ) {
-                    return TRUE;
-                }
-                text++;
-            }
-        }
-        else if( (*pattern == *text) || ((*pattern == '?') && (*text != '\0')) ) {
-            pattern++;
-            text++;
-            continue;
-        }
-
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static BOOL SearchPattern( const char * text, const char * pattern )
-{
-    BOOL result = TRUE;
-
-    if( pattern != NULL && *pattern != '\0' ) {
-        if( *pattern == '*' ) {
-            result = HasPattern( text, pattern );
-        }
-        else {
-            result = FALSE;
-
-            while( *text != '\0' ) {
-                if( HasPattern( text, pattern ) ) {
-                    result = TRUE;
-                    break;
-                }
-                text++;
-            }
-        }
-    }
-
-    return result;
-}
-
-/* [AS] Setup the game list according to the specified filter */
-static int GameListToListBox( HWND hDlg, BOOL boReset, char * pszFilter, struct GameListStats * stats )
-{
-    ListGame * lg = (ListGame *) gameList.head;
-    int nItem;
-    BOOL hasFilter = FALSE;
-    int count = 0;
-    struct GameListStats dummy;
-
-    /* Initialize stats (use a dummy variable if caller not interested in them) */
-    if( stats == NULL ) {
-        stats = &dummy;
-    }
-
-    stats->white_wins = 0;
-    stats->black_wins = 0;
-    stats->drawn = 0;
-    stats->unfinished = 0;
-
-    if( boReset ) {
-        SendDlgItemMessage(hDlg, OPT_GameListText, LB_RESETCONTENT, 0, 0);
-    }
-
-    if( pszFilter != NULL ) {
-        if( strlen( pszFilter ) > 0 ) {
-            hasFilter = TRUE;
-        }
-    }
-
-    for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){
-        char * st = GameListLine(lg->number, &lg->gameInfo);
-        BOOL skip = FALSE;
-
-        if( hasFilter ) {
-            if( ! SearchPattern( st, pszFilter ) ) {
-                skip = TRUE;
-            }
-        }
-
-        if( ! skip ) {
-            SendDlgItemMessage(hDlg, OPT_GameListText, LB_ADDSTRING, 0, (LPARAM) st);
-            count++;
-
-            /* Update stats */
-            if( lg->gameInfo.result == WhiteWins )
-                stats->white_wins++;
-            else if( lg->gameInfo.result == BlackWins )
-                stats->black_wins++;
-            else if( lg->gameInfo.result == GameIsDrawn )
-                stats->drawn++;
-            else
-                stats->unfinished++;
-        }
-
-        free(st);
-        lg = (ListGame *) lg->node.succ;
-    }
-
-    SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, 0, 0);
-
-    return count;
-}
-
-/* [AS] Show number of visible (filtered) games and total on window caption */
-static int GameListUpdateTitle( HWND hDlg, char * pszTitle, int item_count, int item_total, struct GameListStats * stats )
-{
-    char buf[256];
-
-    sprintf( buf, "%s - %d/%d games", pszTitle, item_count, item_total );
-
-    if( stats != 0 ) {
-        sprintf( buf+strlen(buf), " (%d-%d-%d)", stats->white_wins, stats->black_wins, stats->drawn );
-    }
-
-    SetWindowText( hDlg, buf );
-
-    return 0;
-}
-
-#define MAX_FILTER_LENGTH   128
+struct GameListStats\r
+{\r
+    int white_wins;\r
+    int black_wins;\r
+    int drawn;\r
+    int unfinished;\r
+};\r
+\r
+/* [AS] Wildcard pattern matching */\r
+static BOOL HasPattern( const char * text, const char * pattern )\r
+{\r
+    while( *pattern != '\0' ) {\r
+        if( *pattern == '*' ) {\r
+            while( *pattern == '*' ) {\r
+                pattern++;\r
+            }\r
+\r
+            if( *pattern == '\0' ) {\r
+                return TRUE;\r
+            }\r
+\r
+            while( *text != '\0' ) {\r
+                if( HasPattern( text, pattern ) ) {\r
+                    return TRUE;\r
+                }\r
+                text++;\r
+            }\r
+        }\r
+        else if( (*pattern == *text) || ((*pattern == '?') && (*text != '\0')) ) {\r
+            pattern++;\r
+            text++;\r
+            continue;\r
+        }\r
+\r
+        return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+static BOOL SearchPattern( const char * text, const char * pattern )\r
+{\r
+    BOOL result = TRUE;\r
+\r
+    if( pattern != NULL && *pattern != '\0' ) {\r
+        if( *pattern == '*' ) {\r
+            result = HasPattern( text, pattern );\r
+        }\r
+        else {\r
+            result = FALSE;\r
+\r
+            while( *text != '\0' ) {\r
+                if( HasPattern( text, pattern ) ) {\r
+                    result = TRUE;\r
+                    break;\r
+                }\r
+                text++;\r
+            }\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+/* [AS] Setup the game list according to the specified filter */\r
+static int GameListToListBox( HWND hDlg, BOOL boReset, char * pszFilter, struct GameListStats * stats )\r
+{\r
+    ListGame * lg = (ListGame *) gameList.head;\r
+    int nItem;\r
+    BOOL hasFilter = FALSE;\r
+    int count = 0;\r
+    struct GameListStats dummy;\r
+\r
+    /* Initialize stats (use a dummy variable if caller not interested in them) */\r
+    if( stats == NULL ) { \r
+        stats = &dummy;\r
+    }\r
+\r
+    stats->white_wins = 0;\r
+    stats->black_wins = 0;\r
+    stats->drawn = 0;\r
+    stats->unfinished = 0;\r
+\r
+    if( boReset ) {\r
+        SendDlgItemMessage(hDlg, OPT_GameListText, LB_RESETCONTENT, 0, 0);\r
+    }\r
+\r
+    if( pszFilter != NULL ) {\r
+        if( strlen( pszFilter ) > 0 ) {\r
+            hasFilter = TRUE;\r
+        }\r
+    }\r
+\r
+    for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){\r
+        char * st = GameListLine(lg->number, &lg->gameInfo);\r
+        BOOL skip = FALSE;\r
+\r
+        if( hasFilter ) {\r
+            if( ! SearchPattern( st, pszFilter ) ) {\r
+                skip = TRUE;\r
+            }\r
+        }\r
+\r
+        if( ! skip ) {\r
+            SendDlgItemMessage(hDlg, OPT_GameListText, LB_ADDSTRING, 0, (LPARAM) st);\r
+            count++;\r
+\r
+            /* Update stats */\r
+            if( lg->gameInfo.result == WhiteWins )\r
+                stats->white_wins++;\r
+            else if( lg->gameInfo.result == BlackWins )\r
+                stats->black_wins++;\r
+            else if( lg->gameInfo.result == GameIsDrawn )\r
+                stats->drawn++;\r
+            else\r
+                stats->unfinished++;\r
+        }\r
+\r
+        free(st);\r
+        lg = (ListGame *) lg->node.succ;\r
+    }\r
+\r
+    SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, 0, 0);\r
+\r
+    return count;\r
+}\r
+\r
+/* [AS] Show number of visible (filtered) games and total on window caption */\r
+static int GameListUpdateTitle( HWND hDlg, char * pszTitle, int item_count, int item_total, struct GameListStats * stats )\r
+{\r
+    char buf[256];\r
+\r
+    sprintf( buf, "%s - %d/%d games", pszTitle, item_count, item_total );\r
+\r
+    if( stats != 0 ) {\r
+        sprintf( buf+strlen(buf), " (%d-%d-%d)", stats->white_wins, stats->black_wins, stats->drawn );\r
+    }\r
+\r
+    SetWindowText( hDlg, buf );\r
+\r
+    return 0;\r
+}\r
+\r
+#define MAX_FILTER_LENGTH   128\r
 \r
 LRESULT CALLBACK\r
 GameListDialog(HWND hDlg, UINT message,        WPARAM wParam, LPARAM lParam)\r
 {\r
-  static char szDlgTitle[64];
+  static char szDlgTitle[64];\r
   static HANDLE hwndText;\r
   int nItem;\r
   RECT rect;\r
   static int sizeX, sizeY;\r
   int newSizeX, newSizeY, flags;\r
   MINMAXINFO *mmi;\r
-  static BOOL filterHasFocus = FALSE;
-  int count;
-  struct GameListStats stats;
-  static SnapData sd;
+  static BOOL filterHasFocus = FALSE;\r
+  int count;\r
+  struct GameListStats stats;\r
+  static SnapData sd;\r
 \r
   switch (message) {\r
   case WM_INITDIALOG: \r
-    GetWindowText( hDlg, szDlgTitle, sizeof(szDlgTitle) );
-    szDlgTitle[ sizeof(szDlgTitle)-1 ] = '\0';
-
+    GetWindowText( hDlg, szDlgTitle, sizeof(szDlgTitle) );\r
+    szDlgTitle[ sizeof(szDlgTitle)-1 ] = '\0';\r
+\r
     if (gameListDialog) {\r
       SendDlgItemMessage(hDlg, OPT_GameListText, LB_RESETCONTENT, 0, 0);\r
     }\r
-
+\r
     /* Initialize the dialog items */\r
     hwndText = GetDlgItem(hDlg, OPT_TagsText);\r
-
-    count = GameListToListBox( hDlg, gameListDialog ? TRUE : FALSE, NULL, &stats );
-
-    SendDlgItemMessage( hDlg, IDC_GameListFilter, WM_SETTEXT, 0, (LPARAM) "" );
-    SendDlgItemMessage( hDlg, IDC_GameListFilter, EM_SETLIMITTEXT, MAX_FILTER_LENGTH, 0 );
-
-    filterHasFocus = FALSE;
-
+\r
+    count = GameListToListBox( hDlg, gameListDialog ? TRUE : FALSE, NULL, &stats );\r
+\r
+    SendDlgItemMessage( hDlg, IDC_GameListFilter, WM_SETTEXT, 0, (LPARAM) "" );\r
+    SendDlgItemMessage( hDlg, IDC_GameListFilter, EM_SETLIMITTEXT, MAX_FILTER_LENGTH, 0 );\r
+\r
+    filterHasFocus = FALSE;\r
+\r
     /* Size and position the dialog */\r
     if (!gameListDialog) {\r
       gameListDialog = hDlg;\r
@@ -257,8 +257,8 @@ GameListDialog(HWND hDlg, UINT message,     WPARAM wParam, LPARAM lParam)
        sizeX = newSizeX;\r
        sizeY = newSizeY;\r
       }\r
-
-      GameListUpdateTitle( hDlg, szDlgTitle, count, ((ListGame *) gameList.tailPred)->number, &stats );
+\r
+      GameListUpdateTitle( hDlg, szDlgTitle, count, ((ListGame *) gameList.tailPred)->number, &stats );\r
     }\r
     return FALSE;\r
     \r
@@ -271,18 +271,18 @@ GameListDialog(HWND hDlg, UINT message,   WPARAM wParam, LPARAM lParam)
     sizeY = newSizeY;\r
     break;\r
 \r
-  case WM_ENTERSIZEMOVE:
-    return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
-
-  case WM_SIZING:
-    return OnSizing( &sd, hDlg, wParam, lParam );
-
-  case WM_MOVING:
-    return OnMoving( &sd, hDlg, wParam, lParam );
-
-  case WM_EXITSIZEMOVE:
-    return OnExitSizeMove( &sd, hDlg, wParam, lParam );
-
+  case WM_ENTERSIZEMOVE:\r
+    return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
+\r
+  case WM_SIZING:\r
+    return OnSizing( &sd, hDlg, wParam, lParam );\r
+\r
+  case WM_MOVING:\r
+    return OnMoving( &sd, hDlg, wParam, lParam );\r
+\r
+  case WM_EXITSIZEMOVE:\r
+    return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
+  \r
   case WM_GETMINMAXINFO:\r
     /* Prevent resizing window too small */\r
     mmi = (MINMAXINFO *) lParam;\r
@@ -291,27 +291,27 @@ GameListDialog(HWND hDlg, UINT message,   WPARAM wParam, LPARAM lParam)
     break;\r
 \r
   case WM_COMMAND:\r
-      /*
-        [AS]
-        If <Enter> is pressed while editing the filter, it's better to apply
-        the filter rather than selecting the current game.
-      */
-      if( LOWORD(wParam) == IDC_GameListFilter ) {
-          switch( HIWORD(wParam) ) {
-          case EN_SETFOCUS:
-              filterHasFocus = TRUE;
-              break;
-          case EN_KILLFOCUS:
-              filterHasFocus = FALSE;
-              break;
-          }
-      }
-
-      if( filterHasFocus && (LOWORD(wParam) == IDOK) ) {
-          wParam = IDC_GameListDoFilter;
-      }
-      /* [AS] End command replacement */
-
+      /* \r
+        [AS]\r
+        If <Enter> is pressed while editing the filter, it's better to apply\r
+        the filter rather than selecting the current game.\r
+      */\r
+      if( LOWORD(wParam) == IDC_GameListFilter ) {\r
+          switch( HIWORD(wParam) ) {\r
+          case EN_SETFOCUS:\r
+              filterHasFocus = TRUE;\r
+              break;\r
+          case EN_KILLFOCUS:\r
+              filterHasFocus = FALSE;\r
+              break;\r
+          }\r
+      }\r
+\r
+      if( filterHasFocus && (LOWORD(wParam) == IDOK) ) {\r
+          wParam = IDC_GameListDoFilter;\r
+      }\r
+      /* [AS] End command replacement */\r
+\r
     switch (LOWORD(wParam)) {\r
     case IDOK:\r
     case OPT_GameListLoad:\r
@@ -327,8 +327,8 @@ GameListDialog(HWND hDlg, UINT message,     WPARAM wParam, LPARAM lParam)
       nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0);\r
       nItem++;\r
       if (nItem >= ((ListGame *) gameList.tailPred)->number) {\r
-        /* [AS] Removed error message */
-       /* DisplayError("Can't go forward any further", 0); */
+        /* [AS] Removed error message */\r
+       /* DisplayError("Can't go forward any further", 0); */\r
        return TRUE;\r
       }\r
       SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, nItem, 0);\r
@@ -338,27 +338,27 @@ GameListDialog(HWND hDlg, UINT message,   WPARAM wParam, LPARAM lParam)
       nItem = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0);\r
       nItem--;\r
       if (nItem < 0) {\r
-        /* [AS] Removed error message, added return */
-       /* DisplayError("Can't back up any further", 0); */
-        return TRUE;
+        /* [AS] Removed error message, added return */\r
+       /* DisplayError("Can't back up any further", 0); */\r
+        return TRUE;\r
       }\r
       SendDlgItemMessage(hDlg, OPT_GameListText, LB_SETCURSEL, nItem, 0);\r
       break; /* load the game*/\r
-      \r
-    /* [AS] */
-    case IDC_GameListDoFilter:
-        {
-            char filter[MAX_FILTER_LENGTH+1];
-
-            if( GetDlgItemText( hDlg, IDC_GameListFilter, filter, sizeof(filter) ) >= 0 ) {
-                filter[ sizeof(filter)-1 ] = '\0';
-                count = GameListToListBox( hDlg, TRUE, filter, &stats );
-                GameListUpdateTitle( hDlg, szDlgTitle, count, ((ListGame *) gameList.tailPred)->number, &stats );
-            }
-        }
-        return FALSE;
-        break;
-
+\r
+    /* [AS] */\r
+    case IDC_GameListDoFilter:\r
+        {\r
+            char filter[MAX_FILTER_LENGTH+1];\r
+            \r
+            if( GetDlgItemText( hDlg, IDC_GameListFilter, filter, sizeof(filter) ) >= 0 ) {\r
+                filter[ sizeof(filter)-1 ] = '\0';\r
+                count = GameListToListBox( hDlg, TRUE, filter, &stats );\r
+                GameListUpdateTitle( hDlg, szDlgTitle, count, ((ListGame *) gameList.tailPred)->number, &stats );\r
+            }\r
+        }\r
+        return FALSE;\r
+        break;\r
+\r
     case IDCANCEL:\r
     case OPT_GameListClose:\r
       GameListPopDown();\r
@@ -374,47 +374,47 @@ GameListDialog(HWND hDlg, UINT message,   WPARAM wParam, LPARAM lParam)
        return FALSE;\r
       }\r
       break;\r
-      \r
+\r
     default:\r
       return FALSE;\r
     }\r
-
+\r
     /* Load the game */\r
-    {
-        /* [AS] Get index from the item itself, because filtering makes original order unuseable. */
-        int index = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0);
-        char * text;
-        LRESULT res;
-
-        if( index < 0 ) {
-            return TRUE;
-        }
-
-        res = SendDlgItemMessage( hDlg, OPT_GameListText, LB_GETTEXTLEN, index, 0 );
-
-        if( res == LB_ERR ) {
-            return TRUE;
-        }
-
-        text = (char *) malloc( res+1 );
-
-        res = SendDlgItemMessage( hDlg, OPT_GameListText, LB_GETTEXT, index, (LPARAM)text );
-
-        index = atoi( text );
-
-        nItem = index - 1;
-
-        free( text );
-        /* [AS] End: nItem has been "patched" now! */
-
-    if (cmailMsgLoaded) {\r
-      CmailLoadGame(gameFile, nItem + 1, gameFileName, TRUE);\r
-        }
-        else {
-      LoadGame(gameFile, nItem + 1, gameFileName, TRUE);\r
+    {\r
+        /* [AS] Get index from the item itself, because filtering makes original order unuseable. */\r
+        int index = SendDlgItemMessage(hDlg, OPT_GameListText, LB_GETCURSEL, 0, 0);\r
+        char * text;\r
+        LRESULT res;\r
+\r
+        if( index < 0 ) {\r
+            return TRUE;\r
+        }\r
+\r
+        res = SendDlgItemMessage( hDlg, OPT_GameListText, LB_GETTEXTLEN, index, 0 );\r
+\r
+        if( res == LB_ERR ) {\r
+            return TRUE;\r
+        }\r
+\r
+        text = (char *) malloc( res+1 );\r
+\r
+        res = SendDlgItemMessage( hDlg, OPT_GameListText, LB_GETTEXT, index, (LPARAM)text );\r
+\r
+        index = atoi( text );\r
+\r
+        nItem = index - 1;\r
+\r
+        free( text );\r
+        /* [AS] End: nItem has been "patched" now! */\r
+\r
+        if (cmailMsgLoaded) {\r
+            CmailLoadGame(gameFile, nItem + 1, gameFileName, TRUE);\r
+        }\r
+        else {\r
+            LoadGame(gameFile, nItem + 1, gameFileName, TRUE);\r
+        }\r
     }\r
-    }
-
+\r
     return TRUE;\r
 \r
   default:\r
@@ -483,56 +483,56 @@ VOID ShowGameListProc()
     }\r
   }\r
 }\r
-
-HGLOBAL ExportGameListAsText()
-{
-    HGLOBAL result = NULL;
-    LPVOID lpMem = NULL;
-    ListGame * lg = (ListGame *) gameList.head;
-    int nItem;
-    DWORD dwLen = 0;
-
-    if( ! gameFileName || ((ListGame *) gameList.tailPred)->number <= 0 ) {
-        DisplayError("Game list not loaded or empty", 0);
-        return NULL;
-    }
-
-    /* Get list size */
-    for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){
-        char * st = GameListLineFull(lg->number, &lg->gameInfo);
-
-        dwLen += strlen(st) + 2; /* Add extra characters for "\r\n" */
-
-        free(st);
-        lg = (ListGame *) lg->node.succ;
-    }
-
-    /* Allocate memory for the list */
-    result = GlobalAlloc(GHND, dwLen+1 );
-
-    if( result != NULL ) {
-        lpMem = GlobalLock(result);
-    }
-
-    /* Copy the list into the global memory block */
-    if( lpMem != NULL ) {
-        char * dst = (char *) lpMem;
-        size_t len;
-
-        lg = (ListGame *) gameList.head;
-
-        for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){
-            char * st = GameListLineFull(lg->number, &lg->gameInfo);
-
-            len = sprintf( dst, "%s\r\n", st );
-            dst += len;
-
-            free(st);
-            lg = (ListGame *) lg->node.succ;
-        }
-
-        GlobalUnlock( result );
-    }
-
-    return result;
-}
+\r
+HGLOBAL ExportGameListAsText()\r
+{\r
+    HGLOBAL result = NULL;\r
+    LPVOID lpMem = NULL;\r
+    ListGame * lg = (ListGame *) gameList.head;\r
+    int nItem;\r
+    DWORD dwLen = 0;\r
+\r
+    if( ! gameFileName || ((ListGame *) gameList.tailPred)->number <= 0 ) {\r
+        DisplayError("Game list not loaded or empty", 0);\r
+        return NULL;\r
+    }\r
+\r
+    /* Get list size */\r
+    for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){\r
+        char * st = GameListLineFull(lg->number, &lg->gameInfo);\r
+\r
+        dwLen += strlen(st) + 2; /* Add extra characters for "\r\n" */\r
+\r
+        free(st);\r
+        lg = (ListGame *) lg->node.succ;\r
+    }\r
+\r
+    /* Allocate memory for the list */\r
+    result = GlobalAlloc(GHND, dwLen+1 );\r
+\r
+    if( result != NULL ) {\r
+        lpMem = GlobalLock(result);\r
+    }\r
+\r
+    /* Copy the list into the global memory block */\r
+    if( lpMem != NULL ) {\r
+        char * dst = (char *) lpMem;\r
+        size_t len;\r
+\r
+        lg = (ListGame *) gameList.head;\r
+\r
+        for (nItem = 0; nItem < ((ListGame *) gameList.tailPred)->number; nItem++){\r
+            char * st = GameListLineFull(lg->number, &lg->gameInfo);\r
+\r
+            len = sprintf( dst, "%s\r\n", st );\r
+            dst += len;\r
+\r
+            free(st);\r
+            lg = (ListGame *) lg->node.succ;\r
+        }\r
+\r
+        GlobalUnlock( result );\r
+    }\r
+\r
+    return result;\r
+}\r
index 92b0ca1..e4895bf 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * wgamelist.h -- Game list window for WinBoard\r
- * $Id: wgamelist.h,v 2.1 2003/10/27 19:21:02 mann Exp $
+ * $Id: wgamelist.h,v 2.1 2003/10/27 19:21:02 mann Exp $\r
  *\r
  * Copyright 1995 Free Software Foundation, Inc.\r
  *\r
index 60af898..6b5b857 100644 (file)
-/*
- * Move history for WinBoard
- *
- * Author: Alessandro Scotti (Dec 2005)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#include "config.h"
-
-#include <windows.h> /* required for all Windows applications */
-#include <richedit.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <commdlg.h>
-#include <dlgs.h>
-
-#include "common.h"
-#include "winboard.h"
-#include "frontend.h"
-#include "backend.h"
-
-#include "wsnap.h"
-
-VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
-VOID MoveHistoryPopUp();
-VOID MoveHistoryPopDown();
-BOOL MoveHistoryIsUp();
-
-/* Imports from backend.c */
-char * SavePart(char *str);
-
-/* Imports from winboard.c */
-extern HWND moveHistoryDialog;
-extern BOOLEAN moveHistoryDialogUp;
-
-extern HINSTANCE hInst;
-extern HWND hwndMain;
-
-extern WindowPlacement wpMoveHistory;
-
-extern BoardSize boardSize;
-
-/* Module globals */
-typedef char MoveHistoryString[ MOVE_LEN*2 ];
-
-static int lastFirst = 0;
-static int lastLast = 0;
-static int lastCurrent = -1;
-
-static char lastLastMove[ MOVE_LEN ];
-
-static MoveHistoryString * currMovelist;
-static ChessProgramStats_Move * currPvInfo;
-static int currFirst = 0;
-static int currLast = 0;
-static int currCurrent = -1;
-
-typedef struct {
-    int memoOffset;
-    int memoLength;
-} HistoryMove;
-
-static HistoryMove histMoves[ MAX_MOVES ];
-
-#define WM_REFRESH_HISTORY  (WM_USER+4657)
-
-#define DEFAULT_COLOR       0xFFFFFFFF
-
-#define H_MARGIN            2
-#define V_MARGIN            2
-
-/* Note: in the following code a "Memo" is a Rich Edit control (it's Delphi lingo) */
-
-static VOID HighlightMove( int index, BOOL highlight )
-{
-    if( index >= 0 && index < MAX_MOVES ) {
-        CHARFORMAT cf;
-        HWND hMemo = GetDlgItem( moveHistoryDialog, IDC_MoveHistory );
-
-        SendMessage( hMemo,
-            EM_SETSEL,
-            histMoves[index].memoOffset,
-            histMoves[index].memoOffset + histMoves[index].memoLength );
-
-
-        /* Set style */
-        ZeroMemory( &cf, sizeof(cf) );
-
-        cf.cbSize = sizeof(cf);
-        cf.dwMask = CFM_BOLD | CFM_COLOR;
-
-        if( highlight ) {
-            cf.dwEffects |= CFE_BOLD;
-            cf.crTextColor = RGB( 0x00, 0x00, 0xFF );
-        }
-        else {
-            cf.dwEffects |= CFE_AUTOCOLOR;
-        }
-
-        SendMessage( hMemo, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf );
-    }
-}
-
-static BOOL OnlyCurrentPositionChanged()
-{
-    BOOL result = FALSE;
-
-    if( lastFirst >= 0 &&
-        lastLast >= lastFirst &&
-        lastCurrent >= lastFirst &&
-        currFirst == lastFirst &&
-        currLast == lastLast &&
-        currCurrent >= 0 &&
-        TRUE )
-    {
-        result = TRUE;
-
-        /* Special case: last move changed */
-        if( currCurrent == currLast-1 ) {
-            if( strcmp( currMovelist[currCurrent], lastLastMove ) != 0 ) {
-                result = FALSE;
-            }
-        }
-    }
-
-    return result;
-}
-
-static BOOL OneMoveAppended()
-{
-    BOOL result = FALSE;
-
-    if( lastCurrent >= 0 && lastCurrent >= lastFirst && lastLast >= lastFirst &&
-        currCurrent >= 0 && currCurrent >= currFirst && currLast >= currFirst &&
-        lastFirst == currFirst &&
-        lastLast == (currLast-1) &&
-        lastCurrent == (currCurrent-1) &&
-        currCurrent == (currLast-1) &&
-        TRUE )
-    {
-        result = TRUE;
-    }
-
-    return result;
-}
-
-static VOID ClearMemo()
-{
-    SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, WM_SETTEXT, 0, (LPARAM) "" );
-}
-
-static int AppendToMemo( char * text, DWORD flags, DWORD color )
-{
-    CHARFORMAT cf;
-
-    HWND hMemo = GetDlgItem( moveHistoryDialog, IDC_MoveHistory );
-
-    /* Select end of text */
-    int cbTextLen = (int) SendMessage( hMemo, WM_GETTEXTLENGTH, 0, 0 );
-
-    SendMessage( hMemo, EM_SETSEL, cbTextLen, cbTextLen );
-
-    /* Set style */
-    ZeroMemory( &cf, sizeof(cf) );
-
-    cf.cbSize = sizeof(cf);
-    cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_COLOR | CFM_UNDERLINE;
-    cf.dwEffects = flags;
-
-    if( color != DEFAULT_COLOR ) {
-        cf.crTextColor = color;
-    }
-    else {
-        cf.dwEffects |= CFE_AUTOCOLOR;
-    }
-
-    SendMessage( hMemo, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf );
-
-    /* Append text */
-    SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );
-
-    /* Return offset of appended text */
-    return cbTextLen;
-}
-
-static VOID AppendMoveToMemo( int index )
-{
-    char buf[64];
-    DWORD flags = 0;
-    DWORD color = DEFAULT_COLOR;
-
-    if( index < 0 || index >= MAX_MOVES ) {
-        return;
-    }
-
-    buf[0] = '\0';
-
-    /* Move number */
-    if( (index % 2) == 0 ) {
-        sprintf( buf, "%d.%s ", (index / 2)+1, index & 1 ? ".." : "" );
-        AppendToMemo( buf, CFE_BOLD, DEFAULT_COLOR );
-    }
-
-    /* Move text */
-    strcpy( buf, SavePart( currMovelist[index] ) );
-    strcat( buf, " " );
-
-    histMoves[index].memoOffset = AppendToMemo( buf, flags, color );
-    histMoves[index].memoLength = strlen(buf)-1;
-
-    /* PV info (if any) */
-    if( appData.showEvalInMoveHistory && currPvInfo[index].depth > 0 ) {
-        sprintf( buf, "{%s%.2f/%d} ",
-            currPvInfo[index].score >= 0 ? "+" : "",
-            currPvInfo[index].score / 100.0,
-            currPvInfo[index].depth );
-
-        AppendToMemo( buf, flags,
-            color == DEFAULT_COLOR ? GetSysColor(COLOR_GRAYTEXT) : color );
-    }
-}
-
-static void RefreshMemoContent()
-{
-    int i;
-
-    ClearMemo();
-
-    for( i=currFirst; i<currLast; i++ ) {
-        AppendMoveToMemo( i );
-    }
-}
-
-static void MemoContentUpdated()
-{
-    int caretPos;
-
-    HighlightMove( lastCurrent, FALSE );
-    HighlightMove( currCurrent, TRUE );
-
-    lastFirst = currFirst;
-    lastLast = currLast;
-    lastCurrent = currCurrent;
-    lastLastMove[0] = '\0';
-
-    if( lastLast > 0 ) {
-        strcpy( lastLastMove, SavePart( currMovelist[lastLast-1] ) );
-    }
-
-    /* Deselect any text, move caret to end of memo */
-    if( currCurrent >= 0 ) {
-        caretPos = histMoves[currCurrent].memoOffset + histMoves[currCurrent].memoLength;
-    }
-    else {
-        caretPos = (int) SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, WM_GETTEXTLENGTH, 0, 0 );
-    }
-
-    SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SETSEL, caretPos, caretPos );
-
-    SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SCROLLCARET, 0, 0 );
-}
-
-int FindMoveByCharIndex( int char_index )
-{
-    int index;
-
-    for( index=currFirst; index<currLast; index++ ) {
-        if( char_index >= histMoves[index].memoOffset &&
-            char_index <  (histMoves[index].memoOffset + histMoves[index].memoLength) )
-        {
-            return index;
-        }
-    }
-
-    return -1;
-}
-
-LRESULT CALLBACK HistoryDialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
-{
-    static SnapData sd;
-
-    switch (message) {
-    case WM_INITDIALOG:
-        if( moveHistoryDialog == NULL ) {
-            moveHistoryDialog = hDlg;
-
-            /* Enable word wrapping and notifications */
-            SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SETTARGETDEVICE, 0, 0 );
-
-            SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS );
-
-            /* Set font */
-           SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, MAKELPARAM(TRUE, 0 ));
-
-            /* Restore window placement */
-            RestoreWindowPlacement( hDlg, &wpMoveHistory );
-        }
-
-        /* Update memo */
-        RefreshMemoContent();
-
-        MemoContentUpdated();
-
-        return FALSE;
-
-    case WM_COMMAND:
-        switch (LOWORD(wParam)) {
-        case IDOK:
-          EndDialog(hDlg, TRUE);
-          return TRUE;
-
-        case IDCANCEL:
-          EndDialog(hDlg, FALSE);
-          return TRUE;
-
-        default:
-          break;
-        }
-
-        break;
-
-    case WM_NOTIFY:
-        if( wParam == IDC_MoveHistory ) {
-            MSGFILTER * lpMF = (MSGFILTER *) lParam;
-
-            if( lpMF->msg == WM_LBUTTONDBLCLK && (lpMF->wParam & (MK_CONTROL | MK_SHIFT)) == 0 ) {
-                POINTL pt;
-                LRESULT index;
-
-                pt.x = LOWORD( lpMF->lParam );
-                pt.y = HIWORD( lpMF->lParam );
-
-                index = SendDlgItemMessage( hDlg, IDC_MoveHistory, EM_CHARFROMPOS, 0, (LPARAM) &pt );
-
-                index = FindMoveByCharIndex( index );
-
-                if( index >= 0 ) {
-                    ToNrEvent( index + 1 );
-                }
-
-                /* Zap the message for good: apparently, returning non-zero is not enough */
-                lpMF->msg = WM_USER;
-
-                return TRUE;
-            }
-        }
-        break;
-
-    case WM_REFRESH_HISTORY:
-        /* Update the GUI */
-        if( OnlyCurrentPositionChanged() ) {
-            /* Only "cursor" changed, no need to update memo content */
-        }
-        else if( OneMoveAppended() ) {
-            AppendMoveToMemo( currCurrent );
-        }
-        else {
-            RefreshMemoContent();
-        }
-
-        MemoContentUpdated();
-
-        break;
-
-    case WM_SIZE:
-        SetWindowPos( GetDlgItem( moveHistoryDialog, IDC_MoveHistory ),
-            HWND_TOP,
-            H_MARGIN, V_MARGIN,
-            LOWORD(lParam) - 2*H_MARGIN,
-            HIWORD(lParam) - 2*V_MARGIN,
-            SWP_NOZORDER );
-        break;
-
-    case WM_GETMINMAXINFO:
-        {
-            MINMAXINFO * mmi = (MINMAXINFO *) lParam;
-
-            mmi->ptMinTrackSize.x = 100;
-            mmi->ptMinTrackSize.y = 100;
-        }
-        break;
-
-    case WM_CLOSE:
-        MoveHistoryPopDown();
-        break;
-
-    case WM_ENTERSIZEMOVE:
-        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
-
-    case WM_SIZING:
-        return OnSizing( &sd, hDlg, wParam, lParam );
-
-    case WM_MOVING:
-        return OnMoving( &sd, hDlg, wParam, lParam );
-
-    case WM_EXITSIZEMOVE:
-        return OnExitSizeMove( &sd, hDlg, wParam, lParam );
-    }
-
-    return FALSE;
-}
-
-VOID MoveHistoryPopUp()
-{
-  FARPROC lpProc;
-
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowMoveHistory, MF_CHECKED);
-
-  if( moveHistoryDialog ) {
-    SendMessage( moveHistoryDialog, WM_INITDIALOG, 0, 0 );
-
-    if( ! moveHistoryDialogUp ) {
-        ShowWindow(moveHistoryDialog, SW_SHOW);
-    }
-  }
-  else {
-    lpProc = MakeProcInstance( (FARPROC) HistoryDialogProc, hInst );
-
-    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */
-    CreateDialog( hInst, MAKEINTRESOURCE(DLG_MoveHistory), hwndMain, (DLGPROC)lpProc );
-
-    FreeProcInstance(lpProc);
-  }
-
-  moveHistoryDialogUp = TRUE;
-}
-
-VOID MoveHistoryPopDown()
-{
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowMoveHistory, MF_UNCHECKED);
-
-  if( moveHistoryDialog ) {
-      ShowWindow(moveHistoryDialog, SW_HIDE);
-  }
-
-  moveHistoryDialogUp = FALSE;
-}
-
-VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo )
-{
-    /* [AS] Danger! For now we rely on the movelist parameter being a static variable! */
-
-    currMovelist = movelist;
-    currFirst = first;
-    currLast = last;
-    currCurrent = current;
-    currPvInfo = pvInfo;
-
-    if( moveHistoryDialog ) {
-        SendMessage( moveHistoryDialog, WM_REFRESH_HISTORY, 0, 0 );
-    }
-}
-
-BOOL MoveHistoryIsUp()
-{
-    return moveHistoryDialogUp;
-}
+/*\r
+ * Move history for WinBoard\r
+ *\r
+ * Author: Alessandro Scotti (Dec 2005)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#include "config.h"\r
+\r
+#include <windows.h> /* required for all Windows applications */\r
+#include <richedit.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <commdlg.h>\r
+#include <dlgs.h>\r
+\r
+#include "common.h"\r
+#include "winboard.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+\r
+#include "wsnap.h"\r
+\r
+VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );\r
+VOID MoveHistoryPopUp();\r
+VOID MoveHistoryPopDown();\r
+BOOL MoveHistoryIsUp();\r
+\r
+/* Imports from backend.c */\r
+char * SavePart(char *str);\r
+\r
+/* Imports from winboard.c */\r
+extern HWND moveHistoryDialog;\r
+extern BOOLEAN moveHistoryDialogUp;\r
+\r
+extern HINSTANCE hInst;\r
+extern HWND hwndMain;\r
+\r
+extern WindowPlacement wpMoveHistory;\r
+\r
+extern BoardSize boardSize;\r
+\r
+/* Module globals */\r
+typedef char MoveHistoryString[ MOVE_LEN*2 ];\r
+\r
+static int lastFirst = 0;\r
+static int lastLast = 0;\r
+static int lastCurrent = -1;\r
+\r
+static char lastLastMove[ MOVE_LEN ];\r
+\r
+static MoveHistoryString * currMovelist;\r
+static ChessProgramStats_Move * currPvInfo;\r
+static int currFirst = 0;\r
+static int currLast = 0;\r
+static int currCurrent = -1;\r
+\r
+typedef struct {\r
+    int memoOffset;\r
+    int memoLength;\r
+} HistoryMove;\r
+\r
+static HistoryMove histMoves[ MAX_MOVES ];\r
+\r
+#define WM_REFRESH_HISTORY  (WM_USER+4657)\r
+\r
+#define DEFAULT_COLOR       0xFFFFFFFF\r
+\r
+#define H_MARGIN            2\r
+#define V_MARGIN            2\r
+\r
+/* Note: in the following code a "Memo" is a Rich Edit control (it's Delphi lingo) */\r
+\r
+static VOID HighlightMove( int index, BOOL highlight )\r
+{\r
+    if( index >= 0 && index < MAX_MOVES ) {\r
+        CHARFORMAT cf;\r
+        HWND hMemo = GetDlgItem( moveHistoryDialog, IDC_MoveHistory );\r
+\r
+        SendMessage( hMemo, \r
+            EM_SETSEL, \r
+            histMoves[index].memoOffset, \r
+            histMoves[index].memoOffset + histMoves[index].memoLength );\r
+\r
+\r
+        /* Set style */\r
+        ZeroMemory( &cf, sizeof(cf) );\r
+\r
+        cf.cbSize = sizeof(cf);\r
+        cf.dwMask = CFM_BOLD | CFM_COLOR;\r
+\r
+        if( highlight ) {\r
+            cf.dwEffects |= CFE_BOLD;\r
+            cf.crTextColor = RGB( 0x00, 0x00, 0xFF );\r
+        }\r
+        else {\r
+            cf.dwEffects |= CFE_AUTOCOLOR;\r
+        }\r
+\r
+        SendMessage( hMemo, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf );\r
+    }\r
+}\r
+\r
+static BOOL OnlyCurrentPositionChanged()\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    if( lastFirst >= 0 &&\r
+        lastLast >= lastFirst &&\r
+        lastCurrent >= lastFirst && \r
+        currFirst == lastFirst &&\r
+        currLast == lastLast &&\r
+        currCurrent >= 0 &&\r
+        TRUE )\r
+    {\r
+        result = TRUE;\r
+\r
+        /* Special case: last move changed */\r
+        if( currCurrent == currLast-1 ) {\r
+            if( strcmp( currMovelist[currCurrent], lastLastMove ) != 0 ) {\r
+                result = FALSE;\r
+            }\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static BOOL OneMoveAppended()\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    if( lastCurrent >= 0 && lastCurrent >= lastFirst && lastLast >= lastFirst &&\r
+        currCurrent >= 0 && currCurrent >= currFirst && currLast >= currFirst &&\r
+        lastFirst == currFirst &&\r
+        lastLast == (currLast-1) &&\r
+        lastCurrent == (currCurrent-1) &&\r
+        currCurrent == (currLast-1) &&\r
+        TRUE )\r
+    {\r
+        result = TRUE;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static VOID ClearMemo()\r
+{\r
+    SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, WM_SETTEXT, 0, (LPARAM) "" );\r
+}\r
+\r
+static int AppendToMemo( char * text, DWORD flags, DWORD color )\r
+{\r
+    CHARFORMAT cf;\r
+\r
+    HWND hMemo = GetDlgItem( moveHistoryDialog, IDC_MoveHistory );\r
+\r
+    /* Select end of text */\r
+    int cbTextLen = (int) SendMessage( hMemo, WM_GETTEXTLENGTH, 0, 0 );\r
+\r
+    SendMessage( hMemo, EM_SETSEL, cbTextLen, cbTextLen );\r
+\r
+    /* Set style */\r
+    ZeroMemory( &cf, sizeof(cf) );\r
+\r
+    cf.cbSize = sizeof(cf);\r
+    cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_COLOR | CFM_UNDERLINE;\r
+    cf.dwEffects = flags;\r
+\r
+    if( color != DEFAULT_COLOR ) {\r
+        cf.crTextColor = color;\r
+    }\r
+    else {\r
+        cf.dwEffects |= CFE_AUTOCOLOR;\r
+    }\r
+\r
+    SendMessage( hMemo, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf );\r
+\r
+    /* Append text */\r
+    SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
+\r
+    /* Return offset of appended text */\r
+    return cbTextLen;\r
+}\r
+\r
+static VOID AppendMoveToMemo( int index )\r
+{\r
+    char buf[64];\r
+    DWORD flags = 0;\r
+    DWORD color = DEFAULT_COLOR;\r
+\r
+    if( index < 0 || index >= MAX_MOVES ) {\r
+        return;\r
+    }\r
+\r
+    buf[0] = '\0';\r
+\r
+    /* Move number */\r
+    if( (index % 2) == 0 ) {\r
+        sprintf( buf, "%d.%s ", (index / 2)+1, index & 1 ? ".." : "" );\r
+        AppendToMemo( buf, CFE_BOLD, DEFAULT_COLOR );\r
+    }\r
+\r
+    /* Move text */\r
+    strcpy( buf, SavePart( currMovelist[index] ) );\r
+    strcat( buf, " " );\r
+\r
+    histMoves[index].memoOffset = AppendToMemo( buf, flags, color );\r
+    histMoves[index].memoLength = strlen(buf)-1;\r
+\r
+    /* PV info (if any) */\r
+    if( appData.showEvalInMoveHistory && currPvInfo[index].depth > 0 ) {\r
+        sprintf( buf, "{%s%.2f/%d} ", \r
+            currPvInfo[index].score >= 0 ? "+" : "",\r
+            currPvInfo[index].score / 100.0,\r
+            currPvInfo[index].depth );\r
+\r
+        AppendToMemo( buf, flags, \r
+            color == DEFAULT_COLOR ? GetSysColor(COLOR_GRAYTEXT) : color );\r
+    }\r
+}\r
+\r
+static void RefreshMemoContent()\r
+{\r
+    int i;\r
+\r
+    ClearMemo();\r
+\r
+    for( i=currFirst; i<currLast; i++ ) {\r
+        AppendMoveToMemo( i );\r
+    }\r
+}\r
+\r
+static void MemoContentUpdated()\r
+{\r
+    int caretPos;\r
+\r
+    HighlightMove( lastCurrent, FALSE );\r
+    HighlightMove( currCurrent, TRUE );\r
+\r
+    lastFirst = currFirst;\r
+    lastLast = currLast;\r
+    lastCurrent = currCurrent;\r
+    lastLastMove[0] = '\0';\r
+\r
+    if( lastLast > 0 ) {\r
+        strcpy( lastLastMove, SavePart( currMovelist[lastLast-1] ) );\r
+    }\r
+\r
+    /* Deselect any text, move caret to end of memo */\r
+    if( currCurrent >= 0 ) {\r
+        caretPos = histMoves[currCurrent].memoOffset + histMoves[currCurrent].memoLength;\r
+    }\r
+    else {\r
+        caretPos = (int) SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, WM_GETTEXTLENGTH, 0, 0 );\r
+    }\r
+\r
+    SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SETSEL, caretPos, caretPos );\r
+\r
+    SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SCROLLCARET, 0, 0 );\r
+}\r
+\r
+int FindMoveByCharIndex( int char_index )\r
+{\r
+    int index;\r
+\r
+    for( index=currFirst; index<currLast; index++ ) {\r
+        if( char_index >= histMoves[index].memoOffset &&\r
+            char_index <  (histMoves[index].memoOffset + histMoves[index].memoLength) )\r
+        {\r
+            return index;\r
+        }\r
+    }\r
+\r
+    return -1;\r
+}\r
+\r
+LRESULT CALLBACK HistoryDialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )\r
+{\r
+    static SnapData sd;\r
+\r
+    switch (message) {\r
+    case WM_INITDIALOG:\r
+        if( moveHistoryDialog == NULL ) {\r
+            moveHistoryDialog = hDlg;\r
+\r
+            /* Enable word wrapping and notifications */\r
+            SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SETTARGETDEVICE, 0, 0 );\r
+\r
+            SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS );\r
+\r
+            /* Set font */\r
+           SendDlgItemMessage( moveHistoryDialog, IDC_MoveHistory, WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, MAKELPARAM(TRUE, 0 ));\r
+\r
+            /* Restore window placement */\r
+            RestoreWindowPlacement( hDlg, &wpMoveHistory );\r
+        }\r
+\r
+        /* Update memo */\r
+        RefreshMemoContent();\r
+\r
+        MemoContentUpdated();\r
+\r
+        return FALSE;\r
+\r
+    case WM_COMMAND:\r
+        switch (LOWORD(wParam)) {\r
+        case IDOK:\r
+          EndDialog(hDlg, TRUE);\r
+          return TRUE;\r
+\r
+        case IDCANCEL:\r
+          EndDialog(hDlg, FALSE);\r
+          return TRUE;\r
+\r
+        default:\r
+          break;\r
+        }\r
+\r
+        break;\r
+\r
+    case WM_NOTIFY:\r
+        if( wParam == IDC_MoveHistory ) {\r
+            MSGFILTER * lpMF = (MSGFILTER *) lParam;\r
+\r
+            if( lpMF->msg == WM_LBUTTONDBLCLK && (lpMF->wParam & (MK_CONTROL | MK_SHIFT)) == 0 ) {\r
+                POINTL pt;\r
+                LRESULT index;\r
+\r
+                pt.x = LOWORD( lpMF->lParam );\r
+                pt.y = HIWORD( lpMF->lParam );\r
+\r
+                index = SendDlgItemMessage( hDlg, IDC_MoveHistory, EM_CHARFROMPOS, 0, (LPARAM) &pt );\r
+\r
+                index = FindMoveByCharIndex( index );\r
+\r
+                if( index >= 0 ) {\r
+                    ToNrEvent( index + 1 );\r
+                }\r
+\r
+                /* Zap the message for good: apparently, returning non-zero is not enough */\r
+                lpMF->msg = WM_USER;\r
+\r
+                return TRUE;\r
+            }\r
+        }\r
+        break;\r
+\r
+    case WM_REFRESH_HISTORY:\r
+        /* Update the GUI */\r
+        if( OnlyCurrentPositionChanged() ) {\r
+            /* Only "cursor" changed, no need to update memo content */\r
+        }\r
+        else if( OneMoveAppended() ) {\r
+            AppendMoveToMemo( currCurrent );\r
+        }\r
+        else {\r
+            RefreshMemoContent();\r
+        }\r
+\r
+        MemoContentUpdated();\r
+\r
+        break;\r
+\r
+    case WM_SIZE:\r
+        SetWindowPos( GetDlgItem( moveHistoryDialog, IDC_MoveHistory ),\r
+            HWND_TOP,\r
+            H_MARGIN, V_MARGIN,\r
+            LOWORD(lParam) - 2*H_MARGIN,\r
+            HIWORD(lParam) - 2*V_MARGIN,\r
+            SWP_NOZORDER );\r
+        break;\r
+\r
+    case WM_GETMINMAXINFO:\r
+        {\r
+            MINMAXINFO * mmi = (MINMAXINFO *) lParam;\r
+        \r
+            mmi->ptMinTrackSize.x = 100;\r
+            mmi->ptMinTrackSize.y = 100;\r
+        }\r
+        break;\r
+\r
+    case WM_CLOSE:\r
+        MoveHistoryPopDown();\r
+        break;\r
+\r
+    case WM_ENTERSIZEMOVE:\r
+        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_SIZING:\r
+        return OnSizing( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_MOVING:\r
+        return OnMoving( &sd, hDlg, wParam, lParam );\r
+\r
+    case WM_EXITSIZEMOVE:\r
+        return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+VOID MoveHistoryPopUp()\r
+{\r
+  FARPROC lpProc;\r
+  \r
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowMoveHistory, MF_CHECKED);\r
+\r
+  if( moveHistoryDialog ) {\r
+    SendMessage( moveHistoryDialog, WM_INITDIALOG, 0, 0 );\r
+\r
+    if( ! moveHistoryDialogUp ) {\r
+        ShowWindow(moveHistoryDialog, SW_SHOW);\r
+    }\r
+  }\r
+  else {\r
+    lpProc = MakeProcInstance( (FARPROC) HistoryDialogProc, hInst );\r
+\r
+    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */\r
+    CreateDialog( hInst, MAKEINTRESOURCE(DLG_MoveHistory), hwndMain, (DLGPROC)lpProc );\r
+\r
+    FreeProcInstance(lpProc);\r
+  }\r
+\r
+  moveHistoryDialogUp = TRUE;\r
+}\r
+\r
+VOID MoveHistoryPopDown()\r
+{\r
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowMoveHistory, MF_UNCHECKED);\r
+\r
+  if( moveHistoryDialog ) {\r
+      ShowWindow(moveHistoryDialog, SW_HIDE);\r
+  }\r
+\r
+  moveHistoryDialogUp = FALSE;\r
+}\r
+\r
+VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo )\r
+{\r
+    /* [AS] Danger! For now we rely on the movelist parameter being a static variable! */\r
+\r
+    currMovelist = movelist;\r
+    currFirst = first;\r
+    currLast = last;\r
+    currCurrent = current;\r
+    currPvInfo = pvInfo;\r
+\r
+    if( moveHistoryDialog ) {\r
+        SendMessage( moveHistoryDialog, WM_REFRESH_HISTORY, 0, 0 );\r
+    }\r
+}\r
+\r
+BOOL MoveHistoryIsUp()\r
+{\r
+    return moveHistoryDialogUp;\r
+}\r
index a96aeb6..dbf3c90 100644 (file)
@@ -424,7 +424,7 @@ VOID EngineOutputPopDown();
 BOOL EngineOutputIsUp();\r
 VOID EngineOutputUpdate( FrontEndProgramStats * stats );\r
 \r
-VOID GothicPopUp(char *title, char up);\r
+VOID GothicPopUp(char *title, VariantClass variant);\r
 /*\r
  * Setting "frozen" should disable all user input other than deleting\r
  * the window.  We do this while engines are initializing themselves.\r
@@ -691,11 +691,12 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
                0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
 \r
+#if 0\r
   /* [AS] Disable the FRC stuff if not playing the proper variant */\r
   if( gameInfo.variant != VariantFischeRandom ) {\r
       EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );\r
   }\r
-\r
+#endif\r
   if (hwndConsole) {\r
 #if AOT_CONSOLE\r
     SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
@@ -1220,6 +1221,15 @@ ArgDescriptor argDescriptors[] = {
   /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */\r
   { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },\r
 #endif\r
+  /* [HGM] options for broadcasting and time odds */\r
+  { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },\r
+  { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },\r
+  { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },\r
+  { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },\r
+  { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },\r
+  { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },\r
+  { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },\r
+  { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },\r
   { NULL, ArgNone, NULL, FALSE }\r
 };\r
 \r
@@ -1896,6 +1906,13 @@ InitAppData(LPSTR lpCmdLine)
   appData.alphaRank    = FALSE;\r
   appData.allWhite     = FALSE;\r
   appData.upsideDown   = FALSE;\r
+  appData.serverPause  = 15;\r
+  appData.serverMovesName   = NULL;\r
+  appData.suppressLoadMoves = FALSE;\r
+  appData.firstTimeOdds  = 1;\r
+  appData.secondTimeOdds = 1;\r
+  appData.firstAccumulateTC  = 1; // combine previous and current sessions\r
+  appData.secondAccumulateTC = 1;\r
 \r
 #ifdef ZIPPY\r
   appData.zippyTalk = ZIPPY_TALK;\r
@@ -1940,6 +1957,35 @@ InitAppData(LPSTR lpCmdLine)
      appData.NrRanks > BOARD_SIZE   )\r
       DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);\r
 \r
+  /* [HGM] After parsing the options from the .ini file, and overruling them\r
+   * with options from the command line, we now make an even higher priority\r
+   * overrule by WB options attached to the engine command line. This so that\r
+   * tournament managers can use WB options (such as /timeOdds) that follow\r
+   * the engines.\r
+   */\r
+  if(appData.firstChessProgram != NULL) {\r
+      char *p = StrStr(appData.firstChessProgram, "WBopt");\r
+      static char *f = "first";\r
+      char buf[MSG_SIZ], *q = buf;\r
+      if(p != NULL) { // engine command line contains WinBoard options\r
+          sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"\r
+          ParseArgs(StringGet, &q);\r
+          p[-1] = 0; // cut them offengine command line\r
+      }\r
+  }\r
+  // now do same for second chess program\r
+  if(appData.secondChessProgram != NULL) {\r
+      char *p = StrStr(appData.secondChessProgram, "WBopt");\r
+      static char *s = "second";\r
+      char buf[MSG_SIZ], *q = buf;\r
+      if(p != NULL) { // engine command line contains WinBoard options\r
+          sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"\r
+          ParseArgs(StringGet, &q);\r
+          p[-1] = 0; // cut them offengine command line\r
+      }\r
+  }\r
+\r
+\r
   /* Propagate options that affect others */\r
   if (appData.matchMode || appData.matchGames) chessProgram = TRUE;\r
   if (appData.icsActive || appData.noChessProgram) {\r
@@ -2307,7 +2353,7 @@ enum {
     PM_WO = (int) WhiteCannon, \r
     PM_WU = (int) WhiteUnicorn, \r
     PM_WH = (int) WhiteNightrider, \r
-    PM_WA = (int) WhiteCardinal, \r
+    PM_WA = (int) WhiteAngel, \r
     PM_WC = (int) WhiteMarshall, \r
     PM_WG = (int) WhiteGrasshopper, \r
     PM_WK = (int) WhiteKing,\r
@@ -2323,7 +2369,7 @@ enum {
     PM_BO = (int) BlackCannon, \r
     PM_BU = (int) BlackUnicorn, \r
     PM_BH = (int) BlackNightrider, \r
-    PM_BA = (int) BlackCardinal, \r
+    PM_BA = (int) BlackAngel, \r
     PM_BC = (int) BlackMarshall, \r
     PM_BG = (int) BlackGrasshopper, \r
     PM_BK = (int) BlackKing\r
@@ -2554,8 +2600,7 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_WQ;\r
     case WhiteKing:\r
         return PM_WK;\r
-#ifdef FAIRY\r
-    case BlackCardinal:\r
+    case BlackAngel:\r
         return PM_BA;\r
     case BlackMarshall:\r
         return PM_BC;\r
@@ -2575,7 +2620,7 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_BG;\r
     case BlackMan:\r
         return PM_BM;\r
-    case WhiteCardinal:\r
+    case WhiteAngel:\r
         return PM_WA;\r
     case WhiteMarshall:\r
         return PM_WC;\r
@@ -2595,7 +2640,6 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_WG;\r
     case WhiteMan:\r
         return PM_WM;\r
-#endif\r
     }\r
 \r
     return 0;\r
@@ -2677,7 +2721,7 @@ void CreatePiecesFromFont()
                 }\r
                 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {\r
                     /* Fairy symbols */\r
-                     SetCharTable(pieceToFontChar, "PNBRQFWEMOUHACGSKpnbrqfwemouhacgsk");\r
+                     SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");\r
                 }\r
                 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {\r
                     /* Good Companion (Some characters get warped as literal :-( */\r
@@ -3057,10 +3101,15 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     }\r
   }\r
 \r
+  /* [HGM] Licensing requirement */\r
 #ifdef GOTHIC\r
-  /* [HGM] Gothic licensing requirement */\r
-  GothicPopUp( GOTHIC, gameInfo.variant == VariantGothic );\r
+  if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else\r
 #endif\r
+#ifdef FALCON\r
+  if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else\r
+#endif\r
+  GothicPopUp( "", VariantNormal);\r
+\r
 \r
 /*  if (boardSize == oldBoardSize) return; [HGM] variant might have changed */\r
   oldBoardSize = boardSize;\r
@@ -3076,6 +3125,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     }\r
   }\r
 \r
+  // Orthodox Chess pieces\r
   pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");\r
   pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");\r
   pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");\r
@@ -3092,85 +3142,126 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");\r
   pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");\r
   if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {\r
-  pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
-  pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
-  pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
-  } else {\r
-  pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");\r
-  pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");\r
-  pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");\r
-  }\r
-  if(squareSize==72 || squareSize==49) { /* experiment with some home-made bitmaps */\r
-  pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");\r
-  pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");\r
-  pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");\r
-  pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");\r
-  pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");\r
-  pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
-  pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
-  pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
-  pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");\r
-  pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");\r
-  pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");\r
-  pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");\r
-  pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");\r
-  pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");\r
-  pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
-  pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
-  pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
-  if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */\r
-  pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
-  pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "wp", squareSize, "o");\r
-  pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");\r
-  pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");\r
-  pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");\r
-  pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");\r
-  pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");\r
-  pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");\r
-  pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  } else {\r
-  pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
-  pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
-  pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
-  pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");\r
-  pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");\r
-  pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");\r
-  pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");\r
-  pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");\r
-  pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");\r
-  pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
-  pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
-  pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
-  }\r
-  if(gameInfo.variant != VariantCrazyhouse && gameInfo.variant != VariantShogi) {\r
-  pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");\r
-  pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");\r
-  pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");\r
+    // in Shogi, Hijack the unused Queen for Lance\r
+    pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+    pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+    pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
   } else {\r
-  pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "s");\r
-  pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "o");\r
-  pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "w");\r
-  }\r
+    pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");\r
+    pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");\r
+    pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");\r
+  }\r
+\r
+  if(squareSize <= 72 && squareSize >= 33) { \r
+    /* A & C are available in most sizes now */\r
+    if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like\r
+      pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
+      pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
+      pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
+      pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+      pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+      pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+      pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+      pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
+    } else { // Smirf-like\r
+      pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");\r
+      pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");\r
+      pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");\r
+    }\r
+    if(gameInfo.variant == VariantGothic) { // Vortex-like\r
+      pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+    } else { // WinBoard standard\r
+      pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");\r
+      pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");\r
+      pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");\r
+    }\r
+  }\r
+\r
+\r
+  if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */\r
+    pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");\r
+    pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");\r
+    pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");\r
+    pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");\r
+    pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");\r
+    pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+    pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
+    pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
+    pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
+    pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");\r
+    pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");\r
+    pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");\r
+    pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
+    pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
+    pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
+    pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");\r
+    pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");\r
+    pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");\r
+    pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");\r
+    pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");\r
+    pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");\r
+    pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");\r
+    pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");\r
+    pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");\r
+    pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+    pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+    pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
+    pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
+    pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
+    pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
+\r
+    if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */\r
+      pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
+      pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");\r
+      pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+      pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");\r
+      pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");\r
+      pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+      pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");\r
+      pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");\r
+      pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+      pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");\r
+      pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");\r
+      pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+    } else {\r
+      pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");\r
+      pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");\r
+      pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");\r
+      pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");\r
+      pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");\r
+      pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");\r
+      pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+      pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");\r
+      pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");\r
+      pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");\r
+    }\r
+\r
   } else { /* other size, no special bitmaps available. Use smaller symbols */\r
-      if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;\r
-      else  minorSize = sizeInfo[(int)boardSize - 2].squareSize;\r
-  pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");\r
-  pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");\r
-  pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");\r
-  pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "s");\r
-  pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "o");\r
-  pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "b", minorSize, "w");\r
-  pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "r", minorSize, "s");\r
-  pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "r", minorSize, "o");\r
-  pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "r", minorSize, "w");\r
-  pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");\r
-  pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");\r
-  pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");\r
+    if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;\r
+    else  minorSize = sizeInfo[(int)boardSize - 2].squareSize;\r
+    pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");\r
+    pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");\r
+    pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");\r
+    pieceBitmap[0][WhiteCardinal]   = DoLoadBitmap(hInst, "b", minorSize, "s");\r
+    pieceBitmap[1][WhiteCardinal]   = DoLoadBitmap(hInst, "b", minorSize, "o");\r
+    pieceBitmap[2][WhiteCardinal]   = DoLoadBitmap(hInst, "b", minorSize, "w");\r
+    pieceBitmap[0][WhiteDragon]   = DoLoadBitmap(hInst, "r", minorSize, "s");\r
+    pieceBitmap[1][WhiteDragon]   = DoLoadBitmap(hInst, "r", minorSize, "o");\r
+    pieceBitmap[2][WhiteDragon]   = DoLoadBitmap(hInst, "r", minorSize, "w");\r
+    pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");\r
+    pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");\r
+    pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");\r
   }\r
+\r
+\r
   if(gameInfo.variant == VariantShogi && squareSize == 58)\r
   /* special Shogi support in this size */\r
   { for (i=0; i<=2; i++) { /* replace all bitmaps */\r
@@ -3189,10 +3280,10 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");\r
   pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");\r
   pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");\r
-  pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
+  pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
   pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");\r
   pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");\r
-  pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
+  pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
   pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");\r
   pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");\r
   pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");\r
@@ -3203,10 +3294,10 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");\r
   pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");\r
   pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");\r
-  pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
+  pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
   pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");\r
   pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");\r
-  pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
+  pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
   pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");\r
   pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");\r
   pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
@@ -3217,10 +3308,10 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");\r
   pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
   pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
-  pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
+  pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
   pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");\r
   pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
-  pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
+  pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
   pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");\r
   pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
   minorSize = 0;\r
@@ -3428,7 +3519,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
       if( color )\r
               oldBrush = SelectObject(hdc, whitePieceBrush);\r
       else    oldBrush = SelectObject(hdc, blackPieceBrush);\r
-      if(appData.upsideDown && !color)\r
+      if(appData.upsideDown && color==flipView)\r
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
@@ -3442,7 +3533,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
 #else\r
       /* Use black for outline of white pieces */\r
       SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
-      if(appData.upsideDown && !color)\r
+      if(appData.upsideDown && color==flipView)\r
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
@@ -3464,7 +3555,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
       /* Use square color for details of black pieces */\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
       oldBrush = SelectObject(hdc, blackPieceBrush);\r
-      if(appData.upsideDown)\r
+      if(appData.upsideDown && !flipView)\r
         StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
@@ -5558,7 +5649,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case EP_WhiteCardinal:\r
-      EditPositionMenuEvent(WhiteCardinal, fromX, fromY);\r
+      EditPositionMenuEvent(WhiteAngel, fromX, fromY);\r
       fromX = fromY = -1;\r
       break;\r
 \r
@@ -5618,7 +5709,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case EP_BlackCardinal:\r
-      EditPositionMenuEvent(BlackCardinal, fromX, fromY);\r
+      EditPositionMenuEvent(BlackAngel, fromX, fromY);\r
       fromX = fromY = -1;\r
       break;\r
 \r
@@ -6841,23 +6932,26 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 }\r
 \r
 VOID\r
-GothicPopUp(char *title, char up)\r
+GothicPopUp(char *title, VariantClass variant)\r
 {\r
   FARPROC lpProc;\r
   char *p, *q;\r
   BOOLEAN modal = hwndMain == NULL;\r
+  static char *lastTitle;\r
 \r
   strncpy(errorTitle, title, sizeof(errorTitle));\r
   errorTitle[sizeof(errorTitle) - 1] = '\0';\r
 \r
-  if(up && gothicDialog == NULL) {\r
+  if(lastTitle != title && gothicDialog != NULL) {\r
+    DestroyWindow(gothicDialog);\r
+    gothicDialog = NULL;\r
+  }\r
+  if(variant != VariantNormal && gothicDialog == NULL) {\r
+    title = lastTitle;\r
     lpProc = MakeProcInstance((FARPROC)GothicDialog, hInst);\r
     CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error),\r
                 hwndMain, (DLGPROC)lpProc);\r
     FreeProcInstance(lpProc);\r
-  } else if(!up && gothicDialog != NULL) {\r
-    DestroyWindow(gothicDialog);\r
-    gothicDialog = NULL;\r
   }\r
 }\r
 #endif\r
@@ -9129,7 +9223,7 @@ StartChildProcess(char *cmdLine, char *dir, ProcRef *pr)
 void\r
 DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)\r
 {\r
-  ChildProc *cp;\r
+  ChildProc *cp; int result;\r
 \r
   cp = (ChildProc *) pr;\r
   if (cp == NULL) return;\r
@@ -9146,22 +9240,23 @@ DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)
     /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/\r
 \r
     /* [AS] Special termination modes for misbehaving programs... */\r
-    if( signal == 9 ) {\r
+    if( signal == 9 ) { \r
+        result = TerminateProcess( cp->hProcess, 0 );\r
+\r
         if ( appData.debugMode) {\r
-            fprintf( debugFP, "Terminating process %u\n", cp->pid );\r
+            fprintf( debugFP, "Terminating process %u, result=%d\n", cp->pid, result );\r
         }\r
-\r
-        TerminateProcess( cp->hProcess, 0 );\r
     }\r
     else if( signal == 10 ) {\r
         DWORD dw = WaitForSingleObject( cp->hProcess, 3*1000 ); // Wait 3 seconds at most\r
 \r
         if( dw != WAIT_OBJECT_0 ) {\r
+            result = TerminateProcess( cp->hProcess, 0 );\r
+\r
             if ( appData.debugMode) {\r
-                fprintf( debugFP, "Process %u still alive after timeout, killing...\n", cp->pid );\r
+                fprintf( debugFP, "Process %u still alive after timeout, killing... result=%d\n", cp->pid, result );\r
             }\r
 \r
-            TerminateProcess( cp->hProcess, 0 );\r
         }\r
     }\r
 \r
index 890e071..9944ccc 100644 (file)
@@ -135,7 +135,8 @@ VOID ExitArgError(char *msg, char *badArg);
 #define CONSOLE_FONT 3\r
 #define COMMENT_FONT 4\r
 #define EDITTAGS_FONT 5\r
-#define NUM_FONTS 6\r
+#define MOVEHISTORY_FONT 6\r
+#define NUM_FONTS 7\r
 \r
 /* Positions of some menu items.  Origin is zero and separator lines count. */\r
 /* It's gross that these are needed. */\r
@@ -163,18 +164,18 @@ extern MyFont *font[NUM_SIZES][NUM_FONTS];
 \r
 #define COPY_TMP "wbcopy.tmp"\r
 #define PASTE_TMP "wbpaste.tmp"\r
-
-/* [AS] Layout management */
-typedef struct {
-    Boolean visible;
-    int x;
-    int y;
-    int width;
-    int height;
-} WindowPlacement;
-
-VOID InitWindowPlacement( WindowPlacement * wp );
-
-VOID RestoreWindowPlacement( HWND hWnd, WindowPlacement * wp );
-
-VOID ReattachAfterMove( LPRECT lprcOldPos, int new_x, int new_y, HWND hWndChild, WindowPlacement * pwpChild );
+\r
+/* [AS] Layout management */\r
+typedef struct {\r
+    Boolean visible;\r
+    int x;\r
+    int y;\r
+    int width;\r
+    int height;\r
+} WindowPlacement;\r
+\r
+VOID InitWindowPlacement( WindowPlacement * wp );\r
+\r
+VOID RestoreWindowPlacement( HWND hWnd, WindowPlacement * wp );\r
+\r
+VOID ReattachAfterMove( LPRECT lprcOldPos, int new_x, int new_y, HWND hWndChild, WindowPlacement * pwpChild );\r
index 6682aab..d8d6aec 100644 (file)
@@ -635,6 +635,12 @@ BEGIN
                     10\r
     CONTROL         "Shatran&j",OPT_VariantShatranj,"Button",BS_AUTORADIOBUTTON,134,\r
                     34,50,10\r
+    CONTROL         "&FRC",OPT_VariantFRC,"Button",BS_AUTORADIOBUTTON,134,\r
+                    44,50,10\r
+    CONTROL         "c&ylinder",OPT_VariantCylinder,"Button",BS_AUTORADIOBUTTON,134,\r
+                    54,50,10\r
+    CONTROL         "&Falcon",OPT_VariantFalcon,"Button",BS_AUTORADIOBUTTON,134,\r
+                    64,50,10\r
     GROUPBOX        "Variant",IDC_STATIC,4,4,185,75\r
     LTEXT           "Board size:",IDC_STATIC,10,95,40,8\r
     EDITTEXT        IDC_Ranks,60,91,14,14,ES_AUTOHSCROLL\r
@@ -1657,7 +1663,9 @@ TIM                     BITMAP  MOVEABLE PURE   "bitmaps\\tim.bmp"
 // [HGM] Some fairy symbols:\r
 E72O                    BITMAP  MOVEABLE PURE   "bitmaps\\e72o.bmp"\r
 A72O                    BITMAP  MOVEABLE PURE   "bitmaps\\a72o.bmp"\r
+AA72O                   BITMAP  MOVEABLE PURE   "bitmaps\\as72o.bmp"\r
 C72O                    BITMAP  MOVEABLE PURE   "bitmaps\\c72o.bmp"\r
+CV72O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv72o.bmp"\r
 F72O                    BITMAP  MOVEABLE PURE   "bitmaps\\f72o.bmp"\r
 M72O                    BITMAP  MOVEABLE PURE   "bitmaps\\m72o.bmp"\r
 W72O                    BITMAP  MOVEABLE PURE   "bitmaps\\w72o.bmp"\r
@@ -1665,6 +1673,8 @@ O72O                    BITMAP  MOVEABLE PURE   "bitmaps\\o72o.bmp"
 U72O                    BITMAP  MOVEABLE PURE   "bitmaps\\u72o.bmp"\r
 H72O                    BITMAP  MOVEABLE PURE   "bitmaps\\h72o.bmp"\r
 G72O                    BITMAP  MOVEABLE PURE   "bitmaps\\g72o.bmp"\r
+V72O                    BITMAP  MOVEABLE PURE   "bitmaps\\v72o.bmp"\r
+S72O                    BITMAP  MOVEABLE PURE   "bitmaps\\s72o.bmp"\r
 L72O                    BITMAP  MOVEABLE PURE   "bitmaps\\l72o.bmp"\r
 DK72O                   BITMAP  MOVEABLE PURE   "bitmaps\\dk72o.bmp"\r
 WP72O                   BITMAP  MOVEABLE PURE   "bitmaps\\wp72o.bmp"\r
@@ -1673,7 +1683,9 @@ WL72O                   BITMAP  MOVEABLE PURE   "bitmaps\\wl72o.bmp"
 WS72O                   BITMAP  MOVEABLE PURE   "bitmaps\\ws72o.bmp"\r
 E72S                    BITMAP  MOVEABLE PURE   "bitmaps\\e72s.bmp"\r
 A72S                    BITMAP  MOVEABLE PURE   "bitmaps\\a72s.bmp"\r
+AA72S                   BITMAP  MOVEABLE PURE   "bitmaps\\as72s.bmp"\r
 C72S                    BITMAP  MOVEABLE PURE   "bitmaps\\c72s.bmp"\r
+CV72S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv72s.bmp"\r
 F72S                    BITMAP  MOVEABLE PURE   "bitmaps\\f72s.bmp"\r
 M72S                    BITMAP  MOVEABLE PURE   "bitmaps\\m72s.bmp"\r
 W72S                    BITMAP  MOVEABLE PURE   "bitmaps\\w72s.bmp"\r
@@ -1681,6 +1693,8 @@ O72S                    BITMAP  MOVEABLE PURE   "bitmaps\\o72s.bmp"
 U72S                    BITMAP  MOVEABLE PURE   "bitmaps\\u72s.bmp"\r
 H72S                    BITMAP  MOVEABLE PURE   "bitmaps\\h72s.bmp"\r
 G72S                    BITMAP  MOVEABLE PURE   "bitmaps\\g72s.bmp"\r
+V72S                    BITMAP  MOVEABLE PURE   "bitmaps\\v72s.bmp"\r
+S72S                    BITMAP  MOVEABLE PURE   "bitmaps\\s72s.bmp"\r
 L72S                    BITMAP  MOVEABLE PURE   "bitmaps\\l72s.bmp"\r
 DK72S                   BITMAP  MOVEABLE PURE   "bitmaps\\dk72s.bmp"\r
 WP72S                   BITMAP  MOVEABLE PURE   "bitmaps\\wp72s.bmp"\r
@@ -1689,7 +1703,9 @@ WL72S                   BITMAP  MOVEABLE PURE   "bitmaps\\wl72s.bmp"
 WS72S                   BITMAP  MOVEABLE PURE   "bitmaps\\ws72s.bmp"\r
 E72W                    BITMAP  MOVEABLE PURE   "bitmaps\\e72w.bmp"\r
 A72W                    BITMAP  MOVEABLE PURE   "bitmaps\\a72w.bmp"\r
+AA72W                   BITMAP  MOVEABLE PURE   "bitmaps\\as72w.bmp"\r
 C72W                    BITMAP  MOVEABLE PURE   "bitmaps\\c72w.bmp"\r
+CV72W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv72w.bmp"\r
 F72W                    BITMAP  MOVEABLE PURE   "bitmaps\\f72w.bmp"\r
 M72W                    BITMAP  MOVEABLE PURE   "bitmaps\\m72w.bmp"\r
 W72W                    BITMAP  MOVEABLE PURE   "bitmaps\\w72w.bmp"\r
@@ -1697,11 +1713,15 @@ O72W                    BITMAP  MOVEABLE PURE   "bitmaps\\o72w.bmp"
 U72W                    BITMAP  MOVEABLE PURE   "bitmaps\\u72w.bmp"\r
 H72W                    BITMAP  MOVEABLE PURE   "bitmaps\\h72w.bmp"\r
 G72W                    BITMAP  MOVEABLE PURE   "bitmaps\\g72w.bmp"\r
+V72W                    BITMAP  MOVEABLE PURE   "bitmaps\\v72w.bmp"\r
+S72W                    BITMAP  MOVEABLE PURE   "bitmaps\\s72w.bmp"\r
 L72W                    BITMAP  MOVEABLE PURE   "bitmaps\\l72w.bmp"\r
 DK72W                   BITMAP  MOVEABLE PURE   "bitmaps\\dk72w.bmp"\r
 E49O                    BITMAP  MOVEABLE PURE   "bitmaps\\e49o.bmp"\r
 A49O                    BITMAP  MOVEABLE PURE   "bitmaps\\a49o.bmp"\r
+AA49O                   BITMAP  MOVEABLE PURE   "bitmaps\\as49o.bmp"\r
 C49O                    BITMAP  MOVEABLE PURE   "bitmaps\\c49o.bmp"\r
+CV49O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv49o.bmp"\r
 F49O                    BITMAP  MOVEABLE PURE   "bitmaps\\f49o.bmp"\r
 M49O                    BITMAP  MOVEABLE PURE   "bitmaps\\m49o.bmp"\r
 W49O                    BITMAP  MOVEABLE PURE   "bitmaps\\w49o.bmp"\r
@@ -1709,6 +1729,8 @@ O49O                    BITMAP  MOVEABLE PURE   "bitmaps\\o49o.bmp"
 U49O                    BITMAP  MOVEABLE PURE   "bitmaps\\u49o.bmp"\r
 H49O                    BITMAP  MOVEABLE PURE   "bitmaps\\h49o.bmp"\r
 G49O                    BITMAP  MOVEABLE PURE   "bitmaps\\g49o.bmp"\r
+V49O                    BITMAP  MOVEABLE PURE   "bitmaps\\v49o.bmp"\r
+S49O                    BITMAP  MOVEABLE PURE   "bitmaps\\s49o.bmp"\r
 L49O                    BITMAP  MOVEABLE PURE   "bitmaps\\l49o.bmp"\r
 DK49O                   BITMAP  MOVEABLE PURE   "bitmaps\\dk49o.bmp"\r
 WP49O                   BITMAP  MOVEABLE PURE   "bitmaps\\wp49o.bmp"\r
@@ -1717,7 +1739,9 @@ WL49O                   BITMAP  MOVEABLE PURE   "bitmaps\\wl49o.bmp"
 WS49O                   BITMAP  MOVEABLE PURE   "bitmaps\\ws49o.bmp"\r
 E49S                    BITMAP  MOVEABLE PURE   "bitmaps\\e49s.bmp"\r
 A49S                    BITMAP  MOVEABLE PURE   "bitmaps\\a49s.bmp"\r
+AA49S                   BITMAP  MOVEABLE PURE   "bitmaps\\as49s.bmp"\r
 C49S                    BITMAP  MOVEABLE PURE   "bitmaps\\c49s.bmp"\r
+CV49S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv49s.bmp"\r
 F49S                    BITMAP  MOVEABLE PURE   "bitmaps\\f49s.bmp"\r
 M49S                    BITMAP  MOVEABLE PURE   "bitmaps\\m49s.bmp"\r
 W49S                    BITMAP  MOVEABLE PURE   "bitmaps\\w49s.bmp"\r
@@ -1725,6 +1749,8 @@ O49S                    BITMAP  MOVEABLE PURE   "bitmaps\\o49s.bmp"
 U49S                    BITMAP  MOVEABLE PURE   "bitmaps\\u49s.bmp"\r
 H49S                    BITMAP  MOVEABLE PURE   "bitmaps\\h49s.bmp"\r
 G49S                    BITMAP  MOVEABLE PURE   "bitmaps\\g49s.bmp"\r
+V49S                    BITMAP  MOVEABLE PURE   "bitmaps\\v49s.bmp"\r
+S49S                    BITMAP  MOVEABLE PURE   "bitmaps\\s49s.bmp"\r
 L49S                    BITMAP  MOVEABLE PURE   "bitmaps\\l49s.bmp"\r
 DK49S                   BITMAP  MOVEABLE PURE   "bitmaps\\dk49s.bmp"\r
 WP49S                   BITMAP  MOVEABLE PURE   "bitmaps\\wp49s.bmp"\r
@@ -1733,7 +1759,9 @@ WL49S                   BITMAP  MOVEABLE PURE   "bitmaps\\wl49s.bmp"
 WS49S                   BITMAP  MOVEABLE PURE   "bitmaps\\ws49s.bmp"\r
 E49W                    BITMAP  MOVEABLE PURE   "bitmaps\\e49w.bmp"\r
 A49W                    BITMAP  MOVEABLE PURE   "bitmaps\\a49w.bmp"\r
+AA49W                   BITMAP  MOVEABLE PURE   "bitmaps\\as49w.bmp"\r
 C49W                    BITMAP  MOVEABLE PURE   "bitmaps\\c49w.bmp"\r
+CV49W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv49w.bmp"\r
 F49W                    BITMAP  MOVEABLE PURE   "bitmaps\\f49w.bmp"\r
 M49W                    BITMAP  MOVEABLE PURE   "bitmaps\\m49w.bmp"\r
 W49W                    BITMAP  MOVEABLE PURE   "bitmaps\\w49w.bmp"\r
@@ -1741,8 +1769,128 @@ O49W                    BITMAP  MOVEABLE PURE   "bitmaps\\o49w.bmp"
 U49W                    BITMAP  MOVEABLE PURE   "bitmaps\\u49w.bmp"\r
 H49W                    BITMAP  MOVEABLE PURE   "bitmaps\\h49w.bmp"\r
 G49W                    BITMAP  MOVEABLE PURE   "bitmaps\\g49w.bmp"\r
+V49W                    BITMAP  MOVEABLE PURE   "bitmaps\\v49w.bmp"\r
+S49W                    BITMAP  MOVEABLE PURE   "bitmaps\\s49w.bmp"\r
 L49W                    BITMAP  MOVEABLE PURE   "bitmaps\\l49w.bmp"\r
 DK49W                   BITMAP  MOVEABLE PURE   "bitmaps\\dk49w.bmp"\r
+A33O                    BITMAP  MOVEABLE PURE   "bitmaps\\a33o.bmp"\r
+AA33O                   BITMAP  MOVEABLE PURE   "bitmaps\\as33o.bmp"\r
+C33O                    BITMAP  MOVEABLE PURE   "bitmaps\\c33o.bmp"\r
+CV33O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv33o.bmp"\r
+V33O                    BITMAP  MOVEABLE PURE   "bitmaps\\v33o.bmp"\r
+E33O                    BITMAP  MOVEABLE PURE   "bitmaps\\e33o.bmp"\r
+F33O                    BITMAP  MOVEABLE PURE   "bitmaps\\f33o.bmp"\r
+H33O                    BITMAP  MOVEABLE PURE   "bitmaps\\h33o.bmp"\r
+G33O                    BITMAP  MOVEABLE PURE   "bitmaps\\g33o.bmp"\r
+L33O                    BITMAP  MOVEABLE PURE   "bitmaps\\l33o.bmp"\r
+W33O                    BITMAP  MOVEABLE PURE   "bitmaps\\w33o.bmp"\r
+M33O                    BITMAP  MOVEABLE PURE   "bitmaps\\m33o.bmp"\r
+O33O                    BITMAP  MOVEABLE PURE   "bitmaps\\o33o.bmp"\r
+DK33O                   BITMAP  MOVEABLE PURE   "bitmaps\\dk33o.bmp"\r
+A33W                    BITMAP  MOVEABLE PURE   "bitmaps\\a33w.bmp"\r
+AA33W                   BITMAP  MOVEABLE PURE   "bitmaps\\as33w.bmp"\r
+C33W                    BITMAP  MOVEABLE PURE   "bitmaps\\c33w.bmp"\r
+CV33W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv33w.bmp"\r
+V33W                    BITMAP  MOVEABLE PURE   "bitmaps\\v33w.bmp"\r
+E33W                    BITMAP  MOVEABLE PURE   "bitmaps\\e33w.bmp"\r
+F33W                    BITMAP  MOVEABLE PURE   "bitmaps\\f33w.bmp"\r
+H33W                    BITMAP  MOVEABLE PURE   "bitmaps\\h33w.bmp"\r
+G33W                    BITMAP  MOVEABLE PURE   "bitmaps\\g33w.bmp"\r
+L33W                    BITMAP  MOVEABLE PURE   "bitmaps\\l33w.bmp"\r
+W33W                    BITMAP  MOVEABLE PURE   "bitmaps\\w33w.bmp"\r
+M33W                    BITMAP  MOVEABLE PURE   "bitmaps\\m33w.bmp"\r
+O33W                    BITMAP  MOVEABLE PURE   "bitmaps\\o33w.bmp"\r
+DK33W                   BITMAP  MOVEABLE PURE   "bitmaps\\dk33w.bmp"\r
+A33S                    BITMAP  MOVEABLE PURE   "bitmaps\\a33s.bmp"\r
+AA33S                   BITMAP  MOVEABLE PURE   "bitmaps\\as33s.bmp"\r
+C33S                    BITMAP  MOVEABLE PURE   "bitmaps\\c33s.bmp"\r
+CV33S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv33s.bmp"\r
+V33S                    BITMAP  MOVEABLE PURE   "bitmaps\\v33s.bmp"\r
+E33S                    BITMAP  MOVEABLE PURE   "bitmaps\\e33s.bmp"\r
+F33S                    BITMAP  MOVEABLE PURE   "bitmaps\\f33s.bmp"\r
+H33S                    BITMAP  MOVEABLE PURE   "bitmaps\\h33s.bmp"\r
+G33S                    BITMAP  MOVEABLE PURE   "bitmaps\\g33s.bmp"\r
+L33S                    BITMAP  MOVEABLE PURE   "bitmaps\\l33s.bmp"\r
+W33S                    BITMAP  MOVEABLE PURE   "bitmaps\\w33s.bmp"\r
+M33S                    BITMAP  MOVEABLE PURE   "bitmaps\\m33s.bmp"\r
+O33S                    BITMAP  MOVEABLE PURE   "bitmaps\\o33s.bmp"\r
+DK33S                   BITMAP  MOVEABLE PURE   "bitmaps\\dk33s.bmp"\r
+\r
+A37O                    BITMAP  MOVEABLE PURE   "bitmaps\\a37o.bmp"\r
+L37O                    BITMAP  MOVEABLE PURE   "bitmaps\\l37o.bmp"\r
+C37O                    BITMAP  MOVEABLE PURE   "bitmaps\\c37o.bmp"\r
+CV37O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv37o.bmp"\r
+A40O                    BITMAP  MOVEABLE PURE   "bitmaps\\a40o.bmp"\r
+L40O                    BITMAP  MOVEABLE PURE   "bitmaps\\l40o.bmp"\r
+C40O                    BITMAP  MOVEABLE PURE   "bitmaps\\c40o.bmp"\r
+CV40O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv40o.bmp"\r
+A45O                    BITMAP  MOVEABLE PURE   "bitmaps\\a45o.bmp"\r
+L45O                    BITMAP  MOVEABLE PURE   "bitmaps\\l45o.bmp"\r
+C45O                    BITMAP  MOVEABLE PURE   "bitmaps\\c45o.bmp"\r
+CV45O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv45o.bmp"\r
+A54O                    BITMAP  MOVEABLE PURE   "bitmaps\\a54o.bmp"\r
+L54O                    BITMAP  MOVEABLE PURE   "bitmaps\\l54o.bmp"\r
+C54O                    BITMAP  MOVEABLE PURE   "bitmaps\\c54o.bmp"\r
+CV54O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv54o.bmp"\r
+V54O                    BITMAP  MOVEABLE PURE   "bitmaps\\v54o.bmp"\r
+A58O                    BITMAP  MOVEABLE PURE   "bitmaps\\a58o.bmp"\r
+L58O                    BITMAP  MOVEABLE PURE   "bitmaps\\l58o.bmp"\r
+C58O                    BITMAP  MOVEABLE PURE   "bitmaps\\c58o.bmp"\r
+CV58O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv58o.bmp"\r
+A64O                    BITMAP  MOVEABLE PURE   "bitmaps\\a64o.bmp"\r
+L64O                    BITMAP  MOVEABLE PURE   "bitmaps\\l64o.bmp"\r
+C64O                    BITMAP  MOVEABLE PURE   "bitmaps\\c64o.bmp"\r
+CV64O                   BITMAP  MOVEABLE PURE   "bitmaps\\cv64o.bmp"\r
+A37W                    BITMAP  MOVEABLE PURE   "bitmaps\\a37w.bmp"\r
+L37W                    BITMAP  MOVEABLE PURE   "bitmaps\\l37w.bmp"\r
+C37W                    BITMAP  MOVEABLE PURE   "bitmaps\\c37w.bmp"\r
+CV37W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv37w.bmp"\r
+A40W                    BITMAP  MOVEABLE PURE   "bitmaps\\a40w.bmp"\r
+L40W                    BITMAP  MOVEABLE PURE   "bitmaps\\l40w.bmp"\r
+C40W                    BITMAP  MOVEABLE PURE   "bitmaps\\c40w.bmp"\r
+CV40W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv40w.bmp"\r
+A45W                    BITMAP  MOVEABLE PURE   "bitmaps\\a45w.bmp"\r
+L45W                    BITMAP  MOVEABLE PURE   "bitmaps\\l45w.bmp"\r
+C45W                    BITMAP  MOVEABLE PURE   "bitmaps\\c45w.bmp"\r
+CV45W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv45w.bmp"\r
+A54W                    BITMAP  MOVEABLE PURE   "bitmaps\\a54w.bmp"\r
+L54W                    BITMAP  MOVEABLE PURE   "bitmaps\\l54w.bmp"\r
+C54W                    BITMAP  MOVEABLE PURE   "bitmaps\\c54w.bmp"\r
+CV54W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv54w.bmp"\r
+V54W                    BITMAP  MOVEABLE PURE   "bitmaps\\v54w.bmp"\r
+A58W                    BITMAP  MOVEABLE PURE   "bitmaps\\a58w.bmp"\r
+L58W                    BITMAP  MOVEABLE PURE   "bitmaps\\l58w.bmp"\r
+C58W                    BITMAP  MOVEABLE PURE   "bitmaps\\c58w.bmp"\r
+CV58W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv58w.bmp"\r
+A64W                    BITMAP  MOVEABLE PURE   "bitmaps\\a64w.bmp"\r
+L64W                    BITMAP  MOVEABLE PURE   "bitmaps\\l64w.bmp"\r
+C64W                    BITMAP  MOVEABLE PURE   "bitmaps\\c64w.bmp"\r
+CV64W                   BITMAP  MOVEABLE PURE   "bitmaps\\cv64w.bmp"\r
+A37S                    BITMAP  MOVEABLE PURE   "bitmaps\\a37s.bmp"\r
+L37S                    BITMAP  MOVEABLE PURE   "bitmaps\\l37s.bmp"\r
+C37S                    BITMAP  MOVEABLE PURE   "bitmaps\\c37s.bmp"\r
+CV37S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv37s.bmp"\r
+A40S                    BITMAP  MOVEABLE PURE   "bitmaps\\a40s.bmp"\r
+L40S                    BITMAP  MOVEABLE PURE   "bitmaps\\l40s.bmp"\r
+C40S                    BITMAP  MOVEABLE PURE   "bitmaps\\c40s.bmp"\r
+CV40S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv40s.bmp"\r
+A45S                    BITMAP  MOVEABLE PURE   "bitmaps\\a45s.bmp"\r
+L45S                    BITMAP  MOVEABLE PURE   "bitmaps\\l45s.bmp"\r
+C45S                    BITMAP  MOVEABLE PURE   "bitmaps\\c45s.bmp"\r
+CV45S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv45s.bmp"\r
+A54S                    BITMAP  MOVEABLE PURE   "bitmaps\\a54s.bmp"\r
+L54S                    BITMAP  MOVEABLE PURE   "bitmaps\\l54s.bmp"\r
+C54S                    BITMAP  MOVEABLE PURE   "bitmaps\\c54s.bmp"\r
+CV54S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv54s.bmp"\r
+V54S                    BITMAP  MOVEABLE PURE   "bitmaps\\v54s.bmp"\r
+A58S                    BITMAP  MOVEABLE PURE   "bitmaps\\a58s.bmp"\r
+L58S                    BITMAP  MOVEABLE PURE   "bitmaps\\l58s.bmp"\r
+C58S                    BITMAP  MOVEABLE PURE   "bitmaps\\c58s.bmp"\r
+CV58S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv58s.bmp"\r
+A64S                    BITMAP  MOVEABLE PURE   "bitmaps\\a64s.bmp"\r
+L64S                    BITMAP  MOVEABLE PURE   "bitmaps\\l64s.bmp"\r
+C64S                    BITMAP  MOVEABLE PURE   "bitmaps\\c64s.bmp"\r
+CV64S                   BITMAP  MOVEABLE PURE   "bitmaps\\cv64s.bmp"\r
 \r
 SP58O                   BITMAP  MOVEABLE PURE   "shogibitmaps\\sp58o.bmp"\r
 SN58O                   BITMAP  MOVEABLE PURE   "shogibitmaps\\sn58o.bmp"\r
index c0606bb..d5e8153 100644 (file)
-/*
- * Layout management
- *
- * Author: Alessandro Scotti (Dec 2005)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#include "config.h"
-
-#include <windows.h> /* required for all Windows applications */
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <commdlg.h>
-#include <dlgs.h>
-
-#include "common.h"
-#include "winboard.h"
-
-VOID RestoreWindowPlacement( HWND hWnd, WindowPlacement * wp )
-{
-    if( wp->x != CW_USEDEFAULT ||
-        wp->y != CW_USEDEFAULT ||
-        wp->width != CW_USEDEFAULT ||
-        wp->height != CW_USEDEFAULT )
-    {
-       WINDOWPLACEMENT stWP;
-
-        ZeroMemory( &stWP, sizeof(stWP) );
-
-       EnsureOnScreen( &wp->x, &wp->y);
-
-       stWP.length = sizeof(stWP);
-       stWP.flags = 0;
-       stWP.showCmd = SW_SHOW;
-       stWP.ptMaxPosition.x = 0;
-        stWP.ptMaxPosition.y = 0;
-       stWP.rcNormalPosition.left = wp->x;
-       stWP.rcNormalPosition.right = wp->x + wp->width;
-       stWP.rcNormalPosition.top = wp->y;
-       stWP.rcNormalPosition.bottom = wp->y + wp->height;
-
-       SetWindowPlacement(hWnd, &stWP);
-    }
-}
-
-VOID InitWindowPlacement( WindowPlacement * wp )
-{
-    wp->visible = TRUE;
-    wp->x = CW_USEDEFAULT;
-    wp->y = CW_USEDEFAULT;
-    wp->width = CW_USEDEFAULT;
-    wp->height = CW_USEDEFAULT;
-}
-
-static BOOL IsAttachDistance( int a, int b )
-{
-    BOOL result = FALSE;
-
-    if( a == b ) {
-        result = TRUE;
-    }
-
-    return result;
-}
-
-static BOOL IsDefaultPlacement( WindowPlacement * wp )
-{
-    BOOL result = FALSE;
-
-    if( wp->x == CW_USEDEFAULT || wp->y == CW_USEDEFAULT || wp->width == CW_USEDEFAULT || wp->height == CW_USEDEFAULT ) {
-        result = TRUE;
-    }
-
-    return result;
-}
-
-static BOOL GetActualPlacement( HWND hWnd, WindowPlacement * wp )
-{
-    BOOL result = FALSE;
-
-    if( hWnd != NULL ) {
-        WINDOWPLACEMENT stWP;
-
-        ZeroMemory( &stWP, sizeof(stWP) );
-
-        stWP.length = sizeof(stWP);
-
-        GetWindowPlacement( hWnd, &stWP );
-
-        wp->x = stWP.rcNormalPosition.left;
-        wp->y = stWP.rcNormalPosition.top;
-        wp->width = stWP.rcNormalPosition.right - stWP.rcNormalPosition.left;
-        wp->height = stWP.rcNormalPosition.bottom - stWP.rcNormalPosition.top;
-
-        result = TRUE;
-    }
-
-    return result;
-}
-
-static BOOL IsAttachedByWindowPlacement( LPRECT lprcMain, WindowPlacement * wp )
-{
-    BOOL result = FALSE;
-
-    if( ! IsDefaultPlacement(wp) ) {
-        if( IsAttachDistance( lprcMain->right, wp->x ) ||
-            IsAttachDistance( lprcMain->bottom, wp->y ) ||
-            IsAttachDistance( lprcMain->left, (wp->x + wp->width) ) ||
-            IsAttachDistance( lprcMain->top, (wp->y + wp->height) ) )
-        {
-            result = TRUE;
-        }
-    }
-
-    return result;
-}
-
-VOID ReattachAfterMove( LPRECT lprcOldPos, int new_x, int new_y, HWND hWndChild, WindowPlacement * pwpChild )
-{
-    if( ! IsDefaultPlacement( pwpChild ) ) {
-        GetActualPlacement( hWndChild, pwpChild );
-
-        if( IsAttachedByWindowPlacement( lprcOldPos, pwpChild ) ) {
-            /* Get position delta */
-            int delta_x = pwpChild->x - lprcOldPos->left;
-            int delta_y = pwpChild->y - lprcOldPos->top;
-
-            /* Adjust placement */
-            pwpChild->x = new_x + delta_x;
-            pwpChild->y = new_y + delta_y;
-
-            /* Move window */
-            if( hWndChild != NULL ) {
-                SetWindowPos( hWndChild, HWND_TOP,
-                    pwpChild->x, pwpChild->y,
-                    0, 0,
-                    SWP_NOZORDER | SWP_NOSIZE );
-            }
-        }
-    }
-}
+/*\r
+ * Layout management\r
+ *\r
+ * Author: Alessandro Scotti (Dec 2005)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#include "config.h"\r
+\r
+#include <windows.h> /* required for all Windows applications */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+#include <commdlg.h>\r
+#include <dlgs.h>\r
+\r
+#include "common.h"\r
+#include "winboard.h"\r
+\r
+VOID RestoreWindowPlacement( HWND hWnd, WindowPlacement * wp )\r
+{\r
+    if( wp->x != CW_USEDEFAULT || \r
+        wp->y != CW_USEDEFAULT ||\r
+        wp->width != CW_USEDEFAULT || \r
+        wp->height != CW_USEDEFAULT )\r
+    {\r
+       WINDOWPLACEMENT stWP;\r
+\r
+        ZeroMemory( &stWP, sizeof(stWP) );\r
+\r
+       EnsureOnScreen( &wp->x, &wp->y);\r
+\r
+       stWP.length = sizeof(stWP);\r
+       stWP.flags = 0;\r
+       stWP.showCmd = SW_SHOW;\r
+       stWP.ptMaxPosition.x = 0;\r
+        stWP.ptMaxPosition.y = 0;\r
+       stWP.rcNormalPosition.left = wp->x;\r
+       stWP.rcNormalPosition.right = wp->x + wp->width;\r
+       stWP.rcNormalPosition.top = wp->y;\r
+       stWP.rcNormalPosition.bottom = wp->y + wp->height;\r
+\r
+       SetWindowPlacement(hWnd, &stWP);\r
+    }\r
+}\r
+\r
+VOID InitWindowPlacement( WindowPlacement * wp )\r
+{\r
+    wp->visible = TRUE;\r
+    wp->x = CW_USEDEFAULT;\r
+    wp->y = CW_USEDEFAULT;\r
+    wp->width = CW_USEDEFAULT;\r
+    wp->height = CW_USEDEFAULT;\r
+}\r
+\r
+static BOOL IsAttachDistance( int a, int b )\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    if( a == b ) {\r
+        result = TRUE;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static BOOL IsDefaultPlacement( WindowPlacement * wp )\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    if( wp->x == CW_USEDEFAULT || wp->y == CW_USEDEFAULT || wp->width == CW_USEDEFAULT || wp->height == CW_USEDEFAULT ) {\r
+        result = TRUE;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static BOOL GetActualPlacement( HWND hWnd, WindowPlacement * wp )\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    if( hWnd != NULL ) {\r
+        WINDOWPLACEMENT stWP;\r
+\r
+        ZeroMemory( &stWP, sizeof(stWP) );\r
+\r
+        stWP.length = sizeof(stWP);\r
+\r
+        GetWindowPlacement( hWnd, &stWP );\r
+\r
+        wp->x = stWP.rcNormalPosition.left;\r
+        wp->y = stWP.rcNormalPosition.top;\r
+        wp->width = stWP.rcNormalPosition.right - stWP.rcNormalPosition.left;\r
+        wp->height = stWP.rcNormalPosition.bottom - stWP.rcNormalPosition.top;\r
+\r
+        result = TRUE;\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+static BOOL IsAttachedByWindowPlacement( LPRECT lprcMain, WindowPlacement * wp )\r
+{\r
+    BOOL result = FALSE;\r
+\r
+    if( ! IsDefaultPlacement(wp) ) {\r
+        if( IsAttachDistance( lprcMain->right, wp->x ) ||\r
+            IsAttachDistance( lprcMain->bottom, wp->y ) ||\r
+            IsAttachDistance( lprcMain->left, (wp->x + wp->width) ) ||\r
+            IsAttachDistance( lprcMain->top, (wp->y + wp->height) ) )\r
+        {\r
+            result = TRUE;\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+VOID ReattachAfterMove( LPRECT lprcOldPos, int new_x, int new_y, HWND hWndChild, WindowPlacement * pwpChild )\r
+{\r
+    if( ! IsDefaultPlacement( pwpChild ) ) {\r
+        GetActualPlacement( hWndChild, pwpChild );\r
+\r
+        if( IsAttachedByWindowPlacement( lprcOldPos, pwpChild ) ) {\r
+            /* Get position delta */\r
+            int delta_x = pwpChild->x - lprcOldPos->left;\r
+            int delta_y = pwpChild->y - lprcOldPos->top;\r
+\r
+            /* Adjust placement */\r
+            pwpChild->x = new_x + delta_x;\r
+            pwpChild->y = new_y + delta_y;\r
+\r
+            /* Move window */\r
+            if( hWndChild != NULL ) {\r
+                SetWindowPos( hWndChild, HWND_TOP,\r
+                    pwpChild->x, pwpChild->y,\r
+                    0, 0,\r
+                    SWP_NOZORDER | SWP_NOSIZE );\r
+            }\r
+        }\r
+    }\r
+}\r
index df3c699..f2a797e 100644 (file)
@@ -65,6 +65,7 @@ extern char installDir[];
 extern HWND hCommPort;    /* currently open comm port */\r
 extern DCB dcb;\r
 extern BOOLEAN chessProgram;\r
+extern startedFromPositionFile; /* [HGM] loadPos */\r
 \r
 /* types */\r
 \r
@@ -773,7 +774,10 @@ VariantWhichRadio(HWND hDlg)
          (IsDlgButtonChecked(hDlg, OPT_VariantSuicide) ? VariantSuicide :\r
          (IsDlgButtonChecked(hDlg, OPT_VariantAtomic) ? VariantAtomic :\r
          (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj :\r
-          VariantNormal )))))))))))))));\r
+         (IsDlgButtonChecked(hDlg, OPT_VariantFRC) ? VariantFischeRandom :\r
+         (IsDlgButtonChecked(hDlg, OPT_VariantCylinder) ? VariantCylinder :\r
+         (IsDlgButtonChecked(hDlg, OPT_VariantFalcon) ? VariantFalcon :\r
+          VariantNormal ))))))))))))))))));\r
 }\r
 \r
 LRESULT CALLBACK\r
@@ -836,6 +840,9 @@ NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     case VariantShatranj:\r
       CheckDlgButton(hDlg, OPT_VariantShatranj, TRUE);\r
       break;\r
+    case VariantFischeRandom:\r
+      CheckDlgButton(hDlg, OPT_VariantFRC, TRUE);\r
+      break;\r
     }\r
 \r
     SetDlgItemInt( hDlg, IDC_Files, -1, TRUE );\r
@@ -874,6 +881,8 @@ NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       if(!n2_ok) appData.NrRanks = -1;\r
       if(!n3_ok) appData.holdingsSize = -1;\r
 \r
+      startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */\r
+      appData.pieceToCharTable = NULL;\r
       Reset(TRUE, TRUE);\r
 \r
       return TRUE;\r
index 6213680..c6507d3 100644 (file)
-#include "wplugin.h"
-
-static char * makePluginExeName( const char * name )
-{
-    char buf[ MAX_PATH ];
-
-    strcpy( buf, "" );
-
-    strcat( buf, "plugins\\" );
-    strcat( buf, name );
-    strcat( buf, ".exe" );
-
-    return strdup( buf );
-}
-
-WbPlugin * wbpCreate( const char * name )
-{
-    char buf[MAX_PATH];
-    int result = 0;
-
-    // Create the plugin
-    WbPlugin * plugin = (WbPlugin *) malloc( sizeof(WbPlugin) );
-
-    memset( plugin, 0, sizeof(WbPlugin) );
-
-    plugin->name_ = strdup( name );
-    plugin->exe_name_ = makePluginExeName( name );
-    plugin->hPipe_ = INVALID_HANDLE_VALUE;
-    plugin->hProcess_ = INVALID_HANDLE_VALUE;
-
-    // Create the named pipe for plugin communication
-    if( result == 0 ) {
-        strcpy( buf, "\\\\.\\pipe\\" );
-        strcat( buf, name );
-
-        plugin->hPipe_ = CreateNamedPipe( buf,
-            PIPE_ACCESS_DUPLEX,
-            0, // Byte mode
-            2, // Max instances
-            4*1024,
-            4*1024,
-            1000, // Default timeout
-            NULL );
-
-        if( plugin->hPipe_ == INVALID_HANDLE_VALUE ) {
-            DWORD err = GetLastError();
-            result = -1;
-        }
-    }
-
-    // Create the plugin process
-    if( result == 0 ) {
-        STARTUPINFO si;
-        PROCESS_INFORMATION pi;
-
-        ZeroMemory( &si, sizeof(si) );
-        ZeroMemory( &pi, sizeof(pi) );
-
-        si.cb = sizeof(si);
-
-        strcpy( buf, "\"" );
-        strcat( buf, plugin->exe_name_ );
-        strcat( buf, "\"" );
-
-        strcpy( buf, "\"C:\\Program Files\\Borland\\Delphi5\\Projects\\History\\History.exe\"" );
-
-        if( CreateProcess( NULL,
-            buf,
-            NULL,
-            NULL,
-            FALSE, // Inherit handles
-            0, // Creation flags
-            NULL, // Environment
-            NULL, // Current directory
-            &si,
-            &pi ) )
-        {
-            CloseHandle( pi.hThread );
-            plugin->hProcess_ = pi.hProcess;
-        }
-        else {
-            result = -2;
-        }
-    }
-
-    // Destroy the plugin instance if something went wrong
-    if( result != 0 ) {
-        wbpDelete( plugin );
-        plugin = 0;
-    }
-
-    return plugin;
-}
-
-void wbpDelete( WbPlugin * plugin )
-{
-    if( plugin != 0 ) {
-        if( plugin->hPipe_ != INVALID_HANDLE_VALUE ) {
-            CloseHandle( plugin->hPipe_ );
-        }
-
-        if( plugin->hProcess_ != INVALID_HANDLE_VALUE ) {
-            CloseHandle( plugin->hProcess_ );
-        }
-
-        free( plugin->name_ );
-
-        free( plugin->exe_name_ );
-
-        plugin->name_ = 0;
-        plugin->exe_name_ = 0;
-        plugin->hPipe_ = INVALID_HANDLE_VALUE;
-        plugin->hProcess_ = INVALID_HANDLE_VALUE;
-
-        free( plugin );
-    }
-}
-
-int wbpSendMessage( WbPlugin * plugin, const char * msg, size_t msg_len )
-{
-    int result = -1;
-
-    if( plugin != 0 && plugin->hPipe_ != INVALID_HANDLE_VALUE ) {
-        DWORD zf = 0;
-        BOOL ok = TRUE;
-
-        while( ok && (msg_len > 0) ) {
-            DWORD cb = 0;
-
-            ok = WriteFile( plugin->hPipe_,
-                msg,
-                msg_len,
-                &cb,
-                NULL );
-
-            if( ok ) {
-                if( cb > msg_len ) break; // Should *never* happen!
-
-                msg_len -= cb;
-                msg += cb;
-            }
-
-            if( cb == 0 ) {
-                zf++;
-                if( zf >= 3 ) ok = FALSE;
-            }
-            else {
-                zf = 0;
-            }
-        }
-
-        if( ok ) {
-            result = 0;
-        }
-    }
-
-    return result;
-}
-
-int wbpListInit( WbPluginList * list )
-{
-    list->item_count_ = 0;
-
-    return 0;
-}
-
-int wbpListAdd( WbPluginList * list, WbPlugin * plugin )
-{
-    int result = -1;
-
-    if( plugin != 0 ) {
-        if( list->item_count_ < MaxWbPlugins ) {
-            list->item_[ list->item_count_ ] = plugin;
-            list->item_count_++;
-
-            result = 0;
-        }
-    }
-
-    return result;
-}
-
-WbPlugin * wbpListGet( WbPluginList * list, int index )
-{
-    WbPlugin * result = 0;
-
-    if( index >= 0 && index < list->item_count_ ) {
-        result = list->item_[ index ];
-    }
-
-    return result;
-}
-
-int wbpListGetCount( WbPluginList * list )
-{
-    return list->item_count_;
-}
-
-int wbpListDeleteAll( WbPluginList * list )
-{
-    int i;
-
-    for( i=0; i<list->item_count_; i++ ) {
-        wbpDelete( list->item_[i] );
-    }
-
-    return wbpListInit( list );
-}
-
-int wbpListBroadcastMessage( WbPluginList * list, const char * msg, size_t msg_len )
-{
-    int result = 0;
-    int i;
-
-    for( i=0; i<list->item_count_; i++ ) {
-        if( wbpSendMessage( list->item_[i], msg, msg_len ) == 0 ) {
-            result++;
-        }
-        else {
-            // Error sending message to plugin...
-        }
-    }
-
-    return result;
-}
+#include "wplugin.h"\r
+\r
+static char * makePluginExeName( const char * name )\r
+{\r
+    char buf[ MAX_PATH ];\r
+\r
+    strcpy( buf, "" );\r
+\r
+    strcat( buf, "plugins\\" );\r
+    strcat( buf, name );\r
+    strcat( buf, ".exe" );\r
+\r
+    return strdup( buf );\r
+}\r
+\r
+WbPlugin * wbpCreate( const char * name )\r
+{\r
+    char buf[MAX_PATH];\r
+    int result = 0;\r
+\r
+    // Create the plugin\r
+    WbPlugin * plugin = (WbPlugin *) malloc( sizeof(WbPlugin) );\r
+\r
+    memset( plugin, 0, sizeof(WbPlugin) );\r
+\r
+    plugin->name_ = strdup( name );\r
+    plugin->exe_name_ = makePluginExeName( name );\r
+    plugin->hPipe_ = INVALID_HANDLE_VALUE;\r
+    plugin->hProcess_ = INVALID_HANDLE_VALUE;\r
+\r
+    // Create the named pipe for plugin communication\r
+    if( result == 0 ) {\r
+        strcpy( buf, "\\\\.\\pipe\\" );\r
+        strcat( buf, name );\r
+\r
+        plugin->hPipe_ = CreateNamedPipe( buf,\r
+            PIPE_ACCESS_DUPLEX,\r
+            0, // Byte mode\r
+            2, // Max instances\r
+            4*1024,\r
+            4*1024,\r
+            1000, // Default timeout\r
+            NULL );\r
+\r
+        if( plugin->hPipe_ == INVALID_HANDLE_VALUE ) {\r
+            DWORD err = GetLastError();\r
+            result = -1;\r
+        }\r
+    }\r
+\r
+    // Create the plugin process\r
+    if( result == 0 ) {\r
+        STARTUPINFO si;\r
+        PROCESS_INFORMATION pi;\r
+\r
+        ZeroMemory( &si, sizeof(si) );\r
+        ZeroMemory( &pi, sizeof(pi) );\r
+\r
+        si.cb = sizeof(si);\r
+\r
+        strcpy( buf, "\"" );\r
+        strcat( buf, plugin->exe_name_ );\r
+        strcat( buf, "\"" );\r
+\r
+        strcpy( buf, "\"C:\\Program Files\\Borland\\Delphi5\\Projects\\History\\History.exe\"" );\r
+\r
+        if( CreateProcess( NULL,\r
+            buf,\r
+            NULL,\r
+            NULL,\r
+            FALSE, // Inherit handles\r
+            0, // Creation flags\r
+            NULL, // Environment\r
+            NULL, // Current directory\r
+            &si,\r
+            &pi ) )\r
+        {\r
+            CloseHandle( pi.hThread );\r
+            plugin->hProcess_ = pi.hProcess;\r
+        }\r
+        else {\r
+            result = -2;\r
+        }\r
+    }\r
+\r
+    // Destroy the plugin instance if something went wrong\r
+    if( result != 0 ) {\r
+        wbpDelete( plugin );\r
+        plugin = 0;\r
+    }\r
+\r
+    return plugin;\r
+}\r
+\r
+void wbpDelete( WbPlugin * plugin )\r
+{\r
+    if( plugin != 0 ) {\r
+        if( plugin->hPipe_ != INVALID_HANDLE_VALUE ) {\r
+            CloseHandle( plugin->hPipe_ );\r
+        }\r
+\r
+        if( plugin->hProcess_ != INVALID_HANDLE_VALUE ) {\r
+            CloseHandle( plugin->hProcess_ );\r
+        }\r
+\r
+        free( plugin->name_ );\r
+\r
+        free( plugin->exe_name_ );\r
+\r
+        plugin->name_ = 0;\r
+        plugin->exe_name_ = 0;\r
+        plugin->hPipe_ = INVALID_HANDLE_VALUE;\r
+        plugin->hProcess_ = INVALID_HANDLE_VALUE;\r
+\r
+        free( plugin );\r
+    }\r
+}\r
+\r
+int wbpSendMessage( WbPlugin * plugin, const char * msg, size_t msg_len )\r
+{\r
+    int result = -1;\r
+\r
+    if( plugin != 0 && plugin->hPipe_ != INVALID_HANDLE_VALUE ) {\r
+        DWORD zf = 0;\r
+        BOOL ok = TRUE;\r
+\r
+        while( ok && (msg_len > 0) ) {\r
+            DWORD cb = 0;\r
+\r
+            ok = WriteFile( plugin->hPipe_,\r
+                msg,\r
+                msg_len,\r
+                &cb,\r
+                NULL );\r
+\r
+            if( ok ) {\r
+                if( cb > msg_len ) break; // Should *never* happen!\r
+\r
+                msg_len -= cb;\r
+                msg += cb;\r
+            }\r
+\r
+            if( cb == 0 ) {\r
+                zf++;\r
+                if( zf >= 3 ) ok = FALSE;\r
+            }\r
+            else {\r
+                zf = 0;\r
+            }\r
+        }\r
+\r
+        if( ok ) {\r
+            result = 0;\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+int wbpListInit( WbPluginList * list )\r
+{\r
+    list->item_count_ = 0;\r
+\r
+    return 0;\r
+}\r
+\r
+int wbpListAdd( WbPluginList * list, WbPlugin * plugin )\r
+{\r
+    int result = -1;\r
+\r
+    if( plugin != 0 ) {\r
+        if( list->item_count_ < MaxWbPlugins ) {\r
+            list->item_[ list->item_count_ ] = plugin;\r
+            list->item_count_++;\r
+\r
+            result = 0;\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+WbPlugin * wbpListGet( WbPluginList * list, int index )\r
+{\r
+    WbPlugin * result = 0;\r
+\r
+    if( index >= 0 && index < list->item_count_ ) {\r
+        result = list->item_[ index ];\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+int wbpListGetCount( WbPluginList * list )\r
+{\r
+    return list->item_count_;\r
+}\r
+\r
+int wbpListDeleteAll( WbPluginList * list )\r
+{\r
+    int i;\r
+\r
+    for( i=0; i<list->item_count_; i++ ) {\r
+        wbpDelete( list->item_[i] );\r
+    }\r
+\r
+    return wbpListInit( list );\r
+}\r
+\r
+int wbpListBroadcastMessage( WbPluginList * list, const char * msg, size_t msg_len )\r
+{\r
+    int result = 0;\r
+    int i;\r
+\r
+    for( i=0; i<list->item_count_; i++ ) {\r
+        if( wbpSendMessage( list->item_[i], msg, msg_len ) == 0 ) {\r
+            result++;\r
+        }\r
+        else {\r
+            // Error sending message to plugin...\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
index 100ae1c..3b1830b 100644 (file)
@@ -1,40 +1,40 @@
-#ifndef WPLUGIN_H_
-#define WPLUGIN_H_
-
-#include <windows.h>
-
-#define MaxWbPlugins 16
-
-typedef struct WbPlugin_tag
-{
-    char * name_;
-    char * exe_name_;
-    HANDLE hPipe_;
-    HANDLE hProcess_;
-} WbPlugin;
-
-typedef struct WbPluginList_tag
-{
-    int item_count_;
-    WbPlugin * item_[MaxWbPlugins];
-} WbPluginList;
-
-WbPlugin * wbpCreate( const char * name );
-
-void wbpDelete( WbPlugin * plugin );
-
-int wbpSendMessage( WbPlugin * plugin, const char * msg, size_t msg_len );
-
-int wbpListInit( WbPluginList * list );
-
-int wbpListAdd( WbPluginList * list, WbPlugin * plugin );
-
-WbPlugin * wbpListGet( WbPluginList * list, int index );
-
-int wbpListGetCount( WbPluginList * list );
-
-int wbpListDeleteAll( WbPluginList * list );
-
-int wbpListBroadcastMessage( WbPluginList * list, const char * msg, size_t msg_len );
-
-#endif // WPLUGIN_H_
+#ifndef WPLUGIN_H_\r
+#define WPLUGIN_H_\r
+\r
+#include <windows.h>\r
+\r
+#define MaxWbPlugins 16\r
+\r
+typedef struct WbPlugin_tag\r
+{\r
+    char * name_;\r
+    char * exe_name_;\r
+    HANDLE hPipe_;\r
+    HANDLE hProcess_;\r
+} WbPlugin;\r
+\r
+typedef struct WbPluginList_tag\r
+{\r
+    int item_count_;\r
+    WbPlugin * item_[MaxWbPlugins];\r
+} WbPluginList;\r
+\r
+WbPlugin * wbpCreate( const char * name );\r
+\r
+void wbpDelete( WbPlugin * plugin );\r
+\r
+int wbpSendMessage( WbPlugin * plugin, const char * msg, size_t msg_len );\r
+\r
+int wbpListInit( WbPluginList * list );\r
+\r
+int wbpListAdd( WbPluginList * list, WbPlugin * plugin );\r
+\r
+WbPlugin * wbpListGet( WbPluginList * list, int index );\r
+\r
+int wbpListGetCount( WbPluginList * list );\r
+\r
+int wbpListDeleteAll( WbPluginList * list );\r
+\r
+int wbpListBroadcastMessage( WbPluginList * list, const char * msg, size_t msg_len );\r
+\r
+#endif // WPLUGIN_H_\r
index e6f6151..6d84304 100644 (file)
-/*
- * Smart "snapping" for window moving and sizing
- *
- * Author: Alessandro Scotti (Dec 2005)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#include "wsnap.h"
-
-/* Imports from winboard.c */
-extern HINSTANCE hInst;
-
-extern HWND hwndMain;
-extern HWND moveHistoryDialog;
-extern HWND evalGraphDialog;
-extern HWND engineOutputDialog;
-extern HWND gameListDialog;
-
-static BOOL SnappingEnabled = TRUE;
-
-static void AddSnapPoint( int * grid, int * grid_len, int value )
-{
-    int len = *grid_len;
-
-    if( len < MAX_SNAP_POINTS ) {
-        int i;
-
-        for( i=0; i<len; i++ ) {
-            if( grid[i] == value ) {
-                return;
-            }
-        }
-
-        grid[ len++ ] = value;
-
-        *grid_len = len;
-    }
-}
-
-static void AddSnapRectangle( SnapData * sd, RECT * rc )
-{
-    AddSnapPoint( sd->x_grid, &sd->x_grid_len, rc->left );
-    AddSnapPoint( sd->x_grid, &sd->x_grid_len, rc->right );
-
-    AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->top );
-    AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->bottom );
-}
-
-static void AddSnapWindow( HWND hWndCaller, SnapData * sd, HWND hWndSnapWindow )
-{
-    if( hWndSnapWindow != NULL && hWndCaller != hWndSnapWindow && IsWindowVisible(hWndSnapWindow) ) {
-        RECT rc;
-
-        GetWindowRect( hWndSnapWindow, &rc );
-
-        AddSnapRectangle( sd, &rc );
-    }
-}
-
-static BOOL AdjustToSnapPoint( int * grid, int grid_len, int value, int * snap_size, int * delta )
-{
-    BOOL result = FALSE;
-    int i;
-
-    for( i=0; i<grid_len; i++ ) {
-        int distance = value - grid[i];
-
-        if( distance < 0 ) distance = -distance;
-
-        if( distance < *snap_size ) {
-            result = TRUE;
-            *snap_size = distance;
-            *delta = grid[i] - value;
-        }
-    }
-
-    return result;
-}
-
-LRESULT OnEnterSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
-{
-    RECT rc;
-
-    snapData->x_grid_len = 0;
-    snapData->y_grid_len = 0;
-
-    /* Add desktop area */
-    if( SystemParametersInfo( SPI_GETWORKAREA, 0, &rc, 0 ) ) {
-        AddSnapRectangle( snapData, &rc );
-    }
-
-    if( hWnd != hwndMain ) {
-        /* Add other windows */
-        AddSnapWindow( hWnd, snapData, hwndMain );
-        AddSnapWindow( hWnd, snapData, moveHistoryDialog );
-        AddSnapWindow( hWnd, snapData, evalGraphDialog );
-        AddSnapWindow( hWnd, snapData, engineOutputDialog );
-        AddSnapWindow( hWnd, snapData, gameListDialog );
-    }
-
-    return 0;
-}
-
-LRESULT OnMoving( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
-{
-    LPRECT lprc = (LPRECT) lParam;
-    int delta_x = 0;
-    int delta_y = 0;
-    int snap_size_x = SNAP_DISTANCE;
-    int snap_size_y = SNAP_DISTANCE;
-
-    if( ! SnappingEnabled ) {
-        return FALSE;
-    }
-
-    AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );
-    AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );
-
-    AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );
-    AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );
-
-    OffsetRect( lprc, delta_x, delta_y );
-
-    return TRUE;
-}
-
-LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
-{
-    LPRECT lprc = (LPRECT) lParam;
-    int delta_x = 0;
-    int delta_y = 0;
-    int snap_size_x = SNAP_DISTANCE;
-    int snap_size_y = SNAP_DISTANCE;
-
-    if( ! SnappingEnabled ) {
-        return FALSE;
-    }
-
-    switch( wParam ) {
-    case WMSZ_BOTTOM:
-        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );
-        lprc->bottom += delta_y;
-        break;
-    case WMSZ_BOTTOMLEFT:
-        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );
-        lprc->bottom += delta_y;
-        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );
-        lprc->left += delta_x;
-        break;
-    case WMSZ_BOTTOMRIGHT:
-        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );
-        lprc->bottom += delta_y;
-        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );
-        lprc->right += delta_x;
-        break;
-    case WMSZ_LEFT:
-        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );
-        lprc->left += delta_x;
-        break;
-    case WMSZ_RIGHT:
-        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );
-        lprc->right += delta_x;
-        break;
-    case WMSZ_TOP:
-        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );
-        lprc->top += delta_y;
-        break;
-    case WMSZ_TOPLEFT:
-        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );
-        lprc->top += delta_y;
-        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );
-        lprc->left += delta_x;
-        break;
-    case WMSZ_TOPRIGHT:
-        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );
-        lprc->top += delta_y;
-        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );
-        lprc->right += delta_x;
-        break;
-    default:
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-LRESULT OnExitSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
-{
-    return 0;
-}
+/*\r
+ * Smart "snapping" for window moving and sizing\r
+ *\r
+ * Author: Alessandro Scotti (Dec 2005)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#include "wsnap.h"\r
+\r
+/* Imports from winboard.c */\r
+extern HINSTANCE hInst;\r
+\r
+extern HWND hwndMain;\r
+extern HWND moveHistoryDialog;\r
+extern HWND evalGraphDialog;\r
+extern HWND engineOutputDialog;\r
+extern HWND gameListDialog;\r
+\r
+static BOOL SnappingEnabled = TRUE;\r
+\r
+static void AddSnapPoint( int * grid, int * grid_len, int value )\r
+{\r
+    int len = *grid_len;\r
+\r
+    if( len < MAX_SNAP_POINTS ) {\r
+        int i;\r
+\r
+        for( i=0; i<len; i++ ) {\r
+            if( grid[i] == value ) {\r
+                return;\r
+            }\r
+        }\r
+\r
+        grid[ len++ ] = value;\r
+\r
+        *grid_len = len;\r
+    }\r
+}\r
+\r
+static void AddSnapRectangle( SnapData * sd, RECT * rc )\r
+{\r
+    AddSnapPoint( sd->x_grid, &sd->x_grid_len, rc->left );\r
+    AddSnapPoint( sd->x_grid, &sd->x_grid_len, rc->right );\r
+\r
+    AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->top );\r
+    AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->bottom );\r
+}\r
+\r
+static void AddSnapWindow( HWND hWndCaller, SnapData * sd, HWND hWndSnapWindow )\r
+{\r
+    if( hWndSnapWindow != NULL && hWndCaller != hWndSnapWindow && IsWindowVisible(hWndSnapWindow) ) {\r
+        RECT rc;\r
+\r
+        GetWindowRect( hWndSnapWindow, &rc );\r
+\r
+        AddSnapRectangle( sd, &rc );\r
+    }\r
+}\r
+\r
+static BOOL AdjustToSnapPoint( int * grid, int grid_len, int value, int * snap_size, int * delta )\r
+{\r
+    BOOL result = FALSE;\r
+    int i;\r
+\r
+    for( i=0; i<grid_len; i++ ) {\r
+        int distance = value - grid[i];\r
+\r
+        if( distance < 0 ) distance = -distance;\r
+\r
+        if( distance < *snap_size ) {\r
+            result = TRUE;\r
+            *snap_size = distance;\r
+            *delta = grid[i] - value;\r
+        }\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+LRESULT OnEnterSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
+{\r
+    RECT rc;\r
+\r
+    snapData->x_grid_len = 0;\r
+    snapData->y_grid_len = 0;\r
+\r
+    /* Add desktop area */\r
+    if( SystemParametersInfo( SPI_GETWORKAREA, 0, &rc, 0 ) ) {\r
+        AddSnapRectangle( snapData, &rc );\r
+    }\r
+\r
+    if( hWnd != hwndMain ) {\r
+        /* Add other windows */\r
+        AddSnapWindow( hWnd, snapData, hwndMain );\r
+        AddSnapWindow( hWnd, snapData, moveHistoryDialog );\r
+        AddSnapWindow( hWnd, snapData, evalGraphDialog );\r
+        AddSnapWindow( hWnd, snapData, engineOutputDialog );\r
+        AddSnapWindow( hWnd, snapData, gameListDialog );\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+LRESULT OnMoving( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
+{\r
+    LPRECT lprc = (LPRECT) lParam;\r
+    int delta_x = 0;\r
+    int delta_y = 0;\r
+    int snap_size_x = SNAP_DISTANCE;\r
+    int snap_size_y = SNAP_DISTANCE;\r
+\r
+    if( ! SnappingEnabled ) {\r
+        return FALSE;\r
+    }\r
+\r
+    AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
+    AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
+\r
+    AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
+    AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
+\r
+    OffsetRect( lprc, delta_x, delta_y );\r
+\r
+    return TRUE;\r
+}\r
+\r
+LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
+{\r
+    LPRECT lprc = (LPRECT) lParam;\r
+    int delta_x = 0;\r
+    int delta_y = 0;\r
+    int snap_size_x = SNAP_DISTANCE;\r
+    int snap_size_y = SNAP_DISTANCE;\r
+\r
+    if( ! SnappingEnabled ) {\r
+        return FALSE;\r
+    }\r
+\r
+    switch( wParam ) {\r
+    case WMSZ_BOTTOM:\r
+        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
+        lprc->bottom += delta_y;\r
+        break;\r
+    case WMSZ_BOTTOMLEFT:\r
+        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
+        lprc->bottom += delta_y;\r
+        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
+        lprc->left += delta_x;\r
+        break;\r
+    case WMSZ_BOTTOMRIGHT:\r
+        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
+        lprc->bottom += delta_y;\r
+        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
+        lprc->right += delta_x;\r
+        break;\r
+    case WMSZ_LEFT:\r
+        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
+        lprc->left += delta_x;\r
+        break;\r
+    case WMSZ_RIGHT:\r
+        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
+        lprc->right += delta_x;\r
+        break;\r
+    case WMSZ_TOP:\r
+        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
+        lprc->top += delta_y;\r
+        break;\r
+    case WMSZ_TOPLEFT:\r
+        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
+        lprc->top += delta_y;\r
+        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
+        lprc->left += delta_x;\r
+        break;\r
+    case WMSZ_TOPRIGHT:\r
+        AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
+        lprc->top += delta_y;\r
+        AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
+        lprc->right += delta_x;\r
+        break;\r
+    default:\r
+        return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+LRESULT OnExitSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
+{\r
+    return 0;\r
+}\r
index 818144a..7cc428d 100644 (file)
@@ -1,43 +1,43 @@
-/*
- * Smart "snapping" for window moving and sizing
- *
- * Author: Alessandro Scotti (Dec 2005)
- *
- * ------------------------------------------------------------------------
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- * ------------------------------------------------------------------------
- */
-#ifndef WSNAP_H_
-#define WSNAP_H_
-
-#include <windows.h>
-
-#define MAX_SNAP_POINTS     12
-
-#define SNAP_DISTANCE       4
-
-typedef struct {
-    int x_grid[ MAX_SNAP_POINTS ];
-    int x_grid_len;
-    int y_grid[ MAX_SNAP_POINTS ];
-    int y_grid_len;
-} SnapData;
-
-LRESULT OnEnterSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );
-LRESULT OnMoving( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );
-LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );
-LRESULT OnExitSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );
-
-#endif // WSNAP_H_
+/*\r
+ * Smart "snapping" for window moving and sizing\r
+ *\r
+ * Author: Alessandro Scotti (Dec 2005)\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * ------------------------------------------------------------------------\r
+ */\r
+#ifndef WSNAP_H_\r
+#define WSNAP_H_\r
+\r
+#include <windows.h>\r
+\r
+#define MAX_SNAP_POINTS     12\r
+\r
+#define SNAP_DISTANCE       4\r
+\r
+typedef struct {\r
+    int x_grid[ MAX_SNAP_POINTS ];\r
+    int x_grid_len;\r
+    int y_grid[ MAX_SNAP_POINTS ];\r
+    int y_grid_len;\r
+} SnapData;\r
+\r
+LRESULT OnEnterSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );\r
+LRESULT OnMoving( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );\r
+LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );\r
+LRESULT OnExitSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam );\r
+\r
+#endif // WSNAP_H_\r
diff --git a/zippy.c b/zippy.c
index aed634e..c788318 100644 (file)
--- a/zippy.c
+++ b/zippy.c
-/*
- * zippy.c -- Implements Zippy the Pinhead chess player on ICS in XBoard
- * $Id: zippy.c,v 2.2 2003/11/25 05:25:20 mann Exp $
- *
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
- * Enhancements Copyright 1992-2001 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.
- * ------------------------------------------------------------------------
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <string.h>
-#else /* not STDC_HEADERS */
-extern char *getenv();
-# if HAVE_STRING_H
-#  include <string.h>
-# else /* not HAVE_STRING_H */
-#  include <strings.h>
-# endif /* not HAVE_STRING_H */
-#endif /* not STDC_HEADERS */
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-# else
-#  include <time.h>
-# endif
-#endif
-#define HI "hlelo "
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "common.h"
-#include "zippy.h"
-#include "frontend.h"
-#include "backend.h"
-#include "backendz.h"
-
-static char zippyPartner[MSG_SIZ];
-static char zippyLastOpp[MSG_SIZ];
-static int zippyConsecGames;
-static time_t zippyLastGameEnd;
-
-void ZippyInit()
-{
-    char *p;
-
-    /* Get name of Zippy lines file */
-    p = getenv("ZIPPYLINES");
-    if (p != NULL) {
-      appData.zippyLines = p;
-    }
-
-    /* Get word that Zippy thinks is insulting */
-    p = getenv("ZIPPYPINHEAD");
-    if (p != NULL) {
-      appData.zippyPinhead = p;
-    }
-
-    /* What password is used for remote control? */
-    p = getenv("ZIPPYPASSWORD");
-    if (p != NULL) {
-      appData.zippyPassword = p;
-    }
-
-    /* What password is used for remote commands to gnuchess? */
-    p = getenv("ZIPPYPASSWORD2");
-    if (p != NULL) {
-      appData.zippyPassword2 = p;
-    }
-
-    /* Joke feature for people who try an old password */
-    p = getenv("ZIPPYWRONGPASSWORD");
-    if (p != NULL) {
-      appData.zippyWrongPassword = p;
-    }
-
-    /* While testing, I want to accept challenges from only one person
-       (namely, my "anonymous" account), so I set an environment
-       variable ZIPPYACCEPTONLY. */
-    p = getenv("ZIPPYACCEPTONLY");
-    if ( p != NULL ) {
-      appData.zippyAcceptOnly = p;
-    }
-    
-    /* Should Zippy use "i" command? */
-    /* Defaults to 1=true */
-    p = getenv("ZIPPYUSEI");
-    if (p != NULL) {
-      appData.zippyUseI = atoi(p);
-    }
-
-    /* How does Zippy handle bughouse partnering? */
-    /* 0=say we can't play, 1=manual partnering, 2=auto partnering */
-    p = getenv("ZIPPYBUGHOUSE");
-    if (p != NULL) {
-      appData.zippyBughouse = atoi(p);
-    }
-
-    /* Does Zippy abort games with Crafty? */
-    /* Defaults to 0=false */
-    p = getenv("ZIPPYNOPLAYCRAFTY");
-    if (p != NULL) {
-      appData.zippyNoplayCrafty = atoi(p);
-    }
-
-    /* What ICS command does Zippy send at game end?  Default: "gameend". */
-    p = getenv("ZIPPYGAMEEND");
-    if (p != NULL) {
-      appData.zippyGameEnd = p;
-    }
-
-    /* What ICS command does Zippy send at game start?  Default: none. */
-    p = getenv("ZIPPYGAMESTART");
-    if (p != NULL) {
-      appData.zippyGameStart = p;
-    }
-
-    /* Should Zippy accept adjourns? */
-    /* Defaults to 0=false */
-    p = getenv("ZIPPYADJOURN");
-    if (p != NULL) {
-      appData.zippyAdjourn = atoi(p);
-    }
-
-    /* Should Zippy accept aborts? */
-    /* Defaults to 0=false */
-    p = getenv("ZIPPYABORT");
-    if (p != NULL) {
-      appData.zippyAbort = atoi(p);
-    }
-
-    /* Should Zippy play chess variants (besides bughouse)? */
-    p = getenv("ZIPPYVARIANTS");
-    if (p != NULL) {
-      appData.zippyVariants = p;
-    }
-    strcpy(first.variants, appData.zippyVariants);
-
-    srandom(time(NULL));
-}
-
-/*
- * Routines to implement Zippy talking
- */
-
-
-char *swifties[] = { 
-    "i acclaims:", "i admonishes:", "i advertises:", "i advises:",
-    "i advocates:", "i affirms:", "i alleges:", "i anathematizes:",
-    "i animadverts:", "i announces:", "i apostrophizes:",
-    "i appeals:", "i applauds:", "i approves:", "i argues:",
-    "i articulates:", "i asserts:", "i asseverates:", "i attests:",
-    "i avers:", "i avows:", "i baas:", "i babbles:", "i banters:",
-    "i barks:", "i bawls:", "i bays:", "i begs:", "i belches:",
-    "i bellows:", "i belts out:", "i berates:", "i beshrews:",
-    "i blabbers:", "i blabs:", "i blares:", "i blasphemes:",
-    "i blasts:", "i blathers:", "i bleats:", "i blithers:",
-    "i blubbers:", "i blurts out:", "i blusters:", "i boasts:",
-    "i brags:", "i brays:", "i broadcasts:", "i burbles:",
-    "i buzzes:", "i cachinnates:", "i cackles:", "i caterwauls:",
-    "i calumniates:", "i caws:", "i censures:", "i chants:",
-    "i chatters:", "i cheeps:", "i cheers:", "i chides:", "i chins:",
-    "i chirps:", "i chortles:", "i chuckles:", "i claims:",
-    "i clamors:", "i clucks:", "i commands:", "i commends:",
-    "i comments:", "i commiserates:", "i communicates:",
-    "i complains:", "i concludes:", "i confabulates:", "i confesses:",
-    "i coos:", "i coughs:", "i counsels:", "i cries:", "i croaks:",
-    "i crows:", "i curses:", "i daydreams:", "i debates:",
-    "i declaims:", "i declares:", "i delivers:", "i denounces:",
-    "i deposes:", "i directs:", "i discloses:", "i disparages:",
-    "i discourses:", "i divulges:", "i documents:", "i drawls:",
-    "i dreams:", "i drivels:", "i drones:", "i effuses:",
-    /*"i ejaculates:",*/ "i elucidates:", "i emotes:", "i endorses:",
-    "i enthuses:", "i entreats:", "i enunciates:", "i eulogizes:",
-    "i exclaims:", "i execrates:", "i exhorts:", "i expatiates:",
-    "i explains:", "i explicates:", "i explodes:", "i exposes:",
-    "i exposits:", "i expounds:", "i expresses:", "i extols:",
-    "i exults:", "i fantasizes:", "i fibs:", "i filibusters:",
-    "i flatters:", "i flutes:", "i fools:", "i free-associates:",
-    "i fulminates:", "i gabbles:", "i gabs:", "i gasps:",
-    "i giggles:", "i gossips:", "i gripes:", "i groans:", "i growls:",
-    "i grunts:", "i guesses:", "i guffaws:", "i gushes:", "i hails:",
-    "i hallucinates:", "i harangues:", "i harmonizes:", "i hectors:",
-    "i hints:", "i hisses:", "i hollers:", "i honks:", "i hoots:",
-    "i hosannas:", "i howls:", "i hums:", "i hypothecates:",
-    "i hypothesizes:", "i imagines:", "i implies:", "i implores:",
-    "i imprecates:", "i indicates:", "i infers:",
-    "i informs everyone:",  "i instructs:", "i interjects:", 
-    "i interposes:", "i intimates:", "i intones:", "i introspects:",
-    "i inveighs:", "i jabbers:", "i japes:", "i jests:", "i jibes:",
-    "i jives:", "i jokes:", "i joshes:", "i keens:", "i laments:",
-    "i lauds:", "i laughs:", "i lectures:", "i lies:", "i lilts:",
-    "i lisps:", "i maintains:", "i maledicts:", "i maunders:",
-    "i meows:", "i mewls:", "i mimes:", "i minces:", "i moans:",
-    "i moos:", "i mourns:", "i mouths:", "i mumbles:", "i murmurs:",
-    "i muses:", "i mutters:", "i nags:", "i natters:", "i neighs:",
-    "i notes:", "i nuncupates:", "i objurgates:", "i observes:",
-    "i offers:", "i oinks:", "i opines:", "i orates:", "i orders:",
-    "i panegyrizes:", "i pantomimes:", "i pants:", "i peals:",
-    "i peeps:", "i perorates:", "i persuades:", "i petitions:",
-    "i phonates:", "i pipes up:", "i pitches:", "i pleads:",
-    "i points out:", "i pontificates:", "i postulates:", "i praises:",
-    "i prates:", "i prattles:", "i preaches:", "i prescribes:",
-    "i prevaricates:", "i proclaims:", "i projects:", "i pronounces:",
-    "i proposes:", "i proscribes:", "i quacks:", "i queries:",
-    "i questions:", "i quips:", "i quotes:", "i rages:", "i rambles:",
-    "i rants:", "i raps:", "i rasps:", "i rattles:", "i raves:",
-    "i reacts:", "i recites:", "i recommends:", "i records:",
-    "i reiterates:", "i rejoins:", "i releases:", "i remarks:",
-    "i reminisces:", "i remonstrates:", "i repeats:", "i replies:",
-    "i reports:", "i reprimands:", "i reproaches:", "i reproves:",
-    "i resounds:", "i responds:", "i retorts:", "i reveals:",
-    "i reviles:", "i roars:", "i rumbles:", "i sanctions:",
-    "i satirizes:", "i sauces:", "i scolds:", "i screams:",
-    "i screeches:", "i semaphores:", "i sends:", "i sermonizes:",
-    "i shrieks:", "i sibilates:", "i sighs:", "i signals:",
-    "i signifies:", "i signs:", "i sings:", "i slurs:", "i snaps:",
-    "i snarls:", "i sneezes:", "i snickers:", "i sniggers:",
-    "i snivels:", "i snores:", "i snorts:", "i sobs:",
-    "i soliloquizes:", "i sounds off:", "i sounds out:", "i speaks:",
-    "i spews:", "i spits out:", "i splutters:", "i spoofs:",
-    "i spouts:", "i sputters:", "i squalls:", "i squawks:",
-    "i squeaks:", "i squeals:", "i stammers:", "i states:",
-    "i stresses:", "i stutters:", "i submits:", "i suggests:",
-    "i summarizes:", "i sums up:", "i swears:", "i talks:",
-    "i tattles:", "i teases:", "i telegraphs:", "i testifies:",
-    "i threatens:", "i thunders:", "i titters:", "i tongue-lashes:",
-    "i toots:", "i transcribes:", "i transmits:", "i trills:",
-    "i trumpets:", "i twaddles:", "i tweets:", "i twitters:",
-    "i types:", "i upbraids:", "i urges:", "i utters:", "i ventures:",
-    "i vibrates:", "i vilifies:", "i vituperates:", "i vocalizes:",
-    "i vociferates:", "i voices:", "i waffles:", "i wails:",
-    "i warbles:", "i warns:", "i weeps:", "i wheezes:", "i whimpers:",
-    "i whines:", "i whinnies:", "i whistles:", "i wisecracks:",
-    "i witnesses:", "i woofs:", "i writes:", "i yammers:", "i yawps:",
-    "i yells:", "i yelps:", "i yodels:", "i yowls:", "i zings:",
-};
-
-#define MAX_SPEECH 250
-
-void Speak(how, whom) 
-     char *how, *whom;
-{
-    static FILE *zipfile = NULL;
-    static struct stat zipstat;
-    char zipbuf[MAX_SPEECH + 1];
-    static time_t lastShout = 0;
-    time_t now;
-    char  *p;
-    int c, speechlen;
-    Boolean done;
-               
-    if (strcmp(how, "shout") == 0) {
-       now = time((time_t *) NULL);
-       if (now - lastShout < 1*60) return;
-       lastShout = now;
-       if (appData.zippyUseI) {
-           how = swifties[(unsigned) random() %
-                          (sizeof(swifties)/sizeof(char *))];
-       }
-    }
-
-    if (zipfile == NULL) {
-       zipfile = fopen(appData.zippyLines, "r");
-       if (zipfile == NULL) {
-           DisplayFatalError("Can't open Zippy lines file", errno, 1);
-           return;
-       }
-       fstat(fileno(zipfile), &zipstat);
-    }
-               
-    for (;;) {
-       fseek(zipfile, (unsigned) random() % zipstat.st_size, 0);
-       do {
-         c = getc(zipfile);
-       } while (c != NULLCHAR && c != '^' && c != EOF);
-       if (c == EOF) continue;
-       while ((c = getc(zipfile)) == '\n') ;
-       if (c == EOF) continue;
-       break;
-    }
-    done = FALSE;
-
-    /* Don't use ics_prefix; we need to let FICS expand the alias i -> it,
-       but use the real command "i" on ICC */
-    strcpy(zipbuf, how);
-    strcat(zipbuf, " ");
-    if (whom != NULL) {
-       strcat(zipbuf, whom);
-       strcat(zipbuf, " ");
-    }
-    speechlen = strlen(zipbuf);
-    p = zipbuf + speechlen;
-
-    while (++speechlen < MAX_SPEECH) {
-       if (c == NULLCHAR || c == '^') {
-           *p++ = '\n';
-           *p = '\0';
-           SendToICS(zipbuf);
-           return;
-       } else if (c == '\n') {
-           *p++ = ' ';
-           do {
-               c = getc(zipfile);
-           } while (c == ' ');
-       } else if (c == EOF) {
-           break;
-       } else {
-           *p++ = c;
-           c = getc(zipfile);
-       }
-    }
-    /* Tried to say something too long, or junk at the end of the
-       file.  Try something else. */
-    Speak(how, whom);  /* tail recursion */
-}
-
-int ZippyCalled(str)
-     char *str;
-{
-    return ics_handle[0] != NULLCHAR && StrCaseStr(str, ics_handle) != NULL;
-}
-
-static char opp_name[128][32];
-static int num_opps=0;
-
-extern ColorClass curColor;
-
-static void SetCurColor( ColorClass color )
-{
-    curColor = color;
-}
-
-static void ColorizeEx( ColorClass color, int cont )
-{
-    if( appData.colorize ) {
-        Colorize( color, cont );
-        SetCurColor( color );
-    }
-}
-
-int ZippyControl(buf, i)
-     char *buf;
-     int *i;
-{
-    char *player, *p;
-    char reply[MSG_SIZ];
-
-#if TRIVIA
-#include "trivia.c"
-#endif
-
-    /* Possibly reject Crafty as opponent */
-    if (appData.zippyPlay && appData.zippyNoplayCrafty && forwardMostMove < 4
-       && looking_at(buf, i, "* kibitzes: Hello from Crafty"))
-    {
-        player = StripHighlightAndTitle(star_match[0]);
-       if ((gameMode == IcsPlayingWhite &&
-            StrCaseCmp(player, gameInfo.black) == 0) ||
-           (gameMode == IcsPlayingBlack &&
-            StrCaseCmp(player, gameInfo.white) == 0)) {
-
-         sprintf(reply, "%ssay This computer does not play Crafty clones\n%sabort\n%s+noplay %s\n",
-                 ics_prefix, ics_prefix, ics_prefix, player);
-         SendToICS(reply);
-       }
-       return TRUE;
-    }
-
-    /* If this is a computer, save the name.  Then later, once the */
-    /* game is really started, we will send the "computer" notice to */
-    /* the engine.  */ 
-    if (appData.zippyPlay &&
-       looking_at(buf, i, "* is in the computer list")) {
-       int i;
-       for (i=0;i<num_opps;i++)
-         if (!strcmp(opp_name[i],star_match[0])) break;
-       if (i >= num_opps) strcpy(opp_name[num_opps++],star_match[0]);
-    }
-    if (appData.zippyPlay && looking_at(buf, i, "* * is a computer *")) {
-       int i;
-       for (i=0;i<num_opps;i++)
-         if (!strcmp(opp_name[i],star_match[1])) break;
-       if (i >= num_opps) strcpy(opp_name[num_opps++],star_match[1]);
-    }
-
-    /* Tells and says */
-    if (appData.zippyPlay && 
-       (looking_at(buf, i, "* offers to be your bughouse partner") ||
-        looking_at(buf, i, "* tells you: [automatic message] I chose you"))) {
-       player = StripHighlightAndTitle(star_match[0]);
-       if (appData.zippyBughouse > 1 && first.initDone) {
-           sprintf(reply, "%spartner %s\n", ics_prefix, player);
-           SendToICS(reply);
-           if (strcmp(zippyPartner, player) != 0) {
-               strcpy(zippyPartner, player);
-               SendToProgram(reply + strlen(ics_prefix), &first);
-           }
-       } else if (appData.zippyBughouse > 0) {
-           sprintf(reply, "%sdecline %s\n", ics_prefix, player);
-           SendToICS(reply);
-       } else {
-           sprintf(reply, "%stell %s This computer cannot play bughouse\n",
-                   ics_prefix, player);
-           SendToICS(reply);
-       }
-       return TRUE;
-    }
-
-    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&
-       looking_at(buf, i, "* agrees to be your partner")) {
-       player = StripHighlightAndTitle(star_match[0]);
-       sprintf(reply, "partner %s\n", player);
-       if (strcmp(zippyPartner, player) != 0) {
-           strcpy(zippyPartner, player);
-           SendToProgram(reply, &first);
-       }
-       return TRUE;
-    }
-
-    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&
-       (looking_at(buf, i, "are no longer *'s partner") ||
-        looking_at(buf, i,
-                   "* tells you: [automatic message] I'm no longer your"))) {
-       player = StripHighlightAndTitle(star_match[0]);
-       if (strcmp(zippyPartner, player) == 0) {
-           zippyPartner[0] = NULLCHAR;
-           SendToProgram("partner\n", &first);
-       }
-       return TRUE;
-    }
-
-    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&
-       (looking_at(buf, i, "no longer have a bughouse partner") ||
-        looking_at(buf, i, "partner has disconnected") ||
-        looking_at(buf, i, "partner has just chosen a new partner"))) {
-      zippyPartner[0] = NULLCHAR;
-      SendToProgram("partner\n", &first);
-      return TRUE;
-    }
-
-    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&
-       looking_at(buf, i, "* (your partner) tells you: *")) {
-       /* This pattern works on FICS but not ICC */
-       player = StripHighlightAndTitle(star_match[0]);
-       if (strcmp(zippyPartner, player) != 0) {
-           strcpy(zippyPartner, player);
-           sprintf(reply, "partner %s\n", player);
-           SendToProgram(reply, &first);
-       }
-       sprintf(reply, "ptell %s\n", star_match[1]);
-       SendToProgram(reply, &first);
-       return TRUE;
-    }
-
-    if (looking_at(buf, i, "* tells you: *") ||
-       looking_at(buf, i, "* says: *"))
-    {
-       player = StripHighlightAndTitle(star_match[0]);
-       if (appData.zippyPassword[0] != NULLCHAR &&
-           strncmp(star_match[1], appData.zippyPassword,
-                   strlen(appData.zippyPassword)) == 0) {
-           p = star_match[1] + strlen(appData.zippyPassword);
-           while (*p == ' ') p++;
-           SendToICS(p);
-           SendToICS("\n");
-       } else if (appData.zippyPassword2[0] != NULLCHAR && first.initDone &&
-           strncmp(star_match[1], appData.zippyPassword2,
-                   strlen(appData.zippyPassword2)) == 0) {
-           p = star_match[1] + strlen(appData.zippyPassword2);
-           while (*p == ' ') p++;
-           SendToProgram(p, &first);
-           SendToProgram("\n", &first);
-       } else if (appData.zippyWrongPassword[0] != NULLCHAR &&
-           strncmp(star_match[1], appData.zippyWrongPassword,
-                   strlen(appData.zippyWrongPassword)) == 0) {
-           p = star_match[1] + strlen(appData.zippyWrongPassword);
-           while (*p == ' ') p++;
-           sprintf(reply, "wrong %s\n", player);
-           SendToICS(reply);
-       } else if (appData.zippyBughouse && first.initDone &&
-                  strcmp(player, zippyPartner) == 0) {
-           SendToProgram("ptell ", &first);
-           SendToProgram(star_match[1], &first);
-           SendToProgram("\n", &first);
-       } else if (strncmp(star_match[1], HI, 6) == 0) {
-           extern char* programVersion;
-           sprintf(reply, "%stell %s %s\n",
-                   ics_prefix, player, programVersion);
-           SendToICS(reply);
-       } else if (strncmp(star_match[1], "W0W!! ", 6) == 0) {
-           extern char* programVersion;
-           sprintf(reply, "%stell %s %s\n", ics_prefix,
-                   player, programVersion);
-           SendToICS(reply);
-       } else if (appData.zippyTalk && (((unsigned) random() % 10) < 9)) {
-           if (strcmp(player, ics_handle) != 0) {
-               Speak("tell", player);
-           }
-       }
-
-        ColorizeEx( ColorTell, FALSE );
-
-       return TRUE;
-    }
-
-    if( appData.colorize && looking_at(buf, i, "* (*) seeking") ) {
-       ColorizeEx(ColorSeek, FALSE);
-        return FALSE;
-    }
-
-    if (looking_at(buf, i, "* spoofs you:")) {
-        player = StripHighlightAndTitle(star_match[0]);
-        sprintf(reply, "spoofedby %s\n", player);
-        SendToICS(reply);
-    }
-
-    return FALSE;
-}
-
-int ZippyConverse(buf, i)
-     char *buf;
-     int *i;
-{
-    static char lastgreet[MSG_SIZ];
-    char reply[MSG_SIZ];
-    int oldi;
-
-    /* Shouts and emotes */
-    if (looking_at(buf, i, "--> * *") ||
-       looking_at(buf, i, "* shouts: *"))
-    {
-      if (appData.zippyTalk) {
-       char *player = StripHighlightAndTitle(star_match[0]);
-       if (strcmp(player, ics_handle) == 0) {
-           return TRUE;
-       } else if (appData.zippyPinhead[0] != NULLCHAR &&
-                  StrCaseStr(star_match[1], appData.zippyPinhead) != NULL) {
-           sprintf(reply, "insult %s\n", player);
-           SendToICS(reply);
-       } else if (ZippyCalled(star_match[1])) {
-           Speak("shout", NULL);
-       }
-      }
-
-      ColorizeEx(ColorShout, FALSE);
-
-      return TRUE;
-    }
-
-    if (looking_at(buf, i, "* kibitzes: *")) {
-      if (appData.zippyTalk && ((unsigned) random() % 10) < 9) {
-       char *player = StripHighlightAndTitle(star_match[0]);
-       if (strcmp(player, ics_handle) != 0) {
-           Speak("kibitz", NULL);
-       }
-      }
-
-      ColorizeEx(ColorKibitz, FALSE);
-
-      return TRUE;
-    }
-
-    if (looking_at(buf, i, "* whispers: *")) {
-      if (appData.zippyTalk && ((unsigned) random() % 10) < 9) {
-       char *player = StripHighlightAndTitle(star_match[0]);
-       if (strcmp(player, ics_handle) != 0) {
-           Speak("whisper", NULL);
-       }
-      }
-
-      ColorizeEx(ColorKibitz, FALSE);
-
-      return TRUE;
-    }
-
-    /* Messages */
-    if ((looking_at(buf, i, ". * (*:*): *") && isdigit(star_match[1][0])) ||
-        looking_at(buf, i, ". * at *:*: *")) {
-      if (appData.zippyTalk) {
-       FILE *f;
-       char *player = StripHighlightAndTitle(star_match[0]);
-
-       if (strcmp(player, ics_handle) != 0) {
-           if (((unsigned) random() % 10) < 9)
-             Speak("message", player);
-           f = fopen("zippy.messagelog", "a");
-           fprintf(f, "%s (%s:%s): %s\n", player,
-                   star_match[1], star_match[2], star_match[3]);
-           fclose(f);
-       }
-      }
-      return TRUE;
-    }
-
-    /* Channel tells */
-    oldi = *i;
-    if (looking_at(buf, i, "*(*: *")) {
-       char *player;
-       char *channel;
-       if (star_match[0][0] == NULLCHAR  ||
-           strchr(star_match[0], ' ') ||
-           strchr(star_match[1], ' ')) {
-           /* Oops, did not want to match this; probably a message */
-           *i = oldi;
-           return FALSE;
-       }
-       if (appData.zippyTalk) {
-         player = StripHighlightAndTitle(star_match[0]);
-         channel = strrchr(star_match[1], '(');
-         if (channel == NULL) {
-           channel = star_match[1];
-         } else {
-           channel++;
-         }
-         channel[strlen(channel)-1] = NULLCHAR;
-#if 0
-         /* Always tell to the channel (probability 90%) */
-         if (strcmp(player, ics_handle) != 0 &&
-             ((unsigned) random() % 10) < 9) {
-           Speak("tell", channel);
-         }
-#else
-         /* Tell to the channel only if someone mentions our name */
-         if (ZippyCalled(star_match[2])) {
-           Speak("tell", channel);
-         }
-#endif
-
-          ColorizeEx( atoi(channel) == 1 ? ColorChannel1 : ColorChannel, FALSE );
-       }
-       return TRUE;
-    }
-
-    if (!appData.zippyTalk) return FALSE;
-
-    if ((looking_at(buf, i, "You have * message") &&
-        atoi(star_match[0]) != 0) ||
-       looking_at(buf, i, "* has left a message for you") ||
-       looking_at(buf, i, "* just sent you a message")) {
-        sprintf(reply, "%smessages\n%sclearmessages *\n",
-               ics_prefix, ics_prefix);
-       SendToICS(reply);
-       return TRUE;
-    }
-
-    if (looking_at(buf, i, "Notification: * has arrived")) {
-       if (((unsigned) random() % 3) == 0) {
-           char *player = StripHighlightAndTitle(star_match[0]);
-           strcpy(lastgreet, player);
-           sprintf(reply, "greet %s\n", player);
-           SendToICS(reply);
-           Speak("tell", player);
-       }
-    }  
-
-    if (looking_at(buf, i, "Notification: * has departed")) {
-       if (((unsigned) random() % 3) == 0) {
-           char *player = StripHighlightAndTitle(star_match[0]);
-           sprintf(reply, "farewell %s\n", player);
-           SendToICS(reply);
-       }
-    }  
-
-    if (looking_at(buf, i, "Not sent -- * is censoring you")) {
-       char *player = StripHighlightAndTitle(star_match[0]);
-       if (strcmp(player, lastgreet) == 0) {
-           sprintf(reply, "%s-notify %s\n", ics_prefix, player);
-           SendToICS(reply);
-       }
-    }  
-
-    if (looking_at(buf, i, "command is currently turned off")) {
-       appData.zippyUseI = 0;
-    }
-
-    return FALSE;
-}
-
-void ZippyGameStart(white, black)
-     char *white, *black;
-{
-    if (!first.initDone) {
-      /* Game is starting prematurely.  We can't deal with this */
-      SendToICS(ics_prefix);
-      SendToICS("abort\n");
-      SendToICS(ics_prefix);
-      SendToICS("say Sorry, the chess program is not initialized yet.\n");
-      return;
-    }
-
-    if (appData.zippyGameStart[0] != NULLCHAR) {
-      SendToICS(appData.zippyGameStart);
-      SendToICS("\n");
-    }
-}
-
-void ZippyGameEnd(result, resultDetails)
-     ChessMove result;
-     char *resultDetails;
-{
-    if (appData.zippyAcceptOnly[0] == NULLCHAR &&
-       appData.zippyGameEnd[0] != NULLCHAR) {
-      SendToICS(appData.zippyGameEnd);
-      SendToICS("\n");
-    }
-    zippyLastGameEnd = time(0);
-}
-
-/*
- * Routines to implement Zippy playing chess
- */
-
-void ZippyHandleChallenge(srated, swild, sbase, sincrement, opponent)
-     char *srated, *swild, *sbase, *sincrement, *opponent;
-{
-    char buf[MSG_SIZ];
-    int base, increment;
-    char rated;
-    VariantClass variant;
-    char *varname;
-
-    rated = srated[0];
-    variant = StringToVariant(swild);
-    varname = VariantName(variant);
-    base = atoi(sbase);
-    increment = atoi(sincrement);
-
-    /* If desired, you can insert more code here to decline matches
-       based on rated, variant, base, and increment, but it is
-       easier to use the ICS formula feature instead. */
-
-    if (variant == VariantLoadable) {
-        sprintf(buf,
-        "%stell %s This computer can't play wild type %s\n%sdecline %s\n",
-               ics_prefix, opponent, swild, ics_prefix, opponent);
-       SendToICS(buf);
-       return;
-    }
-    if (StrStr(appData.zippyVariants, varname) == NULL) {
-        sprintf(buf,
-        "%stell %s This computer can't play %s [%s], only %s\n%sdecline %s\n",
-               ics_prefix, opponent, swild, varname, appData.zippyVariants,
-               ics_prefix, opponent);
-       SendToICS(buf);
-       return;
-    }
-
-    /* Are we blocking match requests from all but one person? */
-    if (appData.zippyAcceptOnly[0] != NULLCHAR &&
-       StrCaseCmp(opponent, appData.zippyAcceptOnly)) {
-        /* Yes, and this isn't him.  Ignore challenge. */
-       return;
-    }
-    
-    /* Too many consecutive games with same opponent?  If so, make him
-       wait until someone else has played or a timeout has elapsed. */
-    if (appData.zippyMaxGames &&
-       strcmp(opponent, zippyLastOpp) == 0 &&
-       zippyConsecGames >= appData.zippyMaxGames &&
-       difftime(time(0), zippyLastGameEnd) < appData.zippyReplayTimeout) {
-      sprintf(buf, "%stell %s Sorry, you have just played %d consecutive games against %s.  To give others a chance, please wait %d seconds or until someone else has played.\n%sdecline %s\n",
-             ics_prefix, opponent, zippyConsecGames, ics_handle,
-             appData.zippyReplayTimeout, ics_prefix, opponent);
-      SendToICS(buf);
-      return;
-    }
-
-    /* Engine not yet initialized or still thinking about last game? */
-    if (!first.initDone || first.lastPing != first.lastPong) {
-      sprintf(buf, "%stell %s I'm not quite ready for a new game yet; try again soon.\n%sdecline %s\n",
-             ics_prefix, opponent, ics_prefix, opponent);
-      SendToICS(buf);
-      return;
-    }
-
-    sprintf(buf, "%saccept %s\n", ics_prefix, opponent);
-    SendToICS(buf);
-    if (appData.zippyTalk) {
-      Speak("tell", opponent);
-    }
-}
-
-
-/* Accept matches */
-int ZippyMatch(buf, i)
-     char *buf;
-     int *i;
-{
-    if (looking_at(buf, i, "* * match * * requested with * (*)")) {
-
-       ZippyHandleChallenge(star_match[0], star_match[1],
-                            star_match[2], star_match[3],
-                            StripHighlightAndTitle(star_match[4]));
-       return TRUE;
-    }
-
-    /* Old FICS 0-increment form */
-    if (looking_at(buf, i, "* * match * requested with * (*)")) {
-
-       ZippyHandleChallenge(star_match[0], star_match[1],
-                            star_match[2], "0",
-                            StripHighlightAndTitle(star_match[3]));
-       return TRUE;
-    }
-
-    if (looking_at(buf, i,
-                  "* has made an alternate proposal of * * match * *.")) {
-
-       ZippyHandleChallenge(star_match[1], star_match[2],
-                            star_match[3], star_match[4],
-                            StripHighlightAndTitle(star_match[0]));
-       return TRUE;
-    }
-
-    /* FICS wild/nonstandard forms */
-    if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * Loaded from *")) {
-       /* note: star_match[2] can include "[white] " or "[black] "
-          before our own name. */
-       ZippyHandleChallenge(star_match[4], star_match[8],
-                            star_match[6], star_match[7],
-                            StripHighlightAndTitle(star_match[0]));
-       return TRUE;
-    }
-
-    if (looking_at(buf, i,
-                  "Challenge: * (*) *(*) * * * * : * * Loaded from *")) {
-       /* note: star_match[2] can include "[white] " or "[black] "
-          before our own name. */
-       ZippyHandleChallenge(star_match[4], star_match[10],
-                            star_match[8], star_match[9],
-                            StripHighlightAndTitle(star_match[0]));
-       return TRUE;
-    }
-
-    /* Regular forms */
-    if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * : * *") |
-       looking_at(buf, i, "Challenge: * (*) *(*) * * * * * *")) {
-       /* note: star_match[2] can include "[white] " or "[black] "
-          before our own name. */
-       ZippyHandleChallenge(star_match[4], star_match[5],
-                            star_match[8], star_match[9],
-                            StripHighlightAndTitle(star_match[0]));
-       return TRUE;
-    }
-
-    if (looking_at(buf, i, "Challenge: * (*) *(*) * * * *")) {
-       /* note: star_match[2] can include "[white] " or "[black] "
-          before our own name. */
-       ZippyHandleChallenge(star_match[4], star_match[5],
-                            star_match[6], star_match[7],
-                            StripHighlightAndTitle(star_match[0]));
-       return TRUE;
-    }
-
-    if (looking_at(buf, i, "offers you a draw")) {
-        if (first.sendDrawOffers && first.initDone) {
-           SendToProgram("draw\n", &first);
-       }
-       return TRUE;
-    }
-
-    if (looking_at(buf, i, "requests that the game be aborted") ||
-        looking_at(buf, i, "would like to abort")) {
-       if (appData.zippyAbort ||
-           (gameMode == IcsPlayingWhite && whiteTimeRemaining < 0) ||
-           (gameMode == IcsPlayingBlack && blackTimeRemaining < 0)) {
-           SendToICS(ics_prefix);
-           SendToICS("abort\n");
-       } else {
-           SendToICS(ics_prefix);
-           if (appData.zippyTalk)
-             SendToICS("say Whoa no!  I am having FUN!!\n");
-           else
-             SendToICS("say Sorry, this computer doesn't accept aborts.\n");
-       }
-       return TRUE;
-    }
-
-    if (looking_at(buf, i, "requests adjournment") ||
-       looking_at(buf, i, "would like to adjourn")) {
-      if (appData.zippyAdjourn) {
-       SendToICS(ics_prefix);
-       SendToICS("adjourn\n");
-      } else {
-       SendToICS(ics_prefix);
-       if (appData.zippyTalk)
-         SendToICS("say Whoa no!  I am having FUN playing NOW!!\n");
-       else
-         SendToICS("say Sorry, this computer doesn't accept adjourns.\n");
-      }
-      return TRUE;
-    }
-
-    return FALSE;
-}
-
-/* Initialize chess program with data from the first board 
- * of a new or resumed game.
- */
-void ZippyFirstBoard(moveNum, basetime, increment)
-     int moveNum, basetime, increment;
-{
-    char buf[MSG_SIZ];
-    int w, b;
-    char *opp = (gameMode==IcsPlayingWhite ? gameInfo.black : gameInfo.white);
-    Boolean sentPos = FALSE;
-
-    if (!first.initDone) {
-      /* Game is starting prematurely.  We can't deal with this */
-      SendToICS(ics_prefix);
-      SendToICS("abort\n");
-      SendToICS(ics_prefix);
-      SendToICS("say Sorry, the chess program is not initialized yet.\n");
-      return;
-    }
-
-    /* Send the variant command if needed */
-    if (gameInfo.variant != VariantNormal) {
-      sprintf(buf, "variant %s\n", VariantName(gameInfo.variant));
-      SendToProgram(buf, &first);
-    }
-
-    if ((startedFromSetupPosition && moveNum == 0) ||
-       (!appData.getMoveList && moveNum > 0)) {
-      SendToProgram("force\n", &first);
-      SendBoard(&first, moveNum);
-      sentPos = TRUE;
-    }
-
-    sprintf(buf, "level 0 %d %d\n", basetime, increment);
-    SendToProgram(buf, &first);
-
-    /* Count consecutive games from one opponent */
-    if (strcmp(opp, zippyLastOpp) == 0) {
-      zippyConsecGames++;
-    } else {
-      zippyConsecGames = 1;
-      strcpy(zippyLastOpp, opp);
-    }
-
-    /* Send the "computer" command if the opponent is in the list
-       we've been gathering. */
-    for (w=0; w<num_opps; w++) {
-       if (!strcmp(opp_name[w], opp)) {
-           SendToProgram(first.computerString, &first);
-           break;
-       }
-    }
-
-    /* Ratings might be < 0 which means "we haven't seen a ratings
-       message from ICS." Send 0 in that case */
-    w = (gameInfo.whiteRating >= 0) ? gameInfo.whiteRating : 0;
-    b = (gameInfo.blackRating >= 0) ? gameInfo.blackRating : 0;
-    
-    firstMove = FALSE;
-    if (gameMode == IcsPlayingWhite) {
-        if (first.sendName) {
-         sprintf(buf, "name %s\n", gameInfo.black);
-         SendToProgram(buf, &first);
-       }
-       strcpy(ics_handle, gameInfo.white);
-       sprintf(buf, "rating %d %d\n", w, b);
-       SendToProgram(buf, &first);
-       if (sentPos) {
-           /* Position sent above, engine is in force mode */
-           if (WhiteOnMove(moveNum)) {
-             /* Engine is on move now */
-             if (first.sendTime) {
-               if (first.useColors) {
-                 SendToProgram("black\n", &first); /*gnu kludge*/
-                 SendTimeRemaining(&first, TRUE);
-                 SendToProgram("white\n", &first);
-               } else {
-                 SendTimeRemaining(&first, TRUE);
-               }
-             }
-             SendToProgram("go\n", &first);
-           } else {
-               /* Engine's opponent is on move now */
-               if (first.usePlayother) {
-                 if (first.sendTime) {
-                   SendTimeRemaining(&first, TRUE);
-                 }
-                 SendToProgram("playother\n", &first);
-               } else {
-                 /* Need to send a "go" after opponent moves */
-                 firstMove = TRUE;
-               }
-           }
-       } else {
-           /* Position not sent above, move list might be sent later */
-           if (moveNum == 0) {
-               /* No move list coming; at start of game */
-             if (first.sendTime) {
-               if (first.useColors) {
-                 SendToProgram("black\n", &first); /*gnu kludge*/
-                 SendTimeRemaining(&first, TRUE);
-                 SendToProgram("white\n", &first);
-               } else {
-                 SendTimeRemaining(&first, TRUE);
-               }
-             }
-             SendToProgram("go\n", &first);
-           }
-       }
-    } else if (gameMode == IcsPlayingBlack) {
-        if (first.sendName) {
-         sprintf(buf, "name %s\n", gameInfo.white);
-         SendToProgram(buf, &first);
-       }
-       strcpy(ics_handle, gameInfo.black);
-       sprintf(buf, "rating %d %d\n", b, w);
-       SendToProgram(buf, &first);
-       if (sentPos) {
-           /* Position sent above, engine is in force mode */
-           if (!WhiteOnMove(moveNum)) {
-               /* Engine is on move now */
-             if (first.sendTime) {
-               if (first.useColors) {
-                 SendToProgram("white\n", &first); /*gnu kludge*/
-                 SendTimeRemaining(&first, FALSE);
-                 SendToProgram("black\n", &first);
-               } else {
-                 SendTimeRemaining(&first, FALSE);
-               }
-             }
-             SendToProgram("go\n", &first);
-           } else {
-               /* Engine's opponent is on move now */
-               if (first.usePlayother) {
-                 if (first.sendTime) {
-                   SendTimeRemaining(&first, FALSE);
-                 }
-                 SendToProgram("playother\n", &first);
-               } else {
-                 /* Need to send a "go" after opponent moves */
-                 firstMove = TRUE;
-               }
-           }
-       } else {
-           /* Position not sent above, move list might be sent later */
-           /* Nothing needs to be done here */
-       }       
-    }
-}
-
-
-void
-ZippyHoldings(white_holding, black_holding, new_piece)
-     char *white_holding, *black_holding, *new_piece;
-{
-    char buf[MSG_SIZ];
-    if (gameMode != IcsPlayingBlack && gameMode != IcsPlayingWhite) return;
-    sprintf(buf, "holding [%s] [%s] %s\n",
-           white_holding, black_holding, new_piece);
-    SendToProgram(buf, &first);
-}
+/*\r
+ * zippy.c -- Implements Zippy the Pinhead chess player on ICS in XBoard\r
+ * $Id: zippy.c,v 2.2 2003/11/25 05:25:20 mann Exp $\r
+ *\r
+ * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
+ * Enhancements Copyright 1992-2001 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
+#include "config.h"\r
+\r
+#include <stdio.h>\r
+#include <errno.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <ctype.h>\r
+\r
+#if STDC_HEADERS\r
+# include <stdlib.h>\r
+# include <string.h>\r
+#else /* not STDC_HEADERS */\r
+extern char *getenv();\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
+#if TIME_WITH_SYS_TIME\r
+# include <sys/time.h>\r
+# include <time.h>\r
+#else\r
+# if HAVE_SYS_TIME_H\r
+#  include <sys/time.h>\r
+# else\r
+#  include <time.h>\r
+# endif\r
+#endif\r
+#define HI "hlelo "\r
+\r
+#if HAVE_UNISTD_H\r
+# include <unistd.h>\r
+#endif\r
+\r
+#include "common.h"\r
+#include "zippy.h"\r
+#include "frontend.h"\r
+#include "backend.h"\r
+#include "backendz.h"\r
+\r
+static char zippyPartner[MSG_SIZ];\r
+static char zippyLastOpp[MSG_SIZ];\r
+static int zippyConsecGames;\r
+static time_t zippyLastGameEnd;\r
+\r
+void ZippyInit()\r
+{\r
+    char *p;\r
+\r
+    /* Get name of Zippy lines file */\r
+    p = getenv("ZIPPYLINES");\r
+    if (p != NULL) {\r
+      appData.zippyLines = p;\r
+    }\r
+\r
+    /* Get word that Zippy thinks is insulting */\r
+    p = getenv("ZIPPYPINHEAD");\r
+    if (p != NULL) {\r
+      appData.zippyPinhead = p;\r
+    }\r
+\r
+    /* What password is used for remote control? */\r
+    p = getenv("ZIPPYPASSWORD");\r
+    if (p != NULL) {\r
+      appData.zippyPassword = p;\r
+    }\r
+\r
+    /* What password is used for remote commands to gnuchess? */\r
+    p = getenv("ZIPPYPASSWORD2");\r
+    if (p != NULL) {\r
+      appData.zippyPassword2 = p;\r
+    }\r
+\r
+    /* Joke feature for people who try an old password */\r
+    p = getenv("ZIPPYWRONGPASSWORD");\r
+    if (p != NULL) {\r
+      appData.zippyWrongPassword = p;\r
+    }\r
+\r
+    /* While testing, I want to accept challenges from only one person\r
+       (namely, my "anonymous" account), so I set an environment\r
+       variable ZIPPYACCEPTONLY. */\r
+    p = getenv("ZIPPYACCEPTONLY");\r
+    if ( p != NULL ) {\r
+      appData.zippyAcceptOnly = p;\r
+    }\r
+    \r
+    /* Should Zippy use "i" command? */\r
+    /* Defaults to 1=true */\r
+    p = getenv("ZIPPYUSEI");\r
+    if (p != NULL) {\r
+      appData.zippyUseI = atoi(p);\r
+    }\r
+\r
+    /* How does Zippy handle bughouse partnering? */\r
+    /* 0=say we can't play, 1=manual partnering, 2=auto partnering */\r
+    p = getenv("ZIPPYBUGHOUSE");\r
+    if (p != NULL) {\r
+      appData.zippyBughouse = atoi(p);\r
+    }\r
+\r
+    /* Does Zippy abort games with Crafty? */\r
+    /* Defaults to 0=false */\r
+    p = getenv("ZIPPYNOPLAYCRAFTY");\r
+    if (p != NULL) {\r
+      appData.zippyNoplayCrafty = atoi(p);\r
+    }\r
+\r
+    /* What ICS command does Zippy send at game end?  Default: "gameend". */\r
+    p = getenv("ZIPPYGAMEEND");\r
+    if (p != NULL) {\r
+      appData.zippyGameEnd = p;\r
+    }\r
+\r
+    /* What ICS command does Zippy send at game start?  Default: none. */\r
+    p = getenv("ZIPPYGAMESTART");\r
+    if (p != NULL) {\r
+      appData.zippyGameStart = p;\r
+    }\r
+\r
+    /* Should Zippy accept adjourns? */\r
+    /* Defaults to 0=false */\r
+    p = getenv("ZIPPYADJOURN");\r
+    if (p != NULL) {\r
+      appData.zippyAdjourn = atoi(p);\r
+    }\r
+\r
+    /* Should Zippy accept aborts? */\r
+    /* Defaults to 0=false */\r
+    p = getenv("ZIPPYABORT");\r
+    if (p != NULL) {\r
+      appData.zippyAbort = atoi(p);\r
+    }\r
+\r
+    /* Should Zippy play chess variants (besides bughouse)? */\r
+    p = getenv("ZIPPYVARIANTS");\r
+    if (p != NULL) {\r
+      appData.zippyVariants = p;\r
+    }\r
+    strcpy(first.variants, appData.zippyVariants);\r
+\r
+    srandom(time(NULL));\r
+}\r
+\r
+/*\r
+ * Routines to implement Zippy talking\r
+ */\r
+\r
+\r
+char *swifties[] = { \r
+    "i acclaims:", "i admonishes:", "i advertises:", "i advises:",\r
+    "i advocates:", "i affirms:", "i alleges:", "i anathematizes:",\r
+    "i animadverts:", "i announces:", "i apostrophizes:",\r
+    "i appeals:", "i applauds:", "i approves:", "i argues:",\r
+    "i articulates:", "i asserts:", "i asseverates:", "i attests:",\r
+    "i avers:", "i avows:", "i baas:", "i babbles:", "i banters:",\r
+    "i barks:", "i bawls:", "i bays:", "i begs:", "i belches:",\r
+    "i bellows:", "i belts out:", "i berates:", "i beshrews:",\r
+    "i blabbers:", "i blabs:", "i blares:", "i blasphemes:",\r
+    "i blasts:", "i blathers:", "i bleats:", "i blithers:",\r
+    "i blubbers:", "i blurts out:", "i blusters:", "i boasts:",\r
+    "i brags:", "i brays:", "i broadcasts:", "i burbles:",\r
+    "i buzzes:", "i cachinnates:", "i cackles:", "i caterwauls:",\r
+    "i calumniates:", "i caws:", "i censures:", "i chants:",\r
+    "i chatters:", "i cheeps:", "i cheers:", "i chides:", "i chins:",\r
+    "i chirps:", "i chortles:", "i chuckles:", "i claims:",\r
+    "i clamors:", "i clucks:", "i commands:", "i commends:",\r
+    "i comments:", "i commiserates:", "i communicates:",\r
+    "i complains:", "i concludes:", "i confabulates:", "i confesses:",\r
+    "i coos:", "i coughs:", "i counsels:", "i cries:", "i croaks:",\r
+    "i crows:", "i curses:", "i daydreams:", "i debates:",\r
+    "i declaims:", "i declares:", "i delivers:", "i denounces:",\r
+    "i deposes:", "i directs:", "i discloses:", "i disparages:",\r
+    "i discourses:", "i divulges:", "i documents:", "i drawls:",\r
+    "i dreams:", "i drivels:", "i drones:", "i effuses:",\r
+    /*"i ejaculates:",*/ "i elucidates:", "i emotes:", "i endorses:",\r
+    "i enthuses:", "i entreats:", "i enunciates:", "i eulogizes:",\r
+    "i exclaims:", "i execrates:", "i exhorts:", "i expatiates:",\r
+    "i explains:", "i explicates:", "i explodes:", "i exposes:",\r
+    "i exposits:", "i expounds:", "i expresses:", "i extols:",\r
+    "i exults:", "i fantasizes:", "i fibs:", "i filibusters:",\r
+    "i flatters:", "i flutes:", "i fools:", "i free-associates:",\r
+    "i fulminates:", "i gabbles:", "i gabs:", "i gasps:",\r
+    "i giggles:", "i gossips:", "i gripes:", "i groans:", "i growls:",\r
+    "i grunts:", "i guesses:", "i guffaws:", "i gushes:", "i hails:",\r
+    "i hallucinates:", "i harangues:", "i harmonizes:", "i hectors:",\r
+    "i hints:", "i hisses:", "i hollers:", "i honks:", "i hoots:",\r
+    "i hosannas:", "i howls:", "i hums:", "i hypothecates:",\r
+    "i hypothesizes:", "i imagines:", "i implies:", "i implores:",\r
+    "i imprecates:", "i indicates:", "i infers:",\r
+    "i informs everyone:",  "i instructs:", "i interjects:", \r
+    "i interposes:", "i intimates:", "i intones:", "i introspects:",\r
+    "i inveighs:", "i jabbers:", "i japes:", "i jests:", "i jibes:",\r
+    "i jives:", "i jokes:", "i joshes:", "i keens:", "i laments:",\r
+    "i lauds:", "i laughs:", "i lectures:", "i lies:", "i lilts:",\r
+    "i lisps:", "i maintains:", "i maledicts:", "i maunders:",\r
+    "i meows:", "i mewls:", "i mimes:", "i minces:", "i moans:",\r
+    "i moos:", "i mourns:", "i mouths:", "i mumbles:", "i murmurs:",\r
+    "i muses:", "i mutters:", "i nags:", "i natters:", "i neighs:",\r
+    "i notes:", "i nuncupates:", "i objurgates:", "i observes:",\r
+    "i offers:", "i oinks:", "i opines:", "i orates:", "i orders:",\r
+    "i panegyrizes:", "i pantomimes:", "i pants:", "i peals:",\r
+    "i peeps:", "i perorates:", "i persuades:", "i petitions:",\r
+    "i phonates:", "i pipes up:", "i pitches:", "i pleads:",\r
+    "i points out:", "i pontificates:", "i postulates:", "i praises:",\r
+    "i prates:", "i prattles:", "i preaches:", "i prescribes:",\r
+    "i prevaricates:", "i proclaims:", "i projects:", "i pronounces:",\r
+    "i proposes:", "i proscribes:", "i quacks:", "i queries:",\r
+    "i questions:", "i quips:", "i quotes:", "i rages:", "i rambles:",\r
+    "i rants:", "i raps:", "i rasps:", "i rattles:", "i raves:",\r
+    "i reacts:", "i recites:", "i recommends:", "i records:",\r
+    "i reiterates:", "i rejoins:", "i releases:", "i remarks:",\r
+    "i reminisces:", "i remonstrates:", "i repeats:", "i replies:",\r
+    "i reports:", "i reprimands:", "i reproaches:", "i reproves:",\r
+    "i resounds:", "i responds:", "i retorts:", "i reveals:",\r
+    "i reviles:", "i roars:", "i rumbles:", "i sanctions:",\r
+    "i satirizes:", "i sauces:", "i scolds:", "i screams:",\r
+    "i screeches:", "i semaphores:", "i sends:", "i sermonizes:",\r
+    "i shrieks:", "i sibilates:", "i sighs:", "i signals:",\r
+    "i signifies:", "i signs:", "i sings:", "i slurs:", "i snaps:",\r
+    "i snarls:", "i sneezes:", "i snickers:", "i sniggers:",\r
+    "i snivels:", "i snores:", "i snorts:", "i sobs:",\r
+    "i soliloquizes:", "i sounds off:", "i sounds out:", "i speaks:",\r
+    "i spews:", "i spits out:", "i splutters:", "i spoofs:",\r
+    "i spouts:", "i sputters:", "i squalls:", "i squawks:",\r
+    "i squeaks:", "i squeals:", "i stammers:", "i states:",\r
+    "i stresses:", "i stutters:", "i submits:", "i suggests:",\r
+    "i summarizes:", "i sums up:", "i swears:", "i talks:",\r
+    "i tattles:", "i teases:", "i telegraphs:", "i testifies:",\r
+    "i threatens:", "i thunders:", "i titters:", "i tongue-lashes:",\r
+    "i toots:", "i transcribes:", "i transmits:", "i trills:",\r
+    "i trumpets:", "i twaddles:", "i tweets:", "i twitters:",\r
+    "i types:", "i upbraids:", "i urges:", "i utters:", "i ventures:",\r
+    "i vibrates:", "i vilifies:", "i vituperates:", "i vocalizes:",\r
+    "i vociferates:", "i voices:", "i waffles:", "i wails:",\r
+    "i warbles:", "i warns:", "i weeps:", "i wheezes:", "i whimpers:",\r
+    "i whines:", "i whinnies:", "i whistles:", "i wisecracks:",\r
+    "i witnesses:", "i woofs:", "i writes:", "i yammers:", "i yawps:",\r
+    "i yells:", "i yelps:", "i yodels:", "i yowls:", "i zings:",\r
+};\r
+\r
+#define MAX_SPEECH 250\r
+\r
+void Speak(how, whom) \r
+     char *how, *whom;\r
+{\r
+    static FILE *zipfile = NULL;\r
+    static struct stat zipstat;\r
+    char zipbuf[MAX_SPEECH + 1];\r
+    static time_t lastShout = 0;\r
+    time_t now;\r
+    char  *p;\r
+    int c, speechlen;\r
+    Boolean done;\r
+               \r
+    if (strcmp(how, "shout") == 0) {\r
+       now = time((time_t *) NULL);\r
+       if (now - lastShout < 1*60) return;\r
+       lastShout = now;\r
+       if (appData.zippyUseI) {\r
+           how = swifties[(unsigned) random() %\r
+                          (sizeof(swifties)/sizeof(char *))];\r
+       }\r
+    }\r
+\r
+    if (zipfile == NULL) {\r
+       zipfile = fopen(appData.zippyLines, "r");\r
+       if (zipfile == NULL) {\r
+           DisplayFatalError("Can't open Zippy lines file", errno, 1);\r
+           return;\r
+       }\r
+       fstat(fileno(zipfile), &zipstat);\r
+    }\r
+               \r
+    for (;;) {\r
+       fseek(zipfile, (unsigned) random() % zipstat.st_size, 0);\r
+       do {\r
+         c = getc(zipfile);\r
+       } while (c != NULLCHAR && c != '^' && c != EOF);\r
+       if (c == EOF) continue;\r
+       while ((c = getc(zipfile)) == '\n') ;\r
+       if (c == EOF) continue;\r
+       break;\r
+    }\r
+    done = FALSE;\r
+\r
+    /* Don't use ics_prefix; we need to let FICS expand the alias i -> it,\r
+       but use the real command "i" on ICC */\r
+    strcpy(zipbuf, how);\r
+    strcat(zipbuf, " ");\r
+    if (whom != NULL) {\r
+       strcat(zipbuf, whom);\r
+       strcat(zipbuf, " ");\r
+    }\r
+    speechlen = strlen(zipbuf);\r
+    p = zipbuf + speechlen;\r
+\r
+    while (++speechlen < MAX_SPEECH) {\r
+       if (c == NULLCHAR || c == '^') {\r
+           *p++ = '\n';\r
+           *p = '\0';\r
+           SendToICS(zipbuf);\r
+           return;\r
+       } else if (c == '\n') {\r
+           *p++ = ' ';\r
+           do {\r
+               c = getc(zipfile);\r
+           } while (c == ' ');\r
+       } else if (c == EOF) {\r
+           break;\r
+       } else {\r
+           *p++ = c;\r
+           c = getc(zipfile);\r
+       }\r
+    }\r
+    /* Tried to say something too long, or junk at the end of the\r
+       file.  Try something else. */\r
+    Speak(how, whom);  /* tail recursion */\r
+}\r
+\r
+int ZippyCalled(str)\r
+     char *str;\r
+{\r
+    return ics_handle[0] != NULLCHAR && StrCaseStr(str, ics_handle) != NULL;\r
+}\r
+\r
+static char opp_name[128][32];\r
+static int num_opps=0;\r
+\r
+extern ColorClass curColor;\r
+\r
+static void SetCurColor( ColorClass color )\r
+{\r
+    curColor = color;\r
+}\r
+\r
+static void ColorizeEx( ColorClass color, int cont )\r
+{\r
+    if( appData.colorize ) {\r
+        Colorize( color, cont );\r
+        SetCurColor( color );\r
+    }\r
+}\r
+\r
+int ZippyControl(buf, i)\r
+     char *buf;\r
+     int *i;\r
+{\r
+    char *player, *p;\r
+    char reply[MSG_SIZ];\r
+\r
+#if TRIVIA\r
+#include "trivia.c"\r
+#endif\r
+\r
+    /* Possibly reject Crafty as opponent */\r
+    if (appData.zippyPlay && appData.zippyNoplayCrafty && forwardMostMove < 4\r
+       && looking_at(buf, i, "* kibitzes: Hello from Crafty")) \r
+    {\r
+        player = StripHighlightAndTitle(star_match[0]);\r
+       if ((gameMode == IcsPlayingWhite &&\r
+            StrCaseCmp(player, gameInfo.black) == 0) ||\r
+           (gameMode == IcsPlayingBlack &&\r
+            StrCaseCmp(player, gameInfo.white) == 0)) {\r
+\r
+         sprintf(reply, "%ssay This computer does not play Crafty clones\n%sabort\n%s+noplay %s\n",\r
+                 ics_prefix, ics_prefix, ics_prefix, player);\r
+         SendToICS(reply);\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    /* If this is a computer, save the name.  Then later, once the */\r
+    /* game is really started, we will send the "computer" notice to */\r
+    /* the engine.  */ \r
+    if (appData.zippyPlay &&\r
+       looking_at(buf, i, "* is in the computer list")) {\r
+       int i;\r
+       for (i=0;i<num_opps;i++)\r
+         if (!strcmp(opp_name[i],star_match[0])) break;\r
+       if (i >= num_opps) strcpy(opp_name[num_opps++],star_match[0]);\r
+    }\r
+    if (appData.zippyPlay && looking_at(buf, i, "* * is a computer *")) {\r
+       int i;\r
+       for (i=0;i<num_opps;i++)\r
+         if (!strcmp(opp_name[i],star_match[1])) break;\r
+       if (i >= num_opps) strcpy(opp_name[num_opps++],star_match[1]);\r
+    }\r
+\r
+    /* Tells and says */\r
+    if (appData.zippyPlay && \r
+       (looking_at(buf, i, "* offers to be your bughouse partner") ||\r
+        looking_at(buf, i, "* tells you: [automatic message] I chose you"))) {\r
+       player = StripHighlightAndTitle(star_match[0]);\r
+       if (appData.zippyBughouse > 1 && first.initDone) {\r
+           sprintf(reply, "%spartner %s\n", ics_prefix, player);\r
+           SendToICS(reply);\r
+           if (strcmp(zippyPartner, player) != 0) {\r
+               strcpy(zippyPartner, player);\r
+               SendToProgram(reply + strlen(ics_prefix), &first);\r
+           }\r
+       } else if (appData.zippyBughouse > 0) {\r
+           sprintf(reply, "%sdecline %s\n", ics_prefix, player);\r
+           SendToICS(reply);\r
+       } else {\r
+           sprintf(reply, "%stell %s This computer cannot play bughouse\n",\r
+                   ics_prefix, player);\r
+           SendToICS(reply);\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&\r
+       looking_at(buf, i, "* agrees to be your partner")) {\r
+       player = StripHighlightAndTitle(star_match[0]);\r
+       sprintf(reply, "partner %s\n", player);\r
+       if (strcmp(zippyPartner, player) != 0) {\r
+           strcpy(zippyPartner, player);\r
+           SendToProgram(reply, &first);\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&\r
+       (looking_at(buf, i, "are no longer *'s partner") ||\r
+        looking_at(buf, i,\r
+                   "* tells you: [automatic message] I'm no longer your"))) {\r
+       player = StripHighlightAndTitle(star_match[0]);\r
+       if (strcmp(zippyPartner, player) == 0) {\r
+           zippyPartner[0] = NULLCHAR;\r
+           SendToProgram("partner\n", &first);\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&\r
+       (looking_at(buf, i, "no longer have a bughouse partner") ||\r
+        looking_at(buf, i, "partner has disconnected") ||\r
+        looking_at(buf, i, "partner has just chosen a new partner"))) {\r
+      zippyPartner[0] = NULLCHAR;\r
+      SendToProgram("partner\n", &first);\r
+      return TRUE;\r
+    }\r
+\r
+    if (appData.zippyPlay && appData.zippyBughouse && first.initDone &&\r
+       looking_at(buf, i, "* (your partner) tells you: *")) {\r
+       /* This pattern works on FICS but not ICC */\r
+       player = StripHighlightAndTitle(star_match[0]);\r
+       if (strcmp(zippyPartner, player) != 0) {\r
+           strcpy(zippyPartner, player);\r
+           sprintf(reply, "partner %s\n", player);\r
+           SendToProgram(reply, &first);\r
+       }\r
+       sprintf(reply, "ptell %s\n", star_match[1]);\r
+       SendToProgram(reply, &first);\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "* tells you: *") ||\r
+       looking_at(buf, i, "* says: *")) \r
+    {\r
+       player = StripHighlightAndTitle(star_match[0]);\r
+       if (appData.zippyPassword[0] != NULLCHAR &&\r
+           strncmp(star_match[1], appData.zippyPassword,\r
+                   strlen(appData.zippyPassword)) == 0) {\r
+           p = star_match[1] + strlen(appData.zippyPassword);\r
+           while (*p == ' ') p++;\r
+           SendToICS(p);\r
+           SendToICS("\n");\r
+       } else if (appData.zippyPassword2[0] != NULLCHAR && first.initDone &&\r
+           strncmp(star_match[1], appData.zippyPassword2,\r
+                   strlen(appData.zippyPassword2)) == 0) {\r
+           p = star_match[1] + strlen(appData.zippyPassword2);\r
+           while (*p == ' ') p++;\r
+           SendToProgram(p, &first);\r
+           SendToProgram("\n", &first);\r
+       } else if (appData.zippyWrongPassword[0] != NULLCHAR &&\r
+           strncmp(star_match[1], appData.zippyWrongPassword,\r
+                   strlen(appData.zippyWrongPassword)) == 0) {\r
+           p = star_match[1] + strlen(appData.zippyWrongPassword);\r
+           while (*p == ' ') p++;\r
+           sprintf(reply, "wrong %s\n", player);\r
+           SendToICS(reply);\r
+       } else if (appData.zippyBughouse && first.initDone &&\r
+                  strcmp(player, zippyPartner) == 0) {\r
+           SendToProgram("ptell ", &first);\r
+           SendToProgram(star_match[1], &first);\r
+           SendToProgram("\n", &first);\r
+       } else if (strncmp(star_match[1], HI, 6) == 0) {\r
+           extern char* programVersion;\r
+           sprintf(reply, "%stell %s %s\n",\r
+                   ics_prefix, player, programVersion);\r
+           SendToICS(reply);\r
+       } else if (strncmp(star_match[1], "W0W!! ", 6) == 0) {\r
+           extern char* programVersion;\r
+           sprintf(reply, "%stell %s %s\n", ics_prefix,\r
+                   player, programVersion);\r
+           SendToICS(reply);\r
+       } else if (appData.zippyTalk && (((unsigned) random() % 10) < 9)) {\r
+           if (strcmp(player, ics_handle) != 0) {\r
+               Speak("tell", player);\r
+           }\r
+       }\r
+\r
+        ColorizeEx( ColorTell, FALSE );\r
+\r
+       return TRUE;\r
+    }\r
+\r
+    if( appData.colorize && looking_at(buf, i, "* (*) seeking") ) {\r
+       ColorizeEx(ColorSeek, FALSE);\r
+        return FALSE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "* spoofs you:")) {\r
+        player = StripHighlightAndTitle(star_match[0]);\r
+        sprintf(reply, "spoofedby %s\n", player);\r
+        SendToICS(reply);\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+int ZippyConverse(buf, i)\r
+     char *buf;\r
+     int *i;\r
+{\r
+    static char lastgreet[MSG_SIZ];\r
+    char reply[MSG_SIZ];\r
+    int oldi;\r
+\r
+    /* Shouts and emotes */\r
+    if (looking_at(buf, i, "--> * *") ||\r
+       looking_at(buf, i, "* shouts: *")) \r
+    {\r
+      if (appData.zippyTalk) {\r
+       char *player = StripHighlightAndTitle(star_match[0]);\r
+       if (strcmp(player, ics_handle) == 0) {\r
+           return TRUE;\r
+       } else if (appData.zippyPinhead[0] != NULLCHAR &&\r
+                  StrCaseStr(star_match[1], appData.zippyPinhead) != NULL) {\r
+           sprintf(reply, "insult %s\n", player);\r
+           SendToICS(reply);\r
+       } else if (ZippyCalled(star_match[1])) {\r
+           Speak("shout", NULL);\r
+       }\r
+      }\r
+\r
+      ColorizeEx(ColorShout, FALSE);\r
+\r
+      return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "* kibitzes: *")) {\r
+      if (appData.zippyTalk && ((unsigned) random() % 10) < 9) {\r
+       char *player = StripHighlightAndTitle(star_match[0]);\r
+       if (strcmp(player, ics_handle) != 0) {\r
+           Speak("kibitz", NULL);\r
+       }\r
+      }\r
+\r
+      ColorizeEx(ColorKibitz, FALSE);\r
+\r
+      return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "* whispers: *")) {\r
+      if (appData.zippyTalk && ((unsigned) random() % 10) < 9) {\r
+       char *player = StripHighlightAndTitle(star_match[0]);\r
+       if (strcmp(player, ics_handle) != 0) {\r
+           Speak("whisper", NULL);\r
+       }\r
+      }\r
+\r
+      ColorizeEx(ColorKibitz, FALSE);\r
+\r
+      return TRUE;\r
+    }\r
+\r
+    /* Messages */\r
+    if ((looking_at(buf, i, ". * (*:*): *") && isdigit(star_match[1][0])) ||\r
+        looking_at(buf, i, ". * at *:*: *")) {\r
+      if (appData.zippyTalk) {\r
+       FILE *f;\r
+       char *player = StripHighlightAndTitle(star_match[0]);\r
+\r
+       if (strcmp(player, ics_handle) != 0) {\r
+           if (((unsigned) random() % 10) < 9)\r
+             Speak("message", player);\r
+           f = fopen("zippy.messagelog", "a");\r
+           fprintf(f, "%s (%s:%s): %s\n", player,\r
+                   star_match[1], star_match[2], star_match[3]);\r
+           fclose(f);\r
+       }\r
+      }\r
+      return TRUE;\r
+    }\r
+\r
+    /* Channel tells */\r
+    oldi = *i;\r
+    if (looking_at(buf, i, "*(*: *")) {\r
+       char *player;\r
+       char *channel;\r
+       if (star_match[0][0] == NULLCHAR  ||\r
+           strchr(star_match[0], ' ') ||\r
+           strchr(star_match[1], ' ')) {\r
+           /* Oops, did not want to match this; probably a message */\r
+           *i = oldi;\r
+           return FALSE;\r
+       }\r
+       if (appData.zippyTalk) {\r
+         player = StripHighlightAndTitle(star_match[0]);\r
+         channel = strrchr(star_match[1], '(');\r
+         if (channel == NULL) {\r
+           channel = star_match[1];\r
+         } else {\r
+           channel++;\r
+         }\r
+         channel[strlen(channel)-1] = NULLCHAR;\r
+#if 0\r
+         /* Always tell to the channel (probability 90%) */\r
+         if (strcmp(player, ics_handle) != 0 &&\r
+             ((unsigned) random() % 10) < 9) {\r
+           Speak("tell", channel);\r
+         }\r
+#else\r
+         /* Tell to the channel only if someone mentions our name */\r
+         if (ZippyCalled(star_match[2])) {\r
+           Speak("tell", channel);\r
+         }\r
+#endif\r
+\r
+          ColorizeEx( atoi(channel) == 1 ? ColorChannel1 : ColorChannel, FALSE );\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    if (!appData.zippyTalk) return FALSE;\r
+\r
+    if ((looking_at(buf, i, "You have * message") &&\r
+        atoi(star_match[0]) != 0) ||\r
+       looking_at(buf, i, "* has left a message for you") ||\r
+       looking_at(buf, i, "* just sent you a message")) {\r
+        sprintf(reply, "%smessages\n%sclearmessages *\n",\r
+               ics_prefix, ics_prefix);\r
+       SendToICS(reply);\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "Notification: * has arrived")) {\r
+       if (((unsigned) random() % 3) == 0) {\r
+           char *player = StripHighlightAndTitle(star_match[0]);\r
+           strcpy(lastgreet, player);\r
+           sprintf(reply, "greet %s\n", player);\r
+           SendToICS(reply);\r
+           Speak("tell", player);\r
+       }\r
+    }  \r
+\r
+    if (looking_at(buf, i, "Notification: * has departed")) {\r
+       if (((unsigned) random() % 3) == 0) {\r
+           char *player = StripHighlightAndTitle(star_match[0]);\r
+           sprintf(reply, "farewell %s\n", player);\r
+           SendToICS(reply);\r
+       }\r
+    }  \r
+\r
+    if (looking_at(buf, i, "Not sent -- * is censoring you")) {\r
+       char *player = StripHighlightAndTitle(star_match[0]);\r
+       if (strcmp(player, lastgreet) == 0) {\r
+           sprintf(reply, "%s-notify %s\n", ics_prefix, player);\r
+           SendToICS(reply);\r
+       }\r
+    }  \r
+\r
+    if (looking_at(buf, i, "command is currently turned off")) {\r
+       appData.zippyUseI = 0;\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+void ZippyGameStart(white, black)\r
+     char *white, *black;\r
+{\r
+    if (!first.initDone) {\r
+      /* Game is starting prematurely.  We can't deal with this */\r
+      SendToICS(ics_prefix);\r
+      SendToICS("abort\n");\r
+      SendToICS(ics_prefix);\r
+      SendToICS("say Sorry, the chess program is not initialized yet.\n");\r
+      return;\r
+    }\r
+\r
+    if (appData.zippyGameStart[0] != NULLCHAR) {\r
+      SendToICS(appData.zippyGameStart);\r
+      SendToICS("\n");\r
+    }\r
+}\r
+\r
+void ZippyGameEnd(result, resultDetails)\r
+     ChessMove result;\r
+     char *resultDetails;\r
+{\r
+    if (appData.zippyAcceptOnly[0] == NULLCHAR &&\r
+       appData.zippyGameEnd[0] != NULLCHAR) {\r
+      SendToICS(appData.zippyGameEnd);\r
+      SendToICS("\n");\r
+    }\r
+    zippyLastGameEnd = time(0);\r
+}\r
+\r
+/*\r
+ * Routines to implement Zippy playing chess\r
+ */\r
+\r
+void ZippyHandleChallenge(srated, swild, sbase, sincrement, opponent)\r
+     char *srated, *swild, *sbase, *sincrement, *opponent;\r
+{\r
+    char buf[MSG_SIZ];\r
+    int base, increment, i=0;\r
+    char rated;\r
+    VariantClass variant;\r
+    char *varname;\r
+\r
+    rated = srated[0];\r
+    variant = StringToVariant(swild);\r
+    varname = VariantName(variant);\r
+    base = atoi(sbase);\r
+    increment = atoi(sincrement);\r
+\r
+    /* If desired, you can insert more code here to decline matches\r
+       based on rated, variant, base, and increment, but it is\r
+       easier to use the ICS formula feature instead. */\r
+\r
+    if (variant == VariantLoadable) {\r
+        sprintf(buf,\r
+        "%stell %s This computer can't play wild type %s\n%sdecline %s\n",\r
+               ics_prefix, opponent, swild, ics_prefix, opponent);\r
+       SendToICS(buf);\r
+       return;\r
+    }\r
+    if (StrStr(appData.zippyVariants, varname) == NULL ||\r
+                (i=first.protocolVersion) != 1 && StrStr(first.variants, varname) == NULL /* [HGM] zippyvar */\r
+                                                          ) {\r
+        sprintf(buf,\r
+        "%stell %s This computer can't play %s [%s], only %s\n%sdecline %s\n",\r
+               ics_prefix, opponent, swild, varname, \r
+                i ? first.variants : appData.zippyVariants,                               /* [HGM] zippyvar */\r
+               ics_prefix, opponent);\r
+       SendToICS(buf);\r
+       return;\r
+    }\r
+\r
+    /* Are we blocking match requests from all but one person? */\r
+    if (appData.zippyAcceptOnly[0] != NULLCHAR &&\r
+       StrCaseCmp(opponent, appData.zippyAcceptOnly)) {\r
+        /* Yes, and this isn't him.  Ignore challenge. */\r
+       return;\r
+    }\r
+    \r
+    /* Too many consecutive games with same opponent?  If so, make him\r
+       wait until someone else has played or a timeout has elapsed. */\r
+    if (appData.zippyMaxGames &&\r
+       strcmp(opponent, zippyLastOpp) == 0 &&\r
+       zippyConsecGames >= appData.zippyMaxGames &&\r
+       difftime(time(0), zippyLastGameEnd) < appData.zippyReplayTimeout) {\r
+      sprintf(buf, "%stell %s Sorry, you have just played %d consecutive games against %s.  To give others a chance, please wait %d seconds or until someone else has played.\n%sdecline %s\n",\r
+             ics_prefix, opponent, zippyConsecGames, ics_handle,\r
+             appData.zippyReplayTimeout, ics_prefix, opponent);\r
+      SendToICS(buf);\r
+      return;\r
+    }\r
+\r
+    /* Engine not yet initialized or still thinking about last game? */\r
+    if (!first.initDone || first.lastPing != first.lastPong) {\r
+      sprintf(buf, "%stell %s I'm not quite ready for a new game yet; try again soon.\n%sdecline %s\n",\r
+             ics_prefix, opponent, ics_prefix, opponent);\r
+      SendToICS(buf);\r
+      return;\r
+    }\r
+\r
+    sprintf(buf, "%saccept %s\n", ics_prefix, opponent);\r
+    SendToICS(buf);\r
+    if (appData.zippyTalk) {\r
+      Speak("tell", opponent);\r
+    }\r
+}\r
+\r
+\r
+/* Accept matches */\r
+int ZippyMatch(buf, i)\r
+     char *buf;\r
+     int *i;\r
+{\r
+    if (looking_at(buf, i, "* * match * * requested with * (*)")) {\r
+\r
+       ZippyHandleChallenge(star_match[0], star_match[1],\r
+                            star_match[2], star_match[3],\r
+                            StripHighlightAndTitle(star_match[4]));\r
+       return TRUE;\r
+    }\r
+\r
+    /* Old FICS 0-increment form */\r
+    if (looking_at(buf, i, "* * match * requested with * (*)")) {\r
+\r
+       ZippyHandleChallenge(star_match[0], star_match[1],\r
+                            star_match[2], "0",\r
+                            StripHighlightAndTitle(star_match[3]));\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i,\r
+                  "* has made an alternate proposal of * * match * *.")) {\r
+\r
+       ZippyHandleChallenge(star_match[1], star_match[2],\r
+                            star_match[3], star_match[4],\r
+                            StripHighlightAndTitle(star_match[0]));\r
+       return TRUE;\r
+    }\r
+\r
+    /* FICS wild/nonstandard forms */\r
+    if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * Loaded from *")) {\r
+       /* note: star_match[2] can include "[white] " or "[black] "\r
+          before our own name. */\r
+       ZippyHandleChallenge(star_match[4], star_match[8],\r
+                            star_match[6], star_match[7],\r
+                            StripHighlightAndTitle(star_match[0]));\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i,\r
+                  "Challenge: * (*) *(*) * * * * : * * Loaded from *")) {\r
+       /* note: star_match[2] can include "[white] " or "[black] "\r
+          before our own name. */\r
+       ZippyHandleChallenge(star_match[4], star_match[10],\r
+                            star_match[8], star_match[9],\r
+                            StripHighlightAndTitle(star_match[0]));\r
+       return TRUE;\r
+    }\r
+\r
+    /* Regular forms */\r
+    if (looking_at(buf, i, "Challenge: * (*) *(*) * * * * : * *") |\r
+       looking_at(buf, i, "Challenge: * (*) *(*) * * * * * *")) {\r
+       /* note: star_match[2] can include "[white] " or "[black] "\r
+          before our own name. */\r
+       ZippyHandleChallenge(star_match[4], star_match[5],\r
+                            star_match[8], star_match[9],\r
+                            StripHighlightAndTitle(star_match[0]));\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "Challenge: * (*) *(*) * * * *")) {\r
+       /* note: star_match[2] can include "[white] " or "[black] "\r
+          before our own name. */\r
+       ZippyHandleChallenge(star_match[4], star_match[5],\r
+                            star_match[6], star_match[7],\r
+                            StripHighlightAndTitle(star_match[0]));\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "offers you a draw")) {\r
+        if (first.sendDrawOffers && first.initDone) {\r
+           SendToProgram("draw\n", &first);\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "requests that the game be aborted") ||\r
+        looking_at(buf, i, "would like to abort")) {\r
+       if (appData.zippyAbort ||\r
+           (gameMode == IcsPlayingWhite && whiteTimeRemaining < 0) ||\r
+           (gameMode == IcsPlayingBlack && blackTimeRemaining < 0)) {\r
+           SendToICS(ics_prefix);\r
+           SendToICS("abort\n");\r
+       } else {\r
+           SendToICS(ics_prefix);\r
+           if (appData.zippyTalk)\r
+             SendToICS("say Whoa no!  I am having FUN!!\n");\r
+           else\r
+             SendToICS("say Sorry, this computer doesn't accept aborts.\n");\r
+       }\r
+       return TRUE;\r
+    }\r
+\r
+    if (looking_at(buf, i, "requests adjournment") ||\r
+       looking_at(buf, i, "would like to adjourn")) {\r
+      if (appData.zippyAdjourn) {\r
+       SendToICS(ics_prefix);\r
+       SendToICS("adjourn\n");\r
+      } else {\r
+       SendToICS(ics_prefix);\r
+       if (appData.zippyTalk)\r
+         SendToICS("say Whoa no!  I am having FUN playing NOW!!\n");\r
+       else\r
+         SendToICS("say Sorry, this computer doesn't accept adjourns.\n");\r
+      }\r
+      return TRUE;\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+/* Initialize chess program with data from the first board \r
+ * of a new or resumed game.\r
+ */\r
+void ZippyFirstBoard(moveNum, basetime, increment)\r
+     int moveNum, basetime, increment;\r
+{\r
+    char buf[MSG_SIZ];\r
+    int w, b;\r
+    char *opp = (gameMode==IcsPlayingWhite ? gameInfo.black : gameInfo.white);\r
+    Boolean sentPos = FALSE;\r
+\r
+    if (!first.initDone) {\r
+      /* Game is starting prematurely.  We can't deal with this */\r
+      SendToICS(ics_prefix);\r
+      SendToICS("abort\n");\r
+      SendToICS(ics_prefix);\r
+      SendToICS("say Sorry, the chess program is not initialized yet.\n");\r
+      return;\r
+    }\r
+\r
+    /* Send the variant command if needed */\r
+    if (gameInfo.variant != VariantNormal) {\r
+      sprintf(buf, "variant %s\n", VariantName(gameInfo.variant));\r
+      SendToProgram(buf, &first);\r
+    }\r
+\r
+    if ((startedFromSetupPosition && moveNum == 0) ||\r
+       (!appData.getMoveList && moveNum > 0)) {\r
+      SendToProgram("force\n", &first);\r
+      SendBoard(&first, moveNum);\r
+      sentPos = TRUE;\r
+    }\r
+\r
+    sprintf(buf, "level 0 %d %d\n", basetime, increment);\r
+    SendToProgram(buf, &first);\r
+\r
+    /* Count consecutive games from one opponent */\r
+    if (strcmp(opp, zippyLastOpp) == 0) {\r
+      zippyConsecGames++;\r
+    } else {\r
+      zippyConsecGames = 1;\r
+      strcpy(zippyLastOpp, opp);\r
+    }\r
+\r
+    /* Send the "computer" command if the opponent is in the list\r
+       we've been gathering. */\r
+    for (w=0; w<num_opps; w++) {\r
+       if (!strcmp(opp_name[w], opp)) {\r
+           SendToProgram(first.computerString, &first);\r
+           break;\r
+       }\r
+    }\r
+\r
+    /* Ratings might be < 0 which means "we haven't seen a ratings\r
+       message from ICS." Send 0 in that case */\r
+    w = (gameInfo.whiteRating >= 0) ? gameInfo.whiteRating : 0;\r
+    b = (gameInfo.blackRating >= 0) ? gameInfo.blackRating : 0;\r
+    \r
+    firstMove = FALSE;\r
+    if (gameMode == IcsPlayingWhite) {\r
+        if (first.sendName) {\r
+         sprintf(buf, "name %s\n", gameInfo.black);\r
+         SendToProgram(buf, &first);\r
+       }\r
+       strcpy(ics_handle, gameInfo.white);\r
+       sprintf(buf, "rating %d %d\n", w, b);\r
+       SendToProgram(buf, &first);\r
+       if (sentPos) {\r
+           /* Position sent above, engine is in force mode */\r
+           if (WhiteOnMove(moveNum)) {\r
+             /* Engine is on move now */\r
+             if (first.sendTime) {\r
+               if (first.useColors) {\r
+                 SendToProgram("black\n", &first); /*gnu kludge*/\r
+                 SendTimeRemaining(&first, TRUE);\r
+                 SendToProgram("white\n", &first);\r
+               } else {\r
+                 SendTimeRemaining(&first, TRUE);\r
+               }\r
+             }\r
+             SendToProgram("go\n", &first);\r
+           } else {\r
+               /* Engine's opponent is on move now */\r
+               if (first.usePlayother) {\r
+                 if (first.sendTime) {\r
+                   SendTimeRemaining(&first, TRUE);\r
+                 }\r
+                 SendToProgram("playother\n", &first);\r
+               } else {\r
+                 /* Need to send a "go" after opponent moves */\r
+                 firstMove = TRUE;\r
+               }\r
+           }\r
+       } else {\r
+           /* Position not sent above, move list might be sent later */\r
+           if (moveNum == 0) {\r
+               /* No move list coming; at start of game */\r
+             if (first.sendTime) {\r
+               if (first.useColors) {\r
+                 SendToProgram("black\n", &first); /*gnu kludge*/\r
+                 SendTimeRemaining(&first, TRUE);\r
+                 SendToProgram("white\n", &first);\r
+               } else {\r
+                 SendTimeRemaining(&first, TRUE);\r
+               }\r
+             }\r
+             SendToProgram("go\n", &first);\r
+           }\r
+       }\r
+    } else if (gameMode == IcsPlayingBlack) {\r
+        if (first.sendName) {\r
+         sprintf(buf, "name %s\n", gameInfo.white);\r
+         SendToProgram(buf, &first);\r
+       }\r
+       strcpy(ics_handle, gameInfo.black);\r
+       sprintf(buf, "rating %d %d\n", b, w);\r
+       SendToProgram(buf, &first);\r
+       if (sentPos) {\r
+           /* Position sent above, engine is in force mode */\r
+           if (!WhiteOnMove(moveNum)) {\r
+               /* Engine is on move now */\r
+             if (first.sendTime) {\r
+               if (first.useColors) {\r
+                 SendToProgram("white\n", &first); /*gnu kludge*/\r
+                 SendTimeRemaining(&first, FALSE);\r
+                 SendToProgram("black\n", &first);\r
+               } else {\r
+                 SendTimeRemaining(&first, FALSE);\r
+               }\r
+             }\r
+             SendToProgram("go\n", &first);\r
+           } else {\r
+               /* Engine's opponent is on move now */\r
+               if (first.usePlayother) {\r
+                 if (first.sendTime) {\r
+                   SendTimeRemaining(&first, FALSE);\r
+                 }\r
+                 SendToProgram("playother\n", &first);\r
+               } else {\r
+                 /* Need to send a "go" after opponent moves */\r
+                 firstMove = TRUE;\r
+               }\r
+           }\r
+       } else {\r
+           /* Position not sent above, move list might be sent later */\r
+           /* Nothing needs to be done here */\r
+       }       \r
+    }\r
+}\r
+\r
+\r
+void\r
+ZippyHoldings(white_holding, black_holding, new_piece)\r
+     char *white_holding, *black_holding, *new_piece;\r
+{\r
+    char buf[MSG_SIZ];\r
+    if (gameMode != IcsPlayingBlack && gameMode != IcsPlayingWhite) return;\r
+    sprintf(buf, "holding [%s] [%s] %s\n",\r
+           white_holding, black_holding, new_piece);\r
+    SendToProgram(buf, &first);\r
+}\r
diff --git a/zippy.h b/zippy.h
index c8cf6e8..f42d1d3 100644 (file)
--- a/zippy.h
+++ b/zippy.h
@@ -1,57 +1,57 @@
-/*
- * zippy.h -- Interface to zippy.c module in XBoard
- * $Id: zippy.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.
- *
- * 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.
- * ------------------------------------------------------------------------
- */
-
-void ZippyInit P((void));
-int ZippyControl P((char *buf, int *i));
-int ZippyConverse P((char *buf, int *i));
-void ZippyGameStart P((char *white, char *black));
-int ZippyMatch P((char *buf, int *i));
-void ZippyFirstBoard P((int moveNum, int basetime, int increment));
-void ZippyGameEnd P((ChessMove result, char *resultDetails));
-void ZippyHoldings P((char *white_holding, char *black_holding,
-                     char *new_piece));
+/*\r
+ * zippy.h -- Interface to zippy.c module in XBoard\r
+ * $Id: zippy.h,v 2.1 2003/10/27 19:21:01 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
+void ZippyInit P((void));\r
+int ZippyControl P((char *buf, int *i));\r
+int ZippyConverse P((char *buf, int *i));\r
+void ZippyGameStart P((char *white, char *black));\r
+int ZippyMatch P((char *buf, int *i));\r
+void ZippyFirstBoard P((int moveNum, int basetime, int increment));\r
+void ZippyGameEnd P((ChessMove result, char *resultDetails));\r
+void ZippyHoldings P((char *white_holding, char *black_holding,\r
+                     char *new_piece));\r