We have only one call place so inline its content.
BTW, function is already declared as FORCE_INLINE.
Also some small refactoring while there.
No functional change.
We have a crash with this position:
rkqbnnbr/pppppppp/8/8/8/8/PPPPPPPP/RKQBNNBR w HAha -
What happens is that even if we are castling QUEEN_SIDE,
in this case we have kfrom (B8) < kto (C8) so the loop
that checks for attackers runs forever leading to a crash.
The fix is to check for (kto > kfrom) instead of
Side == KING_SIDE, but this is slower in the normal case of
ortodhox chess, so rewrite generate_castle() to handle the
chess960 case as a template parameter and allow the compiler
to optimize out the comparison in case of normal chess.
Reported by Ray Banks.
The trick here is to check for legality only in the
(rare) cases we have pinned pieces or a king move
or an en-passant.
This trick is able to increase the speed of perft
of more then 20%!
No functional change.
Further reduce redundancy in move generation.
Veirifed no speed regression on MSVC, Clang and gcc.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Greatly simplify these very performace critical functions.
Amazingly we don't have any speed regression actually under
MSVC we have the same assembly for generate_moves() !
In generate_direct_checks() 'target' is calculated only
once being a loop invariant.
On Clang there is even a slight speed up.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems more accurate: lsb is clear while 'first
bit' depends from where you look at the bitboard.
And fix compile in case of 64 bits platforms that
do not use BSFQ intrinsics.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Let first argument to be the 'color'. This allows to align
pos.pieces() signatures with piece_list(), piece_count() and
all the other functions where 'color' argument is passed as
first one.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is more correct given what the function does. In
particular single_bit() returns true also in case of
empty bitboards.
Of course also the usual renaming while there :-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Shrinking from [16] to [2][2] is able to speedup
perft of start position of almost 5% !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also some microoptimizations, were there from ages
but hidden: the renaming suddendly made them visible!
This is a good example of how better naming lets you write
better code. Naming is really a kind of black art!
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Pre compute castle path so to quickly test
for impeded rule.
This speeds up perft on starting position
of more than 2%.
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This allows to retire ClearMaskBB[] and use just
one SquareBB[] array to set and clear a bit.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They are almost the same, if the function arguments would
have been the same they could even be integrated.
Also a bit of renaming while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Skip calling promotion generation functions in
the very common case of no possible promotion
evasion. Also retire generate_pawn_captures()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It should help to avoid recalculating check squares
of sliding attackers for queen when already done for
bishops and rooks. Of course this helps when there are
bishop, rook and queen on the board !
Fixed also a subtle bug (use of same variable b in while
condition and in condition body) introduced recently by
revision d655147e8c that triggers
in case we have at least 2 non-pawn discovered check pieces.
This is very rare that's why didn't show in the node count
verification where we actually have a case of 2 dc pieces
in position 14, but one is a pawn.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
During generation of non-captures checks (in qsearch)
we don't consider castling moves that give check,
this patch includes also this rare case. Verified with
perft that all the non-capture checks are now generated.
There should be a very little slowdown due to the extra
work, but actually I failed to measure it. I don't expect
any ELO improvment, there is even no functional change on
the standard depth 12 search, it is just to have a correct
move generator.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The full movegen patch series shows a speed up of almost
6% (!) on perft, and code is much more readable too.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
MV_CHECK is an alias of the more appropiate named
MV_NON_CAPTURE_CHECK so use only the latter.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The aim is to have shorter names without losing
readibility but, if possible, increasing it.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It's only necessary to do the checking at the end of every non-const
member (including the constructors and from_fen()) of class Position.
Once the post-condition of every modifier guarantees the class invariant,
we don't need to verify sanity of the position as preconditions for outside
callers such as movegen, search etc. For non-class types such as Move and
Square we still need to assert of course.
Suggested by Rein Halbersma.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After previous patch is no more needed to pass
the color, becuase it is always the side to move.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It worked by accident because we always called both directions,
but definition was wrong.
Functional change due to different generation order, but
perft numbers are the correct ones.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>