}
}
+ if(moveType == Swap && killX < 0) killX = fromX, killY = fromY, moveType = NormalMove;
FinishMove(moveType, fromX, fromY, toX, toY, promoChar);
}
typedef char Markers[BOARD_RANKS][BOARD_FILES];
Markers *m = (Markers *) closure;
if(rf == fromY && ff == fromX && (killX < 0 ? !(rt == rf && ft == ff) && legNr & 1 :
- kill2X < 0 ? rt == killY && ft == killX || legNr & 2 : rt == killY && ft == killX || legNr & 4))
+ kill2X < 0 ? rt == killY && ft == killX || legNr & 2 : rt == killY && ft == killX || legNr & 4)) {
(*m)[rt][ft] = 1 + (board[rt][ft] != EmptySquare
|| kind == WhiteCapturesEnPassant
- || kind == BlackCapturesEnPassant) + 3*(kind == FirstLeg && (killX < 0 & legNr || legNr & 2 && kill2X < 0)), legal[rt][ft] = 3;
- else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3, legal[rt][ft] = 3;
+ || kind == BlackCapturesEnPassant), legal[rt][ft] = 3;
+ if(kind == FirstLeg && (killX < 0 & legNr || legNr & 2 && kill2X < 0)) (*m)[rt][ft] = 5;
+ } else if(flags & F_MANDATORY_CAPTURE && board[rt][ft] != EmptySquare) (*m)[rt][ft] = 3, legal[rt][ft] = 3;
}
static int hoverSavedValid;
board[EP_STATUS] = EP_CAPTURE;
if( kill2X >= 0 && kill2Y >= 0)
killed2 = board[kill2Y][kill2X], board[kill2Y][kill2X] = EmptySquare;
+ if(killed == EmptySquare) // [HGM] unload: kill-square also used for push destination
+ board[killY][killX] = board[toY][toX], board[EP_STATUS] = EP_NONE;
}
if( board[toY][toX] != EmptySquare ) {
WhitePromotion, WhiteNonPromotion,
BlackPromotion, BlackNonPromotion,
WhiteCapturesEnPassant, BlackCapturesEnPassant,
- WhiteDrop, BlackDrop, FirstLeg,
+ WhiteDrop, BlackDrop, FirstLeg, Swap,
NormalMove, AmbiguousMove, IllegalMove, ImpossibleMove,
WhiteWins, BlackWins, GameIsDrawn, GameUnfinished,
GNUChessGame, XBoardGame, MoveNumberOne, Open, Close, Nothing,
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;
- char *cont = NULL;
+ int expo = -1, dx, dy, x, y, mode, dirSet, ds2=0, retry=0, initial=0, jump=1, skip = 0, all = 0, put = 0, u = 0;
+ char *cont = NULL, *q;
while(*p == 'i') initial++, desc = ++p;
while(islower(*p)) p++; // skip prefixes
if(!isupper(*p)) return; // syntax error: no atom
}
if(mine == 2 && tx < 0) dirSet = dirSet >> 4 | dirSet << 4 & 255; // invert black moves
mode = 0; // build mode mask
+ if(*desc == 'u') put++, desc++; // unload stuff at start of leg
if(*desc == 'm') mode |= 4, desc++; // move to empty
if(*desc == 'c') mode |= his, desc++; // capture foe
if(*desc == 'd') mode |= mine, desc++; // destroy (capture friend)
} else {
strncpy(buf, cont, 80); cont = buf; // copy next leg(s), so we can modify
atom = buf; while(islower(*atom)) atom++; // skip to atom
+ for(q=buf; q!=atom && *q != 'a'; q++) // test whether next leg unloads
+ if(*q == 'u') u = 1;
if(mode & 32) mode ^= 256 + 32; // in non-final legs 'p' means 'pass through'
if(mode & 64 + 512) {
mode |= 256; // and 'g' too, but converts leaper <-> slider
if(occup & mode) { // valid intermediate square, do continuation
char origAtom = *atom;
int rg = (expo != 1 ? expo - i + 1 : range); // pass length of last *slider* leg
+ int transp = occup & mode & 0x104; // no side effect on intermediate square
if(!(bit & all)) *atom = rotate[*atom - 'A']; // orth-diag interconversion to make direction valid
- if(occup & mode & 0x104) { // no side effects, merge legs to one move
+ if(transp && !u) { // no side effects, merge legs to one move
if(skip < 0 && occup == 4) { // create e.p. rights on this square
if(viaX != 100) { // second e.p. square!
if(viaX == x && viaY == y - vy) viaY = y | 128; // flag it when we can handle it
MovesFromString(board, flags, f, r, x, y, dir, rg, cont, cb, cl);
if(viaY & 128) viaY = y - vy; else viaX = viaY = 100;
}
- if(occup & mode & 3 && (killX < 0 || kill2X < 0 && (legNr > 1 || killX == x && killY == y) ||
+ if((occup & mode & 3 || transp && u) && (killX < 0 || kill2X < 0 && (legNr > 1 || killX == x && killY == y) ||
(legNr == 1 ? kill2X == x && kill2Y == y : killX == x && killY == y))) { // destructive first leg
int cnt = 0;
legNr <<= 1;
break;
}
if(mode & 16 && (board[y][x] == WhiteKing || board[y][x] == BlackKing)) break; // tame piece, cannot capture royal
- if(occup & mode) cb(board, flags, y == promoRank ? promo : NormalMove, r, f, y, x, cl); // allowed, generate
+ if(occup & mode) {
+ cb(board, flags, y == promoRank ? promo : put ? Swap : NormalMove, r, f, y, x, cl); // allowed, generate
+ }
if(occup != 4) break; // not valid transit square
} while(--i);
}