We don't need that !
We can infere from starting fen string if we are in
a Chess960 game or not. And note that this is a per-position
property, not an application wide one.
A nice trick is to use a custom manipulator (that is an
enum actually) to keep using the handy operator<<() on the
move when sending to std::cout, yes, I have indulged a
bit here ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We don't need to pass side_to_move because we can get
it directly from the position object.
Note that in benchmark we always used to pass '0' and
it was a bug, but with no effect because was used only
in time[] and increment[], set always to 0 for both
colors.
Also additional small cleanup while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the world's fussiest compiler with +w1
Warnings reported by Richard Lloyd.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We can do this only when needed, if we get a cut-off
before we skip sorting entirely. This reduces sorting
time of about 20%.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
With negative history we don't have anymore a
lot of zeroes to score, so just split moves in
positives and non-positives sets.
Speed up is almost zero, we cannot test speed directly
because node count changed due to reorder, but I have
verified sorting is correct. With a profiler I have
seen we gain a little in sort_moves() and lose a little
in insertion_sort(), so the net effect is almost zero,
but code is simpler.
No real change, just move reordering.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Becasue we have a lot of zero scores (around 30% of moves)
it is a good idea to do a couple a presorting loops across
the move list and shuffle the moves a bit so that with a
small effort we end up with 3 groups of moves: positives
scores, zero scores and negative scores.
We have two advantages
1) We don't need to sort zero scores
2) Sort two small groups is faster then sort a single big one
Speed up is of about 2%
Because equal scored moves could be reordered in a different way
this is not a "no functional change" although I have verified
the output list is always correctly sorted.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When the move list is very small, like captures normally
are, it is faster to pick the best move with a linear
scan, one per cycle.
This has the added advantage that the picked capture move is
very possibly a cut-off move, so that other searches are
avoided. For non-captures it is still faster to sort in
advance.
Because scan-and-pick alghortim is not stable, node count
has changed.
After 885 games at 1+0
Mod vs Orig +196 =510 -179 50.96% 451.0/885
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is stable and it is also a bit faster then std::sort()
on the tipical small move lists that we need to handle.
Verified to have same functionality of std::stable_sort()
After 999 games at 1+0
Mod vs Orig +240 =534 -225 50.75% 507.0/999 +5 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Unfortunatly std::stable_sort() implementation in gcc is
horrendously slow. We have a big performance regression on
Linux systems (-20% !)
So revert the commit and wait to fix the issue in a different
way, perhaps with an our home grown sorting, that should be
comparable in speed with std::sort()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Standard does not mandate std::sort() to be stable, so we
can have, and actually do have different node count on
different platforms.
So use the platform independent std::stable_sort() and gain
same functionality on any platform (Windows, Unix, Mac OS)
and with any compiler (MSVC, gcc or Intel C++).
This sort is teoretically slower, but profiling shows only a very
minimal drop in performance, probably due to the fact that
the set to sort is very small, mainly only captures and with
less frequency non-captures, anyhow we are talking of 30-40 moves
in the worst average case. Sorting alghortims are build to work on
thousands or even milions of elements. With such small sets
performance difference seems not noticable.
After 999 games at 1+0
Mod vs Orig +234 =523 -242 -3 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Rename to move_is_promotion() to be more clear, also add
a new function move_promotion_piece() to get the
promotion piece type in the few places where is needed.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of a delayed selection sort so that the highest
score move is picked up from the list when needed, sort all
the moves up front just after score them.
Selection sort is O(n*n) while std::sort is O(n*log n), it
is true that delayed selection allows us to just pick the move
until a cut off occurs or up to a given limit (12), but with
an average of 30 non capture-moves delayed pick become slower
just after 5-6 moves and we now pick up to 12.
Profiling seem to prove this idea and movepick.cpp is now 10%
faster.
Also tests seem to confirm this:
After 700 games at 1+0: Mod vs Orig +178 -160 =362 +9 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>