Merge branch 'v4.8.x'
[xboard.git] / moves.c
diff --git a/moves.c b/moves.c
index bef359e..867a940 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -5,7 +5,8 @@
  * Massachusetts.
  *
  * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free
+ * Software Foundation, Inc.
  *
  * Enhancements Copyright 2005 Alessandro Scotti
  *
@@ -126,7 +127,7 @@ char
 PieceToChar (ChessSquare p)
 {
     int c;
-    if((int)p < 0 || (int)p >= (int)EmptySquare) return('x'); /* [HGM] for safety */
+    if((int)p < 0 || (int)p >= (int)EmptySquare) return('?'); /* [HGM] for safety */
     c = pieceToChar[(int) p];
     if(c & 128) c = c & 63 | 64;
     return c;
@@ -204,7 +205,7 @@ CollectPieceDescriptors ()
     // dump all engine defined pieces, and pieces with non-standard names,
     // but suppress black pieces that are the same as their white counterpart
     ChessSquare p;
-    static char buf[MSG_SIZ];
+    static char buf[MSG_SIZ], s[2];
     char *m, c, d, *pieceName = defaultName;
     int len;
     *buf = NULLCHAR;
@@ -215,21 +216,55 @@ CollectPieceDescriptors ()
     for(p=WhitePawn; p<EmptySquare; p++) {
        if((c = pieceToChar[p]) == '.' || c == '~') continue;  // does not participate
        m = pieceDesc[p]; d = (c == '+' ? pieceToChar[DEMOTED(p)] : c);
-       if(p >= BlackPawn && pieceToChar[BLACK_TO_WHITE p] == toupper(c)
+       if(p >= BlackPawn && pieceToChar[BLACK_TO_WHITE p] == (c & ~32)
              && (c != '+' || pieceToChar[DEMOTED(BLACK_TO_WHITE p)] == d)) {// black member of normal pair
            char *wm = pieceDesc[BLACK_TO_WHITE p];
            if(!m && !wm || m && wm && !strcmp(wm, m)) continue;            // moves as a white piece
        } else                                                              // white or unpaired black
-       if((p < BlackPawn || CharToPiece(toupper(d)) != EmptySquare) &&     // white or lone black
+       if((p < BlackPawn || CharToPiece(d & ~32) != EmptySquare) &&        // white or lone black
           !pieceDesc[p] /*&& pieceName[p] == c*/) continue; // orthodox piece known by its usual name
 // TODO: listing pieces because of unusual name can only be done if we have accurate Betza of all defaults
        if(!m) m = defaultDesc[p];
+       if(!m) continue;
        len = strlen(buf);
-       snprintf(buf+len, MSG_SIZ-len, "%s%s%c:%s", len ? ";" : "", c == '+' ? "+" : "", d, m);
+       *s = (d > 128 ? SUFFIXES[d-128>>6] : 0); d = 64 + (d & 63);
+       snprintf(buf+len, MSG_SIZ-len, "%s%s%c%s:%s", len ? ";" : "", c == '+' ? "+" : "", d, s, m);
     }
     return buf;
 }
 
+int
+LoadPieceDesc (char *s)
+{
+    ChessSquare piece;
+    static char suf[] = SUFFIXES;
+    char *r, *p, *q = s;
+    int ok = TRUE, promoted, c;
+    while(q && *s) {
+       p = s;
+       q = strchr(s, ';');
+       if(q) *q = 0, s = q+1;
+       if(*p == '+') promoted = 1, p++; else promoted = 0;
+       c = *p++;
+       if(!c) { ok = FALSE; continue; } // bad syntax
+       if(*p && (r = strchr(suf, *p))) c += 64*(r - suf + 1), p++;
+       if(*p++ != ':') { ok = FALSE; continue; } // bad syntax
+       if(!strcmp(p, "(null)")) continue; // handle bug in writing of XBoard 4.8.0
+        piece = CharToPiece(c);
+       if(piece >= EmptySquare) { ok = FALSE; continue; } // non-existent piece
+       if(promoted) {
+           piece = promoPartner[piece];
+           if(pieceToChar[piece] != '+') { ok = FALSE; continue; } // promoted form does not exist
+       }
+       ASSIGN(pieceDesc[piece], p);
+       if(piece < BlackPawn && (pieceToChar[WHITE_TO_BLACK piece] == pieceToChar[piece] + 32 || promoted)) {
+           ASSIGN(pieceDesc[WHITE_TO_BLACK piece], p);
+       }
+       pieceDefs = TRUE;
+    }
+    return ok;
+}
+
 // [HGM] gen: configurable move generation from Betza notation sent by engine.
 // Some notes about two-leg moves: GenPseudoLegal() works in two modes, depending on whether a 'kill-
 // square has been set: without one is generates all moves, and a global int legNr flags in bits 0 and 1
@@ -2414,7 +2449,10 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p
        int r, f;
       for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<=BOARD_RGHT; f++)
                c += (board[r][f] == piece); // count on-board pieces of given type
-       *outp++ = ToUpper(PieceToChar(piece));
+        *outp = PieceToChar(piece);
+        if(*outp == '+') outp++, piece = CHUDEMOTED(piece);
+        *outp++ = ToUpper(PieceToChar(piece));
+        if(*outp = PieceSuffix(piece)) outp++;
     }
   if(c != 1) { // [HGM] but if there is only one piece of the mentioned type, no from-square, thank you!
     *outp++ = ff + AAA;