X-Git-Url: http://winboard.nl/cgi-bin?p=capablanca.git;a=blobdiff_plain;f=lasker-2.2.3%2Fsrc%2Fmovecheck.c;h=6996d09215fa25f9b8ad571079b234b7773d5bb0;hp=30ada65a3b6797751c188110bc5da3f9020402a3;hb=ec7b6bb32ba9632cda17b308808ce9ba1e27c090;hpb=8d865da206fa04e0642d6a134a85b12a068ed0ac diff --git a/lasker-2.2.3/src/movecheck.c b/lasker-2.2.3/src/movecheck.c index 30ada65..6996d09 100644 --- a/lasker-2.2.3/src/movecheck.c +++ b/lasker-2.2.3/src/movecheck.c @@ -140,21 +140,21 @@ int InitPieceLoop(board_t b, int *f, int *r, int color) /* See legal_move() */ static int legal_pawn_move( struct game_state_t *gs, int ff, int fr, int tf, int tr ) { - if (ff == tf) { - if (gs->board[tf][tr] != NOPIECE && !gs->palace && gs->promoType != 3) return 0; // [HGM] XQ and Shogi pawns can capture straight ahead - if (gs->onMove == WHITE) { - if (tr - fr == 1) return 1; + if (ff == tf) { + if (gs->board[tf][tr] != NOPIECE && !gs->palace && gs->promoType != 3) return 0; // [HGM] XQ and Shogi pawns can capture straight ahead + if (gs->onMove == WHITE) { + if (tr - fr == 1) return 1; if ((fr <= gs->pawnDblStep) && (tr - fr == 2) && gs->board[ff][fr+1]==NOPIECE) return 1; - } else { - if (fr - tr == 1) return 1; - if ((fr >= gs->ranks - 1 - gs->pawnDblStep) && (fr - tr == 2) && gs->board[ff][fr-1]==NOPIECE) return 1; - } - return 0; - } + } else { + if (fr - tr == 1) return 1; + if ((fr >= gs->ranks - 1 - gs->pawnDblStep) && (fr - tr == 2) && gs->board[ff][fr-1]==NOPIECE) return 1; + } + return 0; + } if (ff != tf && gs->promoType != 3) { /* Capture ? ([HGM] but not in Shogi) */ if ((ff - tf != 1) && (tf - ff != 1)) return 0; if (gs->onMove == WHITE) { - if(gs->palace) return (fr >= gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns + if(gs->palace) return (fr >= gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns if (tr != fr+1) return 0; if ((gs->board[tf][tr] != NOPIECE) && iscolor(gs->board[tf][tr],BLACK)) return 1; @@ -164,7 +164,7 @@ static int legal_pawn_move( struct game_state_t *gs, int ff, int fr, int tf, int if ((tf==ff-1) && (gs->board[ff-1][fr] == B_PAWN)) return 1; } } else { - if(gs->palace) return (fr < gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns + if(gs->palace) return (fr < gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns if (tr != fr-1) return 0; if ((gs->board[tf][tr] != NOPIECE) && iscolor(gs->board[tf][tr],WHITE)) return 1; @@ -366,16 +366,16 @@ static int legal_queen_move(struct game_state_t * gs, int ff, int fr, int tf, in return legal_rook_move(gs, ff, fr, tf, tr) || legal_bishop_move(gs, ff, fr, tf, tr); } -static int legal_cardinal_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_knight_move(gs, ff, fr, tf, tr) || legal_bishop_move(gs, ff, fr, tf, tr); -} - -static int legal_marshall_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_rook_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr); -} - +static int legal_cardinal_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_knight_move(gs, ff, fr, tf, tr) || legal_bishop_move(gs, ff, fr, tf, tr); +} + +static int legal_marshall_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_rook_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr); +} + /* Ckeck, if square (kf,kr) is attacked by enemy piece. * Used in castling from/through check testing. */ @@ -387,7 +387,7 @@ static int is_square_attacked (struct game_state_t *gs, int kf, int kr) int oldk = gs->onMove == WHITE ? gs->wkmoved : gs->bkmoved; fakeMove = *gs; - fakeMove.board[oldk][kr] = NOPIECE; // [HGM] castle: this routine is called only when King has not moved + fakeMove.board[oldk][kr] = NOPIECE; // [HGM] castle: this routine is called only when King has not moved fakeMove.board[kf][kr] = KING | fakeMove.onMove; fakeMove.onMove = CToggle (fakeMove.onMove); if (in_check(&fakeMove)) return 1; @@ -412,148 +412,148 @@ static int is_square_attacked(struct game_state_t * gs, int kf, int kr) } */ -static int legal_man_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - if (abs(ff - tf) > 1) - return 0; - if (abs(fr - tr) > 1) - return 0; - return 1; -} - -static int legal_wazir_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ +static int legal_man_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + if (abs(ff - tf) > 1) + return 0; + if (abs(fr - tr) > 1) + return 0; + return 1; +} + +static int legal_wazir_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ if(gs->palace && (tr > gs->palace && tr < gs->ranks - gs->palace || tf < (gs->files - gs->palace)/2 || tf >= (gs->files + gs->palace)/2)) - return 0; - if (abs(ff - tf) == 1 && fr == tr) - return 1; - if (abs(fr - tr) == 1 && ff == tf) - return 1; - return 0; -} - -static int legal_dababba_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - if (abs(ff - tf) == 2 && fr == tr) - return 1; - if (abs(fr - tr) == 2 && ff == tf) - return 1; - return 0; -} - -static int legal_ferz_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - if (abs(ff - tf) != 1) - return 0; - if (abs(fr - tr) != 1) - return 0; - return 1; -} - -static int legal_mandarin_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ + return 0; + if (abs(ff - tf) == 1 && fr == tr) + return 1; + if (abs(fr - tr) == 1 && ff == tf) + return 1; + return 0; +} + +static int legal_dababba_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + if (abs(ff - tf) == 2 && fr == tr) + return 1; + if (abs(fr - tr) == 2 && ff == tf) + return 1; + return 0; +} + +static int legal_ferz_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + if (abs(ff - tf) != 1) + return 0; + if (abs(fr - tr) != 1) + return 0; + return 1; +} + +static int legal_mandarin_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ if(gs->palace && (tr > gs->palace && tr < gs->ranks - gs->palace || tf < (gs->files - gs->palace)/2 || tf >= (gs->files + gs->palace)/2)) - return 0; - if (abs(ff - tf) != 1) - return 0; - if (abs(fr - tr) != 1) - return 0; - return 1; -} - -static int legal_alfil_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - if (abs(ff - tf) != 2) - return 0; - if (abs(fr - tr) != 2) - return 0; - return 1; -} - -static int legal_elephant_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - if (abs(ff - tf) != 2) - return 0; - if (abs(fr - tr) != 2) + return 0; + if (abs(ff - tf) != 1) + return 0; + if (abs(fr - tr) != 1) + return 0; + return 1; +} + +static int legal_alfil_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + if (abs(ff - tf) != 2) + return 0; + if (abs(fr - tr) != 2) + return 0; + return 1; +} + +static int legal_elephant_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + if (abs(ff - tf) != 2) + return 0; + if (abs(fr - tr) != 2) return 0; if(gs->board[(ff+tf)/2][(fr+tr)/2] != NOPIECE) return 0; // blocked - if((tr >= gs->ranks/2) != (fr >= gs->ranks/2)) return 0; // do not cross river - return 1; -} - -static int legal_gold_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_wazir_move(gs, ff, fr, tf, tr) || (abs(ff-tf) == 1 && tr == fr + (gs->onMove==WHITE ? 1 : -1)); -} - -static int legal_silver_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_ferz_move(gs, ff, fr, tf, tr) || (tf == ff && tr == fr + (gs->onMove==WHITE ? 1 : -1) ); -} - -static int legal_woody_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_wazir_move(gs, ff, fr, tf, tr) || legal_dababba_move(gs, ff, fr, tf, tr); -} - -static int legal_squirrel_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ + if((tr >= gs->ranks/2) != (fr >= gs->ranks/2)) return 0; // do not cross river + return 1; +} + +static int legal_gold_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_wazir_move(gs, ff, fr, tf, tr) || (abs(ff-tf) == 1 && tr == fr + (gs->onMove==WHITE ? 1 : -1)); +} + +static int legal_silver_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_ferz_move(gs, ff, fr, tf, tr) || (tf == ff && tr == fr + (gs->onMove==WHITE ? 1 : -1) ); +} + +static int legal_woody_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_wazir_move(gs, ff, fr, tf, tr) || legal_dababba_move(gs, ff, fr, tf, tr); +} + +static int legal_squirrel_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ return legal_alfil_move(gs, ff, fr, tf, tr) || legal_dababba_move(gs, ff, fr, tf, tr) - || legal_knight_move(gs, ff, fr, tf, tr); -} - -static int legal_mastodon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ + || legal_knight_move(gs, ff, fr, tf, tr); +} + +static int legal_mastodon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ return legal_man_move(gs, ff, fr, tf, tr) || legal_alfil_move(gs, ff, fr, tf, tr) - || legal_dababba_move(gs, ff, fr, tf, tr); -} - -static int legal_centaur_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_man_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr); -} - -static int legal_amazon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_queen_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr); -} - -static int legal_dragonking_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_rook_move(gs, ff, fr, tf, tr) || legal_ferz_move(gs, ff, fr, tf, tr); -} - -static int legal_dragonhorse_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_bishop_move(gs, ff, fr, tf, tr) || legal_wazir_move(gs, ff, fr, tf, tr); -} - -static int legal_modernelephant_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ - return legal_ferz_move(gs, ff, fr, tf, tr) || legal_alfil_move(gs, ff, fr, tf, tr); -} - -static int legal_priestess_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ + || legal_dababba_move(gs, ff, fr, tf, tr); +} + +static int legal_centaur_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_man_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr); +} + +static int legal_amazon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_queen_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr); +} + +static int legal_dragonking_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_rook_move(gs, ff, fr, tf, tr) || legal_ferz_move(gs, ff, fr, tf, tr); +} + +static int legal_dragonhorse_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_bishop_move(gs, ff, fr, tf, tr) || legal_wazir_move(gs, ff, fr, tf, tr); +} + +static int legal_modernelephant_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ + return legal_ferz_move(gs, ff, fr, tf, tr) || legal_alfil_move(gs, ff, fr, tf, tr); +} + +static int legal_priestess_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ return legal_knight_move(gs, ff, fr, tf, tr) || legal_ferz_move(gs, ff, fr, tf, tr) - || legal_alfil_move(gs, ff, fr, tf, tr); -} - -static int legal_minister_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) -{ + || legal_alfil_move(gs, ff, fr, tf, tr); +} + +static int legal_minister_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) +{ return legal_knight_move(gs, ff, fr, tf, tr) || legal_wazir_move(gs, ff, fr, tf, tr) - || legal_dababba_move(gs, ff, fr, tf, tr); -} - + || legal_dababba_move(gs, ff, fr, tf, tr); +} + static int legal_king_move(struct game_state_t * gs, int ff, int fr, int tf, int tr) { int result; // [HGM] castle: test first if valid as regular King move; result = 1 or 0 - if(gs->royalKnight) - result = legal_knight_move(gs, ff, fr, tf, tr); + if(gs->royalKnight) + result = legal_knight_move(gs, ff, fr, tf, tr); else if(gs->palace) { result = legal_wazir_move(gs, ff, fr, tf, tr); if(!result && ff == tf && piecetype(gs->board[tf][tr]) == KING) { // XQ regicide @@ -562,50 +562,50 @@ static int legal_king_move(struct game_state_t * gs, int ff, int fr, int tf, int if(gs->board[ff][i] != NOPIECE) return 0; // line of sight blocked return 1; } - } else + } else result = legal_man_move(gs, ff, fr, tf, tr); - if(result) return 1; + if(result) return 1; // [HGM] castle: orthodox legal castlings given as King move return 2 - if (gs->onMove == WHITE) { - /* King side castling */ - if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->wkmoved >= 0) - && (gs->wkrmoved >= 0) && (gs->board[gs->files-3][0] == NOPIECE) && - (gs->board[gs->files-2][0] == NOPIECE) && (gs->board[gs->files-1][0] == W_ROOK) && - (gs->board[gs->files/2+1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, 0)) && - (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, gs->files-3, 0))) { - return 2; - } - /* Queen side castling */ - if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == 2) && (gs->wkmoved >= 0) - && (gs->wqrmoved >= 0) && (gs->board[3][0] == NOPIECE) && - (gs->board[2][0] == NOPIECE) && (gs->board[1][0] == NOPIECE) && - (gs->board[0][0] == W_ROOK) && - (gs->board[gs->files/2-1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, 0)) && - (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, 3, 0))) { - return 2; - } - } else { /* Black */ - /* King side castling */ - if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->bkmoved >= 0) - && (gs->bkrmoved >= 0) && (gs->board[gs->files-3][7] == NOPIECE) && - (gs->board[gs->files-2][gs->ranks-1] == NOPIECE) && (gs->board[gs->files-1][gs->ranks-1] == B_ROOK) && - (gs->board[gs->files/2+1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, gs->ranks-1)) && - (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, gs->files-3, gs->ranks-1))) { - return 2; - } - /* Queen side castling */ - if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == 2) && (gs->bkmoved >= 0) - && (gs->bqrmoved >= 0) && (gs->board[3][gs->ranks-1] == NOPIECE) && - (gs->board[2][gs->ranks-1] == NOPIECE) && (gs->board[1][gs->ranks-1] == NOPIECE) && - (gs->board[0][gs->ranks-1] == B_ROOK) && - (gs->board[gs->files/2-1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, gs->ranks-1)) && - (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, 3, gs->ranks-1))) { - return 2; - } - } - + if (gs->onMove == WHITE) { + /* King side castling */ + if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->wkmoved >= 0) + && (gs->wkrmoved >= 0) && (gs->board[gs->files-3][0] == NOPIECE) && + (gs->board[gs->files-2][0] == NOPIECE) && (gs->board[gs->files-1][0] == W_ROOK) && + (gs->board[gs->files/2+1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, 0)) && + (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, gs->files-3, 0))) { + return 2; + } + /* Queen side castling */ + if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == 2) && (gs->wkmoved >= 0) + && (gs->wqrmoved >= 0) && (gs->board[3][0] == NOPIECE) && + (gs->board[2][0] == NOPIECE) && (gs->board[1][0] == NOPIECE) && + (gs->board[0][0] == W_ROOK) && + (gs->board[gs->files/2-1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, 0)) && + (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, 3, 0))) { + return 2; + } + } else { /* Black */ + /* King side castling */ + if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->bkmoved >= 0) + && (gs->bkrmoved >= 0) && (gs->board[gs->files-3][7] == NOPIECE) && + (gs->board[gs->files-2][gs->ranks-1] == NOPIECE) && (gs->board[gs->files-1][gs->ranks-1] == B_ROOK) && + (gs->board[gs->files/2+1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, gs->ranks-1)) && + (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, gs->files-3, gs->ranks-1))) { + return 2; + } + /* Queen side castling */ + if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == 2) && (gs->bkmoved >= 0) + && (gs->bqrmoved >= 0) && (gs->board[3][gs->ranks-1] == NOPIECE) && + (gs->board[2][gs->ranks-1] == NOPIECE) && (gs->board[1][gs->ranks-1] == NOPIECE) && + (gs->board[0][gs->ranks-1] == B_ROOK) && + (gs->board[gs->files/2-1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, gs->ranks-1)) && + (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, 3, gs->ranks-1))) { + return 2; + } + } + return 0; // neither regular King move nor castling } @@ -620,375 +620,375 @@ static void possible_pawn_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - if (gs->onMove == WHITE) { - if (gs->board[onf][onr + 1] == NOPIECE || gs->palace || gs->promoType == 3) { - add_pos(onf, onr + 1, posf, posr, numpos); - if ((onr <= gs->pawnDblStep) && (gs->board[onf][onr + 2] == NOPIECE)) - add_pos(onf, onr + 2, posf, posr, numpos); - } + if (gs->onMove == WHITE) { + if (gs->board[onf][onr + 1] == NOPIECE || gs->palace || gs->promoType == 3) { + add_pos(onf, onr + 1, posf, posr, numpos); + if ((onr <= gs->pawnDblStep) && (gs->board[onf][onr + 2] == NOPIECE)) + add_pos(onf, onr + 2, posf, posr, numpos); + } if (onf > 0) { - if (gs->board[onf - 1][onr + 1] != NOPIECE && + if (gs->board[onf - 1][onr + 1] != NOPIECE && iscolor(gs->board[onf - 1][onr + 1], BLACK) && - !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf - 1, onr + 1, posf, posr, numpos); if(gs->palace && onr >= gs->ranks/2 && (gs->board[onf-1][onr] || iscolor(gs->board[onf-1][onr], BLACK))) add_pos(onf - 1, onr, posf, posr, numpos); // XQ promoted pawn - } + } if (onf < gs->files-1) { - if (gs->board[onf + 1][onr + 1] != NOPIECE && + if (gs->board[onf + 1][onr + 1] != NOPIECE && iscolor(gs->board[onf + 1][onr + 1], BLACK) && - !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf + 1, onr + 1, posf, posr, numpos); if(gs->palace && onr >= gs->ranks/2 && (gs->board[onf+1][onr] || iscolor(gs->board[onf+1][onr], BLACK))) add_pos(onf + 1, onr, posf, posr, numpos); // XQ promoted pawn - } - if (gs->ep_possible[0][onf] == -1) - add_pos(onf - 1, onr + 1, posf, posr, numpos); - if (gs->ep_possible[0][onf] == 1) + } + if (gs->ep_possible[0][onf] == -1) + add_pos(onf - 1, onr + 1, posf, posr, numpos); + if (gs->ep_possible[0][onf] == 1) add_pos(onf + 1, onr + 1, posf, posr, numpos); - } else { - if (gs->board[onf][onr - 1] == NOPIECE || gs->palace || gs->promoType == 3) { - add_pos(onf, onr - 1, posf, posr, numpos); - if ((onr >= gs->ranks - gs->pawnDblStep - 1) && (gs->board[onf][onr - 2] == NOPIECE)) - add_pos(onf, onr - 2, posf, posr, numpos); - } + } else { + if (gs->board[onf][onr - 1] == NOPIECE || gs->palace || gs->promoType == 3) { + add_pos(onf, onr - 1, posf, posr, numpos); + if ((onr >= gs->ranks - gs->pawnDblStep - 1) && (gs->board[onf][onr - 2] == NOPIECE)) + add_pos(onf, onr - 2, posf, posr, numpos); + } if (onf > 0) { - if (gs->board[onf - 1][onr - 1] != NOPIECE && - iscolor(gs->board[onf - 1][onr - 1], WHITE) && - !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi + if (gs->board[onf - 1][onr - 1] != NOPIECE && + iscolor(gs->board[onf - 1][onr - 1], WHITE) && + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf - 1, onr - 1, posf, posr, numpos); if(gs->palace && onr < gs->ranks/2 && !iscolor(gs->board[onf-1][onr], BLACK)) add_pos(onf - 1, onr, posf, posr, numpos); // XQ promoted pawn - } + } if (onf < gs->files-1) { - if (gs->board[onf + 1][onr - 1] != NOPIECE && - iscolor(gs->board[onf + 1][onr - 1], WHITE) && - !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi + if (gs->board[onf + 1][onr - 1] != NOPIECE && + iscolor(gs->board[onf + 1][onr - 1], WHITE) && + !gs->palace && gs->promoType != 3) // no diagonal capture in XQ and Shogi add_pos(onf + 1, onr - 1, posf, posr, numpos); if(gs->palace && onr < gs->ranks/2 && !iscolor(gs->board[onf+1][onr], BLACK)) add_pos(onf + 1, onr, posf, posr, numpos); // XQ promoted pawn - } - if (gs->ep_possible[1][onf] == -1) - add_pos(onf - 1, onr - 1, posf, posr, numpos); - if (gs->ep_possible[1][onf] == 1) - add_pos(onf + 1, onr - 1, posf, posr, numpos); - } + } + if (gs->ep_possible[1][onf] == -1) + add_pos(onf - 1, onr - 1, posf, posr, numpos); + if (gs->ep_possible[1][onf] == 1) + add_pos(onf + 1, onr - 1, posf, posr, numpos); + } } static void possible_knight_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - static int knightJumps[8][2] = {{-1, 2}, {1, 2}, {2, -1}, {2, 1}, - {-1, -2}, {1, -2}, {-2, 1}, {-2, -1}}; - int f, r; - int j; - - for (j = 0; j < 8; j++) { - f = knightJumps[j][0] + onf; - r = knightJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) - continue; - if ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove)))) - add_pos(f, r, posf, posr, numpos); - } + static int knightJumps[8][2] = {{-1, 2}, {1, 2}, {2, -1}, {2, 1}, + {-1, -2}, {1, -2}, {-2, 1}, {-2, -1}}; + int f, r; + int j; + + for (j = 0; j < 8; j++) { + f = knightJumps[j][0] + onf; + r = knightJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) + continue; + if ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove)))) + add_pos(f, r, posf, posr, numpos); + } } static void possible_horse_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - static int knightJumps[8][4] = {{-1, 2, 0, 1}, {1, 2, 0, 1}, {2, -1, 1, 0}, {2, 1, 1, 0}, - {-1, -2, 0, -1}, {1, -2, 0, -1}, {-2, 1, -1, 0}, {-2, -1, -1, 0}}; - int f, r; - int j; - - for (j = 0; j < 8; j++) { - f = knightJumps[j][0] + onf; - r = knightJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) - continue; + static int knightJumps[8][4] = {{-1, 2, 0, 1}, {1, 2, 0, 1}, {2, -1, 1, 0}, {2, 1, 1, 0}, + {-1, -2, 0, -1}, {1, -2, 0, -1}, {-2, 1, -1, 0}, {-2, -1, -1, 0}}; + int f, r; + int j; + + for (j = 0; j < 8; j++) { + f = knightJumps[j][0] + onf; + r = knightJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) + continue; if ((gs->board[knightJumps[j][2] + onf][knightJumps[j][3] + onr] == NOPIECE) && - ((gs->board[f][r] == NOPIECE) || (iscolor(gs->board[f][r], CToggle(gs->onMove))))) - add_pos(f, r, posf, posr, numpos); - } + ((gs->board[f][r] == NOPIECE) || (iscolor(gs->board[f][r], CToggle(gs->onMove))))) + add_pos(f, r, posf, posr, numpos); + } } static void possible_bishop_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - int f, r; - - /* Up Left */ - f = onf; - r = onr; - for (;;) { - f--; - r++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Up Right */ - f = onf; - r = onr; - for (;;) { - f++; - r++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Down Left */ - f = onf; - r = onr; - for (;;) { - f--; - r--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Down Right */ - f = onf; - r = onr; - for (;;) { - f++; - r--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } + int f, r; + + /* Up Left */ + f = onf; + r = onr; + for (;;) { + f--; + r++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Up Right */ + f = onf; + r = onr; + for (;;) { + f++; + r++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Down Left */ + f = onf; + r = onr; + for (;;) { + f--; + r--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Down Right */ + f = onf; + r = onr; + for (;;) { + f++; + r--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } } static void possible_rook_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - int f, r; - - /* Left */ - f = onf; - r = onr; - for (;;) { - f--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Right */ - f = onf; - r = onr; - for (;;) { - f++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Up */ - f = onf; - r = onr; - for (;;) { - r++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Down */ - f = onf; - r = onr; - for (;;) { - r--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } + int f, r; + + /* Left */ + f = onf; + r = onr; + for (;;) { + f--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Right */ + f = onf; + r = onr; + for (;;) { + f++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Up */ + f = onf; + r = onr; + for (;;) { + r++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Down */ + f = onf; + r = onr; + for (;;) { + r--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } } static void possible_cannon_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - int f, r, i; - - /* Left */ - f = onf; - r = onr; - for (i=0;;) { - f--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; + int f, r, i; + + /* Left */ + f = onf; + r = onr; + for (i=0;;) { + f--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue; if(i == 0) add_pos(f, r, posf, posr, numpos); // no hop: non-capt else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove)) - add_pos(f, r, posf, posr, numpos); // hop: capt - if (gs->board[f][r] != NOPIECE) - break; - } - /* Right */ - f = onf; - r = onr; - for (i=0;;) { - f++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; + add_pos(f, r, posf, posr, numpos); // hop: capt + if (gs->board[f][r] != NOPIECE) + break; + } + /* Right */ + f = onf; + r = onr; + for (i=0;;) { + f++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue; if(i == 0) add_pos(f, r, posf, posr, numpos); // no hop: non-capt else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove)) - add_pos(f, r, posf, posr, numpos); // hop: capt - if (gs->board[f][r] != NOPIECE) - break; - } - /* Up */ - f = onf; - r = onr; - for (i=0;;) { - r++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; + add_pos(f, r, posf, posr, numpos); // hop: capt + if (gs->board[f][r] != NOPIECE) + break; + } + /* Up */ + f = onf; + r = onr; + for (i=0;;) { + r++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue; if(i == 0) add_pos(f, r, posf, posr, numpos); // no hop: non-capt else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove)) - add_pos(f, r, posf, posr, numpos); // hop: capt - if (gs->board[f][r] != NOPIECE) - break; - } - /* Down */ - f = onf; - r = onr; - for (i=0;;) { - r--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; + add_pos(f, r, posf, posr, numpos); // hop: capt + if (gs->board[f][r] != NOPIECE) + break; + } + /* Down */ + f = onf; + r = onr; + for (i=0;;) { + r--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue; if(i == 0) add_pos(f, r, posf, posr, numpos); // no hop: non-capt else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove)) - add_pos(f, r, posf, posr, numpos); // hop: capt - if (gs->board[f][r] != NOPIECE) - break; - } + add_pos(f, r, posf, posr, numpos); // hop: capt + if (gs->board[f][r] != NOPIECE) + break; + } } static void possible_lance_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - int f, r; - - /* Up */ - f = onf; - r = onr; - for (;gs->onMove == WHITE;) { - r++; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } - /* Down */ - f = onf; - r = onr; - for (;gs->onMove == BLACK;) { - r--; - if ((f < 0) || (f >= gs->files)) - break; - if ((r < 0) || (r >= gs->ranks)) - break; - if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) - break; - add_pos(f, r, posf, posr, numpos); - if (gs->board[f][r] != NOPIECE) - break; - } -} - -static void possible_cardinal_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - possible_knight_moves(gs, onf, onr, posf, posr, numpos); - possible_bishop_moves(gs, onf, onr, posf, posr, numpos); -} - -static void possible_marshall_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - possible_rook_moves(gs, onf, onr, posf, posr, numpos); - possible_knight_moves(gs, onf, onr, posf, posr, numpos); -} - + int f, r; + + /* Up */ + f = onf; + r = onr; + for (;gs->onMove == WHITE;) { + r++; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } + /* Down */ + f = onf; + r = onr; + for (;gs->onMove == BLACK;) { + r--; + if ((f < 0) || (f >= gs->files)) + break; + if ((r < 0) || (r >= gs->ranks)) + break; + if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove))) + break; + add_pos(f, r, posf, posr, numpos); + if (gs->board[f][r] != NOPIECE) + break; + } +} + +static void possible_cardinal_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + possible_knight_moves(gs, onf, onr, posf, posr, numpos); + possible_bishop_moves(gs, onf, onr, posf, posr, numpos); +} + +static void possible_marshall_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + possible_rook_moves(gs, onf, onr, posf, posr, numpos); + possible_knight_moves(gs, onf, onr, posf, posr, numpos); +} + static void possible_queen_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) @@ -997,118 +997,118 @@ static void possible_queen_moves(struct game_state_t * gs, possible_bishop_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_alfil_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; - int f, r; - int j; - - for (j = 0; j < 4; j++) { - f = 2*kingJumps[j][0] + onf; - r = 2*kingJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) - continue; - if ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove)))) - add_pos(f, r, posf, posr, numpos); - } -} - -static void possible_ferz_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; - int f, r; - int j; - - for (j = 0; j < 4; j++) { - f = kingJumps[j][0] + onf; - r = kingJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) +static void possible_alfil_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; + int f, r; + int j; + + for (j = 0; j < 4; j++) { + f = 2*kingJumps[j][0] + onf; + r = 2*kingJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) continue; - if ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove)))) - add_pos(f, r, posf, posr, numpos); - } -} - -static void possible_mandarin_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; - int f, r; - int j; - - for (j = 0; j < 4; j++) { - f = kingJumps[j][0] + onf; - r = kingJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) + if ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove)))) + add_pos(f, r, posf, posr, numpos); + } +} + +static void possible_ferz_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; + int f, r; + int j; + + for (j = 0; j < 4; j++) { + f = kingJumps[j][0] + onf; + r = kingJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) + continue; + if ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove)))) + add_pos(f, r, posf, posr, numpos); + } +} + +static void possible_mandarin_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; + int f, r; + int j; + + for (j = 0; j < 4; j++) { + f = kingJumps[j][0] + onf; + r = kingJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) continue; if(gs->palace && (r >= gs->palace && r < gs->ranks - gs->palace || f < (gs->files - gs->palace)/2 || f >= (gs->files + gs->palace)/2)) - continue; - if ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove)))) - add_pos(f, r, posf, posr, numpos); - } -} - -static void possible_wazir_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - static int kingJumps[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; - int f, r; - int j; - - for (j = 0; j < 4; j++) { - f = kingJumps[j][0] + onf; - r = kingJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) - continue; + continue; + if ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove)))) + add_pos(f, r, posf, posr, numpos); + } +} + +static void possible_wazir_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + static int kingJumps[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; + int f, r; + int j; + + for (j = 0; j < 4; j++) { + f = kingJumps[j][0] + onf; + r = kingJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) + continue; if(gs->palace && (r >= gs->palace && r < gs->ranks - gs->palace || f < (gs->files - gs->palace)/2 || f >= (gs->files + gs->palace)/2)) - continue; - if ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove)))) - add_pos(f, r, posf, posr, numpos); - } -} - -static void possible_dababba_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - static int kingJumps[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; - int f, r; - int j; - - for (j = 0; j < 4; j++) { - f = 2*kingJumps[j][0] + onf; - r = 2*kingJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) - continue; - if ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove)))) - add_pos(f, r, posf, posr, numpos); - } -} - -static void possible_man_moves(struct game_state_t * gs, + continue; + if ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove)))) + add_pos(f, r, posf, posr, numpos); + } +} + +static void possible_dababba_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + static int kingJumps[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}; + int f, r; + int j; + + for (j = 0; j < 4; j++) { + f = 2*kingJumps[j][0] + onf; + r = 2*kingJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) + continue; + if ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove)))) + add_pos(f, r, posf, posr, numpos); + } +} + +static void possible_man_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1116,7 +1116,7 @@ static void possible_man_moves(struct game_state_t * gs, possible_ferz_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_dragonking_moves(struct game_state_t * gs, +static void possible_dragonking_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1124,7 +1124,7 @@ static void possible_dragonking_moves(struct game_state_t * gs, possible_ferz_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_dragonhorse_moves(struct game_state_t * gs, +static void possible_dragonhorse_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1132,7 +1132,7 @@ static void possible_dragonhorse_moves(struct game_state_t * gs, possible_bishop_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_centaur_moves(struct game_state_t * gs, +static void possible_centaur_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1140,7 +1140,7 @@ static void possible_centaur_moves(struct game_state_t * gs, possible_knight_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_woody_moves(struct game_state_t * gs, +static void possible_woody_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1148,7 +1148,7 @@ static void possible_woody_moves(struct game_state_t * gs, possible_dababba_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_squirrel_moves(struct game_state_t * gs, +static void possible_squirrel_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1157,7 +1157,7 @@ static void possible_squirrel_moves(struct game_state_t * gs, possible_knight_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_mastodon_moves(struct game_state_t * gs, +static void possible_mastodon_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1166,7 +1166,7 @@ static void possible_mastodon_moves(struct game_state_t * gs, possible_dababba_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_amazon_moves(struct game_state_t * gs, +static void possible_amazon_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1174,7 +1174,7 @@ static void possible_amazon_moves(struct game_state_t * gs, possible_knight_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_modernelephant_moves(struct game_state_t * gs, +static void possible_modernelephant_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1182,7 +1182,7 @@ static void possible_modernelephant_moves(struct game_state_t * gs, possible_alfil_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_priestess_moves(struct game_state_t * gs, +static void possible_priestess_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1191,7 +1191,7 @@ static void possible_priestess_moves(struct game_state_t * gs, possible_knight_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_minister_moves(struct game_state_t * gs, +static void possible_minister_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1200,7 +1200,7 @@ static void possible_minister_moves(struct game_state_t * gs, possible_knight_moves(gs, onf, onr, posf, posr, numpos); } -static void possible_gold_moves(struct game_state_t * gs, +static void possible_gold_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { @@ -1208,83 +1208,83 @@ static void possible_gold_moves(struct game_state_t * gs, if(gs->onMove == WHITE) { if(onr < gs->ranks-1) if(onf > 0 && !iscolor(gs->board[onf-1][onr+1], WHITE)) - add_pos(onf-1, onr+1, posf, posr, numpos); + add_pos(onf-1, onr+1, posf, posr, numpos); if(onf < gs->files-1 && !iscolor(gs->board[onf+1][onr+1], WHITE)) - add_pos(onf+1, onr+1, posf, posr, numpos); + add_pos(onf+1, onr+1, posf, posr, numpos); } else { if(onr > 0) if(onf > 0 && !iscolor(gs->board[onf-1][onr-1], BLACK)) - add_pos(onf-1, onr-1, posf, posr, numpos); + add_pos(onf-1, onr-1, posf, posr, numpos); if(onf < gs->files-1 && !iscolor(gs->board[onf+1][onr-1], BLACK)) - add_pos(onf+1, onr-1, posf, posr, numpos); + add_pos(onf+1, onr-1, posf, posr, numpos); } } -static void possible_silver_moves(struct game_state_t * gs, +static void possible_silver_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { possible_ferz_moves(gs, onf, onr, posf, posr, numpos); if(gs->onMove == WHITE) { if(onr < gs->ranks-1 && !iscolor(gs->board[onf][onr+1], WHITE)) - add_pos(onf, onr+1, posf, posr, numpos); + add_pos(onf, onr+1, posf, posr, numpos); } else { if(onr > 0 && !iscolor(gs->board[onf][onr-1], BLACK)) - add_pos(onf, onr-1, posf, posr, numpos); + add_pos(onf, onr-1, posf, posr, numpos); } } -static void possible_honorablehorse_moves(struct game_state_t * gs, - int onf, int onr, - int *posf, int *posr, int *numpos) -{ - int f, r = onr + (gs->onMove == WHITE ? 2 : -2); +static void possible_honorablehorse_moves(struct game_state_t * gs, + int onf, int onr, + int *posf, int *posr, int *numpos) +{ + int f, r = onr + (gs->onMove == WHITE ? 2 : -2); - if(r < 0 || r >= gs->ranks) return; + if(r < 0 || r >= gs->ranks) return; if(onf > 0) { - if ((gs->board[onf-1][r] == NOPIECE) || - (iscolor(gs->board[onf-1][r], CToggle(gs->onMove)))) - add_pos(onf - 1, r, posf, posr, numpos); - } + if ((gs->board[onf-1][r] == NOPIECE) || + (iscolor(gs->board[onf-1][r], CToggle(gs->onMove)))) + add_pos(onf - 1, r, posf, posr, numpos); + } if(onf < gs->files - 1) { - if ((gs->board[onf+1][r] == NOPIECE) || - (iscolor(gs->board[onf+1][r], CToggle(gs->onMove)))) - add_pos(onf + 1, r, posf, posr, numpos); - } -} - + if ((gs->board[onf+1][r] == NOPIECE) || + (iscolor(gs->board[onf+1][r], CToggle(gs->onMove)))) + add_pos(onf + 1, r, posf, posr, numpos); + } +} + static void possible_king_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) { - if(gs->royalKnight) - possible_knight_moves(gs, onf, onr, posf, posr, numpos); + if(gs->royalKnight) + possible_knight_moves(gs, onf, onr, posf, posr, numpos); else if(gs->palace) possible_wazir_moves(gs, onf, onr, posf, posr, numpos); - else - possible_man_moves(gs, onf, onr, posf, posr, numpos); + else + possible_man_moves(gs, onf, onr, posf, posr, numpos); } static void possible_elephant_moves(struct game_state_t * gs, int onf, int onr, int *posf, int *posr, int *numpos) -{ - static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; - int f, r; - int j; - - for (j = 0; j < 4; j++) { - f = 2*kingJumps[j][0] + onf; - r = 2*kingJumps[j][1] + onr; - if ((f < 0) || (f >= gs->files)) - continue; - if ((r < 0) || (r >= gs->ranks)) - continue; - if ((gs->board[(f+onf)/2][(r+onr)/2] == NOPIECE) && ((gs->board[f][r] == NOPIECE) || - (iscolor(gs->board[f][r], CToggle(gs->onMove))))) - add_pos(f, r, posf, posr, numpos); - } -} +{ + static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}}; + int f, r; + int j; + + for (j = 0; j < 4; j++) { + f = 2*kingJumps[j][0] + onf; + r = 2*kingJumps[j][1] + onr; + if ((f < 0) || (f >= gs->files)) + continue; + if ((r < 0) || (r >= gs->ranks)) + continue; + if ((gs->board[(f+onf)/2][(r+onr)/2] == NOPIECE) && ((gs->board[f][r] == NOPIECE) || + (iscolor(gs->board[f][r], CToggle(gs->onMove))))) + add_pos(f, r, posf, posr, numpos); + } +} /* Doesn't check for check */ int legal_move(struct game_state_t * gs, @@ -1296,7 +1296,7 @@ int legal_move(struct game_state_t * gs, 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) @@ -1387,18 +1387,20 @@ int legal_move(struct game_state_t * gs, case ROOK: legal = legal_rook_move(gs, fFile, fRank, tFile, tRank); break; - case CARDINAL: - case PRINCESS: - legal = legal_cardinal_move(gs, fFile, fRank, tFile, tRank); - break; - case MARSHALL: - case EMPRESS: - legal = legal_marshall_move(gs, fFile, fRank, tFile, tRank); - break; - case MAN: - case MAN2: - legal = legal_man_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); + break; + case MAN: + case MAN2: + legal = legal_man_move(gs, fFile, fRank, tFile, tRank); + break; case QUEEN: legal = legal_queen_move(gs, fFile, fRank, tFile, tRank); break; @@ -1483,17 +1485,18 @@ int legal_move(struct game_state_t * gs, * the move is legal. Returns MOVE_ILLEGAL if move leaves you in check */ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int promote) { - struct game_state_t fakeMove; - - mt->pieceCaptured = gs->board[mt->toFile][mt->toRank]; - mt->enPassant = 0; /* Don't know yet, let execute move take care - of it */ - if (mt->fromFile == ALG_DROP) { - mt->piecePromotionTo = NOPIECE; - sprintf(mt->moveString, "%s/%c%c-%c%d", - wpstring[mt->fromRank], - DROP_CHAR, DROP_CHAR, - mt->toFile + 'a', mt->toRank + 1 - (gs->ranks>9)); + 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 + of it */ + if (mt->fromFile == ALG_DROP) { + mt->piecePromotionTo = NOPIECE; + sprintf(mt->moveString, "%s/%c%c-%c%d", + wpstring[mt->fromRank], + DROP_CHAR, DROP_CHAR, + mt->toFile + 'a', mt->toRank + 1 - (gs->ranks>9)); } 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"); @@ -1528,56 +1531,73 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom if(mt->toRank == 0 || mt->toRank == gs->files-1) promote = GOLD; default: break; } - if(promote) mt->piecePromotionTo = promote | (colorval(gs->board[mt->fromFile][mt->fromRank])); + if(promote) mt->piecePromotionTo = promote | (colorval(gs->board[mt->fromFile][mt->fromRank])); } else if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) && - !gs->palace && // [HGM] XQ: no promotions in xiangqi - ((mt->toRank == 0) || (mt->toRank == gs->ranks-1))) { + !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; + if(promote == PAWN) return MOVE_ILLEGAL; // nothing available + } + } // 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 - mt->piecePromotionTo = promote | - (colorval(gs->board[mt->fromFile][mt->fromRank])); - } else { - mt->piecePromotionTo = NOPIECE; - } - if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) && - ((mt->fromRank - mt->toRank == 2) || (mt->toRank - mt->fromRank == 2))) { - mt->doublePawn = mt->fromFile; - } else { - mt->doublePawn = -1; + // 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; + } + if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) && + ((mt->fromRank - mt->toRank == 2) || (mt->toRank - mt->fromRank == 2))) { + mt->doublePawn = mt->fromFile; + } else { + mt->doublePawn = -1; } #if 0 - if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) && + if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) && (mt->fromFile == gs->files/2) && (mt->toFile == 2) && - mt->fromRank == mt->toRank) { - sprintf(mt->moveString, "o-o-o"); - } else if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) && + mt->fromRank == mt->toRank) { + sprintf(mt->moveString, "o-o-o"); + } else if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) && (mt->fromFile == gs->files/2) && (mt->toFile == gs->files-2) && - mt->fromRank == mt->toRank) { + mt->fromRank == mt->toRank) { sprintf(mt->moveString, "o-o"); } else { #else { -#endif - sprintf(mt->moveString, "%s/%c%d-%c%d", - wpstring[piecetype(gs->board[mt->fromFile][mt->fromRank])], - mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks>9), - mt->toFile + 'a', mt->toRank + 1 - (gs->ranks>9)); - } - } - /* Replace this with an algabraic de-parser */ - - sprintf(mt->algString, alg_unparse(gs, mt)); - fakeMove = *gs; - /* Calculates enPassant also */ - execute_move(&fakeMove, mt, 0); - - /* Does making this move leave ME in check? */ - if (in_check(&fakeMove)) - return MOVE_ILLEGAL; - /* IanO: bughouse variants: drop cannot be check/checkmate */ - - return MOVE_OK; +#endif + sprintf(mt->moveString, "%s/%c%d-%c%d", + wpstring[piecetype(gs->board[mt->fromFile][mt->fromRank])], + mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks>9), + mt->toFile + 'a', mt->toRank + 1 - (gs->ranks>9)); + } + } + /* Replace this with an algabraic de-parser */ + + sprintf(mt->algString, alg_unparse(gs, mt)); + 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)) + return MOVE_ILLEGAL; + /* IanO: bughouse variants: drop cannot be check/checkmate */ + + return MOVE_OK; } int legal_andcheck_move(struct game_state_t * gs, @@ -1585,6 +1605,7 @@ int legal_andcheck_move(struct game_state_t * gs, int tFile, int tRank) { struct move_t mt; + if (!legal_move(gs, fFile, fRank, tFile, tRank)) return 0; mt.color = gs->onMove; @@ -1593,7 +1614,7 @@ int legal_andcheck_move(struct game_state_t * gs, mt.toFile = tFile; mt.toRank = tRank; /* This should take into account a pawn promoting to another piece */ - if (move_calculate(gs, &mt, QUEEN) == MOVE_OK) + if (move_calculate(gs, &mt, NOPIECE) == MOVE_OK) return 1; else return 0; @@ -1603,36 +1624,36 @@ int legal_andcheck_move(struct game_state_t * gs, */ int in_check(struct game_state_t * gs) { - int f, r; - int kf = -1, kr = -1; - - /* Find the king */ - if (gs->onMove == WHITE) { - for (f = 0; f < gs->files && kf < 0; f++) - for (r = 0; r < gs->ranks && kf < 0; r++) - if (gs->board[f][r] == B_KING) { - kf = f; - kr = r; - } - } else { - for (f = 0; f < gs->files && kf < 0; f++) - for (r = 0; r < gs->ranks && kf < 0; r++) - if (gs->board[f][r] == W_KING) { - kf = f; - kr = r; - } - } - if (kf < 0) { - d_printf( "CHESSD: Error game with no king!\n"); - return 0; - } - for (InitPieceLoop(gs->board, &f, &r, gs->onMove); - NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) { + int f, r; + int kf = -1, kr = -1; + + /* Find the king */ + if (gs->onMove == WHITE) { + for (f = 0; f < gs->files && kf < 0; f++) + for (r = 0; r < gs->ranks && kf < 0; r++) + if (gs->board[f][r] == B_KING) { + kf = f; + kr = r; + } + } else { + for (f = 0; f < gs->files && kf < 0; f++) + for (r = 0; r < gs->ranks && kf < 0; r++) + if (gs->board[f][r] == W_KING) { + kf = f; + kr = r; + } + } + if (kf < 0) { + d_printf( "CHESSD: Error game with no king!\n"); + return 0; + } + for (InitPieceLoop(gs->board, &f, &r, gs->onMove); + NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) { if (legal_move(gs, f, r, kf, kr)) { /* In Check? */ - return 1; - } - } - return 0; + return 1; + } + } + return 0; } int has_legal_move(struct game_state_t * gs) @@ -1658,18 +1679,20 @@ int has_legal_move(struct game_state_t * gs) case ROOK: possible_rook_moves(gs, f, r, possiblef, possibler, &numpossible); break; - case CARDINAL: - case PRINCESS: - possible_cardinal_moves(gs, f, r, possiblef, possibler, &numpossible); - break; - case MARSHALL: - case EMPRESS: - possible_marshall_moves(gs, f, r, possiblef, possibler, &numpossible); - break; - case MAN: - case MAN2: - possible_man_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); + break; + case MAN: + case MAN2: + possible_man_moves(gs, f, r, possiblef, possibler, &numpossible); + break; case QUEEN: possible_queen_moves(gs, f, r, possiblef, possibler, &numpossible); break; @@ -1753,31 +1776,29 @@ int has_legal_move(struct game_state_t * gs) } } - /* IanO: if we got here, then kf and kr must be set */ + /* IanO: if we got here, then kf and kr must be set */ if (gs->gameNum >=0 && game_globals.garray[gs->gameNum].link >= 0 - || gs->holdings) { // [HGM] zh: also in 2-player games with drops - /* bughouse: potential drops as check interpositions */ - gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]++; - for (f=kf-1; f<=kf+1; f++) for (r=kr-1; r<=kr+1; r++) { - if (f>=0 && ffiles && r>=0 && rranks && gs->board[f][r] == NOPIECE) { - /* try a drop next to the king */ - if (legal_andcheck_move(gs, ALG_DROP, QUEEN, f, r)) { + || gs->holdings) { // [HGM] zh: also in 2-player games with drops + /* bughouse: potential drops as check interpositions */ + gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]++; + for (f=kf-1; f<=kf+1; f++) for (r=kr-1; r<=kr+1; r++) { + if (f>=0 && ffiles && r>=0 && rranks && gs->board[f][r] == NOPIECE) { + /* try a drop next to the king */ + if (legal_andcheck_move(gs, ALG_DROP, QUEEN, f, r)) { gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]--; // OK, so we have an interposing drop. But do we have something to drop? if(game_globals.garray[gs->gameNum].link < 0) { // we have no partner, so we must have something to drop now for(i=QUEEN; i>=PAWN; i--) - if(gs->holding[gs->onMove==WHITE ? 0 : 1][i-1]) break; - if(i > PAWN) return 1; // we have a non-Pawn to drop - // We have a Pawn, but check if it legal to drop it - if(i == PAWN && r != 0 && r != gs->ranks-1) return 1; // [HGM] todo: for Shogi there are extra conditions on Pawn drops! - } - return 1; - } - } - } - gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]--; - } + if (legal_andcheck_move(gs, ALG_DROP, i, f, r)) return 1; + return 0; + } + return 1; + } + } + } + gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]--; + } return 0; } @@ -1785,80 +1806,80 @@ int has_legal_move(struct game_state_t * gs) /* This will end up being a very complicated function */ int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int promote) { - int type = is_move(mstr); - int result; - - mt->piecePromotionTo = NOPIECE; - mt->color = gs->onMove; - switch (type) { - case MS_NOTMOVE: - return MOVE_ILLEGAL; - break; - case MS_COMP: - mt->fromFile = mstr[0] - 'a'; - mt->fromRank = mstr[1] - '1' + (gs->ranks>9); - mt->toFile = mstr[2] - 'a'; - mt->toRank = mstr[3] - '1' + (gs->ranks>9); - break; - case MS_COMPDASH: - mt->fromFile = mstr[0] - 'a'; - mt->fromRank = mstr[1] - '1' + (gs->ranks>9); - mt->toFile = mstr[3] - 'a'; - mt->toRank = mstr[4] - '1' + (gs->ranks>9); - break; - case MS_KCASTLE: + int type = is_move(mstr); + int result; + + mt->piecePromotionTo = NOPIECE; + mt->color = gs->onMove; + switch (type) { + case MS_NOTMOVE: + return MOVE_ILLEGAL; + break; + case MS_COMP: + mt->fromFile = mstr[0] - 'a'; + mt->fromRank = mstr[1] - '1' + (gs->ranks>9); + mt->toFile = mstr[2] - 'a'; + mt->toRank = mstr[3] - '1' + (gs->ranks>9); + break; + case MS_COMPDASH: + mt->fromFile = mstr[0] - 'a'; + mt->fromRank = mstr[1] - '1' + (gs->ranks>9); + mt->toFile = mstr[3] - 'a'; + mt->toRank = mstr[4] - '1' + (gs->ranks>9); + break; + case MS_KCASTLE: #if 0 - mt->fromFile = gs->files/2; - mt->toFile = gs->files-2; - if (gs->onMove == WHITE) { - mt->fromRank = 0; - mt->toRank = 0; - } else { - mt->fromRank = gs->ranks-1; - mt->toRank = gs->ranks-1; - } + mt->fromFile = gs->files/2; + mt->toFile = gs->files-2; + if (gs->onMove == WHITE) { + mt->fromRank = 0; + mt->toRank = 0; + } else { + mt->fromRank = gs->ranks-1; + mt->toRank = gs->ranks-1; + } break; #endif // [HGM] castle: for now always assume Fischer-type castling (of which normal castling is a special case). - mt->fromFile = ALG_CASTLE; - mt->toFile = gs->files-2; - mt->fromRank = gs->onMove == WHITE ? gs->wkrmoved : gs->bkrmoved; - mt->toRank = mt->toFile-1; // R next to K - break; + mt->fromFile = ALG_CASTLE; + mt->toFile = gs->files-2; + mt->fromRank = gs->onMove == WHITE ? gs->wkrmoved : gs->bkrmoved; + mt->toRank = mt->toFile-1; // R next to K + break; case MS_QCASTLE: -#if 0 - mt->fromFile = gs->files/2; - mt->toFile = 2; - if (gs->onMove == WHITE) { - mt->fromRank = 0; - mt->toRank = 0; - } else { - mt->fromRank = gs->ranks-1; - mt->toRank = gs->ranks-1; - } +#if 0 + mt->fromFile = gs->files/2; + mt->toFile = 2; + if (gs->onMove == WHITE) { + mt->fromRank = 0; + mt->toRank = 0; + } else { + mt->fromRank = gs->ranks-1; + mt->toRank = gs->ranks-1; + } break; -#endif - mt->fromFile = ALG_CASTLE; - mt->toFile = 2; - mt->fromRank = gs->onMove == WHITE ? gs->wqrmoved : gs->bqrmoved; +#endif + mt->fromFile = ALG_CASTLE; + mt->toFile = 2; + mt->fromRank = gs->onMove == WHITE ? gs->wqrmoved : gs->bqrmoved; mt->toRank = mt->toFile+1; - break; - case MS_ALG: - /* Fills in the mt structure */ - if ((result = alg_parse_move(mstr, gs, mt)) != MOVE_OK) - return result; - break; - default: - return MOVE_ILLEGAL; - break; + break; + case MS_ALG: + /* Fills in the mt structure */ + if ((result = alg_parse_move(mstr, gs, mt)) != MOVE_OK) + return result; + break; + default: + return MOVE_ILLEGAL; + break; } if((mt->fromRank >= gs->ranks || mt->fromRank < 0 || mt->fromFile >= gs->files) && - mt->fromFile != ALG_DROP && mt->fromFile != ALG_CASTLE - || mt->toRank < 0 || mt->toRank >= gs->ranks || mt->toFile >= gs->files) + mt->fromFile != ALG_DROP && mt->fromFile != ALG_CASTLE + || mt->toRank < 0 || mt->toRank >= gs->ranks || mt->toFile >= gs->files) return MOVE_ILLEGAL; // [HGM] make sure move stays on board - + if (!(result = legal_move(gs, mt->fromFile, mt->fromRank, mt->toFile, mt->toRank))) - return MOVE_ILLEGAL; + return MOVE_ILLEGAL; if(result == 2) { // [HGM] castle: orthodox castling was given as King move; convert it to new format if(mt->fromFile - mt->toFile > 1) { // Q-side @@ -1869,14 +1890,13 @@ int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int pro mt->toRank = mt->toFile-1; } mt->fromFile = ALG_CASTLE; - } - + } + if (mt->piecePromotionTo != NOPIECE) { - promote = piecetype(mt->piecePromotionTo); -printf("promotion piece = %d, type = %d",mt->piecePromotionTo, promote); - } - - return move_calculate(gs, mt, promote); + promote = piecetype(mt->piecePromotionTo); + } else if(gs->promoType == 3 && promote == MASTODON) promote = GOLD; + + return move_calculate(gs, mt, promote); } /* Returns MOVE_OK, MOVE_NOMATERIAL, MOVE_CHECKMATE, or MOVE_STALEMATE */ @@ -1907,20 +1927,28 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st gs->bkmoved = -gs->bkmoved-2; } // move Rook & King, in a way that is resistant to ending where they started (for FRC!) - rook = gs->board[mt->fromRank][backRank]; // first remember - king = gs->board[fKing][backRank]; - gs->board[mt->fromRank][backRank] = NOPIECE; // then erase gs->board[fKing][backRank] = NOPIECE; gs->board[mt->toRank][backRank] = rook; // then put back + rook = gs->board[mt->fromRank][backRank]; // first remember + king = gs->board[fKing][backRank]; + gs->board[mt->fromRank][backRank] = NOPIECE; // then erase + gs->board[fKing][backRank] = NOPIECE; + gs->board[mt->toRank][backRank] = rook; // then put back gs->board[mt->toFile][backRank] = king; } 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)) { @@ -1942,11 +1970,11 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st } gs->board[mt->toFile][mt->fromRank] = NOPIECE; } - /* Check en-passant flags for next moves */ - for (i = 0; i < gs->files; i++) { - gs->ep_possible[0][i] = 0; - gs->ep_possible[1][i] = 0; - } + /* Check en-passant flags for next moves */ + for (i = 0; i < gs->files; i++) { + gs->ep_possible[0][i] = 0; + gs->ep_possible[1][i] = 0; + } /* Added by Sparky 3/16/95 From soso@Viktoria.drp.fmph.uniba.sk Thu Mar 16 13:08:51 1995 @@ -1963,105 +1991,106 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st if ((mt->toFile+1 < 7 ) .... should be : (mt->toFile < 7 ) } */ - if ((piecetype(movedPiece) == PAWN) && - ((mt->fromRank == mt->toRank + 2) || (mt->fromRank + 2 == mt->toRank))) { - /* Should turn on enpassent flag if possible */ - if (gs->onMove == WHITE) { - if ((mt->toFile < gs->files-1) && gs->board[mt->toFile + 1][mt->toRank] == B_PAWN) { - gs->ep_possible[1][mt->toFile + 1] = -1; - } - if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][mt->toRank] == B_PAWN) { - gs->ep_possible[1][mt->toFile - 1] = 1; - } - } else { - if ((mt->toFile < gs->files-1) && gs->board[mt->toFile + 1][mt->toRank] == W_PAWN) { - gs->ep_possible[0][mt->toFile + 1] = -1; - } - if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][mt->toRank] == W_PAWN) { - gs->ep_possible[0][mt->toFile - 1] = 1; - } - } - } - if ((piecetype(movedPiece) == ROOK) && (mt->fromRank == 0) && (gs->onMove == WHITE)) { - if (mt->fromFile == gs->wqrmoved) // [HGM] castle: flip w.r.t. -1 to remember original - gs->wqrmoved = -gs->wqrmoved-2; - if (mt->fromFile == gs->wkrmoved) - gs->wkrmoved = -gs->wkrmoved-2; - } - if ((piecetype(movedPiece) == ROOK) && (mt->fromRank == gs->ranks-1) && (gs->onMove == BLACK)) { - if (mt->fromFile == gs->bqrmoved) - gs->bqrmoved = -gs->bqrmoved-2; - if (mt->fromFile == gs->bkrmoved) - gs->bkrmoved = -gs->bkrmoved-2; - } - if (piecetype(movedPiece) == KING) { - if ((gs->onMove == WHITE) && (mt->fromFile == gs->wkmoved)) - gs->wkmoved = -gs->wkmoved-2; - if ((gs->onMove == BLACK) && (mt->fromFile == gs->bkmoved)) - gs->bkmoved = -gs->bkmoved-2; - } -#if 0 - if ((piecetype(movedPiece) == KING) && + if ((piecetype(movedPiece) == PAWN) && + ((mt->fromRank == mt->toRank + 2) || (mt->fromRank + 2 == mt->toRank))) { + /* Should turn on enpassent flag if possible */ + if (gs->onMove == WHITE) { + if ((mt->toFile < gs->files-1) && gs->board[mt->toFile + 1][mt->toRank] == B_PAWN) { + gs->ep_possible[1][mt->toFile + 1] = -1; + } + if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][mt->toRank] == B_PAWN) { + gs->ep_possible[1][mt->toFile - 1] = 1; + } + } else { + if ((mt->toFile < gs->files-1) && gs->board[mt->toFile + 1][mt->toRank] == W_PAWN) { + gs->ep_possible[0][mt->toFile + 1] = -1; + } + if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][mt->toRank] == W_PAWN) { + gs->ep_possible[0][mt->toFile - 1] = 1; + } + } + } + if ((piecetype(movedPiece) == ROOK) && (mt->fromRank == 0) && (gs->onMove == WHITE)) { + if (mt->fromFile == gs->wqrmoved) // [HGM] castle: flip w.r.t. -1 to remember original + gs->wqrmoved = -gs->wqrmoved-2; + if (mt->fromFile == gs->wkrmoved) + gs->wkrmoved = -gs->wkrmoved-2; + } + if ((piecetype(movedPiece) == ROOK) && (mt->fromRank == gs->ranks-1) && (gs->onMove == BLACK)) { + if (mt->fromFile == gs->bqrmoved) + gs->bqrmoved = -gs->bqrmoved-2; + if (mt->fromFile == gs->bkrmoved) + gs->bkrmoved = -gs->bkrmoved-2; + } + if (piecetype(movedPiece) == KING) { + if ((gs->onMove == WHITE) && (mt->fromFile == gs->wkmoved)) + gs->wkmoved = -gs->wkmoved-2; + if ((gs->onMove == BLACK) && (mt->fromFile == gs->bkmoved)) + gs->bkmoved = -gs->bkmoved-2; + } +#if 0 + if ((piecetype(movedPiece) == KING) && ((mt->fromFile == gs->files/2) && (mt->toFile == gs->files-2)) && - mt->fromRank == mt->toRank) { /* Check for KS castling */ - gs->board[gs->files-3][mt->toRank] = gs->board[gs->files-1][mt->toRank]; - gs->board[gs->files-1][mt->toRank] = NOPIECE; - } - if ((piecetype(movedPiece) == KING) && + mt->fromRank == mt->toRank) { /* Check for KS castling */ + gs->board[gs->files-3][mt->toRank] = gs->board[gs->files-1][mt->toRank]; + gs->board[gs->files-1][mt->toRank] = NOPIECE; + } + if ((piecetype(movedPiece) == KING) && ((mt->fromFile == gs->files/2) && (mt->toFile == 2)) && - mt->fromRank == mt->toRank) { /* Check for QS castling */ - gs->board[3][mt->toRank] = gs->board[0][mt->toRank]; - gs->board[0][mt->toRank] = NOPIECE; - } -#endif - } - if (gs->onMove == BLACK) - gs->moveNum++; - - if (check_game_status) { - /* Does this move result in check? */ - if (in_check(gs)) { - /* Check for checkmate */ - gs->onMove = CToggle(gs->onMove); - if (!has_legal_move(gs)) - return MOVE_CHECKMATE; - } else { - /* Check for stalemate */ - gs->onMove = CToggle(gs->onMove); - if (!has_legal_move(gs)) - return gs->stalemate ? MOVE_STALEMATE : MOVE_CHECKMATE; // [HGM] in XQ and shatranj stalemate loses - } -/* loon: check for insufficient mating material, first try */ - foobar = wCnt = bCnt = 0; - for (i=0; ifiles; i++) { + mt->fromRank == mt->toRank) { /* Check for QS castling */ + gs->board[3][mt->toRank] = gs->board[0][mt->toRank]; + gs->board[0][mt->toRank] = NOPIECE; + } +#endif + } + if (gs->onMove == BLACK) + gs->moveNum++; + + if (check_game_status) { + /* Does this move result in check? */ + if (in_check(gs)) { + /* Check for checkmate */ + gs->onMove = CToggle(gs->onMove); + if (!has_legal_move(gs)) + return MOVE_CHECKMATE; + } else { + /* Check for stalemate */ + gs->onMove = CToggle(gs->onMove); + if (!has_legal_move(gs)) + return gs->stalemate ? MOVE_STALEMATE : MOVE_CHECKMATE; // [HGM] in XQ and shatranj stalemate loses + } +/* loon: check for insufficient mating material, first try */ + foobar = wCnt = bCnt = 0; + for (i=0; ifiles; i++) { for (j=0; jranks; j++) { - int p = gs->board[i][j]; - switch(piecetype(p)) { - case KNIGHT: - case BISHOP: - foobar++; - break; - case KING: - case NOPIECE: - break; - default: - foobar = 2; - break; + int p = gs->board[i][j]; + switch(piecetype(p)) { + case KNIGHT: + case BISHOP: + foobar++; + break; + case KING: + case NOPIECE: + break; + default: + foobar = 2; + break; } if(p != NOPIECE && iscolor(p, WHITE)) wCnt++; - if(iscolor(p, BLACK)) bCnt++; - } + if(iscolor(p, BLACK)) bCnt++; + } } if(gs->bareKingLoses) { // [HGM] with bare-King-loses rule only KK is insuff. material if(gs->onMove == BLACK && wCnt == 1 && bCnt > 1) return MOVE_BARE; if(gs->onMove == WHITE && bCnt == 1 && wCnt > 1) return MOVE_BARE; if(bCnt == 1 && wCnt == 1) return MOVE_NOMATERIAL; - } else if (foobar < 2) - return MOVE_NOMATERIAL; - } else { - gs->onMove = CToggle(gs->onMove); - } - return MOVE_OK; + } else if (foobar < 2) + return MOVE_NOMATERIAL; + } else { + gs->onMove = CToggle(gs->onMove); + } + + return MOVE_OK; } int backup_move(int g, int mode) @@ -2126,36 +2155,36 @@ int backup_move(int g, int mode) if (i == game_globals.garray[g].numHalfMoves - 1) gs->wqrmoved = m->fromFile; } - if ((m->fromFile == -gs->wkrmoved-2) && (m->fromRank == 0)) { - for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { - m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; - if ((m1->fromFile == -gs->wkrmoved-2) && (m1->fromRank == 0)) - break; - } - if (i == game_globals.garray[g].numHalfMoves - 1) - gs->wkrmoved = m->fromFile; - } - } else { - if ((m->fromFile == -gs->bqrmoved-2) && (m->fromRank == gs->ranks-1)) { - for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { - m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; - if ((m1->fromFile == -gs->bkrmoved-2) && (m1->fromRank == gs->ranks-1)) - break; - } - if (i == game_globals.garray[g].numHalfMoves - 1) - gs->bqrmoved = m->fromFile; - } - if ((m->fromFile == -gs->bkrmoved-2) && (m->fromRank == gs->ranks-1)) { - for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { - m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; - if ((m1->fromFile == -gs->wkrmoved-2) && (m1->fromRank == gs->ranks-1)) - break; - } - if (i == game_globals.garray[g].numHalfMoves - 1) - gs->bkrmoved = m->fromFile; - } - } - } + if ((m->fromFile == -gs->wkrmoved-2) && (m->fromRank == 0)) { + for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { + m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; + if ((m1->fromFile == -gs->wkrmoved-2) && (m1->fromRank == 0)) + break; + } + if (i == game_globals.garray[g].numHalfMoves - 1) + gs->wkrmoved = m->fromFile; + } + } else { + if ((m->fromFile == -gs->bqrmoved-2) && (m->fromRank == gs->ranks-1)) { + for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { + m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; + if ((m1->fromFile == -gs->bkrmoved-2) && (m1->fromRank == gs->ranks-1)) + break; + } + if (i == game_globals.garray[g].numHalfMoves - 1) + gs->bqrmoved = m->fromFile; + } + if ((m->fromFile == -gs->bkrmoved-2) && (m->fromRank == gs->ranks-1)) { + for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { + m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; + if ((m1->fromFile == -gs->wkrmoved-2) && (m1->fromRank == gs->ranks-1)) + break; + } + if (i == game_globals.garray[g].numHalfMoves - 1) + gs->bkrmoved = m->fromFile; + } + } + } if (piecetype(gs->board[m->fromFile][m->fromRank]) == KING) { gs->board[m->toFile][m->toRank] = m->pieceCaptured; #if 0 @@ -2203,29 +2232,29 @@ int backup_move(int g, int mode) we should scan moveList. *******************/ - if (m->color == WHITE) { - - if ((m->fromFile == -gs->wkmoved-2) && (m->fromRank == 0)) { - for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { - m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; - if ((m1->fromFile == gs->wkmoved-2) && (m1->fromRank == 0)) - break; - } - if (i == game_globals.garray[g].numHalfMoves - 1) - gs->wkmoved = m->fromFile; - } - } else { - if ((m->fromFile == -gs->bkmoved-2) && (m->fromRank == gs->ranks-1)) { - for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { - m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; - if ((m1->fromFile == -gs->bkmoved-2) && (m1->fromRank == gs->ranks-1)) - break; - } - if (i == game_globals.garray[g].numHalfMoves - 1) - gs->bkmoved = m->fromFile; - } - } - } + if (m->color == WHITE) { + + if ((m->fromFile == -gs->wkmoved-2) && (m->fromRank == 0)) { + for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { + m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; + if ((m1->fromFile == gs->wkmoved-2) && (m1->fromRank == 0)) + break; + } + if (i == game_globals.garray[g].numHalfMoves - 1) + gs->wkmoved = m->fromFile; + } + } else { + if ((m->fromFile == -gs->bkmoved-2) && (m->fromRank == gs->ranks-1)) { + for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) { + m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i]; + if ((m1->fromFile == -gs->bkmoved-2) && (m1->fromRank == gs->ranks-1)) + break; + } + if (i == game_globals.garray[g].numHalfMoves - 1) + gs->bkmoved = m->fromFile; + } + } + } if (m->enPassant) { /* Do enPassant */ gs->board[m->toFile][m->fromRank] = PAWN | (colorval(gs->board[m->fromFile][m->fromRank]) == WHITE ? BLACK : WHITE); @@ -2234,6 +2263,9 @@ int backup_move(int g, int mode) 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); @@ -2304,28 +2336,28 @@ cleanupMove: array. (patch from Soso, added by Sparky 3/17/95) ********/ - if (game_globals.garray[g].numHalfMoves > 0) { - m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves - 1] : - &game_globals.garray[g].examMoveList[game_globals.garray[g].numHalfMoves - 1]; - if (piecetype(gs->board[m1->toFile][m1->toRank]) == PAWN) { - if ((m1->toRank - m1->fromRank) == 2) { - if ((m1->toFile < gs->files-1) && gs->board[m1->toFile + 1][m1->toRank] == B_PAWN) { - gs->ep_possible[1][m1->toFile + 1] = -1; - } - if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][m1->toRank] == B_PAWN) { - gs->ep_possible[1][m1->toFile - 1] = 1; - } - } - if ((m1->toRank - m1->fromRank) == -2) { - if ((m1->toFile < gs->files-1) && gs->board[m1->toFile + 1][m1->toRank] == W_PAWN) { - gs->ep_possible[0][m1->toFile + 1] = -1; - } - if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][m1->toRank] == W_PAWN) { - gs->ep_possible[0][m1->toFile - 1] = 1; - } - } - } - } + if (game_globals.garray[g].numHalfMoves > 0) { + m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves - 1] : + &game_globals.garray[g].examMoveList[game_globals.garray[g].numHalfMoves - 1]; + if (piecetype(gs->board[m1->toFile][m1->toRank]) == PAWN) { + if ((m1->toRank - m1->fromRank) == 2) { + if ((m1->toFile < gs->files-1) && gs->board[m1->toFile + 1][m1->toRank] == B_PAWN) { + gs->ep_possible[1][m1->toFile + 1] = -1; + } + if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][m1->toRank] == B_PAWN) { + gs->ep_possible[1][m1->toFile - 1] = 1; + } + } + if ((m1->toRank - m1->fromRank) == -2) { + if ((m1->toFile < gs->files-1) && gs->board[m1->toFile + 1][m1->toRank] == W_PAWN) { + gs->ep_possible[0][m1->toFile + 1] = -1; + } + if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][m1->toRank] == W_PAWN) { + gs->ep_possible[0][m1->toFile - 1] = 1; + } + } + } + } /************** and here's the end **************/ return MOVE_OK; }