Bug is subtle because appears only under MSVC 32 bits in
optimized version, hence was missed before.
Bug is due to the fact that evaluation order of terms of a
sum is undefined by the standard, so in get_int() we have:
return 256 * get_int<n-1>() + bookFile.get();
And if get() is evaluated before get_int() we have a corrupted
key.
The patch rewrites the code in a more natural and predictable way.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If blockSq is already on rank 8, blockSq + pawn_push(Us) is on rank 9,
outside of board. It does not make sense to measure king distance to
a field outside the board.
Bug spotted by Fruity:
http://open-chess.org/viewtopic.php?f=5&t=1156&start=10
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Almost useless for the user and now is in sync with
the material value that is already weighted.
A small speedup of 0,4% because we avoid an apply_weight()
call in a fast path.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also simplify tracing because evaluate_unstoppable_pawns()
return always zero if both colors have non pawn material.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Extensive test series on tweaking history limit and bonus
formula. At the end this was the best.
After 11959 games:
Mod vs Orig 2087 - 1934 - 7938 ELO +4 (+- 3.7) LOS 92%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Node count is different just becuase now we don't log on
"bench.txt" file anymore so that we avoid some calls to
pretty_pv() that calls Position::do_move().
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This prevent crashing on mobile devices with limited RAM,
currently with MAX_THREADS = 32 we would need 44MB that
could be too much for a poor cellphone.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This change allows to remove some quite a bit of code
and seems the natural thing to do.
Introduced file thread.cpp to move away from search.cpp a lot
of threads related stuff.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
According to Heinz's tests current setup is in fact too
strong for weak players. This seems the best according
to his tests.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems gain is practically unuseful, so remove.
After 13554 games:
Mod vs Orig 2252 - 2319 - 8983 ELO -1 (+- 3.4)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Shrink search() signature for better readibility.
We get also a nice 1.3% speed increase.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Unfortunatly icc does not understand that weakerSide and
strongerSide belongs to the base class :-(
So we have define them in the derived class.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now that we prefetch in material hash table we
can increase its size and gain something.
Hit rate is now of 98% from 92%
Speedup of 0.8%
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Prefetch both pawn and material tables in do_move() and
prefetch always, not only after a pawn move or a capture.
Speed up of 0,7%
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The only interesting thing is that a backward or isolated
pawn cannot be a candidate passer, so code this condition.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems we have a lot of totally useless code !
After 8577 games 1504 - 1451 - 5622 ELO +2 (+- 4.4)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Add blunder cabability to skill level feature.
The idea is that instead of choosing the best move at the end
of the ID loop, we now do this at a randomly chosen sampling depth
dependent on SkillLevel, so that at low skill levels we sample when
ID loop has reached only a small depth and so we have an higher
probability to pick up a blunder.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The idea is to try a shallow search with reduced beta
on bad captures so to quickly prune them out in case
are really bad.
After 5529 games 966 - 868 - 3695 ELO +6 (+- 5.4) LOS 91%
Tested also version without upper limitation to 8 plies:
After 8780 games 1537 - 1398 - 5850 ELO +5 (+- 4.3) LOS 93%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Rescaled Skill level from 0 to 20. At level 19 is still
comparable with Crafty 20.14, while at low levels strength
increase is now less steep.
Thanks to Joona and Heinz for testing and valuable
comments.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is now possible to adjust skill level of Stockfish
from 10 (full strength) to 0.
Skill adjustment is done in such a way that is CPU speed and
time control largely independent, at least at low skills. It
means that given a skill we have same play level on a mobile
phone and on a super OCTAL CPU, at 1' per game or at 180'.
At skill 9 strength is that of an average engine, I have used
Crafty 20.14 to tune and we are more or less there. At skill 0
engine is pretty weak but still shows a realistic play.
When skill is not used we don't have any impact on the regular
code.
Idea to use MultiPV is from Heinz van Saanen, implementation and
formulas by me.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is how Shredder, Rybka and others do and
avoids user is confused by a fail high (sent to GUI)
followed by a fail low (not sent).
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Has been reported by Justin Blanchard that
this creates problems on some buggy GUI.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
With off-by-one bug in InFrontBB[] loop fixed.
Also use int instead of File to workaround a bug
in mingw 4.4.0 in first loop that cycles forever.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
No speed regression after 8731 games:
Mod vs Orig 1394 - 1342 - 5995 ELO +2 (+- 4.1)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Otherwise in case we change an option with setoption and
then ask for "eval" command the evaluation is not updated.
Spotted by Justin Blanchard.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix a corner case where we start aspiration window and
suddendly we get a VALUE_KNOWN_WIN / MATE score, this makes
aspiration to blow up in a series of researches loops.
Exit aspiration loop in that case.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use first iteration to get a proper startup score
and possibly detect an easy move.
After 5180 games:
Mod vs Orig 847 - 823 - 3510 ELO +1 (+- 5.5)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because we are never in check there and evaluation cannot
return a mated value the condition is useless.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch is based on Justin Blanchard's original
work and allows to breakdown evaluation in its sub terms and
show to the user.
Tracing code has zero speed impact when not used.
Note that tracing code is not thread-safe, but this
should not be a problem given the typical usage scenario.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use Square instead. At the end is the same because we were
anyway foreseen operators on mixed terms (Square, SquareDelta).
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now that we don't have anymore a search stack array in
SplitPoint we can rename this data member to somthing more
usual.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a local variable instead. To make it work we need to
correctly init next ply search stack at the beginning of the
search because now that ss is allocated on the stack instead
of on the global storage it contains garbage.
As a side effect we can peform a fast search stack
init in id_loop().
With this patch size of SplitPoint goes from 71944 to 136 bytes,
and consequently size of Thread goes from 575568 to 1104 bytes.
Finally the size of ThreadsManager that contains all the thread
info goes from 9209248 to just 17824 bytes !!
No functional change also in faked split.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This allow us to restore the old depth 12 benchmark
and fixes one and for all the depth mess.
Test confirms no regression:
After 5658 games 892 - 924 - 3842 ELO -1 (+- 5.2)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Note that this introduces an asymmetry in which best move
is searched deeper then others also in MultiPV, but this is
not an error per se.
No functional change when MultiPV = 1
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch removes a condition that allows a PV entry to remain
in TT across games for an unlimited time.
Although this produces a nice ELO boost in the long term it
is an artifact that affects tests results bewteen version
with and without this feature.
So remove now and readd before to release because it actually
seems a strong feature.
As example a verification tournament against SF 2.0.1 starting around
+10 ELO after 4K games sligltly climbed to +21 ELO after 14K games !!!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Skip writing fail high/low sequences. Note that we don't need
fail high/low markers anymore in pretty_pv().
No functional change but some do/undo move sequences.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
First search should be done at iteration = 1, not 2. So offset
the variable by one.
As a nice side effect now search correctly stops at PLY_MAX
included, not after searching (PLY_MAX - 1) as before.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Interestingly this patch will make people complain search depth
is reduced against 2.0.1 ;-) but actually it is only an artifact.
Spotted by Joona.
No functional change apart from a different do / undo move
sequence due to teh fact that we don't call pv_info_to_uci()
anymore before entering id loop.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
No functional change apart form move reordering because
pv_info_to_uci() performs a do / undo_move sequence.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Biggest advantage is be able to analize positions
without "loss of memory" when goind back/forth in
a position.
Patch has proven to fix analysys problems and is even
worths some elo points.
After 5811 games Mod- Orig:
1037 - 902 - 3872 +8 ELO (+- 3.6) LOS 97%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Warning C4146: unary minus operator applied to
unsigned type, result still unsigned.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We dont' call MovePicker from print() anymore, so that
reentrancy check in now not needed.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This let us get rid of number_of_evasions()
After 5487 games
Mod- Orig: 851 - 852 - 3784 +0 ELO (+- 3.7)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move qsearch scoring functionality out of RootMoveList
initialization. Will be needed by future patches.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is used for secondary scoring so it does not
changes the fact that Rml[0].pv[0] is always tried
as first anyhow.
It happens this is even a no functional change patch
becuase we reinsert PV in TT after a search so that
TT move is actually Rml[0].pv[0].
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
So to better spot where the differences really
count. Also add some more additional cleanup.
Harmless functional change and no regression.
After 5780 games
Mod- Orig: 931 - 955 - 3894 ELO -1 (+- 3.6)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In case of a Root node we can leave with bestValue set
to -VALUE_INFINITE if search is stopped by the GUI and
stopReques flag is raised.
This patch fixes the issue.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A bit of template magic to restore a proper and readable moves
'while' loop that now is again 'similar' to the one that used
to be in search().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Teach search() to behave as a root node if requested.
Just added code, but still no functional change.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And sync root_search() with search()
After 9384 games Mod - Orig:
1532 - 1433 - 6419 ELO +3 (+- 2.8)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Returns an int64_t while we want a simple int.
This occurs only when compiling with MSVC on a 64 bit platform.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Respin this old idea. Earlier we tried only
with < 1000 games and result was inconclusive.
After 5845 games
Mod vs Orig: 935 - 936 - 3974 ELO (+-3.6)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If size_t is defined as a 32 bit quanitity then we have an
overflow in the left term of the while condition if mbSize
is bigger then 2048.
For instance if mbSize is 2049 then when newSize will reach
0x80000000 (2048MB) comparison is still true, 'while' loops
again and we have an overflow in the expression (2*newSize)
so that result is 0 and at that point 'while' keeps looping
forever hanging the application.
This patch fixes the bug and also makes operator new do not
throw an exception upon failure but return a NULL pointer
instead.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In input_available() we use function select(), so
we have to set as unbuffered also C library I/O
functions otherwise we can miss some input.
For instance in case GUI sends "go infinite\nstop\n" we
parse the "go infinite" but then input_available() under Linux
is unable to detect that we still have "stop" to be processed.
This is because "select" uses file descriptors instead of file
pointers. So it cannot know about the buffer associated to a file
pointer.
This patch, by BB+, should fix the problem.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also let do_setup_move() don't reuse same StateInfo so that
we can remove the check about different StateInfo objects
before memcpy() in do_move.
Functional change due to harmless additionals
do_move() / undo_move() steps.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Actually it is san.cpp renamed. Because now has the move
conversions functions and doesn't have any more the bulky
move_from_san(), it is better to call it move.cpp
Remove san.h while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a reverse logic: among the list of generated legal moves
transformed in UCI coordinate notation find the one that
matches the given string.
It is a bit slower, but here is not performance critical and
is much more simplified then before.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This partially reverts 1e7aaed8bc keeping the conversion
functions from/to move to uci string in the same file.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I got report from Werner that Shredder Gui has problems with
UCI values which maximum value is greater than 30000.
Of course it's stupid to change engine to fix a GUI's bug,
but on the other hand 30000 ms as maximum value is clearly enough,
so why not to be merciful
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Added checking of (stdin->_cnt > 0) from Greko.
This seems to greatly improve responsivness when running
under console. Now while running a 'stockfish bench', any key
press immediately is detected by SF while before there was a
delay of some fraction of a second.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is an old Glaurung bug that prevented a Polyglot
book move to be read correctly in case of underpromotion.
This patch fixes the bug restoring support for both
queen and underpromotions.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
MSVC (and possibly other compilers) does not inline
as requested, so force it to do so.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move the castling condition test out of the
function. This avoids a function call most of
the times.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Functional change due only to moves reorder. Anyhow after
5242 games at 15"+0.1 TC verified we have no regression.
Mod vs Orig 994 - 958 - 3290 +2 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Shrink of 1 bit so to fit a move in an uint_16 and
possibly a MoveStack in an uint_32.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A bit faster on 32 bits machines, more similar to
TranspositionTable::first_entry() and same result.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There was a strange "int16" type and "int64_t"
was defined twice.
Spotted by Joona.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We never reach a position where rule50 > 100.
When rule50 == 100, it's either draw or mate and
there is no way search could go deeper.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We must be able to filter out also moves where move_is_ok()
is false.
And actually we are. Tested on all the default position injecting
a number from -1000000 to 1000000 casted to a Move.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
As is defined now is always true, tested with:
for (long i=-1000000; i < 1000000; i++)
if (!move_is_ok(Move(i)))
exit(0);
Reason is that move_from() and move_to() already truncate the
input value to something in the range [0, 63] that is always
a possible square.
So change definition to something useful.
The same applies also to square_is_ok()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now first move has moveCount == 1 also in root_search()
Also added small readibility touches.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Should be already inlined by the compiler when
optimizing but better safe than sorry ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Keep the isChess960 flag inside Position so that is
copied with the Position, but esplicitly highlight the
fact that a FEN string has not enough information to detect
Chess960 in general case. To do this add a boolean argument
isChess960 to from_fen() function so to self document this
shortcoming of FEN notation.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems HP's ANSI C++ doesn't understand very well
standard function-style cast.
Reported by Richard Lloyd.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And set them as default.
Introduce compile switch OLD_LOCKS to allow to fallback on
compatible locks supported by Windows XP and older versions.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Introduced by me in before 1.9 and found by Tord that says:
The 'isChess960' slot in the 'Position' class is currently
set depending on the initial files of the rooks, and not on the value
of the UCI_Chess960 parameter. This is incorrect, as there are lots of
Chess960 positions where the rooks start on the usual files. As a
consequence (unless I am missing something), Stockfish will occasionally
output castling moves as e1g1/e1c1 rather than the correct e1h1/e1a1 format
in Chess960 games. It is possible that some or even most GUIs are robust
enough to accept both notations, but I wouldn't bet on it. And in any case,
Stockfish's behavior clearly violates the protocol.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This time I have removed the function alltogether !
Sorry to work above a patch of UncombedCoconut (Justin Blanchard)
but I couldn't resist ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When we log best and ponder move to a file before to
return from think we change the position. If position is
then not resended by GUI, as for manual user input we got
an error:
justinb@malibu:~$ stockfish
Stockfish 2.0 JA 64bit by Tord Romstad, Marco Costalba, Joona Kiiski
setoption name Use Search Log value true
go depth 1
info depth 1
info depth 1 seldepth 1 multipv 1 score cp 72 time 59 nodes 20 nps 338 pv g1f3
info depth 2
info depth 2 seldepth 2 multipv 1 score cp 12 time 59 nodes 44 nps 745 pv g1f3 g8f6
info nodes 84 nps 1423 time 59
bestmove g1f3 ponder g8f6
go depth 1
info depth 1 score mate 0
info nodes 87 nps 0 time 0
bestmove (none) ponder (none)
Bug spotted and fixed by UncombedCoconut.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And set "Use Sleeping Threads" to true because it keeps
much more responsive and cool my QUAD during tests :-)
It will be reverted back before to release that's the
reason to bundle it here.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Always same siganture: 7224363
Hopefully some more bug fixed and restored
compatibility with WIndows XP.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They are not compatible with Windows XP
Revert to old CRITICAL_SECTION locks and events.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Second parameter of insertion_sort() is a pointer to the
element _after_ the last of the list, e.g. end() when sorting
all items.
If we want to sort say the first 2 moves we should write:
sort_multipv(2);
So, becuase in root moves loop move counter 'i' starts
from 0, we need to pass:
sort_multipv(i+1);
To sort up to move 'i' included.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It doesn't seem to have any meaning.
Also add a FIXME on the MaxNodes condition that now is broken
in SMP case due to known issue with pos.nodes_searched()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We were not quitting the engine after a "quit" command
while still in the book and pondering.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If flag StopOnPonderhit is set it means that we UseTimeManagement
and also we are at Iteration >= 3.
So we can safely simplify the formula.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is called only from one place, so move code there.
Add a bit of renaming and documentation while at there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And set "Use Sleeping Threads" to true because it keeps
much more responsive and cool my QUAD during tests :-)
It will be reverted back before to release that's the
reason to bundle it here.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It was introduced by patch 66d16592 of 22/3/2009 merging
from Glarurung iPhone.
Tord says:
That change is only found in the Glaurung iPhone app, and not
in the latest Glaurung UCI source code. I don't remember why
this was added (and the iPhone app, unlike the UCI engine,
was never version controlled), but it was almost certainly
because it was somehow needed in the communication between
the engine and the iPhone GUI, and that it was never meant to be
included in the UCI engine. My guess is that it has something to
do with castling moves being entered as e1-g1 in the GUI, but
represented as e1-h1 in the chess engine.
Removing it in Stockfish should be completely safe, and won't harm
the iPhone version. Initially the iPhone GUI called functions in the
chess engine for checking for legality of moves, writing the move
list in SAN format, and various other tasks, but this is no longer
the case in the current version.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the "selective search depth in plies" and we set
equal to PV line length.
Tested that works under FritzGUI.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems a more appropiate place (IMHO) and helps to clarify
that idle_loop() should return a move, not a score.
Fix also handling of stalemate positions (we were not
sending any score) and we don't need to wait on "ponderhit",
this is done when returning in think().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We have a small functionality change in case we have a
fail-high so that both rml[].pv and pv[] are updated, but if,
after researching, we have a fail-low then rml score is updated
again but pv[] remains the same and coming back from search we
used a PV line that has failed-low (after having failed-high).
With this patch we always use the 'correct' PV line, i.e. the
line with highest score at the end of the whole search.
Retire also redundant RootMove's 'move' member and directly
use pv[0] instead.
Define symbol '<' to mean 'minor of', as it should be. Its meaning
was reversed to be used with std::sort() that sorts in ascending order
while we want a descending order.
But now that we use our own sorting code we don't need this
trick anymore.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When a reference breaks things !
Here we take a reference (that is a pointer) to an
entry in a vector that changes below us --> BOOM !
References are essential but should be considered with
care in C++ because could lead to nasty surprises.
Restored functionality.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of a default member by member copy use set_pv()
to copy the useful part of pv[] array and skip the remaining.
This greatly speeds up sorting of root move list !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is redundant being a move list ;-)
Also better document the two scores used by root list.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Function ray_bb() was used just in one endgame where can
be used squares_in_front_of() instead.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Remark 1418: external function definition with no prior declaration
and
Remark 1419: external declaration in primary source file
Can be safely ignored because are pure idiocy.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Namely we use only two types of depth in TT:
DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And rename move_from/to_string() in a more specific
move_from/to_uci() that is a simple coordinate notation.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use one sleep lock per thread insted of a single one shared.
Also renamed WaitLock in SleepLock.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
By mean of an an UCI option it is possible let the available
threads to sleep, this should help with Hyper Threading although
is not the best solution when number of threads equals number
of available cores.
Option is disabled by default.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
No speed regression and no functional change.
After 7826 games Mod- Orig:
1188 - 1230 - 5408 ELO -1 (+- 3.1)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Non-PV LMR is left unchanged.
After 8819 games
Mod- Orig: 1442 - 1343 - 6034 ELO +3 (+- 2.9) LOS 86%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Bug introduced in 9dcc2aad98
We can be asked to open a non-exsistent file,
in this case we should gracefully handle the
case and silently return instead of exiting.
Bug discovered and bisected down by Joona.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This time we try very hard to avoid false positives.
The obvious downside is that we also miss many true
winning positions.
After 10544 games on RC
Mod- Orig: 1744 - 1646 - 7154 ELO +3 (+- 2.7) LOS 83%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After 2036 games Mod- Orig:
381 - 278 - 1377 ELO +17 (+- 6.2) LOS 99%
One of the biggest increases ever !
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When MultiPV > 1, always take bestmove from the RootMoveList
(and don't bother with a ponder move). Without that the bestmove
is most probably incorrect.
Patch from Peter Petrov.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When we store this value in TT we cut this to 9 bits,
so we need a smaller variable otherwise comparisons
like:
replace->generation() == generation
Are always false if generation is bigger then the maximum
TT storable value.
This fixes a very nasty and difficult to spot bug (2 weeks for
regression hunting).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is a redundant boiler plate, just call initialization and
resource release directly from main()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Correctly handle uci option names in a case insensitive way.
Alos fix some indentation while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Was introduced by 403db5a6e9
on 1/12/2009 to correctly handle "loose on time"
LSN filtering functionality, but is now unused.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This L1/L2 optimization has an incredible +4.7% speedup
in perft test where this function is the most time consumer.
Verified a speed up also in normal bench, although smaller.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
UCI protocol uses "true" and "false" for check and button types,
so store that values instead of "1" and "0", this simplifies a
bit the code.
Also a bit strictier option's type checking in debug mode.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch greatly cleanups generation of pawn moves but
we change the order in which moves are generated so there is
a change in functionality, but not in perft.
The only real functionality change is that now when type == CHECK
we generate knight underpromotion captures only if give check and
not always as before.
Perft is 2% faster and fully verified.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now stockfish bench' defaults to
stockfish bench 128 1 12 default depth
that is the most used line (at least by me)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Let to sleep even split point master, it will be waken
up by its slaves when they return from the search.
This time let it be enabled by an UCI option, so
people is free to test it on their Hyper Thread box.
Option is disabled by default.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Search at fixed depth with one thread must be
reproducible so remove randomess from time().
Also better license description.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I finally got SF to compile under MinGW (after adding pthread libraries)
and here are the fixed warnings.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And also store the node counter in Position and not in Thread.
This will allow to properly count nodes also in sub trees with
SMP active.
This requires a surprisingly high number of changes
in a lot of places to make it work properly.
No functional change but node count changed for obvious reasons.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This was subtle and google was my friend.
The leak was in _dl_allocate_tls called by pthread_create() and
is due to the fact that threads are created in joinable state so that
once terminated are not freed. To make the thread to release
its resources upon termination we should set them in detached state.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix warning: "Source and destination overlap in memcpy"
This happens when we call multiple time do_move() with the
same state, for instance when we don't need to undo the move.
This is what valgrind docs say:
You don't want the two blocks to overlap because one of them could
get partially overwritten by the copying.
You might think that Memcheck is being overly pedantic reporting this
in the case where 'dst' is less than 'src'. For example, the obvious way
to implement memcpy() is by copying from the first byte to the last.
However, the optimisation guides of some architectures recommend copying
from the last byte down to the first. Also, some implementations of
memcpy() zero 'dst' before copying, because zeroing the destination's
cache line(s) can improve performance.
In addition, for many of these functions, the POSIX standards have wording
along the lines "If copying takes place between objects that overlap,
the behavior is undefined." Hence overlapping copies violate the standard.
The moral of the story is: if you want to write truly portable code, don't
make any assumptions about the language implementation.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems we have a speed regression under Linux, anyhow
commit and revert to leave some documentation in case we
want to try again in the future.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Let to sleep even split point master, it will be waken up
by its slaves when they return from the search.
With this patch we get maximum HT speedup
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It has more sense to treat the two evaluation metrics
in the same way.
As a side effect now we use the correct eval margin when
pruning in a SplitPoint node.
No functional change in single thread.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix the movcount updating bug and let search() to completely
subsititute sp_search().
No functional change even with fakes split.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There is a bug in the conversion that is triggered when testing
with faked split and that I missed somehow :-(
To allow proper testing on cluster restore old sp_search()
until I don't fiugre up what's happened.
Restored to be functional equivalent to old behaviour both in
single thread and in faked split.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When entering and exiting from think() we don't need any special
wake up / sleeping code because we want available threads to keep
sleeping.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This simple patch has devastating consequences ;-)
Now an available thread goes to sleep and is waked up after
being allocated.
This patch allows Stockfish to dramatically increase performances
on HyperThreading systems.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They are fast and also have the same semantic of Linux ones.
This allow to simplify the code and especially to use
SleepConditionVariableSRW() to wait on a condition releaseing the lock,
this has the same semantic as pthread_cond_wait().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is a prerequisite for future work and anyhow removes
a state flag, so it is good anyhow.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is redundant and complicates the already complicated
SMP code for no reason.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We already do this for locks. Also rename SitIdleEvent
in WaitCond to be uniform with Lunix naming.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the native way done in Windows and we will use it
for future work, so change Linux to do the same.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Plus some other icc warnings popped up with new and strictier
compile options.
No functional and speed change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It has more sense to treat the two evaluation metrics
in the same way.
As a side effect now we use the correct eval margin when
pruning in a SplitPoint node.
No functional change in single thread.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Rewrite sp_search() to have same signature of search()
This is the first prerequistite step toward unification.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Actually it is an error to update back moveCount value after split()
because it is used in update_history() to access movesSearched[]
array. But becasue this vector is not updated in the split point
we end up with an access of stale data.
Bug has been hidden til now because we 'forgot' to update
moveCount before returning from split().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Mostly suggested by Justin (UncombedCoconut), the 0ULL -> 0 conversion
is mine.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Language guarantees that c'tor is called, but without any c'tor
it happens to work by accident because OS zeroes out the freshly
allocated pages. The problem is that if I deallocate and allocate
again, the second time pages are no more newly come by the OS and
so could contain stale info.
A practical case could be if we change TT size or numbers of
threads on the fly while already running.
Bug spotted by Justin Blanchard.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix release to workaround chess960 on some GUIs
Signature is:
stockfish bench 128 1 12 default depth
Node counts: 10914593
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Get rid of macros and use templates instead,
this is safer and allows us fix the warning:
ISO C++ forbids braced-groups within expressions
That broke compilation with -pedantic flag under
gcc and POPCNT enabled.
No functional and no performance change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch from Joona greatly reduces move count pruning,
below is the old and new move count limits starting from
ONE_PLY with half-play increment:
Old: 4,5,5,5, 7, 7,11,11,11,19,19,19,35,35
New: 4,5,7,9,12,15,19,23,28,33,39,45,52,59
Surprisingly results are even a bit better at a quite
fast time control.
After 5260 games at 30"+0.1
Mod - Orig: 864 - 806 - 3590 ELO +3 (+- 3.8)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems totally unuseful because killers are not
used to order the moves in qsearch. Although there
is some functionality change, probably just a small
side effect.
After 5656 games on rc
Mod vs Orig: 1007 - 980 - 3669 ELO +1 (+- 3.7)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
So there is no need to explicitly check for king moves
when detecting prunable evasions.
Perhaps teoretically a very bit slower (I didn't test),
but it is more clear now what evasions we consider prunable.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Greatly cleanup SEE code and now it is also a bit
faster on gcc, about +0.6%.
Thanks to Mike Whiteley new SEE code that gave me
fresh ideas on how to cleanup this old stuff.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A code semplification that could even be a slight increase,
anyhow is a reducing pruning patch, so it is good even
at equal strenght.
After 6342 games
Mod - Orig: 1040 - 974 - 4328 ELO +3 (+- 3.5)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Were removed when merged from Glaurung 2.2, but without
any test.
Note that weight has been increased from original 2 to 4 and
has been also fixed a bug where in the original version were
considered also diagonal sqaures for the rook, that are
contact squares but not checks.
After 4449 games at 30"+0.1
Mod - Orig: 717 - 649 - 3083 ELO +5 (+- 4.1)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use the tail of moves[] array to store bad captures.
No functional change but some move reorder. Verified with old perft.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And also other check bonuses.
After 4272 games on russian cluster at 30"+0.1
Mod - Orig: 711 - 612 - 2949 ELO +8 (+- 4.2)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
More then 100 lines of almost useless evaluations. Prefer
code semplification to a very small and dubious advantage.
After 7457 games on russian cluster:
Mod - Orig: 1285 - 1334 - 4838 ELO -2 (+- 3.2)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And rename in nodes now that we have only one.
After the beta-cut off counters removing we can
get rid also of this one.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
For now keep FutilityMarginsMatrix[] unchanged, in
future we are going to reduce to compensate for extra
margin.
At this moment it is enough we don't have regressions.
After 9694 games on russian cluster
Mod - Orig 1608 - 1578 - 6508 ELO +1 (+- 2.8)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of one comparison in while() condition use two,
the first to check if the piece is exsistant and the second
to loop across pieces of that type.
This should help branch prediction in cases we have only
one piece of the same type, for instance for queens, the
first branch is always true and the second is almost always
false.
Increased speed of 0.3-0.5 % on Gcc pgo compiles.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently are used by evaluation itself and the
whole EvalInfo will be removed from global visibility
by next patch, so no reason to use them.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It will be more clear when we will go to add stuff
apart from king danger itself.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
First accumulate the bonus for each pawn, then call the
not very fast apply_weight().
Should be no functional change apart from rounding issues.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Set manually to zero the few fields that are
optionally populated and that's enough.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid one address lookup in a very critical time path.
Unified also outpost bonus tables for knights and bishops.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Another 100 lines of dubious and ad-hoc code.
After 7644 games on russian cluster:
Mod - Orig 1285 - 1249 - 5110 ELO +1 (+- 3.2)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
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>
Plus a bunch of other minor optimizations.
With this power pack we have an increase
of a whopping 1.4% :-)
...and it took 3 good hours of profiling + hacking to get it out !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
One hundred lines of code should be compensated by an
important ELO increase, otherwise are candidate for removal...
...and is not the case. We are well within error margin, so
remove the code even if we lose a couple of elo points, but
semplification is huge.
After 6494 games on russian cluster
Orig vs Mod 1145 - 1107 - 4242 (-2 ELO)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After testing on our russian cluster: +3 elo after 4200 games
So keep it becuase it allows a good semplification.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Where they belong.
Note that array PieceValueMidgame[] and PieceValueEndgame[]
are now declared extern in the header and moved in piece.cpp
so to avoid allocate the array each time the header is
included !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
To avoid nasty bugs due to silently overriding of
common operator we enable the templates on a type
by type base using partial template specialization.
No functional change, zero overhead at runtime.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Note that in value we leave two specialized functions
to allow adding an integer, we don't want to add this
as a template becasue we want to control implicit
conversions to integer of an enum.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is tricky because there are some special
binary fnctions with SquareDelta that we should
leave as they are.
Also note that we needed to add Unary minus template
to fix a comile error in SERIALIZE_MOVES_D macro that was
triggered because now we don't allow conversion to int.
No fuctional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Doing the conversion the compiler is now able to
spot two possible ambiguity calls that now we can
easily fix.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When depth < DEPTH_ZERO we store with the same depth all
the positions, use -OnePly instead of -1 for consistency
with depth arithmetic.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There is no reason to use a variable for this.
Also remove unused DEPTH_ZERO and DEPTH_MAX.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Regression test found the patches to be harmless,
so revert to keep code simpler.
Test1 at 20+0.1: (2500 - 3000) +0 ELO
Test2 at 1+0: (~1000) +2 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There is a functional change because we now skip
more moves and because do_move() / undo_move() is
well known to be not reversible we end up with a
change in node count, although there is actually
no change but a bit speed up.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
To be uniform across the sources. As a nice side effect
I quickly spotted a couple of needed renames:
captured_piece() -> captured_piece_type()
st->capture -> st->capturedType
Proposed by Ralph and done with QtCreator
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In root_search() we can compute depth at the beginning
once and for all.
Spotted by Ralph Stoesser.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We don't need to generate captures and non
captures in a separate step. This gives another
7% push to perft speed.
yes, I know, it is totally useless :-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We can now set member data as private because is no more
directly accessed.
Should be more clear now.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move OptimumSearchTime, MaximumSearchTime and
ExtraSearchTime in TimeManager.
Note that we remove an useless initialization to 0 because
these variables are used only with time management.
Also introduce and use TimeManager::available_time()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Firt step in unifying all time management under
a single umbrella. Just introduced the class without
even member data.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After razoring, IID, null verification and singular
extension searches we have could have a dirty ss->bestMove,
restore to MOVE_NONE before to enter moves loop.
This should avoid to store in TT a stale move when
we fail low.
Tested together with previous patch that is the
one that gives ELO.
After 1152 games at 1+0 on my QUAD
Mod vs Orig +233 =716 -203 (+9 ELO)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If singular extension search was succesful in the past then
skip another the SE search and extend of one ply.
Another way to mitigate the cost of SE at the price of
some more spurious extension, but on 90% of cases info
is correct.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Renamed in OptimumSearchTime and MaximumSearchTime,
should be more clear now.
Suggested by Joona.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I created three different systems, tested them all separately and
attached one did best:
1/40: Orig - Mod: 841 - 850 (+2 elo)
1+1 : Orig - Mod: 474 - 498 (+9 elo)
1+0 : Orig - Mod: 455 - 495 (+15 elo)
Because such testing system is not statistically reliable, I made a
confirmation test:
1/40: Orig - Mod: 502 - 543 (+14 elo)
1+1: Orig - Mod: 447 - 489 (+16 elo)
1+0: Orig - Mod: 641 - 656 (+4 elo)
All tests show positive score :-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of ss->currentMove. It is more consistent and
clear to understand.
Remark by Ralph Stoesser.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
To compensate for the extra work skip singular
searches deemed to fail because excluded node
failed high already in the past.
After 1200 games at 1+0
Mod vs Orig +387 =1274 -339 (+8 ELO)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The one in evaluate_passed_pawns() is just a micro
optimization, the other in evaluate_unstoppable_pawns()
is indeed a fix, although almost unmeasurable in real
games.
Bugs report and fixes by Marek Kwiatkowski
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Broken by recent patch. Also better document what's
happening there.
Verified to restore original behaviour.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Square and piece colors are two different things,
so use different types to avoid misunderstandings.
Suggested by Tord.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Less invasive then previous patches, but still a good
enhancement.
Also some indulge on STL algorithms :-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Complete rewrite the function and extend compatibility
also to X-FEN notation for Chess960.
We are now able to read standard FEN, Shredder-FEN and X-FEN.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After 'Randomness' is retired, this is no longer necessary.
NOTE: Possibly some extra care is needed when tuning branch is synced
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Using multiple threads and good opening book is
much better and more reliable source of randomness than
spoiling psqt-tables
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Let be explicit about what this functions do, and
we save some code lines too.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After we set ss->threatMove we could go under a IID step that
resets SearchStack ss and so also ss->threatMove.
When later we use that field in futility pruning we have this
set to MOVE_NONE !
The fix is to use a local variable and add threatMove to SplitPoint
to pass this move to slaves.
Spotted by Ralph Stoesser, fix suggested by Richard Vida.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Improvement is easily in error bar and there is
some added complexity making future changes more
difficult.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because not all backward pawns are the same ;-) if the
blocking enemy pawn is near then our pawn is more backward
than another whose enemy pawn is far away so that can advance
for some sqaures.
After 2925 games at 30"+0 on my QUAD
Mod vs Orig +602 =1745 -578 +3 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Update outdated and even misleading documentation.
Also check #include-directives
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
These functions have little to do with TranspositionTable
class and more with the search and in particular with the PV
handling. So move them where they belong.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
So to maximize the possibility to avoid to recalculate it
in the future. A small speed-up of 0.8%
Idea by Ralph Stoesser.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The seocond check is no more needed now and
anyhow is wrong to overwrite a TT entry if
present.
Spotted by Ralph Stoesser.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
KILLER_MAX in search.h is quite pointless, because
we already hardcode this to 2 in MovePicker anyway.
By hard-coding this to 2 we can keep code simpler.
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is more clear and also more correct because we
consider enemy pawns only in fornt of us and not just
on our file.
Very small functional change, almost not measurable, but
keep the patch for documenting purposes.
Spotted by Marek Kwiatkowski.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Almost no change so commit because is a pruning
reduction patch.
After 1088 games at 1'+0 with QUAD
Mod vs Orig +178 =727 -183 (-2 ELO)
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>
Considering only VALUE_TYPE_EXACT nodes is too
restrictive and has a number of side-effects, most
notably the truncation of PV line after a fail high
at root.
Note that in this way we are no more guaranteed that
PV line is built up with PV nodes only, because
it could happen that a side search overwrites with a
cut-off move a PV node and this cut-off move ends up
in PV.
Change should be almost not measurable, perhaps with
ponder on we could have some beneficial effect.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently starting from depth 12*OnePly on we have a verification
search deeper then the null search.
Note that, although reduction is R we start from one ply less then
null search, so actually we reach a depth that is OnePly shallower
then null search.
After 1130 games at 1'+0 on QUAD
Mod vs Orig +202 =756 -172 +9 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After the previous patch, it's impossible to build
anything else than x86 32-bit binary!
So revert.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Tested with Orig set at f5ef5632f so to evaluate
direct gain against 1.8
After 3239 games at 10"+0.1
Mod vs Orig +701 =1906 -632 +7 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Unfortunatly the source of this issue is not in the
different handling of log(0) illegal value.
No functional change on MSVC.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It happens that when d == 0 we calculate:
log(double(0 * 0) / 2)
Unfortunately, log(0) is "illegal" and can generate either a
floating point exception or return a nonsense "huge" value
depending on the platform.
This fixs in the proper way the GCC/ICC rounding difference,
bug was from our side, not in the intel compiler.
Also fixed some few other warnings.
Bug spotted by Richard Lloyd.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also renamed history access value in something more
in line with the meaning.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems there is absolutely no difference in using gains.
After 7025 games at 5"+0
Mod vs Orig +1903 =3236 -1886 (+1 ELO)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This time with a new algorithm by Joona.
It works basically like this:
repeat
{
1) pick 8000 random positions from qsearch
2) "go depth 8" to get the true evaluation.
3) "eval" to get the stand pat score
4) Adjusting parameters one by one to minimize deltasum between
true evaluation and stand pat scores.
}
* Good news: method seems to converge
* Bad news: Point where it converges is not optimum.
So it's more or less trial and error... sometimes works, sometimes
doesn't. It can give you the right direction, but if you let it run
too long, it fails. Far from scientific ;)
After 14800 games with 5s/game
Orig - Mod: 3318 - 3570 - 7626 (+6 elo)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When first condition is met then second one is
always true.
Spotted by Ralph Stoesser.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This should allow to skip overwritten nodes because
only in PV we store in TT with VALUE_TYPE_EXACT flag.
Test result for the whole series is:
After 3627 games at 5"
Mod vs Orig +1037 =1605 -985 +5 ELO
After 1311 games at 1'+0"
Mod vs Orig +234 =850 -227 +2 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Extract PV info from TT instead of using
a set of arrays. This is almost equivalent
except for cases when TT is full and the PV entry
is overwritten, but this is very rare.
(Almost) No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Due to rounding errors in apply_weight() where we divide
by 0x100 it is not possible to keep some functionality.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A pawn is unstoppable also if enemy king can reach it
but path to queening is protected.
Original idea by Ralph Stoesser fixed by me.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Many killers moves, around 40%, are not legal, so
skip earlier in this case.
Some Movepicker c'tor cleanup while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This code is platform specific and has nothing to
do with TT class, so move to misc.cpp
This patch is a prerequisite to use extend prefetch use
also to other hash tables apart from Transposition Table.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Search ply and game ply are rwo different things !
Revert bogus commit.
No functional change on bench, but it changes in real games
when engine sends all the moves up to current one.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If we are there it means we already had that info stored in TT,
so we don't need to overwrite with the same content !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In statement:
*tte = TTEntry(posKey32, v, t, d, m, generation, statV, kingD);
We first create a TTEntry, then we copy the temporary entry to
its final destination in *tte then we discard the TTEntry.
Instead of this assign the fields directly to the destination TTEntry.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is more clear and should be a bit faster too.
Reverted also previous optimization patch because
seems do not increase actual speed.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Almost no change, but it is in sync with what we do in search
and in any case the ELO difference is very small (because the
events when the intermediate research triggers are very rare),
too small to be measured, we just verify we don't have any
unexpected regressions.
After 802 games at 1+0 full QUAD
Mod vs Orig +114 =581 -107 +3 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If we have pruned one capture due to its final value
we can prune also following ones because captures are
MVV ordered.
Also avoid a compare when not in PV because in that
case is always false.
No functional change.
Get it from the position instead.
A good semplification of function calling and a speedup too.
No functional change also with faked split.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the best place because when we split we do a
copy of the position and also threadID, once set in a
given position, never changes anymore.
Forbid use of Position's default and copy c'tor to avoid
nasty bugs in case a position is created without explicitly
setting the threadID.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Do it once at the beginning becuase they are always reset
after use in the calling place where are set.
No functional change also with faked split.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also renamed allowNullmove in skipNullMove to reverse
the logic so that the field is initialized to 0 (false)
instead of 1 (true).
No functional change also with faked split.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use log() instead because we are not in speed
critical paths.
Also a bit of renaming and code shuffle while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Has been remained the same from ages also with the FIXME.
Retire for now and rearrange the conditions order for
maximum performance.
Also a small touch at null zugzwang verification.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is more up to the point. Also small speedup
due to checking for threat move before calling
the function. This saves more then 90% of function calls.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In 44% of cases we call search() just to call
qsearch() one moment later, avoid this double dispatch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And avoid a redundant one passed as argument in
search calls.
Also renamed gamePly in ply to better clarify this
is used as search ply and is set to zero at the
beginning of the search.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In RootMoveList c'tor we call qsearch() with
ply == 1 but SearchStack at 0.
We never noticed before because in qsearch we don't access
previous's ply SearchStack, otherwise we would have got
a nice crash ;-)
This bug is a fall down of previous patch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a pointer to current SearchStack to avoid ss[ply]
address calculation.
Gives 1% speedup on Intel compiler
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And remove from main do_move() flow. Just a small speedup
because we avoid two branches in the common case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In case tte->depth() is far lower the current depth
and we are in a PV node.
Almost 45% of researches give a different ttMove !
After 999 games at 1+0
Mod vs Orig +174 =694 -131 +15 ELO !!!!!!!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Do not search immediately at full depth, but try a second
chance at lower depth. This is a feature that should scale
well because become important at high depths where we have
big reductions and also big savings in avoiding a costly
full depth search.
After 942 games at 1+0
Mod vs Orig +158 =645 -139 +7 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The index at 0 was reserved for no-pieces
information. But we don't need that.
This is a prerequisite for next patch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They are both 64 bits unsigned integer, but it
is correct to use the proper type.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After 999 games at 1+0
Mod vs Orig +148 =712 -139 +3 ELO
The added complexity doesn't seems to pay off and could
even scale worst with longer TC. So revert.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The tested square comes from a bitboard anded with
pos.pieces_of_color(Us), so assert is useless.
Another nitpick report by Marek Kwiatkowski ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
One of the most nitpicking patches I have ever seen.
Of course almost no functional change, but added just
becasue we are very pedantic ;-)
Spotted by Marek Kwiatkowski
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It was erroneusly reversed. Bug from Glaurung times.
Probably a full re-tuning is needed anyhow.
Spotted and fixed by Ralph Stoesser.
After 999 games almost no change, but modified anyway
for documentation reasons.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Increase threats score according to the number of
threats and to the side to move.
Constants have been balanced after ~34k iterations.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It does not seem to increase anything even with a QUAD,
so revert.
After 1000 games with a QUAD
Mod - Orig: 500 - 497 (+1 elo)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When compiling with MSVC we don't use the Makefile
so tweak a bit the Makefile to allow to let prefetch
in by default so that it works under Windows.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
No gain in the worst case of 2 threads, but also no
loss and good potential for QUAD or OCTAL machines.
After 922 games at 1+0 with 2 threads
Mod vs Orig +143 =533 -143 +0 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We already tested few lines before with:
assert(pos.pawn_is_passed(Us, s));
Spotted by Marek Kwiatkowski.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Does not help and it slows downs a bit because it
is not cheap to get the possible discovered checks
out of a position.
After 997 games at 1+0
Mod vs orig +153 =692 -152 +0 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There is no reason for that since tr cannot become negative.
Spotted by Ralph Stoesser.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Final values for threath tuning (after ~30k iterations)
Verified to be equivalent with tuning branch.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is a more standard naming (see chessprogramming wiki)
and is more stick to what table is and not what is used for.
Code in pawns.cpp is a bit more readable now, at least for me ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid a double bitcount in test for candidate passed
pawn when we don't have any supporting pawn.
Also use outpost_mask() instead of build it up on
the fly.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Pass the color for which the square is to be
considered weak, not the opposite.
It is more natural and intuitive in this way.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Function split() doesn't need to return a value, also
remove useless 'master' field.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is redundant with splitPoint->slaves[].
Also move slaves[MAX_THREADS] among the shared data in
SplitPoint definition as it should have been already.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Small twekas to make the two searches as similar as
possible.
Also removed an useless setting of mateKiller in sp_search()
No functional change (tested with FakeSplit)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We don't need to comment/uncomment code, just
set FakeSplit bool to true to enable faked split.
Also reintroduced some asserts and cleaned up a bit.
Tested that with FakeSplit = true we have reproducible
finger printing even in SMP.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also introduce a new rule:
In sp_search() always must hold: sp->alpha < sp->beta
Should fix some rear but very nasty races
To keep everything in sync, search() is also modified to
obey this rule. Because this affects only PV-nodes, should
have zero meaning to speed.
No functional change in fake mode
Regression test after 854 games
Mod vs Orig 433 - 421, no crashes.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It was broken on Windows 64bit with MSVC and possibly
on other platforms, so revert to old proven one.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Remove a lot of complex, obscure and useless code.
After 999 games at 1+0
Mod vs Orig +162 =673 -164 -1 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We don't need to evaluate the position if it
is already cached in TT. We already do this
in non-PV case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is what actually is.
A standard naming convention suggests to name a variable
with someting resembling _what_ the variable is and not
_how_ the variable is used. This normally results
in easier to read code.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A bigger "safety" value is actually a bigger
threat for the king, so it is a bigger "danger"
With this renaming "Cowardice" and "Aggressiveness"
UCI parameters become easier to understand.
It is also easier to understand why the once "safety"
value (that is a "danger") is subtracted from evaluation
instead of being added.
No functional change.
Use a Weights[] array instead of named variables to
store evaluation weights.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
More aggressive LMR reductions.
Tested at different time controls:
- Tested with 1CPU 1+0, after 3000 games, result was +12 ELO
- Tested this with 4CPU 1+0 and got sth around 5-10 ELO increase
- Last one at long time control,after ~1000 games with 10+0 result is:
Orig - Mod: 491 - 520 (+10 elo)
A testing marathon by Joona for this important change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Master thread returns from idle_loop() when sp->cpus == 0,
but cpus is decremented by slave threads under sp->lock,
so it could happen that we return in split(), where we release
the split point, with sp->lock still held.
This patch guarantees that sp->lock is released when returning
to split().
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The idea here is that if we cut-off after a stand pat the
already exsisting TT entry was not usable with current
beta, so overwrite anyway.
After 999 games at 1+0
Mod vs Orig +173 =665 -161 + 4 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Almost no change and simplifies a bit the code.
After 961 games at 1+0
Mod vs Orig +156 =650 -146 +4 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Re-save the same TT entry if value is usable and allow
us to cut-off, it means that entry is valuable and
we want to keep it fresh updating the 'generation'
parameter up to the current value.
Patch suggested by J. Wesley Cleveland and better
clarified by Miguel A. Ballicora.
After 999 games at 1+0 64MB hash size
Mod vs Orig +167 =677 -155 +4 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In this case we avoid to name the 'black' version of the
endgame function but use a vector indexed by color instead.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because exit_threads() references the global object TM, we
need to call the function when still inside main(), otherwise,
due to undefined global object initialization and destruction
we could end up with referencing an already destroyed object.
Actually this should not happen because Application singleton
is initialized _only_ after all the other globals due to how
Application::initialize() is defined, but this is very tricky
C++ and not easy to follow, even for me ;-)
Also rearranged a bit main() code flow.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Moved evaluation of unstoppable pawns out of
evauation of passed pawns because event frequency is
much lower. Added evaluate_unstoppable_pawns() that
is called very seldom and contains all the unstoppable
pawn logic.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Should be a very minor change, but there is a small
functional change because futility_margin() is used in more
places then in the pruning formula.
After 999 games at 1+0
Mod vs Orig +167 =678 -154 +5 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also fix dimension of UnpairedPawnsTable[] to accomodate the
case in which we have 8 unpaired pawns, i.e. only one side has
pawns, the other side has no pawns.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The idea is to reduce the score if we have many
pawns opposing an enemy pawn so that the draw
possibility increases.
Just introduced the logic, but no functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A pawn is candidate to be passed if doesn't have enemy pawns
in just front of him, not also behind !
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Absolutely no useful at all, just code obfuscation so
use real definition instead.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It will be used to lookup squares in front of
a given square. Same concept of PassedPawnMask[]
and OutpostMask[].
Also small tweaks in bitboard.h
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now with:
stockfish bench 128 1 5 default perft
it is possible to get perft 5 results of each position and
the first 3 positions correspond to the well known test
position in:
http://chessprogramming.wikispaces.com/Perft+Results
This allow to quickly check for perft consistency running
the 'bench' command.
No functional change but signature has changed because
bench default positions 2 and 3 have changed.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Revert all the patches that introduced the change and
more or less fixed the zugzwang issue.
There is a gain against last current version and we
can remove a lot of code.
After 979 games at 1+0 on my QUAD
Mod vs Orig +152 =688 -139 +5 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Real search is considered of higher quality then null
search one.
This allows to fix the zugzwang issue with a minimal
impact on ELO.
Zugzwang verified on position:
8/7P/8/8/K2b4/p7/1k6/1B6 b - -
After 999 games at 1+0 on my QUAD
Mod vs Orig(94bb196) +168 =657 -174 -2 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Is a boolean option that when set allows Stockfish
to select the best book move across the possible ones.
Feature requested by Salvo Spitaleri.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid incorrect mate scores in positions like
BK5/1R4b1/2k1Np2/3p3b/2p3pq/p1rB4/n2n1p2/8 w - -
Thanks for Jouni Uski for reporting the problem
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>
Add an UCI option "Zugzwang detection" OFF by default that
enables correct detection of zugzwang.
This is just to let 1.7.1 be 100% compatible with 1.7 and
should be removed after release.
Verified 100% functional equivalent to 1.7
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It fails in test position:
8/7P/8/8/K2b4/p7/1k6/1B6 b - -
Not clear why but we revert because it fixes the issue.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In this case use a normal VALUE_TYPE_LOWER TT type instead of
VALUE_TYPE_NS_LO. This allow us to TT cut-off in a bit more nodes.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This patch fixes an issue with zugzwang well explained by Tord:
"Assume that a zugzwang position occurs at iteration N,
at a search depth d, with d < 6*OnePly. The null move search
fails high, and no verification search is done, because the
depth is too small. The position gets stored in the transposition
table with a good score and a depth of d.
Now, consider what happens when the same position occurs at iteration
N+1, this time with a depth of d+OnePly (i.e. one ply deeper than at
the previous iteration). Once again, the null move search fails
high. The point is that the verification search will also fail high,
because of an instant transposition table cutoff caused by the value
stored in the TT during the previous iteration."
With this patch we simply do not allow TT cutoffs at the root node
of a null move verification search if the TT value was found by a
null search.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Add VALUE_TYPE_NS_LO to enum ValueType and use it when
saving in TT a value from a null search.
Currently no action is performed, the next patch will enable
the new type.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Reported warning is:
warning #2514-D: pointless comparison of unsigned
integer with a negative constant
Spotted by Richard Lloyd.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Under gcc we have:
warning: dereferencing type-punned pointer will break
strict-aliasing rules
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use full depth, not reduced one. This allows
to avoid to do a null search when in the same
position and at the same or bigger depth the
null search failed high.
A very small increase, if any.
After 963 games at 1+0
Mod vs Orig: +158 =657 -147 +4 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In this form it is even more evident we have some
issue there to be fixed sooner then later....
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After previous patch we don't need any more the call parameters.
This fixes a couple of warnings under MSVC.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After 500 games at 5+0 on my QUAD (3 days) there
is no difference with old version, so probably it
is a feature that doesn't scale with search depth.
So revert for now, perhaps we should readd under a
different form.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
MSVC complains about an implicit conversion from double to int.
Also small comments tweaks.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In the beginning use milder reduction and at the end be
more aggressive.
After 1500 games on Joona's QUAD
Mod - Orig: 791 - 720 +16 elo
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Causes very small functional change which is not observable with
our usual set of test positions.
However change is observable fx. with following position:
4k3/3r4/5Q2/6K1/8/8/8/8 w - - 0 1
go depth 24
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If null search fails high return null value instead of beta.
With TT hash there may be a small advantage for fail-soft since
storing slightly better bounds may cause slightly more hash hits.
After 990 games at 1+0
Mod vs Orig +171 =665 -154 +6 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Array castleRightsMask[] is not static because it can
be different for different positions, so let it be
a Position member data. This allows to remove tricky
hacks to take in account that although it was defined
static it could change.
Theoretically now copying a position is a bit slower because
we need to copy also an array of 64 integers, but because in
split() we don't copy the position anymore, but just keep the
pointer, the added burden is not mesurable even in MP case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also don't use __cpuid() intrinsic for Intel under
Linux because gives wrong results when detecting HT,
use the gcc version instead. Finally clean up the code.
Error was due to changed __cpuid() signature for
gcc compiler.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This will allow to use the function also for other
purposes then detecting POPCNT.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It will be used by future patches and also rearranges some
half cooked code that mistakenly ended up in master in the
past.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently, in case of fail high/low we research with
a window increased by 2*AspirationDelta at first
attempt, this patch instead makes the research be
done with an increase of just AspirationDelta size,
in case of a consecutive fail we will widen to
2*AspirationDelta and so on.
After Joona's test:
Orig - Mod: 850 - 890
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
One for failing highs and one for failing lows, this
should reduce average window size in case of positions
that fail first high and then low (or the contrary).
After ~2000 games on Joona's quad we have:
Mod - Orig: 1012- 975 (+6 elo)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead to leave uninitialized or scattered in the code
as is the case for ExtraSearchTime.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently we use original sorting after a fail low to
research at wider window. This patch instead sorts the
moves according to the last available move's scores.
Strangely no functional change, but should be.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Changed FutilityMarginsMatrix dimensions to be a power of two
so that compiler can produce a faster accessing code.
Introduced print_pv_info() to remove some redundant code in
root_search()
Remaining stuff is triviality and documentation tweaks.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Under Windows we use CreateThread() to setup threads and
we pass a pointer to a variable that receives the thread
identifier, but this parameter is optional and we don't
use it, so remove it.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It happens that NULL is 0, but the conventional meaning is of
a zero pointer, so repleace with an explicit 0 integer value.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Consider sligtly negative captures as good if at low
depth and far from beta.
After 999 games at 1+0
Mod vs Orig +169 =694 -136 +11 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It raises an assert under Windows, it is not clear why but it
happens that idle_loop() is called with incorrect threadID and
the assert triggered is:
assert(threadID >= 0 && threadID < MAX_THREADS);
So revert the patch for now, but we should understand why it
fails.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We can't do it with full guarantee anyway because
there is always a possible race between the setting of
state to THREAD_SLEEPING and actual sleeping.
So just remove the not perfect code to avoid misunderstandings.
This reflects what we have done in wake_sleeping_threads() in
the previous patch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently there is no guarantee that threads are sleeping
when calling wake_sleeping_threads() because put_threads_to_sleep()
returns without waiting for threads to actually sleep.
Assert can be easily triggered calling put_threads_to_sleep() and
wake_sleeping_threads() in a tight loop.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This option likely has very low meaning for playing strength and style,
so I see no need to keep this configurable
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
search() is used as a "leading star" and other routines
are modified according to it.
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Was broken and fixing would be too messy.
Now this option is only activated in single thread mode
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Just to avoid misunderstandings.
True staticValue is available through search stack
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Bug spotted by Jouni Uski and fix suggested by Pablo Vazquez
Also add note that we are not always handling fifty move rule correctly
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I cannot see connection between the two.
Also add one FIXME for illogical behaviour
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I don't know if enumerating sections is a good idea,
but for me code is more readable this way
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I cannot see any reason to do this. Even this is not enough to fix
theoretical race case on Windows which doesn't seem to cause any
problems in practice anyhow
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Resurrect extra check for sleeping in POSIX code.
This necessary to prevent ugly races between
thread_broadcast and thread_cond_wait.
After thread has woken up, it marks itself as available.
Another thread must not do this, because of possible race.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
So we can use a const value instead of a pointer in
split().
Also pass NULL instead of a faked address of alpha in
case split is called from a non-PV node.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Intrinsic __popcnt64() returns an unsigned __int64, cast
to an integer and silence the warning.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Joona says that sp_update_pv() does not pass the split point
boundaries, so there is no risk to corrupt data from another
split point. Also the race on thread_should_stop() is harmless
because of this.
So revert the patch and come back to single lock.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Joona says:
1. We should not be afraid of "AllThreadsShouldExit" flag.
Because when this is set to true we _must_not_ be searching (= All
splits must have been undone).
And if we are not searching it's impossible that some other thread
could give us work to do. So setting state to THREAD_AVAILABLE
doesn't do any harm. If you want to add check for this, you could do
it like this:
if (threads[threadID].state == THREAD_WORKISWAITING)
{
+ assert(!AllThreadsShouldExit)
threads[threadID].state = THREAD_SEARCHING;
2a. If waitSp->cpus == 0, setting state to THREAD_AVAILABLE makes
no harm either, because helpful master concept dictates that _only_
our own slave can book us. If we don't have any slaves, noone has the
right to book us.
2b. If point (2a) is not correct then your extra check only adds extra race:
In smp code checking for waitSp->cpus > 0 is not enough. It's possible that
our slave immediately exits and another thread
books us as a slave when our state is still
THREAD_AVAILABLE. So instead of adding extra level of security we have
just introduced extra race.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When we found a cut-off then lock all the split point chain,
not only current one to avoid races in case two threads running
on different split points where one is ancestor then the other,
find a beta cut-off at the same time, in this case we want only
one to call sp_update_pv().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is a per split-point request, not per-thread. When we find
a beta cut-off in current thread's split point or in or in some
ancestor of the current split point then threads should stop
immediately the search and return to idle_loop().
The check is done by thread_should_stop() that now looks only
at split point's chain.
No functional change and a good semplification.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is easier to follow and also reduces the points
where state changes to mainly idle_loop() and split().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is because when we are below 4 * OnePly, the null move
will directly jump to qsearch and if we are below beta,
our opponent is above beta and will get immediate
stand pat cut off.
So basically this patch is just optimizing away useless
evaluation calls. dbg_hit_on() runs show that this heuristic
is correct >99% of cases. Transposition table probably causes
some inaccurary?
After 1148 games on QUAD
mod-orig: 583 - 565 +5 elo
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In this case is dangerous because in split() we reset the flag to
false, but if it was set due to a cut-off higher in the tree we
completely miss that and go on with the full search.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of other flags this is not a state flag, i.e. does
not defines a state for the thread, but a request because
after we raise 'stopRequest' flag the corresponding thread is
not stopped, but continues to run for a while until it returns
from sp_search() in idle_loop.
It is important the name reflects this.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Among them 'stop' and 'printCurrentLineRequest' could have
random value, so reset to a known state before to leave the
search.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the first nice effect of previous patch !
Because thread_should_stop() should be declared 'const' we
need to remove the setting of 'stop' flag to true that
turns out to be a bug because thread_should_stop() is called
outside from lock protection while 'stop' flag is a volatile
shared variable so cannot be changed when not in lock.
Note that this bugs fires ONLY when we use more then 2 threads,
so commonly only in a QUAD or OCTAL machine.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Main aim of this patch is to consolidate all the thread related stuff
behind a single class interface so to avoid messing with global flags
and having thread code scattered among non-thread related stuff.
Another advantage is that now access to thread's variables is
more controlled, in particular we can differentiate between
read and write accesses by the mean of different interfaces, it
is so simpler to understand how a function is related to threads.
Lastly this rewrite is the base for future code consolidations and
semplifications that are easier now that we have only one thread's
access point.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Ensure threads are sleeping when leaving init_threads() and
the newly introduced put_threads_to_sleep().
Also ensure threads are not sleeping when leaving
wake_sleeping_threads().
As a side effect we now leave think() with all the threads
(but the main one) guaranteed to sleep. So when we enter
again in think(), after the opponent next move, we know
threads must be sleeping.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Wait inside wake_sleeping_threads() for the threads to be
effectively and reliably woken up.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Will be used by future patches. Also:
- Renamed Idle in AllThreadsShouldSleep
- Explicitly inited AllThreadsShouldExit and AllThreadsShouldSleep
in init_thread() instead of use an anonymous global initialization.
- Rewritten idle_loop() while condition to avoid a 'break' statement
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Patch from Richard Lloyd (slightly edited from me), following the list
of changes as described by the author:
src/Makefile:
- Added PREFIX and BINDIR for the install: rule.
- Added a "make hpux" line to the help: rule.
- Added "make test"/"make check" rule that runs the $(PGOBENCH) command.
- "make clean" now additionally removes core and bench.txt.
- Added an hpux: rule.
- Added an install: rule to mkdir $(BINDIR), copy $(EXE) to $(BINDIR) and
then strip it.
- "make strip" now ensures that $(EXE) is built first before trying to
strip it.
- Hide errors and output from the g++ command used by the .depend: rule and
then touch .depend in case g++ isn't available.
- Hide errors from the "include .depend" in case .depend doesn't exist
(e.g. directly after a "make clean").
src/book.cpp and src/book.h:
- HP-UX's aCC really didn't like the const keywords used for the
Book::file_name() definitions, so they were removed. I checked that this
didn't affect a Linux build and it was still fine.
src/misc.cpp:
- HP-UX uses <sys/pstat.h> and pstat_getdynamic() to determine the number of
CPU cores, so added conditional code for that (if pstat_getdynamic() fails,
set the number of cores to 1).
src/tt.cpp:
- <xmmintrin.h> and _mm_prefetch() seem highly specific to the Intel x86(_64)
and gcc platforms - neither exist in HP-UX, so conditionally avoid that
code in HP-UX's case. Perhaps some sort of define is needed here
such as -DHAS_MM_PREFETCH that could be #ifdef'ed for instead?
Even after these changes, it's more convenient for HP-UX users to edit the
default: rule in the Makefile to run "$(MAKE) hpux" before they build
stockfish, but that's not a big deal if they're warned about that first (the
same applies to all other builds other than the standard "$(MAKE) gcc" one).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Compiler complains because in Book we have a d'tor but not
copy c'tor and assignement operator (warning C4511 and C4512),
note that after adding them (just declared) you now need also
default c'tor !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is an hidden bug waiting to fire. The main problem is
that ss[ply] is overwritten by search() and qsearch() called
from IID and razoring, so that we cannot hold a pointer to a
local EvalInfo variable.
For instance if we go razoring then we overwrite the pointer
with the address of a variable local to qsearch(), when we return
from qsearch() variable goes out of scope and now ss[ply].evalInfo
holds a stale pointer !
Because we are not looking for troubles we go through the
safe route and we remove it entirely.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Gain value is multiplied by 16 to be of comparable magnitudo
of negative history, on average.
This patch shows very good results in tactical tests, but
started very bad in real games, so I have run two test matches.
After 896 games at 1+0
Mod vs Orig +187 =525 -184 +1 ELO
After 999 games at 1+0
Mod vs Orig +223 =590 -186 +13 ELO
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>
In search routines we use information from previous ply
and init killers two plies ahead.
So for me it seems correct to copy 4 searchstack items
in split:
ply - 1, ply, ply + 1, ply + 2
Because
a) we do not split at root (ply == 0)
b) ply < PLY_MAX and SearchStack size is PLY_MAX_PLUS_2
there should be no risk of underflows or overflows
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>
It was only used to control StopOnPonderHit variable.
Now use FailLow variable instead.
Patch has a minor effect on time management when ponder is on.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
noProblemFound condition is never true.
This was verified by running 800 games 1+0 match in 1 CPU computer.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because H.move_ordering_score() can return negative values
some negative see moves could be searched before non-negative
see moves with negative history.
This patch restores proper ordering.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now that history can go negative and is almost alwyas
non zero we have no more reasons to use also psqt term.
After 994 games at 1+0
Mod vs Orig +204 =597 -193 +4 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of piece-from-to, in this way it is similar
to what we already do for history.
Almost no change, but seems a bit simpler in this way.
After 995 games at 1+0
Mod vs Orig +207 =596 -192 +5 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems more standard conformant. Also added a bit of
description directly from Tord.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We erroneusly added two times the same scaling function
to endgame's map.
Fix detected by valgrind becasue resulted in a memleak
of the first added scaling function.
Bug introduced by 30e8f0c9ad6a473 of 13/02/2009
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We had an overflow due to use an integer for hash size,
now we use a size_t as we should, so we can increase to
an higher limit.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Normally it's up to the GUI to check for option's limits,
but we could receive the new value directly from the user
by teminal window. So let's check the bounds anyway.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
With new target 'make gcc-popcnt' it is now
possible to compile with enabled hardware POPCNT
support also with gcc. Until now was possible only
for Intel and MSVC compilers.
When this instruction is supported by CPU, for instance
on Intel i7 or i5 family, produced binary is a bit faster.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This reverts commit c43c5fe9e0.
Produces following build error after 'make clean', 'make icc' under Mandriva
with icc version 11.0
Makefile:306: .depend: No such file or directory
In file included from tt.cpp:28:
/usr/lib/gcc/i586-manbo-linux-gnu/4.3.2/include/xmmintrin.h:35:3: error: #error "SSE instruction set not enabled"
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Futility captures alone does not seem an improvment.
Perhaps is a combination of stand pat + futility that is winning,
so revert for now and continue testing starting from a standard
base until we find the correct receipe.
After 999 games at 1+0
Mod vs Orig +231 0506 -201 +10 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Under some rare cases we can have a search tree explosion
due to a perpetual check or to a very long non-capture TT
sequence.
This avoids the tree explosion not following TT moves that
are not captures or promotions when we are below the
'generate checks' depth.
Idea suggested by Richard Vida.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Not a biggie but is a reduced pruned patch that doesn't
seems to hurt, so it is welcomed ;-)
After 999 games at 1+0
Mod vs Orig +207 =601 -191 +6 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
At ply == OnePly (common case) we avoid some useless
floating point computation.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Previously input like "setoption name Use Search Log value true "
(note space at the end of the line) didn't work.
Now parse value same way as option name. This way we implicitly
left- and right-trim value.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Initializing high-level object at startup is very dangerous,
because low-level snippets are not yet initialized.
For example Position's constructor calls find_checkers() which
calls attackers_to() which depends on various global bitboard arrays
which are not yet initialized. I think we are lucky not to crash.
RootPosition.from_fen(StartPosition); is called immediately after
all initializations are made at uci_main_loop() which is the
correct behaviour
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Joona new aspiration window. Main idea is to always
research aspiration fail highs/low at the same
ply and use much smaller aspiration window than previously.
Testing result is very positive.
1CPU:
953-1149
4CPU:
545 - 656
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid to take the lock two times in a tight sequence, the first
in get_next_move() and the second to update sp->moves.
Do all with one lock and so retire the now useless locked version
of get_next_move().
Also fix some theorical race due to comparison sp->bestValue < sp->beta
is done out of lock protection. Finally fix another (harmless but time
waster) race that coudl occur because thread_should_stop() is also
called outside of lock protection.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In debug run with 2 threads it happens to be following
assert after some minutes:
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
in search(), line 1615.
I am not able to understand why, anyhow reverted for the moment.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This avoid us to forget some very needed tests now that
futility has changed in a whole big chunk we need to fine
tuning every splitted change.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This will be useful to use gains table in move
ordering along with history table.
No functional change and big code remove.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
With current search control system, I can see absolutely no
reason to classify fixed time search as infinite search.
So remove old dated hack
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Value of uip.eof() should not be trusted.
input like "go infinite searchmoves " (note space in the end of line)
causes problems.
Check the return value of (uip >> token) instead
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In less then 1% of cases value > sp->bestValue, so avoid
an useless lock in the common case. This is the same change
already applied to sp_search().
Also SplitPoint futilityValue is not volatile because
never changes after has been assigned in split()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When we have more then 2 threads then we do an array
access with index 'Threads[slave].activeSplitPoints - 1'
This should be >= 0 because we tested the variable just
few statements before, but because is a shared variable
it could be that the 'slave' thread set the value to zero
just after we test it, so that when we use the decremented
variable for array access we crash.
Bug spotted by Bruno Causse.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Unify start loop for master and slave threads. Also guarantee
that all the 'stop' flags are set to false before first slave
is started, should be no harm because only master thread can
reset 'stop' flag of slaves to true, so should be no race but
better safe then sorry.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Only pure blocking evasions are candidate
for pruning.
After 998 games at 1+0
Mod vs Orig +215 =596 -187 +10 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In move_to_san() we create by copy a new position just
to detect if move gives check. This could be very costly in
line_to_san() that calls move_to_san() for every move, so
create the position only once and pass a reference to move_to_san()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When pondering threads are put to sleep, but when thinking
the threads are parked in idle_loop in a tight polling loop
checking for workIsWaiting falg.
So before we set the slave's flag workIsWaiting we have to
guarantee that all the slave data is already setup because
slave can start in any moment from there.
Rearrange the last loop to fix this race.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Once we have allocated our slave threads and we have removed
master from available threads we can safely remove the lock
so that the lenghty search stack copy operation will not
impact lock contention.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A pointer is enough because after a split point has been
setup master and slaves thread end up calling sp_search() or
sp_search_pv() and here a full copy of split point position is
done again, note that even master does another copy (of itself)
and this is done before any do_move() call so that master Position
is never updated between split() and sp_search().
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And detach splitPoint Position from the master one.
So we duplicate StateInfo only once in split() instead
of one for each thread in sp_search
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Renamed a bit the functions to be more clear what
we actually are doing when we craete a Position object
and explained how StateInfo works.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also removed some trailing whitespaces and aligned
indentation to current standard.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Only the previous, the current and the next ply SearchStack
are copied.
This reduces split overhead especially at low depth (high ply)
and with many threads.
Possibly no functional change (it is not easy to prove in SMP)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The init_eval() function corrupted the static array castleRightsMask[]
in the Position class, resulting in instant crashes in most Chess960
games. Fixed by repairing the damage directly after the function is
called. Also modified the Position::to_fen() function to display
castle rights correctly for Chess960 positions, and added sanity checks
for uncastled rook files in Position::is_ok().
It is a good programming practice to verify a system
call has indeed succeed.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When a search fails high then sp->alpha is increased and
slave threads are requested to stop.
So we have to check for a stop request before to start a search
otherwise we could end up with sp->alpha >= sp->beta
leading to an assert in debug run in search_pv().
This patch fixes the assert and get rid of some of possible races.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
maximum depth during a "go movetime ..." search. This prevents
Stockfish from hanging forever after finding a mate in two or
three while running a test suite at a level of a few seconds
per move.
No functional change when playing games at normal time controls.
In qsearch() try to get a cutoff with the help of an
extra check if we are already very near.
Small increase in actual games but a good result in tactical
test sets where this patch makes SF more tactical.
Mod vs Orig +197 =620 -181 +6 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Louis Zulli reports a miscompile with g++-4.4 from MacPorts.
Namely enum Value is compiled as unsigned instead of signed integer
and this yields an issue in score_string() where float(v) is incorrectly
casted when Value v is negative.
This patch ensure that compiler choses a signed variable to store a Value.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Value is never used un-initialized, but MSVC is not
smart enough to detect itself :-(
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use the same scoring system used for evasions. Small if any
increase, but should be in at least for completeness.
After 999 games at 1+0
Mod vs Orig +208 =601 -190 +6 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now that we have position static score we don't
need to call evaluate() a second time.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This will allow to have wider access to attack
information, for instance from MovePicker.
Note that 'eval' field become obsolete, it is kept
just becasue when we get a position score from TT
we update 'eval' even without an EvalInfo object.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In sp_search_pv() we do a LMR search using sp->alpha, at the end
we detect a fail high with condition (value > sp->alpha), but if
another thread has increased sp->alpha during our LMR search we
could miss to detect a fail high event becasue value will be equal
to old alpha and so smaller then new one.
This patch fixes this SMP-bug and changes also the non SMP versions
of the search to keep code style in sync.
Bug spotted by Bruno Causse.
No functional change (for single CPU case)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
futilityValue is now calculated immediately after
staticValue, so remove small bunch of unused code
No functional change
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
MSVC raises an "use of partially uninitialized variable" for futilityValue
and staticValue but this is not rue becasue when !isCheck variables
are never used, anyhow silence the warning.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is less prone to bugs because now it's up to the
compiler don't forget this important initialization.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
No change in functionality signature
The only functional change is that when we reach PLY_MAX,
we now return VALUE_DRAW instead of evaluating position.
But we reach PLY_MAX only when position is dead drawn and
transposition table is filled with draw scores, so this
shouldn't matter at all.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This way razoring is always based on exact evaluation and
follows simple formula.
Joona's test results are positive:
32-bit 1CPU:
Mod - Orig: 1073 - 993
64-bit 4CPU:
Mod - Orig: 759 - 721
Functionality Signature: 11448962
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Don't clamp to zero if a move continues to fail.
After 946 games at 1+0
Mod vs Orig +208 =562 -176 +12 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also retire razoring margins vector and use
a simpler formula instead.
Now that we use a more accurate static evaluation
try to avoid useless null searches when we are well
below beta. And for teh same reason increase a bit
the razoring.
After 972 games at 1+0
Mod vs Orig +224 =558 -190 +12 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It means we have already received "stop" or "quit" commands.
This fixes an hang in tactical test in Fritz GUI. Bug
introduced by previous bug fix :-(
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
According to UCI standard once engine receives 'go infinite'
command it should search until the "stop" command and do not exit
the search without being told so, even if PLY_MAX has been reached.
Patch is quite invasive because it cleanups some hacks used
by fixed depth and fixed nodes modes, mainly during benchmarks.
Bug found by Pascal Georges.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After deep tests Louis Zulli found on his OCTAL machine that
best setup for an 8 core CPU is as following
"Threads" = 8
"Minimum Split Depth" = 6 or 7 (mSD)
"Maximum Number of Threads per Split Point" = not important (MNTpSP)
Here are testing results:
mSD7 (8 threads) vs mSD4 (8 threads): 291 - 120 - 589
mSD6 vs mSD7: 168 - 188 - 644
mSD6-MNTpSP5 vs mSD6-MNTpSP6: 172 - 172 - 656
SF-7threads vs SF-8threads: 179 - 204 - 617
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
So to have the same layout and be as much similar as
possible. The only functional change is that now we
try ttMove as first also in PV nodes and at the end
we save the ttMove, as it happens in search. This
should have almost zero impact on ELO but it seems
the correct thing to do.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is an important design change because we know
compute evaluation in each node.
This is a 2.0 type change!
After 977 games at 1+0
Mod vs Orig +236 =538 -202 51.74% +12 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If after 'moves' there is a space then we crash.
The problem is that operator>>() trims whitespaces so that
after 'moves' has been extract we are still not at eof()
but remaining string contains only spaces. So that the next
extarction operation uip >> token ends up with unchanged token
value that remains 'moves', this garbage value is then feeded
to RootPosition.do_move() through move_from_string() that does
not detect the invalid move value leading to a crash.
This bug is triggered by Shredder 12 interface under Mac that
puts a space after 'moves' without any actual move list.
Bug fixed by Justin Blanchard
After reviewing UCI parsing code I spotted other possible weak
points due to the fact that we don't test if the last extract
operation has been succesful. So I have extended Justing patch
to fix the remaining possible holes in uci.cpp
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
According to standard en-passant is recorded in fen string regardless
of whether there is a pawn in position to make an en passant capture.
Instead internally we set ep square only if the pawn can be captured.
So teach from_fen() to correctly handle this difference.
Bug reported and fixed by Justin Blanchard.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Try to get a position evaluation better then
the quick one with the help of the TT table.
This allows the null search conditions and
chosen reductions to be more accurate.
After 908 games at 1+0
Mod vs Orig +209 =526 -173 +14 ELO
Functionality Signature: 16627355
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Linear rule, less aggressive then Dann's one.
It seems it scales well with depth. We will need to
verify against weaker engine if it keeps the score.
After 999 games at 1+0 on my Dual Core
Mod vs Orig +232 =534 -207 +9 ELO
After 1000 games by Martin Thoresen on his QUAD at 1+0
Mod vs Orig 521/479 52.10%
Functionality Signature: 17655312
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The most interesting thing is a bit of rewrite
and semplification in connected_moves()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is not useful becasue it is safe to call
get_next_move() multiple times when phase == PH_STOP
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because that's the correct meaning. Note that also the
corresponding UCI option has been renamed.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After history accounting rewrite in 1.6, a small
tweak of history parameters seems positive.
Note that these are not to be considered the optimal
values, just a wild guess that proved good.
Finding the optimal values would require a much longer
testing time.
After 967 games at 1+0
Mod vs Orig 240 529 198 +15 ELO
Functionality Signature: 21222553
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
According to the standard, compiler is free to choose
the enum type as long as can keep its data.
Also cast to short and right shift are implementation
defined in case of a signed integer.
Normally all the compilers implement this stuff in
the "usual" way, but gcc with -O3 and -O2 pushes
aggressively the language to its limits to squeeze
even the last bit of speed. And this broke our
not 100% standard conforming code.
The fix is to rewrite the Score enum and the 16 bits
word extracting functions in a way that is 100% standard
compliant and with no speed regression on gcc and also on
the other compilers.
Verified it works on all compilers and with equivalent
functionality.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The compiler is allowed to chose the size of an enum variable
based on the values it is expected to store. So force the compiler
to use at least a 32 bit integer type for the Score.
MSVC and Intel do not change, while gcc under -O3 is affected
by this change.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We cannot cast a pointer type to an unrelated pointer type.
This is a violation of the strict aliasing rules.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is not clear why is not true, even in single thread
case, but as a matter of fact it is not!
So remove it.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Unfortunatly we need to slow down to -O1 to be sure
it works always.
Note that sometime it works also with -O2 or even -O3,
but user has to try himself.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead should be read by the corresponding UCI
option "Book File".
Bug reported and fixed by Justin Blanchard (Arch Linux)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Was a long standing hidden bug from Glaurung times,
triggered only now that we enable IID at non PV nodes.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We want to increrase the opportunities
of doing an exclusion search.
After 999 games at 1+0
Mod vs Orig +216 =574 -209 50.35% 503.0/999 +2 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead decrement history value on failure.
After 999 games at 1+0
Mod vs Orig +236 =558 -204 51.60% +11 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This way we avoid overwriting valuable TT entries which
are needed to calculate exclusion search extension for pv.
Mod - Orig: 483 - 410 (+28 elo!)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After 999 games we are almost equal (+2 ELO),
but we have a good result against Rybka
Rybka 2.3.2a mp 32-bit vs Mod 254.5 - 242.5 +152/-140/=205 51.21%
Rybka 2.3.2a mp 32-bit vs Orig 259.5 - 236.5 +151/-128/=217 52.32%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now we always try to filter out moves, we will have
more wasted evaluation calls, but also more pruned
nodes.
After 786 games
Mod vs Orig +196 =413 -177 +8 ELO
Verified also against Rybka it increases score to 50-51%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We might be asked to ponder mate or stalemate position.
This being the case, simply wait for stop or ponderhit.
Currently we crash.
UCI specs aren't clear on the issue, but it cost nothing to
add little check.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Problem is that
istream& operator>> (istream& is, char* str );
according to C++ documentation "Ends extraction when the
next character is either a valid whitespace or a null character,
or if the End-Of-File is reached."
So if the parameter value is a string with spaces the currently
used instruction 'ss >> ret;' copies the chars only up to the first
white space and not the whole string.
Use a specialization of get_option_value() to fix this corner case.
Bug reported by xiaozhi
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now we use a formula to calculate margins on the fly.
Node count has changed because we fixed a leftover when
we still where using FutilityMargins to calculate futilityValue
in the case that we had the evaluation score in TT.
Also small indentation fix.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Increase pruning at low depths while tone downa bit at
higher depths (linearize a bit the logaritmic behaviour)
This goes togheter with IncrementalFutilityMargin decreased
to 4 compensate the bigger pruning effect.
Total pruned nodes are more or less the same. We go from 36%
of nodes after prune to 37% with this patch.
After 999 games at 1+0
Mod vs Orig +250 =526 -223 +9 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If we arrive until the exclusion search call then
we know that move == ttMove == tte->move()
But using ttMove in search call while, during excluded search
conditions we have used tte->Move()could be a little bit suboptimal.
On the other side using tte->move() also in search call is a bit ugly
so opt for the third choice that is the most clean becasue from the
conditions the reader easily understands that we are talking of ttMove
and that we ant to exclude the move we are evaluating in that moment.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If tte->move() != MOVE_NONE then tte->move() == ttMove
What could happen is that we have a ttMove without a tte, or,
we have a tte but tte->move() == MOVE_NONE
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Due to IID we could have a ttMove and not a tte, or,
even if we have a tte they could belong to different
searches so that the depth and type of tte don't
have the same origin of the ttMove.
To fix this we always use tte entry in excluded search
condition and, after an IID, we reprobe the TT table.
No functional change. Apart from possible crash fix.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They gave bad results:
Mod - Orig: 361 - 404
Master is now verified to be functional equivalent with F_63
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>
We already reset loseOnTime flag at the beginning of
a new game, so we can simplify a bit the ligic there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
* New version is documented and logic should be easier to follow
* Add extra check to not use LSN with x moves / y seconds time control
* New code fixes some rear cases where old code (still) causes program to lose on time at move 1.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
* The function is called only in one place
* It must not be called elsewhere
* The function call easily replaced with simple one line condition
No functional change (tested with usual set + 2000 random positions)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
* First one is without any documentation, code is working just fine,
so there seems to be nothing that really should be fixed.
* Second one requesting emergency measures on aspiration fail low
when we are running out of time and we are without good move.
After very long time, I've come to conclusion that this is
impossible to fix, so remove request.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use an exponenital law instead of a linear one for
history pruning.
This should prune more at low depths and a bit less
at high depths.
After 965 games
Mod vs Orig +233 =504 -228 +2 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Correct beta by razor margin when callin qsearch
After 1019 games on Joona's QUAD
Mod - Orig: 524 - 495 (+10 elo)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Game phase is a strictly function of the material
combination so its natural place is MaterialInfo,
not position.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Call directly 'perft 6' to search up to depth 6*OnePly
instead of the old 'perft depth 6'.
It is more in line to what other engines do. Also a bit
of cleanup while there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move the code to the caller and also move mob_area
computation out of evaluate_pieces(). It is more clear
the code flow and it is also faster.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When false (common case) we avoid to update checkers
bitboard that although not so costly slows down a bit
this very hot and critical path.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid a 64 bit load using a pointer. It saves a couple of push/pop
instructions so advantage is only theorical, but anyway we use
pop_1st_bit() as a reference implementation for 32 bit systems so
we keep it more for documentation purposes then for other reasons.
Idea of pointer is of Eric Mullins.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
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>
Save mid and end game scores in an union so to
operate on both values in one instruction.
This patch just introduces the infrastructure and changes
EvalInfo to use a single Score value instead of mgValue
and egValue.
Speed is more or less the same because we still don't use
unified midgame-endgame tables where the single assignment
optimization can prove effective.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Try an internal iterative deepening not only when we don't
have a TT move but also if search depth is more then 4*OnePly
higher then TT move depth.
On some tests it seems that in around 20% of cases ttMove changes !
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also remove some fallback templates that prevent a
compile error in case the user runs 'make icc-profile-popcnt'
from a non supported machine.
We want to loudly fail in that case instead of silently
fallback in a non-popcount compilation.
Updated documentation too.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Variable 'f' in 'for' loop scope hides same named
one in outer scope.
Of curse no functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Thanks to Eric Mullins we have now endian friendly
pop_1st_bit() and also is removed the need to use
-fno-strict-aliasing compiler option with GCC.
Speed is almost as fast, very small difference if any in
perft test, so I assume almost no difference in real games.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This allow us to avoid the generation of the
evasion moves if we already have a TT move, and
in case we have a cut-off we skip evasion generation
altoghter.
Node count is changed because now we try TT move _before_
to generate evasions. The search on the TT move alters the
piece lists so that when we come back to generate evasions
we build the move list with a diferent order and this alters
the node count.
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>
Generate captures of checking piece and blocking
evasions in one go.
Also reduce of one indentation level early returning
when we have a double check.
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>
Always try ttMove as first. Then try good captures ordered
by MVV/LVA, then non-captures if destination square is not
under attack, ordered by history value, and at the end
bad-captures and non-captures with a negative SEE. This
last group is ordered by the SEE score.
After 999 games at 1+0
Mod vs Orig +254 =546 -199 +19 ELO
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>
Check generation is used only in qsearch and
only at Depth(0), castling moves that give check
are very rare overall and even almost not exsistent
at Depth(0).
So retire this almost never used code that adds
a small but consistent slow down in the normal path.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because discovery checks are very rare it is better to handle
them all in one go and strip from usual check generation
function.
Also rewrite direct checks generation to use piece lists instead
of pop_1st_bit()
On perft test we have a +6% of speed up and is verified we
generate the same moves, although in a different order.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Patch from Joona with extension to benchmark and inclusion
of Depth(0) moves generation by me.
Note that to test also qsearch and in particulary checks
generations a change in the end condition is needed.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Verified against tuning branch.
After 100 games at 1+0 on Joona QUAD
Mod - Orig: 527.5 - 471.5 (+20 elo)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Give a bonus for each kind of attacked piece. Bonus
value is based on the type of attacked piece and the
type of attacking one.
Penalize pieces attacked by enemy pawns, also in
this case penality value depends on the type of
attacked piece.
This patch oboletes as redundant the increased mobility
count of the attcked squares that is then removed.
After 956 games at 1+0
Mod vs Orig +262 =462 -232 51.57% 493.0/956 +11 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Small code cleanup and a bit faster too.
The only functional change is that in extension
in pv node we extend promotions and not only captures
when condition met.
This is practically an undetectable change and has
no impact on strenght.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Even if SEE is negative there is always a good possibility
that TT move is a cut move anyway. For instance a lot of
BXN exchanges that have negative SEE can very easily be
good exchanges.
A nice side effect is a bit reduced frequency of
see_sign() calls.
After 643 games at 1+0
Mod vs Orig +174 =327 -142 52.49% 337.5/643 +17 ELO
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>
Only in less then 2% of cases we have a new sp->bestValue,
so check before to lock and save a costly locking
most of the times.
Patch suggested by Joona.
No functional search.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use futility pruning also in split points.
Do not use history pruning in split points when
getting mated.
After 1000 games on Joona QUAD
Orig - Mod: 496 - 504
Added an optimization to avoid a costly lock in the
very common case that sp->futilityValue <= sp->bestValue.
A test on a dual CPU shows only 114 hits on 23196 events,
so avoid a lock in all the other cases.
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>
If after the first tried 2 + int(depth) moves we still
have no any move that takes us out of a mate then do
not prune the following move, it is more important to
escape mate then speed up search.
This fixes an odd behaviour regarding mates, as example
the following diagram is a mate in 4, not in 3 as bogusly
reported before this patch.
1B2n3/8/2R5/5p2/3kp1n1/4p3/B3K3/8 w - - bm #4;
The performance impact should be minimal, the increment
in searched nodes is less then 0.1 %%
Idea and patch by Joona
After 999 games at 1+0
Mod vs Orig +193 =604 -202 -3 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Marco's new code for evaluating two unstoppable passed pawns where
one pawn promotes a single ply before the other tried to detect
cases where the pawn that promotes first could immediately capture
the pawn that promotes a ply later, but didn't work in cases where
the two pawns are on the same file. An example of this is the
following position:
8/8/3K4/2P5/2p5/3k4/8/8 w - -
With the new code, such positions are handled correctly.
In this case we call evaluate() being in check and this
is not allowed.
Bug found testing with reduced PLY_MAX value as suggested
by Miguel A. Ballicora on talkchess.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Add a rule about the situation when one side queens exactly
one ply before the other. To avoid difficult (but luckly rare)
cases we only handle the case of free paths to queen for
both sides.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix a condition for x-ray attack of a queen or
a rook behind a pawn of us. Previous condition does
not check if the enemy slider behind our pawn is
really attacking the pawn.
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>
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>
This allow to resolve a lot of addresses at compile time
instead of an indirect access at runtime.
Speed up on pgo compile is of 1.3%
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>
In case we reach ply == PLY_MAX we exit the function
writing
pv[PLY_MAX] = MOVE_NONE;
And because SearchStack is defined as:
struct SearchStack {
Move pv[PLY_MAX];
Move currentMove;
.....
We end up with the unwanted assignment
SearchStack.currentMove = MOVE_NONE;
Fortunatly this is harmless because currentMove is not used where
extarct_pv() is called. But neverthless this is a bug that
needs to be fixed.
Thanks to Uri Blass for spotting out this.
No functional change.
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>
When pondering InfiniteSearch == false but myTime == 0 so that
NodesBetweenPolls = 1000 instead of the standard.
The patch fixes the bug and is more robust because checks
directly myTime for a non-zero value, without relying on
an indirect test (InfiniteSearch in this case).
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of checking the time every 100 nodes in the last second,
and every 1000 nodes in the last five seconds, Stockfish now checks
every 1000 nodes in the last second and every 5000 nodes in the last
five seconds. This was tested in 1036 games at a time control of
40 moves/10 seconds, and no losses on time occured.
Also fixed a bug pointed out by Marco: In infinite mode, myTime
is actually 0, but of course we still don't want to check the time
more frequently than the standard once per 30000 nodes in this
case.
In RootMoveList c'tor we allocate a search stack and then
call directly qsearch.
There is called init_node() that clears all the fields of the search
stack array that refers to current ply but not the the killer moves.
The killer moves cleared correspond to ply+2.
In id_loop() this is not a problem because killer moves of
corresponding ply are cleared anyway few instructions later,
but in RootMoveList c'tor we leave them uninitialized.
This patch fixes this very old bug. It comes direclty
from Glaurung age.
Bug spotted by Valgrind.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In particular don't use an array of StateInfo, this
avoids a possible overflow and is in any case redundant.
Also pass as argument the pv[] array size to avoid a second
possible overflow on this one.
Fix suggested by Joona.
No functional change.
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.
If an enemy piece is defended by a pawn don't give the
extra mobility bonus in case we attack it.
Joona says that "Paralyzing pawn" is usually worth of nothing.
On Joona QUAD after 964 games:
Orig - Patch_2: 191 - 218 - 555 (+ 10 elo)
On my PC after 999 games at 1+0:
Mod vs Orig +227 =550 -222 50.25% 502.0/999 +2 ELO
In both cases we tested against the original version (without
increased mobility), not against the previous patch that instead
seems to fail on Joona QUAD:
Orig vs. Prev.Patch: 237 - 217 - 627 (-6 elo)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now in mobility we count enemy attacked pieces as
empty squares.
With this patch we try to give an higher score to positions
where the number of attacked pieces is higher.
After 999 games at 1+0
Mod vs Orig +262 =517 -219 52.15% 520.5/998 +15 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They are pawn structure invariant so has a sense to
store togheter with pawn info instead of recalculating
them each time evaluate() is called.
Speed up is around 1%
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This satisfies a specific user request of 28/8/2009
"The only issue I have is that during multiPV analysis, the depth 1
best move score is not reported by the engine (reporting for the best
move begins at depth 2). I need it at depth 1 also. Would it be
possible to make this modification in future versions? This would be
of great help as otherwise I will have to use a lesser engine.
The goal of my project is to calculate the ELO performance in a game
and also the ELO rating of individual moves. For this I need depth 1
scores for lower rated performances. I intend to distribute the program
for free upon completion.
Thanks, Jack Welbourne"
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Is used only in weight_option() so inline there.
Unroll color loop also for evaluate_space() and
finally also some assorted code style fixes.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use templates to manually unroll the loops so that
many values could be calculated at compile time or at
runtime but with a fast direct memory access instead of
an indirect one.
This change gives a speed up of 3.5 % on pgo build !!! :-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move to what we already do in generate_piece_moves()
This simple patch gives a spped up of 1.4% !!
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use equivalent Windows function _ftime() instead.
This patch also removes two long standing warnings
under MSVC.
No functional change and no change for non-Windows systems.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
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>
With this very simple patch we get a speed boost
of 0.8% on my PC !
Sometime we find the most complex tricks to increase speed
when instead the best results come from the simplest solutions.
No functional change of course ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A better and more specific name. Also a bit of code reshuffle.
Verified No functional change and No performance change
for the whole series.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Rewrite in the form normally used in other similar
functions like generate_pawn_noncaptures()
This allow an easier reading of the pawn moves generators
and simplify a bit the code.
No functional change (tested on more then 100M nodes).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A bunch of trivial code style and comment fixes.
Among them there is a real fix for a subtle case
involving promotion moves.
We currently check that a pawn push to 8/1th rank
must be a promotion, but we don't check the contary,
i.e. that a pawn push on a different rank must NOT be
a promotion. Note that, funny enough, we perform this
control for all the other pieces, but not for the pawns!
This patch fixes this really corner case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Remove a bunch of difficult and tricky code to test
legality of castle and ep moves and instead use a slower
but simpler check against the list of generated legal moves.
Because these moves are very rare the performance impact
is small but code semplification is ver big: almost 100 lines
of difficult code removed !
No functionality change. No performance change (strangely enough
there is no even minimal performance regression in pgo builds but
instead a slightly and unexpected increase).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In qsearch at depth 0 we generate only captures and checks.
Queen promotion moves are generated among the captures, but
under-promotion moves (both captures and non-captures) are
never generated even if they could give a discovery check.
This patch fixes this limitation extending generate_pawn_noncaptures()
to generate also check moves when required.
Apart for adding the (rare) case of an under-promotion that gives
discovery check, the patch is also a good cleanup because removes
generate_pawn_checks() altoghter.
This patch does the code clean-up but not enables the functional
change so to allow an easier debug.
No functional change and no performance change (actually a very
very small speed increase).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We are generating also king moves that give check !
Of course these moves are illegal so are in any case
filtered out in MovePicker. Neverthless we should avoid
to generate them.
Also simplify a bit the code.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Idea from Joona.
After 999 games at 1+0 on my Intel Core 2 Duo
Orig - Mod: +215 =538 -226 (+11 ELO)
On Joona QUAD after 845 games at 1+0
Orig - Mod: 151 - 181 - 513 (+13 elo)
So it seems a good change !
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When a node fails low and bestValue is still equal to
the original static node evaluation, then save this
in TT along with usual info.
This will allow us to avoid a future costly evaluation() call.
This patch extends to failed low nodes what we already do
for failed high ones.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Still not clear if it helps and, especially, how it
helps. So revert for now to avoid any influence on
future feature now under test.
With this patch we come back to be functional
equivalent to patch e33c94883 F_53.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After 828 games at 1+0
Mod vs Orig +191 =447 -190 50.06% 414.5/828
So almost no difference. Patch is committed more for
documentation purposes then for other reasons.
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>
It seems that it works better without compensation
of drifted value when saving static evaluation in TT.
After 818 games at 1+0
Mod vs Orig +217 =429 -172 52.75% 431.5/818 +19 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This avoids inclusion of a bunch of not very commonly
used headers from windows.h
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>
After 934 games at 1+0
Mod vs Orig +228 =493 -213 50.80% 474.5/934 +6 ELO
So it seems not negative and there is also the added
benefit to unify LMRPVMoves use in search_pv() and in
root list.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I managed to completely mismerge correct values
for QuadraticCoefficientsOppositeColor table :-(
Now it correspond to tuning branch for real.
After 999 games at 1+0
Mod vs Orig +247 =512 -240 50.35% 503.0/999 +2 ELO
So almost no change, but the new values comes from the
same tuning session of the others, so has more sense to
use these ones.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because of a hard-to-spot single-character bug in connected_moves(),
the discovered check code had no effect whatsoever. The condition
in the if (...) statement at the beginning of the code would always
return false.
Thanks to Edsel Apostol for pointing out this bug!
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>
It seems that pos.has_mate_threat() changes the position !
So that calling MovePicker c'tor before or after the
has_mate_threat() call changes the things !
Bug was unhidden by previous patch that makes MovePicker c'tor
to generate, score and sort good captures under some circumstances.
Because scoring the captures is position dependent it seems that
the moves returned by MovePicker are different when c'tor is
called before has_mate_threat()
Of course this is only a workaround because the real bug is still
hidden :-(
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If we don't have tt moves to search skip the
useless loop associated with TT_MOVES phase.
Another 1% speed boost that brings this series
to a +6.2% against original revision 595a90df
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This not only cleans up the code but gives another
speed boost of 1.8%
From revision 595a90dfd0 we have increased pgo compiled binary
speed of a whopping +5.2% without any functional change !!
This is really awsome considering that we have also
cut line count by 25 lines.
Sometime we spend days for getting an extra 1% from move
generation while instead the biggest optimizations come
from anonymous and apparently dull parts of the code.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Does not seem to improve on the standard, latest results
from Joona after 2040 games are negative:
Orig - Mod: 454 - 424 - 1162
And is more or less the same I got few days ago.
So revert for now.
Verified same functionality of 595a90dfd
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use the same way of loop along the move list used for
the others move kinds so to be consistent in get_next_move()
And a bit of the usual clean up too, but just a bit.
It is even a bit (+0.3%) faster now. ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Always after TT move but before captures.
This seems a better setup against version before this
patch.
After 999 games at 1+0
Mod - Orig +252 =527 -220 +11 ELO
Unfortunatly it does not seems to improve on the standard
version, with null move outside of movepicker (595a90df) with
the latest speed-up patches added in.
After 999 games at 1+0
Mod - Standard +244 =506 -249 -2 ELO
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>
In MovePicker we get the next move with pick_move_from_list(),
then check if the return value is equal to MOVE_NONE and
in this case we update the state to the new phase.
This patch reorders the flow so that now from pick_move_from_list()
renamed get_next_move() we directly call go_next_phase() to
generate and sort the next bunch of moves when there are no more
move to try. This avoids to always check for pick_move_from_list()
returned value and the flow is more linear and natural.
Also use a local variable instead of a pointer dereferencing in a
time critical switch statement in get_next_move()
With this patch alone we have an incredible speed up of 3.2% !!!
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Try good captures before null move when depth < 3 * OnePly.
Use this kind of null move also in Depth == OnePly.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Original patch from Joona with added optimizations
by me.
Great cleanup of MovePicker with speed improvment of 1%
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Explicitly write the conditions for pawn to 7th
and passed pawn instead of wrapping in redundant
helpers.
Also retire the now unused move_is_pawn_push_to_7th()
and the never used move_was_passed_pawn_push() and
move_is_deep_pawn_push()
Function extension() is so time critical that this
simple patch speeds up the pgo compile of 0.5% and
it is also more clear what actually happens there.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Remove the 'b' uint32_t local variable.
Optimized assembly is more or less the same
(one 'mov' instruction less), but now it is
written in a way more similar to the final assembly
flow so it should be easier for compiler to optimize.
Also guarantee that BitTable[] is always aligned.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Verified correct against tuning branch.
After 999 games at 1+0
Mod vs Orig +257 =510 -232 51.20% +9 ELO
Very small increase but an increase anyway !
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
The following new targets were added:
* osx-icc32: 32-bit x86 compiled with icpc.
* osx-icc64: 64-bit x86 compiled with icpc.
* osx-icc32-profile: 32-bit x86 compiled with icpc and pgo.
* osx-icc64-profile: 64-bit x86 compiled with icpc and pgo.
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>
In Movepicker c'tor we access during initialization one of
MainSearchPhaseIndex..QsearchWithoutChecksPhaseIndex globals.
Postpone definition of PhaseTable[] just after them so that
when PhaseTable[] will be accessed later in get_next_move()
it will be already present in L1/L2.
It works like an implicit prefetching of PhaseTable[].
Also shrink PhaseTable[] to fit an L1 cache line of 16 bytes
using uint8_t instead of int.
This apparentely innocuous patch gives an astonish speed
up of 1.6% under MSVC 2010 beta, pgo optimized !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It was due to a missing -msse compiler option !
Without this option the CPU silently discards
prefetcht2 instructions during execution.
Also added a (gcc documented) hack to prevent Intel
compiler to optimize away the prefetches.
Special thanks to Heinz for testing and suggesting
improvments. And for Jim for testing icc on Windows.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
But this time with the guarantee of an always aligned
access so that prefetching is not adversely impacted.
On Joona PC
1+0, 64Mb hash:
Orig - Mod: 174 - 237 - 359
Instead after 1000 games at 1+0 with 128MB hash size
we are at + 1 ELO (just 4 games of difference).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After fixing the cpu frequency with RightMark tool I was
able to test speed all the different prefetch combinations.
Here the results:
OS Windows Vista 32bit, MSVC compile
CPU Intecl Core 2 Duo T5220 1.55 GHz
bench on depth 12, 1 thread, 26552844 nodes searched
results in nodes/sec
no-prefetch
402486, 402005, 402767, 401439, 403060
single prefetch (aligned 64)
410145, 409159, 408078, 410443, 409652
double prefetch (aligned 64) 0+32
414739, 411238, 413937, 414641, 413834
double prefetch (aligned 64) 0+64
413537, 414337, 413537, 414842, 414240
And now also some crazy stuff:
single prefetch (aligned 128)
410145, 407395, 406230, 410050, 409949
double prefetch (aligned 64) 0+0
409753, 410044, 409456
single prefetch (aligned 64) +32
408379, 408272, 406809
single prefetch (aligned 64) +64
408279, 409059, 407395
So it seems the best is a double prefetch at the addres + 32 or +64,
I will choose the second one because it seems more natural to me.
It is still a mystery why it doesn't work under Linux :-(
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Prefetch always form a chache line boundary. It seems
that if prefetch address is not cache line aligned then
performance is adversely impacted.
Hopefully we will resuse that 32 bits of padding for something
useful in the future.
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>
Move prefetching code inside do_move() so to allow a
very early prefetching and to put as many instructions
as possible between prefetching and following retrieve().
With this patch retrieve() times are cutted of another 25%
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
TT.retrieve() is the most time consuming function
because almost always involves a very slow RAM access.
TT table is so big that is never cached. This patch
prefetches TT data just after a move is done, so that
subsequent TT.retrieve will be very fast.
Profiling with VTune shows that TT:retrieve() times are
almost cutted in half !
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Shrink key to 32 bits instead of 64. To still avoid
collisions use the high 32 bits of position key as the
TT key and the low 32 bits to retrieve the correct
cluster index in the table.
With this patch size og TTentry shrinks to 96 bits instead
of 128 and the cluster of 4 TTEntry sums to 48 bytes instead
of 64.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Binaries are always built with symbol table in to easy
debugging and profiling.
It is now possible to run:
make strip
To remove symbol table from the compiled binary. This
could be useful to prepare the release version.
Patch by Heinz van Saanen.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Current formula enable LMR when
i + MultiPV >= LMRPVMoves
It means that, for instance, if MultiPV == 1 then LMR
will be started to be considered at move i = LMRPVMoves - 1,
while if MultiPV == 3 then it will start before,
at move i = LMRPVMoves - 3.
With this patch the formula becomes
i >= MultiPV + LMRPVMoves - 2
So that LMR will always start after LMRPVMoves - 1 moves
from the last PV move.
No functional change when MultiPV == 1
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Access pos.piece_count() only once and avoid some
branches in the inner loop.
Profiling with VTune shows a 20% speed improvement in
get_material_info(), and it is also a bit more cleaned
up this way ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And put it in an already existing one so to
optimze a bit.
Also additional cleanups and code shuffles
all around the place.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And build also symbol table. It can easily stripped
after .exe is done and it is necessary for profiling.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After Joona's direct testing with ~2000 games it seems
values after 100.000 games does not give any advantage,
so revert for now.
Score of Stockfish_0 vs Stockfish_15: 491 - 392 - 1102
Score of Stockfish_0 vs Stockfish_40: 461 - 439 - 1076
Score of Stockfish_0 vs Stockfish_65: 442 - 518 - 1018 (13 elo)
Score of Stockfish_0 vs Stockfish_100: 504 - 502 - 984
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently minimum split depth is set automatically to 6
when number of CPUs is more than 4. I believe this is a bad
idea since for example my quad (4CPU with hyperthreading) is
detected as 8CPU computer. I've manually lowered down the number
of Threads, but so far I have played all games with Minimum
Split Depth set to 6!
Since 4CPU computers with hyperthreading are quite common and
8 CPU computers extremely rear (I expect we can get a direct
jump to 16 or 32 cores), this automatic adjusting is likely
to do more harm than good. Add a note in Readme.txt, so that
those rear 8CPU owners can manually tweak the "Minimum Split
Depth" parameter
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
previous used move_is_legal to verify that the move from the TT
was legal, and the old version of move_is_legal only works when
the side to move is not in check. Fixed this by adding a separate,
slower version of move_is_legal which works even when the side to
move is in check.
down the transposition table.
When the search was stopped before a fail high at the root was
resolved, Stockfish would often print a very short PV, sometimes
consisting of just a single move. This was not only a little
user-unfriendly, but also harmed the strength a little in
ponder-on games: Single-move PVs mean that there is no ponder
move to search.
It is perhaps worth considering to remove the pv[][] array
entirely, and always build the entire PV from the transposition
table. This would simplify the source code somewhat and probably
make the program infinitesimally faster, at the expense of
sometimes getting shorter PVs or PVs with rubbish moves near
the end.
Added the UCI_LimitStrength and the UCI_Elo options, with an Elo
range of 2100-2900. When UCI_LimitStrength is enabled, the number
of threads is set to 1, and the search speed is slowed down according
to the chosen Elo level.
Todo:
1. Implement Elo levels below 2100 by blundering on purpose and/or
crippling the evaluation.
2. Automatically calibrate the maximum Elo by measuring the CPU speed
during program initialization, perhaps by doing some bitboard
computations and measuring the time taken.
No functional change when UCI_LimitStrength is false (the default).
It is like a never finished painting. Everyday a little touch
more.
But this time it is very little ;-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Small micro-optimization in this very
time critical function.
Use bitwise 'or' instead of logic 'or' to avoid branches
in the assembly and use the result to skip an handful of checks.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Verified it is equivalent to the tuning branch results
with parameter values sampled after 100.000 games.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Some unwanted changes to Makefile slept in in patch
"Introduced the UCI_AnalyseMode option".
Revert them. No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is more similar to how get_material_info() and
get_pawn_info() work and also removes some clutter from
evaluate_king().
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When ordering moves we push all captures with negative SEE values
to badCaptures[] array during the scoring phase.
This patch delays the costly SEE call up to when the move has been
picked up in pick_move_from_list(), this way we save some SEE calls
in case we get a cutoff.
It seems we have a speed gain of about 1-1.5 % in terms of nodes/sec
and profiling seems to confirm the small but real speed increase.
Idea from Pablo Vazquez on talkchess.com
http://www.talkchess.com/forum/viewtopic.php?t=29018&start=20
It would be a no functional change but actually it is not because
now sorting set is different and so std::sort(), that is not a
stable sort, does not guarantees the order of same scored moves to
remain the same as before.
After 952 games at 1+0 we are below error bar, almost equal just
6 games of difference (+2 ELO)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Do not call count_1s_max_15() if not necessary, as is
not in the common case (>95%).
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a polynomial weighted evaluation to calculate
material value.
This is far more flexible and elegant then applying
a series of single euristic rules as before.
Also correct a design issue in which we returned two
values, one for middle game and one for endgame, while
instead, because game phase is a function of board
material itself, only one value should be calculated and
used both for mid and end game.
Verified it is equivalent to the tuning branch results with
parameter values sampled after 40.000 games.
After 999 games at 1+0
Mod vs Orig +277 =482 -240 51.85% 518.0/999 +13 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
To use the same naming rule of the other types and
to be compatible with inttypes.h, used under Linux.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We do not accept null search returned mate values,
but we always do a full search in those cases.
So the variable mateThreat that is set only if null move
search returns a mate value is always false.
Restore the functionality of mateThreat moving the
assignement where it can be triggered.
After 999 games at 1+0
Mod vs Orig +253 =517 -229 51.20% +8 ELO
Bug reported by xiaozhi
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Tord says that using a lower horizon at PV nodes
looks strange and inconsistent with the general
philosophy of our search (i.e. always being more
conservative at PV nodes). So set LMR at 3 also
on search_pv().
Test result after 601 games seems to confirm this.
Mod vs Orig +156 =318 -127 52.41% 315.0/601 +17 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Test extension of LMR horizon to 3 plies alone, without
touching null move search. To keep the patch minimal we still
don't change LMR horizon in PV search. This will be the object
of the next patch.
Result seems good after 998 games:
Mod vs Orig +252/=518/-228 51.20% 511.0/998 +8 ELO
So dynamic null move reduction seems a bit stronger then
fixed reduction even with LMR horizon set to 3.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Revert to LMR horizont of 2 plies. Only if parent move
is a null move increase to 3 so to avoid the bad combination
of null move reduction + LMR reduction. This is a more
aggressive patch then previous one, but it seems we are
going in the wromg direction.
After 531 games result is not good:
Mod vs Orig +123/=265/-143 48.12% 255.5/531 -13 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Set null move reduction to R=4, but increase the LMR horizon
to 3 plies. The two tweaks are related and should compensate
the combined effect of null move + LMR reduction at shallow
depths.
Idea from Tord.
After 999 games at 1+0
Mod vs Orig +251 =522 -225 51.30% + 9 ELO
On Tord iMac Core 2 Duo 2.8 GHz, one thread,
Mac OS X 10.6, at 1+0 time control we have:
Mod vs Orig 994-1006 -1.4 ELO
But Orig version is pgo compiled and Mod is not.
The PGO compiled version is about 8% faster, which
corresponds to about 7 Elo points. This means that
results are reasonably consistent.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Code that compiles cleanly under MSVC triggers one
compile error (correct) under Intel C++ and two(!)
under gcc.
The first is the same complained by Intel, but the second
is an interesting corner case of C++ standard (there are many)
that is correctly spotted only by gcc.
Both MSVC and Intel pass this silently, probably to avoid
breaking people code.
Now we are fully C++ compliant ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This avoid to duplicate storage allocation for every file
where they are used.
Note that simple numeric constant can remain in header because
are automatically folded by the compiler.
Patch suggested by Tord.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Push on the templatization even more to chip out some code
and take the opportunity to show some neat template trick ;-)
Ok. I would say we can stop here now....it is quickly becoming
a style exercise but we are not boost developers so give it a stop.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
a static eval cached in the transposition table would always equal the static
eval of the current position. This is in general not true, because the cached
value could be from a previous search with different evaluation parameter
settings, or from a search from the opposite side (Stockfish's evaluation
function is assymmetric by default).
We really don't need to have global endgame functions. We can
allocate them on the heap at initialization time and store the
corresponding pointer directly in the functions maps. To avoid
leaks we just need to remember to deallocate them in map d'tor.
These functions are always created in couple, one for each color,
so remove a lot of redundant hard coded info and just use the minimum
required: the type and the corresponding named string.
This greatly simplifies the code and also it is less error prone,
now is much simpler to add a new endgame specialized function: just
add the corresponding enum in endgame.h and the obvious add_xx()
call in EndgameFunctions c'tor, and of course, the most important part,
the EvaluationFunction<xxx>::apply() specialization in endgame.cpp
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This feature makes sense during development, but
It doesn't seem to make sense for normal users.
Also fix a possible race where the GUI adjudicates
the game a fraction of second before the engine sets
looseOnTime flag so that it will bogusly waits until
it ran out of time at the beginning of the next new game.
The fix is to always reset looseOnTime at the beginning
of a new game.
Race condition spotted by Tord.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is another moves serialization macro but this time
focused on pawn moves where the 'from' square is given as
a delta from the 'to' square.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is very rare we have pawns on 7(2) rank, so we
can skip the promotion handling stuff in most cases.
With this patch pawn moves generation is almost 20% faster.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Mostly of times we are interested only in the sign of SEE,
namely if a capture is negative or not.
If the capturing piece is smaller then the captured one we
already know SEE cannot be negative and this information
is enough most of the times. And of course it is much
faster to detect then a full SEE.
Note that in case see_sign() is negative then the returned
value is exactly the see() value, this is very important,
especially for ordering capturing moves.
With this patch the calls to the costly see() are reduced
of almost 30%.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Some variables were global due to some old and now removed code,
but now can be moved in local scope.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Verification test give unusless result
After 999 games at 1+0
Mod vs Orig +250 =503 -246 50.20% +1 ELO
So we are well below our radar level. Neverthless
there are 100.000 games on Joona QUAD that we could
take in account and that shows that this tweak perhaps
has something good in it, altough very little.
Verification tests shows should not be a regression, at
least not a big one even in the worst case, so apply the
change anyway and keep the finger crossed ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It turned out that the input sent to set_option_value() when it is called by
set_option() in uci.cpp always started with at least one whitespace. In most
cases, this is not a problem, because the majority of UCI options have numeric
values. It did, however, cause a problem for UCI options with non-numerical
values, like options of type CHECK and COMBO. In particular, changing the
value of an option of type CHECK didn't work, because the comparisons with
"true" and "false" would always return false. This means that the "Ponder"
and "UCI_Chess960" options haven't been working for a while.
Unfortunatly this tweak does not give good results.
After 894 games at 1+0 we have:
Mod vs Orig +205/-236/=453 48.27% -12 ELO !!
Perhaps we should test again, but in the mean time
we are going to revert this.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
A promotion move is not considered a possible evasion as it could be.
Bug introduced by patch
Convert also generate_pawn_blocking_evasions() to new API (7/5/2009)
Bug spotted by Kenny Dail.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Set gcc as default compiler on Linux, also compile
with symbols stripped to shrink binary file.
Original patch by Heinz van Saanen.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Predefined macro __INTEL_COMPILER is defined only for Intel,
while _MSC_VER is defined for both Intel C++ and MSVC.
So rearrange ifdefs to take in account this and test __INTEL_COMPILER
first and only if not defined check _MSC_VER for MSVC.
Patch suggested by Joona.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Add a new argument to bench to specify the name of the
file where timing information will be saved for each
benchmark session.
This argument is optional, if not specified file will
not be created.
Original patch by Heinz van Saanen
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is mainly intended to allow 64 bit compiles on any
system and avoid to crash when the binary, compiled on a
box where POPCNT is not supported, is run on a Core i7
system or similar CPU.
What could happen is that when compiled in a standard 64 bit
system, because the correct headers for the POPCNT intrinsic
are not found, the compiler creates dummy bit count functions
instead, these are never called at runtime on the machine where
Stockfish has been compiled. But if we run the same binary on a
Core i7 system, because POPCNT is detected at run time, the dummy
bitcount functions will be called giving false results that will
crash the application.
Note that would be possible to fallback on software bit count in
these cases, but this is even more subtle because POPCNT path is not
optimized so that we have an application working but at sub-optimal
speed, so better to crash, at least user is loudly warned that there
is something wrong.
If, instead, Stockfish is compiled on a Core i7 system with POPCNT
enabled, then if the PGO compile has been done properly, the same binary
will run at optimal speed _both_ on the Core i7 machine and on any other
64 bit standard machine. This is the ideal mode for binary distribution.
Finally this patch disables bsfq support under Windows, because it seems
inline assembly is not supported both by MSVC and by Intel Windows version.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also rename DISABLE_POPCNT_SUPPORT in NO_POPCNT and simplify a bit
the macro logic.
Always define a __popcnt64()or _mm_popcnt_u64() template, if the proper
function with the same name is defined in the intrinsics header, then it
will be choosen as first otherwise we fall back on the dummy template
that is never called at runtime anyway because cpu_has_popcnt() returns
false.
This fixes the compile error reported by Jim.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid indirect calling of piece_of_color_and_type(c, PAWN) and its
alias pawns(c) in the pawn evaluation loop, but use the pawns
bitboards accessed only once before entering the loop.
Also explicitly mark functions as static to better self-document.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Was erroneusly changed with the 32bit in recent
patch "Retire USE_COMPACT_ROOK_ATTACKS...".
Also another clean up of define magics. Move compiler
specific definitions in types.h and remove redundant cruft.
Now this macro ugly mess seems more reasonable.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
On 64 bit systems we can use bsfq instruction to count
set bits in a bitboard.
This is a patch for GCC and Intel compilers to take advantage
of that and get a 2% speed up.
Original patch from Heinz van Saanen, adapted to current tree
by me.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This greatly simplifies bitboard.cpp that now has only two setups,
respectively for 32 and 64 bits CPU according to IS_64BIT define
that is automatically set but can be tweaked manually in
bitboard.h
No functional change both in 32 and in 64 bits.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Testing on Joona QUAD failed to give any
advantage. Actually we had a little loss:
Mod - Orig: 342.0 - 374.0
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the backport of tuned piece values.
We needed to change also the psqt tables so that their
values, that are relative to piece values, remain the same.
Amost no change after 999 games:
Mod vs Orig 594-495 + 2 ELO points so well within error bar
It was expected somehow given the very little change of the
parameters values.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of add and subtract pqst values corrisponding to
the move starting and destination squares, do it in one
go with the helper function pst_delta<>()
This simplifies the code and also better documents that what
we need is a delta value, not an absolute one.
No functional change.
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>
Under MS Visual C++ debug window always unconditionally closes
when program exits, this is bad because we want to read results before.
So limit this kludge on Windows only.
Original patch by Heinz van Saanen.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Micro optimization in do_move(), a quick check
avoid us to update castle rights in almost 90%
of cases.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When we are hunting for mate, transposition table is filled in
with mate scores. Current implemenatation of aspiration search
can't cope with this very well.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Problem is that npMaterial is compared to _endgame_ value
of rook, although npMaterial is always (also in endgame!)
calculated using _middlegame_ values.
Bug was hidden as long as Rook middlegame
and endgame values were same.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
These are the tuned values of mobility and outposts
after 100.000 games on Joona QUAD.
After 999 games at 1+0
Mod vs Orig +248 =537 -214 51.70% +12 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When SEE piece values changed in aaad48464b
of 9/12/2008 we forgot to update the value assigned in
case of captured king.
In that patch we changed the SEE piece values but without
proper testing. Probably it is a good idea to make some
tests with the old Glaurung values.
Bug spotted by Joona.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move TT object away from heavy write accessed NodesSincePoll
and also, inside TT isolate the heavy accessed writes variable.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We can have false positives, but these are filtered out
anyhow by following conditions so they are harmless.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This was needed by an old optimization in sorting of
non-captures that is now obsoleted by new std::sort()
approach.
Remove also the unused depth member data. Interestingly
this has always been unused since the Glaurung days.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
These are the tuned psqt values after 100.000 games
on Joona QUAD. Results seem very good.
On PC 1 after 999 games
Mod vs Orig +261 =511 -227 51.70 % +12 ELO
On PC 2 after 913 games
Mod vs Orig +254 =448 -211 52.35 % +16 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Creating an History object requires clearing the History tables,
although fast is an useless job in san.cpp where History is used
just as a dummy argument for MovePicker c'tor.
So use a file scoped constant instead of creating a new History()
object each time MovePicker c'tor is called as in move_ambiguity()
This optimizes pretty_pv() through the following calling chain:
pretty_pv() -> line_to_san() -> move_to_san() -> move_ambiguity()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This also allow us to better track what is already
optimized and what still needs optimization.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
King evaluation is special in any case and as an added
benefit we can use the HasPopCnt optimization also for king.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is an old patch, was part of a series, but is
good also alone as a cleanup.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also move NodesSincePoll away from the same cache line
of other heavy read accessed only variables.
Fortunatly we don't have anymore write access contention,
but still read access contention in some cases.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They are always true anyway and are heavy used file scope
variables where there could be SMP contention. Although read only.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This reduces contention and reduce history trashing
effect especially at high search depths.
No functional change for single CPU case.
After 999 games at 1+0 on Dual Core Intel we have
Mod vs Orig +233 =526 -240 -2 ELO
We need to test at longer time controls and possibly with
a QUAD where we could foreseen an improvment.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is a first step for future patches and in
any case seems a nice thing to do.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In Position we store a pointer to a StateInfo record
kept outside of the Position object.
When copying a position we copy also that pointer so
after the copy we have two Position objects pointing
to the same StateInfo record. This can be dangerous
so fix by copying also the StateInfo record inside
the new Position object and let the new st pointer
point to it. This completely detach the copied
Position from the original one.
Also rename setStartState() as saveState() and clean up
the API to state more clearly what the function does.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Do not penalize if in our adavncing pawn's path there are
non-pawns enemy pieces. Especially if they can be attacked
by us.
Patch is mine, but original idea and also fixing of a first, wrong,
version of the patch is from Eelco de Groot.
Tests with Joona framework seems to confirm patch is good
Results for patch 'disabled' based on 5776 games: Win percentage:
41.309 (+- 0.526) [+- 1.053]
Results for patch 'enabled' based on 6400 games: Win percentage:
42.422 (+- 0.500) [+- 1.000]
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Tests on Joona luxury iCore7 QUAD show that speed increase
against standrd 64bit routine is between 3% and 4%.
So it seems a good thing to have. Also the user feedback at
startup regarding the compile and the hardware detection can
be an useful debug tool.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In MovePicker consider killer moves as a separate
phase from non-capture picking.
Note that this change guarantees that killer1 is always
tried before killer2. Until now, because scoring difference
of the two moves was just 1 point, if psqt tables of killer1
gave a lower value then killer2, the latter was tried as first.
After 999 games at 1+0 we have
Mod vs Orig: +245 =527 -227 +6 ELO
Not a lot but patch is anyhow something worth to have.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It shows almost no improvment and adds a good
bunch of complexity.
So remove for now. No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We don't need different names between a function and a
template. Compiler will know when use one or the other.
This let use restore original count_1s_xx() names instead of
sw_count_1s_xxx so to simplify a bit the code.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
With this patch at the applications startup a line is printed
with info about use of optimized 64 bit routines and hardware
POPCNT.
Also allow the possibility to disable POPCNT support during
PGO compiles to exercise the fallback software only path.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Runtime detect POPCNT instruction support and
use it.
Also if POPCNT is not supported we don't add _any_ overhead so
that we don't lose any speed in standard case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Unfortunatly, due to Chess960 compatibility we cannot
extend also to castling where the destinations squares
are not guaranteed to be empty.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid a clear_bit() + set_bit() sequence but update bitboards
with only one xor instructions.
This is faster and simplifies the code.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This gives more weight to newer entries.
After 999 games at 1'+ 0" we have:
Mod vs Orig +233/-208/=558 51.25% +9 ELO
Confirmed by another session of 437 games:
Mod vs Orig +109/-92/=236 51.95% +14 ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use the plain array lookup in the only place where it
is used. This remove an unecessary indirection and better
clarifies what code does.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the same change we have already done in search.cpp,
this time for evaluation.cpp
If a variable will be populated reading an UCI option
then do not hard code its default values.
This avoids misleadings when reading the sources.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This should reduce concurrent accessing in SMP case.
Suggestion by Tord Romstad.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Both with added comment and changing the API to
reflect that only destination square and moved piece
is important for history.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Aspiration window search must be disabled for
multi-pv case.
We missed one point where aspiration window should
be disabled in this case.
Patch from Joona, with a little added edit by me.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a better condition to find candidate direct check pawns.
In particular consider only pawns in the front ranks of the
enemy king, this greatly reduces pawns candidates bitboard
that now is empty more then 90% of the time so that we
can early skip further tests.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Be more strict, is not enough dc bitboard is not empty, but
needs to inclde also at least one pawn.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We can parametrize for the capture direction too.
Also use a single template parameter and calculate (at
compile time) remainin parameters directly in the function.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Centralize in a single object all the global resources
management and avoid a bunch of sparse exit() calls.
This is more reliable and clean and more stick to C++ coding
practices.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move closing of file in Book destructor. This
guarantees us against leaving the file open under
any case and simplifies also Book use.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Let Book be derived directly from std::ifstream
and rewrite the functions accordingly.
Also simplify file reading by use of operator>>()
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In case we have a correct white pawn move but pawn
is black (or the contrary) we fail to detect the
move as illegal.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use pieces_of_type() instead of pieces_of_color_and_type()
in an hot loop and cut of almost 10% SEE execution time.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of a position because the key is all that we
need.
Interface is more clear and also very very little bit faster.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It breaks also Glaurung 2 book parsing.
We really need to work on book.cpp, but for now just
leave compatibility just for Glaurung 2 books.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We currently fail on an option with a sapece in the name,
as example
setoption name Clear Hash
returns error message "Option Clear not found". This
patch fixes this off-by-one type bug.
Thanks to Joona for spotting this.
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>
We don't want to return unproven null move fails high, so
that if a position is so good that null move fails high we
want to check this with real do_move() / undo_move() test,
not just razoring the position because, from the opponent
point of view, is very bad.
These are tests results at 1+0
Mod vs Orig +252 -264 =483 49.40%
Mod vs Toga II 1.4.1SE +365 -325 =309 52.00%
So it seems a very slightly regression regarding orig version (but
withing error bar) and a nice increase against Toga that is what we
are interested most. Orig version scores 49.75% against Toga, so
we welcome this change ;-)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is bogusly assigned from moves[i].move instead of mlist[i].move
or equivalently to moves[count].move that it seem more clear to me.
Bug is hidden while all the moves are included, in this default case
moves[i].move and mlist[i].move are the same variable.
Also a bit of cleanup while there.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After proof testing on 3 different engines these
are the results:
Stockfish - Toga II 1.4.1SE +130 -132 =132 49.75%
Stockfish - Deep Sieng 3.0 +145 -110 =150 54.45%
Stockfish - HIARCS 12 MP +94 -149 =150 43.00%
So it seems no regressions occurs, although also no
improvment. But anyhow this patch increases Stockfish
strenght against itself, so merge it.
Note that this patch not only adds back razoring at depth
one, but also increases razor depth limit from 3 to 4
because hard coded depth 4 limit is no more overwritten
by UCI parameter that otherwise defaults to 3.
Because futility margins array has a fixed size we cannot
arbitrarly choose or change the SelectiveDepth parameter,
otherwise we have a crash for values bigger then array size.
On the other hand tweaking of this parameter requires some
modification to the hardcoded margins, so makes sense to hard
code also this very bounded one.
Who wants to experiment is of course free to change the sources.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is a very hot path function, profiling on Intel compiler
shows that inlining cuts in half the overhead.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Move the only function gettimeofday in misc.cpp
where is used.
This avoids polluting the global namespace.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Max hash size is 4096 MB, not 1024 MB, see the corresponding
"Hash" UCI parameter in ucioption.cpp
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently futility is allowed when depth < SelectiveDepth
and SelectiveDepth is 7*OnePly, so the comprison is
always true.
Patch could introduce a functional change only if
we choose to increase SelectiveDepth.
Currently no functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When testing at 1'+0" time control results are still
reasonably good. We have made two sessions on two
different PC.
After 840 games Mod - Orig: +221 -194 =425 +10 ELO (two CPU)
After 935 games Mod - Orig: +246 -222 =467 +9 ELO (single CPU)
So it seems that with fast CPU and/or longer time controls
benefits of the patch are a bit reduced. This could be due
to the fact that only 3% of nodes are pruned by razoring at
depth one and these nodes are very swallow ones, mostly get
pruned anyway with only a slightly additional cost, even
without performing any do_move() call.
Another reason is that sometime (0,3%% of cases) a possible
good move is missed typically in positions when moving side
gives check, as example in the following one
3r2k1/pbpp1nbp/1p6/3P3q/6RP/1P4P1/P4Pb1/3Q2K1 w - -
The winning move Rxg7+ is missed.
Bottom line is that patch seems good for blitz times, perhaps
also for longer times. We should test against a third engine
(Toga ?) to have a final answer regarding this new setup.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Some time ago it was found by Marco Costalba that it's better
to disable razoring at depth one, because given the very low
evaluation of the node, futility pruning would already do
the job at very low cost and avoiding missing important moves.
Now enable razoring there again, but only when our quickly evaluated
material advantage is more than a rook. The idea is to try razoring
only when it's extremely likely that it will succeed.
Extreme lightning speed test show promising result:
Orig - Mod: +1285 =1495 -1348
This needs to be tested with longer time controls though.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Restructure RazorMargins and FutilityMargins arrays so that their
values can be more easily tuned.
Add RazorApprMargins array which replaces razorAtDepthOne concept,
because setting RazorApprMargin very high value at ply one is
same as not razoring there at all.
Comment out setting razoring and futility margins through uci to
avoid errors while tuning.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If a variable will be populated reading an UCI option
then do not hard code its default values.
This avoids misleadings when reading the sources.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of loop across all legal moves to find a mate
loop across possible check moves only.
This reduces more then 10 times the number of moves to
check for a possible mate.
Also rename generate_checks() in generate_non_capture_checks()
so to better clarify what the function does.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Avoid calculating piece attacks if there aren't
available check sqaures for the given piece.
About 15% of cases. Not a biggie but still something
especially in the middle game where king is well covered
inside his castle.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
And upon reentering the same position try it as first.
Normally qsearch moves order is already very good, first move
is the cut off in almost 90% of cases. With this patch, we get
a cut off on TT move of 98%.
Another good side effect is that we don't generate captures
and/or checks when we already have a TT move.
Unfortunatly we found a TT move only in 1% of cases. So real
impact of this patch is relatively low.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Restore old behaviour that after search is aborted we call insert_pv,
before breaking out from the iterative deepening loop.
Remove one useless FIXME and document other better.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Check all fail highs in assumed PV with greater care (fruit/Toga already does this).
Add a flag when aspiration search fails high at ply 1 to prevent search to
be terminated prematurely.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This reverts commit 55dd98f7c717b94a659931cd20e088334b1cf7a6.
Revert fallback-system for root_search
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
However also this patch is immediately reverted. For three reasons:
1) the case it affects is very rare (and then we are likely to lose anyway),
so we can well live without this.
2) Because the case is so rare it's hard to test this change properly.
3) To perform fallback search, we must reset so many global variables that this
patch is very likely both buggy and extremely bad style.
Consider including this again if we clean-up global variables one day...
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
However just after finished writing this patch I realized that this
is not the way to go. So this will be immediately reverted.
(Just save this here in git in case I change my mind later :) )
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Implement system where aspiration search window is calculated using
values from previous iterations.
And then some crazy experimental stuff: If search fails low at the root,
don't widen window, but continue and hope we will find a better move
with given window. If search fails high at the root, cut immediately,
add some more time and start new iteration.
Note: this patch is not complete implementation, but a first test
for this idea. There are many FIXMEs left around. Most importantly
how to deal with the situation when we don't have any move!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Sometimes C++ can be really bad!
In this case an hard coded c string selects Option c'tor
with int argument instead of the std::string one becuase
it is considered a better matching by the compiler.
Fix the bug changing the argument type from std::string to
const char* so to be a better match then the int one.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Store boolean values as "1" and "0" instead of "true" and "false"
and convert back to UCI protocol convention when needed.
This is simpler then the other way around.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Apart from the teoretical speed increase, the main reason
of this patch is a good amount of code cleanup.
Note that now UCI options are printed in alphabetical
order and not in insertion order as before. Next patch
will take care of restoring old behaviour.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In null move search do not jump directly in
qsearch() from depth(4*OnePly), but only
from depth(3*OnePly).
After 999 games at 1+0: +248 -224 =527 +8ELO
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It doesn't seem to work against Toga. After more then 400 games
we are at -13 ELO while, without it we are at + 5 ELO after 1000
games.
So revert for now to keep code simple.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
MSVC gives:
warning C4146: unary minus operator applied to unsigned type,
result still unsigned
When finds -b where b is an unsigned integer. So rewrite the two's
complement in a way to avoid the warning. Theoretically the new
version is slower, but in practice changes nothing.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Strangely enough it seems that optimization doesn't work.
After 760 games at 1+0: +155 -184 =421 -13 ELO
Probably the overhead, although small, for setting the flag
is not compensated by the saved evaluation call.
This could be due to the fact that after a TT value is stored,
if and when we hit the position again the stored TT value is
actually used as a cut-off so that we don't need to go on
with another search and evaluation is avoided in any case.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
If we want to store a value of type VALUE_TYPE_EVAL for
a given position and we found an already exsisting entry
for the same position then we skip.
We don't want to overwrite a more valuable score with a
lesser one. Note that also in case the exsisting entry is
of VALUE_TYPE_EVAL type the overwrite is unuseful because
we would store the same score again.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When the stored TT value equals the static value set a
proper flag so to not call evaluation() if we hit the
same position again but use the stored TT value instead.
This is another trick to avoid calling costly evaluation()
in qsearch.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix a bug in the way a move is stored and read in a TT entry.
We use a mask of 19 bits insteaad of 17 so that the last
two bits in the TT entry end up to be random data.
This bug will bite us when we will use these two until now
unused bits.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After testing it seems patch is bad:
After 999 games 1+0: +242 -271 =486 -10 ELO
So restore saving of TT at the end but using new Joona
idea of storing as VALUE_TYPE_UPPER/VALUE_TYPE_LOWER instead
of VALUE_TYPE_EXACT.
Some optimization is still possible but better test new ideas
one by one.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of just drop evaluation score after stand pat
logic save it in TT so to be reused if the same position
occurs again.
Note that we NEVER use the cached value apart to avoid an
evaluation call, in particulary we never return to caller
after a succesful tt hit.
To accomodate this a new value type VALUE_TYPE_EVAL has been
introduced so that ok_to_use_TT() always returns false.
With this patch we cut about 15% of total evaluation calls.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is now disabled by default due to bad results
against a pool of engines...more testing is needed tough.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is the only "correct" exact value we can store.
Otherwise there could be spurious failed high/low nodes.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Some changes to the zobrist keys, to make them identical
to those used by Glaurung 1.
The only purpose is to make it possible for both programs
to use the same opening book.
Merged from Glaurung current development snapshot.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is what prevented USE_32BIT_ATTACKS from working
on some architectures (like PowerPC).
Merged from Glaurung current development snapshot.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We implicitly considered the minimum depth stored in TT
to be Depth(0), but because we store values in TT also in
qsearch() where depth is < 0, we need to use a negative
number as minimum depth.
Bug spotted by Joona Kiiski.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
I have just made a new rule that no modification
that increases pruning is allowed if after 1000 games
ELO is not increased by at least 10 point (was +5 in this case)
Yes, I like this kind of nosense rules :-)
Previous setup didn't change anything
After 996 games 1+0: +267 -261 =468 +2 ELO
Now with this new setup we have
After 999 games 1+0: +277 -245 =477 +11 ELO
Seems reasonable...
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Reduce of two plies near the leafs and when we still
have enough depth to go so to limit horizon effects.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Try to save space and use the minimum size
possible.
In particular restore int16_t for values and int8_t
for halfOpenFiles.
Use int16_t for storm values insted of int and also
instead of original buggy and too small int8_t.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Note that some pawns and material info has been switched
to int from int8_t.
This is a waste of space but it is not clear if we have a
faster or slower code (or nothing changed), some test should be
needed.
Few warnings still are alive.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
These fields are defined as int8_t but values bigger
then 127 are stored there so that we silently overflow.
Fix bringing up all the fields to a sane int type. This
will increase memory usage, but apart from being safe, it is
not clear if code is slower or faster. Test is needed.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It does not seem to clearly improve things and
in any case is disabled by default, so retire for now.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Prune more moves after a null search because of
a lower beta limit then in main search.
In test positions reduces the searched nodes of 30% !!!!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It seems that these compilers do not like inline functions
that call a template when template definition is not in scope.
So move functions from header to in *.cpp file
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Quickly filter out some calls to sliders attacks
when we already know that will fail for sure.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Rewritten hidden_checkers() to avoid calling
sliders attacks functions but just a much
faster squares_between()
Also a good code semplification.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of copying all, copy only the fields that
are updated incrementally, not the ones that are
recalcuated form scratch anyway.
This reduces copy overhead of 30%.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is slower the previous uglier but faster code.
So completely restore old one for now :-(
Just leave in the rework of status backup/restore in do_move().
We will cherry pick bits of previous work once we are sure
we have fixed the performance regression.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Another optimization that let us remove another half
of find_hidden_checks(them, DcCandidates) calls.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This let us to calculate only pinners when we now that
dc candidates are not possible.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a more strict condition to check if we have captured
an opponent pinner or hidden checker.
With this patch the occurrence of checkerCaptured == true are
reduced of 50%.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In do_move() use previous pinned bitboards values to compute
the new one after the move. In particulary we end up with the
same bitboards in most cases. So detect these cases and just
keep the old values.
This should speedup a lot this slow computation in a very hot
path so that we can use this important info everywhere in the
code at very cheap cost.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
There was one occurence when the StateInfo variable went
out of scope before the corresponding Position object.
This yelds to a crash. Bug was not hit before because occurs
only when using an UCI interface and not the usual benchmark.
The fix consists in copying internally the content of the
about to stale StateInfo.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Remove pinned pieces from attacks when calculating
SEE value.
Algorithm is not perfect, there should be no false
positives, but can happen that we miss to remove a
pinned piece. Currently we don't cach 100% of cases,
but is a tradeoff between speed and accuracy. In any
case we stay on the safe side, so we remove an attacker
when we are sure it is pinned.
About only 0,5% of cases are affected by this patch, not
a lot given the hard work: this is a difficult patch!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of copy the old state in the new one, copy only
fields that will be updated incrementally, not the ones
that will be recalculcated anyway.
This let us copy 13 bytes instead of 28 for each do_move()
call.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Probably is slightly slow, but code is surely better
in this way. We will optimize later for speed.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We don't backup anymore but use the renamed StateInfo
argument passed in do_move() to store the new position
state when doing a move.
Backup is now just revert to previous StateInfo that we know
because we store a pointer to it.
Note that now backing store is up to the caller, Position is
stateless in that regard, state is accessed through a pointer.
This patch will let us remove all the backup/restore copying,
just a pointer switch is now necessary.
Note that do_null_move() still uses StateInfo as backup.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We store it now in the same UndoInfo struct as 'previous'
field, so when doing a move we also know where to get
the previous info when undoing the back the move.
This is needed for future patches and is a nice cleanup anyway.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also templetize compute_value() can be simpler now that
the above is templetized too.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This nice union trick let us optimize the speed and
remove the now unuseful backup() and restore() functions.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After have been calculated cache their values
so to avoid another expensive call to hidden_checks()
if pinned_pieces() or discovered_check_candidates() are
called with the same position.
Add also interface to get pinners bitboard, we already have
this value so save it instead of discard.
Now that, after the first call to pinned_pieces() the following
are very cheap we can rewrite and cleanup all the checking handling.
So this patch is a prerequisite for future work.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
They hide the underlying uniform function call with
no benefit.
A little bit more verbose but now is clear what happens.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Pass value as an argument instead or recalculating it.
Altough call is cheap this is a very hot path so with
this patch total time spent for move_is_capture() is almost
halved.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Currently fails if we test with a move that is not of
from the side to move but from the opponent.
This is the typical case of the threat from null move
search. The result is an erroneus prune of the defending
moves, see PruneDefendingMoves in ok_to_prune()
Fix the test to work also with threat moves.
Bug was always in but was unhidden by a patch of 17/12/2008
"Trigger of PawnEndgameExtension if capture is not a pawn"
Until then it was hidden by a tricky check in the prune
conditions instead of the natural move_is_capture()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use Position::compute_material_key() to do the job,
so we are sure there is not key mismatch during
endgame function lookups.
This fixes two endgames hash errors that caused two
endgames to be disabled.
This patch is also a code cleanup because removes a lot
of messy key assignments.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Also integrate scaling and evaluation in a
single base class.
Nice use of templates here :-)
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In generate_piece_moves() to be more uniform with other
functions. Unfortunatly the different number of calling arguments
do not allow us to easily integrate in generate_piece_moves()
template family.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Small code tidy up and a little optimization
to avoid calling generate_piece_blocking_evasions()
when blockSquares is empty (30% of cases).
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Now that we have removed sliders checkers attacks
from evasion's set we can simplyfy legality check.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Rewrite as in generate_piece_moves() using a for
loop instead of the slower serializing of the
bitboard with pop_1st_bit()
This will allow also to merge with generate_piece_moves()
when we will drop legality constrain on generate_evasions()
Generated moves are not changed, but are generated in a
different order, this changes the number of nodes at fixed
depth test.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Discovery check candidates are normally empty, so
avoid discovery checks generation in that common case.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Find squares attacked by slider checkers, we will
remove them from king evasions set so to avoid a couple
of cycles in the slow king evasions legality check loop.
Not a biggie, but now generate_evasions() is faster then
generate_non_captures(), before was slower.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When we generate checks one case is missing: generation
of castling moves that give check to the opponent king.
This is a very rare case but anyway it is a case
and we can do this without slowing down the common
case of no castling checks.
So this is the patch.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Go back to original direct assignment, this allows to
add an include in pawns.h to teach about memset()
This fix a compile error under Ubuntu.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
For queen mobility could be bigger then 15, so
we need count_1s() not count_1s_max_15().
This bug was introduced by patch:
"Group common evaluate code" of 24/9/2008
So it's almost 4 months and two release old!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Do not consider squares protected by enemy pawns
in mobility evaluation.
This reduces the mobility value by about 15%
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This is somewhat taken from Stockfish 1.2 Default,
only the razoring thresold are updated, not the
razoring depth.
At the end razoring is a bit more aggressive. Results
seems slightly positive.
After 999 games +239 =536 -224 Elo +5
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Optimistic razoring settings. It is stronger with
most engines but weaker with someones.
The default is instead more solid and uniform with all
the opponents.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Add also the possibility to razor at ply one.
It is disable dby default but it seems stronger
against Stockfish itself. It is still not clear if
is stronger against other engines. By now leave
disabled.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Less prune at the bottom and at the middle, a bit more
at the top.
After 747 games: +215 =345 -187 +13 elo
Also introduced a vector of margins, now that start to be a lot
it is a more flexible solution.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Because razoring verification after qsearch() cuts more
then 40% of candidates, do not waste a costly qsearch for
nodes at depth one that will be probably discarded anyway
by futility.
Also tight razoring conditions to keep dangerous false
negatives below 0,05%. Still not clear if it is enough.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Bug fix merged from Glaurung 2.2 for search_pv()
Added the same fix also to sp_search_pv() where
was missing.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Is a new evaluation rule that gives bonus in midgame
to the side that has more space behind pawns for its
minor pieces.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a margin to compare with beta so that positions
that after the verifying qsearch have gained a lot of points
are not discarded just becasue not above beta.
Also remove the second condition on depth <= OnePly, it
was too risky and added only a 2% more of pruned nodes.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Fix the logic in search_pv and sp_search_pv
An additional issue to consider is that a castle move
is not a capture but destination square is not empty.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of number of searched nodes use the number of
opponent beta-cutoff occurred under the move subtree.
After 570 games 1+0 we have: +150 =288 -132 (+11 ELO)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Catched counting the nodes searched at
fixed depth. A quick and reliable cross check,
expecially in inflate only patches.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
In this case firstlocates the least valuable attacker, if any,
then proceed as usual.
This will be used by next patch.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
When a null move fails low due to a capture, try
to detect if without the capture we are above beta,
in this case there is a good possibility this is
a cut-node and the capture is just a null move
artifact due to side to move change. So if we still
don't have a TT move it's a good time to start an IID.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It happens that more then 70% of cases are HxL, where
we call see() anyway. The mesured saving of calling
see is about 0,5% of total time, but considering the
added burden in score_captures() the saving is only
0,35% locally and due to more difficult inlining of
the function it ends up that we have no advantage at all,
possibly a small slow down!
So revert.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Null move can fail low because of a capture artifact due
to the side to move change. Try to detect this condition
and fail high instead.
This pruning is very powerful, around 7% of nodes, but is
still experimental so is disabled by default.
Set UseNullCapturePruning to true to enable.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Actually square 0 can be dirty, so that move_is_capture(0)
can return any random values.
Add an assert to be sure it is caught.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Use a state machine to parse the input. Fixed
the many broken cases.
Tested on more then 15 milions nodes.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Strength increase was due to an hidden bug introduced
by the patch, namely the time per move to /30 instead
of /40 (see previous patch).
After testing this feature do not add any substantial
increase so is removed.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
After deep test (1000 games) it seems do not improve anything,
actually seems slightly weaker.
So remove it for now.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Make a copy of the position when needed instead
of passing as a reference. It is cleaner and
let us to simplify also Position::print()
A small space inflate while there.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Default argument should be in declaration where it
is visible through header include, not in definition.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Does not seem to improve anything.
Anyhow idea is nice, maybe we still have to find
correct recipe.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Cleanup and document.
The real functional change is that not mate threat
moves are never pruned, as could happen before.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
We can have depth(0) also in problematic cases
according to how extensions are tweaked by the user.
In any case we don't want to prune these moves.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
EvalInfo has missing attack info when a specialized
endgame function is used.
We missed this case and were using an empty attack bitboard
instead so that no captures were generated for endgames.
After testing the EvalInfo optimization gave worst results,
so after a (long) debug session this nasty bug was found.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Add infrastructure to threat killer moves as a vector,
this will allow us to easily parametrize the number of
killer moves, instead of hardcode this value to two as is now.
This patch just add the infrastructure, no functional
change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Teach Position::print() to optionally print a
given move in san notation in addition to
the ASCII representation of the board.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Instead of pospone until picking. No functional
change and probably no performance change but it is
needed for following patch.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
It is erroneusly considered a capture because king
moves on the same square of the rook.
Use the correct function Position::move_is_capture()
instead of the open coded (and buggy) one.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Make the logic work as advertised in the function
description.
Still a fallback from TT cleanup.
This should be less serious then the one in retrieve(),
but it's still a bug.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Killers should not be captures, but checks are not
and are produced also in qsearch.
Use this information, will be useful for move ordering.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Is set during the last iteration.
Sometime also during the second last.
During the last iteration is set in the 95% of cases.
During the second last is set in the 40% of cases.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.