Compare commits

...

2323 Commits

Author SHA1 Message Date
Marco Costalba 54f8a9cb13 Stockfish 5
Stockfish bench signature is: 8732553
2014-05-31 09:16:54 +02:00
Marco Costalba ad937d0b2d Revert "Symmetric king safety"
Regression test of 40K games at 60 secs shows
this commit to be a 2-3 ELO regression.

So revert to original king safety.

bench: 8732553
2014-05-26 21:39:48 +02:00
Marco Costalba 495a0fa699 Fix a warning with Intel compiler
warning #2259: non-pointer conversion from
"int" to "int16_t={short}" may lose significant
bits.

No functional change.
2014-05-25 00:21:46 +02:00
Marco Costalba 585655b16e Tidy up tt.h
Backport some non-functional changes
found working on 'dense TT' patch.

No functional change.
2014-05-25 00:02:09 +02:00
Marco Costalba e49eb67119 Add perft 'divide' command
To show perft numbers for each move. Just
use 'divide' instead of 'perft', for instance:

position startpos moves e2e4 e7e5
divide 4

Inspired by Ronald de Man.

No functional change.
2014-05-24 09:56:32 +02:00
Marco Costalba 88b5100e29 Update polyglot.ini after last patch
No functional change.
2014-05-19 21:19:47 +02:00
Lucas Braesch 40f5abba10 Symmetric king safety
Retire current asymmetric king evaluation
and use a much simpler symmetric one.

As a side effect retire the infamous
'Aggressiveness' and 'Cowardice' UCI
options.

Tested in no-regression mode,

Passed both STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 33855 W: 5863 L: 5764 D: 22228

And LTC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 40571 W: 5852 L: 5760 D: 28959

bench: 8321835
2014-05-19 14:24:39 +02:00
Marco Costalba 5e03734eac Fix an off-by-one bug in extract_pv_from_tt
At root we start counting plies from 1,
instead pv[] array starts from 0. So
the variable 'ply' we use in extract_pv_from_tt
to index pv[] is misnamed, indeed it is
not the real ply, but ply-1.

The fix is to leave ply name in extract_pv_from_tt
but assign it the correct start value and
consequentely change all the references to pv[].
Instead in insert_pv_in_tt it's simpler to rename
the misnamed 'ply' in 'idx'.

The off-by-one bug was unhidden when trying to use
'ply' for what it should have been, for instance in
this position:

position fen 8/6R1/8/3k4/8/8/8/2K5 w - - 0 1

at depth 24 mate line is erroneusly truncated due
to value_from_tt() using the wrong ply.

Spotted by Ronald de Man.

bench: 8732553
2014-05-17 22:59:07 +02:00
Marco Costalba e46a72dd1d Extract a reliable PV line
Truncate the extracted PV from the point where
the score stored in hash starts to deviate from
the root score.

Idea from Ronald de Man.

bench: 8732553
2014-05-17 12:49:52 +02:00
Michel Van den Bergh 5ec63eb6b6 Drop to qsearch at low depth in razoring
If razoring conditions are satisfied and
depth is low, then directly drop in qsearch.

Passed both STC
LLR: 2.98 (-2.94,2.94) [-1.50,4.50]
Total: 12914 W: 2345 L: 2208 D: 8361

And LTC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 50600 W: 7548 L: 7230 D: 35822

bench: 8739659
2014-05-13 22:37:28 +02:00
Arjun Temurnikar a3c8c4b70d Remove undefended minors
Tested in "no regression" mode.

Passed both STC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 68026 W: 12277 L: 12236 D: 43513

And LTC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 85682 W: 12861 L: 12836 D: 59985

bench: 7311935
2014-05-13 21:37:42 +02:00
Marco Costalba 696d6cedb9 Save stalemates in TT
When there aren't legal moves after
a search, instead of returning imediately,
save bestValue in TT as in the usual case.

There is really no reason to special case
this one.

With this patch is fully fixed (again) follwing
position:

    7k/6p1/6B1/5K1P/8/8/8/8 w - - 0 1

Also in SMP case.

bench: 8802105
2014-05-11 10:56:25 +02:00
Marco Costalba 9f843adf89 Retire "Idle Threads Sleep" UCI option
After last Joona's patch there is no measurable
difference between the option set or unset.

Tested by Andreas Strangmüller with 16 threads
on his Dual Opteron 6376.

After 5000 games at 15+0.05 the result is:

1 Stockfish_14050822_T16_on   : 3003  5000 (+849,=3396,-755), 50.9 %
2 Stockfish_14050822_T16_off  : 2997  5000 (+755,=3396,-849), 49.1 %

bench: 880215
2014-05-11 10:29:56 +02:00
Arjun Temurnikar bfd8704a7d Make imbalance table more clear
No functional change.
2014-05-10 08:54:31 +02:00
Reuven Peleg f89a8f0769 Pass Position as const ref in update_stats()
No functional change.
2014-05-08 22:36:30 +02:00
Marco Costalba 6ba1d3ead6 Clarify some comments in SMP code
Spotted by Joona.

No functional change.
2014-05-08 09:09:35 +02:00
Marco Costalba 7e3dba4f4c Reformat and simplify previous patch
No functional change.
2014-05-07 08:56:16 +02:00
Joona Kiiski f6e98a924a Allow a slave to 'late join' another splitpoint
Instead of waiting to be allocated, actively search
for another split point to join when finishes its
search. Also modify split conditions.

This patch has been tested with 7 threads SMP and
passed both STC:

LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 2885 W: 519 L: 410 D: 1956

And a reduced-LTC at  25+0.05
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 4401 W: 684 L: 566 D: 3151

Was then retested against regression in 3 thread case
at standard LTC of  60+0.05:

LLR: 2.96 (-2.94,2.94) [-4.00,0.00]
Total: 40809 W: 5446 L: 5406 D: 29957

bench: 8802105
2014-05-07 08:38:56 +02:00
Ron Britvich 8f6a494ad7 Rewrite Score extractors
Less tricky and even a bit faster. With this
version Visual Studio Ultimate 2013 Update 2 RC
runs fine even in O2 optimization.

No functional change.
2014-05-05 09:05:29 +02:00
Marco Costalba b8e6f83cfb Change search() signature
Pass SpNode as template parameter.

No functional change.
2014-05-04 13:35:30 +02:00
Marco Costalba 5413fda739 Revert dynamic contempt
On a final fixed game number test it failed
to prove better than standard version.

STC 15+0.05

ELO: -0.86 +-1.7 (95%) LOS: 15.8%
Total: 57578 W: 10070 L: 10213 D: 37295

bench: 8802105
2014-05-04 09:58:49 +02:00
Marco Costalba 145d293142 Revert stalemate detection in evaluation
Unfortunatly we have a slow down that causes
a regression in STC with no-regression mode:

LLR: -2.96 (-2.94,2.94) [-3.00,1.00]
Total: 22454 W: 3836 L: 4029 D: 14589

bench: 8678654
2014-05-04 09:42:32 +02:00
Marco Costalba f1240483fb Revert back KBPsK to latest Gary's version
The bug was found to be elsewhere. This version
is correct and also is able to detect as draw
positions like:

8/8/5b2/8/8/4k1p1/6P1/5K2 b - - 6 133

bench: 8678654
2014-05-04 09:34:22 +02:00
Ronald de Man c0d3010438 Fix KXK endgame
Position is win also if strong side has a bishop
and a knight (plus other material, otherwise
KBNK would be triggered instead of KXK).

This fixes a subtle bug where a search on position

k7/8/8/8/8/P7/PB6/K7 b - - 6 1

Instead of returning a draw score, suddendly returns
a big score. This happens because at one point in
search we reach this position:

8/Pk6/8/8/8/4B3/P7/K7 w - - 3 8

Where white can promote. In case of rook promotion (and also in case of
queen promotion) the resutling position gets a huge static eval that is
above VALUE_KNOWN_WIN (from the point of view of white). So for rook
promotion it is

          &&  futilityBase > -VALUE_KNOWN_WIN

that prevents futility pruning in qsearch. (Removing this condition indeed
lets the problem occur). Raising the static eval for K+B+N+X v K to a value
higher than VALUE_KNOWN_WIN fixes this particular problem without having to
introduce an extra futility pruning condition in qsearch.

I just checked and it seems K+R v K, K+2B v K and even K+B+N v K already get
a huge static eval. Why not K+B+N+P v K?

I think this fix corrects an oversight. There is special code for KBNK, but
KBNXK is handled by KXK, so the test for sufficient material should also test
for B+N.

bench: 8678654
2014-05-03 21:40:09 +02:00
Marco Costalba a9e93fa6a5 Fully correct stealmate detection
In the (rare) cases when the two conditions
are true, then fully check again with a slow
but correct MoveList<LEGAL>(pos).size().

This is able to detect false positives like
this one:

8/8/8/Q7/5k1p/5P2/4KP2/8 b - - 0 17

When we have a possible simple pawn push that
is not stored in attacks[] array. Because the
third condition triggers very rarely, even if
it is slow, it does not alters in a measurable
way the average speed of the engine.

bench: 8678654
2014-05-03 12:12:22 +02:00
Marco Costalba 9e8bf82350 Add stealmate detection to evaluation
Currently a stealmate position is misevaluated
in a negative/positive score, this leads qsearch(),
that does not detects stealmates too, to return the
wrong score and this yields to some kind of endgames
to be completely misevaluated.

With this patch is fully fixed follwing position

7k/6p1/6B1/5K1P/8/8/8/8 w - - 0 1

Also in SMP case.

Correct root cause analysys by Ronald de Man.

bench: 8678654
2014-05-03 11:47:49 +02:00
Marco Costalba dc87ec7258 Revert to Galurung's KBPsK endgame
After reverting to the original Tord's
endgame, a search on position

7k/6p1/6B1/5K1P/8/8/8/8 w - - 0 1

Reports, correctly, a draw score instead of
an advantage for white.

Issue reported by Uri Blass.

bench: 8678654
2014-05-02 11:04:18 +02:00
Marco Costalba 43973f43c6 Use only standard conforming eg_value()
Remove the optimization for Intel, is not
standard and can break at any time, moreover
our release build is not done with Intel C++
anymore so we don't need to sqeeze the extra
speed out from this compiler.

No functional change.
2014-05-01 23:08:07 +02:00
Marco Costalba bee4f1cf09 Don't save stale value in TT after split
If we return from split with a stale value
due to a stop or a cutoff upstream occurred,
then we exit moves loop and save a stale value
in TT before returning search().

This patch, from Joona, fixes this.

bench: 8678654
2014-05-01 16:26:18 +02:00
Marco Costalba da91a34c09 Better document search stop condition
Handling a stop or a cutoff in the search is
a tricky business, so better document this
difficult part of the code.

No functional change.
2014-05-01 08:48:59 +02:00
Marco Costalba 626dc8a03b Remove dead code in search
We can never have bestValue == -VALUE_INFINITE at
the end of move loop because if no legal move exists
we detect it with previous condition on !moveCount,
if a legal move exists we never prune it due to
futility pruning condition:

bestValue > VALUE_MATED_IN_MAX_PLY

So this code never executes, as I have also verified
directly.

Issue reported by Joona.

No functional change.
2014-05-01 07:46:44 +02:00
Marco Costalba cf50e265fa Fix a compile error with Intel C++
Intel compiler is very picky:
"error: this operation on an enumerated type requires an
applicable user-defined operator function"

Reported by Tony Gaor.

No functional change.
2014-04-30 08:55:45 +02:00
snicolet d3ffd0ffca Penalize hanging pieces
Passed both STC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 8519 W: 1565 L: 1440 D: 5514

And LTC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 60618 W: 9141 L: 8777 D: 42700

bench: 8678654
2014-04-30 08:36:44 +02:00
Marco Costalba db229504e2 Rearrange interpolation formula
Put the division at the end to reduce
rounding errors. This alters the bench
due to different rounding errors, but
should not alter ELO in any way.

bench: 7615217
2014-04-28 17:27:49 +02:00
mstembera 918c29f83a Minor stuff scattered around
Just random minor stuff I found while browsing the code.

No functional change.
2014-04-28 17:07:43 +02:00
Marco Costalba a1f39c1ef9 Remove other useless floor()
No functional change.
2014-04-27 19:17:40 +02:00
Marco Costalba 9f2a64abd2 Don't need floor() in timeman.cpp
For positive numbers result is equivalent:
http://stackoverflow.com/questions/3300290/cast-to-int-vs-floor

Spotted by Joseph Ellis.

No functional change.
2014-04-27 19:10:00 +02:00
Marco Costalba 93e3b06fe2 Fix Intel compiler warnings
Fallout from previous patch: Intel compiler
is very noisy.

No functional change.
2014-04-27 12:02:36 +02:00
Marco Costalba 86c20416c8 Remove some useless casts
No functional change.
2014-04-27 11:44:16 +02:00
Marco Costalba c9e396b542 We can add an integer to a Value
We have defined corresponding operators,
so rely on them to streamline the code
and increase readibility.

No functional change.
2014-04-27 11:25:42 +02:00
Arjun Temurnikar fe23f27086 Remove rook passers eval completely
Tested in no-regression mode.

Passed STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 17727 W: 3248 L: 3122 D: 11357

And (a very long!) LTC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 106327 W: 16258 L: 16265 D: 73804

bench: 7396783
2014-04-27 09:51:48 +02:00
Marco Costalba de6fe2cb4e Reformatting in material.h
No functional change.
2014-04-27 09:31:22 +02:00
Marco Costalba 057c3d60cd Move game phase constants to enum Value
No functional change.
2014-04-27 09:23:45 +02:00
Marco Costalba cb4ac4221e Speed up by almost 3%
This apparentely silly tweak allows
to speed up the bench by almost 3%.

Not clear why, repeating with perft,
the speed up vanishes.

Suggested by Jonathan Calovski.

No functional change.
2014-04-27 00:25:47 +02:00
Marco Costalba 55604f156b Fix issues detected by Coverity Scan
Most of Coverity Scan reports are false
positives, but in rare cases we have
confirmed (very small) issues.

No functional change.
2014-04-26 09:33:50 +02:00
Marco Costalba 7ddbcf7e87 Speed up picking of killers
Changing the order of the conditions gives
about 1% speed up!

No functional change.
2014-04-25 12:53:51 +02:00
Arjun Temurnikar 3705559fdb Remove RookOn7th and merge values into psqt
Tested in no-regression mode:

STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 55678 W: 9954 L: 9892 D: 35832

LTC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 9238 W: 1448 L: 1311 D: 6479

bench: 7905850
2014-04-24 08:53:46 +02:00
Arjun Temurnikar 6579a65bbb Remove penalty for knight when few enemy pawns
Tested in standard mode at STC and no-regression
mode at LTC:

STC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 19503 W: 3502 L: 3349 D: 12652

LTC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 67474 W: 9974 L: 9921 D: 47579

bench: 8331217
2014-04-24 08:47:13 +02:00
Jonathan Calovski f70cef3b79 Shuffle movepicker score
Believed to be a speed optimization as benched
on Windows with bench realtime affinity 0x1 deleting
highest and lowest runs:

Base	Test
1549259	1608202
1538115	1583934
1543168	1556938
1536365	1554179
1533026	1582010

Signature remains unchanged and gives anywhere from 1-2% nps
boost in analysis depending on number of cores used.

No functional change.
2014-04-24 08:38:11 +02:00
Marco Costalba a89b26bedd Correctly apply previous patch
Apply the correct values from previous patch.

bench: 8082049
2014-04-24 08:35:13 +02:00
joergoster 8bfb53efe2 Move queen vs. 3 minors rule to imbalance tables
Tuned with CLOP after 57k games.

Simplification: tested in no-regression mode.

Passed both STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 17254 W: 3159 L: 3032 D: 11063

And LTC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 32413 W: 4967 L: 4864 D: 22582

bench: 8082049
2014-04-23 08:51:34 +02:00
Marco Costalba a66e6e5ad9 Revert "Generalize shift_bb() to handle double pushes"
Seems to intorduce some compiler warning as
reported by Gary. Warning seems bogus, but
revert anyhow.

No functional change.
2014-04-21 20:56:12 +02:00
Marco Costalba 56273fca1e Reset DrawValue[] before new search
Spotted by Ronald de Man

bench: 7384368
2014-04-21 14:30:27 +02:00
Leonid Pechenik ef43e6b05d Rise contempt when in advantage
This is a very discussed patch with many
argumentations pro and against. The fact is
it passed both STC:

LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 16305 W: 3001 L: 2855 D: 10449

And LTC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 34273 W: 5180 L: 4931 D: 24162

Although it is true that a correct test should
include foreign engines, we commit it anyhow so
people can test it out in the wild, under broader
conditions.

bench: 7384368
2014-04-21 12:23:03 +02:00
Marco Costalba 223ebe7b40 Streamline implementation of Position::pretty()
Simpler and more in line with Bitboards::pretty()

No functional change.
2014-04-21 11:47:01 +02:00
Stefan Geschwentner 0e8ad40ef0 Raise penalty blocked enemy pawn on 6th rank
Idea from Lyudmil Tsvetkov.

The value seems to be raised a bit abruptly, but as
Gary said, a blocked pawn on the sixth rank has been
instrumental in limiting king mobility in multiple
losses that I've seen from SF. A blocked pawn on fifth
rank is much less serious on the king safety impact.

Passed both STC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 14551 W: 2750 L: 2607 D: 9194

and LTC
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 43595 W: 6917 L: 6618 D: 30060

And even a retest at 60" fixed games 40K
ELO: 1.79 +-1.9 (95%) LOS: 97.0%
Total: 39889 W: 6018 L: 5813 D: 28058

bench: 7154916
2014-04-21 07:47:50 +02:00
Marco Costalba eced15fe36 Generalize shift_bb() to handle double pushes
And use it in evaluate_space.

No functional change.
2014-04-20 15:52:37 +02:00
Arjun Temurnikar a4d058bca2 Small simplification to passed pawns
Tested in no-regression mode.

Passed both STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 28521 W: 5066 L: 4958 D: 18497

And LTC
LLR: 3.04 (-2.94,2.94) [-3.00,1.00]
Total: 21939 W: 3261 L: 3138 D: 15540

bench: 8165681
2014-04-20 10:06:51 +02:00
Joseph Hellis 619d66b7ab Remove supporting pawns
Tested in no-regression mode

Passed both STC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 44957 W: 7984 L: 7903 D: 29070

and LTC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 12396 W: 1916 L: 1783 D: 8697

Bench: 7907885
2014-04-17 08:45:31 +02:00
Jean-Francois Romang 9073866491 Enable BMI1 too when using BMI2 ARCH
Adding BMI1 allows the compiler to use _blsr_u64
automatically (the advertised 0.3% speed gain).
I verified that the compiler does not use this
instruction with the -mbmi2 flag only. Also, all
processors supporting BMI2 is also supporting BMI1.

No functional change
2014-04-14 07:54:24 +02:00
Marco Costalba 7bce8831d3 More readable trapped rook condition
Prefer

file_of(s) < file_of(ksq)

to the inidrect

file_of(ksq) < FILE_E

To evaluate if semiopen side to check is the left side.

Also other small touches while there.

No functional change.
2014-04-13 14:29:42 +02:00
Daylen Yang 81a8c1118b Simplify Makefile by removing OS X targets
Right now the Makefile is cluttered with OS X equivalents
of all the x86 targets. We can get rid of all of them and
just check UNAME against "Darwin" for the few OS X-specific
things we need to do.

We also disable Clang LTO when using BMI2 instructions. For
some reason, LLVM cannot find the PEXT instruction when using
LTO. I don't know why, but disabling LTO for BMI2 fixes it.

No functional change.
2014-04-13 09:05:21 +02:00
Marco Costalba b2c0634d48 Move args parsing to UCI::loop
This leaves a very clean main.cpp

No functional change.
2014-04-12 13:51:52 +02:00
Marco Costalba ada55c5d0a Reshuffle in uci.cpp
Move function definitions before call site.

No functional change.
2014-04-12 12:05:25 +02:00
Marco Costalba 17cb7e7fa3 Reshuffle in timeman.cpp
Move template definitions before call site.

No functional change.
2014-04-12 12:00:37 +02:00
Marco Costalba 800ba28e83 Fix a typo in evaluate
Spotted by Lyudmil Antonov.

No functional change.
2014-04-12 10:17:41 +02:00
Marco Costalba 0b2794ae12 Retire signature-build
Does not seem used.

No functional change.
2014-04-12 09:18:55 +02:00
Jean-Francois Romang 226bbc1e63 Add ARCH x86-64-bmi2 support
Intel Haswell and newer CPUs can calculate sliders
attacks using special PEXT asm instructions instead
of magic bitboards. This gives a +3% speed up.

To enable it just compile with ARCH=x86-64-bmi2

No functional change.
2014-04-12 09:15:14 +02:00
Marco Costalba da2f8880b9 Switch to hardware PEXT
Retire software pext and introduce hardware
call when USE_PEXT is defined during compilation.

This is a full complete implementation of sliding
attacks using PEXT.

No functional change.
2014-04-12 08:55:30 +02:00
Marco Costalba c556fe1d71 Implement PEXT based attacks
According to:

https://chessprogramming.wikispaces.com/BMI2#PEXTBitboards

No functional change.
2014-04-12 08:55:30 +02:00
Marco Costalba 2bfe61c33b Add PEXT software implementation
For development/debug purposes.

No functional change.
2014-04-12 08:55:30 +02:00
Marco Costalba 2f92e3b525 Big reshuffle in evaluate.cpp
Reshuffle functions to define them in reverse
calling order (C style).

This allow us to define templates before they are
used. Currently it is not like this, for instance
evaluate_pieces is defined after do_evaluate that
calls it. This happens to work for some strange
reason (two phase lookup?) but we want to avoid
code that works 'by magic'.

As a nice side-effect we can now remove the function
prototypes.

No functional change.
2014-04-12 08:39:18 +02:00
Gary Linscott 0510112f91 Move LowMobPenalty into psq/mobility tables
Tested in no-regression mode.

Passed both STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 36705 W: 6537 L: 6443 D: 23725

and LTC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 9358 W: 1495 L: 1358 D: 6505

bench: 6921356
2014-04-12 07:15:51 +02:00
Gary Linscott 4597324572 Reduce penalty for doubled pawns further away from each other
Passed both STC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 38339 W: 6849 L: 6649 D: 24841

and LTC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 22693 W: 3455 L: 3256 D: 15982

bench: 7508468
2014-04-12 07:05:02 +02:00
Marco Costalba ce6b7a1b85 Further simplification in evaluate
No functional change
2014-04-11 08:38:09 +02:00
Marco Costalba e3b54235ad Get rid of an evaluate_pieces() overload
Rewrite and greatly simplify that part of code.

No functional change.
2014-04-10 19:45:18 +02:00
Gary Linscott 8863afeb84 Add a penalty for low mobility pieces
Passed both STC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 81857 W: 14652 L: 14342 D: 52863

and LTC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 45400 W: 6999 L: 6697 D: 31704

bench: 7716978
2014-04-10 08:35:10 +02:00
Gary Linscott 5c75455c8e Restrict queen mobility to safe squares
Passed both STC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 16188 W: 3119 L: 2971 D: 10098

and LTC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 6336 W: 1010 L: 882 D: 4444

bench: 7533692
2014-04-08 22:25:54 +02:00
Lucas Braesch 0d8a4c7565 Rescale UCI scores to PawnValueEg
This is more consistent with what other engines are doing.
Often people thinks that SF's scores are overblown. In the
end, it just boils down to the arbitrary way of rescaling them.

No functional change.
2014-04-06 11:53:28 +02:00
Marco Costalba 64d29a6330 Sync some common names
No functional change.
2014-04-06 11:26:12 +02:00
Marco Costalba fcf2a34080 Some more work in pretty_pv
No functional change.
2014-04-06 10:15:11 +02:00
Marco Costalba 698b645e10 Small tidy up in move_to_san
No functional change.
2014-04-05 19:05:37 +02:00
mstembera d28ea7b518 Smaller and faster profile-build binaries
I have noticed that increasing the bench depth produces
progressively smaller and slightly faster executables at
the cost of longer compile times.  Also using bench "time"
instead of "depth" seems to produce slightly smaller/faster
executables  given comparable compile times.

I have made a new Makefile that generates smaller and
about 1% to 2% faster profile executables at only a
little extra compile time.  On  my mobile 2GHz i7 a
full profile build time goes from 3'48" to 4'13" and
the exe goes down by 5% from 416,310 bytes to 395,567
bytes.

No functional change.
2014-04-05 12:48:20 +02:00
Lucas Braesch be641e881f Remove QueenOn7th and QueenOnPawn
Small simplification.

Passed SPRT(-3,1) both at STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 17051 W: 3132 L: 3005 D: 10914

and LTC:
LLR: 4.55 (-2.94,2.94) [-3.00,1.00]
Total: 24890 W: 3842 L: 3646 D: 17402

The rationale behind this is that I've never managed to add a
Queen on 7th rank bonus in DiscoCheck, because it never showed
to be positive (evne slightly) in testing. The only thing that
worked is Rook on 7th rank.

In terms of SF code, it seemed natural to group it with QueenOnPawn
as well as those are done together. I know you're against groupping
in general, but when it comes to non regression test, you are being
more conservative by groupping. If the group passes SPRT(-3,1) it's
safer to commit, than test every component in SPRT(-3,1) and end up
with the risk of commiting several -1 elo regression instead of just
one -1 elo regression.

In chess terms, perhaps it's just easier to manouver a Queen (which
can more also diagonaly) than a Rook. Therefore you can let the search
do its job without needing eval ad-hoc terms to guide it. For the Rook
which takes more moves to manouver such eval terms can be (marginally)
useful.

bench: 7473314
2014-04-05 11:26:44 +02:00
mstembera 3b19ea6ae5 Speed up apply_weight
Speed up by about 2% this hot path function pre-calculating
midgame and endgame values of the weight.

No functional change.
2014-04-05 11:12:18 +02:00
Marco Costalba ccf59b0228 Update Readme to 128 max threads
No functional change.
2014-04-03 11:33:42 +02:00
Joerg Oster 299afcd886 Queen vs. 3 pieces imbalance
Passed both STC
LLR: 7.32 (-2.94,2.94) [-1.50,4.50]
Total: 98108 W: 18087 L: 17576 D: 62445

And LTC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 15082 W: 2417 L: 2248 D: 10417

bench: 7717336
2014-04-03 10:42:06 +02:00
Marco Costalba c15b132f03 Make operator<< to return void
This should help preventing misuse.

No functional change.
2014-04-03 10:34:25 +02:00
Stefan Geschwentner 0ba814b3ca Drop not defended by pawn condition
Passed no-regression test both at STC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 96554 W: 17563 L: 17572 D: 61419

and at LTC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 31891 W: 4905 L: 4801 D: 22185

bench: 7720896
2014-04-01 11:59:25 +02:00
Marco Costalba d2caba1f66 Do not workaround function argument evaluation
Rewrite options initialization to do not trying to
hack upon the undefined evaluation order of function
arguments.

No functional change.
2014-04-01 09:39:41 +02:00
Marco Costalba 1efc19ade0 Fix a compile error with Intel C++
Error: a value of type "int" cannot be assigned
to an entity of type "Value"

No functional change.
2014-03-30 14:20:12 +02:00
Marco Costalba 678425f274 Fix a warning with MSVC 2010
Warning C4804: '<' : unsafe use of type 'bool' in operation

No functional change.
2014-03-30 14:25:57 +02:00
Marco Costalba 422c9c2acd Show evaluation from white POV in trace
We chose this instead of negamax sign convention
(ie. from the point of view of the side to move)
because it is more in line to how the eval
table is presented.

Also some tweak to formatting while there.

No functional change.
2014-03-30 10:45:46 +02:00
Marco Costalba 9350d0dce5 Raise VALUE_INFINITE
In some legal positions like this one:
R6R/3Q4/1Q4Q1/4Q3/2Q4Q/Q4Q2/Np1Q4/kB1N1KB1  b -- 0 1

We can have a very high score, in this case 30177 and 29267
for midgame and endgame respectively, and because
VALUE_INFINITE = 30001 we have an assert in interpolate()

Midgame and endgame scores are stored in 16 bit signed integers
so we can rise VALUE_INFINITE a little bit. This does not fix
the possibility of overflow in general case, just makes the
condition more difficult to trigger and anyhow better uses all
the score width.

Raising VALUE_INFINITE to 32000 seems to fix the problem for this
particular case.

No functional change.
2014-03-29 11:13:42 +01:00
Jean-Francois Romang 4833887842 Further simplification of TT replace strategy
No functional change
2014-03-29 10:05:02 +01:00
Marco Costalba f811a5693e Restore old aspiration window to 16
Tested directly at LTC because previous long
test series on this topic shows it is TC dependant.

Tested with no-regression mode because gets rid of
an ugly and ad-hoc rule.

Test at LTC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 67918 W: 10590 L: 10541 D: 46787

bench: 7926803
2014-03-29 08:45:40 +01:00
Stefan Geschwentner af0c13ba6a Pinned pieces affect king safety
Here the new idea is to link pinned pieces
with king safety.

Passed both STC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 10047 W: 1867 L: 1737 D: 6443

And LTC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 10419 W: 1692 L: 1543 D: 7184

bench: 8325087
2014-03-29 08:37:55 +01:00
Marco Costalba c7cf45241c Fix a bug in pawns eval tracing
Instead of totals we were showing white and
black values.

Spotted by Sven Schüle

No functional change.
2014-03-26 07:06:29 +01:00
Marco Costalba 865b71309c Simplify TT replace strategy
Tested for no-regression with SPRT[-3, 1] at STC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 32046 W: 6020 L: 5918 D: 20108

No functional change.
2014-03-24 08:32:08 +01:00
snicolet e7362dae78 Introduce penalty for weak (=unsupported) pawns.
We add a penalty for each pawn which is not protected by another pawn
of the same color.

Passed both short TC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 12107 W: 2411 L: 2272 D: 7424

And long TC
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 9204 W: 1605 L: 1458 D: 6141

bench: 7682173
2014-03-24 08:27:40 +01:00
Marco Costalba 9e72e35942 Fix an incorrect 'friend' declaration
Spotted by Lee David.

No functional change.
2014-03-23 11:17:38 +01:00
Marco Costalba bc183b0c04 Retire last usage of operator|(File f, Rank r)
This for some reason was missed.

No functional change.
2014-03-23 10:42:37 +01:00
mstembera ffdf63ff7c Refresh TT entries generation automatically on probe
And other assorted simplifications, tested with SPRT[-3, 1]

Passed both short TC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 18814 W: 3600 L: 3475 D: 11739

And long TC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 20731 W: 3217 L: 3096 D: 14418

No functional change.
2014-03-23 09:46:15 +01:00
Marco Costalba f12449d492 Rename score to value in ExtMove
We use 'score' for the value mid-endgame pair.

No functional change.
2014-03-23 08:54:10 +01:00
Marco Costalba 441a34a1c6 Trivial formatting in ucioption.cpp
No functional change.
2014-03-23 00:06:26 +01:00
Marco Costalba 5f12069cbf Retire operator|(File f, Rank r)
Use make_square() instead. Less fancy but
more clear.

No functional change.
2014-03-22 23:54:18 +01:00
Marco Costalba 4eee603433 Fix a subtle bug in UCI options printing
We want all the UCI options are printed in the order in which are
assigned, so we use an index that, depending on Options.size(),
increases after each option is added to the map. The problem is
that, for instance, in the first assignment:

o["Write Debug Log"] = Option(false, on_logger);

Options.size() can value 0 or 1 according if the l-value (that
increments the size) has been evaluated after or before the
r-value (that uses the size value).

The culprit is that assignment operator in C++ is not a
sequence point:

http://en.wikipedia.org/wiki/Sequence_point

(Note: to be nitpick here we actually use std::map::operator=()
 that being a function can evaluate its arguments in any order)

So there is no guarantee on what term is evaluated first and
behavior is undefined by standard in this case. The net result
is that in case r-value is evaluated after l-value the last
idx is not size() - 1, but size() and in the printing loop
we miss the last option!

Bug was there since ages but only recently has been exposed by
the removal of UCI_Analyze option so that the last one becomes
UCI_Chess960 and when it is missing engine cannot play anymore
Chess960.

The fix is trivial (although a bit hacky): just increase the
last loop index.

Reported by Eric Mullins that found it on an ARM and MIPS
platforms with gcc 4.7

No functional change.
2014-03-22 11:30:06 +01:00
Marco Costalba c714b90594 Fix a typo
Spotted by Isaac Haïk Dunn.

No functional change.
2014-03-18 18:36:39 +01:00
Marco Costalba aab5863dd4 Increase max threads to 128
Thanks to std::bitset we can easily increase
the limit of active threads above 64.

Thanks to Lucas Braesch for pointing at the
correct solution of using std::bitset.

No functional change.
2014-03-18 12:07:26 +01:00
Marco Costalba fa3f6dcbea Fix a crash under MSVC
Using memset on a std::vector is undefined behavior,
so manually init all the data memebers of LimitsType.

Bug intorduced in 41641e3b1e

No functional change.
2014-03-16 10:55:58 +01:00
Marco Costalba a091ae4cc8 Split also if no slaves are found
Because we test for available slaves before
entering split(), we almost always allocate a
slave, only in the rare case of a race (less
then 2% of cases) this is not true, but to
special case this occurrence is not worth
the added complexity.

bench: 7451319
2014-03-15 23:43:35 +01:00
Marco Costalba a1a7bc84da Remove "Max Threads per Split Point" UCI option
Experimental patch to verify if drop of nps
in endgames at very long TC is due to this.

Suggested by Ronald de Man.

bench: 7451319
2014-03-15 21:26:04 +01:00
Marco Costalba 6e4b4c42ed Merge default tests in pos_is_ok
No functional change.
2014-03-15 15:34:31 +01:00
Marco Costalba 142874b058 Microptimize castling in undo_move()
We don't need to set 'captured' and 'pt' after we
castle back.

No functional change.
2014-03-15 11:47:30 +01:00
Mysseno 36c381154b Depth dependant aspiration window delta
Split delta value in aspiration window so that when
search depth is less than 24 a smaller delta value
is used. The idea is that the search is likely to
be more accurate at lower depths and so we can exclude
more possibilities, 25% to be exact.

Passed STC
LLR: 2.96 (-2.94, 2.94) [-1.50, 4.50]
Total: 20430 W: 3775 L: 3618 D: 13037

And LTC
LLR: 2.96 (-2.94, 2.94) [0.00, 6.00]
Total: 5032 W: 839 L: 715 D: 3478

Bench: 7451319
2014-03-14 19:47:41 +01:00
Marco Costalba d0587f2c7f Use legal positions for endgame initialization
During endgame initialization we get the material
hash key of each endgame forging and ad-hoc position
that in same cases is illegal (leaves teh king under
capture). This is not a problem for the material key,
but rises an assert when SF is run in debug mode with
'testKingCapture' set in pos_is_ok().

So rewrite the code to always produce legal positions.

No functional change.
2014-03-14 09:57:34 +01:00
Marco Costalba 1f4798a173 Further work in pos_is_ok()
No functional change.
2014-03-14 09:43:19 +01:00
Daylen Yang 61e4443342 Re-add link time optimization on OS X
In the new version of clang, -O4 does not imply -flto, so we set the
flag
2014-03-14 08:49:08 +01:00
Marco Costalba 6571acffaa Reformat do_castling()
No functional change.
2014-03-13 12:53:03 +01:00
Marco Costalba 6f3d787692 Further merge StateInfo setup functions
No functional change.
2014-03-12 22:46:17 +01:00
Marco Costalba 1e032ece92 Merge hash key computation functions
No functional change.
2014-03-12 09:14:38 +01:00
Marco Costalba cc3002ff04 Use std::count in pos_is_ok()
No functional change.
2014-03-11 23:19:47 +01:00
Marco Costalba c40d4e0133 Small simplification in gives_check
Use switch statement also for normal case.

No speed regression.

No functional change.
2014-03-11 22:58:08 +01:00
Marco Costalba ca0804dfe4 Print dbg counters after bench
Print last debug counters update just
before to exit benchmark.

Suggested by Stephane Nicolet.

No functional change.
2014-03-11 22:19:14 +01:00
Marco Costalba d2a8ba3299 Simplify pseudo_legal()
Big simplification of pawn move check.

Code has been tested with a brute force approach: for
every position reached during a bench search, the function
has been called for each combinations of Move(from, to)
and verified the result is the same of old code.

Actually this function is very critical becuase is the
one that ensures corrupted TT moves are discarded, so
to properly test it a simple bench is not enough.

Verified also speed is not changed.

No functional chnage.
2014-03-10 08:38:23 +01:00
Marco Costalba 20ff12e1be Simplify generate<EVASIONS>
No speed regression, tested with both perft and
bench.

No functional change.
2014-03-09 12:16:27 +01:00
Marco Costalba 5cf9e0b254 Retire SERIALIZE macros
Explicitly write the 'while' loops. This adds some
code but makes clear what's the code behind the
macro.

No functional change.
2014-03-09 11:10:33 +01:00
Marco Costalba 1d1b7df7c6 Rename castling flag to castling right
This is a more conventional naming as
reported also in:

http://chessprogramming.wikispaces.com/Castling+rights

No functional change.
2014-03-08 15:08:55 +01:00
Stephane Nicolet 13b9e1e098 Fix dbg_mean_of() for negative numbers
Type should be int64_t instead of uint64_t

No functional change.
2014-03-05 08:55:12 +01:00
mstembera 553ead429d Some minor cleanup stuff
I came across while browsing the code.

No functional change.
2014-03-03 08:57:20 +01:00
Marco Costalba bbd69c0260 Revert dynamic draw value
When tested with weaker engines did not
performed as expected, actually it was even
a regression from standard version.

bench: 8430785
2014-03-03 08:39:34 +01:00
Marco Costalba 708cb311a0 Pass CastlingFlag argument only
Instead of Color and CastlingSide. Change functions API
accordingly.

No functional change.
2014-03-02 13:21:19 +01:00
Marco Costalba 3e5470d88f Remove limit of minimumSplitDepth
There is no reason why an user cannot set
it at a value less than 4.

No functional change.
2014-03-01 23:22:14 +01:00
Marco Costalba 3d8c0f16c2 Rename xxx_to_char() -> to_char()
No functional change.
2014-03-01 22:07:41 +01:00
Marco Costalba de2ba70830 Simplify Bitboards::pretty
No functional change.
2014-03-01 13:10:05 +01:00
Marco Costalba 9f0485e343 Retire UCI_AnalyseMode option
It has been obsoleted out already some time ago
and currently there is no point in changing eval
score according to if we are in game or analyzing.

So retire the option.

No functional change.
2014-03-01 12:10:42 +01:00
Joerg Oster b917cd275e Dynamic draw value
Try to avoid repetition draws at early midgame,
this should give an edge against weaker opponents
and reduce draw rate.

Tested for regressions with SPRT[-3, 1] and
passed both short TC
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 68498 W: 12928 L: 12891 D: 42679

And long TC
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 40212 W: 6386 L: 6295 D: 27531

bench: 7990513
2014-02-26 19:33:52 +01:00
Marco Costalba 0949f06a60 Fix a warning with Intel compiler
warning #2259: non-pointer conversion from "int" to
"uint8_t={unsigned char}" may lose significant bits

No functional change
2014-02-22 12:00:14 +01:00
Marco Costalba 012f20d66e Fix an assert in Probcut
When running the following position:

8/kPp5/2P3p1/p1P1p1P1/2PpPp2/3p1p2/3P1P2/5K2 w - - 0 1

An assert is raised at depth 92:

assert(-VALUE_INFINITE <= alpha && alpha < beta && beta <= VALUE_INFINITE);

This is because it happens that beta = 29832,
so rbeta = 30032 that is > VALUE_INFINITE

Bug spotted and analyzed by Uri, fix suggested by Joerg.

Other fixes where possible but this one is pointed
exactly at the source of the bug, so it is the best
from a code documentation point of view.

bench: 8430785
2014-02-22 10:38:21 +01:00
Leonid Pechenik b8cfc255d4 Distribute part of first move time to other moves
Passed both short TC:
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 18907 W: 3475 L: 3322 D: 12110

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 19044 W: 2997 L: 2811 D: 13236

bench: 8430785
2014-02-20 08:39:00 +01:00
Marco Costalba 9fcefb2760 Avoid recalculating CheckInfo in generate_castling()
No functional change.
2014-02-20 08:27:13 +01:00
Marco Costalba 64a71c3c02 Don't update pieceCount for ALL_PIECES
It is currently unused and only adds
overhead for nothing.

Also set proper type of chess960.

No functional change.
2014-02-18 16:41:24 +01:00
Marco Costalba 7b0a2f2a90 Update SEE to return a Value
It seems more natural because the actual returned
value is from PieceValue[] array.

No functional change.
2014-02-16 13:06:31 +01:00
Marco Costalba 17ffc22279 Sync code style in material.cpp
Update to use common code style.

No functional change.
2014-02-16 12:56:54 +01:00
Marco Costalba 52ebf87238 Increase MAX_PLY from 100 to 120
Under some very rare case 100 plies of search
could be not enough. Increasing more could lead
to crashes due to reached stack size limit on
some platforms.

Strongly requested by Uri.

bench: 8430785
2014-02-16 12:20:37 +01:00
Marco Costalba d91079d4b0 Fix material key for King
Currently king has no material key associated because
it can never happen to find a legal position without
both kings, so there is no need to keep track of it.

The consequence is that a position with only the two
kings has material key set at zero and if the material
hash table is empty any entry will match and this is
wrong.

Normally bug is hidden becuase the checking for a draw
with pos.is_draw() is done earlier than evaluate() call,
so that we never check in gameplay the material key of a
position with two kings.

Nevertheless the bug is there and can be reproduced setting
at startup a position with only two kings and typing
'eval' from prompt.

The fix is very simple: add a random key also for the king.

Also fixed the condition in material.cpp to avoid asserting
when a 'just 2 kings' postion is evaluated.

No functional change.
2014-02-16 11:51:30 +01:00
Marco Costalba 62c0dc5dea Restore PorbCut name
Actually MultiCut is too different from current scheme.
Note that neither ProbCut is exactly what we do because
we try just a handful of captures instead of all moves,
nevertheless it seems more in line with what we do.

Suggested by Joona.

No functional change.
2014-02-15 22:21:39 +01:00
Marco Costalba 7bdb8c9c5c Reformat of eval tracing code
Also assorted rename while there.

No functional change.
2014-02-15 14:11:26 +01:00
Marco Costalba 3336963185 Rename ProbCut to Multicut
The teqnique used is actually MultiCut:

https://chessprogramming.wikispaces.com/Multi-Cut

And not ProbCut:

https://chessprogramming.wikispaces.com/ProbCut

No functional change.
2014-02-15 09:37:55 +01:00
Marco Costalba 4808d15a85 Assorted renaming in search
Inspired by DON.

No functional change.
2014-02-15 09:20:27 +01:00
Joerg Oster 67f88f5e3e Return static eval when reaching MAX_PLY
Makes more sense than returning a draw score. Tested
with reduced MAX_PLY = 30 and passed both short TC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 17434 W: 3345 L: 3194 D: 10895

And long TC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 2610 W: 488 L: 373 D: 1749

With current limit of MAX_PLY = 100 the patch should not
introduce any measurable change, nevertheless is the correct
approach.

Idea of returning eval is from  Michel Van den Bergh.

bench: 8430785
2014-02-15 08:20:33 +01:00
Marco Costalba b3470d7ab1 Fix magic boosters conversion
Fix small overflow error while converting
magic boosters from right rotate to left rotate,
in particular booster 38 was converted to 4122
instead of the corrcet value 26.

Formula used was:

s1 = original & 63, s2 = (original >> 6) & 63;
new = (64 - s1) | ((64 - s2) << 6);

Instead of:

s1 = original & 63, s2 = (original >> 6) & 63;
new = ((64 - s1) & 63) | (((64 - s2) & 63) << 6);

This has no impact in number of cycles needed, but
just in the resultig number that yields to a rotate
amount bigger than 63.

Spotted by Ehsan Rashid.

No functional change.
2014-02-14 10:43:37 +01:00
Marco Costalba e4695f15bc Additional renaming from DON
Assorted renaming and triviality.

No functional change.
2014-02-14 09:42:50 +01:00
joergoster ffd6685f79 Fix a compiler warning
Latest master triggers a compiler warning due
to comparing int64_t to uint64_t.

notation.cpp: In Funktion »std::string pretty_pv(Position&, int, Value, int64_t, Move*)«:
notation.cpp:230:30: Warnung: Vergleich zwischen vorzeichenbehafteten und vorzeichenlosen Ganzzahlausdrücken [-Wsign-compare]

This patch should fix it.

No functional change.
2014-02-12 21:52:21 +01:00
Leonid Pechenik 72e8640f4d Simplify time management
Tested with simplification mode SPRT[-4, 0]

Passed both short TC
LLR: 2.95 (-2.94,2.94) [-4.00,0.00]
Total: 34102 W: 6184 L: 6144 D: 21774

And long TC
LLR: 2.96 (-2.94,2.94) [-4.00,0.00]
Total: 16518 W: 2647 L: 2545 D: 11326

And also 40/10 TC
LLR: 2.95 (-2.94,2.94) [-4.00,0.00]
Total: 22406 W: 4390 L: 4312 D: 13704

bench: 8430785
2014-02-12 20:01:11 +01:00
Marco Costalba e6523e56b8 Move magic random to RKISS
When initializing the magic numbers used to
compute sliding attacks, we endless generate a
random and test it as a possible magic.

In the general case this takes a lot of iterations,
but here, insteaad of picking a casual random, we
rotate it a couple of times and generate a number that
we know has a good probability to be a magic candidate.

This is becuase the quantities by which we rotate the
number are known in advance to produce quickly a good
canidate.

The patch, inspired by DON, just moves the shuffle to RKISS
changing the boosters to take in account a left rotation
instead of a right rotation as in the original.

No functional change.
2014-02-12 14:47:36 +01:00
Marco Costalba b534176d4a Revert "Retire null search verification"
Although does not change ELO level, it seems
verification is useful in many zugzwang positions
as reported by many sources.

So revert this simplification.

bench: 8430785
2014-02-12 14:16:21 +01:00
Henri Wiechers ddeb01612b Faster handling of king captures in Position::see
Another SEE speed up that passed the SPRT short TC test!

LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 81337 W: 15060 L: 14745 D: 51532

No functional change.
2014-02-09 19:42:24 +01:00
Marco Costalba 41641e3b1e Assorted tweaks from DON
Mainly renames and some little code style improvment,
inspired by looking at DON sources:

https://github.com/erashid/DON

No functional change.
2014-02-09 17:31:45 +01:00
Marco Costalba 2f5aaf7de6 Rewrite previous patch removing the macro
No functional change.
2014-02-08 13:27:44 +01:00
Thanar2 d48a304262 Inline common path of pos.gives_check
Test for common case which, when running default
stockfish bench, avoids 96% of 19 million calls to
pos.gives_check().

Yields to a 2-4% speed up according to platform.

Passed fishtest at STC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 12441 W: 2333 L: 2196 D: 7912
http://tests.stockfishchess.org/tests/view/52f02d790ebc5901df50f887

Passed fishtest at LTC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 42175 W: 6702 L: 6409 D: 29064
http://tests.stockfishchess.org/tests/view/52f0dbe00ebc5901df50f8a0

No functional change.
2014-02-08 13:17:29 +01:00
Marco Costalba 0a1092f64e Don't fear races when are harmless
Actually race conditions do exist in an engine, just
think for a moment to TT concurrent access. Racy code
is not a problem per se, if the consequences are well
known and correctly handled.

In case of TT access we ensure that the TT move is validated
before to be tried, here we just retry the same move in less
that 1 case out of a million: this is totally harmless considering
that very probably the second time the move is tried we get
immediately a TT hit and search quickly returns.

So we simplify the code for no harm.

No fuctional change (in single thread case)
2014-02-08 13:07:57 +01:00
Lucas Braesch 399968f1d0 Retire null search verification
Tested with SPRT in simplification mode [-4.00,0.00],
this ensures that the patch is (very probably) not
a regression.

Passed both short TC
LLR: 2.95 (-2.94,2.94) [-4.00,0.00]
Total: 27543 W: 4278 L: 4209 D: 19056

And long TC
LLR: 2.95 (-2.94,2.94) [-4.00,0.00]
Total: 39483 W: 7325 L: 7305 D: 24853

bench: 8347121
2014-02-08 08:25:08 +01:00
Lucas Braesch e5c3effdb1 Better document null search window
Hopefully this patch makes the code more:

* Self-documenting: Null search is always a zero window search,
  because it is testing for a fail high. It should never be done
  on a full window! The current code only works because we don't
  do it at PV nodes, and therefore (alpha, beta) = (beta-1, beta):
  that's the kind of "clever" trick we should avoid.

* Idiot-proof: If we want to enable null search at PV nodes, all we
  need to do now is comment out the !PvNode condition. It's that simple!

In theory, null search should not be done at PV nodes, because PV nodes
should never fail high. But in practice, they DO fail high, because of
aspiration windows, and search inconsistencies, for example. So it makes
sense to keep that flexibility in the code.

No functional change.
2014-02-04 08:24:46 +01:00
Lucas Braesch e88ef801af Better document razoring
Use ralpha instead of rbeta

* rbeta is confusing people. It took THREE attempts to code razoring
at PV nodes correctly in a recent test, because of the rbeta trick.
Unnecessary tricks should be avoided.

* The more correct and self-documenting way of doing this, is to say
that we use a zero window around alpha-margin, not beta-margin.
The fact that, because we only do it at PV nodes, alpha happens to be
beta-1 and that the current stuff with rbeta works, may be correct,
but is confusing.

Remove the misleading and partially erroneous comment about returning
v + margin:

* comments should explain what the code does, not what it could have done.

* this comment is partially wrong in saying that v+margin is "logical",
  and that it is "surprising" that is doesn't work.

From a theoretical perspective, at least 3 ways of doing this are equally
defendable:

1/ fail hard: return alpha: The most conservative. We bet that the search
will fail low, but we don't know by how much and don't want to take risks.

2/ aggressive fail soft: return v (what the current code does). This
corresponds to normal fail soft, with the added assumption that we don't
care about the reduction effect (see below point 3/)

3/ conservative fail soft: return v + margin. If the reduced search (qsearch)
gives us a score <= v, we bet that the non reduced search will give us a
score <= v + margin.

* Saying that 2/ is "logical" implies that 1/ and 3/ are not, which is
arguably wrong. Besides, experimental results tell us that 2/ beats 3/,
and that's not something we can argue against: experimental results are
the only trusted metric.

* Also, with the benefit of hindsight, I don't think the fact that 2/ is
better than 3/ is surprising at all. The point is that it is YOUR turn to
move, and you are assuming that by NOT playing (and letting the opponent
capture your hanging pieces in QS) you cannot generally GAIN razor_margin(depth).

No functional change.
2014-02-03 21:37:14 +01:00
Joona Kiiski d8796fe7e9 H-file penalty and center bonus
After almost 50K at long TC it seems
slightly positive:

ELO: 1.73 +-1.8 (95%) LOS: 97.3%
Total: 47122 W: 7507 L: 7273 D: 32342

bench: 8430785
2014-02-03 21:23:49 +01:00
Joona Kiiski 77341f67f3 Tweak bishop PSQT tables
Tuned after 49K iterations of SPSA.

Passed both short TC:
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 14231 W: 2684 L: 2542 D: 9005

And long TC:
LLR: 2.94 (-2.94,2.94) [0.00,4.00]
Total: 87556 W: 13757 L: 13342 D: 60457

bench: 6875743
2014-01-29 18:02:13 +01:00
Uri Blass 93f95cc936 Reduce VALUE_KNOWN_WIN to 10000
With some positions like

8/8/8/2p2K2/1pp5/br1p1b2/2p2r2/qqkqq3 w - -

The eval score is higher than VALUE_INFINITE because
is the sum of VALUE_KNOWN_WIN plus a big material
advantage. This leads to an assert. Here are the
steps to reproduce:

Compile SF with debug=yes then do

./stockfish
position fen 8/8/8/2p2K2/1pp5/br1p1b2/2p2r2/qqkqq3 w - -
go depth 1

This patch fixes the issue in this case, but do exsist
other positions for which the patch is not enough and
we will need to limit the eval score to be sure not
overflow the limit.

Note that is not possible to increase the value of
VALUE_INFINITE because should remain within int16_t
type to be stored in a TT entry.

bench: 7356053
2014-01-27 20:09:51 +01:00
Marco Costalba f434cea287 Fix null reduction formula
Depth is already dependent on the actual value
of ONE_PLY, in particular can be expressed like:

Depth = n * ONE_PLY

And because formula is used to calculate R that is
also dependent on the value of ONE_PLY and can be
expressed like:

R = x * ONE_PLY

We don't want to divide depth by a 'ply' value but
directly by an integer number.

Spotted by sf-x

No functional change.
2014-01-27 08:18:48 +01:00
Marco Costalba 216972186e Grammar fix in MovePicker::next_move
Thanks to Lyudmil Antonov and Michel Van den Bergh
for spotting this and suggesting the fix.

No functional change.
2014-01-26 23:09:22 +01:00
Stefan Geschwentner 074c7a3c30 Variable null-move value based reduction
Instead of a fixed reduction of ONE_PLY, now
Null move dynamic reduction based on value can
grow larger in case we are above beta of a value
much higher then PawnValueMg.

Note that now an eval returning VALUE_KNOWN_WIN
makes null search to drop in qsearch.

Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 26141 W: 4871 L: 4699 D: 16571

And long TC:
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 33695 W: 5309 L: 5056 D: 23330

bench: 7356053
2014-01-26 10:23:31 +01:00
Joona Kiiski cf95a55d76 Do not set default value for architeture in Makefile
Fixes a regression that ARCH parameter was not properly validated.
Invalid value would default to generic 32-bit build.

No functional change.
2014-01-25 11:29:32 +01:00
Henri Wiechers a08a21d5a0 Small simplification to Position::see
Verified there are no hidden bugs and is
actually a speed optimization:

Fixed games at 15+0.05 TC
ELO: 1.72 +-2.9 (95%) LOS: 87.5%
Total: 20000 W: 3741 L: 3642 D: 12617

No functional change
2014-01-19 11:16:34 +01:00
Joona Kiiski cabd512916 Fix +M0 score when low on time
When time remaining is less than Emergency Move Time,
we won't even complete one iteration and engine reports
a stale +M0 score.

To reproduce run "go wtime 10"

info depth 1 seldepth 1 score mate 0 upperbound nodes 2 nps 500 time 4 multipv 1 pv a2a3
info nodes 2 time 4
bestmove a2a3 ponder (none)

This patch fixes the issue.

Tested by Binky at very short TC: 0.05+0.05
ELO: 5.96 +-12.9 (95%) LOS: 81.7%
Total: 1458 W: 394 L: 369 D: 695

And at a bit longer TC:
ELO: 1.56 +-3.7 (95%) LOS: 79.8%
Total: 16511 W: 3983 L: 3909 D: 8619

bench: 7804908
2014-01-19 11:09:44 +01:00
Marco Costalba 40c863d41a Increase max hash size to 16GB
TCEC season 3, which is due to start in a few weeks, just
had its server upgraded to 64GB RAM and will therefore allow
16GB hash to be used per engine.

This is almost the upper limit without changing the
type of size and hashMask. After this we need to
move to uint64_t instead of uint32_t.

No functional change.
2014-01-18 18:22:32 +01:00
Joona Kiiski be61edbd19 Tweak knight PSQT tables
Passed both short TC:
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 31765 W: 6103 L: 5913 D: 19749

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 38867 W: 6268 L: 5988 D: 26611

bench: 7804908
2014-01-18 17:52:37 +01:00
Chris Cain df201175c6 Simplify pawnless endgame evaluation
Retire KmmKm evaluation function. Instead give a very drawish
scale factor when the material advantage is small and not much
material remains.

Retire NoPawnsSF array. Pawnless endgames without a bishop will
now be scored higher. Pawnless endgames with a bishop pair will
be scored lower. The effect of this is hopefully small.

Consistent results both at short TC (fixed games):
ELO: -0.00 +-2.1 (95%) LOS: 50.0%
Total: 40000 W: 7405 L: 7405 D: 25190

And long TC (fixed games):
ELO: 0.77 +-1.9 (95%) LOS: 78.7%
Total: 39690 W: 6179 L: 6091 D: 27420

bench: 7213723
2014-01-18 17:22:54 +01:00
Stefan Geschwentner 53ab32ef0b Introduce 'follow up' moves
When we have a fail-high of a quiet move, store it in
a Followupmoves table indexed by the previous move of
the same color (instead of immediate previous move as
is in countermoves case).

Then use this table for quiet moves ordering in the same
way we are already doing with countermoves.

These followup moves will be tried just after countermoves
and before remaining quiet moves.

Passed both short TC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 10350 W: 1998 L: 1866 D: 6486

And long TC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 14066 W: 2303 L: 2137 D: 9626

bench: 7205153
2014-01-14 09:24:35 +01:00
Ralph Stößer 402a7ae151 Ad-hoc shelter rule
This hacky rule allows to get an about right eval out of this position:
r2qk2r/ppp2p2/2npbn2/2b1p3/2P1P1P1/2NB1PPp/PPNP3K/R1BQ1R2 b kq - 0 13

And, more importantly, passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 6239 W: 1249 L: 1127 D: 3863

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 38371 W: 6165 L: 5888 D: 26318

bench: 8183238
2014-01-12 22:48:08 +01:00
Marco Costalba 3d58092ec1 Retire KBBKN endgame
As pointed out by Joona, Lucas and otehr people in
the forum, this endgame is not a known, there are many
positions where it takes more than 50 moves to claim the
win and becasue exact rules is not possible better to
retire and allow the search to workout the endgame for us.

bench: 8502826
2014-01-12 22:32:41 +01:00
Henri Wiechers db05b1f9f5 Rename Position::hidden_checkers to check_blockers
No functional change.
2014-01-12 04:10:46 +09:00
Henri Wiechers 262c380c4b Position::gives_check - use ci.ksq
Also remove a couple of local variables while
there.

No functional change.
2014-01-09 07:38:04 +09:00
Marco Costalba 6a6fd0b5f5 Fix early stop condition
While editing original Uri's messy patch
I have incorrectly simplified the logic
condition. Here is the correct original
version, as it was tested.

bench: 8502826
2014-01-09 06:58:25 +09:00
Ralph Stoesser f14cd1bb89 Retire easy move
Remove the easy move code and add the condition to
play instantly if only one legal move is available.

Verified there is no regression at 60+0.05
ELO: 0.17 +-1.9 (95%) LOS: 57.0%
Total: 40000 W: 6397 L: 6377 D: 27226

bench: 8502826
2014-01-08 23:57:06 +09:00
Uri Blass a5869d8d25 Stop earlier if iteration is taking too long
If we are still at first move, without a fail-low and
current iteration is taking too long to complete then
stop the search.

Passed short TC:
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 26030 W: 4959 L: 4785 D: 16286

Long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 18019 W: 2936 L: 2752 D: 12331

And performed well at 40/30
ELO: 4.33 +-2.8 (95%) LOS: 99.9%
Total: 20000 W: 3480 L: 3231 D: 13289

bench: 8502826
2014-01-08 23:45:55 +09:00
renouve 45dbd9cd03 Retire grain size code
Seems useless at long TC.

Tested at 60+0.05
ELO: 2.98 +-2.2 (95%) LOS: 99.6%
Total: 30440 W: 4934 L: 4673 D: 20833

And at 120+0.05
ELO: 2.50 +-2.6 (95%) LOS: 97.1%
Total: 19633 W: 2848 L: 2707 D: 14078

bench: 8502826
2014-01-08 23:22:17 +09:00
Marco Costalba a646f74e6a Assorted grammar fixes
Mainly from Lyudmil Antonov and
one from Henri Wiechers and Louis Zulli.

No functional change.
2014-01-07 14:30:41 +09:00
Joona Kiiski 1fee23a598 Tweak King PST tables
First tested with 50K games at very short TC of 5+0.05
ELO: 3.11 +-2.0 (95%) LOS: 99.9%
Total: 49665 W: 10941 L: 10497 D: 28227

Then retested with usual SPRT at short TC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 16875 W: 3198 L: 3049 D: 10628

And at long TC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 5890 W: 985 L: 857 D: 4048

bench: 7800379
2014-01-07 13:41:16 +09:00
Marco Costalba 1574428f64 Fix a typo
Spotted by Isaac H. Dunn.

No functional change.
2014-01-06 01:22:44 +01:00
Pablo Vazquez 0118623495 Remove duplicated code
Introduce update_stats() and remove correspondng
duplicated code.

No functional change.
2014-01-05 14:10:29 +01:00
H. Felix Wittmann 8454d871ec Ensure move_importance() is non-zero
In case ply is very high, function will round
to zero (although mathematically it is always
bigger than zero). On my system this happens at
movenumber 6661.

Although 6661 moves in a game is, of course,
probably impossible, for safety and to be locally
consistent makes sense to ensure returned value
is positive.

Non functional change.
2014-01-02 13:01:24 +01:00
shane31 153309e287 Scale eval when down to only one pawn
Passed both short TC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 11921 W: 2346 L: 2208 D: 7367

And long TC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 21002 W: 3395 L: 3197 D: 14410

bench: 7602383
2014-01-02 12:44:46 +01:00
Marco Costalba c9dcda6ac4 Update copyright year
No functional change.
2014-01-02 01:49:18 +01:00
Marco Costalba 29e0d8caa7 Simplify move_importance(): take 3
Use pow() of a negative number instead of 1/x

No functional change.
2014-01-01 13:43:58 +01:00
Marco Costalba a795187c50 Further simplify move_importance()
Function move_importance() is already always
positive, so we don't need to add a constant
term to ensure it.

Becuase move_importance() is used to calculate
ratios of a linear combination (as explained in
previous patch), result is not affected. I have
also verified it directly.

No functional change.
2014-01-01 13:35:11 +01:00
H. Felix Wittmann 92faa74dfa Simplify move_importance()
Drop a useless parameter. This works because ratio1 and ratio2
are ratios of linear combinations of thisMoveImportance and
otherMovesImportance and so the yscale cancels out.

Therefore the values of ratio1 and ratio2 are independent
of yscale and yscale can be retired.

The same applies to yshift, but here we want to ensure
move_importance() > 0, so directly hard-code this safety
guard in function definition.

Actually there are some small differences due to rounding errors
and usually are at most few millisecond, that's means below 1% of
returned time, apart from very short intervals in which a difference
of just 1 msec can raise to 2-3% of total available time.

No functional change.
2014-01-01 12:58:10 +01:00
Marco Costalba c5d478b923 Rename pawn chain to connected
The flag raises also in case of a pawn duo, i.e.
when we have two adjacent pawns on the same rank,
and not only in case of a chain, i.e. when the two
pawns are on a diagonal line.

See this for a reference:
http://en.wikipedia.org/wiki/Connected_pawns

Renaming suggested by Ralph.

No functional change.
2014-01-01 10:56:57 +01:00
Gary Linscott 9b1d594456 Remove bishop pin bonus
Shows no regression at LTC after 20K games:

ELO: 0.03 +-2.7 (95%) LOS: 51.0%
Total: 20608 W: 3252 L: 3250 D: 14106

bench: 7516178
2013-12-31 15:27:52 +01:00
Arjun Temurnikar 71440cf77b Retire KingExposed[] array
And merge its values into KPSQT table.

Passed blazingly fast both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 5348 W: 1091 L: 971 D: 3286

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 3029 W: 530 L: 415 D: 2084

bench: 8702197
2013-12-31 12:05:22 +01:00
Henri Wiechers 082fbf4264 Remove asymmThreshold stale comment
No functional change.
2013-12-30 10:34:20 +01:00
Marco Costalba f7742669cb Retire asymmThreshold
Verified with 40K games at long TC does not regress:
ELO: 1.74 +-1.9 (95%) LOS: 96.2%
Total: 39624 W: 6402 L: 6203 D: 27019

bench: 7762310
2013-12-30 01:27:57 +01:00
Matt Sullivan 59a9bc9351 Retire MoveImportance[]
Use a skew-logistic function to replace the
MoveImportance[] array.

Verified it does not regress at fixed number
of games both at short TC:
LLR: -2.91 (-2.94,2.94) [-1.50,4.50]
Total: 39457 W: 7539 L: 7538 D: 24380

And long TC:
ELO: -0.49 +-1.9 (95%) LOS: 31.0%
Total: 39358 W: 6135 L: 6190 D: 27033

bench: 7335588
2013-12-29 10:33:39 +01:00
Stefan Geschwentner 8ca80cb0f1 Fine tune previous patch
Passed short TC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 18331 W: 3608 L: 3453 D: 11270

And scored above 50% on a very long test in long TC
LLR: -2.97 (-2.94,2.94) [0.00,6.00]
Total: 51533 W: 8181 L: 8047 D: 35305

bench: 7335588
2013-12-27 18:46:49 +01:00
Marco Costalba 14aebe2b7c Further simplify previous patch
Use a single XOR instead of NEGATE + AND

No functional change.
2013-12-26 12:08:23 +01:00
Stefan Geschwentner cf0a2a26a9 Bonus for file distance of the outermost pawns
In endgame it's better to have pawns on both wings.
So give a bonus according to file distance between left
and right outermost pawns.

Passed both short TC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 39073 W: 7749 L: 7536 D: 23788

And long TC
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 6149 W: 1040 L: 910 D: 4199

bench: 7665034
2013-12-25 21:31:41 +01:00
Ralph Stößer 899a2c033e Loosened trigger condition for king safety
Reduce eval discontinuity becuase now we kick in
king safety evaluation in many more cases.

Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 8708 W: 1742 L: 1613 D: 5353

And long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 6743 W: 1122 L: 990 D: 4631

bench: 6835416
2013-12-23 20:55:30 +01:00
Chris Caino 8aa4f3fde4 Increase pawn king attack weight
Tighter lower bound for pawn attacks so to
activate king safety in some cases like here:

6k1/2B3p1/2Pp1p2/2nPp3/2Q1P2K/P2n1qP1/R6P/1R6 w

Original patch by Chris, further simplified by
Jörg Oster.

Passed both short TC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 30171 W: 5887 L: 5700 D: 18584

And long TC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 20706 W: 3402 L: 3204 D: 14100

bench: 7607562
2013-12-23 20:52:12 +01:00
Gary Linscott 26689d8c2a Faster and simplified threat eval
Add a bonus according if the attacking
pieces are minor or major.

Passed both short TC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 13142 W: 2625 L: 2483 D: 8034

And long TC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 18059 W: 3031 L: 2844 D: 12184

bench: 7425809
2013-12-19 18:52:34 +01:00
Marco Costalba f196c1bad8 Further simplify Makefile
No functional change.
2013-12-17 10:16:00 +01:00
Marco Costalba e460ab74ad Reformat Makefile
No functional change.
2013-12-17 10:02:14 +01:00
Lucas Braesch f5727deee3 Remove threat move stuff
A great simplification that shows no regression
and it seems even a bit scalable.

Tested with fixed number of games:

Short TC
ELO: 0.60 +-2.1 (95%) LOS: 71.1%
Total: 39554 W: 7477 L: 7409 D: 24668

Long TC
ELO: 2.97 +-2.0 (95%) LOS: 99.8%
Total: 36424 W: 5894 L: 5583 D: 24947

bench: 8184352
2013-12-15 09:43:29 +01:00
Marco Costalba b96079f86b Sync history and counter moves updating
Change updating rule after a TT hit to match
the same one at the end of the search.

Small change in functionality, but we want to
have uniform rules in the code.

bench: 7767864
2013-12-10 07:05:06 +01:00
Lucas Braesch 86347100a5 Update History and Counter move on TT hit
We already update killers so it is natural to extend to
history and counter move too.

Passed both short TC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 52690 W: 9955 L: 9712 D: 33023

And long TC
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 5555 W: 935 L: 808 D: 3812

bench: 7876473
2013-12-10 06:57:06 +01:00
Ralph Stößer 8e9d4081ee Research at intermediate depth if LMR is very high
After a fail high in LMR, if reduction is very high do
a research at lower depth before teh full depth one.
Chances are that the re-search will fail low and the
full depth one is skipped.

Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 11363 W: 2204 L: 2069 D: 7090

And long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 7292 W: 1195 L: 1061 D: 5036

bench: 7869223
2013-12-09 08:03:47 +01:00
Marco Costalba 4630ab5743 More work on Bitboards::init()
No functional change.
2013-12-07 12:32:18 +01:00
Marco Costalba 1ff5ce8863 More readable init of MS1BTable[]
Because now it uses lsb(), the BSFTable[] must be
already initialized.

No functional change.
2013-12-07 11:35:26 +01:00
Marco Costalba b71418defa Further simplify Bitboards init()
No functional change.
2013-12-07 10:57:05 +01:00
Marco Costalba 47b89f2e37 Clarify definition of capture_or_promotion()
No functional change.
2013-12-06 10:43:17 +01:00
Arjun Temurnikar 431c3ac485 Even more spelling fixes
No functional change.
2013-12-06 09:03:24 +01:00
Arjun Temurnikar 190aea4cdc Assorted spelling/grammar/captitalization
No functional change.
2013-12-04 23:30:37 +01:00
Chris Caino f026517e5e Micro-optimise dangerous condition
Since all ENPASSANT moves are now considered dangerous, this
change of order should give a slight speedup.

Also simplify futilityValue formula.

No functional change.
2013-12-04 17:51:25 +01:00
Marco Costalba b71cedb2b0 Retire TheirHalf[]
We avoid to use an ad-hoc table at the cost of a
relative_rank() call in advanced_pawn_push().

On my 32 bit system it is even slightly faster (on 64bit
may be different). This is the speed in nps alternating
old and new bench runs:

new

368890
368825
369972

old

367798
367635
368026

No functional change.
2013-12-04 17:45:09 +01:00
Chris Caino 69a14554ee Broader condition for dangerous pawn moves
Instead of a passed pawn now we just require the pawn to
be in the opponent camp to be considered a dangerous
move. Added some renaming to reflect the change.

Passed both short TC test
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 10358 W: 2033 L: 1900 D: 6425

And long TC
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 21459 W: 3486 L: 3286 D: 14687

bench: 8322172
2013-12-04 17:19:45 +01:00
Marco Costalba 2408243cf4 Shrink Position::is_draw()
No functional change.
2013-12-03 11:40:31 +01:00
Marco Costalba 342fd6385b Remove redundant argument from hidden_checkers()
No functional change.
2013-12-03 11:15:39 +01:00
Marco Costalba e6c9ce6358 Small improvment to Position::fen()
No functional change.
2013-12-03 10:53:21 +01:00
Jerry Donald c7e7d9217b Re-fix a comment
No functional change.
2013-12-03 08:50:12 +01:00
Jerry Donald a8af78c833 Another round of spelling fixes
And also renamed a loop variable while there.

No functional change.
2013-12-02 23:51:29 +01:00
Richard Lloyd 13a73f67c0 Big assorted spelling fixes
No functional change.
2013-12-02 20:29:35 +01:00
Jerry Donald 500b9b0eb3 Assorted spelling fixes
No functional change.
2013-12-02 18:41:30 +01:00
Marco Costalba f99cb3dc27 Rename CASTLE to CASTLING
It is call 'castling move', not 'castle move'

Noticed while reading DiscoCheck sources.

No functional change.
2013-12-01 11:16:47 +01:00
Marco Costalba dd4e5db2be Simplify a condition in gives_check()
Now that aligned() is quite fast we can skip
some logic.

No functional change.
2013-12-01 10:09:30 +01:00
Marco Costalba 5f2bf91ad1 Rename Bitboards print to pretty
To align to same named Position function and
avoid using std::cout directly.

Also remove some stale <iostream> include while
there.

No functional change.
2013-11-30 11:32:49 +01:00
Marco Costalba 034a2b04f2 Rewrite some bitboard init code
And move the static function Position::attacks_from() to
bitboard code renaming it attacks_bb()

No functional change.
2013-11-30 11:02:56 +01:00
Daylen Yang 6ea5dc294c Makefile improvements for compiling on OS X
Add a Mac SSE4.2 target. Also change the Mac OS X minimum version to
10.6. Rationale: 97% of Macs run at least 10.6, version 10.9 is now
free, and using 10.6 as the minimum version gives a small 5% boost in
benchmark speed over versions using 10.0 as the minimum version.

Finally, enable Clang’s Link Time Optimization when compiling for the
Mac.

No functional change.
2013-11-30 00:09:17 +01:00
Marco Costalba 8f5deaea61 Restore development version
bench: 8596156
2013-11-29 10:50:43 +01:00
Marco Costalba c5bb9b9da9 Stockfish DD
Stockfish bench signature is: 8596156
2013-11-29 10:23:14 +01:00
Kelly Wilson 67e5581e37 Add support for PPC 64bit on Linux
In particular Debian Linux-3.9.8-1- PPC64

No functional change.
2013-11-29 10:06:54 +01:00
Joona Kiiski 3ede7daab3 Generate Qsearch checks only at depth 0
An old idea retested at SPRT(0, 3) with 60+0.05 TC:
LLR: 2.95 (-2.94,2.94) [0.00,3.00]
Total: 98872 W: 15549 L: 15123 D: 68200

This is a very small elo increase patch so it really
stresses the limits of fishtest.

bench: 8596156
2013-11-24 10:26:49 +01:00
Marco Costalba dbd6156fce Revert previous fix
It seems to intorduce a regression when tested
with 3 threads at 15+0.05:

ELO: -2.26 +-2.2 (95%) LOS: 2.4%
Total: 30000 W: 4813 L: 5008 D: 20179

bench: 8331357
2013-11-19 07:20:50 +01:00
Hongzhi Cheng 691ed425ba Get correct excluded moves for split nodes
Tested setting FakeSplit to true and running

./stockfish bench 128 2

There is a different signature with and without
the patch so it affects functionality but
only in SMP case.

bench: 8331357
2013-11-18 16:41:49 +01:00
Marco Costalba c376ffce0f Revert previous patch
It seems a regression at 15+0.05:
ELO: -4.82 +-2.1 (95%) LOS: 0.0%
Total: 40000 W: 7181 L: 7736 D: 25083

bench: 8331357
2013-11-17 23:47:18 +01:00
Marco Costalba 917944e9c5 Fix an assert in SMP case
SMP case is very tricky and raises an assert in stage_moves():

assert(stage == KILLERS_S1 || stage == QUIETS_1_S1 || stage == QUIETS_2_S1)

So rewrite the code to just return moves[] when we are sure
we are in quiet moves stages.

Also rename stage_moves to quiet_moves to reflect that.

No functional change (but needs testing in SMP case)
2013-11-17 10:24:25 +01:00
Marco Costalba d9c7cad630 Retire quietsSearched[]
Use MovePicker moves[] to access already tried
quiet moves. A bit of care shall be taken
to avoid calling stage_moves() when we are still
at ttMove stage, because moves are yet to be
generated. Actually our staging move generation
makes this code a bit more tricky than what I'd
like, but removing an ausiliary redundant
array like quietsSearched[] is a good thing.

Idea by DiscoCheck

bench: 9355734
2013-11-17 09:51:04 +01:00
Marco Costalba 9763c69fa5 Simplify generate<EVASIONS>
Use the newly introduced LineBB[] to simplify this
super hot-path function.

Verified with perft we don't have any speed regression, although
the number of squares removed is less than before in case of
contact check.

Insipred by DiscoCheck implementation.

Perft numbers are the same, but we have an harmless functional
change due to reorder of moves, because now some illegal moves
are no more detected at generation time, but in the search.

bench: 8331357
2013-11-11 19:53:19 +01:00
Gregor Cramer 555d9a8711 Faster castling in Chess960 case
Only rook attackers has to be considered, all other attackers are
already handled in the lines above.

No functional change.
2013-11-11 15:55:08 +01:00
Joona Kiiski b9768b8bc5 Reintroduce gains
This seems a die hard idea :-)

Passed both short TC
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 17485 W: 3307 L: 3156 D: 11022

And long TC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 38181 W: 6002 L: 5729 D: 26450

bench: 8659830
2013-11-11 08:46:11 +01:00
Jörg Oster 4ef6b2c32a Remove opposed flag for doubled pawns
Actually, it is not used, as both arrays have the
same values. Some local tests in either direction
showed no improvement.

Also some minor corrections in the comments.

No functional change.
2013-11-10 17:21:59 +01:00
Marco Costalba 1d18647e73 Rename squares_aligned()
Rename to the shorter but still
clear aligned()

No functional change.
2013-11-10 17:14:46 +01:00
Marco Costalba a518d5d3ad Simplify squares_aligned()
Use newly introduced LineBB[]

No functional change.
2013-11-10 12:05:19 +01:00
Chris Caino 091aff0445 Evaluate mobility of pinned pieces exactly
Previously some squares could be "incorrectly" awarded
to a pinned piece.

e.g. in 3k4/1q6/3b4/3Q4/8/5K2/B7/8 b - - 0 1 the black
bishop get 4 squares too many and the white queen gets 6.

Passed both short TC.
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 4871 W: 934 L: 817 D: 3120

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 38968 W: 6113 L: 5837 D: 27018

bench: 9282549
2013-11-10 11:52:38 +01:00
Chris Caino 3ed86ed3f9 Remove RedundantMajor
But compensate by reducing rook and queen
value by 53 = (160 / 3)

Material imbalances are affected as follows:

       Red. Major   Rook  Queen  Total
QRR      +160      -2*53    -53     +1
QR       +160        -53    -53    +54
RR       +160      -2*53      0    +54
R           0        -53      0    -53
Q           0          0    -53    -53

so that the imbalance changes by at most 54 + 53 = 107 units.
This corresponds to appromximately 3.5cp in the final evaluation.

Verified with fixed number 40000 games at both short
and long TC it does not regress.

Short TC 15+0.05
ELO: 1.93 +-2.1 (95%) LOS: 96.6%
Total: 40000 W: 7520 L: 7298 D: 25182

Long TC 60+0.05
ELO: -0.33 +-1.9 (95%) LOS: 36.5%
Total: 39663 W: 6067 L: 6105 D: 27491

bench: 6703846
2013-11-10 09:48:49 +01:00
Marco Costalba e4d34e1815 Fix printing of incorrect PV in some cases
As, Gary (that analyzed the bug) says:

SF does not print a PV when the original best move fails low,
we hit our time allowance, and stop the search.  The output from
the SF search is below.  It was failing low on Ne1 at depth 34.
Then, we get bestmove Qd3, but no PV change.

info depth 34 seldepth 45 score cp 38 upperbound nodes 483484489 nps 15464575 time 31264 multipv 1 pv f3e1 h5h4 e1d3 h4g3 f2g3 a6f6 f1f6 e7f6 d1a4 f6e7 a1f1 d8f8 a4b3 b7b6 b3c2 f7f6 c2a4 h3g5 b2b3 g5f7 a4c6 f7d6 h1g2 f6f5 e4f5 d6f5
info depth 34 seldepth 45 score cp 38 upperbound nodes 483484489 nps 15464575 time 31264 multipv 1 pv f3e1 h5h4 e1d3 h4g3 f2g3 a6f6 f1f6 e7f6 d1a4 f6e7 a1f1 d8f8 a4b3 b7b6 b3c2 f7f6 c2a4 h3g5 b2b3 g5f7 a4c6 f7d6 h1g2 f6f5 e4f5 d6f5
info depth 34 seldepth 47 score cp 30 upperbound nodes 2112334132 nps 17255517 time 122415 multipv 1 pv f3e1 h5h4 d1a4 a6f6 e1d3 d8f8 a4c2 h4g3 f2g3 f6f1 a1f1 h7g8 b2b3 f7f6 a3a4 b7b6
info depth 34 seldepth 47 score cp 30 upperbound nodes 2112334132 nps 17255517 time 122415 multipv 1 pv f3e1 h5h4 d1a4 a6f6 e1d3 d8f8 a4c2 h4g3 f2g3 f6f1 a1f1 h7g8 b2b3 f7f6 a3a4 b7b6
info nodes 18235667001 time 969824
bestmove e2d3 ponder c8d7

Looking at the code, if we hit Signals.stop, we return from id_loop
before printing any PV.  It is possible for us to have resorted the
RootMove list though, which will change the move that is actually
played.

No functional change.
2013-11-09 19:05:43 +01:00
Marco Costalba 42caebfaa5 Fix compile in debug mode
No functional change.
2013-11-09 18:41:51 +01:00
Lucas Braesch eed508b444 Futility pruning simplification
1/ eval margin and gains removed:
16bit are now free on TT entries, due to the removal of eval margin. may be useful
in the future :) gains removed: use instead by Value(128). search() and qsearch()
are now consistent in this regard.

2/ futility_margin()
linear formula instead of complex (log(depth), movecount) formula.

3/ unify pre & post futility pruning
pre futility pruning used depth < 7 plies, while post futility pruning used
depth < 4 plies. Now it's always depth < 7.

Tested with fixed number of games both at short TC:
ELO: 0.82 +-2.1 (95%) LOS: 77.3%
Total: 40000 W: 7939 L: 7845 D: 24216

And long TC
ELO: 0.59 +-2.0 (95%) LOS: 71.9%
Total: 40000 W: 6876 L: 6808 D: 26316

bench 7243575
2013-11-09 10:17:27 +01:00
Marco Costalba 343544f3f7 Revert "Retire eval margin and gains"
This reverts commit ecd07e51d0.

Patch was incorrect and partial. It will be reapplied in
the correct form.

bench: 9189063
2013-11-07 22:32:13 +01:00
Gary Linscott 13d1f0ae43 Restrict mobility of pinned pieces
Passed both short TC:
LLR: 3.00 (-2.94,2.94) [-1.50,4.50]
Total: 54342 W: 10950 L: 10692 D: 32700

And long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 61976 W: 10654 L: 10251 D: 41071

This patch introduces a slowdown of 3.5 % !!!!!

bench: 7911558
2013-11-07 22:26:03 +01:00
Lucas Braesch ecd07e51d0 Retire eval margin and gains
1/ eval margin and gains removed:
 - gains removed by Value(128): search() and qsearch() now behave consistently!

2/ futility_margin()
 - testing showed that there is no added value in this weird (log(depth), movecount)
   formula, and a much simpler linear formula is just as good. In fact, it is most
   likely better, as it is not yet optimally tuned.
 - the new simplified formula also means we get rid of FutilityMargins[], its
   initialization code, and more importantly ss->futilityMoveCount, and the hacky
   code that updates it throughout the search().
 - the current formula gives negative futility margins, and there is a hidden interaction
   between the move coutn pruning formula and the futility margin one: what happens is
   that MCP is supposed to be triggered before we use the non-sensical negative futility
   margins.

3/ unify pre & post futility pruning
 - pre futility pruning (what SF calls value based pruning) used depth < 7 plies,
   while post futility pruning (what SF calls static null move pruning) used depth < 4 plies.
 - also the condition depth < 7 in pre futility pruning was not obvious, and it seemd
   to be depth < 16 (futility_margin() returns an infinite value when depth >= 7).

Tested with fixed number of games both at short TC:
ELO: 0.82 +-2.1 (95%) LOS: 77.3%
Total: 40000 W: 7939 L: 7845 D: 24216

And long TC
ELO: 0.59 +-2.0 (95%) LOS: 71.9%
Total: 40000 W: 6876 L: 6808 D: 26316

bench: 10206576
2013-11-07 19:46:51 +01:00
Chris Caino 52ae0efccf Two more parameters eliminated
RedundantRook and RedundantQueen replaced by simple
variable RedundantMajor. Also the SameColor coefficient
for Queen<->Queen has been set by definition to 0.

The remaining 5 parameters:

LinearCoefficients[ROOK]
LinearCoefficients[QUEEN]
QuadraticCoefficientsSameColor[ROOK][ROOK]
QuadraticCoefficientsSameColor[QUEEN][ROOK]
RedundantMajor

are sufficient to equate the material imbalances for the
5 common material configurations of R, RR, Q, QR and QRR
to any desired values simultaneously.

With the chosen parameters there should be no functional
change unless one side has more than 2 rooks or more
than 1 queen. For example bench from the start position
using the commands:

./stockfish
go depth 16

produces identical output except for one extra node
in the last iteration.

bench: 8198094
2013-11-07 19:20:24 +01:00
Chris Caino 53c04c0429 Zero more redundant coefficients
Coefficients for Bishop<->BishopPair and Bishop<->Bishop
are also pretty much redundant. By altering the values
in LinearCoefficients[] these coefficients can be zeroed
without changing the imbalance calculations in any position
with less than 3 bishops for one side.

bench: 7995098
2013-11-05 20:08:39 +01:00
Chris Caino 1064288b38 Zero redundant material imbalance terms
First coefficient in the SameColor array does an
equivalent job when folded into the LinearCoefficients
array.

All of the diagonal terms in the OppositeColor array
are redundant due to cancellation.

No functional change.
2013-11-05 20:08:39 +01:00
Joona Kiiski d34bb889b1 Test Easy Move if no BestMoveChanges
In case we find a very good move after a
troubled start, we don't return immediately
anymore.

Tested directly at long TC where it passed:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 13910 W: 2397 L: 2228 D: 9285

bench: 7995098
2013-11-02 11:34:42 +01:00
Marco Costalba a3a0df92a3 Set timer to a fixed interval
And remove a complex (and broken) formula.

Indeed previous code was broken in case of TC with big
time increments where available_time() was too similar
to total time yielding to many time losses, so for instance:

go wtime 2600 winc 2600
info nodes 4432770 time 2601 <-- time forfeit!

maximum search time = 2530 ms
available_time = 2300 ms

For a reference and further details see:

https://groups.google.com/forum/?fromgroups=#!topic/fishcooking/dCPAvQDcm2E

Speed tested with bench disabling timer alltogheter vs timer set at
max resolution, showed we have no speed regressions both in single
core and when using all physical cores.

No functional change.
2013-11-01 08:56:15 +01:00
Ralph Ster e8f9447b11 Use a formula for chain membership bonus
Passed both short TC:
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 5087 W: 1072 L: 951 D: 3064

And long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 28620 W: 5042 L: 4798 D: 18780

bench: 7995098
2013-10-31 06:13:30 +01:00
Marco Costalba 3cc47edf62 Tweak bishop pair and knight weight
A combo of two patches that failed SPRT with score
higher than 50% but togheter they succeed:

SPRT at 60+0.05
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 7312 W: 1276 L: 1139 D: 4897

bench: 8029334
2013-10-28 19:31:25 +01:00
Matthew Sullivan d454cd4216 Fix divide by zero bug in late game
If the game got late enough that move_importance(currentPly) * slowMover / 100
rounds to 0, then we ended up dividing 0 by 0 when only looking 1 move ahead.

This apparently caused the search to almost immediately abort and Stockfish
would blunder in long games. So convert thisMoveImportance to a double.

No functional change.
2013-10-27 08:03:58 +01:00
Marco Costalba 48f38f3092 Retire mirror()
Inline the only caller site.

No functional change.
2013-10-24 20:40:26 +02:00
Marco Costalba 281472e50e Prefer file_bb() to FileBB[]
No functional change.
2013-10-24 20:34:23 +02:00
Jörg Oster f011a5af11 Penalty for Knight when enemy pawns are few
This seems more a material imbalance topic,
anyhow test is good and so patch is applied
as is.

Passed both short TC:
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 17391 W: 3548 L: 3393 D: 10450

And long TC:
LLR: 3.00 (-2.94,2.94) [0.00,6.00]
Total: 34660 W: 5972 L: 5700 D: 22988

bench: 8291883
2013-10-24 20:11:33 +02:00
Marco Costalba 67b0da83da Further smplify pawn endgames
Dumb down a bit the code and trade some possible
speed (but this is far from hot path anyhow) for
some added readability for the layman.

No functional change.
2013-10-23 19:56:35 +02:00
Chris Caino 3674f18b97 Use flip_sq idea in endgame.cpp
The normalising transformation is computed all at
once by the helper function get_flip_sq and then
applied immediately to the relevant squares as soon
as they are loaded from the position class.

bench: 8350690
2013-10-23 16:00:49 +02:00
Chris Caino 72f7282ad4 Simplify futility move count formula
Simpler formula but introduces some slight changes if d >= 10

Original code grows like  0.225 * d^1.8
New code grows like       0.222 * d^1.8

Full list of values:

d old new diff
--------------
0 2 2 0
1 2 2 0
2 3 3 0
3 4 4 0
4 5 5 0
5 6 6 0
6 7 7 0
7 9 9 0
8 11 11 0
9 13 13 0
10 15 16 1
11 18 19 1
12 21 21 0
13 24 24 0
14 27 28 1
15 31 31 0
16 35 35 0
17 39 38 -1
18 42 42 0
19 47 46 -1
20 51 51 0
21 55 55 0
22 60 60 0
23 65 65 0
24 70 70 0
25 75 75 0
26 81 80 -1
27 87 86 -1
28 92 91 -1
29 98 97 -1
30 104 103 -1
31 111 109 -2

Test code:

int main() {

  for(int d=0; d<32; d++)
  {
     int a = int(3 + 0.3 * pow(double(d), 1.8)) * 3/4 + (2 < d && d < 5);
     int b = int(2.4 + 0.222 * pow(d + 0.0, 1.8));

     std::cout << d << " " << a << " " << b << " " << b-a << std::endl;
  }

  return 0;
}

bench: 8350690
2013-10-22 23:09:40 +02:00
Chris Caino fbfce2132a Simplify futility margins formula
New formula mathces the old formula until d = 45

Test code:

int main() {

  for(int d=1; d<=45; d++)
  {
     int a = int(log(double(d * d) / 2) / log(2.0) + 1.001);
     int b = int(2.9 * log(double(d)));

     if (a != b) std::cout << d << std::endl;
  }

  return 0;
}

bench: 8455956
2013-10-22 23:06:06 +02:00
Marco Costalba 2c825294ec Tweak again chain pawn bonus
This is the first chain bonus version
from Ralph that also passed both

Short TC:
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 23460 W: 4727 L: 4556 D: 14177

And long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 31858 W: 5497 L: 5240 D: 21121

And performed better against current
committed version, always at 60secs:

LLR: -2.94 (-2.94,2.94) [-3.00,3.00]
Total: 26301 W: 4477 L: 4580 D: 17244

This test was done by Leonid.

bench: 8455956
2013-10-22 17:47:16 +02:00
Marco Costalba f86d2aee29 Re-add "Further increase safe checks bonus"
After 40K games at 60 secs, result is still
not clear, but not a regression against SF 4

After
ELO: 50.11 +-2.1 (95%) LOS: 100.0%
Total: 40000 W: 10547 L: 4817 D: 24636

Before
ELO: 49.51 +-2.1 (95%) LOS: 100.0%
Total: 40000 W: 10483 L: 4821 D: 24696

So re-apply the patch to avoid to
special-case this one.

bench: 7403882
2013-10-22 17:33:11 +02:00
Marco Costalba 35ea39bed2 Restore behaviour after count<ALL_PIECES> fix
Because pos.count<ALL_PIECES>(Us) was always zero,
rewrite the formula as if this would still be
the case.

bench: 8510004
2013-10-22 17:27:58 +02:00
Ralph Stößer 97015afce8 Further improve chain pawn evaluation
Passed both short TC:
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 28299 W: 5854 L: 5667 D: 16778

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 9738 W: 1797 L: 1644 D: 6297

bench: 9294116
2013-10-20 23:41:40 +02:00
Marco Costalba f22a63ce67 Fix pos.count<ALL_PIECES>()
It was never updated !

Currently it only affects evaluate_passed_pawns()
and in particularly the rule to increase the bonus
if we have more non-pawn pieces. We could simply use
popcount() instead and avoid the little slowdown
in put_piece() and remove_piece(), but this would
leave a very subtle and tricky hole where people
are forced to remember that pos.count<ALL_PIECES>()
does not work. This is not obvious and so dangerous.

Thanks to Ronald de Man for spotting this.

bench: 7931424
2013-10-20 23:36:46 +02:00
Marco Costalba c08e7419a0 Fix build on Intel compiler
Due to a strange issue (bug?) the ternary
operator does not return a BitCountType for
icc, so revert to the expression.

The same patch was already applied in
9749f1f14c

Thanks to NssY Wanyonyi for pointing out
this.

No functional change.
2013-10-20 23:19:08 +02:00
Marco Costalba 67f91bc5ea Revert "Further increase safe checks bonus"
This reverts commit 4bc2374450 for
two reasons.

First regression testing shows almost equal
score:

Before the patch:
ELO: 49.75 +-2.5 (95%) LOS: 100.0%
Total: 27205 W: 7113 L: 3244 D: 16848

After the patch:
ELO: 48.87 +-2.9 (95%) LOS: 100.0%
Total: 20860 W: 5478 L: 2563 D: 12819

Second, and more sensible to me, this patch
increases safe check bonuses to 4 times their
original value (!) and considering:

- Values were already well tuned

- Values are highly critical

- King safety is highly critical, very TC
  dependent and very difficult to test

- Our testing coverage is partial (self-testing,
  blitz times)

I think is better to be safe than sorry and so
I revert the patch.

bench: 8440524
2013-10-20 10:04:43 +02:00
Ralph Stößer 4bc2374450 Further increase safe checks bonus
Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 10466 W: 2087 L: 1953 D: 6426

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 26334 W: 4540 L: 4310 D: 17484

And also proved stronger than a slightly
different patch, also succesful against master:

https://github.com/mcostalba/Stockfish/commit/dc6830a3b4ed12

But losing against current one in a match
at 60secs with SPRT [-3, 3]:

LLR: -2.96 (-2.94,2.94) [-3.00,3.00]
Total: 44484 W: 7360 L: 7463 D: 29661

bench: 9160831
2013-10-19 12:19:36 +02:00
Marco Costalba f5e872a0e3 Some evaluation code reshuffle
No functional change.
2013-10-18 09:49:38 -07:00
Jörg Oster 25cb851f8a Score chain pawn also by rank
Use the (rescaled) CandidatePassed[] table
that is already rank based.

Passed both short TC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 11048 W: 2272 L: 2135 D: 6641

And long TC
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 4116 W: 769 L: 645 D: 2702

bench: 8440524
2013-10-18 10:27:55 +02:00
Chris Caino 3cddb0c076 Simplification of KPsK function
Also the drawing criteria has been slightly loosened.
It now detects a draw if the king is ahead of all the
pawns and on the same file or the adjacent file.

bench: 7700683
2013-10-15 07:36:01 +02:00
Chris Caino 2bf18bfc63 Bug fix for KQKRPs endgame
This lost position 8/8/3q4/8/5k2/2P1R3/2K2P2/8 w - - 0 1
was previously evaluated as a draw.

The king and rook need to be correctly placed with
respect to the _same_ pawn.

(Note also that the check for the pawn being on RANK_2
in the old version is redundant: it must be on RANK_2 if
it hopes to protect a rook on RANK_3)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-10-15 07:34:29 +02:00
Ralph Stößer 5aeb907fa1 Double king safety weights
Good both at short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 5448 W: 1133 L: 1012 D: 3303

And at long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 40509 W: 6836 L: 6541 D: 27132

bench: 7700683
2013-10-14 23:24:29 +02:00
Chris Caino 0c68971c13 Remove a drawing rule from KBPsK function
The rule can be incorrect if the attacking king is
well placed e.g. 8/6K1/8/8/7k/1B6/7P/8 w - - 0 1

bench: 8279065
2013-10-14 19:55:07 +02:00
Marco Costalba d9be00342c Massive stronger/weaker renming
No functional change.
2013-10-14 19:38:08 +02:00
Chris Caino 027d85e82a Add helper function verify_material
Allows to remove a lot of assert code in endgames.

No functional change.
2013-10-14 19:23:57 +02:00
ceebo 3bc3c069f1 Add some knowledge for KRPKB endgame
bench: 8279065
2013-10-14 07:44:02 +02:00
ceebo e9366fa155 Improve KBPsK endgame
Better endgame with bishop and blocked g-pawn

bench: 8279065
2013-10-14 07:44:01 +02:00
Marco Costalba 549b5c478f Remove unuseful optimization in RKISS
Don't need a struct here. Speed test shows
result is teh same. Moreover RKISS is used
mainly at startup to compute magics, so
prefer to keep it simple...RKISS ;-)

Also some assorted triviality while there.

No functional change.
2013-10-13 03:35:17 -07:00
Joona Kiiski b15e148b5e Smoother transition for LMR
Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 12376 W: 2596 L: 2454 D: 7326

And long TC:
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 14798 W: 2584 L: 2409 D: 9805

bench: 8279065
2013-10-09 19:13:41 +02:00
Uri Blass bb83a417cb Increase slowmover and reduce instability
These two changes go in opposite directions and it
seems that the combination is stronger than original.

Here are the positive tests at various TC:

15+0.05
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 24561 W: 4946 L: 4772 D: 14843

60+0.05
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 15259 W: 2598 L: 2423 D: 10238

40/30
LLR: 2.96 (-2.94,2.94) [-3.00,3.00]
Total: 2570 W: 527 L: 422 D: 1621

Unfortunately there is also a bad result
with one sec time increment that needs
to be further investigated:

12+1
LLR: -2.97 (-2.94,2.94) [-3.00,3.00]
Total: 2694 W: 438 L: 543 D: 1713

bench: 8340585
2013-10-08 21:24:21 +02:00
Lucas Braesch 984ee9d05b Use TT refined value to stand pat
Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 17811 W: 3520 L: 3366 D: 10925

And long TC:
LLR: 2.95 (-2.94,2.94) [0.00,6.00]
Total: 30255 W: 5070 L: 4825 D: 20360

bench: 8340585
2013-10-08 19:51:08 +02:00
Lucas Braesch a0cc15ccbc Use double everywhere
Rationale:

- Speed of double and float is about the same (not on the hot path anyway)

- Double makes code prettier (no need to write 1.0f, just 1.0)

- Only practical advantage of float is to use less memory, but since we never
  store large arrays of double, we don't care.

No functional change.
2013-10-05 18:12:52 +02:00
Lucas Braesch 7f142d6817 Use prefix operators wherever possible
No functional change.
2013-10-05 18:10:43 +02:00
Marco Costalba bd1c3ed7e3 Add more depth/positions to bench
Increase bench default depth from 12 to 13 and
add 15 new endgame positions to have broader
coverage and also more reliable nps calulcation
used for fishtest framework.

Due to the new endgame positions, where nps is higher,
the total nps is increased of about 15%.

Thanks to Lucas and Jörg for the suggestions.

No functional change, but bench number is now:

bench: 8336338
2013-09-29 09:43:10 +02:00
Marco Costalba cca34e234c Drop 'is' prefix from query functions
Most but not all.

No functional change.
2013-09-28 06:47:59 -07:00
Marco Costalba ed95ad1c0e Fix build on Mac OS X
For some users -stack_size,0x4000 does not work,
so revert for now.

osX 10.6.8
gcc version 4.7.3 (MacPorts gcc47 4.7.3_2)

g++: error: unrecognized command line option '-stack_size,0x4000'
make[2]: *** [stockfish] Error 1
make[1]: *** [gcc-profile-make] Error 2
make: *** [profile-build] Error 2

No functional change.
2013-09-28 04:16:16 -07:00
Marco Costalba c65d67feb5 Revert "Use a per-thread array"
This reverts commit 800410eef1 and instead increases
stack size.

I went through the old emails with Daylen that reported the
crash issue on Mac OS X and was fixed by 0049d3f337.

It was reported default stack size for a thread in Mac OS X is 8
megabytes while the patch that we are reverting allows to reduce
stack size at max of about 217KB, so the reason for the crash was
only marginal in MAX_MOVES value. On those emails Daylen also
hinted how to increase stack size for Mac OS X to 16MB.

So prefer to increase stack size to 16MB instad of re-inventing
the wheel and do our home grown stack as we did with the patch
that we are now reverting (it will remain anyhow in git history
for documentation purposes).

No functional change.
2013-09-28 10:10:51 +02:00
Lucas Braesch bc6faf633e Simplify extensions
Unify extensions between PV and not PV nodes
and remove all but check extensions.

This is a simplification so tested at fixed number
of games where proved to not regress.

About 45k games at 15+0.05
ELO: 1.23 +-2.0 (95%) LOS: 88.5%
Total: 45643 W: 9107 L: 8946 D: 27590

About 45k games at 60+0.05
ELO: 1.07 +-1.8 (95%) LOS: 87.8%
Total: 46786 W: 7728 L: 7584 D: 31474

bench: 3172206
2013-09-28 09:54:22 +02:00
Reuven Peleg 8d1c1074d5 Simplify tte use condition
No functional change.
2013-09-27 09:40:48 +02:00
Raminder Singh e654209211 Fix best move lookup bug
If the uci option 'Best Book Move' is set to true the lookup still
returns a move at random instead of the move with the highest
weight.

No functional change.
2013-09-27 09:04:24 +02:00
Marco Costalba b742a3f29a Increase MAX_MOVES to 256
This should be enough for any legal position, even
the handcrafted ones, like the one presented by Reuven:

1Q5R/4Q1K1/B1Q5/B4Q2/N2Q4/pQ4Q1/pn2Q3/krQ4R w - -

Where currently we crash. This reverts the patch
0049d3f337 of 8/4/2012 where stack
was shrinked due to crashes while in deep analysys.

No functional change.
2013-09-27 08:59:03 +02:00
Marco Costalba 800410eef1 Use a per-thread array for generated moves
This greately reduces stack usage and is a
prerequisite for next patch.

Verified with 40K games both in single and SMP
case that there are no regressions.

No functional change.
2013-09-27 08:44:36 +02:00
Jean-Francois Romang 7b2cda95d9 Update disabled warnings for Intel compiler
No functional change.
2013-09-23 08:11:43 +02:00
Jean-Francois Romang c2cefa6de0 Replace -O3 with -fast for intel compiler
No functional change.
2013-09-23 08:11:14 +02:00
Ralph Stößer d7f5f15d69 Reduce negative quiets by ONE_PLY / 2
Passed both short TC:
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 3402 W: 708 L: 593 D: 2101

And long TC:
LLR: 2.93 (-2.94,2.94) [0.00,6.00]
Total: 23379 W: 3972 L: 3759 D: 15648

bench: 3529630
2013-09-23 08:08:52 +02:00
Marco Costalba 84906b83ec Final time management setup
This is an even safer setup proposed and tested
by Alexandre Meirelles.

Regression testing of 40K games at 10+0.05 show
result is stable both against current master:

ELO: -0.29 +-2.2 (95%) LOS: 39.7%
Total: 40000 W: 8010 L: 8043 D: 23947

and again original master (the one with smallest
time parameters):

ELO: 1.71 +-2.2 (95%) LOS: 93.8%
Total: 40000 W: 8325 L: 8128 D: 23547

Alexandre verified with LittleBlitzer time losses are
greately reduced with this setup:

Games Completed = 2100 of 3000 (Avg game length = 35.745 sec)

Settings = RR/128MB/15000ms+50ms/M 1000cp for 12 moves, D 150 moves/
Time = 39200 sec elapsed, 16800 sec remaining
 1.  Stockfish 190913             1091.5/2100    803-720-577      (L: m=313 t=1 i=0 a=406)    (D: r=278 i=91 f=136 s=8 a=64)    (tpm=212.5 d=14.75 nps=925427)
 2.  Houdini 2.0 w32              1008.5/2100    720-803-577      (L: m=250 t=299 i=0 a=254)    (D: r=278 i=91 f=136 s=8 a=64)    (tpm=204.1 d=12.04 nps=1326351)

No functional change.
2013-09-23 07:59:51 +02:00
Marco Costalba 274079990a Increase Emergency Move Time to 20
Goes in the direction of avoiding time losses and seems
equivalent after almost 40K games at super fast TC of 10+0.05

ELO: 2.61 +-2.2 (95%) LOS: 99.1%
Total: 39869 W: 8258 L: 7959 D: 23652

No functional change.
2013-09-19 07:26:36 +02:00
Marco Costalba 10cb19d534 Increase Emergency Move Time to 10
Goes in the direction of avoiding time losses and seems
equivalent after almost 40K games at super fast TC of 10+0.05

ELO: 2.41 +-2.3 (95%) LOS: 98.1%
Total: 37222 W: 7843 L: 7585 D: 21794

No functional change.
2013-09-17 16:32:39 +02:00
Marco Costalba d50b33cacd Fix a silly unstoppable eval bug
The logic is broken for black side because we get more bonus
for pawn in 7th rank than for pawn in 2nd rank!

Spotted by Reuven Peleg

bench:3884409
2013-09-16 23:59:37 +02:00
Joona Kiiski 77b5ee0117 Fix time parameters for blitz games
The ideal setting for super-blitz might be something like:

    "Emergency Base Time" = 50
    "Emergency Move Time" = 5

This would give a total emergency time buffer of:

    50 + 40 * 5 = 250 ms

This setup replaces the previous half cooked hack
"Don't blunder under extreme time pressure".

Test results are very good at super blitz, but keep good even
at 60 secs.

At 5+0.05
ELO: 24.30 +-2.4 (95%) LOS: 100.0%
Total: 37802 W: 10060 L: 7420 D: 20322

At 15+0.05
ELO: 13.41 +-2.9 (95%) LOS: 100.0%
Total: 22271 W: 4853 L: 3994 D: 13424

At 60+0.05
ELO: 5.30 +-3.2 (95%) LOS: 99.9%
Total: 16000 W: 2897 L: 2653 D: 10450

No functional change.
2013-09-16 09:07:47 +02:00
Marco Costalba af750bd2ef Rewrite unstoppable pawns evaluation
Instead of current code, give a bonus according to the frontmost
square among candidate + passed pawns.

This is a big simplification that removes a lot of accurate code
substituting it with a statistically based one using the common
'bonus' scheme, leaving to the search to sort out the details.

Results are equivalent but code is much less and, as an added bonus,
we now store candidates bitboard in pawns hash and allow this
info to be used in evaluation. This paves the way to possible
candidate pawns evaluations together with all the other pieces,
as we do for passed.

Patch passed short TC
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 16927 W: 3462 L: 3308 D: 10157

Then failed (quite quickly) at long TC
LLR: -2.95 (-2.94,2.94) [0.00,6.00]
Total: 8451 W: 1386 L: 1448 D: 5617

But when ran with a conclusive 40K fixed games at 60 secs it proved
almost equivalent to original one.

ELO: 1.08 +-2.0 (95%) LOS: 85.8%
Total: 40000 W: 6739 L: 6615 D: 26646

bench: 3884003
2013-09-16 08:57:37 +02:00
Reuven Peleg 21cbfafc03 Code style at passed pawn eval
No functional change.
2013-09-15 21:49:06 +02:00
Reuven Peleg d3947b2f3e Nicer operator declerations
No functional change.
2013-09-15 21:45:18 +02:00
Kojirion a71209868b Use pre-increment also for native types
Now that we use pre-increment on enums, it
make sense, for code style uniformity, to
swith to pre-increment also for native types,
although there is no speed difference.

No functional change.
2013-09-15 09:17:21 +02:00
Marco Costalba 7a1ff6d8ff Fix operator++ definition
ENABLE_OPERATORS_ON has incorrect definitions of
post-increment and post-decrement operators.

In particularly the returned value is the variable
already incremented/decremented, while instead they
should return the variable _before_ inc/dec.

This has no real effect because are only used in loops
and where the returned value is never used, neverthless
it is wrong. The fix would be to copy the variable to a
dummy, then inc/dec the variable, then return the dummy.

So instead, rename to pre-increment that can be implemented
without the dummy, actually the current implementation
it is already the correct pre-increment, with the only change
to return a reference (an l-value) and not a copy, so
to properly mimic the pre-increment on native integers.

Spotted by Kojirion.

No functional change.
2013-09-15 09:09:06 +02:00
Marco Costalba 82f6779c2e Don't blunder under extreme time pressure
We always attempt to keep at least this emergencyBaseTime
at clock. But if available time is very low it means that
we will force ourself to play immediately to satisfy the
emergencyBaseTime constrain and so leading to blunders.

Patch is good at short and very short TC (15secs and 5secs respectively)
LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 26590 W: 5426 L: 5245 D: 15919

LLR: 2.96 (-2.94,2.94) [-1.50,4.50]
Total: 5767 W: 1397 L: 1268 D: 3102

Instead seems has no influence at longer TC (60 secs)
LLR: -2.96 (-2.94,2.94) [0.00,6.00]
Total: 79862 W: 13623 L: 13339 D: 52900

So it is committed to have a broader testing but is
to be consider still EXPERIMENTAL and can be reverted
easily.

No functional change.
2013-09-15 07:59:09 +02:00
Marco Costalba 3abccdc82d Move classify_leaf() to c'tor in bitbases
No functional change.
2013-09-14 13:08:37 +02:00
Marco Costalba 8d6d0223bf Small touches to bitbase.cpp
Inspired by Lucas's code:

https://github.com/lucasart/chess/blob/master/src/kpk.cc

No functional change.
2013-09-14 11:19:12 +02:00
Reuven Peleg fc17d0de77 Increase passed bonus for having more pieces
Passed both short TC:
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 36463 W: 7575 L: 7365 D: 21523

And long TC:
LLR: 2.97 (-2.94,2.94) [0.00,6.00]
Total: 2953 W: 564 L: 446 D: 1943

bench: 3846852
2013-09-13 18:08:22 +02:00
Marco Costalba 27f2ce8f6e Revert "Move draw by material check"
Possible regression

bench: 4554579
2013-09-12 08:44:11 +02:00
Marco Costalba 45b0aea875 Revert "Fix random moves when time < 10ms"
Possible regression.

No functional change.
2013-09-12 08:38:19 +02:00
Marco Costalba 4803d5772c Extend checks more when below alpha
Passed both short TC:
LLR: 2.97 (-2.94,2.94) [-1.50,4.50]
Total: 8739 W: 1830 L: 1698 D: 5211

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 6716 W: 1238 L: 1101 D: 4377

bench: 4554576
2013-09-11 19:15:28 +02:00
Uri Blass 738c5595ad Extend checks more in losing positions
Passed both short TC:
LLR: 2.98 (-2.94,2.94) [-1.50,4.50]
Total: 3974 W: 860 L: 741 D: 2373

And long TC:
LLR: 2.96 (-2.94,2.94) [0.00,6.00]
Total: 16807 W: 2917 L: 2733 D: 11157

bench: 3767999
2013-09-11 09:15:47 +02:00
Reuven Peleg bebd6e16f6 Simplify unstoppable pawns evaluation
No functional change
2013-09-10 23:02:05 +02:00
Marco Costalba 49e110c52b Fix random moves when time < 10ms
In case we have less then 10ms to think as soon as
we wake up the timer, it immediately fires and calls
check_time() where due to condition:

elapsed > TimeMgr.maximum_time() - 2 * TimerResolution

the stop flag is set and search returns immediately, without
actually search anything.

Here the somewhat hacky fix is to start the timer after
at least one iteration as been completed.

No functional change.
2013-09-10 21:23:20 +02:00
Reuven Peleg 4d90aeb0ab More readable space mask
No functional change.
2013-09-10 19:18:10 +02:00
homoSapiensSapiens 03cd049c68 Change condition to use relative rank
No functional change
2013-09-10 00:47:31 +02:00
Marco Costalba 6ab8b9b6c6 Fix some comments in position.cpp
No functional change.
2013-09-08 06:28:53 -07:00
Marco Costalba 490f67a3f8 Move draw by material check
It is more natural to test this case among
others material distributions.

No functional change.
2013-09-08 06:11:35 -07:00
Marco Costalba 0515ad0fb0 Remove unreachable values in mobility table
The possible maximum mobility cardinality (plus one in case of
zero squares available) is:

- Knights: max. 8  squares -> max. 9  entries
- Bishops: max. 13 squares -> max. 14 entries
- Rooks:   max. 14 squares -> max. 15 entries
- Queen:   max. 27 squares -> max. 28 entries

So remove the extra entries in the table.

Spotted by Dariusz Orzechowski.

No functional change.
2013-09-07 18:25:24 +02:00
Marco Costalba bf51db2526 Fix warning: double to float truncation
MSVC 2013 says:
warning C4305: '*=' : truncation from 'double' to 'float'

No functional change.
2013-09-07 12:30:44 +02:00
Lucas Braesch 59702aca0d Singular extension at 8 plies also for PV nodes
Passed both short TC:
LLR: 2.96 (-2.94,2.94)
Total: 11451 W: 2455 L: 2282 D: 6714

And long TC
LLR: 2.96 (-2.94,2.94)
Total: 15813 W: 2907 L: 2723 D: 10183

bench: 3864419
2013-09-07 09:34:22 +02:00
Lucas Braesch c86eee3918 Union of 2 changes
Union of

- LMR >= 3 plies from Gary tests.stockfishchess.org/tests/view/522522960ebc595d328fcafd

- allows() tweak from Reuven tests.stockfishchess.org/tests/view/5225fa1c0ebc595d328fcb53

Both passed Step I and failed Step II.

Instead this union passed both short TC:
LLR: 2.95 (-2.94,2.94)
Total: 14525 W: 3063 L: 2874 D: 8588

And long TC
LLR: 2.94 (-2.94,2.94)
Total: 31075 W: 5566 L: 5308 D: 20201

bench: 4238160
2013-09-07 09:25:45 +02:00
Lucas Braesch 10b53e1c5e Do not prune useless checks in QS
Passed both SPRT tests in "simplification mode", so with
elo0: -3.00 alpha: 0.05 elo1: 3.00 beta: 0.05

Short TC:
LLR: 2.96 (-2.94,2.94)
Total: 6243 W: 1302 L: 1195 D: 3746

Long TC
LLR: 2.96 (-2.94,2.94)
Total: 22972 W: 4124 L: 4020 D: 14828

bench: 4633330
2013-09-05 18:50:16 +02:00
Marco Costalba a30d3571ca Revert "Fix check for bishop pair in material imbalance"
Idea is sound but implementation is partial. Ryan and Joona noticed that
    we leave an hole in material table. Also we got another report by an user
    of an odd behaviour. Namely, if you start stockfish and from the prompt
    give 'bench' you get 3453941, then if you run again bench you get 3453940.

    The reason is that two different positions with the same number of pieces,
    but one with a bishop pair and another without have the same material key.
    But after Eelco patch also different material imbalance and this yields
    to this issue.

    Restesting at long TC shows the patch does not really contribute at
    ELO improvement. Actually patch failed at long TC.

    LLR: -2.97 (-2.94,2.94)
    Total: 23109 W: 4104 L: 4092 D: 14913

    So revert.

    bench: 3453945
2013-09-05 06:34:48 +02:00
Reuven Peleg 457ac26de5 Rewrite backward pawn detection
Use the new backmost_sq() instead of a loop.

No functional change.
2013-09-03 20:11:00 +02:00
Eelco de Groot 679c2ea227 Fix check for bishop pair in material imbalance
Prefer pos.bishop_pair() to pos.count<BISHOP>(WHITE) > 1
because the first checks that the two bishops are on
different color squares.

Although the change seems to kick in only in very rare cases,
quite surprisingly it was able to pass SPRT test at short TC.

LLR: 2.95 (-2.94,2.94)
Total: 39818 W: 8174 L: 7956 D: 23688

bench: 3453941
2013-09-03 19:40:34 +02:00
Marco Costalba 9ff594c3a9 Rewrite KBBKN endgame
This was thought to be a draw but the bishops generally win. However,
it takes up to 66 moves. The position in the diagram was thought to be
a draw for over one hundred years, but tablebases show that White wins
in 45 moves. All of the long wins go through this type of semi-fortress
position. It takes several moves to force Black out of the temporary
fortress in the corner; then precise play with the bishops prevents Black
from forming the temporary fortress in another corner (Nunn 1995:265ff).

Before computer analysis, Speelman listed this position as unresolved,
but "probably a draw" (Speelman 1981:109).

bench: 3453945
2013-09-02 11:03:01 +02:00
Marco Costalba 849b089a63 Don't use lpthread for Android
Thanks to Peter Osterlund for the feedback.

No functional change.
2013-09-01 13:48:09 -07:00
Marco Costalba aee404f532 Improve ARM compatibility
STANDALONE-TOOLCHAIN.html in Android NDK says:

It is recommended to use the -mthumb compiler flag to force the generation
of 16-bit Thumb-1 instructions (the default being 32-bit ARM ones).

If you want to target the 'armeabi-v7a' ABI, you will need ensure that the
following two flags are being used:

  CFLAGS='-march=armv7-a -mfloat-abi=softfp'

Note: The first flag enables Thumb-2 instructions, and the second one
      enables H/W FPU instructions while ensuring that floating-point
      parameters are passed in core registers, which is critical for
      ABI compatibility. Do *not* use these flags separately!

Thanks to Peter Osterlund for pointout this doc and for showing me
an example Makefile to follow.

No functional change.
2013-09-01 09:18:37 -07:00
Uri Blass 0915f85895 Union of 2 changes that failed with good score
This is a union of 2 changes:

A tweak of recaptures limit from Joona Kiiski
http://tests.stockfishchess.org/tests/view/52166d7c0ebc59319a242400

and a tweak of move count pruning from Leonid Pechenik
http://tests.stockfishchess.org/tests/view/5217c7e60ebc59319a242456

The set passed both short TC at 30+0.05
LLR: 2.96 (-2.94,2.94)
Total: 18936 W: 3723 L: 3566 D: 11647

And the usual long TC at 60+0.05
LLR: 2.95 (-2.94,2.94)
Total: 48962 W: 8837 L: 8487 D: 31638

bench: 3453945
2013-09-01 08:07:21 -07:00
Marco Costalba 5e8bc6ac2a Assorted clean up in endgames
No functional change.
2013-09-01 07:39:04 -07:00
Marco Costalba 3e4dcaa06e Fix a bogus assert in allows()
Becuase castle is coded as "king captures the rook"
the to_sq(move), A1/8 or H1/8 is empty after the move,
leading to assert assert(p != NO_PIECE) in color_of().

Teach allows() asserts about castle and fix the crash.

Bug reported by Ryan Takker and tracked down by Tom Vijlbrief.

No functional change.
2013-08-30 16:42:18 +02:00
Marco Costalba 14f47c8ac6 Use frontmost_sq() and backmost_sq helpers
Should easier to read than the lsb() / msb() low
level functions.

No functional change.
2013-08-30 16:22:22 +02:00
Gary Linscott 5d90c149b5 Enable LMR for dangerous moves
Passed both short TC
LLR: 2.96 (-2.94,2.94)
Total: 5598 W: 1250 L: 1125 D: 3223

And long TC
LLR: 2.97 (-2.94,2.94)
Total: 16441 W: 3102 L: 2912 D: 10427

bench: 4620975
2013-08-29 23:02:18 +02:00
homoSapiensSapiens 4b9e338541 Bonus for rook behind a passed
If our rook is behind a passed pawn, all
squares are defended.

One of the longest tests to pass !

Passed both short TC
LLR: 2.97 (-2.94,2.94)
Total: 44560 W: 9518 L: 9281 D: 25761

And long TC
LLR: 2.96 (-2.94,2.94)
Total: 61348 W: 11618 L: 11192 D: 38538

bench: 3787694
2013-08-29 22:53:21 +02:00
homoSapiensSapiens a0cf424cfc Replace hardcoded 128 by constant
No functional change.
2013-08-29 13:59:49 +02:00
Gary Linscott aecdbfc4a0 Add lsb() overload
Helper to find least significant bit relative to
the given color.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-08-28 19:50:11 +02:00
Uri Blass e6482b7d97 Time management: move faster if PV is stable
Move faster but compensate by allocating more
time when the best move changes.

Passed short TC at 15+0.05
LLR: 2.93 (-2.94,2.94)
Total: 13895 W: 3030 L: 2882 D: 798

Long TC at 60+0.05
LLR: 2.96 (-2.94,2.94)
Total: 9266 W: 1777 L: 1624 D: 5865

At time increment 30+0.5
LLR: 2.96 (-2.94,2.94)
Total: 6703 W: 1238 L: 1134 D: 4331

And at fixed game number, longer TC 120+0.05
ELO: 5.17 +-2.8 (95%) LOS: 100.0%
Total: 19306 W: 3378 L: 3091 D: 12837

bench: 4728533
2013-08-26 10:29:58 -07:00
homoSapiensSapiens 6e6c5b6103 Simplify chain detection
No functional change.
2013-08-25 18:36:49 +02:00
homoSapiensSapiens 04fd7efdfa Simplify kf definition in shelter_storm()
No functional change.
2013-08-25 18:31:47 +02:00
Chris Caino 5e331f9618 Fix KBPK bug
With

position fen 7k/8/8/8/8/7P/6K1/7B w - - 0 1
go depth 25

The evaluation at depth 22 is not draw as it should be. The reason is that
when search reaches the position 8/6kP/8/8/8/3B4/6K1/8 w - - 0 1 if white plays
h8R or h8N then we get a position that is a "KNOWN_WIN" and is _not_ a check, so
futility pruning in qsearch kicks in and black may think that it is "futile"
to reply Kxh8 since, according to the logic of the code, it cannot raise the score
back towards a draw.

bench: 4728533
2013-08-24 10:08:03 +02:00
homoSapiensSapiens b9f5d1c6ff Simplify condition for backward pawn
No functional changes.
2013-08-22 14:39:08 +02:00
Marco Costalba c4533e0d94 Retire redundant endgames
The case of two lone kings on the board is already considered
by the "No pawns" scaling factor rules in material.cpp as is
KBK and KNK.

Moreover we had a small leak in endgames map because for
KK endgame it happens white and black material keys are the
same (both equal to zero), so when adding the black endgame in
Endgames::add() we were overwriting the already exsisting
white one, leading to a memory leak found by Valgrind.

So remove the endgames althogheter and rely on scaling
to correctly set the endgames value to a draw.

No functional change.
2013-08-22 13:13:06 +02:00
Joona Kiiski f39cf1b008 Use null move when depth >= 2 plies
Passed both short TC:
LLR: 2.96 (-2.94,2.94)
Total: 23725 W: 5031 L: 4855 D: 13839

And long TC:
LLR: 2.96 (-2.94,2.94)
Total: 15730 W: 2939 L: 2754 D: 10037

bench: 4729333
2013-08-22 09:06:48 +02:00
Marco Costalba c6baefb79d Restore development version
No functional change.
2013-08-21 08:41:47 +02:00
Marco Costalba 4d120ee02e Stockfish 4
Stockfish bench signature is: 4132374
2013-08-20 09:01:25 +02:00
Tom Vijlbrief f45eee318b Fix crash when reaching max ply
Bug introduced in 1b7223a53c that
updated the ss base stack without increasing
the dimension.

No functional change.
2013-08-19 16:53:46 +02:00
Tom Vijlbrief 8c2fd2170a Remove useless condition in KXK endgame
Because eval is never called when in check.

No functional change.
2013-08-19 08:55:17 +02:00
Leonid Pechenik 91c2c44fb1 Further tweak movecount pruning
Passed both short TC
LLR: 2.95 (-2.94,2.94)
Total: 15140 W: 3125 L: 2976 D: 9039

And long TC
LLR: 2.95 (-2.94,2.94)
Total: 17118 W: 3165 L: 2974 D: 10979

bench: 4132374
2013-08-18 09:13:57 +02:00
Marco Costalba 27e9fc1067 Normalize "pawn in front of minor" patch
No functional change.
2013-08-17 11:05:55 +02:00
homoSapiensSapiens e005270fb6 Use constants arguments where possible
No functional changes.
2013-08-16 09:57:21 +02:00
Marco Costalba 4f55ed14d3 Revert using exceptions
Due to crashes. It will be reapplied once
we understand what's happening.

No functional change.
2013-08-15 09:36:26 +02:00
homoSapiensSapiens a6c0ba2100 Simplify DistanceRingsBB init
Verified by same benchmark and picking some random values.

No functional change.
2013-08-14 10:53:43 +02:00
homoSapiensSapiens fc316cbca9 Some renaming in TT store()
No functional change.
2013-08-14 09:38:35 +02:00
Marco Costalba 11b1a76f35 Use exceptions to stop the search
Instead of classical flags, throw an
exception when we want to immediately halt
the search. Currently only one type
is used for both UCI stop and threads
cut off.

No functional change.
2013-08-14 08:29:57 +02:00
Tom Vijlbrief bd8f463b7e Bonus for a pawn in front of knight/bishop
Idea originated from a post of Don Dailey
on talkchess and reported by Eelco.

This is the last succesful attempt of a long
series of trials (as usually happens, the
'idea' alone is not enough).

Passed both short 15secs TC
LLR: 2.97 (-2.94,2.94)
Total: 7629 W: 1645 L: 1515 D: 4469

And long 60secs TC
LLR: 2.96 (-2.94,2.94)
Total: 10218 W: 1932 L: 1775 D: 6511

bench: 4944581
2013-08-13 14:20:02 +02:00
Ryan Takker 4d14f97482 Remove Now Unneeded Help Text
With the new automatic setting of split depth
instead of a default, the user no longer needs
guidance on setting the split point.

Also threads now defaults to one.

No functional change.
2013-08-13 07:36:33 +02:00
Marco Costalba 15616ad199 Don't set Search::RootColor in Eval::trace
Search::RootColor is a global parameter set
before to start a search, it is not something
trace() should change.

This patch allows to add trace() calls, for
debugging, inside search itself without altering
the bench, and also ensures that the values
returned by trace() and evaluate() are fully
equivalent.

No functional change.
2013-08-11 07:02:50 +02:00
Marco Costalba 94a3608ab9 Fix GrainSize rounding error
The rounding formula is different between
positive and negative scores due to the
GrainSize/2 term that is asymmetric.

So use truncation instead of rounding. This
guarantees that evaluation is rounded to zero
in the same way for both positive and negative
scores.

Found with position's flip

bench: 4634244
2013-08-10 17:11:13 +02:00
Marco Costalba 5769509d72 Fix 'improving' condition
Because VALUE_NONE is 30002, it happens that
after a check the next move is never an improving
one.

After this patch bench signature is independent from
VALUE_NONE actual value.

bench: 4303194
2013-08-09 08:21:55 +02:00
Marco Costalba fff6b9f061 Increase LMR when not improving
Apply to LMR the same Eelco's idea
applied to move count pruning.

This is the result of a series of
attempts started by Thomas Kolarik.

Passed both short TC
LLR: 2.95 (-2.94, 2.94)
Total: 5675 W: 1241 L: 1117 D: 3317


And long TC:
LLR: 2.95 (-2.94, 2.94)
Total: 8748 W: 1689 L: 1539 D: 5520

bench: 4356801
2013-08-08 10:28:48 +02:00
Marco Costalba 56d2c3844a Further tweak Position::flip
No functional change.
2013-08-05 14:44:06 +02:00
Marco Costalba 23b6809f3d Rewrite flip() to use FEN string manipulation
Instead of dealing directly with internal parameters
just "flip" the FEN string and set the position from
that.

No functional change.
2013-08-05 12:58:14 +02:00
Marco Costalba f31847302d Streamline time computation
No functional change.
2013-08-03 18:30:43 +02:00
Marco Costalba b1a4a18d63 Update polyglot.ini with new "Min Split Depth" default
No functional change.
2013-08-03 16:41:18 +02:00
Dan Schmidt f7096ea7ce Refactor do_castle()
Not a real functional change, but bench changed due to different piecelist
reordering. To verify it a temporary my canonicalize_rooks function was
written as follows. It just ensures that the rook on the "smaller" square
is listed first.

void Position::canonicalize_rooks(Color c)
{
   if (pieceCount[c][ROOK] == 2)
   {
      Square s0 = pieceList[c][ROOK][0];
      Square s1 = pieceList[c][ROOK][1];
      if (s0 > s1)
      {
         pieceList[c][ROOK][0] = s1;
         pieceList[c][ROOK][1] = s0;
         index[s0] = 1;
         index[s1] = 0;
      }
   }
}

With this both bench and the test on Chess960 positions

./stockfish bench 128 1 8 Chess960.epd file > /dev/null

Gives same result.

bench: 4424151
2013-08-03 16:18:28 +02:00
Joona Kiiski a16ba5bbd1 Retire cpu_count()
Set threads number always to 1 at startup and let the
user explicitly to chose the number of threads.

Also preserve the useful behavior of automatically set
"Min Split Depth" according to the requested threads,
indeed this parameter is too technical for a casual user,
so, when left to zero, we set it on a sensible value.

No functional change
2013-08-02 16:48:25 +02:00
Marco Costalba 408e6ee9b6 Further factor out position update code
Along the lines of previous patch.

No functional change
2013-08-01 16:32:46 +02:00
Dan Schmidt 7b4f5c8f72 Factor out pieceList updating code
The new Position methods add_piece, move_piece, and remove_piece
now manage the member variables pieceList, pieceCount, and index,
and 9 blocks of code in Position that used to manipulate those
data structures by hand now call the new methods.

There is a slightly slowdown (< 1%) on Clang and on perft,
but the cleanup compensates the little speed loss.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-08-01 15:50:19 +02:00
Marco Costalba 55948623e7 Rework Thread hierarchy
Introduce ThreadBase struct that is search
agnostic and just handles low level stuff,
and derive all the other specialized classes
form here.

In particular TimerThread does not hinerits
anymore all the search related stuff from Thread.

Also some renaming while there.

Suggested by Steven Edwards

No functional change.
2013-07-31 18:35:52 +02:00
Marco Costalba 4d46d29efe Fix a race at thread creation
At thread creation start_routine() is called
and from there the virtual function idle_loop()
because we do this inside Thread c'tor, where the
virtual mechanism is disabled, it could happen that
the base class idle_loop() is called instead.

The issue happens with TimerThread and MainThread
where, at launch, start_routine calls
Thread::idle_loop instead of the derived ones.

Normally this bug is hidden because c'tor finishes
before start_routine() is actually called in the
just created execution thread, but on some platforms
and in some cases this is not guaranteed and the
engine hangs.

Reported by Ted Wong on talkchess

No functional change.
2013-07-31 18:35:32 +02:00
Marco Costalba cc608a7aba Tidy up Position::pretty
No functional change.
2013-07-29 19:33:30 +02:00
Marco Costalba 1f40cd6d02 Small renaming
No functional change.
2013-07-29 19:32:59 +02:00
Marco Costalba 28bc8ed462 Speed up move generation
Pass the color as template parameter
to generate_all()

Speedup of 1,3% in perft and 2,5% in bench !

No functional change.
2013-07-29 19:01:50 +02:00
Eelco de Groot 5ee16a180a Increase pruning if evaluation is not improving
Add an additional set of margins to movecount pruning
to be used when static evaluation is getting worse
than previous move.

Here are the margins table with changing
depth (fm0 not improving, fm1 improving):

    d: 0, fm0: 3, fm1: 3
    d: 1, fm0: 4, fm1: 4
    d: 2, fm0: 6, fm1: 6
    d: 3, fm0: 7, fm1: 10
    d: 4, fm0: 11, fm1: 15
    d: 5, fm0: 15, fm1: 21
    d: 6, fm0: 21, fm1: 29
    d: 7, fm0: 27, fm1: 37
    d: 8, fm0: 35, fm1: 47
    d: 9, fm0: 42, fm1: 57
    d: 10, fm0: 51, fm1: 68
    d: 11, fm0: 60, fm1: 81
    d: 12, fm0: 70, fm1: 94
    d: 13, fm0: 81, fm1: 108
    d: 14, fm0: 92, fm1: 123
    d: 15, fm0: 104, fm1: 139

Good at both short TC

LLR: 2.97 (-2.94,2.94)
Total: 11502 W: 2503 L: 2361 D: 6638

And long TC

LLR: 2.98 (-2.94,2.94)
Total: 7189 W: 1421 L: 1277 D: 4491

bench: 4364793
2013-07-29 01:21:21 +02:00
Marco Costalba d30dfc084c Annotate an unlikely condition
No functional change.
2013-07-27 11:34:15 +02:00
Marco Costalba 6373e88b5b Fix an assert in KBK endgame
The endgame king + minor vs king is erroneusly
detected as king + minor vs king + minor

Here the fix is to detect king + minor earlier,
in particular to add these trivial cases to
endgame evaluation functions.

Spotted by Reuven Peleg

bench: 4727133
2013-07-27 08:25:45 +02:00
Tom Vijlbrief 7487eb0dca Rewrite pawn shield and storm code
Passes quickly both short TC:
LLR: 2.95 (-2.94,2.94)
Total: 5755 W: 1349 L: 1222 D: 3184

And long TC:
LLR: 2.95 (-2.94,2.94)
Total: 2744 W: 628 L: 505 D: 1611

bench: 4727133
2013-07-26 00:12:46 +02:00
Marco Costalba 2067a99c07 Fix a typo in bitboard.h
Introduced by previous patch.

Spotted by Joerg Oster

No functional change.
2013-07-25 07:44:27 +02:00
homoSapiensSapiens 002062ae93 Use #ifndef instead of #if !defined
And #ifdef instead of #if defined

This is more standard form (see for example iostream file).

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-07-24 19:49:17 +02:00
Marco Costalba 4064ee5406 Simplify captures ordering
A big simplification and removing of useless code.

Finished at 50% both at short TC (with SPRT) than
at long TC at fixed number of games:
ELO: -0.14 +-3.4 (95%) LOS: 46.8%
Total: 15206 W: 2836 L: 2842 D: 9528

bench: 5059948
2013-07-24 07:53:32 +02:00
Marco Costalba b0fd2b6b98 Revert "Halve king eval margin"
This reverts commit 4b3a0fdab0.

As Gary says: " It failed when I tried it at long TC previously, and only
barely passed this time.  Some anecdotal evidence is that it hurts vs other
engines as well (the Lightspeed rating list showed a 16 elo drop from previous
best version - still +- 5 error bars on both, but that's still significant)"

I also agree that if we have some doubts (like in this case) it is better to
be safe than sorry.

bench: 4615572
2013-07-24 07:46:25 +02:00
Ryan Schmitt d0bc951835 Tune pawn PSQT values
Reduces the influence of PSQT for entries such as
the extended center and the h-file.

Passed both short TC test:
LLR: 2.95 (-2.94,2.94)
Total: 23919 W: 5207 L: 5029 D: 13683

And long TC one:
LLR: 2.96 (-2.94,2.94)
Total: 5762 W: 1108 L: 974 D: 3680

Bench: 4617880

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-07-24 07:41:51 +02:00
Reuven Peleg 73131e7c78 Use arrow operator instead of * and .
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-07-22 20:22:40 +02:00
Reuven Peleg 1cc18d8a7a Better condition in is_pseudo_legal()
Simplify occupied destination condition.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-07-22 20:02:31 +02:00
Marco Costalba c45c6d308f Small touches in move generation
No functional change.
2013-07-21 11:01:24 +02:00
Marco Costalba f73bb438aa Some renaming in MovePicker
No functional change.
2013-07-21 09:55:08 +02:00
Marco Costalba 71dd8a333f Rewrite and simplify SEE
This very speed critical code was full of clever (!)
tricks and subtle details.

So I have rewritten it in a more straithforward way
and, as very often happens, result is even faster
than original.

No functional change.
2013-07-21 01:04:29 +02:00
Marco Costalba 9207baed65 Revert "Fix critical SEE bug (take 2)"
This reverts commit 3e95800814

For some reason it fails the short TC test:
LLR: -2.96 (-2.94,2.94)
Total: 20033 W: 4214 L: 4265 D: 11554

bench: 4769737
2013-07-20 18:45:38 +02:00
Marco Costalba b191df5ebe Revert "Yet another attempt at signature-build"
Still broken on OS X

No functional change.
2013-07-20 15:15:31 +02:00
Marco Costalba 3e95800814 Fix critical SEE bug (take 2)
It is somewhat unbilievable but our SEE is broken !

    If the first SEE move is a king capture and square is
    defended then SEE continues instead of breaking.

    The bug shows only on normal SEE, not see_sign() so
    probing with a:

    dbg_hit_on_c(slIndex==1, captured == KING);

    reports just a tiny:

    Total 3465656 Hits 6646 hit rate (%) 0

    Bug was there since Retire seeValues[] and move PieceValue[] out of Position of 26/6/2011 (!)
    although for some reason didn't show immediately, indeed the
    bougous patch was a "No functional change" (!!)

    bench: 4699504
2013-07-20 14:24:47 +02:00
Marco Costalba 2ed56f4d5f Revert all the SEE stuff
The speed up seems to introduce some
functionality change.

Revert to original master for now.

bench: 4769737
2013-07-20 14:20:33 +02:00
Marco Costalba 7b0b463720 Yet another attempt at signature-build
This one should work on all flavours of sed

Suggested by by Louis Zulli

No functional change.
2013-07-20 14:05:04 +02:00
Marco Costalba a6c5b4c6fb Fix critical SEE bug
It is somewhat unbilievable but our SEE is broken !

If the first SEE move is a king capture and square is
defended then SEE continues instead of breaking.

The bug shows only on normal SEE, not see_sign() so
probing with a:

dbg_hit_on_c(slIndex==1, captured == KING);

reports just a tiny:

Total 3465656 Hits 6646 hit rate (%) 0

Bug was there since 351ef5c85b of 26/6/2011 (!)
although for some reason didn't show immediately, indeed the
bougous patch was a "No functional change" (!!)

bench: 4793754
2013-07-20 13:37:12 +02:00
Marco Costalba 0504a6975d Speedup see()
And rename next_attacker() SEE helper

This very simple patch is able to speed up
bench run of almost 2% !

No functional change.
2013-07-20 12:34:35 +02:00
Marco Costalba a5b5a91512 Fix signature-build under OSX
On OS X when you use -i an extension for the in-place
substitution a backup files is required.

http://stackoverflow.com/questions/4247068/sed-command-failing-on-mac-but-works-on-linux

So rewrite to make sed flushing sign.txt in one go and avoid
using -i option.

Reported by Louis Zulli

No functional change.
2013-07-20 02:38:14 +02:00
Reuven Peleg 1a8f63a896 Microptimize gives_check() for castling case
Without patch we have 333198 nps, with patch 334249.

A very small +0.3%, not a lot manily becuase this is a
side path that is taken very few times.

Anyhow idea is correct becuase first 'quick' condition
has an hit rate of about 95%.

No functional change.
2013-07-19 17:07:54 +02:00
Marco Costalba ee5514b8fd Small simplification in space eval scoring
No functional change.
2013-07-19 11:13:18 +02:00
Marco Costalba 99e547f4cb Rename MoveStack to ExtMove
Stack has no meaning here, while ExtMove (extended move),
better clarifies that we have a move + a score.

No functional change.
2013-07-19 10:27:58 +02:00
Marco Costalba 110644d918 Better document what we skip when in check
No functional change.
2013-07-19 09:37:31 +02:00
homoSapiensSapiens 4b3a0fdab0 Halve king eval margin
But still keep the same original
margin for score.

Passed both short TC test
LR: 2.95 (-2.94,2.94)
Total: 3710 W: 845 L: 726 D: 2139

And long TC
LLR: 2.95 (-2.94,2.94)
Total: 57859 W: 10939 L: 10532 D: 36388

bench: 4769737

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-07-19 08:16:39 +02:00
Marco Costalba 05e31c5e5f Drop grep and tr dependency in Makefile
Use only sed to get the bench signature.

No functional change.
2013-07-15 21:39:06 +02:00
Marco Costalba 46fdb14b2f Don't use __builtin_expect
Partially revert previous patch and use
unlikey() just as code annotation.

Actually it is better to rely on a profiler for branch prediction:

http://blog.man7.org/2012/10/how-much-do-builtinexpect-likely-and.html

"In fact, even when only one in ten thousand values is nonzero,
we're still at only roughly the break-even point"

No functional change,
2013-07-15 21:09:06 +02:00
Marco Costalba cbb1a8ed31 Better annotate unlikely conditions
And in case of gcc we win also a small
speed optimization due to better branch
prediction.

No functional change.
2013-07-15 21:01:02 +02:00
Reuven Peleg a6c5f60caa Simplify a condition in refutes()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-07-15 20:40:49 +02:00
Marco Costalba 9518cc3254 Update 'make help'
No functional change.
2013-07-14 12:23:28 +02:00
Marco Costalba b0a177bc67 Add signature-profile-build make target
Extend patch 3f64a2af6a to profile builds.

here the make command is:

make signature-profile-build ARCH=xxx COMP=xxx

No functional change.
2013-07-14 11:57:06 +02:00
Marco Costalba 5b7b330616 Retire engine Tag
It is somewhat redundant and could make SF
name too long, so use just Version, in case
of a signature build Version will be set to
'sig-xxx' otherwise, if left empty, we fall
back on usual date stamp.

No functional change.
2013-07-14 11:13:13 +02:00
Marco Costalba 3f64a2af6a Add signature-build make target
When compiling with:

make signature-build ARCH=xxx COMP=xxx

After binary has been roduced, it will be run to
get the signature 'stockfish bench' and this
number will be used as Version, so that it
will be easy to track the original sources
from a binary.

No functinal change.
2013-07-14 10:59:25 +02:00
Marco Costalba 9749f1f14c Fix build on Intel compiler
Due to a strange issue (bug?) the ternary
operator does not return a BitCountType for
icc, so revert to the expression used
before bcbc9bfd1f

No functional change.
2013-07-13 23:13:30 +02:00
Marco Costalba 4ede49cd85 Fully qualify memset and memcpy
And other trivial touches.

Ispired by Lucas's DiscoCheck

No functional change.
2013-07-13 18:01:13 +02:00
Tom Vijlbrief 6960f41e03 Retire enoughMaterial + lower trapped rook threshold
Here speed up is the name of the game.

Speed up is gained:

- Removing the useless enoughMaterial code

- Limiting trapped rook evaluation to where it counts

Tested at long TC:
LLR: 2.97 (-2.94,2.94)
Total: 10061 W: 1948 L: 1790 D: 6323

bench: 4558173
2013-07-13 18:01:03 +02:00
Marco Costalba bf90499fc3 A useless assignment found by Clang’s static analyzer
Warning is: "Value stored to 'xxx' is never read" and
it is raised in SpNode case.

No functional change.
2013-07-13 16:57:03 +02:00
Marco Costalba 404c4122ce Fix build with MSVC 2013
Also add an assert hinted by MSVC code analysis tool.

No functional change.
2013-07-13 13:03:09 +02:00
Marco Costalba 2a0bbb9faa Fix printing of PV info: take 2
Now last PV line is printed twice, fix that.

No functional change.
2013-07-13 07:43:50 +02:00
Marco Costalba 128e097d03 Fix printing of PV info
It was erroneusly skipped after the
aspiration window rework.

Reported by Eelco.

No functional change.
2013-07-12 23:42:42 +02:00
Marco Costalba c1264e46d0 Rename some UCI options
Thanks to Don, Miguel, Louis and the other people
of talkchess forum for the suggestion:

http://www.talkchess.com/forum/viewtopic.php?t=48612

Also sync polyglot.ini with current UCI options

No functional change.
2013-07-11 16:07:10 +02:00
Marco Costalba 366f6b0dab Fix a crash with depth 1 perft
Bug recently introduced in e215a88cdd

No functional change.
2013-07-11 07:23:48 +02:00
Marco Costalba 58aee9a9ea Don't IID when in check also in PvNodes
This tiny functional change allows to
nicely simplify things.

Performed at 50% in short TC:
LLR: -0.43 (-2.94,2.94)
Total: 46406 W: 9681 L: 9565 D: 27160

And succesfully passed long TC reverse test:
LLR: -2.95 (-2.94,2.94)
Total: 4945 W: 858 L: 937 D: 3150

bench: 4507230
2013-07-09 19:03:11 +02:00
Marco Costalba 4b703b1429 Revert previous patch
Unfortunatly a reverse test at long TC failed:

master^ vs master
LLR: 1.37 (-2.94,2.94)
Total: 33682 W: 6294 L: 6071 D: 21317

So becuase short TC score is 50% there is a good
possibility patch is not scalable.

So revert it.

bench: 4507288
2013-07-09 08:04:12 +02:00
Marco Costalba 62d38f0196 Simplify "fail high upon reduction" in null search
Do not use threat move to detect the condition. This
let us to retire the big allows() function.

Test at short TC was within 50% score:
LLR: -2.95 (-2.94,2.94)
Total: 38272 W: 7941 L: 7940 D: 22391

To be verified with reverse long TC

bench: 4191565
2013-07-08 07:23:30 +02:00
Marco Costalba 7e575512ae Skip node-level cut-off tests when in check
No functional change.
2013-07-07 13:39:58 +02:00
Marco Costalba a55fb76dcc Simplify aspiration window code
Here the main difference is that now we center
aspiration window on last returned score. This allows
to simplify handling of mate scores.

We have done a reversed SPRT tests, where we wanted to
verify if master is stronger than this patch.

Long TC: master vs this patch (reverse test)
LLR: -2.95 (-2.94,2.94)
Total: 37992 W: 7012 L: 6920 D: 24060

bench: 4507288
2013-07-03 18:59:23 +02:00
Marco Costalba 838255ef91 Workaround github issue
Temporary revert aspiration window patch
so to be visible to everybody: it will be
re-applied with next patch

No functional change (together with next one)
2013-07-03 18:58:23 +02:00
Marco Costalba 6fbe027da0 Simplify aspiration window code
Here the main difference is that now we center
aspiration window on last returned score. This allows
to simplify handling of mate scores.

We have done a reversed SPRT tests, where we wanted to
verify if master is stronger than this patch.

Long TC: master vs this patch (reverse test)
LLR: -2.95 (-2.94,2.94)
Total: 37992 W: 7012 L: 6920 D: 24060

bench: 4507288
2013-07-03 09:06:03 +02:00
Marco Costalba ddcb572c41 Disable flto when debugging
Link-time optimization does not work well with
generation of debugging information:

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

Reported by Louis Zulli

No functional change.
2013-07-03 08:21:21 +02:00
Marco Costalba 12c0dfc113 Revert "Remove confusing optimization"
This reverts commit e05c80a088.

we gain a speed up of 1.5% under gcc !

No functional change.
2013-07-02 20:12:57 +02:00
Marco Costalba db53883f06 Merge branch 'master' into aspiration
bench: 4507288
2013-07-02 07:27:08 +02:00
Marco Costalba 13ffb08136 Revert "Increase earlier aspiration window size"
This reverts commit b88bc7b766.
2013-07-02 07:25:39 +02:00
Marco Costalba 2d82db1d14 Entering a pawn endgame is no more dangerous
A simplification of the 'dangerous' definition.

Seems neutral at reverse test at long TC

master vs patch
LLR: -2.96 (-2.94,2.94)
Total: 16974 W: 3122 L: 3139 D: 10713

bench: 4689029
2013-07-02 07:24:17 +02:00
Marco Costalba b88bc7b766 Increase earlier aspiration window size
bench: 4377851
2013-07-01 19:29:38 +02:00
Marco Costalba e074a19f5c Merge branch 'master' into aspiration 2013-07-01 19:25:23 +02:00
Marco Costalba b8930d0c26 Fix a stale comment
No functional change.
2013-06-30 13:12:04 +02:00
Marco Costalba 4fc7734547 Simplify search results update
Also some rename while there.

No functional change.
2013-06-30 12:49:39 +02:00
Marco Costalba 92dcbfa658 Reorder conditions according to their frequency
This should minimize useless tests.

No functional change.
2013-06-30 11:35:53 +02:00
Marco Costalba b50eb6bea8 Center aspiration window on last returned score
bench: 4428212
2013-06-30 11:14:02 +02:00
Marco Costalba 6f079ae720 Simplify aspiration window loop
Don't open the window in case we find a mate score: this
will be takes care with next patch.

No functional change.
2013-06-30 10:54:09 +02:00
Marco Costalba 203fdc9ac1 Use calloc() in TranspositionTable::set_size()
Function calloc() already initializes memory to
zero, so avoid calling clear() afterwards.

Also some renaming while there (inspired by DiscoCheck).

No functional change.
2013-06-29 11:23:07 +02:00
Marco Costalba 17d41b3861 Fix some stale comments
No functional change.
2013-06-23 13:19:03 +02:00
Marco Costalba 8cff4862a6 Move SquareDistance[] to bitboard.cpp
No functional change.
2013-06-23 13:13:13 +02:00
Marco Costalba 908d98820b Don't explicitize enum values when not needed
Compiler will chose the correct values in sequential
order for you.

Also move file and rank bitboards definitions to
bitboard.h

No functional change.
2013-06-23 11:30:40 +02:00
Marco Costalba a4c11b71ac Retire in_front_bb(Color c, Square s) overload
Explciitly call rank_of() in the few places where
it is used.

No functional change.
2013-06-23 10:16:43 +02:00
Marco Costalba b2fadf32aa Retire ThisAndAdjacentFilesBB[]
It is unused. Also renamed attack_span_mask to
pawn_attack_span

No functional change.
2013-06-23 10:09:24 +02:00
Marco Costalba 378bcfe760 Simplify hidden_checkers()
De-templetize and pass color as function argument.
No speed change.

No functional change.
2013-06-23 09:03:40 +02:00
Marco Costalba fe2ed42661 Name functions along corresponding UCI commands
No functional change.
2013-06-22 12:46:03 +02:00
Marco Costalba e215a88cdd Micro-optimize perft
Avoid to call perft function when we just need to count
moves, at leaf nodes.

Speed up of almost 2%

No functional change.
2013-06-21 09:10:03 +02:00
Ryan Schmitt e95e69515a Include file attacks in 'major on pawn'
Passed both short TC:
LLR: 2.97 (-2.94,2.94)
Total: 57846 W: 12248 L: 11974 D: 33624

And long one:
LLR: 2.95 (-2.94,2.94)
Total: 9181 W: 1732 L: 1581 D: 5868

bench: 4609948
2013-06-19 07:22:10 +02:00
Reuven Peleg e05c80a088 Remove confusing optimization
Here we skip the call to pos.attacks_from<ROOK>(s) in the 98%
of cases, testing the first 2 members first. Unfortunatly
code is a bit triky and not clear. So we give up to the
speed optimization in exchange of more code clarity.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-06-17 18:12:15 +02:00
Reuven Peleg 7b31e81d77 Merge some if statements in pos_is_ok()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-06-17 18:02:59 +02:00
Marco Costalba c0964fc70f Remove redundant condition in probcut
When !ss->skipNullMove it is assured that excludedMove == MOVE_NONE

No functional change.
2013-06-17 09:30:59 +02:00
Marco Costalba cd782c11ec Rename piece_count and piece_list
No functional change.
2013-06-16 13:21:10 +02:00
Marco Costalba 5ea984ac35 Don't calculate pawnsOnSquares twice
And reformat some code while there.

No functional change.
2013-06-16 11:32:10 +02:00
Marco Costalba 1fd020a8ba Use move_pawns() in Pawns::probe
And rename some stuff.

No functional change.
2013-06-16 10:40:36 +02:00
Marco Costalba 02420d4670 Revert "Reduce more CUT nodes only if parent node is reduced"
This reverts commit d54e8a5955.

It was not proved with SPRT this tweak is stronger. So revert it
for now to follow fishtest guidelines.

bench: 5108393
2013-06-14 08:27:06 +02:00
Marco Costalba 2c7ab488a8 Fix description of TT entry
It was way outdated and wrong !

No functional change.
2013-06-14 08:21:02 +02:00
Marco Costalba d54e8a5955 Reduce more CUT nodes only if parent node is reduced
So when we are doing a LMR search at the parent ALL node.

This patch didn't prove stronger at 60" TC
LLR: -2.97 (-2.94,2.94)
Total: 22398 W: 4070 L: 4060 D: 14268

But, first, it scores at 50%, second (and most important for me) the opposite,
i.e. normal reduction when parent node is not reduced, seems very bad:
LLR: -2.95 (-2.94,2.94)
Total: 7036 W: 1446 L: 1534 D: 4056

According to Don, this idea of increased reduction of CUT nodes
works because if parent node is reduced, missing a cut-off due to
reduced depth search (meaning position is somehow tricky) forces
a full depth research at parent node, giving due insight in this
set of sensible positions.

IOW if we expect a node to fail-high at depth n, then we assume it
should fail-high also at depth n-1, if this doesn't happen it means
position is tricky enough to deserve a research at depth n+1.

bench: 4687419
2013-06-13 20:05:02 +02:00
Marco Costalba 4bebb15e94 Reduce more CUT nodes
We got a good result from this tweak, in line with
what was already found by Don Dailey.

At short TC:
LLR: 2.95 (-2.94,2.94)
Total: 13097 W: 2742 L: 2598 D: 7757

At long TC:
LLR: 2.97 (-2.94,2.94)
Total: 7281 W: 1408 L: 1265 D: 4608

bench: 5108393
2013-06-13 19:50:32 +02:00
Marco Costalba 3b8f66f8ac Introduce Cut/All node definitions
Follow Don Dailey definition of cut/all node:

"If the previous node was a cut node, we consider this an ALL node.
The only exception is for PV nodes which are a special case of ALL nodes.
In the PVS framework, the first zero width window searched from a PV
node is by our definition a CUT node and if you have to do a re-search
then it is suddenly promoted to a PV nodes (as per PVS search) and only
then can the cut and all nodes swap positions. In other words, these
internal search failures can force the status of every node in the subtree
to swap if it propagates back to the last PV nodes."

http://talkchess.com/forum/viewtopic.php?topic_view=threads&p=519741&t=47577

With this definition we have an hit rate higher than 90% on:

    if (!PvNode && depth > 4 * ONE_PLY)
        dbg_hit_on_c(cutNode, (bestValue >= beta));

And an hit rate of just 28% on:

    if (!PvNode && depth > 4 * ONE_PLY)
        dbg_hit_on_c(!cutNode, (bestValue >= beta));

No functional change.
2013-06-13 19:46:49 +02:00
Marco Costalba b6e9d901b0 Don't use std::vector::data()
It is a C++11 only function.

Reported by Eelco.

No functional change.
2013-06-13 07:42:43 +02:00
Marco Costalba 1b7223a53c Fix again early stop ss pointer
Fix was wrong becuase search starts from ss+1,
code is a bit tricky here, so rewrite in a way
to be more easy to read and understand.

Spotted by Eelco.

No functional change.
2013-06-09 23:36:46 +02:00
Marco Costalba de1dc4f2de Don't need to expose namespace Zobrist
It can be local to position.cpp

No functional change.
2013-06-09 23:27:07 +02:00
Marco Costalba a6e0f62a4f Zobrist::init() should be Position::init()
No functional change.
2013-06-09 13:54:38 +02:00
Marco Costalba 81e242a96d Convert pieceSquareTable to 3 dimensions
No functional change.
2013-06-09 13:10:21 +02:00
Marco Costalba dd1855eb2f More consistent 'piece' variable naming
No functional change.
2013-06-09 12:56:05 +02:00
Marco Costalba db4cd89cb8 Introduce operator~(Piece c)
Small syntactic sugar to reverse piece color.

No functional change.
2013-06-09 12:44:04 +02:00
Marco Costalba 7e95495b35 Retire psq_delta()
No functional change.
2013-06-09 12:32:16 +02:00
Marco Costalba 55eb7dd1e9 Use alpha instead of beta-1
It is more directly related to a fail-low.

No functional change.
2013-06-09 11:52:39 +02:00
Marco Costalba 902c0566a6 Fix incorrect 'ss' pointer in early stop check
The exclusion search used to verify one move is much
better than other shall be called with 'ss' and not
'ss+1'

No functional change.
2013-06-09 11:01:11 +02:00
Dariusz Orzechowski bc02cc0c8a Fix a typo
No functional change.
2013-06-08 11:01:28 +02:00
Marco Costalba 05c6f7a40b Fix search log when using skills
In case of we pick a sub-optimal move be
sure to print this, and not the best one
on seach log file.

Bug spotted by Guenther Demetz.

No functional change.
2013-06-08 10:56:20 +02:00
Marco Costalba 2a98042c21 Fix a crash when 'go' multiple times
Search is started after setting a position and
issuing UCI 'go' command. Then if we stop the search
and call 'go' again without setting a new position it
is assumed that the previous setup is preserved, but
this is not the case because what happens is that
SetupStates is reset to NULL, leading to a crash as
soon as RootPos.is_draw() is called because st->previous
is now stale.

UCI protocol is not very clear about requiring that a
position is setup always before launching a search,
so here we easy the life of GUI developers assuming
that the current state is preserved after returning
from a 'stop' command.

Bug reported by Gregor Cramer.

No functional change.
2013-06-01 16:19:42 +02:00
Marco Costalba 46409a7852 Assorted renaming in evaluation
And some reshuffle too.

No functional change.
2013-06-01 13:17:39 +02:00
jundery d8b266af8b Passed pawn tuning
A small number of tests with simulated
annealing at 15s indicated these values
may be better

And this is verified at long 60+0.05 TC
LLR: 2.95 (-2.94,2.94)
Total: 40658 W: 7821 L: 7501 D: 25336

bench: 4931544
2013-05-31 09:17:48 +02:00
Marco Costalba abb40777bf Shrink engine UCI name
Some GUI have problems with long names.

Reported by George Speight.

No functional change.
2013-05-27 17:43:38 +02:00
Marco Costalba 90abcac1c7 Add Pawn Structure also to polyglot.ini
No functional change.
2013-05-25 13:14:41 +02:00
Marco Costalba 7222f47350 Re-add "Pawn Structure" UCI option
And reshuffle the code to not special case
this parameter.

No functional change.
2013-05-25 12:38:14 +02:00
Marco Costalba eafb66e1aa More uniform tracing code
No functional change.
2013-05-25 12:01:50 +02:00
Uri Blass d4a02b135d Bunch of 3 small patches
This patch is the sum of:

- Grainsize of 4 instead of 8

- Removing "depth < DEPTH_ZERO"

- Change DEPTH_QS_RECAPTURES = -5 to -7

All the patches individually failed to pass SPRT but scored
around 50%.

Together they pass easily short TC:
LLR: 2.96 (-2.94,2.94)
Total: 4429 W: 964 L: 844 D: 2621

And with some difficult long TC of 60+0.05:
LLR: 2.95 (-2.94,2.94)
Total: 64133 W: 11968 L: 11532 D: 40633

bench: 4821467
2013-05-23 17:59:39 +02:00
Marco Costalba d3608c4e79 Microptimize MoveList loop
Add MOVE_NONE at the tail, this allows to loop
across MoveList checking for *it != MOVE_NONE,
and because *it is used imediately after compiler
is able to reuse it.

With this small patch perft speed increased of 3%

And it is also a semplification !

No functional change.
2013-05-19 22:00:49 +02:00
Marco Costalba 38cfbeeb50 Delay killers[] initialization
Most of the time we cut-off earlier, at captures, so this
results in useless work.

There is a small functionality change becuase 'ss' can change
from MovePicker c'tor to when killers are tried due, for
instance, to singular search.

bench: 4603795
2013-05-19 21:41:56 +02:00
Marco Costalba 77547a4ef1 Reduce countermoves less in LMR
Passed SPRT for both short TC 15+0.05:
LLR: 2.95 (-2.94,2.94)
Total: 17724 W: 3756 L: 3598 D: 10370

And long TC 60+0.05:
LLR: 2.95 (-2.94,2.94)
Total: 22672 W: 4232 L: 4011 D: 14429

bench: 4418832
2013-05-19 21:36:23 +02:00
Marco Costalba 8ceef92266 Mimic an iterator for looping across MoveList
Seems more conventional.

No functional change.
2013-05-19 13:28:25 +02:00
Joona Kiiski f7c013edd0 Use two counter moves instead of one
Very good at long 60"+0.05 TC
LLR: 2.95 (-2.94,2.94)
Total: 5954 W: 1151 L: 1016 D: 3787

[edit: slightly changed form original patch to avoid useless loop
 across killers when killer is MOVE_NONE]

bench: 4327405
2013-05-16 16:20:50 +02:00
Marco Costalba 148490f04c Rename Refutation to Countermove
Use proper naming according to:

http://chessprogramming.wikispaces.com/Countermove+Heuristic

The name of this idea is "Countermove Heuristic" and was
first introduced by Jos Uiterwijk in 1992

No functional change.
2013-05-15 20:59:56 +02:00
Uri Blass 7c6f346c90 Increased mobility array
Performed more or less well at short TC
LLR: 2.95 (-2.94,2.94)
Total: 50517 W: 9815 L: 9574 D: 31128

And a bit better at long TC
LLR: 2.96 (-2.94,2.94)
Total: 15564 W: 2805 L: 2624 D: 10135

bench: 4375253
2013-05-15 00:34:05 +02:00
Marco Costalba 1a34496761 Revert trapped rook bug fix
It seems that do  not limiting checking the
trapped rook only on rank 1 improves the
score.

At long TC
LLR: 2.97 (-2.94,2.94)
Total: 6581 W: 1346 L: 1204 D: 4031

bench: 4985012
2013-05-15 00:06:11 +02:00
Gary Linscott 049e5ca191 Minor bugfixes to refutation table
Don't update refutation table in case of
previous move is MOVE_NULL or MOVE_NONE
and don't try refutation if is already
a killer move.

Pass both short TC
LLR: 2.96 (-2.94,2.94)
Total: 4310 W: 953 L: 869 D: 2488

And long one
LLR: 2.95 (-2.94,2.94)
Total: 6707 W: 1254 L: 1184 D: 4269

bench: 4785954
2013-05-14 23:52:44 +02:00
Marco Costalba 19dd0de4ff Reformat previous patch
No functional change.
2013-05-13 20:42:44 +02:00
Joona Kiiski 8a61b030a6 Enable refuation table
Very good result both at short TC 15+0.05
LLR: 2.95 (-2.94,2.94)
Total: 2803 W: 596 L: 483 D: 1724

And at long TC 60+0.05
LLR: 2.95 (-2.94,2.94)
Total: 2862 W: 548 L: 431 D: 1883

bench: 4329221
2013-05-13 19:48:41 +02:00
Joona Kiiski c7e31d5aa8 Simple always overwrite Refutation table 2013-05-12 21:21:46 +01:00
Marco Costalba 818a3537a7 Use Them instead of ~Us
Unortunatly we have no guarantee that the call to
operator~(Color c) is resolved at compile time.

Perhaps the solution would be to use C++11 const_expr,
but for now simply use the good old-style ternary operator
that works as expected.

No functional change.
2013-05-11 11:49:44 +02:00
Marco Costalba bcbc9bfd1f Some code reformat in evaluate_pieces
No functional change.
2013-05-11 11:13:06 +02:00
Marco Costalba 7eda7335fd Simplify previous patch
No functional change.
2013-05-09 19:09:51 +02:00
Marco Costalba 02606a8c83 Merge 'passed_pawns' tweaks
Good at both short and long TC

15+0.05
LLR: 2.96 (-2.94,2.94)
Total: 28220 W: 5531 L: 5349 D: 17340

TC 60+0.05
LLR: 2.95 (-2.94,2.94)
Total: 12612 W: 2221 L: 2057 D: 8334

bench: 4857939
2013-05-08 23:04:11 +02:00
Reuven Peleg e7505324f6 Avoid explicit bitwise operators
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-05-05 22:51:18 +02:00
jundery 653c0527a7 Passed pawn eval
Use a stepped function to evaluate bonuses and add the bonus to the
middle game

bench: 4857939
2013-05-05 11:12:04 -06:00
Marco Costalba 7f4c7cd785 Merge increased 'movecount' pruning
Good at both short and long TC

15+0.05
LLR: 2.95 (-2.94,2.94)
Total: 13814 W: 2731 L: 2588 D: 8495

TC 60+0.05
LLR: 2.95 (-2.94,2.94)
Total: 18013 W: 3136 L: 2946 D: 11931

bench: 4306557
2013-05-05 13:46:26 +02:00
Marco Costalba 0958e5c6d3 Simplify previous condition
No functional change.
2013-05-05 12:31:32 +02:00
Marco Costalba 9fc77bc414 Fix trapped rook condition
A rook is trapped if on rank 1 as is the king.
Currently the condition aloows for the rook
to be also in front of the pawns as long
as king is on first rank.

Verified with short TC test:
LLR: -1.71 (-2.94,2.94)
Total: 23234 W: 4317 L: 4317 D: 14600

Here what it counts is that after 23K games
result is equal.

bench: 4696542
2013-05-05 12:27:11 +02:00
Marco Costalba 3b92159908 Further simplify previous patch
No functional change.
2013-05-04 12:15:31 +02:00
homoSapiensSapiens e00bb13e85 Merge some conditions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-05-04 11:13:22 +02:00
Marco Costalba 3b41e62666 Drop some redundant defined(_WIN64)
When it is already defined(_WIN32).

According to Microsoft documentation:
http://msdn.microsoft.com/en-us/library/b0084kay.aspx

_WIN32 Defined for applications for Win32 and Win64. Always defined.

_WIN64 Defined for applications for Win64.

Patch suggested by Joona.

No functional change.
2013-05-03 15:24:54 +02:00
Marco Costalba 37c91aa94c Print time and node count before search ends
This info is normally printed together with
PV info in uci_pv() but when search is stopped,
for instance when max search time is reached,
uci_pv is not called and we miss this bits.

Suggested by gravy_train

No functional change.
2013-05-03 10:26:03 +02:00
Marco Costalba 43f67eab5f Merge mobility area tweak
A nice improvment.

Was good at 15+0.05
LLR: 2.96 (-2.94,2.94)
Total: 10731 W: 2176 L: 2040 D: 6515

And at 60"+0.05
LLR: 2.96 (-2.94,2.94)
Total: 10601 W: 1968 L: 1810 D: 6823

bench: 4676606
2013-05-03 10:12:31 +02:00
Gary Linscott 11d30b6298 Fix rounding issue 2013-05-02 14:37:55 -04:00
Gary Linscott 3edb15d183 More aggressive move count pruning 2013-05-02 09:47:34 -04:00
Marco Costalba d44ac0a485 Another take at TT alignment
This time revert to original version but using
uintptr_t instead of size_t

Suggested by Lucas.

No functional change.
2013-05-02 09:38:23 +02:00
Marco Costalba 481eda4ca0 Re-add "Cache line aligned TT"
But this time do not play with pointers, in
particular do not assume that size_t is an
unsigned type of the same width as pointers.

This code should be fully portable.

No functional change.
2013-05-01 23:42:16 +02:00
jhellis3 7323231786 Tweak Mobility Area
Only consider pawns and the king as restricting.
2013-05-01 02:37:50 -05:00
Marco Costalba e381951a24 Restore development version
No functional change.
2013-04-30 20:01:07 +02:00
Marco Costalba aa2368a687 Stockfish 3
Stockfish bench signature is: 4176431
2013-04-30 19:42:43 +02:00
Marco Costalba 293c44bc09 Revert "Cache line aligned TT"
This reverts commit 083fe58124

It seems to break Android build

No functional change.
2013-04-30 19:42:21 +02:00
Marco Costalba 06b9140e5c Temporary revert "Expose EvalInfo struct to search"
It is not needed for the release and introduces
a slowdown, although very small.

Probably it will be readded after the release.

No functional change.
2013-04-29 00:55:32 +02:00
Marco Costalba 156635749b Fix a 'value > VALUE_INFINITE' assert
This fixes an assert while testing with debug on.

Assert was due to static null pruning returning value

eval - futility_margin(depth, (ss-1)->futilityMoveCount)

That was sometimes higher than VALUE_INFINITE triggering
an assert at the caller site.

Because eval con be equal to ttValue and anyhow is read from
TT that can be corrupted in SMP case, we need to sanity
check it before to use.

bench: 4176431
2013-04-27 13:08:11 +02:00
Marco Costalba 083fe58124 Cache line aligned TT
Let TT clusters (16*4=64 bytes) to hold on a singe cache line.
This avoids the need for the double prefetch.

Original patches by Lucas and Jean-Francois that has also tested
on his AMD FX:

BIG HASHTABLE

./stockfish bench 1024 1 18 > /dev/null

Before:
1437642 nps
1426519 nps
1438493 nps

After:
1474482 nps
1476375 nps
1475877 nps

SMALL HASHTABLE

./stockfish bench 128 1 18 > /dev/null

Before:
1435207 nps
1435586 nps
1433741 nps

After:
1479143 nps
1471042 nps
1472286 nps

No functional change.
2013-04-26 19:38:11 +02:00
Marco Costalba e508494a99 Fix a crash introduced few days ago
Crash is due to uninitialized ss->futilityMoveCount that
when happens to be negative, yields to an out of range
access in futility_margin().

Bug is subtle because it shows itself only in SMP case.
Indeed in single thread mode we only use the

Stack ss[MAX_PLY_PLUS_2];

Allocated at the begin of id_loop() and due to pure
(bad) luck, it happens that for all the MAX_PLY_PLUS_2
elements, ss[i].futilityMoveCount >= 0

Note that the patch does not prevent futilityMoveCount
to be overwritten after, for instance singular search
or null verification, but to keep things readable and
because the effect is almost unmeasurable, we here
prefer a slightly incorrect but simpler patch.

bench: 4311634
2013-04-26 12:14:01 +02:00
Marco Costalba 2ef53ee368 Store Eval::Info in Search::Stack
Instead of a pointer. This should fix the issue of
remaining with a stale pointer when for instance calling
IID, but also null search verification, singular search
and razoring where we call search with the same ss
pointer. In this case ss->ei is overwritten in the
search() call and upon returning remains stale.

This patch could have a performance hit because Eval::Info
is big (176 bytes) and during splitting we copy 4 ss entries.

On the good side, this patch is a clean solution.

Proposed by Gary.

No functional change.
2013-04-25 21:52:26 +02:00
Marco Costalba d810441b35 Expose EvalInfo struct to search
Allow to use EvalInfo struct, populated by
evaluation(), in search.

In particular we allocate Eval::Info on the stack
and pass a pointer to this to evaluate().

Also add to Search::Stack a pointer to Eval::Info,
this allows to reference eval info of previous/next
nodes.

WARNING: Eval::Info is NOT initialized and is populated
by evaluate(), only if the latter is called, and this
does not happen in all the code paths, so care should be
taken when accessing this struct.

No functional change.
2013-04-25 12:57:37 +02:00
Ryan Schmitt 79bcb2ca54 Increase rook/queen on 7th bonus
Shows an increase at 15+0.05
LLR: 3.01 (-2.94,2.94)
Total: 20450 W: 4091 L: 3927 D: 12432

And at 60+0.05
LLR: 2.97 (-2.94,2.94)
Total: 61432 W: 10849 L: 10441 D: 40142

bench: 4493356

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-04-25 12:13:17 +02:00
Marco Costalba 289a767ab3 Merge Joona's increased static null pruning
The idea is to fail high more easily in static
null test if in the parent node we are already
very deep in the move list, so the propability
to fail high there is very low.

[edit: I have slightly changed the functionality
moving

ss->futilityMoveCount = moveCount;

At the end of the pruning code, this should not affect
ELO in anyway, but makes code more natural and logic]

Test with SPRT is good at 15+0.05
LLR: 2.96 (-2.94,2.94)
Total: 50653 W: 10024 L: 9780 D: 30849

And at 60+0.05
LLR: 2.97 (-2.94,2.94)
Total: 40799 W: 7227 L: 6921 D: 26651

bench: 4530093
2013-04-25 12:05:00 +02:00
Marco Costalba 4381ea23fe Fix cpu_count() on some platforms
When we use sysconf(_SC_NPROCESSORS_ONLN) to get number of
cores, we have to include sysconf library that is unistd.h

Sometimes it happens to work just becuase unistd.h indirectly
included by some other libraries, but not always.

Reported and fixed by Eyal BD

No functional change.
2013-04-25 10:56:56 +02:00
Joona Kiiski 817ca1820b Fix potential overflow 2013-04-23 07:26:36 +01:00
Joona Kiiski 8df17204f4 More aggressive post-futility pruning 2013-04-21 14:53:27 +01:00
Marco Costalba f84f04742a Skip a couple of popcount in previous patch
And some little tidy up

No functional change.
2013-04-19 10:31:18 +02:00
Marco Costalba cc40d1c46a Merge Joona's bishop+pawn tweak
The idea is to penalize a bishop in case of
its pawns are on the same colored squares.

Good at short 15"+0.05 TC
LLR: 2.95 (-2.94,2.94)
Total: 4252 W: 925 L: 806 D: 2521

And at longer 60"+0.05 TC
LLR: 2.95 (-2.94,2.94)
Total: 15006 W: 2743 L: 2564 D: 9699

bench: 5274705
2013-04-19 09:36:00 +02:00
Joona Kiiski 818e0b2d2b Try more aggressive version 2013-04-17 07:58:59 +01:00
Joona Kiiski 3e4dfb49a7 Give a small penalty for bishop for each pawn on the same colored square 2013-04-16 21:20:31 +01:00
Marco Costalba 87436e5544 Skip a redundant check
Spotted by Joona

No functional change.
2013-04-14 23:29:25 +02:00
Marco Costalba fe72c93141 De-templetize Position::is_draw()
Now that we always check for repetition we don't
need a template anymore.

No functional change.
2013-04-10 22:23:48 +02:00
Joona Kiiski 75221fcf5e Always check repetition
It seems stronger both at fast 15+0.05 TC with fixed game number test:
ELO: 2.74 +-2.7 (95%) LOS: 97.6%
Total: 24000 W: 4698 L: 4509 D: 14793

And also at long 60+0.05 TC with SPRT
LLR: 3.05 (-2.94,2.94)
Total: 38986 W: 6845 L: 6547 D: 25594

bench: 5157061
2013-04-10 22:20:40 +02:00
Marco Costalba a95cbca568 Simplify and speed up previous patch
Use an optinal argument instead of a template
parameter. Interestingly, not only is simpler,
but also faster, perhaps due to less L1 instruction
cache pressure because we don't duplicate the very
used SEE code path.

No functional change.
2013-04-09 23:32:06 +02:00
Joona Kiiski d23454854e Document asymmetric SEE pruning trick
Here are the tests:

sprt @ 60+0.05
ELO: 3.53 +-2.8 (95%) LOS: 99.3%
Total: 18794 W: 3098 L: 2907 D: 12789

16000 @ 60+0.05
ELO: 1.39 +-3.1 (95%) LOS: 81.0%
Total: 16000 W: 2689 L: 2625 D: 10686

16000 @ 15+0.05
ELO: 2.82 +-3.3 (95%) LOS: 95.1%
Total: 16000 W: 3148 L: 3018 D: 9834

No functional change

Signature: 4969307
2013-04-09 23:31:57 +02:00
Joona Kiiski c2902112e5 Don't treat king safety differently in AnalysisMode
Rationale:

- Current settings seem to make engine *significantly* weaker in analysis mode.
- In practice this setting only has effect when king safety scores are high.
- Even in analysis mode its far more important to know if one side is getting mated,
rather than get evaluation correct with 1cp accuracy.

No functional change
2013-04-09 23:29:58 +02:00
Marco Costalba 9498b2af82 Rescale UCI parameters to 100
And correspondingly modify internal ones
to compensate it.

No functional change.
2013-04-09 23:29:58 +02:00
Marco Costalba 2a5ae34bb2 Tweak some UCI parameters
According to Jean-Paul this setup should be stronger
than default.

And SPRT test seems to confirm it:

At fast TC 15"+0.05
ELO: 3.33 +-2.7 (95%) LOS: 99.2%
Total: 25866 W: 5461 L: 5213 D: 15192

At longer TC 60"+0.05
ELO: 7.27 +-5.0 (95%) LOS: 99.8%
Total: 6544 W: 1212 L: 1075 D: 4257

bench: 5473339

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-04-09 23:29:58 +02:00
Marco Costalba d3fe153fe6 Re-add 'Cowardice' and 'Aggressiveness' UCI options
I have lost my bet with Jean-Paul, so now I re-add
the two options...and I am glad of it :-)

No functional change.
2013-04-09 23:29:58 +02:00
Marco Costalba 889922041b Increase null verification threshold to 12 plies
Increasing depth limit to 10 plies seems stronger
after 16K games at 15"+0.05 (ELO: +3.56) and also
repeating the test at 60"+0.05 TC:

ELO: 2.08 +-3.1 (95%) LOS: 90.9%
Total: 16000 W: 2641 L: 2545 D: 10814

Moreover setting the limit to 12 is proved stronger
then limit set to 10 by direct SPRT test at 15"+0.05:

ELO: 2.56 +-2.0 (95%) LOS: 99.5%
Total: 46568 W: 9240 L: 8897 D: 28431

So we directly set the limit to 12, the strongest setup.

bench: 4361224
2013-04-09 23:29:58 +02:00
Joona Kiiski 7bad50773a Make use of asymmetric SEE 2013-04-05 19:05:32 +01:00
Joona Kiiski d3c3c4f8e7 Fix a silly bug 2013-04-05 19:05:32 +01:00
Joona Kiiski 2097cd1221 Introduce asymmetric SEE.
No functional change
2013-04-05 19:05:32 +01:00
Marco Costalba 0c1b40c5e2 Lower minimum allowed TT size to 1 MB
Setting a very low TT size could be used
for some specific testing.

No functional change.
2013-04-05 16:56:01 +02:00
Marco Costalba 8c10029df1 Revert "Double Impact of Gain tables"
This reverts commit 36c82b751c

Seems a regression against 2.3.1 tested with 20K games at 60"+0.05

With patch applied
ELO: 15.44 +-2.8 (95%) LOS: 100.0%
Total: 20000 W: 3928 L: 3040 D: 13032

Without patch applied
ELO: 18.76 +-2.8 (95%) LOS: 100.0%
Total: 20000 W: 3903 L: 2824 D: 13273

bench: 4781239
2013-04-05 08:59:38 +02:00
Hiraoka Takuya 6e2371a86b Don't early stop if we have a mated score
No functional change.
2013-04-04 21:39:48 +02:00
Joona Kiiski 36c82b751c Double Impact of Gain tables
Very unorthodox idea.

After 16000 games at 60"+0.05
ELO: 3.14 +-3.4 (95%) LOS: 96.6%
Total: 13407 W: 2278 L: 2157 D: 8972

bench: 4705335
2013-04-03 19:14:59 +02:00
Marco Costalba 7d42d02ec7 Set IID half way between d/2 and d-4
Master IID formula is depth / 2
Previous patch is depth - 4 * ONE_PLY

This one is the middle way:

(dept/2 + depth-4*ONE_PLY)/2  -> depth-2*ONE_PLY-depth/4

After 16000 games at 60+0.05 th 1
ELO: 4.08 +-3.1 (95%) LOS: 99.5%
Total: 16000 W: 2742 L: 2554 D: 10704

bench: 4781239
2013-03-30 22:26:30 +01:00
Marco Costalba c89274d8fb Merge branch 'master' into increase_iid 2013-03-29 22:50:04 +01:00
Marco Costalba f2638816bf Raise Min Split Depth
Raise the limit to 12 so to allow people to test
on many cores machines.

Suggested by Gary and Martin.

No functional change.
2013-03-25 20:04:49 +01:00
Marco Costalba 0b4ea54da9 Update bestValue when futility pruning (2)
Same idea of 5af8179647
in qsearch() but applied to search()

After 15500 games at 15+0.05
ELO: 4.48 +-3.4 (95%) LOS: 99.5%
Total: 15500 W: 3061 L: 2861 D: 9578

bench: 4985829
2013-03-24 23:32:21 +01:00
Joona Kiiski 09f1fdf52f Fix bogus mate scores in some positions
Always before pruning the move, it's important to check that:

bestValue > VALUE_MATED_IN_MAX_PLY

See example position:

8/2p1p3/P1NpP3/3k4/1P1BN3/2P1P3/2Q5/6K1 w - - 0 1
http://support.stockfishchess.org/discussions/problems/268-wrong-declaring-a-forced-mate-in-3-moves

This problem was present in 2.3.1, then it was fixed by my patch.

After 24000 games at 15+0.05
ELO: 2.40 +-4.4 (95%) LOS: 95.7%
Total: 24000 W: 4774 L: 4608 D: 14618

bench: 4465997
2013-03-23 21:28:51 +01:00
jundery d39b22927e Use ALL_PIECES value to reference attackedBy
No functional change
2013-03-23 12:17:12 +01:00
Marco Costalba 81e9cf043a Increase non-PV IID search depth
bench: 5146380
2013-03-22 20:57:31 +01:00
Marco Costalba 077e32efc9 Better document bitbase loop
Thanks to Lucas to spot the weak comment and
to Jundery to suggest a better one.

No functional change.
2013-03-19 19:08:41 +01:00
Gary Linscott 52f3e717fa Add KNPKB endgame
In a game vs Junior, SF had the option to trade into a winning
pawn endgame, and failed to do so. PGN at bottom.

This FEN was one key position: 8/2Nb1k2/6pp/4Pp2/5K1P/5PP1/8/8 w - - 5 62.

SF master chooses h5 here, with a fail high, which goes into the drawn KNPKB
ending. With the patch, SF correctly chooses Ke3, which maintains chances to win.

[Event "nTCEC - Stage 2a - Season 1"]
[Site "http://www.tcec-chess.net"]
[Date "2013.03.05"]
[Round "11.3"]
[White "Stockfish 210213"]
[Black "Junior 13.3"]
[Result "1/2-1/2"]
[Variant "normal"]

1. d4 f5 2. g3 Nf6 3. Bg2 e6 4. c4 d5 5. Nh3 c6 6. O-O Bd6 7. Bf4 Be7 8. Nd2 O-O
9. Qb3 a5 10. Rfd1 Ne4 11. Be3 Nd7 12. Nf4 Ndf6 13. f3 a4 14. Qc2 Nxd2 15. Bxd2
dxc4 16. Qxc4 b5 17. Qc3 Qb6 18. Rac1 e5 19. Nd3 exd4 20. Qxc6 Qxc6 21. Rxc6
Bd7 22. Rcc1 Be6 23. Bb4 Rae8 24. Bxe7 Rxe7 25. Nb4 Bc4 26. Bf1 Rd7 27. Rd2 Re8
28. Rcd1 Rc7 29. Ra1 Rd8 30. Rc1 Rdd7 31. Rcd1 Re7 32. Ra1 Nd5 33. Nc2 Ne3
34. Nxd4 Bxa2 35. Nxb5 Rc5 36. Nd4 Bf7 37. Kf2 g6 38. Rd3 Nxf1 39. Kxf1 Rc4
40. b3 axb3 41. Nxb3 Kf8 42. Rd8+ Re8 43. Rxe8+ Bxe8 44. Kf2 Ke7 45. Ra7+ Bd7
46. Ke1 Rc3 47. Rb7 Rc2 48. Kd1 Rc4 49. Kd2 Kd6 50. Kd3 Rc7 51. Rxc7 Kxc7
52. Kd4 Kd6 53. Nc5 Bb5 54. e4 Be2 55. e5+ Ke7 56. Ke3 Bd1 57. Kf4 h6 58. h3
Kf7 59. h4 Bc2 60. Na6 Ba4 61. Nc7 Bd7 62. h5 g5+ 63. Ke3 Ba4 64. f4 Bd1
65. fxg5 hxg5 66. h6 Kg6 67. e6 f4+ 68. gxf4 gxf4+ 69. Kxf4 Bh5 70. Ke5 Kh7
71. Kf6 Kxh6 72. Na6 Bg4 73. e7 Bh5 74. Nc7 Bg6 75. Nd5 Be8 76. Ne3 Kh7 77. Nc4
Kh6 78. Nd2 Kh5 79. Nf3 Kg4 80. Nd4 Bh5 81. Ne6 Be8 82. Nc5 Kf3 83. Kf5 Ke3
84. Ke5 Ke2 85. Kf4 Kd2 86. Ne4+ Kd3 87. Ke5 Ke3 88. Nf6 Bf7 89. Nd5+ Kf3
90. Kf5 Ke2 91. Ke4 Be8 92. Nc3+ Kd2 93. Kd4 Kc2 94. Nd5 Kd1 95. Nf6 Bf7
96. Ne4 Be8 97. Ke3 Kc2 98. Nd6 Bd7 99. Kd4 Kd1 100. Kd3 Ba4 101. Nc4 Bb5
102. Kc3 Be8 103. Nb2+ Ke1 104. Kd3 Kf2 105. Nd1+ 1/2-1/2

No functional change (just because bench does not change)
2013-03-18 20:40:06 +01:00
Marco Costalba 0586b51f9c Further increase SEE prune depth
After 16000 games at 60+0.05
ELO: 2.89 +-5.4 (95%) LOS: 96.5%
Total: 16000 W: 2775 L: 2642 D: 10583

bench: 5442365
2013-03-16 11:20:03 +01:00
Marco Costalba d2eeef89aa Revert "Check for easy move just once"
This reverts commit a24da071f0

Seems a regression when tested against 2.3.1

With this patch, have after 20000 games at 60+0.05, we have

ELO: 13.42 +-4.8 (95%) LOS: 100.0%
Total: 20000 W: 3746 L: 2974 D: 13280

Instead with the patch reverted:

ELO: 16.62 +-4.8 (95%) LOS: 100.0%
Total: 20000 W: 3816 L: 2860 D: 13324

Although we are within error bounds here we take the conservative
approach of not introducing changes that are not proved stronger
It doesn't mean that the change shall be weaker, simply that we
don't want to take any risk.

No functional change.
2013-03-16 11:12:35 +01:00
RyanTaker 70d20326b0 Improved Readability of Material
This is a non-functional change that simply changes the look
of the code to help clarity.

No functional change.
2013-03-15 09:14:00 +01:00
jundery ccf4ec6768 Do more work between prefetch and querying transposition table
More time to load the cache line before access

No functional change.
2013-03-12 19:58:32 +01:00
Gary Linscott a24da071f0 Check for easy move just once
Here the rational seems to be that if after one try easy
move detection fails then the easy move is not so easy :-)

After 15563 games at 60+0.05
ELO: 3.04 +-5.5 (95%) LOS: 97.0%
Total: 15563 W: 2664 L: 2528 D: 10371

No functional change.
2013-03-11 22:23:19 +01:00
Gary Linscott 3698d9aa55 Be more aggressive on trying to finish iterations
Increase MaxRatio to use more time when in trouble.

After 16000 games at 60+0.05
ELO: 4.89 +-5.4 (95%) LOS: 99.9%
Total: 16000 W: 2700 L: 2475 D: 10825

No functional change.
2013-03-11 19:07:55 +01:00
Marco Costalba 10429dd616 Increase see prune depth
This seems good at short TC controls.

After 10000 games at 20+0.05
ELO: 9.56 +-6.8 (95%) LOS: 100.0%
Total: 10000 W: 1949 L: 1674 D: 6377

Testing at long TC and regression testing is still
ongoing. So this is a bit speculative commit and
could be reverted in the future.

Also re-testing at long TC the SEE pruning in PV nodes
seems less effective (perhaps even a regression, but
still ongoing) so disabled for now.

bench: 4968764
2013-03-04 09:41:56 +01:00
Marco Costalba db322e6a63 Revert "Store moves sent with "position" UCI command"
This reverts commit 0d68b523a3.

After easy move semplification this machinery is not
needed anymore (because of we don't need to know if a
root move is a recapture)

No functional change.
2013-03-04 09:29:46 +01:00
Marco Costalba 45dba12c5b Simplify "easy move" detection
Detect a move as easy only if it is the only one ;-)
or if is much better than remaining ones after we
have spent 20% of search time.

Tests are ongoing, but it seems this semplification
stands. Anyhow it is experimental for now and could
be reverted/improved with further work Gary is
testing right now.

No functional change.
2013-03-04 09:27:00 +01:00
Marco Costalba ccad601389 Avoid locking/unlocking in a tight loop
After previous patch if split point master is
waiting for job and "Use Sleeping Threads" is
false (our condition for official releases) then
it will lock/unlock splitPoint mutex in a super
tight loop badly affecting performance.

Rewrite the code to lock only when we are about
to finish. Note that race condition on slavesMask
is anyhow fixed.

No functional change.
2013-03-04 09:07:48 +01:00
jundery d165d5af91 Fix race condition where idle_loop() gets called from Split()
SplitPoint member slavesMask wasn't read under lock

No functional change.
2013-03-04 08:52:24 +01:00
jhellis3 3ce43c20de Stop search if only 1 legal move
There is no point searching a move that is forced.
It wastes time while allowing computer opponents to
fill hash with 100% accuracy.

[edit: Condition moved together with "easy move" ones]

Bench identical: 4922272
2013-03-04 08:30:55 +01:00
Marco Costalba def50020ad Fix easy re-capture case
We detect an easy move as a recapture with an
high margin on the second best move.

Unfortunatly the recapture detection is broken
becuase we identify as a recapture any move that
follows an opponent's previous capture !

This patch fix the logic to correctly detect a
real re-capture.

No functional change.
2013-03-02 13:20:40 +01:00
Marco Costalba 0d68b523a3 Store moves sent with "position" UCI command
Store all the game moves until current position.

This will be used by next patch.

No functional change.
2013-03-02 13:08:50 +01:00
Marco Costalba 0e1ad3ad33 Rename sp to splitPoint
Still keep 'sp' name when used as local
variable with limited scope.

From Jundery.

No functional change.
2013-03-01 09:44:19 +01:00
jundery 0fc9a01933 Remove strange use of the ternary operator
Note that we read shared data without lock
protection, so code is theoretically prone to
torn reads. But, first splitPoint pointer
never changes, and alpha is of integer type so
it is read in a single DWORD access.

No functional change.
2013-03-01 08:05:47 +01:00
jundery 68d1bebd8e Split() clean up locking
Only unlock and relock when idle_loop() is actually called

No functional change
2013-03-01 07:57:18 +01:00
Marco Costalba 57b6df4874 Merge Lucas's "SEE pruning at PV nodes"
bench: 4922272
2013-02-27 08:14:00 +01:00
Marco Costalba bc38efd128 Remove pruning condition on alpha
Further simplifying on Lucas's idea, seems reliable
in tests:

ELO: 2.15 +-7 (95%) LOS: 84.9%
Total: 9999 W: 1831 L: 1769 D: 6399
2013-02-27 08:07:26 +01:00
Lucas Braesch 335b57b5ef Prune negative SEE moves also in PV nodes
This patch is actually the sum of two contributions that
have been tested independently:

1) Pruning of negative SEE moves in PV

After 10000 games at 20+0.05
ELO: 5.18 +-7 (95%) LOS: 99.2%
Total: 10000 W: 1952 L: 1803 D: 6245

2) Remove of bestValue > VALUE_MATED_IN_MAX_PLY condition

After 23000 games at 20+0.05
ELO: 1.63 +-4 (95%) LOS: 88.1%
Total: 23000 W: 4232 L: 4124 D: 14644

The whole patch as been re-tested at long TC with positive results:

After 10000 games at 60+0.05
ELO: 4.31 +-7 (95%) LOS: 98.3%
Total: 10000 W: 1765 L: 1641 D: 6594
2013-02-27 08:04:32 +01:00
Marco Costalba dbd28bc7f8 Avoid a tricky line in shelter_storm()
kf = (kf == FILE_A) ? kf++ : ....

is tricky becuase kf is updated twice and it happens
to do the right thing just by accident.

Rewrite in a better way.

Spotted by pdimov

No functional change.
2013-02-23 19:27:32 +01:00
Marco Costalba ccf21f5595 Convert Readme to markdown format
Looks better on GitHub, that supports this format.

No functional change.
2013-02-23 17:05:28 +01:00
Marco Costalba 1d1fcf80a0 Use DD-MM-YY as date format
In engine name and version number.

No functional change.
2013-02-21 07:19:48 +01:00
Marco Costalba 373503f4a9 Statically link std libraries under mingw
Allows for easier redistribution.

No functional change.
2013-02-21 05:51:04 +01:00
Marco Costalba 9a1d5f0f1d Merge Gary's bishop_pin patch
Give a bonus if a bishop can pin a piece or can
give a discovered check through an x-ray attack.

Seems good after 24000 games at 15"+0.05 (single thread):

ELO: 12.30 +- 99%: 5.79 95%: 4.40 LOS: 100.00%
Total: 24000 W: 4931 L: 4082 D: 14987

bench: 4917064
2013-02-20 12:39:09 +01:00
jundery d5e49a3ad4 Print leading zeroes in hash keys
And convert to uppercase. Reset the stream to dec too.

[Edit: Also fixed the hash key in Position::pretty()]
2013-02-19 20:06:01 +01:00
Gary Linscott ea4e22be1d Merge branch 'master' into bishop_pin_clop 2013-02-19 10:31:52 -05:00
Gary Linscott dc8c6ea2d1 Bring back original bonus 2013-02-19 10:31:50 -05:00
Marco Costalba c5ec94d0f1 Update copyright year
No functional change.
2013-02-19 07:54:14 +01:00
Gary Linscott d570260a28 Back to CLOP average values 2013-02-16 22:36:58 -05:00
Marco Costalba 76caef8ba1 Account for gamePly after each move
Rename startPosPly to gamePly and increment/decrement
the variable after each do/undo move. This adds a little
overhead in do_move() but we will need to have the
game ply during the search for the next patches now
under test.

Currently we don't increment gamePly in do_null_move()
becuase it is not needed at the moment. Could change
in the future.

As a nice side effect we can now remove an hack in
startpos_ply_counter().

No functional change.
2013-02-16 12:44:17 +01:00
Marco Costalba 5a156df719 Merge Gary's king safety tweak
Still well within error bars, so probably not a big improvement,
but may be worthwhile. I will let the test keep running. The idea
for the tweak came from the TCEC game against Houdini. Stockfish saw
it as a draw, well past when it should have seen problems. King safety
was off, since it was QN and pawns only, but in fact the king was
quite vulnerable.

After 8000 games at 60/1 (Gary's test)

ELO: -0.43 +- 99%: 10.02 95%: 7.62
Wins: 1235 Losses: 1245 Draws: 5520 Total: 8000

PGN of game against houdini. Moves 55-59 it was seeing a draw, and
Houdini was seeing a good sized advantage for black. With the change,
Stockfish now recognizes that moving the king there is a bad idea.

[Event "nTCEC - Stage 1 - Season 1"]
[Site "http://www.tcec-chess.net"]
[Date "2013.02.07"]
[Round "4.2"]
[White "Stockfish 2.31"]
[Black "Houdini 3.0"]
[Result "0-1"]
[Variant "normal"]

1. Nf3 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 O-O 5. a3 Bxc3 6. Qxc3 b6 7. b4 a5 8. Bb2
axb4 9. axb4 Rxa1+ 10. Bxa1 Na6 11. e3 Qe7 12. b5 Nc5 13. Qc2 Bb7 14. Be2 d6
15. O-O Ra8 16. Bb2 h6 17. Ra1 Rxa1+ 18. Bxa1 e5 19. Qa2 Be4 20. Ne1 Bg6
21. Bb2 Kh7 22. f3 Nfd7 23. Bc3 h5 24. Qa1 h4 25. Kf1 Qf6 26. Qa7 Qd8 27. Qa2
e4 28. Qa1 h3 29. g3 exf3 30. Nxf3 Bf5 31. Bd4 g6 32. Kf2 Kg8 33. Qa3 Bg4
34. d3 Qc8 35. Bxc5 bxc5 36. Ke1 Qb7 37. e4 Bxf3 38. Bxf3 Ne5 39. Be2 Qc8
40. Qa6 Qd8 41. Qa5 Kh7 42. Kd1 Kg7 43. Qa7 Kg8 44. Qa5 Kh7 45. Qa7 Kg7 46. Qa5
Qb8 47. Kd2 Kh7 48. Kc2 Kg8 49. Qa6 Qd8 50. Qa5 Qf6 51. Qe1 Kg7 52. Qf1 Qe6
53. Qe1 Qd7 54. Qc1 Qe8 55. Kc3 Qa8 56. Kb3 Kh7 57. Qa3 Qd8 58. Qc1 c6 59. Qc3
Qb6 60. Ka4 Qb7 61. Qd2 Nd7 62. Qc3 Qa7+ 63. Kb3 Kg8 64. Bg4 cxb5 65. cxb5 Nb6
66. Bxh3 Qa4+ 67. Kb2 Qd1 68. Ka3 Qe2 69. Kb3 Qh5 70. Bg2 Qxh2 71. Qf6 Qxg3
72. Bf1 Qe3 73. Kc2 Na4 74. b6 Nxb6 75. Qd8+ Kg7 76. Qxb6 Qf2+ 77. Kc3 Qxf1
78. Qxd6 Qf6+ 79. Qxf6+ Kxf6 80. Kc4 g5 81. Kxc5 Ke5 82. d4+ Kxe4 83. d5 g4
84. d6 g3 85. d7 g2 86. d8=Q g1=Q+ 87. Kb5 Qb1+ 88. Ka4 Qa2+ 89. Kb4 f5
90. Qe8+ Kf4 91. Qg6 Qd5 92. Qg1 Qe4+ 93. Ka5 Qe2 94. Qg8 Kf3 95. Qd5+ Qe4
96. Qd1+ Kg2 97. Qd2+ Kf1 98. Qh2 f4 99. Qh3+ Ke2 100. Qg4+ Kd2 101. Qg5 Kc2
102. Qh4 0-1

bench: 5518286
2013-02-15 16:25:33 +01:00
Marco Costalba e0dfb0bc34 Further speed up bitbase generation
Another trick, along the same lines of previous
patch. This time we first check positions with
white side to move that, becuase we start with
pawn on rank 7, are easily classified as wins,
then black ones.

Number of cycles reduced to 15 !

Becuase now it is faster we can remove a lot of
code to detect theoretical draws. We will calculate
them anyhow, although a bit slower, but the speed
up trick more than compensates it.

Verified that generated bitbases match original ones.

No functional change.
2013-02-15 11:58:33 +01:00
Gary Linscott 3922ac2fe4 Add new clop tuned value 2013-02-14 20:29:24 -05:00
Gary Linscott 66a1a77487 Merge branch 'master' into bishop_pin_clop 2013-02-13 21:41:15 -05:00
Gary Linscott cd0ecace19 Revert "Use CLOP mean value instead of max"
This reverts commit d0c2faa5fd.
2013-02-13 21:40:38 -05:00
Marco Costalba 10d29add18 Speedup KPK bitbase of 25%
Change the way the index is coded so that
now looping from 0 to IndexMax generates
the pawns from RANK_7 down to RANK2.

Becuase positions with pawns at RANK_7
are easily classified as wins/draws, this
small trick allows to reduce the number
of needed iterations from 30 down to 26!

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-02-13 20:13:56 +01:00
Marco Costalba f2950ae206 Simplify bitbase.cpp
Use a std::vector to store positions and
rearrange KPKPosition.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-02-13 20:13:44 +01:00
Gary Linscott d0c2faa5fd Use CLOP mean value instead of max 2013-02-13 12:21:16 -05:00
Gary Linscott 671f24ff35 Merge branch 'simplify_eval' into bishop_pin_clop 2013-02-13 12:19:54 -05:00
Gary Linscott f32f899467 CLOP tuned 2013-02-13 00:12:02 -05:00
Gary Linscott 17b71fe51d Add clop parameters 2013-02-12 00:10:21 -05:00
Gary Linscott 30c2e3828a Merge branch 'master' into simplify_eval 2013-02-11 10:26:25 -05:00
Gary Linscott a7cdf7299a Bishop pins only 2013-02-11 10:26:18 -05:00
Marco Costalba 733d0099b2 Rename and de-templetize sort()
Rename to insertion_sort so to avoid confusion
with std::sort, also move it to movepicker.cpp
and use the bit slower std::stable_sort in
search.cpp where it is used in not performance
critical paths.

No functional change.
2013-02-11 00:09:21 +01:00
Marco Costalba 0be7b8c542 Further simplify first_entry()
We can encode the ClusterSize directly in the
hashMask, this allows to skip the left shift.

There is no real change, but bench number is now
different because instead of using the lowest order
bits of the key to index the start of the cluster,
now we don't use the last two lsb bits that are
always set to zero (cluster size is 4). So for
instance, if 10 bits are used to index the cluster,
instead of bits [9..0] now we use bits [11..2].
This changes the positions that end up in the same
cluster affecting TT hits and so bench is different.

Also some renaming while there.

bench: 5383795
2013-02-09 16:37:20 +01:00
Marco Costalba c698362680 Microptimize first_entry() for 32bits
Do a 32bit bitwise 'and' instead of a 64bit
subtract and bitwise 'and'.

This is possible because even in the biggest
hash table case (8GB) the number of entries
is 2^29 so storable in an unsigned int.

No functional change.
2013-02-09 10:55:38 +01:00
Marco Costalba fe3352665b Retire TTCluster and simplify TT
Also some renaming while there.

No functional change.
2013-02-09 10:55:20 +01:00
Marco Costalba 3f44be9baa Simplify move_to_san()
Nicely simplify disambiguation code.

No functional change.
2013-02-09 07:43:53 +01:00
Gary Linscott 0c06b4509d Slight tweak to king safety. Bench: 5534531 2013-02-08 08:53:13 -05:00
Marco Costalba e5bc79fb9c Retire slavesPositions
Save the current active position in each Thread
instead of keeping a centralized array in struct
SplitPoint.

This allow to skip a memset() call at each split.

No functional change.
2013-02-08 11:45:33 +01:00
Marco Costalba 880726c13a Add const qualifer to go()
Obsolete renmant of when position was directly
passed to the search instead of being copied
for the main thread as is now.

From Jundery.

No functional change.
2013-02-08 10:07:09 +01:00
Marco Costalba 50a7200b18 Workaround value-initialization in MSVC
The syntax splitPoints() should force the compiler to
value-initialize the array and because there is no
user defined c'tor it falls back on zero-initialization.

Unfortunatly this is broken in MSVC compilers, because
value initialization for non-POD types is not supported,
so left splitPoints un-initialized and add in split()
initialization of slavesPositions, that is the only
member not already set at split time.

This fixes an assert under MSVC when running with
more than one thread.

Spotted and reported by Jundery.

No functional change.
2013-02-08 09:20:40 +01:00
Gary Linscott c67fb8ef04 Add KBPKP endgame
It is a draw if pawns are on G or B files, weaker pawn is
on rank 7 and bishop can't attack the pawn.

No functional change (because it is very rare and does not appear in bench)
2013-02-07 06:51:55 +01:00
Marco Costalba 14c2c1395b Change slave_available() API
To return a pointer to the available
thread instead of a bool. This allows
to simplify the core loop in split().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-02-06 20:48:26 +01:00
jundery 88c3670edf Rename posKey stored in the transposition table
[Edit: Slightly extended by me]

No functional change.
2013-02-06 08:03:37 +01:00
jundery f69c185e02 Add const qualifer to check_is_dangerous
No functional change.
2013-02-06 07:49:40 +01:00
Marco Costalba bf706c4a4f Slightly change split() API
This function "returns" two values: bestValue and bestMove

Instead of returning one and passing as pointer the other
be consistent and pass as pointers both.

No functional change.
2013-02-05 06:35:38 +01:00
Marco Costalba 1a414cd9cb Derive ThreadPool from std::vector
Prefer sub-classing to composition in this case.

No functional change.
2013-02-04 22:59:20 +01:00
Marco Costalba 91427c8242 Move split() under Thread
Previous renaming patch suggested this reformat:
when a better naming leads to a better code!

No functional change.
2013-02-04 22:17:04 +01:00
Marco Costalba b8c5ea869c Some renaming in split()
Naming suggested by jundery.

No functional change.
2013-02-04 22:00:41 +01:00
Marco Costalba 6560e4cc5b Be clear about not LMR the ttMove
Currently a ttMove is reduced with ss->reduction = DEPTH_ZERO,
so it is actually not reduced (as it should be), but the
trick works just becuase it happens that ttMove is the first
to be tried and

reduction(depth, 1)

Always returns zero. So explicitly forbid reduction of ttMove
in the LMR condition. This is much clear and self-documented.

No functional change.
2013-02-03 11:14:21 +01:00
Marco Costalba 08d615cc95 Templetize score_xxx() functions
So to be style-wise aligned with the corresponding
generate() functions.

No functional change.
2013-02-03 10:11:12 +01:00
Marco Costalba 1c4e6d7ea2 Rename prevents_move() to refutes()
Better! From DiscoCheck.

No functional change.
2013-02-03 09:23:04 +01:00
Marco Costalba 5f58db8c99 Correctly score enpassant captures
Surprisingly this rare case was not considered
when scoring a capture.

Also take in account that in the promotion case
we gain a new piece (typically a queen) but we
lose the promoting pawn.

These small issues were present since Glaurung times!

Found while browsing DiscoCheck sources

bench: 5400063
2013-02-03 09:08:32 +01:00
Marco Costalba ddbe6082c4 Unify History and Gains under a single Stats class
Handling of History and Gains is almost the same, with
the exception of the update logic, so unify both
classes under a single Stats struct.

No functional change.
2013-02-02 17:45:09 +01:00
Marco Costalba 53051eefc7 Retire history.h
And move the contents to movepick.cpp, where they are
mostly used.

Idea from DiscoCheck.

No functional change (bench 5379503)
2013-02-02 16:54:35 +01:00
Gary Linscott a72710c660 Simplify eval take 2. Bench 5097444 2013-02-02 10:19:59 -05:00
Marco Costalba 9f94d22801 Restore "fail-low of reduced" and close regression
This reverts "Threat Extensions" and is the last of
this revert series.

In single-thread tests we should now be on par with 2.3.1
2013-02-02 07:16:33 +01:00
Marco Costalba 0901e12102 Revert "Simplify Evaluation"
This reverts commit 496c7497cb
2013-02-02 06:44:04 +01:00
Marco Costalba 58c9fbacc7 Revert "Extend full 3 fold detection to PvNodes" 2013-02-02 06:41:05 +01:00
Marco Costalba 483c98a69e Rewrite do_castle_move()
And handle the castle directly in do/undo_move().
This allow to greatly simplify the code.

Here the beast is the nasty Chess960 that is
really tricky to get it right because could be
that 'from' and 'to' squares are the same or
that king's 'to' square is rook's 'from' square.

Anyhow should work: verified on all Chess960
starting positions.

No functional and no speed change also in Chess960.
2013-01-28 13:40:47 +01:00
Marco Costalba 2218a5836a Rewrite do_null_move()
Use a more traditional approach, along the same lines
of do_move().

It is true that we copy more in do_null_move(), but we
save the work in undo_null_move(). Speed test shows the
new code to be even a bit faster.

No functional change.
2013-01-27 12:15:02 +01:00
Marco Costalba 76a0d3c05a Get rid of some locals in do_castle_move()
Rewrite the logic to get rid of kBefore and rBefore.

No functional change.
2013-01-27 11:03:55 +01:00
Marco Costalba 52cab06fff Don't prefetch if not needed
Prefetch access to hash tables only in case we
have changed pawn or material hash keys.

No functional change.
2013-01-27 10:19:11 +01:00
Marco Costalba bd87ab9ff5 Retire generate_king_moves()
We have only one call place so inline its content.
BTW, function is already declared as FORCE_INLINE.

Also some small refactoring while there.

No functional change.
2013-01-26 22:43:58 +01:00
Gary Linscott 57797822f8 Bring back just bishop pins 2013-01-26 15:35:00 -05:00
Marco Costalba 7062db7cb2 Clarify slavesMask usage
When a thread is allocated a bit is set in slavesMask.
This bit corresponds to the thread's index field that,
because it happens to be the position in the threads
array, eventually it is equal to the loop index 'i'.

But instead of relying on this 'coincidence', explicitly
use the 'idx' field so to clarify slavesMask usage.

Backported from c++11 branch.

No functional change.
2013-01-26 14:38:51 +01:00
Marco Costalba 166cc0292c Revert "Further push singular extension"
This reverts commit 4c91dbc28e

Seems a regression on extended test by both Gary and me.
2013-01-26 10:20:46 +01:00
Marco Costalba 496c7497cb Merge branch 'simplify_eval' of https://github.com/glinscott/Stockfish
Test results are looking good after 12500 games.

ELO: 6.55 +- 99%: 8.02 95%: 6.09
LOS: 99.99%
Wins: 1968 Losses: 1732 Draws: 8813

Also, here are the noise.py results, which seem to have stabilized:
Games: 12526 , result: [1969, 1734, 8823]
Estimated ELO: 6.94963842777
Noise as function of number of games:
['81.89', '565.26', '110.87', '104.39', '38.22', '49.98', '18.56', '16.76',
'11.02', '8.90', '17.36', '9.84', '10.81', '5.13', '6.22', '3.32', '5.83',
'7.21', '15.27', '1.63', '4.04', '9.51', '0.54', '0.75', '1.06', '2.93',
'4.59', '6.85', '13.62', '9.87', '14.74', '20.46', '22.18', '24.33', '31.02',
'34.99', '35.22', '33.22', '32.46', '37.02', '29.10', '36.34', '42.11', '39.33',
'26.16', '28.25', '35.42', '31.04', '29.26', '23.91', '22.52', '23.49', '20.00',
'24.39', '17.22', '16.50', '10.69', '9.15', '9.57', '4.77', '6.67', '3.87', '2.57',
'2.84', '2.60', '3.32', '2.08', '2.93', '4.47', '4.41', '4.83', '4.86', '6.40',
'5.98', '6.10', '6.83', '5.83', '6.22', '5.71', '8.52', '9.25', '5.98', '7.52',
'7.76', '8.76', '8.55', '8.64', '7.19', '5.83', '4.59', '4.77', '4.26', '4.98',
'5.29', '5.41', '4.92', '5.59']

bench: 5229106
2013-01-26 10:18:36 +01:00
Gary Linscott e83b9075ff Simplify evaluation 2013-01-24 08:54:13 -05:00
Marco Costalba 6950d07bf4 Small reformat of split()
No functional chhange.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-01-21 23:31:33 +01:00
Marco Costalba 054d117d25 Fix an idiotic icc warning
Intel Compiler has 'invented' this pearl:

warning #1476: field uses tail padding of a base class

Just becuase we have subclassed MainThread and added
the field 'bool thinking'.

Pure nosense. Silence the warning.

No functional change.
2013-01-20 17:36:24 +01:00
Marco Costalba 62b32a4737 Futher renaming in thread.cpp
No functional change.
2013-01-20 17:35:55 +01:00
Marco Costalba 588670e8d2 Big renaming in thread stuff
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-01-16 20:00:05 +01:00
Marco Costalba c465f4c4df Fix race while exiting
Fix again TimerThread::idle_loop() to prevent a
theoretical race with 'exit' flag in ~Thread().

Indeed in Thread d'tor we raise 'exit' and then
call notify() that is lock protected, so we
have to check again for 'exit' before going to
sleep in idle_loop().

Also same change in Thread::idle_loop() where we
now check for 'exit' before to go to sleep.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2013-01-16 19:58:55 +01:00
Lucas Braesch 8737b26a23 Remove Threat Extension
Great code simplification: - instead do not futility
prune threat refutations. allows_move() is therefore removed.

4000 games at 50,000 nodes/move:
1085-989-1926 [51.2%] LOS=98.3%

4000 games in 10"+0.1"
756-751-2493 [50.1%] LOS=55.1%

EDIT: I have retested the patch of Lucas in a slightly different form
(without pruning in PvNode) and test mre or less confirms that
60 lines of code are totally unuseful:

After 6195 games at 15"+0.05"
1333 - 1325 - 3537 ELO 0

bench 5140990
2013-01-15 17:03:56 +01:00
Marco Costalba 78a9531773 Fix a bug in timer loop
Silly logic bug introduced in dda7de17e7

Timer thread, when msec = 0, instead of going
to sleep, calls check_time() in an endless loop.

Spotted and reported by snino64 due to abnormally
high CPU usage.

No functional change.
2013-01-14 19:32:30 +01:00
Marco Costalba d1143794a0 Polymorphic Thread hierarchy
Subclass MainThread and TimerThread and declare
idle_loop() virtual. This allow us to cleanly
remove a good bunch of hacks, relying on C++
polymorphism to do the job.

No functional change.
2013-01-14 02:01:37 +01:00
Marco Costalba e70eae2c91 Don't use do_sleep flag
Rename it is_finished and use it only in main
thread to signal search is finished. This allows
us to simplify the complex SMP logic.

Ultra tricky patch: deep test is required under
wide conditions like pondering on and option
"Use Sleeping Threads" set to false.

No functional change.
2013-01-14 00:02:32 +01:00
Marco Costalba 99ae47716a Re-add the hack
This reverts commit 869c924410

I misunderstood here. Actually it can happen that
thread is created but still not entered idle_loop
and at the same time start_searching() is called.

Becuase 'do_sleep' is set start_searching() will
set it to false and start the search, but when,
at last, the thread enters idle_loop(), resets
the flag and goes to sleep: not what we want.

Revert the hack waiting for a better solution
in the next patches.

No functional change.
2013-01-13 23:56:04 +01:00
Marco Costalba dda7de17e7 Retire set_timer()
Also assure in Thread::timer_loop() that when
timer interval is 0 (timer is disabled) we
never call check_time()

No functional change.
2013-01-13 18:24:43 +01:00
Marco Costalba 869c924410 Retire obsolete race hack
This hack was introduced in d282cf6964
to workaround a race with start_searching(),
but these days is no more needed.

No functional change.
2013-01-13 17:05:30 +01:00
Marco Costalba ea6c1f7a17 Retire Threads wake_up() and sleep()
These functions are used in just one place.
And generalize wait_for_stop()

No functional change.
2013-01-13 16:57:40 +01:00
Marco Costalba 81cd7d787e Rename wake_up() to notify_one()
To align to C++ std::thread conventions.

No functional change.
2013-01-13 16:43:26 +01:00
Marco Costalba a523cea772 Unify 'ponderhit' handling
Finally we can now merge the 'ponderhit' case with
'stop' and 'quit'.

The patches have been done step by step to help debugging
becuase this is really tricky code.

No functional change.
2013-01-13 14:39:41 +01:00
Marco Costalba a66a7c3870 Small change to "ponderhit" handling
Reset Limits.ponder only if search continue, but if
we are going to stop the search there is no need
(and is also confusing) to clear the 'ponder' flag.

This mimics the behaviour upon rceiving 'stop' when
pondering.

No functional change.
2013-01-13 14:32:30 +01:00
Marco Costalba 89a89eb605 Simplify and rename wait_for_stop_or_ponderhit()
Setting stopOnPonderhit is now done by the caller.

No functional change.
2013-01-13 14:15:19 +01:00
Marco Costalba 3b14b17664 Simplify a condition in search()
And rearrange best value update in case of SpNode.

No functional change.
2013-01-13 13:17:16 +01:00
Marco Costalba 3a836dab59 Clarify SAN disambiguation in case of a pinned piece
In SAN notation when two pieces of the same type can
move to a given destination square, a disambiguation
additional info (like starting file) shall be added
to the SAN move.

If one of the two pieces is pinned, the corresponding
move _could_ be illegal and in this case disambiguation
is not needed. But to be pinned alone it is not enough
to deduce that the move is illegal, for instance in this
position:

R3rk2/2r6/8/8/8/8/8/K7 b - - 0 1

The move Rc8 is ambiguous although the rook in e8 is pinned
and the correct SAN notation should be Rcc8.

No functional change.
2013-01-12 13:21:14 +01:00
Marco Costalba e1191b35e8 Async 'stop' command
Don't wait for the search to finish after a 'stop'
command, but keep processing the GUI input if any.

Also explicitly wake up the main thread (that could be
sleeping) after a 'stop' or 'quit' command and do not
rely on wait_for_search_finished() doing it for us.

This patch cleans up the code and functions's definitions,
but it is risky and needs a good test under different
conditions to be sure it does not introduces hungs up.

No functional change.
2013-01-12 12:06:55 +01:00
Marco Costalba edce2a8448 Revert so called "fromNull patch"
Revert patch c581b7ea36

Seems a regression after testing from Gary:
ELO: 7.24 +- 99%: 17.03 95%: 12.93
LOS: 97.86%
Wins: 439 Losses: 381 Draws: 1962

And mine:
After 5410 games at 15"+0.05
Wins: 936 Losses: 1141 Draws: 3333  ELO -13

Moreover we know that there is a regression in the range
of patches which include the fromNull patch.

Probably this is not the only regression since 2.3.1 and
perhaps the idea under fromNull is good, but at the moment,
while in deep regression hunting, better to be on the safe
side and revert it entirely.

My guess on why this is a regression is that using the
negated evaluation of previous ply in case of null search
fails to take in account the king safety asymmetry between
the two colors. This is of course just a guess.

bench 5503830
2013-01-06 23:06:20 +01:00
Marco Costalba 9b1cf3cf43 Have fun with union in book.cpp
Fancy way to use an union to map polyglot
zobrist keys in one go.

Also some renaming while there.

No functional change.
2013-01-06 12:06:19 +01:00
Marco Costalba bff65a211f Retire 'Cowardice' and 'Aggressiveness' UCI options
They are not self-describing and create a lot of user
requests about them.

Given that the values are already well tuned there
is no need to expose them as UCI options.

No functional change.
2013-01-04 17:11:24 +01:00
Marco Costalba 2d60995c00 Retire 'mate in x' hack
Sometimes is faster, but not always and on very long mates
produces strange scores probably due to truncation of PV
artifacts.

So simply perform normal search also in case of UCI 'mate x'
command, with the only difference that when a mate in x is
found search returns immediately.

No functional change.
2013-01-04 16:30:46 +01:00
Marco Costalba 0454bbc54f Don't exit if unable to find bench file
Now that we can call 'bench' command also from
interactive terminal it makes no more sense to
exit the application if the user types a wrong
file name.

No functional change.
2013-01-04 14:52:21 +01:00
Marco Costalba 900e2d4e1e Teach file_to_char() about upper/lower case
This allows to further simplify Position::fen()

No functional change.
2013-01-04 14:45:04 +01:00
Marco Costalba 9d1151575d Reformat FEN construction
Simplify and shrink code.

No functional change.
2013-01-04 13:38:14 +01:00
Marco Costalba 193741218c Remove some obsolete asserts on TT values
Now that insert_pv_in_tt() stores VALUE_NONE in
TT's position evaluation those 2 asserts are
obselete.

No functional change.
2012-12-31 17:20:39 +01:00
Marco Costalba 896420b166 Allow to pass a 'seed' to RKISS
This somewhat simplifies the code.

Suggested by Lucas Braesch.

No functional change.
2012-12-31 11:59:53 +01:00
Marco Costalba 009a0f88e0 Micro-optimization in evaluate_space()
Since &-ing with SpaceMask restricts the set to the home
half of the board, it is possible to use just one popcount
instead of 2 by shifting "safe" to the other half of the
board. This gives a small speedup especially on systems
where hardware popcount is not available.

Patch kindly sent by Richard Vida.

No functional change.
2012-12-31 11:34:18 +01:00
Marco Costalba e1d681458e Add 'mate' limit to 'bench' command
It is now possible to run SF on a 'mate in x' testsuite.

For instance in case of a file with fen strings of
positions with mate in 10 we can now 'bench' on it:

stockfish bench 128 1 10 mate_in_10.epd mate

No functional change.
2012-12-30 15:49:02 +01:00
Marco Costalba ce063f59cd Handle UCI command "mate in x moves"
Following a user request I added the handling of UCI:

go mate x

Currently we just return from a PV node if x moves have been
done. Probably not the best approach. I have looked at Fruit/Toga
sources and there is even simpler: engine falls back on a fixed
depth search.

No functional change.
2012-12-30 14:43:23 +01:00
Marco Costalba 3cf6471738 Revert evaluation cache
And return on using TT as backing store for position
evaluations.

Tests (even on single thread) show eval cache was a regression.
In multi thread result should be even worst because eval cache
is a per-thread struct, while TT is shared.

After 4957 games at 15"+0.05 (single thread)
eval cache vs master 969 - 1093 - 2895  -9 ELO

So previous reported result of +18 ELO was probably due to an
issue in the testing framework (a bug in cutechess-cli) that
has been fixed in the meanwhile.

bench: 5386711
2012-12-27 13:57:17 +01:00
Marco Costalba f78b68b7ff Add list of legal moves to Position::pretty()
Along the same lines of previous patch now we add
the list of the legal moves in the given position.

No functional change.
2012-12-27 11:34:48 +01:00
Marco Costalba e9ab7353de Add checkers info to Position::pretty()
In case current position is under check, list the
squares of the checker(s) pieces.

This should satisfy a specific user request.

No functional change.
2012-12-26 18:28:45 +01:00
Marco Costalba 9d1978e217 Remove two obsolete asserts in prevents_move
Now that this function is called also to calculate
move's extensions the asserts are no more valid.

No functional change.
2012-12-26 12:27:41 +01:00
Marco Costalba db097921bc Rename yields_to_threat and prevents_threat
Follow Lucas suggestions and better name these
two functions.

No functional change.
2012-12-26 12:21:59 +01:00
Marco Costalba 894c43a1d6 Introduce Null Threat extension
In case of null search at low depths returns a fail low
due to a threat then, rather than return beta-1 (to cause
a re-search at full depth in the parent node), we set a flag
threatExtension = true (false by default) that will cause
moves that prevent the threat to be extended of one ply
in the following search.

Idea and patch is by Lucas Braesch.

Lucas also did the tests:
1500 games in 5"+0.05":
SF_threatExtension vs SF_20121222: 366 - 331 - 803 [51.2%] LOS=90.8%

3000 games in 10"+0.1":
SF_threatExtension vs SF_20121222: 610 - 559 - 1831 [50.8%] LOS=93.2%

Tests confirmed by Gary after 10570 games,
ELO: 2.79 +- 99%: 8.72 95%: 6.63
LOS: 94.08%
Wins: 1523 Losses: 1438 Draws: 7607

And finally by me at 15"+0.05, single thread, 3824 games
threatExtension vs master 768 - 692 - 2364  +7 ELO

bench 4918443
2012-12-25 19:17:27 +01:00
Marco Costalba b5b799b5ab Fix a couple of extra spaces
No functional change.
2012-12-25 18:48:41 +01:00
Marco Costalba e82382703c Retire Position::in_check()
It is redundant with Position::checkers()

No functional change.
2012-12-25 17:59:35 +01:00
Marco Costalba 3b49aeb4f2 Retire Position::move_is_legal()
Use the new contains() method of struct MoveList

No functional change.
2012-12-25 11:51:08 +01:00
Marco Costalba 423c6d8a8a Small tweak in is_pseudo_legal()
This is difficult code becuase a bug here could lead
to very subtle crashes in case of SMP games where we
have TT move corruption due to concurrent access.

Anyhow I have fully verified te code throwing at it
random moves. It shoudl work.

No functional change.
2012-12-25 11:31:32 +01:00
Marco Costalba 158014b39d Introduce namespace Pawns
And retire old struct PawnTable along the same lines
of previous patch.

No functional change.
2012-12-22 11:38:36 +01:00
Marco Costalba 231f62baf7 Introduce namespace Material
And retire old struct MaterialTable simplifying the code.

No functional change.
2012-12-16 12:58:39 +01:00
Marco Costalba 52bbf372bb Don't need to check for bestValue < beta to split
With rearrangement of fail high code this condition
is no more necessary.

Found by Jörg Oster.

No fuctional change.
2012-12-15 13:11:10 +01:00
Marco Costalba 3ddf91d9d1 Remove an extra semicolon
No functional change.
2012-12-15 11:20:04 +01:00
Marco Costalba a2f46446cf Revert store of distinct upper and lower bounds
Test by Joona prooves the new feature don't value 70 added lines of code.

Grand totals after 10040 games (crashes: 0) for tt_both

master_9edc7 - 6a93488_6a934: 1756 - 1688 - 6596 ELO +2 (+- 2.7)

Confirmed by test of Gary:

After 8680 games:
ELO: 0.80 +- 99%: 9.62 95%: 7.31
LOS: 65.38%
Wins: 1288 Losses: 1268 Draws: 6130

Thanks a lot to both for testing it !!!

bench 5149248
2012-12-15 11:18:52 +01:00
Marco Costalba 9edc7d6958 Merge branch 'eval_cache'
Unusually good result. Defenitly needs further verifications.

After 2160 games at 15"+0.05
Mod vs Orig 486 - 367 - 1307 ELO +19

bench: 6261882
2012-12-10 09:26:02 +01:00
Marco Costalba 55db871472 Fix comparison with alpha, not beta
This silly bug seems the reason of the unsual bench
value.

bench: 6261882
2012-12-09 14:19:21 +01:00
Marco Costalba da98a45bcb Ensure valueLower <= valueUpper
In case a TTEntry stores both an upper and a lower bound
ensure that upper bound is not smaller than lower bound.

bench 1813815
2012-12-09 14:14:44 +01:00
Marco Costalba feeafb0a50 Store distinct upper and lower bound scores
This is more complex than what I'd like but I
was unable to split in small chunks.

Here we add 2 slots to TTEntry (valueUpper and depthUpper)
so that sizeof(TTEntry) returns to the original 16 bytes
and we can pack exactly 4 entries in a 64 bytes cache line.

Now we save an upper bound score alongside a lower (exact)
score. The idea is to increase TT cut-offs rates becuase
there is now an higher probability for a node to use TT info.

This patch is highly experimental and probably needs further
steps as is hinted by an unrealistic bench number:

bench: 2022385
2012-12-09 13:15:50 +01:00
Marco Costalba 22c557ca7c Micro-optimize color_of()
In almost all cases we already know in advance that
color_of() argument is different from NO_PIECE.

So avoid the check for NO_PIECE in color_of() and
test at caller site in the very few places where
this case could occur.

As a nice side effect, this patch fixes a (bogus)
warning under some versions of gcc.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-12-08 12:32:48 +01:00
thaspel 6a93488291 Update Readme.txt now that we support 64 threads
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-12-04 19:57:16 +01:00
Marco Costalba 6fa83f5188 Merge branch 'eval_cache'
Use an eval cache instead of TT to store node
position evaluations.

It is already an improvment and, because it frees
two TT entry slots, paves the way to extend TT to
store both upper and lower bounds.

After 4855 games, single thread, 15"+0.05
Mod vs Orig 1165 -920 - 2770 ELO +18

bench: 5149248
2012-12-04 08:05:15 +01:00
Marco Costalba ce248e7920 Increase MAX_THREADS to 64
And document why this is an hard limit. It
seems for some (lucky) people 32 threads
are not enough.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-12-04 07:57:15 +01:00
Marco Costalba 23bdd06442 Reintroduce eval optimizaion from null search
Now that conversion to eval cache is finished
we can reintroduce this optimization.

bench: 5149248
2012-12-01 18:11:01 +01:00
Marco Costalba 98cd8239cc Don't save eval score in TT
This patch completes the removal of eval info
in TT table.

No functional change.
2012-12-01 15:19:50 +01:00
Marco Costalba 2a585b63b8 Don't use TT just to save a node evaluation
In search(), after we evalute the position, in case there
isn't any TT entry we create one with just the evaluation
score.

This patches removes that code. The reason becuase the patch
deserves a single commit it is becuase introduces a (very small)
functional change due to the fact that the total number of
TT stores is less now and this slightly alters the TT hits
of our benchmark.

bench: 4983262
2012-12-01 15:13:08 +01:00
Marco Costalba a5ea3a202e Don't read eval from TT anymore
Rely fully on eval cache. Note that we still save eval
info to TT, this is not needed at this moment and will be
removed in future patches. We keep it so to have a "non
functional change" patch.

No functional change.
2012-12-01 15:01:00 +01:00
Marco Costalba 69de670353 Retire eval optimization from null search
Simplify things preparing for further changes.

bench: 4983282
2012-12-01 14:48:13 +01:00
Marco Costalba 4e5d834e8e Add eval cache infrastructure
With this patch series we want to introduce a per-thread
evaluation cache to store node evaluation and do not
rely anymore on the TT table for this.

This patch just introduces the infrastructure.

No functional change.
2012-12-01 14:01:20 +01:00
Marco Costalba 4502917665 Don't double check for move legality
In case of a RootNode or a SpNode move has
been already checked for legality so we can
skip a redundant check.

Spotted by Frank Genot.

No functional change.
2012-11-27 20:05:03 +01:00
Marco Costalba 5af8179647 Update bestValue when futility pruning
In qsearch we should update the bestValue as we do
in case of futilityValue < beta, also when pruning
moves with non-positive see.

Spotted by Lucas Braesch

Bench: 5695710
2012-11-26 16:13:36 +01:00
Marco Costalba 55df3fa2d7 Avoid spamming the GUI in multipv search
Send the PV lines to GUI only once at the end of the
PV search loop or just in case of long searches.

We need to sync also sending of "currmove" info to
avoid sending info on current move without first
informing the GUI on the PV line we are searching on.

No functional change.
2012-11-18 11:46:37 +01:00
Marco Costalba 8367cf15da Triviality in move_gives_check()
It seems even a bit faster, although handling of the special
cases is not the hot path.

No functional change.
2012-11-17 13:08:04 +01:00
Marco Costalba 942989939a Better document fail-high condition
At this point we have already verified (value > alpha)
and this implies, in case of a non-PV node, where search
window size is zero, that value >= beta.

This is not so self-evident, so document the code with
an assert condition.

No functional change.
2012-11-17 12:50:10 +01:00
Marco Costalba 239d7b3fd1 Don't access std::cout from Position::print()
Let the caller to decide where to redirect (cout or cerr) the
ASCII representation of the position. Rename the function to
reflect this.

Renamed also from_fen() and to_fen() to set() and fen() respectively.

No functional change.
2012-11-11 13:30:20 +01:00
Marco Costalba 116234d6c6 Restore old BOUND_EXACT logic in qsearch
In case a PvNode node has a static evaluation above alpha but
no available moves we want to flag the node as BOUND_EXACT,
not as BOUND_UPPER as is currently.

The behaviour was recently introduced with patch d471c49700
of 3/10/2012

Spotted by Hongzhi Cheng.

bench: 5558464
2012-11-11 11:52:11 +01:00
Marco Costalba c45a4e0b48 Revert "Don't prune discovered checks"
Both Lucas re-test and Jean-Francois confirrm it
is a regression.

Here Jean-Francois's results after 3600 games :
Score of 96d3b1c92b vs 3b87314: 690 - 729 - 2181 [0.495] 3600
ELO: -3.86 +- 99%: 14.94 95%: 11.35
LOS: 15.03%
Wins: 690 Losses: 729 Draws: 2181 Total: 3600

Bench: 5404066
2012-11-11 11:20:39 +01:00
Marco Costalba 96d3b1c92b Don't prune discovered checks
Don't prune and eventually extend check moves of type
DISCO_CHECK (pun intended, Lucas will understand :-) ).

Patch from Lucas Braesch that has also tested it:

Result: 879-661-2137, score=52.96%, LOS=100.00% (time 10"+0.1")

I have started a verification test right now.

bench: 6004966
2012-11-07 18:29:56 +01:00
Marco Costalba 3b87314331 Previous patch test results
From Jean-Francois's

Final result after 5000 games :
Score of c581b7e vs a878312: 1163 - 970 - 2867 [0.519] 5000
ELO: 13.35 +- 99%: 12.71 95%: 9.65
LOS: 100.00%
Wins: 1163 Losses: 970 Draws: 2867 Total: 5000

From me

After 3266 games at 20"+0,05
Score of c581b7e vs a878312: 612 - 607 - 2047

So no regression at longer TC and perhaps a little gain at
fast TC.
2012-11-07 18:07:03 +01:00
Marco Costalba c581b7ea36 Another attempt at evaluation shortcut
In this case we try a rather drastic
approach: we simply don't futility prune
in qsearch when arriving from a null move.

So we save evaluating and also save to mess
with eval margins at all because margin is used
only in futility.

Also accuracy should not be affected, actually it
improves because we don't prune anything anymore.

bench: 5404066
2012-11-05 16:12:28 +01:00
Marco Costalba a5b1f4774f Temporary revert previous patch
Performs well at very short TC of 40/4+0.05 (courtesy of Jean-Francois):
Wins: 2503 Losses: 2146 Draws: 5581 Total: 10230 +12 ELO

But is poor at longer TC of 20"+0.05
Wins: 321 Losses: 373 Draws: 1141 Total: 1808 -10 ELO

The patch was clearly a tradoff between speed and accuracy and
the most interesting part of it are test results that can be
commented as follows:

- A short TC is very sensible to any speed increase
- A longer TC is more sensible to accuracy and less to speed

So a patch that does not change speed is suitable to be tested at
short TC, while a speed/accuracy compromise patch is IMO better to
be tested at longer TC to verify loss of accuracy can be tolerated.

In this case the revert is only temporary. We will come back again
once we will be able to preserve the evaluation margin.

bench: 5809010
2012-11-05 07:41:28 +01:00
Marco Costalba 37e9802411 Skip evaluate() call after a null move
Reuse the evaluation of the parent with inverted sign and
set margin to zero (this is an hack!).

This is done only in qsearch where almost 15% of calls are
from a null move. In normal search the number of nodes where

(ss-1)->currentMove == MOVE_NULL

is almost zero and so there is no need of using this trick.

The big advantage of this patch is a speed-up due to skipped
evaluate() calls, that are very costly.

Functionality is of course affected and we will need to proper
test it later. For now we just register a 3-4% speed up.

Suggested by Hongzhi Cheng.

bench: 5051328
2012-11-04 10:48:14 +01:00
Marco Costalba a87831230d Correctly fix "break from split" patch
In case split cut-offs we return with still
some moves to go but we really want to break
out from the loop now.

No functional change.
2012-11-03 17:09:18 +01:00
Marco Costalba dd5b3086f5 Relax constrain in prevents_threat()
When testing if a move blocks the threat path there is no
reason to require the threat to be a slider. Indeed threat
can be a double pawn push like in this example:

r1bq1rk1/ppp1np1p/4n1p1/3p4/3P2Q1/2P1B3/PPBN2PP/R4RK1 w - - 0 16

Where white's move Rf6 blocks the threat f5.

As a nice side effect we can retire the now useless helper
piece_is_slider().

This patch kicks in only very rare cases, indeed the bench is
still the same!

bench: 5809010
2012-11-03 15:57:20 +01:00
Marco Costalba 47f988f05f Sync connected_threat() and yields_to_threat()
Rename stuff so to sync as much as posisble the
two related functions.

No functional change.
2012-11-03 15:36:12 +01:00
Marco Costalba 07989712af Don't 'break' upon returning from split()
There is no guarantee that split() consumes all the node's
moves. Indeed split() can return without performing any job
for instance because MAX_SPLITPOINTS_PER_THREAD is reached
or becuase no available threads are found (this latter case
is much more common).

So search must continue in those cases and we cannot force
exiting from move's loop.

Bug introduced by 1ac417edb8 of 5/10/2012

Spotted by Frank Genot.

No functional change.
2012-11-03 14:54:38 +01:00
Marco Costalba d0d69a5358 Remove a redundant condition in connected_moves()
If a previous move attacks the king (with the piece
of the threat move removed) then must be a discovered
check, otherwise it means that first move gave check
and we were not able to do a null move.

Also renamed stuff to better document the function's
context.

No functional change.
2012-11-03 14:24:29 +01:00
Marco Costalba 972de506a0 Relax constrain in connected_moves()
When testing if a piece is moving through the squares
vacated by a previous move there is no reason to require
the piece to be a slider, indeed we can have a double
pawn push like in this example:

r1q2rk1/2p1bppp/2Pp4/pN5b/Q1P1p3/4B2P/PP1R1PP1/1K5R w - - 3 18

Where black's move f5 is connected to previous move Be7 that
frees the path.

Or we can have a castle move:

r1bqkb1r/pppp1ppp/2n1pn2/1B6/4P3/2N2N2/PPPP1PPP/R1BQK2R b KQkq - 5 1

Where a previous move Bb5 allows the white to castle king side.

This time patch is mine ;-)

new bench: 5809010
2012-11-03 13:34:04 +01:00
Marco Costalba ed1574e46c Reformat connected_moves()
Prepare code for the next patch that
will affect functionality.

No functional change.
2012-11-03 13:27:44 +01:00
Marco Costalba 52f55179a8 Fix an off-by-one bug in multi pv print
We send to GUI multi-pv info after each cycle,
not just once at the end of the PV loop. This is
because at high depths a single root search can
be very slow and we want to update the gui as
soon as we have a new PV score.

Idea is good but implementation is broken because
sort() takes as arguments a pointer to the first
element and one past the last element.

So fix the bug and rename sort arguments to better
reflect their meaning.

Another hit by Hongzhi Cheng.  Impressive!

No functional change.
2012-11-03 00:36:40 +01:00
Marco Costalba bbdf9e4737 Fix a condition in connected_moves()
When checking if the moving piece p1 in a previous
move m1 defends the destination square of a move m2
we have to use the occupancy with the from square of
m2 removed so to take in account the case in which
f2 will block an x-ray attack from p1.

For instance in this position:
r2k3r/p1pp1pb1/qn3np1/1N2P3/1p3P2/2B5/PPP3QP/R3K2R b KQ - 1 9

The move eXf6 is connected to the previous move Bc3 that
defends the destination square f6.

With this patch we have about 10% more moves detected as
'connected'. Anyhow the absolute number is very low, about
4000 more moves out of 6M nodes searched.

Another issue spotted by Hongzhi "Hawk Eye" Cheng ;-)

new bench: 5757373
2012-11-02 17:18:38 +01:00
Marco Costalba 94ecdef8ac Micro-optimize pop_lsb() for 64bit case
On Intel, perhaps due to 'lea' instruction this way of
zeroing the lsb of *b seems faster than a shift+negate.

On perft (where any speed difference is magnified) I
got a 6% speed up on my Intel i5 64bit.

Suggested by Hongzhi Cheng.

No functional change.
2012-11-02 12:11:49 +01:00
Marco Costalba e3b0327812 Fix a warning under MSVC
Compiler complies that 'cnt' is initialized but
unused (in !CheckThreeFold case). Moving the
definition of 'cnt'out of the loop  seems to do
the trick.

No functional change.
2012-11-02 11:43:23 +01:00
Marco Costalba c039103b31 Pass InCheck as template parameter of qsearch()
Instead of use a variable so to resolve many conditions
already at compile time. In quiesce is also where we
have most of the InCheck nodes and is one of the most
performance critical code paths.

Speed up of 1.5% with Clang and 1% with gcc

Suggested by Hongzhi Cheng.

No functional change.
2012-11-01 18:45:38 +01:00
Marco Costalba fe1cbe2638 Use correct occupancy in connected_threat()
When checking if a move defends the threatened piece
we correctly remove from the occupancy bitboard the
moved piece. This patch removes from the occupancy also
the threatening piece so to consider the cases of moves
that defend the threatened piece x-raying through the
threat move.

As example in this position:
r3k2r/p1ppqp2/Bn4p1/3p1n2/4P1N1/5Q1P/PPP2P1P/R3K2R w KQkq - 1 10

The threat black move is dxe4. With this patch we include
(and so don't prune) white's Bb7 that would be pruned otherwise.

The number of affected position is very low, around 1% of cases,
so we don't expect ELO changes, neverthless this is the logical
and natural thing to do.

Patch suggested by Hongzhicheng.

new bench: 5323798
2012-10-30 20:27:07 +01:00
Marco Costalba 4e31c39a64 Retire move_attacks_square()
There is only one call site. This patch is a
preparation for the next one that will affect
functionality.

No functional change.
2012-10-30 20:03:35 +01:00
Marco Costalba 13f90a30ef Get rid of ReducedStateInfo struct
ReducedStateInfo is a redundant struct that is also
prone to errors, indeed must be updated any time is
updated StateInfo. It is a trick to partial copy a
StateInfo object in do_move().

This patch takes advantage of builtin macro offsetof()
to directly calculate the number of quad words to copy.
Note that we still use memcpy to do the actual job of
copying the (48 bytes) of data.

Idea by Richard Vida.

No functional and no performance change.
2012-10-29 08:07:17 +01:00
Marco Costalba ad1941fd00 Creative formatting in uci.cpp
Have some fun breaking the indentation rules :-)

No functional change.
2012-10-28 11:28:14 +01:00
Gary Linscott cee6336515 Detect drawish KQKP endings
Based off of the rules from the wikipedia page,
here: http://en.wikipedia.org/wiki/Queen_versus_pawn_endgame.

bench does not change: 5312693 but patch is real, has been
tested on specific positions.
2012-10-28 10:17:57 +01:00
Marco Costalba b3d030294b Reformat check_is_dangerous()
And shuffle some code at search.cpp tail.

No functional change.
2012-10-27 15:07:20 +02:00
Marco Costalba cd80762c13 Use std::stack instead of fixed size array
Only in not performance critical code like pretty_pv(),
otherwise continue to use the good old C-style arrays
like in extract/insert PV where I have done some code
refactoring anyhow.

No functional change.
2012-10-27 13:31:23 +02:00
Marco Costalba 00a853950f Fix broken uci notation for promotions
Silly typo (introduced in e304db9d1e) completely
messed up move notation in case of promotions causing
"Illegal move" warning in cutechess-cli.

Reported by Jörg Oster.

No functional change.
2012-10-26 16:06:47 +02:00
Marco Costalba 4c7a71a44b Fix asserts due to TT access races
In multi-threads runs with debug on we experience some
asserts due to the fact that TT access is intrinsecally
racy and its contents cannot be always trusted so must
be validated before to be used and this is what the
patch does.

No functional case.
2012-10-26 12:41:12 +02:00
Marco Costalba c594b989c0 Extend full 3 fold detection to PvNodes
And restore old behaviour of not returning from a RootNode
without updating RootMoves[].

Also renamed is_draw() template parameters to reflect a
'positive' logic (Check instead of Skip) that is easier
to follow.

New bench: 5312693
2012-10-26 11:56:33 +02:00
Marco Costalba 71f37ac1aa Merge pull request #34 from jromang/repetition
Improve 3 fold repetition detection
2012-10-26 02:01:10 -07:00
Jean-Francois Romang 77c91ac1ba Full three fold repetition detection only at root node 2012-10-25 15:57:44 +02:00
Jean-Francois Romang 5436d98fc5 Enable true 3 fold detection in search 2012-10-25 06:54:05 +00:00
Jean-Francois Romang 0587c5b605 Allow full repetition detection
Based on sshivaji 6ee19aa5389ce60181907ba53bbb50642f2d5657 commit
2012-10-25 06:28:55 +00:00
Marco Costalba c1f4000426 Fix an assert when we stop the search
When signal 'stop' is raised we return bestValue
that could be still set at -VALUE_INFINITE and
this triggers an assert. Fix it by returning
a value we know for sure is not +-VALUE_INFINITE.

Reported by 平岡拓也 Hiraoka.

No functional change.
2012-10-25 00:07:59 +02:00
Marco Costalba 22715259a0 Rename RootPosition and shuffle think()
Just slightly code reshuffles, noting interesting here...

No functional change.
2012-10-24 15:01:39 +02:00
Marco Costalba 4eda653a56 Drop Chess960 and UCIMultiPV globals and rename MultiPV
No functional change.
2012-10-24 14:31:33 +02:00
Marco Costalba e8e5b9f537 Wrap in a class Skill Level code
Note that the actual pickup is done in the class
d'tor so to be sure it is always triggered, even
in case of a sudden exit due to a 'stop' signal.

No functional change.
2012-10-24 12:52:29 +02:00
Marco Costalba 9c2b3faec4 Shuffle aspiration window loop
No functional change.
2012-10-24 11:35:53 +02:00
Marco Costalba 70b1b79264 Retire refine_eval()
Inline its content and better comment what it does through
some renaming.

No functional change.
2012-10-22 10:03:53 +02:00
Marco Costalba 5fc8b27db9 Don't copy a full Position object in print()
Function move_to_san() requires the Position to be
passed by referenced because a do/undo move is done
inside the function to detect a possible mate and to
add to the san string the corresponding '#' suffix.

Instead of passing a copy of current position pass
directly the original position object after const
casting it. This has the advantage to avoid a costly
Position copy, on the down side a bench test could
report different searched nodes if print(move) is
used, due to the additionals do_move() calls.

No functional change.
2012-10-22 00:55:16 +02:00
Marco Costalba dbbbd3880c Don't need to init board[] with NO_PIECE
Now that NO_PIECE == 0 the common memset() will
do the work.

No functional change.
2012-10-22 00:38:12 +02:00
Marco Costalba e40b06a050 Change NO_PIECE value and shrink PieceValue[]
This requires changing color_of() definition.

No functional change.
2012-10-21 11:50:56 +02:00
Marco Costalba e304db9d1e Use self-describing constants instead of numbers
And remove now useless comments.

No functional change.
2012-10-21 11:16:21 +02:00
Marco Costalba 6b909b2343 Move RootColor from Eval to Search
No functional change.
2012-10-21 09:12:02 +02:00
Marco Costalba 55bd27b8f0 Contempt factor: use DrawValue also in case of stealmates
Spotted by Jörg Oster.

No functional change (when contempt factor is not used).
2012-10-20 11:02:37 +02:00
Marco Costalba 1018474853 Fix compatibility with old Windows 95 and 98
Report and patches by bnemias.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-10-20 10:48:26 +02:00
Marco Costalba c11edd3b0b Merge pull request #33 from daylen/master
Further improve OS X compatibility

Change the minimum supported version from 10.6 to 10.0

No functional change.
2012-10-20 01:07:27 -07:00
Daylen Yang f0298862f5 Further improve compatibility when compiling on OS X
Change the minimum supported version from 10.6 to 10.0
2012-10-16 00:13:16 -07:00
Marco Costalba 739d23f2a3 Fix Makefile for PowerPC with prefetch enabled
Existing Makefile is buggy for PowerPC, it has no
SSE, yet it is given it if Prefetch is enabled,
because it isn't ARMv7.

Patch from Matthew Brades.

No functional change.
2012-10-15 01:13:41 +02:00
Marco Costalba 3aa2d6db18 Document why is safe ttValue == VALUE_NONE
We can have ttValue == VALUE_NONE when we use a TT
slot to just save a position static evaluation, but
in this case we also save DEPTH_NONE so to avoid
using the ttValue in search. This happens to work,
but due to a number of lucky and tricky cases that
we now documnet through a bunch of asserts and a
little change to value_from_tt() that has no real
effect but clarifing the code.

No functional change.
2012-10-14 12:47:16 +02:00
Marco Costalba 6a75291ab1 Set TT size to 32 MB during 'bench'
On some platforms 128 MB of RAM for TT is too much,
so run 'bench' with the default 32 MB size.

No functional change although of course now 'bench'
reports a different number: 5545018
2012-10-14 09:02:17 +02:00
Marco Costalba eb1a4f11fa Move all Contempt Factor code to search.cpp
Where it is used.

No functional change.
2012-10-13 14:49:01 +02:00
Marco Costalba d023be5a21 Retire BitCount8Bit[] table
Use popcount() instead in the only calling place.
It is used only at initialization so there is no
speed regression and anyhow even initialization
itself is not slowed down: magic bitboard setup
stays around 175 msec on my slow 32bit Core Duo.

No functional change.
2012-10-13 14:24:01 +02:00
Marco Costalba c2cd75843e Use new 64 bit De Bruijn BitScan
Allows to sync 32 and 64 bits implementations.

Idea by Kim Walisch, reported by Gerd Isenberg:
http://talkchess.com/forum/viewtopic.php?t=45554

No functional change.
2012-10-13 13:45:45 +02:00
Marco Costalba 189b6fc270 Retire can_return_tt() and rewirte TT-hit code
Simplify the code and doing this introduce a couple
of (very small) functional changes:

- Always compare to depth even in "mate value" condition
- TT cut-off in qsearch also in case of PvNode, as in search

Verified against regression with 2500 games at 30"+0.05
on 2 threads: 451 - 444 - 1602

Functional changed: new bench is 5544977
2012-10-13 11:45:14 +02:00
Marco Costalba 6c8663341e Scale contempt factor to zero at endgame
Contempt Factor is more effective at opening/middle game
and seems harmful at endgame phase. See:

http://chessprogramming.wikispaces.com/Contempt+Factor

http://web.archive.org/web/20070707023203/www.brucemo.com/compchess/programming/contempt.htm

Therefore we scale down the contempt factor while going
on with the game so to reach zero at endgame phase.

No functional change.
2012-10-13 10:40:38 +02:00
Marco Costalba aba152ea3a Fix a minor bug in search
As Joona says: "The problem is that when doing full
window search (-VALUE_INFINITE, VALUE_INFINITE), and
pruning all the moves will return fail low which is
mate score, because only clause touching alpha is
"mate distance pruning". So we are returning mate score
although we are just pruning all the moves. In reality
there probably is no mate in sight.

Bug spotted and fixed by Joona.
2012-10-11 21:12:43 +02:00
Jean-Francois Romang 7f9ebf8e86 ARM lsb/msb assembly
Implement lsb/msb using armv7 assembly instructions.
msb is the easiest one, using a gcc intrinsic that generates
code using the ARM's clz instruction. lsb is also using this
clz instruction, but with the help of ARM's 'rbit' (bit
reversing) instruction. This leads to a >2% speed gain.

I also renamed 'arm-32' to the more meaningfull 'armv7' in the Makefile

No functional change.
2012-10-11 21:01:52 +02:00
Jean-Francois Romang 4e7da9be3d Introduce arm-32 ARCH in Makefile
No functional change.
2012-10-11 07:34:48 +02:00
Marco Costalba 46c01b5083 Retire is_dangerous() and inline its content
No functional change.
2012-10-10 08:13:36 +02:00
Marco Costalba dae843d4d6 Rearrange prefetch code
No functional change.
2012-10-08 11:43:47 +02:00
Marco Costalba 78fe0cfb8d Merge pull request #29 from RyanTaker/patch-3
Add Contempt Factor to Polyglot.ini
2012-10-07 15:36:08 -07:00
RyanTaker d77d555c72 Add Contempt Factor in Polyglot
The contempt factor was previously not included in polyglot.ini
2012-10-07 09:49:55 -07:00
Marco Costalba bbaef048cd Sync qsearch with search
Port to qsearch() the same changes we recently
added to search().

Overall this search refactoring series shows
almost 2% speed up on gcc compile.

No functional change.
2012-10-07 13:15:41 +02:00
Daylen Yang 7e2d49368d Improve compatibility with older versions of Mac OS X
Use the -mmacosx-version-min flag to support older versions of Mac OS X
(like version 10.6 and 10.7) when compiled on a machine running version
10.8.
2012-10-06 17:56:12 -07:00
Marco Costalba 954fc950d9 Fix POPCNT support on mingw 64
When using asm 'popcnt' instruction the given
operand registers must be of the same type.

No functional change.
2012-10-06 13:01:44 +02:00
Marco Costalba d777c4d789 Fix mingw compile with ARCH=x86-64
When using the Makefile (as for the mingw case),
IS_64BIT and USE_BSFQ are already set with
ARCH=x86-64 and do not need to be redefined.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-10-06 12:34:09 +02:00
Marco Costalba cedbd3332a Fix Contempt Factor implementation
First disable Contempt Factor during analysis, then
calculate the modified draw score from the point of
view of the player, so from the point of view of
RootPosition color.

Thanks to Ryan Taker for suggesting the fixes.

No functional change.
2012-10-06 10:12:34 +02:00
Marco Costalba ff9ca3e76e Fix fallouts from previous patch
These kind of arch specific code is really nasty
to make it right becuase you need to verify on
all the platforms.

Now should compile properly also on ARM

Reported by Jean-Francois.

No functional change.
2012-10-06 09:09:27 +02:00
Jean-Francois Romang b8948e84b8 Allow prefetching on non-x86 platforms with gcc
In particular on ARM processors. Original patch by
Jean-Francois, sligtly modified by me to preserve
the meaning of NO_PREFETCH flag.

Verified with gcc, clang and icc that prefetch instruction
is correctly created.

No functional change.
2012-10-06 00:43:16 +02:00
Marco Costalba 1ac417edb8 Retire futility_move_count()
And remove (bestValue < beta) condition from
moves loop.

No functional change.
2012-10-05 18:24:38 +02:00
Marco Costalba d471c49700 Rewrite search best value update
A simplification and also a small speed-up of
about 1% mainly due to reducing calls to
thisThread->cutoff_occurred().

Worst case split point recovering time after a
cut-off occurred is limited to 3 msec on my slow
PC, and usually is below 1 msec, so it seems safe
to remove the cutoff_occurred() check.

No functional change.
2012-10-05 13:53:05 +02:00
Marco Costalba c9f9262a49 Add experimental contempt factor
This is very crude and very basic: simply in case
of a draw for repetition or 50 moves rule return
a negative score instead of zero according to the
contempt factor (in centipawns). If contempt is
positive engine will try to avoid draws (to use
with weaker opponents), if negative engine will
try to draw. If zero (default) there are no changes.

No functional change.
2012-10-05 08:28:23 +02:00
Marco Costalba bd7a0d4ce4 Retire EasyMoveMargin
Use a value related to PawnValue instead.

This is a different patch from previous one because
could affect game play and skill levels, although
in a mostly unmeasurable way. Indeed thresold has
been raised so easy move is a bit harder to trigger
and skill level is a bit more prone to blunders.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-10-03 18:59:24 +02:00
Marco Costalba 561eb34aea Don't hide thresolds values
Show the real value in the code, not hide it
behind a variable name, especially when there
is only once occurence.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-10-03 18:56:36 +02:00
Marco Costalba 4c91dbc28e Further push singular extension
Extend for an extra half-ply in case the node is (probably)
going to fail high. In this case the added overhead is limited.

A novelity is the way this patch has been tested: Always in
self-play but with a much longer TC to allow the singular
extension to fully kick in and also (my impression) to have
less noisy results.

Ater 1015 games on my QUAD at 60"+0.05
Mod vs Orig 173 - 150 - 692 ELO +8
2012-10-02 06:39:27 +02:00
Marco Costalba 1b6b711c44 Further rearrange search()
No functional change.
2012-10-01 10:44:04 +02:00
Marco Costalba faaa1f1116 Don't push on the stack 200KB in one go
This could be a limit on some platforms (as it seems
to be in Native Client). Patch from a SF fork on github:

https://github.com/ccherng/Stockfish/commit/47374afd6fdfabd9de183a7a67d645daad45fb21

No functional change.
2012-09-30 11:35:14 +02:00
Marco Costalba ed0fb0b05f Add support for node limited search
Handle also the SMP case. This has been quite tricky, not
trivial to enforce the node limit in SMP case becuase
with "helpful master" concept we can have recursive split
points and we cannot lock them all at once so there is the
risk of counting the same nodes more than once.

Anyhow this patch should be race free and counted nodes are
correct.

No functional change.
2012-09-30 10:19:22 +02:00
Marco Costalba e5463eb3ae Skip some useless initializations in search()
And rearrange a bit the initialization code. Still
some polishing to do, but it is a first step.

No functional change.
2012-09-29 23:12:39 +02:00
Marco Costalba d53c928261 Don't need to early check PV moves for legality
As long as isPvMove (renamed to pvMove) is set after
legality check, we can postpone legality even in PV case.

Patch aligns the PV case with the common non-pv one.

No functional change.
2012-09-29 18:05:49 +02:00
Marco Costalba bc8f5fe0bf Drop a magic in book.cpp
Mask out move's spacial flags without relying
on internal Move representation.

No functional change.
2012-09-22 11:19:10 +02:00
Marco Costalba 9204a60dbb Tweaks to bitcount functions
Seems even a bit faster now (almost 1% in 32bit case).

No functional change.
2012-09-22 10:59:33 +02:00
Marco Costalba 1cb2722c95 Restore development version 2012-09-22 00:37:18 +02:00
Marco Costalba 3caeabf73b Stockfish 2.3.1
Stockfish bench signature is: 5423738
2012-09-22 00:20:44 +02:00
Gary Linscott fdbe8006e0 Bonus for rook/queen attacking pawns on same rank
Patch and tuning by Gary Linscott from an idea of Ryan Taker.

Double tested by Gary:

Wins: 3390 Losses: 2972 Draws: 11323
LOS: 99.999992%
ELO: 8.213465 +- 99%: 6.746506 95%: 5.124415
Win%: 51.181792 +- 99%: 0.969791 95%: 0.736740

And by me:

After 5612 games 1255  1085  3271 +11 ELO
2012-09-21 23:25:13 +02:00
Marco Costalba 09acdac56b Fix compile on 64 bits
Reported by Quocvuong82.

No functional change.
2012-09-20 19:25:27 +02:00
Marco Costalba e4a0482e43 Simplify BSFTable initialization
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-09-19 20:47:53 +02:00
Marco Costalba 22a5f91aa7 Fix crash under Chess 960
We have a crash with this position:

rkqbnnbr/pppppppp/8/8/8/8/PPPPPPPP/RKQBNNBR w HAha -

What happens is that even if we are castling QUEEN_SIDE,
in this case we have kfrom (B8) < kto (C8) so the loop
that checks for attackers runs forever leading to a crash.

The fix is to check for (kto > kfrom) instead of
Side == KING_SIDE, but this is slower in the normal case of
ortodhox chess, so rewrite generate_castle() to handle the
chess960 case as a template parameter and allow the compiler
to optimize out the comparison in case of normal chess.

Reported by Ray Banks.
2012-09-16 14:14:55 +02:00
Marco Costalba 9ce7469846 Rename class Book to PolyglotBook
And move struct BookEntry out of the header where it is
not needed.

No functional change.
2012-09-16 10:32:57 +02:00
Marco Costalba 4b7dbb3922 Fix KpsK endgame
Broken by commit a44c5cf4f7 of 3 /12 / 2011 that
was labeled "No functional change" because our 'bench'
test didn't triggered that particular endgame. Indeed
we need to run a specific bench on a set of endgames
position when touching endgame.cpp because normal bench
does not cover endgames properly.

Found by MSVC 2012 code analyzer.
2012-09-16 08:57:26 +02:00
Marco Costalba e0035e9ca9 Restore development version
No functional change.
2012-09-15 11:02:08 +02:00
Marco Costalba 0a18adb02a Stockfish 2.3
Stockfish bench signature is: 5416292
2012-09-15 10:56:17 +02:00
Marco Costalba 630b3b2482 Fix compile with Intel 13.0
It seems Intel is unable to properly workout templates with 'static'
storage specifier.

Workaround using an anonymous namespace instead.

No functional change.
2012-09-15 10:55:39 +02:00
Marco Costalba 6008f6538e Don't exit earlier from aspiration window loop
Currently we exit the loop when

abs(bestValue) >= VALUE_KNOWN_WIN

but there is no logical reason for this. It seems more
natural to re-search again with full open window.

This has practically no impact in most cases, we have a
'no functional change' running 'bench' command.
2012-09-14 10:05:46 +02:00
Marco Costalba afcee1e8a4 Fix MSVC 2012 64bits warnings
Reported by Rein.

No functional change.
2012-09-14 09:57:13 +02:00
Marco Costalba e0bd0f250b Speed-up generate<LEGAL>
The trick here is to check for legality only in the
(rare) cases we have pinned pieces or a king move
or an en-passant.

This trick is able to increase the speed of perft
of more then 20%!

No functional change.
2012-09-11 20:24:31 +02:00
Marco Costalba 1598a3edf8 Remove redundancy in move generation
Introduce generate_all_moves() and remove a good
bunch of redundant code.

No functional change.
2012-09-09 17:05:02 +02:00
Marco Costalba 0dacab65eb Simplify generate_castle()
Skipping the calls to std::min(), std::man() we get
even a nice speed-up on perft.

No functional change.
2012-09-09 11:50:28 +02:00
Marco Costalba 834bd9edd7 Rename *last to *end
It is a more correct name because it points past the
last move of the list.

No functional change.
2012-09-09 10:24:40 +02:00
Marco Costalba 6e840f8033 Enable link time optimization only when optimizing
Because it is quite slow, skip it when 'optimize' flag is 'no'

No functional change.
2012-09-09 10:02:11 +02:00
Marco Costalba 2379312028 Revert "Simplify Option c'tor"
std::to_string() is C++11 material, not c++03.

So revert the patch.
2012-09-07 15:21:50 +02:00
Marco Costalba 37db62b2ea Simplify Option c'tor
No functional change.
2012-09-06 18:18:13 +02:00
Marco Costalba b50ce5ebfb Get rid of struct Time
We just need the milliseconds of current system
time for our needs. This allows to simplify the
API.

No functional change.
2012-09-04 09:38:51 +02:00
Marco Costalba 5900ab76a0 Rename current_time() to now()
Follow C++11 naming conventions.

No functional change.
2012-09-02 17:04:22 +02:00
Marco Costalba e6d8e74152 Greatly speed up SEE
Simply reshuffling the code inverting the condition in next_attacker()
yields a miraculous speed up of more than 3% under gcc!

On my laptop a bench run goes from 320Knps to 330Knps

No functional change.
2012-09-02 00:27:53 +02:00
Marco Costalba 9cdca7516c Unroll least valuable attacker loop in SEE
This allows to reduce the scanning for new X-ray attacks
according to the capturing piece type.

It seems to be just a very small speed increase in MSVC 64
bit and gcc 32 bit, I guess cache issues value more than some
instruction less to execute (as usual).

No functional change.
2012-09-01 18:57:38 +02:00
Marco Costalba 6436e75858 Slightly simplify SEE
Some renaming and small code reshuffle.

No fuctional change.
2012-09-01 15:42:04 +02:00
Marco Costalba 831f91b859 Retire Time::restart()
Simplify API.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-31 19:47:07 +02:00
Marco Costalba 1258c7aabe Don't need to memset HashTable
Default c'tor Entry() already initializes
to zero all its POD members.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-31 19:47:00 +02:00
Marco Costalba 8dcb4bc3cc Terminate threads before to exit main()
It is very difficult and risky to assure
that a running thread doesn't access a global
variable. This is currently true, but could
change in the future and we don't want to rely
on code that works 'by accident'. The threads
are still running when ThreadPool destructor is
called (after main() returns) and this could
lead to crashes if a thread accesses a global
that has been already freed. The solution is to
use an exit() function and call it while we are
still in main(), ensuring global variables are
still alive at threads termination time.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-29 19:11:44 +02:00
Marco Costalba 0a003d3ba1 Convert to sync_cout and sync_endl
Serialize access to std::cout all over the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-29 19:11:44 +02:00
Marco Costalba 92e759a676 Introduce serialization of accesses to std::cout
When many threds concurrently print you need to serialize
the access to std::cout to avoid output lines are intermixed
with the contents of each thread.

This is not strictly needed at the moment because
only main thread prints out, although some ad-hoc
test could trigger UCI::loop() printing while searching.

Anyhow we want to lift this pretty avoidable constrain
also as a prerequisite for future work.

This patch just introduces the support, next one will enable
the serialization.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-29 19:11:31 +02:00
Marco Costalba 3df2c01b57 Correctly handle handover of setup states
Before the search we setup the starting position doing all the
moves (sent by GUI) from start position to the position just
before to start searching.

To do this we use a set of StateInfo records used by each
do_move() call. These records shall be kept valid during all
the search because repetition draw detection uses them to back
track all the earlier positions keys. The problem is that, while
searching, the GUI could send another 'position' command, this
calls set_position() that clears the states! Of course a crash
follows shortly.

Before searching all the relevant parameters are copied in
start_searching() just for this reason: to fully detach data
accessed during the search from the UCI protocol handling.
So the natural solution would be to copy also the setup states.
Unfortunatly this approach does not work because StateInfo
contains a pointer to the previous record, so naively copying and
then freeing the original memory leads to a crash.

That's why we use two std::auto_ptr (one belonging to UCI and another
to Search) to safely transfer ownership of the StateInfo records to
the search, after we have setup the root position.

As a nice side-effect all the possible memory leaks are magically
sorted out for us by std::auto_ptr semantic.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-27 19:17:02 +02:00
Marco Costalba 8991a6f005 Use std::deque to store setup states 2012-08-26 18:07:54 +02:00
Marco Costalba 16f380e5c1 Document PolyGlotRandoms[] offsets
Should be more clear from where the 'magic' numbers
come from.

Also bit of reformat while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-25 20:00:07 +01:00
Marco Costalba cbd7ce468c Explicitly use threads.size()
Instead of just size(). Although code is longer,
should be more immediate to understand when reading.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-24 13:41:29 +01:00
Marco Costalba b6883c872d Introduce struct Mutex and ConditionVariable
To mimics C++11 std::mutex and std::condition_variable,
also rename locks and condition variables to be more
uniform across the classes.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-24 12:30:36 +01:00
Marco Costalba fde0b9e701 Slightly microptimize SEE
Reduce of one instruction. It seems a tad faster on
the profiler now. Very slightly but anyhow it is a
code semplification.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-24 09:30:50 +01:00
Marco Costalba 7a2825053e Use size_t as operator[] argument type
This better mimics std::vector::operator[] and
fixes a warning with MSVC 64bit.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-22 11:44:43 +01:00
Marco Costalba 4e619a13d6 Merge generate_direct_checks() in generate_moves()
Further reduce redundancy in move generation.
Veirifed no speed regression on MSVC, Clang and gcc.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-22 11:34:52 +01:00
Marco Costalba 0de9257610 Streamline generate_moves()
Greatly simplify these very performace critical functions.
Amazingly we don't have any speed regression actually under
MSVC we have the same assembly for generate_moves() !

In generate_direct_checks() 'target' is calculated only
once being a loop invariant.

On Clang there is even a slight speed up.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-22 09:23:03 +01:00
Marco Costalba b84af67f4c Reformat piece values arrays
And rename stuff while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-20 19:17:58 +01:00
Marco Costalba 7c8b7222f5 Move zobrist keys out of Position
Are used by Position but do not belong to that class,
there is only one instance of them (that's why were
defined as static), so move to a proper namespace instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-20 18:24:06 +01:00
Marco Costalba ec9038b7b4 Retire copy c'tor from class Position
Not needed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-20 14:44:30 +01:00
Marco Costalba ab65d3fd0e Prefer a reference to a pointer
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-20 07:54:38 +01:00
Marco Costalba e8b7109eff Use enums instead of constants for piece values
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-20 00:08:34 +01:00
Marco Costalba 0c6ed5929c Document De Bruijn sequences
Insted of raw magic numbers.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-19 23:01:48 +01:00
Marco Costalba 2f4a9a140a Avoid wake up master thread when useless
Check we are the last slave of the split point
before to wake up the master. This should avoid
spurious wakes up.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-19 23:01:47 +01:00
Marco Costalba dba1bc354a Simplify idle_loop() signature
We can detect the split point master also from within idle_loop,
so we can call the function without parameters and remove an
overloaded member hack in Thread class.

Note that we don't need to take a lock around curSplitPoint
when entering idle_loop() because if we are the master then
curSplitPoint cannot change under our feet (because is_searching
is set and so we cannot be reallocated), if we are a slave
we enter idle_loop() only upon Thread creation and in that case
is always splitPointsCnt == 0. This is true even in the very rare
case that curSplitPoint != NULL, if we have been already allocated
even before entering idle_loop().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-19 23:01:28 +01:00
Marco Costalba 4b19430103 Prefer size_t over int for array sizes
Align to standard library conventions.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-19 11:01:46 +01:00
Marco Costalba 7c1f8dbde9 Introduce namespace Bitbases
Let's continue this namespace galore...

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-18 13:08:12 +01:00
Marco Costalba 2c1ba2ab0d Introduce namespace UCI
Ater previous patch it comes naturally to take this
extra step.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-18 12:26:22 +01:00
Marco Costalba b011818917 Retire struct OptionsMap
Directly use the underlying std::map instead and avoid
a useless inheritance.

As a nice side-effect Options global object has now a
default c'tor avoiding possible issues with globals
initializations.

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-18 11:30:27 +01:00
Marco Costalba bc4de9edae Explicitly qualify STL functions
Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-18 11:00:56 +01:00
Marco Costalba 9de4ee6d32 Retire MovePickerExt struct
Templetize MovePicker::next_move() member function instead. It
is easier and we also avoid the forwarding of MovePicker() c'tor
arguments in the common case.

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-08-18 10:46:24 +01:00
Marco Costalba 90ec4a403a Guard against 'divide by zero' in bench
Also remove an useless cast.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-30 18:05:15 +01:00
Joseph R. Prostko b61ec33f22 Added Haiku-specific changes to Makefile
First change: If Haiku is host platform, change
installation prefix to /boot/common/bin

Second change: Only link in pthreads if Haiku isn't
host platform.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-30 06:29:46 +01:00
Marco Costalba 1f7b5d9a79 Fix UCI promotion move notation
Regression introduced by revision
f0db6a6c0b

Spotted by Joona.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-26 18:16:24 +01:00
Linus Arver 5c6ba81cf2 Readme.txt: more grammar/style fixes 2012-07-19 12:09:39 -07:00
Linus Arver 591adf564a Readme.txt: grammar/stylistic fixes 2012-07-18 16:46:51 -07:00
Marco Costalba f0db6a6c0b Fix regression in move_to_san()
Broken since commit 628808a113

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-15 09:22:00 +01:00
Marco Costalba 520e680278 Introduce notation.h
And group there all the formatting functions but
uci_pv() that requires access to search.cpp variables.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-15 08:29:07 +01:00
Marco Costalba abc6a0be2f Rewrite pv_info_xxx() signatures
Use the helpers to format the PV info but without
writing to output stream (file or cout). Message
formatting and sending are two logically different
task.

Incidentaly reintroduce the pretty_pv() name,
from Glaurung memories :-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-15 07:48:33 +01:00
Marco Costalba 9dbda6652e Include castle moves in 'dangerous' flag
Simplifies the code and seems more natural.

We have a very small fucntional change becuase now
at PV nodes castles are extended one ply anyhow.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-14 12:29:11 +01:00
Marco Costalba 5dc0df8435 Merge exclusion search conditions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-14 12:18:14 +01:00
Marco Costalba 6e5a334c95 Remove redundant condition in is_dangerous()
A pawn on 7th is always passed so retire
this redundant condition.

No funtional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-13 17:57:26 +01:00
Marco Costalba 6becc81446 Silence a MSVC warning in class Tie
With warning level 4 MSVC complains that a default
assignment operator could not be generated due to
member 'file' is a reference (warning C4512).

Use a pointer instead of a reference and move
struct Tie outisde class Logger while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-08 10:50:23 +01:00
Marco Costalba 6b5322ce00 Rename first_1 / last_1 in lsb / msb
It seems more accurate: lsb is clear while 'first
bit' depends from where you look at the bitboard.

And fix compile in case of 64 bits platforms that
do not use BSFQ intrinsics.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-08 09:36:40 +01:00
Marco Costalba 67d91dfd50 Use last_1() to compute new TT size
Transposition table consists of a power of 2
number of TTCluster entries.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-07 19:46:13 +01:00
Marco Costalba 089e54c7fd Revert to -O3 with Clang
Instead of -O4 option that does not work with both mingw and
Linux gcc (tested with Clang 3.1).

As reported by Reed Kotler:
Turns out that -O4 is not a valid option for clang unless you have
the proper gold linker and plugins built. That's because -O4 enables
LTO, which writes out bitcode files during the compile, and then loads
those and optimizes them during the link phase.

It requires a linker that supports LLVM's LTO. There is a plugin for
Gold available as part of LLVM.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-07 19:05:38 +01:00
Marco Costalba 0b3ffb54b7 Fix signedness warning in time_to_msec()
We have a signed integer here so let the return type
take in account that.

Found by Clang with -Weverything option.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-07 16:28:39 +01:00
Marco Costalba 775488340e More idiomatic signature for operator=()
Return a reference instead of void so to enable
chained assignments like

"p = q = Position(...);"

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-05 11:55:35 +01:00
Marco Costalba 7d2530873e Streamline null search reduction formula
Although a (little) functional change, we have no ELO change
but formula it is now more clear.

After 13019 games at 30"+0.05
Mod vs Orig 2075 - 2088 - 8856 ELO 0 (+- 3.4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-07-05 11:48:17 +01:00
Marco Costalba 18505f1fc4 Clear transposition table on "ucinewgame"
It seems the standard behaviour as implemented
in most engines although UCI protocol does not
specify what to do upon "ucinewgame" command.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-30 08:00:48 +01:00
Marco Costalba dc88cd691f Templetize make_move() helpers
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-25 08:09:55 +01:00
Marco Costalba ebe8009aff Reduce indentation in UCIOption::operator=()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-25 00:14:42 +01:00
Marco Costalba 628808a113 Micro-optimize move_to_san()
Calculate the attacks only for the piece to disambiguate,
not for all.

Also some reformatting while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-24 12:38:29 +01:00
Marco Costalba dc7fd868f4 Use type_of() to categorize the moves
Needed to rename old MoveType (used in move generation)
to GenType.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-24 11:07:18 +01:00
Marco Costalba 7b4aa10708 Rename move.cpp to notation.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-24 09:46:31 +01:00
Marco Costalba 960a689769 Rename ThreadsManager to ThreadPool
It is a more standard naming convention.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-24 09:45:37 +01:00
Marco Costalba 5f5d056c8f Replace make_square() with operator|(File, Rank)
Be fancy :-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-23 09:17:54 +01:00
Marco Costalba 9c7e2c8f9d Coding style in move.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-23 08:34:07 +01:00
Marco Costalba 4f5680950a Add min pawn-king distance to endgame evaluation
At endgame time push the king near his pawns (actually
one of them).

Original idea is from Critter (although slightly different),
implementation is mine and is completely different from the
original, in particular it is different the algorithm to
compute the minimum distance from pawns.

After 19895 games at 15"+0.05
Mod vs Orig 3638 - 3248 - 13009 ELO +7

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-22 06:31:18 +01:00
Marco Costalba 9793fa1906 Calculate min distance between king and his pawns
Just added infrastructure.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-17 09:41:18 +01:00
Marco Costalba 0446fc85de Reformat pick_random() in magics calculation
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-10 11:46:52 +01:00
Marco Costalba 764d3f44b6 Fix a compile error in opposite_colors()
Error is due to ambiguous overloading of operator^
because we have both the built-in operator^(int, int)
and the user defined operator^(Bitboard, Square).

This error does not trigger when using Makefile becuase,
due to luck, the user defined operator^(Bitboard, Square)
happens to be always defined _after_ opposite_colors() so
that compiler does not claim. But in case of Microsoft MSVC
we don't have a Makefile and the order of files compilation
is chosen by the compiler (in an unpredictable way). So it
could still happen that error is not detected (as in my case),
but in another case the order of compilation of the files could
be so that at some point both operator^ were defined before
opposite_colors() and this triggers the error.

The fix is much simpler than the explanation :-)

Reported by Quocvuong82.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-06-02 09:04:11 +01:00
Marco Costalba 0412f4a1ee Fix an issue when adding a book during the game
Currently when we fail to open a book file, for instance
if it doesn't exsist, we leave Book::open() with ifstream
failbit set. If then the book file is added, we correctly
open it at next attempt, but failbit is still set so that
after opening we exit because ifstream::good() returns false.

The fix is to reset failbit upon exiting.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-27 14:13:14 +01:00
Marco Costalba 6828325881 Retire PieceOffset[] in book.cpp
And calculate piece offset on the fly. Also
improve comments.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-27 13:46:55 +01:00
Marco Costalba 61a054b170 Fix a possible 'Division by zero'
In case a book entry has 'count' field set to 0
we crash. Spotted by Clang's static analyzer.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-26 23:17:22 +01:00
Marco Costalba 3361ad4242 Rename psq_score in ReducedStateInfo
So to be fully in sync with StateInfo, and move struct
to position.h, just below StateInfo.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-26 22:43:23 +01:00
Marco Costalba 6c9c6dd989 Fix book file regression
Revision 2aac860db3 of 27 / 4 / 2012
changed can_castle() signatures from bool to int and
this broke the code that calculates polyglot hash key
in book.cpp

Instead of directly fixing the code we prefer to change
castling rights definitions to align to the polyglot ones
(as we did in previous patch). After this step we can simply
take internal castle rights as they are and use them
directly to calculate polyglot book hash key, as we do
in this patch that fixes the regression.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-26 10:14:08 +01:00
Marco Costalba a358dfe934 Redefine enum CastleRight
To be aligned with PolyGlot book castle right definitions.

This will be used by next patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-26 10:03:35 +01:00
Marco Costalba 0ecc920a09 Add a known draw case in kpk bitbase generation
Early classify as known draws the positions
where white king is trapped on the rook file.

Suggested by Dan Honeycutt.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-19 08:45:16 +01:00
Marco Costalba f86182e791 Simplify Position::print()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-12 12:50:11 +01:00
Marco Costalba c19a6ef82d Revert "Don't split if reduced below min_split_depth"
After extensive testing (I was off line this week and let
the test go on) it seems this change is useless:

After 33968 games on a QUAD (4 threads) at 15"+0.05
Mod vs Orig 5425 - 5550 - 22993 ELO -1 (+-2.1)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-12 10:00:26 +01:00
Marco Costalba ecb84464f9 Improve previous patch
Only in case of promotion we care about an upper case
promotion piece char, so std::transform() is overkill
for the task.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-12 09:21:52 +01:00
Balint Pfliegel 1b2af05ea6 Junior promotion patch
Assumption: Junior sends promotions according to the side to move (ucase/lcase).
Fact: Stockfish generally handles promotion lcase.
Patch: Handling position fen input moves always with lcase promotions.

Ported back by Portfish. No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-12 00:04:17 +01:00
Marco Costalba caef319219 Fix compilation with Android NDK
It seems ADL lookup is broken with the STLPort library. Peter says:

The compiler is gcc 4.4.3, but I don't know how many patches they
have applied to it. I think gcc has had support for Koenig lookup
a long time. I think the problem is the type of the vector iterator.
For example, line 272 in search.cpp:

 if (bookMove && count(RootMoves.begin(), RootMoves.end(), bookMove))

gives the error:

jni/stockfish/search.cpp:272: error: 'count' was not declared in this scope

Here RootMoves is:

 std::vector<RootMove> RootMoves;

If std::vector<T>::iterator is implemented as T*, then Koenig lookup
would fail because RootMove* is not in namespace std.

I compile with the stlport implementation of STL, which in its vector
class has:

 typedef value_type* iterator;

I'm not sure if this is allowed by the C++ standard. I did not find
anything that says the iterator type must belong to namespace std.
The consensus in this thread

http://compgroups.net/comp.lang.c++.moderated/argument-dependent-lookup/433395

is that the stlport iterator type is allowed.

Report and patch by Peter Osterlund.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-11 17:16:51 +01:00
Marco Costalba 2f47844c7c Simplify attacks_bb()
And some formatting while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-01 13:16:20 +01:00
Marco Costalba b9bc6e823f Change pos.pieces() argument order
Let first argument to be the 'color'. This allows to align
pos.pieces() signatures with piece_list(), piece_count() and
all the other functions where 'color' argument is passed as
first one.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-01 12:09:20 +01:00
Marco Costalba 5e90580088 Convert constants to decimal representation
Hex representation doesn't add any value in those cases.
Preserve hex representation where more self-documenting
for instance for binary masks values.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-05-01 11:37:12 +01:00
Marco Costalba ef0496ff40 Don't split if reduced depth is below min_split_depth
It seems to increase SMP performances. To note that
this patch goes in the opposite direction of "Active
reparenting" where we try to reparent an idle slave
as soon as possible. Instead here we prefer to keep
it idle instead of splitting on a shallow / near the
leaves node.

After 11550 games on a QUAD (4 threads) at 15"+0.05
Mod vs Orig 1972 - 1752 - 7826 ELO +6 (+-3.6)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-29 23:28:07 +01:00
Marco Costalba 96f4ab48d8 Increase optimization level of Clang
Set optimization level to 4 and get a 2.564% faster binary:

Stockfish (Clang, Level 4) bench:
$ make build ARCH=osx-x86-64 COMP=clang
(Clang does not support PGO)
Average of 4 trials:
Total time (ms): 5137.5
Nodes searched: 5631135
Nodes/second: 1096084.5

Stockfish (Clang, Level 3) bench:
$ make build ARCH=osx-x86-64 COMP=clang
(Clang does not support PGO)
Average of 4 trials:
Total time (ms): 5269.25
Nodes searched: 5631135
Nodes/second: 1068679.25

Stockfish (GCC, PGO) bench:
$ make profile-build ARCH=osx-x86-64
Average of 4 trials:
Total time (ms): 5286
Nodes searched: 5631135
Nodes/second: 1065292.25

Suggestion and performance tests by Daylen Yang.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-29 23:11:23 +01:00
Marco Costalba 39c08c17c5 Remove unreachable extension condition
A PvNode that givesCheck has been already granted
an extension of ONE_PLY in previous condition.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-29 18:58:48 +01:00
Andy Duplain b93693b831 Add support for Mac clang compiler
Makefile modified to support the clang compiler under Mac.
This was tested using clang 4 under Mountain Lion, but should
also work fine under Lion and possibly under Snow Leopard.

It requires the 'Xcode 4.x Command Line Tools' to be installed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-29 11:47:02 +01:00
Marco Costalba cdfe43eb8f Proper indenting of multiple conditions
Triviality due to a boring saturday morning.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-28 11:10:51 +01:00
Marco Costalba 456f37b8ab Rename square_empty() to is_empty()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-28 10:54:33 +01:00
Marco Costalba e8d89ca5b0 Micro-optimize king evaluation
Reuse already calculated value, instead of calling
king_safety() again.

Patch suggested by Balint Pfliegel.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-28 10:37:55 +01:00
Marco Costalba 2aac860db3 Fix wrong condition in PawnEntry::king_safety()
Since revision 374c9e6b63
we use also castling information to calculate king safety.
So before to reuse the cached king safety score we have to
veify not only king position, but also castling rights are
the same of the pre-calculated ones.

This is a very subtle bug, found only becuase even after
previous patch, consecutives runs of 'bench' _still_ showed
different numbers. Pawn tables are not cleared between 'bench'
runs and in the second run a king safety score, previously
evaluated under some castling rights, was reused by another
position with different castling rights instead of being
recalculated from scratch.

Bug spotted and tracked down by Balint Pfliegel

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-27 10:59:18 +01:00
Marco Costalba 8b00e50cb7 Clear TT before running 'bench'
Now that we can call bench multiple times
from command prompt we need to ensure searched
nodes remain constant across different runs.

Spotted by Blint Pfliegel.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-26 19:37:30 +01:00
Marco Costalba be3b8f3ae9 Retire "Active reparenting"
After 6K games at 60" + 0.1 on QUAD with 4 threads
this implementation fails to show a measurable increase,
result is well within error bar.

Perhaps with 8 or more threads resut is better but we
don't have the hardware to test. So retire for now and
in case re-add in the future if it proves good on big
machines.

The only good news is that we don't have a regression and
implementation is stable and bug-free, so could be reused
somewhere in the future.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-22 17:52:31 +01:00
Marco Costalba ce159b16b9 Fix endless reaparenting loop
The check for detecting when a split point has all the
slaves still running is done with:

   slavesMask == allSlavesMask

When a thread reparents, slavesMask is increased, then, if
the same thread finishes, because there are no more moves,
slavesMask returns to original value and the above condition
returns to be true. So that the just finished thread immediately
reparents again with the same split point, then starts and
then immediately exits in a tight loop that ends only when a
second slave finishes, so that slavesMask decrements and the
condition becomes false. This gives a spurious and anomaly
high number of faked reparents.

With this patch, that rewrites the logic to avoid this pitfall,
the reparenting success rate drops to a more realistical 5-10%
for 4 threads case.

As a side effect note that now there is no more the limit of
maxThreadsPerSplitPoint when reparenting.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-17 18:51:49 +01:00
Marco Costalba 5392007a24 Improved cutoff check when reparenting
Check for a cutoff occurred also high in
the tree and not only at current split
point.

This avoids some more wasted reparenting.

No functional chnage.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-16 18:28:08 +01:00
Marco Costalba f59323b56a Use more_than_one() instead of single_bit()
It is more correct given what the function does. In
particular single_bit() returns true also in case of
empty bitboards.

Of course also the usual renaming while there :-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-14 09:51:59 +01:00
Marco Costalba 25a9b601b2 Reparent to latest
Instead of reparenting to oldest split point, try to reparent
to latest. The nice thing here is that we can use the YBWC
helpful master condition to allow the reparenting of a split
point master as long as is reparented to one of its slaves.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-14 07:20:31 +01:00
Marco Costalba c645aca199 Don't reparent if a cutoff is pending
And update master->splitPointsCnt under lock
protection. Not stricly necessary because
single_bit() condition takes care of false
positives anyhow, but it is a bit tricky and
moving under lock is the most natural thing
to do to avoid races with "reparenting".

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-12 21:17:52 +01:00
Marco Costalba 44432f67d7 Active Reparenting
In Young Brothers Wait Concept (YBWC) available slaves are
booked by the split point master, then start to search below
the assigned split point and, once finished, return in idle
state waiting to be booked by another master.

This patch introduces "Active Reparenting" so that when a
slave finishes its job on the assigned split point, instead
of passively waiting to be booked, searches a suitable active
split point and reprents itselfs to that split point. Then
immediately starts to search below the split point in exactly
the same way of the others split point's slaves. This reduces
to zero the time waiting in idle loop and should increase
scalability especially whit many (8 or more) cores.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-10 18:22:58 +01:00
Marco Costalba d66b765eb6 Sync compute_xxx implementations
Also refactored Position::pos_is_ok() while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-09 13:11:38 +01:00
Marco Costalba e72b93e44f Move Tempo to evaluation
Apart from the semplification it is now more clear that
the actual Tempo added was half of the indicated score.
This is becuase at start compute_psq_score() added half
Tempo unit and in do_move() white/black were respectively
adding/subtracting one Tempo unit.

Now we have directly halved Tempo constant and everything
is more clear.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-09 11:14:00 +01:00
Marco Costalba 68885f78f3 Micro-optimize do_castle_move()
Use the same tables update trick used in do_move().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-09 09:41:41 +01:00
Marco Costalba 4a310baae2 Disable book during analysis
It is still enabled during fixed limit search so to
use it during fixed depth/nodes/time matches.

Bug reported by Daylen.

No functional changes.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-09 08:09:02 +01:00
Marco Costalba d549497144 Introduce make_castle_right() helper
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-08 17:19:49 +01:00
Marco Costalba e56342ed00 Shrink castlePath[] and castleRookSquare[] sizes
Shrinking from [16] to [2][2] is able to speedup
perft of start position of almost 5% !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-08 16:55:01 +01:00
Marco Costalba 0049d3f337 Reduce stack usage
Shrink dimensions of the biggest stack consumers arrays.
In particular movesSearched[] can be safely shrinked
without any impact on strenght or risk of crashing.
Also MAX_PLY can be reverted to 100 with almost no impact
so to limit search recursion and hence stack allocation.

A different case is for MAX_MOVES (used by Movepicker's
moves[]), because we know that do exsist some artificial
position with about 220 legal moves, so in those cases SF
will crash. Anyhow these cases are never found in games.
An open risk remains perft, especially run above handcrafted
positions.

This patch originates from a report by Daylen that found
SF crashing on his Mac OS X 10.7.3 while in deep analysys
on the following position:

8/3Q1pk1/5p2/4r3/5K2/8/8/8 w - - 0 1

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-08 08:46:04 +01:00
Marco Costalba e0cae4bef8 Fix 'bench' for Chess960 case
Now a fen file with Chess960 positions is
correctly parsed. But it is mandatory to set
"UCI_Chess960" option _before_ to call bench.

Note that this was not needed/possible before
adding the possibility to call 'bench' from
command prompt.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-07 14:07:30 +01:00
Marco Costalba 9546b79e20 Use bench to implement UI 'perft' command
Now that we can call bench on current position
we can directly use it to perform our perft.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-07 13:45:53 +01:00
Marco Costalba cc04a745e2 Teach 'bench' to run current position
Now that we can call bench from command prompt
has a sense to teach bench to run the current
set position. To do this is enough to call bench
with 'current' as fen source parameter.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-07 12:08:34 +01:00
Marco Costalba ce5b972736 Don't need to wait after a "ponderhit"
It is enough to wake up main thread. This is
a better fix than d033d5e06a.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-07 11:47:37 +01:00
Marco Costalba f30f384757 Revert "Penalty for undefended rook"
After extensive test Gary says:

"So, after 16k games at 10"+1" on an i7, the undefended rook test
looks to be not good (albeit by a very small margin).
3063 - 3093 - 9844 (-1).

I doubt that is causing the regression, but even so, it looks like
it's not worth keeping, and we can go back to the simpler undefended
minors check."

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-07 11:34:22 +01:00
Marco Costalba 676b2c8435 Replace Position::copy()
With assignment operator. And fix Position::flip().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 19:42:45 +01:00
Marco Costalba c2fc80e5d1 Revert thread_local stuff
Unfortunatly accessing thread local variable
is much slower than object data (see previous
patch log msg), so we have to revert to old code
to avoid speed regression.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 18:47:55 +01:00
Marco Costalba b1f57e92ce Use thread_local compiler specifics
Much faster then pthread_getspecific() but still a
speed regression against the original code.

Following are the nps on a bench:

Position
454165
454838
455433

tls
441046
442767
442767

ms (Win)
450521
447510
451105

ms (pthread)
422115
422115
424276

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 18:03:15 +01:00
Marco Costalba bed4075580 Fix a (theoretical) race leading to a crash
After we release the SplitPoint lock the master, suppose
is main thread, can safely return and if a "quit" command
is pending, main thread exits and associated Thread object
is freed. So when we access master->is_searching a crash
occurs.

I have never found such a race that is of course very rare
becuase assumes that from lock releasing we go to sleep for
a time long enough for the main thread to end the search and
return. But you can never know, and anyhow a race is a race.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 15:30:41 +01:00
Marco Costalba 5a2d525048 Teach UI thread to use main thread resources
So to avoid a crash when setting the moves in
UCI "position startpos moves ...." command.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 15:05:52 +01:00
Marco Costalba e1919384a2 Don't store Thread info in Position
But use the newly introduced local storage
for this. A good code semplification and also
the correct way to go.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 14:36:45 +01:00
Marco Costalba 699f700162 Introduce thread local storage
Use thread local storage to store a pointer to the thread we
are running on. This will allow to remove thread info from
Position class.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 14:36:39 +01:00
Marco Costalba 797c960d20 Rewrite pop_1st_bit() to be endian independent
With this change sources are fully endianess
independent, so we can simplify the Makefile.

Somewhat surprisingly we don't have any speed
regression !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-06 12:38:27 +01:00
Marco Costalba 673bc5526f Use a Thread instead of an array index
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-04 12:12:08 +01:00
Marco Costalba 0439a79566 Big Position renaming
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-04 07:35:49 +01:00
Marco Costalba 37fa8adc2b Micro-optimize last_1() for 32bits
Verified assembly it is a bit simpler.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-04 06:54:48 +01:00
Marco Costalba 2f99de0c6c Fix bench with fen files regression
Erroneusly adds default positions to the fens
loaded from external file.

Bug introduced in adb71b8096

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-02 18:40:12 +01:00
Marco Costalba 7a8429d9f1 Simplify Endgames::probe()
With this API change we simplify both function and caller site.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-02 09:58:29 +01:00
Marco Costalba dda0fa1a43 Use polymorphism to resolve map() overloading
The 2 overload functions map() accept a pointer to
EndgameBase<Value> or a pointer to EndgameBase<ScaleFactor>.

Because Endgame<E> is derived from one of them we can
directly use a pointer to this class to resolve the
overload as is needed in Endgames::add().

Also made class Endgames fully parametrized and no more
hardcoded to the types (Value or ScaleFactor) of endgames
stored.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-01 16:16:51 +01:00
Marco Costalba 7eb6a488ad Use a std::vector to store searchMoves
A std::set (that is a rb_tree) seems really
overkill to store at most a handful of moves
and nothing in the common case.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-01 12:45:43 +01:00
Marco Costalba 72641dcaae Retire platform specifics include in misc.cpp
Now that platform.h is included in types.h we
don't need this stuff anymore.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-01 12:00:15 +01:00
Marco Costalba 6e00aa6bae Better document square flipping helpers
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-01 11:30:54 +01:00
Marco Costalba 9bbd27a80f Introduce Bitboards namespace
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-01 11:01:13 +01:00
Marco Costalba adb71b8096 Process 'bench' also from SF prompt
It is possible to start with 'stockfish', then from
command prompt type 'bench' and SF will do what you expect.
Old behaviour is anyhow preserved. As a bonus we can now
start from command line any UCI command understood by
Stockfish. The difference is that after execution of a
command from arguments SF quits, while at the end of the
same command from prompt SF stays in UCI loop.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-04-01 10:06:30 +01:00
Marco Costalba 32c504076f Use std::vector to implement HashTable
Allows some code semplification and avoids directly
allocation and managing heap memory.

Also the usual renaming while there.

No functional change and no speed regression.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-31 19:07:11 +01:00
Marco Costalba 304deb5e83 Rename Materials and Pawns hash stuff
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-31 11:59:23 +01:00
Marco Costalba d84865eac3 Complete the renaming in Search::LimitsType
This completes the job started with revision
4124c94583.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-31 09:16:09 +01:00
Marco Costalba cc6c745b54 Reset search time as early as possible
In particualr before to wake up main thread that
could take some random time. Until we don't reset
search time we are not able to correctly track
the elapsed search time and this can be dangerous
under extreme time pressure.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-31 10:01:31 +01:00
Marco Costalba d033d5e06a Revert "Call wait_for_search_finished() only when quitting"
We need to wake up main thread if it is sleeping
waiting for stop or ponderhit, so we cannot skip
calling wait_for_search_finished().

Found by Othello1984.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-30 18:58:58 +01:00
Marco Costalba b0b9bb3462 Last touches to pawns shelter code
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-29 21:14:15 +01:00
Marco Costalba 5e18b81e87 Fix an hang when max depth is reached
In this case SF stop searching and goes sleeping
waiting for a stop / ponderhit before to return
best move. So when a "stop" arrives we need to wake
up the main thread again.

Another regression introduced by 3aa471f2a9,
hopefully the last one.

Thanks to Otello1984 to reporting this.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-29 20:04:27 +01:00
Marco Costalba 10e64e0509 Refactor pawns shelter and storm
Renamed stuff and added comments. The aim is to make more
readable, at least by me ;-) , this newly added part of code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-29 00:09:27 +01:00
Marco Costalba 76622342ec Restore MS1BTable[]
Incredible typo from my side!

The 2 tables are completely different, one counts 1s the
other returns the msb position. Even more incredible
the 'stockfish bench' command returns the same number
of nodes!!!

Spotted by Justin Blanchard.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-28 19:11:37 +01:00
Marco Costalba d6e3a40c81 Silently handle "ucinewgame" command
Avoid returning "Unknown command", it seems some
GUI are misguided by this.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-28 18:24:02 +01:00
Marco Costalba 46a50cbf38 Replace MS1BTable[] with BitCount8Bit[]
We already have the necessary infrastructure
in place.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-28 14:08:19 +01:00
Marco Costalba cc2b3ece5c Merge pull request #11 from glinscott/squash
Add more detailed pawn shelter/storm evaluation

After 10670 games at 10"+0.05
Mod vs Orig 2277 - 1941 - 6452 ELO +11 !!!

The first real increase since 2.2.2, congratulations Gary !!!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-28 07:48:30 +01:00
Marco Costalba 22e294e044 Set do_sleep out of lock protection
Fixes a not so rare crash (once every 100 games)
newly introduced. Unfortunatly I am still not
able to figure out why :-(

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-27 19:27:20 +01:00
Marco Costalba 4124c94583 Use UCI names in Search::LimitsType
There is no need to "invent" different names
from the original UCI parameters.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-27 14:26:58 +01:00
Marco Costalba a56322fde8 Merge pull request #9 from glinscott/master
Penalty for undefended rook

Almost no change at longer TC, but perhaps there
is a tiny increase....

After 17522 games at 10"+0.05
Mod vs Orig 3064 - 2967 - 11491 ELO +2

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-26 19:57:27 +01:00
Marco Costalba 3d0d0237c5 Simplify start_searching() signature
Retire the "sync" behaviour that now is up to
the caller to honour.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-26 18:59:01 +01:00
Marco Costalba d11a529904 Call wait_for_search_finished() only when quitting
When quitting we should avoid RootPosition to be
destroyed while threads are still running, leading
to a crash. In case of a "stop" or "ponderhit"
command there is no need for the UI thread to wait.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-26 18:44:30 +01:00
Marco Costalba 3aa471f2a9 Introduce and use wait_for_search_finished()
Helper function that allows us to simplify
the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-26 18:22:41 +01:00
Gary Linscott 374c9e6b63 Add more detailed pawn shelter/storm evaluation 2012-03-26 07:52:10 -04:00
Marco Costalba 32d3a07c67 Move ThreadsManager::exit() to d'tor
And add final touches to this long patch series.

All the series has been verified against regression with
20K games at fast TC.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-26 08:18:17 +01:00
Marco Costalba b978eb05dc Fix compile error with gcc
We have a clash with start_fn defined both as a
Thread memeber and as a function pointer type in
pthread_create().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 23:08:35 +01:00
Marco Costalba e4efc8b741 Reset Thread::maxPly before a new search
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 16:44:55 +01:00
Marco Costalba 58c2fe391d Fix race in ThreadsManager::sleep()
We cannot set do_sleep flag of main thread before
"bestmove" is sent to GUI, otherwise GUI could send
immediately the next "go" command that triggers
start_thinking() and because do_sleep is set UI
thread resets the flag to launch a new search. But
when shortly after main thread returns to main_loop()
flag is incorrectly reset and main thread goes to sleep
hanging the engine.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 16:37:48 +01:00
Gary Linscott dbe5e28eaa Merge remote-tracking branch 'upstream/master' 2012-03-25 10:18:29 -04:00
Marco Costalba c483ffc773 Try to mimic std::thread API
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 12:43:19 +01:00
Marco Costalba 41561c9bb8 Use std::vector<Thread*> to store threads
We store pointers instead of Thread objects because
Thread is not copy-constructible nor copy-assignable
and default ones are not suitable. So we cannot store
directly in a std::vector.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 10:23:52 +01:00
Marco Costalba 553655eb07 Refactor Thread class
Associate platform OS thread to the Thread class instead of
creating it from ThreadsManager.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 10:23:51 +01:00
Marco Costalba f01b53c374 Refactor ThreadsManager::set_size() functionality
Split the data allocation, now done (mostly once)
in read_uci_options(), from the wake up and sleeping
of the slave threads upon entering/exiting the search.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 10:23:49 +01:00
Marco Costalba 8ec421fa14 Revert "Don't sync with C library I/O buffers"
It seems is the cause of strange and rare hangs
reported by some users where Stockfish stops
responding to GUI. It is not clear why but for
the moment revert the patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 10:23:16 +01:00
Marco Costalba 11b0c7b44a Don't ceil cpu_count()
It is already done at calling site where it is
more appropiate.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-25 09:57:33 +01:00
Marco Costalba f8224fc7d3 Fix a MSVC warning
Not correct warning about use of an uninitialized
variable. The warning is not correct becuase we can
never reach the warned code when in SpNode, anyhow
the fix is simple.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-24 10:14:21 +01:00
Marco Costalba b356e0fae3 Rename lock.h to platform.h
And move some more platform specific code there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-24 10:05:17 +01:00
Marco Costalba 06f33ff1ee Remove last platform specific code form thread.cpp
A somewhat tricky function pointer cast allows us
to move the platform specifics to lock.h, the cast
is tricky because return type is not the same of the
casted function in Linux (for Windows return type is
a DWORD that is a long) but this should not be a
problem as long as the size is the same;

From: http://stackoverflow.com/questions/188839/function-pointer-cast-to-different-signature

"OpenSSL was only casting functions pointers to
other function types taking and returning the same
number of values of the same exact sizes, and this
(assuming you're not dealing with floating-point)
happens to be safe across all the platforms and
calling conventions I know of. However, anything
else is potentially unsafe."

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-23 19:28:20 +01:00
Marco Costalba c47a74ec62 Merge two loops in ThreadsManager::init()
In analogy with ThreadsManager::exit()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-22 22:40:04 +01:00
Marco Costalba e26d13bb31 Use a local copy of tte->value()
This should avoid some aliasing issues
with TT table access.

After 3913 games at 10"+0.05
Mod vs Orig 662 - 651 - 2600  ELO +0 (+- 6.4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-22 19:32:30 +01:00
Gary Linscott f41a21fefd Penalty for undefended rook as well 2012-03-22 07:33:47 -04:00
mcostalba d4c9abb967 Merge pull request #8 from glinscott/master
Optimize undefended minor check. Little editing by
me, no change even at assembly level.

No regression after 8K games at fast TC on a 64bit CPU.
2012-03-22 07:49:11 +01:00
Gary Linscott d1e18fc7dd Optimize undefended minor check. 2012-03-21 08:19:21 -04:00
Gary Linscott 3c6a4bfbed Penalize undefended minors
Even if not under attack. This seems to be good
especially on openings.

After 12112 games at 10"+0.05
Mod vs Orig 2175 - 1997 - 7940 ELO +5 (+- 3.7)

[Patch series from Gary, little edited by me]

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-21 08:00:57 +01:00
Marco Costalba 3b7dbc4f6d Fix Logger under MSVC iostream libraries
We need splitted Tie classes because MSVC stream library
takes a lock on buffer both on reading and on writing and
this causes an hang because, while searching, the I/O
thread is locked on getline() and when main thread is
trying to std::cout() something it blocks on the same
lock waiting for I/O thread getting some input and
releasing the lock.

The solution is to use separated streambuf objects for
cin and cout.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-20 21:46:08 +01:00
Marco Costalba 17d1940278 Remove cruft from Logger class
A big code simplification and cruft removing, make
Logger class a singleton and fully self conteined.
Also add direction indicators (">>" and "<<") to
better differentiate input and output lines in the
log file.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-20 19:24:52 +01:00
Marco Costalba 258da28e79 Better on_change() argument name
Using "o" as a parameter with the on_xxx(const UICOption& o)
functions is a bit dangerous because of confusion with "0".

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-20 07:09:58 +01:00
Marco Costalba df80232495 Add also logging of std::cin
Some trial was needed to find the correct recipe but now
we log both stdin and stdout to file "io_log.txt".

Link http://spec.winprog.org/streams/ was very useful
to understand the details of iostreams implementation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-19 21:59:25 +01:00
Marco Costalba eb28a683bd Add (smart) logging facility
By means of "Use Debug Log" UCI option it is possible to toggle
the logging of std::cout to file "out.txt" while preserving
the usual output to stdout. There is zero overhead when logging
is disabled and we achieved this without changing a single line
of exsisting code, in particular we still use std::cout as usual.

The idea and part of the code comes from this article:
http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-18 23:10:24 +01:00
Marco Costalba 2dfc94e0b6 Show startup messages immediately
In particular before initialization. So that SF
seems more snappy at startup.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-18 23:10:18 +01:00
Marco Costalba 7bc3688714 Revert to byTypeBB[0] storing occupied squares
As it was in Glaurung times. Also rearranged order
so that byTypeBB[0] is accessed before byTypeBB[x]
to be more cache friendly. It seems there is even
a small speedup.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-18 12:02:23 +01:00
Marco Costalba fc3ea7365a Rename occupied_squares() to pieces()
Also some microoptimizations, were there from ages
but hidden: the renaming suddendly made them visible!

This is a good example of how better naming lets you write
better code. Naming is really a kind of black art!

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-18 11:18:38 +01:00
Marco Costalba 55376219b7 UCI buttons don't need a value
Take advantage of this to further simplify the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-17 21:44:50 +01:00
Marco Costalba 9b26356347 Don't use "OwnBook" by default
Stick to UCI protocol that says:

* by default all the opening book handling is done by the GUI,
  but there is an option for the engine to use its own book
  ("OwnBook" option, see below)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-17 13:16:51 +01:00
Marco Costalba 7c8a8e038f Retire "ucinewgame" UCI option
UCI protocol it is not clear about what the engine
should be supposed to do when "ucinewgame" is
received. Stockfish simply sets the position to
start FEN, but it is redundant becuase the GUI always
resends the position after "ucinewgame" command, so
it seems we can safely ignore that command.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-17 11:24:19 +01:00
Marco Costalba ee838f56f7 Fix UCI 'button' options
When a button fires UCIOption::operator=() is called and from
there the on_change() function. Now it happens that in case of
a button the on_change() function resets option's value to
"false" triggering again UCIOption::operator=() that calls again
on_change() and so on in an endless loop that is experienced
by the user as an application hang.

Rework the button logic to fix the issue and also be more clear
about how button works.

Reported by several people working with Scid and tracked down
to the "Clear Hash" UCI button by Steven Atkinson.

Bug recently introduced by 2ef5b4066e.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-17 10:35:01 +01:00
Marco Costalba 9934b8ec31 Don't sync with C library I/O buffers
Now we are forced to just use C++ iostream becuase
buffers are independent and using C library functions
like printf() or scanf() could yield to issues.

Speed up of about 1%.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-12 19:34:19 +01:00
Marco Costalba 3dccdf5b83 Fix time_to_msec() precision
Result of t.time * 1000 should be a 64 bit value, not an int.

Bug reported by several users.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-10 19:38:56 +01:00
Marco Costalba 4220f191d8 Introduce Eval namespace
Wrap evaluation related stuff and reshuffle
a bit the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-07 07:39:01 +01:00
Marco Costalba 843a5961e1 Double pinner bonus
Fine tune newly introduced pinner bonus score:

After 34696 games at 2"+0.05
Mod vs Orig 7474 - 7087 - 20135 ELO +3 (+- 2.4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-07 07:31:43 +01:00
Marco Costalba d8e56cbe54 Convert init of eval to async option
So to be done only once at startup and in the (unlikely)
cases that a relevant UCI parameter is changed, instead
of doing it at the beginning of each search.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-06 19:21:00 +01:00
Marco Costalba 2ef5b4066e Async UCI options actions
Introduce 'on change' actions that are triggered as soon as
an UCI option is changed by the GUI. This allows to set hash
size before to start the game, helpful especially on very fast
TC and big TT size.

As a side effect remove the 'button' type option, that now
is managed as a 'check' type.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-05 19:20:07 +01:00
Marco Costalba 482b5b7ece Use new Time class in timed_wait()
And simplify the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-05 19:18:46 +01:00
Marco Costalba 19540c9ee8 Introduce single_bit() helper
Self-documenting code instead of a tricky
bitwise tweak, not known by everybody.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-04 23:37:44 +01:00
Marco Costalba cf0561d31a Introduce pinning bonus
Add a bonus if a slider is pinning an enemy piece.
Idea from Critter.

After 27443 games at 2"+0.05
Mod vs Orig 5900 - 5518 - 16025 ELO +4 (+- 2.7)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-04 23:01:31 +01:00
Marco Costalba 161c6b025e Rewrite time measurement code
Introduce and use a new Time class designed after
QTime, from Qt framework. Should be a more clear and
self documented code.

As an added benefit we now use 64 bits internally to get
millisecs from system time. This avoids to wrap around
to 0 every 2^32 milliseconds, which is 49.71 days.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-03-03 18:01:39 +01:00
Marco Costalba b966adf103 Halve rook on open file bonus for endgame
After 42206 fast games TC 2"+0.05
Mod vs Orig 12871 - 16849 - 12486 ELO +3 (+- 2.6)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-29 06:20:48 +01:00
Marco Costalba c2a68708ef Fix a shift overflow warning
Visual Studio 11 is worried that shift result could
overflow an integer, this is impossible becuase max
value of the shift is 4, but compiler cannot know it.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-27 20:32:41 +01:00
Marco Costalba 34178205fc Micro-optmize castling moves
Pre compute castle path so to quickly test
for impeded rule.

This speeds up perft on starting position
of more than 2%.

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-27 19:44:04 +01:00
Marco Costalba 5bb766e826 Rename promotion_piece_type() to promotion_type()
Shorter and equally clear to understand.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-26 18:39:53 +01:00
Marco Costalba 96eefc4af6 Introduce another two (bitboard,square) operators
And simplify the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-26 18:39:40 +01:00
Marco Costalba 8751b18cf0 Fix MSVC warning on streampos to size_t conversion
Fix this warning with MSVC 64 bits:

warning C4244: '=' : conversion from 'std::streampos' to 'size_t',
possible loss of data

Point is that std::streampos could be negative, while size_t
is always non-negative.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-26 12:05:37 +01:00
Marco Costalba 2608b9249d Retire ss->bestMove
And introduce SPlitPoint bestMove to pass back the
best move after a split point.

This allow to define as const the search stack passed
to split.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-21 20:31:22 +01:00
Marco Costalba 43f84efa15 Don't update bestValue in check_is_dangerous()
It is a prerequisite for next patch and simplifies
the function. testing at ultra fast TC shows no
regression.

After 24302 games at 2"+0.05
Mod vs Orig 5122 - 5038 - 13872 ELO +1 (+- 2.9)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-21 20:29:05 +01:00
Marco Costalba ea5616785e Fix a wrong check in pos_is_ok()
Bug introduced by revision a44c5cf4f7
of 3/12/2011.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-20 19:34:43 +01:00
Marco Costalba 6a48325c49 Further simplify castling rights
Reverse the meaning of castleRightsMask[sq] so that now
is stored the castling right that will be removed in
case a move starts from or arrives to sq square. This
allows to simplify the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-20 19:20:13 +01:00
Marco Costalba 50edb7cd73 Spread usage of pos.piece_moved()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-19 12:20:29 +01:00
Marco Costalba 4aadd1e401 Retire empty_squares()
Use ~pos.occupied_squares() instead and avoid to
hide the ~ computation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-19 11:50:50 +01:00
Marco Costalba ec5b9994b5 Index en-passant zobrist keys by file
Instead of by square. This is a more conventional
approach, as reported also in:

http://chessprogramming.wikispaces.com/Zobrist+Hashing

We shrink zobEp[] from 64 to 8 keys at the cost of an extra
'and 7' at runtime to get the file out of the ep square.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-19 11:31:36 +01:00
Marco Costalba 3441e0075d Move some stuff out of lock protection in split()
We shouldn't need lock protection to increment
splitPointsCnt and set curSplitPoint of masterThread.

Anyhow because this code is very tricky and prone to
races bound the change in a single patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-19 10:32:38 +01:00
Marco Costalba 821e1c7233 Micro-optimize castleRights update
When updating castleRights in do_move() perform only one
64bit xor with zobCastle[] instead of two.

The trick here is to define zobCastle[] keys of composite
castling rights as a xor combination of the keys of the
single castling rights, instead of 16 independent keys.

Idea from Critter although implementation is different.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-19 10:04:49 +01:00
Marco Costalba 6088ac2108 Small renaming in Thread struct
Should be a bit more clear the meaning of the
single variables.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-18 10:57:00 +01:00
Marco Costalba d8349f9d0f Fix a race when extracting PV from TT
Because TT table is shared tte->move() could change
under our feet, in particular we could validate
tte->move() then the move is changed by another
thread and we call pos.do_move() with a move different
from the original validated one !

This leads to a very rare but reproducible crash once
every about 20K games.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-18 10:20:07 +01:00
Marco Costalba fd35d92c1e Increase MAX_PLY from 100 to 256
There is no need to limit the maximum ply searched to
100, with deep exclusion search extensions we could
reach it even with much smaller search depths.

The only drawback is an increase in stack usage, but
is limited mainly to id_loop(), in particular the
recursive search() functions are not affected.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-18 10:16:01 +01:00
Marco Costalba 3b906ffc27 Micro-optimize pop_1st_bit() for 32 bits
Small perft speed-up of 2% and also a code
simplification.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-13 10:07:09 +01:00
Marco Costalba 7b4b65d7a9 Templetize sliding attacks
No functional change and no speed regression, it seems
to be even a bit faster on MSVC and gcc.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-13 09:15:55 +01:00
Marco Costalba 099b5e45e6 Speedup sliders attacks for 32bit CPU
Replace a 64 bit 'and' by two 32 bits ones and
use unsigned instead of int.

This simple patch increases perft speed of 6% on
my Intel Core 2 Duo !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-12 15:26:18 +01:00
Marco Costalba b1768c115c Don't wake up threads at the beginning of the search
But only when needed, after a split point. This behaviour
does not apply when useSleepingThreads is false, becuase
in this case threads are not woken up at split points so
must be already running.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-12 14:17:12 +01:00
Marco Costalba 86e159997c Don't reset 50-move counter after castling
Rule says should be reset only after a capture and/or
a pawn move.

This incredible bug was here since Glaurung times !

Spotted by Kiriakos.

No functional change in the test bench because we
don't reach the 50 moves limits.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-12 10:07:10 +01:00
mcostalba 576f0f6985 Merge pull request #3 from glinscott/b46bf29
Detect stalemate in evaluation
2012-02-05 21:34:32 -08:00
Gary Linscott b46bf2950f Simpler stalemate check. 2012-02-05 14:52:01 -05:00
Gary Linscott 0347339970 Detect stalemate in KXK endgames
Also, handle cases where there are 2 bishops of the same color.
2012-02-05 10:24:53 -05:00
Marco Costalba 40e939421f Add "Slow Mover" UCI parameter to adjust time management
With default value of 100 no change in regard of current
behaviour. Increasing the value makes SF to think a
longer time for each move. Decreasing the value makes SF
to move faster.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-04 10:41:09 +01:00
Marco Costalba b1cf1acb93 Move wait_for_stop_or_ponderhit() under Thread
This method belongs to Thread, not to ThreadsManager.

Reshuffle stuff in thread.cpp while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-03 17:33:09 +01:00
Marco Costalba c94cfebb7e Reduce lock contention in idle_loop
Release split point lock before to wake up
master thread. This seems to increase speed
in case "sleeping threads" are used:

After 7792 games with 4 threads at very fast TC (2"+0.05)
Mod vs Orig 1722 - 1627 - 4443 ELO +4 (+- 5.1)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-03 13:43:58 +01:00
Marco Costalba 57e942145c Fix an alignment warning with MSVC
The declared alignment is different from the one
in the definition.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-02-03 13:14:57 +01:00
Marco Costalba 51e8efdab5 Fix subtle race with slave allocation
When allocating a slave we set both is_searching
and splitPoint under lock protection.

Unfortunatly the order in which the variables are
set is not defined. This article was very clarifying:

http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/

So when in idle loop we test for is_searching and then
access splitPoint, it could happen that splitPoint is still
not updated leading to a possible crash.

Fix the race lock protecting splitPoint access.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-31 20:19:25 +01:00
Marco Costalba df31398bb9 Fix bug in useless checks prune
With current code we could raise bestValue above beta,
not what is intended for.

Spotted by Richard Vida.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-31 20:17:37 +01:00
Marco Costalba a94fd3bbec Reformat kpk bitbase
Simplify and streamline the code. Verified all the
resulting bitbases are not changed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-30 19:19:47 +01:00
Marco Costalba 1a1742ac4f Don't log search info after a stop
Fix an issue where the log file stores an incorrect +0.00
eval after a search has been stopped.

Bug reported by Ajedrecista.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-29 11:25:02 +01:00
Marco Costalba a492a9dd07 Bitwise operator overloads between Bitboard and Square
Yes, we try to be fancy here ;-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-29 10:59:50 +01:00
Marco Costalba 875a8079bc Replace clear_bit() with xor_bit()
This allows to retire ClearMaskBB[] and use just
one SquareBB[] array to set and clear a bit.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-29 09:38:40 +01:00
Marco Costalba b76c04c097 Rename ValueType to Bound
It is a more conventional and common naming.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-27 19:49:38 +01:00
Marco Costalba f7b4983137 Do not require -lpthread when linking in mingw
With this we should compeltely remove the need
of installing third party POSIX threads library
when compiling with mingw-gcc under Windows.

Spotted by Trung Tu.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-27 19:41:24 +01:00
Marco Costalba eeef654cd7 Restore LMR depth limit
It is not clear the advantage and we don't want
to risk of introducing regressions on this
very critical parameter. So revert to old limit.

After 16003 games
Mod vs Orig 2496 - 2421 - 11086 ELO +1 (+-3)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-27 19:31:41 +01:00
Marco Costalba 7fb6fd2f55 Reformat threads code
Apart from some renaming the biggest change
is the retire of split_point_finished()
replaced by slavesMask flags. As a side
effect we now take also split point lock
when allocation available threads.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-27 19:24:22 +01:00
Marco Costalba a189a5f0c5 Use Windows threads library with mingw
Instead of Posix threads. This seems to fix time
losses of the gcc compiled version for Windows.
The patch replaces the MSVC specific _MSC_VER flag
with _WIN32 and _WIN64 that are defined both by
MSVC and mingw-gcc.

Workaround found by Jim Ablett.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-25 07:32:31 +01:00
Marco Costalba 24b25b4827 Order bad captures by MVV/LVA
Instead of by SEE. Almost no ELO change but it is
a bit easier and is a more natural choice given
that good captures are ordered in the same way.

After 10424 games
Mod vs Orig 1639 - 1604 - 7181 ELO +1 (+-3.8)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-24 07:12:19 +01:00
Marco Costalba 830ff985db Revert "Fix link time optimization gcc option"
It seems we need to pass the full optimization
flags to the linker otherwise we end up in a
slow compile:

http://lists.debian.org/debian-devel/2011/06/msg00181.html

Regression reported by Benigno Hernandez.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-23 20:52:21 +01:00
Marco Costalba 3d937e1e90 Simplify locking usage
pass references (Windows style) instead of
pointers (Posix style) as function arguments.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-23 20:30:19 +01:00
Marco Costalba 04ff9c2548 Simplify our insertion sort implementation
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-23 20:24:15 +01:00
Auguste Pop 28bf56e725 Fix link time optimization gcc option
The previous line, LDFLAGS += $(CXXFLAGS), does not make sense, and
breaks profile-build, thus changing it into: LDFLAGS += -flto.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 21:58:42 +01:00
Marco Costalba 662d1859bd Shrink sequencer table
Integrate TT_MOVE step into the first state. This allows to
avoid the first call to next_phase() in case of a TT move.

And use overflow detection instead of the bunch of STOP_XX
states to detect end of moves.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 16:06:29 +01:00
Marco Costalba 97e0b0a01e Assorted code style in movepicker.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 13:57:24 +01:00
Marco Costalba 04ac1bcabe Fix incorrect assert(PvNode == (alpha != beta - 1))
In case of a PvNode could happen that alpha == beta - 1,
for instance in case the same previous node was visited
with same beta during a non-pv search, the node failed low
and stored beta-1 in TT. Then the node is searched again
in PV mode, TT value beta-1 is retrieved and updates alpha
that now happens to be beta-1.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 11:41:34 +01:00
Marco Costalba ec9b037e5f Order the recaptures by MVV/LVA
Almost no functional change because multiple recaptures
to same square are very rare, but neverthless it seems
the correct thing to do.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 11:19:44 +01:00
Marco Costalba 6f6be95bad Rename NON_CAPTURE to QUIET
It is a more conventional naming and is nicer.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 00:42:59 +01:00
Marco Costalba b96db269a8 Reshuffle stuff in MovePicker
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-22 00:13:47 +01:00
Marco Costalba dcbb05ef39 Fix ss->currentMove when probcutting
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-21 23:30:56 +01:00
Marco Costalba e25de55fac Use an enum instead of a table as MovePicker sequencer
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-21 16:05:54 +01:00
Marco Costalba 28892666bd Sync generate_direct_checks() with generate_piece_moves()
They are almost the same, if the function arguments would
have been the same they could even be integrated.

Also a bit of renaming while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-21 12:49:37 +01:00
Marco Costalba 6058e7cf60 Triviality in SERIALIZE_PAWNS() macro usage
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-18 17:52:55 +01:00
Justin Blanchard 2a21543c88 Remove unused #include lines 2012-01-19 00:48:53 +08:00
Justin Blanchard 007613cb5e Fix "go nodes", at least when Threads=1 2012-01-19 00:48:53 +08:00
Marco Costalba 1b69ef8e6c Don't allow LMR to fall in qsearch
And increase LMR limit. Tests show no change ELO wise,
but we prefer to take the risk to commit anyhow becuase
is a 'prune reducing' patch.

After 10749 games
Mod vs Orig: 1670 - 1676 - 7403 ELO 0 (+-3.7)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-18 08:10:40 +01:00
Marco Costalba 972dec454c Microptimize generation of pawn evasions
Skip calling promotion generation functions in
the very common case of no possible promotion
evasion. Also retire generate_pawn_captures()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-18 07:47:42 +01:00
Marco Costalba b6b8c62ba5 Simplify pawn captures generation
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-16 19:29:15 +01:00
Marco Costalba db57b5f8f4 Fix a (bogus) warning with gcc 4.4
Fix an incorrect warning: 'bm may be used uninitialized'
with the old but still commonly used gcc 4.4

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-16 19:26:42 +01:00
Marco Costalba 4a4513d126 Retire double-profile-build Makefile target
Now that we don't support anymore popcount detection
at runtime this target is obsolete.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-15 17:02:06 +01:00
Marco Costalba 2b1324eddb Fix gcc name used in Link Time Optimization
Use $(CXX) instead of assuming compiler name is 'gcc'

Spotted by Louis Zulli.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-15 12:50:09 +01:00
Marco Costalba dfd030b67a Make init_magic() piece agnostic
All the piece dependant data is passed now as
function arguments so that the code is exactly
the same for bishop and rook.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-15 09:21:00 +01:00
Marco Costalba 20621ed3e3 Unify some template specializations
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 23:11:59 +01:00
Marco Costalba 2aec8fb956 Retire queen_attacks_bb()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 23:00:10 +01:00
Marco Costalba 3ec94abcdb Use 'adjacent' instead of 'neighboring'
It is more correct and specific. Another naming
improvement while reading Critter sources.

No functional changes.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 18:04:13 +01:00
Marco Costalba e1907e349f Restore development version
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 15:27:24 +01:00
Marco Costalba f237e8b8ea Stockfish 2.2.2
Dedicated to the new Jim's super fast builds ! :-)

stockfish bench signature is: 5447426

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 15:01:21 +01:00
Marco Costalba 103b368ab7 Move struct RootMove to Search namespace
And directly pass RootMoves instead of SearchMoves
to main thread. A class declaration is better suited
in a header and slims a bit the fatty search.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 14:22:34 +01:00
Marco Costalba a29dd88f75 Use a set to store SearchMoves
We just need to verify if a legal move is among the
SearchMoves, so we don't need a vector for this.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-14 13:06:01 +01:00
Marco Costalba a1076cc68a Fix a gcc 4.7 warning
New gcc 4.7 complains about casting a volatile pointer
to void* so assign the variables directly.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-13 07:58:21 +01:00
Marco Costalba 78908b7aed Enable easy move detection only for recaptures
It could lead to terrible mistakes otherwise, as
it happened during a game on playchess when on
this position (after white's f4):

2q4r/4b1k1/p3rpp1/3np2p/PpNpNP1P/1P1P2PQ/2P1R3/4R1K1 b - - 0 1

SF moves immediately e5xf4 instead of the correct f5.
In general during engine matches it is impossible the
opponent leaves a piece hanging or anyhow starts a
clear losing sequence. So avoid to fall in subtle traps.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-13 07:27:01 +01:00
Marco Costalba d98150dffc Use operator~ to flip colors and squares
More natural and nicer. Idea from Critter.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-12 19:37:44 +01:00
Marco Costalba c549f71f64 Small touches in FEN decoding
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-12 18:40:58 +01:00
Marco Costalba c19ea4b000 Retire is_mate()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-10 21:53:07 +01:00
Marco Costalba bede30e7a6 Introduce piece_moved() to simplify common code
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-09 22:36:45 +01:00
Marco Costalba b05fbb3733 Unify PseudoAttacks arrays
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-09 22:08:37 +01:00
Marco Costalba 9b43fd7937 Use CheckInfo to generate checks
It should help to avoid recalculating check squares
of sliding attackers for queen when already done for
bishops and rooks. Of course this helps when there are
bishop, rook and queen on the board !

Fixed also a subtle bug (use of same variable b in while
condition and in condition body) introduced recently by
revision d655147e8c that triggers
in case we have at least 2 non-pawn discovered check pieces.
This is very rare that's why didn't show in the node count
verification where we actually have a case of 2 dc pieces
in position 14, but one is a pawn.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-08 16:09:18 +01:00
Marco Costalba 87fc9dcaa3 Add castling to generation of checking moves
During generation of non-captures checks (in qsearch)
we don't consider castling moves that give check,
this patch includes also this rare case. Verified with
perft that all the non-capture checks are now generated.

There should be a very little slowdown due to the extra
work, but actually I failed to measure it. I don't expect
any ELO improvment, there is even no functional change on
the standard depth 12 search, it is just to have a correct
move generator.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-08 12:28:51 +01:00
Marco Costalba 83f3ea7ab4 Last touches to movegen.cpp
The full movegen patch series shows a speed up of almost
6% (!) on perft, and code is much more readable too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 13:13:28 +01:00
Marco Costalba 9c8c4ff46f Retire the redundant MV_CHECK
MV_CHECK is an alias of the more appropiate named
MV_NON_CAPTURE_CHECK so use only the latter.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 12:03:19 +01:00
Marco Costalba d655147e8c Retire generate_discovered_checks
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 12:03:17 +01:00
Marco Costalba 3c675db3d0 Rearrange pawn moves generation
Functional change due only to rearrangement

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 12:03:16 +01:00
Marco Costalba cf247e7e30 Reshuffle stuff in movegen.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 12:03:15 +01:00
Marco Costalba 0026c88b3a Retire OLD_LOCKS option
And make CRITICAL_SECTION locks the only option for Windows.
This guarantees backward compatibility with all the Windows
versions (even XP and older) and an hassle free experience
when compiling for Windows. Tests performed by Ingo and
reported on talkchess confirm there is no speed penalty
against the most modern SRW locks:

http://www.talkchess.com/forum/viewtopic.php?t=41835&start=20

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 11:18:09 +01:00
Marco Costalba 6482ce2bb2 Fix compile on HP-UX 11's HP's C++
On that platform non-bracketed casting are not supported.

Reported by Richard Lloyd.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-07 00:04:08 +01:00
Marco Costalba 867a5a8cd2 Restore development version
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-06 18:09:25 +01:00
Marco Costalba 78e6b361c5 Stockfish 2.2.1
Hopefully fixed the "lose on time" issue.

stockfish bench signature is: 5457475

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-06 17:01:40 +01:00
Marco Costalba aa392c366e Extra time management safety
Further increase safety against time losses. After this
change (tested on LittleBlitzer and cutechess) I had no
more time losses at 2" and 1"+0.02 TC both on Windows
and Linux on more than 10000 games.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-06 13:24:37 +01:00
Marco Costalba f80c50bcdd Try hard not to lose on time
We try hard not to lose on time even under extreme
time pressure. We achieve this through 3 different but
coordinated steps:

    1) Increase max frequency of timer events

    2) Quickly return after a stop signal

    3) Take in account timer resolution

With these SF played under LittleBlitzer at 1"+0.02 and 3"+0
without losing on time even one game.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-06 01:41:45 +01:00
Marco Costalba d282cf6964 Avoid a race at thread creation
Before creating main thread we set its do_sleep flag to true,
then thread is created and it will go to sleep in main_loop()
after resetting do_sleep.

But if after the setting of do_sleep and before its resetting
the UI thread calls start_thinking() it will not wait on:

  if (!asyncMode)
      while (!main.do_sleep)
          cond_wait(&sleepCond, &main.sleepLock);

as it should but will immediately return before the main thread has
started the search. This very rare race show itself during bench,
when the first position is erroneusly skipped so that bench node count
results of 5309038 instead of the correct 5457475.

The patch is somewhat tricky, but is simple and it works!

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-03 21:31:50 +01:00
Marco Costalba b1fcfe4c5d Streamline generation of MV_NON_EVASION
Small speed-up of 3% in perft.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-03 19:18:38 +01:00
Marco Costalba 30418a3cfc Fix a warning under gcc
Locals left and right shadow two same named
variables in the std::ifstream base class.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-03 19:01:47 +01:00
Marco Costalba cb1709ef5e Revert cond_signal() fix
It seems it yields to missing wake-up events with the
result of SF loosing on time as reported by many people.

So revert the patch and use a more robust approach: assume
there can be spurious wake ups events and make the code to
work also in those cases.

While debugging I found that WaitForSingleObject() had wrong
parameter 0 instead of INFINITE yielding to a crash while
exiting under Windows, strangely unnoticed til now.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-02 16:44:04 +01:00
Marco Costalba 67338e6f32 Big renaming of move's helpers
The aim is to have shorter names without losing
readibility but, if possible, increasing it.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-02 12:03:54 +01:00
Marco Costalba 8300ab149c Simplify Book APIs
Retire open(), close() and name() from public visibility
and greately simplify the code. It is amazing how much
can be squeezed out of an already mature code !

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2012-01-01 14:46:18 +01:00
Marco Costalba c00443b19e Restore development version
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-31 15:44:00 +01:00
Marco Costalba 9db9e4f7d3 Stockfish 2.2
stockfish bench signature is: 5457475

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-31 15:43:28 +01:00
Marco Costalba 22e40c8c10 Fix cond_signal() semantics when using OLD_LOCKS
In Windows when OLD_LOCKS is defined we use SetEvent() to mimic
the semantic of the POSIX pthread_cond_signal().

Unfortunatly there is not a direct mapping because with SetEvent()
the state of an event object remains signaled until it is set
explicitly to the nonsignaled state or until a single waiting thread
has been released. Instead in case of pthread_cond_signal(), if there
are no waiting threads it has no effect. What we may want is something
like PulseEvent() instead of SetEvent(). Unfortunatly it is documented
by Mcrosoft as 'unreliable' due to spurious wakes up that could
filter out the signal resetting. So we opt to reset manually any
pending signaled state before to go to sleep.

This fixes the strange misbehaves during 'stockfish bench'
when using OLD_LOCKS under Windows.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-31 15:40:12 +01:00
Marco Costalba e9296d694c Unify BitCountType selection
Now that HasPopCnt is a compile time constant we can
centralize and unify the BitCountType selection.

Also rename count_1s() in the more standard popcount()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-31 10:46:14 +01:00
Marco Costalba fb4b4f772e Fix Windows 64 build
Broken by previous patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-31 08:48:16 +01:00
Marco Costalba f4dadee5e2 Reformat types.h
Retire obsolete code and reshuffle stuff.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 19:13:44 +01:00
Marco Costalba 808a312e1c Simplify debug functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 16:23:11 +01:00
Marco Costalba 93e539d909 Assorted cleanups in benchmark.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 15:23:33 +01:00
Marco Costalba 9d7a36121a Retire RootMove::nodes
Was used for time management but is no more used
today.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 14:16:15 +01:00
Marco Costalba 8307da0de7 Update copyright year to 2012
And refresh Readme.txt while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 13:52:16 +01:00
Marco Costalba ad43ce1436 Simplify printing of engine info
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 13:19:20 +01:00
Marco Costalba 0a6532a39d Retire run-time detection of hardware POPCNT
It was meant to build a single binary optimized
for any kind of CPU: with and without hardware POPCNT.

This is a nice idea but in practice was never used, or
people builds binary with popcnt enabled or not, mainly
according to their type of CPU. And it was also never
used in the official Jim's builds where, in case, would
be easier for a number of reasons, do build two different
versions: with and without SEE42 support.

So retire this feature and simplify the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 12:17:03 +01:00
Marco Costalba 20a6f99cdb Fix an off-by-one bug in ucioption.cpp
Harmless but anyhow wrong.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 11:58:55 +01:00
Marco Costalba 4554d8b2ac Better use STL algorithms in Endgame functions
This leads to a further and unexpected simplification
of this already very size optimized code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-30 11:58:54 +01:00
Marco Costalba 9cb187762a Wait for main thread to finish before to exit
Currently after a 'quit' command UI thread raises stop
signal, exits from uci_loop() and calls Threads.exit()
while the search threads are still active.

In Threads.exit() main thread is asked to terminate, but
if it is parked in idle_loop() it will exit and free its
resources (in particular the shared Movepicker object) while
sibling slaves are still active and this leads to a crash.

The fix is to let the UI thread always wait for main thread
to finish the search before to return from uci_loop().

Found by Valgrind when running with 8 threads.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-29 10:33:06 +01:00
Marco Costalba 4a8c1b2470 Use for_each() in Endgames d'tor
And fix some comments while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-29 10:25:11 +01:00
Marco Costalba 0759d8f430 Add user-defined conversions to UCIOption
Greatly improves the usage. User defined conversions
are a novelity for SF, another amazing C++ facility
at work !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-28 19:42:50 +01:00
Marco Costalba ae65ab25d5 Fix score_to_uci()
The condition for a mate score was wrong:

abs(v) < VALUE_MATE - PLY_MAX * ONE_PLY

instead of

abs(v) < VALUE_MATE_IN_PLY_MAX

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-28 14:20:24 +01:00
Marco Costalba 24417a6cd9 Better document how mate scores are stored in TT
During the search we score a mate as "plies to mate
from the root" to compare in an homogeneous way the
values returned by different sub-trees. However we
store in TT a mate score as "plies to mate from the
current position" the let the TT value remain valid
across the game.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-28 13:33:31 +01:00
Marco Costalba ad4739a6d4 Retire SquaresByColorBB[] and enum SquareColor
Use same_color_squares() instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-28 10:57:08 +01:00
Marco Costalba a695ed65a8 Rename Pieces
Align with PieceType naming convention and
make them more readable.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-28 10:38:48 +01:00
Marco Costalba 750ac9ac50 Document mate distance pruning
It is simple but somewhat tricky code that deserves
a bit of documentation. A bit of renaming while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-27 18:53:00 +01:00
Marco Costalba 07f3f0384a Assert enhancements in search
Add the check that alpha < beta - 1 if and only if PvNode is true.
The current code would not flag PvNode and alpha == beta - 1. In
other words, the || is not an exclusive OR!.

Also sync assert conditions of search() and qsearch()

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-27 01:04:00 +01:00
Marco Costalba 87b483f999 Reformat UCI option code
Make a better use of C++ operators overloading to
streamline the APIs.

Also sync polyglot.ini file while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-27 00:56:11 +01:00
Marco Costalba c2d42ea833 Rename getters functions removing 'get_' prefix
Follow the suggested Qt style:

http://doc.qt.nokia.com/qq/qq13-apis.html

It seems to me simpler and easier to read.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-25 11:50:59 +01:00
Marco Costalba b5f6c2241b Restore std::cout instead of printf()
I am not able to reproduce the speed regression anymore,
and also we were using cout even before speed regression
so probably the reason is not there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-25 09:29:51 +01:00
Marco Costalba e89a8e0913 Correctly define operators in types.h
Be consistent with the way these operators are defined
in plain C (and in C++).

Spotted by Lucas Braesch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-24 09:58:46 +01:00
Marco Costalba d543a64cc7 Don't update killers for evasions
We don't use killers to order evasions, so it
seems natural do not consider an evasion cut-off
move as a possible killer. Test shows almost no
change, as it should be becuase this is a really
tiny change, but neverthless seems the correct
thing to do.

After 11893 games
Mod vs Orig 1773 - 1696 - 8424 ELO +2 (+-3.4)

Idea from Critter.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-24 09:25:20 +01:00
Marco Costalba 939b621e5c Use ADL to skip std:: qualifier
Take advantage of argument-dependent lookup (ADL) to
avoid specifying std:: qualifier in some STL functions.
When a function argument refers to a namespace (in this
case std) then the compiler will search the unqualified
function in that namespace too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-18 21:18:51 +01:00
Marco Costalba a77a3b723f Disable again buffering at startup
Partially revert efd2167998
Without this patch SF does not send "bestmove" to GUI.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-17 16:59:32 +01:00
Marco Costalba 976270916b Headers cleanup in ucioption.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-17 15:58:19 +01:00
Marco Costalba 87f7e99bc4 Use printf() instead of std::cout()
Seems sensibly faster: On a

./stockfish bench > /dev/null

We have +2% on mingw and even +5% on MSVC !

Also removed the nice but complex enum set960 machinery,
use directly the underlying move_to_uci() function.

Speed regression reported by Heinz van Saanen.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-17 15:50:06 +01:00
Marco Costalba 72d8d27234 Retire update_history() Inline the only caller site
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-16 19:17:47 +01:00
Marco Costalba 1ae6ae9b60 Fix book move with searchmoves compatibility
Do not return the book move if is not among the
RootMoves,in particular if we have been asked to
search on a move subset with "searchmoves" then
return book move only if it is among this subset.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-16 07:23:24 +01:00
Marco Costalba af4fadebda Simplify id_loop() signature
And related assorted cleanup of this
very important function.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-14 21:56:37 +01:00
Marco Costalba 0af3af5d25 Reformat sending of PV information
Introduce pv_info_to_log() and pv_info_to_uci() and
greatly cleanup this stuff.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-14 19:22:22 +01:00
Marco Costalba 852d45a600 Further simplify aspiration code
Actually after last patch it happens that delta
starts always with the fixed value of 16.

So further remove useless code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-14 06:18:33 +01:00
Marco Costalba 96213689e4 Simplify aspiration window calculation
It seems that we just need to look at previous score to
compute aspiration window size.

After 5350 games:
Mod vs Orig 800 - 803  - 3647 ELO +0 (+- 5.2)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-14 05:56:53 +01:00
Marco Costalba 4e59c5c274 Retire RootMoveList
Diretcly use the underlying std::vector<Move> and the
STL algorithms. Also a bit of cleanup while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-12 20:13:24 +01:00
Marco Costalba 7d97ebfe7f Fix another crash triggered by previous patch
It is ok to redirect st pointer to startState, but the latter
should be updated with the content pointed by the st of the
original position. The bug is hidden when startState and *st
are the same as is the case of searching from start position,
but as soon as moves are made (as is the case when splitting)
the bug leads to a crash.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-11 11:44:09 +01:00
Marco Costalba 377c406c74 Fix a crash when quitting while searching
The Position object used by UI thread is a local variable in
uci_loop(), so after receiving "quit" command the function
returns and the position is freed from the stack.

This should not be a problem becuase in start_thinking() we copy
the position to RootPosition that is the one used by main search
thread. Unfortunatly we blindly copy also StateInfo pointer that
still points to the startState struct inside UI position. So the
pointer becomes stale as soon as UI thread leaves uci_loop() and
because this happens while main search thread is still recovering
after the 'stop' signal we have a crash.

The fix is to update the pointer to the correct startState after
the copy.

Found with Valgrind.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-11 10:31:46 +01:00
Marco Costalba 91601d7f95 Prune silly comments in search()
Comments should be informative but not pedantic / obvious.
The only exception is the function description where we
indulge a bit on the "chatty" side, but has always been like
this since Glaurung times, so we continue with this tradition.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-10 19:14:49 +01:00
Marco Costalba f3728e66f8 Allow to prune also first move
Tested togheter with previous patch; shows no regression and
is a semplification.

After 5817 games:
Mod vs Orig 939 - 892 - 3986 ELO +2 (+- 5.1)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-10 17:35:37 +01:00
Marco Costalba 3f14ed6602 Don't update bestValue when pruning
Simply return a fail-low score

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-10 17:35:36 +01:00
Marco Costalba 14df99130f Fix description of endgame scaling functions
Triggered by a comment of Eelco on talkchess. Also
a bit of cleanup while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-10 12:40:05 +01:00
Marco Costalba 47bcb892af Fix compile for 64 bits
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-08 13:55:27 +01:00
Marco Costalba 6e05055f06 Set captureThreshold according to static evaluation
Consider negative captures as good if
still enough to reach beta.

After 7502 games:
Mod vs Orig 1225 - 1158 - 5119 ELO +3 (+- 4.5)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-08 13:48:18 +01:00
Marco Costalba da6e53a436 Remove some (int) casts
A cast rarely is the right solution. In this case was enough
to redifine 3 variables with type size_t instead of int

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-07 17:30:28 +01:00
Marco Costalba 56774fff20 Retire all extensions (but checks) for non-PV nodes
It seems we don't have any added value. Note that the
moves that were used to be extended are still flagged
as dangerous so to avoid at least pruning them.

After 9555 games
Mod vs Orig 1562 - 1540 - 6453 ELO +0 (+- 4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-07 07:49:24 +01:00
Marco Costalba 3527a42063 Prefer empty() to size()
As Heinz says:

"Function empty() should have a constant run-time even
 on lousy compilers and you spare the not.

The change is even measurable: + 100-150 nodes/sec. Wow:-)"

Patch from Heinz van Saanen

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-06 19:41:48 +01:00
Marco Costalba 98352a5e84 Use operator() instead of apply() in endgames
It is more idiomatic for a functor (a function object) as are
the endgames.

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-05 21:04:32 +01:00
Marco Costalba 11a7980976 Fix disambiguation bug in move_to_san()
A pinned piece cannot move and so does not play any role
in SAN disambiguation.

Reported by Steven Edwards.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-04 12:24:15 +01:00
Marco Costalba 5b8ca1eee7 Move SearchStack under Search namespace
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-04 12:03:59 +01:00
Marco Costalba 81cd417b45 Retire move.h
Also some assorted comments fixes and other trivia.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-04 11:36:03 +01:00
Marco Costalba a44c5cf4f7 Prefer 0 to EmptyBoardBB
Easier and even faster or at least easier to optimize.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-03 12:02:13 +01:00
Marco Costalba 5c5af4fa65 Retire neighboring_files_bb() overload
Rarely used and we prefer to not hide the complexity.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-03 11:58:55 +01:00
Marco Costalba efd2167998 Don't disable IO buffering at startup
It was never clear to me why we needed this trick, and now
that we rely only on C++ std::getline() and std::cout for
input / output it is even more a mistery what this code does.

So disable it and wait to see if someone screams ;-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-03 10:54:44 +01:00
Marco Costalba 348f824104 Tidy up comments in uci.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-03 10:48:31 +01:00
Marco Costalba 0f7cbaca75 Tidy up comments in thread.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-12-03 09:58:46 +01:00
Marco Costalba e870afa5d5 Include <cstring> in search.h
Now we use memset() directly there.

Spotted by Justin Blanchard.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-28 07:30:31 +01:00
Marco Costalba 9bacd921fa Little reformat of elapsed_search_time()
Change name and argument type.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-27 22:36:13 +01:00
Marco Costalba bb3427ca85 Detach search arguments from UI thread
Detach from the UI thread the input arguments used by
the search threads so that the UI thread is able to receive
and process any command sent by the GUI while other threads
keep searching.

With this patch there is no more need to block the UI
thread after a "stop", so it is a more reliable and
robust solution than the previous patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-27 17:46:18 +01:00
Marco Costalba 6809b57cfc After a "stop" do not read new input until search finishes
Unfortunatly xboard sends immediately the new position to
search after sending "stop" when we have a ponder miss.

Becuase main thread position is not copied but is referenced
directly from root position and the latter is modified by
the "position.." UCI command we end up with the working position
that changes under our feet while the search is still recovering
after the "stop" and this causes a crash.

This happens only with the (broken) xboard, native UCI does not
have this problem.

Reported by otello1984

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-27 12:19:33 +01:00
Marco Costalba ffa75215cc Fix a race in pondering mode
Fixes an hang when playing with ponder ON. Perhaps there is still
a very small race but now it seems engine does not hang anymore.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-26 18:29:40 +01:00
Marco Costalba c4517c013c Introduce Search namespace
Move global search-related variables under "Search" namespace.

As a side effect we can move uci_async_command() and
wait_for_stop_or_ponderhit() away from search.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-26 13:43:22 +01:00
Marco Costalba ed04c010eb Rewrite async I/O
Use the starting thread to wait for GUI input and instead use
the other threads to search. The consequence is that now think()
is alwasy started on a differnt thread than the caller that
returns immediately waiting for input. This reformat greatly
simplifies the code and is more in line with the common way
to implement this feature.

As a side effect now we don't need anymore Makefile tricks
with sleep() to allow profile builds.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-26 11:51:12 +01:00
Marco Costalba e9dc2e9e1e Reformat search dispatch code
Reduce indentation level and lines of code and tidy up
some comment.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-20 00:02:13 +01:00
Marco Costalba 9c7d72739c Fix regression with printing of debug info
Output of debug info each second was disabled
due to recent patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-19 14:37:57 +01:00
Marco Costalba 3fc08f8ab6 Don't check for early stop when StopOnPonderhit is set
If we are pondering we will stop the search only when
GUI sends "ponderhit" or "stop" commands or when we reach
maximum depth. In all the other cases we continue to search
so there is no need to verify for available time.

Also better clarify why wait_for_stop_or_ponderhit() before
to exit in some cases.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-19 12:04:42 +01:00
Marco Costalba c56a7ee803 Early stop: retire redundant Rml.size() == 1 case
In case there is only 1 legal move we will stop the
search at depth 10 anyway because the exclusion search
probe will fail low.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-19 11:19:12 +01:00
Marco Costalba 35fa4fc71f Rewrite early stop logic
In the "easy move" paradigm we verify if the best move has
ever changed over a good number of iterations and if the
biggest part of the searched nodes are consumed on it.
This is a kind of hacky ad indirect heuristic to deduce
if one move is much better than others.

Rewrite the early stop condition to verify directly if one
move is much better than others performing an exclusion
search.

Idea to use exclusion search for time management if form Critter.

After 12245 games at 30"+0.1
Mod vs Orig 1776 - 1775 - 8694 ELO +0 (+-3.4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-18 21:01:34 +01:00
Marco Costalba b56a098cfb CLOP: Passed pawns weights tuning
Tuned with CLOP against a pool of 3 engines. Result
verified with a direct match:

After 11720 games at 10"+0.1
Mod vs Orig 1922 - 1832 - 7966 ELO +2 (+-3.6)

So no change in self match but if CLOP is right it should
be a bit better against an engine pool.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-14 09:05:20 +01:00
Marco Costalba 4cc272cb94 Rename value in bestValue in id_loop()
The value returned by root search it is actually
our best value, so rename the variable to reflect this.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-13 10:54:30 +01:00
Marco Costalba c4fc82c6b7 Rewrite link time optimization in Makefile
Instead of binding link time optimization to the choice of
popcount support, do the right thing and add -flto option
when gcc 4.5 or later is detected.

Although it should be supported also under mingw, it happens
that it doesn't, at least on my 4.6.1 due to some known bugs.

Thanks to Mike for helping me with this patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-12 11:55:45 +01:00
Marco Costalba a40ded2884 Simplify passed pawns logic
Remove the bonus for no *friendly* pieces in the pawn's path and
reduce a bit the bonus based on kings proximity.

This patch is part of to the ongoing effort to remove form evaluation
all the terms that do not add value.

After 16284 games:

Mod vs Orig 2728 - 2651 - 10911 ELO +1 (+- 3.1)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-12 09:09:41 +01:00
Marco Costalba 44c78fdb7a Fix regression: engine hangs while pondering
After a "stop" due to a ponder miss Xboard sends
immediately the new position to search, without
waiting for engine to effectively stop the search.

It is not clear if this is a GUI bug (as I suspect)
or allowed behaviour, but because it won't be fixed
anyway workaround this issue making listener thread
to switch to in-sync mode as soon as a "stop" command
is received.

Thanks to Mike Whiteley for reporting this.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-10 15:08:53 +01:00
Marco Costalba ecb98a3330 Stop is not an unknown command
If GUI sends stop while we are waiting for
a command do not reply with a silly:

Unknown command: stop

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-10 15:06:28 +01:00
Marco Costalba 9b6b510ca8 Another fix to profile-build on gcc 4.6
Oliver reports profile builds error with new gcc 4.6, he says:

"We need to add -lgov with profile-generate AND profile-use.
So it has to be added to the second stage of building too.

The problem occurred first with the introduction of gcc4.6 and
I think this is because the previous version did find the gcov
library automatically. gcc4.6 needs more precise options and
does less guesses. I have seen it in debian, Ubuntu and also with
mingw on Windows. And all use gcc4.6."

This patch fixes the issue.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-09 05:20:35 +01:00
Marco Costalba c2600a73cf Fix profile-build
After async I/O patches 'bench' changed behaviour and now waits for
input at the end of the test run. This is due to listener thread stay
blocked on std::getline() even after test run is finished, as soon as
we feed something the thread unblocks and then quickly exits.

This is not a big problem, but has the bad side effect of breaking
profile builds that hang forever at the end of the test run.

The tricky workaround is to create a pipe that connects to stockfish
input and then, when test run is finished, breaking the pipe: this
makes std::getline() immediately return.

So this patch adds a 'sleep 10' piped into 'stockfish bench' test run
command. After 10 seconds sleep ends, the pipe breaks and 'bench'
finishes as usual.

Thanks to Oliver Korff for reporting the issue, and to Mike Whiteley
for having co-authored this solution.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-08 07:39:06 +01:00
Marco Costalba 43204d9ac2 Reformat all_slaves_finished()
Rename and move under ThreadsManager class.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-06 13:45:47 +01:00
Marco Costalba 369789b426 Better document and reshuffle stuff in think()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-06 13:32:25 +01:00
Marco Costalba 8fa53a5b92 Better define wait_for_stop_or_ponderhit()
Use do_uci_async_cmd() instead of process input commands
directly and clarify that what we are waiting for is
something that is able to raise StopRequest flag.

Also fix some stale comments in do_uci_async_cmd(). Here
we need to reset Limits.ponder only upon receiving "ponderhit".
In the case of "quit" or "stop" resetting Limits.ponder has no
effect because the search is going to be stopped anyway.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-06 12:48:16 +01:00
Marco Costalba d58176bfea Use a timer to avoid polling
The timer will be fired asynchronously to handle
time management flags, while other threads are
searching.

This implementation uses a thread waiting on a
timed condition variable instead of real timers.
This approach allow to reduce platform dependant
code to a minimum and also is the most portable given
that timers libraries are very different among platforms
and also the best ones are not compatible with olds
Windows.

Also retire the now unused polling code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-05 18:19:38 +01:00
Marco Costalba 0095f423f2 Retire now unused input_available()
With our new listener thread we don't need anymore
this ugly and platform dependent code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-05 08:43:44 +01:00
Marco Costalba 2617aa415e Rewrite how commands from GUI are read
Instead of polling for input use a dedicated listener
thread to read commands from the GUI independently
from other threads.

To do this properly we have to delegate to the listener
all the reading from the GUI: while searching but also
while waiting for a command, like in std::getline().

So we have two possible behaviours: in-sync mode, in which
the thread mimics std::getline() and the caller blocks until
something is read from GUI, and async mode where the listener
continuously reads and processes GUI commands while other
threads are searching.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-05 08:35:17 +01:00
Marco Costalba 22b9307aba Further touches to magic bitboards code
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-11-01 10:38:01 +01:00
Marco Costalba ac7339877b Fix compile error in cpu_count()
The std::min() template function requires both arguments
to be of the same type.

But here we have the integer MAX_THREADS compared to a long:

long sysconf(int name);

So cast to integer and fix the compile.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-31 20:03:30 +01:00
Marco Costalba 90890844ad Document magics bitboards code
Add comments and rename stuff to better clarify what the
magic bitboard initialization code does.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-31 18:57:13 +01:00
mcostalba 8a89b12641 Merge pull request #1 from Panthee/master
Code Cleanup - Replacing macros Min() and Max() with corresponding STL algorithms std::min() and std::max()
2011-10-31 05:32:18 -07:00
Alexander Kure 4a3b162c8c Retire update_gains() 2011-10-31 03:28:59 -04:00
Alexander Kure 5c8af7ccb8 Replaced macros Min() and Max() with corresponding STL algorithms std::min() and std::max() 2011-10-31 00:38:44 -04:00
Marco Costalba 7942e6f3bf Retire update_gains()
Called from one place only.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 23:05:31 +01:00
Marco Costalba c6f497f09d Fix small bug in move_attacks_square()
We test if the piece moved in 'to' attacks the square 's' with:

bit_is_set(attacks_from(piece, to), s))

But we should instead consider the new occupancy, changed after
the piece is moved, and so test with:

bit_is_set(attacks_from(piece, to, occ), s))

Otherwise we can miss some cases, for instance a queen in b1 that
moves in c1 is not detected to attack a1 while instead she does.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 19:31:50 +01:00
Marco Costalba 29be28e1a2 Inline pinned_pieces() and discovered_check_candidates()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 18:48:23 +01:00
Marco Costalba e7939f450f Code style and 80 chars cols in Position::from_fen()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 18:02:18 +01:00
Marco Costalba 81801d395f Sync do_move() and undo_move()
It is not possible to unify due to the fact that the
sequence steps are reversed. What we can do is to try
to sync comments and code as much as we can to easy
reading and documentation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 13:58:44 +01:00
Marco Costalba bc76c62c63 Explicitly use a dedicated bitboard for occupied squares
Instead of byTypeBB[0]. This better self-documents the code.

No functional and speed change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 13:51:20 +01:00
Marco Costalba fd5d6c5340 Retire do_capture_move()
It is called only in do_move() that now has been fully
expanded. This is the most time consuming function of
all the engine.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-30 10:59:55 +01:00
Marco Costalba 08abe8b4a3 Retire undo_null_move()
Use a templetized do_null_move() to do/undo the null move.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-29 18:01:56 +01:00
Marco Costalba e896368496 Retire undo_castle_move()
Use a templetized do_castle_move() to do/undo the castling.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-29 17:31:15 +01:00
Marco Costalba 2fe4e10b0b Retire Position::set_castling_rights()
Is called in just one place. And rename set_castle() in the
now free to use and more appropiate set_castle_right().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-29 13:43:44 +01:00
Marco Costalba f2e78d9f84 Retire PieceValueXXX[] getters
They don't add any value given that the corresponding
table has global visibility anyhow.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-22 16:06:59 +01:00
Marco Costalba b5bbc1f713 Simplify the promotion case of move_gives_check()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-22 15:01:21 +01:00
Marco Costalba 23943208ec Remove redundancy in definitions of attack helpers
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-22 14:25:53 +01:00
Marco Costalba c555e1aa96 Convert PST tables to relative values
This is a prerequisite to allow changing piece values
at runtime, needed for tuning.

Also use scores instead of separated midgame and endgame values.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-22 13:17:24 +01:00
Marco Costalba 36cc214703 Increase Mobility
First tuning with CLOP against a pool of 3 engines. Result
verified with a direct match:

After 8736 games at 10"+0.1
Mod vs Orig 1470 - 1496 - 5770 ELO -1 (+-4.3)

So no change in self match but if CLOP is right it should
be a bit better against an engine pool.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-20 07:06:05 +01:00
Marco Costalba 8f7d36a85d Better document mate and stalemate detection
In particular add that we can have an harmless false positive
in case StopRequest or thread.cutoff_occurred() are set.

Reported by David Lee.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-18 20:01:21 +01:00
Marco Costalba e7cfe42d3f Use newly added log facility instead of LogFile
As a side effect now log file is open and closed every
time it is used instead of remaining open for the whole
thinking time.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-17 21:07:14 +01:00
Marco Costalba 500fff920b Add basic log facility
Mainly used to log stuff to a file while playing, when
stdout is used for the comunication with the GUI.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-17 21:07:00 +01:00
Marco Costalba 782c3f36cc Fix compile error in debug mode
Build broken by commit 3141490374
where we renamed move_is_ok() in is_ok() and this clashes
with the same named method in Position that overrides the
move's one causing compile errors.

The fix is to rename the method in Position.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-16 23:56:25 +01:00
Marco Costalba 8272dcb6cd Link Time Optimization doesn't needs -static
Justin reports that it breaks the compilation on Fedore 15 and as Tom says:

-static is only needed to work around the gcc on ubuntu 11.10 beta bug.
If -static introduces issues on its own then it is better to remove it.
It will not be needed in most environments.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-09 08:24:56 +01:00
Marco Costalba fec623d68d Better document how MultiPV search works
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-08 12:11:53 +01:00
Marco Costalba a3bf09c5c9 Send again all the PV lines in multiPV searching
Partially revert 1036cadcec because UCI protocol
in case of multipv explicitly requires:

for the best move/pv add "multipv 1" in the string when you send the pv.
in k-best mode always send all k variants in k strings together.

Thanks to Justin Blanchard for pointing this out.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-08 10:24:54 +01:00
Marco Costalba 325dedc7da Added gcc -msse3 support
It is enabled when selecting x86-64-modern target, this gives
another nice speed up:

On a Core i5-2500 (3300 Mhz, Sandy Bridge):

64 bit download version: 1597151 n/s

-flto : 1659664 n/s

-flto -msse3: 1732344 n/s

Patch suggested by Tom Vijlbrief.

Also unify flto, popcount and msse3 optimization under "modern"
target, note that this can break the "modern" build on old gcc that
do not support -flto option: in this case update gcc ;-) or default
to the standard build.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-08 08:50:11 +01:00
Tom Vijlbrief 09b5949cd2 Added gcc lto (Link Time Optimization) option
Just by adding the -flto option to CXXFLAGS link command
we can gain a few percent in speed.

On a Core i5-2500 (3300 Mhz, Sandy Bridge):

64 bit download version:

Without -flto: 1597151 n/s
With -flto : 1659664 n/s

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-06 20:10:12 +01:00
Marco Costalba 3141490374 Shrink names of move helpers
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-03 14:18:57 +01:00
Marco Costalba 1a8e3f0b2e Small touches in position.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-03 14:18:56 +01:00
Marco Costalba 80dd90f972 Small touches to book.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-03 14:18:30 +01:00
Marco Costalba c2c185423b Better naming borrowed from Critter
In line with http://chessprogramming.wikispaces.com conventions.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-02 10:16:59 +01:00
Marco Costalba 25b4d0c127 Revert "Retire Rml full PV search at depth == 1"
Yet another random crash source !

Hopefully this is the last one.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-02 07:40:46 +01:00
Marco Costalba 2225e3bbe7 Rename kingZone[] and reverse the king's color
Seems easier to understand to me. From Critter.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-02 06:54:57 +01:00
Marco Costalba a90a990118 Document why Book is defined static
This was not clear to someone on talkchess and actually
is not trivial to understand.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-02 06:54:57 +01:00
Marco Costalba 83d8fe2d59 When exiting wake up all threads at once
It seems we have a very rare crash under Linux, once
every 10K games without this patch.

Is faster to wake up all the threads, especially on SMP,
where the threads can then exit in parallel while the main
thread is waiting for the next one to terminate.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-10-02 06:54:43 +01:00
Marco Costalba 63a04134d0 No need to test for MOVE_NONE before move_is_ok()
Function move_is_ok() already catches the move == MOVE_NONE case.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-09-25 16:30:29 +01:00
Marco Costalba 6bc16f3ff1 Update killers after a TT hit
Almost no increase but seems the logic thing to do.

After 16707 games 2771 - 2595 - 11341 ELO +3 (+- 3.2)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-09-24 17:20:35 +01:00
Marco Costalba 10b24af98a Correctly score capture underpromotions
Be sure a queen capture promotion is tried in front of
an underpromotion.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-09-24 17:13:14 +01:00
Marco Costalba be9aba2fa0 Don't lock before check for termination
Restore old locking scheme changed with
commit 1e92df6b20.

This seems to prevent a very rare crash that occurs
once every 5-10K games.

With this patch we have no crashes after 33K games.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-09-24 17:12:36 +01:00
Marco Costalba 35018fa307 Use the map type template parameter to access map()
It is more natural than using the family subtype and also
use two single maps instead of a std::pair.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-09-11 11:38:23 +01:00
Marco Costalba b706165527 Lookup square distance instead of calculate on the fly
Microptimization that gives a +0.7% speed increase.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-09-11 10:11:43 +01:00
Marco Costalba 6963c3802d Detect family type of endgame from its enum value
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-22 00:49:47 +01:00
Marco Costalba 3b67636f0e Indulge a bit on the template wizardy
Push the template pedal a bit in our "showoff" endgame code ;-)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-14 13:15:58 +01:00
Marco Costalba 48e39c5c8e Small simplification of endgame functions API
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-14 12:12:14 +01:00
Marco Costalba 13524bea9b Fix use of uninitialized variable
When initializing endgames map we build a faked FEN string
in mat_key() to get the position hash's key.

This fen string lacks full move numbers, so when parsing the
fen in Position::from_fen() we leave startPosPly un-initialized.

Spotted by Valgrind (this is a kind of bug that is almost impossible
for humans to find).

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-12 11:56:11 +01:00
Marco Costalba 500c7f44ab Fix silly icc remark #2259
Another stupid remark to quiet out:

remark #2259: non-pointer conversion from "int" to "UINT16={unsigned short}"
may lose significant bits

In this case icc always converts to an integer the result of a shift operation
if the bit size of the operand is smaller, hence the warning when assignin
back to n.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-12 11:54:54 +01:00
Marco Costalba d156e7a20b Use a boolean instead as thread's state
Now that we have just two mutually exclusive thread's states
we can repleace them by a simple boolean.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-10 12:26:52 +01:00
Marco Costalba c386ce0023 Remove Thread::WORKISWAITING
Set the state directly to Thread::SEARCHING

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-10 12:05:33 +01:00
Marco Costalba b69d9ee3f7 Don't need pthread_detach() after pthread_join()
Spotted by Joona and verified with Valgrind.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-10 08:17:15 +01:00
Marco Costalba 7d5b8fcf77 Change start_routine argument
Directly pass the thread pointer.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-09 14:19:44 +01:00
Marco Costalba bc6a6e04a0 Retire Rml full PV search at depth == 1
Now that Rml ordering is based on normal MovePicker logic,
apart for the ttMove that is given, we can avoid to score
all the root moves at depth 1. We only need it for easy move
detection logic, but in this case we just need to score the
first two best moves and not all the Rml set.

No regression after 6400 games
Mod vs Orig 1052 1012 4336 ELO +2 (+- 4.9)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-09 09:58:10 +01:00
Marco Costalba e5ffe9959c Retire ThreadsManager::init_hash_tables()
Allocation of pawn and material hash tables should
be strictly bounded to the change of the number of
activeThreads, so move the code inside set_size().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 23:08:34 +01:00
Marco Costalba 86b95f2105 Retire Thread::TERMINATED
Use proper way to detect for thread terimnation instead of
our homegrown flag.

It adds more code than it removes and adds also platform specific
code, neverthless I think is the way to go becuase Thread::TERMINATED
flag is intrinsecly racy given that when we raise it thread is still
_not_ terminated nor it can be, and also we don't want to reinvent
the (broken) wheel of thread termination detection when there is
already available the proper one.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 22:10:01 +01:00
Marco Costalba 1e92df6b20 Retire Thread::INITIALIZING
Was used to prevent issues when creating multiple threads
on Windows, but now it seems we can remove it safely.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 14:12:02 +01:00
Marco Costalba ba85c59d96 Move idle_loop() under Thread
This greatly removes clutter from the difficult idle_loop() function

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 13:23:03 +01:00
Marco Costalba dafd5b5864 Tidy up comments in thread.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 11:49:58 +01:00
Marco Costalba eabba1119f Retire broken SendSearchedNodes
Now that we can split at root it happens that SendSearchedNodes
works only once at the end of the iteration, but this is useless
becuase speed info is sent anyhow toghter with the pv line.

So retire for now, waiting to find something SMP compatible.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 10:08:41 +01:00
Marco Costalba 06e0d48794 Sync search() and qsearch() alpha update
Change qsearch() to reflect alpha update logic
of search().

To be consistent changed also moves loop condition and
futility pruning condition.

No regression after 5072 games at TC 10"+0.1

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 07:46:01 +01:00
Marco Costalba 4a71c86270 Retire Thread::BOOKED
Start a slave as soon as is allocated.

No functional change with faked split.

Regression tested the full split() series and after
2000 games no regression and no crash.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-08 07:45:24 +01:00
Marco Costalba 68583f4d48 Fix obey the "maxThreadsPerSplitPoint" setting
Spotted by Joona.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-07 15:15:19 +01:00
Marco Costalba 5b35c149e8 Do not modify alpha in split()
When calling split or we immediately return because unable to
find available slaves, or we start searching on _all_ the moves
of the node or until a cut-off occurs, so that when returning
from split we immediately leave the moves loop.

Because of this we don't need to change alpha inside split() and
we can use a signature similar to search() so to better clarify
that split() is actually a search on the remaining node's moves.

No functional change with faked split.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-07 15:10:41 +01:00
Marco Costalba 9a542d9698 Initialize a new split point out of lock
Allocate and initialize a new split point
out of lock becuase modified data is local to
master thread only.

Also better document why we need a lock at
the end of split().

No functional change with faked split.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-07 14:37:14 +01:00
Marco Costalba cd27ed9a74 Update comment on why we call root search with ss+1
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-07 10:36:14 +01:00
Marco Costalba b9f8cb7837 Fix an assert when stopping the search
When StopRequest is raised we cannot immediately exit the
move loop but first we need to update bestValue so to avoid
assert:

assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-07 10:36:13 +01:00
Joona Kiiski ffa150bec3 Split at root!
Another great success by Joona !

After 5876 games at 10"+0.1
Mod vs Orig: 1073 - 849 - 3954 ELO +13 (+- 5.2)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-07 10:35:56 +01:00
Joona Kiiski 13bc6ba2c6 Preparations for splitting at root
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-06 10:31:30 +01:00
Marco Costalba 30b3edf328 Simplify MovePickerExt<>
Now that we don't special case the root moves anymore
we don't need to pass NodeType anymore as template parameter,
a simple bool to detect a SpNode will be enough.

Spotted by Joona.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-05 07:23:54 +01:00
Marco Costalba 7902d6089e Fix silly bug in uci loop
After issuing "go"-command, at the end of the search
SF shows: "Unknown command: ...".

Spotted by Joona.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-05 07:15:45 +01:00
Marco Costalba b6b0878da8 Fix a (silly) warning under icc compiler
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-04 10:10:03 +01:00
Marco Costalba 3a76163aba Use std::lexicographical_compare() in UCI options
Instead of our home grown function to perform a case
insensitive compare on option names as required by UCI
protocol.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-03 15:00:23 +01:00
Marco Costalba 1e7c6fc761 Consistently set ttMove to Rml.pv[0] in root node
No functional change, but reduce risks of subtle aliasing bugs.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 22:28:03 +01:00
Marco Costalba c50ad85c3c Fix an off-by-one error in UCI print loop
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 21:47:31 +01:00
Marco Costalba bb6a6e159a Rename ok_to_use_TT() in can_return_tt()
Seems more appropiate. From Lucas Braesch's DoubleCheck.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 18:49:06 +01:00
Marco Costalba 1036cadcec Send PV only for updated lines
It seems FritzGUI already remembers the old lines, so
we just need to update PV info only for the new lines.

Also introduced prevScore field in RootMove to avoid
a bulk copy of Rml.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 18:00:47 +01:00
Marco Costalba c71ae794df Sort PV moves always in two steps
This should fix following issue:

Suppose the search with MultiPVIteration == 0 returns an exact score

move = Nxf4, score = 100

Now search with MultiPVIteration == 1 and get two scores

move = Qg8, score = 150
move = Ra1, score = 180

If we now reorder all the moves in one step we end up with

pv[0] = Ra1, pv[1] = Qg8

Instead reordering as the current patch we end up in:

pv[0] = Ra1, pv[1] = Nxf4

preserving the first searched move.

No functional change in single PV.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 18:00:47 +01:00
Marco Costalba 409930e98c Small cleanup of previous patches
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 18:00:22 +01:00
Joona Kiiski b88f7df387 Reimplement MultiPV mode
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 06:47:33 +01:00
Joona Kiiski adcfffceeb Reimplement support for "searchmoves" option
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 06:47:22 +01:00
Joona Kiiski a3c1d64a5f Remove now unused RootMove.non_pv_score
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 06:47:06 +01:00
Joona Kiiski ce24a229df Make root search to use standard MovePicker.
This patch temporarily breaks MultiPV and searchmove
features, but they will be re-implemented in future
patches.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-08-02 06:46:50 +01:00
Joona Kiiski ce619b3b6c Don't probe TT at RootNode
In that case we should also update RootMoveList to avoid
bogus output

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-29 12:42:22 +01:00
Marco Costalba 2e2a4b4ea3 Fix pretty_pv() output in Chess960
And move it to search.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-26 12:39:15 +01:00
Joona Kiiski 7f519a2463 Fix PV output in Chess960
We missed to set chess960 flag into the std::stringstream used to
setup the PV line.

Bug introduced with commit f803f33e63
of 30/12/2010 when we started to print PV line into a std::stringstream
instead of directly into cout, where the chess960 flag is correctly set.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 18:27:29 +01:00
Marco Costalba ff1ecb5d6c Tidy up benchmark.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 08:53:36 +01:00
Marco Costalba dab1cd8af9 Rename execute_uci_command() to uci_loop()
As a side effect now root position can be directly
allocated on the stack and doesn't need to be defined
static anymore.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 08:12:07 +01:00
Marco Costalba 5b0c6b9bc0 Unhide the istringstream behind UCIParser
It is misnamed because it is not a parser, perhaps a
tokenizer, anyhow better call it for what it is, an
input string stream.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 07:39:07 +01:00
Marco Costalba fc290dc30b Fix startpos_ply_counter() regression
Return the correct number of played plies at the end
of the setup moves. Currently it always returns 0 when
starting from start position, like in real games.

We fix this adding st->pliesFromNull that starts from 0
and is incremented after each setup move and is never
reset in the setup phase but only once search is started.

It is an hack because startpos_ply_counter() will return
different values during the search and is correct only
at the beginning of the search.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:59:14 +01:00
Marco Costalba 5f7eb20090 Use a circular buffer to keep track of setup states
This fixes a regression on real games due to the fact that
we have some mismatches:

    history[st->gamePly - i] != stp->key

when st->gamePly - i == 0,this is due to a nasty bug I have
introduced when using std::vector<> as StateInfo backup. The
point is that StateInfo keeps inside a pointer to the previous
StateInfo in a kind of linked list. But when std::vector<> is
resized reallocates a larger chunk of memory and moves the
data there so these pointers became stale.

This patch fixes the issue.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:15:40 +01:00
Marco Costalba 03ad183384 Don't update gamePly after each move
We just need startup value to calculate available
thinking time. So remove from state.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:15:39 +01:00
Marco Costalba 527a2ec541 Use std::vector<Move> to store UCI search moves
Avoid the ugly and anyhow incorrect hard limit on the
maximum number of moves and allow to handle an arbitrary
number of moves to search.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:15:38 +01:00
Marco Costalba 3185c36a65 Use st->gamePly to store fullMoves
This allow to retire do_setup_move() and also to simplify
draw detection logic becuase now we always have:

Min(st->rule50, st->gamePly) = st->rule50

This was already true when starting from starting position,
but now is true even when starting from a FEN string because
now we take in account fullmove number in counting gamePly so
that it is always.

st->rule50 <= st->gamePly

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:15:36 +01:00
Marco Costalba 3d8140a541 Retire history[]
Use key saved in state instead.

No functional change (in real games) and no speed regression.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:15:35 +01:00
Joona Kiiski a6fc3d6ee5 Do not exit early even when seeing mate
Fixes the reported KNNK ending problem:

http://talkchess.com/forum/viewtopic.php?t=39347

Joona says:

Now I finally had a time to take a look at on this issue.

I've reproduced the problem starting from this position:
1B6/1B2k3/P7/1P3p2/1K6/8/4b3/4b3 w - - 6 85

I made Stockfish play as white and Fruit as black.
I repeated test ten times and once SF was not able to deliver mate.

But I observed several times that SF had reported on last something like mate in 10.
However next time it played move with score mate in 15.

Easiest way to solve the problem is attached as a patch. I tested it several times and SF always
ended up playing the optimal move. Of course the downside is that now delivering mate
takes a bit longer, but IMO it's better to lose once in a while by time in sudden death
game than not being able to deliver simple mate with long time controls.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-24 06:13:29 +01:00
Marco Costalba a1f9bf19d9 Revert previous patches due to bug
We have a bug (possibly because of returning draw from
root move list), it is possible to see when looking at
games with a GUI, we can see rarely but consistently the
score return as #0 for many depths until it comes back to
normal values.

Revert patches until it is not fixed.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-20 03:34:39 +01:00
Joona Kiiski 4ad6a3496b Move the draw check also for qsearch
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-19 17:36:22 +01:00
Joona Kiiski 969ad8001c Move draw checks right after doing the move
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-19 17:36:14 +01:00
Marco Costalba 07e0dd27fb Small touches in set_option()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-17 12:55:26 +01:00
Marco Costalba b8eb699db7 Validate input UCI moves
Running following command:

  position startpos moves e1e8

Makes SF to assert in debug mode in do_move() but to accept
bad input and continue in release mode where probably it is
going to crash little later.

So validate input before to feed do_move().

Suggestion by Yakovlev Vadim.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-17 10:22:55 +01:00
Marco Costalba ad1f28bc1c Remove some useless include
Spotted by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-16 22:59:14 +01:00
Marco Costalba 67686b7684 Don't need to assert for pos.is_ok() when position is constant
It's only necessary to do the checking at the end of every non-const
member (including the constructors and from_fen()) of class Position.
Once the post-condition of every modifier guarantees the class invariant,
we don't need to verify sanity of the position as preconditions for outside
callers such as movegen, search etc. For non-class types such as Move and
Square we still need to assert of course.

Suggested by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-16 10:53:34 +01:00
Marco Costalba 69f4954df1 Change hidden checkers API
After previous patch is no more needed to pass
the color, becuase it is always the side to move.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-16 10:12:46 +01:00
Marco Costalba 4894231ff7 Simplified discovered check connected_moves()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-16 09:50:35 +01:00
Marco Costalba 36bb57a47e Simplify and micro-optimize hidden_checkers()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-16 08:53:21 +01:00
Marco Costalba a042449f5d No need to declare default Position c'tor
Pointed out by Rein Halbersma.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-15 21:53:47 +01:00
Marco Costalba f5e434c2d9 Fix a warning under MSVC
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-15 12:20:31 +01:00
Marco Costalba 37d551fb39 Fix parametrized direction in pawns generation
It worked by accident because we always called both directions,
but definition was wrong.

Functional change due to different generation order, but
perft numbers are the correct ones.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-15 12:13:55 +01:00
Marco Costalba 9c8c0de538 Cleanup handling of Delta enums
Ispired by Rein's code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-15 12:13:48 +01:00
Marco Costalba fbdabe2975 Use std library to sort moves
Functional change due to the fact that now pick_best() is
stable, but should be no change in strenght.

Example code and ideas by Rein Halbersma.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-14 12:43:13 +01:00
Marco Costalba 0cfb30e5be Fix icc's "unreachable code" warning
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-11 11:17:50 +01:00
Marco Costalba c081a81daf Teach to_fen() about Halfmove and Fullmove number
And also fix the last '/' at the end of the piece placement field.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-03 12:08:02 +01:00
Marco Costalba 155bed18f5 Use MoveList also in Position::move_is_pl_slow()
And rename it in Position::move_is_legal()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-03 11:00:28 +01:00
Marco Costalba 95d9687d95 Retire move_is_short_castle() and move_is_long_castle()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-03 10:27:15 +01:00
Marco Costalba ff41b8df76 Restore startpos_ply_counter() instead of full_moves()
And pass correct currentPly to TimeManager::init().

This restores old behaviour, in particular now black has
a different timing than white becuase is no more:

currentPly = 2 * fullMoveNumber;

but becomes

2 * (fullMoves - 1) + int(sideToMove == BLACK)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-03 06:54:46 +01:00
Marco Costalba 53ccba8457 Introduce and use struct MoveList
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-02 14:04:33 +01:00
Marco Costalba 7ac6e3b850 Remove MSVC debug window hack in bench
Interference with profile-build under mingw

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-02 11:52:22 +01:00
Marco Costalba d15217b953 Rearrange structs to avoid internal padding
Found with gcc -Wpadded gcc option.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-02 11:01:12 +01:00
Marco Costalba bc54a44010 Revert PHQ-2
No clear advantage again standard, possibly we will
retest before to release.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-07-02 09:47:06 +01:00
Marco Costalba 3f806df0ca Small touches to do/undo_castle_move()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-30 20:04:46 +01:00
Marco Costalba f3799aa750 Better document generate_castle_moves()
No functional change also in Chess960

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-30 19:58:44 +01:00
Marco Costalba 30ca6935a5 Small tweaks to search()
No functional change also in faked split mode

To be sure verified in real games with 4 threads TC 2"+0.1
After 11125 games 2497 - 2469 - 6159 ELO +0 (+- 4.4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-30 06:54:09 +01:00
Marco Costalba f25582d4b8 Remove duplicated enum Phase definition
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-29 17:54:12 +01:00
Marco Costalba fb2fdb21d3 Retire find_checkers()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 18:01:51 +01:00
Marco Costalba 31a0d2200c Retire square_is_weak()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 17:22:33 +01:00
Marco Costalba e0a00c4996 Retire one piece_list() overload
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 17:11:03 +01:00
Marco Costalba e5077dc11e Rename pieces_of_color() in pieces()
To be uniform with other overloads.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 17:10:44 +01:00
Marco Costalba 01a191936e Retire redundant square_is_occupied()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 17:10:27 +01:00
Marco Costalba 8094b2add8 Change Position::pst() signature
To be more clear what is the underlying table.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 17:10:18 +01:00
Marco Costalba ffb638995d Fix Shredder-FEN regression in from_fen()
Fix also an incredible 3% speed regression by an almost
never called function. I guess this is due to mingw very low
quality standard libraries implementation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-28 17:10:05 +01:00
Marco Costalba c2a4856f9e Greatly simplify castling rights handling
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-27 19:26:30 +01:00
Marco Costalba c9b24c3358 Assume input FEN string is correct in from_fen()
And also tolerate a 0 value for full move number.

Revert BUG_41 patch, now we set initial King file only
if a castling is possible, so we don't need the fix
anymore in case of correct FEN.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-27 12:08:12 +01:00
Marco Costalba 9305983018 Fix a bug in Position::is_ok()
If we cannot castle castleRightsMask[] could be not valid,
for instance when king initial file is FILE_A as queen rook.

In this case castleRightsMask[] at initialQRFile is different
from the expected (ALL_CASTLES ^ WHITE_OOO).

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-26 11:44:12 +01:00
Marco Costalba ae2f5f25cd Rename type_of_piece() and color_of_piece()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-26 10:52:42 +01:00
Marco Costalba 923b14afaa Retire Position::color_of_piece_on()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-26 10:37:13 +01:00
Marco Costalba a9782b94e6 Retire Position::type_of_piece_on()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-26 10:28:54 +01:00
Marco Costalba 351ef5c85b Retire seeValues[] and move PieceValue[] out of Position
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-26 10:19:37 +01:00
Marco Costalba be2925b3c5 Restore user weights to 100
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-24 10:31:03 +01:00
Marco Costalba ace27831ee PHQ settings for King and Mobility
See:
http://talkchess.com/forum/viewtopic.php?t=39327

After 8130 games on QUAD at 20"+0.1
1342 - 1359 - 5429 ELO +0 (+- 4.4)

Tried also version with just king settings changed:
After 5932 games 962 - 1052 - 3918 ELO -5 (+- 5.2)

And with just mobility settings changed:
After 4114 games 618 - 619  - 2877 ELO +0 (+- 5.9)

Frank has tested only 1200 games, but at longer TC and
against many engines, so because PHQ results are not worst
than other combination and not worst than original let's
commit his version.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-24 09:47:30 +01:00
Marco Costalba 6a1707889c Fix move_is_capture() to detect capture promotions
We miss to account as a capture a promotion capture !

Incredible bug in this critical function that is here
since a long time (b50921fd5c of 21/10/2009 !!)

This patch fixes the bug and readds the faster
move_is_capture_or_promotion() that slightly increases
overall speed.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-23 12:09:31 +01:00
Marco Costalba 1c42d15340 Rewrite how uci info is sent to GUI
It is now much more modular than before and also we
always send the seldepth when we send the depth, this
avoids to make seldepth disappearing from GUI at the
start of a new iteration.

Print also fails high/low pv lines at high enough
search depths.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-22 17:32:22 +01:00
Marco Costalba fe26967ea0 Simplify sliding_attacks()
Easy, almost trivial simplification, I don't understand
how I missed this before !!

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-21 19:01:00 +01:00
Marco Costalba e7413417ce Retire ksq from CheckInfo
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-21 12:13:26 +01:00
Marco Costalba 018022b866 Use CheckInfo to store pinned bitboard
This trivial change gives an impressive 2,5% speedup !!!!

Also retire one unused move_gives_check() overload.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-20 12:09:11 +01:00
Marco Costalba 7ea38e980b Omit mate distance pruning at root
Restore original behaviour, before root unification and
remove a now useless ugly hack for alpha in multi-pv case.

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-18 17:11:09 +01:00
Marco Costalba 8173d92dd2 Use an array index instead of an iterator in root list
It is not correct to use an iterator stick on a vector that
is sorted becuase iterator is invalidated in general case.

It happens to work by accident because iterators are implemented
as pointers and so they behave in the same (correct) way then
using array indices, but the latters are the correct thing to use.

Also better document the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-18 08:03:59 +01:00
Marco Costalba 808a4fe817 Remove useless bestValue = alpha assignement
It is a fossil from the root_search() era, no more
needed today.

Spotted by Onno

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-15 12:49:59 +01:00
Marco Costalba 72760c05c6 Try only recaptures in qsearch if depth is very low
This avoids search explosion in qsearch for some
patological cases like:

r1n1n1b1/1P1P1P1P/1N1N1N2/2RnQrRq/2pKp3/3BNQbQ/k7/4Bq2 w - - 0 1

After 9078 games 20"+0.1 QUAD:
Mod vs Orig 1413 - 1319 - 6346 ELO +3 (+- 4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-15 12:17:49 +01:00
Marco Costalba 15683034a7 Speed up kpk initialization
The trick is to classify more position at first cycle,
so to reduce following work. Speed up is of about 50% !

Also some cleanup while there.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-15 12:11:35 +01:00
Marco Costalba 4c9d570e43 Use Carry-Rippler trick to speed up magics
Nice trick discovered on:

http://chessprogramming.wikispaces.com/Traversing+Subsets+of+a+Set

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-15 02:15:41 +01:00
Marco Costalba fc519ca74a Retire init_piece_square_tables()
Merge in init_zobrist() and rename the latter.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-13 17:28:09 +01:00
Marco Costalba a24c0a736c Increase LMR limit by one ply
Seems there is no regression so prefer to prune less.

After 8278 games
Mod vs Orig 1246 - 1265 - 5767 +0 ELO (+- 4.2)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-12 21:14:07 +01:00
Marco Costalba b3a0b389d2 Better self-document init_zobrist()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-12 11:50:19 +01:00
Marco Costalba 47959c56fd Fix initialization of BSFTable[]
We should start from i = 0, it works by accident because
static storage BSFTable[] is init to zero by default.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-12 11:37:02 +01:00
Marco Costalba aee75ae105 Don't update_gains() in qsearch
Is almost unuseful becuase captures are skipped.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-12 07:09:30 +01:00
Marco Costalba 4b8a7f2793 Fix score_captures() for the case of capture promotions
In case we have more than one promotion move, prefer
the one that captures the biggest piece.

Almost no functional change, anyhow I don't expect any
ELO change, it is just the correct thing to do.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-11 22:12:13 +01:00
Marco Costalba 89ec224cb9 Retire some unused functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-11 15:56:12 +01:00
Marco Costalba b21a5e2f06 Micro-optimize castling handling in do_move()
And better self-document the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-11 15:31:39 +01:00
Marco Costalba 735cac5d53 Retire PieceLetters struct
Use a much simpler std::string instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-10 17:12:10 +01:00
Marco Costalba bc4f3155ae Better document move_to_san()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-10 11:59:53 +01:00
Marco Costalba a21a110188 Revert refinedValue in ProbCut
It seems much worst in number of nodes seacrhed to reach
the depth and anyhow does not give any advantage to the
Onno's oroginal one.

So revert by now and perhaps readd when we find something
clearly better.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-09 21:59:24 +01:00
Marco Costalba b414fc0dfd Use double rotate for magic generation
Allow to choose among 4096 instances of pseudo-random
sequences instead of the previous 64 so the probability
to find a better sequence increases and actually we have
a much better 64 bit case and we can also use the 64 bit
version of pick_magic() also for 32 bits and althoug sub
optimal, because now we can have more choices results are
even slightly better also for 32 bit.

Use also a faster submask().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-09 18:47:58 +01:00
Marco Costalba e0215f3222 Use refinedValue in ProbCut condition
After 12613 games at 20"+0.1 on QUAD
Mod vs Orig 1870 - 1863 - 8880 ELO +0 (+- 3.3)

So no performance change but it is a code semplification
and also is more easy to understand.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-08 18:03:26 +01:00
Marco Costalba 3dfff5bdae Small pick_magic() touches
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-08 17:59:47 +01:00
Marco Costalba d632e77058 Find magics on the fly
Good result for 32 bit case where computation is very fast,
still not satisfying on 64 bit case where the magics seem
a bit harder to get.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-07 20:59:12 +01:00
Marco Costalba 6d665b7f78 Partially revert previous patches
Due to a -2% speed penalty. This patch takes the best
of the previous series without the regression due to
introduction of Magic struct.

Speedup against previous revision is of almost 3% !!!!

No functional change both in 32 and 64 bits.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-06 11:56:17 +01:00
Marco Costalba b1b0c64046 Skip offset calculation in slider attacks
Another small simplification and micro optimization.

No functional change in both 32 and 64 bits.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-05 15:01:22 +01:00
Marco Costalba 670cee44f0 Get rid of Shift[] tables
We can calculate them counting the masks bits.

Also small tweak to sliding_attacks()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-05 14:13:41 +01:00
Marco Costalba 3092f0c646 Better name and document magic botboard stuff
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-05 12:28:36 +01:00
Marco Costalba 2f6142cb9b Try to keep memory access in the same cache line
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-05 12:27:53 +01:00
Marco Costalba 3b2bcee0a8 Skip draw by repetition check in qsearch
Cut in half the time spent in pos.draw() that accounts
for a whopping 1% of total time !

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-04 11:29:54 +01:00
Marco Costalba 91407f4f74 Move bitboards initializations under one function
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-04 11:05:12 +01:00
Marco Costalba 025d57855a Calculate Bit Scan tables at initialization
Instead of hard-coding them.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-04 09:59:18 +01:00
Marco Costalba 8647fbd6ed Do not sort negative non captures at low depth
Speedup of the whole 3 patch series is of 2,5% !!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-04 06:35:24 +01:00
Marco Costalba 811037c845 Split non capture in two sets when ordering
But keep same ordering. This patch is prerequisite
for future work.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-03 22:10:23 +01:00
Marco Costalba 181cc3f93f Inline extension()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-03 13:14:03 +01:00
Marco Costalba 91b919fd1d Use TT also in Root nodes
And other small stuff ti be tested in SMP

No functional change in single thread.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-03 12:59:50 +01:00
Marco Costalba 5ff6289afd Microoptimize generate<MV_EVASION>
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-06-02 12:49:40 +01:00
Marco Costalba fca0a2dd88 New extended probcut implementation
Here the idea is to test probcut not only after bad
captures, but after any bad move, i.e. any move that
leaves the opponent with a good capture.

Ported by a patch from Onno, the difference from
original version is that we have moved probcut after
null search.

After 7917 games 4 threads 20"+0.1
Mod vs Orig: 1261 - 1095 - 5561 ELO +7 (+- 4.2) LOS 96%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-30 20:49:04 +01:00
Marco Costalba 462a39ec49 Fix SAN disambiguation bug
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-29 10:52:03 +01:00
Marco Costalba 70125a3be0 Rename PH_TT_MOVES in PH_TT_MOVE
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-29 09:17:03 +01:00
Marco Costalba cff8877a1a Retire mateKiller
Practically useless:
After 6456 games 1281 - 1293 - 3882 ELO +0 (+- 5.5)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-28 22:50:22 +01:00
Marco Costalba 8f51f09de7 Unify MovePickerExt template parameters
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-28 13:23:32 +01:00
Marco Costalba 013dc43d5d Unify search() template parameters
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-28 12:44:39 +01:00
Marco Costalba 853e2a9495 Fix moveCount after legality check delay
We really want PV moves and also Split Point moves to be
legal to avoid messing the move counter and corresonding
PV move detection or shared Split Point's counter variable.

This fixes a real bug where a position with only one move
allowed returns bestValue == -VALUE_INFINITE if the move
turns out to be illegal.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-28 11:16:00 +01:00
Marco Costalba 4c3a000211 A bit of reformatting after previous series
And some documentation update.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-24 21:24:40 +01:00
Marco Costalba 9884573561 Test for legality only after futility pruning
Although there is a small functional change it seems
an improvment of about 2% in speed !

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-23 20:21:02 +01:00
Marco Costalba 4b232f5ddc Move legal check out of MovePicker
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-23 20:20:52 +01:00
Marco Costalba 45ce92b89c Rename move_is_legal() in move_is_pl()
We disjoint pseudo legal detection from full legal detection.

It will be used by future patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-23 20:20:42 +01:00
Marco Costalba bc86668ba4 Output debug info to cerr
So to be clearly visible when redirecting stdout to /dev/null

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-23 20:20:31 +01:00
Marco Costalba 0783211950 Fix a shadowed variable warning under gcc
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-23 20:20:19 +01:00
Marco Costalba 13fe7ee4df Bug wrong evasion detection for king moves
When we are in check and we move the king then testing with
pl_move_is_legal(m, pinned) is not enough becuase we cannot
rely on attackers_to() but we have to explicitly remove the
king form the occupied bitboard to catch as invalid moves like
b1a1 when opposite queen is on c1.

Our move generator already produces correct evasions so we
just need to add the extra verification to move_is_legal().

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-22 11:51:28 +01:00
Marco Costalba 21fc66c246 Add file distance condition in move_is_legal()
Found another missed control in move_is_legal() thanks to
brute force testing.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-22 09:49:44 +01:00
Marco Costalba ff9e49bac9 Remove useless casts in types.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-22 08:52:39 +01:00
Marco Costalba 90e83fa879 Promotion piece must be empty if is not a promotion
Add a new check in  move_is_legal()

Avoid useless casting in move.h while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-22 08:48:19 +01:00
Marco Costalba 3ef4fdeaa0 Introduce MovePicker::isBadCapture() and use in probcut
Small functional change due to the fact that now we skip
probcut on evasions.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-21 10:40:36 +01:00
Marco Costalba 13d8af1852 Correctly handle castle in see()
Suggested by Onno.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-20 06:58:53 +01:00
Marco Costalba 5b7a141065 Fix brekage from previous patches
It is interesting the fact that we need to test for
move_is_castle(m) anyway and not relying on testing
if destination square is attacked. Indeed the latter
condition fails if the castling rook is attacked,
castling is coded as "king captures the rook" but it
is legal in that case.

Verified no functional change with beginning of the series.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-18 07:05:36 +01:00
Marco Costalba 89a06f6651 Micro-optimize pl_move_is_legal()
Remove the check for castling moves because it is
already implicit in the check for king moves and castling
is so rare that doing the check is just a slow down.

Thanks to Marek Kwiatkowski.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 23:47:26 +01:00
Marco Costalba a2e924039b Retire move_is_capture_or_promotion()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 23:39:14 +01:00
Marco Costalba 85d1f9c5ec Fix move_is_capture() definition
The structure of move is changed so should also the two
functions. It happens that it works by accident !

Bug spotted by Marek Kwiatkowski

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 23:31:40 +01:00
Marco Costalba e444e18d2b Retire test for king moves in see()
We already test this condition in see_sign() and
so it is almost always a redundant verification.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 12:25:49 +01:00
Marco Costalba ad0fdf0da6 Retire Position::see(Square from, Square to) overload
Alomst unuseful.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 12:17:57 +01:00
Marco Costalba fbbc7e421c Prefer an assert to a comment in position.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 12:17:48 +01:00
Marco Costalba 1cc42ac9e4 Let 'make' with no arguments to show compilation options
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 12:17:38 +01:00
Marco Costalba 6624105b5b Prefer ttMove to tte->move() in search()
Avoids aliasing problems due to TT overwrites.

Node changes becuase of IID.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-17 12:17:29 +01:00
Marco Costalba de58594b0f Use standard naming conventions in book.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-08 11:50:38 +01:00
Marco Costalba d5f0b91c06 Reintroduce operator>>() in Book class
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-08 09:15:18 +01:00
Marco Costalba f78488bbdb Restore development version
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-08 09:11:36 +01:00
Marco Costalba e3b23eb818 Stockfish 2.1.1
stockfish bench signature is: 6487630

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-08 08:46:33 +01:00
Marco Costalba d494725400 Spell fix in evaluate.cpp
Spotted by Eelco.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-07 10:08:53 +01:00
Marco Costalba 2535dc1340 Fix reading of book file
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>
2011-05-07 09:51:33 +01:00
Marco Costalba 339bf9b7e1 Remove redundant assignment in search()
It is already assigned few lines before.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-05 12:16:26 +01:00
Marco Costalba bb86691a0d Restore development version
No functional change.
2011-05-05 06:35:42 +01:00
Marco Costalba f7fee4c616 Fix a warning in debug mode
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-03 19:29:21 +01:00
Marco Costalba 315c58354e Stockfish 2.1
stockfish bench signature is: 6487630

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-03 12:11:19 +01:00
Marco Costalba 5ef2b8c494 Reintroduce permanent PV entries in TT
We are now ready to release so restore this
improvment before 2.1

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-03 12:11:10 +01:00
Marco Costalba 9c5a53ca45 Update Readme.txt to 32 threads and bsfq on Windows
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-03 12:11:02 +01:00
Marco Costalba b1929960f9 Fix bug in evaluate_passed_pawns()
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>
2011-05-03 12:10:53 +01:00
Marco Costalba 8447248705 Retire "Pawn Structure" UCI option
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>
2011-05-02 17:50:46 +01:00
Marco Costalba a10487b074 Rename stuff in evaluate.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-02 17:50:37 +01:00
Marco Costalba db31efb8a6 Additional tweaks in evaluate_unstoppable_pawns()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-01 12:15:40 +01:00
Marco Costalba 75acd52415 Remove redundancy in evaluate_unstoppable_pawns()
Spotted by Fruity
http://open-chess.org/viewtopic.php?f=5&t=1156&start=20

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-01 10:31:27 +01:00
Marco Costalba 18c9b5ee86 Small reformat in evaluate_unstoppable_pawns()
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>
2011-05-01 09:58:45 +01:00
Marco Costalba 33bd67e052 Update polyglot.ini
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-05-01 07:49:40 +01:00
Marco Costalba 4dc7ba1619 Rename check related functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-29 18:56:48 +01:00
Marco Costalba 92d70fb667 Small renaming in thread.cpp
To better self document the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-29 13:08:35 +01:00
Marco Costalba 0bf475ec55 Rename Option in UCIOPtion
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-29 13:08:27 +01:00
Marco Costalba bb7713c8e9 Limit history range to +-2000
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>
2011-04-28 08:00:34 +01:00
Marco Costalba e656ddcf18 Perft counts leaf nodes not generated moves.
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-27 23:21:46 +01:00
Marco Costalba 1d0159075e Use probe() as name for looking up into an hash table
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-27 07:31:51 +01:00
Marco Costalba 321320b081 Tidy up uci.cpp and siblings
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-26 13:23:47 +01:00
Marco Costalba ca9d40c145 Move OpeningBook and RK where are actually used
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-26 13:23:39 +01:00
Marco Costalba 03f4d1e8d6 Fix a compile error with gcc
It seems gcc does not like an extra semicolon.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-25 22:59:56 +01:00
Marco Costalba 87f2b52ace Move MovePickerExt specializations away from headings
This unclutters a bit the heading part of search.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-25 13:35:13 +01:00
Marco Costalba 09d01ee9dc Tidy up benchmark.cpp
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>
2011-04-25 12:07:30 +01:00
Marco Costalba 05cfb00f26 Large API rename in ThreadsManager
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-25 10:30:39 +01:00
Marco Costalba 339e1b49f6 Don't allocate MAX_THREADS hash tables if not necessary
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>
2011-04-24 19:23:07 +01:00
Marco Costalba fecefbb99c Move pawn and material tables under Thread class
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>
2011-04-24 17:07:22 +01:00
Marco Costalba c9d7e99de6 Rename MOVES_MAX in MAX_MOVES
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-24 08:54:36 +01:00
Marco Costalba ccd5ccbcdb Retire extensions as UCI option
There is no real need why an user should change these values.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-24 08:52:16 +01:00
Marco Costalba 633c83f648 Document why we use per-thread pawn and material tables
Arisen from a discussion on talkchess.

No fnctional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-24 08:18:39 +01:00
Marco Costalba fe213d30fa Fix some comments in early stop detection
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-23 15:52:51 +01:00
Marco Costalba 8b2adcf99e Retire UseLogFile in search.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-23 15:00:44 +01:00
Marco Costalba 1d368bbbdc Introduce and use SearchLimits
Pack a bit of global variables related to search limits in
a single struct.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-23 13:11:03 +01:00
Marco Costalba bbfe452f85 Use move_is_special() in pawn endgame condition
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-22 12:30:51 +01:00
Marco Costalba 8bf9dc8254 Retire SearchStartTime global
Use a static variable inside current_search_time() instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-22 12:30:43 +01:00
Marco Costalba f349143a6b Reduce loops in init_threads() and exit_threads()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-22 12:30:35 +01:00
Marco Costalba 79e50a2fbf Move wake_sleeping_thread() to Thread class
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-20 12:05:07 +01:00
Marco Costalba 2c317d7b28 Correctly implementg selDepth feature
Send to GUI the deepest search depth apart from
qsearch of the PV line.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-20 12:04:59 +01:00
Marco Costalba fdc9f8cbd7 Move sleepLock and sleepCond under Thread
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-20 12:04:52 +01:00
Marco Costalba 2e6839c9a0 Increase risk of blunders at low skill levels
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>
2011-04-20 12:04:43 +01:00
Marco Costalba 67b0d0b1cc Use only history to score non captures
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>
2011-04-17 22:32:12 +01:00
Marco Costalba 068561f86a Small simplification in scale_by_game_phase()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-17 10:31:26 +01:00
Marco Costalba 076b62310e Move ply to SearchStack
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>
2011-04-17 08:59:54 +01:00
Marco Costalba 5ba85ef441 Remove one indentation level in get_next_move()
Small renaming and fix some comments.

No functional and no speed change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-16 12:57:06 +01:00
Marco Costalba c13b53a514 Code style in tt.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-16 10:49:35 +01:00
Marco Costalba a860576493 Better self-document LMR reduction() formula
Suggested by Onno

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-16 10:49:27 +01:00
Marco Costalba 786564068b Promote OptionsMap to a class
And add a bit of documentation too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-16 10:49:20 +01:00
Marco Costalba 6056a43419 Fix a stale comment
Spotted by Onno

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-16 10:21:31 +01:00
Marco Costalba f8e767388b Remove src/COPYING file
It is enough the one in the base directory

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-14 07:06:56 +01:00
Marco Costalba b41b590457 Remove "divide by zero" workaround
It is now useless because of the condition at the beginning.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-14 07:04:32 +01:00
Marco Costalba 7f367e6019 Cleanup debug counters
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-13 18:51:56 +01:00
Marco Costalba 54f1c383d3 Move move_is_legal() under Position class
It is a more logical place than in move generation file.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-13 13:18:19 +01:00
Marco Costalba fe8f5b3497 Some more cleanup in endgame.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-13 13:17:21 +01:00
Marco Costalba 6608a16a6a Fix some warnings and a compile error with icc
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>
2011-04-12 08:05:41 +01:00
Marco Costalba b5d5646c84 Move EndgameFunctions to endgame.cpp
And cleanup code while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-11 21:25:24 +01:00
Marco Costalba 08c464c690 Increase MaterialTableSize 8 times
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>
2011-04-11 18:15:40 +01:00
Marco Costalba f28ddbb852 Introduce and use NoPawnsSF[] in material.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-11 18:11:16 +01:00
Marco Costalba c88eebc989 Tempeltize material imbalance
Speedup of almost 1%

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-11 12:35:54 +01:00
Marco Costalba 7a84b8ca34 Sync material.h with pawns.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-11 12:24:10 +01:00
Marco Costalba 6738b65be9 Prefetch also material tables
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>
2011-04-11 12:24:02 +01:00
Marco Costalba 2f1935078d Assorted code style and comments in pawns.cpp and pawns.h
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>
2011-04-10 12:16:36 +01:00
Marco Costalba 8e71ee7ec6 Retire mate threat extension
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>
2011-04-08 07:48:05 +01:00
Marco Costalba 9bee5f51d8 Fix a compile error in debug mode
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-07 08:09:41 +01:00
Marco Costalba 927f1b0bd3 Assorted code style and comments in search.cpp
Nothing really serious....

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-05 19:00:40 +01:00
Marco Costalba 04108d4541 Added -Wshadow option and fixed resulting warnings
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-04 12:11:01 +01:00
Marco Costalba f7ef48b478 Teach SF to blunder
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>
2011-04-02 10:04:34 +01:00
Joona Kiiski 2e8998eac9 Use prob cut search to prune bad captures
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>
2011-04-02 08:39:54 +01:00
Marco Costalba 8402b40341 Retire recapture extension also for PvNode
Seems that extension is useless.

After 10105 games
Mod vs Orig 1738 - 1702 - 6665  ELO +1 (+- 4)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-01 22:02:18 +01:00
Marco Costalba 408fdcc93f Use a constant instead of value_mate_in(PLY_MAX)
And also apply the same to value_mated_in(PLY_MAX)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-01 21:46:45 +01:00
Marco Costalba b27e237b04 Retire value_is_mate()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-01 21:46:34 +01:00
Marco Costalba f5b8db7a1e Simplify wait_for_stop_or_ponderhit()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-01 21:46:27 +01:00
Marco Costalba 8d4caebabe Retire update_killers()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-04-01 21:46:12 +01:00
Marco Costalba d173285da5 Fine tune skill level
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>
2011-03-28 13:09:13 +01:00
Marco Costalba 41fe70d703 Add "Skill level functionality
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>
2011-03-27 11:50:22 +01:00
Marco Costalba d372f2e39a Fix a compile error with icc
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-26 09:25:26 +01:00
Marco Costalba 4270aec558 Send PV line to GUI only after resolving a fail high
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>
2011-03-24 13:21:54 +01:00
Marco Costalba f427acbd27 Triviality in position.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-24 13:21:47 +01:00
Marco Costalba 87ca13a79a Retire move_ambiguity() altogether
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-23 13:09:04 +01:00
Marco Costalba d52d91064f Simplify move_ambiguity()
And additional small touches in move.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-22 13:23:41 +01:00
Marco Costalba 920b1abede Do not send ponder move if we don't have it
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>
2011-03-19 16:08:19 +01:00
Marco Costalba 5ea08e79c4 Use intrinsic in pop_1st_bit() under MSVC 64 bits
Around 1% speedup when compiled with MSVC 64

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-17 14:29:09 +01:00
Marco Costalba 635be39acf Additional cleanup in bitbase.cpp
Also better document what code does.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-12 18:22:22 +01:00
Marco Costalba c1c0984452 Move KPKBitbase[] where it belongs
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-12 12:12:41 +01:00
Marco Costalba d653aeca05 Fix a couple of issues in bitbase.cpp
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-12 11:22:02 +01:00
Marco Costalba 09d217bff7 Reintroduce initialization of some bitboards
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>
2011-03-10 19:23:39 +01:00
Marco Costalba d9113d127b Rename NonSlidingAttacksBB[] in StepAttacksBB[]
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-10 08:10:26 +01:00
Marco Costalba c2511243b4 Update copyright notes in rkiss.h
New info after a thread on talkchess:

http://www.talkchess.com/forum/viewtopic.php?t=38313

and some emails exchange with Heinz.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-10 08:08:34 +01:00
Marco Costalba d85cf6d9c3 Revert previous patch due to miscompile under gcc
I need to understand what's going on, in the
meantime revert.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-10 08:08:04 +01:00
Marco Costalba a617b03875 Change initialization of some bitboards
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-08 19:44:19 +01:00
Marco Costalba c980163316 Increase MAX_THREADS to 32
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>
2011-03-08 13:16:33 +01:00
Marco Costalba 76506bd3d1 Introduce and use rot() in rkiss.h
Also fix indentation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-07 19:04:54 +01:00
Marco Costalba 9069193125 Simplify aspirationDelta update rule
After 7522 games:
Mod vs Orig 1229 - 1148 - 5145  ELO +3 (+- 4.5) LOS 83%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-03-02 22:01:30 +01:00
Marco Costalba 0c775fae4b Be sure to read options before to call trace_evaluate()
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>
2011-03-01 13:32:42 +01:00
Marco Costalba 1f73a9ed63 Fix aspiration corner case
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>
2011-02-28 20:17:57 +01:00
Marco Costalba af236373cb Remove a FIXME in id_loop()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-28 20:16:22 +01:00
Marco Costalba ce2845d333 Score root move list during first iteration
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>
2011-02-28 07:51:28 +01:00
Marco Costalba 204efb109b Remove an useless condition in equal SEE pruning
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>
2011-02-27 09:45:54 +01:00
Marco Costalba 91a2766308 Prune moves with equal SEE in qsearch
After 5166 games:
Mod vs Orig 890 - 762 - 3514  ELO +8 (+- 5.5) LOS 96%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-27 09:19:59 +01:00
Marco Costalba bd33766da0 Add evaluation tracing code
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>
2011-02-26 14:26:27 +01:00
Marco Costalba dd718d92a7 Correctly round evaluation to grain size
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 23:52:51 +01:00
Marco Costalba 23cbb221b2 Depth dependant singular extension margin
After 7965 games:
Mod vs Orig 1324 - 1249 - 5392  ELO +3 (+- 4.4) LOS 81%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 23:51:20 +01:00
Marco Costalba 0fcda095df Move all enum types definitions to types.h
Cleanup headers while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 21:52:55 +01:00
Marco Costalba 95212222c7 Retire color.h
Move contents to piece.h and square.h

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 18:42:45 +01:00
Marco Costalba 2ff2b59727 Rename piece_of_color_and_type() to make_piece()
To be aligned with make_square()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 18:42:35 +01:00
Marco Costalba 5b2ac7590c Retire piece_type_from_char()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 18:42:27 +01:00
Marco Costalba 2511386155 Triviality in main.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 18:41:58 +01:00
Marco Costalba deb212cb05 Retire enum SquareDelta
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>
2011-02-23 18:41:35 +01:00
Marco Costalba aa40d0a917 Small simplifications in square.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-23 18:41:27 +01:00
Marco Costalba b3108547de Introduce and use speed_to_uci()
And retire nps()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-19 13:31:35 +01:00
Marco Costalba 706b44a966 Rename SplitPoint parentSstack
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>
2011-02-18 17:04:55 +01:00
Marco Costalba 823a5918e7 Retire SearchStack sstack[] from SplitPoint
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>
2011-02-18 16:54:49 +01:00
Marco Costalba 932ae761c6 Sync Root new depth to what we do in search()
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>
2011-02-18 11:24:42 +01:00
Marco Costalba 29fa6f3c5f Unify best move update logic
Try to rewrite the Root case using as most as common
code as possible.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-17 09:51:22 +01:00
Marco Costalba 5815718177 Do not special case reductions for MultiPV case
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>
2011-02-17 09:08:27 +01:00
Marco Costalba 6a19f5832a Avoid permanent PV entries in TT
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>
2011-02-16 08:57:35 +01:00
Marco Costalba 4ead60e2a7 Write the LogFile only at the end of an iteration
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>
2011-02-13 11:45:49 +01:00
Marco Costalba 2786aed195 Spell checking fixes in search.cpp
Reported by Eelco on open-chess.org

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-12 19:06:07 +01:00
Marco Costalba 876ceb1feb Rename iteration in depth in id_loop()
And retire the redundant one.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-12 18:53:02 +01:00
Marco Costalba 29076043e0 Start to count iterations from 1
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>
2011-02-12 18:17:37 +01:00
Marco Costalba aa84731fb9 Fix wrong reported depth
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>
2011-02-12 17:58:25 +01:00
Marco Costalba c006435bb4 Move sending of PV line to id_loop()
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>
2011-02-11 06:28:55 +01:00
Marco Costalba 141410f177 Maximum aspiration delta of 24
After 9080 games
1430 - 1342 - 6308  ELO +3 (+- 2.9)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-10 21:09:20 +01:00
Joona Kiiski 3abff79df3 Maximum aspiration delta of 64
After 9242 games
Mod vs Orig: 1483 - 1373 - 6386  ELO +4 (+- 2.9)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-09 23:52:24 +01:00
Marco Costalba 62c707e1d5 Simplify latest patches
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-06 12:41:47 +01:00
Joona Kiiski 26e7673c18 Retire some conditions from ok_to_use_TT_pv
After 4844 games 768 - 747 - 3329  ELO +2

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-02-05 11:06:08 +01:00
Marco Costalba b366c7dc38 Use TT for pruning also in PV nodes
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>
2011-01-31 13:07:26 +01:00
Marco Costalba 2f6788104f Silence silly MSVC warning c4146
Warning C4146: unary minus operator applied to
unsigned type, result still unsigned.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-29 14:10:05 +01:00
Marco Costalba 69726f4df3 Remove defined(IS_64BIT) in init_sliding_attacks()
No functional change bith in 32 and 64 bits.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-29 14:06:29 +01:00
Marco Costalba f3e0b32def Do not use <algorithm> in to_fen()
Seems there are some problems on HP-UX compiler.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-29 13:28:00 +01:00
Marco Costalba 188700d7f1 Retire obsolete reentrancy check in pos.print()
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>
2011-01-29 12:17:47 +01:00
Marco Costalba 9ba7f701ea Retire singleEvasion
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>
2011-01-27 07:55:04 +01:00
Marco Costalba afae86bfb4 Add a MovePicker c'tor specialized for qsearch
This simple patch shows a speed increase of
more then 2% !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-23 23:13:14 +01:00
Marco Costalba f352008958 Introduce and use qsearch_scoring()
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>
2011-01-23 10:54:16 +01:00
Marco Costalba 6849f0800e Retire InitialDepth
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-23 10:52:51 +01:00
Marco Costalba 5194b2bb06 Pass TT move instead of Rml[0].pv[0] to MovePicker
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>
2011-01-23 09:11:31 +01:00
Joona Kiiski a8f457d425 Different searchedMoves system
After 8751 games on russian cluster
Mod- Orig: 1426 - 1323 - 6002  ELO +4 (+- 2.9) LOS 86%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-23 08:36:47 +01:00
Marco Costalba 79b1a7417f Remove special Root cases
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>
2011-01-23 08:36:12 +01:00
Marco Costalba b67de36671 Retire init_ss_array()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-20 19:34:25 +01:00
Marco Costalba 59c85346d2 Small cleanup in init_sliding_attacks()
No functional change both in 32 and 64 bits.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-19 19:50:44 +01:00
Marco Costalba e8f885145b Numbers formatting in bitboard.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-19 19:50:32 +01:00
Marco Costalba 324ca87aff Use opposite_color_squares() instead of same_color_squares()
It is almost alwasy the requested test and is a bit faster too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-19 13:50:51 +01:00
Marco Costalba 4f3fe89fb6 Retire RelativeRankBB[]
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-19 13:33:38 +01:00
Marco Costalba 45acec1865 Retire some unused functions in bitboard.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-19 13:33:26 +01:00
Marco Costalba a38b14bd33 Fix some warnings under icc
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 18:53:19 +01:00
Marco Costalba d91d6da3c4 Sort root moves moves in MovePickerExt
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 18:52:52 +01:00
Marco Costalba 5bad5fc0a7 Fix a (bestValue == -VALUE_INFINITE) assert
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>
2011-01-18 13:30:13 +01:00
Marco Costalba 6119e4ea37 Additional cleanup in id_loop()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 13:30:13 +01:00
Marco Costalba 5555b60b38 Use a global RootMoveList object instead of a pointer
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 13:30:12 +01:00
Marco Costalba 846087e4fb Move globals to id_loop()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 13:30:11 +01:00
Marco Costalba 2e2f1064ba Introduce and use MovePickerExt
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>
2011-01-18 13:30:11 +01:00
Marco Costalba 392c7f2ab6 Unify root_search() step 3
Retire root_search()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 13:30:10 +01:00
Marco Costalba 6b8026806c Unify root_search() step 2
Enable the change: now we use search() instead of root_search()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-18 13:29:57 +01:00
Marco Costalba 299bda9ea3 Unify root_search() step 1
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>
2011-01-18 13:28:34 +01:00
Joona Kiiski 998845763a Fix very theoretical History corner case
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-17 20:22:10 +01:00
Marco Costalba 842efefcad Sync root_search() with search()
This will let unification easier.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-16 13:45:34 +01:00
Marco Costalba c17a127c42 Move fail loops out of root_search() to id_loop()
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>
2011-01-16 13:45:23 +01:00
Marco Costalba e06c99cad0 Last touches in history.h
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-15 18:03:43 +01:00
Marco Costalba 04001f776e Fix a warning with __popcnt64() intrinsics
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>
2011-01-15 12:05:31 +01:00
Marco Costalba 877b468e3e Partially restore HistoryMax
Should be not useful but better safe than sorry.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-15 11:31:14 +01:00
Marco Costalba 13a42284b6 Move Min() and Max() macros to types.h
As usual a bit of cleanup while there...

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-15 11:00:00 +01:00
Marco Costalba 3bb1ab34e4 Clarify we want Score and Value to be integers
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-15 10:37:36 +01:00
Marco Costalba 7faeab0878 Retire history.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-15 10:02:45 +01:00
Marco Costalba 2052407090 Retire HistoryMax
Infact we don't use it anymore already.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-15 09:30:39 +01:00
Joona Kiiski d6fdd4f6d9 Set HistoryMax infinitely high
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>
2011-01-14 19:13:22 +01:00
Marco Costalba b85bcc039c Simplify from_fen()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-14 12:56:31 +01:00
Marco Costalba 62cd133b3a Initialize killers at ss+2 also in root_search()
After 4955 games:
Mod - Orig: 786 - 768 - 3401 +1 ELO

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-14 07:27:06 +01:00
Marco Costalba 6442981cb6 Fix an hang on 32 bits while allocating big TT table
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>
2011-01-13 22:03:18 +01:00
Marco Costalba d4b92ae9a0 Set unbuffered I/O also for C standard library
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>
2011-01-11 18:58:56 +01:00
Marco Costalba 611a29f767 Big book.cpp cleanup
Better document PolyGlot formats and greatly
reduce line count.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-10 19:55:02 +01:00
Marco Costalba d84ffc0cfa Compile fix in types.h
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-10 12:54:08 +01:00
Marco Costalba caa02b0e43 Small cleanup in execute_uci_command()
With a little fall out in siblings functions...

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-09 16:24:30 +01:00
Marco Costalba a8741bd59f Simplify set_option()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-09 15:15:52 +01:00
Joona Kiiski 06c14d0a37 TTEntry simplification
Now that move is fitted in 16 bits we can simplify TTEntry.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-09 13:20:04 +01:00
Marco Costalba 15153a1de7 Don't copy Position in pretty_pv()
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>
2011-01-09 12:55:22 +01:00
Marco Costalba c89762288b Merge line_to_san() into pretty_pv()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-08 18:31:14 +01:00
Marco Costalba b4acf83704 Ressurect move.cpp
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>
2011-01-08 17:52:02 +01:00
Joona Kiiski ee0afea1e5 Fix build failure under Linux
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-08 16:26:55 +01:00
Marco Costalba c82906a2c3 Retire move_from_san()
It is unused and it is big.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-08 16:23:46 +01:00
Marco Costalba 6b49d509a1 Greatly simplify move_from_uci()
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>
2011-01-08 16:12:42 +01:00
Marco Costalba 82d5386435 Move uci move parsing under san.cpp
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>
2011-01-08 15:53:49 +01:00
Joona Kiiski f4b4d4901c Change Emergency time maximum from 60000 to 30000
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>
2011-01-08 14:27:11 +01:00
Joona Kiiski 8d86e95e37 Fix Makefile's GPL-notice to be similar to other files
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-08 14:26:59 +01:00
Marco Costalba 0f81f97bb6 Improve I/O responsivness
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>
2011-01-08 14:17:41 +01:00
Marco Costalba d9b96f0e49 Fix reading a book under-promotion move
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>
2011-01-08 13:23:25 +01:00
Marco Costalba 4fa0395eb8 Triviality in data_available()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-08 12:53:41 +01:00
Marco Costalba b3545737fa Force inlining of move generation functions
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>
2011-01-07 16:57:15 +01:00
Marco Costalba 44fbbeafc9 Small tweak to generate_castle_moves()
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>
2011-01-07 16:57:14 +01:00
Marco Costalba 57b3ca916f Unify move generation
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>
2011-01-07 16:56:42 +01:00
Marco Costalba 12f4bbc8f2 Templetize move generation API
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-07 14:46:29 +01:00
Marco Costalba 1e7aaed8bc Retire move.cpp
Move its functions where they belong.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-07 13:40:13 +01:00
Marco Costalba a46b53e1c2 Use 16 bits to store a move instead of 17
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>
2011-01-07 12:13:05 +01:00
Marco Costalba dcbc8a7e75 Use a 32 bit bitwise 'and' in SimpleHash lookup
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>
2011-01-07 11:25:13 +01:00
Marco Costalba 0ddf84870a Introduce SimpleHash class
And use it for pawns and material infos.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-07 11:20:49 +01:00
Marco Costalba 803c8e0be3 Small tidy up of inttypes for Windows
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>
2011-01-06 23:28:06 +01:00
Joona Kiiski fca74b1882 Simplify 50 move rule condition
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>
2011-01-06 14:46:49 +01:00
Joona Kiiski b08ba446f6 Clean up position setup code
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-06 13:54:03 +01:00
Joona Kiiski 1a20d72701 Parse halfmove clock and fullmove number from FEN
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-06 13:44:11 +01:00
Joona Kiiski 916c0cbfbc Minimal restructuring of value.h
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-06 13:36:02 +01:00
Marco Costalba 2e46db4369 Do not make any assumption on the move in move_is_legal()
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>
2011-01-06 13:33:40 +01:00
Marco Costalba 5fc8f86a4f Change move_is_ok() and square_is_ok() in something useful
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>
2011-01-06 10:55:48 +01:00
Marco Costalba c14dae1fa2 Improve update_killers() signature
Will be used by future patches and is cleaner.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-06 09:09:53 +01:00
Joona Kiiski d4ded09e17 Fix variable naming in prototypes at uci.cpp
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-05 23:41:08 +01:00
Joona Kiiski 631fa6a100 Remove a false comment
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-05 23:38:33 +01:00
Marco Costalba dadf6a6fe9 Set moveCount base to 1 as in search()
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>
2011-01-05 23:19:12 +01:00
Marco Costalba 6a5dc14251 Use killers also in root_search()
After 4238 games
Mod-Orig 800 - 686 - 2752 +9 ELO

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-05 23:17:28 +01:00
Marco Costalba 55b16593a4 Perft should return an int64_t not an int
Found by Louis Zulli with his super fast
hardware: 65M nodes/sec at perft !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-05 21:13:21 +01:00
Marco Costalba 7614501362 Fix POPCNT support for Intel compiler under Windows
Reported by Martin Wyngaarden that also confirmed
this patch to work.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-05 21:12:19 +01:00
Marco Costalba 22ca7a601f Esplicitly inline generate_piece_moves() & friends
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>
2011-01-05 09:59:20 +01:00
Marco Costalba 97212bafc9 Use 'moveCount' name also in RootSearch
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-04 11:35:54 +01:00
Marco Costalba 07fcc8076d Use -O3 instead of -fast for Linux icc
Reported by Heinz and confirmed by Joona to increase
the speed of 6% !

No change for icc on OSX

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-04 11:12:43 +01:00
Marco Costalba be5b32bb9c Another round of bitboard.cpp cleanups
Also renamed StepAttackBB[] in NonSlidingAttacksBB[]

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-04 11:12:31 +01:00
Marco Costalba 9da1f45b1d Restore development version
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-04 09:55:42 +01:00
Marco Costalba 096351d1f5 Stockfish 2.0.1
Always same siganture: 7224363

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-04 08:24:05 +01:00
Marco Costalba 6b96e6f33d Update Readme and polyglot files
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-03 23:55:12 +01:00
Marco Costalba f200f3ccd2 Another attempt at fixing Chess960
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>
2011-01-03 22:50:38 +01:00
Marco Costalba 2bb555025f Revert Chess960 fix
Will be substituted by a better next patch.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-03 22:48:08 +01:00
Tord Romstad d5f2e32b5c Reintroduce the old "trapped bishop in the corner" evaluation term
for Chess960 games.

After 1918 games at 30"
Mod - Orig: 1052-866 (+532,-346,=1040), Elo +33.8
2011-01-03 22:32:57 +01:00
Joona Kiiski 83d8d54216 Use simple macro to enable operators
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-03 22:27:17 +01:00
Marco Costalba 078354060e Workaround broken function-style cast support in HP-UX
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>
2011-01-03 11:36:32 +01:00
Marco Costalba 5973e09854 Readd SRWLOCK and Condition Variables under Windows
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>
2011-01-03 10:49:33 +01:00
Marco Costalba 22ede4442c Fix Chess960 regression
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>
2011-01-03 00:41:39 +01:00
Marco Costalba deee18c758 Another (final?) attempt at squares_delta()
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>
2011-01-02 11:52:51 +01:00
Marco Costalba 0693ff178e Fix old Glaurung bug related to search logging
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>
2011-01-02 11:22:41 +01:00
Marco Costalba 57c51dd1ef Simplify squares_delta()
And rename in ray_direction()

Patch from UncombedCoconut.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-02 10:59:08 +01:00
Marco Costalba f902ddaa89 Fix a crash on multi-pv
Bug reported by Tobias Haspel and fixed by Joona.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-01 23:10:37 +01:00
Marco Costalba 24485df3df Restore development version
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>
2011-01-01 16:19:08 +01:00
Marco Costalba aa2de53a83 Stockfish 2.0 (take 2)
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>
2011-01-01 16:10:30 +01:00
Marco Costalba f826923f8e Don't use SRWLOCK and Condition Variables under Windows
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>
2011-01-01 16:07:32 +01:00
Marco Costalba 3201a43460 Fix an off-by-one bug in sort_multipv()
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>
2011-01-01 16:07:30 +01:00
Marco Costalba 5405efabcb Remove artificial Iteration >= 3 constraint on time manager
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>
2011-01-01 16:07:29 +01:00
Marco Costalba 6df86fc9da Fix: Honour UCI "quit" command while still in the book
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>
2011-01-01 16:07:28 +01:00
Marco Costalba 7315001f37 Simplify "ponderhit" handling
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>
2011-01-01 16:07:26 +01:00
Marco Costalba 191662a159 Retire ponderhit()
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>
2011-01-01 16:07:25 +01:00
Marco Costalba a01df59f5e Restore development version
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>
2011-01-01 12:30:03 +01:00
Marco Costalba 9f3c7ded5c Stockfish 2.0
stockfish bench signature is: 7224363

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2011-01-01 11:47:34 +01:00
Marco Costalba df73af30dd Send correct searched nodes statistic
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-31 19:47:17 +01:00
Marco Costalba 9394db765f Remove dubious castle detector
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>
2010-12-31 14:32:25 +01:00
Marco Costalba 4d6258bb32 Implement "seldepth" UCI info
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>
2010-12-31 14:27:24 +01:00
Marco Costalba 3e8bb6f63d Retire a couple of unused debug functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-30 16:44:10 +01:00
Marco Costalba 3835f49aa1 Leave threads go to sleep when waiting for a ponderhit
No need to heat up CPU in this case ;-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-30 16:18:22 +01:00
Marco Costalba 8e75384dd2 Move printing of best move on think
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>
2010-12-30 16:12:51 +01:00
Marco Costalba db4a68a99b Unify single and multi PV 'new best move' handling
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-30 14:03:08 +01:00
Marco Costalba f803f33e63 Move print_pv_info() under RootMove
And rename to pv_info_to_uci()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-30 12:27:59 +01:00
Marco Costalba 6f2e4c006c Better document value_to_uci()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-30 11:46:53 +01:00
Marco Costalba afe0203f98 Standardize root_search() signature
Now pass alpha and beta by copy as in serach()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-30 10:54:33 +01:00
Marco Costalba b01e5fc612 Move extract_pv_from_tt() and insert_pv_in_tt() under RootMove
Functional change only due to additional do/undo move
but absolutly harmless.

Also handle re-insertion in tt of PV lines also for multi PV case.
2010-12-29 15:24:40 +01:00
Marco Costalba d2a4aac53d Use rml[0].pv[] instead of dedicated pv[] array
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.
2010-12-29 09:22:30 +01:00
Marco Costalba 58c6e64069 Last small touches in RootMoveList
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-28 23:10:21 +01:00
Marco Costalba 3346ccc9d9 Retire LMR intermediate research
It does not seem to improve anything.

After 8344 games Mod - Orig:
1362 - 1321 - 5661 ELO +2

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-28 18:51:08 +01:00
Marco Costalba 0007b43a91 Use insertion_sort() in RootMoveList
Simplify code and get a bit of extra speed, about +0.5%

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-28 18:36:34 +01:00
Marco Costalba 6235904898 Redefine MoveStack comparison as the natural one
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>
2010-12-28 13:06:53 +01:00
Marco Costalba 5b08494312 Fix broken last patch series
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>
2010-12-28 13:01:14 +01:00
Marco Costalba 30c14fdc95 Speedup moves root list sorting
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>
2010-12-27 13:55:34 +01:00
Marco Costalba e8b5420300 Use a std::vector to store root moves
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-27 13:10:32 +01:00
Marco Costalba 12eb27b6e9 Rename RootMoveList members removing 'move'
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>
2010-12-27 11:36:57 +01:00
Marco Costalba e7ab3a0d16 Retire DirectionTable[]
With this patch even word 'direction' is disappeared !

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-27 03:08:10 +01:00
Marco Costalba 4dded4e72f Retire direction.cpp
Move the code to bitboard.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-26 16:51:21 +01:00
Marco Costalba cb7f20913e Retire enum Direction
Use SquareDelta instead

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-26 16:17:51 +01:00
Marco Costalba f08a6eed0d Retire SignedDirectionTable[] and RayBB[]
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>
2010-12-26 12:12:58 +01:00
Marco Costalba 6080fecf9c Retire direction.h
Move all to square.h

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-26 10:58:52 +01:00
Marco Costalba 94a67c49b0 Simplify enum SquareDelta definition
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-26 10:43:22 +01:00
Marco Costalba 0a73a23dc9 Unify MovePicker c'tor call
And use the standard one.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-25 18:03:43 +01:00
Marco Costalba a0f0a7dc4f Use generate_moves() in san.cpp
Instead of MovePicker and cleanup san.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-25 17:54:08 +01:00
Marco Costalba 61c03b9d22 Ignore two braindamaged remarks under icc
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>
2010-12-25 09:16:30 +01:00
Marco Costalba dee8780829 Renamed thread_should_stop() in cutoff_at_splitpoint()
It is more clear what happened.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-25 00:11:53 +01:00
Marco Costalba d40a12f948 Simplify a condition in update of best move
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-24 17:09:39 +01:00
Marco Costalba f97c5b6909 Triviality in struct PieceLetters
And little touches in search() too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-24 16:58:25 +01:00
Marco Costalba d55a5a4d81 Better clarify how we use TT depth in qsearch
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>
2010-12-18 11:19:31 +01:00
Marco Costalba 201e8d5f87 Second cleanup wave on check_is_useless()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-18 10:20:15 +01:00
Joona Kiiski 47f5560e2d Let check_is_useless() follow SF coding style
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-14 18:57:22 +01:00
Tord Romstad cf85ffbb97 Fixed a bug in move_from_uci(): En passant captures were not handled
correctly.
2010-12-14 12:07:37 +01:00
Joona Kiiski 6596dc9516 Selective checks at qsearch
After 5821 games
Mod- Orig:  1014 - 869 - 3938 ELO +8 (+- 3.6) LOS 97%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-14 07:50:37 +01:00
Marco Costalba 6afcfd00f2 Retire uci_main_loop()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-13 20:38:41 +01:00
Marco Costalba 2d63f2157e Small cleanup in uci.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-13 20:29:40 +01:00
Marco Costalba 56de5ae561 Retire square_from_string()
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>
2010-12-13 20:29:38 +01:00
Marco Costalba 556b63b6b6 Move the last multi-threads globals to ThreadsManager
Also rename ThreadsManager memeber data to be lower case.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-13 07:30:59 +01:00
Marco Costalba 4ad03c9bad Further reduce sleep lock contention
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>
2010-12-13 07:30:59 +01:00
Marco Costalba dedc6d7588 Allow threads to sleep when available
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>
2010-12-11 09:22:38 +01:00
Marco Costalba 38e7ec3e44 Increase MAX_THREADS to 16
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>
2010-12-10 07:24:48 +01:00
Marco Costalba 421f7b74c6 Increase PV LMR to SF 1.8 levels
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>
2010-12-07 13:13:06 +01:00
Marco Costalba 0da461f23b Various cleanups in Position's ancillary functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-06 18:01:18 +01:00
Marco Costalba 97a6e1559e Fix a crash due to a broken Book::open()
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>
2010-12-05 09:24:18 +01:00
Joona Kiiski 8a858aea34 New try for unstoppable pawn evaluation
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>
2010-12-04 09:07:45 +01:00
Marco Costalba 03dd1d3c13 Allow razoring after a null move
After 8322 games on Russian Cluster
Mod- Orig:  1341 - 1281 - 5700 ELO +2 (+- 3) LOS 75%

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-12-04 09:04:54 +01:00
Joona Kiiski 5529706426 Prune all negative see moves at low depths
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>
2010-12-02 07:42:18 +01:00
Marco Costalba 6ed409ecee Fix bestmove output in multi PV case
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>
2010-11-28 17:05:49 +01:00
Marco Costalba 200fc56e9c Fix 'generation' type to uint8_t
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>
2010-11-28 17:01:01 +01:00
Marco Costalba d0dc05ad41 Revert sleeping threads
Revert 141caf1d5b + c59efc53c9

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-27 21:26:00 +01:00
Marco Costalba 9ecdfd2401 Revert "Allow split point master to sleep (take 2)"
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-27 21:25:59 +01:00
Marco Costalba 5d6b2f2144 We don't need a stringstream in buildKey()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-23 13:01:11 +01:00
Marco Costalba efeb37c33f Retire Application class
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>
2010-11-22 18:36:18 +01:00
Marco Costalba 00d9fe8af0 Retire piece.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-22 13:13:48 +01:00
Marco Costalba 85df24624a UCI options names should not be case sensitive
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>
2010-11-21 23:52:51 +01:00
Marco Costalba f44aea7508 Retire "New Game" UCI option
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>
2010-11-21 14:25:30 +01:00
Marco Costalba fa80479b1d Remove hardcoded 16 from benchmark default positions size
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-21 13:06:53 +01:00
Marco Costalba df6ba1fa5c Micro-optimize pl_move_is_legal()
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>
2010-11-21 12:49:16 +01:00
Marco Costalba f57d51b7f3 Store "true" and "false" in bool options
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>
2010-11-20 18:06:38 +01:00
Marco Costalba 358ccf206b Debug counters don't need to be global
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-20 11:48:04 +01:00
Marco Costalba 24e6ed907b Small touches to engine_name()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-19 23:57:11 +01:00
Marco Costalba bdfd656c24 Use occupied_squares() in book_key()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-16 19:28:09 +01:00
Marco Costalba d08a8d76f7 Rearrange pawn moves generation
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>
2010-11-16 13:43:05 +01:00
Marco Costalba 6f70e762a9 Introduce generate_promotions()
A bit ugly to guarantee no functional change.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-16 13:02:52 +01:00
Marco Costalba b36900ef44 Simplify generate_pawn_captures()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-15 18:58:15 +01:00
Marco Costalba a1c02815cc Cleanup Bioskey()
And rename in dataAvailable()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-15 18:58:00 +01:00
Marco Costalba 660378d10e Let bench to have full defaults arguments
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>
2010-11-09 05:05:08 +01:00
Marco Costalba 9dcc2aad98 Various cleanup in book.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-08 18:51:42 +01:00
Marco Costalba fad595f5b6 Let benchmark to default to depth 12
And also simplify a lot the code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-08 13:53:44 +01:00
Marco Costalba d2d953713f Move PieceValue[] and SlidingArray[] where they belong
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-08 13:18:18 +01:00
Marco Costalba c28b9ef182 Allow split point master to sleep (take 2)
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>
2010-11-07 23:51:09 +01:00
Marco Costalba da6e2b5fd1 Use namespace in position.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 13:51:03 +01:00
Marco Costalba b06f0460a2 Retire uci.h and benchmark.h
Moved the single prototipes where are needed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 13:31:33 +01:00
Marco Costalba d2ad5acddd Object OpeningBook doen't need to be global
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 13:12:48 +01:00
Marco Costalba 4cd53b68d0 Make rkiss seed deterministic
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>
2010-11-07 12:48:23 +01:00
Marco Costalba 8fb16df70e Let rkiss.h to follow SF coding style
Fix also Makefile after mersenne.cpp has been removed

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 12:22:15 +01:00
Marco Costalba f5e28ef512 Use Heinz's RKiss instead of marsenne
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 11:52:59 +01:00
Marco Costalba 287556f97d Fix an off by one bug in print_uci_options()
Last option was not printed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 10:53:31 +01:00
Marco Costalba 469e7c5143 Retire bitbase.h
Moved the only prototipe where is needed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-07 10:53:19 +01:00
Marco Costalba bacb645939 Rewrite options handling in an object oriented fashion
Big rewrite and about 100 lines removed.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-05 06:10:05 +01:00
Marco Costalba fb50e16cdd Retire push_button() and button_was_pressed()
Directly access the underlying bool option.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-03 13:19:55 +01:00
Marco Costalba 9f626725ae Prefer int to uint8_t when possible
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-01 13:17:01 +01:00
Marco Costalba cfca92cd7c Add "mingw" compiler to Makefile
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-11-01 12:17:54 +01:00
Marco Costalba d607febb38 Fix MinGW warnings
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>
2010-11-01 11:44:46 +01:00
Marco Costalba 19cf779629 Allocate RootPosition on the stack
And pass it as an argument.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-31 11:53:49 +01:00
Marco Costalba d74025a34e Update nodes after a do_move()
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>
2010-10-31 11:22:40 +01:00
Marco Costalba 49a6fee4fa Fix some icc's "statement is unreachable" warnings
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-30 19:19:40 +01:00
Marco Costalba 2991ff0dc2 Move moveCount update near the SpNode case
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-30 18:26:41 +01:00
Marco Costalba c416133e2f Introduce and use TranspositionTable::refresh()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-30 15:22:10 +01:00
Marco Costalba ff95bbd41f Use margins[] array in evaluate
It will be used by future patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-30 14:24:19 +01:00
Marco Costalba 2d7a417d0a More readable search/qsearch dispatch
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-30 12:32:38 +01:00
Marco Costalba f790752daa Fix last leak detected by Valgrind
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>
2010-10-24 09:57:30 +01:00
Marco Costalba 5254ca22f3 Fix a memcpy() warning under Valgrind
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>
2010-10-24 09:56:57 +01:00
Marco Costalba 5b445cdf59 Revert previous patch
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>
2010-10-24 09:53:19 +01:00
Marco Costalba 96e589646d Allow split point master to sleep
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>
2010-10-23 13:50:54 +01:00
Marco Costalba c81bf3743f Re-add "Pass evalMargin through SearchStack as eval"
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>
2010-10-23 08:07:26 +01:00
Marco Costalba f6e11ee2a3 Finally retire sp_search()
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>
2010-10-23 07:51:35 +01:00
Marco Costalba 65606bc49e Temporary restore old sp_search()
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>
2010-10-18 08:34:25 +01:00
Marco Costalba 3b7bf34b02 Revert "Pass evalMargin through SearchStack as eval"
Restore full no functional change also in Faked Split mode.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-18 08:19:48 +01:00
Marco Costalba 141caf1d5b Don't wake up /sleep threads in think() anymore
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>
2010-10-17 13:12:58 +01:00
Marco Costalba c59efc53c9 Enable sleeping of available threads
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>
2010-10-17 11:38:00 +01:00
Marco Costalba 8fdc635255 Use fast SRWLOCK locks under Windows
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>
2010-10-17 11:04:52 +01:00
Marco Costalba 472971f851 Remove some ifdef from wake_sleeping_thread()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-17 09:35:44 +01:00
Marco Costalba 389edb8099 Retire put_threads_to_sleep()
Obsoleted by previous patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-17 09:03:39 +01:00
Marco Costalba 13d8231746 Retire THREAD_SLEEPING and use THREAD_AVAILABLE instead
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>
2010-10-17 08:59:07 +01:00
Marco Costalba 9440fb06da Retire AllThreadsShouldSleep flag
It is redundant and complicates the already complicated
SMP code for no reason.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-17 08:39:03 +01:00
Marco Costalba 3a564ed5db Destroy wait conditions before exiting
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>
2010-10-17 07:36:14 +01:00
Marco Costalba 1fdb436e78 Change thread API to use one wait condition per thread
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>
2010-10-17 08:00:42 +01:00
Marco Costalba dcf2edfdea Do not shadow SplitPoint struct with search() parameter
Also retire move_is_killer() is called only from one place.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-16 15:39:07 +01:00
Marco Costalba 85a7456bd7 Fixed some warnings when using -Weffc++ gcc option
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>
2010-10-16 15:00:20 +01:00
Marco Costalba d664773a83 Fix a shadowed variable warning under icc
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-16 15:00:07 +01:00
Marco Costalba f092667460 Retire now obsoleted do_sp_search() trampoline code
We can call search() directly from idle_loop()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-16 12:20:16 +01:00
Marco Costalba 19ff8e2902 Pass evalMargin through SearchStack as eval
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>
2010-10-16 11:54:44 +01:00
Marco Costalba a7f4ee7540 Unify sp_search() and search() step 3
Remove old sp_search() code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-16 11:40:49 +01:00
Marco Costalba f7722d4de7 Unify sp_search() and search() step 2
Modify search() to be able to handle split points

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-16 11:20:43 +01:00
Marco Costalba 37055ad002 Unify sp_search() and search() step 1
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>
2010-10-16 09:49:45 +01:00
Marco Costalba 79a7647fe0 Pass moveCount by value in split()
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>
2010-10-12 12:33:44 +01:00
Marco Costalba 00950fec00 Sync sp_search() with search()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-12 12:19:47 +01:00
Marco Costalba 7c7a77698a Better document some threads functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-12 12:11:20 +01:00
Marco Costalba 083ed1ce94 Document an assert in idle_loop()
Thanks to Bruno Causse for the clarification.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-11 19:56:35 +01:00
Marco Costalba 2feeb206ff Use VALUE_DRAW instead of VALUE_ZERO where better
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-10 09:05:46 +01:00
Marco Costalba 5dfbbb79be Use do_move_bb() in move_attacks_square()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-10 08:32:12 +01:00
Marco Costalba d440ddb487 Another cleanup in evaluate_pawns()
Suggested by Marek Kwiatkowski.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-10 08:32:03 +01:00
Marco Costalba 9c9914d72a Micro optimize open files calculation
Committed mostly because is also a cleanup...

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-09 15:22:00 +01:00
Marco Costalba a0474a72a6 Rearrange pawn penalities arrays
A clean up that is also a prerequisite for next patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-09 13:43:43 +01:00
Marco Costalba 7733dadfd7 Small codestyle touches
Mostly suggested by Justin (UncombedCoconut), the 0ULL -> 0 conversion
is mine.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-09 13:05:58 +01:00
Marco Costalba 9ca4359f36 Properly set to zero stuff returned by 'new'
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>
2010-10-07 03:57:33 +01:00
Marco Costalba f00c976bb2 Retire updateKingTables[]
Suggested by Marek Kwiatkowski.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-06 19:28:27 +01:00
Marco Costalba 1bbbc13b46 Skip ei.kingZone[] initialization together with king safety
Another microptimization by Marek Kwiatkowski.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-05 22:32:53 +01:00
Marco Costalba 1ee1d852fe Skip an useless compare in space evaluation
Spotted by Marek Kwiatkowski.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-05 22:16:09 +01:00
Marco Costalba 812e843939 Restore development version
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-05 19:40:49 +01:00
Marco Costalba 71e14bb67b Stockfish 1.9.1
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>
2010-10-05 12:00:24 +01:00
Marco Costalba 66a64406ca Fix broken chess960 under Shredder GUI
We need to add a dummy option anyway to make GUIs happy.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-05 12:00:16 +01:00
Marco Costalba d4876dc963 Rewrite bit counting functions
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>
2010-10-04 18:40:44 +01:00
Marco Costalba 3249777cdb Remove -pedantic option
Breaks current POPCNT code.

Perhaps we will readd with a proper fix...

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-03 14:43:17 +01:00
Marco Costalba 544adf7e41 Use special handling for promotions in move_is_legal()
Simplifies a bit the code and the common case too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-03 11:15:53 +01:00
Marco Costalba 98b09b4038 Fix an obsoleted NO_PIECE_TYPE in a comment
Spotted by Ralph Stoesser.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-02 18:57:46 +01:00
Marco Costalba 0aeba002c8 Restore development version
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-02 14:36:43 +01:00
Marco Costalba 247c2cd207 Increase warning level
Both under gcc and icc: sf compiles with no warnings !

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-02 14:32:43 +01:00
Marco Costalba 46c16ab783 Stockfish 1.9
Signature is:

stockfish bench 128 1 12 default depth

Node counts: 10914593

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-10-02 09:55:10 +01:00
Joona Kiiski 3fd0079807 Less aggressive move count based futility pruning
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>
2010-09-26 10:27:15 +01:00
Marco Costalba a28f4a56d3 Fix handling of 50 move rule and remove a fixme
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-25 11:24:20 +01:00
Marco Costalba 7305b56957 Shrink OutpostBonus[] definition
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-25 11:12:55 +01:00
Marco Costalba 045beac156 Simplify scale factors implementation
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-24 12:56:45 +01:00
Marco Costalba 0e3535ea23 Rename no_mob_area in mobilityArea
It is the correct name.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-24 12:56:38 +01:00
Marco Costalba c254861ee6 Small code style in qsearch
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-21 20:04:15 +01:00
Marco Costalba c1558dde12 Do not update killers in qsearch
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>
2010-09-21 06:25:47 +01:00
Marco Costalba 9d1522b24f A king move can never have negative SEE
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>
2010-09-19 13:56:50 +01:00
Marco Costalba 23fd379694 Simplify SEE
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>
2010-09-19 13:41:54 +01:00
Marco Costalba 9ab0e1bb13 Retire NullMoveMargin
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>
2010-09-16 08:22:39 +01:00
Marco Costalba debc815352 We need just one eval margin in search
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-14 18:06:10 +01:00
Marco Costalba dd8a076128 Reintroduce rook contact checks
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>
2010-09-14 13:48:26 +01:00
Marco Costalba 4350d9e8a6 Fix a warning under icc
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-14 07:56:02 +01:00
Marco Costalba 42ed488987 Retire badCaptures[] array in MovePicker
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>
2010-09-13 13:22:00 +01:00
Marco Costalba 4143d00011 Increase QueenContactCheckBonus
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>
2010-09-13 00:10:48 +01:00
Marco Costalba 1a2768705a Do not update king tables when we skip king safety
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-12 14:28:07 +01:00
Joona Kiiski fa2478a81f Retire pawn storm evaluation
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>
2010-09-11 09:46:00 +01:00
Marco Costalba 5b5b496a6d Array FutilityMarginsMatrix stores Values
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-09-04 14:10:48 +01:00
Marco Costalba 6096ca7a95 Remove get_* prefix from RootMoveList API
And small additional cleanup in RootMoveList.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-30 12:56:12 +01:00
Marco Costalba 427dc2a82c Use only cumulativeNodes in RootMoveList
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>
2010-08-30 12:56:04 +01:00
Marco Costalba b177e6dd91 Use evaluation margins also in main search
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>
2010-08-28 12:07:15 +01:00
Marco Costalba d9dc9dbd65 Split branches in generate_piece_moves()
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>
2010-08-27 13:28:07 +01:00
Marco Costalba 2a2353aac6 Speed up updateShelter()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 18:52:53 +02:00
Marco Costalba 1b4084b4a5 Assorted code style in evaluation.cpp
Renaming, cleanu up, etc.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:47:38 +01:00
Marco Costalba c7dd9b8d0c Finally remove value from EvalInfo
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:47:29 +01:00
Marco Costalba 9ee42d83b6 Remove dependency from ei.value in evaluate functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:41:28 +01:00
Marco Costalba 3107e68c03 Remove margin[] from EvalInfo
Directly pass arguments to king evaluation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:41:28 +01:00
Marco Costalba d4250c52f0 Remove MaterialInfo* from EvalInfo
Use a local variable instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:41:27 +01:00
Marco Costalba 15d265cc66 Change evaluate() signature
Hide EvalInfo and return just the score and the margin.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:41:26 +01:00
Marco Costalba fff59319b0 Retire attackedBy[] access functions
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>
2010-08-26 13:41:26 +01:00
Marco Costalba b196af4dcd Decrypt some magics in bitboards definitions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-26 13:41:25 +01:00
Marco Costalba eb4858256b We don't need EvalInfo c'tor anymore
We know always get complete info from TT, so this
code is obsolete.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-25 00:20:53 +01:00
Marco Costalba c7a932bc74 Rename ei.kingDanger in ei.margin
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>
2010-08-24 19:16:03 +01:00
Marco Costalba 00469d1798 Call apply_weight() only once in passed pawns evaluation
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>
2010-08-24 19:13:13 +01:00
Marco Costalba 17d820e248 Don't need to memset() EvalInfo
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>
2010-08-24 18:58:51 +01:00
Marco Costalba d73eea3f71 There is no need of storing mobility in EvalInfo
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-24 18:55:40 +01:00
Marco Costalba 74033b004e Refresh comments in evaluate.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-24 18:55:31 +01:00
Marco Costalba 6125966da0 Unify single MobilityBonus[] tables in a big single one
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>
2010-08-24 13:34:41 +01:00
Marco Costalba 421867ea2d Retire trapped bishop evaluation
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>
2010-08-24 13:13:20 +01:00
Marco Costalba e17fa64aec Retire UCI_Chess960 option
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>
2010-08-22 16:51:20 +01:00
Marco Costalba 7b721b3663 Prefetch pawn hash key
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>
2010-08-22 14:04:06 +01:00
Marco Costalba b6ba5f7fe4 Retire unstoppable pawns evaluation
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>
2010-08-22 01:39:31 +01:00
Marco Costalba 73f1179d39 Remove my address from README
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-21 17:21:44 +01:00
Marco Costalba 0363b54358 Retire beta counters stuff
Is now obsoleted by previous patch.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-20 18:33:19 +01:00
Joona Kiiski a44f79141e Use MovePicker's move ordering also at root
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>
2010-08-20 18:04:02 +01:00
Marco Costalba 79a28841f9 Move StartPositionFEN out of the header
It is not needed to have global visibility.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 18:22:48 +01:00
Marco Costalba df4b106716 Move piece values in piece.h / piece.cpp
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>
2010-08-19 18:22:48 +01:00
Marco Costalba a952c6bc6d Retire is_upper_bound() and friend
Directly expand in the few places where is called.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 18:22:47 +01:00
Marco Costalba 391e176274 Retire useless piece_value_midgame() overloads
Directly access the table in the few call places.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 18:22:46 +01:00
Marco Costalba 5bed82cd4e Introduce and use SCORE_ZERO
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 18:22:46 +01:00
Marco Costalba 4419924fcf Do not score PH_QCHECKS
They are picked unsorted anyway, so score is unuseful.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 14:50:02 +01:00
Marco Costalba a5ae7fe260 Disable templetized operators by default
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>
2010-08-19 13:48:41 +01:00
Marco Costalba 94b9c65e09 Introduce enum VALUE_ZERO instead of Value(0)
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 13:48:38 +01:00
Marco Costalba 0e800c527a Use Use templetized operations for Score and Value
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>
2010-08-19 13:48:37 +01:00
Marco Costalba 13bd0cff0d Use templetized operations for Piece
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 13:48:35 +01:00
Marco Costalba 8e31764c49 Use templetized operations for Square
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>
2010-08-19 13:48:33 +01:00
Marco Costalba 4ce08482c3 Use templetized operations for File and Rank
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>
2010-08-19 13:48:30 +01:00
Marco Costalba 80bee85d5f Use templetize enum operations for Depth
Instead of hardcoded ones.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 13:48:28 +01:00
Marco Costalba 4f96f420a3 Store in TT with depth == -OnePly instead of -1
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>
2010-08-19 13:48:26 +01:00
Marco Costalba 4f28e19fc0 (Re)introduce DEPTH_ZERO to replace Depth(0)
No functional changes.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 13:48:24 +01:00
Marco Costalba ea2b8a93eb Retire some unused Depth operator() functions
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 13:48:23 +01:00
Marco Costalba 4aeffc8c9a Rename OnePly in ONE_PLY
Use enum values standard naming policy also for this one.

No fuctional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-19 13:48:20 +01:00
Marco Costalba cfb52fcd5d Define OnePly as a Depth enum costant
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>
2010-08-19 13:48:11 +01:00
Marco Costalba cf4c28ff86 Revert F_90 and F_92
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>
2010-08-18 10:07:28 +01:00
Marco Costalba 252537fd9c Cleanup and optimize Position::has_mate_threat()
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>
2010-08-09 12:30:33 +01:00
Marco Costalba f26e0fec64 Usual material.cpp small touches
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-08 13:14:18 +01:00
Marco Costalba e6376d9b8d Rename constants to use *_NONE scheme
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>
2010-08-07 18:56:24 +01:00
Marco Costalba 2170fa18bf Move depth computation out of fail low loop
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>
2010-08-06 22:30:50 +01:00
Marco Costalba be540b6dd7 Another push to perft speed
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>
2010-08-06 12:10:07 +01:00
Marco Costalba 3a2cd37080 Faster perft
Skip moves scoring and sorting: this more then
doubles the speed !

Verified is correct.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-06 11:15:41 +01:00
Marco Costalba d6904157aa Rename TM in ThreadsMgr
This avoid misunderstandings with new TimeManager
object called TimeMgr.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-03 13:06:56 +01:00
Marco Costalba 5fc98745c3 TimeManager API rename
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>
2010-08-03 11:49:28 +01:00
Marco Costalba c295599e4a Move time related global variables under TimeManager
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>
2010-08-03 11:47:52 +01:00
Marco Costalba dda53e831d Introduce TimeManager class
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>
2010-08-03 11:39:42 +01:00
Marco Costalba 977f6349a9 Small cleanup in search Step.5
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-02 22:09:20 +01:00
Marco Costalba 5aef9186ac Reset bestMove before entering main moves loop
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>
2010-08-02 22:02:59 +01:00
Marco Costalba cbcc581a86 Use past SE information also for success cases
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>
2010-08-02 18:47:27 +01:00
Marco Costalba fe23c70cf1 Rename MaxSearchTime and AbsoluteMaxSearchTime
Renamed in OptimumSearchTime and MaximumSearchTime,
should be more clear now.

Suggested by Joona.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-02 18:41:55 +01:00
Marco Costalba cf0295f1ad Templetize xxx_time_for_MTG()
Also fixed some warnings under MSVC.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-02 11:55:45 +01:00
Marco Costalba 391cd57b52 Little timeman.cpp massage
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-02 11:49:49 +01:00
Joona Kiiski f40e481fd6 Tweak default values for ucioptions
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>
2010-08-02 11:49:31 +01:00
Joona Kiiski c0616d773d New Time management system
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-08-02 11:48:03 +01:00
Marco Costalba 87139d018c Always use ss->bestMove to store ply best move
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>
2010-07-31 07:29:29 +01:00
Marco Costalba 9645e8e4e7 Lower SingularExtensionDepth to 7 plies for non-pv
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>
2010-07-30 22:50:03 +01:00
Marco Costalba 935fc09fd4 Two small fixes in passed pawns evaluation
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>
2010-07-26 06:10:01 +01:00
Marco Costalba 5ee7dfebf7 Fix KBNK endgame
Broken by recent patch. Also better document what's
happening there.

Verified to restore original behaviour.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-25 21:58:09 +01:00
Marco Costalba 6b6f3c4ca4 Rename EMPTY in NO_PIECE
It is more correct and more in line with enum PieceType

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-25 12:10:22 +01:00
Marco Costalba 14f059072a Introduce enum SquareColor
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>
2010-07-25 11:49:58 +01:00
Marco Costalba 9b1d5bd534 Introduce and use same_color_squares()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-25 11:49:32 +01:00
Marco Costalba a84e4b2049 Cleanup Position::print()
And remove not used OUTSIDE enum Piece.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-25 09:57:57 +01:00
Joona Kiiski 4d438fae9e Fix build failure on GCC
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-25 08:57:23 +01:00
Marco Costalba 02882dfe81 Cleanup Position::to_fen()
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>
2010-07-24 18:56:07 +01:00
Marco Costalba c2048136ec Last touches to from_fen()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-24 16:31:12 +01:00
Marco Costalba 839088205e Rewrite Position::from_fen()
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>
2010-07-24 09:43:01 +01:00
Joona Kiiski 098ac5e44e Don't initialize psqt-tables when 'ucinewgame' is received
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>
2010-07-23 12:21:54 +01:00
Joona Kiiski d3260ce70f Retire 'Randomness' ucioption
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>
2010-07-23 12:21:46 +01:00
Joona Kiiski 71ba48c4ff Always init pthread locks to NULL
This is the only way to keep Windows and POSIX behaviour in sync,
so better hardcode it.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-23 07:03:39 +01:00
Joona Kiiski 65f8b6dbc0 Remove other locking options
Currently broken and we use pthreads in search.cpp
anyway, so I see no reason to keep these around

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-23 07:03:32 +01:00
Marco Costalba d5520977b9 Retire SearchStack init() and initKillers()
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>
2010-07-23 02:42:27 +01:00
Marco Costalba d004ec924d Fix errouneus reset of ss->threatMove
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>
2010-07-23 02:26:57 +01:00
Marco Costalba 5c3aeae566 Revert previous patch
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>
2010-07-22 18:30:18 +01:00
Marco Costalba 26a8b84417 Weight backward-ness of a pawn
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>
2010-07-22 18:15:16 +01:00
Joona Kiiski 6aef4429fd ValueType needs only 2 bits to be stored in TT
Also update some more TT documentation

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-22 17:51:33 +01:00
Joona Kiiski 23db43e698 Update TT documentation
Update outdated and even misleading documentation.

Also check #include-directives

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-22 17:51:26 +01:00
Marco Costalba 6f6f59ea6a Move insert_pv() and extract_pv() out of TT class
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>
2010-07-21 12:09:09 +01:00
Marco Costalba e2c0b5f995 Store position static score in TT as soon as possible
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>
2010-07-21 12:08:45 +01:00
Marco Costalba 02f96fcf5e Introduce DEPTH_NONE and use it
Also better fix previous patch.

Suggestions by Joona and Ralph.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-20 19:06:09 +01:00
Joona Kiiski 28feb2c6b0 Remove pointless tte->static_value() != VALUE_NONE checks
Now in non-check nodes we are guaranteed to always have static value
in TT Entry.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-20 19:01:10 +01:00
Joona Kiiski ba1a44f216 Store static value and king danger in TT also in TT.insert_pv() method
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-20 19:01:01 +01:00
Marco Costalba 0fb5d7a737 Fix "pass ss->eval to qsearch()" condition
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>
2010-07-19 12:28:33 +01:00
Marco Costalba 201f924d53 Triviality in material.cpp
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-19 12:01:36 +01:00
Marco Costalba 95388a952b Small rewrite of backward pawn test
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-19 07:13:50 +01:00
Joona Kiiski b5178597bd Initialize SearchStack only once at RootMoveList c'tor
Just fix current ugly behaviour :-)

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-19 03:53:37 +01:00
Joona Kiiski b75e68860c Every node is responsible for initializing its own SearchStack entry
More logical than doing partly initialization at init_ss_array()

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-19 03:52:21 +01:00
Joona Kiiski 66c5835080 Drop KILLER_MAX. Hardcode to 2 instead.
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>
2010-07-19 03:51:25 +01:00
Joona Kiiski a6d13428f6 Do not initialize ss->reduction to zero in the beginning of node
It must already be zero because zeroed in SearchStack initialization

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-19 03:48:51 +01:00
Joona Kiiski 1322ab97c7 Do not reset ss->eval in the beginning of the node
This avoids problems with IID clearing ss->eval and
eval not being available when we return

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-19 03:43:58 +01:00
Marco Costalba 6e06db93fd Fix isolated and backward pawns scoring
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>
2010-07-17 17:32:54 +01:00
Marco Costalba 53bbcb78d5 Triviality in endgame.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-17 14:00:25 +01:00
Joona Kiiski a6dcaa575f Update Makefile
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-16 12:04:02 +01:00
Joona Kiiski 05c5442633 Find balance between 1.7 and 1.8 reductions
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>
2010-07-15 20:53:16 +01:00
Marco Costalba b6ab610e2f Remove redundant argument in think()
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>
2010-07-15 17:14:30 +01:00
Marco Costalba a98dee7835 Retire apply_scale_factor() and scale.h
Directly inline in the only occurence.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-15 17:05:23 +01:00
Marco Costalba 3e38e61565 Inline history and gain getters
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-15 16:55:35 +01:00
Marco Costalba bc0c1c8d7b Retire value.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-15 12:16:36 +01:00
Marco Costalba 605b3aedd5 Retire LSN machinery
Now that we use cutechess-cli we can set the auto-resign
parameter that makes LSN less effective.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-14 17:29:36 +01:00
Marco Costalba 8547798345 Triviality in ucioption.cpp
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-14 17:29:34 +01:00
Marco Costalba 3703d12eb9 Add moves from failed high nodes in PV
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>
2010-07-12 21:06:40 +01:00
Marco Costalba a47a7dadeb Fix (zugzwang) verification to be shallower then null search
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>
2010-07-12 21:03:30 +01:00
Joona Kiiski 00e86078a5 Remove TranspositionTable::overwrites variable
Doesn't provide useful information and
can cause slowdown with many Threads.

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-11 22:25:02 +01:00
Marco Costalba 2adbb80b8b Space inflate bitbase.cpp
Also heavy cleanup while there.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-11 12:05:06 +01:00
Marco Costalba ee8cdb1721 There is no need to clear TT at allocation time
Operator new() already returns a zeroed memory.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-11 09:42:04 +01:00
Marco Costalba 82bd61a8fa Revert previous patch
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>
2010-07-10 16:43:05 +01:00
Marco Costalba 87502c0fcb Makefile: default on gcc 32 bits when type 'make'
From Vratko Polak

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-10 12:16:43 +01:00
Marco Costalba aa172032c4 Reword singular extension comments
Should be more stick to original definition (Hsu, Campbell)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-06 17:56:04 +01:00
Joona Kiiski 8689ff7d03 Tweak Makefile a bit
To fix some build problems on debian's
automatic building system.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-06 06:24:58 +01:00
Marco Costalba 04e1ba8aa2 Move SplitPoint array under its thread
And cleanup / rename that part of code.

No functional change also with faked split.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-05 20:55:01 +01:00
Marco Costalba 2dfec0f614 Tweak non-captures scoring
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>
2010-07-04 21:49:23 +01:00
Joona Kiiski e0056c3851 Fix TT documentation
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-04 20:15:09 +01:00
Marco Costalba a5c85d3cfc Reintroduce GCC/ICC rounding hack
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>
2010-07-03 19:05:04 +01:00
Joona Kiiski d0fdc20231 Fix Makefile for HPUX
On hpux there is no prefetch.

Reported by Richard Lloyd

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-03 18:54:34 +01:00
Marco Costalba 1d4e7bbdf5 Fix DIVIDE BY ZERO exception in init_search()
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>
2010-07-03 16:12:20 +01:00
Marco Costalba 3578207974 PSQT access functions can be static
Also renamed history access value in something more
in line with the meaning.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-03 05:49:13 +01:00
Marco Costalba 40ad5194aa Use only history to score non-captures
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>
2010-07-03 05:36:53 +01:00
Marco Costalba f5ef5632ff Restore development version
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-03 05:34:57 +01:00
Marco Costalba 21de03fad7 Revert "Another PSQT tuning round"
At longer TC of 1'+0" patch fails:
Orig - Mod: 841 - 819 (-6 elo!)

Just before the release ;-)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-02 06:55:03 +01:00
Marco Costalba 2d635f7b74 Stockfish 1.8
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-02 06:23:15 +01:00
Marco Costalba b50dc1647f Mark CheckInfo c'tor as explicit
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-01 22:21:09 +01:00
Marco Costalba 971c591be7 Move singleEvasion assignment out of move's loop
We don't need to recheck after every move.

Spotted by Ralph Stoesser.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-07-01 22:18:53 +01:00
Joona Kiiski b24a2dfc72 Another PSQT tuning round
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>
2010-06-29 18:52:51 +01:00
Marco Costalba 4d170725ab Remove a redundant check in passed pawn eval
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>
2010-06-29 18:35:54 +01:00
Marco Costalba aad8c82cf6 Code style triviality in san.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-29 18:33:43 +01:00
Marco Costalba 6c0a37bbf2 Rename TranspositionTable 'writes' in 'overwrites'
Better documents what that variable means.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-29 18:23:45 +01:00
Marco Costalba 5c3ebd1fbf Extract only exact scores to get the PV
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>
2010-06-29 18:23:28 +01:00
Marco Costalba 62c68c2d21 Retire update_pv() and sp_update_pv()
Expand inline instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-26 15:43:54 +01:00
Marco Costalba adb43cc0cc Retire pv[] from SearchStack
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>
2010-06-26 15:13:39 +01:00
Marco Costalba 0a687b2cf0 Introduce bestMove to store PV move
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-26 14:42:44 +01:00
Marco Costalba eb48c54687 Cleanup code that stores score in TT
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-26 11:01:43 +01:00
Joona Kiiski 3c3b129e7b Fix some wrong documentation
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-26 10:23:31 +01:00
Joona Kiiski 918533dc06 Remove unused constant
Fixes warning on ICC

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-26 10:22:26 +01:00
Marco Costalba 0ac44b40c9 Stockfish 1.8 beta 2
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-25 18:56:42 +01:00
Joona Kiiski b839ea6c0c Hack to fix GCC/ICC rounding difference
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-25 18:54:33 +01:00
Marco Costalba 726df58131 Stockfish 1.8 beta 1
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-24 18:00:14 +01:00
Marco Costalba d9a8dd0f7a Revert "Do IID also when we already have a ttMove"
Joona's testing reports very bad results at 5s, 30s and
even 1 minute TC, so revert.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-24 18:00:03 +01:00
Marco Costalba 6776f76d20 Call apply_weight() for both colors in one go
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>
2010-06-24 17:53:01 +01:00
Marco Costalba 74db0f0f40 Tweak unstoppable pawns detection
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>
2010-06-24 17:52:56 +01:00
Marco Costalba a010d438a2 Merge branch 'master' of free2.projectlocker.com:sf 2010-06-21 20:50:20 +01:00
Tord Romstad a4988fecee Moved a misplaced #endif in misc.cpp, which broke compilation in
Mac OS X.

No functional change.
2010-06-21 11:25:06 +02:00
Marco Costalba dc5caff638 Test killer for legality earlier
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>
2010-06-19 17:27:10 +01:00
Marco Costalba 4e7a898d7e Optimize for king moves in see_sign()
Because we only test legal moves, a king move
cannot have negative SEE.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-19 15:58:14 +01:00
Marco Costalba 47ee6d9fa4 Move prefetch() out of TT
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>
2010-06-19 11:10:54 +01:00
Marco Costalba 221f41c2df Extend checks only if SEE is non-negative
Idea from Dr. Hyatt

After 10k games at 5"+0 on my QUAD
Mod vs Orig +2750 =4601 -2649 +4 ELO

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-15 07:02:09 +01:00
Marco Costalba a8b9c11f56 Revert "Use ply counter in Position object"
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>
2010-06-13 02:38:16 +01:00
Marco Costalba e9eea87341 Set LSNTime to 100 ms
This is a timeout compatible with very short TC of 5 sec/game.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-12 10:29:50 +01:00
Marco Costalba a128faf0b0 Remove a wrong FIXME
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>
2010-06-06 00:17:33 +01:00
Marco Costalba ed2754227a Avoid a double copy when saving a TTEntry
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>
2010-06-05 12:35:44 +01:00
Marco Costalba 287b46aa63 Avoid calling evaluate() while razoring
Micro optimization that gives a 0.5% speed improvment

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-05 09:42:16 +02:00
Marco Costalba a04dcce628 Offset pv[] always from 0
We don't need to offset from current ply.

Also rewritten a bit update_pv()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-04 19:41:41 +01:00
Marco Costalba 452f0d1696 Big qsearch() cleanup
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>
2010-06-03 19:15:44 +01:00
Marco Costalba 9337c6da46 Extend intermediate LMR to root search
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>
2010-06-03 12:17:05 +01:00
Marco Costalba 5f3c660d5d Shortcut futility pruning in qsearch
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.
2010-06-03 12:10:57 +01:00
Marco Costalba ab127028ed Do not pass threadID as argument of search() and evaluate()
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>
2010-06-02 20:48:40 +01:00
Marco Costalba 2f6927ac08 Save threadID info in Position
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>
2010-06-02 20:19:43 +01:00
Marco Costalba f148a8f6cc Don't initialize excludedMove and skipNullMove at each node
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>
2010-06-02 19:41:45 +01:00
Marco Costalba c51e12200a Use SearchStack to pass allowNullmove
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>
2010-06-02 13:49:48 +01:00
Marco Costalba 5804bef824 Use SearchStack to pass excludedMove
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-02 13:22:48 +01:00
Marco Costalba 2572055c87 Fix white space breakage
No functional change with faked split.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-02 11:25:02 +01:00
Marco Costalba c6ba14b7c9 Sync sp_search() with main search()
And fix qserahc() dispatch also there.

No functional change tested wit Faked Split.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-02 10:49:34 +01:00
Marco Costalba 5212995563 Retire bitScanReverse32()
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>
2010-06-01 21:58:54 +01:00
Marco Costalba 50e094ef8d Retire ok_to_do_nullmove()
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>
2010-06-01 20:50:08 +01:00
Marco Costalba 7903495b0a Move invariant of singular ext. check out of loop
It is almost always false.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-01 15:47:28 +01:00
Marco Costalba a3819188de Rename ok_to_prune() in connected_threat()
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>
2010-06-01 15:12:31 +01:00
Marco Costalba c0136fb728 Avoid double function dispatch
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>
2010-06-01 14:47:55 +01:00
Marco Costalba 9b17083912 Retire init_node()
Also don't poll in qsearch()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-01 12:34:49 +01:00
Marco Costalba 05c5f08372 Don't init SplitPointStack[i][j].parent
It is already set to zero because is allocated in
the global storage area.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-06-01 07:36:30 +01:00
Marco Costalba 6716337f40 Use ply counter in Position object
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>
2010-05-31 22:03:22 +01:00
Marco Costalba ee8ccac622 Fix SearchStack and ply misalignment in RootMoveList
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>
2010-05-31 18:33:43 +01:00
Marco Costalba e4e12ed595 Convert SearchStack ss[] to SearchStack*
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>
2010-05-31 17:36:16 +01:00
Marco Costalba d81def4fa9 Add function to get ply from position
It will be used by future patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-31 12:10:39 +01:00
Marco Costalba 9446dd6da3 Move gamePly among the StateInfo data
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-31 12:09:18 +01:00
Marco Costalba b7bc0d4c57 Move promotion and ep under pawn handling
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>
2010-05-31 12:08:34 +01:00
Marco Costalba c35c18a705 Thread::splitPoint is a volatile pointer
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-31 06:16:50 +01:00
Marco Costalba 2ea323aec6 Do IID also when we already have a ttMove
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>
2010-05-31 06:15:39 +01:00
Marco Costalba ec0f0eba6b If LMR search fails high research at intemediate depth
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>
2010-05-29 23:35:12 +01:00
Marco Costalba 0719470e50 Fix IIDMargin description
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-29 11:19:53 +01:00
Marco Costalba 3ccdb57d6f Retire zobMaterial[]
Use zobrist[] array to compute material key.

Space save of 2KB in L1 cache.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-29 08:54:15 +01:00
Marco Costalba 03cfd94414 Change zobMaterial[] index 0 definition
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>
2010-05-29 08:49:16 +01:00
Marco Costalba 8c32878701 Use Key type instead of Bitboard
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>
2010-05-29 08:11:36 +01:00
Marco Costalba 0c5e89e3e1 Revert non-linear threats evaluation
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>
2010-05-23 14:53:04 +01:00
Marco Costalba 4a081280ed Remove an useless assert in evaluate_passed_pawns()
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>
2010-05-22 19:14:19 +01:00
Marco Costalba ee9e162dd5 Account for double pawn push in evaluate_unstoppable_pawns()
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>
2010-05-22 18:42:00 +01:00
Marco Costalba 7e82f793b8 Fix StormOpenFileBonus[] bug
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>
2010-05-22 18:35:00 +01:00
Marco Costalba a7bfaede91 Fix a warning on array of size 0 under Windows
And better document new reality.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-22 12:45:05 +01:00
Joona Kiiski 1afbe1a1d7 Drop completely illogical ei.kingDanger == 0 requirement
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-22 12:37:19 +01:00
Joona Kiiski 226bd54064 Always save static value and kingDanger to TT
Around 5% speed-up

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-22 12:37:11 +01:00
Joona Kiiski de0c9e84ca Drop TTClusterSize from 5 to 4
Very small obvious functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-22 12:37:02 +01:00
Marco Costalba 66b751713e Add non-linear threats evaluation
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>
2010-05-22 12:01:51 +01:00
Marco Costalba ecc100d1bb Revert "Simple implementation of strong YBWC"
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>
2010-05-22 11:36:51 +01:00
Joona Kiiski 85559cc597 Add some automatic detection for Windows
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-21 23:09:53 +01:00
Joona Kiiski 187451294f Documentation fix
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-21 06:56:57 +01:00
Joona Kiiski ac4c971e06 Correct 'prefetch' handling for Makefile
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-21 06:56:48 +01:00
Marco Costalba cab8b78846 Let prefetch to be enabled by default on Windows
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>
2010-05-20 21:37:37 +01:00
Joona Kiiski efdd1e697a Small tweaks to install gcc-profile-clean targets
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-20 21:23:00 +01:00
Joona Kiiski 09884756d8 Modify source to follow new Makefile
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-20 21:22:51 +01:00
Joona Kiiski 32590884df Rewrite Makefile
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-20 21:22:42 +01:00
Marco Costalba 977cd9520a Simple implementation of strong YBWC
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>
2010-05-20 21:17:47 +01:00
Marco Costalba 471e745a91 Remove an assert in evaluate_passed_pawns()
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>
2010-05-20 17:48:55 +01:00
Marco Costalba 8dc4396477 Indentation fix in middle-game evaluation
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-17 17:32:31 +01:00
Marco Costalba 6181e01c2a Introduce init_attack_tables() in evaluate()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-17 06:45:59 +01:00
Marco Costalba 0d207ec2c6 Do not consider discovered checks in king safety
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>
2010-05-16 15:37:42 +01:00
Marco Costalba 93f64577c3 Fix RootMove::operator<() description
Reported by Melvin Sprague.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-16 08:56:58 +01:00
Marco Costalba 8b6bcd9731 Remove an useless Max() in passed pawns evaluation
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>
2010-05-16 00:56:05 +01:00
Marco Costalba 6c0b2f5003 Threath tuning results
Final values for threath tuning (after ~30k iterations)

Verified to be equivalent with tuning branch.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-15 21:44:57 +01:00
Marco Costalba 52fd1a3d37 Add support for gcc-profile
It's now possible to build PGO builds with GCC

Patch from Oystein Johansen

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-15 07:51:46 +02:00
Marco Costalba 0c9c5032e8 Rename OutpostMask[] in AttackSpanMask[]
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>
2010-05-14 16:55:35 +01:00
Marco Costalba 9079bab84c Micro optimization in evaluate_pawns()
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>
2010-05-14 12:59:03 +01:00
Marco Costalba ea5af9b8c0 Introduce evaluate_pawn_storm() to unify redundant code
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-14 12:08:48 +01:00
Marco Costalba 0b49ec9822 Code style tweaks to pawns.cpp
Also a small speedup.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-14 12:05:17 +01:00
Marco Costalba 6c27bf1880 Change color argument of square_is_weak()
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>
2010-05-14 11:59:25 +01:00
Marco Costalba da1165ae5d Space inflate marsenne
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-13 21:53:56 +01:00
Marco Costalba 6e5bb3279f Another split() tweak session
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>
2010-05-13 21:53:55 +01:00
Joona Kiiski e63ab4bd03 Document old test result
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-12 17:33:56 +01:00
Joona Kiiski d72e862a5b Remove one hack caused by misunderstanding
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-12 17:33:42 +01:00
Marco Costalba 02fe05cd0d Fix a possible out of range access in previous patch
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-12 12:30:00 +01:00
Marco Costalba 16d6faf479 Retire splitPoint->cpus field
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>
2010-05-12 12:17:01 +01:00
Marco Costalba 2cec7347db Syncing sp_search() and search()
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>
2010-05-12 07:01:50 +01:00
Marco Costalba 1288a5a10a Simplify init_safety()
In this for is also ready to be tuned....to be continued ;-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-11 12:03:32 +01:00
Marco Costalba 7f095b0a36 Greatly simplify weight_option()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-11 11:59:50 +01:00
Marco Costalba 2aa455ce95 Small evaluate_passed_pawns() cleanup
Mainly renamed local variables with sensible names.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-11 07:06:48 +01:00
Marco Costalba c053f0b838 Better integration of faked split
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>
2010-05-11 07:05:31 +01:00
Joona Kiiski 7abe5f12ef Disable fake-mode
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-11 07:05:30 +01:00
Joona Kiiski 253428bb3f Unite sp_search() and sp_search_pv()
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>
2010-05-11 07:05:17 +01:00
Joona Kiiski 36f4fe52f0 Introduce fake-mode for split
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-09 23:06:13 +01:00
Marco Costalba e4ad6a38ee Revert to old prefetch detection logic
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>
2010-05-09 13:05:21 +01:00
Marco Costalba 6c6b6cd1a4 Fix an off-by-one bug in ThreatBonus[] table
We need a retuning anyhow.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-09 11:30:50 +02:00
Joona Kiiski c20a41c9cf Templatize qsearch
No functional change and 2% speed-up on GCC.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 23:32:31 +01:00
Marco Costalba e0e4bdc991 Retire mate threat detection from evaluation
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>
2010-05-08 23:09:40 +01:00
Marco Costalba 35e39a196d Add a comment and a FIXME
And fix indentation too.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 13:36:44 +01:00
Marco Costalba 276513c19f Lookup TT for eval also in PV nodes
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>
2010-05-08 13:12:46 +01:00
Marco Costalba 9643d7524e Fix an obsoleted descrption comment
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 13:06:55 +01:00
Marco Costalba b763b40101 Unify Internal iterative deepening
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 13:00:07 +01:00
Marco Costalba b4870595a5 Templetize extension() function
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 12:41:36 +01:00
Marco Costalba f010685136 Templetize reduction() functions
No functional or speed change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 12:26:34 +01:00
Marco Costalba 91ce930b28 Use enum NodeType instead of opaque true/false
Increase readibility.

No functional and speed change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 11:49:55 +01:00
Joona Kiiski b075d8ca53 Unite search_pv() and search()
A lot of redundant code removed: -182 lines of code

No functional and speed change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-08 11:48:45 +01:00
Marco Costalba c0334c7bac Rename AttackWeight[] in KingAttackWeights[]
Also simplify a bit the code removing useless
named constants.

No functional change.
2010-05-07 12:04:23 +01:00
Marco Costalba 0f712ad4fd Array ThreatBonus[] is initialized at zero by compiler
We don't need to do the job.

No functional change.
2010-05-07 12:04:23 +01:00
Marco Costalba 7488d216fd Properly indent evaluate_king()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-07 12:04:22 +01:00
Marco Costalba b95b1a9705 Rename futilityMargin in kingDanger in EvalInfo
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>
2010-05-07 12:04:22 +01:00
Marco Costalba b14846b6d7 Simplify some obsolete code in king safety
Now that QueenCheckBonus and friends are always > 0
we can remove a bunch of useless 'if' statements.

No functional change.
2010-05-07 12:04:21 +01:00
Marco Costalba 921bd87280 Rename king "safety" to king "danger"
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.
2010-05-07 12:04:21 +01:00
Marco Costalba 569bc75eb8 Evaluation weights cleanup
Use a Weights[] array instead of named variables to
store evaluation weights.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-07 12:04:20 +01:00
Marco Costalba 0544d6c8f7 Set Mate Threat Extension to OnePly
For both PV and non-PV nodes.

After 981 games at 1+0
Mod vs Orig +153 =686 -142 +4 ELO

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-07 12:04:08 +01:00
Marco Costalba fe76787a77 Avoid a call to apply_weight() in evaluate_king()
Precompute scores in SafetyTable[] instead of calculate
them on the fly.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-05 13:56:54 +02:00
Joona Kiiski 8e269d781a Further push the LMR pedal
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>
2010-05-05 12:20:39 +01:00
Marco Costalba df7cd94aee A promotion piece cannot be a king or a pawn
Or any other garbage value bigger then QUEEN.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-05 12:16:16 +01:00
Marco Costalba f16c231bc9 Do not return from idle_loop() with lock held
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>
2010-05-05 12:16:12 +01:00
Marco Costalba b89733b46c Reverse the logic used to detect prefetch
Explicitly search for x86 architecture instead of
excluding the others.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-05-05 12:16:10 +01:00
Marco Costalba 67f611f3eb Allow a static evaluation to overwrite an exsisting entry
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>
2010-05-05 12:15:40 +01:00
Marco Costalba 80f5ca88f6 Do not refresh TT in qsearch
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>
2010-05-02 07:50:19 +01:00
Marco Costalba 8425b2b499 Refresh TT entry after a cut-off to avoid aging
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>
2010-05-01 05:09:55 +01:00
Joona Kiiski a086f34f36 Fix compile error on GCC
Add missing prototype.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-28 12:01:00 +02:00
Marco Costalba 83631c89ce Endgame's apply() method can be 'const'
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-27 06:17:32 +01:00
Marco Costalba bedf80a4c0 Remove an obsolete comment
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-27 06:09:04 +01:00
Marco Costalba cb9399445f Another small material tweak
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>
2010-04-26 18:45:28 +01:00
Marco Costalba fe7e0a425e Cleanup material distribution detectors
No functional change (verified each function)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-26 12:21:22 +01:00
Marco Costalba fb0e19dc8b Do not call exit_threads() in Application d'tor
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>
2010-04-25 10:35:55 +01:00
Marco Costalba e6b5d03cc4 Small passed pawns evaluation cleanup
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>
2010-04-25 09:50:27 +01:00
Marco Costalba b2c1e15698 Simplify a bit futility marging formula
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>
2010-04-23 18:52:22 +01:00
Marco Costalba 11207f7c1f Revert scale factor in pawn evaluation
It simply doesn't seems to work both in direct matches
and in balance tuning.

So revert the idea.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-21 20:35:47 +01:00
Marco Costalba 97f5d19bdc Introduce PawnsQtyTable[] to refine pawn's drawish calculation
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>
2010-04-19 12:24:26 +01:00
Marco Costalba fc89dbcab2 First attempt at tweaking UnpairedPawnsTable[] values
Values by Joona.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-19 06:37:07 +01:00
Marco Costalba 6b7efa0cd1 Introduce scale factor in pawn evaluation
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>
2010-04-19 06:21:13 +01:00
Marco Costalba c23cd4d90a Fix candidate passed pawn definition
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>
2010-04-18 10:09:12 +01:00
Marco Costalba a9fa1fc7f7 Retire Position::pawn_is_passed() and friends
Absolutely no useful at all, just code obfuscation so
use real definition instead.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-18 09:58:57 +01:00
Marco Costalba 1f1ef0897c Introduce table SquaresInFrontMask[2][64]
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>
2010-04-18 09:47:31 +01:00
Marco Costalba a49e4fac98 Better perft integration in benchmark
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>
2010-04-18 09:18:49 +01:00
Marco Costalba 87379c2929 Space inflate bitboard.cpp
This file, somehow, avoided the "space inflate" treatment...until now ;-)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-18 08:58:26 +01:00
Marco Costalba 53b522d95d Convert polyglot.ini to use Linux line ending
Instead of Windows cr/lf

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-17 11:24:25 +01:00
Marco Costalba ef0bbe6e18 Teach polyglot the new "Best Book Move" UCI option
Also turn off log by default as is in UCI case.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-17 11:22:40 +01:00
Marco Costalba 65c2715d9a Revert saving of null search value in TT
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>
2010-04-17 10:57:37 +01:00
Marco Costalba ec0a650dff Don't overwrite exsisting TT with null search value
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>
2010-04-16 05:52:18 +01:00
Joona Kiiski abae3c5678 Prevent the use of nullmove TT value only at verification search
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-16 05:47:31 +01:00
Joona Kiiski f3809f2a18 Introduce NullStatus enum
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-16 05:47:29 +01:00
Joona Kiiski 81ae7cad2d Revert "Introduce "Zugzwang detection" temporary hack for 1.7.1"
This reverts commit f9d3b48ad0.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-16 05:47:28 +01:00
Marco Costalba 94bb1964f6 Add "Best Book Move" UCI option
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>
2010-04-16 05:45:30 +01:00
Joona Kiiski 13431922a3 Fix overflow in init_safety
Also write the code in more clean way

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-14 19:19:11 +01:00
Joona Kiiski 9a3fc4d3fb Fix evasion pruning condition
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>
2010-04-13 20:28:49 +01:00
Marco Costalba a4a0ffce71 Fix some warnings under +w1 HP-UX compile
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>
2010-04-11 17:03:03 +01:00
Marco Costalba e81108a855 Restore development version
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 20:42:31 +01:00
Marco Costalba f967f1a25e Update polyglot.ini
Remove obsolete options and add a few ones.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 20:41:10 +01:00
Marco Costalba 86c2d2fc3b Stockfish 1.7.1
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 16:48:25 +01:00
Marco Costalba f9d3b48ad0 Introduce "Zugzwang detection" temporary hack for 1.7.1
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>
2010-04-10 16:41:40 +01:00
Marco Costalba d720778b2b Revert HT detection
Fall back on 1.6.3 behaviour.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 11:35:30 +01:00
Marco Costalba e2880f9b8e Revert last patch
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>
2010-04-10 11:16:55 +01:00
Marco Costalba 909e3adede Relax TT condition for zugzwang verified null values
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>
2010-04-10 10:48:08 +01:00
Marco Costalba 626b1f8c6a Avoid TT cutoffs at root of null zugzwang verification
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>
2010-04-10 10:35:29 +01:00
Marco Costalba 06a350f1ae Use a flag in TT to track null search values
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>
2010-04-10 10:07:53 +01:00
Marco Costalba a9e9746495 Fix a warning under HP-UX ANSI C++
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>
2010-04-09 07:54:00 +01:00
Marco Costalba a7fcdfd6bf Stockfish 1.7
Signatures are:

./stockfish bench 128 1 12 default depth
8299338

./stockfish bench 128 1 13 default depth
15694903

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-07 13:08:50 +02:00
Tord Romstad 41816b7ced Fix PowerPC and ARM compatibility. 2010-04-06 10:19:09 +02:00
Tord Romstad 13224e1d9d Add -mdynamic-no-pic to CFLAGS when compiling with GCC under OS X.
Without this flag, the __cpuid() function doesn't compile correctly
in 32-bit mode.
2010-04-05 21:47:28 +02:00
Marco Costalba 10c1ae8da0 Fix one gcc 4.4 warning
Properly fix previous warning. Patch from Joona.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-05 20:11:41 +01:00
Marco Costalba 3a62738174 Fix a warning in HT_enabled()
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>
2010-04-05 15:36:06 +01:00
Marco Costalba 84451191f3 Store score in TT when null search fails high
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>
2010-04-04 11:23:18 +01:00
Marco Costalba 2ed3358faf Cleanup pawn storm code
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>
2010-04-02 11:51:39 +01:00
Marco Costalba 08634b06a3 Fix a comment in evaluate.cpp
Function name is wrong.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-02 11:45:12 +01:00
Marco Costalba 0e33fc6fd4 Change poll() signature
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>
2010-03-31 06:43:12 +01:00
Tord Romstad a5a8830e97 Remove several unnecessary UCI options: All king safety options
except "Aggressiveness" and "Cowardice", and "UCI_ShowCurrLine".
No functional change compared to the previous version with the
default settings.
2010-03-30 15:15:01 +02:00
Marco Costalba 2a14123550 Revert LMR reduction based on thinking time
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>
2010-03-28 12:04:41 +01:00
Marco Costalba 8fabd69d4a Small comments tweaks in search.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-28 11:53:30 +01:00
Marco Costalba 1fc88071d1 Sync static null conditions with real one
Almost no functional change, but it seems more
in line with the meaning of static null pruning.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-28 11:53:16 +01:00
Marco Costalba 7dca461927 Silence a couple of warnings
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>
2010-03-23 23:34:31 +01:00
Joona Kiiski 7618ee2df1 Vary reduction aggressiveness as a function of thinking time
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>
2010-03-23 23:29:23 +01:00
Joona Kiiski 661d48c27b Base work for different reduction schemes
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-23 23:25:58 +01:00
Joona Kiiski 42de93ac15 Do not return unproven mate scores from null move search
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>
2010-03-22 07:27:05 +01:00
Marco Costalba 426f55b78d Use fail soft in null search
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>
2010-03-21 15:12:44 +01:00
Marco Costalba b638f6b035 Remove castleRightsMask[] hack
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>
2010-03-20 11:59:22 +01:00
Marco Costalba 3de0bc43a2 Retire Position::fast_copy()
It is never used and could be tricky, so remove it.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-20 11:45:04 +01:00
Marco Costalba 9fc602bae7 Updated copyright year to 2010
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-20 11:27:07 +01:00
Marco Costalba 49c50399fe Fix POPCNT detection gcc compile error
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>
2010-03-17 21:04:56 +01:00
Marco Costalba a4551c59e0 Fix __cpuid() compile error with gcc
Use same __cpuid() signature used under Windows.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-17 13:22:28 +01:00
Marco Costalba c853b87c08 Add hyper-threading detection
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-14 12:52:58 +01:00
Marco Costalba 92bada1a32 Move __cpuid() definition for gcc in types.h
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>
2010-03-14 12:52:56 +01:00
Marco Costalba eaed535c5f Introduce captured_piece()
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>
2010-03-13 11:07:10 +01:00
Marco Costalba 49dfc50b12 Reduce increase progression of aspiration window
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>
2010-03-13 11:05:27 +01:00
Marco Costalba c835ee8853 Use separated research counters in root_search()
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>
2010-03-13 11:00:12 +01:00
Marco Costalba 7ff9678651 Group time management globals initialization
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>
2010-03-13 10:59:03 +01:00
Marco Costalba 4ef068a506 Highlight that alpha and beta could change in root_search()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 18:17:04 +01:00
Marco Costalba f23a9e8f88 Fix a comment and add an assert in root_search()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 17:51:56 +01:00
Marco Costalba cc2a249952 Retire RootMoveNumber and use FirstRootMove instead
It is more clear why we use that global flag.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 17:34:36 +01:00
Joona Kiiski 55f0d6377f Save mateThreat flag in splitPoint and make use of it
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 12:18:03 +01:00
Joona Kiiski aeb664e0ea Document one test result
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 12:17:41 +01:00
Joona Kiiski 8abdb131c8 Synchronize root_search() with other search routines
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 12:14:46 +01:00
Joona Kiiski 43c93cb151 Remove obsolete code snippet from root_search
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-03-06 12:07:37 +01:00
Marco Costalba 8d1d9f7181 Sort again root moves after a fail low
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>
2010-03-06 11:43:31 +01:00
Marco Costalba a303bde26c Additional search.cpp cleanup
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>
2010-03-06 11:14:38 +01:00
Marco Costalba 0f50f10327 Destroy all locks before to exit
And use platform-independent functions
where possible.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-28 23:36:02 +01:00
Marco Costalba 8286e6ded2 We don't need lpThreadId parameter in CreateThread()
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>
2010-02-28 23:36:01 +01:00
Marco Costalba 3a558a3d8b Function init_thread() should return an integer under Windows
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>
2010-02-28 23:36:01 +01:00
Marco Costalba 14dbeb22dd Try bad captures before non-captures
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>
2010-02-28 23:35:51 +01:00
Marco Costalba 68eb7e77f1 Revert previous patch
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>
2010-02-27 17:24:58 +01:00
Marco Costalba 57340c109b Do not wait for sleeping in init_threads()
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>
2010-02-27 13:26:04 +01:00
Marco Costalba 111aa44662 Remove an incorrect assert in wake_sleeping_threads()
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>
2010-02-27 12:01:07 +01:00
Joona Kiiski 29fb389760 Add some commentary
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-26 00:43:19 +01:00
Joona Kiiski 0d292d1a2d Clean up common adjustments
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-26 00:41:40 +01:00
Joona Kiiski 5bb9da9287 Remove "Threat Depth" ucioption
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>
2010-02-26 00:41:31 +01:00
Joona Kiiski 34c7f1387d Cleanup steps 12, 14
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-26 00:39:08 +01:00
Joona Kiiski fc23466236 Clean up step 11
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-26 00:38:34 +01:00
Joona Kiiski 01b228b5e1 Clean steps 8 and 9.
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-26 00:37:56 +01:00
Joona Kiiski 2142be7d7f Clean razoring code (step 6)
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-26 00:37:09 +01:00
Joona Kiiski 3888d14bd4 Synchronize variable listing of 4 different search routines
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>
2010-02-26 00:36:29 +01:00
Joona Kiiski 7bcd97933a Remove current line printing in SMP mode
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>
2010-02-26 00:35:35 +01:00
Joona Kiiski 9d4abbc6eb Synchronize sp_search() with search() part I
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-25 07:30:19 +01:00
Joona Kiiski c3b3dcc31a Rename staticValue to refinedValue
Just to avoid misunderstandings.
True staticValue is available through search stack

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-25 07:30:09 +01:00
Joona Kiiski e6f2d43b8a Fix repetition detection bug
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>
2010-02-24 19:56:48 +01:00
Joona Kiiski 1a03f0b0d3 Synchronize sp_search_pv() with search_pv()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:42:24 +01:00
Joona Kiiski 62f6d39204 Synchronize sp_search() with search() part II
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:41:51 +01:00
Joona Kiiski 936cd5b83d Simplify locking in splitpoint search
One rule: Always lock before picking up a move.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:37:05 +01:00
Joona Kiiski 3c31776a20 Synchronize search_pv() with search take II
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:36:21 +01:00
Joona Kiiski 0980f43ab0 Synchronize search_pv() with search take I
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:34:55 +01:00
Joona Kiiski 9eedc0a463 Search code documentation, take III
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:30:02 +01:00
Joona Kiiski 195b54c312 Search code documentation take II
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:26:05 +01:00
Joona Kiiski 89b4ad6433 Separate razoring from null move
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>
2010-02-24 19:24:10 +01:00
Joona Kiiski 77bb9a94ae Split search() in independent sections
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>
2010-02-24 19:20:26 +01:00
Joona Kiiski 8a78ac84f3 Avoid research in case thread has already been asked to stop
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 19:19:52 +01:00
Joona Kiiski 5c944fb3b4 Add one assert
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 07:28:50 +01:00
Joona Kiiski c974d9ef33 Do not wait for threads falling asleep
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>
2010-02-24 07:27:45 +01:00
Joona Kiiski 12feb5866f Remove unnecessary conditions from if-clauses and replace them with asserts
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-24 07:26:28 +01:00
Joona Kiiski 80810e4951 Fix crash in debug mode
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-23 07:23:03 +01:00
Joona Kiiski c67b9916f1 Fix some races
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>
2010-02-23 07:22:56 +01:00
Joona Kiiski 78c6bb1079 Fix one assert
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-23 07:22:49 +01:00
Joona Kiiski 85e60bfc8e Fix compile errors in debug mode
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-23 07:22:42 +01:00
Marco Costalba 79b57dd4ca Document struct SplitPoint fields constness
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-21 16:10:19 +01:00
Marco Costalba b9537edbb0 Beta is never changed after an sp_search()
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>
2010-02-21 15:32:39 +01:00
Marco Costalba d38f4f61e7 Supress make warning on missing .depend file
This is generated by make itself, so the warning
is useless.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-21 15:18:35 +01:00
Marco Costalba 27c74c5245 Fix an icc warning
remark #1599: declaration hides variable "i" (declared at line 2651)

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-21 15:07:53 +01:00
Marco Costalba 2f2e8a68d8 Code style triviality in split()
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-21 14:05:38 +01:00
Marco Costalba 1ea70dd9dd Fix a warning with POPCNT and MSVC
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>
2010-02-21 13:44:36 +01:00
Marco Costalba 13c096f839 Revert "Recursive lock"
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>
2010-02-20 23:59:47 +01:00
Marco Costalba 2de2b76896 Remove a couple of useless thread_should_stop() calls
We test for it anyway few lines below and even under lock
protection.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-20 23:48:54 +01:00
Marco Costalba 8b99e94562 Revert small state change optimization in idle_loop()
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>
2010-02-20 18:36:07 +01:00
Marco Costalba 512a4e4ff0 Recursive lock all split point's chain
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>
2010-02-20 18:29:53 +01:00
Marco Costalba 2da290d72b Retire per-thread stopRequest flag
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>
2010-02-20 17:52:09 +01:00
Marco Costalba b39a24ecca Use state instead of flags to track threads
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>
2010-02-20 16:57:24 +01:00
Marco Costalba 189a005a0b Rename THREAD_MAX in MAX_THREADS
Also rename idle_thread_exists() in available_thread_exists()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-20 13:38:04 +01:00
Joona Kiiski 7c61b8ad2a Search negative SEE moves in qsearch in PV
After 2704 games on slow single core
mod - orig: 1381 - 1323

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-15 19:15:44 +01:00
Joona Kiiski a093f33154 Use zero null move margin when depth < 4 * OnePly
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>
2010-02-15 19:14:41 +01:00
Marco Costalba 0895f1ac71 Fix another setting of a flag out of lock protection
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>
2010-02-14 16:31:30 +01:00
Marco Costalba b29198354c Rename flag 'stop' in 'stopRequest'
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>
2010-02-14 16:04:53 +01:00
Marco Costalba 40a7ffd53f Reset thread flags to a known state before to exit think()
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>
2010-02-14 15:59:12 +01:00
Marco Costalba 8eae6a95fb Fix 'stop' flag changed out of lock protection
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>
2010-02-14 13:43:26 +01:00
Marco Costalba 2b740f5495 Introduce ThreadsManager class
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>
2010-02-14 12:53:27 +01:00
Marco Costalba fb5ba1d329 Fix compile error under gcc
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-13 13:40:23 +01:00
Marco Costalba 78e494fcbc Ensure function boundaries for threads state changes
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>
2010-02-13 12:40:29 +01:00
Marco Costalba a16415f44d Rename stop_threads() to exit_threads()
More stick to what actually happens.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-13 12:07:13 +01:00
Marco Costalba 8a504d36f9 Be sure threads are woken in wake_sleeping_threads()
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>
2010-02-13 12:02:34 +01:00
Marco Costalba 093dd8fe88 Use Thread c'tor to properly init the struct
This is what c'tors are for.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-13 11:41:34 +01:00
Marco Costalba 6382324afd Add 'sleeping' flag to struct Thread
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>
2010-02-13 11:28:33 +01:00
Marco Costalba cb08413dc4 Allow build on HP-UX 11.X
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>
2010-02-12 06:49:16 +01:00
Marco Costalba 711ef615c7 Fix a couple of new MSVC 2010 warnings
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>
2010-02-10 21:27:44 +01:00
Marco Costalba 74203e181d Retire EvalInfo* in SearchStack
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>
2010-02-08 10:50:17 +01:00
Marco Costalba 97fe0ac777 Small code style triviality
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-07 13:23:00 +01:00
Joona Kiiski 7ae16a193b Implement init_search()
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-07 13:09:03 +01:00
Joona Kiiski 8261f61964 Document lookup tables
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-07 13:08:56 +01:00
Joona Kiiski 6e1cb6e45b Implement futility move count array
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-07 13:08:48 +01:00
Joona Kiiski 4bfa0c429e Implement futility margins matrix
No functinal change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-07 13:08:40 +01:00
Marco Costalba 2e70a2873f Use gain table to order non-captures
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>
2010-02-07 08:55:51 +01:00
Joona Kiiski 9429d2d028 Use posKey instead of pos.get_key() after NonPVIID
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-06 17:40:01 +01:00
Joona Kiiski d44fa46082 Use opening book when pondering
Otherwise we will not use move given by opening book
when we receive 'ponderhit'-command.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-06 17:39:53 +01:00
Marco Costalba c7866a4215 Delay sorting of negative scored non-captures
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>
2010-02-05 18:31:09 +01:00
Joona Kiiski 69644d3f73 Copy 4 SearchStack items in split()
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>
2010-02-05 18:06:41 +01:00
Marco Costalba b0858877ae Remove sorting optimization for many zeroes
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>
2010-02-05 18:04:08 +01:00
Joona Kiiski 321f6d1d19 Give FailLow flag more descriptive name
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-05 15:21:21 +01:00
Joona Kiiski e738fa7d10 Remove Problem variable
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>
2010-02-05 15:21:12 +01:00
Joona Kiiski c5d546e18e Remove unused failHighPly1 flag
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-05 15:21:05 +01:00
Joona Kiiski 8d65fcc0f3 Remove unused FailHigh flag
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-05 15:20:57 +01:00
Joona Kiiski d8e5b8c133 Simplify time management
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>
2010-02-05 15:20:47 +01:00
Marco Costalba 6fe36d13de Be sure negative see evasions are at the bottom
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>
2010-02-05 08:19:39 +01:00
Marco Costalba 337ec0f3d0 Score non-captures only by history
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>
2010-02-05 00:34:17 +01:00
Joona Kiiski 5b1043ee11 Reduction lookup table
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-04 19:09:51 +01:00
Marco Costalba 439aea9ab7 Convert gains to use a piece-to mapping
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>
2010-02-03 19:33:59 +01:00
Marco Costalba 770db27164 Fix a compile error from previous patch
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-02 19:01:24 +01:00
Joona Kiiski 21d32aa7fe Fix indentations
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-02 18:58:00 +01:00
Joona Kiiski 95d33aef9f Retire outdated aspiration search code
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-02 18:57:50 +01:00
Marco Costalba b5a4edd86f Renamed stand pat as 'static null move pruning'
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>
2010-02-02 08:51:54 +01:00
Marco Costalba 35ada63174 Save futilityMargin for both colors
It will be needed by future patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-02-01 20:06:56 +01:00
Marco Costalba 06a695d5b8 Fix duplicated scaling function
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>
2010-02-01 19:33:02 +01:00
Marco Costalba 4b55d3d883 Increase TT size limit to 8 GB
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>
2010-02-01 16:53:10 +01:00
Marco Costalba 8008f78415 Check bounds in set_option_value()
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>
2010-02-01 14:17:37 +01:00
Marco Costalba 3941e4bdb3 Some code style triviality in root search
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-31 11:14:42 +01:00
Marco Costalba d7d2c1b7e3 Add hardware POPCNT support for gcc
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>
2010-01-31 09:39:32 +01:00
Marco Costalba 17502a5659 Revert "Remove pointless gcc flag when generating dependencies"
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>
2010-01-30 10:37:03 +01:00
Marco Costalba e84488ed6b Retire captures pruning
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>
2010-01-30 09:59:28 +01:00
Marco Costalba 252844e899 Avoid search tree explosion in qsearch
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>
2010-01-29 16:47:04 +01:00
Joona Kiiski b651e5334b Correct qsearch() TT save
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-29 11:03:06 +01:00
Marco Costalba bd358533a4 Stricter conditions in main search stand pat
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>
2010-01-29 00:12:03 +01:00
Marco Costalba e4d3a15656 Use float instead of double in reduction parameters
This is faster on 32 bit CPU and precision is enough.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 12:47:48 +01:00
Marco Costalba 1d7a3f26e0 Micro optimize reduction_parameters()
At ply == OnePly (common case) we avoid some useless
floating point computation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 12:39:15 +01:00
Marco Costalba a0005ba45f Avoid to calculate reduction for each move
This is slow because some floating point operation is
involved.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 12:34:28 +01:00
Joona Kiiski bdd61b1744 Remove useless variable 'PostFutilityValueMargin'
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 11:17:59 +01:00
Joona Kiiski 973e574e1f Precalculate FutilityMargins
This way we don't need to copy+paste formula everywhere

No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 11:16:56 +01:00
Joona Kiiski 27393ebae2 Use calculate_reduction() function to simplify code
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 11:15:41 +01:00
Joona Kiiski 3c7eebb48d Bugfix: reduction was not set to zero in full depth search
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 11:15:18 +01:00
Joona Kiiski 548bae80bd Implement calculate_reduction function
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-28 11:14:43 +01:00
Joona Kiiski 2360c8aa2f Standardize set_option function
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>
2010-01-27 20:03:44 +01:00
Joona Kiiski 32bd6e44f0 Do not initialize RootPosition at startup
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>
2010-01-27 20:00:28 +01:00
Marco Costalba c83fd08fd4 Aspiration window rewrite
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>
2010-01-27 19:59:34 +01:00
Marco Costalba 62b43130e2 Be sure we exit while loop with lock held
This fixes an hang introduced by recent locking
rewrite patch.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 19:23:16 +01:00
Joona Kiiski cd112ee8eb Fix capture pruning
We forgot to update bestValue previously

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 18:58:42 +01:00
Marco Costalba bb968fd42a Simplify locking in sp_search and sp_search_pv
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>
2010-01-27 17:58:04 +01:00
Marco Costalba 307909bed8 Temporary revert "captures pruning" due to an assert
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>
2010-01-27 17:57:04 +01:00
Marco Costalba b95ba7b37e Added some FIXME to track needed tests
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>
2010-01-27 11:49:03 +01:00
Marco Costalba f37741cc83 Integrate gains table in History
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>
2010-01-27 11:22:38 +01:00
Marco Costalba 54b3d44194 Introduce update_gains() and refactor some code
No functional change

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 11:09:07 +01:00
Joona Kiiski ea53006a9d Fix some silly bugs
SelectiveDepth was ignored

Test results for the whole futility pruning series:

4CPU:
Orig - Mod: 959 - 1027 (+12 elo)

1CPU:
Orig - Mod: 763 - 830 (+15 elo)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 10:14:20 +01:00
Joona Kiiski 6247f27a05 MaxGain based futility pruning for captures
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 09:57:51 +01:00
Joona Kiiski 5b2fc1e1c0 MaxGain based pruning
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 09:57:41 +01:00
Joona Kiiski 05a8c318b8 Implement post futility pruning
and prevent futility pruning from pruning
castling moves

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 09:57:31 +01:00
Joona Kiiski 22b8dc8c98 Collect MaxGain statistics
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 09:57:24 +01:00
Joona Kiiski cfe59de27d Implement MaxGain table
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 09:57:14 +01:00
Joona Kiiski c43c5fe9e0 Remove pointless gcc flag when generating dependencies
When generating dependencies there is absolutely no point
to pass -msse flag to gcc, so remove it.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-27 09:53:30 +01:00
Joona Kiiski d0daa16769 Remove InfiniteSearch hack
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>
2010-01-27 09:52:47 +01:00
Joona Kiiski 87303d7ed3 Remove last use of uip.eof()
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>
2010-01-27 09:52:15 +01:00
Marco Costalba cf9bf4e58f Reduce lock contention in sp_search_pv()
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>
2010-01-26 12:12:11 +01:00
Marco Costalba 5ca4284027 Fix a possible crash in thread_is_available()
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>
2010-01-25 23:34:21 +01:00
Marco Costalba dac1bcab90 Small split() cleanup
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>
2010-01-25 19:59:33 +01:00
Marco Costalba 81cfd81366 Prune evasions with negative SEE in qsearch
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>
2010-01-25 16:31:56 +01:00
Marco Costalba d844a75d2c Avoid copy a Position to get a move's san notation
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>
2010-01-25 16:22:50 +01:00
Marco Costalba c5e71f5150 Fix a race in idle_loop() exiting
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>
2010-01-25 15:02:06 +01:00
Marco Costalba c5858ff9ae In split() release the lock before slow search stack copy
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>
2010-01-25 14:12:30 +01:00
Marco Costalba 0ff91e16da Do not copy master position in split()
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>
2010-01-25 12:46:08 +01:00
Marco Costalba c2df60048e Use fast_copy() instead of full copy in sp_search
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>
2010-01-25 12:13:16 +01:00
Marco Costalba 84ec1f7331 Better document how Position c'tor works
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>
2010-01-25 12:04:00 +01:00
Marco Costalba b1ac6c69a0 Fix a couple of MSVC casting warnings
Also removed some trailing whitespaces and aligned
indentation to current standard.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-25 11:27:32 +01:00
Marco Costalba 56e09b4cc8 Copy only the search stack tail in split()
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>
2010-01-25 11:11:22 +01:00
Tord Romstad 5ed0a60203 Merge branch 'master' of ssh://free2.projectlocker.com/sf 2010-01-24 16:09:54 +01:00
Tord Romstad 1588a4e846 Fixes a Chess960 bug when playing with more than one search thread.
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().
2010-01-24 16:09:32 +01:00
Marco Costalba 5894c759cd Check for thread creation successful completion
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>
2010-01-24 14:33:51 +01:00
Marco Costalba 3975a2b94f Fix some races in SMP code
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>
2010-01-24 14:30:09 +01:00
Tord Romstad eb6ddd54f1 Make sure we make a move at the end of the search when reaching
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.
2010-01-22 13:42:33 +01:00
Marco Costalba 01ebb3d996 If near beta generate checks at -OnePly
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>
2010-01-21 00:31:01 +01:00
Marco Costalba 285df57a9a Retire LMRPVMoves and LMRNonPVMoves
Are no used anymore.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-20 18:43:29 +01:00
Marco Costalba 806c1d8723 Fix enum Value issue with gcc 4.4
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>
2010-01-19 23:30:23 +01:00
Marco Costalba a1b8c8109b Small lnArray[] cleanup
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-19 11:52:13 +01:00
Marco Costalba c01af56769 Silence some silly MSVC warnings
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>
2010-01-19 11:23:00 +01:00
Marco Costalba 66d5c13a88 Order check moves used in qsearch
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>
2010-01-19 11:22:49 +01:00
Marco Costalba 0edad63b44 Avoid an useless evaluate() call
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>
2010-01-18 15:47:43 +01:00
Marco Costalba b833c8247a Allow SearchStack to link an EvalInfo object
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>
2010-01-18 10:03:09 +01:00
Joona Kiiski 419c5b69ca Make reduction search code SMP-friendly
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>
2010-01-18 09:11:58 +01:00
Joona Kiiski 72e1e9b986 Small cleanup of unused code in sp_search
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>
2010-01-17 14:21:14 +01:00
Marco Costalba 1062459029 Fix silly MSVC warning
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>
2010-01-17 13:54:52 +01:00
Marco Costalba b5d38ad1e5 Initialize futilityMargin in EvalInfo c'tor
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>
2010-01-17 13:24:40 +01:00
Joona Kiiski 000a975eaf Retire quick_evaluate()
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>
2010-01-17 13:15:44 +01:00
Joona Kiiski d457594197 Razor at depth one, but do razoring only when not in check
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>
2010-01-17 11:46:40 +01:00
Marco Costalba 942c18ef66 Allow negative history values
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>
2010-01-13 22:10:43 +01:00
Marco Costalba 007285be2d Store node evaluation in SearchStack
This info will be used by future patches.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-11 21:18:30 +01:00
Marco Costalba e817a55bc6 Decrease NullMoveMargin and adjust razoring
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>
2010-01-11 21:17:02 +01:00
Marco Costalba 638f3d31cc Do not wait when AbortSearch is set
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>
2010-01-11 11:19:12 +01:00
Marco Costalba 55745f4105 Fix sending of best move during an infinite search
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>
2010-01-10 13:18:43 +01:00
Marco Costalba 968c3de8e0 Fix threads count setting
Was broken after "Optimal tune for 8 cores" patch.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-09 16:49:54 +01:00
Marco Costalba 6a6facc058 Optimal tune for 8 cores
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>
2010-01-08 12:58:51 +01:00
Marco Costalba 5b21c10afb Sync qsearch with search
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>
2010-01-08 12:03:47 +01:00
Marco Costalba dba072c449 Use full evaluation in null search
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>
2010-01-08 10:20:35 +01:00
Joona Kiiski e2e360fcbc Slow down reductions
After testing on Joona QUAD the whole LMR series:

Orig - Mod: 335 - 405 (+33 elo)

Functionality Signature: 12581900

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-07 15:49:48 +01:00
Joona Kiiski 49b1c5dccd Use logarithmic LMR also at root
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-07 15:40:04 +01:00
Joona Kiiski c99d963fa5 Logarithmic LMR
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-07 15:35:57 +01:00
Marco Costalba 7c0679ad61 Fix 'position ..... moves ' parsing bug
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>
2010-01-07 11:59:32 +01:00
Marco Costalba cc974fa7a4 Fix en-passant parsing from fen string
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>
2010-01-06 10:07:07 +01:00
Marco Costalba 807844eab1 Introduce refine_eval()
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>
2010-01-05 14:57:59 +01:00
Marco Costalba 860260c3b1 Increase null reduction at high depths
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>
2010-01-05 08:09:09 +01:00
Marco Costalba d11af1de11 Fix a compile error under gcc
And some warnings on the picky icc.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-04 17:19:42 +01:00
Marco Costalba 721d557681 Last round of search.cpp cleanup
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>
2010-01-04 12:39:13 +01:00
Marco Costalba 0e15b0f1d3 Space inflate bottom part of search.cpp
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-03 21:30:46 +01:00
Marco Costalba 9e6d38d224 Rename MaxActiveSplitPoints
And move in thread.h togheter with THREAD_MAX

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-03 15:37:23 +01:00
Marco Costalba c8af7a867e Retire 'finished' from MovePicker
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>
2010-01-03 15:37:17 +01:00
Marco Costalba 5c8f571459 Rename SingleReplyExtension in SingleEvasionExtension
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>
2010-01-03 15:37:03 +01:00
Marco Costalba 0256db2a11 Small cleanup in search.cpp
Also clarify some comments.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-03 15:36:40 +01:00
Marco Costalba 12d8f74242 Retire approximateEval field from SplitPoint
It is not used anymore after the futility pruning
rewrite in a66f31f12.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-01-02 10:30:05 +01:00
Marco Costalba 7824603549 Double HistoryMax and reduce aging
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>
2009-12-31 13:45:57 +01:00
Marco Costalba 0f39e5c4ff Fix a little warning under gcc compiler
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2009-12-30 13:25:22 +01:00
Marco Costalba 990d83a72d Optimized bitScanReverse32()
Should be a bit faster then previous one.
Hacked by Pascal Georges.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2009-12-30 13:25:21 +01:00
Marco Costalba cf486cf229 Restore development version
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2009-12-30 13:25:21 +01:00
68 changed files with 9079 additions and 15077 deletions
+70
View File
@@ -0,0 +1,70 @@
### Overview
Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is
not a complete chess program and requires some UCI-compatible GUI
(e.g. XBoard with PolyGlot, eboard, Arena, Sigma Chess, Shredder, Chess
Partner or Fritz) in order to be used comfortably. Read the
documentation for your GUI of choice for information about how to use
Stockfish with it.
This version of Stockfish supports up to 128 CPUs. The engine defaults
to one search thread, so it is therefore recommended to inspect the value of
the *Threads* UCI parameter, and to make sure it equals the number of CPU
cores on your computer.
### Files
This distribution of Stockfish consists of the following files:
* Readme.md, the file you are currently reading.
* Copying.txt, a text file containing the GNU General Public License.
* src, a subdirectory containing the full source code, including a Makefile
that can be used to compile Stockfish on Unix-like systems. For further
information about how to compile Stockfish yourself read section below.
* polyglot.ini, for using Stockfish with Fabien Letouzey's PolyGlot
adapter.
### Opening books
This version of Stockfish has support for PolyGlot opening books. For
information about how to create such books, consult the PolyGlot
documentation. The book file can be selected by setting the *Book File*
UCI parameter.
### Compiling it yourself
On Unix-like systems, it should be possible to compile Stockfish
directly from the source code with the included Makefile.
Stockfish has support for 32 or 64-bit CPUs, the hardware POPCNT
instruction, big-endian machines such as Power PC, and other platforms.
In general it is recommended to run `make help` to see a list of make
targets with corresponding descriptions. When not using the Makefile to
compile (for instance with Microsoft MSVC) you need to manually
set/unset some switches in the compiler command line; see file *types.h*
for a quick reference.
### Terms of use
Stockfish is free, and distributed under the **GNU General Public License**
(GPL). Essentially, this means that you are free to do almost exactly
what you want with the program, including distributing it among your
friends, making it available for download from your web site, selling
it (either by itself or as part of some bigger software package), or
using it as the starting point for a software project of your own.
The only real limitation is that whenever you distribute Stockfish in
some way, you must always include the full source code, or a pointer
to where the source code can be found. If you make any changes to the
source code, these changes must also be made available under the GPL.
For full details, read the copy of the GPL found in the file named
*Copying.txt*
-90
View File
@@ -1,90 +0,0 @@
1. Introduction
---------------
Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is
not a complete chess program, but requires some UCI compatible GUI
(like XBoard with PolyGlot, eboard, Jos, Arena, Sigma Chess, Shredder,
Chess Partner, or Fritz) in order to be used comfortably. Read the
documentation for your GUI of choice for information about how to use
Stockfish with your GUI.
This version of Stockfish supports up to 8 CPUs, but has not been
tested thoroughly with more than 2. The program tries to detect the
number of CPUs on your computer and set the number of search threads
accordingly, but please be aware that the detection is not always
correct. It is therefore recommended to inspect the value of the
"Threads" UCI parameter, and to make sure it equals the number of CPU
cores on your computer. If you are using more than four threads, it
is recommended to raise the value of "Minimum Split Depth" UCI parameter
to 6.
2. Files
--------
This distribution of Stockfish consists of the following files:
* Readme.txt, the file you are currently reading.
* Copying.txt, a text file containing the GNU General Public
License.
* src/, a subdirectory containing the full source code, including a
Makefile that can be used to compile Stockfish on Unix-like
systems. For further information about how to compile Stockfish
yourself, read section 4 below.
* polyglot.ini, for using Stockfish with Fabien Letouzey's PolyGlot
adapter.
3. Opening books
----------------
This version of Stockfish has experimental support for PolyGlot opening
books. For information about how to create such books, consult the
PolyGlot documentation. The book file can be selected by setting the
UCI parameter "Book File".
4. Compiling it yourself
------------------------
On Unix-like systems, it should usually be possible to compile
Stockfish directly from the source code with the included Makefile.
For big-endian machines like Power PC you need to enable the proper
flag changing from -DNBIGENDIAN to -DBIGENDIAN in the Makefile.
Stockfish has POPCNT instruction runtime detection and support. This can
give an extra speed on Core i7 or similar systems. To enable this feature
compile with 'make icc-profile-popcnt'
On 64 bit Unix-like systems the 'bsfq' assembly instruction will be used
for bit counting. Detection is automatic at compile time, but in case you
experience compile problems you can comment out #define USE_BSFQ line in types.h
5. Terms of use
---------------
Stockfish is free, and distributed under the GNU General Public License
(GPL). Essentially, this means that you are free to do almost exactly
what you want with the program, including distributing it among your
friends, making it available for download from your web site, selling
it (either by itself or as part of some bigger software package), or
using it as the starting point for a software project of your own.
The only real limitation is that whenever you distribute Stockfish in
some way, you must always include the full source code, or a pointer
to where the source code can be found. If you make any changes to the
source code, these changes must also be made available under the GPL.
For full details, read the copy of the GPL found in the file named
Copying.txt.
6. Feedback
-----------
The author's e-mail address is mcostalba@gmail.com
+43 -63
View File
@@ -1,63 +1,43 @@
[PolyGlot]
EngineDir = .
EngineCommand = ./stockfish
Book = false
BookFile = book.bin
Log = true
LogFile = stockfish.log
Resign = true
ResignScore = 600
[Engine]
Hash = 128
Threads = 1
OwnBook = false
Book File = book.bin
Use Search Log = false
Mobility (Middle Game) = 100
Mobility (Endgame) = 100
Pawn Structure (Middle Game) = 100
Pawn Structure (Endgame) = 100
Passed Pawns (Middle Game) = 100
Passed Pawns (Endgame) = 100
Aggressiveness = 100
Cowardice = 100
King Safety Curve = Quadratic
Quadratic = Linear
King Safety Coefficient = 40
King Safety X Intercept = 0
King Safety Max Slope = 30
King Safety Max Value = 500
Queen Contact Check Bonus = 3
Queen Check Bonus = 2
Rook Check Bonus = 1
Bishop Check Bonus = 1
Knight Check Bonus = 1
Discovered Check Bonus = 3
Mate Threat Bonus = 3
Check Extension (PV nodes) = 2
Check Extension (non-PV nodes) = 1
Single Reply Extension (PV nodes) = 2
Single Reply Extension (non-PV nodes) = 2
Mate Threat Extension (PV nodes) = 0
Mate Threat Extension (non-PV nodes) = 0
Pawn Push to 7th Extension (PV nodes) = 1
Pawn Push to 7th Extension (non-PV nodes) = 1
Passed Pawn Extension (PV nodes) = 1
Passed Pawn Extension (non-PV nodes) = 0
Pawn Endgame Extension (PV nodes) = 2
Pawn Endgame Extension (non-PV nodes) = 2
Full Depth Moves (PV nodes) = 14
Full Depth Moves (non-PV nodes) = 3
Threat Depth = 5
Futility Pruning (Main Search) = true
Futility Pruning (Quiescence Search) = true
Randomness = 0
Minimum Split Depth = 4
Maximum Number of Threads per Split Point = 5
[PolyGlot]
EngineDir = .
EngineCommand = ./stockfish
Book = false
BookFile = book.bin
Log = false
LogFile = stockfish.log
Resign = true
ResignScore = 600
[Engine]
Write Debug Log = false
Write Search Log = false
Search Log Filename = SearchLog.txt
Book File = book.bin
Best Book Move = false
Contempt Factor = 0
Mobility (Midgame) = 100
Mobility (Endgame) = 100
Pawn Structure (Midgame) = 100
Pawn Structure (Endgame) = 100
Passed Pawns (Midgame) = 100
Passed Pawns (Endgame) = 100
Space = 100
King Safety = 100
Min Split Depth = 0
Threads = 1
Hash = 128
Ponder = true
OwnBook = false
MultiPV = 1
Skill Level = 20
Emergency Move Horizon = 40
Emergency Base Time = 200
Emergency Move Time = 70
Minimum Thinking Time = 20
Slow Mover = 100
UCI_Chess960 = false
-674
View File
@@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+445 -255
View File
@@ -1,8 +1,6 @@
# Stockfish, a UCI chess playing engine derived from Glaurung 2.1
# Copyright (C) 2004-2007 Tord Romstad
# Copyright (C) 2008 Marco Costalba
# This file is part of Stockfish.
# Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
# Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
#
# Stockfish is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,289 +16,481 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
### Executable name. Do not change
### ==========================================================================
### Section 1. General Configuration
### ==========================================================================
### Establish the operating system name
UNAME = $(shell uname)
### Executable name
EXE = stockfish
### Installation dir definitions
PREFIX = /usr/local
# Haiku has a non-standard filesystem layout
ifeq ($(UNAME),Haiku)
PREFIX=/boot/common
endif
BINDIR = $(PREFIX)/bin
### Built-in benchmark for pgo-builds
PGOBENCH = ./$(EXE) bench 32 1 1 default time
### Object files
OBJS = benchmark.o bitbase.o bitboard.o book.o endgame.o evaluate.o main.o \
material.o misc.o movegen.o movepick.o notation.o pawns.o position.o \
search.o thread.o timeman.o tt.o uci.o ucioption.o
### ==========================================================================
### Compiler speed switches for both GCC and ICC. These settings are generally
### fast on a broad range of systems, but may be changed experimentally
### Section 2. High-level Configuration
### ==========================================================================
GCCFLAGS = -O3 -msse
ICCFLAGS = -fast -msse
ICCFLAGS-OSX = -fast -mdynamic-no-pic
#
# flag --- Comp switch --- Description
# ----------------------------------------------------------------------------
#
# debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode
# optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations
# arch = (name) --- (-arch) --- Target architecture
# os = (name) --- --- Target operating system
# bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system
# prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch x86 asm-instruction
# bsfq = yes/no --- -DUSE_BSFQ --- Use bsfq x86_64 asm-instruction (only
# with GCC and ICC 64-bit)
# popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt x86_64 asm-instruction
# sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions
# pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction
#
# Note that Makefile is space sensitive, so when adding new architectures
# or modifying existing flags, you have to make sure there are no extra spaces
# at the end of the line for flag values.
### 2.1. General and architecture defaults
optimize = yes
debug = no
os = any
bits = 32
prefetch = no
bsfq = no
popcnt = no
sse = no
pext = no
### 2.2 Architecture specific
ifeq ($(ARCH),general-32)
arch = any
endif
ifeq ($(ARCH),x86-32-old)
arch = i386
endif
ifeq ($(ARCH),x86-32)
arch = i386
prefetch = yes
sse = yes
endif
ifeq ($(ARCH),general-64)
arch = any
bits = 64
endif
ifeq ($(ARCH),x86-64)
arch = x86_64
bits = 64
prefetch = yes
bsfq = yes
sse = yes
endif
ifeq ($(ARCH),x86-64-modern)
arch = x86_64
bits = 64
prefetch = yes
bsfq = yes
popcnt = yes
sse = yes
endif
ifeq ($(ARCH),x86-64-bmi2)
arch = x86_64
bits = 64
prefetch = yes
bsfq = yes
popcnt = yes
sse = yes
pext = yes
endif
ifeq ($(ARCH),armv7)
arch = armv7
prefetch = yes
bsfq = yes
endif
ifeq ($(ARCH),ppc-32)
arch = ppc
endif
ifeq ($(ARCH),ppc-64)
arch = ppc64
bits = 64
endif
### ==========================================================================
### Enable/disable debugging, disabled by default
### Section 3. Low-level configuration
### ==========================================================================
GCCFLAGS += -DNDEBUG
ICCFLAGS += -DNDEBUG
ICCFLAGS-OSX += -DNDEBUG
### 3.1 Selecting compiler (default = gcc)
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -fno-rtti $(EXTRACXXFLAGS)
LDFLAGS += $(EXTRALDFLAGS)
ifeq ($(COMP),)
COMP=gcc
endif
ifeq ($(COMP),gcc)
comp=gcc
CXX=g++
CXXFLAGS += -ansi -pedantic -Wno-long-long -Wextra -Wshadow
endif
ifeq ($(COMP),mingw)
comp=mingw
CXX=g++
CXXFLAGS += -Wextra -Wshadow
LDFLAGS += -static-libstdc++ -static-libgcc
endif
ifeq ($(COMP),icc)
comp=icc
CXX=icpc
CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi
endif
ifeq ($(COMP),clang)
comp=clang
CXX=clang++
CXXFLAGS += -ansi -pedantic -Wno-long-long -Wextra -Wshadow
endif
ifeq ($(comp),icc)
profile_prepare = icc-profile-prepare
profile_make = icc-profile-make
profile_use = icc-profile-use
profile_clean = icc-profile-clean
else
profile_prepare = gcc-profile-prepare
profile_make = gcc-profile-make
profile_use = gcc-profile-use
profile_clean = gcc-profile-clean
endif
ifeq ($(UNAME),Darwin)
CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.6
LDFLAGS += -arch $(arch) -mmacosx-version-min=10.6
endif
### On mingw use Windows threads, otherwise POSIX
ifneq ($(comp),mingw)
# On Android Bionic's C library comes with its own pthread implementation bundled in
ifneq ($(arch),armv7)
# Haiku has pthreads in its libroot, so only link it in on other platforms
ifneq ($(UNAME),Haiku)
LDFLAGS += -lpthread
endif
endif
endif
### 3.4 Debugging
ifeq ($(debug),no)
CXXFLAGS += -DNDEBUG
else
CXXFLAGS += -g
endif
### 3.5 Optimization
ifeq ($(optimize),yes)
ifeq ($(comp),gcc)
CXXFLAGS += -O3
ifeq ($(UNAME),Darwin)
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
ifeq ($(arch),x86_64)
CXXFLAGS += -mdynamic-no-pic
endif
endif
ifeq ($(arch),armv7)
CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp
endif
endif
ifeq ($(comp),mingw)
CXXFLAGS += -O3
endif
ifeq ($(comp),icc)
ifeq ($(UNAME),Darwin)
CXXFLAGS += -fast -mdynamic-no-pic
else
CXXFLAGS += -fast
endif
endif
ifeq ($(comp),clang)
CXXFLAGS += -O3
ifeq ($(UNAME),Darwin)
ifeq ($(pext),no)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
ifeq ($(arch),i386)
CXXFLAGS += -mdynamic-no-pic
endif
ifeq ($(arch),x86_64)
CXXFLAGS += -mdynamic-no-pic
endif
endif
endif
endif
### 3.6. Bits
ifeq ($(bits),64)
CXXFLAGS += -DIS_64BIT
endif
### 3.7 prefetch
ifeq ($(prefetch),yes)
ifeq ($(sse),yes)
CXXFLAGS += -msse
DEPENDFLAGS += -msse
endif
else
CXXFLAGS += -DNO_PREFETCH
endif
### 3.8 bsfq
ifeq ($(bsfq),yes)
CXXFLAGS += -DUSE_BSFQ
endif
### 3.9 popcnt
ifeq ($(popcnt),yes)
CXXFLAGS += -msse3 -DUSE_POPCNT
endif
### 3.10 pext
ifeq ($(pext),yes)
CXXFLAGS += -DUSE_PEXT
ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -mbmi -mbmi2
endif
endif
### 3.11 Link Time Optimization, it works since gcc 4.5 but not on mingw.
### This is a mix of compile and link time options because the lto link phase
### needs access to the optimization flags.
ifeq ($(comp),gcc)
ifeq ($(optimize),yes)
ifeq ($(debug),no)
GCC_MAJOR := `$(CXX) -dumpversion | cut -f1 -d.`
GCC_MINOR := `$(CXX) -dumpversion | cut -f2 -d.`
ifeq (1,$(shell expr \( $(GCC_MAJOR) \> 4 \) \| \( $(GCC_MAJOR) \= 4 \& $(GCC_MINOR) \>= 5 \)))
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
endif
endif
endif
### ==========================================================================
### Remove below comments to compile for a big-endian machine
### Section 4. Public targets
### ==========================================================================
#GCCFLAGS += -DBIGENDIAN
#ICCFLAGS += -DBIGENDIAN
#ICCFLAGS-OSX += -DBIGENDIAN
### ==========================================================================
### Run built-in benchmark for pgo-builds with: 32MB hash 1 thread 10 depth
### These settings are generally fast, but may be changed experimentally
### ==========================================================================
PGOBENCH = ./$(EXE) bench 32 1 10 default depth
### General compiler settings. Do not change
GCCFLAGS += -g -Wall -fno-exceptions -fno-rtti
ICCFLAGS += -g -Wall -fno-exceptions -fno-rtti -wd383,869,981,10187,10188,11505,11503
ICCFLAGS-OSX += -g -Wall -fno-exceptions -fno-rtti -wd383,869,981,10187,10188,11505,11503
### General linker settings. Do not change
LDFLAGS = -lpthread
### Object files. Do not change
OBJS = application.o bitboard.o pawns.o material.o endgame.o evaluate.o main.o \
misc.o move.o movegen.o history.o movepick.o search.o piece.o \
position.o direction.o tt.o value.o uci.o ucioption.o \
mersenne.o book.o bitbase.o san.o benchmark.o
### General rules. Do not change
default:
$(MAKE) gcc
help:
@echo ""
@echo "Makefile options:"
@echo "To compile stockfish, type: "
@echo ""
@echo "make > Default: Compiler = g++"
@echo "make icc > Compiler = icpc"
@echo "make icc-profile > Compiler = icpc + automatic pgo-build"
@echo "make icc-profile-popcnt > Compiler = icpc + automatic pgo-build + popcnt-support"
@echo "make osx-ppc32 > PPC-Mac OS X 32 bit. Compiler = g++"
@echo "make osx-ppc64 > PPC-Mac OS X 64 bit. Compiler = g++"
@echo "make osx-x86 > x86-Mac OS X 32 bit. Compiler = g++"
@echo "make osx-x86_64 > x86-Mac OS X 64 bit. Compiler = g++"
@echo "make osx-icc32 > x86-Mac OS X 32 bit. Compiler = icpc"
@echo "make osx-icc64 > x86-Mac OS X 64 bit. Compiler = icpc"
@echo "make osx-icc32-profile > OSX 32 bit. Compiler = icpc + automatic pgo-build"
@echo "make osx-icc64-profile > OSX 64 bit. Compiler = icpc + automatic pgo-build"
@echo "make strip > Strip executable"
@echo "make clean > Clean up"
@echo "make target ARCH=arch [COMP=comp]"
@echo ""
@echo "Supported targets:"
@echo ""
@echo "build > Standard build"
@echo "profile-build > PGO build"
@echo "strip > Strip executable"
@echo "install > Install executable"
@echo "clean > Clean up"
@echo ""
@echo "Supported archs:"
@echo ""
@echo "x86-64 > x86 64-bit"
@echo "x86-64-modern > x86 64-bit with popcnt support"
@echo "x86-64-bmi2 > x86 64-bit with pext support"
@echo "x86-32 > x86 32-bit with SSE support"
@echo "x86-32-old > x86 32-bit fall back for old hardware"
@echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit"
@echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit"
@echo ""
@echo "Supported compilers:"
@echo ""
@echo "gcc > Gnu compiler (default)"
@echo "mingw > Gnu compiler with MinGW under Windows"
@echo "clang > LLVM Clang compiler"
@echo "icc > Intel compiler"
@echo ""
@echo "Non-standard targets:"
@echo ""
@echo "make hpux > Compile for HP-UX. Compiler = aCC"
@echo ""
@echo "Examples. If you don't know what to do, you likely want to run: "
@echo ""
@echo "make build ARCH=x86-64 (This is for 64-bit systems)"
@echo "make build ARCH=x86-32 (This is for 32-bit systems)"
@echo ""
all: $(EXE) .depend
.PHONY: build profile-build
build:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
clean:
$(RM) *.o .depend *~ $(EXE)
### Possible targets. You may add your own ones here
gcc:
$(MAKE) \
CXX='g++' \
CXXFLAGS="$(GCCFLAGS)" \
all
icc:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS)" \
all
icc-profile-make:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS)" \
CXXFLAGS+='-prof-gen=srcpos -prof_dir ./profdir' \
all
icc-profile-use:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS)" \
CXXFLAGS+='-prof_use -prof_dir ./profdir' \
all
icc-profile:
@rm -rf profdir
@mkdir profdir
profile-build:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
@echo ""
@echo "Step 0/4. Preparing for profile build."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_prepare)
@echo ""
@echo "Step 1/4. Building executable for benchmark ..."
@touch *.cpp *.h
$(MAKE) icc-profile-make
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make)
@echo ""
@echo "Running benchmark for pgo-build ..."
@echo "Step 2/4. Running benchmark for pgo-build ..."
@$(PGOBENCH) > /dev/null
@echo "Benchmark finished. Build final executable now ..."
@echo ""
@touch *.cpp *.h
$(MAKE) icc-profile-use
@rm -rf profdir bench.txt
icc-profile-make-with-popcnt:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS) -DUSE_POPCNT" \
CXXFLAGS+='-prof-gen=srcpos -prof_dir ./profdir' \
all
icc-profile-use-with-popcnt:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS) -DUSE_POPCNT" \
CXXFLAGS+='-prof_use -prof_dir ./profdir' \
all
icc-profile-popcnt:
@rm -rf profdir
@mkdir profdir
@touch *.cpp *.h
$(MAKE) icc-profile-make
@echo "Step 3/4. Building final executable ..."
@touch *.cpp
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use)
@echo ""
@echo "Running benchmark for pgo-build (popcnt disabled)..."
@$(PGOBENCH) > /dev/null
@touch *.cpp *.h
$(MAKE) icc-profile-make-with-popcnt
@echo ""
@echo "Running benchmark for pgo-build (popcnt enabled)..."
@$(PGOBENCH) > /dev/null
@echo "Benchmarks finished. Build final executable now ..."
@echo ""
@touch *.cpp *.h
$(MAKE) icc-profile-use-with-popcnt
@rm -rf profdir bench.txt
osx-ppc32:
$(MAKE) \
CXX='g++' \
CXXFLAGS="$(GCCFLAGS)" \
CXXFLAGS+='-arch ppc' \
LDFLAGS+='-arch ppc' \
all
osx-ppc64:
$(MAKE) \
CXX='g++' \
CXXFLAGS="$(GCCFLAGS)" \
CXXFLAGS+='-arch ppc64' \
LDFLAGS+='-arch ppc64' \
all
osx-x86:
$(MAKE) \
CXX='g++' \
CXXFLAGS="$(GCCFLAGS)" \
CXXFLAGS+='-arch i386' \
LDFLAGS+='-arch i386' \
all
osx-x86_64:
$(MAKE) \
CXX='g++' \
CXXFLAGS="$(GCCFLAGS)" \
CXXFLAGS+='-arch x86_64' \
LDFLAGS+='-arch x86_64' \
all
osx-icc32:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS-OSX)" \
CXXFLAGS+='-arch i386' \
LDFLAGS+='-arch i386' \
all
osx-icc64:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS-OSX)" \
CXXFLAGS+='-arch x86_64' \
LDFLAGS+='-arch x86_64' \
all
osx-icc32-profile-make:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS-OSX)" \
CXXFLAGS+='-arch i386' \
CXXFLAGS+='-prof_gen -prof_dir ./profdir' \
LDFLAGS+='-arch i386' \
all
osx-icc32-profile-use:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS-OSX)" \
CXXFLAGS+='-arch i386' \
CXXFLAGS+='-prof_use -prof_dir ./profdir' \
LDFLAGS+='-arch i386' \
all
osx-icc32-profile:
@rm -rf profdir
@mkdir profdir
@touch *.cpp *.h
$(MAKE) osx-icc32-profile-make
@echo ""
@echo "Running benchmark for pgo-build ..."
@$(PGOBENCH) > /dev/null
@echo "Benchmark finished. Build final executable now ..."
@echo ""
@touch *.cpp *.h
$(MAKE) osx-icc32-profile-use
@rm -rf profdir bench.txt
osx-icc64-profile-make:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS-OSX)" \
CXXFLAGS+='-arch x86_64' \
CXXFLAGS+='-prof_gen -prof_dir ./profdir' \
LDFLAGS+='-arch x86_64' \
all
osx-icc64-profile-use:
$(MAKE) \
CXX='icpc' \
CXXFLAGS="$(ICCFLAGS-OSX)" \
CXXFLAGS+='-arch x86_64' \
CXXFLAGS+='-prof_use -prof_dir ./profdir' \
LDFLAGS+='-arch x86_64' \
all
osx-icc64-profile:
@rm -rf profdir
@mkdir profdir
@touch *.cpp *.h
$(MAKE) osx-icc64-profile-make
@echo ""
@echo "Running benchmark for pgo-build ..."
@$(PGOBENCH) > /dev/null
@echo "Benchmark finished. Build final executable now ..."
@echo ""
@touch *.cpp *.h
$(MAKE) osx-icc64-profile-use
@rm -rf profdir bench.txt
@echo "Step 4/4. Deleting profile data ..."
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_clean)
strip:
strip $(EXE)
install:
-mkdir -p -m 755 $(BINDIR)
-cp $(EXE) $(BINDIR)
-strip $(BINDIR)/$(EXE)
clean:
$(RM) $(EXE) $(EXE).exe *.o .depend *~ core bench.txt *.gcda
default:
help
### ==========================================================================
### Section 5. Private targets
### ==========================================================================
all: $(EXE) .depend
config-sanity:
@echo ""
@echo "Config:"
@echo "debug: '$(debug)'"
@echo "optimize: '$(optimize)'"
@echo "arch: '$(arch)'"
@echo "os: '$(os)'"
@echo "bits: '$(bits)'"
@echo "prefetch: '$(prefetch)'"
@echo "bsfq: '$(bsfq)'"
@echo "popcnt: '$(popcnt)'"
@echo "sse: '$(sse)'"
@echo "pext: '$(pext)'"
@echo ""
@echo "Flags:"
@echo "CXX: $(CXX)"
@echo "CXXFLAGS: $(CXXFLAGS)"
@echo "LDFLAGS: $(LDFLAGS)"
@echo ""
@echo "Testing config sanity. If this fails, try 'make help' ..."
@echo ""
@test "$(debug)" = "yes" || test "$(debug)" = "no"
@test "$(optimize)" = "yes" || test "$(optimize)" = "no"
@test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7"
@test "$(os)" = "any"
@test "$(bits)" = "32" || test "$(bits)" = "64"
@test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
@test "$(bsfq)" = "yes" || test "$(bsfq)" = "no"
@test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
@test "$(sse)" = "yes" || test "$(sse)" = "no"
@test "$(pext)" = "yes" || test "$(pext)" = "no"
@test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang"
### Compilation. Do not change
$(EXE): $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $(OBJS)
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
gcc-profile-prepare:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) gcc-profile-clean
gcc-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-generate' \
EXTRALDFLAGS='-lgcov' \
all
gcc-profile-use:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-fprofile-use' \
EXTRALDFLAGS='-lgcov' \
all
gcc-profile-clean:
@rm -rf *.gcda *.gcno bench.txt
icc-profile-prepare:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) icc-profile-clean
@mkdir profdir
icc-profile-make:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \
all
icc-profile-use:
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) \
EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \
all
icc-profile-clean:
@rm -rf profdir bench.txt
### Dependencies. Do not change
.depend:
$(CXX) -msse -MM $(OBJS:.o=.cpp) > $@
-@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null
-include .depend
### ==========================================================================
### Section 6. Non-standard targets
### ==========================================================================
hpux:
$(MAKE) \
CXX='/opt/aCC/bin/aCC -AA +hpxstd98 -mt +O3 -DNDEBUG -DNO_PREFETCH' \
CXXFLAGS="" \
LDFLAGS="" \
all
include .depend
-75
View File
@@ -1,75 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include "bitboard.h"
#include "direction.h"
#include "endgame.h"
#include "evaluate.h"
#include "material.h"
#include "mersenne.h"
#include "misc.h"
#include "movepick.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "ucioption.h"
/// Application class is in charge of initializing global resources
/// at startup and cleanly releases them when program terminates.
Application::Application() {
init_mersenne();
init_direction_table();
init_bitboards();
init_uci_options();
Position::init_zobrist();
Position::init_piece_square_tables();
init_eval(1);
init_bitbases();
init_threads();
// Make random number generation less deterministic, for book moves
for (int i = abs(get_system_time() % 10000); i > 0; i--)
genrand_int32();
}
Application::~Application() {
stop_threads();
quit_eval();
}
void Application::initialize() {
// A static Application object is allocated
// once only when this function is called.
static Application singleton;
}
void Application::exit_with_failure() {
exit(EXIT_FAILURE); // d'tor will be called automatically
}
+110 -119
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,29 +17,25 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <fstream>
#include <sstream>
#include <iostream>
#include <istream>
#include <vector>
#include "benchmark.h"
#include "misc.h"
#include "notation.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
using namespace std;
////
//// Variables
////
const string BenchmarkPositions[] = {
static const char* Defaults[] = {
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"r4rk1/1b2qppp/p1n1p3/1p6/1b1PN3/3BRN2/PP3PPP/R2Q2K1 b - - 7 16",
"4r1k1/ppq3pp/3b4/2pP4/2Q1p3/4B1P1/PP5P/R5K1 b - - 0 20",
"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10",
"8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11",
"4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
"rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14",
"r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14",
@@ -51,131 +47,126 @@ const string BenchmarkPositions[] = {
"r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16",
"3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22",
"r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18",
"4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - 3 22",
"3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26"
"4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22",
"3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26",
"6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1",
"3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1",
"2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1",
"8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1",
"7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1",
"8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1",
"8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1",
"8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1",
"8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1",
"5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1",
"6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1",
"1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1",
"6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1",
"8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1"
};
////
//// Functions
////
/// benchmark() runs a simple benchmark by letting Stockfish analyze a set
/// of positions for a given time each. There are four parameters; the
/// of positions for a given limit each. There are five parameters: the
/// transposition table size, the number of search threads that should
/// be used, the time in seconds spent for each position (optional, default
/// is 60) and an optional file name where to look for positions in fen
/// format (default are the BenchmarkPositions defined above).
/// The analysis is written to a file named bench.txt.
/// be used, the limit value spent for each position (optional, default is
/// depth 13), an optional file name where to look for positions in FEN
/// format (defaults are the positions defined above) and the type of the
/// limit value: depth (default), time in secs or number of nodes.
void benchmark(const string& commandLine) {
void benchmark(const Position& current, istream& is) {
istringstream csVal(commandLine);
istringstream csStr(commandLine);
string ttSize, threads, fileName, limitType, timFile;
int val, secsPerPos, maxDepth, maxNodes;
string token;
Search::LimitsType limits;
vector<string> fens;
csStr >> ttSize;
csVal >> val;
if (val < 4 || val > 1024)
{
cerr << "The hash table size must be between 4 and 1024" << endl;
Application::exit_with_failure();
}
csStr >> threads;
csVal >> val;
if (val < 1 || val > THREAD_MAX)
{
cerr << "The number of threads must be between 1 and " << THREAD_MAX << endl;
Application::exit_with_failure();
}
set_option_value("Hash", ttSize);
set_option_value("Threads", threads);
set_option_value("OwnBook", "false");
set_option_value("Use Search Log", "true");
set_option_value("Search Log Filename", "bench.txt");
// Assign default values to missing arguments
string ttSize = (is >> token) ? token : "32";
string threads = (is >> token) ? token : "1";
string limit = (is >> token) ? token : "13";
string fenFile = (is >> token) ? token : "default";
string limitType = (is >> token) ? token : "depth";
csVal >> val;
csVal >> fileName;
csVal >> limitType;
csVal >> timFile;
secsPerPos = maxDepth = maxNodes = 0;
Options["Hash"] = ttSize;
Options["Threads"] = threads;
TT.clear();
if (limitType == "time")
secsPerPos = val * 1000;
else if (limitType == "depth" || limitType == "perft")
maxDepth = val;
limits.movetime = 1000 * atoi(limit.c_str()); // movetime is in ms
else if (limitType == "nodes")
limits.nodes = atoi(limit.c_str());
else if (limitType == "mate")
limits.mate = atoi(limit.c_str());
else
maxNodes = val;
limits.depth = atoi(limit.c_str());
vector<string> positions;
if (fenFile == "default")
fens.assign(Defaults, Defaults + 30);
if (fileName != "default")
else if (fenFile == "current")
fens.push_back(current.fen());
else
{
ifstream fenFile(fileName.c_str());
if (!fenFile.is_open())
{
cerr << "Unable to open positions file " << fileName << endl;
Application::exit_with_failure();
}
string pos;
while (fenFile.good())
{
getline(fenFile, pos);
if (!pos.empty())
positions.push_back(pos);
}
fenFile.close();
} else
for (int i = 0; i < 16; i++)
positions.push_back(string(BenchmarkPositions[i]));
string fen;
ifstream file(fenFile.c_str());
ofstream timingFile;
if (!timFile.empty())
{
timingFile.open(timFile.c_str(), ios::out | ios::app);
if (!timingFile.is_open())
if (!file.is_open())
{
cerr << "Unable to open timing file " << timFile << endl;
Application::exit_with_failure();
cerr << "Unable to open file " << fenFile << endl;
return;
}
while (getline(file, fen))
if (!fen.empty())
fens.push_back(fen);
file.close();
}
uint64_t nodes = 0;
Search::StateStackPtr st;
Time::point elapsed = Time::now();
for (size_t i = 0; i < fens.size(); ++i)
{
Position pos(fens[i], Options["UCI_Chess960"], Threads.main());
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
if (limitType == "divide")
for (MoveList<LEGAL> it(pos); *it; ++it)
{
StateInfo si;
pos.do_move(*it, si);
uint64_t cnt = limits.depth > 1 ? Search::perft(pos, (limits.depth - 1) * ONE_PLY) : 1;
pos.undo_move(*it);
cerr << move_to_uci(*it, pos.is_chess960()) << ": " << cnt << endl;
nodes += cnt;
}
else if (limitType == "perft")
{
uint64_t cnt = Search::perft(pos, limits.depth * ONE_PLY);
cerr << "\nPerft " << limits.depth << " leaf nodes: " << cnt << endl;
nodes += cnt;
}
else
{
Threads.start_thinking(pos, limits, st);
Threads.wait_for_think_finished();
nodes += Search::RootPos.nodes_searched();
}
}
vector<string>::iterator it;
int cnt = 1;
int64_t totalNodes = 0;
int startTime = get_system_time();
elapsed = Time::now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero'
for (it = positions.begin(); it != positions.end(); ++it, ++cnt)
{
Move moves[1] = {MOVE_NONE};
int dummy[2] = {0, 0};
Position pos(*it);
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
if (limitType == "perft")
totalNodes += perft(pos, maxDepth * OnePly);
else if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
break;
totalNodes += nodes_searched();
}
dbg_print(); // Just before to exit
cnt = get_system_time() - startTime;
cerr << "==============================="
<< "\nTotal time (ms) : " << cnt
<< "\nNodes searched : " << totalNodes
<< "\nNodes/second : " << (int)(totalNodes/(cnt/1000.0)) << endl << endl;
if (!timFile.empty())
{
timingFile << cnt << endl << endl;
timingFile.close();
}
// Under MS Visual C++ debug window always unconditionally closes
// when program exits, this is bad because we want to read results before.
#if (defined(WINDOWS) || defined(WIN32) || defined(WIN64))
cerr << "Press any key to exit" << endl;
cin >> fileName;
#endif
cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed
<< "\nNodes searched : " << nodes
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl;
}
-37
View File
@@ -1,37 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(BENCHMARK_H_INCLUDED)
#define BENCHMARK_H_INCLUDED
////
//// Includes
////
#include <string>
////
//// Prototypes
////
extern void benchmark(const std::string& commandLine);
#endif // !defined(BENCHMARK_H_INCLUDED)
+117 -292
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,334 +17,159 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include <vector>
#include "bitbase.h"
#include "bitboard.h"
#include "move.h"
#include "square.h"
////
//// Local definitions
////
#include "types.h"
namespace {
// There are 24 possible pawn squares: the first 4 files and ranks from 2 to 7
const unsigned MAX_INDEX = 2*24*64*64; // stm * psq * wksq * bksq = 196608
// Each uint32_t stores results of 32 positions, one per bit
uint32_t KPKBitbase[MAX_INDEX / 32];
// A KPK bitbase index is an integer in [0, IndexMax] range
//
// Information is mapped in a way that minimizes the number of iterations:
//
// bit 0- 5: white king square (from SQ_A1 to SQ_H8)
// bit 6-11: black king square (from SQ_A1 to SQ_H8)
// bit 12: side to move (WHITE or BLACK)
// bit 13-14: white pawn file (from FILE_A to FILE_D)
// bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2)
unsigned index(Color us, Square bksq, Square wksq, Square psq) {
return wksq + (bksq << 6) + (us << 12) + (file_of(psq) << 13) + ((RANK_7 - rank_of(psq)) << 15);
}
enum Result {
RESULT_UNKNOWN,
RESULT_INVALID,
RESULT_WIN,
RESULT_LOSS,
RESULT_DRAW
INVALID = 0,
UNKNOWN = 1,
DRAW = 2,
WIN = 4
};
inline Result& operator|=(Result& r, Result v) { return r = Result(r | v); }
struct KPKPosition {
void from_index(int index);
int to_index() const;
bool is_legal() const;
bool is_immediate_draw() const;
bool is_immediate_win() const;
Bitboard wk_attacks() const;
Bitboard bk_attacks() const;
Bitboard pawn_attacks() const;
Square whiteKingSquare, blackKingSquare, pawnSquare;
Color sideToMove;
KPKPosition(unsigned idx);
operator Result() const { return result; }
Result classify(const std::vector<KPKPosition>& db)
{ return us == WHITE ? classify<WHITE>(db) : classify<BLACK>(db); }
private:
template<Color Us> Result classify(const std::vector<KPKPosition>& db);
Color us;
Square bksq, wksq, psq;
Result result;
};
} // namespace
Result *Bitbase;
const int IndexMax = 2*24*64*64;
int UnknownCount = 0;
void initialize();
bool next_iteration();
Result classify_wtm(const KPKPosition &p);
Result classify_btm(const KPKPosition &p);
int compute_index(Square wksq, Square bksq, Square psq, Color stm);
int compress_result(Result r);
bool Bitbases::probe_kpk(Square wksq, Square wpsq, Square bksq, Color us) {
assert(file_of(wpsq) <= FILE_D);
unsigned idx = index(us, bksq, wksq, wpsq);
return KPKBitbase[idx / 32] & (1 << (idx & 0x1F));
}
////
//// Functions
////
void Bitbases::init_kpk() {
void generate_kpk_bitbase(uint8_t bitbase[]) {
// Allocate array and initialize:
Bitbase = new Result[IndexMax];
initialize();
unsigned idx, repeat = 1;
std::vector<KPKPosition> db;
db.reserve(MAX_INDEX);
// Iterate until all positions are classified:
while(next_iteration());
// Initialize db with known win / draw positions
for (idx = 0; idx < MAX_INDEX; ++idx)
db.push_back(KPKPosition(idx));
// Compress bitbase into the supplied parameter:
int i, j, b;
for(i = 0; i < 24576; i++) {
for(b = 0, j = 0; j < 8; b |= (compress_result(Bitbase[8*i+j]) << j), j++);
assert(b == int(uint8_t(b)));
bitbase[i] = (uint8_t)b;
}
// Iterate through the positions until none of the unknown positions can be
// changed to either wins or draws (15 cycles needed).
while (repeat)
for (repeat = idx = 0; idx < MAX_INDEX; ++idx)
repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN);
// Release allocated memory:
delete [] Bitbase;
// Map 32 results into one KPKBitbase[] entry
for (idx = 0; idx < MAX_INDEX; ++idx)
if (db[idx] == WIN)
KPKBitbase[idx / 32] |= 1 << (idx & 0x1F);
}
namespace {
void KPKPosition::from_index(int index) {
int s;
sideToMove = Color(index % 2);
blackKingSquare = Square((index / 2) % 64);
whiteKingSquare = Square((index / 128) % 64);
s = (index / 8192) % 24;
pawnSquare = make_square(File(s % 4), Rank(s / 4 + 1));
KPKPosition::KPKPosition(unsigned idx) {
wksq = Square((idx >> 0) & 0x3F);
bksq = Square((idx >> 6) & 0x3F);
us = Color ((idx >> 12) & 0x01);
psq = make_square(File((idx >> 13) & 0x03), Rank(RANK_7 - (idx >> 15)));
result = UNKNOWN;
// Check if two pieces are on the same square or if a king can be captured
if ( square_distance(wksq, bksq) <= 1
|| wksq == psq
|| bksq == psq
|| (us == WHITE && (StepAttacksBB[PAWN][psq] & bksq)))
result = INVALID;
else if (us == WHITE)
{
// Immediate win if a pawn can be promoted without getting captured
if ( rank_of(psq) == RANK_7
&& wksq != psq + DELTA_N
&& ( square_distance(bksq, psq + DELTA_N) > 1
||(StepAttacksBB[KING][wksq] & (psq + DELTA_N))))
result = WIN;
}
// Immediate draw if it is a stalemate or a king captures undefended pawn
else if ( !(StepAttacksBB[KING][bksq] & ~(StepAttacksBB[KING][wksq] | StepAttacksBB[PAWN][psq]))
|| (StepAttacksBB[KING][bksq] & psq & ~StepAttacksBB[KING][wksq]))
result = DRAW;
}
template<Color Us>
Result KPKPosition::classify(const std::vector<KPKPosition>& db) {
int KPKPosition::to_index() const {
return compute_index(whiteKingSquare, blackKingSquare, pawnSquare,
sideToMove);
}
// White to Move: If one move leads to a position classified as WIN, the result
// of the current position is WIN. If all moves lead to positions classified
// as DRAW, the current position is classified as DRAW, otherwise the current
// position is classified as UNKNOWN.
//
// Black to Move: If one move leads to a position classified as DRAW, the result
// of the current position is DRAW. If all moves lead to positions classified
// as WIN, the position is classified as WIN, otherwise the current position is
// classified as UNKNOWN.
const Color Them = (Us == WHITE ? BLACK : WHITE);
bool KPKPosition::is_legal() const {
if(whiteKingSquare == pawnSquare || whiteKingSquare == blackKingSquare ||
pawnSquare == blackKingSquare)
return false;
if(sideToMove == WHITE) {
if(bit_is_set(this->wk_attacks(), blackKingSquare))
return false;
if(bit_is_set(this->pawn_attacks(), blackKingSquare))
return false;
}
else {
if(bit_is_set(this->bk_attacks(), whiteKingSquare))
return false;
}
return true;
}
Result r = INVALID;
Bitboard b = StepAttacksBB[KING][Us == WHITE ? wksq : bksq];
while (b)
r |= Us == WHITE ? db[index(Them, bksq, pop_lsb(&b), psq)]
: db[index(Them, pop_lsb(&b), wksq, psq)];
bool KPKPosition::is_immediate_draw() const {
if(sideToMove == BLACK) {
Bitboard wka = this->wk_attacks();
Bitboard bka = this->bk_attacks();
if (Us == WHITE && rank_of(psq) < RANK_7)
{
Square s = psq + DELTA_N;
r |= db[index(BLACK, bksq, wksq, s)]; // Single push
// Case 1: Stalemate
if((bka & ~(wka | this->pawn_attacks())) == EmptyBoardBB)
return true;
// Case 2: King can capture pawn
if(bit_is_set(bka, pawnSquare) && !bit_is_set(wka, pawnSquare))
return true;
}
else {
// Case 1: Stalemate
if(whiteKingSquare == SQ_A8 && pawnSquare == SQ_A7 &&
(blackKingSquare == SQ_C7 || blackKingSquare == SQ_C8))
return true;
if (rank_of(psq) == RANK_2 && s != wksq && s != bksq)
r |= db[index(BLACK, bksq, wksq, s + DELTA_N)]; // Double push
}
return false;
if (Us == WHITE)
return result = r & WIN ? WIN : r & UNKNOWN ? UNKNOWN : DRAW;
else
return result = r & DRAW ? DRAW : r & UNKNOWN ? UNKNOWN : WIN;
}
bool KPKPosition::is_immediate_win() const {
// The position is an immediate win if it is white to move and the white
// pawn can be promoted without getting captured:
return
sideToMove == WHITE &&
square_rank(pawnSquare) == RANK_7 &&
(square_distance(blackKingSquare, pawnSquare+DELTA_N) > 1 ||
bit_is_set(this->wk_attacks(), pawnSquare+DELTA_N));
}
Bitboard KPKPosition::wk_attacks() const {
return StepAttackBB[WK][whiteKingSquare];
}
Bitboard KPKPosition::bk_attacks() const {
return StepAttackBB[BK][blackKingSquare];
}
Bitboard KPKPosition::pawn_attacks() const {
return StepAttackBB[WP][pawnSquare];
}
void initialize() {
KPKPosition p;
for(int i = 0; i < IndexMax; i++) {
p.from_index(i);
if(!p.is_legal())
Bitbase[i] = RESULT_INVALID;
else if(p.is_immediate_draw())
Bitbase[i] = RESULT_DRAW;
else if(p.is_immediate_win())
Bitbase[i] = RESULT_WIN;
else {
Bitbase[i] = RESULT_UNKNOWN;
UnknownCount++;
}
}
}
bool next_iteration() {
KPKPosition p;
int previousUnknownCount = UnknownCount;
for(int i = 0; i < IndexMax; i++)
if(Bitbase[i] == RESULT_UNKNOWN) {
p.from_index(i);
Bitbase[i] = (p.sideToMove == WHITE)? classify_wtm(p) : classify_btm(p);
if(Bitbase[i] == RESULT_WIN || Bitbase[i] == RESULT_LOSS ||
Bitbase[i] == RESULT_DRAW)
UnknownCount--;
}
return UnknownCount != previousUnknownCount;
}
Result classify_wtm(const KPKPosition &p) {
// If one move leads to a position classified as RESULT_LOSS, the result
// of the current position is RESULT_WIN. If all moves lead to positions
// classified as RESULT_DRAW, the current position is classified as
// RESULT_DRAW. Otherwise, the current position is classified as
// RESULT_UNKNOWN.
bool unknownFound = false;
Bitboard b;
Square s;
// King moves
b = p.wk_attacks();
while(b) {
s = pop_1st_bit(&b);
switch(Bitbase[compute_index(s, p.blackKingSquare, p.pawnSquare,
BLACK)]) {
case RESULT_LOSS:
return RESULT_WIN;
case RESULT_UNKNOWN:
unknownFound = true;
break;
case RESULT_DRAW: case RESULT_INVALID:
break;
default:
assert(false);
}
}
// Pawn moves
if(square_rank(p.pawnSquare) < RANK_7) {
s = p.pawnSquare + DELTA_N;
switch(Bitbase[compute_index(p.whiteKingSquare, p.blackKingSquare, s,
BLACK)]) {
case RESULT_LOSS:
return RESULT_WIN;
case RESULT_UNKNOWN:
unknownFound = true;
break;
case RESULT_DRAW: case RESULT_INVALID:
break;
default:
assert(false);
}
if(square_rank(s) == RANK_3 &&
s != p.whiteKingSquare && s != p.blackKingSquare) {
s += DELTA_N;
switch(Bitbase[compute_index(p.whiteKingSquare, p.blackKingSquare, s,
BLACK)]) {
case RESULT_LOSS:
return RESULT_WIN;
case RESULT_UNKNOWN:
unknownFound = true;
break;
case RESULT_DRAW: case RESULT_INVALID:
break;
default:
assert(false);
}
}
}
return unknownFound? RESULT_UNKNOWN : RESULT_DRAW;
}
Result classify_btm(const KPKPosition &p) {
// If one move leads to a position classified as RESULT_DRAW, the result
// of the current position is RESULT_DRAW. If all moves lead to positions
// classified as RESULT_WIN, the current position is classified as
// RESULT_LOSS. Otherwise, the current position is classified as
// RESULT_UNKNOWN.
bool unknownFound = false;
Bitboard b;
Square s;
// King moves
b = p.bk_attacks();
while(b) {
s = pop_1st_bit(&b);
switch(Bitbase[compute_index(p.whiteKingSquare, s, p.pawnSquare,
WHITE)]) {
case RESULT_DRAW:
return RESULT_DRAW;
case RESULT_UNKNOWN:
unknownFound = true;
break;
case RESULT_WIN: case RESULT_INVALID:
break;
default:
assert(false);
}
}
return unknownFound? RESULT_UNKNOWN : RESULT_LOSS;
}
int compute_index(Square wksq, Square bksq, Square psq, Color stm) {
int p = int(square_file(psq)) + (int(square_rank(psq)) - 1) * 4;
int result = int(stm) + 2*int(bksq) + 128*int(wksq) + 8192*p;
assert(result >= 0 && result < IndexMax);
return result;
}
int compress_result(Result r) {
return (r == RESULT_WIN || r == RESULT_LOSS)? 1 : 0;
}
}
} // namespace
+293 -510
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,528 +17,311 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <iostream>
#include <algorithm>
#include <cstring> // For memset
#include "bitboard.h"
#include "bitcount.h"
#include "direction.h"
#if defined(IS_64BIT)
const uint64_t BMult[64] = {
0x440049104032280ULL, 0x1021023c82008040ULL, 0x404040082000048ULL,
0x48c4440084048090ULL, 0x2801104026490000ULL, 0x4100880442040800ULL,
0x181011002e06040ULL, 0x9101004104200e00ULL, 0x1240848848310401ULL,
0x2000142828050024ULL, 0x1004024d5000ULL, 0x102044400800200ULL,
0x8108108820112000ULL, 0xa880818210c00046ULL, 0x4008008801082000ULL,
0x60882404049400ULL, 0x104402004240810ULL, 0xa002084250200ULL,
0x100b0880801100ULL, 0x4080201220101ULL, 0x44008080a00000ULL,
0x202200842000ULL, 0x5006004882d00808ULL, 0x200045080802ULL,
0x86100020200601ULL, 0xa802080a20112c02ULL, 0x80411218080900ULL,
0x200a0880080a0ULL, 0x9a01010000104000ULL, 0x28008003100080ULL,
0x211021004480417ULL, 0x401004188220806ULL, 0x825051400c2006ULL,
0x140c0210943000ULL, 0x242800300080ULL, 0xc2208120080200ULL,
0x2430008200002200ULL, 0x1010100112008040ULL, 0x8141050100020842ULL,
0x822081014405ULL, 0x800c049e40400804ULL, 0x4a0404028a000820ULL,
0x22060201041200ULL, 0x360904200840801ULL, 0x881a08208800400ULL,
0x60202c00400420ULL, 0x1204440086061400ULL, 0x8184042804040ULL,
0x64040315300400ULL, 0xc01008801090a00ULL, 0x808010401140c00ULL,
0x4004830c2020040ULL, 0x80005002020054ULL, 0x40000c14481a0490ULL,
0x10500101042048ULL, 0x1010100200424000ULL, 0x640901901040ULL,
0xa0201014840ULL, 0x840082aa011002ULL, 0x10010840084240aULL,
0x420400810420608ULL, 0x8d40230408102100ULL, 0x4a00200612222409ULL,
0xa08520292120600ULL
};
const uint64_t RMult[64] = {
0xa8002c000108020ULL, 0x4440200140003000ULL, 0x8080200010011880ULL,
0x380180080141000ULL, 0x1a00060008211044ULL, 0x410001000a0c0008ULL,
0x9500060004008100ULL, 0x100024284a20700ULL, 0x802140008000ULL,
0x80c01002a00840ULL, 0x402004282011020ULL, 0x9862000820420050ULL,
0x1001448011100ULL, 0x6432800200800400ULL, 0x40100010002000cULL,
0x2800d0010c080ULL, 0x90c0008000803042ULL, 0x4010004000200041ULL,
0x3010010200040ULL, 0xa40828028001000ULL, 0x123010008000430ULL,
0x24008004020080ULL, 0x60040001104802ULL, 0x582200028400d1ULL,
0x4000802080044000ULL, 0x408208200420308ULL, 0x610038080102000ULL,
0x3601000900100020ULL, 0x80080040180ULL, 0xc2020080040080ULL,
0x80084400100102ULL, 0x4022408200014401ULL, 0x40052040800082ULL,
0xb08200280804000ULL, 0x8a80a008801000ULL, 0x4000480080801000ULL,
0x911808800801401ULL, 0x822a003002001894ULL, 0x401068091400108aULL,
0x4a10a00004cULL, 0x2000800640008024ULL, 0x1486408102020020ULL,
0x100a000d50041ULL, 0x810050020b0020ULL, 0x204000800808004ULL,
0x20048100a000cULL, 0x112000831020004ULL, 0x9000040810002ULL,
0x440490200208200ULL, 0x8910401000200040ULL, 0x6404200050008480ULL,
0x4b824a2010010100ULL, 0x4080801810c0080ULL, 0x400802a0080ULL,
0x8224080110026400ULL, 0x40002c4104088200ULL, 0x1002100104a0282ULL,
0x1208400811048021ULL, 0x3201014a40d02001ULL, 0x5100019200501ULL,
0x101000208001005ULL, 0x2008450080702ULL, 0x1002080301d00cULL,
0x410201ce5c030092ULL
};
const int BShift[64] = {
58, 59, 59, 59, 59, 59, 59, 58, 59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 57, 57, 57, 57, 59, 59, 59, 59, 57, 55, 55, 57, 59, 59,
59, 59, 57, 55, 55, 57, 59, 59, 59, 59, 57, 57, 57, 57, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 58, 59, 59, 59, 59, 59, 59, 58
};
const int RShift[64] = {
52, 53, 53, 53, 53, 53, 53, 52, 53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53, 53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53, 53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53, 52, 53, 53, 53, 53, 53, 53, 52
};
#else // if !defined(IS_64BIT)
const uint64_t BMult[64] = {
0x54142844c6a22981ULL, 0x710358a6ea25c19eULL, 0x704f746d63a4a8dcULL,
0xbfed1a0b80f838c5ULL, 0x90561d5631e62110ULL, 0x2804260376e60944ULL,
0x84a656409aa76871ULL, 0xf0267f64c28b6197ULL, 0x70764ebb762f0585ULL,
0x92aa09e0cfe161deULL, 0x41ee1f6bb266f60eULL, 0xddcbf04f6039c444ULL,
0x5a3fab7bac0d988aULL, 0xd3727877fa4eaa03ULL, 0xd988402d868ddaaeULL,
0x812b291afa075c7cULL, 0x94faf987b685a932ULL, 0x3ed867d8470d08dbULL,
0x92517660b8901de8ULL, 0x2d97e43e058814b4ULL, 0x880a10c220b25582ULL,
0xc7c6520d1f1a0477ULL, 0xdbfc7fbcd7656aa6ULL, 0x78b1b9bfb1a2b84fULL,
0x2f20037f112a0bc1ULL, 0x657171ea2269a916ULL, 0xc08302b07142210eULL,
0x880a4403064080bULL, 0x3602420842208c00ULL, 0x852800dc7e0b6602ULL,
0x595a3fbbaa0f03b2ULL, 0x9f01411558159d5eULL, 0x2b4a4a5f88b394f2ULL,
0x4afcbffc292dd03aULL, 0x4a4094a3b3f10522ULL, 0xb06f00b491f30048ULL,
0xd5b3820280d77004ULL, 0x8b2e01e7c8e57a75ULL, 0x2d342794e886c2e6ULL,
0xc302c410cde21461ULL, 0x111f426f1379c274ULL, 0xe0569220abb31588ULL,
0x5026d3064d453324ULL, 0xe2076040c343cd8aULL, 0x93efd1e1738021eeULL,
0xb680804bed143132ULL, 0x44e361b21986944cULL, 0x44c60170ef5c598cULL,
0xf4da475c195c9c94ULL, 0xa3afbb5f72060b1dULL, 0xbc75f410e41c4ffcULL,
0xb51c099390520922ULL, 0x902c011f8f8ec368ULL, 0x950b56b3d6f5490aULL,
0x3909e0635bf202d0ULL, 0x5744f90206ec10ccULL, 0xdc59fd76317abbc1ULL,
0x881c7c67fcbfc4f6ULL, 0x47ca41e7e440d423ULL, 0xeb0c88112048d004ULL,
0x51c60e04359aef1aULL, 0x1aa1fe0e957a5554ULL, 0xdd9448db4f5e3104ULL,
0xdc01f6dca4bebbdcULL,
};
const uint64_t RMult[64] = {
0xd7445cdec88002c0ULL, 0xd0a505c1f2001722ULL, 0xe065d1c896002182ULL,
0x9a8c41e75a000892ULL, 0x8900b10c89002aa8ULL, 0x9b28d1c1d60005a2ULL,
0x15d6c88de002d9aULL, 0xb1dbfc802e8016a9ULL, 0x149a1042d9d60029ULL,
0xb9c08050599e002fULL, 0x132208c3af300403ULL, 0xc1000ce2e9c50070ULL,
0x9d9aa13c99020012ULL, 0xb6b078daf71e0046ULL, 0x9d880182fb6e002eULL,
0x52889f467e850037ULL, 0xda6dc008d19a8480ULL, 0x468286034f902420ULL,
0x7140ac09dc54c020ULL, 0xd76ffffa39548808ULL, 0xea901c4141500808ULL,
0xc91004093f953a02ULL, 0x2882afa8f6bb402ULL, 0xaebe335692442c01ULL,
0xe904a22079fb91eULL, 0x13a514851055f606ULL, 0x76c782018c8fe632ULL,
0x1dc012a9d116da06ULL, 0x3c9e0037264fffa6ULL, 0x2036002853c6e4a2ULL,
0xe3fe08500afb47d4ULL, 0xf38af25c86b025c2ULL, 0xc0800e2182cf9a40ULL,
0x72002480d1f60673ULL, 0x2500200bae6e9b53ULL, 0xc60018c1eefca252ULL,
0x600590473e3608aULL, 0x46002c4ab3fe51b2ULL, 0xa200011486bcc8d2ULL,
0xb680078095784c63ULL, 0x2742002639bf11aeULL, 0xc7d60021a5bdb142ULL,
0xc8c04016bb83d820ULL, 0xbd520028123b4842ULL, 0x9d1600344ac2a832ULL,
0x6a808005631c8a05ULL, 0x604600a148d5389aULL, 0xe2e40103d40dea65ULL,
0x945b5a0087c62a81ULL, 0x12dc200cd82d28eULL, 0x2431c600b5f9ef76ULL,
0xfb142a006a9b314aULL, 0x6870e00a1c97d62ULL, 0x2a9db2004a2689a2ULL,
0xd3594600caf5d1a2ULL, 0xee0e4900439344a7ULL, 0x89c4d266ca25007aULL,
0x3e0013a2743f97e3ULL, 0x180e31a0431378aULL, 0x3a9e465a4d42a512ULL,
0x98d0a11a0c0d9cc2ULL, 0x8e711c1aba19b01eULL, 0x8dcdc836dd201142ULL,
0x5ac08a4735370479ULL,
};
const int BShift[64] = {
26, 27, 27, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 25, 25, 25, 25, 27, 27, 27, 27, 25, 23, 23, 25, 27, 27,
27, 27, 25, 23, 23, 25, 27, 27, 27, 27, 25, 25, 25, 25, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 26, 27, 27, 27, 27, 27, 27, 26
};
const int RShift[64] = {
20, 21, 21, 21, 21, 21, 21, 20, 21, 22, 22, 22, 22, 22, 22, 21,
21, 22, 22, 22, 22, 22, 22, 21, 21, 22, 22, 22, 22, 22, 22, 21,
21, 22, 22, 22, 22, 22, 22, 21, 21, 22, 22, 22, 22, 22, 22, 21,
21, 22, 22, 22, 22, 22, 22, 21, 20, 21, 21, 21, 21, 21, 21, 20
};
#endif // defined(IS_64BIT)
const Bitboard SquaresByColorBB[2] = { BlackSquaresBB, WhiteSquaresBB };
const Bitboard FileBB[8] = {
FileABB, FileBBB, FileCBB, FileDBB, FileEBB, FileFBB, FileGBB, FileHBB
};
const Bitboard NeighboringFilesBB[8] = {
FileBBB, FileABB|FileCBB, FileBBB|FileDBB, FileCBB|FileEBB,
FileDBB|FileFBB, FileEBB|FileGBB, FileFBB|FileHBB, FileGBB
};
const Bitboard ThisAndNeighboringFilesBB[8] = {
FileABB|FileBBB, FileABB|FileBBB|FileCBB,
FileBBB|FileCBB|FileDBB, FileCBB|FileDBB|FileEBB,
FileDBB|FileEBB|FileFBB, FileEBB|FileFBB|FileGBB,
FileFBB|FileGBB|FileHBB, FileGBB|FileHBB
};
const Bitboard RankBB[8] = {
Rank1BB, Rank2BB, Rank3BB, Rank4BB, Rank5BB, Rank6BB, Rank7BB, Rank8BB
};
const Bitboard RelativeRankBB[2][8] = {
{ Rank1BB, Rank2BB, Rank3BB, Rank4BB, Rank5BB, Rank6BB, Rank7BB, Rank8BB },
{ Rank8BB, Rank7BB, Rank6BB, Rank5BB, Rank4BB, Rank3BB, Rank2BB, Rank1BB }
};
const Bitboard InFrontBB[2][8] = {
{ Rank2BB | Rank3BB | Rank4BB | Rank5BB | Rank6BB | Rank7BB | Rank8BB,
Rank3BB | Rank4BB | Rank5BB | Rank6BB | Rank7BB | Rank8BB,
Rank4BB | Rank5BB | Rank6BB | Rank7BB | Rank8BB,
Rank5BB | Rank6BB | Rank7BB | Rank8BB,
Rank6BB | Rank7BB | Rank8BB,
Rank7BB | Rank8BB,
Rank8BB,
EmptyBoardBB
},
{ EmptyBoardBB,
Rank1BB,
Rank2BB | Rank1BB,
Rank3BB | Rank2BB | Rank1BB,
Rank4BB | Rank3BB | Rank2BB | Rank1BB,
Rank5BB | Rank4BB | Rank3BB | Rank2BB | Rank1BB,
Rank6BB | Rank5BB | Rank4BB | Rank3BB | Rank2BB | Rank1BB,
Rank7BB | Rank6BB | Rank5BB | Rank4BB | Rank3BB | Rank2BB | Rank1BB
}
};
Bitboard RMask[64];
int RAttackIndex[64];
Bitboard RAttacks[0x19000];
Bitboard BMask[64];
int BAttackIndex[64];
Bitboard BAttacks[0x1480];
Bitboard SetMaskBB[65];
Bitboard ClearMaskBB[65];
Bitboard StepAttackBB[16][64];
Bitboard RayBB[64][8];
Bitboard BetweenBB[64][64];
Bitboard PassedPawnMask[2][64];
Bitboard OutpostMask[2][64];
Bitboard BishopPseudoAttacks[64];
Bitboard RookPseudoAttacks[64];
Bitboard QueenPseudoAttacks[64];
uint8_t BitCount8Bit[256];
////
//// Local definitions
////
namespace {
void init_masks();
void init_ray_bitboards();
void init_attacks();
void init_between_bitboards();
Bitboard sliding_attacks(int sq, Bitboard block, int dirs, int deltas[][2],
int fmin, int fmax, int rmin, int rmax);
Bitboard index_to_bitboard(int index, Bitboard mask);
void init_sliding_attacks(Bitboard attacks[],
int attackIndex[], Bitboard mask[],
const int shift[2], const Bitboard mult[],
int deltas[][2]);
void init_pseudo_attacks();
}
////
//// Functions
////
/// print_bitboard() prints a bitboard in an easily readable format to the
/// standard output. This is sometimes useful for debugging.
void print_bitboard(Bitboard b) {
for(Rank r = RANK_8; r >= RANK_1; r--) {
std::cout << "+---+---+---+---+---+---+---+---+" << std::endl;
for(File f = FILE_A; f <= FILE_H; f++)
std::cout << "| " << (bit_is_set(b, make_square(f, r))? 'X' : ' ') << ' ';
std::cout << "|" << std::endl;
}
std::cout << "+---+---+---+---+---+---+---+---+" << std::endl;
}
/// init_bitboards() initializes various bitboard arrays. It is called during
/// program initialization.
void init_bitboards() {
int rookDeltas[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
int bishopDeltas[4][2] = {{1,1},{-1,1},{1,-1},{-1,-1}};
init_masks();
init_ray_bitboards();
init_attacks();
init_between_bitboards();
init_sliding_attacks(RAttacks, RAttackIndex, RMask, RShift, RMult, rookDeltas);
init_sliding_attacks(BAttacks, BAttackIndex, BMask, BShift, BMult, bishopDeltas);
init_pseudo_attacks();
}
/// first_1() finds the least significant nonzero bit in a nonzero bitboard.
/// pop_1st_bit() finds and clears the least significant nonzero bit in a
/// nonzero bitboard.
#if defined(IS_64BIT) && !defined(USE_BSFQ)
#include "rkiss.h"
CACHE_LINE_ALIGNMENT
static const int BitTable[64] = {
0, 1, 2, 7, 3, 13, 8, 19, 4, 25, 14, 28, 9, 34, 20, 40, 5, 17, 26, 38, 15,
46, 29, 48, 10, 31, 35, 54, 21, 50, 41, 57, 63, 6, 12, 18, 24, 27, 33, 39,
16, 37, 45, 47, 30, 53, 49, 56, 62, 11, 23, 32, 36, 44, 52, 55, 61, 22, 43,
51, 60, 42, 59, 58
};
Square first_1(Bitboard b) {
return Square(BitTable[((b & -b) * 0x218a392cd3d5dbfULL) >> 58]);
}
Bitboard RMasks[SQUARE_NB];
Bitboard RMagics[SQUARE_NB];
Bitboard* RAttacks[SQUARE_NB];
unsigned RShifts[SQUARE_NB];
Square pop_1st_bit(Bitboard* b) {
Bitboard bb = *b;
*b &= (*b - 1);
return Square(BitTable[((bb & -bb) * 0x218a392cd3d5dbfULL) >> 58]);
}
Bitboard BMasks[SQUARE_NB];
Bitboard BMagics[SQUARE_NB];
Bitboard* BAttacks[SQUARE_NB];
unsigned BShifts[SQUARE_NB];
#elif !defined(USE_BSFQ)
Bitboard SquareBB[SQUARE_NB];
Bitboard FileBB[FILE_NB];
Bitboard RankBB[RANK_NB];
Bitboard AdjacentFilesBB[FILE_NB];
Bitboard InFrontBB[COLOR_NB][RANK_NB];
Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
Bitboard LineBB[SQUARE_NB][SQUARE_NB];
Bitboard DistanceRingsBB[SQUARE_NB][8];
Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
static CACHE_LINE_ALIGNMENT
const int BitTable[64] = {
63, 30, 3, 32, 25, 41, 22, 33, 15, 50, 42, 13, 11, 53, 19, 34, 61, 29, 2,
51, 21, 43, 45, 10, 18, 47, 1, 54, 9, 57, 0, 35, 62, 31, 40, 4, 49, 5, 52,
26, 60, 6, 23, 44, 46, 27, 56, 16, 7, 39, 48, 24, 59, 14, 12, 55, 38, 28,
58, 20, 37, 17, 36, 8
};
Square first_1(Bitboard b) {
b ^= (b - 1);
uint32_t fold = int(b) ^ int(b >> 32);
return Square(BitTable[(fold * 0x783a9b23) >> 26]);
}
// Use type-punning
union b_union {
Bitboard b;
struct {
#if defined (BIGENDIAN)
uint32_t h;
uint32_t l;
#else
uint32_t l;
uint32_t h;
#endif
} dw;
};
Square pop_1st_bit(Bitboard* bb) {
b_union u;
Square ret;
u.b = *bb;
if (u.dw.l)
{
ret = Square(BitTable[((u.dw.l ^ (u.dw.l - 1)) * 0x783a9b23) >> 26]);
u.dw.l &= (u.dw.l - 1);
*bb = u.b;
return ret;
}
ret = Square(BitTable[((~(u.dw.h ^ (u.dw.h - 1))) * 0x783a9b23) >> 26]);
u.dw.h &= (u.dw.h - 1);
*bb = u.b;
return ret;
}
#endif
int bitScanReverse32(uint32_t b)
{
int result = 0;
if (b > 0xFFFF) {
b >>= 16;
result += 16;
}
if (b > 0xFF) {
b >>= 8;
result += 8;
}
if (b > 0xF) {
b >>= 4;
result += 4;
}
if (b > 0x3) {
b >>= 2;
result += 2;
}
return result + (b > 0) + (b > 1);
}
int SquareDistance[SQUARE_NB][SQUARE_NB];
namespace {
// All functions below are used to precompute various bitboards during
// program initialization. Some of the functions may be difficult to
// understand, but they all seem to work correctly, and it should never
// be necessary to touch any of them.
// De Bruijn sequences. See chessprogramming.wikispaces.com/BitScan
const uint64_t DeBruijn_64 = 0x3F79D71B4CB0A89ULL;
const uint32_t DeBruijn_32 = 0x783A9B23;
void init_masks() {
SetMaskBB[SQ_NONE] = 0ULL;
ClearMaskBB[SQ_NONE] = ~SetMaskBB[SQ_NONE];
for(Square s = SQ_A1; s <= SQ_H8; s++) {
SetMaskBB[s] = (1ULL << s);
ClearMaskBB[s] = ~SetMaskBB[s];
}
for(Color c = WHITE; c <= BLACK; c++)
for(Square s = SQ_A1; s <= SQ_H8; s++) {
PassedPawnMask[c][s] =
in_front_bb(c, s) & this_and_neighboring_files_bb(s);
OutpostMask[c][s] = in_front_bb(c, s) & neighboring_files_bb(s);
}
CACHE_LINE_ALIGNMENT
for (Bitboard b = 0ULL; b < 256ULL; b++)
BitCount8Bit[b] = (uint8_t)count_1s(b);
int MS1BTable[256];
Square BSFTable[SQUARE_NB];
Bitboard RTable[0x19000]; // Storage space for rook attacks
Bitboard BTable[0x1480]; // Storage space for bishop attacks
typedef unsigned (Fn)(Square, Bitboard);
void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
Bitboard masks[], unsigned shifts[], Square deltas[], Fn index);
FORCE_INLINE unsigned bsf_index(Bitboard b) {
// Matt Taylor's folding for 32 bit systems, extended to 64 bits by Kim Walisch
b ^= (b - 1);
return Is64Bit ? (b * DeBruijn_64) >> 58
: ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn_32) >> 26;
}
}
/// lsb()/msb() finds the least/most significant bit in a non-zero bitboard.
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard.
#ifndef USE_BSFQ
Square lsb(Bitboard b) { return BSFTable[bsf_index(b)]; }
Square pop_lsb(Bitboard* b) {
Bitboard bb = *b;
*b = bb & (bb - 1);
return BSFTable[bsf_index(bb)];
}
Square msb(Bitboard b) {
unsigned b32;
int result = 0;
if (b > 0xFFFFFFFF)
{
b >>= 32;
result = 32;
}
b32 = unsigned(b);
if (b32 > 0xFFFF)
{
b32 >>= 16;
result += 16;
}
if (b32 > 0xFF)
{
b32 >>= 8;
result += 8;
}
return Square(result + MS1BTable[b32]);
}
#endif // ifndef USE_BSFQ
/// Bitboards::pretty() returns an ASCII representation of a bitboard to be
/// printed to standard output. This is sometimes useful for debugging.
const std::string Bitboards::pretty(Bitboard b) {
std::string s = "+---+---+---+---+---+---+---+---+\n";
for (Rank r = RANK_8; r >= RANK_1; --r)
{
for (File f = FILE_A; f <= FILE_H; ++f)
s.append(b & make_square(f, r) ? "| X " : "| ");
s.append("|\n+---+---+---+---+---+---+---+---+\n");
}
return s;
}
/// Bitboards::init() initializes various bitboard tables. It is called at
/// startup and relies on global objects to be already zero-initialized.
void Bitboards::init() {
for (Square s = SQ_A1; s <= SQ_H8; ++s)
BSFTable[bsf_index(SquareBB[s] = 1ULL << s)] = s;
for (Bitboard b = 1; b < 256; ++b)
MS1BTable[b] = more_than_one(b) ? MS1BTable[b - 1] : lsb(b);
for (File f = FILE_A; f <= FILE_H; ++f)
FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB;
for (Rank r = RANK_1; r <= RANK_8; ++r)
RankBB[r] = r > RANK_1 ? RankBB[r - 1] << 8 : Rank1BB;
for (File f = FILE_A; f <= FILE_H; ++f)
AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0);
for (Rank r = RANK_1; r < RANK_8; ++r)
InFrontBB[WHITE][r] = ~(InFrontBB[BLACK][r + 1] = InFrontBB[BLACK][r] | RankBB[r]);
for (Color c = WHITE; c <= BLACK; ++c)
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
ForwardBB[c][s] = InFrontBB[c][rank_of(s)] & FileBB[file_of(s)];
PawnAttackSpan[c][s] = InFrontBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)];
PassedPawnMask[c][s] = ForwardBB[c][s] | PawnAttackSpan[c][s];
}
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
if (s1 != s2)
{
SquareDistance[s1][s2] = std::max(file_distance(s1, s2), rank_distance(s1, s2));
DistanceRingsBB[s1][SquareDistance[s1][s2] - 1] |= s2;
}
int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 },
{}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } };
for (Color c = WHITE; c <= BLACK; ++c)
for (PieceType pt = PAWN; pt <= KING; ++pt)
for (Square s = SQ_A1; s <= SQ_H8; ++s)
for (int i = 0; steps[pt][i]; ++i)
{
Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]);
if (is_ok(to) && square_distance(s, to) < 3)
StepAttacksBB[make_piece(c, pt)][s] |= to;
}
Square RDeltas[] = { DELTA_N, DELTA_E, DELTA_S, DELTA_W };
Square BDeltas[] = { DELTA_NE, DELTA_SE, DELTA_SW, DELTA_NW };
init_magics(RTable, RAttacks, RMagics, RMasks, RShifts, RDeltas, magic_index<ROOK>);
init_magics(BTable, BAttacks, BMagics, BMasks, BShifts, BDeltas, magic_index<BISHOP>);
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
{
PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0);
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
{
Piece pc = (PseudoAttacks[BISHOP][s1] & s2) ? W_BISHOP :
(PseudoAttacks[ROOK][s1] & s2) ? W_ROOK : NO_PIECE;
if (pc == NO_PIECE)
continue;
LineBB[s1][s2] = (attacks_bb(pc, s1, 0) & attacks_bb(pc, s2, 0)) | s1 | s2;
BetweenBB[s1][s2] = attacks_bb(pc, s1, SquareBB[s2]) & attacks_bb(pc, s2, SquareBB[s1]);
}
}
}
namespace {
Bitboard sliding_attack(Square deltas[], Square sq, Bitboard occupied) {
Bitboard attack = 0;
for (int i = 0; i < 4; ++i)
for (Square s = sq + deltas[i];
is_ok(s) && square_distance(s, s - deltas[i]) == 1;
s += deltas[i])
{
attack |= s;
if (occupied & s)
break;
}
return attack;
}
// init_magics() computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
// use the so called "fancy" approach.
void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[],
Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) {
int MagicBoosters[][8] = { { 969, 1976, 2850, 542, 2069, 2852, 1708, 164 },
{ 3101, 552, 3555, 926, 834, 26, 2131, 1117 } };
RKISS rk;
Bitboard occupancy[4096], reference[4096], edges, b;
int i, size, booster;
// attacks[s] is a pointer to the beginning of the attacks table for square 's'
attacks[SQ_A1] = table;
for (Square s = SQ_A1; s <= SQ_H8; ++s)
{
// Board edges are not considered in the relevant occupancies
edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
// Given a square 's', the mask is the bitboard of sliding attacks from
// 's' computed on an empty board. The index must be big enough to contain
// all the attacks for each possible subset of the mask and so is 2 power
// the number of 1s of the mask. Hence we deduce the size of the shift to
// apply to the 64 or 32 bits word to get the index.
masks[s] = sliding_attack(deltas, s, 0) & ~edges;
shifts[s] = (Is64Bit ? 64 : 32) - popcount<Max15>(masks[s]);
// Use Carry-Rippler trick to enumerate all subsets of masks[s] and
// store the corresponding sliding attack bitboard in reference[].
b = size = 0;
do {
occupancy[size] = b;
reference[size] = sliding_attack(deltas, s, b);
if (HasPext)
attacks[s][_pext_u64(b, masks[s])] = reference[size];
size++;
b = (b - masks[s]) & masks[s];
} while (b);
// Set the offset for the table of the next square. We have individual
// table sizes for each square with "Fancy Magic Bitboards".
if (s < SQ_H8)
attacks[s + 1] = attacks[s] + size;
if (HasPext)
continue;
booster = MagicBoosters[Is64Bit][rank_of(s)];
// Find a magic for square 's' picking up an (almost) random number
// until we find the one that passes the verification test.
do {
do magics[s] = rk.magic_rand<Bitboard>(booster);
while (popcount<Max15>((magics[s] * masks[s]) >> 56) < 6);
std::memset(attacks[s], 0, size * sizeof(Bitboard));
// A good magic must map every possible occupancy to an index that
// looks up the correct sliding attack in the attacks[s] database.
// Note that we build up the database for square 's' as a side
// effect of verifying the magic.
for (i = 0; i < size; ++i)
{
Bitboard& attack = attacks[s][index(s, occupancy[i])];
if (attack && attack != reference[i])
break;
assert(reference[i]);
attack = reference[i];
}
} while (i < size);
}
}
void init_ray_bitboards() {
int d[8] = {1, -1, 16, -16, 17, -17, 15, -15};
for(int i = 0; i < 128; i = (i + 9) & ~8) {
for(int j = 0; j < 8; j++) {
RayBB[(i&7)|((i>>4)<<3)][j] = EmptyBoardBB;
for(int k = i + d[j]; (k & 0x88) == 0; k += d[j])
set_bit(&(RayBB[(i&7)|((i>>4)<<3)][j]), Square((k&7)|((k>>4)<<3)));
}
}
}
void init_attacks() {
int i, j, k, l;
int step[16][8] = {
{0},
{7,9,0}, {17,15,10,6,-6,-10,-15,-17}, {9,7,-7,-9,0}, {8,1,-1,-8,0},
{9,7,-7,-9,8,1,-1,-8}, {9,7,-7,-9,8,1,-1,-8}, {0}, {0},
{-7,-9,0}, {17,15,10,6,-6,-10,-15,-17}, {9,7,-7,-9,0}, {8,1,-1,-8,0},
{9,7,-7,-9,8,1,-1,-8}, {9,7,-7,-9,8,1,-1,-8}
};
for(i = 0; i < 64; i++) {
for(j = 0; j <= int(BK); j++) {
StepAttackBB[j][i] = EmptyBoardBB;
for(k = 0; k < 8 && step[j][k] != 0; k++) {
l = i + step[j][k];
if(l >= 0 && l < 64 && abs((i&7) - (l&7)) < 3)
StepAttackBB[j][i] |= (1ULL << l);
}
}
}
}
Bitboard sliding_attacks(int sq, Bitboard block, int dirs, int deltas[][2],
int fmin=0, int fmax=7, int rmin=0, int rmax=7) {
Bitboard result = 0ULL;
int rk = sq / 8, fl = sq % 8, r, f, i;
for(i = 0; i < dirs; i++) {
int dx = deltas[i][0], dy = deltas[i][1];
for(f = fl+dx, r = rk+dy;
(dx==0 || (f>=fmin && f<=fmax)) && (dy==0 || (r>=rmin && r<=rmax));
f += dx, r += dy) {
result |= (1ULL << (f + r*8));
if(block & (1ULL << (f + r*8))) break;
}
}
return result;
}
void init_between_bitboards() {
SquareDelta step[8] = {
DELTA_E, DELTA_W, DELTA_N, DELTA_S, DELTA_NE, DELTA_SW, DELTA_NW, DELTA_SE
};
SignedDirection d;
for(Square s1 = SQ_A1; s1 <= SQ_H8; s1++)
for(Square s2 = SQ_A1; s2 <= SQ_H8; s2++) {
BetweenBB[s1][s2] = EmptyBoardBB;
d = signed_direction_between_squares(s1, s2);
if(d != SIGNED_DIR_NONE)
for(Square s3 = s1 + step[d]; s3 != s2; s3 += step[d])
set_bit(&(BetweenBB[s1][s2]), s3);
}
}
Bitboard index_to_bitboard(int index, Bitboard mask) {
int i, j, bits = count_1s(mask);
Bitboard result = 0ULL;
for(i = 0; i < bits; i++) {
j = pop_1st_bit(&mask);
if(index & (1 << i)) result |= (1ULL << j);
}
return result;
}
void init_sliding_attacks(Bitboard attacks[],
int attackIndex[], Bitboard mask[],
const int shift[2], const Bitboard mult[],
int deltas[][2]) {
int i, j, k, index = 0;
Bitboard b;
for(i = 0; i < 64; i++) {
attackIndex[i] = index;
mask[i] = sliding_attacks(i, 0ULL, 4, deltas, 1, 6, 1, 6);
#if defined(IS_64BIT)
j = (1 << (64 - shift[i]));
#else
j = (1 << (32 - shift[i]));
#endif
for(k = 0; k < j; k++) {
#if defined(IS_64BIT)
b = index_to_bitboard(k, mask[i]);
attacks[index + ((b * mult[i]) >> shift[i])] =
sliding_attacks(i, b, 4, deltas);
#else
b = index_to_bitboard(k, mask[i]);
attacks[index +
(unsigned(int(b) * int(mult[i]) ^
int(b >> 32) * int(mult[i] >> 32))
>> shift[i])] =
sliding_attacks(i, b, 4, deltas);
#endif
}
index += j;
}
}
void init_pseudo_attacks() {
Square s;
for(s = SQ_A1; s <= SQ_H8; s++) {
BishopPseudoAttacks[s] = bishop_attacks_bb(s, EmptyBoardBB);
RookPseudoAttacks[s] = rook_attacks_bb(s, EmptyBoardBB);
QueenPseudoAttacks[s] = queen_attacks_bb(s, EmptyBoardBB);
}
}
}
+226 -240
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,125 +18,134 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(BITBOARD_H_INCLUDED)
#ifndef BITBOARD_H_INCLUDED
#define BITBOARD_H_INCLUDED
////
//// Includes
////
#include "direction.h"
#include "piece.h"
#include "square.h"
#include "types.h"
namespace Bitboards {
////
//// Constants and variables
////
void init();
const std::string pretty(Bitboard b);
const Bitboard EmptyBoardBB = 0ULL;
}
const Bitboard WhiteSquaresBB = 0x55AA55AA55AA55AAULL;
const Bitboard BlackSquaresBB = 0xAA55AA55AA55AA55ULL;
namespace Bitbases {
void init_kpk();
bool probe_kpk(Square wksq, Square wpsq, Square bksq, Color us);
}
const Bitboard FileABB = 0x0101010101010101ULL;
const Bitboard FileBBB = 0x0202020202020202ULL;
const Bitboard FileCBB = 0x0404040404040404ULL;
const Bitboard FileDBB = 0x0808080808080808ULL;
const Bitboard FileEBB = 0x1010101010101010ULL;
const Bitboard FileFBB = 0x2020202020202020ULL;
const Bitboard FileGBB = 0x4040404040404040ULL;
const Bitboard FileHBB = 0x8080808080808080ULL;
const Bitboard FileBBB = FileABB << 1;
const Bitboard FileCBB = FileABB << 2;
const Bitboard FileDBB = FileABB << 3;
const Bitboard FileEBB = FileABB << 4;
const Bitboard FileFBB = FileABB << 5;
const Bitboard FileGBB = FileABB << 6;
const Bitboard FileHBB = FileABB << 7;
const Bitboard Rank1BB = 0xFFULL;
const Bitboard Rank2BB = 0xFF00ULL;
const Bitboard Rank3BB = 0xFF0000ULL;
const Bitboard Rank4BB = 0xFF000000ULL;
const Bitboard Rank5BB = 0xFF00000000ULL;
const Bitboard Rank6BB = 0xFF0000000000ULL;
const Bitboard Rank7BB = 0xFF000000000000ULL;
const Bitboard Rank8BB = 0xFF00000000000000ULL;
const Bitboard Rank1BB = 0xFF;
const Bitboard Rank2BB = Rank1BB << (8 * 1);
const Bitboard Rank3BB = Rank1BB << (8 * 2);
const Bitboard Rank4BB = Rank1BB << (8 * 3);
const Bitboard Rank5BB = Rank1BB << (8 * 4);
const Bitboard Rank6BB = Rank1BB << (8 * 5);
const Bitboard Rank7BB = Rank1BB << (8 * 6);
const Bitboard Rank8BB = Rank1BB << (8 * 7);
extern const Bitboard SquaresByColorBB[2];
extern const Bitboard FileBB[8];
extern const Bitboard NeighboringFilesBB[8];
extern const Bitboard ThisAndNeighboringFilesBB[8];
extern const Bitboard RankBB[8];
extern const Bitboard RelativeRankBB[2][8];
extern const Bitboard InFrontBB[2][8];
CACHE_LINE_ALIGNMENT
extern Bitboard SetMaskBB[65];
extern Bitboard ClearMaskBB[65];
extern Bitboard RMasks[SQUARE_NB];
extern Bitboard RMagics[SQUARE_NB];
extern Bitboard* RAttacks[SQUARE_NB];
extern unsigned RShifts[SQUARE_NB];
extern Bitboard StepAttackBB[16][64];
extern Bitboard RayBB[64][8];
extern Bitboard BetweenBB[64][64];
extern Bitboard BMasks[SQUARE_NB];
extern Bitboard BMagics[SQUARE_NB];
extern Bitboard* BAttacks[SQUARE_NB];
extern unsigned BShifts[SQUARE_NB];
extern Bitboard PassedPawnMask[2][64];
extern Bitboard OutpostMask[2][64];
extern Bitboard SquareBB[SQUARE_NB];
extern Bitboard FileBB[FILE_NB];
extern Bitboard RankBB[RANK_NB];
extern Bitboard AdjacentFilesBB[FILE_NB];
extern Bitboard InFrontBB[COLOR_NB][RANK_NB];
extern Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB];
extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
extern Bitboard DistanceRingsBB[SQUARE_NB][8];
extern Bitboard ForwardBB[COLOR_NB][SQUARE_NB];
extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB];
extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB];
extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
extern const uint64_t RMult[64];
extern const int RShift[64];
extern Bitboard RMask[64];
extern int RAttackIndex[64];
extern Bitboard RAttacks[0x19000];
extern int SquareDistance[SQUARE_NB][SQUARE_NB];
extern const uint64_t BMult[64];
extern const int BShift[64];
extern Bitboard BMask[64];
extern int BAttackIndex[64];
extern Bitboard BAttacks[0x1480];
const Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL;
extern Bitboard BishopPseudoAttacks[64];
extern Bitboard RookPseudoAttacks[64];
extern Bitboard QueenPseudoAttacks[64];
/// Overloads of bitwise operators between a Bitboard and a Square for testing
/// whether a given bit is set in a bitboard, and for setting and clearing bits.
extern uint8_t BitCount8Bit[256];
////
//// Inline functions
////
/// Functions for testing whether a given bit is set in a bitboard, and for
/// setting and clearing bits.
inline Bitboard bit_is_set(Bitboard b, Square s) {
return b & SetMaskBB[s];
inline Bitboard operator&(Bitboard b, Square s) {
return b & SquareBB[s];
}
inline void set_bit(Bitboard *b, Square s) {
*b |= SetMaskBB[s];
inline Bitboard& operator|=(Bitboard& b, Square s) {
return b |= SquareBB[s];
}
inline void clear_bit(Bitboard *b, Square s) {
*b &= ClearMaskBB[s];
inline Bitboard& operator^=(Bitboard& b, Square s) {
return b ^= SquareBB[s];
}
inline Bitboard operator|(Bitboard b, Square s) {
return b | SquareBB[s];
}
inline Bitboard operator^(Bitboard b, Square s) {
return b ^ SquareBB[s];
}
inline bool more_than_one(Bitboard b) {
return b & (b - 1);
}
inline int square_distance(Square s1, Square s2) {
return SquareDistance[s1][s2];
}
inline int file_distance(Square s1, Square s2) {
return abs(file_of(s1) - file_of(s2));
}
inline int rank_distance(Square s1, Square s2) {
return abs(rank_of(s1) - rank_of(s2));
}
/// Functions used to update a bitboard after a move. This is faster
/// then calling a sequence of clear_bit() + set_bit()
/// shift_bb() moves bitboard one step along direction Delta. Mainly for pawns.
inline Bitboard make_move_bb(Square from, Square to) {
return SetMaskBB[from] | SetMaskBB[to];
template<Square Delta>
inline Bitboard shift_bb(Bitboard b) {
return Delta == DELTA_N ? b << 8 : Delta == DELTA_S ? b >> 8
: Delta == DELTA_NE ? (b & ~FileHBB) << 9 : Delta == DELTA_SE ? (b & ~FileHBB) >> 7
: Delta == DELTA_NW ? (b & ~FileABB) << 7 : Delta == DELTA_SW ? (b & ~FileABB) >> 9
: 0;
}
inline void do_move_bb(Bitboard *b, Bitboard move_bb) {
*b ^= move_bb;
}
/// rank_bb() and file_bb() gives a bitboard containing all squares on a given
/// file or rank. It is also possible to pass a square as input to these
/// functions.
/// rank_bb() and file_bb() take a file or a square as input and return
/// a bitboard representing all squares on the given file or rank.
inline Bitboard rank_bb(Rank r) {
return RankBB[r];
}
inline Bitboard rank_bb(Square s) {
return rank_bb(square_rank(s));
return RankBB[rank_of(s)];
}
inline Bitboard file_bb(File f) {
@@ -144,212 +153,189 @@ inline Bitboard file_bb(File f) {
}
inline Bitboard file_bb(Square s) {
return file_bb(square_file(s));
return FileBB[file_of(s)];
}
/// neighboring_files_bb takes a file or a square as input, and returns a
/// bitboard representing all squares on the neighboring files.
/// adjacent_files_bb() takes a file as input and returns a bitboard representing
/// all squares on the adjacent files.
inline Bitboard neighboring_files_bb(File f) {
return NeighboringFilesBB[f];
}
inline Bitboard neighboring_files_bb(Square s) {
return neighboring_files_bb(square_file(s));
inline Bitboard adjacent_files_bb(File f) {
return AdjacentFilesBB[f];
}
/// this_and_neighboring_files_bb takes a file or a square as input, and
/// returns a bitboard representing all squares on the given and neighboring
/// files.
inline Bitboard this_and_neighboring_files_bb(File f) {
return ThisAndNeighboringFilesBB[f];
}
inline Bitboard this_and_neighboring_files_bb(Square s) {
return this_and_neighboring_files_bb(square_file(s));
}
/// relative_rank_bb() takes a color and a rank as input, and returns a bitboard
/// representing all squares on the given rank from the given color's point of
/// view. For instance, relative_rank_bb(WHITE, 7) gives all squares on the
/// 7th rank, while relative_rank_bb(BLACK, 7) gives all squares on the 2nd
/// rank.
inline Bitboard relative_rank_bb(Color c, Rank r) {
return RelativeRankBB[c][r];
}
/// in_front_bb() takes a color and a rank or square as input, and returns a
/// bitboard representing all the squares on all ranks in front of the rank
/// (or square), from the given color's point of view. For instance,
/// in_front_bb(WHITE, RANK_5) will give all squares on ranks 6, 7 and 8, while
/// in_front_bb(BLACK, SQ_D3) will give all squares on ranks 1 and 2.
/// in_front_bb() takes a color and a rank as input, and returns a bitboard
/// representing all the squares on all ranks in front of the rank, from the
/// given color's point of view. For instance, in_front_bb(BLACK, RANK_3) will
/// give all squares on ranks 1 and 2.
inline Bitboard in_front_bb(Color c, Rank r) {
return InFrontBB[c][r];
}
inline Bitboard in_front_bb(Color c, Square s) {
return in_front_bb(c, square_rank(s));
}
/// between_bb() returns a bitboard representing all squares between two squares.
/// For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with the bits for
/// square d5 and e6 set. If s1 and s2 are not on the same rank, file or diagonal,
/// 0 is returned.
/// behind_bb() takes a color and a rank or square as input, and returns a
/// bitboard representing all the squares on all ranks behind of the rank
/// (or square), from the given color's point of view.
inline Bitboard behind_bb(Color c, Rank r) {
return InFrontBB[opposite_color(c)][r];
}
inline Bitboard behind_bb(Color c, Square s) {
return in_front_bb(opposite_color(c), square_rank(s));
}
/// ray_bb() gives a bitboard representing all squares along the ray in a
/// given direction from a given square.
inline Bitboard ray_bb(Square s, SignedDirection d) {
return RayBB[s][d];
}
/// Functions for computing sliding attack bitboards. rook_attacks_bb(),
/// bishop_attacks_bb() and queen_attacks_bb() all take a square and a
/// bitboard of occupied squares as input, and return a bitboard representing
/// all squares attacked by a rook, bishop or queen on the given square.
#if defined(IS_64BIT)
inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
Bitboard b = blockers & RMask[s];
return RAttacks[RAttackIndex[s] + ((b * RMult[s]) >> RShift[s])];
}
inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
Bitboard b = blockers & BMask[s];
return BAttacks[BAttackIndex[s] + ((b * BMult[s]) >> BShift[s])];
}
#else // if !defined(IS_64BIT)
inline Bitboard rook_attacks_bb(Square s, Bitboard blockers) {
Bitboard b = blockers & RMask[s];
return RAttacks[RAttackIndex[s] +
(unsigned(int(b) * int(RMult[s]) ^
int(b >> 32) * int(RMult[s] >> 32))
>> RShift[s])];
}
inline Bitboard bishop_attacks_bb(Square s, Bitboard blockers) {
Bitboard b = blockers & BMask[s];
return BAttacks[BAttackIndex[s] +
(unsigned(int(b) * int(BMult[s]) ^
int(b >> 32) * int(BMult[s] >> 32))
>> BShift[s])];
}
#endif
inline Bitboard queen_attacks_bb(Square s, Bitboard blockers) {
return rook_attacks_bb(s, blockers) | bishop_attacks_bb(s, blockers);
}
/// squares_between returns a bitboard representing all squares between
/// two squares. For instance, squares_between(SQ_C4, SQ_F7) returns a
/// bitboard with the bits for square d5 and e6 set. If s1 and s2 are not
/// on the same line, file or diagonal, EmptyBoardBB is returned.
inline Bitboard squares_between(Square s1, Square s2) {
inline Bitboard between_bb(Square s1, Square s2) {
return BetweenBB[s1][s2];
}
/// squares_in_front_of takes a color and a square as input, and returns a
/// bitboard representing all squares along the line in front of the square,
/// from the point of view of the given color. For instance,
/// squares_in_front_of(BLACK, SQ_E4) returns a bitboard with the squares
/// e3, e2 and e1 set.
/// forward_bb() takes a color and a square as input, and returns a bitboard
/// representing all squares along the line in front of the square, from the
/// point of view of the given color. Definition of the table is:
/// ForwardBB[c][s] = in_front_bb(c, s) & file_bb(s)
inline Bitboard squares_in_front_of(Color c, Square s) {
return in_front_bb(c, s) & file_bb(s);
inline Bitboard forward_bb(Color c, Square s) {
return ForwardBB[c][s];
}
/// squares_behind is similar to squares_in_front, but returns the squares
/// behind the square instead of in front of the square.
/// pawn_attack_span() takes a color and a square as input, and returns a bitboard
/// representing all squares that can be attacked by a pawn of the given color
/// when it moves along its file starting from the given square. Definition is:
/// PawnAttackSpan[c][s] = in_front_bb(c, s) & adjacent_files_bb(s);
inline Bitboard squares_behind(Color c, Square s) {
return in_front_bb(opposite_color(c), s) & file_bb(s);
inline Bitboard pawn_attack_span(Color c, Square s) {
return PawnAttackSpan[c][s];
}
/// passed_pawn_mask takes a color and a square as input, and returns a
/// passed_pawn_mask() takes a color and a square as input, and returns a
/// bitboard mask which can be used to test if a pawn of the given color on
/// the given square is a passed pawn.
/// the given square is a passed pawn. Definition of the table is:
/// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_bb(c, s)
inline Bitboard passed_pawn_mask(Color c, Square s) {
return PassedPawnMask[c][s];
}
/// outpost_mask takes a color and a square as input, and returns a bitboard
/// mask which can be used to test whether a piece on the square can possibly
/// be driven away by an enemy pawn.
/// squares_of_color() returns a bitboard representing all squares with the same
/// color of the given square.
inline Bitboard outpost_mask(Color c, Square s) {
return OutpostMask[c][s];
inline Bitboard squares_of_color(Square s) {
return DarkSquares & s ? DarkSquares : ~DarkSquares;
}
/// isolated_pawn_mask takes a square as input, and returns a bitboard mask
/// which can be used to test whether a pawn on the given square is isolated.
/// aligned() returns true if the squares s1, s2 and s3 are aligned
/// either on a straight or on a diagonal line.
inline Bitboard isolated_pawn_mask(Square s) {
return neighboring_files_bb(s);
inline bool aligned(Square s1, Square s2, Square s3) {
return LineBB[s1][s2] & s3;
}
/// first_1() finds the least significant nonzero bit in a nonzero bitboard.
/// pop_1st_bit() finds and clears the least significant nonzero bit in a
/// nonzero bitboard.
/// Functions for computing sliding attack bitboards. Function attacks_bb() takes
/// a square and a bitboard of occupied squares as input, and returns a bitboard
/// representing all squares attacked by Pt (bishop or rook) on the given square.
template<PieceType Pt>
FORCE_INLINE unsigned magic_index(Square s, Bitboard occ) {
#if defined(USE_BSFQ) // Assembly code by Heinz van Saanen
Bitboard* const Masks = Pt == ROOK ? RMasks : BMasks;
Bitboard* const Magics = Pt == ROOK ? RMagics : BMagics;
unsigned* const Shifts = Pt == ROOK ? RShifts : BShifts;
inline Square first_1(Bitboard b) {
Bitboard dummy;
__asm__("bsfq %1, %0": "=r"(dummy): "rm"(b) );
return (Square)(dummy);
if (HasPext)
return unsigned(_pext_u64(occ, Masks[s]));
if (Is64Bit)
return unsigned(((occ & Masks[s]) * Magics[s]) >> Shifts[s]);
unsigned lo = unsigned(occ) & unsigned(Masks[s]);
unsigned hi = unsigned(occ >> 32) & unsigned(Masks[s] >> 32);
return (lo * unsigned(Magics[s]) ^ hi * unsigned(Magics[s] >> 32)) >> Shifts[s];
}
inline Square pop_1st_bit(Bitboard* b) {
const Square s = first_1(*b);
*b &= ~(1ULL<<s);
template<PieceType Pt>
inline Bitboard attacks_bb(Square s, Bitboard occ) {
return (Pt == ROOK ? RAttacks : BAttacks)[s][magic_index<Pt>(s, occ)];
}
inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occ) {
switch (type_of(pc))
{
case BISHOP: return attacks_bb<BISHOP>(s, occ);
case ROOK : return attacks_bb<ROOK>(s, occ);
case QUEEN : return attacks_bb<BISHOP>(s, occ) | attacks_bb<ROOK>(s, occ);
default : return StepAttacksBB[pc][s];
}
}
/// lsb()/msb() finds the least/most significant bit in a non-zero bitboard.
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard.
#ifdef USE_BSFQ
# if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
FORCE_INLINE Square lsb(Bitboard b) {
unsigned long idx;
_BitScanForward64(&idx, b);
return (Square) idx;
}
FORCE_INLINE Square msb(Bitboard b) {
unsigned long idx;
_BitScanReverse64(&idx, b);
return (Square) idx;
}
# elif defined(__arm__)
FORCE_INLINE int lsb32(uint32_t v) {
__asm__("rbit %0, %1" : "=r"(v) : "r"(v));
return __builtin_clz(v);
}
FORCE_INLINE Square msb(Bitboard b) {
return (Square) (63 - __builtin_clzll(b));
}
FORCE_INLINE Square lsb(Bitboard b) {
return (Square) (uint32_t(b) ? lsb32(uint32_t(b)) : 32 + lsb32(uint32_t(b >> 32)));
}
# else
FORCE_INLINE Square lsb(Bitboard b) { // Assembly code by Heinz van Saanen
Bitboard idx;
__asm__("bsfq %1, %0": "=r"(idx): "rm"(b) );
return (Square) idx;
}
FORCE_INLINE Square msb(Bitboard b) {
Bitboard idx;
__asm__("bsrq %1, %0": "=r"(idx): "rm"(b) );
return (Square) idx;
}
# endif
FORCE_INLINE Square pop_lsb(Bitboard* b) {
const Square s = lsb(*b);
*b &= *b - 1;
return s;
}
#else // if !defined(USE_BSFQ)
#else // if defined(USE_BSFQ)
extern Square first_1(Bitboard b);
extern Square pop_1st_bit(Bitboard* b);
extern Square msb(Bitboard b);
extern Square lsb(Bitboard b);
extern Square pop_lsb(Bitboard* b);
#endif
/// frontmost_sq() and backmost_sq() find the square corresponding to the
/// most/least advanced bit relative to the given color.
////
//// Prototypes
////
inline Square frontmost_sq(Color c, Bitboard b) { return c == WHITE ? msb(b) : lsb(b); }
inline Square backmost_sq(Color c, Bitboard b) { return c == WHITE ? lsb(b) : msb(b); }
extern void print_bitboard(Bitboard b);
extern void init_bitboards();
extern int bitScanReverse32(uint32_t b);
#endif // !defined(BITBOARD_H_INCLUDED)
#endif // #ifndef BITBOARD_H_INCLUDED
+59 -97
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,126 +18,88 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(BITCOUNT_H_INCLUDED)
#ifndef BITCOUNT_H_INCLUDED
#define BITCOUNT_H_INCLUDED
#include <cassert>
#include "types.h"
// Select type of intrinsic bit count instruction to use, see
// README.txt on how to pgo compile with POPCNT support.
enum BitCountType {
CNT_64,
CNT_64_MAX15,
CNT_32,
CNT_32_MAX15,
CNT_HW_POPCNT
};
#if defined(__INTEL_COMPILER) && defined(USE_POPCNT) // Intel compiler
/// Determine at compile time the best popcount<> specialization according to
/// whether the platform is 32 or 64 bit, the maximum number of non-zero
/// bits to count and if the hardware popcnt instruction is available.
const BitCountType Full = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64 : CNT_32;
const BitCountType Max15 = HasPopCnt ? CNT_HW_POPCNT : Is64Bit ? CNT_64_MAX15 : CNT_32_MAX15;
#include <nmmintrin.h>
inline bool cpu_has_popcnt() {
/// popcount() counts the number of non-zero bits in a bitboard
template<BitCountType> inline int popcount(Bitboard);
int CPUInfo[4] = {-1};
__cpuid(CPUInfo, 0x00000001);
return (CPUInfo[2] >> 23) & 1;
template<>
inline int popcount<CNT_64>(Bitboard b) {
b -= (b >> 1) & 0x5555555555555555ULL;
b = ((b >> 2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
b = ((b >> 4) + b) & 0x0F0F0F0F0F0F0F0FULL;
return (b * 0x0101010101010101ULL) >> 56;
}
#define POPCNT_INTRINSIC(x) _mm_popcnt_u64(x)
#elif defined(_MSC_VER) && defined(USE_POPCNT) // Microsoft compiler
#include <intrin.h>
inline bool cpu_has_popcnt() {
int CPUInfo[4] = {-1};
__cpuid(CPUInfo, 0x00000001);
return (CPUInfo[2] >> 23) & 1;
template<>
inline int popcount<CNT_64_MAX15>(Bitboard b) {
b -= (b >> 1) & 0x5555555555555555ULL;
b = ((b >> 2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
return (b * 0x1111111111111111ULL) >> 60;
}
#define POPCNT_INTRINSIC(x) __popcnt64(x)
#else // Safe fallback for unsupported compilers or when USE_POPCNT is disabled
inline bool cpu_has_popcnt() { return false; }
#define POPCNT_INTRINSIC(x) 0
#endif // cpu_has_popcnt() and POPCNT_INTRINSIC() definitions
/// Software implementation of bit count functions
#if defined(IS_64BIT)
inline int count_1s(Bitboard b) {
b -= ((b>>1) & 0x5555555555555555ULL);
b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
b = ((b>>4) + b) & 0x0F0F0F0F0F0F0F0FULL;
b *= 0x0101010101010101ULL;
return int(b >> 56);
}
inline int count_1s_max_15(Bitboard b) {
b -= (b>>1) & 0x5555555555555555ULL;
b = ((b>>2) & 0x3333333333333333ULL) + (b & 0x3333333333333333ULL);
b *= 0x1111111111111111ULL;
return int(b >> 60);
}
#else // if !defined(IS_64BIT)
inline int count_1s(Bitboard b) {
template<>
inline int popcount<CNT_32>(Bitboard b) {
unsigned w = unsigned(b >> 32), v = unsigned(b);
v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
w -= (w >> 1) & 0x55555555;
v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
v = ((v >> 4) + v) & 0x0F0F0F0F; // 0-8 in 8 bits
v += (((w >> 4) + w) & 0x0F0F0F0F); // 0-16 in 8 bits
v *= 0x01010101; // mul is fast on amd procs
return int(v >> 24);
v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
w -= (w >> 1) & 0x55555555;
v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
v = ((v >> 4) + v + (w >> 4) + w) & 0x0F0F0F0F;
return (v * 0x01010101) >> 24;
}
inline int count_1s_max_15(Bitboard b) {
template<>
inline int popcount<CNT_32_MAX15>(Bitboard b) {
unsigned w = unsigned(b >> 32), v = unsigned(b);
v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
w -= (w >> 1) & 0x55555555;
v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
v += w; // 0-8 in 4 bits
v *= 0x11111111;
return int(v >> 28);
v -= (v >> 1) & 0x55555555; // 0-2 in 2 bits
w -= (w >> 1) & 0x55555555;
v = ((v >> 2) & 0x33333333) + (v & 0x33333333); // 0-4 in 4 bits
w = ((w >> 2) & 0x33333333) + (w & 0x33333333);
return ((v + w) * 0x11111111) >> 28;
}
#endif // BITCOUNT
template<>
inline int popcount<CNT_HW_POPCNT>(Bitboard b) {
#ifndef USE_POPCNT
/// count_1s() counts the number of nonzero bits in a bitboard.
/// If template parameter is true an intrinsic is called, otherwise
/// we fallback on a software implementation.
assert(false);
return b != 0; // Avoid 'b not used' warning
template<bool UseIntrinsic>
inline int count_1s(Bitboard b) {
#elif defined(_MSC_VER) && defined(__INTEL_COMPILER)
return UseIntrinsic ? POPCNT_INTRINSIC(b) : count_1s(b);
}
return _mm_popcnt_u64(b);
template<bool UseIntrinsic>
inline int count_1s_max_15(Bitboard b) {
#elif defined(_MSC_VER)
return UseIntrinsic ? POPCNT_INTRINSIC(b) : count_1s_max_15(b);
}
return (int)__popcnt64(b);
// Global constant initialized at startup that is set to true if
// CPU on which application runs supports POPCNT intrinsic. Unless
// USE_POPCNT is not defined.
const bool CpuHasPOPCNT = cpu_has_popcnt();
// Global constant used to print info about the use of 64 optimized
// functions to verify that a 64 bit compile has been correctly built.
#if defined(IS_64BIT)
const bool CpuHas64BitPath = true;
#else
const bool CpuHas64BitPath = false;
#endif
#endif // !defined(BITCOUNT_H_INCLUDED)
__asm__("popcnt %1, %0" : "=r" (b) : "r" (b));
return b;
#endif
}
#endif // #ifndef BITCOUNT_H_INCLUDED
+138 -243
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,46 +17,43 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
The code in this file is based on the opening book code in PolyGlot
by Fabien Letouzey. PolyGlot is available under the GNU General
by Fabien Letouzey. PolyGlot is available under the GNU General
Public License, and can be downloaded from http://wbec-ridderkerk.nl
*/
////
//// Includes
////
#include <algorithm>
#include <cassert>
#include "book.h"
#include "mersenne.h"
#include "misc.h"
#include "movegen.h"
using namespace std;
////
//// Global variables
////
Book OpeningBook;
////
//// Local definitions
////
namespace {
/// Book entry size in bytes
const int EntrySize = 16;
// A Polyglot book is a series of "entries" of 16 bytes. All integers are
// stored in big-endian format, with the highest byte first (regardless of
// size). The entries are ordered according to the key in ascending order.
struct Entry {
uint64_t key;
uint16_t move;
uint16_t count;
uint32_t learn;
};
/// Random numbers from PolyGlot, used to compute book hash keys
const uint64_t Random64[781] = {
// Random numbers from PolyGlot, used to compute book hash keys
const union {
Key PolyGlotRandoms[781];
struct {
Key psq[12][64]; // [piece][square]
Key castling[4]; // [castling flag]
Key enpassant[8]; // [file]
Key turn;
} Zobrist;
} PG = {{
0x9D39247E33776D41ULL, 0x2AF7398005AAA5C7ULL, 0x44DB015024623547ULL,
0x9C15F73E62A76AE2ULL, 0x75834465489C0C89ULL, 0x3290AC3A203001BFULL,
0x0FBBAD1F61042279ULL, 0xE83A908FF2FB60CAULL, 0x0D7E765D58755C10ULL,
@@ -318,266 +315,164 @@ namespace {
0x003A93D8B2806962ULL, 0x1C99DED33CB890A1ULL, 0xCF3145DE0ADD4289ULL,
0xD0E4427A5514FB72ULL, 0x77C621CC9FB3A483ULL, 0x67A34DAC4356550BULL,
0xF8D626AAAF278509ULL
};
}};
// polyglot_key() returns the PolyGlot hash key of the given position
Key polyglot_key(const Position& pos) {
/// Indices to the Random64[] array
Key key = 0;
Bitboard b = pos.pieces();
const int RandomPiece = 0;
const int RandomCastle = 768;
const int RandomEnPassant = 772;
const int RandomTurn = 780;
while (b)
{
Square s = pop_lsb(&b);
Piece pc = pos.piece_on(s);
// PolyGlot pieces are: BP = 0, WP = 1, BN = 2, ... BK = 10, WK = 11
key ^= PG.Zobrist.psq[2 * (type_of(pc) - 1) + (color_of(pc) == WHITE)][s];
}
/// Prototypes
b = pos.can_castle(ANY_CASTLING);
uint64_t book_key(const Position& pos);
uint64_t book_piece_key(Piece p, Square s);
uint64_t book_castle_key(const Position& pos);
uint64_t book_ep_key(const Position& pos);
uint64_t book_color_key(const Position& pos);
}
while (b)
key ^= PG.Zobrist.castling[pop_lsb(&b)];
if (pos.ep_square() != SQ_NONE)
key ^= PG.Zobrist.enpassant[file_of(pos.ep_square())];
////
//// Functions
////
if (pos.side_to_move() == WHITE)
key ^= PG.Zobrist.turn;
/// Destructor. Be sure file is closed before we leave.
Book::~Book() {
close();
}
/// Book::open() opens a book file with a given file name
void Book::open(const string& fName) {
// Close old file before opening the new
close();
fileName = fName;
ifstream::open(fileName.c_str(), ifstream::in | ifstream::binary);
if (!is_open())
return;
// Get the book size in number of entries
seekg(0, ios::end);
bookSize = tellg() / EntrySize;
seekg(0, ios::beg);
if (!good())
{
cerr << "Failed to open book file " << fileName << endl;
Application::exit_with_failure();
return key;
}
} // namespace
PolyglotBook::PolyglotBook() : rkiss(Time::now() % 10000) {}
PolyglotBook::~PolyglotBook() { if (is_open()) close(); }
/// operator>>() reads sizeof(T) chars from the file's binary byte stream and
/// converts them into a number of type T. A Polyglot book stores numbers in
/// big-endian format.
template<typename T> PolyglotBook& PolyglotBook::operator>>(T& n) {
n = 0;
for (size_t i = 0; i < sizeof(T); ++i)
n = T((n << 8) + ifstream::get());
return *this;
}
template<> PolyglotBook& PolyglotBook::operator>>(Entry& e) {
return *this >> e.key >> e.move >> e.count >> e.learn;
}
/// Book::close() closes the file only if it is open, otherwise
/// we can end up in a little mess due to how std::ifstream works.
/// open() tries to open a book file with the given name after closing any
/// existing one.
void Book::close() {
bool PolyglotBook::open(const char* fName) {
if (is_open())
ifstream::close();
if (is_open()) // Cannot close an already closed file
close();
ifstream::open(fName, ifstream::in | ifstream::binary);
fileName = is_open() ? fName : "";
ifstream::clear(); // Reset any error flag to allow a retry ifstream::open()
return !fileName.empty();
}
/// Book::file_name() returns the file name of the currently active book,
/// or the empty string if no book is open.
/// probe() tries to find a book move for the given position. If no move is
/// found, it returns MOVE_NONE. If pickBest is true, then it always returns
/// the highest-rated move, otherwise it randomly chooses one based on the
/// move score.
const string Book::file_name() const {
Move PolyglotBook::probe(const Position& pos, const string& fName, bool pickBest) {
return is_open() ? fileName : "";
}
/// Book::get_move() gets a book move for a given position. Returns
/// MOVE_NONE if no book move is found.
Move Book::get_move(const Position& pos) {
if (!is_open() || bookSize == 0)
if (fileName != fName && !open(fName.c_str()))
return MOVE_NONE;
int bookMove = 0, scoresSum = 0;
uint64_t key = book_key(pos);
BookEntry entry;
Entry e;
uint16_t best = 0;
unsigned sum = 0;
Move move = MOVE_NONE;
Key key = polyglot_key(pos);
// Choose a book move among the possible moves for the given position
for (int idx = find_key(key); idx < bookSize; idx++)
seekg(find_first(key) * sizeof(Entry), ios_base::beg);
while (*this >> e, e.key == key && good())
{
read_entry(entry, idx);
if (entry.key != key)
break;
best = max(best, e.count);
sum += e.count;
int score = entry.count;
assert(score > 0);
// Choose book move according to its score. If a move has a very
// high score it has more probability to be choosen then a one with
// lower score. Note that first entry is always chosen.
scoresSum += score;
if (int(genrand_int32() % scoresSum) < score)
bookMove = entry.move;
// Choose book move according to its score. If a move has a very high
// score it has a higher probability of being choosen than a move with
// a lower score. Note that first entry is always chosen.
if ( (!pickBest && sum && rkiss.rand<unsigned>() % sum < e.count)
|| (pickBest && e.count == best))
move = Move(e.move);
}
if (!bookMove)
if (!move)
return MOVE_NONE;
MoveStack mlist[256];
MoveStack* last = generate_moves(pos, mlist);
for (MoveStack* cur = mlist; cur != last; cur++)
if ((int(cur->move) & 07777) == bookMove)
return cur->move;
// A PolyGlot book move is encoded as follows:
//
// bit 0- 5: destination square (from 0 to 63)
// bit 6-11: origin square (from 0 to 63)
// bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
//
// Castling moves follow the "king captures rook" representation. If a book
// move is a promotion, we have to convert it to our representation and in
// all other cases, we can directly compare with a Move after having masked
// out the special Move flags (bit 14-15) that are not supported by PolyGlot.
int pt = (move >> 12) & 7;
if (pt)
move = make<PROMOTION>(from_sq(move), to_sq(move), PieceType(pt + 1));
// Add 'special move' flags and verify it is legal
for (MoveList<LEGAL> it(pos); *it; ++it)
if (move == (*it ^ type_of(*it)))
return *it;
return MOVE_NONE;
}
/// Book::find_key() takes a book key as input, and does a binary search
/// through the book file for the given key. The index to the first book
/// entry with the same key as the input is returned. When the key is not
/// found in the book file, bookSize is returned.
/// find_first() takes a book key as input, and does a binary search through
/// the book file for the given key. Returns the index of the leftmost book
/// entry with the same key as the input.
int Book::find_key(uint64_t key) {
size_t PolyglotBook::find_first(Key key) {
int left, right, mid;
BookEntry entry;
seekg(0, ios::end); // Move pointer to end, so tellg() gets file's size
// Binary search (finds the leftmost entry)
left = 0;
right = bookSize - 1;
size_t low = 0, mid, high = (size_t)tellg() / sizeof(Entry) - 1;
Entry e;
assert(left <= right);
assert(low <= high);
while (left < right)
while (low < high && good())
{
mid = (left + right) / 2;
mid = (low + high) / 2;
assert(mid >= left && mid < right);
assert(mid >= low && mid < high);
read_entry(entry, mid);
if (key <= entry.key)
right = mid;
seekg(mid * sizeof(Entry), ios_base::beg);
*this >> e;
if (key <= e.key)
high = mid;
else
left = mid + 1;
low = mid + 1;
}
assert(left == right);
assert(low == high);
read_entry(entry, left);
return (entry.key == key)? left : bookSize;
}
/// Book::read_entry() takes a BookEntry reference and an integer index as
/// input, and looks up the opening book entry at the given index in the book
/// file. The book entry is copied to the first input parameter.
void Book::read_entry(BookEntry& entry, int idx) {
assert(idx >= 0 && idx < bookSize);
assert(is_open());
seekg(idx * EntrySize, ios_base::beg);
*this >> entry;
if (!good())
{
cerr << "Failed to read book entry at index " << idx << endl;
Application::exit_with_failure();
}
}
/// Book::read_integer() reads size chars from the file stream
/// and converts them in an integer number.
uint64_t Book::read_integer(int size) {
char buf[8];
read(buf, size);
// Numbers are stored on disk as a binary byte stream
uint64_t n = 0ULL;
for (int i = 0; i < size; i++)
n = (n << 8) + (unsigned char)buf[i];
return n;
}
////
//// Local definitions
////
namespace {
uint64_t book_key(const Position& pos) {
uint64_t result = 0ULL;
for (Color c = WHITE; c <= BLACK; c++)
{
Bitboard b = pos.pieces_of_color(c);
while (b)
{
Square s = pop_1st_bit(&b);
Piece p = pos.piece_on(s);
assert(piece_is_ok(p));
assert(color_of_piece(p) == c);
result ^= book_piece_key(p, s);
}
}
result ^= book_castle_key(pos);
result ^= book_ep_key(pos);
result ^= book_color_key(pos);
return result;
}
uint64_t book_piece_key(Piece p, Square s) {
/// Convert pieces to the range 0..11
static const int PieceTo12[] = { 0, 0, 2, 4, 6, 8, 10, 0, 0, 1, 3, 5, 7, 9, 11 };
return Random64[RandomPiece + (PieceTo12[int(p)]^1) * 64 + int(s)];
}
uint64_t book_castle_key(const Position& pos) {
uint64_t result = 0ULL;
if (pos.can_castle_kingside(WHITE))
result ^= Random64[RandomCastle+0];
if (pos.can_castle_queenside(WHITE))
result ^= Random64[RandomCastle+1];
if (pos.can_castle_kingside(BLACK))
result ^= Random64[RandomCastle+2];
if (pos.can_castle_queenside(BLACK))
result ^= Random64[RandomCastle+3];
return result;
}
uint64_t book_ep_key(const Position& pos) {
return (pos.ep_square() == SQ_NONE ? 0ULL : Random64[RandomEnPassant + square_file(pos.ep_square())]);
}
uint64_t book_color_key(const Position& pos) {
return (pos.side_to_move() == WHITE ? Random64[RandomTurn] : 0ULL);
}
return low;
}
+12 -51
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,68 +17,29 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
The code in this file is based on the opening book code in PolyGlot
by Fabien Letouzey. PolyGlot is available under the GNU General
Public License, and can be downloaded from http://wbec-ridderkerk.nl
*/
#if !defined(BOOK_H_INCLUDED)
#ifndef BOOK_H_INCLUDED
#define BOOK_H_INCLUDED
////
//// Includes
////
#include <fstream>
#include <string>
#include "move.h"
#include "position.h"
#include "rkiss.h"
////
//// Types
////
struct BookEntry {
uint64_t key;
uint16_t move;
uint16_t count;
uint16_t n;
uint16_t sum;
};
class Book : private std::ifstream {
class PolyglotBook : private std::ifstream {
public:
~Book();
void open(const std::string& fName);
void close();
const std::string file_name() const;
Move get_move(const Position& pos);
PolyglotBook();
~PolyglotBook();
Move probe(const Position& pos, const std::string& fName, bool pickBest);
private:
Book& operator>>(uint64_t& n) { n = read_integer(8); return *this; }
Book& operator>>(uint16_t& n) { n = (uint16_t)read_integer(2); return *this; }
void operator>>(BookEntry& e) { *this >> e.key >> e.move >> e.count >> e.n >> e.sum; }
template<typename T> PolyglotBook& operator>>(T& n);
uint64_t read_integer(int size);
void read_entry(BookEntry& e, int n);
int find_key(uint64_t key);
bool open(const char* fName);
size_t find_first(Key key);
RKISS rkiss;
std::string fileName;
int bookSize;
};
////
//// Global variables
////
extern Book OpeningBook;
#endif // !defined(BOOK_H_INCLUDED)
#endif // #ifndef BOOK_H_INCLUDED
-50
View File
@@ -1,50 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(COLOR_H_INCLUDED)
#define COLOR_H_INCLUDED
////
//// Types
////
enum Color {
WHITE,
BLACK,
COLOR_NONE
};
////
//// Inline functions
////
inline void operator++ (Color &c, int) { c = Color(int(c) + 1); }
inline Color opposite_color(Color c) {
return Color(int(c) ^ 1);
}
inline bool color_is_ok(Color c) {
return c == WHITE || c == BLACK;
}
#endif // !defined(COLOR_H_INCLUDED)
-59
View File
@@ -1,59 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(DEPTH_H_INCLUDED)
#define DEPTH_H_INCLUDED
////
//// Types
////
enum Depth {
DEPTH_ZERO = 0,
DEPTH_MAX = 200 // 100 * OnePly;
};
////
//// Constants
////
const Depth OnePly = Depth(2);
////
//// Inline functions
////
inline Depth operator+ (Depth d, int i) { return Depth(int(d) + i); }
inline Depth operator+ (Depth d1, Depth d2) { return Depth(int(d1) + int(d2)); }
inline void operator+= (Depth &d, int i) { d = Depth(int(d) + i); }
inline void operator+= (Depth &d1, Depth d2) { d1 += int(d2); }
inline Depth operator- (Depth d, int i) { return Depth(int(d) - i); }
inline Depth operator- (Depth d1, Depth d2) { return Depth(int(d1) - int(d2)); }
inline void operator-= (Depth & d, int i) { d = Depth(int(d) - i); }
inline Depth operator* (Depth d, int i) { return Depth(int(d) * i); }
inline Depth operator* (int i, Depth d) { return Depth(int(d) * i); }
inline void operator*= (Depth &d, int i) { d = Depth(int(d) * i); }
inline Depth operator/ (Depth d, int i) { return Depth(int(d) / i); }
inline void operator/= (Depth &d, int i) { d = Depth(int(d) / i); }
#endif // !defined(DEPTH_H_INCLUDED)
-87
View File
@@ -1,87 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include "direction.h"
#include "square.h"
////
//// Local definitions
////
namespace {
const SquareDelta directionToDelta[] = {
DELTA_E, DELTA_W, DELTA_N, DELTA_S, DELTA_NE, DELTA_SW, DELTA_NW, DELTA_SE
};
bool reachable(Square orig, Square dest, SignedDirection dir) {
SquareDelta delta = directionToDelta[dir];
Square from = orig;
Square to = from + delta;
while (to != dest && square_distance(to, from) == 1 && square_is_ok(to))
{
from = to;
to += delta;
}
return (to == dest && square_distance(from, to) == 1);
}
}
////
//// Variables
////
uint8_t DirectionTable[64][64];
uint8_t SignedDirectionTable[64][64];
////
//// Functions
////
void init_direction_table() {
for (Square s1 = SQ_A1; s1 <= SQ_H8; s1++)
for (Square s2 = SQ_A1; s2 <= SQ_H8; s2++)
{
DirectionTable[s1][s2] = uint8_t(DIR_NONE);
SignedDirectionTable[s1][s2] = uint8_t(SIGNED_DIR_NONE);
if (s1 == s2)
continue;
for (SignedDirection d = SIGNED_DIR_E; d != SIGNED_DIR_NONE; d++)
{
if (reachable(s1, s2, d))
{
SignedDirectionTable[s1][s2] = uint8_t(d);
DirectionTable[s1][s2] = uint8_t(d / 2);
break;
}
}
}
}
-92
View File
@@ -1,92 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(DIRECTION_H_INCLUDED)
#define DIRECTION_H_INCLUDED
////
//// Includes
////
#include "square.h"
#include "types.h"
////
//// Types
////
enum Direction {
DIR_E = 0, DIR_N = 1, DIR_NE = 2, DIR_NW = 3, DIR_NONE = 4
};
enum SignedDirection {
SIGNED_DIR_E = 0, SIGNED_DIR_W = 1,
SIGNED_DIR_N = 2, SIGNED_DIR_S = 3,
SIGNED_DIR_NE = 4, SIGNED_DIR_SW = 5,
SIGNED_DIR_NW = 6, SIGNED_DIR_SE = 7,
SIGNED_DIR_NONE = 8
};
////
//// Variables
////
extern uint8_t DirectionTable[64][64];
extern uint8_t SignedDirectionTable[64][64];
////
//// Inline functions
////
inline void operator++ (Direction& d, int) {
d = Direction(int(d) + 1);
}
inline void operator++ (SignedDirection& d, int) {
d = SignedDirection(int(d) + 1);
}
inline Direction direction_between_squares(Square s1, Square s2) {
return Direction(DirectionTable[s1][s2]);
}
inline SignedDirection signed_direction_between_squares(Square s1, Square s2) {
return SignedDirection(SignedDirectionTable[s1][s2]);
}
inline int direction_is_diagonal(Square s1, Square s2) {
return DirectionTable[s1][s2] & 2;
}
inline bool direction_is_straight(Square s1, Square s2) {
return DirectionTable[s1][s2] < 2;
}
////
//// Prototypes
////
extern void init_direction_table();
#endif // !defined(DIRECTION_H_INCLUDED)
+494 -550
View File
File diff suppressed because it is too large Load Diff
+85 -70
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,90 +17,105 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(ENDGAME_H_INCLUDED)
#ifndef ENDGAME_H_INCLUDED
#define ENDGAME_H_INCLUDED
////
//// Includes
////
#include <map>
#include <string>
#include "position.h"
#include "scale.h"
#include "value.h"
#include "types.h"
////
//// Types
////
/// EndgameType lists all supported endgames
enum EndgameType {
// Evaluation functions
KXK, // Generic "mate lone king" eval
KBNK, // KBN vs K
KPK, // KP vs K
KRKP, // KR vs KP
KRKB, // KR vs KB
KRKN, // KR vs KN
KQKR, // KQ vs KR
KBBKN, // KBB vs KN
KNNK, // KNN vs K
KmmKm, // K and two minors vs K and one or two minors
// Evaluation functions
// Scaling functions
KBPsK, // KB+pawns vs K
KQKRPs, // KQ vs KR+pawns
KRPKR, // KRP vs KR
KRPPKRP, // KRPP vs KRP
KPsK, // King and pawns vs king
KBPKB, // KBP vs KB
KBPPKB, // KBPP vs KB
KBPKN, // KBP vs KN
KNPK, // KNP vs K
KPKP // KP vs KP
KNNK, // KNN vs K
KXK, // Generic "mate lone king" eval
KBNK, // KBN vs K
KPK, // KP vs K
KRKP, // KR vs KP
KRKB, // KR vs KB
KRKN, // KR vs KN
KQKP, // KQ vs KP
KQKR, // KQ vs KR
// Scaling functions
SCALE_FUNS,
KBPsK, // KB and pawns vs K
KQKRPs, // KQ vs KR and pawns
KRPKR, // KRP vs KR
KRPKB, // KRP vs KB
KRPPKRP, // KRPP vs KRP
KPsK, // K and pawns vs K
KBPKB, // KBP vs KB
KBPPKB, // KBPP vs KB
KBPKN, // KBP vs KN
KNPK, // KNP vs K
KNPKB, // KNP vs KB
KPKP // KP vs KP
};
/// Template abstract base class for all special endgame functions
/// Endgame functions can be of two types depending on whether they return a
/// Value or a ScaleFactor. Type eg_fun<int>::type returns either ScaleFactor
/// or Value depending on whether the template parameter is 0 or 1.
template<int> struct eg_fun { typedef Value type; };
template<> struct eg_fun<1> { typedef ScaleFactor type; };
/// Base and derived templates for endgame evaluation and scaling functions
template<typename T>
class EndgameFunctionBase {
struct EndgameBase {
virtual ~EndgameBase() {}
virtual Color color() const = 0;
virtual T operator()(const Position&) const = 0;
};
template<EndgameType E, typename T = typename eg_fun<(E > SCALE_FUNS)>::type>
struct Endgame : public EndgameBase<T> {
explicit Endgame(Color c) : strongSide(c), weakSide(~c) {}
Color color() const { return strongSide; }
T operator()(const Position&) const;
private:
const Color strongSide, weakSide;
};
/// The Endgames class stores the pointers to endgame evaluation and scaling
/// base objects in two std::map typedefs. We then use polymorphism to invoke
/// the actual endgame function by calling its virtual operator().
class Endgames {
typedef std::map<Key, EndgameBase<eg_fun<0>::type>*> M1;
typedef std::map<Key, EndgameBase<eg_fun<1>::type>*> M2;
M1 m1;
M2 m2;
M1& map(M1::mapped_type) { return m1; }
M2& map(M2::mapped_type) { return m2; }
template<EndgameType E> void add(const std::string& code);
public:
EndgameFunctionBase(Color c) : strongerSide(c), weakerSide(opposite_color(c)) {}
virtual ~EndgameFunctionBase() {}
virtual T apply(const Position&) = 0;
Color color() const { return strongerSide; }
Endgames();
~Endgames();
protected:
Color strongerSide, weakerSide;
template<typename T> T probe(Key key, T& eg)
{ return eg = map(eg).count(key) ? map(eg)[key] : NULL; }
};
typedef EndgameFunctionBase<Value> EndgameEvaluationFunctionBase;
typedef EndgameFunctionBase<ScaleFactor> EndgameScalingFunctionBase;
/// Templates subclass for various concrete endgames
template<EndgameType>
struct EvaluationFunction : public EndgameEvaluationFunctionBase {
typedef EndgameEvaluationFunctionBase Base;
explicit EvaluationFunction(Color c): EndgameEvaluationFunctionBase(c) {}
Value apply(const Position&);
};
template<EndgameType>
struct ScalingFunction : public EndgameScalingFunctionBase {
typedef EndgameScalingFunctionBase Base;
explicit ScalingFunction(Color c) : EndgameScalingFunctionBase(c) {}
ScaleFactor apply(const Position&);
};
////
//// Prototypes
////
extern void init_bitbases();
#endif // !defined(ENDGAME_H_INCLUDED)
#endif // #ifndef ENDGAME_H_INCLUDED
+684 -1020
View File
File diff suppressed because it is too large Load Diff
+9 -87
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,97 +17,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(EVALUATE_H_INCLUDED)
#ifndef EVALUATE_H_INCLUDED
#define EVALUATE_H_INCLUDED
////
//// Includes
////
#include "types.h"
#include <iostream>
#include "material.h"
#include "pawns.h"
////
//// Types
////
/// The EvalInfo struct contains various information computed and collected
/// by the evaluation function. An EvalInfo object is passed as one of the
/// arguments to the evaluation function, and the search can make use of its
/// contents to make intelligent search decisions.
///
/// At the moment, this is not utilized very much: The only part of the
/// EvalInfo object which is used by the search is futilityMargin.
class Position;
struct EvalInfo {
namespace Eval {
// Middle game and endgame evaluations
Score value;
extern void init();
extern Value evaluate(const Position& pos);
extern std::string trace(const Position& pos);
// Pointers to material and pawn hash table entries
MaterialInfo* mi;
PawnInfo* pi;
}
// attackedBy[color][piece type] is a bitboard representing all squares
// attacked by a given color and piece type, attackedBy[color][0] contains
// all squares attacked by the given color.
Bitboard attackedBy[2][8];
Bitboard attacked_by(Color c) const { return attackedBy[c][0]; }
Bitboard attacked_by(Color c, PieceType pt) const { return attackedBy[c][pt]; }
// kingZone[color] is the zone around the enemy king which is considered
// by the king safety evaluation. This consists of the squares directly
// adjacent to the king, and the three (or two, for a king on an edge file)
// squares two ranks in front of the king. For instance, if black's king
// is on g8, kingZone[WHITE] is a bitboard containing the squares f8, h8,
// f7, g7, h7, f6, g6 and h6.
Bitboard kingZone[2];
// kingAttackersCount[color] is the number of pieces of the given color
// which attack a square in the kingZone of the enemy king.
int kingAttackersCount[2];
// kingAttackersWeight[color] is the sum of the "weight" of the pieces of the
// given color which attack a square in the kingZone of the enemy king. The
// weights of the individual piece types are given by the variables
// QueenAttackWeight, RookAttackWeight, BishopAttackWeight and
// KnightAttackWeight in evaluate.cpp
int kingAttackersWeight[2];
// kingAdjacentZoneAttacksCount[color] is the number of attacks to squares
// directly adjacent to the king of the given color. Pieces which attack
// more than one square are counted multiple times. For instance, if black's
// king is on g8 and there's a white knight on g5, this knight adds
// 2 to kingAdjacentZoneAttacksCount[BLACK].
int kingAdjacentZoneAttacksCount[2];
// mateThreat[color] is a move for the given side which gives a direct mate.
Move mateThreat[2];
// Middle game and endgame mobility scores.
Score mobility;
// Extra futility margin. This is added to the standard futility margin
// in the quiescence search.
Value futilityMargin;
};
////
//// Prototypes
////
extern Value evaluate(const Position& pos, EvalInfo& ei, int threadID);
extern Value quick_evaluate(const Position& pos);
extern void init_eval(int threads);
extern void quit_eval();
extern void read_weights(Color sideToMove);
#endif // !defined(EVALUATE_H_INCLUDED)
#endif // #ifndef EVALUATE_H_INCLUDED
-92
View File
@@ -1,92 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include <cstring>
#include "history.h"
////
//// Functions
////
/// Constructor
History::History() { clear(); }
/// History::clear() clears the history tables
void History::clear() {
memset(history, 0, 2 * 8 * 64 * sizeof(int));
}
/// History::success() registers a move as being successful. This is done
/// whenever a non-capturing move causes a beta cutoff in the main search.
/// The three parameters are the moving piece, the destination square, and
/// the search depth.
void History::success(Piece p, Square to, Depth d) {
assert(piece_is_ok(p));
assert(square_is_ok(to));
history[p][to] += int(d) * int(d);
// Prevent history overflow
if (history[p][to] >= HistoryMax)
for (int i = 0; i < 16; i++)
for (int j = 0; j < 64; j++)
history[i][j] /= 4;
}
/// History::failure() registers a move as being unsuccessful. The function is
/// called for each non-capturing move which failed to produce a beta cutoff
/// at a node where a beta cutoff was finally found.
void History::failure(Piece p, Square to, Depth d) {
assert(piece_is_ok(p));
assert(square_is_ok(to));
history[p][to] -= int(d) * int(d);
if (history[p][to] < 0)
history[p][to] = 0;
}
/// History::move_ordering_score() returns an integer value used to order the
/// non-capturing moves in the MovePicker class.
int History::move_ordering_score(Piece p, Square to) const {
assert(piece_is_ok(p));
assert(square_is_ok(to));
return history[p][to];
}
-73
View File
@@ -1,73 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(HISTORY_H_INCLUDED)
#define HISTORY_H_INCLUDED
////
//// Includes
////
#include "depth.h"
#include "move.h"
#include "piece.h"
////
//// Types
////
/// The History class stores statistics about how often different moves
/// have been successful or unsuccessful during the current search. These
/// statistics are used for reduction and move ordering decisions. History
/// entries are stored according only to moving piece and destination square,
/// in particular two moves with different origin but same destination and
/// same piece will be considered identical.
class History {
public:
History();
void clear();
void success(Piece p, Square to, Depth d);
void failure(Piece p, Square to, Depth d);
int move_ordering_score(Piece p, Square to) const;
private:
int history[16][64]; // [piece][square]
};
////
//// Constants and variables
////
/// HistoryMax controls how often the history counters will be scaled down:
/// When the history score for a move gets bigger than HistoryMax, all
/// entries in the table are divided by 4. It is difficult to guess what
/// the ideal value of this constant is. Scaling down the scores often has
/// the effect that parts of the search tree which have been searched
/// recently have a bigger importance for move ordering than the moves which
/// have been searched a long time ago.
const int HistoryMax = 25000 * OnePly;
#endif // !defined(HISTORY_H_INCLUDED)
-103
View File
@@ -1,103 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(LOCK_H_INCLUDED)
#define LOCK_H_INCLUDED
// x86 assembly language locks or OS spin locks may perform faster than
// mutex locks on some platforms. On my machine, mutexes seem to be the
// best.
//#define ASM_LOCK
//#define OS_SPIN_LOCK
#if defined(ASM_LOCK)
typedef volatile int Lock;
static inline void LockX86(Lock *lock) {
int dummy;
asm __volatile__("1: movl $1, %0" "\n\t"
" xchgl (%1), %0" "\n\t" " testl %0, %0" "\n\t"
" jz 3f" "\n\t" "2: pause" "\n\t"
" movl (%1), %0" "\n\t" " testl %0, %0" "\n\t"
" jnz 2b" "\n\t" " jmp 1b" "\n\t" "3:"
"\n\t":"=&q"(dummy)
:"q"(lock)
:"cc");
}
static inline void UnlockX86(Lock *lock) {
int dummy;
asm __volatile__("movl $0, (%1)":"=&q"(dummy)
:"q"(lock));
}
# define lock_init(x, y) (*(x) = 0)
# define lock_grab(x) LockX86(x)
# define lock_release(x) UnlockX86(x)
# define lock_destroy(x)
#elif defined(OS_SPIN_LOCK)
# include <libkern/OSAtomic.h>
typedef OSSpinLock Lock;
# define lock_init(x, y) (*(x) = 0)
# define lock_grab(x) OSSpinLockLock(x)
# define lock_release(x) OSSpinLockUnlock(x)
# define lock_destroy(x)
#elif !defined(_MSC_VER)
# include <pthread.h>
typedef pthread_mutex_t Lock;
# define lock_init(x, y) pthread_mutex_init(x, y)
# define lock_grab(x) pthread_mutex_lock(x)
# define lock_release(x) pthread_mutex_unlock(x)
# define lock_destroy(x) pthread_mutex_destroy(x)
#else
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
typedef CRITICAL_SECTION Lock;
# define lock_init(x, y) InitializeCriticalSection(x)
# define lock_grab(x) EnterCriticalSection(x)
# define lock_release(x) LeaveCriticalSection(x)
# define lock_destroy(x) DeleteCriticalSection(x)
#endif
#endif // !defined(LOCK_H_INCLUDED)
+21 -63
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,73 +17,31 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// To profile with callgrind uncomment following line
//#define USE_CALLGRIND
////
//// Includes
////
#include <iostream>
#include <string>
#include "benchmark.h"
#include "bitcount.h"
#include "misc.h"
#include "uci.h"
#include "bitboard.h"
#include "evaluate.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
#ifdef USE_CALLGRIND
#include <valgrind/callgrind.h>
#endif
int main(int argc, char* argv[]) {
using namespace std;
std::cout << engine_info() << std::endl;
UCI::init(Options);
Bitboards::init();
Position::init();
Bitbases::init_kpk();
Search::init();
Pawns::init();
Eval::init();
Threads.init();
TT.resize(Options["Hash"]);
////
//// Functions
////
UCI::loop(argc, argv);
int main(int argc, char *argv[]) {
// Disable IO buffering
cout.rdbuf()->pubsetbuf(NULL, 0);
cin.rdbuf()->pubsetbuf(NULL, 0);
// Initialization through global resources manager
Application::initialize();
#ifdef USE_CALLGRIND
CALLGRIND_START_INSTRUMENTATION;
#endif
// Process command line arguments if any
if (argc > 1)
{
if (string(argv[1]) != "bench" || argc < 4 || argc > 8)
cout << "Usage: stockfish bench <hash size> <threads> "
<< "[time = 60s] [fen positions file = default] "
<< "[time, depth, perft or node limited = time] "
<< "[timing file name = none]" << endl;
else
{
string time = argc > 4 ? argv[4] : "60";
string fen = argc > 5 ? argv[5] : "default";
string lim = argc > 6 ? argv[6] : "time";
string tim = argc > 7 ? argv[7] : "";
benchmark(string(argv[2]) + " " + string(argv[3]) + " " + time + " " + fen + " " + lim + " " + tim);
}
return 0;
}
// Print copyright notice
cout << engine_name()
<< ". By Tord Romstad, Marco Costalba, Joona Kiiski." << endl;
if (CpuHasPOPCNT)
cout << "Good! CPU has hardware POPCNT. We will use it." << endl;
// Enter UCI mode
uci_main_loop();
return 0;
Threads.exit();
}
+172 -338
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,415 +17,249 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <algorithm> // For std::min
#include <cassert>
#include <sstream>
#include <map>
#include <cstring>
#include "material.h"
using namespace std;
////
//// Local definitions
////
namespace {
// Values modified by Joona Kiiski
const Value MidgameLimit = Value(15581);
const Value EndgameLimit = Value(3998);
// Polynomial material balance parameters
const Value RedundantQueenPenalty = Value(320);
const Value RedundantRookPenalty = Value(554);
const int LinearCoefficients[6] = { 1617, -162, -1172, -190, 105, 26 };
// pair pawn knight bishop rook queen
const int LinearCoefficients[6] = { 1852, -162, -1122, -183, 249, -154 };
const int QuadraticCoefficientsSameColor[][6] = {
{ 7, 7, 7, 7, 7, 7 }, { 39, 2, 7, 7, 7, 7 }, { 35, 271, -4, 7, 7, 7 },
{ 7, 25, 4, 7, 7, 7 }, { -27, -2, 46, 100, 56, 7 }, { 58, 29, 83, 148, -3, -25 } };
const int QuadraticCoefficientsSameSide[][PIECE_TYPE_NB] = {
// OUR PIECES
// pair pawn knight bishop rook queen
{ 0 }, // Bishop pair
{ 39, 2 }, // Pawn
{ 35, 271, -4 }, // knight OUR PIECES
{ 0, 105, 4, 0 }, // Bishop
{ -27, -2, 46, 100, -141 }, // Rook
{-177, 25, 129, 142, -137, 0 } // Queen
};
const int QuadraticCoefficientsOppositeColor[][6] = {
{ 41, 41, 41, 41, 41, 41 }, { 37, 41, 41, 41, 41, 41 }, { 10, 62, 41, 41, 41, 41 },
{ 57, 64, 39, 41, 41, 41 }, { 50, 40, 23, -22, 41, 41 }, { 106, 101, 3, 151, 171, 41 } };
const int QuadraticCoefficientsOppositeSide[][PIECE_TYPE_NB] = {
// THEIR PIECES
// pair pawn knight bishop rook queen
{ 0 }, // Bishop pair
{ 37, 0 }, // Pawn
{ 10, 62, 0 }, // Knight OUR PIECES
{ 57, 64, 39, 0 }, // Bishop
{ 50, 40, 23, -22, 0 }, // Rook
{ 98, 105, -39, 141, 274, 0 } // Queen
};
// Named endgame evaluation and scaling functions, these
// are accessed direcly and not through the function maps.
EvaluationFunction<KmmKm> EvaluateKmmKm(WHITE);
EvaluationFunction<KXK> EvaluateKXK(WHITE), EvaluateKKX(BLACK);
ScalingFunction<KBPsK> ScaleKBPsK(WHITE), ScaleKKBPs(BLACK);
ScalingFunction<KQKRPs> ScaleKQKRPs(WHITE), ScaleKRPsKQ(BLACK);
ScalingFunction<KPsK> ScaleKPsK(WHITE), ScaleKKPs(BLACK);
ScalingFunction<KPKP> ScaleKPKPw(WHITE), ScaleKPKPb(BLACK);
// Endgame evaluation and scaling functions are accessed directly and not through
// the function maps because they correspond to more than one material hash key.
Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
typedef EndgameEvaluationFunctionBase EF;
typedef EndgameScalingFunctionBase SF;
}
Endgame<KBPsK> ScaleKBPsK[] = { Endgame<KBPsK>(WHITE), Endgame<KBPsK>(BLACK) };
Endgame<KQKRPs> ScaleKQKRPs[] = { Endgame<KQKRPs>(WHITE), Endgame<KQKRPs>(BLACK) };
Endgame<KPsK> ScaleKPsK[] = { Endgame<KPsK>(WHITE), Endgame<KPsK>(BLACK) };
Endgame<KPKP> ScaleKPKP[] = { Endgame<KPKP>(WHITE), Endgame<KPKP>(BLACK) };
////
//// Classes
////
/// EndgameFunctions class stores endgame evaluation and scaling functions
/// in two std::map. Because STL library is not guaranteed to be thread
/// safe even for read access, the maps, although with identical content,
/// are replicated for each thread. This is faster then using locks.
class EndgameFunctions {
public:
EndgameFunctions();
~EndgameFunctions();
template<class T> T* get(Key key) const;
private:
template<class T> void add(const string& keyCode);
static Key buildKey(const string& keyCode);
static const string swapColors(const string& keyCode);
// Here we store two maps, for evaluate and scaling functions
pair<map<Key, EF*>, map<Key, SF*> > maps;
// Maps accessing functions returning const and non-const references
template<typename T> const map<Key, T*>& get() const { return maps.first; }
template<typename T> map<Key, T*>& get() { return maps.first; }
};
// Explicit specializations of a member function shall be declared in
// the namespace of which the class template is a member.
template<> const map<Key, SF*>&
EndgameFunctions::get<SF>() const { return maps.second; }
template<> map<Key, SF*>&
EndgameFunctions::get<SF>() { return maps.second; }
////
//// Functions
////
/// MaterialInfoTable c'tor and d'tor, called once by each thread
MaterialInfoTable::MaterialInfoTable(unsigned int numOfEntries) {
size = numOfEntries;
entries = new MaterialInfo[size];
funcs = new EndgameFunctions();
if (!entries || !funcs)
{
cerr << "Failed to allocate " << numOfEntries * sizeof(MaterialInfo)
<< " bytes for material hash table." << endl;
Application::exit_with_failure();
// Helper templates used to detect a given material distribution
template<Color Us> bool is_KXK(const Position& pos) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
return !pos.count<PAWN>(Them)
&& pos.non_pawn_material(Them) == VALUE_ZERO
&& pos.non_pawn_material(Us) >= RookValueMg;
}
}
MaterialInfoTable::~MaterialInfoTable() {
template<Color Us> bool is_KBPsKs(const Position& pos) {
return pos.non_pawn_material(Us) == BishopValueMg
&& pos.count<BISHOP>(Us) == 1
&& pos.count<PAWN >(Us) >= 1;
}
delete funcs;
delete [] entries;
}
template<Color Us> bool is_KQKRPs(const Position& pos) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
return !pos.count<PAWN>(Us)
&& pos.non_pawn_material(Us) == QueenValueMg
&& pos.count<QUEEN>(Us) == 1
&& pos.count<ROOK>(Them) == 1
&& pos.count<PAWN>(Them) >= 1;
}
/// imbalance() calculates the imbalance by comparing the piece count of each
/// piece type for both colors.
/// MaterialInfoTable::game_phase() calculates the phase given the current
/// position. Because the phase is strictly a function of the material, it
/// is stored in MaterialInfo.
template<Color Us>
int imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
Phase MaterialInfoTable::game_phase(const Position& pos) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
Value npm = pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK);
int pt1, pt2, pc, v;
int value = 0;
if (npm >= MidgameLimit)
return PHASE_MIDGAME;
else if (npm <= EndgameLimit)
return PHASE_ENDGAME;
// Second-degree polynomial material imbalance by Tord Romstad
for (pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
{
pc = pieceCount[Us][pt1];
if (!pc)
continue;
return Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
}
v = LinearCoefficients[pt1];
/// MaterialInfoTable::get_material_info() takes a position object as input,
/// computes or looks up a MaterialInfo object, and returns a pointer to it.
/// If the material configuration is not already present in the table, it
/// is stored there, so we don't have to recompute everything when the
/// same material configuration occurs again.
for (pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2)
v += QuadraticCoefficientsSameSide[pt1][pt2] * pieceCount[Us][pt2]
+ QuadraticCoefficientsOppositeSide[pt1][pt2] * pieceCount[Them][pt2];
MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) {
value += pc * v;
}
Key key = pos.get_material_key();
int index = key & (size - 1);
MaterialInfo* mi = entries + index;
return value;
}
// If mi->key matches the position's material hash key, it means that we
} // namespace
namespace Material {
/// Material::probe() takes a position object as input, looks up a MaterialEntry
/// object, and returns a pointer to it. If the material configuration is not
/// already present in the table, it is computed and stored there, so we don't
/// have to recompute everything when the same material configuration occurs again.
Entry* probe(const Position& pos, Table& entries, Endgames& endgames) {
Key key = pos.material_key();
Entry* e = entries[key];
// If e->key matches the position's material hash key, it means that we
// have analysed this material configuration before, and we can simply
// return the information we found the last time instead of recomputing it.
if (mi->key == key)
return mi;
if (e->key == key)
return e;
// Clear the MaterialInfo object, and set its key
mi->clear();
mi->key = key;
std::memset(e, 0, sizeof(Entry));
e->key = key;
e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL;
e->gamePhase = game_phase(pos);
// Store game phase
mi->gamePhase = MaterialInfoTable::game_phase(pos);
// Let's look if we have a specialized evaluation function for this particular
// material configuration. Firstly we look for a fixed configuration one, then
// for a generic one if the previous search failed.
if (endgames.probe(key, e->evaluationFunction))
return e;
// Let's look if we have a specialized evaluation function for this
// particular material configuration. First we look for a fixed
// configuration one, then a generic one if previous search failed.
if ((mi->evaluationFunction = funcs->get<EF>(key)) != NULL)
return mi;
else if ( pos.non_pawn_material(BLACK) == Value(0)
&& pos.piece_count(BLACK, PAWN) == 0
&& pos.non_pawn_material(WHITE) >= RookValueMidgame)
if (is_KXK<WHITE>(pos))
{
mi->evaluationFunction = &EvaluateKXK;
return mi;
e->evaluationFunction = &EvaluateKXK[WHITE];
return e;
}
else if ( pos.non_pawn_material(WHITE) == Value(0)
&& pos.piece_count(WHITE, PAWN) == 0
&& pos.non_pawn_material(BLACK) >= RookValueMidgame)
{
mi->evaluationFunction = &EvaluateKKX;
return mi;
}
else if ( pos.pieces(PAWN) == EmptyBoardBB
&& pos.pieces(ROOK) == EmptyBoardBB
&& pos.pieces(QUEEN) == EmptyBoardBB)
{
// Minor piece endgame with at least one minor piece per side and
// no pawns. Note that the case KmmK is already handled by KXK.
assert((pos.pieces(KNIGHT, WHITE) | pos.pieces(BISHOP, WHITE)));
assert((pos.pieces(KNIGHT, BLACK) | pos.pieces(BISHOP, BLACK)));
if ( pos.piece_count(WHITE, BISHOP) + pos.piece_count(WHITE, KNIGHT) <= 2
&& pos.piece_count(BLACK, BISHOP) + pos.piece_count(BLACK, KNIGHT) <= 2)
{
mi->evaluationFunction = &EvaluateKmmKm;
return mi;
}
if (is_KXK<BLACK>(pos))
{
e->evaluationFunction = &EvaluateKXK[BLACK];
return e;
}
// OK, we didn't find any special evaluation function for the current
// material configuration. Is there a suitable scaling function?
//
// The code below is rather messy, and it could easily get worse later,
// if we decide to add more special cases. We face problems when there
// are several conflicting applicable scaling functions and we need to
// decide which one to use.
SF* sf;
// We face problems when there are several conflicting applicable
// scaling functions and we need to decide which one to use.
EndgameBase<ScaleFactor>* sf;
if ((sf = funcs->get<SF>(key)) != NULL)
if (endgames.probe(key, sf))
{
mi->scalingFunction[sf->color()] = sf;
return mi;
e->scalingFunction[sf->color()] = sf;
return e;
}
// Generic scaling functions that refer to more then one material
// distribution. Should be probed after the specialized ones.
// Generic scaling functions that refer to more than one material
// distribution. They should be probed after the specialized ones.
// Note that these ones don't return after setting the function.
if ( pos.non_pawn_material(WHITE) == BishopValueMidgame
&& pos.piece_count(WHITE, BISHOP) == 1
&& pos.piece_count(WHITE, PAWN) >= 1)
mi->scalingFunction[WHITE] = &ScaleKBPsK;
if (is_KBPsKs<WHITE>(pos))
e->scalingFunction[WHITE] = &ScaleKBPsK[WHITE];
if ( pos.non_pawn_material(BLACK) == BishopValueMidgame
&& pos.piece_count(BLACK, BISHOP) == 1
&& pos.piece_count(BLACK, PAWN) >= 1)
mi->scalingFunction[BLACK] = &ScaleKKBPs;
if (is_KBPsKs<BLACK>(pos))
e->scalingFunction[BLACK] = &ScaleKBPsK[BLACK];
if ( pos.piece_count(WHITE, PAWN) == 0
&& pos.non_pawn_material(WHITE) == QueenValueMidgame
&& pos.piece_count(WHITE, QUEEN) == 1
&& pos.piece_count(BLACK, ROOK) == 1
&& pos.piece_count(BLACK, PAWN) >= 1)
mi->scalingFunction[WHITE] = &ScaleKQKRPs;
if (is_KQKRPs<WHITE>(pos))
e->scalingFunction[WHITE] = &ScaleKQKRPs[WHITE];
else if ( pos.piece_count(BLACK, PAWN) == 0
&& pos.non_pawn_material(BLACK) == QueenValueMidgame
&& pos.piece_count(BLACK, QUEEN) == 1
&& pos.piece_count(WHITE, ROOK) == 1
&& pos.piece_count(WHITE, PAWN) >= 1)
mi->scalingFunction[BLACK] = &ScaleKRPsKQ;
else if (is_KQKRPs<BLACK>(pos))
e->scalingFunction[BLACK] = &ScaleKQKRPs[BLACK];
if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) == Value(0))
Value npm_w = pos.non_pawn_material(WHITE);
Value npm_b = pos.non_pawn_material(BLACK);
if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN))
{
if (pos.piece_count(BLACK, PAWN) == 0)
if (!pos.count<PAWN>(BLACK))
{
assert(pos.piece_count(WHITE, PAWN) >= 2);
mi->scalingFunction[WHITE] = &ScaleKPsK;
assert(pos.count<PAWN>(WHITE) >= 2);
e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
}
else if (pos.piece_count(WHITE, PAWN) == 0)
else if (!pos.count<PAWN>(WHITE))
{
assert(pos.piece_count(BLACK, PAWN) >= 2);
mi->scalingFunction[BLACK] = &ScaleKKPs;
assert(pos.count<PAWN>(BLACK) >= 2);
e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
}
else if (pos.piece_count(WHITE, PAWN) == 1 && pos.piece_count(BLACK, PAWN) == 1)
else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
{
// This is a special case because we set scaling functions
// for both colors instead of only one.
mi->scalingFunction[WHITE] = &ScaleKPKPw;
mi->scalingFunction[BLACK] = &ScaleKPKPb;
e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
}
}
// No pawns makes it difficult to win, even with a material advantage. This
// catches some trivial draws like KK, KBK and KNK and gives a very drawish
// scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW : npm_b <= BishopValueMg ? 4 : 12);
if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW : npm_w <= BishopValueMg ? 4 : 12);
if (pos.count<PAWN>(WHITE) == 1 && npm_w - npm_b <= BishopValueMg)
e->factor[WHITE] = (uint8_t) SCALE_FACTOR_ONEPAWN;
if (pos.count<PAWN>(BLACK) == 1 && npm_b - npm_w <= BishopValueMg)
e->factor[BLACK] = (uint8_t) SCALE_FACTOR_ONEPAWN;
// Compute the space weight
if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >=
2*QueenValueMidgame + 4*RookValueMidgame + 2*KnightValueMidgame)
if (npm_w + npm_b >= 2 * QueenValueMg + 4 * RookValueMg + 2 * KnightValueMg)
{
int minorPieceCount = pos.piece_count(WHITE, KNIGHT)
+ pos.piece_count(BLACK, KNIGHT)
+ pos.piece_count(WHITE, BISHOP)
+ pos.piece_count(BLACK, BISHOP);
int minorPieceCount = pos.count<KNIGHT>(WHITE) + pos.count<BISHOP>(WHITE)
+ pos.count<KNIGHT>(BLACK) + pos.count<BISHOP>(BLACK);
mi->spaceWeight = minorPieceCount * minorPieceCount;
e->spaceWeight = make_score(minorPieceCount * minorPieceCount, 0);
}
// Evaluate the material balance
const int pieceCount[2][6] = { { pos.piece_count(WHITE, BISHOP) > 1, pos.piece_count(WHITE, PAWN), pos.piece_count(WHITE, KNIGHT),
pos.piece_count(WHITE, BISHOP), pos.piece_count(WHITE, ROOK), pos.piece_count(WHITE, QUEEN) },
{ pos.piece_count(BLACK, BISHOP) > 1, pos.piece_count(BLACK, PAWN), pos.piece_count(BLACK, KNIGHT),
pos.piece_count(BLACK, BISHOP), pos.piece_count(BLACK, ROOK), pos.piece_count(BLACK, QUEEN) } };
Color c, them;
int sign, pt1, pt2, pc;
int v, vv, matValue = 0;
// Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
// for the bishop pair "extended piece", which allows us to be more flexible
// in defining bishop pair bonuses.
const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = {
{ pos.count<BISHOP>(WHITE) > 1, pos.count<PAWN>(WHITE), pos.count<KNIGHT>(WHITE),
pos.count<BISHOP>(WHITE) , pos.count<ROOK>(WHITE), pos.count<QUEEN >(WHITE) },
{ pos.count<BISHOP>(BLACK) > 1, pos.count<PAWN>(BLACK), pos.count<KNIGHT>(BLACK),
pos.count<BISHOP>(BLACK) , pos.count<ROOK>(BLACK), pos.count<QUEEN >(BLACK) } };
for (c = WHITE, sign = 1; c <= BLACK; c++, sign = -sign)
{
// No pawns makes it difficult to win, even with a material advantage
if ( pos.piece_count(c, PAWN) == 0
&& pos.non_pawn_material(c) - pos.non_pawn_material(opposite_color(c)) <= BishopValueMidgame)
{
if ( pos.non_pawn_material(c) == pos.non_pawn_material(opposite_color(c))
|| pos.non_pawn_material(c) < RookValueMidgame)
mi->factor[c] = 0;
else
{
switch (pos.piece_count(c, BISHOP)) {
case 2:
mi->factor[c] = 32;
break;
case 1:
mi->factor[c] = 12;
break;
case 0:
mi->factor[c] = 6;
break;
}
}
}
// Redundancy of major pieces, formula based on Kaufman's paper
// "The Evaluation of Material Imbalances in Chess"
// http://mywebpages.comcast.net/danheisman/Articles/evaluation_of_material_imbalance.htm
if (pieceCount[c][ROOK] >= 1)
matValue -= sign * ((pieceCount[c][ROOK] - 1) * RedundantRookPenalty + pieceCount[c][QUEEN] * RedundantQueenPenalty);
them = opposite_color(c);
v = 0;
// Second-degree polynomial material imbalance by Tord Romstad
//
// We use NO_PIECE_TYPE as a place holder for the bishop pair "extended piece",
// this allow us to be more flexible in defining bishop pair bonuses.
for (pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; pt1++)
{
pc = pieceCount[c][pt1];
if (!pc)
continue;
vv = LinearCoefficients[pt1];
for (pt2 = NO_PIECE_TYPE; pt2 <= pt1; pt2++)
vv += pieceCount[c][pt2] * QuadraticCoefficientsSameColor[pt1][pt2]
+ pieceCount[them][pt2] * QuadraticCoefficientsOppositeColor[pt1][pt2];
v += pc * vv;
}
matValue += sign * v;
}
mi->value = int16_t(matValue / 16);
return mi;
e->value = (int16_t)((imbalance<WHITE>(pieceCount) - imbalance<BLACK>(pieceCount)) / 16);
return e;
}
/// EndgameFunctions member definitions.
/// Material::game_phase() calculates the phase given the current
/// position. Because the phase is strictly a function of the material, it
/// is stored in MaterialEntry.
EndgameFunctions::EndgameFunctions() {
Phase game_phase(const Position& pos) {
add<EvaluationFunction<KNNK> >("KNNK");
add<EvaluationFunction<KPK> >("KPK");
add<EvaluationFunction<KBNK> >("KBNK");
add<EvaluationFunction<KRKP> >("KRKP");
add<EvaluationFunction<KRKB> >("KRKB");
add<EvaluationFunction<KRKN> >("KRKN");
add<EvaluationFunction<KQKR> >("KQKR");
add<EvaluationFunction<KBBKN> >("KBBKN");
Value npm = pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK);
add<ScalingFunction<KNPK> >("KNPK");
add<ScalingFunction<KRPKR> >("KRPKR");
add<ScalingFunction<KBPKB> >("KBPKB");
add<ScalingFunction<KBPPKB> >("KBPPKB");
add<ScalingFunction<KBPKN> >("KBPKN");
add<ScalingFunction<KRPPKRP> >("KRPPKRP");
add<ScalingFunction<KRPPKRP> >("KRPPKRP");
return npm >= MidgameLimit ? PHASE_MIDGAME
: npm <= EndgameLimit ? PHASE_ENDGAME
: Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
}
EndgameFunctions::~EndgameFunctions() {
for (map<Key, EF*>::iterator it = maps.first.begin(); it != maps.first.end(); ++it)
delete (*it).second;
for (map<Key, SF*>::iterator it = maps.second.begin(); it != maps.second.end(); ++it)
delete (*it).second;
}
Key EndgameFunctions::buildKey(const string& keyCode) {
assert(keyCode.length() > 0 && keyCode[0] == 'K');
assert(keyCode.length() < 8);
stringstream s;
bool upcase = false;
// Build up a fen string with the given pieces, note that
// the fen string could be of an illegal position.
for (size_t i = 0; i < keyCode.length(); i++)
{
if (keyCode[i] == 'K')
upcase = !upcase;
s << char(upcase? toupper(keyCode[i]) : tolower(keyCode[i]));
}
s << 8 - keyCode.length() << "/8/8/8/8/8/8/8 w -";
return Position(s.str()).get_material_key();
}
const string EndgameFunctions::swapColors(const string& keyCode) {
// Build corresponding key for the opposite color: "KBPKN" -> "KNKBP"
size_t idx = keyCode.find("K", 1);
return keyCode.substr(idx) + keyCode.substr(0, idx);
}
template<class T>
void EndgameFunctions::add(const string& keyCode) {
typedef typename T::Base F;
get<F>().insert(pair<Key, F*>(buildKey(keyCode), new T(WHITE)));
get<F>().insert(pair<Key, F*>(buildKey(swapColors(keyCode)), new T(BLACK)));
}
template<class T>
T* EndgameFunctions::get(Key key) const {
typename map<Key, T*>::const_iterator it(get<T>().find(key));
return (it != get<T>().end() ? it->second : NULL);
}
} // namespace Material
+33 -135
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,161 +17,59 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(MATERIAL_H_INCLUDED)
#ifndef MATERIAL_H_INCLUDED
#define MATERIAL_H_INCLUDED
////
//// Includes
////
#include "endgame.h"
#include "misc.h"
#include "position.h"
#include "scale.h"
#include "types.h"
namespace Material {
////
//// Types
////
/// MaterialInfo is a class which contains various information about a
/// material configuration. It contains a material balance evaluation,
/// a function pointer to a special endgame evaluation function (which in
/// most cases is NULL, meaning that the standard evaluation function will
/// be used), and "scale factors" for black and white.
/// Material::Entry contains various information about a material configuration.
/// It contains a material balance evaluation, a function pointer to a special
/// endgame evaluation function (which in most cases is NULL, meaning that the
/// standard evaluation function will be used), and "scale factors".
///
/// The scale factors are used to scale the evaluation score up or down.
/// For instance, in KRB vs KR endgames, the score is scaled down by a factor
/// of 4, which will result in scores of absolute value less than one pawn.
class MaterialInfo {
struct Entry {
friend class MaterialInfoTable;
Score material_value() const { return make_score(value, value); }
Score space_weight() const { return spaceWeight; }
Phase game_phase() const { return gamePhase; }
bool specialized_eval_exists() const { return evaluationFunction != NULL; }
Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
public:
MaterialInfo() : key(0) { clear(); }
// scale_factor takes a position and a color as input, and returns a scale factor
// for the given color. We have to provide the position in addition to the color,
// because the scale factor need not be a constant: It can also be a function
// which should be applied to the position. For instance, in KBP vs K endgames,
// a scaling function for draws with rook pawns and wrong-colored bishops.
Score material_value() const;
ScaleFactor scale_factor(const Position& pos, Color c) const;
int space_weight() const;
Phase game_phase() const;
bool specialized_eval_exists() const;
Value evaluate(const Position& pos) const;
ScaleFactor scale_factor(const Position& pos, Color c) const {
private:
inline void clear();
return !scalingFunction[c] || (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE
? ScaleFactor(factor[c]) : (*scalingFunction[c])(pos);
}
Key key;
int16_t value;
uint8_t factor[2];
EndgameEvaluationFunctionBase* evaluationFunction;
EndgameScalingFunctionBase* scalingFunction[2];
int spaceWeight;
uint8_t factor[COLOR_NB];
EndgameBase<Value>* evaluationFunction;
EndgameBase<ScaleFactor>* scalingFunction[COLOR_NB];
Score spaceWeight;
Phase gamePhase;
};
/// The MaterialInfoTable class represents a pawn hash table. It is basically
/// just an array of MaterialInfo objects and a few methods for accessing these
/// objects. The most important method is get_material_info, which looks up a
/// position in the table and returns a pointer to a MaterialInfo object.
class EndgameFunctions;
typedef HashTable<Entry, 8192> Table;
class MaterialInfoTable {
Entry* probe(const Position& pos, Table& entries, Endgames& endgames);
Phase game_phase(const Position& pos);
public:
MaterialInfoTable(unsigned numOfEntries);
~MaterialInfoTable();
MaterialInfo* get_material_info(const Position& pos);
} // namespace Material
static Phase game_phase(const Position& pos);
private:
unsigned size;
MaterialInfo* entries;
EndgameFunctions* funcs;
};
////
//// Inline functions
////
/// MaterialInfo::material_value simply returns the material balance
/// evaluation that is independent from game phase.
inline Score MaterialInfo::material_value() const {
return make_score(value, value);
}
/// MaterialInfo::clear() resets a MaterialInfo object to an empty state,
/// with all slots at their default values but the key.
inline void MaterialInfo::clear() {
value = 0;
factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL);
evaluationFunction = NULL;
scalingFunction[WHITE] = scalingFunction[BLACK] = NULL;
spaceWeight = 0;
}
/// MaterialInfo::scale_factor takes a position and a color as input, and
/// returns a scale factor for the given color. We have to provide the
/// position in addition to the color, because the scale factor need not
/// to be a constant: It can also be a function which should be applied to
/// the position. For instance, in KBP vs K endgames, a scaling function
/// which checks for draws with rook pawns and wrong-colored bishops.
inline ScaleFactor MaterialInfo::scale_factor(const Position& pos, Color c) const {
if (scalingFunction[c] != NULL)
{
ScaleFactor sf = scalingFunction[c]->apply(pos);
if (sf != SCALE_FACTOR_NONE)
return sf;
}
return ScaleFactor(factor[c]);
}
/// MaterialInfo::space_weight() simply returns the weight for the space
/// evaluation for this material configuration.
inline int MaterialInfo::space_weight() const {
return spaceWeight;
}
/// MaterialInfo::game_phase() returns the game phase according
/// to this material configuration.
inline Phase MaterialInfo::game_phase() const {
return gamePhase;
}
/// MaterialInfo::specialized_eval_exists decides whether there is a
/// specialized evaluation function for the current material configuration,
/// or if the normal evaluation function should be used.
inline bool MaterialInfo::specialized_eval_exists() const {
return evaluationFunction != NULL;
}
/// MaterialInfo::evaluate applies a specialized evaluation function
/// to a given position object. It should only be called when
/// specialized_eval_exists() returns 'true'.
inline Value MaterialInfo::evaluate(const Position& pos) const {
return evaluationFunction->apply(pos);
}
#endif // !defined(MATERIAL_H_INCLUDED)
#endif // #ifndef MATERIAL_H_INCLUDED
-149
View File
@@ -1,149 +0,0 @@
/*
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
#include "types.h"
#include "mersenne.h"
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializes mt[N] with a seed */
static void init_genrand(unsigned long s)
{
mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
mt[mti] =
(1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
static void init_by_array(unsigned long init_key[], int key_length)
{
int i, j, k;
init_genrand(19650218UL);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++; j++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}
/* generates a random number on [0,0xffffffff]-interval */
uint32_t genrand_int32(void) {
unsigned long y;
static unsigned long mag01[2]={0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if init_genrand() has not been called, */
init_genrand(5489UL); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
uint64_t genrand_int64(void) {
uint64_t x, y;
x = genrand_int32(); y = genrand_int32();
return (x<<32)|y;
}
void init_mersenne(void) {
unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4;
init_by_array(init, length);
}
-40
View File
@@ -1,40 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(MERSENNE_H_INCLUDED)
#define MERSENNE_H_INCLUDED
////
//// Includes
////
#include "types.h"
////
//// Prototypes
////
extern uint32_t genrand_int32(void);
extern uint64_t genrand_int64(void);
extern void init_mersenne(void);
#endif // !defined(MERSENNE_H_INCLUDED)
+153 -227
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,262 +17,188 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#if !defined(_MSC_VER)
# include <sys/time.h>
# include <sys/types.h>
# include <unistd.h>
#else
#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <sys/timeb.h>
#endif
#include <cassert>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "bitcount.h"
#include "misc.h"
#include "thread.h"
using namespace std;
/// Version number. If this is left empty, the current date (in the format
/// YYMMDD) is used as a version number.
static const string EngineVersion = "1.6.2";
static const string AppName = "Stockfish";
static const string AppTag = "";
/// Version number. If Version is left empty, then compile date in the format
/// DD-MM-YY and show in engine_info.
static const string Version = "5";
////
//// Variables
////
/// engine_info() returns the full name of the current Stockfish version. This
/// will be either "Stockfish <Tag> DD-MM-YY" (where DD-MM-YY is the date when
/// the program was compiled) or "Stockfish <Version>", depending on whether
/// Version is empty.
bool Chess960;
const string engine_info(bool to_uci) {
uint64_t dbg_cnt0 = 0;
uint64_t dbg_cnt1 = 0;
const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
string month, day, year;
stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008"
bool dbg_show_mean = false;
bool dbg_show_hit_rate = false;
ss << "Stockfish " << Version << setfill('0');
if (Version.empty())
{
date >> month >> day >> year;
ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2);
}
////
//// Functions
////
ss << (Is64Bit ? " 64" : "")
<< (HasPext ? " BMI2" : (HasPopCnt ? " SSE4.2" : ""))
<< (to_uci ? "\nid author ": " by ")
<< "Tord Romstad, Marco Costalba and Joona Kiiski";
void dbg_hit_on(bool b) {
assert(!dbg_show_mean);
dbg_show_hit_rate = true;
dbg_cnt0++;
if (b)
dbg_cnt1++;
}
void dbg_hit_on_c(bool c, bool b) {
if (c)
dbg_hit_on(b);
}
void dbg_before() {
assert(!dbg_show_mean);
dbg_show_hit_rate = true;
dbg_cnt0++;
}
void dbg_after() {
assert(!dbg_show_mean);
dbg_show_hit_rate = true;
dbg_cnt1++;
}
void dbg_mean_of(int v) {
assert(!dbg_show_hit_rate);
dbg_show_mean = true;
dbg_cnt0++;
dbg_cnt1 += v;
}
void dbg_print_hit_rate() {
cout << "Total " << dbg_cnt0 << " Hit " << dbg_cnt1
<< " hit rate (%) " << (dbg_cnt1*100)/(dbg_cnt0 ? dbg_cnt0 : 1) << endl;
}
void dbg_print_mean() {
cout << "Total " << dbg_cnt0 << " Mean "
<< (float)dbg_cnt1 / (dbg_cnt0 ? dbg_cnt0 : 1) << endl;
}
void dbg_print_hit_rate(ofstream& logFile) {
logFile << "Total " << dbg_cnt0 << " Hit " << dbg_cnt1
<< " hit rate (%) " << (dbg_cnt1*100)/(dbg_cnt0 ? dbg_cnt0 : 1) << endl;
}
void dbg_print_mean(ofstream& logFile) {
logFile << "Total " << dbg_cnt0 << " Mean "
<< (float)dbg_cnt1 / (dbg_cnt0 ? dbg_cnt0 : 1) << endl;
}
/// engine_name() returns the full name of the current Stockfish version.
/// This will be either "Stockfish YYMMDD" (where YYMMDD is the date when the
/// program was compiled) or "Stockfish <version number>", depending on whether
/// the constant EngineVersion (defined in misc.h) is empty.
const string engine_name() {
const string cpu64(CpuHas64BitPath ? " 64bit" : "");
if (!EngineVersion.empty())
return AppName+ " " + EngineVersion + cpu64;
string date(__DATE__); // From compiler, format is "Sep 21 2008"
string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec");
size_t mon = 1 + months.find(date.substr(0, 3)) / 4;
stringstream s;
string day = (date[4] == ' ' ? date.substr(5, 1) : date.substr(4, 2));
string name = AppName + " " + AppTag + " ";
s << name << date.substr(date.length() - 2) << setfill('0')
<< setw(2) << mon << setw(2) << day << cpu64;
return s.str();
return ss.str();
}
/// get_system_time() returns the current system time, measured in
/// milliseconds.
/// Debug functions used mainly to collect run-time statistics
int get_system_time() {
static int64_t hits[2], means[2];
#if defined(_MSC_VER)
struct _timeb t;
_ftime(&t);
return int(t.time*1000 + t.millitm);
void dbg_hit_on(bool b) { ++hits[0]; if (b) ++hits[1]; }
void dbg_hit_on_c(bool c, bool b) { if (c) dbg_hit_on(b); }
void dbg_mean_of(int v) { ++means[0]; means[1] += v; }
void dbg_print() {
if (hits[0])
cerr << "Total " << hits[0] << " Hits " << hits[1]
<< " hit rate (%) " << 100 * hits[1] / hits[0] << endl;
if (means[0])
cerr << "Total " << means[0] << " Mean "
<< (double)means[1] / means[0] << endl;
}
/// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
/// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
/// can toggle the logging of std::cout and std:cin at runtime whilst preserving
/// usual i/o functionality, all without changing a single line of code!
/// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81
struct Tie: public streambuf { // MSVC requires splitted streambuf for cin and cout
Tie(streambuf* b, ofstream* f) : buf(b), file(f) {}
int sync() { return file->rdbuf()->pubsync(), buf->pubsync(); }
int overflow(int c) { return log(buf->sputc((char)c), "<< "); }
int underflow() { return buf->sgetc(); }
int uflow() { return log(buf->sbumpc(), ">> "); }
streambuf* buf;
ofstream* file;
int log(int c, const char* prefix) {
static int last = '\n';
if (last == '\n')
file->rdbuf()->sputn(prefix, 3);
return last = file->rdbuf()->sputc((char)c);
}
};
class Logger {
Logger() : in(cin.rdbuf(), &file), out(cout.rdbuf(), &file) {}
~Logger() { start(false); }
ofstream file;
Tie in, out;
public:
static void start(bool b) {
static Logger l;
if (b && !l.file.is_open())
{
l.file.open("io_log.txt", ifstream::out | ifstream::app);
cin.rdbuf(&l.in);
cout.rdbuf(&l.out);
}
else if (!b && l.file.is_open())
{
cout.rdbuf(l.out.buf);
cin.rdbuf(l.in.buf);
l.file.close();
}
}
};
/// Used to serialize access to std::cout to avoid multiple threads writing at
/// the same time.
std::ostream& operator<<(std::ostream& os, SyncCout sc) {
static Mutex m;
if (sc == IO_LOCK)
m.lock();
if (sc == IO_UNLOCK)
m.unlock();
return os;
}
/// Trampoline helper to avoid moving Logger to misc.h
void start_logger(bool b) { Logger::start(b); }
/// timed_wait() waits for msec milliseconds. It is mainly a helper to wrap
/// the conversion from milliseconds to struct timespec, as used by pthreads.
void timed_wait(WaitCondition& sleepCond, Lock& sleepLock, int msec) {
#ifdef _WIN32
int tm = msec;
#else
struct timeval t;
gettimeofday(&t, NULL);
return t.tv_sec*1000 + t.tv_usec/1000;
timespec ts, *tm = &ts;
uint64_t ms = Time::now() + msec;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000LL;
#endif
cond_timedwait(sleepCond, sleepLock, tm);
}
/// cpu_count() tries to detect the number of CPU cores.
/// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking
/// function that doesn't stall the CPU waiting for data to be loaded from memory,
/// which can be quite slow.
#ifdef NO_PREFETCH
#if !defined(_MSC_VER)
void prefetch(char*) {}
# if defined(_SC_NPROCESSORS_ONLN)
int cpu_count() {
return Min(sysconf(_SC_NPROCESSORS_ONLN), 8);
}
# else
int cpu_count() {
return 1;
}
#else
void prefetch(char* addr) {
# if defined(__INTEL_COMPILER)
// This hack prevents prefetches from being optimized away by
// Intel compiler. Both MSVC and gcc seem not be affected by this.
__asm__ ("");
# endif
#else
int cpu_count() {
SYSTEM_INFO s;
GetSystemInfo(&s);
return Min(s.dwNumberOfProcessors, 8);
# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
_mm_prefetch(addr, _MM_HINT_T0);
# else
__builtin_prefetch(addr);
# endif
}
#endif
/*
From Beowulf, from Olithink
*/
#ifndef _WIN32
/* Non-windows version */
int Bioskey()
{
fd_set readfds;
struct timeval timeout;
FD_ZERO(&readfds);
FD_SET(fileno(stdin), &readfds);
/* Set to timeout immediately */
timeout.tv_sec = 0;
timeout.tv_usec = 0;
select(16, &readfds, 0, 0, &timeout);
return (FD_ISSET(fileno(stdin), &readfds));
}
#else
/* Windows-version */
#include <windows.h>
#include <conio.h>
int Bioskey()
{
static int init = 0,
pipe;
static HANDLE inh;
DWORD dw;
/* If we're running under XBoard then we can't use _kbhit() as the input
* commands are sent to us directly over the internal pipe */
#if defined(FILE_CNT)
if (stdin->_cnt > 0)
return stdin->_cnt;
#endif
if (!init) {
init = 1;
inh = GetStdHandle(STD_INPUT_HANDLE);
pipe = !GetConsoleMode(inh, &dw);
if (!pipe) {
SetConsoleMode(inh, dw & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
FlushConsoleInputBuffer(inh);
}
}
if (pipe) {
if (!PeekNamedPipe(inh, NULL, 0, NULL, &dw, NULL))
return 1;
return dw;
} else {
// Count the number of unread input records, including keyboard,
// mouse, and window-resizing input records.
GetNumberOfConsoleInputEvents(inh, &dw);
if (dw <= 0)
return 0;
// Read data from console without removing it from the buffer
INPUT_RECORD rec[256];
DWORD recCnt;
if (!PeekConsoleInput(inh, rec, Min(dw, 256), &recCnt))
return 0;
// Search for at least one keyboard event
for (DWORD i = 0; i < recCnt; i++)
if (rec[i].EventType == KEY_EVENT)
return 1;
return 0;
}
}
#endif
+38 -50
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,64 +17,52 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(MISC_H_INCLUDED)
#ifndef MISC_H_INCLUDED
#define MISC_H_INCLUDED
////
//// Includes
////
#include <fstream>
#include <string>
#include <vector>
#include "application.h"
#include "types.h"
////
//// Macros
////
#define Min(x, y) (((x) < (y))? (x) : (y))
#define Max(x, y) (((x) < (y))? (y) : (x))
////
//// Variables
////
extern bool Chess960;
////
//// Prototypes
////
extern const std::string engine_name();
extern int get_system_time();
extern int cpu_count();
extern int Bioskey();
////
//// Debug
////
extern bool dbg_show_mean;
extern bool dbg_show_hit_rate;
extern uint64_t dbg_cnt0;
extern uint64_t dbg_cnt1;
extern const std::string engine_info(bool to_uci = false);
extern void timed_wait(WaitCondition&, Lock&, int);
extern void prefetch(char* addr);
extern void start_logger(bool b);
extern void dbg_hit_on(bool b);
extern void dbg_hit_on_c(bool c, bool b);
extern void dbg_before();
extern void dbg_after();
extern void dbg_mean_of(int v);
extern void dbg_print_hit_rate();
extern void dbg_print_mean();
extern void dbg_print_hit_rate(std::ofstream& logFile);
extern void dbg_print_mean(std::ofstream& logFile);
extern void dbg_print();
#endif // !defined(MISC_H_INCLUDED)
struct Log : public std::ofstream {
Log(const std::string& f = "log.txt") : std::ofstream(f.c_str(), std::ios::out | std::ios::app) {}
~Log() { if (is_open()) close(); }
};
namespace Time {
typedef int64_t point;
inline point now() { return system_time_to_msec(); }
}
template<class Entry, int Size>
struct HashTable {
HashTable() : table(Size, Entry()) {}
Entry* operator[](Key k) { return &table[(uint32_t)k & (Size - 1)]; }
private:
std::vector<Entry> table;
};
enum SyncCout { IO_LOCK, IO_UNLOCK };
std::ostream& operator<<(std::ostream&, SyncCout);
#define sync_cout std::cout << IO_LOCK
#define sync_endl std::endl << IO_UNLOCK
#endif // #ifndef MISC_H_INCLUDED
-152
View File
@@ -1,152 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include "move.h"
#include "piece.h"
#include "position.h"
////
//// Functions
////
/// move_from_string() takes a position and a string as input, and attempts to
/// convert the string to a move, using simple coordinate notation (g1f3,
/// a7a8q, etc.). In order to correctly parse en passant captures and castling
/// moves, we need the position. This function is not robust, and expects that
/// the input move is legal and correctly formatted.
Move move_from_string(const Position& pos, const std::string& str) {
Square from, to;
Piece piece;
Color us = pos.side_to_move();
if (str.length() < 4)
return MOVE_NONE;
// Read the from and to squares
from = square_from_string(str.substr(0, 2));
to = square_from_string(str.substr(2, 4));
// Find the moving piece
piece = pos.piece_on(from);
// If the string has more than 4 characters, try to interpret the 5th
// character as a promotion
if (type_of_piece(piece) == PAWN && str.length() > 4)
{
switch (tolower(str[4])) {
case 'n':
return make_promotion_move(from, to, KNIGHT);
case 'b':
return make_promotion_move(from, to, BISHOP);
case 'r':
return make_promotion_move(from, to, ROOK);
case 'q':
return make_promotion_move(from, to, QUEEN);
}
}
if (piece == piece_of_color_and_type(us, KING))
{
// Is this a castling move? A king move is assumed to be a castling
// move if the destination square is occupied by a friendly rook, or
// if the distance between the source and destination squares is more
// than 1.
if (pos.piece_on(to) == piece_of_color_and_type(us, ROOK))
return make_castle_move(from, to);
else if (square_distance(from, to) > 1)
{
// This is a castling move, but we have to translate it to the
// internal "king captures rook" representation.
SquareDelta delta = (to > from ? DELTA_E : DELTA_W);
Square s = from + delta;
while (relative_rank(us, s) == RANK_1 && pos.piece_on(s) != piece_of_color_and_type(us, ROOK))
s += delta;
return (relative_rank(us, s) == RANK_1 ? make_castle_move(from, s) : MOVE_NONE);
}
}
else if (piece == piece_of_color_and_type(us, PAWN))
{
// En passant move? We assume that a pawn move is an en passant move
// without further testing if the destination square is epSquare.
if (to == pos.ep_square())
return make_ep_move(from, to);
}
return make_move(from, to);
}
/// move_to_string() converts a move to a string in coordinate notation
/// (g1f3, a7a8q, etc.). The only special case is castling moves, where we
/// print in the e1g1 notation in normal chess mode, and in e1h1 notation in
/// Chess960 mode.
const std::string move_to_string(Move move) {
std::string str;
Square from = move_from(move);
Square to = move_to(move);
if (move == MOVE_NONE)
str = "(none)";
else if (move == MOVE_NULL)
str = "0000";
else
{
if (!Chess960)
{
if (move_is_short_castle(move))
return (from == SQ_E1 ? "e1g1" : "e8g8");
if (move_is_long_castle(move))
return (from == SQ_E1 ? "e1c1" : "e8c8");
}
str = square_to_string(from) + square_to_string(to);
if (move_is_promotion(move))
str += piece_type_to_char(move_promotion_piece(move), false);
}
return str;
}
/// Overload the << operator, to make it easier to print moves.
std::ostream &operator << (std::ostream& os, Move m) {
return os << move_to_string(m);
}
/// move_is_ok(), for debugging.
bool move_is_ok(Move m) {
return square_is_ok(move_from(m)) && square_is_ok(move_to(m));
}
-230
View File
@@ -1,230 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(MOVE_H_INCLUDED)
#define MOVE_H_INCLUDED
////
//// Includes
////
#include <iostream>
#include "misc.h"
#include "piece.h"
#include "square.h"
////
//// Types
////
class Position;
/// A move needs 17 bits to be stored
///
/// bit 0- 5: destination square (from 0 to 63)
/// bit 6-11: origin square (from 0 to 63)
/// bit 12-14: promotion piece type
/// bit 15: en passant flag
/// bit 16: castle flag
///
/// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in
/// because in any normal move destination square is always different
/// from origin square while MOVE_NONE and MOVE_NULL have the same
/// origin and destination square, 0 and 1 respectively.
enum Move {
MOVE_NONE = 0,
MOVE_NULL = 65
};
struct MoveStack {
Move move;
int score;
};
// Note that operator< is set up such that sorting will be in descending order
inline bool operator<(const MoveStack& f, const MoveStack& s) { return s.score < f.score; }
// An helper insertion sort implementation
template<typename T>
inline void insertion_sort(T* firstMove, T* lastMove)
{
T value;
T *cur, *p, *d;
if (firstMove != lastMove)
for (cur = firstMove + 1; cur != lastMove; cur++)
{
p = d = cur;
value = *p--;
if (value < *p)
{
do *d = *p;
while (--d != firstMove && value < *--p);
*d = value;
}
}
}
// Our dedicated sort in range [firstMove, lastMove), it is well
// tuned for non-captures where we have a lot of zero scored moves.
template<typename T>
inline void sort_moves(T* firstMove, T* lastMove)
{
T tmp;
T *p, *d;
d = lastMove;
p = firstMove - 1;
d->score = -1; // right guard
// Split positives vs non-positives
do {
while ((++p)->score > 0);
if (p != d)
{
while (--d != p && d->score <= 0);
tmp = *p;
*p = *d;
*d = tmp;
}
} while (p != d);
// Sort positives
insertion_sort<T>(firstMove, p);
d = lastMove;
p--;
// Split zero vs negatives
do {
while ((++p)->score == 0);
if (p != d)
{
while (--d != p && d->score < 0);
tmp = *p;
*p = *d;
*d = tmp;
}
} while (p != d);
// Sort negatives
insertion_sort<T>(p, lastMove);
}
// Picks up the best move in range [curMove, lastMove), one per cycle.
// It is faster then sorting all the moves in advance when moves are few,
// as normally are the possible captures. Note that is not a stable alghoritm.
template<typename T>
inline T pick_best(T* curMove, T* lastMove)
{
T bestMove, tmp;
bestMove = *curMove;
while (++curMove != lastMove)
{
if (*curMove < bestMove)
{
tmp = *curMove;
*curMove = bestMove;
bestMove = tmp;
}
}
return bestMove;
}
////
//// Inline functions
////
inline Square move_from(Move m) {
return Square((int(m) >> 6) & 0x3F);
}
inline Square move_to(Move m) {
return Square(m & 0x3F);
}
inline PieceType move_promotion_piece(Move m) {
return PieceType((int(m) >> 12) & 7);
}
inline int move_is_special(Move m) {
return m & (0x1F << 12);
}
inline int move_is_promotion(Move m) {
return m & (7 << 12);
}
inline int move_is_ep(Move m) {
return m & (1 << 15);
}
inline int move_is_castle(Move m) {
return m & (1 << 16);
}
inline bool move_is_short_castle(Move m) {
return move_is_castle(m) && (move_to(m) > move_from(m));
}
inline bool move_is_long_castle(Move m) {
return move_is_castle(m) && (move_to(m) < move_from(m));
}
inline Move make_promotion_move(Square from, Square to, PieceType promotion) {
return Move(int(to) | (int(from) << 6) | (int(promotion) << 12));
}
inline Move make_move(Square from, Square to) {
return Move(int(to) | (int(from) << 6));
}
inline Move make_castle_move(Square from, Square to) {
return Move(int(to) | (int(from) << 6) | (1 << 16));
}
inline Move make_ep_move(Square from, Square to) {
return Move(int(to) | (int(from) << 6) | (1 << 15));
}
////
//// Prototypes
////
extern std::ostream& operator<<(std::ostream &os, Move m);
extern Move move_from_string(const Position &pos, const std::string &str);
extern const std::string move_to_string(Move m);
extern bool move_is_ok(Move m);
#endif // !defined(MOVE_H_INCLUDED)
+331 -606
View File
File diff suppressed because it is too large Load Diff
+32 -18
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,28 +17,42 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(MOVEGEN_H_INCLUDED)
#ifndef MOVEGEN_H_INCLUDED
#define MOVEGEN_H_INCLUDED
////
//// Includes
////
#include "types.h"
#include "position.h"
enum GenType {
CAPTURES,
QUIETS,
QUIET_CHECKS,
EVASIONS,
NON_EVASIONS,
LEGAL
};
class Position;
////
//// Prototypes
////
template<GenType>
ExtMove* generate(const Position& pos, ExtMove* mlist);
extern MoveStack* generate_captures(const Position& pos, MoveStack* mlist);
extern MoveStack* generate_noncaptures(const Position& pos, MoveStack* mlist);
extern MoveStack* generate_non_capture_checks(const Position& pos, MoveStack* mlist);
extern MoveStack* generate_evasions(const Position& pos, MoveStack* mlist);
extern MoveStack* generate_moves(const Position& pos, MoveStack* mlist, bool pseudoLegal = false);
extern bool move_is_legal(const Position& pos, const Move m, Bitboard pinned);
extern bool move_is_legal(const Position& pos, const Move m);
/// The MoveList struct is a simple wrapper around generate(). It sometimes comes
/// in handy to use this class instead of the low level generate() function.
template<GenType T>
struct MoveList {
explicit MoveList(const Position& pos) : cur(mlist), last(generate<T>(pos, mlist)) { last->move = MOVE_NONE; }
void operator++() { ++cur; }
Move operator*() const { return cur->move; }
size_t size() const { return last - mlist; }
bool contains(Move m) const {
for (const ExtMove* it(mlist); it != last; ++it) if (it->move == m) return true;
return false;
}
#endif // !defined(MOVEGEN_H_INCLUDED)
private:
ExtMove mlist[MAX_MOVES];
ExtMove *cur, *last;
};
#endif // #ifndef MOVEGEN_H_INCLUDED
+319 -287
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,160 +18,134 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include "history.h"
#include "movegen.h"
#include "movepick.h"
#include "search.h"
#include "value.h"
////
//// Local definitions
////
#include "thread.h"
namespace {
enum MovegenPhase {
PH_TT_MOVES, // Transposition table move and mate killer
PH_GOOD_CAPTURES, // Queen promotions and captures with SEE values >= 0
PH_KILLERS, // Killer moves from the current ply
PH_NONCAPTURES, // Non-captures and underpromotions
PH_BAD_CAPTURES, // Queen promotions and captures with SEE values < 0
PH_EVASIONS, // Check evasions
PH_QCAPTURES, // Captures in quiescence search
PH_QCHECKS, // Non-capture checks in quiescence search
PH_STOP
enum Stages {
MAIN_SEARCH, CAPTURES_S1, KILLERS_S1, QUIETS_1_S1, QUIETS_2_S1, BAD_CAPTURES_S1,
EVASION, EVASIONS_S2,
QSEARCH_0, CAPTURES_S3, QUIET_CHECKS_S3,
QSEARCH_1, CAPTURES_S4,
PROBCUT, CAPTURES_S5,
RECAPTURE, CAPTURES_S6,
STOP
};
CACHE_LINE_ALIGNMENT
const uint8_t MainSearchPhaseTable[] = { PH_TT_MOVES, PH_GOOD_CAPTURES, PH_KILLERS, PH_NONCAPTURES, PH_BAD_CAPTURES, PH_STOP};
const uint8_t EvasionsPhaseTable[] = { PH_TT_MOVES, PH_EVASIONS, PH_STOP};
const uint8_t QsearchWithChecksPhaseTable[] = { PH_TT_MOVES, PH_QCAPTURES, PH_QCHECKS, PH_STOP};
const uint8_t QsearchWithoutChecksPhaseTable[] = { PH_TT_MOVES, PH_QCAPTURES, PH_STOP};
}
////
//// Functions
////
/// Constructor for the MovePicker class. Apart from the position for which
/// it is asked to pick legal moves, MovePicker also wants some information
/// to help it to return the presumably good moves first, to decide which
/// moves to return (in the quiescence search, for instance, we only want to
/// search captures, promotions and some checks) and about how important good
/// move ordering is at the current node.
MovePicker::MovePicker(const Position& p, Move ttm, Depth d,
const History& h, SearchStack* ss) : pos(p), H(h) {
int searchTT = ttm;
ttMoves[0].move = ttm;
finished = false;
lastBadCapture = badCaptures;
pinned = p.pinned_pieces(pos.side_to_move());
if (ss && !p.is_check())
// Our insertion sort, which is guaranteed (and also needed) to be stable
void insertion_sort(ExtMove* begin, ExtMove* end)
{
ttMoves[1].move = (ss->mateKiller == ttm)? MOVE_NONE : ss->mateKiller;
searchTT |= ttMoves[1].move;
killers[0].move = ss->killers[0];
killers[1].move = ss->killers[1];
} else
ttMoves[1].move = killers[0].move = killers[1].move = MOVE_NONE;
ExtMove tmp, *p, *q;
if (p.is_check())
phasePtr = EvasionsPhaseTable;
else if (d > Depth(0))
phasePtr = MainSearchPhaseTable;
else if (d == Depth(0))
phasePtr = QsearchWithChecksPhaseTable;
else
phasePtr = QsearchWithoutChecksPhaseTable;
for (p = begin + 1; p < end; ++p)
{
tmp = *p;
for (q = p; q != begin && *(q-1) < tmp; --q)
*q = *(q-1);
*q = tmp;
}
}
phasePtr += !searchTT - 1;
go_next_phase();
}
// Unary predicate used by std::partition to split positive values from remaining
// ones so as to sort the two sets separately, with the second sort delayed.
inline bool has_positive_value(const ExtMove& ms) { return ms.value > 0; }
/// MovePicker::go_next_phase() generates, scores and sorts the next bunch
/// of moves when there are no more moves to try for the current phase.
void MovePicker::go_next_phase() {
curMove = moves;
phase = *(++phasePtr);
switch (phase) {
case PH_TT_MOVES:
curMove = ttMoves;
lastMove = curMove + 2;
return;
case PH_GOOD_CAPTURES:
lastMove = generate_captures(pos, moves);
score_captures();
return;
case PH_KILLERS:
curMove = killers;
lastMove = curMove + 2;
return;
case PH_NONCAPTURES:
lastMove = generate_noncaptures(pos, moves);
score_noncaptures();
sort_moves(moves, lastMove);
return;
case PH_BAD_CAPTURES:
// Bad captures SEE value is already calculated so just sort them
// to get SEE move ordering.
curMove = badCaptures;
lastMove = lastBadCapture;
return;
case PH_EVASIONS:
assert(pos.is_check());
lastMove = generate_evasions(pos, moves);
score_evasions();
return;
case PH_QCAPTURES:
lastMove = generate_captures(pos, moves);
score_captures();
return;
case PH_QCHECKS:
// Perhaps we should order moves move here? FIXME
lastMove = generate_non_capture_checks(pos, moves);
return;
case PH_STOP:
lastMove = curMove + 1; // hack to be friendly for get_next_move()
return;
default:
assert(false);
return;
// Picks the best move in the range (begin, end) and moves it to the front.
// It's faster than sorting all the moves in advance when there are few
// moves e.g. possible captures.
inline ExtMove* pick_best(ExtMove* begin, ExtMove* end)
{
std::swap(*begin, *std::max_element(begin, end));
return begin;
}
}
/// MovePicker::score_captures(), MovePicker::score_noncaptures() and
/// MovePicker::score_evasions() assign a numerical move ordering score
/// to each move in a move list. The moves with highest scores will be
/// picked first by get_next_move().
/// Constructors of the MovePicker class. As arguments we pass information
/// to help it to return the (presumably) good moves first, to decide which
/// moves to return (in the quiescence search, for instance, we only want to
/// search captures, promotions and some checks) and how important good move
/// ordering is at the current node.
void MovePicker::score_captures() {
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
Move* cm, Move* fm, Search::Stack* s) : pos(p), history(h), depth(d) {
assert(d > DEPTH_ZERO);
cur = end = moves;
endBadCaptures = moves + MAX_MOVES - 1;
countermoves = cm;
followupmoves = fm;
ss = s;
if (pos.checkers())
stage = EVASION;
else
stage = MAIN_SEARCH;
ttMove = (ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE);
end += (ttMove != MOVE_NONE);
}
MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h,
Square s) : pos(p), history(h), cur(moves), end(moves) {
assert(d <= DEPTH_ZERO);
if (pos.checkers())
stage = EVASION;
else if (d > DEPTH_QS_NO_CHECKS)
stage = QSEARCH_0;
else if (d > DEPTH_QS_RECAPTURES)
{
stage = QSEARCH_1;
// Skip TT move if is not a capture or a promotion. This avoids qsearch
// tree explosion due to a possible perpetual check or similar rare cases
// when TT table is full.
if (ttm && !pos.capture_or_promotion(ttm))
ttm = MOVE_NONE;
}
else
{
stage = RECAPTURE;
recaptureSquare = s;
ttm = MOVE_NONE;
}
ttMove = (ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE);
end += (ttMove != MOVE_NONE);
}
MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, PieceType pt)
: pos(p), history(h), cur(moves), end(moves) {
assert(!pos.checkers());
stage = PROBCUT;
// In ProbCut we generate only captures that are better than the parent's
// captured piece.
captureThreshold = PieceValue[MG][pt];
ttMove = (ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE);
if (ttMove && (!pos.capture(ttMove) || pos.see(ttMove) <= captureThreshold))
ttMove = MOVE_NONE;
end += (ttMove != MOVE_NONE);
}
/// score() assign a numerical value to each move in a move list. The moves with
/// highest values will be picked first.
template<>
void MovePicker::score<CAPTURES>() {
// Winning and equal captures in the main search are ordered by MVV/LVA.
// Suprisingly, this appears to perform slightly better than SEE based
// move ordering. The reason is probably that in a position with a winning
@@ -181,180 +155,238 @@ void MovePicker::score_captures() {
// where it is possible to recapture with the hanging piece). Exchanging
// big pieces before capturing a hanging piece probably helps to reduce
// the subtree size.
// In main search we want to push captures with negative SEE values to
// badCaptures[] array, but instead of doing it now we delay till 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 (idea from Pablo Vazquez).
// In main search we want to push captures with negative SEE values to the
// badCaptures[] array, but instead of doing it now we delay until the move
// has been picked up in pick_move_from_list(). This way we save some SEE
// calls in case we get a cutoff.
Move m;
// Use MVV/LVA ordering
for (MoveStack* cur = moves; cur != lastMove; cur++)
for (ExtMove* it = moves; it != end; ++it)
{
m = cur->move;
if (move_is_promotion(m))
cur->score = QueenValueMidgame;
m = it->move;
it->value = PieceValue[MG][pos.piece_on(to_sq(m))]
- Value(type_of(pos.moved_piece(m)));
if (type_of(m) == ENPASSANT)
it->value += PieceValue[MG][PAWN];
else if (type_of(m) == PROMOTION)
it->value += PieceValue[MG][promotion_type(m)] - PieceValue[MG][PAWN];
}
}
template<>
void MovePicker::score<QUIETS>() {
Move m;
for (ExtMove* it = moves; it != end; ++it)
{
m = it->move;
it->value = history[pos.moved_piece(m)][to_sq(m)];
}
}
template<>
void MovePicker::score<EVASIONS>() {
// Try good captures ordered by MVV/LVA, then non-captures if destination square
// is not under attack, ordered by history value, then bad-captures and quiet
// moves with a negative SEE. This last group is ordered by the SEE value.
Move m;
Value see;
for (ExtMove* it = moves; it != end; ++it)
{
m = it->move;
if ((see = pos.see_sign(m)) < VALUE_ZERO)
it->value = see - HistoryStats::Max; // At the bottom
else if (pos.capture(m))
it->value = PieceValue[MG][pos.piece_on(to_sq(m))]
- Value(type_of(pos.moved_piece(m))) + HistoryStats::Max;
else
cur->score = pos.midgame_value_of_piece_on(move_to(m))
- pos.type_of_piece_on(move_from(m));
it->value = history[pos.moved_piece(m)][to_sq(m)];
}
}
void MovePicker::score_noncaptures() {
// First score by history, when no history is available then use
// piece/square tables values. This seems to be better then a
// random choice when we don't have an history for any move.
Move m;
Piece piece;
Square from, to;
int hs;
for (MoveStack* cur = moves; cur != lastMove; cur++)
{
m = cur->move;
from = move_from(m);
to = move_to(m);
piece = pos.piece_on(from);
hs = H.move_ordering_score(piece, to);
/// generate_next_stage() generates, scores and sorts the next bunch of moves,
/// when there are no more moves to try for the current stage.
// Ensure history is always preferred to pst
if (hs > 0)
hs += 1000;
void MovePicker::generate_next_stage() {
// pst based scoring
cur->score = hs + mg_value(pos.pst_delta(piece, from, to));
cur = moves;
switch (++stage) {
case CAPTURES_S1: case CAPTURES_S3: case CAPTURES_S4: case CAPTURES_S5: case CAPTURES_S6:
end = generate<CAPTURES>(pos, moves);
score<CAPTURES>();
return;
case KILLERS_S1:
cur = killers;
end = cur + 2;
killers[0].move = ss->killers[0];
killers[1].move = ss->killers[1];
killers[2].move = killers[3].move = MOVE_NONE;
killers[4].move = killers[5].move = MOVE_NONE;
// Please note that following code is racy and could yield to rare (less
// than 1 out of a million) duplicated entries in SMP case. This is harmless.
// Be sure countermoves are different from killers
for (int i = 0; i < 2; ++i)
if ( countermoves[i] != (cur+0)->move
&& countermoves[i] != (cur+1)->move)
(end++)->move = countermoves[i];
// Be sure followupmoves are different from killers and countermoves
for (int i = 0; i < 2; ++i)
if ( followupmoves[i] != (cur+0)->move
&& followupmoves[i] != (cur+1)->move
&& followupmoves[i] != (cur+2)->move
&& followupmoves[i] != (cur+3)->move)
(end++)->move = followupmoves[i];
return;
case QUIETS_1_S1:
endQuiets = end = generate<QUIETS>(pos, moves);
score<QUIETS>();
end = std::partition(cur, end, has_positive_value);
insertion_sort(cur, end);
return;
case QUIETS_2_S1:
cur = end;
end = endQuiets;
if (depth >= 3 * ONE_PLY)
insertion_sort(cur, end);
return;
case BAD_CAPTURES_S1:
// Just pick them in reverse order to get MVV/LVA ordering
cur = moves + MAX_MOVES - 1;
end = endBadCaptures;
return;
case EVASIONS_S2:
end = generate<EVASIONS>(pos, moves);
if (end > moves + 1)
score<EVASIONS>();
return;
case QUIET_CHECKS_S3:
end = generate<QUIET_CHECKS>(pos, moves);
return;
case EVASION: case QSEARCH_0: case QSEARCH_1: case PROBCUT: case RECAPTURE:
stage = STOP;
/* Fall through */
case STOP:
end = cur + 1; // Avoid another next_phase() call
return;
default:
assert(false);
}
}
void MovePicker::score_evasions() {
// 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.
Move m;
int seeScore;
for (MoveStack* cur = moves; cur != lastMove; cur++)
{
m = cur->move;
if ((seeScore = pos.see_sign(m)) < 0)
cur->score = seeScore;
else if (pos.move_is_capture(m))
cur->score = pos.midgame_value_of_piece_on(move_to(m))
- pos.type_of_piece_on(move_from(m)) + HistoryMax;
else
cur->score = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
}
}
/// MovePicker::get_next_move() is the most important method of the MovePicker
/// class. It returns a new legal move every time it is called, until there
/// are no more moves left.
/// It picks the move with the biggest score from a list of generated moves taking
/// care not to return the tt move if has already been searched previously.
Move MovePicker::get_next_move() {
/// next_move() is the most important method of the MovePicker class. It returns
/// a new pseudo legal move every time it is called, until there are no more moves
/// left. It picks the move with the biggest value from a list of generated moves
/// taking care not to return the ttMove if it has already been searched.
template<>
Move MovePicker::next_move<false>() {
Move move;
while (true)
{
while (curMove != lastMove)
{
switch (phase) {
while (cur == end)
generate_next_stage();
case PH_TT_MOVES:
move = (curMove++)->move;
if ( move != MOVE_NONE
&& move_is_legal(pos, move, pinned))
switch (stage) {
case MAIN_SEARCH: case EVASION: case QSEARCH_0: case QSEARCH_1: case PROBCUT:
++cur;
return ttMove;
case CAPTURES_S1:
move = pick_best(cur++, end)->move;
if (move != ttMove)
{
if (pos.see_sign(move) >= VALUE_ZERO)
return move;
break;
case PH_GOOD_CAPTURES:
move = pick_best(curMove++, lastMove).move;
if ( move != ttMoves[0].move
&& move != ttMoves[1].move
&& pos.pl_move_is_legal(move, pinned))
{
// Check for a non negative SEE now
int seeValue = pos.see_sign(move);
if (seeValue >= 0)
return move;
// Losing capture, move it to the badCaptures[] array, note
// that move has now been already checked for legality.
assert(int(lastBadCapture - badCaptures) < 63);
lastBadCapture->move = move;
lastBadCapture->score = seeValue;
lastBadCapture++;
}
break;
case PH_KILLERS:
move = (curMove++)->move;
if ( move != MOVE_NONE
&& move != ttMoves[0].move
&& move != ttMoves[1].move
&& move_is_legal(pos, move, pinned)
&& !pos.move_is_capture(move))
return move;
break;
case PH_NONCAPTURES:
move = (curMove++)->move;
if ( move != ttMoves[0].move
&& move != ttMoves[1].move
&& move != killers[0].move
&& move != killers[1].move
&& pos.pl_move_is_legal(move, pinned))
return move;
break;
case PH_BAD_CAPTURES:
move = pick_best(curMove++, lastMove).move;
return move;
case PH_EVASIONS:
case PH_QCAPTURES:
move = pick_best(curMove++, lastMove).move;
if ( move != ttMoves[0].move
&& pos.pl_move_is_legal(move, pinned))
return move;
break;
case PH_QCHECKS:
move = (curMove++)->move;
if ( move != ttMoves[0].move
&& pos.pl_move_is_legal(move, pinned))
return move;
break;
case PH_STOP:
return MOVE_NONE;
default:
assert(false);
break;
// Losing capture, move it to the tail of the array
(endBadCaptures--)->move = move;
}
break;
case KILLERS_S1:
move = (cur++)->move;
if ( move != MOVE_NONE
&& move != ttMove
&& pos.pseudo_legal(move)
&& !pos.capture(move))
return move;
break;
case QUIETS_1_S1: case QUIETS_2_S1:
move = (cur++)->move;
if ( move != ttMove
&& move != killers[0].move
&& move != killers[1].move
&& move != killers[2].move
&& move != killers[3].move
&& move != killers[4].move
&& move != killers[5].move)
return move;
break;
case BAD_CAPTURES_S1:
return (cur--)->move;
case EVASIONS_S2: case CAPTURES_S3: case CAPTURES_S4:
move = pick_best(cur++, end)->move;
if (move != ttMove)
return move;
break;
case CAPTURES_S5:
move = pick_best(cur++, end)->move;
if (move != ttMove && pos.see(move) > captureThreshold)
return move;
break;
case CAPTURES_S6:
move = pick_best(cur++, end)->move;
if (to_sq(move) == recaptureSquare)
return move;
break;
case QUIET_CHECKS_S3:
move = (cur++)->move;
if (move != ttMove)
return move;
break;
case STOP:
return MOVE_NONE;
default:
assert(false);
}
go_next_phase();
}
}
/// A variant of get_next_move() which takes a lock as a parameter, used to
/// prevent multiple threads from picking the same move at a split point.
Move MovePicker::get_next_move(Lock &lock) {
lock_grab(&lock);
if (finished)
{
lock_release(&lock);
return MOVE_NONE;
}
Move m = get_next_move();
if (m == MOVE_NONE)
finished = true;
lock_release(&lock);
return m;
}
/// Version of next_move() to use at split point nodes where the move is grabbed
/// from the split point's shared MovePicker object. This function is not thread
/// safe so must be lock protected by the caller.
template<>
Move MovePicker::next_move<true>() { return ss->splitPoint->movePicker->next_move<false>(); }
+75 -53
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,74 +17,96 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined MOVEPICK_H_INCLUDED
#ifndef MOVEPICK_H_INCLUDED
#define MOVEPICK_H_INCLUDED
////
//// Includes
////
#include <algorithm> // For std::max
#include <cstring> // For std::memset
#include "depth.h"
#include "history.h"
#include "lock.h"
#include "movegen.h"
#include "position.h"
#include "search.h"
#include "types.h"
////
//// Types
////
/// The Stats struct stores moves statistics. According to the template parameter
/// the class can store History, Gains and Countermoves. History records how often
/// different moves have been successful or unsuccessful during the current search
/// and is used for reduction and move ordering decisions. Gains records the move's
/// best evaluation gain from one ply to the next and is used for pruning decisions.
/// Countermoves store the move that refute a previous one. Entries are stored
/// using only the moving piece and destination square, hence two moves with
/// different origin but same destination and piece will be considered identical.
template<bool Gain, typename T>
struct Stats {
struct SearchStack;
static const Value Max = Value(2000);
/// MovePicker is a class which is used to pick one legal move at a time from
/// the current position. It is initialized with a Position object and a few
/// moves we have reason to believe are good. The most important method is
/// MovePicker::pick_next_move(), which returns a new legal move each time it
/// is called, until there are no legal moves left, when MOVE_NONE is returned.
/// In order to improve the efficiency of the alpha beta algorithm, MovePicker
/// attempts to return the moves which are most likely to be strongest first.
const T* operator[](Piece pc) const { return table[pc]; }
void clear() { std::memset(table, 0, sizeof(table)); }
void update(Piece pc, Square to, Move m) {
if (m == table[pc][to].first)
return;
table[pc][to].second = table[pc][to].first;
table[pc][to].first = m;
}
void update(Piece pc, Square to, Value v) {
if (Gain)
table[pc][to] = std::max(v, table[pc][to] - 1);
else if (abs(table[pc][to] + v) < Max)
table[pc][to] += v;
}
private:
T table[PIECE_NB][SQUARE_NB];
};
typedef Stats< true, Value> GainsStats;
typedef Stats<false, Value> HistoryStats;
typedef Stats<false, std::pair<Move, Move> > MovesStats;
/// MovePicker class is used to pick one pseudo legal move at a time from the
/// current position. The most important method is next_move(), which returns a
/// new pseudo legal move each time it is called, until there are no moves left,
/// when MOVE_NONE is returned. In order to improve the efficiency of the alpha
/// beta algorithm, MovePicker attempts to return the moves which are most likely
/// to get a cut-off first.
class MovePicker {
MovePicker& operator=(const MovePicker&); // silence a warning under MSVC
MovePicker& operator=(const MovePicker&); // Silence a warning under MSVC
public:
MovePicker(const Position& p, Move ttm, Depth d, const History& h, SearchStack* ss = NULL);
Move get_next_move();
Move get_next_move(Lock& lock);
int number_of_evasions() const;
MovePicker(const Position&, Move, Depth, const HistoryStats&, Square);
MovePicker(const Position&, Move, const HistoryStats&, PieceType);
MovePicker(const Position&, Move, Depth, const HistoryStats&, Move*, Move*, Search::Stack*);
template<bool SpNode> Move next_move();
private:
void score_captures();
void score_noncaptures();
void score_evasions();
void go_next_phase();
template<GenType> void score();
void generate_next_stage();
const Position& pos;
const History& H;
MoveStack ttMoves[2], killers[2];
bool finished;
int phase;
const uint8_t* phasePtr;
MoveStack *curMove, *lastMove, *lastBadCapture;
Bitboard pinned;
MoveStack moves[256], badCaptures[64];
const HistoryStats& history;
Search::Stack* ss;
Move* countermoves;
Move* followupmoves;
Depth depth;
Move ttMove;
ExtMove killers[6];
Square recaptureSquare;
Value captureThreshold;
int stage;
ExtMove *cur, *end, *endQuiets, *endBadCaptures;
ExtMove moves[MAX_MOVES];
};
////
//// Inline functions
////
/// MovePicker::number_of_evasions() simply returns the number of moves in
/// evasions phase. It is intended to be used in positions where the side to
/// move is in check, for detecting checkmates or situations where there is
/// only a single reply to check.
/// WARNING: It works as long as PH_EVASIONS is the _only_ phase for evasions.
inline int MovePicker::number_of_evasions() const {
return int(lastMove - moves);
}
#endif // !defined(MOVEPICK_H_INCLUDED)
#endif // #ifndef MOVEPICK_H_INCLUDED
+256
View File
@@ -0,0 +1,256 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <iomanip>
#include <sstream>
#include <stack>
#include "movegen.h"
#include "notation.h"
#include "position.h"
using namespace std;
static const char* PieceToChar[COLOR_NB] = { " PNBRQK", " pnbrqk" };
/// score_to_uci() converts a value to a string suitable for use with the UCI
/// protocol specifications:
///
/// cp <x> The score from the engine's point of view in centipawns.
/// mate <y> Mate in y moves, not plies. If the engine is getting mated
/// use negative values for y.
string score_to_uci(Value v, Value alpha, Value beta) {
stringstream ss;
if (abs(v) < VALUE_MATE_IN_MAX_PLY)
ss << "cp " << v * 100 / PawnValueEg;
else
ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2;
ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
return ss.str();
}
/// move_to_uci() converts a move to a string in coordinate notation
/// (g1f3, a7a8q, etc.). The only special case is castling moves, where we print
/// in the e1g1 notation in normal chess mode, and in e1h1 notation in chess960
/// mode. Internally castling moves are always encoded as "king captures rook".
const string move_to_uci(Move m, bool chess960) {
Square from = from_sq(m);
Square to = to_sq(m);
if (m == MOVE_NONE)
return "(none)";
if (m == MOVE_NULL)
return "0000";
if (type_of(m) == CASTLING && !chess960)
to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
string move = to_string(from) + to_string(to);
if (type_of(m) == PROMOTION)
move += PieceToChar[BLACK][promotion_type(m)]; // Lower case
return move;
}
/// move_from_uci() takes a position and a string representing a move in
/// simple coordinate notation and returns an equivalent legal Move if any.
Move move_from_uci(const Position& pos, string& str) {
if (str.length() == 5) // Junior could send promotion piece in uppercase
str[4] = char(tolower(str[4]));
for (MoveList<LEGAL> it(pos); *it; ++it)
if (str == move_to_uci(*it, pos.is_chess960()))
return *it;
return MOVE_NONE;
}
/// move_to_san() takes a position and a legal Move as input and returns its
/// short algebraic notation representation.
const string move_to_san(Position& pos, Move m) {
if (m == MOVE_NONE)
return "(none)";
if (m == MOVE_NULL)
return "(null)";
assert(MoveList<LEGAL>(pos).contains(m));
Bitboard others, b;
string san;
Color us = pos.side_to_move();
Square from = from_sq(m);
Square to = to_sq(m);
Piece pc = pos.piece_on(from);
PieceType pt = type_of(pc);
if (type_of(m) == CASTLING)
san = to > from ? "O-O" : "O-O-O";
else
{
if (pt != PAWN)
{
san = PieceToChar[WHITE][pt]; // Upper case
// A disambiguation occurs if we have more then one piece of type 'pt'
// that can reach 'to' with a legal move.
others = b = (pos.attacks_from(pc, to) & pos.pieces(us, pt)) ^ from;
while (b)
{
Square s = pop_lsb(&b);
if (!pos.legal(make_move(s, to), pos.pinned_pieces(us)))
others ^= s;
}
if (!others)
{ /* Disambiguation is not needed */ }
else if (!(others & file_bb(from)))
san += to_char(file_of(from));
else if (!(others & rank_bb(from)))
san += to_char(rank_of(from));
else
san += to_string(from);
}
else if (pos.capture(m))
san = to_char(file_of(from));
if (pos.capture(m))
san += 'x';
san += to_string(to);
if (type_of(m) == PROMOTION)
san += string("=") + PieceToChar[WHITE][promotion_type(m)];
}
if (pos.gives_check(m, CheckInfo(pos)))
{
StateInfo st;
pos.do_move(m, st);
san += MoveList<LEGAL>(pos).size() ? "+" : "#";
pos.undo_move(m);
}
return san;
}
/// pretty_pv() formats human-readable search information, typically to be
/// appended to the search log file. It uses the two helpers below to pretty
/// format the time and score respectively.
static string format(int64_t msecs) {
const int MSecMinute = 1000 * 60;
const int MSecHour = 1000 * 60 * 60;
int64_t hours = msecs / MSecHour;
int64_t minutes = (msecs % MSecHour) / MSecMinute;
int64_t seconds = ((msecs % MSecHour) % MSecMinute) / 1000;
stringstream ss;
if (hours)
ss << hours << ':';
ss << setfill('0') << setw(2) << minutes << ':' << setw(2) << seconds;
return ss.str();
}
static string format(Value v) {
stringstream ss;
if (v >= VALUE_MATE_IN_MAX_PLY)
ss << "#" << (VALUE_MATE - v + 1) / 2;
else if (v <= VALUE_MATED_IN_MAX_PLY)
ss << "-#" << (VALUE_MATE + v) / 2;
else
ss << setprecision(2) << fixed << showpos << double(v) / PawnValueEg;
return ss.str();
}
string pretty_pv(Position& pos, int depth, Value value, int64_t msecs, Move pv[]) {
const uint64_t K = 1000;
const uint64_t M = 1000000;
std::stack<StateInfo> st;
Move* m = pv;
string san, str, padding;
stringstream ss;
ss << setw(2) << depth << setw(8) << format(value) << setw(8) << format(msecs);
if (pos.nodes_searched() < M)
ss << setw(8) << pos.nodes_searched() / 1 << " ";
else if (pos.nodes_searched() < K * M)
ss << setw(7) << pos.nodes_searched() / K << "K ";
else
ss << setw(7) << pos.nodes_searched() / M << "M ";
str = ss.str();
padding = string(str.length(), ' ');
while (*m != MOVE_NONE)
{
san = move_to_san(pos, *m) + ' ';
if ((str.length() + san.length()) % 80 <= san.length()) // Exceed 80 cols
str += "\n" + padding;
str += san;
st.push(StateInfo());
pos.do_move(*m++, st.top());
}
while (m != pv)
pos.undo_move(*--m);
return str;
}
+11 -14
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,22 +17,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NOTATION_H_INCLUDED
#define NOTATION_H_INCLUDED
#if !defined(BITBASE_H_INCLUDED)
#define BITBASE_H_INCLUDED
////
//// Includes
////
#include <string>
#include "types.h"
class Position;
////
//// Prototypes
////
std::string score_to_uci(Value v, Value alpha = -VALUE_INFINITE, Value beta = VALUE_INFINITE);
Move move_from_uci(const Position& pos, std::string& str);
const std::string move_to_uci(Move m, bool chess960);
const std::string move_to_san(Position& pos, Move m);
std::string pretty_pv(Position& pos, int depth, Value score, int64_t msecs, Move pv[]);
extern void generate_kpk_bitbase(uint8_t bitbase[]);
#endif // !defined(BITBASE_H_INCLUDED)
#endif // #ifndef NOTATION_H_INCLUDED
+247 -299
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,352 +17,300 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <algorithm>
#include <cassert>
#include <cstring>
#include "bitboard.h"
#include "bitcount.h"
#include "pawns.h"
#include "position.h"
////
//// Local definitions
////
namespace {
/// Constants and variables
#define V Value
#define S(mg, eg) make_score(mg, eg)
// Doubled pawn penalty by file
const Score DoubledPawnPenalty[8] = {
const Score Doubled[FILE_NB] = {
S(13, 43), S(20, 48), S(23, 48), S(23, 48),
S(23, 48), S(23, 48), S(20, 48), S(13, 43)
};
S(23, 48), S(23, 48), S(20, 48), S(13, 43) };
// Isolated pawn penalty by file
const Score IsolatedPawnPenalty[8] = {
S(25, 30), S(36, 35), S(40, 35), S(40, 35),
S(40, 35), S(40, 35), S(36, 35), S(25, 30)
};
// Isolated pawn penalty by opposed flag and file
const Score Isolated[2][FILE_NB] = {
{ S(37, 45), S(54, 52), S(60, 52), S(60, 52),
S(60, 52), S(60, 52), S(54, 52), S(37, 45) },
{ S(25, 30), S(36, 35), S(40, 35), S(40, 35),
S(40, 35), S(40, 35), S(36, 35), S(25, 30) } };
// Backward pawn penalty by file
const Score BackwardPawnPenalty[8] = {
S(20, 28), S(29, 31), S(33, 31), S(33, 31),
S(33, 31), S(33, 31), S(29, 31), S(20, 28)
};
// Backward pawn penalty by opposed flag and file
const Score Backward[2][FILE_NB] = {
{ S(30, 42), S(43, 46), S(49, 46), S(49, 46),
S(49, 46), S(49, 46), S(43, 46), S(30, 42) },
{ S(20, 28), S(29, 31), S(33, 31), S(33, 31),
S(33, 31), S(33, 31), S(29, 31), S(20, 28) } };
// Pawn chain membership bonus by file
const Score ChainBonus[8] = {
S(11,-1), S(13,-1), S(13,-1), S(14,-1),
S(14,-1), S(13,-1), S(13,-1), S(11,-1)
};
// Connected pawn bonus by file and rank (initialized by formula)
Score Connected[FILE_NB][RANK_NB];
// Candidate passed pawn bonus by rank
const Score CandidateBonus[8] = {
const Score CandidatePassed[RANK_NB] = {
S( 0, 0), S( 6, 13), S(6,13), S(14,29),
S(34,68), S(83,166), S(0, 0), S( 0, 0)
};
S(34,68), S(83,166), S(0, 0), S( 0, 0) };
// Pawn storm tables for positions with opposite castling
const int QStormTable[64] = {
0, 0, 0, 0, 0, 0, 0, 0,
-22,-22,-22,-14,-6, 0, 0, 0,
-6,-10,-10,-10,-6, 0, 0, 0,
4, 12, 16, 12, 4, 0, 0, 0,
16, 23, 23, 16, 0, 0, 0, 0,
23, 31, 31, 23, 0, 0, 0, 0,
23, 31, 31, 23, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
// Bonus for file distance of the two outermost pawns
const Score PawnsFileSpan = S(0, 15);
const int KStormTable[64] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,-10,-19,-28,-33,-33,
0, 0, 0,-10,-15,-19,-24,-24,
0, 0, 0, 0, 1, 1, 1, 1,
0, 0, 0, 0, 1, 10, 19, 19,
0, 0, 0, 0, 1, 19, 31, 27,
0, 0, 0, 0, 0, 22, 31, 22,
0, 0, 0, 0, 0, 0, 0, 0
};
// Unsupported pawn penalty
const Score UnsupportedPawnPenalty = S(20, 10);
// Pawn storm open file bonuses by file
const int16_t KStormOpenFileBonus[8] = { 31, 31, 18, 0, 0, 0, 0, 0 };
const int16_t QStormOpenFileBonus[8] = { 0, 0, 0, 0, 0, 26, 42, 26 };
// Weakness of our pawn shelter in front of the king indexed by [rank]
const Value ShelterWeakness[RANK_NB] =
{ V(100), V(0), V(27), V(73), V(92), V(101), V(101) };
// Pawn storm lever bonuses by file
const int StormLeverBonus[8] = { -8, -8, -13, 0, 0, -13, -8, -8 };
// Danger of enemy pawns moving toward our king indexed by
// [no friendly pawn | pawn unblocked | pawn blocked][rank of enemy pawn]
const Value StormDanger[3][RANK_NB] = {
{ V( 0), V(64), V(128), V(51), V(26) },
{ V(26), V(32), V( 96), V(38), V(20) },
{ V( 0), V( 0), V(160), V(25), V(13) } };
}
// Max bonus for king safety. Corresponds to start position with all the pawns
// in front of the king and no enemy pawn on the horizon.
const Value MaxSafetyBonus = V(263);
#undef S
#undef V
////
//// Functions
////
template<Color Us>
Score evaluate(const Position& pos, Pawns::Entry* e) {
/// Constructor
const Color Them = (Us == WHITE ? BLACK : WHITE);
const Square Up = (Us == WHITE ? DELTA_N : DELTA_S);
const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW);
const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE);
PawnInfoTable::PawnInfoTable(unsigned numOfEntries) {
Bitboard b, p, doubled;
Square s;
File f;
bool passed, isolated, opposed, connected, backward, candidate, unsupported;
Score value = SCORE_ZERO;
const Square* pl = pos.list<PAWN>(Us);
size = numOfEntries;
entries = new PawnInfo[size];
if (!entries)
{
std::cerr << "Failed to allocate " << (numOfEntries * sizeof(PawnInfo))
<< " bytes for pawn hash table." << std::endl;
Application::exit_with_failure();
Bitboard ourPawns = pos.pieces(Us, PAWN);
Bitboard theirPawns = pos.pieces(Them, PAWN);
e->passedPawns[Us] = e->candidatePawns[Us] = 0;
e->kingSquares[Us] = SQ_NONE;
e->semiopenFiles[Us] = 0xFF;
e->pawnAttacks[Us] = shift_bb<Right>(ourPawns) | shift_bb<Left>(ourPawns);
e->pawnsOnSquares[Us][BLACK] = popcount<Max15>(ourPawns & DarkSquares);
e->pawnsOnSquares[Us][WHITE] = pos.count<PAWN>(Us) - e->pawnsOnSquares[Us][BLACK];
// Loop through all pawns of the current color and score each pawn
while ((s = *pl++) != SQ_NONE)
{
assert(pos.piece_on(s) == make_piece(Us, PAWN));
f = file_of(s);
// This file cannot be semi-open
e->semiopenFiles[Us] &= ~(1 << f);
// Previous rank
p = rank_bb(s - pawn_push(Us));
// Our rank plus previous one
b = rank_bb(s) | p;
// Flag the pawn as passed, isolated, doubled,
// unsupported or connected (but not the backward one).
connected = ourPawns & adjacent_files_bb(f) & b;
unsupported = !(ourPawns & adjacent_files_bb(f) & p);
isolated = !(ourPawns & adjacent_files_bb(f));
doubled = ourPawns & forward_bb(Us, s);
opposed = theirPawns & forward_bb(Us, s);
passed = !(theirPawns & passed_pawn_mask(Us, s));
// Test for backward pawn.
// If the pawn is passed, isolated, or connected it cannot be
// backward. If there are friendly pawns behind on adjacent files
// or if it can capture an enemy pawn it cannot be backward either.
if ( (passed | isolated | connected)
|| (ourPawns & pawn_attack_span(Them, s))
|| (pos.attacks_from<PAWN>(s, Us) & theirPawns))
backward = false;
else
{
// We now know that there are no friendly pawns beside or behind this
// pawn on adjacent files. We now check whether the pawn is
// backward by looking in the forward direction on the adjacent
// files, and picking the closest pawn there.
b = pawn_attack_span(Us, s) & (ourPawns | theirPawns);
b = pawn_attack_span(Us, s) & rank_bb(backmost_sq(Us, b));
// If we have an enemy pawn in the same or next rank, the pawn is
// backward because it cannot advance without being captured.
backward = (b | shift_bb<Up>(b)) & theirPawns;
}
assert(opposed | passed | (pawn_attack_span(Us, s) & theirPawns));
// A not-passed pawn is a candidate to become passed, if it is free to
// advance and if the number of friendly pawns beside or behind this
// pawn on adjacent files is higher than or equal to the number of
// enemy pawns in the forward direction on the adjacent files.
candidate = !(opposed | passed | backward | isolated)
&& (b = pawn_attack_span(Them, s + pawn_push(Us)) & ourPawns) != 0
&& popcount<Max15>(b) >= popcount<Max15>(pawn_attack_span(Us, s) & theirPawns);
// Passed pawns will be properly scored in evaluation because we need
// full attack info to evaluate passed pawns. Only the frontmost passed
// pawn on each file is considered a true passed pawn.
if (passed && !doubled)
e->passedPawns[Us] |= s;
// Score this pawn
if (isolated)
value -= Isolated[opposed][f];
if (unsupported && !isolated)
value -= UnsupportedPawnPenalty;
if (doubled)
value -= Doubled[f] / rank_distance(s, lsb(doubled));
if (backward)
value -= Backward[opposed][f];
if (connected)
value += Connected[f][relative_rank(Us, s)];
if (candidate)
{
value += CandidatePassed[relative_rank(Us, s)];
if (!doubled)
e->candidatePawns[Us] |= s;
}
}
// In endgame it's better to have pawns on both wings. So give a bonus according
// to file distance between left and right outermost pawns.
if (pos.count<PAWN>(Us) > 1)
{
b = e->semiopenFiles[Us] ^ 0xFF;
value += PawnsFileSpan * int(msb(b) - lsb(b));
}
return value;
}
} // namespace
namespace Pawns {
/// init() initializes some tables by formula instead of hard-coding their values
void init() {
const int bonusesByFile[8] = { 1, 3, 3, 4, 4, 3, 3, 1 };
int bonus;
for (Rank r = RANK_1; r < RANK_8; ++r)
for (File f = FILE_A; f <= FILE_H; ++f)
{
bonus = r * (r-1) * (r-2) + bonusesByFile[f] * (r/2 + 1);
Connected[f][r] = make_score(bonus, bonus);
}
}
/// Destructor
/// probe() takes a position object as input, computes a Entry object, and returns
/// a pointer to it. The result is also stored in a hash table, so we don't have
/// to recompute everything when the same pawn structure occurs again.
PawnInfoTable::~PawnInfoTable() {
delete [] entries;
Entry* probe(const Position& pos, Table& entries) {
Key key = pos.pawn_key();
Entry* e = entries[key];
if (e->key == key)
return e;
e->key = key;
e->value = evaluate<WHITE>(pos, e) - evaluate<BLACK>(pos, e);
return e;
}
/// PawnInfo::clear() resets to zero the PawnInfo entry. Note that
/// kingSquares[] is initialized to SQ_NONE instead.
void PawnInfo::clear() {
memset(this, 0, sizeof(PawnInfo));
kingSquares[WHITE] = kingSquares[BLACK] = SQ_NONE;
}
/// PawnInfoTable::get_pawn_info() takes a position object as input, computes
/// a PawnInfo object, and returns a pointer to it. The result is also
/// stored in a hash table, so we don't have to recompute everything when
/// the same pawn structure occurs again.
PawnInfo* PawnInfoTable::get_pawn_info(const Position& pos) {
assert(pos.is_ok());
Key key = pos.get_pawn_key();
int index = int(key & (size - 1));
PawnInfo* pi = entries + index;
// If pi->key matches the position's pawn hash key, it means that we
// have analysed this pawn structure before, and we can simply return
// the information we found the last time instead of recomputing it.
if (pi->key == key)
return pi;
// Clear the PawnInfo object, and set the key
pi->clear();
pi->key = key;
// Calculate pawn attacks
Bitboard whitePawns = pos.pieces(PAWN, WHITE);
Bitboard blackPawns = pos.pieces(PAWN, BLACK);
pi->pawnAttacks[WHITE] = ((whitePawns << 9) & ~FileABB) | ((whitePawns << 7) & ~FileHBB);
pi->pawnAttacks[BLACK] = ((blackPawns >> 7) & ~FileABB) | ((blackPawns >> 9) & ~FileHBB);
// Evaluate pawns for both colors
pi->value = evaluate_pawns<WHITE>(pos, whitePawns, blackPawns, pi)
- evaluate_pawns<BLACK>(pos, blackPawns, whitePawns, pi);
return pi;
}
/// PawnInfoTable::evaluate_pawns() evaluates each pawn of the given color
/// Entry::shelter_storm() calculates shelter and storm penalties for the file
/// the king is on, as well as the two adjacent files.
template<Color Us>
Score PawnInfoTable::evaluate_pawns(const Position& pos, Bitboard ourPawns,
Bitboard theirPawns, PawnInfo* pi) {
Square s;
File f;
Rank r;
bool passed, isolated, doubled, chain, backward, candidate;
int bonus;
Score value = make_score(0, 0);
const Square* ptr = pos.piece_list_begin(Us, PAWN);
Value Entry::shelter_storm(const Position& pos, Square ksq) {
// Initialize pawn storm scores by giving bonuses for open files
for (f = FILE_A; f <= FILE_H; f++)
if (!(ourPawns & file_bb(f)))
{
pi->ksStormValue[Us] += KStormOpenFileBonus[f];
pi->qsStormValue[Us] += QStormOpenFileBonus[f];
pi->halfOpenFiles[Us] |= (1 << f);
}
const Color Them = (Us == WHITE ? BLACK : WHITE);
static const Bitboard MiddleEdges = (FileABB | FileHBB) & (Rank2BB | Rank3BB);
// Loop through all pawns of the current color and score each pawn
while ((s = *ptr++) != SQ_NONE)
Value safety = MaxSafetyBonus;
Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq));
Bitboard ourPawns = b & pos.pieces(Us);
Bitboard theirPawns = b & pos.pieces(Them);
Rank rkUs, rkThem;
File kf = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));
for (File f = kf - File(1); f <= kf + File(1); ++f)
{
f = square_file(s);
r = square_rank(s);
b = ourPawns & file_bb(f);
rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
assert(pos.piece_on(s) == piece_of_color_and_type(Us, PAWN));
b = theirPawns & file_bb(f);
rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
// Passed, isolated or doubled pawn?
passed = Position::pawn_is_passed(theirPawns, Us, s);
isolated = Position::pawn_is_isolated(ourPawns, s);
doubled = Position::pawn_is_doubled(ourPawns, Us, s);
// We calculate kingside and queenside pawn storm
// scores for both colors. These are used when evaluating
// middle game positions with opposite side castling.
//
// Each pawn is given a base score given by a piece square table
// (KStormTable[] or QStormTable[]). Pawns which seem to have good
// chances of creating an open file by exchanging itself against an
// enemy pawn on an adjacent file gets an additional bonus.
// Kingside pawn storms
bonus = KStormTable[relative_square(Us, s)];
if (f >= FILE_F)
{
Bitboard b = outpost_mask(Us, s) & theirPawns & (FileFBB | FileGBB | FileHBB);
while (b)
{
Square s2 = pop_1st_bit(&b);
if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
{
// The enemy pawn has no pawn beside itself, which makes it
// particularly vulnerable. Big bonus, especially against a
// weakness on the rook file.
if (square_file(s2) == FILE_H)
bonus += 4*StormLeverBonus[f] - 8*square_distance(s, s2);
else
bonus += 2*StormLeverBonus[f] - 4*square_distance(s, s2);
} else
// There is at least one enemy pawn beside the enemy pawn we look
// at, which means that the pawn has somewhat better chances of
// defending itself by advancing. Smaller bonus.
bonus += StormLeverBonus[f] - 2*square_distance(s, s2);
}
}
pi->ksStormValue[Us] += bonus;
// Queenside pawn storms
bonus = QStormTable[relative_square(Us, s)];
if (f <= FILE_C)
{
Bitboard b = outpost_mask(Us, s) & theirPawns & (FileABB | FileBBB | FileCBB);
while (b)
{
Square s2 = pop_1st_bit(&b);
if (!(theirPawns & neighboring_files_bb(s2) & rank_bb(s2)))
{
// The enemy pawn has no pawn beside itself, which makes it
// particularly vulnerable. Big bonus, especially against a
// weakness on the rook file.
if (square_file(s2) == FILE_A)
bonus += 4*StormLeverBonus[f] - 16*square_distance(s, s2);
else
bonus += 2*StormLeverBonus[f] - 8*square_distance(s, s2);
} else
// There is at least one enemy pawn beside the enemy pawn we look
// at, which means that the pawn has somewhat better chances of
// defending itself by advancing. Smaller bonus.
bonus += StormLeverBonus[f] - 4*square_distance(s, s2);
}
}
pi->qsStormValue[Us] += bonus;
// Member of a pawn chain (but not the backward one)? We could speed up
// the test a little by introducing an array of masks indexed by color
// and square for doing the test, but because everything is hashed,
// it probably won't make any noticable difference.
chain = ourPawns
& neighboring_files_bb(f)
& (rank_bb(r) | rank_bb(r - (Us == WHITE ? 1 : -1)));
// Test for backward pawn
//
// If the pawn is passed, isolated, or member of a pawn chain
// it cannot be backward. If can capture an enemy pawn or if
// there are friendly pawns behind on neighboring files it cannot
// be backward either.
if ( (passed | isolated | chain)
|| (ourPawns & behind_bb(Us, r) & neighboring_files_bb(f))
|| (pos.attacks_from<PAWN>(s, Us) & theirPawns))
backward = false;
if ( (MiddleEdges & make_square(f, rkThem))
&& file_of(ksq) == f
&& relative_rank(Us, ksq) == rkThem - 1)
safety += 200;
else
{
// We now know that there are no friendly pawns beside or behind this
// pawn on neighboring files. We now check whether the pawn is
// backward by looking in the forward direction on the neighboring
// files, and seeing whether we meet a friendly or an enemy pawn first.
Bitboard b = pos.attacks_from<PAWN>(s, Us);
// Note that we are sure to find something because pawn is not passed
// nor isolated, so loop is potentially infinite, but it isn't.
while (!(b & (ourPawns | theirPawns)))
Us == WHITE ? b <<= 8 : b >>= 8;
// The friendly pawn needs to be at least two ranks closer than the enemy
// pawn in order to help the potentially backward pawn advance.
backward = (b | (Us == WHITE ? b << 8 : b >> 8)) & theirPawns;
}
// Test for candidate passed pawn
candidate = !passed
&& !(theirPawns & file_bb(f))
&& ( count_1s_max_15(neighboring_files_bb(f) & (behind_bb(Us, r) | rank_bb(r)) & ourPawns)
- count_1s_max_15(neighboring_files_bb(f) & in_front_bb(Us, r) & theirPawns)
>= 0);
// In order to prevent doubled passed pawns from receiving a too big
// bonus, only the frontmost passed pawn on each file is considered as
// a true passed pawn.
if (passed && (ourPawns & squares_in_front_of(Us, s)))
passed = false;
// Score this pawn
if (passed)
set_bit(&(pi->passedPawns), s);
if (isolated)
{
value -= IsolatedPawnPenalty[f];
if (!(theirPawns & file_bb(f)))
value -= IsolatedPawnPenalty[f] / 2;
}
if (doubled)
value -= DoubledPawnPenalty[f];
if (backward)
{
value -= BackwardPawnPenalty[f];
if (!(theirPawns & file_bb(f)))
value -= BackwardPawnPenalty[f] / 2;
}
if (chain)
value += ChainBonus[f];
if (candidate)
value += CandidateBonus[relative_rank(Us, s)];
safety -= ShelterWeakness[rkUs]
+ StormDanger[rkUs == RANK_1 ? 0 : rkThem == rkUs + 1 ? 2 : 1][rkThem];
}
return value;
return safety;
}
/// PawnInfo::updateShelter calculates and caches king shelter. It is called
/// only when king square changes, about 20% of total get_king_shelter() calls.
int PawnInfo::updateShelter(const Position& pos, Color c, Square ksq) {
/// Entry::do_king_safety() calculates a bonus for king safety. It is called only
/// when king square changes, which is about 20% of total king_safety() calls.
unsigned shelter = 0;
Bitboard pawns = pos.pieces(PAWN, c) & this_and_neighboring_files_bb(ksq);
unsigned r = ksq & (7 << 3);
for (int i = 1, k = (c ? -8 : 8); i < 4; i++)
{
r += k;
shelter += BitCount8Bit[(pawns >> r) & 0xFF] * (128 >> i);
}
kingSquares[c] = ksq;
kingShelters[c] = shelter;
return shelter;
template<Color Us>
Score Entry::do_king_safety(const Position& pos, Square ksq) {
kingSquares[Us] = ksq;
castlingRights[Us] = pos.can_castle(Us);
minKPdistance[Us] = 0;
Bitboard pawns = pos.pieces(Us, PAWN);
if (pawns)
while (!(DistanceRingsBB[ksq][minKPdistance[Us]++] & pawns)) {}
if (relative_rank(Us, ksq) > RANK_4)
return make_score(0, -16 * minKPdistance[Us]);
Value bonus = shelter_storm<Us>(pos, ksq);
// If we can castle use the bonus after the castling if it is bigger
if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right))
bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_G1)));
if (pos.can_castle(MakeCastling<Us, QUEEN_SIDE>::right))
bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1)));
return make_score(bonus, -16 * minKPdistance[Us]);
}
// Explicit template instantiation
template Score Entry::do_king_safety<WHITE>(const Position& pos, Square ksq);
template Score Entry::do_king_safety<BLACK>(const Position& pos, Square ksq);
} // namespace Pawns
+48 -99
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,119 +17,68 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(PAWNS_H_INCLUDED)
#ifndef PAWNS_H_INCLUDED
#define PAWNS_H_INCLUDED
////
//// Includes
////
#include "misc.h"
#include "position.h"
#include "types.h"
#include "bitboard.h"
#include "value.h"
namespace Pawns {
////
//// Types
////
/// Pawns::Entry contains various information about a pawn structure. A lookup
/// to the pawn hash table (performed by calling the probe function) returns a
/// pointer to an Entry object.
/// PawnInfo is a class which contains various information about a pawn
/// structure. Currently, it only includes a middle game and an end game
/// pawn structure evaluation, and a bitboard of passed pawns. We may want
/// to add further information in the future. A lookup to the pawn hash table
/// (performed by calling the get_pawn_info method in a PawnInfoTable object)
/// returns a pointer to a PawnInfo object.
class Position;
struct Entry {
class PawnInfo {
Score pawns_value() const { return value; }
Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
Bitboard candidate_pawns(Color c) const { return candidatePawns[c]; }
friend class PawnInfoTable;
int semiopen_file(Color c, File f) const {
return semiopenFiles[c] & (1 << f);
}
public:
PawnInfo() { clear(); }
int semiopen_side(Color c, File f, bool leftSide) const {
return semiopenFiles[c] & (leftSide ? (1 << f) - 1 : ~((1 << (f + 1)) - 1));
}
Score pawns_value() const;
Value kingside_storm_value(Color c) const;
Value queenside_storm_value(Color c) const;
Bitboard pawn_attacks(Color c) const;
Bitboard passed_pawns() const;
int file_is_half_open(Color c, File f) const;
int has_open_file_to_left(Color c, File f) const;
int has_open_file_to_right(Color c, File f) const;
int get_king_shelter(const Position& pos, Color c, Square ksq);
int pawns_on_same_color_squares(Color c, Square s) const {
return pawnsOnSquares[c][!!(DarkSquares & s)];
}
private:
void clear();
int updateShelter(const Position& pos, Color c, Square ksq);
template<Color Us>
Score king_safety(const Position& pos, Square ksq) {
return kingSquares[Us] == ksq && castlingRights[Us] == pos.can_castle(Us)
? kingSafety[Us] : (kingSafety[Us] = do_king_safety<Us>(pos, ksq));
}
template<Color Us>
Score do_king_safety(const Position& pos, Square ksq);
template<Color Us>
Value shelter_storm(const Position& pos, Square ksq);
Key key;
Bitboard passedPawns;
Bitboard pawnAttacks[2];
Score value;
int16_t ksStormValue[2], qsStormValue[2];
uint8_t halfOpenFiles[2];
Square kingSquares[2];
uint8_t kingShelters[2];
Bitboard passedPawns[COLOR_NB];
Bitboard candidatePawns[COLOR_NB];
Bitboard pawnAttacks[COLOR_NB];
Square kingSquares[COLOR_NB];
Score kingSafety[COLOR_NB];
int minKPdistance[COLOR_NB];
int castlingRights[COLOR_NB];
int semiopenFiles[COLOR_NB];
int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
};
/// The PawnInfoTable class represents a pawn hash table. It is basically
/// just an array of PawnInfo objects and a few methods for accessing these
/// objects. The most important method is get_pawn_info, which looks up a
/// position in the table and returns a pointer to a PawnInfo object.
typedef HashTable<Entry, 16384> Table;
class PawnInfoTable {
void init();
Entry* probe(const Position& pos, Table& entries);
public:
PawnInfoTable(unsigned numOfEntries);
~PawnInfoTable();
PawnInfo* get_pawn_info(const Position& pos);
} // namespace Pawns
private:
template<Color Us>
Score evaluate_pawns(const Position& pos, Bitboard ourPawns, Bitboard theirPawns, PawnInfo* pi);
unsigned size;
PawnInfo* entries;
};
////
//// Inline functions
////
inline Score PawnInfo::pawns_value() const {
return value;
}
inline Bitboard PawnInfo::passed_pawns() const {
return passedPawns;
}
inline Bitboard PawnInfo::pawn_attacks(Color c) const {
return pawnAttacks[c];
}
inline Value PawnInfo::kingside_storm_value(Color c) const {
return Value(ksStormValue[c]);
}
inline Value PawnInfo::queenside_storm_value(Color c) const {
return Value(qsStormValue[c]);
}
inline int PawnInfo::file_is_half_open(Color c, File f) const {
return (halfOpenFiles[c] & (1 << int(f)));
}
inline int PawnInfo::has_open_file_to_left(Color c, File f) const {
return halfOpenFiles[c] & ((1 << int(f)) - 1);
}
inline int PawnInfo::has_open_file_to_right(Color c, File f) const {
return halfOpenFiles[c] & ~((1 << int(f+1)) - 1);
}
inline int PawnInfo::get_king_shelter(const Position& pos, Color c, Square ksq) {
return (kingSquares[c] == ksq ? kingShelters[c] : updateShelter(pos, c, ksq));
}
#endif // !defined(PAWNS_H_INCLUDED)
#endif // #ifndef PAWNS_H_INCLUDED
-49
View File
@@ -1,49 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <string>
#include "piece.h"
using namespace std;
////
//// Functions
////
/// Translating piece types to/from English piece letters
static const string PieceChars(" pnbrqk PNBRQK");
char piece_type_to_char(PieceType pt, bool upcase) {
return PieceChars[pt + upcase * 7];
}
PieceType piece_type_from_char(char c) {
size_t idx = PieceChars.find(c);
return idx != string::npos ? PieceType(idx % 7) : NO_PIECE_TYPE;
}
-107
View File
@@ -1,107 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(PIECE_H_INCLUDED)
#define PIECE_H_INCLUDED
////
//// Includes
////
#include "color.h"
#include "square.h"
////
//// Types
////
enum PieceType {
NO_PIECE_TYPE = 0,
PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5, KING = 6
};
enum Piece {
NO_PIECE = 0, WP = 1, WN = 2, WB = 3, WR = 4, WQ = 5, WK = 6,
BP = 9, BN = 10, BB = 11, BR = 12, BQ = 13, BK = 14,
EMPTY = 16, OUTSIDE = 17
};
////
//// Constants
////
const int SlidingArray[18] = {
0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0
};
////
//// Inline functions
////
inline Piece operator+ (Piece p, int i) { return Piece(int(p) + i); }
inline void operator++ (Piece &p, int) { p = Piece(int(p) + 1); }
inline Piece operator- (Piece p, int i) { return Piece(int(p) - i); }
inline void operator-- (Piece &p, int) { p = Piece(int(p) - 1); }
inline PieceType operator+ (PieceType p, int i) {return PieceType(int(p) + i);}
inline void operator++ (PieceType &p, int) { p = PieceType(int(p) + 1); }
inline PieceType operator- (PieceType p, int i) {return PieceType(int(p) - i);}
inline void operator-- (PieceType &p, int) { p = PieceType(int(p) - 1); }
inline PieceType type_of_piece(Piece p) {
return PieceType(int(p) & 7);
}
inline Color color_of_piece(Piece p) {
return Color(int(p) >> 3);
}
inline Piece piece_of_color_and_type(Color c, PieceType pt) {
return Piece((int(c) << 3) | int(pt));
}
inline int piece_is_slider(Piece p) {
return SlidingArray[int(p)];
}
inline SquareDelta pawn_push(Color c) {
return (c == WHITE ? DELTA_N : DELTA_S);
}
inline bool piece_type_is_ok(PieceType pc) {
return pc >= PAWN && pc <= KING;
}
inline bool piece_is_ok(Piece pc) {
return piece_type_is_ok(type_of_piece(pc)) && color_is_ok(color_of_piece(pc));
}
////
//// Prototypes
////
extern char piece_type_to_char(PieceType pt, bool upcase = false);
extern PieceType piece_type_from_char(char c);
#endif // !defined(PIECE_H_INCLUDED)
+116
View File
@@ -0,0 +1,116 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PLATFORM_H_INCLUDED
#define PLATFORM_H_INCLUDED
#ifdef _MSC_VER
// Disable some silly and noisy warnings from MSVC compiler
#pragma warning(disable: 4127) // Conditional expression is constant
#pragma warning(disable: 4146) // Unary minus operator applied to unsigned type
#pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false'
#pragma warning(disable: 4996) // Function _ftime() may be unsafe
// MSVC does not support <inttypes.h>
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
# include <inttypes.h>
#endif
#ifndef _WIN32 // Linux - Unix
# include <sys/time.h>
inline int64_t system_time_to_msec() {
timeval t;
gettimeofday(&t, NULL);
return t.tv_sec * 1000LL + t.tv_usec / 1000;
}
# include <pthread.h>
typedef pthread_mutex_t Lock;
typedef pthread_cond_t WaitCondition;
typedef pthread_t NativeHandle;
typedef void*(*pt_start_fn)(void*);
# define lock_init(x) pthread_mutex_init(&(x), NULL)
# define lock_grab(x) pthread_mutex_lock(&(x))
# define lock_release(x) pthread_mutex_unlock(&(x))
# define lock_destroy(x) pthread_mutex_destroy(&(x))
# define cond_destroy(x) pthread_cond_destroy(&(x))
# define cond_init(x) pthread_cond_init(&(x), NULL)
# define cond_signal(x) pthread_cond_signal(&(x))
# define cond_wait(x,y) pthread_cond_wait(&(x),&(y))
# define cond_timedwait(x,y,z) pthread_cond_timedwait(&(x),&(y),z)
# define thread_create(x,f,t) pthread_create(&(x),NULL,(pt_start_fn)f,t)
# define thread_join(x) pthread_join(x, NULL)
#else // Windows and MinGW
# include <sys/timeb.h>
inline int64_t system_time_to_msec() {
_timeb t;
_ftime(&t);
return t.time * 1000LL + t.millitm;
}
#ifndef NOMINMAX
# define NOMINMAX // disable macros min() and max()
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#undef NOMINMAX
// We use critical sections on Windows to support Windows XP and older versions.
// Unfortunately, cond_wait() is racy between lock_release() and WaitForSingleObject()
// but apart from this they have the same speed performance of SRW locks.
typedef CRITICAL_SECTION Lock;
typedef HANDLE WaitCondition;
typedef HANDLE NativeHandle;
// On Windows 95 and 98 parameter lpThreadId may not be null
inline DWORD* dwWin9xKludge() { static DWORD dw; return &dw; }
# define lock_init(x) InitializeCriticalSection(&(x))
# define lock_grab(x) EnterCriticalSection(&(x))
# define lock_release(x) LeaveCriticalSection(&(x))
# define lock_destroy(x) DeleteCriticalSection(&(x))
# define cond_init(x) { x = CreateEvent(0, FALSE, FALSE, 0); }
# define cond_destroy(x) CloseHandle(x)
# define cond_signal(x) SetEvent(x)
# define cond_wait(x,y) { lock_release(y); WaitForSingleObject(x, INFINITE); lock_grab(y); }
# define cond_timedwait(x,y,z) { lock_release(y); WaitForSingleObject(x,z); lock_grab(y); }
# define thread_create(x,f,t) (x = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)f,t,0,dwWin9xKludge()))
# define thread_join(x) { WaitForSingleObject(x, INFINITE); CloseHandle(x); }
#endif
#endif // #ifndef PLATFORM_H_INCLUDED
+1074 -1789
View File
File diff suppressed because it is too large Load Diff
+242 -379
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,224 +17,123 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(POSITION_H_INCLUDED)
#ifndef POSITION_H_INCLUDED
#define POSITION_H_INCLUDED
// Disable some silly and noisy warning from MSVC compiler
#if defined(_MSC_VER)
// Forcing value to bool 'true' or 'false' (performance warning)
#pragma warning(disable: 4800)
// Conditional expression is constant
#pragma warning(disable: 4127)
#endif
////
//// Includes
////
#include <cassert>
#include <cstddef>
#include "bitboard.h"
#include "color.h"
#include "direction.h"
#include "move.h"
#include "piece.h"
#include "square.h"
#include "value.h"
#include "types.h"
////
//// Constants
////
/// FEN string for the initial position
const std::string StartPosition = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
/// Maximum number of plies per game (220 should be enough, because the
/// maximum search depth is 100, and during position setup we reset the
/// move counter for every non-reversible move).
const int MaxGameLength = 220;
////
//// Types
////
/// struct checkInfo is initialized at c'tor time and keeps
/// info used to detect if a move gives check.
/// The checkInfo struct is initialized at c'tor time and keeps info used
/// to detect if a move gives check.
class Position;
struct Thread;
struct CheckInfo {
CheckInfo(const Position&);
explicit CheckInfo(const Position&);
Square ksq;
Bitboard dcCandidates;
Bitboard checkSq[8];
};
/// Castle rights, encoded as bit fields
enum CastleRights {
NO_CASTLES = 0,
WHITE_OO = 1,
BLACK_OO = 2,
WHITE_OOO = 4,
BLACK_OOO = 8,
ALL_CASTLES = 15
};
/// Game phase
enum Phase {
PHASE_ENDGAME = 0,
PHASE_MIDGAME = 128
Bitboard dcCandidates;
Bitboard pinned;
Bitboard checkSq[PIECE_TYPE_NB];
Square ksq;
};
/// The StateInfo struct stores information we need to restore a Position
/// The StateInfo struct stores information needed to restore a Position
/// object to its previous state when we retract a move. Whenever a move
/// is made on the board (by calling Position::do_move), an StateInfo object
/// must be passed as a parameter.
/// is made on the board (by calling Position::do_move), a StateInfo
/// object must be passed as a parameter.
struct StateInfo {
Key pawnKey, materialKey;
int castleRights, rule50, pliesFromNull;
Value npMaterial[COLOR_NB];
int castlingRights, rule50, pliesFromNull;
Score psq;
Square epSquare;
Score value;
Value npMaterial[2];
Key key;
PieceType capture;
Bitboard checkersBB;
PieceType capturedType;
StateInfo* previous;
};
/// The position data structure. A position consists of the following data:
///
/// * For each piece type, a bitboard representing the squares occupied
/// by pieces of that type.
/// * For each color, a bitboard representing the squares occupied by
/// pieces of that color.
/// * A bitboard of all occupied squares.
/// * A bitboard of all checking pieces.
/// * A 64-entry array of pieces, indexed by the squares of the board.
/// * The current side to move.
/// * Information about the castling rights for both sides.
/// * The initial files of the kings and both pairs of rooks. This is
/// used to implement the Chess960 castling rules.
/// * The en passant square (which is SQ_NONE if no en passant capture is
/// possible).
/// * The squares of the kings for both sides.
/// * Hash keys for the position itself, the current pawn structure, and
/// the current material situation.
/// * Hash keys for all previous positions in the game for detecting
/// repetition draws.
/// * A counter for detecting 50 move rule draws.
/// When making a move the current StateInfo up to 'key' excluded is copied to
/// the new one. Here we calculate the quad words (64bits) needed to be copied.
const size_t StateCopySize64 = offsetof(StateInfo, key) / sizeof(uint64_t) + 1;
/// The Position class stores the information regarding the board representation
/// like pieces, side to move, hash keys, castling info, etc. The most important
/// methods are do_move() and undo_move(), used by the search to update node info
/// when traversing the search tree.
class Position {
friend class MaterialInfo;
friend class EndgameFunctions;
public:
enum GamePhase {
MidGame,
EndGame
};
// Constructors
Position() {}
Position(const Position& pos);
Position(const std::string& fen);
Position(const Position& pos, Thread* t) { *this = pos; thisThread = t; }
Position(const std::string& f, bool c960, Thread* t) { set(f, c960, t); }
Position& operator=(const Position&);
static void init();
// Text input/output
void from_fen(const std::string& fen);
const std::string to_fen() const;
void print(Move m = MOVE_NONE) const;
void set(const std::string& fenStr, bool isChess960, Thread* th);
const std::string fen() const;
const std::string pretty(Move m = MOVE_NONE) const;
// Copying
void copy(const Position& pos);
void flipped_copy(const Position& pos);
// The piece on a given square
Piece piece_on(Square s) const;
PieceType type_of_piece_on(Square s) const;
Color color_of_piece_on(Square s) const;
bool square_is_empty(Square s) const;
bool square_is_occupied(Square s) const;
Value midgame_value_of_piece_on(Square s) const;
Value endgame_value_of_piece_on(Square s) const;
// Side to move
Color side_to_move() const;
// Bitboard representation of the position
Bitboard empty_squares() const;
Bitboard occupied_squares() const;
Bitboard pieces_of_color(Color c) const;
// Position representation
Bitboard pieces() const;
Bitboard pieces(PieceType pt) const;
Bitboard pieces(PieceType pt, Color c) const;
Bitboard pieces(PieceType pt1, PieceType pt2) const;
Bitboard pieces(PieceType pt1, PieceType pt2, Color c) const;
// Number of pieces of each color and type
int piece_count(Color c, PieceType pt) const;
// The en passant square
Square ep_square() const;
// Current king position for each color
Bitboard pieces(Color c) const;
Bitboard pieces(Color c, PieceType pt) const;
Bitboard pieces(Color c, PieceType pt1, PieceType pt2) const;
Piece piece_on(Square s) const;
Square king_square(Color c) const;
Square ep_square() const;
bool empty(Square s) const;
template<PieceType Pt> int count(Color c) const;
template<PieceType Pt> const Square* list(Color c) const;
// Castling rights
bool can_castle_kingside(Color c) const;
bool can_castle_queenside(Color c) const;
bool can_castle(Color c) const;
Square initial_kr_square(Color c) const;
Square initial_qr_square(Color c) const;
// Castling
int can_castle(Color c) const;
int can_castle(CastlingRight cr) const;
bool castling_impeded(CastlingRight cr) const;
Square castling_rook_square(CastlingRight cr) const;
// Bitboards for pinned pieces and discovered check candidates
Bitboard discovered_check_candidates(Color c) const;
// Checking
Bitboard checkers() const;
Bitboard discovered_check_candidates() const;
Bitboard pinned_pieces(Color c) const;
// Checking pieces and under check information
Bitboard checkers() const;
bool is_check() const;
// Piece lists
Square piece_list(Color c, PieceType pt, int index) const;
const Square* piece_list_begin(Color c, PieceType pt) const;
// Information about attacks to or from a given square
// Attacks to/from a given square
Bitboard attackers_to(Square s) const;
Bitboard attacks_from(Piece p, Square s) const;
Bitboard attackers_to(Square s, Bitboard occ) const;
Bitboard attacks_from(Piece pc, Square s) const;
template<PieceType> Bitboard attacks_from(Square s) const;
template<PieceType> Bitboard attacks_from(Square s, Color c) const;
// Properties of moves
bool pl_move_is_legal(Move m, Bitboard pinned) const;
bool pl_move_is_evasion(Move m, Bitboard pinned) const;
bool move_is_check(Move m) const;
bool move_is_check(Move m, const CheckInfo& ci) const;
bool move_is_capture(Move m) const;
bool move_is_capture_or_promotion(Move m) const;
bool move_is_passed_pawn_push(Move m) const;
bool move_attacks_square(Move m, Square s) const;
bool legal(Move m, Bitboard pinned) const;
bool pseudo_legal(const Move m) const;
bool capture(Move m) const;
bool capture_or_promotion(Move m) const;
bool gives_check(Move m, const CheckInfo& ci) const;
bool advanced_pawn_push(Move m) const;
Piece moved_piece(Move m) const;
PieceType captured_piece_type() const;
// Information about pawns
bool pawn_is_passed(Color c, Square s) const;
static bool pawn_is_passed(Bitboard theirPawns, Color c, Square s);
static bool pawn_is_isolated(Bitboard ourPawns, Square s);
static bool pawn_is_doubled(Bitboard ourPawns, Color c, Square s);
// Weak squares
bool square_is_weak(Square s, Color c) const;
// Piece specific
bool pawn_passed(Color c, Square s) const;
bool pawn_on_7th(Color c) const;
bool bishop_pair(Color c) const;
bool opposite_bishops() const;
// Doing and undoing moves
void saveState();
void do_move(Move m, StateInfo& st);
void do_move(Move m, StateInfo& st, const CheckInfo& ci, bool moveIsCheck);
void undo_move(Move m);
@@ -242,180 +141,121 @@ public:
void undo_null_move();
// Static exchange evaluation
int see(Square from, Square to) const;
int see(Move m) const;
int see(Square to) const;
int see_sign(Move m) const;
Value see(Move m) const;
Value see_sign(Move m) const;
// Accessing hash keys
Key get_key() const;
Key get_exclusion_key() const;
Key get_pawn_key() const;
Key get_material_key() const;
Key key() const;
Key exclusion_key() const;
Key pawn_key() const;
Key material_key() const;
// Incremental evaluation
Score value() const;
// Incremental piece-square evaluation
Score psq_score() const;
Value non_pawn_material(Color c) const;
Score pst_delta(Piece piece, Square from, Square to) const;
// Game termination checks
bool is_mate() const;
bool is_draw() const;
// Check if one side threatens a mate in one
bool has_mate_threat(Color c);
// Number of plies since the last non-reversible move
int rule_50_counter() const;
// Other properties of the position
bool opposite_colored_bishops() const;
bool has_pawn_on_7th(Color c) const;
// Reset the gamePly variable to 0
void reset_game_ply();
Color side_to_move() const;
int game_ply() const;
bool is_chess960() const;
Thread* this_thread() const;
uint64_t nodes_searched() const;
void set_nodes_searched(uint64_t n);
bool is_draw() const;
// Position consistency check, for debugging
bool is_ok(int* failedStep = NULL) const;
// Static member functions
static void init_zobrist();
static void init_piece_square_tables();
bool pos_is_ok(int* step = NULL) const;
void flip();
private:
// Initialization helper functions (used while setting up a position)
// Initialization helpers (used while setting up a position)
void clear();
void put_piece(Piece p, Square s);
void allow_oo(Color c);
void allow_ooo(Color c);
void set_castling_right(Color c, Square rfrom);
void set_state(StateInfo* si) const;
// Helper functions for doing and undoing moves
void do_capture_move(Bitboard& key, PieceType capture, Color them, Square to, bool ep);
void do_castle_move(Move m);
void undo_castle_move(Move m);
void find_checkers();
// Helper functions
Bitboard check_blockers(Color c, Color kingColor) const;
void put_piece(Square s, Color c, PieceType pt);
void remove_piece(Square s, Color c, PieceType pt);
void move_piece(Square from, Square to, Color c, PieceType pt);
template<bool Do>
void do_castling(Square from, Square& to, Square& rfrom, Square& rto);
template<bool FindPinned>
Bitboard hidden_checkers(Color c) const;
// Computing hash keys from scratch (for initialization and debugging)
Key compute_key() const;
Key compute_pawn_key() const;
Key compute_material_key() const;
// Computing incremental evaluation scores and material counts
Score pst(Color c, PieceType pt, Square s) const;
Score compute_value() const;
Value compute_non_pawn_material(Color c) const;
// Board
Piece board[64];
// Bitboards
Bitboard byTypeBB[8], byColorBB[2];
// Piece counts
int pieceCount[2][8]; // [color][pieceType]
// Piece lists
Square pieceList[2][8][16]; // [color][pieceType][index]
int index[64]; // [square]
// Board and pieces
Piece board[SQUARE_NB];
Bitboard byTypeBB[PIECE_TYPE_NB];
Bitboard byColorBB[COLOR_NB];
int pieceCount[COLOR_NB][PIECE_TYPE_NB];
Square pieceList[COLOR_NB][PIECE_TYPE_NB][16];
int index[SQUARE_NB];
// Other info
Color sideToMove;
int gamePly;
Key history[MaxGameLength];
File initialKFile, initialKRFile, initialQRFile;
int castlingRightsMask[SQUARE_NB];
Square castlingRookSquare[CASTLING_RIGHT_NB];
Bitboard castlingPath[CASTLING_RIGHT_NB];
StateInfo startState;
uint64_t nodes;
int gamePly;
Color sideToMove;
Thread* thisThread;
StateInfo* st;
// Static variables
static int castleRightsMask[64];
static Key zobrist[2][8][64];
static Key zobEp[64];
static Key zobCastle[16];
static Key zobMaterial[2][8][16];
static Key zobSideToMove;
static Score PieceSquareTable[16][64];
static Key zobExclusion;
bool chess960;
};
inline uint64_t Position::nodes_searched() const {
return nodes;
}
////
//// Inline functions
////
inline void Position::set_nodes_searched(uint64_t n) {
nodes = n;
}
inline Piece Position::piece_on(Square s) const {
return board[s];
}
inline Color Position::color_of_piece_on(Square s) const {
return color_of_piece(piece_on(s));
inline Piece Position::moved_piece(Move m) const {
return board[from_sq(m)];
}
inline PieceType Position::type_of_piece_on(Square s) const {
return type_of_piece(piece_on(s));
}
inline bool Position::square_is_empty(Square s) const {
return piece_on(s) == EMPTY;
}
inline bool Position::square_is_occupied(Square s) const {
return !square_is_empty(s);
}
inline Value Position::midgame_value_of_piece_on(Square s) const {
return piece_value_midgame(piece_on(s));
}
inline Value Position::endgame_value_of_piece_on(Square s) const {
return piece_value_endgame(piece_on(s));
inline bool Position::empty(Square s) const {
return board[s] == NO_PIECE;
}
inline Color Position::side_to_move() const {
return sideToMove;
}
inline Bitboard Position::occupied_squares() const {
return byTypeBB[0];
}
inline Bitboard Position::empty_squares() const {
return ~(occupied_squares());
}
inline Bitboard Position::pieces_of_color(Color c) const {
return byColorBB[c];
inline Bitboard Position::pieces() const {
return byTypeBB[ALL_PIECES];
}
inline Bitboard Position::pieces(PieceType pt) const {
return byTypeBB[pt];
}
inline Bitboard Position::pieces(PieceType pt, Color c) const {
return byTypeBB[pt] & byColorBB[c];
}
inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const {
return byTypeBB[pt1] | byTypeBB[pt2];
}
inline Bitboard Position::pieces(PieceType pt1, PieceType pt2, Color c) const {
return (byTypeBB[pt1] | byTypeBB[pt2]) & byColorBB[c];
inline Bitboard Position::pieces(Color c) const {
return byColorBB[c];
}
inline int Position::piece_count(Color c, PieceType pt) const {
return pieceCount[c][pt];
inline Bitboard Position::pieces(Color c, PieceType pt) const {
return byColorBB[c] & byTypeBB[pt];
}
inline Square Position::piece_list(Color c, PieceType pt, int index) const {
return pieceList[c][pt][index];
inline Bitboard Position::pieces(Color c, PieceType pt1, PieceType pt2) const {
return byColorBB[c] & (byTypeBB[pt1] | byTypeBB[pt2]);
}
inline const Square* Position::piece_list_begin(Color c, PieceType pt) const {
return pieceList[c][pt];
template<PieceType Pt> inline int Position::count(Color c) const {
return pieceCount[c][Pt];
}
template<PieceType Pt> inline const Square* Position::list(Color c) const {
return pieceList[c][Pt];
}
inline Square Position::ep_square() const {
@@ -426,145 +266,168 @@ inline Square Position::king_square(Color c) const {
return pieceList[c][KING][0];
}
inline bool Position::can_castle_kingside(Color side) const {
return st->castleRights & (1+int(side));
inline int Position::can_castle(CastlingRight cr) const {
return st->castlingRights & cr;
}
inline bool Position::can_castle_queenside(Color side) const {
return st->castleRights & (4+4*int(side));
inline int Position::can_castle(Color c) const {
return st->castlingRights & ((WHITE_OO | WHITE_OOO) << (2 * c));
}
inline bool Position::can_castle(Color side) const {
return can_castle_kingside(side) || can_castle_queenside(side);
inline bool Position::castling_impeded(CastlingRight cr) const {
return byTypeBB[ALL_PIECES] & castlingPath[cr];
}
inline Square Position::initial_kr_square(Color c) const {
return relative_square(c, make_square(initialKRFile, RANK_1));
inline Square Position::castling_rook_square(CastlingRight cr) const {
return castlingRookSquare[cr];
}
inline Square Position::initial_qr_square(Color c) const {
return relative_square(c, make_square(initialQRFile, RANK_1));
template<PieceType Pt>
inline Bitboard Position::attacks_from(Square s) const {
return Pt == BISHOP || Pt == ROOK ? attacks_bb<Pt>(s, byTypeBB[ALL_PIECES])
: Pt == QUEEN ? attacks_from<ROOK>(s) | attacks_from<BISHOP>(s)
: StepAttacksBB[Pt][s];
}
template<>
inline Bitboard Position::attacks_from<PAWN>(Square s, Color c) const {
return StepAttackBB[piece_of_color_and_type(c, PAWN)][s];
return StepAttacksBB[make_piece(c, PAWN)][s];
}
template<PieceType Piece> // Knight and King and white pawns
inline Bitboard Position::attacks_from(Square s) const {
return StepAttackBB[Piece][s];
inline Bitboard Position::attacks_from(Piece pc, Square s) const {
return attacks_bb(pc, s, byTypeBB[ALL_PIECES]);
}
template<>
inline Bitboard Position::attacks_from<BISHOP>(Square s) const {
return bishop_attacks_bb(s, occupied_squares());
}
template<>
inline Bitboard Position::attacks_from<ROOK>(Square s) const {
return rook_attacks_bb(s, occupied_squares());
}
template<>
inline Bitboard Position::attacks_from<QUEEN>(Square s) const {
return attacks_from<ROOK>(s) | attacks_from<BISHOP>(s);
inline Bitboard Position::attackers_to(Square s) const {
return attackers_to(s, byTypeBB[ALL_PIECES]);
}
inline Bitboard Position::checkers() const {
return st->checkersBB;
}
inline bool Position::is_check() const {
return st->checkersBB != EmptyBoardBB;
inline Bitboard Position::discovered_check_candidates() const {
return check_blockers(sideToMove, ~sideToMove);
}
inline bool Position::pawn_is_passed(Color c, Square s) const {
return !(pieces(PAWN, opposite_color(c)) & passed_pawn_mask(c, s));
inline Bitboard Position::pinned_pieces(Color c) const {
return check_blockers(c, c);
}
inline bool Position::pawn_is_passed(Bitboard theirPawns, Color c, Square s) {
return !(theirPawns & passed_pawn_mask(c, s));
inline bool Position::pawn_passed(Color c, Square s) const {
return !(pieces(~c, PAWN) & passed_pawn_mask(c, s));
}
inline bool Position::pawn_is_isolated(Bitboard ourPawns, Square s) {
return !(ourPawns & neighboring_files_bb(s));
inline bool Position::advanced_pawn_push(Move m) const {
return type_of(moved_piece(m)) == PAWN
&& relative_rank(sideToMove, from_sq(m)) > RANK_4;
}
inline bool Position::pawn_is_doubled(Bitboard ourPawns, Color c, Square s) {
return ourPawns & squares_behind(c, s);
}
inline bool Position::square_is_weak(Square s, Color c) const {
return !(pieces(PAWN, c) & outpost_mask(opposite_color(c), s));
}
inline Key Position::get_key() const {
inline Key Position::key() const {
return st->key;
}
inline Key Position::get_exclusion_key() const {
return st->key ^ zobExclusion;
}
inline Key Position::get_pawn_key() const {
inline Key Position::pawn_key() const {
return st->pawnKey;
}
inline Key Position::get_material_key() const {
inline Key Position::material_key() const {
return st->materialKey;
}
inline Score Position::pst(Color c, PieceType pt, Square s) const {
return PieceSquareTable[piece_of_color_and_type(c, pt)][s];
}
inline Score Position::pst_delta(Piece piece, Square from, Square to) const {
return PieceSquareTable[piece][to] - PieceSquareTable[piece][from];
}
inline Score Position::value() const {
return st->value;
inline Score Position::psq_score() const {
return st->psq;
}
inline Value Position::non_pawn_material(Color c) const {
return st->npMaterial[c];
}
inline bool Position::move_is_passed_pawn_push(Move m) const {
Color c = side_to_move();
return piece_on(move_from(m)) == piece_of_color_and_type(c, PAWN)
&& pawn_is_passed(c, move_to(m));
inline int Position::game_ply() const {
return gamePly;
}
inline int Position::rule_50_counter() const {
inline bool Position::opposite_bishops() const {
return st->rule50;
return pieceCount[WHITE][BISHOP] == 1
&& pieceCount[BLACK][BISHOP] == 1
&& opposite_colors(pieceList[WHITE][BISHOP][0], pieceList[BLACK][BISHOP][0]);
}
inline bool Position::opposite_colored_bishops() const {
inline bool Position::bishop_pair(Color c) const {
return piece_count(WHITE, BISHOP) == 1
&& piece_count(BLACK, BISHOP) == 1
&& square_color(piece_list(WHITE, BISHOP, 0)) != square_color(piece_list(BLACK, BISHOP, 0));
return pieceCount[c][BISHOP] >= 2
&& opposite_colors(pieceList[c][BISHOP][0], pieceList[c][BISHOP][1]);
}
inline bool Position::has_pawn_on_7th(Color c) const {
return pieces(PAWN, c) & relative_rank_bb(c, RANK_7);
inline bool Position::pawn_on_7th(Color c) const {
return pieces(c, PAWN) & rank_bb(relative_rank(c, RANK_7));
}
inline bool Position::move_is_capture(Move m) const {
// Move must not be MOVE_NONE !
return (m & (3 << 15)) ? !move_is_castle(m) : !square_is_empty(move_to(m));
inline bool Position::is_chess960() const {
return chess960;
}
inline bool Position::move_is_capture_or_promotion(Move m) const {
inline bool Position::capture_or_promotion(Move m) const {
// Move must not be MOVE_NONE !
return (m & (0x1F << 12)) ? !move_is_castle(m) : !square_is_empty(move_to(m));
assert(is_ok(m));
return type_of(m) != NORMAL ? type_of(m) != CASTLING : !empty(to_sq(m));
}
#endif // !defined(POSITION_H_INCLUDED)
inline bool Position::capture(Move m) const {
// Note that castling is encoded as "king captures the rook"
assert(is_ok(m));
return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == ENPASSANT;
}
inline PieceType Position::captured_piece_type() const {
return st->capturedType;
}
inline Thread* Position::this_thread() const {
return thisThread;
}
inline void Position::put_piece(Square s, Color c, PieceType pt) {
board[s] = make_piece(c, pt);
byTypeBB[ALL_PIECES] |= s;
byTypeBB[pt] |= s;
byColorBB[c] |= s;
index[s] = pieceCount[c][pt]++;
pieceList[c][pt][index[s]] = s;
}
inline void Position::move_piece(Square from, Square to, Color c, PieceType pt) {
// index[from] is not updated and becomes stale. This works as long
// as index[] is accessed just by known occupied squares.
Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to];
byTypeBB[ALL_PIECES] ^= from_to_bb;
byTypeBB[pt] ^= from_to_bb;
byColorBB[c] ^= from_to_bb;
board[from] = NO_PIECE;
board[to] = make_piece(c, pt);
index[to] = index[from];
pieceList[c][pt][index[to]] = to;
}
inline void Position::remove_piece(Square s, Color c, PieceType pt) {
// WARNING: This is not a reversible operation. If we remove a piece in
// do_move() and then replace it in undo_move() we will put it at the end of
// the list and not in its original place, it means index[] and pieceList[]
// are not guaranteed to be invariant to a do_move() + undo_move() sequence.
byTypeBB[ALL_PIECES] ^= s;
byTypeBB[pt] ^= s;
byColorBB[c] ^= s;
/* board[s] = NO_PIECE; */ // Not needed, will be overwritten by capturing
Square lastSquare = pieceList[c][pt][--pieceCount[c][pt]];
index[lastSquare] = index[s];
pieceList[c][pt][index[lastSquare]] = lastSquare;
pieceList[c][pt][pieceCount[c][pt]] = SQ_NONE;
}
#endif // #ifndef POSITION_H_INCLUDED
+64 -154
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,172 +17,82 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(PSQTAB_H_INCLUDED)
#ifndef PSQTAB_H_INCLUDED
#define PSQTAB_H_INCLUDED
////
//// Includes
////
#include "types.h"
#include "value.h"
#define S(mg, eg) make_score(mg, eg)
////
//// Constants modified by Joona Kiiski
////
/// PSQT[PieceType][Square] contains Piece-Square scores. For each piece type on
/// a given square a (middlegame, endgame) score pair is assigned. PSQT is defined
/// for the white side and the tables are symmetric for the black side.
static const Value MP = PawnValueMidgame;
static const Value MK = KnightValueMidgame;
static const Value MB = BishopValueMidgame;
static const Value MR = RookValueMidgame;
static const Value MQ = QueenValueMidgame;
static const int MgPST[][64] = {
static const Score PSQT[][SQUARE_NB] = {
{ },
{// Pawn
// A B C D E F G H
0, 0, 0, 0, 0, 0, 0, 0,
MP-28, MP-6, MP+ 4, MP+14, MP+14, MP+ 4, MP-6, MP-28,
MP-28, MP-6, MP+ 9, MP+36, MP+36, MP+ 9, MP-6, MP-28,
MP-28, MP-6, MP+17, MP+58, MP+58, MP+17, MP-6, MP-28,
MP-28, MP-6, MP+17, MP+36, MP+36, MP+17, MP-6, MP-28,
MP-28, MP-6, MP+ 9, MP+14, MP+14, MP+ 9, MP-6, MP-28,
MP-28, MP-6, MP+ 4, MP+14, MP+14, MP+ 4, MP-6, MP-28,
0, 0, 0, 0, 0, 0, 0, 0
{ // Pawn
S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S(0, 0), S( 0, 0), S( 0, 0), S( 0, 0),
S(-20, 0), S( 0, 0), S( 0, 0), S( 0, 0), S(0, 0), S( 0, 0), S( 0, 0), S(-20, 0),
S(-20, 0), S( 0, 0), S(10, 0), S(20, 0), S(20, 0), S(10, 0), S( 0, 0), S(-20, 0),
S(-20, 0), S( 0, 0), S(20, 0), S(40, 0), S(40, 0), S(20, 0), S( 0, 0), S(-20, 0),
S(-20, 0), S( 0, 0), S(10, 0), S(20, 0), S(20, 0), S(10, 0), S( 0, 0), S(-20, 0),
S(-20, 0), S( 0, 0), S( 0, 0), S( 0, 0), S(0, 0), S( 0, 0), S( 0, 0), S(-20, 0),
S(-20, 0), S( 0, 0), S( 0, 0), S( 0, 0), S(0, 0), S( 0, 0), S( 0, 0), S(-20, 0),
S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S(0, 0), S( 0, 0), S( 0, 0), S( 0, 0)
},
{// Knight
// A B C D E F G H
MK-135, MK-107, MK-80, MK-67, MK-67, MK-80, MK-107, MK-135,
MK- 93, MK- 67, MK-39, MK-25, MK-25, MK-39, MK- 67, MK- 93,
MK- 53, MK- 25, MK+ 1, MK+13, MK+13, MK+ 1, MK- 25, MK- 53,
MK- 25, MK+ 1, MK+27, MK+41, MK+41, MK+27, MK+ 1, MK- 25,
MK- 11, MK+ 13, MK+41, MK+55, MK+55, MK+41, MK+ 13, MK- 11,
MK- 11, MK+ 13, MK+41, MK+55, MK+55, MK+41, MK+ 13, MK- 11,
MK- 53, MK- 25, MK+ 1, MK+13, MK+13, MK+ 1, MK- 25, MK- 53,
MK-193, MK- 67, MK-39, MK-25, MK-25, MK-39, MK- 67, MK-193
{ // Knight
S(-144,-98), S(-109,-83), S(-85,-51), S(-73,-16), S(-73,-16), S(-85,-51), S(-109,-83), S(-144,-98),
S( -88,-68), S( -43,-53), S(-19,-21), S( -7, 14), S( -7, 14), S(-19,-21), S( -43,-53), S( -88,-68),
S( -69,-53), S( -24,-38), S( 0, -6), S( 12, 29), S( 12, 29), S( 0, -6), S( -24,-38), S( -69,-53),
S( -28,-42), S( 17,-27), S( 41, 5), S( 53, 40), S( 53, 40), S( 41, 5), S( 17,-27), S( -28,-42),
S( -30,-42), S( 15,-27), S( 39, 5), S( 51, 40), S( 51, 40), S( 39, 5), S( 15,-27), S( -30,-42),
S( -10,-53), S( 35,-38), S( 59, -6), S( 71, 29), S( 71, 29), S( 59, -6), S( 35,-38), S( -10,-53),
S( -64,-68), S( -19,-53), S( 5,-21), S( 17, 14), S( 17, 14), S( 5,-21), S( -19,-53), S( -64,-68),
S(-200,-98), S( -65,-83), S(-41,-51), S(-29,-16), S(-29,-16), S(-41,-51), S( -65,-83), S(-200,-98)
},
{// Bishop
// A B C D E F G H
MB-40, MB-40, MB-35, MB-30, MB-30, MB-35, MB-40, MB-40,
MB-17, MB+ 0, MB- 4, MB+ 0, MB+ 0, MB- 4, MB+ 0, MB-17,
MB-13, MB- 4, MB+ 8, MB+ 4, MB+ 4, MB+ 8, MB- 4, MB-13,
MB- 8, MB+ 0, MB+ 4, MB+17, MB+17, MB+ 4, MB+ 0, MB- 8,
MB- 8, MB+ 0, MB+ 4, MB+17, MB+17, MB+ 4, MB+ 0, MB- 8,
MB-13, MB- 4, MB+ 8, MB+ 4, MB+ 4, MB+ 8, MB- 4, MB-13,
MB-17, MB+ 0, MB- 4, MB+ 0, MB+ 0, MB- 4, MB+ 0, MB-17,
MB-17, MB-17, MB-13, MB- 8, MB- 8, MB-13, MB-17, MB-17
{ // Bishop
S(-54,-65), S(-27,-42), S(-34,-44), S(-43,-26), S(-43,-26), S(-34,-44), S(-27,-42), S(-54,-65),
S(-29,-43), S( 8,-20), S( 1,-22), S( -8, -4), S( -8, -4), S( 1,-22), S( 8,-20), S(-29,-43),
S(-20,-33), S( 17,-10), S( 10,-12), S( 1, 6), S( 1, 6), S( 10,-12), S( 17,-10), S(-20,-33),
S(-19,-35), S( 18,-12), S( 11,-14), S( 2, 4), S( 2, 4), S( 11,-14), S( 18,-12), S(-19,-35),
S(-22,-35), S( 15,-12), S( 8,-14), S( -1, 4), S( -1, 4), S( 8,-14), S( 15,-12), S(-22,-35),
S(-28,-33), S( 9,-10), S( 2,-12), S( -7, 6), S( -7, 6), S( 2,-12), S( 9,-10), S(-28,-33),
S(-32,-43), S( 5,-20), S( -2,-22), S(-11, -4), S(-11, -4), S( -2,-22), S( 5,-20), S(-32,-43),
S(-49,-65), S(-22,-42), S(-29,-44), S(-38,-26), S(-38,-26), S(-29,-44), S(-22,-42), S(-49,-65)
},
{// Rook
// A B C D E F G H
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12,
MR-12, MR-7, MR-2, MR+2, MR+2, MR-2, MR-7, MR-12
{ // Rook
S(-22, 3), S(-17, 3), S(-12, 3), S(-8, 3), S(-8, 3), S(-12, 3), S(-17, 3), S(-22, 3),
S(-22, 3), S( -7, 3), S( -2, 3), S( 2, 3), S( 2, 3), S( -2, 3), S( -7, 3), S(-22, 3),
S(-22, 3), S( -7, 3), S( -2, 3), S( 2, 3), S( 2, 3), S( -2, 3), S( -7, 3), S(-22, 3),
S(-22, 3), S( -7, 3), S( -2, 3), S( 2, 3), S( 2, 3), S( -2, 3), S( -7, 3), S(-22, 3),
S(-22, 3), S( -7, 3), S( -2, 3), S( 2, 3), S( 2, 3), S( -2, 3), S( -7, 3), S(-22, 3),
S(-22, 3), S( -7, 3), S( -2, 3), S( 2, 3), S( 2, 3), S( -2, 3), S( -7, 3), S(-22, 3),
S(-11, 3), S( 4, 3), S( 9, 3), S(13, 3), S(13, 3), S( 9, 3), S( 4, 3), S(-11, 3),
S(-22, 3), S(-17, 3), S(-12, 3), S(-8, 3), S(-8, 3), S(-12, 3), S(-17, 3), S(-22, 3)
},
{// Queen
// A B C D E F G H
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8,
MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8, MQ+8
{ // Queen
S(-2,-80), S(-2,-54), S(-2,-42), S(-2,-30), S(-2,-30), S(-2,-42), S(-2,-54), S(-2,-80),
S(-2,-54), S( 8,-30), S( 8,-18), S( 8, -6), S( 8, -6), S( 8,-18), S( 8,-30), S(-2,-54),
S(-2,-42), S( 8,-18), S( 8, -6), S( 8, 6), S( 8, 6), S( 8, -6), S( 8,-18), S(-2,-42),
S(-2,-30), S( 8, -6), S( 8, 6), S( 8, 18), S( 8, 18), S( 8, 6), S( 8, -6), S(-2,-30),
S(-2,-30), S( 8, -6), S( 8, 6), S( 8, 18), S( 8, 18), S( 8, 6), S( 8, -6), S(-2,-30),
S(-2,-42), S( 8,-18), S( 8, -6), S( 8, 6), S( 8, 6), S( 8, -6), S( 8,-18), S(-2,-42),
S(-2,-54), S( 8,-30), S( 8,-18), S( 8, -6), S( 8, -6), S( 8,-18), S( 8,-30), S(-2,-54),
S(-2,-80), S(-2,-54), S(-2,-42), S(-2,-30), S(-2,-30), S(-2,-42), S(-2,-54), S(-2,-80)
},
{// King
//A B C D E F G H
287, 311, 262, 214, 214, 262, 311, 287,
262, 287, 238, 190, 190, 238, 287, 262,
214, 238, 190, 142, 142, 190, 238, 214,
190, 214, 167, 119, 119, 167, 214, 190,
167, 190, 142, 94, 94, 142, 190, 167,
142, 167, 119, 69, 69, 119, 167, 142,
119, 142, 94, 46, 46, 94, 142, 119,
94, 119, 69, 21, 21, 69, 119, 94
{ // King
S(298, 27), S(332, 81), S(273,108), S(225,116), S(225,116), S(273,108), S(332, 81), S(298, 27),
S(287, 74), S(321,128), S(262,155), S(214,163), S(214,163), S(262,155), S(321,128), S(287, 74),
S(224,111), S(258,165), S(199,192), S(151,200), S(151,200), S(199,192), S(258,165), S(224,111),
S(196,135), S(230,189), S(171,216), S(123,224), S(123,224), S(171,216), S(230,189), S(196,135),
S(173,135), S(207,189), S(148,216), S(100,224), S(100,224), S(148,216), S(207,189), S(173,135),
S(146,111), S(180,165), S(121,192), S( 73,200), S( 73,200), S(121,192), S(180,165), S(146,111),
S(119, 74), S(153,128), S( 94,155), S( 46,163), S( 46,163), S( 94,155), S(153,128), S(119, 74),
S( 98, 27), S(132, 81), S( 73,108), S( 25,116), S( 25,116), S( 73,108), S(132, 81), S( 98, 27)
}
};
static const Value EP = PawnValueEndgame;
static const Value EK = KnightValueEndgame;
static const Value EB = BishopValueEndgame;
static const Value ER = RookValueEndgame;
static const Value EQ = QueenValueEndgame;
#undef S
static const int EgPST[][64] = {
{ },
{// Pawn
// A B C D E F G H
0, 0, 0, 0, 0, 0, 0, 0,
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8, EP-8,
0, 0, 0, 0, 0, 0, 0, 0
},
{// Knight
// A B C D E F G H
EK-104, EK-79, EK-55, EK-42, EK-42, EK-55, EK-79, EK-104,
EK- 79, EK-55, EK-30, EK-17, EK-17, EK-30, EK-55, EK- 79,
EK- 55, EK-30, EK- 6, EK+ 5, EK+ 5, EK- 6, EK-30, EK- 55,
EK- 42, EK-17, EK+ 5, EK+18, EK+18, EK+ 5, EK-17, EK- 42,
EK- 42, EK-17, EK+ 5, EK+18, EK+18, EK+ 5, EK-17, EK- 42,
EK- 55, EK-30, EK- 6, EK+ 5, EK+ 5, EK- 6, EK-30, EK- 55,
EK- 79, EK-55, EK-30, EK-17, EK-17, EK-30, EK-55, EK- 79,
EK-104, EK-79, EK-55, EK-42, EK-42, EK-55, EK-79, EK-104
},
{// Bishop
// A B C D E F G H
EB-59, EB-42, EB-35, EB-26, EB-26, EB-35, EB-42, EB-59,
EB-42, EB-26, EB-18, EB-11, EB-11, EB-18, EB-26, EB-42,
EB-35, EB-18, EB-11, EB- 4, EB- 4, EB-11, EB-18, EB-35,
EB-26, EB-11, EB- 4, EB+ 4, EB+ 4, EB- 4, EB-11, EB-26,
EB-26, EB-11, EB- 4, EB+ 4, EB+ 4, EB- 4, EB-11, EB-26,
EB-35, EB-18, EB-11, EB- 4, EB- 4, EB-11, EB-18, EB-35,
EB-42, EB-26, EB-18, EB-11, EB-11, EB-18, EB-26, EB-42,
EB-59, EB-42, EB-35, EB-26, EB-26, EB-35, EB-42, EB-59
},
{// Rook
// A B C D E F G H
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3,
ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3, ER+3
},
{// Queen
// A B C D E F G H
EQ-80, EQ-54, EQ-42, EQ-30, EQ-30, EQ-42, EQ-54, EQ-80,
EQ-54, EQ-30, EQ-18, EQ- 6, EQ- 6, EQ-18, EQ-30, EQ-54,
EQ-42, EQ-18, EQ- 6, EQ+ 6, EQ+ 6, EQ- 6, EQ-18, EQ-42,
EQ-30, EQ- 6, EQ+ 6, EQ+18, EQ+18, EQ+ 6, EQ- 6, EQ-30,
EQ-30, EQ- 6, EQ+ 6, EQ+18, EQ+18, EQ+ 6, EQ- 6, EQ-30,
EQ-42, EQ-18, EQ- 6, EQ+ 6, EQ+ 6, EQ- 6, EQ-18, EQ-42,
EQ-54, EQ-30, EQ-18, EQ- 6, EQ- 6, EQ-18, EQ-30, EQ-54,
EQ-80, EQ-54, EQ-42, EQ-30, EQ-30, EQ-42, EQ-54, EQ-80
},
{// King
//A B C D E F G H
18, 77, 105, 135, 135, 105, 77, 18,
77, 135, 165, 193, 193, 165, 135, 77,
105, 165, 193, 222, 222, 193, 165, 105,
135, 193, 222, 251, 251, 222, 193, 135,
135, 193, 222, 251, 251, 222, 193, 135,
105, 165, 193, 222, 222, 193, 165, 105,
77, 135, 165, 193, 193, 165, 135, 77,
18, 77, 105, 135, 135, 105, 77, 18
}
};
#endif // !defined(PSQTAB_H_INCLUDED)
#endif // #ifndef PSQTAB_H_INCLUDED
+81
View File
@@ -0,0 +1,81 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
This file is based on original code by Heinz van Saanen and is
available under the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*/
#ifndef RKISS_H_INCLUDED
#define RKISS_H_INCLUDED
#include "types.h"
/// RKISS is our pseudo random number generator (PRNG) used to compute hash keys.
/// George Marsaglia invented the RNG-Kiss-family in the early 90's. This is a
/// specific version that Heinz van Saanen derived from some public domain code
/// by Bob Jenkins. Following the feature list, as tested by Heinz.
///
/// - Quite platform independent
/// - Passes ALL dieharder tests! Here *nix sys-rand() e.g. fails miserably:-)
/// - ~12 times faster than my *nix sys-rand()
/// - ~4 times faster than SSE2-version of Mersenne twister
/// - Average cycle length: ~2^126
/// - 64 bit seed
/// - Return doubles with a full 53 bit mantissa
/// - Thread safe
class RKISS {
uint64_t a, b, c, d;
uint64_t rotate_L(uint64_t x, unsigned k) const {
return (x << k) | (x >> (64 - k));
}
uint64_t rand64() {
const uint64_t e = a - rotate_L(b, 7);
a = b ^ rotate_L(c, 13);
b = c + rotate_L(d, 37);
c = d + e;
return d = e + a;
}
public:
RKISS(int seed = 73) {
a = 0xF1EA5EED, b = c = d = 0xD4E12C77;
for (int i = 0; i < seed; ++i) // Scramble a few rounds
rand64();
}
template<typename T> T rand() { return T(rand64()); }
/// Special generator used to fast init magic numbers. Here the
/// trick is to rotate the randoms of a given quantity 's' known
/// to be optimal to quickly find a good magic candidate.
template<typename T> T magic_rand(int s) {
return rotate_L(rotate_L(rand<T>(), (s >> 0) & 0x3F) & rand<T>()
, (s >> 6) & 0x3F) & rand<T>();
}
};
#endif // #ifndef RKISS_H_INCLUDED
-436
View File
@@ -1,436 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include <cstring>
#include <iomanip>
#include <string>
#include <sstream>
#include "history.h"
#include "movepick.h"
#include "san.h"
using std::string;
////
//// Local definitions
////
namespace {
enum Ambiguity {
AMBIGUITY_NONE,
AMBIGUITY_FILE,
AMBIGUITY_RANK,
AMBIGUITY_BOTH
};
const History H; // used as dummy argument for MovePicker c'tor
Ambiguity move_ambiguity(const Position& pos, Move m);
const string time_string(int milliseconds);
const string score_string(Value v);
}
////
//// Functions
////
/// move_to_san() takes a position and a move as input, where it is assumed
/// that the move is a legal move from the position. The return value is
/// a string containing the move in short algebraic notation.
const string move_to_san(const Position& pos, Move m) {
assert(pos.is_ok());
assert(move_is_ok(m));
Square from, to;
PieceType pt;
from = move_from(m);
to = move_to(m);
pt = type_of_piece(pos.piece_on(move_from(m)));
string san = "";
if (m == MOVE_NONE)
return "(none)";
else if (m == MOVE_NULL)
return "(null)";
else if (move_is_long_castle(m) || (int(to - from) == -2 && pt == KING))
san = "O-O-O";
else if (move_is_short_castle(m) || (int(to - from) == 2 && pt == KING))
san = "O-O";
else
{
if (pt != PAWN)
{
san += piece_type_to_char(pt, true);
switch (move_ambiguity(pos, m)) {
case AMBIGUITY_NONE:
break;
case AMBIGUITY_FILE:
san += file_to_char(square_file(from));
break;
case AMBIGUITY_RANK:
san += rank_to_char(square_rank(from));
break;
case AMBIGUITY_BOTH:
san += square_to_string(from);
break;
default:
assert(false);
}
}
if (pos.move_is_capture(m))
{
if (pt == PAWN)
san += file_to_char(square_file(move_from(m)));
san += "x";
}
san += square_to_string(move_to(m));
if (move_is_promotion(m))
{
san += '=';
san += piece_type_to_char(move_promotion_piece(m), true);
}
}
// Is the move check? We don't use pos.move_is_check(m) here, because
// Position::move_is_check doesn't detect all checks (not castling moves,
// promotions and en passant captures).
StateInfo st;
Position p(pos);
p.do_move(m, st);
if (p.is_check())
san += p.is_mate()? "#" : "+";
return san;
}
/// move_from_san() takes a position and a string as input, and tries to
/// interpret the string as a move in short algebraic notation. On success,
/// the move is returned. On failure (i.e. if the string is unparsable, or
/// if the move is illegal or ambiguous), MOVE_NONE is returned.
Move move_from_san(const Position& pos, const string& movestr) {
assert(pos.is_ok());
MovePicker mp = MovePicker(pos, MOVE_NONE, OnePly, H);
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
// Castling moves
if (movestr == "O-O-O" || movestr == "O-O-O+")
{
Move m;
while ((m = mp.get_next_move()) != MOVE_NONE)
if (move_is_long_castle(m) && pos.pl_move_is_legal(m, pinned))
return m;
return MOVE_NONE;
}
else if (movestr == "O-O" || movestr == "O-O+")
{
Move m;
while ((m = mp.get_next_move()) != MOVE_NONE)
if (move_is_short_castle(m) && pos.pl_move_is_legal(m, pinned))
return m;
return MOVE_NONE;
}
// Normal moves. We use a simple FSM to parse the san string.
enum { START, TO_FILE, TO_RANK, PROMOTION_OR_CHECK, PROMOTION, CHECK, END };
static const string pieceLetters = "KQRBN";
PieceType pt = NO_PIECE_TYPE, promotion = NO_PIECE_TYPE;
File fromFile = FILE_NONE, toFile = FILE_NONE;
Rank fromRank = RANK_NONE, toRank = RANK_NONE;
Square to;
int state = START;
for (size_t i = 0; i < movestr.length(); i++)
{
char type, c = movestr[i];
if (pieceLetters.find(c) != string::npos)
type = 'P';
else if (c >= 'a' && c <= 'h')
type = 'F';
else if (c >= '1' && c <= '8')
type = 'R';
else
type = c;
switch (type) {
case 'P':
if (state == START)
{
pt = piece_type_from_char(c);
state = TO_FILE;
}
else if (state == PROMOTION)
{
promotion = piece_type_from_char(c);
state = (i < movestr.length() - 1) ? CHECK : END;
}
else
return MOVE_NONE;
break;
case 'F':
if (state == START)
{
pt = PAWN;
fromFile = toFile = file_from_char(c);
state = TO_RANK;
}
else if (state == TO_FILE)
{
toFile = file_from_char(c);
state = TO_RANK;
}
else if (state == TO_RANK && toFile != FILE_NONE)
{
// Previous file was for disambiguation
fromFile = toFile;
toFile = file_from_char(c);
}
else
return MOVE_NONE;
break;
case 'R':
if (state == TO_RANK)
{
toRank = rank_from_char(c);
state = (i < movestr.length() - 1) ? PROMOTION_OR_CHECK : END;
}
else if (state == TO_FILE && fromRank == RANK_NONE)
{
// It's a disambiguation rank instead of a file
fromRank = rank_from_char(c);
}
else
return MOVE_NONE;
break;
case 'x': case 'X':
if (state == TO_RANK)
{
// Previous file was for disambiguation, or it's a pawn capture
fromFile = toFile;
state = TO_FILE;
}
else if (state != TO_FILE)
return MOVE_NONE;
break;
case '=':
if (state == PROMOTION_OR_CHECK)
state = PROMOTION;
else
return MOVE_NONE;
break;
case '+': case '#':
if (state == PROMOTION_OR_CHECK || state == CHECK)
state = END;
else
return MOVE_NONE;
break;
default:
return MOVE_NONE;
break;
}
}
if (state != END)
return MOVE_NONE;
// Look for a matching move
Move m, move = MOVE_NONE;
to = make_square(toFile, toRank);
int matches = 0;
while ((m = mp.get_next_move()) != MOVE_NONE)
if ( pos.type_of_piece_on(move_from(m)) == pt
&& move_to(m) == to
&& move_promotion_piece(m) == promotion
&& (fromFile == FILE_NONE || fromFile == square_file(move_from(m)))
&& (fromRank == RANK_NONE || fromRank == square_rank(move_from(m))))
{
move = m;
matches++;
}
return (matches == 1 ? move : MOVE_NONE);
}
/// line_to_san() takes a position and a line (an array of moves representing
/// a sequence of legal moves from the position) as input, and returns a
/// string containing the line in short algebraic notation. If the boolean
/// parameter 'breakLines' is true, line breaks are inserted, with a line
/// length of 80 characters. After a line break, 'startColumn' spaces are
/// inserted at the beginning of the new line.
const string line_to_san(const Position& pos, Move line[], int startColumn, bool breakLines) {
StateInfo st;
std::stringstream s;
string moveStr;
size_t length = 0;
size_t maxLength = 80 - startColumn;
Position p(pos);
for (int i = 0; line[i] != MOVE_NONE; i++)
{
moveStr = move_to_san(p, line[i]);
length += moveStr.length() + 1;
if (breakLines && length > maxLength)
{
s << '\n' << std::setw(startColumn) << ' ';
length = moveStr.length() + 1;
}
s << moveStr << ' ';
if (line[i] == MOVE_NULL)
p.do_null_move(st);
else
p.do_move(line[i], st);
}
return s.str();
}
/// pretty_pv() creates a human-readable string from a position and a PV.
/// It is used to write search information to the log file (which is created
/// when the UCI parameter "Use Search Log" is "true").
const string pretty_pv(const Position& pos, int time, int depth,
uint64_t nodes, Value score, ValueType type, Move pv[]) {
std::stringstream s;
// Depth
s << std::setw(2) << depth << " ";
// Score
s << ((type == VALUE_TYPE_LOWER)? ">" : ((type == VALUE_TYPE_UPPER)? "<" : " "));
s << std::setw(7) << score_string(score);
// Time
s << std::setw(8) << time_string(time) << " ";
// Nodes
if (nodes < 1000000ULL)
s << std::setw(8) << nodes << " ";
else if (nodes < 1000000000ULL)
s << std::setw(7) << nodes/1000ULL << 'k' << " ";
else
s << std::setw(7) << nodes/1000000ULL << 'M' << " ";
// PV
s << line_to_san(pos, pv, 30, true);
return s.str();
}
namespace {
Ambiguity move_ambiguity(const Position& pos, Move m) {
Square from = move_from(m);
Square to = move_to(m);
Piece pc = pos.piece_on(from);
// King moves are never ambiguous, because there is never two kings of
// the same color.
if (type_of_piece(pc) == KING)
return AMBIGUITY_NONE;
MovePicker mp = MovePicker(pos, MOVE_NONE, OnePly, H);
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
Move mv, moveList[8];
int n = 0;
while ((mv = mp.get_next_move()) != MOVE_NONE)
if (move_to(mv) == to && pos.piece_on(move_from(mv)) == pc && pos.pl_move_is_legal(mv, pinned))
moveList[n++] = mv;
if (n == 1)
return AMBIGUITY_NONE;
int f = 0, r = 0;
for (int i = 0; i < n; i++)
{
if (square_file(move_from(moveList[i])) == square_file(from))
f++;
if (square_rank(move_from(moveList[i])) == square_rank(from))
r++;
}
if (f == 1)
return AMBIGUITY_FILE;
if (r == 1)
return AMBIGUITY_RANK;
return AMBIGUITY_BOTH;
}
const string time_string(int milliseconds) {
std::stringstream s;
s << std::setfill('0');
int hours = milliseconds / (1000*60*60);
int minutes = (milliseconds - hours*1000*60*60) / (1000*60);
int seconds = (milliseconds - hours*1000*60*60 - minutes*1000*60) / 1000;
if (hours)
s << hours << ':';
s << std::setw(2) << minutes << ':' << std::setw(2) << seconds;
return s.str();
}
const string score_string(Value v) {
std::stringstream s;
if (v >= VALUE_MATE - 200)
s << "#" << (VALUE_MATE - v + 1) / 2;
else if(v <= -VALUE_MATE + 200)
s << "-#" << (VALUE_MATE + v) / 2;
else
{
float floatScore = float(v) / float(PawnValueMidgame);
if (v >= 0)
s << '+';
s << std::setprecision(2) << std::fixed << floatScore;
}
return s.str();
}
}
-44
View File
@@ -1,44 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(SAN_H_INCLUDED)
#define SAN_H_INCLUDED
////
//// Includes
////
#include <string>
#include "move.h"
#include "position.h"
#include "value.h"
////
//// Prototypes
////
extern const std::string move_to_san(const Position& pos, Move m);
extern Move move_from_san(const Position& pos, const std::string& str);
extern const std::string line_to_san(const Position& pos, Move line[], int startColumn, bool breakLines);
extern const std::string pretty_pv(const Position& pos, int time, int depth, uint64_t nodes, Value score, ValueType type, Move pv[]);
#endif // !defined(SAN_H_INCLUDED)
-52
View File
@@ -1,52 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(SCALE_H_INCLUDED)
#define SCALE_H_INCLUDED
////
//// Includes
////
#include "value.h"
////
//// Types
////
enum ScaleFactor {
SCALE_FACTOR_ZERO = 0,
SCALE_FACTOR_NORMAL = 64,
SCALE_FACTOR_MAX = 128,
SCALE_FACTOR_NONE = 255
};
////
//// Inline functions
////
inline Value apply_scale_factor(Value v, ScaleFactor f) {
return Value((v * f) / int(SCALE_FACTOR_NORMAL));
}
#endif // !defined(SCALE_H_INCLUDED)
+1349 -2724
View File
File diff suppressed because it is too large Load Diff
+81 -43
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,60 +17,98 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(SEARCH_H_INCLUDED)
#ifndef SEARCH_H_INCLUDED
#define SEARCH_H_INCLUDED
////
//// Includes
////
#include <memory>
#include <stack>
#include <vector>
#include "depth.h"
#include "move.h"
#include "misc.h"
#include "position.h"
#include "types.h"
struct SplitPoint;
////
//// Constants
////
namespace Search {
const int PLY_MAX = 100;
const int PLY_MAX_PLUS_2 = 102;
const int KILLER_MAX = 2;
/// The Stack struct keeps track of the information we need to remember from
/// nodes shallower and deeper in the tree during the search. Each search thread
/// has its own array of Stack objects, indexed by the current ply.
////
//// Types
////
/// The SearchStack struct keeps track of the information we need to remember
/// from nodes shallower and deeper in the tree during the search. Each
/// search thread has its own array of SearchStack objects, indexed by the
/// current ply.
struct SearchStack {
Move pv[PLY_MAX_PLUS_2];
struct Stack {
SplitPoint* splitPoint;
int ply;
Move currentMove;
Move mateKiller;
Move threatMove;
Move killers[KILLER_MAX];
Move ttMove;
Move excludedMove;
Move killers[2];
Depth reduction;
void init(int ply);
void initKillers();
Value staticEval;
int skipNullMove;
};
////
//// Prototypes
////
/// RootMove struct is used for moves at the root of the tree. For each root
/// move we store a score, a node count, and a PV (really a refutation in the
/// case of moves which fail low). Score is normally set at -VALUE_INFINITE for
/// all non-pv moves.
struct RootMove {
extern void init_threads();
extern void stop_threads();
extern bool think(const Position &pos, bool infinite, bool ponder, int side_to_move,
int time[], int increment[], int movesToGo, int maxDepth,
int maxNodes, int maxTime, Move searchMoves[]);
extern int perft(Position &pos, Depth depth);
extern int64_t nodes_searched();
RootMove(Move m) : score(-VALUE_INFINITE), prevScore(-VALUE_INFINITE) {
pv.push_back(m); pv.push_back(MOVE_NONE);
}
bool operator<(const RootMove& m) const { return score > m.score; } // Ascending sort
bool operator==(const Move& m) const { return pv[0] == m; }
void extract_pv_from_tt(Position& pos);
void insert_pv_in_tt(Position& pos);
Value score;
Value prevScore;
std::vector<Move> pv;
};
#endif // !defined(SEARCH_H_INCLUDED)
/// The LimitsType struct stores information sent by GUI about available time
/// to search the current move, maximum depth/time, if we are in analysis mode
/// or if we have to ponder while it's our opponent's turn to move.
struct LimitsType {
LimitsType() { // Using memset on a std::vector is undefined behavior
time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = movestogo =
depth = nodes = movetime = mate = infinite = ponder = 0;
}
bool use_time_management() const { return !(mate | movetime | depth | nodes | infinite); }
std::vector<Move> searchmoves;
int time[COLOR_NB], inc[COLOR_NB], movestogo, depth, nodes, movetime, mate, infinite, ponder;
};
/// The SignalsType struct stores volatile flags updated during the search
/// typically in an async fashion e.g. to stop the search by the GUI.
struct SignalsType {
bool stop, stopOnPonderhit, firstRootMove, failedLowAtRoot;
};
typedef std::auto_ptr<std::stack<StateInfo> > StateStackPtr;
extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<RootMove> RootMoves;
extern Position RootPos;
extern Color RootColor;
extern Time::point SearchTime;
extern StateStackPtr SetupStates;
extern void init();
extern uint64_t perft(Position& pos, Depth depth);
extern void think();
} // namespace Search
#endif // #ifndef SEARCH_H_INCLUDED
-201
View File
@@ -1,201 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(SQUARE_H_INCLUDED)
#define SQUARE_H_INCLUDED
////
//// Includes
////
#include <cstdlib> // for abs()
#include <string>
#include "color.h"
#include "misc.h"
////
//// Types
////
enum Square {
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4,
SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5,
SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE
};
enum File {
FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NONE
};
enum Rank {
RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NONE
};
enum SquareDelta {
DELTA_SSW = -021, DELTA_SS = -020, DELTA_SSE = -017, DELTA_SWW = -012,
DELTA_SW = -011, DELTA_S = -010, DELTA_SE = -07, DELTA_SEE = -06,
DELTA_W = -01, DELTA_ZERO = 0, DELTA_E = 01, DELTA_NWW = 06, DELTA_NW = 07,
DELTA_N = 010, DELTA_NE = 011, DELTA_NEE = 012, DELTA_NNW = 017,
DELTA_NN = 020, DELTA_NNE = 021
};
////
//// Constants
////
const int FlipMask = 070;
const int FlopMask = 07;
////
//// Inline functions
////
inline File operator+ (File x, int i) { return File(int(x) + i); }
inline File operator+ (File x, File y) { return x + int(y); }
inline void operator++ (File &x, int) { x = File(int(x) + 1); }
inline void operator+= (File &x, int i) { x = File(int(x) + i); }
inline File operator- (File x, int i) { return File(int(x) - i); }
inline void operator-- (File &x, int) { x = File(int(x) - 1); }
inline void operator-= (File &x, int i) { x = File(int(x) - i); }
inline Rank operator+ (Rank x, int i) { return Rank(int(x) + i); }
inline Rank operator+ (Rank x, Rank y) { return x + int(y); }
inline void operator++ (Rank &x, int) { x = Rank(int(x) + 1); }
inline void operator+= (Rank &x, int i) { x = Rank(int(x) + i); }
inline Rank operator- (Rank x, int i) { return Rank(int(x) - i); }
inline void operator-- (Rank &x, int) { x = Rank(int(x) - 1); }
inline void operator-= (Rank &x, int i) { x = Rank(int(x) - i); }
inline Square operator+ (Square x, int i) { return Square(int(x) + i); }
inline void operator++ (Square &x, int) { x = Square(int(x) + 1); }
inline void operator+= (Square &x, int i) { x = Square(int(x) + i); }
inline Square operator- (Square x, int i) { return Square(int(x) - i); }
inline void operator-- (Square &x, int) { x = Square(int(x) - 1); }
inline void operator-= (Square &x, int i) { x = Square(int(x) - i); }
inline Square operator+ (Square x, SquareDelta i) { return Square(int(x) + i); }
inline void operator+= (Square &x, SquareDelta i) { x = Square(int(x) + i); }
inline Square operator- (Square x, SquareDelta i) { return Square(int(x) - i); }
inline void operator-= (Square &x, SquareDelta i) { x = Square(int(x) - i); }
inline SquareDelta operator- (Square x, Square y) {
return SquareDelta(int(x) - int(y));
}
inline Square make_square(File f, Rank r) {
return Square(int(f) | (int(r) << 3));
}
inline File square_file(Square s) {
return File(int(s) & 7);
}
inline Rank square_rank(Square s) {
return Rank(int(s) >> 3);
}
inline Square flip_square(Square s) {
return Square(int(s) ^ FlipMask);
}
inline Square flop_square(Square s) {
return Square(int(s) ^ FlopMask);
}
inline Square relative_square(Color c, Square s) {
return Square(int(s) ^ (int(c) * FlipMask));
}
inline Rank relative_rank(Color c, Square s) {
return square_rank(relative_square(c, s));
}
inline Color square_color(Square s) {
return Color((int(square_file(s)) + int(square_rank(s))) & 1);
}
inline int file_distance(File f1, File f2) {
return abs(int(f1) - int(f2));
}
inline int file_distance(Square s1, Square s2) {
return file_distance(square_file(s1), square_file(s2));
}
inline int rank_distance(Rank r1, Rank r2) {
return abs(int(r1) - int(r2));
}
inline int rank_distance(Square s1, Square s2) {
return rank_distance(square_rank(s1), square_rank(s2));
}
inline int square_distance(Square s1, Square s2) {
return Max(file_distance(s1, s2), rank_distance(s1, s2));
}
inline File file_from_char(char c) {
return File(c - 'a') + FILE_A;
}
inline char file_to_char(File f) {
return char(f - FILE_A + int('a'));
}
inline Rank rank_from_char(char c) {
return Rank(c - '1') + RANK_1;
}
inline char rank_to_char(Rank r) {
return char(r - RANK_1 + int('1'));
}
inline Square square_from_string(const std::string& str) {
return make_square(file_from_char(str[0]), rank_from_char(str[1]));
}
inline const std::string square_to_string(Square s) {
std::string str;
str += file_to_char(square_file(s));
str += rank_to_char(square_rank(s));
return str;
}
inline bool file_is_ok(File f) {
return f >= FILE_A && f <= FILE_H;
}
inline bool rank_is_ok(Rank r) {
return r >= RANK_1 && r <= RANK_8;
}
inline bool square_is_ok(Square s) {
return file_is_ok(square_file(s)) && rank_is_ok(square_rank(s));
}
#endif // !defined(SQUARE_H_INCLUDED)
+386
View File
@@ -0,0 +1,386 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm> // For std::count
#include <cassert>
#include "movegen.h"
#include "search.h"
#include "thread.h"
#include "ucioption.h"
using namespace Search;
ThreadPool Threads; // Global object
extern void check_time();
namespace {
// start_routine() is the C function which is called when a new thread
// is launched. It is a wrapper to the virtual function idle_loop().
extern "C" { long start_routine(ThreadBase* th) { th->idle_loop(); return 0; } }
// Helpers to launch a thread after creation and joining before delete. Must be
// outside Thread c'tor and d'tor because the object will be fully initialized
// when start_routine (and hence virtual idle_loop) is called and when joining.
template<typename T> T* new_thread() {
T* th = new T();
thread_create(th->handle, start_routine, th); // Will go to sleep
return th;
}
void delete_thread(ThreadBase* th) {
th->exit = true; // Search must be already finished
th->notify_one();
thread_join(th->handle); // Wait for thread termination
delete th;
}
}
// notify_one() wakes up the thread when there is some work to do
void ThreadBase::notify_one() {
mutex.lock();
sleepCondition.notify_one();
mutex.unlock();
}
// wait_for() set the thread to sleep until condition 'b' turns true
void ThreadBase::wait_for(volatile const bool& b) {
mutex.lock();
while (!b) sleepCondition.wait(mutex);
mutex.unlock();
}
// Thread c'tor just inits data and does not launch any execution thread.
// Such a thread will only be started when c'tor returns.
Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC
searching = false;
maxPly = splitPointsSize = 0;
activeSplitPoint = NULL;
activePosition = NULL;
idx = Threads.size(); // Starts from 0
}
// cutoff_occurred() checks whether a beta cutoff has occurred in the
// current active split point, or in some ancestor of the split point.
bool Thread::cutoff_occurred() const {
for (SplitPoint* sp = activeSplitPoint; sp; sp = sp->parentSplitPoint)
if (sp->cutoff)
return true;
return false;
}
// Thread::available_to() checks whether the thread is available to help the
// thread 'master' at a split point. An obvious requirement is that thread must
// be idle. With more than two threads, this is not sufficient: If the thread is
// the master of some split point, it is only available as a slave to the slaves
// which are busy searching the split point at the top of slave's split point
// stack (the "helpful master concept" in YBWC terminology).
bool Thread::available_to(const Thread* master) const {
if (searching)
return false;
// Make a local copy to be sure it doesn't become zero under our feet while
// testing next condition and so leading to an out of bounds access.
int size = splitPointsSize;
// No split points means that the thread is available as a slave for any
// other thread otherwise apply the "helpful master" concept if possible.
return !size || splitPoints[size - 1].slavesMask.test(master->idx);
}
// TimerThread::idle_loop() is where the timer thread waits msec milliseconds
// and then calls check_time(). If msec is 0 thread sleeps until it's woken up.
void TimerThread::idle_loop() {
while (!exit)
{
mutex.lock();
if (!exit)
sleepCondition.wait_for(mutex, run ? Resolution : INT_MAX);
mutex.unlock();
if (run)
check_time();
}
}
// MainThread::idle_loop() is where the main thread is parked waiting to be started
// when there is a new search. The main thread will launch all the slave threads.
void MainThread::idle_loop() {
while (true)
{
mutex.lock();
thinking = false;
while (!thinking && !exit)
{
Threads.sleepCondition.notify_one(); // Wake up the UI thread if needed
sleepCondition.wait(mutex);
}
mutex.unlock();
if (exit)
return;
searching = true;
Search::think();
assert(searching);
searching = false;
}
}
// init() is called at startup to create and launch requested threads, that will
// go immediately to sleep. We cannot use a c'tor because Threads is a static
// object and we need a fully initialized engine at this point due to allocation
// of Endgames in Thread c'tor.
void ThreadPool::init() {
timer = new_thread<TimerThread>();
push_back(new_thread<MainThread>());
read_uci_options();
}
// exit() cleanly terminates the threads before the program exits. Cannot be done in
// d'tor because we have to terminate the threads before to free ThreadPool object.
void ThreadPool::exit() {
delete_thread(timer); // As first because check_time() accesses threads data
for (iterator it = begin(); it != end(); ++it)
delete_thread(*it);
}
// read_uci_options() updates internal threads parameters from the corresponding
// UCI options and creates/destroys threads to match the requested number. Thread
// objects are dynamically allocated to avoid creating all possible threads
// in advance (which include pawns and material tables), even if only a few
// are to be used.
void ThreadPool::read_uci_options() {
minimumSplitDepth = Options["Min Split Depth"] * ONE_PLY;
size_t requested = Options["Threads"];
assert(requested > 0);
// If zero (default) then set best minimum split depth automatically
if (!minimumSplitDepth)
minimumSplitDepth = requested < 8 ? 4 * ONE_PLY : 7 * ONE_PLY;
while (size() < requested)
push_back(new_thread<Thread>());
while (size() > requested)
{
delete_thread(back());
pop_back();
}
}
// available_slave() tries to find an idle thread which is available as a slave
// for the thread 'master'.
Thread* ThreadPool::available_slave(const Thread* master) const {
for (const_iterator it = begin(); it != end(); ++it)
if ((*it)->available_to(master))
return *it;
return NULL;
}
// split() does the actual work of distributing the work at a node between
// several available threads. If it does not succeed in splitting the node
// (because no idle threads are available), the function immediately returns.
// If splitting is possible, a SplitPoint object is initialized with all the
// data that must be copied to the helper threads and then helper threads are
// told that they have been assigned work. This will cause them to instantly
// leave their idle loops and call search(). When all threads have returned from
// search() then split() returns.
template <bool Fake>
void Thread::split(Position& pos, const Stack* ss, Value alpha, Value beta, Value* bestValue,
Move* bestMove, Depth depth, int moveCount,
MovePicker* movePicker, int nodeType, bool cutNode) {
assert(pos.pos_is_ok());
assert(-VALUE_INFINITE < *bestValue && *bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE);
assert(depth >= Threads.minimumSplitDepth);
assert(searching);
assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD);
// Pick the next available split point from the split point stack
SplitPoint& sp = splitPoints[splitPointsSize];
sp.masterThread = this;
sp.parentSplitPoint = activeSplitPoint;
sp.slavesMask = 0, sp.slavesMask.set(idx);
sp.depth = depth;
sp.bestValue = *bestValue;
sp.bestMove = *bestMove;
sp.alpha = alpha;
sp.beta = beta;
sp.nodeType = nodeType;
sp.cutNode = cutNode;
sp.movePicker = movePicker;
sp.moveCount = moveCount;
sp.pos = &pos;
sp.nodes = 0;
sp.cutoff = false;
sp.ss = ss;
// Try to allocate available threads and ask them to start searching setting
// 'searching' flag. This must be done under lock protection to avoid concurrent
// allocation of the same slave by another master.
Threads.mutex.lock();
sp.mutex.lock();
sp.allSlavesSearching = true; // Must be set under lock protection
++splitPointsSize;
activeSplitPoint = &sp;
activePosition = NULL;
if (!Fake)
for (Thread* slave; (slave = Threads.available_slave(this)) != NULL; )
{
sp.slavesMask.set(slave->idx);
slave->activeSplitPoint = &sp;
slave->searching = true; // Slave leaves idle_loop()
slave->notify_one(); // Could be sleeping
}
// Everything is set up. The master thread enters the idle loop, from which
// it will instantly launch a search, because its 'searching' flag is set.
// The thread will return from the idle loop when all slaves have finished
// their work at this split point.
sp.mutex.unlock();
Threads.mutex.unlock();
Thread::idle_loop(); // Force a call to base class idle_loop()
// In the helpful master concept, a master can help only a sub-tree of its
// split point and because everything is finished here, it's not possible
// for the master to be booked.
assert(!searching);
assert(!activePosition);
// We have returned from the idle loop, which means that all threads are
// finished. Note that setting 'searching' and decreasing splitPointsSize is
// done under lock protection to avoid a race with Thread::available_to().
Threads.mutex.lock();
sp.mutex.lock();
searching = true;
--splitPointsSize;
activeSplitPoint = sp.parentSplitPoint;
activePosition = &pos;
pos.set_nodes_searched(pos.nodes_searched() + sp.nodes);
*bestMove = sp.bestMove;
*bestValue = sp.bestValue;
sp.mutex.unlock();
Threads.mutex.unlock();
}
// Explicit template instantiations
template void Thread::split<false>(Position&, const Stack*, Value, Value, Value*, Move*, Depth, int, MovePicker*, int, bool);
template void Thread::split< true>(Position&, const Stack*, Value, Value, Value*, Move*, Depth, int, MovePicker*, int, bool);
// wait_for_think_finished() waits for main thread to go to sleep then returns
void ThreadPool::wait_for_think_finished() {
MainThread* t = main();
t->mutex.lock();
while (t->thinking) sleepCondition.wait(t->mutex);
t->mutex.unlock();
}
// start_thinking() wakes up the main thread sleeping in MainThread::idle_loop()
// so to start a new search, then returns immediately.
void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, StateStackPtr& states) {
wait_for_think_finished();
SearchTime = Time::now(); // As early as possible
Signals.stopOnPonderhit = Signals.firstRootMove = false;
Signals.stop = Signals.failedLowAtRoot = false;
RootMoves.clear();
RootPos = pos;
Limits = limits;
if (states.get()) // If we don't set a new position, preserve current state
{
SetupStates = states; // Ownership transfer here
assert(!states.get());
}
for (MoveList<LEGAL> it(pos); *it; ++it)
if ( limits.searchmoves.empty()
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), *it))
RootMoves.push_back(RootMove(*it));
main()->thinking = true;
main()->notify_one(); // Starts main thread
}
+139 -42
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,64 +17,161 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(THREAD_H_INCLUDED)
#ifndef THREAD_H_INCLUDED
#define THREAD_H_INCLUDED
#include <bitset>
#include <vector>
////
//// Includes
////
#include "lock.h"
#include "material.h"
#include "movepick.h"
#include "pawns.h"
#include "position.h"
#include "search.h"
const int MAX_THREADS = 128;
const int MAX_SPLITPOINTS_PER_THREAD = 8;
////
//// Constants and variables
////
struct Mutex {
Mutex() { lock_init(l); }
~Mutex() { lock_destroy(l); }
const int THREAD_MAX = 8;
void lock() { lock_grab(l); }
void unlock() { lock_release(l); }
private:
friend struct ConditionVariable;
////
//// Types
////
Lock l;
};
struct ConditionVariable {
ConditionVariable() { cond_init(c); }
~ConditionVariable() { cond_destroy(c); }
void wait(Mutex& m) { cond_wait(c, m.l); }
void wait_for(Mutex& m, int ms) { timed_wait(c, m.l, ms); }
void notify_one() { cond_signal(c); }
private:
WaitCondition c;
};
struct Thread;
struct SplitPoint {
SplitPoint *parent;
Position pos;
SearchStack sstack[THREAD_MAX][PLY_MAX_PLUS_2];
SearchStack *parentSstack;
int ply;
// Const data after split point has been setup
const Position* pos;
const Search::Stack* ss;
Thread* masterThread;
Depth depth;
volatile Value alpha, beta, bestValue, futilityValue;
Value approximateEval;
bool pvNode;
int master, slaves[THREAD_MAX];
Lock lock;
MovePicker *mp;
volatile int moves;
volatile int cpus;
bool finished;
Value beta;
int nodeType;
bool cutNode;
// Const pointers to shared data
MovePicker* movePicker;
SplitPoint* parentSplitPoint;
// Shared data
Mutex mutex;
std::bitset<MAX_THREADS> slavesMask;
volatile bool allSlavesSearching;
volatile uint64_t nodes;
volatile Value alpha;
volatile Value bestValue;
volatile Move bestMove;
volatile int moveCount;
volatile bool cutoff;
};
struct Thread {
SplitPoint *splitPoint;
int activeSplitPoints;
uint64_t nodes;
uint64_t betaCutOffs[2];
bool failHighPly1;
volatile bool stop;
volatile bool running;
volatile bool idle;
volatile bool workIsWaiting;
volatile bool printCurrentLine;
unsigned char pad[64]; // set some distance among local data for each thread
/// ThreadBase struct is the base of the hierarchy from where we derive all the
/// specialized thread classes.
struct ThreadBase {
ThreadBase() : handle(NativeHandle()), exit(false) {}
virtual ~ThreadBase() {}
virtual void idle_loop() = 0;
void notify_one();
void wait_for(volatile const bool& b);
Mutex mutex;
ConditionVariable sleepCondition;
NativeHandle handle;
volatile bool exit;
};
#endif // !defined(THREAD_H_INCLUDED)
/// Thread struct keeps together all the thread related stuff like locks, state
/// and especially split points. We also use per-thread pawn and material hash
/// tables so that once we get a pointer to an entry its life time is unlimited
/// and we don't have to care about someone changing the entry under our feet.
struct Thread : public ThreadBase {
Thread();
virtual void idle_loop();
bool cutoff_occurred() const;
bool available_to(const Thread* master) const;
template <bool Fake>
void split(Position& pos, const Search::Stack* ss, Value alpha, Value beta, Value* bestValue, Move* bestMove,
Depth depth, int moveCount, MovePicker* movePicker, int nodeType, bool cutNode);
SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
Material::Table materialTable;
Endgames endgames;
Pawns::Table pawnsTable;
Position* activePosition;
size_t idx;
int maxPly;
SplitPoint* volatile activeSplitPoint;
volatile int splitPointsSize;
volatile bool searching;
};
/// MainThread and TimerThread are derived classes used to characterize the two
/// special threads: the main one and the recurring timer.
struct MainThread : public Thread {
MainThread() : thinking(true) {} // Avoid a race with start_thinking()
virtual void idle_loop();
volatile bool thinking;
};
struct TimerThread : public ThreadBase {
TimerThread() : run(false) {}
virtual void idle_loop();
bool run;
static const int Resolution = 5; // msec between two check_time() calls
};
/// ThreadPool struct handles all the threads related stuff like init, starting,
/// parking and, most importantly, launching a slave thread at a split point.
/// All the access to shared thread data is done through this class.
struct ThreadPool : public std::vector<Thread*> {
void init(); // No c'tor and d'tor, threads rely on globals that should
void exit(); // be initialized and are valid during the whole thread lifetime.
MainThread* main() { return static_cast<MainThread*>((*this)[0]); }
void read_uci_options();
Thread* available_slave(const Thread* master) const;
void wait_for_think_finished();
void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
Depth minimumSplitDepth;
Mutex mutex;
ConditionVariable sleepCondition;
TimerThread* timer;
};
extern ThreadPool Threads;
#endif // #ifndef THREAD_H_INCLUDED
+126
View File
@@ -0,0 +1,126 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cfloat>
#include <cmath>
#include "search.h"
#include "timeman.h"
#include "ucioption.h"
namespace {
enum TimeType { OptimumTime, MaxTime };
const int MoveHorizon = 50; // Plan time management at most this many moves ahead
const double MaxRatio = 7.0; // When in trouble, we can step over reserved time with this ratio
const double StealRatio = 0.33; // However we must not steal time from remaining moves over this ratio
const double xscale = 9.3;
const double xshift = 59.8;
const double skewfactor = 0.172;
// move_importance() is a skew-logistic function based on naive statistical
// analysis of "how many games are still undecided after n half-moves". Game
// is considered "undecided" as long as neither side has >275cp advantage.
// Data was extracted from CCRL game database with some simple filtering criteria.
double move_importance(int ply) {
return pow((1 + exp((ply - xshift) / xscale)), -skewfactor) + DBL_MIN; // Ensure non-zero
}
template<TimeType T>
int remaining(int myTime, int movesToGo, int currentPly, int slowMover)
{
const double TMaxRatio = (T == OptimumTime ? 1 : MaxRatio);
const double TStealRatio = (T == OptimumTime ? 0 : StealRatio);
double thisMoveImportance = (move_importance(currentPly) * slowMover) / 100;
double otherMovesImportance = 0;
for (int i = 1; i < movesToGo; ++i)
otherMovesImportance += move_importance(currentPly + 2 * i);
double ratio1 = (TMaxRatio * thisMoveImportance) / (TMaxRatio * thisMoveImportance + otherMovesImportance);
double ratio2 = (thisMoveImportance + TStealRatio * otherMovesImportance) / (thisMoveImportance + otherMovesImportance);
return int(myTime * std::min(ratio1, ratio2));
}
} // namespace
void TimeManager::init(const Search::LimitsType& limits, int currentPly, Color us)
{
/* We support four different kinds of time controls:
increment == 0 && movesToGo == 0 means: x basetime [sudden death!]
increment == 0 && movesToGo != 0 means: x moves in y minutes
increment > 0 && movesToGo == 0 means: x basetime + z increment
increment > 0 && movesToGo != 0 means: x moves in y minutes + z increment
Time management is adjusted by following UCI parameters:
emergencyMoveHorizon: Be prepared to always play at least this many moves
emergencyBaseTime : Always attempt to keep at least this much time (in ms) at clock
emergencyMoveTime : Plus attempt to keep at least this much time for each remaining emergency move
minThinkingTime : No matter what, use at least this much thinking before doing the move
*/
int hypMTG, hypMyTime, t1, t2;
// Read uci parameters
int emergencyMoveHorizon = Options["Emergency Move Horizon"];
int emergencyBaseTime = Options["Emergency Base Time"];
int emergencyMoveTime = Options["Emergency Move Time"];
int minThinkingTime = Options["Minimum Thinking Time"];
int slowMover = Options["Slow Mover"];
// Initialize unstablePvFactor to 1 and search times to maximum values
unstablePvFactor = 1;
optimumSearchTime = maximumSearchTime = std::max(limits.time[us], minThinkingTime);
// We calculate optimum time usage for different hypothetical "moves to go"-values and choose the
// minimum of calculated search time values. Usually the greatest hypMTG gives the minimum values.
for (hypMTG = 1; hypMTG <= (limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon); ++hypMTG)
{
// Calculate thinking time for hypothetical "moves to go"-value
hypMyTime = limits.time[us]
+ limits.inc[us] * (hypMTG - 1)
- emergencyBaseTime
- emergencyMoveTime * std::min(hypMTG, emergencyMoveHorizon);
hypMyTime = std::max(hypMyTime, 0);
t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, currentPly, slowMover);
t2 = minThinkingTime + remaining<MaxTime>(hypMyTime, hypMTG, currentPly, slowMover);
optimumSearchTime = std::min(optimumSearchTime, t1);
maximumSearchTime = std::min(maximumSearchTime, t2);
}
if (Options["Ponder"])
optimumSearchTime += optimumSearchTime / 4;
// Make sure that maxSearchTime is not over absoluteMaxSearchTime
optimumSearchTime = std::min(optimumSearchTime, maximumSearchTime);
}
+16 -16
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,23 +17,23 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
#if !defined(APPLICATION_H_INCLUDED)
#define APPLICATION_H_INCLUDED
/// Singleton class used to housekeep memory and global resources
/// so to be sure we always leave in a clean state.
class Application {
Application();
Application(const Application&);
~Application();
/// The TimeManager class computes the optimal time to think depending on the
/// maximum available time, the game move number and other parameters.
class TimeManager {
public:
static void initialize();
static void exit_with_failure();
void init(const Search::LimitsType& limits, int currentPly, Color us);
void pv_instability(double bestMoveChanges) { unstablePvFactor = 1 + bestMoveChanges; }
int available_time() const { return int(optimumSearchTime * unstablePvFactor * 0.71); }
int maximum_time() const { return maximumSearchTime; }
private:
int optimumSearchTime;
int maximumSearchTime;
double unstablePvFactor;
};
#endif // !defined(APPLICATION_H_INCLUDED)
#endif // #ifndef TIMEMAN_H_INCLUDED
+62 -199
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,242 +17,105 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include <cmath>
#include <cstring>
#include <xmmintrin.h>
#include <iostream>
#include "movegen.h"
#include "bitboard.h"
#include "tt.h"
// The main transposition table
TranspositionTable TT;
////
//// Functions
////
TranspositionTable::TranspositionTable() {
size = writes = 0;
entries = 0;
generation = 0;
}
TranspositionTable::~TranspositionTable() {
delete [] entries;
}
TranspositionTable TT; // Our global transposition table
/// TranspositionTable::set_size sets the size of the transposition table,
/// measured in megabytes.
/// TranspositionTable::resize() sets the size of the transposition table,
/// measured in megabytes. Transposition table consists of a power of 2 number
/// of clusters and each cluster consists of ClusterSize number of TTEntry.
void TranspositionTable::set_size(unsigned mbSize) {
void TranspositionTable::resize(uint64_t mbSize) {
assert(mbSize >= 4 && mbSize <= 2048);
assert(msb((mbSize << 20) / sizeof(TTEntry)) < 32);
unsigned newSize = 1024;
uint32_t size = ClusterSize << msb((mbSize << 20) / sizeof(TTEntry[ClusterSize]));
// We store a cluster of ClusterSize number of TTEntry for each position
// and newSize is the maximum number of storable positions.
while ((2 * newSize) * sizeof(TTCluster) <= (mbSize << 20))
newSize *= 2;
if (hashMask == size - ClusterSize)
return;
if (newSize != size)
hashMask = size - ClusterSize;
free(mem);
mem = calloc(size * sizeof(TTEntry) + CACHE_LINE_SIZE - 1, 1);
if (!mem)
{
size = newSize;
delete [] entries;
entries = new TTCluster[size];
if (!entries)
{
std::cerr << "Failed to allocate " << mbSize
<< " MB for transposition table." << std::endl;
Application::exit_with_failure();
}
clear();
std::cerr << "Failed to allocate " << mbSize
<< "MB for transposition table." << std::endl;
exit(EXIT_FAILURE);
}
table = (TTEntry*)((uintptr_t(mem) + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1));
}
/// TranspositionTable::clear overwrites the entire transposition table
/// TranspositionTable::clear() overwrites the entire transposition table
/// with zeroes. It is called whenever the table is resized, or when the
/// user asks the program to clear the table (from the UCI interface).
/// Perhaps we should also clear it when the "ucinewgame" command is recieved?
void TranspositionTable::clear() {
memset(entries, 0, size * sizeof(TTCluster));
std::memset(table, 0, (hashMask + ClusterSize) * sizeof(TTEntry));
}
/// TranspositionTable::first_entry returns a pointer to the first
/// entry of a cluster given a position. The low 32 bits of the key
/// are used to get the index in the table.
/// TranspositionTable::probe() looks up the current position in the
/// transposition table. Returns a pointer to the TTEntry or NULL if
/// position is not found.
inline TTEntry* TranspositionTable::first_entry(const Key posKey) const {
const TTEntry* TranspositionTable::probe(const Key key) const {
return entries[uint32_t(posKey) & (size - 1)].data;
}
TTEntry* tte = first_entry(key);
uint32_t key32 = key >> 32;
/// TranspositionTable::store writes a new entry containing a position,
/// a value, a value type, a search depth, and a best move to the
/// transposition table. Transposition table is organized in clusters of
/// four TTEntry objects, and when a new entry is written, it replaces
/// the least valuable of the four entries in a cluster. A TTEntry t1 is
/// considered to be more valuable than a TTEntry t2 if t1 is from the
/// current search and t2 is from a previous search, or if the depth of t1
/// is bigger than the depth of t2. A TTEntry of type VALUE_TYPE_EVAL
/// never replaces another entry for the same position.
void TranspositionTable::store(const Key posKey, Value v, ValueType t, Depth d, Move m) {
TTEntry *tte, *replace;
uint32_t posKey32 = posKey >> 32; // Use the high 32 bits as key
tte = replace = first_entry(posKey);
for (int i = 0; i < ClusterSize; i++, tte++)
{
if (!tte->key() || tte->key() == posKey32) // empty or overwrite old
for (unsigned i = 0; i < ClusterSize; ++i, ++tte)
if (tte->key32 == key32)
{
// Do not overwrite when new type is VALUE_TYPE_EV_LO
if (tte->key() && t == VALUE_TYPE_EV_LO)
return;
if (m == MOVE_NONE)
m = tte->move();
*tte = TTEntry(posKey32, v, t, d, m, generation);
return;
}
else if (i == 0) // replace would be a no-op in this common case
continue;
int c1 = (replace->generation() == generation ? 2 : 0);
int c2 = (tte->generation() == generation ? -2 : 0);
int c3 = (tte->depth() < replace->depth() ? 1 : 0);
if (c1 + c2 + c3 > 0)
replace = tte;
}
*replace = TTEntry(posKey32, v, t, d, m, generation);
writes++;
}
/// TranspositionTable::retrieve looks up the current position in the
/// transposition table. Returns a pointer to the TTEntry or NULL
/// if position is not found.
TTEntry* TranspositionTable::retrieve(const Key posKey) const {
uint32_t posKey32 = posKey >> 32;
TTEntry* tte = first_entry(posKey);
for (int i = 0; i < ClusterSize; i++, tte++)
if (tte->key() == posKey32)
tte->generation8 = generation; // Refresh
return tte;
}
return NULL;
}
/// TranspositionTable::prefetch looks up the current position in the
/// transposition table and load it in L1/L2 cache. This is a non
/// blocking function and do not stalls the CPU waiting for data
/// to be loaded from RAM, that can be very slow. When we will
/// subsequently call retrieve() the TT data will be already
/// quickly accessible in L1/L2 CPU cache.
/// TranspositionTable::store() writes a new entry containing position key and
/// valuable information of current position. The lowest order bits of position
/// key are used to decide in which cluster the position will be placed.
/// When a new entry is written and there are no empty entries available in the
/// cluster, it replaces the least valuable of the entries. A TTEntry t1 is considered
/// to be more valuable than a TTEntry t2 if t1 is from the current search and t2
/// is from a previous search, or if the depth of t1 is bigger than the depth of t2.
void TranspositionTable::prefetch(const Key posKey) const {
void TranspositionTable::store(const Key key, Value v, Bound b, Depth d, Move m, Value statV) {
#if defined(__INTEL_COMPILER) || defined(__ICL)
// This hack prevents prefetches to be optimized away by the
// Intel compiler. Both MSVC and gcc seems not affected.
__asm__ ("");
#endif
TTEntry *tte, *replace;
uint32_t key32 = key >> 32; // Use the high 32 bits as key inside the cluster
char const* addr = (char*)first_entry(posKey);
_mm_prefetch(addr, _MM_HINT_T2);
_mm_prefetch(addr+64, _MM_HINT_T2); // 64 bytes ahead
}
tte = replace = first_entry(key);
/// TranspositionTable::new_search() is called at the beginning of every new
/// search. It increments the "generation" variable, which is used to
/// distinguish transposition table entries from previous searches from
/// entries from the current search.
void TranspositionTable::new_search() {
generation++;
writes = 0;
}
/// TranspositionTable::insert_pv() is called at the end of a search
/// iteration, and inserts the PV back into the PV. This makes sure
/// the old PV moves are searched first, even if the old TT entries
/// have been overwritten.
void TranspositionTable::insert_pv(const Position& pos, Move pv[]) {
StateInfo st;
Position p(pos);
for (int i = 0; pv[i] != MOVE_NONE; i++)
for (unsigned i = 0; i < ClusterSize; ++i, ++tte)
{
TTEntry *tte = retrieve(p.get_key());
if (!tte || tte->move() != pv[i])
store(p.get_key(), VALUE_NONE, VALUE_TYPE_NONE, Depth(-127*OnePly), pv[i]);
p.do_move(pv[i], st);
if (!tte->key32 || tte->key32 == key32) // Empty or overwrite old
{
if (!m)
m = tte->move(); // Preserve any existing ttMove
replace = tte;
break;
}
// Implement replace strategy
if ( ( tte->generation8 == generation || tte->bound() == BOUND_EXACT)
- (replace->generation8 == generation)
- (tte->depth16 < replace->depth16) < 0)
replace = tte;
}
}
/// TranspositionTable::extract_pv() extends a PV by adding moves from the
/// transposition table at the end. This should ensure that the PV is almost
/// always at least two plies long, which is important, because otherwise we
/// will often get single-move PVs when the search stops while failing high,
/// and a single-move PV means that we don't have a ponder move.
void TranspositionTable::extract_pv(const Position& pos, Move pv[], const int PLY_MAX) {
const TTEntry* tte;
StateInfo st;
Position p(pos);
int ply = 0;
// Update position to the end of current PV
while (pv[ply] != MOVE_NONE)
p.do_move(pv[ply++], st);
// Try to add moves from TT while possible
while ( (tte = retrieve(p.get_key())) != NULL
&& tte->move() != MOVE_NONE
&& move_is_legal(p, tte->move())
&& (!p.is_draw() || ply < 2)
&& ply < PLY_MAX)
{
pv[ply] = tte->move();
p.do_move(pv[ply++], st);
}
pv[ply] = MOVE_NONE;
}
/// TranspositionTable::full() returns the permill of all transposition table
/// entries which have received at least one write during the current search.
/// It is used to display the "info hashfull ..." information in UCI.
int TranspositionTable::full() const {
double N = double(size) * ClusterSize;
return int(1000 * (1 - exp(writes * log(1.0 - 1.0/N))));
replace->save(key32, v, b, d, m, generation, statV);
}
+64 -84
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,108 +17,88 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(TT_H_INCLUDED)
#ifndef TT_H_INCLUDED
#define TT_H_INCLUDED
////
//// Includes
////
#include "misc.h"
#include "types.h"
#include "depth.h"
#include "position.h"
#include "value.h"
////
//// Types
////
/// The TTEntry class is the class of transposition table entries
/// The TTEntry is the 14 bytes transposition table entry, defined as below:
///
/// A TTEntry needs 96 bits to be stored
///
/// bit 0-31: key
/// bit 32-63: data
/// bit 64-79: value
/// bit 80-95: depth
///
/// the 32 bits of the data field are so defined
///
/// bit 0-16: move
/// bit 17-19: not used
/// bit 20-22: value type
/// bit 23-31: generation
/// key 32 bit
/// move 16 bit
/// bound type 8 bit
/// generation 8 bit
/// value 16 bit
/// depth 16 bit
/// eval value 16 bit
class TTEntry {
struct TTEntry {
public:
TTEntry() {}
TTEntry(uint32_t k, Value v, ValueType t, Depth d, Move m, int generation)
: key_ (k), data((m & 0x1FFFF) | (t << 20) | (generation << 23)),
value_(int16_t(v)), depth_(int16_t(d)) {}
uint32_t key() const { return key_; }
Depth depth() const { return Depth(depth_); }
Move move() const { return Move(data & 0x1FFFF); }
Value value() const { return Value(value_); }
ValueType type() const { return ValueType((data >> 20) & 7); }
int generation() const { return (data >> 23); }
Move move() const { return (Move )move16; }
Bound bound() const { return (Bound)bound8; }
Value value() const { return (Value)value16; }
Depth depth() const { return (Depth)depth16; }
Value eval_value() const { return (Value)evalValue; }
private:
uint32_t key_;
uint32_t data;
int16_t value_;
int16_t depth_;
friend class TranspositionTable;
void save(uint32_t k, Value v, Bound b, Depth d, Move m, uint8_t g, Value ev) {
key32 = (uint32_t)k;
move16 = (uint16_t)m;
bound8 = (uint8_t)b;
generation8 = (uint8_t)g;
value16 = (int16_t)v;
depth16 = (int16_t)d;
evalValue = (int16_t)ev;
}
uint32_t key32;
uint16_t move16;
uint8_t bound8, generation8;
int16_t value16, depth16, evalValue;
};
/// This is the number of TTEntry slots for each position
const int ClusterSize = 5;
/// Each group of ClusterSize number of TTEntry form a TTCluster
/// that is indexed by a single position key. Cluster is padded
/// to a cache line size so to guarantee always aligned accesses.
struct TTCluster {
TTEntry data[ClusterSize];
char cache_line_padding[64 - sizeof(TTEntry[ClusterSize])];
};
/// The transposition table class. This is basically just a huge array
/// containing TTEntry objects, and a few methods for writing new entries
/// and reading new ones.
/// A TranspositionTable consists of a power of 2 number of clusters and each
/// cluster consists of ClusterSize number of TTEntry. Each non-empty entry
/// contains information of exactly one position. The size of a cluster should
/// not be bigger than a cache line size. In case it is less, it should be padded
/// to guarantee always aligned accesses.
class TranspositionTable {
static const unsigned ClusterSize = 4;
public:
TranspositionTable();
~TranspositionTable();
void set_size(unsigned mbSize);
~TranspositionTable() { free(mem); }
void new_search() { ++generation; }
const TTEntry* probe(const Key key) const;
TTEntry* first_entry(const Key key) const;
void resize(uint64_t mbSize);
void clear();
void store(const Key posKey, Value v, ValueType type, Depth d, Move m);
TTEntry* retrieve(const Key posKey) const;
void prefetch(const Key posKey) const;
void new_search();
void insert_pv(const Position& pos, Move pv[]);
void extract_pv(const Position& pos, Move pv[], const int PLY_MAX);
int full() const;
void store(const Key key, Value v, Bound type, Depth d, Move m, Value statV);
private:
inline TTEntry* first_entry(const Key posKey) const;
// Be sure 'writes' is at least one cache line away
// from read only variables.
unsigned char pad_before[64 - sizeof(unsigned)];
unsigned writes; // heavy SMP read/write access here
unsigned char pad_after[64];
unsigned size;
TTCluster* entries;
uint8_t generation;
uint32_t hashMask;
TTEntry* table;
void* mem;
uint8_t generation; // Size must be not bigger than TTEntry::generation8
};
extern TranspositionTable TT;
#endif // !defined(TT_H_INCLUDED)
/// TranspositionTable::first_entry() returns a pointer to the first entry of
/// a cluster given a position. The lowest order bits of the key are used to
/// get the index of the cluster.
inline TTEntry* TranspositionTable::first_entry(const Key key) const {
return table + ((uint32_t)key & hashMask);
}
#endif // #ifndef TT_H_INCLUDED
+429 -40
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,60 +17,449 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(TYPES_H_INCLUDED)
#ifndef TYPES_H_INCLUDED
#define TYPES_H_INCLUDED
#if !defined(_MSC_VER)
/// For Linux and OSX configuration is done automatically using Makefile. To get
/// started type 'make help'.
///
/// For Windows, part of the configuration is detected automatically, but some
/// switches need to be set manually:
///
/// -DNDEBUG | Disable debugging mode. Always use this.
///
/// -DNO_PREFETCH | Disable use of prefetch asm-instruction. A must if you want
/// | the executable to run on some very old machines.
///
/// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works
/// | only in 64-bit mode. For compiling requires hardware with
/// | popcnt support.
#include <inttypes.h>
#include <cassert>
#include <cctype>
#include <climits>
#include <cstdlib>
#include "platform.h"
#define unlikely(x) (x) // For code annotation purposes
#if defined(_WIN64) && !defined(IS_64BIT)
# include <intrin.h> // MSVC popcnt and bsfq instrinsics
# define IS_64BIT
# define USE_BSFQ
#endif
#if defined(USE_POPCNT) && defined(_MSC_VER) && defined(__INTEL_COMPILER)
# include <nmmintrin.h> // Intel header for _mm_popcnt_u64() intrinsic
#endif
#if defined(USE_PEXT)
# include <immintrin.h> // Header for _pext_u64() intrinsic
#else
# define _pext_u64(b, m) (0)
#endif
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
# if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER))
# include <xmmintrin.h> // Intel and Microsoft header for _mm_prefetch()
# endif
typedef __int16 int16_t;
typedef __int64 int64_t;
#define CACHE_LINE_SIZE 64
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
# define CACHE_LINE_ALIGNMENT __declspec(align(CACHE_LINE_SIZE))
#else
# define CACHE_LINE_ALIGNMENT __attribute__ ((aligned(CACHE_LINE_SIZE)))
#endif
#endif // !defined(_MSC_VER)
#ifdef _MSC_VER
# define FORCE_INLINE __forceinline
#elif defined(__GNUC__)
# define FORCE_INLINE inline __attribute__((always_inline))
#else
# define FORCE_INLINE inline
#endif
#ifdef USE_POPCNT
const bool HasPopCnt = true;
#else
const bool HasPopCnt = false;
#endif
#ifdef USE_PEXT
const bool HasPext = true;
#else
const bool HasPext = false;
#endif
#ifdef IS_64BIT
const bool Is64Bit = true;
#else
const bool Is64Bit = false;
#endif
// Hash keys
typedef uint64_t Key;
// Bitboard type
typedef uint64_t Bitboard;
const int MAX_MOVES = 256;
const int MAX_PLY = 120;
const int MAX_PLY_PLUS_6 = MAX_PLY + 6;
////
//// Compiler specific defines
////
/// A move needs 16 bits to be stored
///
/// bit 0- 5: destination square (from 0 to 63)
/// bit 6-11: origin square (from 0 to 63)
/// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2)
/// bit 14-15: special move flag: promotion (1), en passant (2), castling (3)
/// NOTE: EN-PASSANT bit is set only when a pawn can be captured
///
/// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in because in
/// any normal move destination square is always different from origin square
/// while MOVE_NONE and MOVE_NULL have the same origin and destination square.
// Quiet a warning on Intel compiler
#if !defined(__SIZEOF_INT__ )
#define __SIZEOF_INT__ 0
#endif
enum Move {
MOVE_NONE,
MOVE_NULL = 65
};
// Check for 64 bits for different compilers: Intel, MSVC and gcc
#if defined(__x86_64) || defined(_M_X64) || defined(_WIN64) || (__SIZEOF_INT__ > 4)
#define IS_64BIT
#endif
enum MoveType {
NORMAL,
PROMOTION = 1 << 14,
ENPASSANT = 2 << 14,
CASTLING = 3 << 14
};
#if defined(IS_64BIT) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
#define USE_BSFQ
#endif
enum Color {
WHITE, BLACK, NO_COLOR, COLOR_NB = 2
};
// Cache line alignment specification
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define CACHE_LINE_ALIGNMENT __declspec(align(64))
#else
#define CACHE_LINE_ALIGNMENT __attribute__ ((aligned(64)))
#endif
enum CastlingSide {
KING_SIDE, QUEEN_SIDE, CASTLING_SIDE_NB = 2
};
#endif // !defined(TYPES_H_INCLUDED)
enum CastlingRight { // Defined as in PolyGlot book hash key
NO_CASTLING,
WHITE_OO,
WHITE_OOO = WHITE_OO << 1,
BLACK_OO = WHITE_OO << 2,
BLACK_OOO = WHITE_OO << 3,
ANY_CASTLING = WHITE_OO | WHITE_OOO | BLACK_OO | BLACK_OOO,
CASTLING_RIGHT_NB = 16
};
template<Color C, CastlingSide S> struct MakeCastling {
static const CastlingRight
right = C == WHITE ? S == QUEEN_SIDE ? WHITE_OOO : WHITE_OO
: S == QUEEN_SIDE ? BLACK_OOO : BLACK_OO;
};
enum Phase {
PHASE_ENDGAME,
PHASE_MIDGAME = 128,
MG = 0, EG = 1, PHASE_NB = 2
};
enum ScaleFactor {
SCALE_FACTOR_DRAW = 0,
SCALE_FACTOR_ONEPAWN = 48,
SCALE_FACTOR_NORMAL = 64,
SCALE_FACTOR_MAX = 128,
SCALE_FACTOR_NONE = 255
};
enum Bound {
BOUND_NONE,
BOUND_UPPER,
BOUND_LOWER,
BOUND_EXACT = BOUND_UPPER | BOUND_LOWER
};
enum Value {
VALUE_ZERO = 0,
VALUE_DRAW = 0,
VALUE_KNOWN_WIN = 10000,
VALUE_MATE = 32000,
VALUE_INFINITE = 32001,
VALUE_NONE = 32002,
VALUE_MATE_IN_MAX_PLY = VALUE_MATE - MAX_PLY,
VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + MAX_PLY,
VALUE_ENSURE_INTEGER_SIZE_P = INT_MAX,
VALUE_ENSURE_INTEGER_SIZE_N = INT_MIN,
PawnValueMg = 198, PawnValueEg = 258,
KnightValueMg = 817, KnightValueEg = 846,
BishopValueMg = 836, BishopValueEg = 857,
RookValueMg = 1270, RookValueEg = 1278,
QueenValueMg = 2521, QueenValueEg = 2558,
MidgameLimit = 15581, EndgameLimit = 3998
};
enum PieceType {
NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
ALL_PIECES = 0,
PIECE_TYPE_NB = 8
};
enum Piece {
NO_PIECE,
W_PAWN = 1, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN = 9, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
PIECE_NB = 16
};
enum Depth {
ONE_PLY = 2,
DEPTH_ZERO = 0 * ONE_PLY,
DEPTH_QS_CHECKS = 0 * ONE_PLY,
DEPTH_QS_NO_CHECKS = -1 * ONE_PLY,
DEPTH_QS_RECAPTURES = -5 * ONE_PLY,
DEPTH_NONE = -127 * ONE_PLY
};
enum Square {
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4,
SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5,
SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6,
SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7,
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE,
SQUARE_NB = 64,
DELTA_N = 8,
DELTA_E = 1,
DELTA_S = -8,
DELTA_W = -1,
DELTA_NN = DELTA_N + DELTA_N,
DELTA_NE = DELTA_N + DELTA_E,
DELTA_SE = DELTA_S + DELTA_E,
DELTA_SS = DELTA_S + DELTA_S,
DELTA_SW = DELTA_S + DELTA_W,
DELTA_NW = DELTA_N + DELTA_W
};
enum File {
FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NB
};
enum Rank {
RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB
};
/// The Score enum stores a middlegame and an endgame value in a single integer
/// (enum). The least significant 16 bits are used to store the endgame value
/// and the upper 16 bits are used to store the middlegame value. The compiler
/// is free to choose the enum type as long as it can store the data, so we
/// ensure that Score is an integer type by assigning some big int values.
enum Score {
SCORE_ZERO,
SCORE_ENSURE_INTEGER_SIZE_P = INT_MAX,
SCORE_ENSURE_INTEGER_SIZE_N = INT_MIN
};
typedef union {
uint32_t full;
struct { int16_t eg, mg; } half;
} ScoreView;
inline Score make_score(int mg, int eg) {
ScoreView v;
v.half.mg = (int16_t)(mg - (uint16_t(eg) >> 15));
v.half.eg = (int16_t)eg;
return Score(v.full);
}
inline Value mg_value(Score s) {
ScoreView v;
v.full = s;
return Value(v.half.mg + (uint16_t(v.half.eg) >> 15));
}
inline Value eg_value(Score s) {
ScoreView v;
v.full = s;
return Value(v.half.eg);
}
#define ENABLE_BASE_OPERATORS_ON(T) \
inline T operator+(const T d1, const T d2) { return T(int(d1) + int(d2)); } \
inline T operator-(const T d1, const T d2) { return T(int(d1) - int(d2)); } \
inline T operator*(int i, const T d) { return T(i * int(d)); } \
inline T operator*(const T d, int i) { return T(int(d) * i); } \
inline T operator-(const T d) { return T(-int(d)); } \
inline T& operator+=(T& d1, const T d2) { return d1 = d1 + d2; } \
inline T& operator-=(T& d1, const T d2) { return d1 = d1 - d2; } \
inline T& operator*=(T& d, int i) { return d = T(int(d) * i); }
ENABLE_BASE_OPERATORS_ON(Score)
#define ENABLE_FULL_OPERATORS_ON(T) \
ENABLE_BASE_OPERATORS_ON(T) \
inline T& operator++(T& d) { return d = T(int(d) + 1); } \
inline T& operator--(T& d) { return d = T(int(d) - 1); } \
inline T operator/(const T d, int i) { return T(int(d) / i); } \
inline T& operator/=(T& d, int i) { return d = T(int(d) / i); }
ENABLE_FULL_OPERATORS_ON(Value)
ENABLE_FULL_OPERATORS_ON(PieceType)
ENABLE_FULL_OPERATORS_ON(Piece)
ENABLE_FULL_OPERATORS_ON(Color)
ENABLE_FULL_OPERATORS_ON(Depth)
ENABLE_FULL_OPERATORS_ON(Square)
ENABLE_FULL_OPERATORS_ON(File)
ENABLE_FULL_OPERATORS_ON(Rank)
#undef ENABLE_FULL_OPERATORS_ON
#undef ENABLE_BASE_OPERATORS_ON
/// Additional operators to add integers to a Value
inline Value operator+(Value v, int i) { return Value(int(v) + i); }
inline Value operator-(Value v, int i) { return Value(int(v) - i); }
inline Value& operator+=(Value& v, int i) { return v = v + i; }
inline Value& operator-=(Value& v, int i) { return v = v - i; }
/// Only declared but not defined. We don't want to multiply two scores due to
/// a very high risk of overflow. So user should explicitly convert to integer.
inline Score operator*(Score s1, Score s2);
/// Division of a Score must be handled separately for each term
inline Score operator/(Score s, int i) {
return make_score(mg_value(s) / i, eg_value(s) / i);
}
extern Value PieceValue[PHASE_NB][PIECE_NB];
struct ExtMove {
Move move;
Value value;
};
inline bool operator<(const ExtMove& f, const ExtMove& s) {
return f.value < s.value;
}
inline Color operator~(Color c) {
return Color(c ^ BLACK);
}
inline Square operator~(Square s) {
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
}
inline CastlingRight operator|(Color c, CastlingSide s) {
return CastlingRight(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c));
}
inline Value mate_in(int ply) {
return VALUE_MATE - ply;
}
inline Value mated_in(int ply) {
return -VALUE_MATE + ply;
}
inline Square make_square(File f, Rank r) {
return Square((r << 3) | f);
}
inline Piece make_piece(Color c, PieceType pt) {
return Piece((c << 3) | pt);
}
inline PieceType type_of(Piece pc) {
return PieceType(pc & 7);
}
inline Color color_of(Piece pc) {
assert(pc != NO_PIECE);
return Color(pc >> 3);
}
inline bool is_ok(Square s) {
return s >= SQ_A1 && s <= SQ_H8;
}
inline File file_of(Square s) {
return File(s & 7);
}
inline Rank rank_of(Square s) {
return Rank(s >> 3);
}
inline Square relative_square(Color c, Square s) {
return Square(s ^ (c * 56));
}
inline Rank relative_rank(Color c, Rank r) {
return Rank(r ^ (c * 7));
}
inline Rank relative_rank(Color c, Square s) {
return relative_rank(c, rank_of(s));
}
inline bool opposite_colors(Square s1, Square s2) {
int s = int(s1) ^ int(s2);
return ((s >> 3) ^ s) & 1;
}
inline char to_char(File f, bool tolower = true) {
return char(f - FILE_A + (tolower ? 'a' : 'A'));
}
inline char to_char(Rank r) {
return char(r - RANK_1 + '1');
}
inline Square pawn_push(Color c) {
return c == WHITE ? DELTA_N : DELTA_S;
}
inline Square from_sq(Move m) {
return Square((m >> 6) & 0x3F);
}
inline Square to_sq(Move m) {
return Square(m & 0x3F);
}
inline MoveType type_of(Move m) {
return MoveType(m & (3 << 14));
}
inline PieceType promotion_type(Move m) {
return PieceType(((m >> 12) & 3) + 2);
}
inline Move make_move(Square from, Square to) {
return Move(to | (from << 6));
}
template<MoveType T>
inline Move make(Square from, Square to, PieceType pt = KNIGHT) {
return Move(to | (from << 6) | T | ((pt - KNIGHT) << 12));
}
inline bool is_ok(Move m) {
return from_sq(m) != to_sq(m); // Catches also MOVE_NULL and MOVE_NONE
}
#include <string>
inline const std::string to_string(Square s) {
char ch[] = { to_char(file_of(s)), to_char(rank_of(s)), 0 };
return ch;
}
#endif // #ifndef TYPES_H_INCLUDED
+173 -297
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,327 +17,203 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <cassert>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include "book.h"
#include "evaluate.h"
#include "misc.h"
#include "move.h"
#include "movegen.h"
#include "notation.h"
#include "position.h"
#include "san.h"
#include "search.h"
#include "uci.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
using namespace std;
////
//// Local definitions:
////
extern void benchmark(const Position& pos, istream& is);
namespace {
// UCIInputParser is a class for parsing UCI input. The class
// is actually a string stream built on a given input string.
// FEN string of the initial position, normal chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
typedef istringstream UCIInputParser;
// The root position. This is set up when the user (or in practice, the GUI)
// sends the "position" UCI command. The root position is sent to the think()
// function when the program receives the "go" command.
Position RootPosition;
// Local functions
bool handle_command(const string& command);
void set_option(UCIInputParser& uip);
void set_position(UCIInputParser& uip);
bool go(UCIInputParser& uip);
void perft(UCIInputParser& uip);
}
// Keep a track of the position keys along the setup moves (from the start position
// to the position just before the search starts). This is needed by the repetition
// draw detection code.
Search::StateStackPtr SetupStates;
////
//// Functions
////
// position() is called when engine receives the "position" UCI command.
// The function sets up the position described in the given FEN string ("fen")
// or the starting position ("startpos") and then makes the moves given in the
// following move list ("moves").
/// uci_main_loop() is the only global function in this file. It is
/// called immediately after the program has finished initializing.
/// The program remains in this loop until it receives the "quit" UCI
/// command. It waits for a command from the user, and passes this
/// command to handle_command and also intercepts EOF from stdin,
/// by translating EOF to the "quit" command. This ensures that Stockfish
/// exits gracefully if the GUI dies unexpectedly.
void position(Position& pos, istringstream& is) {
void uci_main_loop() {
Move m;
string token, fen;
RootPosition.from_fen(StartPosition);
string command;
do {
// Wait for a command from stdin
if (!getline(cin, command))
command = "quit";
} while (handle_command(command));
}
////
//// Local functions
////
namespace {
// handle_command() takes a text string as input, uses a
// UCIInputParser object to parse this text string as a UCI command,
// and calls the appropriate functions. In addition to the UCI
// commands, the function also supports a few debug commands.
bool handle_command(const string& command) {
UCIInputParser uip(command);
string token;
uip >> token; // operator>>() skips any whitespace
if (token == "quit")
return false;
if (token == "go")
return go(uip);
if (token == "uci")
{
cout << "id name " << engine_name()
<< "\nid author Tord Romstad, Marco Costalba, Joona Kiiski\n";
print_uci_options();
cout << "uciok" << endl;
}
else if (token == "ucinewgame")
{
push_button("New Game");
Position::init_piece_square_tables();
RootPosition.from_fen(StartPosition);
}
else if (token == "isready")
cout << "readyok" << endl;
else if (token == "position")
set_position(uip);
else if (token == "setoption")
set_option(uip);
// The remaining commands are for debugging purposes only.
// Perhaps they should be removed later in order to reduce the
// size of the program binary.
else if (token == "d")
RootPosition.print();
else if (token == "flip")
{
Position p(RootPosition);
RootPosition.flipped_copy(p);
}
else if (token == "eval")
{
EvalInfo ei;
cout << "Incremental mg: " << mg_value(RootPosition.value())
<< "\nIncremental eg: " << eg_value(RootPosition.value())
<< "\nFull eval: " << evaluate(RootPosition, ei, 0) << endl;
}
else if (token == "key")
cout << "key: " << hex << RootPosition.get_key()
<< "\nmaterial key: " << RootPosition.get_material_key()
<< "\npawn key: " << RootPosition.get_pawn_key() << endl;
else if (token == "perft")
perft(uip);
else
{
cout << "Unknown command: " << command << endl;
while (!uip.eof())
{
uip >> token;
cout << token << endl;
}
}
return true;
}
// set_position() is called when Stockfish receives the "position" UCI
// command. The input parameter is a UCIInputParser. It is assumed
// that this parser has consumed the first token of the UCI command
// ("position"), and is ready to read the second token ("startpos"
// or "fen", if the input is well-formed).
void set_position(UCIInputParser& uip) {
string token;
uip >> token; // operator>>() skips any whitespace
is >> token;
if (token == "startpos")
RootPosition.from_fen(StartPosition);
{
fen = StartFEN;
is >> token; // Consume "moves" token if any
}
else if (token == "fen")
{
string fen;
while (token != "moves" && !uip.eof())
{
uip >> token;
fen += token;
fen += ' ';
}
RootPosition.from_fen(fen);
}
if (!uip.eof())
{
if (token != "moves")
uip >> token;
if (token == "moves")
{
Move move;
StateInfo st;
while (!uip.eof())
{
uip >> token;
move = move_from_string(RootPosition, token);
RootPosition.do_move(move, st);
if (RootPosition.rule_50_counter() == 0)
RootPosition.reset_game_ply();
}
// Our StateInfo st is about going out of scope so copy
// its content inside RootPosition before they disappear.
RootPosition.saveState();
}
}
}
// set_option() is called when Stockfish receives the "setoption" UCI
// command. The input parameter is a UCIInputParser. It is assumed
// that this parser has consumed the first token of the UCI command
// ("setoption"), and is ready to read the second token ("name", if
// the input is well-formed).
void set_option(UCIInputParser& uip) {
string token, name;
uip >> token;
if (token == "name")
{
uip >> name;
while (!uip.eof())
{
uip >> token;
if (token == "value")
break;
name += (" " + token);
}
if (token == "value")
{
// Reads until end of line and left trim white space
getline(uip, token);
token.erase(0, token.find_first_not_of(" \n\r\t"));
set_option_value(name, token);
} else
push_button(name);
}
}
// go() is called when Stockfish receives the "go" UCI command. The
// input parameter is a UCIInputParser. It is assumed that this
// parser has consumed the first token of the UCI command ("go"),
// and is ready to read the second token. The function sets the
// thinking time and other parameters from the input string, and
// calls think() (defined in search.cpp) with the appropriate
// parameters. Returns false if a quit command is received while
// thinking, returns true otherwise.
bool go(UCIInputParser& uip) {
string token;
int time[2] = {0, 0}, inc[2] = {0, 0};
int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
bool infinite = false, ponder = false;
Move searchMoves[500];
searchMoves[0] = MOVE_NONE;
while (!uip.eof())
{
uip >> token;
if (token == "infinite")
infinite = true;
else if (token == "ponder")
ponder = true;
else if (token == "wtime")
uip >> time[0];
else if (token == "btime")
uip >> time[1];
else if (token == "winc")
uip >> inc[0];
else if (token == "binc")
uip >> inc[1];
else if (token == "movestogo")
uip >> movesToGo;
else if (token == "depth")
uip >> depth;
else if (token == "nodes")
uip >> nodes;
else if (token == "movetime")
uip >> moveTime;
else if (token == "searchmoves")
{
int numOfMoves = 0;
while (!uip.eof())
{
uip >> token;
searchMoves[numOfMoves++] = move_from_string(RootPosition, token);
}
searchMoves[numOfMoves] = MOVE_NONE;
}
}
if (moveTime)
infinite = true; // HACK
assert(RootPosition.is_ok());
return think(RootPosition, infinite, ponder, RootPosition.side_to_move(),
time, inc, movesToGo, depth, nodes, moveTime, searchMoves);
}
void perft(UCIInputParser& uip) {
string token;
int depth, tm, n;
Position pos = RootPosition;
if (uip.eof())
while (is >> token && token != "moves")
fen += token + " ";
else
return;
uip >> depth;
tm = get_system_time();
pos.set(fen, Options["UCI_Chess960"], Threads.main());
SetupStates = Search::StateStackPtr(new std::stack<StateInfo>());
n = perft(pos, depth * OnePly);
tm = get_system_time() - tm;
std::cout << "\nNodes " << n
<< "\nTime (ms) " << tm
<< "\nNodes/second " << (int)(n/(tm/1000.0)) << std::endl;
// Parse move list (if any)
while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)
{
SetupStates->push(StateInfo());
pos.do_move(m, SetupStates->top());
}
}
// setoption() is called when engine receives the "setoption" UCI command. The
// function updates the UCI option ("name") to the given value ("value").
void setoption(istringstream& is) {
string token, name, value;
is >> token; // Consume "name" token
// Read option name (can contain spaces)
while (is >> token && token != "value")
name += string(" ", !name.empty()) + token;
// Read option value (can contain spaces)
while (is >> token)
value += string(" ", !value.empty()) + token;
if (Options.count(name))
Options[name] = value;
else
sync_cout << "No such option: " << name << sync_endl;
}
// go() is called when engine receives the "go" UCI command. The function sets
// the thinking time and other parameters from the input string, and starts
// the search.
void go(const Position& pos, istringstream& is) {
Search::LimitsType limits;
string token;
while (is >> token)
{
if (token == "searchmoves")
while (is >> token)
limits.searchmoves.push_back(move_from_uci(pos, token));
else if (token == "wtime") is >> limits.time[WHITE];
else if (token == "btime") is >> limits.time[BLACK];
else if (token == "winc") is >> limits.inc[WHITE];
else if (token == "binc") is >> limits.inc[BLACK];
else if (token == "movestogo") is >> limits.movestogo;
else if (token == "depth") is >> limits.depth;
else if (token == "nodes") is >> limits.nodes;
else if (token == "movetime") is >> limits.movetime;
else if (token == "mate") is >> limits.mate;
else if (token == "infinite") limits.infinite = true;
else if (token == "ponder") limits.ponder = true;
}
Threads.start_thinking(pos, limits, SetupStates);
}
} // namespace
/// Wait for a command from the user, parse this text string as an UCI command,
/// and call the appropriate functions. Also intercepts EOF from stdin to ensure
/// that we exit gracefully if the GUI dies unexpectedly. In addition to the UCI
/// commands, the function also supports a few debug commands.
void UCI::loop(int argc, char* argv[]) {
Position pos(StartFEN, false, Threads.main()); // The root position
string token, cmd;
for (int i = 1; i < argc; ++i)
cmd += std::string(argv[i]) + " ";
do {
if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input
cmd = "quit";
istringstream is(cmd);
is >> skipws >> token;
if (token == "quit" || token == "stop" || token == "ponderhit")
{
// The GUI sends 'ponderhit' to tell us to ponder on the same move the
// opponent has played. In case Signals.stopOnPonderhit is set we are
// waiting for 'ponderhit' to stop the search (for instance because we
// already ran out of time), otherwise we should continue searching but
// switch from pondering to normal search.
if (token != "ponderhit" || Search::Signals.stopOnPonderhit)
{
Search::Signals.stop = true;
Threads.main()->notify_one(); // Could be sleeping
}
else
Search::Limits.ponder = false;
}
else if (token == "perft" || token == "divide")
{
int depth;
stringstream ss;
is >> depth;
ss << Options["Hash"] << " "
<< Options["Threads"] << " " << depth << " current " << token;
benchmark(pos, ss);
}
else if (token == "key")
sync_cout << hex << uppercase << setfill('0')
<< "position key: " << setw(16) << pos.key()
<< "\nmaterial key: " << setw(16) << pos.material_key()
<< "\npawn key: " << setw(16) << pos.pawn_key()
<< dec << nouppercase << setfill(' ') << sync_endl;
else if (token == "uci")
sync_cout << "id name " << engine_info(true)
<< "\n" << Options
<< "\nuciok" << sync_endl;
else if (token == "eval")
{
Search::RootColor = pos.side_to_move(); // Ensure it is set
sync_cout << Eval::trace(pos) << sync_endl;
}
else if (token == "ucinewgame") { /* Avoid returning "Unknown command" */ }
else if (token == "go") go(pos, is);
else if (token == "position") position(pos, is);
else if (token == "setoption") setoption(is);
else if (token == "flip") pos.flip();
else if (token == "bench") benchmark(pos, is);
else if (token == "d") sync_cout << pos.pretty() << sync_endl;
else if (token == "isready") sync_cout << "readyok" << sync_endl;
else
sync_cout << "Unknown command: " << cmd << sync_endl;
} while (token != "quit" && argc == 1); // Passed args have one-shot behaviour
Threads.wait_for_think_finished(); // Cannot quit whilst the search is running
}
-31
View File
@@ -1,31 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(UCI_H_INCLUDED)
#define UCI_H_INCLUDED
////
//// Prototypes
////
extern void uci_main_loop();
#endif // !defined(UCI_H_INCLUDED)
+111 -279
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,324 +17,156 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <algorithm>
#include <cassert>
#include <map>
#include <string>
#include <cstdlib>
#include <sstream>
#include <vector>
#include "evaluate.h"
#include "misc.h"
#include "thread.h"
#include "tt.h"
#include "ucioption.h"
using std::string;
////
//// Local definitions
////
UCI::OptionsMap Options; // Global object
namespace {
namespace UCI {
///
/// Types
///
enum OptionType { SPIN, COMBO, CHECK, STRING, BUTTON };
typedef std::vector<string> ComboValues;
struct Option {
string name, defaultValue, currentValue;
OptionType type;
size_t idx;
int minValue, maxValue;
ComboValues comboValues;
Option();
Option(const char* defaultValue, OptionType = STRING);
Option(bool defaultValue, OptionType = CHECK);
Option(int defaultValue, int minValue, int maxValue);
bool operator<(const Option& o) const { return this->idx < o.idx; }
};
typedef std::map<string, Option> Options;
///
/// Constants
///
// load_defaults populates the options map with the hard
// coded names and default values.
void load_defaults(Options& o) {
o["Use Search Log"] = Option(false);
o["Search Log Filename"] = Option("SearchLog.txt");
o["Book File"] = Option("book.bin");
o["Mobility (Middle Game)"] = Option(100, 0, 200);
o["Mobility (Endgame)"] = Option(100, 0, 200);
o["Pawn Structure (Middle Game)"] = Option(100, 0, 200);
o["Pawn Structure (Endgame)"] = Option(100, 0, 200);
o["Passed Pawns (Middle Game)"] = Option(100, 0, 200);
o["Passed Pawns (Endgame)"] = Option(100, 0, 200);
o["Space"] = Option(100, 0, 200);
o["Aggressiveness"] = Option(100, 0, 200);
o["Cowardice"] = Option(100, 0, 200);
o["King Safety Curve"] = Option("Quadratic", COMBO);
o["King Safety Curve"].comboValues.push_back("Quadratic");
o["King Safety Curve"].comboValues.push_back("Linear"); /*, "From File"*/
o["King Safety Coefficient"] = Option(40, 1, 100);
o["King Safety X Intercept"] = Option(0, 0, 20);
o["King Safety Max Slope"] = Option(30, 10, 100);
o["King Safety Max Value"] = Option(500, 100, 1000);
o["Queen Contact Check Bonus"] = Option(3, 0, 8);
o["Queen Check Bonus"] = Option(2, 0, 4);
o["Rook Check Bonus"] = Option(1, 0, 4);
o["Bishop Check Bonus"] = Option(1, 0, 4);
o["Knight Check Bonus"] = Option(1, 0, 4);
o["Discovered Check Bonus"] = Option(3, 0, 8);
o["Mate Threat Bonus"] = Option(3, 0, 8);
o["Check Extension (PV nodes)"] = Option(2, 0, 2);
o["Check Extension (non-PV nodes)"] = Option(1, 0, 2);
o["Single Reply Extension (PV nodes)"] = Option(2, 0, 2);
o["Single Reply Extension (non-PV nodes)"] = Option(2, 0, 2);
o["Mate Threat Extension (PV nodes)"] = Option(0, 0, 2);
o["Mate Threat Extension (non-PV nodes)"] = Option(0, 0, 2);
o["Pawn Push to 7th Extension (PV nodes)"] = Option(1, 0, 2);
o["Pawn Push to 7th Extension (non-PV nodes)"] = Option(1, 0, 2);
o["Passed Pawn Extension (PV nodes)"] = Option(1, 0, 2);
o["Passed Pawn Extension (non-PV nodes)"] = Option(0, 0, 2);
o["Pawn Endgame Extension (PV nodes)"] = Option(2, 0, 2);
o["Pawn Endgame Extension (non-PV nodes)"] = Option(2, 0, 2);
o["Full Depth Moves (PV nodes)"] = Option(10, 1, 100);
o["Full Depth Moves (non-PV nodes)"] = Option(3, 1, 100);
o["Threat Depth"] = Option(5, 0, 100);
o["Randomness"] = Option(0, 0, 10);
o["Minimum Split Depth"] = Option(4, 4, 7);
o["Maximum Number of Threads per Split Point"] = Option(5, 4, 8);
o["Threads"] = Option(1, 1, THREAD_MAX);
o["Hash"] = Option(32, 4, 2048);
o["Clear Hash"] = Option(false, BUTTON);
o["New Game"] = Option(false, BUTTON);
o["Ponder"] = Option(true);
o["OwnBook"] = Option(true);
o["MultiPV"] = Option(1, 1, 500);
o["UCI_ShowCurrLine"] = Option(false);
o["UCI_Chess960"] = Option(false);
o["UCI_AnalyseMode"] = Option(false);
// Any option should know its name so to be easily printed
for (Options::iterator it = o.begin(); it != o.end(); ++it)
it->second.name = it->first;
}
///
/// Variables
///
Options options;
// stringify converts a value of type T to a std::string
template<typename T>
string stringify(const T& v) {
std::ostringstream ss;
ss << v;
return ss.str();
}
/// 'On change' actions, triggered by an option's value change
void on_logger(const Option& o) { start_logger(o); }
void on_eval(const Option&) { Eval::init(); }
void on_threads(const Option&) { Threads.read_uci_options(); }
void on_hash_size(const Option& o) { TT.resize(o); }
void on_clear_hash(const Option&) { TT.clear(); }
// get_option_value implements the various get_option_value_<type>
// functions defined later, because only the option value
// type changes a template seems a proper solution.
/// Our case insensitive less() function as required by UCI protocol
bool ci_less(char c1, char c2) { return tolower(c1) < tolower(c2); }
template<typename T>
T get_option_value(const string& optionName) {
T ret = T();
if (options.find(optionName) == options.end())
return ret;
std::istringstream ss(options[optionName].currentValue);
ss >> ret;
return ret;
}
// Specialization for std::string where instruction 'ss >> ret;'
// would erroneusly tokenize a string with spaces.
template<>
string get_option_value<string>(const string& optionName) {
if (options.find(optionName) == options.end())
return string();
return options[optionName].currentValue;
}
}
////
//// Functions
////
/// init_uci_options() initializes the UCI options. Currently, the only
/// thing this function does is to initialize the default value of the
/// "Threads" parameter to the number of available CPU cores.
void init_uci_options() {
load_defaults(options);
// Limit the default value of "Threads" to 7 even if we have 8 CPU cores.
// According to Ken Dail's tests, Glaurung plays much better with 7 than
// with 8 threads. This is weird, but it is probably difficult to find out
// why before I have a 8-core computer to experiment with myself.
assert(options.find("Threads") != options.end());
assert(options.find("Minimum Split Depth") != options.end());
options["Threads"].defaultValue = stringify(Min(cpu_count(), 7));
options["Threads"].currentValue = stringify(Min(cpu_count(), 7));
bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const {
return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), ci_less);
}
/// print_uci_options() prints all the UCI options to the standard output,
/// in the format defined by the UCI protocol.
/// init() initializes the UCI options to their hard-coded default values
void print_uci_options() {
void init(OptionsMap& o) {
static const char optionTypeName[][16] = {
"spin", "combo", "check", "string", "button"
};
// Build up a vector out of the options map and sort it according to idx
// field, that is the chronological insertion order in options map.
std::vector<Option> vec;
for (Options::const_iterator it = options.begin(); it != options.end(); ++it)
vec.push_back(it->second);
std::sort(vec.begin(), vec.end());
for (std::vector<Option>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
std::cout << "\noption name " << it->name
<< " type " << optionTypeName[it->type];
if (it->type == BUTTON)
continue;
if (it->type == CHECK)
std::cout << " default " << (it->defaultValue == "1" ? "true" : "false");
else
std::cout << " default " << it->defaultValue;
if (it->type == SPIN)
std::cout << " min " << it->minValue << " max " << it->maxValue;
else if (it->type == COMBO)
for (ComboValues::const_iterator itc = it->comboValues.begin();
itc != it->comboValues.end(); ++itc)
std::cout << " var " << *itc;
}
std::cout << std::endl;
o["Write Debug Log"] << Option(false, on_logger);
o["Write Search Log"] << Option(false);
o["Search Log Filename"] << Option("SearchLog.txt");
o["Book File"] << Option("book.bin");
o["Best Book Move"] << Option(false);
o["Contempt Factor"] << Option(0, -50, 50);
o["Mobility (Midgame)"] << Option(100, 0, 200, on_eval);
o["Mobility (Endgame)"] << Option(100, 0, 200, on_eval);
o["Pawn Structure (Midgame)"] << Option(100, 0, 200, on_eval);
o["Pawn Structure (Endgame)"] << Option(100, 0, 200, on_eval);
o["Passed Pawns (Midgame)"] << Option(100, 0, 200, on_eval);
o["Passed Pawns (Endgame)"] << Option(100, 0, 200, on_eval);
o["Space"] << Option(100, 0, 200, on_eval);
o["Aggressiveness"] << Option(100, 0, 200, on_eval);
o["Cowardice"] << Option(100, 0, 200, on_eval);
o["Min Split Depth"] << Option(0, 0, 12, on_threads);
o["Threads"] << Option(1, 1, MAX_THREADS, on_threads);
o["Hash"] << Option(32, 1, 16384, on_hash_size);
o["Clear Hash"] << Option(on_clear_hash);
o["Ponder"] << Option(true);
o["OwnBook"] << Option(false);
o["MultiPV"] << Option(1, 1, 500);
o["Skill Level"] << Option(20, 0, 20);
o["Emergency Move Horizon"] << Option(40, 0, 50);
o["Emergency Base Time"] << Option(60, 0, 30000);
o["Emergency Move Time"] << Option(30, 0, 5000);
o["Minimum Thinking Time"] << Option(20, 0, 5000);
o["Slow Mover"] << Option(80, 10, 1000);
o["UCI_Chess960"] << Option(false);
}
/// get_option_value_bool() returns the current value of a UCI parameter of
/// type "check".
/// operator<<() is used to print all the options default values in chronological
/// insertion order (the idx field) and in the format defined by the UCI protocol.
bool get_option_value_bool(const string& optionName) {
std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
return get_option_value<bool>(optionName);
for (size_t idx = 0; idx < om.size(); ++idx)
for (OptionsMap::const_iterator it = om.begin(); it != om.end(); ++it)
if (it->second.idx == idx)
{
const Option& o = it->second;
os << "\noption name " << it->first << " type " << o.type;
if (o.type != "button")
os << " default " << o.defaultValue;
if (o.type == "spin")
os << " min " << o.min << " max " << o.max;
break;
}
return os;
}
/// get_option_value_int() returns the value of a UCI parameter as an integer.
/// Normally, this function will be used for a parameter of type "spin", but
/// it could also be used with a "combo" parameter, where all the available
/// values are integers.
/// Option class constructors and conversion operators
int get_option_value_int(const string& optionName) {
Option::Option(const char* v, OnChange f) : type("string"), min(0), max(0), on_change(f)
{ defaultValue = currentValue = v; }
return get_option_value<int>(optionName);
Option::Option(bool v, OnChange f) : type("check"), min(0), max(0), on_change(f)
{ defaultValue = currentValue = (v ? "true" : "false"); }
Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f)
{}
Option::Option(int v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f)
{ std::ostringstream ss; ss << v; defaultValue = currentValue = ss.str(); }
Option::operator int() const {
assert(type == "check" || type == "spin");
return (type == "spin" ? atoi(currentValue.c_str()) : currentValue == "true");
}
Option::operator std::string() const {
assert(type == "string");
return currentValue;
}
/// get_option_value_string() returns the current value of a UCI parameter as
/// a string. It is used with parameters of type "combo" and "string".
/// operator<<() inits options and assigns idx in the correct printing order
string get_option_value_string(const string& optionName) {
void Option::operator<<(const Option& o) {
return get_option_value<string>(optionName);
static size_t insert_order = 0;
*this = o;
idx = insert_order++;
}
/// set_option_value() inserts a new value for a UCI parameter. Note that
/// the function does not check that the new value is legal for the given
/// parameter: This is assumed to be the responsibility of the GUI.
/// operator=() updates currentValue and triggers on_change() action. It's up to
/// the GUI to check for option's limits, but we could receive the new value from
/// the user by console window, so let's check the bounds anyway.
void set_option_value(const string& name, const string& value) {
Option& Option::operator=(const string& v) {
// UCI protocol uses "true" and "false" instead of "1" and "0", so convert
// value according to standard C++ convention before to store it.
string v(value);
if (v == "true")
v = "1";
else if (v == "false")
v = "0";
assert(!type.empty());
if (options.find(name) != options.end())
options[name].currentValue = v;
else
std::cout << "No such option: " << name << std::endl;
if ( (type != "button" && v.empty())
|| (type == "check" && v != "true" && v != "false")
|| (type == "spin" && (atoi(v.c_str()) < min || atoi(v.c_str()) > max)))
return *this;
if (type != "button")
currentValue = v;
if (on_change)
on_change(*this);
return *this;
}
/// push_button() is used to tell the engine that a UCI parameter of type
/// "button" has been selected:
void push_button(const string& buttonName) {
set_option_value(buttonName, "true");
}
/// button_was_pressed() tests whether a UCI parameter of type "button" has
/// been selected since the last time the function was called, in this case
/// it also resets the button.
bool button_was_pressed(const string& buttonName) {
if (!get_option_value<bool>(buttonName))
return false;
set_option_value(buttonName, "false");
return true;
}
namespace {
// Define constructors of Option class.
Option::Option() {} // To allow insertion in a std::map
Option::Option(const char* def, OptionType t)
: defaultValue(def), currentValue(def), type(t), idx(options.size()), minValue(0), maxValue(0) {}
Option::Option(bool def, OptionType t)
: defaultValue(stringify(def)), currentValue(stringify(def)), type(t), idx(options.size()), minValue(0), maxValue(0) {}
Option::Option(int def, int minv, int maxv)
: defaultValue(stringify(def)), currentValue(stringify(def)), type(SPIN), idx(options.size()), minValue(minv), maxValue(maxv) {}
}
} // namespace UCI
+45 -19
View File
@@ -1,7 +1,7 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Copyright (C) 2008-2014 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,28 +17,54 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(UCIOPTION_H_INCLUDED)
#ifndef UCIOPTION_H_INCLUDED
#define UCIOPTION_H_INCLUDED
////
//// Includes
////
#include <map>
#include <string>
////
//// Prototypes
////
namespace UCI {
extern void init_uci_options();
extern void print_uci_options();
extern bool get_option_value_bool(const std::string& optionName);
extern int get_option_value_int(const std::string& optionName);
extern std::string get_option_value_string(const std::string& optionName);
extern bool button_was_pressed(const std::string& buttonName);
extern void set_option_value(const std::string& optionName,const std::string& newValue);
extern void push_button(const std::string& buttonName);
class Option;
/// Custom comparator because UCI options should be case insensitive
struct CaseInsensitiveLess {
bool operator() (const std::string&, const std::string&) const;
};
#endif // !defined(UCIOPTION_H_INCLUDED)
/// Our options container is actually a std::map
typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap;
/// Option class implements an option as defined by UCI protocol
class Option {
typedef void (*OnChange)(const Option&);
public:
Option(OnChange = NULL);
Option(bool v, OnChange = NULL);
Option(const char* v, OnChange = NULL);
Option(int v, int min, int max, OnChange = NULL);
Option& operator=(const std::string& v);
void operator<<(const Option& o);
operator int() const;
operator std::string() const;
private:
friend std::ostream& operator<<(std::ostream&, const OptionsMap&);
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
OnChange on_change;
};
void init(OptionsMap&);
void loop(int argc, char* argv[]);
} // namespace UCI
extern UCI::OptionsMap Options;
#endif // #ifndef UCIOPTION_H_INCLUDED
-96
View File
@@ -1,96 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////
//// Includes
////
#include <sstream>
#include <string>
#include "value.h"
////
//// Functions
////
/// value_to_tt() adjusts a mate score from "plies to mate from the root" to
/// "plies to mate from the current ply". Non-mate scores are unchanged.
/// The function is called before storing a value to the transposition table.
Value value_to_tt(Value v, int ply) {
if(v >= value_mate_in(100))
return v + ply;
else if(v <= value_mated_in(100))
return v - ply;
else
return v;
}
/// value_from_tt() is the inverse of value_to_tt(): It adjusts a mate score
/// from the transposition table to a mate score corrected for the current
/// ply depth.
Value value_from_tt(Value v, int ply) {
if(v >= value_mate_in(100))
return v - ply;
else if(v <= value_mated_in(100))
return v + ply;
else
return v;
}
/// value_to_centipawns() converts a value from Stockfish's somewhat unusual
/// scale of pawn = 256 to the more conventional pawn = 100.
int value_to_centipawns(Value v) {
return (int(v) * 100) / int(PawnValueMidgame);
}
/// value_from_centipawns() converts a centipawn value to Stockfish's internal
/// evaluation scale. It's used when reading the values of UCI options
/// containing material values (e.g. futility pruning margins).
Value value_from_centipawns(int cp) {
return Value((cp * 256) / 100);
}
/// value_to_string() converts a value to a string suitable for use with the
/// UCI protocol.
const std::string value_to_string(Value v) {
std::stringstream s;
if(abs(v) < VALUE_MATE - 200)
s << "cp " << value_to_centipawns(v);
else {
s << "mate ";
if(v > 0)
s << (VALUE_MATE - v + 1) / 2;
else
s << -(VALUE_MATE + v) / 2;
}
return s.str();
}
-207
View File
@@ -1,207 +0,0 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(VALUE_H_INCLUDED)
#define VALUE_H_INCLUDED
////
//// Includes
////
#include "piece.h"
////
//// Types
////
enum ValueType {
VALUE_TYPE_NONE = 0,
VALUE_TYPE_UPPER = 1, // Upper bound
VALUE_TYPE_LOWER = 2, // Lower bound
VALUE_TYPE_EXACT = 3, // Exact score
VALUE_TYPE_EVAL = 4, // Evaluation cache
VALUE_TYPE_EV_UP = 5, // Evaluation cache for upper bound
VALUE_TYPE_EV_LO = 6 // Evaluation cache for lower bound
};
enum Value {
VALUE_DRAW = 0,
VALUE_KNOWN_WIN = 15000,
VALUE_MATE = 30000,
VALUE_INFINITE = 30001,
VALUE_NONE = 30002
};
/// Score enum keeps a midgame and an endgame value in a single
/// integer (enum), first LSB 16 bits are used to store endgame
/// value, while upper bits are used for midgame value.
// Compiler is free to choose the enum type as long as can keep
// its data, so ensure Score to be an integer type.
enum Score { ENSURE_32_BITS_SIZE_P = (1 << 16), ENSURE_32_BITS_SIZE_N = -(1 << 16)};
// Extracting the _signed_ lower and upper 16 bits it not so trivial
// because according to the standard a simple cast to short is
// implementation defined and so is a right shift of a signed integer.
inline Value mg_value(Score s) { return Value(((int(s) + 32768) & ~0xffff) / 0x10000); }
// Unfortunatly on Intel 64 bit we have a small speed regression, so use a faster code in
// this case, although not 100% standard compliant it seems to work for Intel and MSVC.
#if defined(IS_64BIT) && (!defined(__GNUC__) || defined(__INTEL_COMPILER))
inline Value eg_value(Score s) { return Value(int16_t(s & 0xffff)); }
#else
inline Value eg_value(Score s) { return Value((int)(unsigned(s) & 0x7fffu) - (int)(unsigned(s) & 0x8000u)); }
#endif
inline Score make_score(int mg, int eg) { return Score((mg << 16) + eg); }
inline Score operator-(Score s) { return Score(-int(s)); }
inline Score operator+(Score s1, Score s2) { return Score(int(s1) + int(s2)); }
inline Score operator-(Score s1, Score s2) { return Score(int(s1) - int(s2)); }
inline void operator+=(Score& s1, Score s2) { s1 = Score(int(s1) + int(s2)); }
inline void operator-=(Score& s1, Score s2) { s1 = Score(int(s1) - int(s2)); }
inline Score operator*(int i, Score s) { return Score(i * int(s)); }
// Division must be handled separately for each term
inline Score operator/(Score s, int i) { return make_score(mg_value(s) / i, eg_value(s) / i); }
// Only declared but not defined. We don't want to multiply two scores due to
// a very high risk of overflow. So user should explicitly convert to integer.
inline Score operator*(Score s1, Score s2);
////
//// Constants and variables
////
/// Piece values, middle game and endgame
/// Important: If the material values are changed, one must also
/// adjust the piece square tables, and the method game_phase() in the
/// Position class!
///
/// Values modified by Joona Kiiski
const Value PawnValueMidgame = Value(0x0C6);
const Value PawnValueEndgame = Value(0x102);
const Value KnightValueMidgame = Value(0x331);
const Value KnightValueEndgame = Value(0x34E);
const Value BishopValueMidgame = Value(0x344);
const Value BishopValueEndgame = Value(0x359);
const Value RookValueMidgame = Value(0x4F6);
const Value RookValueEndgame = Value(0x4FE);
const Value QueenValueMidgame = Value(0x9D9);
const Value QueenValueEndgame = Value(0x9FE);
const Value PieceValueMidgame[17] = {
Value(0),
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
RookValueMidgame, QueenValueMidgame,
Value(0), Value(0), Value(0),
PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
RookValueMidgame, QueenValueMidgame,
Value(0), Value(0), Value(0)
};
const Value PieceValueEndgame[17] = {
Value(0),
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
RookValueEndgame, QueenValueEndgame,
Value(0), Value(0), Value(0),
PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
RookValueEndgame, QueenValueEndgame,
Value(0), Value(0), Value(0)
};
/// Bonus for having the side to move (modified by Joona Kiiski)
const Score TempoValue = make_score(48, 22);
////
//// Inline functions
////
inline Value operator+ (Value v, int i) { return Value(int(v) + i); }
inline Value operator+ (Value v1, Value v2) { return Value(int(v1) + int(v2)); }
inline void operator+= (Value &v1, Value v2) {
v1 = Value(int(v1) + int(v2));
}
inline Value operator- (Value v, int i) { return Value(int(v) - i); }
inline Value operator- (Value v) { return Value(-int(v)); }
inline Value operator- (Value v1, Value v2) { return Value(int(v1) - int(v2)); }
inline void operator-= (Value &v1, Value v2) {
v1 = Value(int(v1) - int(v2));
}
inline Value operator* (Value v, int i) { return Value(int(v) * i); }
inline void operator*= (Value &v, int i) { v = Value(int(v) * i); }
inline Value operator* (int i, Value v) { return Value(int(v) * i); }
inline Value operator/ (Value v, int i) { return Value(int(v) / i); }
inline void operator/= (Value &v, int i) { v = Value(int(v) / i); }
inline Value value_mate_in(int ply) {
return Value(VALUE_MATE - Value(ply));
}
inline Value value_mated_in(int ply) {
return Value(-VALUE_MATE + Value(ply));
}
inline bool is_upper_bound(ValueType vt) {
return (int(vt) & int(VALUE_TYPE_UPPER)) != 0;
}
inline bool is_lower_bound(ValueType vt) {
return (int(vt) & int(VALUE_TYPE_LOWER)) != 0;
}
inline Value piece_value_midgame(PieceType pt) {
return PieceValueMidgame[pt];
}
inline Value piece_value_endgame(PieceType pt) {
return PieceValueEndgame[pt];
}
inline Value piece_value_midgame(Piece p) {
return PieceValueMidgame[p];
}
inline Value piece_value_endgame(Piece p) {
return PieceValueEndgame[p];
}
////
//// Prototypes
////
extern Value value_to_tt(Value v, int ply);
extern Value value_from_tt(Value v, int ply);
extern int value_to_centipawns(Value v);
extern Value value_from_centipawns(int cp);
extern const std::string value_to_string(Value v);
#endif // !defined(VALUE_H_INCLUDED)