Allow promotion choice in variant asean
[xboard.git] / backend.c
index d23ddfb..e68b3af 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -848,7 +848,7 @@ InitEngine (ChessProgramState *cps, int n)
     if(cps->tidy == NULL) cps->tidy = (char*) malloc(MSG_SIZ);
     TidyProgramName(cps->program, cps->host, cps->tidy);
     cps->matchWins = 0;
-    ASSIGN(cps->variants, appData.variant);
+    ASSIGN(cps->variants, appData.noChessProgram ? "" : appData.variant);
     cps->analysisSupport = 2; /* detect */
     cps->analyzing = FALSE;
     cps->initDone = FALSE;
@@ -1202,7 +1202,7 @@ InitBackEnd1 ()
        return;
 
       case VariantNormal:     /* definitely works! */
-       if(strcmp(appData.variant, "normal") && appData.chessProgram) { // [HGM] hope this is an engine-defined variant
+       if(strcmp(appData.variant, "normal") && !appData.noChessProgram) { // [HGM] hope this is an engine-defined variant
          safeStrCpy(engineVariant, appData.variant, MSG_SIZ);
          return;
        }
@@ -2108,14 +2108,14 @@ StringToVariant (char *e)
     int wnum = -1;
     VariantClass v = VariantNormal;
     int i, found = FALSE;
-    char buf[MSG_SIZ];
+    char buf[MSG_SIZ], c;
     int len;
 
     if (!e) return v;
 
     /* [HGM] skip over optional board-size prefixes */
-    if( sscanf(e, "%dx%d_", &i, &i) == 2 ||
-        sscanf(e, "%dx%d+%d_", &i, &i, &i) == 3 ) {
+    if( sscanf(e, "%dx%d_%c", &i, &i, &c) == 3 ||
+        sscanf(e, "%dx%d+%d_%c", &i, &i, &i, &c) == 4 ) {
         while( *e++ != '_');
     }
 
@@ -2125,7 +2125,7 @@ StringToVariant (char *e)
     } else
     for (i=0; i<sizeof(variantNames)/sizeof(char*); i++) {
       if (p = StrCaseStr(e, variantNames[i])) {
-       if(p && i >= VariantShogi && isalpha(p[strlen(variantNames[i])])) continue;
+       if(p && i >= VariantShogi && (p != e || isalpha(p[strlen(variantNames[i])]))) continue;
        v = (VariantClass) i;
        found = TRUE;
        break;
@@ -5221,7 +5221,7 @@ SendMoveToICS (ChessMove moveType, int fromX, int fromY, int toX, int toY, char
       case WhitePromotion:
       case BlackPromotion:
         if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-           gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
+           gameInfo.variant == VariantMakruk)
          snprintf(user_move, MSG_SIZ, "%c%c%c%c=%c\n",
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,
                PieceToChar(WhiteFerz));
@@ -5328,6 +5328,7 @@ UploadGameEvent ()
 }
 
 int killX = -1, killY = -1; // [HGM] lion: used for passing e.p. capture square to MakeMove
+int legNr = 1;
 
 void
 CoordsToComputerAlgebraic (int rf, int ff, int rt, int ft, char promoChar, char move[7])
@@ -6515,8 +6516,10 @@ DefaultPromoChoice (int white)
 {
     ChessSquare result;
     if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-       gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN)
+       gameInfo.variant == VariantMakruk)
        result = WhiteFerz; // no choice
+    else if(gameInfo.variant == VariantASEAN)
+       result = WhiteRook; // no choice
     else if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway)
        result= WhiteKing; // in Suicide Q is the last thing we want
     else if(gameInfo.variant == VariantSpartan)
@@ -6608,7 +6611,7 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i
 
     // we either have a choice what to promote to, or (in Shogi) whether to promote
     if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-       gameInfo.variant == VariantMakruk || gameInfo.variant == VariantASEAN) {
+       gameInfo.variant == VariantMakruk) {
        ChessSquare p=BlackFerz;  // no choice
        while(p < EmptySquare) {  //but make sure we use piece that exists
            *promoChoice = PieceToChar(p++);
@@ -7263,7 +7266,7 @@ Mark (Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, VO
 {
     typedef char Markers[BOARD_RANKS][BOARD_FILES];
     Markers *m = (Markers *) closure;
-    if(rf == fromY && ff == fromX && (killX < 0 && !(rt == rf && ft == ff) || abs(ft-killX) < 2 && abs(rt-killY) < 2))
+    if(rf == fromY && ff == fromX && (killX < 0 ? !(rt == rf && ft == ff) && legNr & 1 : rt == killY && ft == killX || legNr & 2))
        (*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare
                         || kind == WhiteCapturesEnPassant
                         || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && killX < 0), legal[rt][ft] = 1;
@@ -7319,7 +7322,7 @@ CanPromote (ChessSquare piece, int y)
        if(IS_SHOGI(gameInfo.variant)          || gameInfo.variant == VariantXiangqi ||
           gameInfo.variant == VariantSuper    || gameInfo.variant == VariantGreat   ||
           gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier ||
-         gameInfo.variant == VariantMakruk   || gameInfo.variant == VariantASEAN) return FALSE;
+         gameInfo.variant == VariantMakruk) return FALSE;
        return (piece == BlackPawn && y <= zone ||
                piece == WhitePawn && y >= BOARD_HEIGHT-1-zone ||
                piece == BlackLance && y == 1 ||
@@ -8892,19 +8895,23 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
       if(startedFromSetupPosition) return;
       ParseFEN(boards[0], &dummy, message+s, FALSE);
       DrawPosition(TRUE, boards[0]);
+      CopyBoard(initialPosition, boards[0]);
       startedFromSetupPosition = TRUE;
       return;
     }
     if(sscanf(message, "piece %s %s", buf2, buf1) == 2) {
       ChessSquare piece = WhitePawn;
       char *p=buf2;
+      if(*p == '+') piece = CHUPROMOTED WhitePawn, p++;
+      piece += CharToPiece(*p) - WhitePawn;
       if(cps != &first || appData.testLegality && *engineVariant == NULLCHAR
+      /* always accept definition of  */       && piece != WhiteFalcon && piece != BlackFalcon
+      /* wild-card pieces.            */       && piece != WhiteCobra  && piece != BlackCobra
       /* For variants we don't have   */       && gameInfo.variant != VariantBerolina
       /* correct rules for, we cannot */       && gameInfo.variant != VariantCylinder
       /* enforce legality on our own! */       && gameInfo.variant != VariantUnknown
+                                               && gameInfo.variant != VariantGreat
                                                && gameInfo.variant != VariantFairy    ) return;
-      if(*p == '+') piece = CHUPROMOTED WhitePawn, p++;
-      piece += CharToPiece(*p) - WhitePawn;
       if(piece < EmptySquare) {
         pieceDefs = TRUE;
         ASSIGN(pieceDesc[piece], buf1);
@@ -12853,7 +12860,7 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
        if (!err) numPGNTags++;
 
         /* [HGM] PGNvariant: automatically switch to variant given in PGN tag */
-        if(gameInfo.variant != oldVariant) {
+        if(gameInfo.variant != oldVariant && (gameInfo.variant != VariantNormal || gameInfo.variantName == NULL || *gameInfo.variantName == NULLCHAR)) {
             startedFromPositionFile = FALSE; /* [HGM] loadPos: variant switch likely makes position invalid */
            ResetFrontEnd(); // [HGM] might need other bitmaps. Cannot use Reset() because it clears gameInfo :-(
            InitPosition(TRUE);
@@ -12872,6 +12879,8 @@ LoadGame (FILE *f, int gameNumber, char *title, int useList)
            return FALSE;
          }
          CopyBoard(boards[0], initial_position);
+         if(*engineVariant) // [HGM] for now, assume FEN in engine-defined variant game is default initial position
+           CopyBoard(initialPosition, initial_position);
          if (blackPlaysFirst) {
            currentMove = forwardMostMove = backwardMostMove = 1;
            CopyBoard(boards[1], initial_position);
@@ -15074,6 +15083,8 @@ EditPositionMenuEvent (ChessSquare selection, int x, int y)
 
     switch (selection) {
       case ClearBoard:
+       fromX = fromY = killX = killY = -1; // [HGM] abort any move entry in progress
+       MarkTargetSquares(1);
        CopyBoard(currentBoard, boards[0]);
        CopyBoard(menuBoard, initialPosition);
        if (gameMode == IcsExamining && ics_type == ICS_FICS) {
@@ -17864,7 +17875,7 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts)
             q = (boards[move][CASTLING][1] == BOARD_LEFT &&
                  boards[move][CASTLING][2] != NoRights  );
             if(handW) { // for S-Chess with pieces in hand, list virgin pieces between K and Q
-                for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q && j; i--)
+                for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--)
                     if((boards[move][0][i] != WhiteKing || k+q == 0) &&
                         boards[move][VIRGIN][i] & VIRGIN_W) *p++ = i + AAA + 'A' - 'a';
             }
@@ -17875,7 +17886,7 @@ PositionToFEN (int move, char *overrideCastling, int moveCounts)
             q = (boards[move][CASTLING][4] == BOARD_LEFT &&
                  boards[move][CASTLING][5] != NoRights  );
             if(handB) {
-                for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q && j; i--)
+                for(i=BOARD_RGHT-1-k; i>=BOARD_LEFT+q; i--)
                     if((boards[move][BOARD_HEIGHT-1][i] != BlackKing || k+q == 0) &&
                         boards[move][VIRGIN][i] & VIRGIN_B) *p++ = i + AAA;
             }