Use flexible promotion assignment
authorH.G.Muller <hgm@hgm-xboard.(none)>
Sat, 30 Jan 2016 08:09:03 +0000 (09:09 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Sat, 30 Jan 2016 08:09:03 +0000 (09:09 +0100)
The promoted partner now comes from an array, rather than by adding
a constant (11, or 27 in chu) to the base type. The array is initialized
so the first 11 pieces (the old 'base pieces') point to the second 11
(the old 'promoted series'), and the latter point back (so the array
also contains the demotions!). The pieces above 21 (= Lion) point to
themselves.
  Parsing of the pieceToChar string now considers ^, - and * prefixes
rather than independent IDs. Nevertheless it is the - and ^ that get
stored in the pieceToCharTable (the latter as '+') for the corresponding
piece. But the ID that follows them specifies what other piece they are
the demoted or promoted partner of, rather than their own ID, and is
thus used to update the promoPartner array for both of them.
  A * prefix does mean the following ID is the ID assigned to the piece,
but that the piece promotes to Tokin (if the latter is assigned a '+').
  The default pieceToChar string for varaint chu is adapted to use this
new assignment mechanism of promotion partner. (Chu is so far the only
variant that needed other pairing than the default.)

backend.c
common.h
moves.c
moves.h

index 8a47479..58905cb 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -5383,9 +5383,7 @@ static ClickType lastClickType;
 int
 Partner (ChessSquare *p)
 { // change piece into promotion partner if one shogi-promotes to the other
-  int stride = gameInfo.variant == VariantChu ? WhiteTokin : 11;
-  ChessSquare partner;
-  partner = (*p/stride & 1 ? *p - stride : *p + stride);
+  ChessSquare partner = promoPartner[*p];
   if(PieceToChar(*p) != '+' && PieceToChar(partner) != '+') return 0;
   *p = partner;
   return 1;
@@ -5994,7 +5992,7 @@ ptclen (const char *s, char *escapes)
 {
     int n = 0;
     if(!*escapes) return strlen(s);
-    while(*s) n += (*s != '/' && !strchr(escapes, *s)), s++;
+    while(*s) n += (*s != '/' && *s != '-' && *s != '^' && *s != '*' && !strchr(escapes, *s)), s++;
     return n;
 }
 
@@ -6004,6 +6002,7 @@ SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
 /*       Basically a safe strcpy that uses the last character as King */
 {
     int result = FALSE; int NrPieces, offs;
+    unsigned char partner[EmptySquare];
 
     if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare
                     && NrPieces >= 12 && !(NrPieces&1)) {
@@ -6011,20 +6010,39 @@ SetCharTableEsc (unsigned char *table, const char * map, char * escapes)
 
         for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.';
         for( i=offs=0; i<NrPieces/2-1; i++ ) {
-            char *p;
+            char *p, c=0;
             if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
+            if(*escapes && (map[j] == '*' || map[j] == '-' || map[j] == '^')) c = map[j++];
             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( i=offs=0; i<NrPieces/2-1; i++ ) {
-            char *p;
+            char *p, c=0;
             if(map[j] == '/' && *escapes) offs = WhiteTokin - i, j++;
+            if(*escapes && (map[j] == '*' || map[j] == '-' || map[j] == '^')) c = map[j++];
             table[WHITE_TO_BLACK i + offs] = map[j++];
             if(p = strchr(escapes, map[j])) j++, table[WHITE_TO_BLACK i + offs] += 64*(p - escapes + 1);
+            if(c) partner[WHITE_TO_BLACK i + offs] = table[WHITE_TO_BLACK i + offs], table[WHITE_TO_BLACK i + offs] = c;
         }
         table[(int) BlackKing]  = map[j++];
 
+
+        if(*escapes) { // set up promotion pairing
+            for( i=0; i<(int) EmptySquare; i++ ) promoPartner[i] = (i%BlackPawn < 11 ? i + 11 : i%BlackPawn < 22 ? i - 11 : i); // default
+            // pieceToChar entirely filled, so we can look up specified partners
+            for(i=0; i<EmptySquare; i++) { // adjust promotion pairing
+                int c = table[i];
+                if(c == '^' || c == '-') { // has specified partner
+                    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
+            }
+        }
+
         result = TRUE;
     }
 
@@ -6117,7 +6135,7 @@ InitPosition (int redraw)
       initialPosition[CASTLING][i] = initialRights[i] = NoRights; /* but no rights yet */
     initialPosition[EP_STATUS] = EP_NONE;
     initialPosition[TOUCHED_W] = initialPosition[TOUCHED_B] = 0;
-    SetCharTable(pieceToChar, "PNBRQ...........Kpnbrq...........k");
+    SetCharTableEsc(pieceToChar, "PNBRQ...........Kpnbrq...........k", SUFFIXES);
     if(startVariant == gameInfo.variant) // [HGM] nicks: enable nicknames in original variant
          SetCharTable(pieceNickName, appData.pieceNickNames);
     else SetCharTable(pieceNickName, "............");
@@ -6210,8 +6228,8 @@ InitPosition (int redraw)
       gameInfo.boardWidth  = 12;
       gameInfo.boardHeight = 12;
       nrCastlingRights = 0;
-      SetCharTableEsc(pieceToChar, "P.BRQSEXOGCATHD.VMLIFN/+.++.++++++++++.+++++K"
-                                   "p.brqsexogcathd.vmlifn/+.++.++++++++++.+++++k", SUFFIXES);
+      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);
       break;
     case VariantCourier:
       pieces = CourierArray;
@@ -6630,9 +6648,8 @@ HasPromotionChoice (int fromX, int fromY, int toX, int toY, char *promoChoice, i
 
     piece = boards[currentMove][fromY][fromX];
     if(gameInfo.variant == VariantChu) {
-        int p = piece >= BlackPawn ? BLACK_TO_WHITE piece : piece;
         promotionZoneSize = BOARD_HEIGHT/3;
-        highestPromotingPiece = (p >= WhiteTokin || PieceToChar(piece + WhiteTokin) != '+') ? WhitePawn : WhiteTokin-1;
+        highestPromotingPiece = (PieceToChar(piece) == '+' || PieceToChar(CHUPROMOTED(piece)) != '+') ? WhitePawn : WhiteKing;
     } else if(gameInfo.variant == VariantShogi) {
         promotionZoneSize = BOARD_HEIGHT/3 +(BOARD_HEIGHT == 8);
         highestPromotingPiece = (int)WhiteAlfil;
index 498bf38..6ba5774 100644 (file)
--- a/common.h
+++ b/common.h
@@ -320,11 +320,12 @@ typedef enum {
 /* [HGM] some macros that can be used as prefixes to convert piece types */
 #define WHITE_TO_BLACK (int)BlackPawn - (int)WhitePawn + (int)
 #define BLACK_TO_WHITE (int)WhitePawn - (int)BlackPawn + (int)
-#define PROMOTED       (int)WhiteDragon - (int)WhiteRook + (int)
-#define DEMOTED        (int)WhiteRook - (int)WhiteDragon + (int)
+#define PROMO          (int)WhiteDragon - (int)WhiteRook + (int)
+#define PROMOTED(X)    (promoPartner[X])
+#define DEMOTED(X)     (promoPartner[X])
 #define SHOGI          (int)EmptySquare + (int)
-#define CHUPROMOTED    ((int)WhitePDragon - (int)WhiteDragon)*(gameInfo.variant == VariantChu) + PROMOTED
-#define CHUDEMOTED     ((int)WhiteDragon - (int)WhitePDragon)*(gameInfo.variant == VariantChu) + DEMOTED
+#define CHUPROMOTED(X) (promoPartner[X])
+#define CHUDEMOTED(X)  (promoPartner[X])
 #define IS_SHOGI(V)    ((V) == VariantShogi || (V) == VariantChu)
 #define IS_LION(V)     ((V) == WhiteLion || (V) == BlackLion)
 
diff --git a/moves.c b/moves.c
index d0cc65c..68bf107 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -121,6 +121,7 @@ unsigned char pieceToChar[EmptySquare+1] = {
                         'o', 'h', 'i', 'j', 'g', 'd', 'v', 'l', 's', 'u', 'k',
                         'x' };
 unsigned char pieceNickName[EmptySquare];
+int promoPartner[EmptySquare];
 
 char
 PieceToChar (ChessSquare p)
diff --git a/moves.h b/moves.h
index aeb6307..674d56e 100644 (file)
--- a/moves.h
+++ b/moves.h
@@ -63,6 +63,7 @@ extern void CopyBoard P((Board to, Board from));
 extern int CompareBoards P((Board board1, Board board2));
 extern unsigned char pieceToChar[(int)EmptySquare+1];
 extern unsigned char pieceNickName[(int)EmptySquare];
+extern int promoPartner[(int)EmptySquare];
 extern char *pieceDesc[(int)EmptySquare];
 extern Board initialPosition;
 extern Boolean pieceDefs;