int SameColor P((ChessSquare, ChessSquare));
int PosFlags(int index);
-extern signed char initialRights[BOARD_FILES]; /* [HGM] all rights enabled, set in InitPosition */
int quickFlag;
char *pieceDesc[EmptySquare];
char *defaultDesc[EmptySquare] = {
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;
// 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;
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
if(pc == WhitePawn || pc == WhiteLance) promo = WhitePromotion, promoRank = BOARD_HEIGHT-1; else
if(pc == BlackPawn || pc == BlackLance) promo = BlackPromotion, promoRank = 0;
while(*p) { // more moves to go
- int expo = 1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0;
+ int expo = -1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0;
char *cont = NULL;
while(*p == 'i') initial++, desc = ++p;
while(islower(*p)) p++; // skip prefixes
if(initial && (board[r][f] != initialPosition[r][f] ||
r == 0 && board[TOUCHED_W] & 1<<f ||
r == BOARD_HEIGHT-1 && board[TOUCHED_B] & 1<<f ) ) continue;
- if(expo > 1 && dx == 0 && dy == 0) { // castling indicated by O + number
+ if(expo > 0 && dx == 0 && dy == 0) { // castling indicated by O + number
mode |= 1024; dy = 1;
}
+ if(expo < 0) expo = 1; // use 1 for default
if(!cont) {
if(!(mode & 15)) mode |= his + 4; // no mode spec, use default = mc
} else {
if(occup == 4) continue; // skip empty squares
if((x == BOARD_LEFT + skip || x > BOARD_LEFT + skip && vx < 0 && board[y][x-1-skip] == DarkSquare)
&& board[y][x] == initialPosition[y][x]) { // reached initial corner piece
- if(pc != WhiteKing && pc != BlackKing) { // non-royal castling (to be entered as two-leg move via 'Rook')
+ if(pc != WhiteKing && pc != BlackKing || expo == 1) { // non-royal castling (to be entered as two-leg move via 'Rook')
if(killX < 0) cb(board, flags, FirstLeg, r, f, y, x, cl); if(killX < f)
legNr <<= 1, cb(board, flags, NormalMove, r, f, y, f - expo, cl), legNr >>= 1;
} else
}
if((x == BOARD_RGHT-1-skip || x < BOARD_RGHT-1-skip && vx > 0 && board[y][x+1+skip] == DarkSquare)
&& board[y][x] == initialPosition[y][x]) {
- if(pc != WhiteKing && pc != BlackKing) {
+ if(pc != WhiteKing && pc != BlackKing || expo == 1) {
if(killX < 0) cb(board, flags, FirstLeg, r, f, y, x, cl); if(killX > f)
legNr <<= 1, cb(board, flags, NormalMove, r, f, y, f + expo, cl), legNr >>= 1;
} else
break;
- case SHOGI WhiteStag:
- case SHOGI BlackStag:
+ case SHOGI WhiteGnu:
+ case SHOGI BlackGnu:
if(gameInfo.variant == VariantShogi) goto BlackGold;
SlideVertical(board, flags, rf, ff, callback, closure);
Ferz(board, flags, rf, ff, callback, closure);
SlideVertical(board, flags, rf, ff, callback, closure);
break;
- case SHOGI WhiteHorned:
+ case SHOGI WhiteCat:
Sting(board, flags, rf, ff, 1, 0, callback, closure);
callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
if(killX >= 0) break;
SlideBackward(board, flags, rf, ff, callback, closure);
break;
- case SHOGI BlackHorned:
+ case SHOGI BlackCat:
Sting(board, flags, rf, ff, -1, 0, callback, closure);
callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
if(killX >= 0) break;
SlideForward(board, flags, rf, ff, callback, closure);
break;
- case SHOGI WhiteEagle:
+ case SHOGI WhiteDagger:
Sting(board, flags, rf, ff, 1, 1, callback, closure);
Sting(board, flags, rf, ff, 1, -1, callback, closure);
callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
SlideDiagBackward(board, flags, rf, ff, callback, closure);
break;
- case SHOGI BlackEagle:
+ case SHOGI BlackDagger:
Sting(board, flags, rf, ff, -1, 1, callback, closure);
Sting(board, flags, rf, ff, -1, -1, callback, closure);
callback(board, flags, NormalMove, rf, ff, rf, ff, closure);
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;