Skip to content

Commit

Permalink
Speed up move generation for xiangqi
Browse files Browse the repository at this point in the history
Filter out invalid soldier and general moves early.
  • Loading branch information
ianfab committed Nov 17, 2019
1 parent ecac535 commit 94bbcff
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 9 deletions.
13 changes: 13 additions & 0 deletions src/movegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ namespace {

Bitboard b1 = ( (pos.attacks_from(us, pt, from) & pos.pieces())
| (pos.moves_from(us, pt, from) & ~pos.pieces())) & target;
// Xiangqi soldier
if (pt == SOLDIER && pos.unpromoted_soldier(us, from))
b1 &= file_bb(file_of(from));
Bitboard b2 = pos.promoted_piece_type(pt) ? b1 : Bitboard(0);
Bitboard b3 = pos.piece_demotion() && pos.is_promoted(from) ? b1 : Bitboard(0);

Expand Down Expand Up @@ -327,6 +330,8 @@ namespace {
{
Square ksq = pos.square<KING>(Us);
Bitboard b = pos.attacks_from<KING>(ksq, Us) & target;
if (pos.xiangqi_general())
b &= PseudoAttacks[Us][WAZIR][ksq];
while (b)
moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, ksq, pop_lsb(&b));

Expand Down Expand Up @@ -429,7 +434,11 @@ ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
Bitboard b = pos.moves_from(us, pt, from) & ~pos.pieces();

if (pt == KING)
{
b &= ~PseudoAttacks[~us][QUEEN][pos.square<KING>(~us)];
if (pos.xiangqi_general())
b &= PseudoAttacks[us][WAZIR][from];
}

while (b)
moveList = make_move_and_gating<NORMAL>(pos, moveList, us, from, pop_lsb(&b));
Expand Down Expand Up @@ -457,6 +466,8 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {
{
Bitboard target = pos.board_bb() & ~pos.pieces(us);
Bitboard b = pos.attacks_from<KING>(ksq, us) & target;
if (pos.xiangqi_general())
b &= PseudoAttacks[us][WAZIR][ksq];
while (b)
moveList = make_move_and_gating<NORMAL>(pos, moveList, us, ksq, pop_lsb(&b));
return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList, target)
Expand All @@ -474,6 +485,8 @@ ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) {

// Generate evasions for king, capture and non capture moves
Bitboard b = pos.attacks_from<KING>(ksq, us) & ~pos.pieces(us) & ~sliderAttacks;
if (pos.xiangqi_general())
b &= PseudoAttacks[us][WAZIR][ksq];
while (b)
moveList = make_move_and_gating<NORMAL>(pos, moveList, us, ksq, pop_lsb(&b));

Expand Down
18 changes: 9 additions & 9 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied, Color c) const {
b |= pieces(c, FERS) & gates(c) & fers_sq;
}

if (var->xiangqiGeneral)
if (xiangqi_general())
b ^= b & pieces(KING) & ~PseudoAttacks[~c][WAZIR][s];

return b;
Expand Down Expand Up @@ -928,14 +928,6 @@ bool Position::legal(Move m) const {
return false;
}

// Xiangqi general
if (var->xiangqiGeneral && type_of(moved_piece(m)) == KING && !(PseudoAttacks[us][WAZIR][from] & to))
return false;

// Xiangqi soldier
if (type_of(moved_piece(m)) == SOLDIER && unpromoted_soldier(us, from) && file_of(from) != file_of(to))
return false;

// If the moving piece is a king, check whether the destination
// square is attacked by the opponent. Castling moves are checked
// for legality during move generation.
Expand Down Expand Up @@ -974,6 +966,14 @@ bool Position::pseudo_legal(const Move m) const {
if (type_of(m) != NORMAL || is_gating(m))
return MoveList<LEGAL>(*this).contains(m);

// Xiangqi general
if (xiangqi_general() && type_of(pc) == KING && !(PseudoAttacks[us][WAZIR][from] & to))
return false;

// Xiangqi soldier
if (type_of(pc) == SOLDIER && unpromoted_soldier(us, from) && file_of(from) != file_of(to))
return false;

// Handle the case where a mandatory piece promotion/demotion is not taken
if ( mandatory_piece_promotion()
&& (is_promoted(from) ? piece_demotion() : promoted_piece_type(type_of(pc)) != NO_PIECE_TYPE)
Expand Down

0 comments on commit 94bbcff

Please sign in to comment.