It will be overwritten anyway.
Also other little small touches that seem to increase
speed more then the whole enum Score patch series :-(
Optimization is really a black art.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Increases performance because now we use one integer
for both midgame and endgame scores.
Unfortunatly the latest patches seem to have reduced a bit
the speed so at the end we are more or less at the same
performance level of the beginning. But this patch series
introduced also some code cleanup so it is the main reason
we commit anyway.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of MgPieceSquareTable[16][64] and EgPieceSquareTable[16][64]
This allows to fetch mg and eg values from adjacent words in memory.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is now no more needed to know dc candidates
inside MovePicker, so avoid calculating there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Big cleanup and semplification of pawns evasions that
now are pseudo-legal as the remaining moves. This
allow us to remove a lot of tricky code.
Verified against perft: no functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This allow a big semplification in move generation
that will be committed with the next patch. And makes
handling of evasions similar to the other type of moves.
This patch plus the next seem to improve also on
the performance side because after 640 games to
verify there are no hidden regressions we are at +9 ELO
Verified with perft no functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Don't seem to help, perhaps because we
return an approximate SEE score instead of the
real negative score so that we have some bad capture
or evasion sub-optimal ordering that compensates
the speed up.
Anyhow after 999 games at 1+0
Mod vs Orig +240 =514 -245 -2 ELO
So almost no harm to remove and make the code simpler.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because we only generate legal moves we can assume
a king cannot be recaptured, so we can safely return
immediately with the captured piece score. If the move
turns out to be illegal it will be pruned anyhow,
independently from SEE value. This gives a good speed up
especially now that we SEE-test all the evasions that
are always legal and very often are king moves.
Another optimization catches almost 15% of cases, unfortunatly
we have already calculated the very expensive attacks, so
benefits are not so big anyway.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch cuts 30% of SEE calculations, as a drawback
a returned negative value is no more always correct if
a shortcut is found.
This could impact move order when based on negative see
score as example bad captures and evasions.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We want piece list to be terminated with SQ_NONE.
This happens with all the pieces but the pawns that
being 8 make the inner loop exit just before writing
the SQ_NONE value at the tail of the list.
This bug was hidden because currently we don't use
piece list to scan pawns, but this will change in the
future and in any case an initialization should be done
correctly for the whole array to avoid subtle bugs in
the future.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is not equivalent because the check for the
50 moves rule get badly affected.
// Draw by the 50 moves rule?
if (st->rule50 > 100 || (st->rule50 == 100 && !is_check()))
return true;
So we _really_ need two counters.
Thanks to Joona and Tord to be patience with a silly guy ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Null moves can artificially create a repetition
draw where instead there is no one.
So use a second counter to reset history after
a null move.
Idea from Joona.
After 999 games at 1+0
Mod vs Orig +238 =553 -208 51.50% 514.5/999 +10 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It turned out that we used do_move_bb to update the king and rook
bitboards when making and unmaking castling moves, which obviously
doesn't work in Chess960, where the source and destination squares
for the king or rook could be identical.
No functional change in normal chess.
This patch make the piece list always terminated by SQ_NONE,
so that we can use a simpler and faster loop in move
generation.
Speedup is about 0.6%.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is in line with attackers_to() and is shorter and
piece is already redundant because is passed as template
parameter anyway.
Integrate also pawn_attacks_from() in the attacks_from()
family so to have an uniform attack info API.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use the definition in the few places where is needed.
As a nice side effect there is also an optimization in
generate_evasions() where the bitboard of enemy pieces
is computed only once and out of a tight loop.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is a bit longer but much easier to understand especially
for people new to the sources. I remember it was not trivial
for me to understand the returned attack bitboard refers to
attacks launched from the given square and not attacking the
given square.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Most of them are not required to be public and are
used in one place only so remove them and use its
definitions.
Also rename piece_attacks_square() in piece_attacks()
to be aligned to the current naming policy.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
These functions return bitboard of attacking pieces,
not the attacks themselfs so reflect this in the name.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of pawn_attacks(Color c, Square s) define as
pawn_attacks(Square s, Color c) to be more aligned to
the others attack info functions.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Remove undefined functions sliding_attacks() and ray_attacks()
and retire square_is_attacked(), use the corresponding definition
instead. It is more clear that we are computing full attack
info for the given square.
Alos fix some obsolete comments in move generation functions.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Return the bitboard with the pawn attacks for both colors
so to be aligned to the meaning of the others piece_attacks<Piece>
templates.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
One of the most time critical functions is move_is_check()
and in particular the call to type_of_piece_on(from) in the
switch statement.
This call lookups in board[] array and can be slow if board[from]
is not already cached. Few instructions before in the execution stream,
we check the move for legality with pl_move_is_legal().
This patch changes pl_move_is_legal() to use type_of_piece_on(from)
for checking for a king move so that board[from] is automatically
cached in L1 and ready to be used by the near follower move_is_check()
Another advantage is that the call to king_square(us) in pl_move_is_legal()
is avoided most of the times.
Speed up of this nice and tricky patch is 0.7% !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch is built on Tord idea to use functions instead of
templates to access position's bitboards. This has the added advantage
that we don't need fallback functions for cases where the piece
type or the color is a variable and not a constant.
Also added Joona suggestion to workaround request for two types
of pieces like bishop_and_queens() and rook_and_queens().
No functionality or performance change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a single template to get bitboard representation of
the position given the type of piece as a constant.
This removes almost 80 lines of code and introduces an
uniform notation to be used for querying for piece type.
No functional change and no performance change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is used mainly in a bunch of inline oneliners
just below its definition. So substitute it with
the explicit definition and avoid information hiding.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is more clear that only in that case the move number is
correct, otherwise is only a partial quantity: the number of
moves of that phase.
In case of PH_EVASIONS instead we have only one phase.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Array index[] and pieceList[] are not guaranteed to be
invariant to a do_move() + undo_move() sequence when a
capture move is involved.
The reason is that the captured piece is removed form
the list and substituted with the last one in do_move()
while in undo_move() is added again but at the end of
the list.
Because index[] and pieceList[] are used in move generation
to scan the pieces it means that moves will be generated
in a different order before and after a do_move() + undo_move()
sequence as, for instance, the one in Position::has_mate_threat()
After latest patches, move generation could now be invoked
also by MovePicker c'tor and this explains why order of
picked moves is different if MovePicker object is istantiated
before or after a Position::has_mate_threat() call.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This avoids calculating the array entry position
at each access and gives another boost of almost 1%.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There were two asserts.
The first was raised because is_ok() was called at the
beginning of do_castle_move() and this is wrong after
the last code reformatting because at that point the state
is already modified by the caller do_move().
The second, raised by debugIncrementalEval, was due to a
rounding error in compute_value() that occurs because
TempoValueEndgame was updated in an odd number by patch
"Merge Joona Kiiski evaluation tweaks" (3ed603cd) of 13/3/2009
This line in compute_value() is the guilty one:
result += (side_to_move() == WHITE)? TempoValue / 2 : -TempoValue / 2;
The fix is to increment TempoValueEndgame so to be even.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch seems bigger then what actually is.
It just moves some code around and adds a bit of coding style fixes
to do_move() and undo_move() so to have uniformity of naming in both
functions.
The diffstat for the whole patch series is
239 insertions(+), 426 deletions(-)
And final MSVC pgo build is even a bit faster:
Before 448.051 nodes/sec
After 453.810 nodes/sec (+1.3%)
No functional change (tested on more then 100M of nodes)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Integrate undo_ep_move in undo_move() this reduces line count
and code readibility.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Integrate do_ep_move in undo_move() this reduces line count
and code readibility.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Integrate do_promotion_move() in do_move() this reduces line count
and code readibility.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Integrate do_ep_move in do_move() this reduces line count
and code readibility.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This fix a compile error under Linux with gcc when
there aren't the intel dev libraries.
Also simplify the previous patch moving TT definition
from search.cpp to tt.cpp so to avoid using passing a
pointer to TT to the current position.
Finally simplify do_move(), now we miss a prefetch in the
rare case of setting an en-passant square but code is
much cleaner and performance penalty is almost zero.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>