Fix spurious promotion partners
[xboard.git] / backend.c
index da945a6..b956f94 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5395,6 +5395,7 @@ Partner (ChessSquare *p)
 { // change piece into promotion partner if one shogi-promotes to the other
   ChessSquare partner = promoPartner[*p];
   if(PieceToChar(*p) != '+' && PieceToChar(partner) != '+') return 0;
+  if(PieceToChar(*p) == '+') partner = boards[currentMove][fromY][fromX];
   *p = partner;
   return 1;
 }
@@ -6002,19 +6003,10 @@ ptclen (const char *s, char *escapes)
 {
     int n = 0;
     if(!*escapes) return strlen(s);
-    while(*s) n += (*s != '-' && *s != '^' && *s != '*' && !strchr(escapes, *s)), s++;
+    while(*s) n += (*s != '/' && *s != '-' && *s != '^' && *s != '*' && !strchr(escapes, *s)), s++;
     return n;
 }
 
-static int pieceOrder[] = {
-  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, // P N B R Q F E A C W M
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, // O H I J G D V L S U Lion
- 45, 23, 24, 25, 26, 27, 28, 29, 46, 31, 32, // Sword Zebra Camel Tower Wolf Dragon Duck Axe Leopard Gnu Cub
- 44, 51, 56, 57, 58, 59, 60, 61, 62, 63, 34, // Whale Pegasus Wizard Copper Iron Viking Flag Amazon Wheel Shield Claw
- 33, 55, 53, 42, 37, 48, 39, 40, 41, 22, 30, // +P +N =B =R +L +S +E +Ph +Kn Butterfly Hat
- 38, 43, 35, 36, 49, 47, 52, 50, 54, 64, 65 // +V +M =H =D Princess HSword +GB HCrown Wheer Shierd King
-};
-
 int
 SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
 /* [HGM] moved here from winboard.c because of its general usefulness */
@@ -6025,25 +6017,26 @@ SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
 
     if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare
                     && NrPieces >= 12 && !(NrPieces&1)) {
-        int i, ii, j = 0; /* [HGM] Accept even length from 12 to 88 */
+        int i, ii, offs, j = 0; /* [HGM] Accept even length from 12 to 88 */
 
         for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';
-        for( ii=0; ii<NrPieces/2-1; ii++ ) {
+        for( i=offs=0; i<NrPieces/2-1; i++ ) {
             char *p, c=0;
-            i = pieceOrder[ii];
+            if(map[j] == '/') offs = WhitePBishop - i, j++;
             if(*escapes && (map[j] == '*' || map[j] == '-' || map[j] == '^')) c = map[j++];
-            table[i] = map[j++];
-            if(p = strchr(escapes, map[j])) j++, table[i] += 64*(p - escapes + 1);
-            if(c) partner[i] = table[i], table[i] = c;
+            table[i+offs] = map[j++];
+            if(p = strchr(escapes, map[j])) j++, table[i+offs] += 64*(p - escapes + 1);
+            if(c) partner[i+offs] = table[i+offs], table[i+offs] = c;
         }
         table[(int) WhiteKing]  = map[j++];
-        for( ii=0; ii<NrPieces/2-1; ii++ ) {
+        for( ii=offs=0; ii<NrPieces/2-1; ii++ ) {
             char *p, c=0;
-            i = WHITE_TO_BLACK pieceOrder[ii];
+            if(map[j] == '/') offs = WhitePBishop - ii, j++;
+            i = WHITE_TO_BLACK ii;
             if(*escapes && (map[j] == '*' || map[j] == '-' || map[j] == '^')) c = map[j++];
-            table[i] = map[j++];
-            if(p = strchr(escapes, map[j])) j++, table[i] += 64*(p - escapes + 1);
-            if(c) partner[i] = table[i], table[i] = c;
+            table[i+offs] = map[j++];
+            if(p = strchr(escapes, map[j])) j++, table[i+offs] += 64*(p - escapes + 1);
+            if(c) partner[i+offs] = table[i+offs], table[i+offs] = c;
         }
         table[(int) BlackKing]  = map[j++];
 
@@ -6057,8 +6050,15 @@ SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
                     int p;
                     for(p=0; p<EmptySquare; p++) if(table[p] == partner[i]) break;
                     if(c == '^') table[i] = '+';
-                    if(p < EmptySquare) promoPartner[p] = i, promoPartner[i] = p; // marry them
-                } else if(c == '*') promoPartner[i] = (i < BlackPawn ? WhiteTokin : BlackTokin); // promotes to Tokin
+                    if(p < EmptySquare) {
+                        if(promoPartner[promoPartner[p]] == p) promoPartner[promoPartner[p]] = promoPartner[p]; // divorce old partners
+                        if(promoPartner[promoPartner[i]] == i) promoPartner[promoPartner[i]] = promoPartner[i];
+                        promoPartner[p] = i, promoPartner[i] = p; // and marry this couple
+                    }
+                } else if(c == '*') {
+                    table[i] = partner[i];
+                    promoPartner[i] = (i < BlackPawn ? WhiteTokin : BlackTokin); // promotes to Tokin
+                }
             }
         }
 
@@ -6247,8 +6247,8 @@ InitPosition (int redraw)
       gameInfo.boardWidth  = 12;
       gameInfo.boardHeight = 12;
       nrCastlingRights = 0;
-      SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN/^P.^B^R.^S^E^X^O^G^C^A^T^H^D.^V^M^L^I^FK"
-                                   "p.brqsexogcathd.vmlifn/^p.^b^r.^s^e^x^o^g^c^a^t^h^d.^v^m^l^i^fk", SUFFIXES);
+      SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN.........^T..^L......^A^H/^F^G^M.^E^X^O^I.^P.^B^R..^D^S^C^VK"
+                                   "p.brqsexogcathd.vmlifn.........^t..^l......^a^h/^f^g^m.^e^x^o^i.^p.^b^r..^d^s^c^vk", SUFFIXES);
       break;
     case VariantCourier:
       pieces = CourierArray;
@@ -7071,11 +7071,9 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar)
            return;
        } else if (toX >= 0 && toY >= 0) {
            if(!appData.pieceMenu && toX == fromX && toY == fromY && boards[0][rf][ff] != EmptySquare) {
-               ChessSquare q, p = boards[0][rf][ff];
-               if(p >= BlackPawn) p = BLACK_TO_WHITE p;
-               if(CHUPROMOTED(p) < BlackPawn) p = q = CHUPROMOTED(boards[0][rf][ff]);
-               else p = CHUDEMOTED (q = boards[0][rf][ff]);
-               if(PieceToChar(q) == '+') gatingPiece = p;
+               ChessSquare p = boards[0][rf][ff];
+               if(PieceToChar(p) == '+') gatingPiece = CHUDEMOTED(p); else
+               if(PieceToChar(CHUPROMOTED(p)) =='+') gatingPiece = CHUPROMOTED(p); 
            }
            boards[0][toY][toX] = boards[0][fromY][fromX];
            if(fromX == BOARD_LEFT-2) { // handle 'moves' out of holdings
@@ -7091,6 +7089,7 @@ UserMoveEvent(int fromX, int fromY, int toX, int toY, int promoChar)
                }
            } else
            boards[0][fromY][fromX] = gatingPiece;
+           ClearHighlights();
            DrawPosition(FALSE, boards[currentMove]);
            return;
        }
@@ -7788,6 +7787,8 @@ LeftClick (ClickType clickType, int xPix, int yPix)
            ClearHighlights();
        }
 #endif
+       if(PieceToChar(CHUPROMOTED(boards[currentMove][fromY][fromX])) == '+')
+         defaultPromoChoice = CHUPROMOTED(boards[currentMove][fromY][fromX]);
        if(gameInfo.variant == VariantChuChess && piece != WhitePawn && piece != BlackPawn) defaultPromoChoice = piece;
        if(marker[y][x] == 5) { // [HGM] lion: this was the release of a to-click or drag on a cyan square
          dragging *= 2;            // flag button-less dragging if we are dragging
@@ -9084,7 +9085,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
       return;
     }
     if(sscanf(message, "choice %s", promoRestrict) == 1 && promoSweep != EmptySquare) {
-      promoSweep = PieceToChar(forwardMostMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict));
+      promoSweep = CharToPiece(currentMove&1 ? ToLower(*promoRestrict) : ToUpper(*promoRestrict));
       Sweep(0);
       return;
     }