Remove the distinction between the king file and the two neighbours
files in the ShelterStrength[] array. Instead we initialize the safety
variable in the evaluate_shelter() function with a -10 penalty if our
king is on a semi-open file (ie. if our king is on a file without a pawn
protection).
Also rename shelter_storm() to evaluate_shelter() while there.
See the commit history in PR#1559 for the proof that the committed
version is equivalent to the version in the tests above:
https://github.com/official-stockfish/Stockfish/pull/1559
Full credit to @protonspring for the renormalized values of the
ShelterStrength[] array used for the simplification. Thanks!
Change the operators of the Option type in uci.h to accept floating
point numbers in double precision on input as the numerical type for
the "spin" values of the UCI protocol.
The output of Stockfish after the "uci" command is unaffected.
This change is compatible with all the existing GUI (as they will
continue sending integers that we can interpret as doubles in SF),
and allows us to pass double parameters to Stockfish in the console
via the "setoption" command. This will be useful if we implement
another tuner as an alternative for SPSA.
A example of the new functionality in action in the branch `tune_float2'`:
https://github.com/snicolet/Stockfish/commit/876c322d0f20ee232da977b4d3489c4cc929765e
I have added the following lines in ucioptions.cpp:
```C++
void on_pi(const Option& o)
{
double x = Options["PI"]; // or double x = o;
std::cerr << "received value is x = " << x << std::endl;
}
By adding a direction (based on the template color), this is reduced to two
operations. This works because b is limited to enemy pawns that are ahead of
the king and on the current file.
```
shift<Down>(b) & ksq
```
I've added a line of code, but the number of executing instructions is reduced
(I think). I'm not sure if this counts as a simplification, but it should
theoretically be a little faster (barely). The code line length is also reduced
making it a little easier to read.
This patch corrects both MultiPV behaviour and "go searchmoves" behaviour
for tablebases.
We change the logic of table base probing at root positions from filtering
to ranking. The ranking code is much more straightforward than the current
filtering code (this is a simplification), and also more versatile.
If the root is a TB position, each root move is probed and assigned a TB score
and a TB rank. The TB score is the Value to be displayed to the user for that
move (unless the search finds a mate score), while the TB rank determines which
moves should appear higher in a multi-pv search. In game play, the engine will
always pick a move with the highest rank.
Ranks run from -1000 to +1000:
901 to 1000 : TB win
900 : normally a TB win, in rare cases this could be a draw
1 to 899 : cursed TB wins
0 : draw
-1 to -899 : blessed TB losses
-900 : normally a TB loss, in rare cases this could be a draw
-901 to -1000 : TB loss
Normally all winning moves get rank 1000 (to let the search pick the best
among them). The exception is if there has been a first repetition. In that
case, moves are ranked strictly by DTZ so that the engine will play a move
that lowers DTZ (and therefore cannot repeat the position a second time).
Losing moves get rank -1000 unless they have relatively high DTZ, meaning
they have some drawing chances. Those get ranks towards -901 (when they
cross -900 the draw is certain).
This patch introduces an Analysis Contempt UCI combo box to control
the behaviour of contempt during analysis. The possible values are
Both, Off, White, Black. Technically, the engine is supposed to be in
analysis mode if UCI_AnalyseMode is set by the graphical user interface
or if the user has chosen infinite analysis mode ("go infinite").
Credits: the idea for the combo box is due to Michel Van den Bergh.
The so-called "contempt" is an optimism value that the engine adds
to one color to avoid simplifications and keep tension in the position
during its search. It was introduced in Stockfish 9 and seemed to give
good results during the TCEC 11 tournament (Stockfish seemed to play a
little bit more actively than in previous seasons).
The patch does not change the play during match or blitz play, but gives
more options for correspondance players to decide for which color(s) they
would like to use contempt in analysis mode (infinite time). Here is a
description of the various options:
* Both : in analysis mode, use the contempt for both players (alternating)
* Off : in analysis mode, use the contempt for none of the players
* White : in analysis mode, White will play actively, Black will play passively
* Black : in analysis mode, Black will play actively, White will play passively
This corrects a bug in Tablebases::probe_dtz() which sometimes causes
a higher DTZ value to be returned for the position one ply before mate
than for the position two plies before mate.
The problem was reported by Kolja Kühn here:
http://talkchess.com/forum/viewtopic.php?p=757497#757497
It is explained here:
http://talkchess.com/forum/viewtopic.php?p=757506#757506
I have also adjusted some comments to make clear that probe_dtz()
returns -1 for a mate position.
Marco Costalba [Thu, 12 Apr 2018 07:22:40 +0000 (09:22 +0200)]
Further documentation and coding style on TB code
This patch adds some documentation and code cleanup to tablebase code.
It took me some time to understand the relation among the differrent
structs, although I have rewrote them fully in the past. So I wrote
some detailed documentation to avoid the same efforts for future readers.
Also noteworthy is the use a standard hash table implementation with a
more efficient 1D array instead of a 2D array. This reduces the average
lookup steps of 90% (from 343 to 38 in a bench 128 1 16 run) and reduces
also the table from 5K to 4K
entries.
I have tested on 5-men and no functional and no slowdown reported. It
should be verified on 6-men that the new hash does not overflow. It is
enough to run ./stockfish with 6-men available: if it does not assert at
startup it means everything is ok with 6-men too.
EDIT: verified for 6-men tablebase by Jörg Oster. Thanks!
We remove an unnecessary condition in the definition of safe squares
in the space evaluation. Only the squares which are occupied by our
pawns or attacked by our opponent's pawns are now excluded.
Mark Tenzer [Fri, 6 Apr 2018 23:20:48 +0000 (01:20 +0200)]
Introduce Overload
This patch applies a S(10, 5) bonus for every square that is:
- Occupied by an enemy piece which is not a pawn
- Attacked exactly once by our pieces
- Defended exactly once by enemy pieces
The idea is that these pieces must be defended. Their defenders have
dramatically limited mobility, and they are vulnerable to our future
attack.
As with connectivity, there are probably many more tests to be run in
this area. In particular:
- I believe @snicolet's queen overload tests have demonstrated a potential
need for a queen overload bonus above and beyond this one; however, the
conditions for "overload" in this patch are different (excluding pieces
we attack twice). My next test after this is (hopefully) merged will be
to intersect the Bitboard I define here with the enemy's queen attacks and
attempt to give additional bonus.
- Perhaps we should exclude pieces attacked by pawns--can pawns really be
overloaded? Should they have the same weight, or less? This didn't work
with a previous version, but it could work with this one.
- More generally, different pieces may need more or less bonus. We could
change bonuses based on what type of enemy piece is being overloaded, what
type of friendly piece is attacking, and/or what type of piece is being
defended by the overloaded piece and attacked by us, or any intersection
of these three. For example, here attacked/defended pawns are excluded,
but they're not totally worthless targets, and could be added again with
a smaller bonus.
- This list is by no means exhaustive.
This is my first time opening a PR, so I apologize if there are errors.
There are too many people to thank since I submitted my first test just
over a month ago. Thank you all for the warm welcome and here is to more
green patches!
In particular, I would like to thank:
- @crossbr, whose comment in a FishCooking thread first inspired me to
consider the overloading of pieces other than queens,
- @snicolet, whose queen overload tests inspired this one and served as
the base of my first overload attempts,
- @protonspring, whose connectivity tests inspired this one and who provided
much of the feedback needed to take this from red to green,
- @vondele, who kindly corrected me when I submitted a bad LTC test,
- @Rocky640, who has helped me over and over again in the past month.
Remove the Queen from the mobility area of minor pieces
In master, we already remove the King from the mobility area of minor pieces
because the King simply stands in the way of other pieces, and since opponent
cannot capture the King, any piece which "protects" the King cannot recapture.
Similarly, this patch introduces the idea that it is rarely a need for a Queen
to be "protected" by a minor (unless it is attacked only by a Queen, in fact).
We used to have a LoosePiece bonus, and in a similar vein the Queen was excluded
from that penalty.
Idea came when reviewing an old game of Kholmov. He was a very good midgame
player, but in the opening his misplace his Queen (and won in the end :-) :
http://www.chessgames.com/perl/chessgame?gid=1134645
Both white queen moves 10.Qd3 and 13.Qb3 are in the way of some minor piece.
I would prefer to not give a bishop mobility bonus at move 10 for the square d3,
or later a knight mobility bonus at move 13 for the square b3. And the textbook
move is 19.Qe3! which prepares 20.Nb3. This short game sample shows how much a
queen can be "in the way" of minor pieces.
Torsten Franz [Tue, 3 Apr 2018 21:33:55 +0000 (23:33 +0200)]
Simplify ThreatBySafePawn evaluation
Simplify ThreatBySafePawn evaluation by removing the 'if (weak)' speed
optimization check from threats evaluation. This is a non functional
change as it removes just a speed optimization conditional which was
probably useful before but does no longer provide benefits. This section
section had a few more lines not long ago, with ThreatByHangingPawn and
a loop through the threatened pieces, but now there is not much left.
In order to understand better the impact of various techniques used in search,
Elo estimates have been run at STC for 60000 games (statistical error ~1.8 Elo),
disabling each feature in turn. This should help future improvements and
simplifications to pick suitable targets.
Note that it will be a waste to recompute these estimates often, even a couple
of [0,5] patches are unlikely to change them by more than the error bars. The
interest of the Elo annotations in the code is not in the details, but in high-
lighting trends such as razoring (2 Elo) and singular extensions (60 Elo). These
estimates should be recomputed at most once a year.
When we reach a position with only two opposite colored bishops and
one pawn on the board, current master would give it a scale factor
of 9/64=0.14 in about one position out of 7200, and a scale factor
of 0.0 in the 7199 others. The patch gives a scale factor of 0.0 in
100% of the cases.
We also have exhaustive coverage analysis of this patch effect by
Alain Savard, comparing the perfect evaluation given by the Syzygy
tablebase with the heuristic play after this patch for the set of
all legal positions of the KBPKP endgame with opposite bishops, in
the comments thread for this pull request:
https://github.com/official-stockfish/Stockfish/pull/1520
Alain's conclusion:
> According to this definition and the data, I consider this PR is
> identical to master to "solve for draw" and slightly better than
> master to solve earlier for "wins".
Note: this patch is a side effect of an ongoing effort to improve
the evaluation of positions involving a pair of opposite bishops.
See the GitHub diff of this LTC test which almost passed at sprt[0..5]
for a discussion:
http://tests.stockfishchess.org/tests/view/5ab9030b0ebc5902932cbf93
Alain SAVARD [Thu, 29 Mar 2018 11:59:35 +0000 (07:59 -0400)]
Candidate Passed Pawn
Include some not fully supported levers in the (candidate) passed pawns
bitboard, if otherwise unblocked. Maybe levers are usually very short
lived, and some inaccuracy in the lever balance for the definition of
candidate passed pawns just triggers a deeper search.
Here is a example of a case where the patch has an effect on the definition
of candidate passers: White c5/e5 pawns, against Black d6 pawn. Let's say
we want to test if e5 is a candidate passer. The previous master looks
only at files d, e and f (which is already very good) and reject e5 as
a candidate. However, the lever d6 is challenged by 2 pawns, so it should
not fully count. Indirectly, this patch will view such case (and a few more)
to be scored as candidates.
This was inspired by this test of Jerry Donald Watson, except the case of
zero supporting pawns against two levers is excluded, and it seems that
not excluding that case is bad, while excluding is it beneficial. See the
following tests on fishtest:
> My thinking as to why this works:
>
> The evaluation is either called in an interior node or in the qsearch.
> The calls at the end of the qsearch are the more important as they
> ultimately determine the scoring of each move, whereas the internal
> values are mainly used for pruning decisions with a margin. Some strong
> engines don't even call the eval at all nodes. Now the whole point of
> the qsearch is to find quiet positions where captures do not change the
> evaluation of the position with regards to the search bounds - i.e. if
> there were good captures they would be tried.* So when a candidate lever
> appears in the evaluation at the end of the qsearch, the qsearch has
> guaranteed that it cannot just be captured, or if it can, this does not
> take the score past the search bounds. Practically this may mean that
> the side with the candidate lever has the turn, or perhaps the stopping
> lever pawn is pinned, or that side is forced for other reasons to make
> some other move (e.g. d6 can only take one of the pawns in the example
> above).
>
> Hence granting the full score for only one lever defender makes some
> sense, at least, to me.
>
> IMO this is also why huge bonuses for possible captures in the evaluation
> (e.g. threat on queen and our turn), etc. don't tend to work. Such things
> are best left to the search to figure out.
Ondrej Mosnáček [Fri, 30 Mar 2018 08:47:05 +0000 (10:47 +0200)]
Use per-thread dynamic contempt
We now use per-thread dynamic contempt. This patch has the following
effects:
* for Threads=1: **non-functional**
* for Threads>1:
* with MultiPV=1: **no regression, little to no ELO gain**
* with MultiPV>1: **clear improvement over master**
First, I tried testing at standard MultiPV=1 play with [0,5] bounds.
This yielded 2 yellow and 1 red test:
Finally, I ran some tests with fixed number of games, checking if
reverting dynamic contempt gains more elo with Skill Level=17 (i.e.
MultiPV) than applying the "prevScore" fix and this patch. These tests
showed, that this patch gains 15 ELO when playing with Skill Level=17:
**Why should this be commited?**
I believe that the gain for multi-thread MultiPV search is a sufficient
justification for this otherwise neutral change. I also believe this
implementation of dynamic contempt is more logical, although this may
be just my opinion.
**Why is per-thread contempt better at MultiPV?**
A likely explanation for the gain in MultiPV mode is that during
search each thread independently switches between rootMoves and via
the shared contempt score skews each other's evaluation.
**Why were the tests done with Skill Level=17?**
This was originally suggested by @Hanamuke and the idea is that with
Skill Level Stockfish sometimes plays also moves it thinks are slightly
sub-optimal and thus the quality of all moves offered by the MultiPV
search is checked by the test.
**Why are the ELO differences so huge?**
This is most likely because of the nature of Skill Level mode --
since it slower and weaker than normal mode, bugs in evaluation have
much greater effect.
Extends valgrind/sanitizer testing to cover syzygy code.
The script downloads 4 man syzygy as needed. The time needed for the
additional testing is small (in fact hard to see a difference compared
to the large fluctuations in testing time in travis).
Possible follow-ups:
* include more TB sensitive positions in bench.
* include the test script of recent commit "Refactor tbprobe.cpp".
* verify unchanged bench with TB (with a long run).
* make the TB part of the continuation integration tests optional.
Closes https://github.com/official-stockfish/Stockfish/pull/1518
and https://github.com/official-stockfish/Stockfish/pull/1490
Adjust criterion for applying extra reduction if not improving.
We now add an extra ply of reduction if r > 1.0, instead of the
previous condition Reductions[NonPV][imp][d][mc] >= 2.
Why does this work? Previously, reductions when not improving had
a discontinuity as the depth and/or move count increases due to the
Reductions[NonPV][imp][d][mc] >= 2 condition. Hence, values of r
such that 0.5 < r < 1.5 would be mapped to a reduction of 1, while
1.5 < r < 2.5 would be mapped to a reduction of 3. This patch allows
values of r satisfying 1.0 < r < 1.5 to be mapped to a reduction of 2,
making the reduction formula more continuous.
protonspring [Tue, 27 Mar 2018 15:29:56 +0000 (17:29 +0200)]
Simplification: remove pawn shelter/storm masks
Encode the pawn shelter/storm masks into the danger score
This highly specialized rule directly contradicts the VERY high
danger score for blocked pawns. Reducing the danger score for
blocked pawns and removing this rule is apparently an effective
compromise.
Ondrej Mosnáček [Wed, 14 Mar 2018 15:47:45 +0000 (16:47 +0100)]
Fix dynamic contempt for MultiPV
Use rootMoves[PVIdx].previousScore instead of bestValue for
dynamic contempt. This is equivalent for MultiPV=1 (bench remained the
same, even for higher depths), but more correct for MultiPV.
Note: although the ELO differences seem huge, they are inflated by the
nature of Skill Level / MultiPV search, so I don't think they can be
reasonably compared with classic ELO strength.
See https://github.com/official-stockfish/Stockfish/pull/1491 for some
verifications searches with MultiPV = 10 at depths 12 and 24 from the
starting position and the position after 1.e4, comparing the outputs
of the full PV by the old master and by this patch.
Ondrej Mosnáček [Sat, 10 Mar 2018 13:37:42 +0000 (14:37 +0100)]
Refactor tbprobe.cpp
This involves:
* replacing the union hacks with simply reusing the EntryPiece arrays
for the no-pawns case
* merging the PairsData structure with the EntryPiece/-Pawn structs
(with credit to Marco: @mcostalba)
* simplifying some HashTable functions
* thanks to previous changes, removing the ugly memsets
* simplifying the template logic for WDL/DTZ distinction
(now we distinguish based on an enum type, not the entry classes)
* removing the unneeded Atomic wrapper
-----------------------------
For reference, here is a manual way to check that patches concerning
table bases code are non-functional changes:
0) Download the Syzygy table bases (up to 6 men).
1) Make sure you have branches master and the pull request pointing to
the right commits.
2) Download the bench calculation scripts from the following URL:
and copy into src inside your Stockfish repo.
3) Make the scripts executable (chmod +x *.sh).
4) Run the following command to use TBs located at <path>:
export SYZYGY_PATH='<path>'
5) After that, run this (it will take a long time, this is a deep bench):
We check at compile time that the TimePoint type is exactly 64 bits long for
the compiler (TimePoint is our alias in Stockfish for std::chrono::milliseconds
-- it is a signed integer type of at least 45 bits according to the C++ standard,
but will most probably be implemented as a 64 bits signed integer on modern
compilers), and we use this TimePoint type consistently across the code.
Bug report by user "fischerandom" on the TCEC chat (thanks), and the
patch includes code and suggestions by user "WOnder93" and Ronald de Man.
Make kingRing always eight squares, extending the bitboard to the
F file if the king is on the H file, and to the C file if the king
is on the A file. This may deal with cases where Stockfish (like
many other engines) would shift the king around on the back rank
like g1h1, not because there is some imminent threat, but because
it makes king safety look a little better just because the king ring
had a smaller area.
This patch probably makes it easier to tune the king safety evaluation,
because the new regularity of the king ring size will make the king
safety function more continuous.
Unifies a bit further the three refuation stages in the MovePicker
class. Also treat the skipping of TT move now always via select_move(),
as discussed in pull request #1454.
Ronald de Man [Sun, 18 Mar 2018 22:38:58 +0000 (23:38 +0100)]
Mark all compile-time constants as constexpr.
To more clearly distinguish them from "const" local variables, this patch
defines compile-time local constants as constexpr. This is consistent with
the definition of PvNode as constexpr in search() and qsearch(). It also
makes the code more robust, since the compiler will now check that those
constants are indeed compile-time constants.
We can go even one step further and define all the evaluation and search
compile-time constants as constexpr.
In generate_castling() I replaced "K" with "step", since K was incorrectly
capitalised (in the Chess960 case).
In timeman.cpp I had to make the non-local constants MaxRatio and StealRatio
constepxr, since otherwise gcc would complain when calculating TMaxRatio and
TStealRatio. (Strangely, I did not have to make Is64Bit constexpr even though
it is used in ucioption.cpp in the calculation of constexpr MaxHashMB.)
I have renamed PieceCount to pieceCount in material.h, since the values of
the array are not compile-time constants.
Some compile-time constants in tbprobe.cpp were overlooked. Sides and MaxFile
are not compile-time constants, so were renamed to sides and maxFile.
Implements renaming suggestions by Marco Costalba, Günther Demetz,
Gontran Lemaire, Ronald de Man, Stéphane Nicolet, Alain Savard,
Joost VandeVondele, Jerry Donald Watson, Mike Whiteley, xoto10,
and I hope that I haven't forgotten anybody.
Perpetual renaming thread for suggestions:
https://github.com/official-stockfish/Stockfish/issues/1426
This patch checks the clock every 1024, instead of 4096 in current master.
This is a step towards a solution to alleviate the problem reported by
Gian-Carlo Pascutto in pull request #1471, about a situation where SF
would sometimes lose on time in endgames at time control 1min+1sec when
using Syzygy EGTB on a spinning drive.
We made four tests called "Estimate the Elo cost of calling now() every
N nodes", with N in {256,1024} and time control in {STC,LTC}. Each test
was 40000 games with auto-purge off, against master branch.
lucasart [Sun, 11 Mar 2018 22:56:14 +0000 (06:56 +0800)]
Use intrinsics only for LSB/MSB
The NO_BSF does not cover any real life use-case today. The only compilers that
can compile SF today, with the current Makefile and no source code changes, are
either GCC compatible (define __GNUC__) or MSVC compatible (define _MSC_VER). So
they all support LSB/MSB intrinsics.
This patch simplifies away the software fall-backs of LSB/MSB that were still
in Stockfish code, but unused in any of the officially supported compilers.
Note the (legacy) MSVC/WIN32 case, where we use a 32-bit BSF/BSR solution, as
64-bit intrinsics aren't available there.
Adjust ProbCut rBeta by whether the score is improving, and also
set improving to false when in check. More precisely, this patch
has two parts:
1) the increased beta threshold for ProbCut is now adjusted based
on whether the score is improving
2) when in check, improving is always set to false.
Co-authored by Joost VandeVondele (@vondele) and Bill Henry (@VoyagerOne).
King and pawn endgames are typically decisive, and a small
advantage is often sufficient to win. Therefore we now take
this into account when computing the initiative adjustment.
This idea came from a series of patches by Gian-Carlo Pascutto.
protonspring [Mon, 12 Mar 2018 01:47:35 +0000 (02:47 +0100)]
MovePicker: combine countermove with killers.
Handle the countermove in the same way we use stages to progress
through the killer moves, using a common array called "refutations".
Removes some lines of code and simplifies a bit the jump table.
protonspring [Sat, 10 Mar 2018 10:46:44 +0000 (11:46 +0100)]
Implement an old Russian proverb
"Loose pieces drop, in blitz keep everything protected"
Adding a small S(2,2) bonus for knights, bishops, rooks, and
queens that are "connected" to each other (in the sense that
they are under attack by our own pieces) apparently is a good
thing. It probably helps the pieces work together a bit better.
How to continue from there (by Stefan Geschwentner)?
• First we should identify all other eval terms which have an overlap
with new connectivity bonus (like the outpost bonus). A simple way
would be subtract the connectivity bonus from them and look if this
better, or use a SPSA session for these terms.
• Tuning Connectivity himself with SPSA seems not so promising because
of the small range which is useful. Here manual testing changes of
Connectivity like +-1 seems better.
• The eg value is more important because in endgame the position gets
more open and so attacks on pieces are easier. Another important point
is that when defending/fortress-like positions each defending piece
needs a protection, otherwise attacks on them can break defense.
Avoid duplicated code after recent commit "Use evaluation trend
to adjust futility margin". We initialize the improving variable
to true in the check case, which allows to avoid redundant code
in the general case.
Tested for speed by snicolet, patch seems about 0.4% faster.
No functional change.
Note: initializing the improving variable to false in the check
case was tested as a functional change, ending yellow in both STC
and LTC. This change is not included in the commit, but it is an
interesting result that could become part of a future patch about
improving or LMR. Reference of the LTC yellow test:
http://tests.stockfishchess.org/tests/view/5aa131560ebc590297cb636e
Alain SAVARD [Fri, 9 Mar 2018 01:04:33 +0000 (20:04 -0500)]
Two steps slider threats on queen
Allow a potential slider threat from a square currently occupied
by a harmless attacker, just as the recent "knight on queen" patch.
Also from not completely safe squares, use the mobilityArea instead
of excluding all pawns for both SlidersOnQueen and KnightOnQueen
We now compute the potential sliders threat on queen only if opponent
has one queen.
Run as SPRT [0,4] since it is some kind of simplification but maybe
not clearly one.
IIvec [Mon, 5 Mar 2018 21:24:26 +0000 (22:24 +0100)]
Simplification: use Arctan for the optimism S-curve
This was an idea of Gontran Lemaire (gonlem), but the graphs
he published did not seem accurate to me. I did my own graphs,
got my own constants and here is the result:
We give a S(21,11) bonus for knight threats on the next moves
against enemy queen. The threats are from squares which are
"not strongly protected" and which may be empty, contain enemy
pieces or even one of our piece at the moment (N,B,Q,R) -- hence
be two-steps threats in the later case because we will have to
move our piece and *then* attack the enemy queen with the knight.
Torsten Franz [Mon, 5 Mar 2018 13:10:13 +0000 (14:10 +0100)]
Remove popcount trick from space evaluation
Similar removal of superposition code trick as in the
"Simplify tropism computation" patch. This simplification
of the space() function will allow us to specify space
masks which can reach into enemy territory.
Add a logarithmic term in the optimism computation, increase
the maximal optimism and lower the contempt offset.
This increases the dynamics of the optimism aspects, giving
a boost for balanced positions without skewing too much on
unbalanced positions (but this version will enter panic mode
faster than previous master when behind, trying to draw faster
when slightly behind). This helps, since optimism is in general
a good thing, for instance at LTC, but too high optimism
rapidly contaminates play.
It must be mentioned that a version of the PR with contempt 0
did not pass STC [0,5]. The version in the patch, which uses
default contempt 12, was found to be as strong as current master
on different matches against SF7 and SF8, both at STC and LTC.
One drawback maybe is that it raises the draw rate in self-play
from 56% to 59%, giving a little bit less sensitivity for SF
developpers to find evaluation improvements by selfplay tests
in fishtest.
Possible further work:
• tune the values accurately, while keeping in mind the drawrate issue
• check whether it is possible to remove linear and offset term
• try to simplify the S-shape curve
Marco Costalba [Sat, 3 Mar 2018 10:29:29 +0000 (11:29 +0100)]
Merge Stats tables
Use a recursive std::array with variadic template
parameters to get rid of the last redundacy.
The first template T parameter is the base type of
the array, the W parameter is the weight applied to
the bonuses when we update values with the << operator,
the D parameter limits the range of updates (range is
[-W * D, W * D]), and the last parameters (Size and
Sizes) encode the dimensions of the array.
This allows greater flexibility because we can now tweak
the range [-W * D, W * D] for each table.
Patch removes more lines than what adds and streamlines
the Stats soup in movepick.h
The first depth 2 margin triggers the verification quiescence search.
This qsearch() result has to be better then the second lower margin,
so we only skip the razoring when the qsearch gives a significant
improvement.
Reformating the razoring code (step 7 in search()) to unify the
depth 1 and depth 2 treatements seems quite possible, this could
possibly lead to more simplifications.
In pawn structures like white pawns f6,h6 against black pawns f7,g6,h7
the attack on the king is blocked by the own pawns. So decrease the
penalty for king safety.
See diagram and discussion in
https://github.com/official-stockfish/Stockfish/pull/1434
A sample position that this patch wants to avoid is the following
1rr2bk1/3q1p1p/2n1bPpP/pp1pP3/2pP4/P1P1B3/1PBQN1P1/1K3R1R w - - 0 1
White pawn storm on the king side was a disaster, it locked the king
side completely. Therefore, all the king tropism bonus that white have
on the king side are useless, and kingadjacent attacks too. Master
gives White a static +4.5 advantage, but White cannot win that game.
The patch is lowering this evaluation artefact.
Leonid Pechenik [Wed, 28 Feb 2018 11:36:36 +0000 (12:36 +0100)]
Tweak time management
Using a SPSA tuning session to optimize the time management
parameters.
With SPSA tuning it is not always possible to say where improvements
came from. Maybe some variables changed randomly or because result
was not sensitive enough to them. So my explanation of changes will
not be necessarily correct, but here it is.
• When decrease of thinking time was added by Joost a few months ago
if best move has not changed for several plies, one more competing
indicator was introduced for the same purpose along with increase
in score and absence of fail low at root. It seems that tuning put
relatively more importance on that new indicator what allowed to save
time.
• Some of this saved time is distributed proportionally between all
moves and some more time were given to moves when score dropped a lot
or best move changed.
• It looks also that SPSA redistributed more time from the beginning to
later stages of game via other changes in variables - maybe because
contempt made game to last longer or for whatever reason.
All of this is just small tweaks here and there (a few percentages changes).
This is a functional patch only for time management, but the bench
does not reflect this because it uses fixed depth search, so the number
of nodes does not change during bench.
Simplification. Tests show that the "shift-and-superpose" trick is no longer
necessary. The speed benefit of avoiding a popcount is no longer relevant
on modern machines.
This is the sequel of the previous patch, we now let the parent node initialize
stat score to zero once for all grandchildren.
Initialize statScore to zero for the grandchildren of the current position.
So statScore is shared between all grandchildren and only the first grandchild
starts with statScore = 0. Later grandchildren start with the last calculated
statScore of the previous grandchild. This influences the reduction rules in
LMR which are based on the statScore of parent position.
Let the parent node initialize stat score to zero once for all siblings.
Initialize statScore to zero for the children of the current position.
So statScore is shared between sibling positions and only the first sibling
starts with statScore = 0. Later siblings start with the last calculated
statScore of the previous sibling. This influences the reduction rules in
in LMR which are based on the statScore of parent position.
No Tempo for draw scores given by heuristic functions
The current master applies Eval::Tempo even to leaves evaluated
as draw by some of the static evaluation functions of endgame.cpp
(for instance KNN vs K or stalemates in KP vs K). This results in
some lines being reported as +0.07 or -0.07 when the terminal
position has reached such endgames (0.07 being about the value
of a tempo for Stockfish).
This patch does not apply Eval::tempo to these positions. This leads
to more nodes being evaluated as VALUE_DRAW during search, giving more
opportunities for cut-offs in alpha-beta.
The previous asymmetry measure of the pawn structure only used to
consider the number of pawns on semi-opened files in the position.
With this patch we also increase the measure by the number of passed
pawns for both players.
Many thanks to the community for the nice feedback on the previous
version, with special mentions to Alain Savard and Marco Costalba
for clarity and speed suggestions.
Stockfish will now evaluate more positions with passed pawns, so
tuning the passed pawns values may bring Elo. The patch has also
consequences on the initiative term, where we might want to give
different weights to passed pawns and semi-openfiles (idea by
Stefano Cardanobile).
Similar to an earlier proposition of Günther Demetz, see pull request #1075.
I think it is more robust and readable than master, why hand-unroll the loop
over the killer array, and duplicate code ?
This version includes review comments from Marco Costalba.
The previous asymmetry measure of the pawn structure only used to
consider the number of pawns on semi-opened files in the postions.
With this patch we also increase the measure by the number of passed
pawns for both players.
How to continue from there: Stockfish will now evaluate more positions
with passed pawns, so tuning the passed pawns values may bring Elo.
The patch also has consequences on the initiative term.
DU-jdto [Sun, 25 Feb 2018 00:14:29 +0000 (01:14 +0100)]
More robust interaction of singular search and iid
When iid (Internal iterative deepening) is invoked, the prior value of ttValue is
not guaranteed to be VALUE_NONE. As such, it is currently possible to enter a state
in which ttValue has a specific value which is inconsistent with tte->bound() and
tte->depth(). Currently, ttValue is only used within the search in a context that
prevents this situation from making a difference (and so this change is non-functional,
but this is not guaranteed to remain the case in the future.
For instance, just changing the tt depth condition in singular extension node to be
tte->depth() >= depth - 4 * ONE_PLY
instead of
tte->depth() >= depth - 3 * ONE_PLY
interacts badly with the absence of ttMove in iid. For the ttMove to become a singular
extension candidate, singularExtensionNode needs to be true. With the current master,
this requires that tte->depth() >= depth - 3 * ONE_PLY. This is not currently possible
if tte comes from IID, since the depth 'd' used for the IID search is always less than
depth - 4 * ONE_PLY for depth >= 8 * ONE_PLY (below depth 8 singularExtensionNode can
never be true anyway). However, with DU-jdto/Stockfish@251281a , this condition can be
met, and it is possible for singularExtensionNode to become true after IID. There are
then two mechanisms by which this patch can affect the search:
• If ttValue was VALUE_NONE prior to IID, the fact that this patch sets ttValue allows
the 'ttValue != VALUE_NONE' condition of singularExtensionNode to be met.
• If ttValue wasn't VALUE_NONE prior to IID, the fact that this patch modifies ttValue's
value causes a different 'rBeta' to be calculated if the singular extension search is
performed.
Tested at STC for non-regression:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 76981 W: 17060 L: 17048 D: 42873
http://tests.stockfishchess.org/tests/view/5a7738b70ebc5902971a9868
DU-jdto [Sat, 24 Feb 2018 12:06:18 +0000 (13:06 +0100)]
Simplification: do razoring only for depth 1
The razoring heuristic is quite a drastic pruning technique,
using a depth 0 search at internal nodes of the search tree
to estimate the true value of depth n nodes. This patch limits
this razoring to the case of internal nodes of depth 1.
Author: Jarrod Torriero (DU-jdto)
Opportunities opened by this patch: it would be interesting to
know if it brings Elo to re-introduce razoring or soft razoring
at depth >= 2, maybe using a larger margin to compensate for the
increased pruning effect.
Mike Whiteley [Wed, 21 Feb 2018 20:46:25 +0000 (21:46 +0100)]
rename shift variables.
Where variable names are explicitly incorrect, I feel morally obligated to at least
suggest an alternative. There are many, but these two are especially egregious.
Mike Whiteley [Thu, 15 Feb 2018 18:34:23 +0000 (19:34 +0100)]
Simplify trapped rook
As far as can tell, semiopenFiles are set if there is a pawn anywhere on
the file. The removed condition would be true even if the pawns were very
advanced, which doesn't make sense if we're looking for a trapped rook.
Seems the engine fairs better with this removed. My guess s that the
condition that mobility is 3 or less does this well enough.
Begs the question whether this is a mobility issue alone... not sure.
Should I do LTC test?
Make contempt dependent on the current score of the root position.
The idea is that we now use a linear formula like the following to decide
on the contempt to use during a search :
contempt = x + y * eval
where x is the base contempt set by the user in the "Contempt" UCI option,
and y * eval is the dynamic part which adapts itself to the estimation of
the evaluation of the root position returned by the search. In this patch,
we use x = 18 centipawns by default, and the y * eval correction can go
from -20 centipawns if the root eval is less than -2.0 pawns, up to +20
centipawns when the root eval is more than 2.0 pawns.
To summarize, the new contempt goes from -0.02 to 0.38 pawns, depending if
Stockfish is losing or winning, with an average value of 0.18 pawns by default.
Finally, we checked that there is no apparent problem with multithreading,
despite the fact that some threads might have a slightly different contempt
level that the main thread.
Match of this version against master, both using 5 threads, time control 30+0.3:
ELO: 2.18 +-3.2 (95%) LOS: 90.8%
Total: 14840 W: 2502 L: 2409 D: 9929
http://tests.stockfishchess.org/tests/view/5a7bf3e80ebc5902971a9aa2
Include suggestions from Marco Costalba, Aram Tumanian, Ronald de Man, etc.
Leonid Pechenik [Tue, 6 Feb 2018 10:14:55 +0000 (05:14 -0500)]
Retire "Extra thinking before accepting draw PVs"
This patch simplifies the time management code, removing the extra
thinking time for moves with draw PV and increasing thinking time
for all moves proportionally by around 4%.
Last time when the time management was carefully tuned was 1.5-2 years
ago. As new patches were getting added, time management was drifting out
of optimum. This happens because when search becomes more precise pv and
score are becoming more stable, there are less fail lows, best move is
picked earlier and there are less best move changes. All this factors are
entering in time management, and average time per move is decreasing with
more and more good patches. For individual patches such effect is small
(except some) and may be up or down, but when there are many of them,
effect is more substantial. The same way benchmark with more and more
patches is slowly drifting down on average.
So my understanding that back in October adding more think time for draw
PV showed positive Elo because time management was not well tuned, there
was more time available, and think_hard patch applied this additional time
to moves with draw PV, while just retuning back to optimum would recover Elo
anyway. It is possible that absence of contempt also helped, as SF9 is showing
less 0.0 scores than the October version.
Anyway, to me it seems that proper place to deal with draw PV is search, and
contempt sounds as much better solution. In time management there is little
additional elo, and if some code is not helping like removed here, it is better
to discard it. It is simpler to find genuine improvement if code is clean.
• Passed an additional non-regression [-5..0] test at the time control
of 60sec for the game (sudden death) with disabled draw adjudication:
LLR: 2.95 (-2.94,2.94) [-5.00,0.00]
Total: 8438 W: 1675 L: 1586 D: 5177
http://tests.stockfishchess.org/tests/view/5a7c3d8d0ebc5902971a9ac0
• Passed an additional non-regression [-5..0] test at the time control
of 1sec+1sec per move with disabled draw adjudication:
LLR: 2.97 (-2.94,2.94) [-5.00,0.00]
Total: 27664 W: 5575 L: 5574 D: 16515
http://tests.stockfishchess.org/tests/view/5a7c3e820ebc5902971a9ac3
This is a functional change for the time management code.
The 'eval' debugging command in Terminal did not initialize the Eval::Contempt
variable, leading to random output during debugging sessions (normal search
was unaffected by the bug).
Example of session where the two 'eval' commands should give the same output,
but did not:
./stockfish
position startpos
d
eval
go depth 20
d
eval
The bug is fixed by initializing Eval::Contempt to SCORE_ZERO in Eval::trace
protonspring [Thu, 8 Feb 2018 09:45:45 +0000 (10:45 +0100)]
Obey skipQuiets strictly in MovePicker
The current logic in master is to continue return quiet moves if their
history score is above 0. It appears as though this check can be
removed, which is also more logically consistent with the “skipQuiets”
semantics used in search.cpp.
This patch may open new opportunitiesto get Elo by changing or
tuning the definition of 'moveCountPruning' in line 830 of search.cpp,
because obeying skipQuiets without checking the history scores makes
the search more sensitive to 'moveCountPruning'.