return;
}
+ if(gs->drops != 2 || (gs->onMove == WHITE ? 0 : gs->ranks-1) != mt->fromRank) { // [HGM] always accept if backrank mover in Seirawan
if (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN) {
return;
}
if (mt->toRank < gs->ranks - gs->promoZone && mt->toRank >= gs->promoZone) {
return;
}
+ }
switch (tolower(s[1])) {
case 'f':
switch(piece) {
case ELEPHANT:
if(strstr(gs->variant, "super")) piece = EMPRESS; else
+ if(strstr(gs->variant, "seirawan"))piece = SELEPHANT; else
if(strstr(gs->variant, "great")) piece = MODERNELEPHANT; else
if(strstr(gs->variant, "courier")) piece = ALFIL2;
break;
if(strstr(gs->variant, "great")) piece = MINISTER;
break;
case HORSE:
+ if(strstr(gs->variant, "shogi")) piece = DRAGONHORSE; else
+ if(strstr(gs->variant, "seirawan")) piece = HAWK; else
if(strstr(gs->variant, "great")) piece = PRIESTESS;
- if(strstr(gs->variant, "shogi")) piece = DRAGONHORSE;
break;
case GOLD:
if(strstr(gs->variant, "great")) piece = MASTODON;
break;
case EMPRESS:
case ELEPHANT:
+ case SELEPHANT:
strcpy(mStr, "E");
break;
case ALFIL:
strcpy(mStr, "V");
break;
case HORSE:
+ case DRAGONHORSE:
+ case HAWK:
strcpy(mStr, "H");
break;
case HONORABLEHORSE:
case DRAGONKING:
strcpy(mStr, "D");
break;
- case DRAGONHORSE:
- strcpy(mStr, "H");
- break;
case LANCE:
strcpy(mStr, "L");
break;
sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9));
strcat(mStr, tmp);
- if ((piece == PAWN || gs->promoType == 3) && (mt->piecePromotionTo != NOPIECE)) {
+ if ((piece == PAWN || gs->promoType == 3 || gs->drops == 2) && (mt->piecePromotionTo != NOPIECE)) {
strcat(mStr, "="); /* = before promoting piece */
switch (piecetype(mt->piecePromotionTo)) {
case KNIGHT:
static int move_calculate(struct game_state_t * gs, struct move_t * mt, int promote)
{
struct game_state_t fakeMove;
- int gating = 0;
+ int gating = 0, stm;
mt->pieceCaptured = gs->board[mt->toFile][mt->toRank];
mt->enPassant = 0; /* Don't know yet, let execute move take care
} else if(mt->fromFile == ALG_CASTLE) {
// [HGM] castle: generalized castling, fr and tr give from and to file of Rook.
sprintf(mt->moveString, mt->toRank > mt->toFile ? "o-o-o" : "o-o");
+ if(gs->drops == 2 && promote && gs->holding[gs->onMove == BLACK][promote-1])
+ mt->piecePromotionTo = promote, gating = 1;
} else {
+ stm = colorval(gs->board[mt->fromFile][mt->fromRank]);
if(gs->promoType == 3) { // Shogi-style promotions: not just Pawns, but many pieces can promote
int piece = gs->board[mt->fromFile][mt->fromRank];
mt->piecePromotionTo = NOPIECE;
if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) &&
!gs->palace && // [HGM] XQ: no promotions in xiangqi
((mt->toRank < gs->promoZone) || (mt->toRank >= gs->ranks - gs->promoZone))) {
- 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=PIECES-1; promote>PAWN; promote--) if(gs->holding[stm == BLACK][promote-1]) break;
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;
+ 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) return MOVE_ILLEGAL;
}
- gating = 1; // gating OK; remember we did it for check test
+ mt->piecePromotionTo = promote; // gating OK
+ gating = 1; // 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)
+ 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))
if (mt->piecePromotionTo != NOPIECE) {
promote = piecetype(mt->piecePromotionTo);
- } else if(gs->promoType == 3 && promote == MASTODON) promote = GOLD;
+ } else if (promote != NOPIECE) { // [HGM] promotion on long algebraic move; correct ambiguous types for variant
+ if(gs->promoType == 3 && promote == MASTODON) promote = GOLD;
+ if(gs->drops == 2 && promote == EMPRESS) promote = SELEPHANT;
+ if(gs->drops == 2 && promote == DRAGONHORSE) promote = HAWK;
+ }
return move_calculate(gs, mt, promote);
}
gs->board[fKing][backRank] = NOPIECE;
gs->board[mt->toRank][backRank] = rook; // then put back
gs->board[mt->toFile][backRank] = king;
+ if(gs->drops == 2 && mt->piecePromotionTo != NOPIECE) { // [HGM] Seirawan-style gating
+ gs->board[fKing][backRank] = mt->piecePromotionTo | gs->onMove; // for now always on King square
+ gs->holding[gs->onMove==WHITE ? 0 : 1][mt->piecePromotionTo-1]--; // remove gated piece from holdings
+ }
} else {
movedPiece = gs->board[mt->fromFile][mt->fromRank];
tookPiece = gs->board[mt->toFile][mt->toRank];
- if(gs->drops == 2 && mt->piecePromotionTo != NOPIECE && pieceType(movedPiece) != PAWN) { // [HGM] Seirawan-style gating
+ 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