// 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
+ if(promote == KNIGHT && gs->royalKnight) return MOVE_ILLEGAL; // Knight not allowed in Knightmate
+ if(gs->promoType != 2 && promote > QUEEN) { // for promoType != 2 we must check explicitly if the requested pieceis compatible with the variant
+ switch(promote) {
+ case HAWK:
+ case SELEPHANT:
+ if(gs->drops != 2) return MOVE_ILLEGAL; // allowed only in S-Chess
+ break;
+ case MARSHALL:
+ case CARDINAL:
+ if(!gs->capablancaPieces) return MOVE_ILLEGAL; // allowed when flagged so
+ break;
+ case FERZ:
+ case FERZ2:
+ if(!gs->pawnDblStep) return MOVE_ILLEGAL; // allowed in Shatranj and Courier
+ break;
+ case MAN2:
+ if(!gs->royalKnight) return MOVE_ILLEGAL; // allowed only in Knightmate
+ break;
+ default:
+ return MOVE_ILLEGAL;
+ }
+ }
} else
if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == HOPLITE) &&
((mt->toRank < gs->promoZone) || (mt->toRank >= gs->ranks - gs->promoZone))) {
for (i = g->numHalfMoves-1; i >= 0; i--) {
if (g->moveList[i].fromFile == mt->fromFile && g->moveList[i].fromRank == mt->fromRank ||
g->moveList[i].toFile == mt->fromFile && g->moveList[i].toRank == mt->fromRank ||
- g->moveList[i].fromFile == ALG_CASTLE && (gs->onMove == WHITE ? 0 : gs->ranks-1) == mt->fromRank &&
+ g->moveList[i].fromFile == ALG_CASTLE && (i&1 ? gs->ranks-1 : 0) == mt->fromRank &&
(g->moveList[i].fromRank == mt->fromFile || gs->files>>1 == mt->fromFile )) return MOVE_ILLEGAL;
}
mt->piecePromotionTo = promote; // gating OK
{
struct game_state_t *gs;
struct move_t *m, *m1;
- int now, i;
+ int now, i, piece;
if (game_globals.garray[g].link >= 0) /*IanO: not implemented for bughouse yet */
return MOVE_ILLEGAL;
gs->board[kingFromFile][rank] = KING | m->color; // King fromSquare
goto cleanupMove;
}
+ piece = gs->board[m->toFile][m->toRank];
if(gs->board[m->fromFile][m->fromRank] != NOPIECE) { // [HGM] from-square occupied; move 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!)
- }
- gs->board[m->fromFile][m->fromRank] = gs->board[m->toFile][m->toRank];
- if (m->piecePromotionTo != NOPIECE) {
- int piece;
+ } else
+ if (m->piecePromotionTo != NOPIECE) { // it is a real promotion
switch(piecetype(m->piecePromotionTo)) { // Spartan pieces came from Hoplite, Shogi is problematic
case KING:
case CAPTAIN:
case GOLD: // TODO: figure out what original was
default: piece = PAWN;
}
- gs->board[m->fromFile][m->fromRank] = piece |
- colorval(gs->board[m->fromFile][m->fromRank]);
+ piece |= colorval(gs->board[m->toFile][m->toRank]);
}
+ gs->board[m->fromFile][m->fromRank] = piece;
/******************
When takeback a _first_ move of rook, the ??rmoved variable
must be cleared . To check, if the move is first, we should