give a default directory for bitmaps files (tiny change)
[xboard.git] / xboard.c
index 2b14ef9..ea5560f 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -346,6 +346,9 @@ void DrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AbortProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void AdjournProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void ResignProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AdjuWhiteProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AdjuBlackProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void AdjuDrawProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void EnterKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void StopObservingProc P((Widget w, XEvent *event, String *prms,
                          Cardinal *nprms));
@@ -453,6 +456,7 @@ Display *xDisplay;
 Window xBoardWindow;
 Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
   jailSquareColor, highlightSquareColor, premoveHighlightColor;
+Pixel lowTimeWarningColor;
 GC lightSquareGC, darkSquareGC, jailSquareGC, lineGC, wdPieceGC, wlPieceGC,
   bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
   wjPieceGC, bjPieceGC, prelineGC, countGC;
@@ -601,6 +605,10 @@ MenuItem actionMenu[] = {
     {"----", NothingProc},
     {N_("Stop Observing"), StopObservingProc},
     {N_("Stop Examining"), StopExaminingProc},
+    {"----", NothingProc},
+    {N_("Adjudicate to White"), AdjuWhiteProc},
+    {N_("Adjudicate to Black"), AdjuBlackProc},
+    {N_("Adjudicate Draw"), AdjuDrawProc},
     {NULL, NULL}
 };
 
@@ -1052,6 +1060,9 @@ XtResource clientResources[] = {
     { "zippyReplayTimeout", "zippyReplayTimeout", XtRInt, sizeof(int),
        XtOffset(AppDataPtr, zippyReplayTimeout), XtRImmediate,
         (XtPointer) ZIPPY_REPLAY_TIMEOUT },
+    { "zippyShortGame", "zippyShortGame", XtRInt, sizeof(int),
+       XtOffset(AppDataPtr, zippyShortGame), XtRImmediate,
+        (XtPointer) 0 },
 #endif
     { "flashCount", "flashCount", XtRInt, sizeof(int),
        XtOffset(AppDataPtr, flashCount), XtRImmediate,
@@ -1185,6 +1196,12 @@ XtResource clientResources[] = {
     { "showButtonBar", "showButtonBar", XtRBoolean,
        sizeof(Boolean), XtOffset(AppDataPtr, showButtonBar),
        XtRImmediate, (XtPointer) True },
+    { "lowTimeWarningColor", "lowTimeWarningColor", XtRString,
+      sizeof(String), XtOffset(AppDataPtr, lowTimeWarningColor),
+      XtRString, COLOR_LOWTIMEWARNING },
+    { "lowTimeWarning", "lowTimeWarning", XtRBoolean,
+      sizeof(Boolean), XtOffset(AppDataPtr, lowTimeWarning),
+      XtRImmediate, (XtPointer) False },
     {"icsEngineAnalyze", "icsEngineAnalyze", XtRBoolean,        /* [DM] icsEngineAnalyze */
         sizeof(Boolean), XtOffset(AppDataPtr, icsEngineAnalyze),
         XtRImmediate, (XtPointer) False },
@@ -1209,6 +1226,9 @@ XtResource clientResources[] = {
     { "defaultFrcPosition", "defaultFrcPositon", XtRInt,
        sizeof(int), XtOffset(AppDataPtr, defaultFrcPosition),
        XtRImmediate, (XtPointer) -1},
+    { "gameListTags", "gameListTags", XtRString,
+        sizeof(String), XtOffset(AppDataPtr, gameListTags),
+       XtRImmediate, (XtPointer) GLT_DEFAULT_TAGS },
 
     // [HGM] 4.3.xx options
     { "boardWidth", "boardWidth", XtRInt,
@@ -1325,6 +1345,12 @@ XtResource clientResources[] = {
     { "secondOptions", "secondOptions", XtRString,
         sizeof(String), XtOffset(AppDataPtr, secondOptions),
        XtRImmediate, (XtPointer) "" },
+    { "firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XtRString,
+        sizeof(String), XtOffset(AppDataPtr, fenOverride1),
+       XtRImmediate, (XtPointer) 0 },
+    { "secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XtRString,
+        sizeof(String), XtOffset(AppDataPtr, fenOverride2),
+       XtRImmediate, (XtPointer) 0 },
 
     // [HGM] Winboard_x UCI options
     { "firstIsUCI", "firstIsUCI", XtRBoolean,
@@ -1585,6 +1611,7 @@ XrmOptionDescRec shellOptions[] = {
     { "-zippyVariants", "zippyVariants", XrmoptionSepArg, NULL },
     { "-zippyMaxGames", "zippyMaxGames", XrmoptionSepArg, NULL },
     { "-zippyReplayTimeout", "zippyReplayTimeout", XrmoptionSepArg, NULL },
+    { "-zippyShortGame", "zippyShortGame", XrmoptionSepArg, NULL },
 #endif
     { "-flashCount", "flashCount", XrmoptionSepArg, NULL },
     { "-flash", "flashCount", XrmoptionNoArg, "3" },
@@ -1653,6 +1680,8 @@ XrmOptionDescRec shellOptions[] = {
     { "-showButtonBar", "showButtonBar", XrmoptionSepArg, NULL },
     { "-buttons", "showButtonBar", XrmoptionNoArg, "True" },
     { "-xbuttons", "showButtonBar", XrmoptionNoArg, "False" },
+    { "-lowTimeWarningColor", "lowTimeWarningColor", XrmoptionSepArg, NULL },
+    { "-lowTimeWarning", "lowTimeWarning", XrmoptionSepArg, NULL },
     /* [AS,HR] New features */
     { "-firstScoreAbs", "firstScoreAbs", XrmoptionSepArg, NULL },
     { "-secondScoreAbs", "secondScoreAbs", XrmoptionSepArg, NULL },
@@ -1677,6 +1706,7 @@ XrmOptionDescRec shellOptions[] = {
     { "-defaultCacheSizeEGTB", "defaultCacheSizeEGTB", XrmoptionSepArg, NULL },
     { "-defaultPathEGTB", "defaultPathEGTB", XrmoptionSepArg, NULL },
     { "-defaultFrcPosition", "defaultFrcPosition", XrmoptionSepArg, NULL },
+    { "-gameListTags", "gameListTags", XrmoptionSepArg, NULL },
     // [HGM] I am sure AS added many more options, but we have to fish them out, from the list in winboard.c
 
     /* [HGM,HR] User-selectable board size */
@@ -1723,6 +1753,8 @@ XrmOptionDescRec shellOptions[] = {
     { "-noGUI", "noGUI", XrmoptionNoArg, "True" },
     { "-firstOptions", "firstOptions", XrmoptionSepArg, NULL },
     { "-secondOptions", "secondOptions", XrmoptionSepArg, NULL },
+    { "-firstNeedsNoncompliantFEN", "firstNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
+    { "-secondNeedsNoncompliantFEN", "secondNeedsNoncompliantFEN", XrmoptionSepArg, NULL },
 };
 
 
@@ -1781,6 +1813,9 @@ XtActionsRec boardActions[] = {
     { "AdjournProc", AdjournProc },
     { "AbortProc", AbortProc },
     { "ResignProc", ResignProc },
+    { "AdjuWhiteProc", AdjuWhiteProc },
+    { "AdjuBlackProc", AdjuBlackProc },
+    { "AdjuDrawProc", AdjuDrawProc },
     { "EnterKeyProc", EnterKeyProc },
     { "StopObservingProc", StopObservingProc },
     { "StopExaminingProc", StopExaminingProc },
@@ -2122,7 +2157,7 @@ CatchDeleteWindow(Widget w, String procname)
 {
   char buf[MSG_SIZ];
   XSetWMProtocols(xDisplay, XtWindow(w), &wm_delete_window, 1);
-  sprintf(buf, "<Message>WM_PROTOCOLS: %s() \n", procname);
+  snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
   XtAugmentTranslations(w, XtParseTranslationTable(buf));
 }
 
@@ -2294,6 +2329,20 @@ main(argc, argv)
     if (argc > 1) {
        fprintf(stderr, _("%s: unrecognized argument %s\n"),
                programName, argv[1]);
+       fprintf(stderr, "Recognized options:\n");
+       for(i = 0; i < XtNumber(shellOptions); i++) {
+           j = fprintf(stderr, "  %s%s", shellOptions[i].option,
+                       (shellOptions[i].argKind == XrmoptionSepArg
+                        ? " ARG" : ""));
+           if (i++ < XtNumber(shellOptions)) {
+               fprintf(stderr, "%*c%s%s\n", 40 - j, ' ',
+                       shellOptions[i].option,
+                       (shellOptions[i].argKind == XrmoptionSepArg
+                        ? " ARG" : ""));
+           } else {
+               fprintf(stderr, "\n");
+           }
+       }
        exit(2);
     }
 
@@ -2312,8 +2361,8 @@ main(argc, argv)
     i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
     gameCopyFilename = (char*) malloc(i);
     gamePasteFilename = (char*) malloc(i);
-    sprintf(gameCopyFilename, "%s/.xboard%05uc.pgn", p, getpid());
-    sprintf(gamePasteFilename, "%s/.xboard%05up.pgn", p, getpid());
+    snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
+    snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
 
     XtGetApplicationResources(shellWidget, (XtPointer) &appData,
                              clientResources, XtNumber(clientResources),
@@ -2551,6 +2600,20 @@ XBoard square size (hint): %d\n\
     if (forceMono) {
       fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
              programName);
+      
+      if (appData.bitmapDirectory == NULL ||
+             appData.bitmapDirectory[0] == NULLCHAR)
+           appData.bitmapDirectory = DEF_BITMAP_DIR;
+    }
+
+    if (appData.lowTimeWarning && !appData.monoMode) {
+      vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
+      vFrom.size = strlen(appData.lowTimeWarningColor);
+      XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+      if (vTo.addr == NULL) 
+               appData.monoMode = True;
+      else
+               lowTimeWarningColor = *(Pixel *) vTo.addr;
     }
 
     if (appData.monoMode && appData.debugMode) {
@@ -3675,7 +3738,7 @@ void CreateXIMPieces()
            fprintf(stderr, "%d", piece+1);
            for (kind=0; kind<4; kind++) {
                fprintf(stderr, ".");
-               sprintf(buf, "%s/%c%s%u.xim",
+               snprintf(buf, sizeof(buf), "%s/%c%s%u.xim",
                        ExpandPathName(appData.pixmapDirectory),
                        ToLower(PieceToChar((ChessSquare)piece)),
                        ximkind[kind], ss);
@@ -3694,7 +3757,7 @@ void CreateXIMPieces()
        /* Load light and dark squares */
        /* If the LSQ and DSQ pieces don't exist, we will
           draw them with solid squares. */
-       sprintf(buf, "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
+       snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
        if (access(buf, 0) != 0) {
            useImageSqs = 0;
        } else {
@@ -3708,7 +3771,7 @@ void CreateXIMPieces()
 
            loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
            fprintf(stderr, _("dark square "));
-           sprintf(buf, "%s/dsq%u.xim",
+           snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
                    ExpandPathName(appData.pixmapDirectory), ss);
            if (appData.debugMode)
              fprintf(stderr, _("(File:%s:) "), buf);
@@ -3797,7 +3860,7 @@ void CreateXPMPieces()
        for (piece = (int) WhitePawn; piece <= (int) WhiteKing; piece++) {
            fprintf(stderr, "%d ", piece+1);
            for (kind=0; kind<4; kind++) {
-               sprintf(buf, "%s/%c%s%u.xpm",
+             snprintf(buf, sizeof(buf), "%s/%c%s%u.xpm",
                        ExpandPathName(appData.pixmapDirectory),
                        ToLower(PieceToChar((ChessSquare)piece)),
                        xpmkind[kind], ss);
@@ -3817,7 +3880,7 @@ void CreateXPMPieces()
        /* If the LSQ and DSQ pieces don't exist, we will
           draw them with solid squares. */
        fprintf(stderr, _("light square "));
-       sprintf(buf, "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
+       snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
        if (access(buf, 0) != 0) {
            useImageSqs = 0;
        } else {
@@ -3831,7 +3894,7 @@ void CreateXPMPieces()
                exit(1);
            }
            fprintf(stderr, _("dark square "));
-           sprintf(buf, "%s/dsq%u.xpm",
+           snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
                    ExpandPathName(appData.pixmapDirectory), ss);
            if (appData.debugMode) {
                fprintf(stderr, _("(File:%s:) "), buf);
@@ -3920,17 +3983,17 @@ void ReadBitmap(pm, name, bits, wreq, hreq)
        if (errcode != BitmapSuccess) {
            switch (errcode) {
              case BitmapOpenFailed:
-               sprintf(msg, _("Can't open bitmap file %s"), fullname);
+               snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
                break;
              case BitmapFileInvalid:
-               sprintf(msg, _("Invalid bitmap in file %s"), fullname);
+               snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
                break;
              case BitmapNoMemory:
-               sprintf(msg, _("Ran out of memory reading bitmap file %s"),
+               snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
                        fullname);
                break;
              default:
-               sprintf(msg, _("Unknown XReadBitmapFile error %d on file %s"),
+               snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
                        errcode, fullname);
                break;
            }
@@ -4186,7 +4249,7 @@ void SetupDropMenu()
                                       && !appData.icsActive));
        count = 0;
        while (p && *p++ == dmEnables[i].piece) count++;
-       sprintf(label, "%s  %d", dmEnables[i].widget, count);
+       snprintf(label, sizeof(label), "%s  %d", dmEnables[i].widget, count);
        j = 0;
        XtSetArg(args[j], XtNlabel, label); j++;
        XtSetValues(entry, args, j);
@@ -6258,7 +6321,7 @@ void CopyPositionProc(w, event, prms, nprms)
     int ret;
 
     if (selected_fen_position) free(selected_fen_position);
-    selected_fen_position = (char *)PositionToFEN(currentMove,1);
+    selected_fen_position = (char *)PositionToFEN(currentMove, NULL);
     if (!selected_fen_position) return;
     ret = XtOwnSelection(menuBarWidget, XA_PRIMARY,
                         CurrentTime,
@@ -6449,7 +6512,7 @@ void AnalyzeModeProc(w, event, prms, nprms)
     char buf[MSG_SIZ];
 
     if (!first.analysisSupport) {
-      sprintf(buf, _("%s does not support analysis"), first.tidy);
+      snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
       DisplayError(buf, 0);
       return;
     }
@@ -6491,7 +6554,7 @@ void AnalyzeFileProc(w, event, prms, nprms)
 {
     if (!first.analysisSupport) {
       char buf[MSG_SIZ];
-      sprintf(buf, _("%s does not support analysis"), first.tidy);
+      snprintf(buf, sizeof(buf), _("%s does not support analysis"), first.tidy);
       DisplayError(buf, 0);
       return;
     }
@@ -6648,6 +6711,33 @@ void ResignProc(w, event, prms, nprms)
     ResignEvent();
 }
 
+void AdjuWhiteProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    UserAdjudicationEvent(+1);
+}
+
+void AdjuBlackProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    UserAdjudicationEvent(-1);
+}
+
+void AdjuDrawProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+    UserAdjudicationEvent(0);
+}
+
 void EnterKeyProc(w, event, prms, nprms)
      Widget w;
      XEvent *event;
@@ -7300,7 +7390,7 @@ void InfoProc(w, event, prms, nprms)
      Cardinal *nprms;
 {
     char buf[MSG_SIZ];
-    sprintf(buf, "xterm -e info --directory %s --directory . -f %s &",
+    snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
            INFODIR, INFOFILE);
     system(buf);
 }
@@ -7317,7 +7407,7 @@ void ManProc(w, event, prms, nprms)
       name = prms[0];
     else
       name = "xboard";
-    sprintf(buf, "xterm -e man %s &", name);
+    snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
     system(buf);
 }
 
@@ -7351,12 +7441,11 @@ void AboutProc(w, event, prms, nprms)
 #else
     char *zippy = "";
 #endif
-    sprintf(buf, "%s%s\n\n%s\n%s\n%s\n%s\n\n%s%s\n%s",
+    snprintf(buf, sizeof(buf), "%s%s\n\n%s\n%s\n%s\n\n%s%s\n%s",
            programVersion, zippy,
            "Copyright 1991 Digital Equipment Corporation",
-           "Enhancements Copyright 1992-2001 Free Software Foundation",
+           "Enhancements Copyright 1992-2009 Free Software Foundation",
            "Enhancements Copyright 2005 Alessandro Scotti",
-           "Enhancements Copyright 2007-2008 H.G.Muller",
            PRODUCT, " is free software and carries NO WARRANTY;",
            "see the file COPYING for more information.");
     ErrorPopUp(_("About XBoard"), buf, FALSE);
@@ -7410,7 +7499,7 @@ void DisplayMessage(message, extMessage)
 
     if (extMessage) {
        if (*message) {
-           sprintf(buf, "%s  %s", message, extMessage);
+           snprintf(buf, sizeof(buf), "%s  %s", message, extMessage);
            message = buf;
        } else {
            message = extMessage;
@@ -7440,11 +7529,11 @@ void DisplayTitle(text)
        strcpy(icon, text);
        strcpy(title, text);
     } else if (appData.icsActive) {
-       sprintf(icon, "%s", appData.icsHost);
-       sprintf(title, "%s: %s", programName, appData.icsHost);
+        snprintf(icon, sizeof(icon), "%s", appData.icsHost);
+       snprintf(title, sizeof(title),"%s: %s", programName, appData.icsHost);
     } else if (appData.cmailGameName[0] != NULLCHAR) {
-       sprintf(icon, "%s", "CMail");
-       sprintf(title, "%s: %s", programName, "CMail");
+        snprintf(icon, sizeof(icon), "%s", "CMail");
+       snprintf(title,sizeof(title), "%s: %s", programName, "CMail");
 #ifdef GOTHIC
     // [HGM] license: This stuff should really be done in back-end, but WinBoard already had a pop-up for it
     } else if (gameInfo.variant == VariantGothic) {
@@ -7461,7 +7550,7 @@ void DisplayTitle(text)
        strcpy(title, programName);
     } else {
        strcpy(icon, first.tidy);
-       sprintf(title, "%s: %s", programName, first.tidy);
+       snprintf(title,sizeof(title), "%s: %s", programName, first.tidy);
     }
     i = 0;
     XtSetArg(args[i], XtNiconName, (XtArgVal) icon);    i++;
@@ -7485,7 +7574,7 @@ void DisplayError(message, error)
            fprintf(stderr, "%s: %s: %s\n",
                    programName, message, strerror(error));
        }
-       sprintf(buf, "%s: %s", message, strerror(error));
+       snprintf(buf,sizeof(buf), "%s: %s", message, strerror(error));
        message = buf;
     }
     ErrorPopUp(_("Error"), message, FALSE);
@@ -7521,7 +7610,7 @@ void DisplayFatalError(message, error, status)
     } else {
        fprintf(stderr, "%s: %s: %s\n",
                programName, message, strerror(error));
-       sprintf(buf, "%s: %s", message, strerror(error));
+       snprintf(buf, sizeof(buf), "%s: %s", message, strerror(error));
        message = buf;
     }
     if (appData.popupExitMessage && boardWidget && XtIsRealized(boardWidget)) {
@@ -7710,7 +7799,7 @@ PlaySound(name)
     putc(BELLCHAR, stderr);
   } else {
     char buf[2048];
-    sprintf(buf, "%s '%s' &", appData.soundProgram, name);
+    snprintf(buf, sizeof(buf), "%s '%s' &", appData.soundProgram, name);
     system(buf);
   }
 }
@@ -8040,6 +8129,14 @@ DisplayTimerLabel(w, color, timer, highlight)
     char buf[MSG_SIZ];
     Arg args[16];
 
+    Pixel foregroundOrWarningColor = timerForegroundPixel;
+
+    if (timer > 0
+       && appData.lowTimeWarning
+       && (timer / 1000) < appData.icsAlarmTime)
+
+      foregroundOrWarningColor = lowTimeWarningColor;
+
     if (appData.clockMode) {
        sprintf(buf, "%s: %s", color, TimeString(timer));
        XtSetArg(args[0], XtNlabel, buf);
@@ -8049,11 +8146,12 @@ DisplayTimerLabel(w, color, timer, highlight)
     }
 
     if (highlight) {
-       XtSetArg(args[1], XtNbackground, timerForegroundPixel);
+
+       XtSetArg(args[1], XtNbackground, foregroundOrWarningColor);
        XtSetArg(args[2], XtNforeground, timerBackgroundPixel);
     } else {
        XtSetArg(args[1], XtNbackground, timerBackgroundPixel);
-       XtSetArg(args[2], XtNforeground, timerForegroundPixel);
+       XtSetArg(args[2], XtNforeground, foregroundOrWarningColor);
     }
 
     XtSetValues(w, args, 3);
@@ -8229,9 +8327,9 @@ int OpenTelnet(host, port, pr)
     char cmdLine[MSG_SIZ];
 
     if (port[0] == NULLCHAR) {
-       sprintf(cmdLine, "%s %s", appData.telnetProgram, host);
+      snprintf(cmdLine, sizeof(cmdLine), "%s %s", appData.telnetProgram, host);
     } else {
-       sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);
+      snprintf(cmdLine,sizeof(cmdLine), "%s %s %s", appData.telnetProgram, host, port);
     }
     return StartChildProcess(cmdLine, "", pr);
 }
@@ -9147,7 +9245,7 @@ DragPieceBegin(x, y)
               boardX == BOARD_LEFT-2 && PieceForSquare(boardX+1, boardY) > 1)
            XCopyArea(xDisplay, xBoardWindow, player.saveBuf, player.blitGC,
                     corner.x, corner.y, squareSize, squareSize,
-                    0, 0); // [HGM] xh: unstack in stead of grab
+                    0, 0); // [HGM] zh: unstack in stead of grab
        damage[boardY][boardX] = True;
     } else {
        player.dragActive = False;