Use the following transformations:
- to check that A is included in B, testing "(A & ~B) == 0" is faster
than "(A & B) == A"
- to remove the intersection of A and B from A, doing "A &= ~B;" is as
fast as "if (A & B) A &= ~B;" but is simpler.
Overall, the simpler patch version is 0.3% than current master.
No functional change.
occupied ^= to; // For the case when captured piece is a pinner
// Don't allow pinned pieces to attack pieces except the king as long all
occupied ^= to; // For the case when captured piece is a pinner
// Don't allow pinned pieces to attack pieces except the king as long all
- // pinners are on their original square. When a pinner moves to the
- // exchange-square or get captured on it, we fall back to standard SEE behaviour.
- if ( (stmAttackers & pinned_pieces(stm))
- && (st->pinnersForKing[stm] & occupied) == st->pinnersForKing[stm])
- stmAttackers &= ~pinned_pieces(stm);
+ // pinners are on their original square.
+ if (!(st->pinnersForKing[stm] & ~occupied))
+ stmAttackers &= ~st->blockersForKing[stm];
if (!stmAttackers)
return swapList[0];
if (!stmAttackers)
return swapList[0];
nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
stm = ~stm;
stmAttackers = attackers & pieces(stm);
nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
stm = ~stm;
stmAttackers = attackers & pieces(stm);
- if ( nextVictim != KING
- && (stmAttackers & pinned_pieces(stm))
- && (st->pinnersForKing[stm] & occupied) == st->pinnersForKing[stm])
- stmAttackers &= ~pinned_pieces(stm);
+
+ // Don't allow pinned pieces to attack pieces except the king
+ if ( nextVictim != KING
+ && !(st->pinnersForKing[stm] & ~occupied))
+ stmAttackers &= ~st->blockersForKing[stm];