if (fFile == ALG_DROP) {
move_piece = fRank;
- if(!gs->drops) return 0; // [HGM] variants: no drops in this variant
+ if(gs->drops != 1) return 0; // [HGM] variants: no drops in this variant
if (move_piece == KING)
return 0;
if (gs->holding[gs->onMove==WHITE ? 0 : 1][move_piece-1] == 0)
case ROOK:
legal = legal_rook_move(gs, fFile, fRank, tFile, tRank);
break;
+ case HAWK:
case CARDINAL:
case PRINCESS:
legal = legal_cardinal_move(gs, fFile, fRank, tFile, tRank);
break;
+ case SELEPHANT:
case MARSHALL:
case EMPRESS:
legal = legal_marshall_move(gs, fFile, fRank, tFile, tRank);
static int move_calculate(struct game_state_t * gs, struct move_t * mt, int promote)
{
struct game_state_t fakeMove;
+ int gating = 0;
mt->pieceCaptured = gs->board[mt->toFile][mt->toRank];
mt->enPassant = 0; /* Don't know yet, let execute move take care
int stm = colorval(gs->board[mt->fromFile][mt->fromRank]);
if(!promote && (mt->toRank == 0 || mt->toRank == gs->ranks-1)) { // promotion obligatory, but not specified
if(gs->promoType != 2) promote = QUEEN; else { // choose a default
- for(promote=KING-1; promote>PAWN; promote--) if(gs->holding[stm == BLACK][promote-1]) break;
+ for(promote=PIECES-1; promote>PAWN; promote--) if(gs->holding[stm == BLACK][promote-1]) break;
if(promote == PAWN) return MOVE_ILLEGAL; // nothing available
}
- } // if not obligatory, we defer unless promoton was explicitly specified!
+ } // if not obligatory, we defer unless promotion was explicitly specified!
if(!gs->pawnDblStep && promote == PRINCESS) promote = MAN2;
if(!gs->pawnDblStep && promote != FERZ2 && promote != MAN2) promote = FERZ; // [HGM] kludge to recognize shatranj
// non-promotion can still be an option for deeper promotion zones
mt->piecePromotionTo = promote ? (promote | stm) : NOPIECE;
if(promote && gs->promoType == 2 && !gs->holding[stm == BLACK][promote-1]) return MOVE_ILLEGAL; // unavailable piece specified
+ } else if(gs->drops == 2 && promote && mt->fromRank == (stm == WHITE ? 0 : gs->ranks-1)) { // [HGM] Seirawan-style gating
+ int i; struct game *g = &game_globals.garray[gs->gameNum];
+ if(!gs->holding[stm == BLACK][promote-1]) return MOVE_ILLEGAL; // unavailable piece specified
+ // now we must test virginity of the moved piece. Yegh!
+ for (i = g->numHalfMoves-2; i > 0; i -= 2) {
+ if (g->moveList[i].toFile == mt->fromFile && g->moveList[i].toRank == mt->fromRank) return MOVE_ILLEGAL;
+ }
+ gating = 1; // gating OK; remember we did it for check test
} else {
mt->piecePromotionTo = NOPIECE;
}
fakeMove = *gs;
/* Calculates enPassant also */
execute_move(&fakeMove, mt, 0);
+ if(gating) fakeMove.board[mt-fromFile][mt->fromRank] = NOPIECE; // [HGM] gating is only legal if non-gating move was (weird, but true)
/* Does making this move leave ME in check? */
if (in_check(&fakeMove))
case ROOK:
possible_rook_moves(gs, f, r, possiblef, possibler, &numpossible);
break;
+ case HAWK:
case CARDINAL:
case PRINCESS:
possible_cardinal_moves(gs, f, r, possiblef, possibler, &numpossible);
break;
+ case SELEPHANT:
case MARSHALL:
case EMPRESS:
possible_marshall_moves(gs, f, r, possiblef, possibler, &numpossible);
} else {
movedPiece = gs->board[mt->fromFile][mt->fromRank];
tookPiece = gs->board[mt->toFile][mt->toRank];
- if (mt->piecePromotionTo == NOPIECE) {
+ if(gs->drops == 2 && mt->piecePromotionTo != NOPIECE && pieceType(movedPiece) != PAWN) { // [HGM] Seirawan-style gating
gs->board[mt->toFile][mt->toRank] = gs->board[mt->fromFile][mt->fromRank];
+ gs->board[mt->fromFile][mt->fromRank] = mt->piecePromotionTo | gs->onMove;;
+ gs->holding[gs->onMove==WHITE ? 0 : 1][mt->piecePromotionTo-1]--; // remove gated piece from holdings
} else {
- gs->board[mt->toFile][mt->toRank] = mt->piecePromotionTo | gs->onMove;
- if(gs->promoType == 2) gs->holding[gs->onMove][mt->piecePromotionTo-1]--;
+ if (mt->piecePromotionTo == NOPIECE) {
+ gs->board[mt->toFile][mt->toRank] = gs->board[mt->fromFile][mt->fromRank];
+ } else {
+ gs->board[mt->toFile][mt->toRank] = mt->piecePromotionTo | gs->onMove;
+ if(gs->promoType == 2) gs->holding[gs->onMove][mt->piecePromotionTo-1]--;
+ }
+ gs->board[mt->fromFile][mt->fromRank] = NOPIECE;
}
- gs->board[mt->fromFile][mt->fromRank] = NOPIECE;
/* Check if irreversable */
if ((piecetype(movedPiece) == PAWN) && (mt->fromRank != mt->toRank) // [HGM] XQ: sideway Pawn move reversible!
|| (tookPiece != NOPIECE)) {
goto cleanupMove;
}
gs->board[m->toFile][m->toRank] = m->pieceCaptured;
+ if(gs->board[m->fromFile][m->fromRank] != NOPIECE) { // [HGM] from-square occupied, must have been Seirawan-style gating
+ gs->holding[gs->onMove==WHITE ? 1 : 0][piecetype(gs->board[m->fromFile][m->fromRank])-1]++; // put back in holdings (onMove not flipped yet!)
+ }
cleanupMove:
if (game_globals.garray[g].status != GAME_EXAMINE) {
game_update_time(g);