From: H.G.Muller Date: Thu, 5 Mar 2015 14:58:56 +0000 (+0100) Subject: Implement piece suffixes X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=0bf664e507241790adc9f419b24be4d1d5963b28;p=xboard.git Implement piece suffixes The piece ID can now be suffixed with an 'ornament', which then is considered part of the piece ID. This expands the number of pieces that can be indicated in FEN or SAN to several times the alphabet. This does not yet work in a promotion suffix, as it is mainly intended for the large Shogi variants, which only use + as promotion suffix. It also does not work on King (which deserves an unadulterated letter). Currently the ornaments ' (single quote) and ! (exclamation point) are defined, (through a macro SUFFIXES in moves.h), increasing the number of piece types that can be represented to 78. --- diff --git a/backend.c b/backend.c index a75a87a..9c734eb 100644 --- a/backend.c +++ b/backend.c @@ -5947,37 +5947,38 @@ SetUpShuffle (Board board, int number) } int -ptclen (const char *s) +ptclen (const char *s, char *escapes) { int n = 0; - while(*s) n += (*s != '\'' && *s != '"' && *s != '`' && *s != '!'), s++; + if(!*escapes) return strlen(s); + while(*s) n += (*s != ':' && !strchr(escapes, *s)), s++; return n; } int -SetCharTable (char *table, const char * map) +SetCharTableEsc (unsigned char *table, const char * map, char * escapes) /* [HGM] moved here from winboard.c because of its general usefulness */ /* Basically a safe strcpy that uses the last character as King */ { int result = FALSE; int NrPieces; - if( map != NULL && (NrPieces=ptclen(map)) <= (int) EmptySquare + if( map != NULL && (NrPieces=ptclen(map, escapes)) <= (int) EmptySquare && NrPieces >= 12 && !(NrPieces&1)) { int i, j = 0; /* [HGM] Accept even length from 12 to 88 */ for( i=0; i<(int) EmptySquare; i++ ) table[i] = '.'; for( i=0; i~' (Crazyhouse) */ p[-1] = PieceToChar((ChessSquare)(CHUDEMOTED piece)); @@ -18083,13 +18091,20 @@ ParseFEN (Board board, int *blackPlaysFirst, char *fen, Boolean autoSize) if (i != 0 && i != BOARD_HEIGHT-1) return FALSE; // only on back-rank board[i][(j++)+gameInfo.holdingsWidth] = ClearBoard; p++; subst++; // placeHolder } else if (*p == '+' || isalpha(*p)) { + char *q, *s = SUFFIXES; if (j >= gameInfo.boardWidth) return FALSE; if(*p=='+') { - piece = CharToPiece(*++p); + char c = *++p; + if(q = strchr(s, p[1])) p++; + piece = CharToPiece(c + (q ? 64*(q - s + 1) : 0)); if(piece == EmptySquare) return FALSE; /* unknown piece */ piece = (ChessSquare) (CHUPROMOTED piece ); p++; if(PieceToChar(piece) != '+') return FALSE; /* unpromotable piece */ - } else piece = CharToPiece(*p++); + } else { + char c = *p++; + if(q = strchr(s, *p)) p++; + piece = CharToPiece(c + (q ? 64*(q - s + 1) : 0)); + } if(piece==EmptySquare) return FALSE; /* unknown piece */ if(*p == '~') { /* [HGM] make it a promoted piece for Crazyhouse */ diff --git a/moves.c b/moves.c index 75772a4..a66c2e0 100644 --- a/moves.c +++ b/moves.c @@ -114,19 +114,32 @@ SameColor (ChessSquare piece1, ChessSquare piece2) #define SameColor(piece1, piece2) (piece1 < EmptySquare && piece2 < EmptySquare && (piece1 < BlackPawn) == (piece2 < BlackPawn) || piece1 == DarkSquare || piece2 == DarkSquare) #endif -char pieceToChar[] = { +unsigned char pieceToChar[EmptySquare+1] = { 'P', 'N', 'B', 'R', 'Q', 'F', 'E', 'A', 'C', 'W', 'M', 'O', 'H', 'I', 'J', 'G', 'D', 'V', 'L', 'S', 'U', 'K', 'p', 'n', 'b', 'r', 'q', 'f', 'e', 'a', 'c', 'w', 'm', 'o', 'h', 'i', 'j', 'g', 'd', 'v', 'l', 's', 'u', 'k', 'x' }; -char pieceNickName[EmptySquare]; +unsigned char pieceNickName[EmptySquare]; char PieceToChar (ChessSquare p) { + int c; if((int)p < 0 || (int)p >= (int)EmptySquare) return('x'); /* [HGM] for safety */ - return pieceToChar[(int) p]; + c = pieceToChar[(int) p]; + if(c & 128) c = c & 63 | 64; + return c; +} + +char +PieceSuffix (ChessSquare p) +{ + int c; + if((int)p < 0 || (int)p >= (int)EmptySquare) return 0; /* [HGM] for safety */ + c = pieceToChar[(int) p]; + if(c < 128) return 0; + return SUFFIXES[c - 128 >> 6]; } int @@ -2339,6 +2352,7 @@ CoordsToAlgebraic (Board board, int flags, int rf, int ff, int rt, int ft, int p } if(c=='+') *outp++ = c; *outp++ = ToUpper(PieceToChar(piece)); + if(*outp = PieceSuffix(piece)) outp++; if (cl.file || (cl.either && !cl.rank)) { *outp++ = ff + AAA; diff --git a/moves.h b/moves.h index 6be5299..c162ffa 100644 --- a/moves.h +++ b/moves.h @@ -51,16 +51,19 @@ *------------------------------------------------------------------------ ** See the file ChangeLog for a revision history. */ +#define SUFFIXES "'!" + extern ChessSquare PromoPiece P((ChessMove moveType)); extern ChessMove PromoCharToMoveType P((int whiteOnMove, int promoChar)); extern char PieceToChar P((ChessSquare p)); +extern char PieceSuffix P((ChessSquare p)); extern ChessSquare CharToPiece P((int c)); extern int PieceToNumber P((ChessSquare p)); extern void CopyBoard P((Board to, Board from)); extern int CompareBoards P((Board board1, Board board2)); -extern char pieceToChar[(int)EmptySquare+1]; -extern char pieceNickName[(int)EmptySquare]; +extern unsigned char pieceToChar[(int)EmptySquare+1]; +extern unsigned char pieceNickName[(int)EmptySquare]; extern char *pieceDesc[(int)EmptySquare]; extern Board initialPosition; extern Boolean pieceDefs; diff --git a/parser.c b/parser.c index 496fef1..13caa9f 100644 --- a/parser.c +++ b/parser.c @@ -418,7 +418,10 @@ NextUnit (char **p) if(**p == '+') (*p)++, promoted++; if(**p >= 'a' && **p <= 'z' && (*p)[1]== '@') piece =*(*p)++ + 'A' - 'a'; else if(**p >= 'A' && **p <= 'Z') { + static char s[] = SUFFIXES; + char *q; piece = *(*p)++; // Note we could test for 2-byte non-ascii names here + if(q = strchr(s, **p)) (*p)++, piece += 64*(q - s + 1); if(**p == '/') slash = *(*p)++; } while(n < 4) { @@ -489,7 +492,7 @@ NextUnit (char **p) else if(toY >= BOARD_HEIGHT || toY < 0) return ImpossibleMove; // vert off-board to-square if(toX < BOARD_LEFT || toX >= BOARD_RGHT) return ImpossibleMove; if(piece) { - cl.pieceIn = CharToPiece(wom ? piece : ToLower(piece)); + cl.pieceIn = CharToPiece(wom ? piece : piece + 'a' - 'A'); if(cl.pieceIn == EmptySquare) return ImpossibleMove; // non-existent piece if(promoted) cl.pieceIn = (ChessSquare) (CHUPROMOTED cl.pieceIn); } else cl.pieceIn = EmptySquare;