Adapt WinBoard front-end to Mighty Lion
[xboard.git] / backend.c
index 48a32a4..4c9968f 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5016,6 +5016,11 @@ SendMoveToProgram (int moveNum, ChessProgramState *cps)
     char buf[MSG_SIZ];
 
     if(moveList[moveNum][1] == '@' && moveList[moveNum][0] == '@') {
+       if(gameInfo.variant == VariantLion || gameInfo.variant == VariantChu) {
+           sprintf(buf, "%s@@@@\n", cps->useUsermove ? "usermove " : "");
+           SendToProgram(buf, cps);
+           return;
+       }
        // null move in variant where engine does not understand it (for analysis purposes)
        SendBoard(cps, moveNum + 1); // send position after move in stead.
        return;
@@ -5058,16 +5063,18 @@ SendMoveToProgram (int moveNum, ChessProgramState *cps)
        }
        else SendToProgram(moveList[moveNum], cps);
       } else
+      if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square
+         snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", moveList[moveNum][0], moveList[moveNum][1] - '0', // convert to two moves
+                                              moveList[moveNum][5], moveList[moveNum][6] - '0',
+                                              moveList[moveNum][5], moveList[moveNum][6] - '0',
+                                              moveList[moveNum][2], moveList[moveNum][3] - '0');
+         SendToProgram(buf, cps);
+      } else
       if(BOARD_HEIGHT > 10) { // [HGM] big: convert ranks to double-digit where needed
        if(moveList[moveNum][1] == '@' && (BOARD_HEIGHT < 16 || moveList[moveNum][0] <= 'Z')) { // drop move
          if(moveList[moveNum][0]== '@') snprintf(buf, MSG_SIZ, "@@@@\n"); else
          snprintf(buf, MSG_SIZ, "%c@%c%d%s", moveList[moveNum][0],
                                              moveList[moveNum][2], moveList[moveNum][3] - '0', moveList[moveNum]+4);
-       } else if(moveList[moveNum][4] == ';') { // [HGM] lion: move is double-step over intermediate square
-         snprintf(buf, MSG_SIZ, "%c%d%c%d,%c%d%c%d\n", moveList[moveNum][0], moveList[moveNum][1] - '0', // convert to two moves
-                                              moveList[moveNum][5], moveList[moveNum][6] - '0',
-                                              moveList[moveNum][5], moveList[moveNum][6] - '0',
-                                              moveList[moveNum][2], moveList[moveNum][3] - '0');
        } else
          snprintf(buf, MSG_SIZ, "%c%d%c%d%s", moveList[moveNum][0], moveList[moveNum][1] - '0',
                                               moveList[moveNum][2], moveList[moveNum][3] - '0', moveList[moveNum]+4);
@@ -5277,7 +5284,8 @@ ProcessICSInitScript (FILE *f)
 }
 
 
-static int lastX, lastY, lastLeftX, lastLeftY, selectFlag, dragging;
+static int lastX, lastY, lastLeftX, lastLeftY, selectFlag;
+int dragging;
 static ClickType lastClickType;
 
 void
@@ -5402,6 +5410,7 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro
       case WhiteNonPromotion:
       case BlackNonPromotion:
       case NormalMove:
+      case FirstLeg:
       case WhiteCapturesEnPassant:
       case BlackCapturesEnPassant:
       case WhiteKingSideCastle:
@@ -5435,7 +5444,8 @@ ParseOneMove (char *move, int moveNum, ChessMove *moveType, int *fromX, int *fro
        if (appData.testLegality) {
          return (*moveType != IllegalMove);
        } else {
-         return !(*fromX == *toX && *fromY == *toY) && boards[moveNum][*fromY][*fromX] != EmptySquare &&
+         return !(*fromX == *toX && *fromY == *toY && killX < 0) && boards[moveNum][*fromY][*fromX] != EmptySquare &&
+                        // [HGM] lion: if this is a double move we are less critical
                        WhiteOnMove(moveNum) == (boards[moveNum][*fromY][*fromX] < BlackPawn);
        }
 
@@ -7113,6 +7123,8 @@ MarkByFEN(char *fen)
        DrawPosition(TRUE, NULL);
 }
 
+static char baseMarker[BOARD_RANKS][BOARD_FILES], baseLegal[BOARD_RANKS][BOARD_FILES];
+
 void
 Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VOIDSTAR closure)
 {
@@ -7130,7 +7142,7 @@ MarkTargetSquares (int clear)
 {
   int x, y, sum=0;
   if(clear) { // no reason to ever suppress clearing
-    for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) sum += marker[y][x], marker[y][x] = 0;
+    for(x=0; x<BOARD_WIDTH; x++) for(y=0; y<BOARD_HEIGHT; y++) sum += marker[y][x], marker[y][x] = baseMarker[y][x] = 0;
     if(!sum) return; // nothing was cleared,no redraw needed
   } else {
     int capt = 0;
@@ -7180,10 +7192,8 @@ CanPromote (ChessSquare piece, int y)
 void
 HoverEvent (int xPix, int yPix, int x, int y)
 {
-       static char baseMarker[BOARD_RANKS][BOARD_FILES], baseLegal[BOARD_RANKS][BOARD_FILES];
        static int oldX = -1, oldY = -1, oldFromX = -1, oldFromY = -1;
        int r, f;
-       if(dragging == 2) DragPieceMove(xPix, yPix); // [HGM] lion: drag without button for second leg
        if(!first.highlight) return;
        if(fromX != oldFromX || fromY != oldFromY)  oldX = oldY = -1; // kludge to fake entry on from-click
        if(x == oldX && y == oldY) return; // only do something if we enter new square
@@ -7454,7 +7464,6 @@ LeftClick (ClickType clickType, int xPix, int yPix)
            return;
        }
        if(dragging == 2) {  // [HGM] lion: just turn buttonless drag into normal drag, and let release to the job
-           dragging = 1;
            return;
        }
        if(x == killX && y == killY) {              // second click on this square, which was selected as first-leg target
@@ -7502,9 +7511,9 @@ LeftClick (ClickType clickType, int xPix, int yPix)
          MarkTargetSquares(1);
          if(x == killX && y == killY) killX = killY = -1; else {
            killX = x; killY = y;     //remeber this square as intermediate
-           MarkTargetSquares(0);
            ReportClick("put", x, y); // and inform engine
            ReportClick("lift", x, y);
+           MarkTargetSquares(0);
            return;
          }
        }
@@ -8287,7 +8296,7 @@ HandleMachineMove (char *message, ChessProgramState *cps)
     char realname[MSG_SIZ];
     int fromX, fromY, toX, toY;
     ChessMove moveType;
-    char promoChar;
+    char promoChar, roar;
     char *p, *pv=buf1;
     int machineWhite, oldError;
     char *bookHit;
@@ -8449,8 +8458,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
          snprintf(buf1, MSG_SIZ*10, _("Illegal move \"%s\" from %s machine"),
                    machineMove, _(cps->which));
            DisplayMoveError(buf1);
-            snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c) res=%d",
-                    machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, moveType);
+            snprintf(buf1, MSG_SIZ*10, "Xboard: Forfeit due to invalid move: %s (%c%c%c%c via %c%c) res=%d",
+                    machineMove, fromX+AAA, fromY+ONE, toX+AAA, toY+ONE, killX+AAA, killY+ONE, moveType);
            if (gameMode == TwoMachinesPlay) {
              GameEnds(machineWhite ? BlackWins : WhiteWins,
                        buf1, GE_XBOARD);
@@ -8603,10 +8612,12 @@ if(appData.debugMode) fprintf(debugFP, "nodes = %d, %lld\n", (int) programStats.
            cps->other->maybeThinking = TRUE;
        }
 
+       roar = (killX >= 0 && IS_LION(boards[forwardMostMove][toY][toX]));
+
        ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/
 
         if (!pausing && appData.ringBellAfterMoves) {
-           RingBell();
+           if(!roar) RingBell();
        }
 
        /*
@@ -9497,6 +9508,7 @@ ParseGameHistory (char *game)
          case WhiteNonPromotion:
          case BlackNonPromotion:
          case NormalMove:
+         case FirstLeg:
          case WhiteCapturesEnPassant:
          case BlackCapturesEnPassant:
          case WhiteKingSideCastle:
@@ -10067,8 +10079,6 @@ MakeMove (int fromX, int fromY, int toX, int toY, int promoChar)
        strcat(parseList[forwardMostMove - 1], "#");
        break;
     }
-
-    killX = killY = -1; // [HGM] lion: used up
 }
 
 /* Updates currentMove if not pausing */
@@ -10088,6 +10098,8 @@ ShowMove (int fromX, int fromY, int toX, int toY)
        currentMove = forwardMostMove;
     }
 
+    killX = killY = -1; // [HGM] lion: used up
+
     if (instant) return;
 
     DisplayMove(currentMove - 1);
@@ -10897,7 +10909,7 @@ GameEnds (ChessMove result, char *resultDetails, int whosays)
              result, resultDetails ? resultDetails : "(null)", whosays);
     }
 
-    fromX = fromY = -1; // [HGM] abort any move the user is entering.
+    fromX = fromY = killX = killY = -1; // [HGM] abort any move the user is entering. // [HGM] lion
 
     if(pausing) PauseEvent(); // can happen when we abort a paused game (New Game or Quit)
 
@@ -11393,6 +11405,7 @@ Reset (int redraw, int init)
     ClearPremoveHighlights();
     gotPremove = FALSE;
     alarmSounded = FALSE;
+    killX = killY = -1; // [HGM] lion
 
     GameEnds(EndOfFile, NULL, GE_PLAYER);
     if(appData.serverMovesName != NULL) {
@@ -11573,6 +11586,7 @@ LoadGameOneMove (ChessMove readAhead)
       case WhiteNonPromotion:
       case BlackNonPromotion:
       case NormalMove:
+      case FirstLeg:
       case WhiteKingSideCastle:
       case WhiteQueenSideCastle:
       case BlackKingSideCastle:
@@ -11594,6 +11608,7 @@ LoadGameOneMove (ChessMove readAhead)
         toX = currentMoveString[2] - AAA;
         toY = currentMoveString[3] - ONE;
        promoChar = currentMoveString[4];
+       if(promoChar == ';') promoChar = NULLCHAR;
        break;
 
       case WhiteDrop:
@@ -11760,6 +11775,7 @@ LoadGameOneMove (ChessMove readAhead)
 
        thinkOutput[0] = NULLCHAR;
        MakeMove(fromX, fromY, toX, toY, promoChar);
+       killX = killY = -1; // [HGM] lion: used up
        currentMove = forwardMostMove;
        return TRUE;
     }
@@ -12257,6 +12273,7 @@ GameContainsPosition (FILE *f, ListGame *lg)
            case WhiteNonPromotion:
            case BlackNonPromotion:
            case NormalMove:
+           case FirstLeg:
            case WhiteKingSideCastle:
            case WhiteQueenSideCastle:
            case BlackKingSideCastle:
@@ -12321,6 +12338,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
     if (gameMode != BeginningOfGame) {
       Reset(FALSE, TRUE);
     }
+    killX = killY = -1; // [HGM] lion: in case we did not Reset
 
     gameFileFP = f;
     if (lastLoadGameFP != NULL && lastLoadGameFP != f) {
@@ -12474,6 +12492,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
            break;
 
          case NormalMove:
+         case FirstLeg:
            /* Only a NormalMove can be at the start of a game
             * without a position diagram. */
            if (lastLoadGameStart == EndOfFile ) {