Speed up move generation for xiangqi
authorFabian Fichter <ianfab@users.noreply.github.com>
Sun, 17 Nov 2019 14:10:37 +0000 (15:10 +0100)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sun, 17 Nov 2019 14:10:37 +0000 (15:10 +0100)
Filter out invalid soldier and general moves early.

src/movegen.cpp
src/position.cpp

index 03ac9ff..e0b0377 100644 (file)
@@ -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);
 
@@ -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));
 
@@ -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));
@@ -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)
@@ -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));
 
index c007d0e..92fde7a 100644 (file)
@@ -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;
@@ -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.
@@ -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)