Compare commits

..

197 Commits

Author SHA1 Message Date
Marco Costalba ec23692433 Stockfish 1.01
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-04 20:56:30 +01:00
Marco Costalba 787d358554 Fix compile under Ubuntu 64bit
Some missing includes.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-04 20:56:30 +01:00
Marco Costalba ff0d9dad2b Fix a serious bug in TranspositionTable::retrieve()
Reported by Tord Romstad.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-04 20:56:30 +01:00
Marco Costalba 046fd4926f Restore development versioning
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-04 20:56:30 +01:00
Marco Costalba c595185b3c Restore LSN filtering
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-04 20:56:18 +01:00
Marco Costalba 1a158c0cf0 Revert movepick optimizations before to release
More testing is needed and better do not risk
just before release.

Reverted:

Disable LSN filtering as defualt for release
Use MVV/LVA in score_evasions()

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:58:10 +01:00
Marco Costalba 8097e99c69 Stockfish 1.0
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:35:32 +01:00
Marco Costalba 2fa9d25e82 Disable LSN filtering as defualt for release
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:35:02 +01:00
Marco Costalba 3e275680d5 Use MVV/LVA in score_evasions()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:00:28 +01:00
Marco Costalba d087b0a34a Delay SEE for scoring captures
Do not calculate SEE on all the moves in MovePicker::score_captures()
but delay until pick_move_from_list() when only the best ones are
double checked against their see value.

If a beta cut-off occurs then we avoid calculating SEE on all
the moves, but just the picked ones.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:00:28 +01:00
Marco Costalba 55b6464d40 search: micro optimization
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:00:28 +01:00
Marco Costalba b5232e2da3 Fix a couple of gcc warnings in position.cpp
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:00:19 +01:00
Marco Costalba 35bd334b30 Update README to Stockfish
Remove Glaurung references.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-02 15:00:09 +01:00
Marco Costalba 6e8bd8bf2d Final touches to material.cpp
No functional changes, altough a bit of code reshuffle.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:54 +01:00
Marco Costalba 899b9455d6 Material: lockless per-thread maps
Adds a good bunch of code but should be faster
and scalable because is lockless.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:54 +01:00
Marco Costalba 8b57416ace Revert "MovePicker::score_captures() order with SEE when pv"
Does not seem to increase the strenght.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:54 +01:00
Marco Costalba 1146fc8d09 Space inflate move.cpp
Also a little cleanup.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:53 +01:00
Marco Costalba 6e5cf2f3c5 Revert "Relax time constraints"
Does not seem to give an improvment, acutually it seems
a totally neutral change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:53 +01:00
Marco Costalba e5ebd4f5d1 Partially space inflate search.cpp
Space inflate main remaining functions in search.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:53 +01:00
Marco Costalba cf2bafb661 Relax time constraints
Allow a seacrh to take a bit more time if needed.

This reduces the chanches of wast all the search time
for the last iteration and also allow to start the last
iteration when we have less time remaining.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:53 +01:00
Marco Costalba 79513e3a43 Material: micro optimize map reading
Do only one map walk per read instead of two.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:52 +01:00
Marco Costalba bd3ec6af15 Material: protect global map access with locks
STL library is not guaranteed to be thread safe, even for
read-access.

So because these global maps are accessed by all the threads
we need to protect them.

This fixes a random crash experienced during testing.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:52 +01:00
Marco Costalba b2b86cfd27 MovePicker::score_captures() order with SEE when pv
Order PV nodes by SEE instead of MVV/LVA.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:52 +01:00
Marco Costalba 7d717df4e4 Revert "Last minute surprise" for now
It defenitly needs more testing. Just postponed.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:52 +01:00
Marco Costalba 5e906ea10e Finish material.cpp cleanup
Hopefully no regression this time!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:52 +01:00
Marco Costalba 73cce873de Start to simplify material.cpp
It is posisble to simplify a lot here!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:51 +01:00
Marco Costalba 038235ba35 Factor out Position::do_capture_move()
Start to slim line count i position.cpp

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:51 +01:00
Marco Costalba 5e2fc2aa16 Fix a bug in generate_evasions()
Introduced in the patch "movegen: prefer (*mlist++) to mlist[n++]"

This was nasty because due to a mismerge the repo in one PC had the bug,
but the testing one did not, so I had non reproducible results according
to which machine I used for testing.

This hopefully closes a more then one week regression that made me go crazy!

It was found by accident comparing, for other reasons, the sources of the
two PC's.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:51 +01:00
Marco Costalba 74fd57220e Refine "few moves" in "last minute surprise"
It seems that "few moves" works because we extend the good
captures at the last ply of PV, so code it directly.

This version seems defenitly stronger then previous one.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-11-01 12:46:51 +01:00
Marco Costalba 74f1efee26 Manual merge 2008-10-26 21:44:58 +01:00
Marco Costalba 0936a96a0e Space inflate extension() code
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 21:30:21 +01:00
Marco Costalba 13d1776a98 TEST: extend when few moves available
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 21:30:21 +01:00
Marco Costalba a56e1c662c Revert see shortcut when only one attacker
It does not seem to work after a little testing.

Perhaps it works on the long terms, but it is also
ugly because not correct, so revert for now.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 21:30:21 +01:00
Marco Costalba fcc49561a1 Prefer out of loop variables in MovePicker::score_captures()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 21:30:21 +01:00
Marco Costalba 714069e248 Effectively use MVV/LVA in MovePicker::score_captures()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 21:30:20 +01:00
Marco Costalba 88885399f4 Reintroduce piece/square tables to score non-captures
Was removed after original movepick restore. But proved
to be useful.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 21:30:20 +01:00
Marco Costalba a5c1b3e8f6 Position: fix a couple of Intel compiler warnings
Plus usual trailing whitespace.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 13:23:27 +01:00
Marco Costalba 8a85007023 Test with SEE shortcut
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 10:11:13 +01:00
Marco Costalba 4397e6c03e Better naming of pseudo-legality and legality testing
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 10:11:13 +01:00
Marco Costalba 4f14bd5032 Try to cleanup movepick
Hopefully without regressions.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 10:11:13 +01:00
Marco Costalba f8bc38a006 Restore original movepick modulo space inflation
We have a regression somewhere here so restart from zero
and proceed one change at a time.

With this modification we have the same strenght of
"Introduce Stockfish" patch that is our strongest to date.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 10:11:13 +01:00
Marco Costalba 5dd9159106 Space inflate position: complete!
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-26 10:10:56 +01:00
Marco Costalba ad956ef00a Space inflate position until do_promotion_move()
We will end some day ;-)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:05 +02:00
Marco Costalba d155cd88d1 Start to space inflate position.cpp
It's a big file!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:05 +02:00
Marco Costalba 2aebf8eb55 Fix a performance bug in generate_move_if_legal
Use the pinned argument in pos.move_is_legal()

No functional change, simply use pos.move_is_legal() as
was meant to be.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:05 +02:00
Marco Costalba 1ac2f50145 Unify pinned and discovery checks code
Templates are our friends here. No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:04 +02:00
Marco Costalba af59cb1d63 Refactor Position::pinned_pieces() to use templates
Also better document this interesting function.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:04 +02:00
Marco Costalba 2f8961beef movegen: add SERIALIZE_MOVES and hides a bunch of loops
Only syntactic sugar, perhaps we should leave as is, anyhow...

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:04 +02:00
Marco Costalba af5743837d Another generate_piece_moves() micro optimization
This time on the for loop.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:10:04 +02:00
Marco Costalba 5e768e4b0a Fix another template conversion bug in movegen
Hopefully the last one.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-24 21:09:51 +02:00
Marco Costalba 2d867109d9 movegen: prefer (*mlist++) to mlist[n++]
Teoretically faster, practically it helps to
removes some more lines.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-23 07:17:04 +02:00
Marco Costalba b145e99559 Fix a bug in generate_pawn_captures()
Introduced in "movegen: Introduce generate_pawn_captures()"
when unifiying black and white functions.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-23 07:17:04 +02:00
Marco Costalba 8f2c1c59eb Fully templetize pawn move generators
A little bit more syntax heavuer but surely faster.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-23 07:17:04 +02:00
Marco Costalba c40249e9d2 Micro optimize generate_piece_moves()
It is a time critical path. The biggest in move generation.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-21 00:10:27 +02:00
Marco Costalba ce93a202b5 Another Intel warning sqeezed
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:57:13 +02:00
Marco Costalba 279ed7ed48 Quiet a warning on Intel compiler
Plus usual trailing whitespace noise.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:55:43 +02:00
Marco Costalba af6571856e Shrink arguments in move generation functions
Perhaps no speedup, but it is more readable.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:21 +02:00
Marco Costalba 0c8659721f Fix a bug in king discoveries checks
Introduced in "Add a generate_piece_checks() specialization for the king"

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:20 +02:00
Marco Costalba 5dc2312121 Update copyright info
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:20 +02:00
Marco Costalba aa94f2f4c2 Last little touches to movegen
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:19 +02:00
Marco Costalba d7161c1ce6 Rename PawnOffsets in PawnParams
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:19 +02:00
Marco Costalba e2af0e775b Pawn move generator: dispatch at compile time
Instead of function pointers use templates to
dispatch shift operations.

It is more clear and possibly also faster because
branches are removed at compile time.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:19 +02:00
Marco Costalba ad1bb084dd Start to templetize pawn move generators
Still very soft, we will see if compiler is
enough or we need more aggressive templetization.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:18 +02:00
Marco Costalba 760f77872f Remove Positions::xxx_count() functions
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:18 +02:00
Marco Costalba 257689dec7 Remove white/black_pawn_attacks_square()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:18 +02:00
Marco Costalba ff211469ba Templetize Position::xxx_attacks_square()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:17 +02:00
Marco Costalba d4f14a8e83 Remove Position::xxx_list() functions
No useful, only obfuscating.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:17 +02:00
Marco Costalba 7eb290a509 Add a generate_piece_checks() specialization for the king
Also reshuffle the code a bit.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:17 +02:00
Marco Costalba d316b02771 Remove white/black_pawn_attacks()
Unuseful syntactic sugar, obfuscates the
real code.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:17 +02:00
Marco Costalba d9e54ceaa1 Prefer template to name decoration
This also allows faster code although bigger.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:16 +02:00
Marco Costalba 691de79eaa Fix a missing comma in BenchmarkPositions[]
An old bug introduced in 3e0dc9ee84 almost
one month ago.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:16 +02:00
Marco Costalba 3f38cca072 Position::is_ok()give more info on failed test
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:16 +02:00
Marco Costalba 6b8a07eccc Fix an assert due to a missing parentesis
Bitwise operators precedence issue here, was
causing an assert.

This is a fallout from recent patches.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:15 +02:00
Marco Costalba 8e85aa3a65 Final semplification of generate_evasions()
Now it's readable!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:15 +02:00
Marco Costalba 4f18528a1c Introduce generate_piece_blocking_evasions()
Start to simplify generate_evasions

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:15 +02:00
Marco Costalba 4a4d62da13 Space inflate generate_evasions()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-20 21:47:15 +02:00
Marco Costalba d3600c39a7 Update copyright info
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 20:43:33 +01:00
Marco Costalba f664ca41ed Last little touches to movegen
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 20:43:21 +01:00
Marco Costalba b397426785 Rename PawnOffsets in PawnParams
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 20:43:09 +01:00
Marco Costalba 68c78400c8 Pawn move generator: dispatch at compile time
Instead of function pointers use templates to
dispatch shift operations.

It is more clear and possibly also faster because
branches are removed at compile time.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 20:42:12 +01:00
Marco Costalba 1bd1f5a293 Start to templetize pawn move generators
Still very soft, we will see if compiler is
enough or we need more aggressive templetization.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 16:20:21 +01:00
Marco Costalba d0e51bc0f0 Remove Positions::xxx_count() functions
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 14:39:29 +01:00
Marco Costalba 0d19437703 Remove white/black_pawn_attacks_square()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 14:06:06 +01:00
Marco Costalba 8b5519a009 Templetize Position::xxx_attacks_square()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 13:56:57 +01:00
Marco Costalba 1eae58523f Remove Position::xxx_list() functions
No useful, only obfuscating.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 13:44:25 +01:00
Marco Costalba 305b711ca8 Add a generate_piece_checks() specialization for the king
Also reshuffle the code a bit.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 13:22:03 +01:00
Marco Costalba 2bea93975e Remove white/black_pawn_attacks()
Unuseful syntactic sugar, obfuscates the
real code.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 12:53:51 +01:00
Marco Costalba f036239521 Prefer template to name decoration
This also allows faster code although bigger.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 12:43:09 +01:00
Marco Costalba 832a8a2719 Fix a missing comma in BenchmarkPositions[]
An old bug introduced in 3e0dc9ee84 almost
one month ago.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 11:55:53 +01:00
Marco Costalba 11910d44e0 Position::is_ok()give more info on failed test
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 10:41:24 +01:00
Marco Costalba 00bcc64787 Fix an assert due to a missing parentesis
Bitwise operators precedence issue here, was
causing an assert.

This is a fallout from recent patches.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 10:17:17 +01:00
Marco Costalba f2ead1004a Final semplification of generate_evasions()
Now it's readable!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 09:33:33 +01:00
Marco Costalba 84ce43498a Introduce generate_piece_blocking_evasions()
Start to simplify generate_evasions

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 08:49:26 +01:00
Marco Costalba 987ff3b4b6 Space inflate generate_evasions()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-19 08:27:24 +01:00
Marco Costalba 72289fcfab movegen: Introduce generate_pawn_noncaptures()
This is the last of pawn moves generators converted
to new unified form.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:35 +02:00
Marco Costalba 73d0d2c0b2 movegen: Introduce generate_pawn_captures()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:35 +02:00
Marco Costalba c1257d45b2 movegen: Fix just introduced move counter bug
This is what happens when you don't tests your patches !!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:35 +02:00
Marco Costalba 34a515f20b movegen: Introduce generate_pawn_checks()
This greatly simplify redundant code.

Perhaps slihtly slower. Test needed.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:35 +02:00
Marco Costalba 5abe8a0816 generate_checks: fix a bug in black double pawn push
It was written pos.black_pawn_attacks(ksq) instead of
pos.white_pawn_attacks(ksq)

Updated to the undrlying pos.pawn_attacks(WHITE, ksq)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:34 +02:00
Marco Costalba 35fd5ce5bc Space inflate generate_castle_moves()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:34 +02:00
Marco Costalba 146bb2dfa7 Unify pieces check generation with generate_piece_checks()
Could be slower: test needed!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:34 +02:00
Marco Costalba ea16985ea5 Do not special case generate_king_moves()
Teoretically a little slowdown. If after testing we
verify the slowdown has impact on ELO we revert the
change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:34 +02:00
Marco Costalba 3b857d1625 Use a const pointer-to-member array for attacks
Allow the compiler to optimize member
function access.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:34 +02:00
Marco Costalba aa7121297d Use pointer-to-members to remove a bunch of duplicated code
Remove all generate_XXX_moves() functions, use an array
of pointer to members instead.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:34 +02:00
Marco Costalba 94f1b31484 movegen: revert see ordering in score_captures()
It works better with MVV ordering.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:33 +02:00
Marco Costalba c852a94009 Movegen: further simplify generate_move_if_legal
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:33 +02:00
Marco Costalba 8be2c483a1 Unify black and white code in generate_move_if_legal()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:33 +02:00
Marco Costalba 158911425b Space inflate movegen.cpp
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:33 +02:00
Marco Costalba cf8ee79b76 Movepick: add and use find_best_index() helper
This removes a bunch of redundant code.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:33 +02:00
Marco Costalba 06d6468ce9 Test with see
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:33 +02:00
Marco Costalba 173ecc0acf Use MVV to score captures when see >=0
This fix a couple of dubious bugs in MVV/LVA
ordering.

Tests seems to confirm now is slightly better.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:32 +02:00
Marco Costalba 2943e1ca31 MovePicker: use const reference instead of pointers
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:32 +02:00
Marco Costalba 486ec580f9 Space inflate movepick.cpp
Also added some FIXME to dubious points.

Still no functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:32 +02:00
Marco Costalba a930aafce0 Better comment previous patch
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:32 +02:00
Marco Costalba b3744eb4d0 Always add psqt scoring
When there is also history, history is always
preferred.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:32 +02:00
Marco Costalba a03ab94f44 Shortcut sorting when no move is in history
An alternative algorithm to psqt scoring.

Still unclear what is the best, more tests needed.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-18 21:35:20 +02:00
Marco Costalba 644db060ae Add psqt ordering when there is no history
This seems to increase strenght (about 15 ELO),
still to test some variations on this theme that
could increase ELO even more.

Idea from Rebel (http://members.home.nl/matador/chess840.htm)

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-15 07:18:05 +01:00
unknown cb76e4a814 Introduce Stockfish
Signed-off-by: unknown <Marco@.(none)>
2008-10-13 22:45:47 +01:00
Marco Costalba d8268024a9 Implement Last Seconds Noise (LSN) filtering
When an engine is in deep trouble at few
seconds from time limit then giveup without
fighting anymore.

This is used to reduce "lucky draws" and time pressure
blunders noises that can obfuscate results during tests
blitz games (typical one minute games).

Goal of this technique is to reduce number of matches
needed to reliably prove then an engine A is stronger
then an opponent B.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-13 20:40:48 +02:00
Marco Costalba 4fa5dd4db5 Add a second margin to razoring
Razor on ply one if the advantage is more then a pawn,
the only way to gap the advantage is to capture, so
go directly in quiesce.

This seems to have a positive effect.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-13 20:40:47 +02:00
Marco Costalba 58c7a5c477 Workaround a static data member bug in MSVC
Without this patch MSVC crashes when compiled
in release mode. It survives and works as
expected in debug mode and with gcc and Intel
compilers.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-13 20:40:47 +02:00
Marco Costalba 3901affb1d Yet another pop_1st_bit() optimization
Always for 32 bit but withot relying on MSVC intrinsics.

It is very similar to previous ones, but this does not
segfaults due to -fno-strict-aliasing compiler option.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-12 14:34:54 +02:00
Marco Costalba a6017aa728 Add mean calculation in debug tools
Another simple performance counter...

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-11 19:25:16 +02:00
Marco Costalba 6a15df1d82 Revert bad capture pruning
After testing does not seem to increase ELO.

Indeed Glaurung is a little bit weaker, so revert.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-11 19:03:59 +02:00
Marco Costalba bbf7a94d76 Better interface to get the current move type
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-06 05:44:23 +02:00
Marco Costalba a3477af2a1 Allow to prune bad captures
Only good capture are preserved from futility pruning
and LMR reducing.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-06 05:44:23 +02:00
Marco Costalba 310e07f292 Teach MovePicker::get_next_move() to return move type
This will be used in future patches.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-06 05:44:22 +02:00
Marco Costalba ea7bebb604 Fix single digit day in engine_name()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-05 10:37:05 +02:00
Marco Costalba 54071312f3 Add dbg_before() and dbg_after()
Other two debug utilities to compute filter rate.

Usage is:

dbg_before(); // counts passages from this point

if(..) // complex code stuff you want to audit
  return/continue
if(...)
  .....

dbg_after(); // counts passages from this point

Then somewhere in the code, normally in poll() add
dbg_print_hit_rate() and you will see the filter rate
of your code under auditing.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-04 10:01:54 +02:00
Marco Costalba 849809e97e Space inflate Position::to_fen()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-10-04 09:50:19 +02:00
Marco Costalba e9e51da4b8 position.cpp: fix a typo introduced by recent patch
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-28 10:59:20 +02:00
Marco Costalba f1f887b6d7 Use relative values in piece square tables
So that will be automatically changed when
pieces values change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-28 10:59:08 +02:00
Marco Costalba 88bb3c9422 Start to cleanup position.cpp
Still a lot to do. No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-28 10:58:56 +02:00
Marco Costalba 8d76de820f Add dbg_hit_on_c(c, x) tool
Like dbg_hit_on(x) but first filter out events and
only when condition 'c' is true the hit counter
is tested with 'x'.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-28 10:58:47 +02:00
Marco Costalba b00abed181 Space inflate evaluate_king()
This is the most complex piece of software
so far.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-26 05:54:49 +02:00
Marco Costalba 2e3faae067 Clarify difference between king zone and adjacent zone
There are subtle differences in the king evaluation
that should be clear to avoid misunderstandings.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-26 05:54:49 +02:00
Marco Costalba 453e815d4b Tidy up quick_evaluate()
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-26 05:54:49 +02:00
Marco Costalba 3e0dc9ee84 Tidy up middle game specific evaluation
Also add starting position to benchmarks.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-26 05:54:49 +02:00
Marco Costalba 597ef38c39 Code style massage evaluate()
No functional changes.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-26 05:54:49 +02:00
Marco Costalba d6618d7325 Add auto configuration for 32/64 bits
Instead of manually adjust defines in bitboard.h
now proper ones are automatically set.

It is anyhow possible to still set them manually
in case of problems.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-25 07:51:56 +02:00
Marco Costalba 3ee3cdc09b Evaluate: weight_option() is static
Declare function under local namespace. This removes a
warning from the picky Intel compiler.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:17:28 +02:00
Marco Costalba ca891e9760 Cleanup read_weights() in evaluate.cpp
Exception to 80 colums rule here, but result
seems better.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:02:16 +02:00
Marco Costalba dfcfed6432 Evaluate: rename king attack variables
A better naming IMHO

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:02:15 +02:00
Marco Costalba 34ca22486a Further cleanup evaluate()
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:02:15 +02:00
Marco Costalba f56af8e84d Rename pawn_rank() in relative_rank()
It is more clear, at last for me.

Also cleanup evaluate_rook() and evaluate_queen()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:02:15 +02:00
Marco Costalba 3263ee8557 Add also outposts evaluation in common code
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:02:14 +02:00
Marco Costalba 853ce65f17 Group common evaluate code
This removes code redundancy but perhaps
impact performance due to uninlining.

Testing for regression is needed. For now
aim to best code readibility.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 21:02:14 +02:00
Marco Costalba 7dd0c39714 Warnings termination fest
A bunch of Intel C++ warnings removed, other silent out.

Still few remaining but need deeper look.

Also usual whitespace crap removal noise.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-24 00:32:53 +02:00
Marco Costalba 060eef4f4e Do not use evaluate() for razoring
Because razoring is reached 10% of times and about 50% of time
first two conditions are met we can save 5% of calls to the fairly
costly evaluate().

On the other side statistics have shown 95% of nodes that pass
the first two razoring conditions pass also the evaluate() test.
So the risk of dropping the third condition seems low enough.

Testing seems to validate this.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-23 23:36:51 +02:00
Marco Costalba 67f975e56b init_eval: small cleanup
Functionality not changed.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-23 08:07:50 +02:00
Marco Costalba 1d8994402b Fix InitKingDanger initialization
Last line was missing.

Also reformat tables constants to be more readable.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-23 08:07:42 +02:00
Marco Costalba 2a3ebc884e Optimize pop_1st_bit() take 2
This time we use MSVC intrinsics that are
C wrappers for Intel assembler 'bsf' instruction.

The speed up in node count is around 3%, probably
it does not worth the effort. Anyway this patch
can be useful at least for documentation purposes.

This optimization covers 32 bit systems only.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-21 22:19:07 +02:00
Marco Costalba 01dd46a309 Change the name to Glaurung clone
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-21 11:51:38 +02:00
Marco Costalba e5cc6f6b85 Switch to developer version numbering
Also clean up code while there.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-21 11:23:50 +02:00
Marco Costalba 29b01b6d82 Use optimized pop_1st_bit() only under Windows
Under Linux we have a segfault after a random time,
about a couple of minutes while running the benchmark.

This happens both with gcc and icc, and both with O2
and O3 optimizations.

Disable for Linux until we understand what's the deal.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-20 22:19:54 +02:00
Marco Costalba cde7b30b65 Add new superlinear interpolator
Faster transition and between phases and
more persistent during mid and ending game.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-20 21:56:46 +02:00
Marco Costalba 2dbc8feae3 Finally remove last old C style I/O stuff
Now I/O is fully done with C++ iostreams.

The only exception is in non-windows version
of Bioskey() in misc.cpp

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-20 06:53:06 +02:00
Marco Costalba c034cce27c Convert book.cpp to use C++ I/O
Instead of old C stdio.h

Also small code clean up while there.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-19 13:53:36 +02:00
Marco Costalba 1373a00187 Final touches to pop_1st_bit optimization
This final version is a little bit faster then
previous patch and is a bit cleaned up also.

On 32 bit x86 pop_1st_bit is now more then
two times faster then the original one that
is optimized for 64 bit processors.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-19 05:33:55 +02:00
Marco Costalba 9ae2b69235 Optimize pop_1st_bit() on 32 bits x86
Operations on 64 bits Bitboard types are slow
on x86 compiled with gcc, so optimize this case.

BTW profiling shows that pop_1st_bit() is a
veeery performance critical path!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 16:09:19 +02:00
Marco Costalba 95ce27f926 Ignore non keyboard events in Bioskey()
Filter out mouse and windows type events.

This fix an issue where Glaurung hangs in console mode
under Windows.

To reproduce simply open a console under Windows (cmd.exe),
run "glaurung.exe bench 50 1", this starts benchmarking.
Then hide the windows and show again or clik the mouse
somewhere on the window, this hangs the benchmark
because Boiskey() returns true and poll() calls std::getline()
that hangs waiting for user pressing a return key.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:27:10 +02:00
Marco Costalba 5c4f6f6226 Cleanup poll()
Reshape this function in preparation
for future work.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:27:09 +02:00
Marco Costalba 18860cce40 Improve time managment
If we need some more and we are in time
advantage take it.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:27:09 +02:00
Marco Costalba d583176baf Pass also opponent time to think()
This patch modifies think() signature to accept
also opponent time. This is needed for future
changes to time managment.

Still no functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:27:09 +02:00
Marco Costalba 4c5eaeb363 Disable a stupid and noisy MSVC warning
Remove the crap from compiler messages.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:27:09 +02:00
Marco Costalba 925f97f4e7 Teach Benchmark to read positions from a file
This comes handy to test the engine on different
sets of positions, not only the 15 default ones.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:27:08 +02:00
Marco Costalba f1e245850f Reformat benchmark interface
Prepare to following patches, still no functional
change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:26:39 +02:00
Marco Costalba 2f5012a3eb Fix another conversion warning: Bitboard->int
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:26:31 +02:00
Marco Costalba 94929c36bd Document where we want a uint16_t instead of a uint64_t
This patch removes some conversion warnings and
better describe where we are going to expect a
small integer.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:26:24 +02:00
Marco Costalba a0aa8e760a Use size_t instead of int
Remove some warning.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:26:18 +02:00
Marco Costalba 52487c4f04 MovePicker: simplify move swapping
We don't need a full swap here because once found
and returned the best move will not be used again.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:26:10 +02:00
Marco Costalba 5080e72ea5 Prefer strncpy() to strcpy()
This removes a warning under MSVC++

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:25:55 +02:00
Marco Costalba 295352d04a Fix: "Ponder" option has type bool not int
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-18 12:25:22 +02:00
Marco Costalba 421fd9c3bf Space inflate sp_search_pv
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-09 11:37:27 +02:00
Marco Costalba eacb42092b Space inflate sp_search
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-09 11:15:58 +02:00
Marco Costalba a10c9632a5 Use TT in qsearch
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-09 07:37:46 +02:00
Marco Costalba bc4e937f05 search: fix a bug and clear history update
When a move produces a beta-cut off is marked as
success in history and all the remaining ones are
marked as failures.

The loop across the searched moves, that is used
to register failures, does not skip the good one,
that is then registered as a failure too.

The patch fixes the bug and cleanup the code.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-07 09:38:19 +02:00
Marco Costalba 6c592955e1 Space inflate qsearch
No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-07 08:31:30 +02:00
Marco Costalba d517080ab6 Space inflate search()
Same as previous patch but for search() function.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 18:25:58 +02:00
Marco Costalba b7781e8faa search_pv: spaces inflate
It seems easier to understand, at least to me.

Hopefully no functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 17:12:39 +02:00
Marco Costalba a230dc1404 Split transposition table lookup in a separate function
This slims down the code and is a prerequisite for
future patches.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 15:53:43 +02:00
Marco Costalba c2c0ba875f TranspositionTable: add first_entry() helper
An inline function to retrieve the first TT entry
given a position.

Plus usual whitespace noise.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 12:30:07 +02:00
Marco Costalba 61f41a057d Add simple debug hit rate counter
Add a very simple debug framework to
measure the hit rate of a given condition.

Simply insert macro

dbg_hit_on(x);

Anywhere you want to compute hit rate of condition x
and then call, as example in poll(), function
dbg_print_hit_rate() to print current results.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 12:22:10 +02:00
Marco Costalba d786822b92 TranspositionTable: micro optimize first cycle
In the common case (>95%) tte == replace so skip
additional comparisons in this case.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 12:21:08 +02:00
Marco Costalba 392360e73b TranspositionTable: early skip on an empty TT entry
Instead of going for the whole 4 cycle loop early
skip if TT entry is empty.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 12:20:28 +02:00
Marco Costalba 7c93b171cb TranspositionTable: spaces inflate
No functional change, just a tidy up in
preparation for next patches.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 12:19:29 +02:00
Marco Costalba dad9a1eca7 RootMoveList: inline trivial accessors
Although not performance critical, trivial
accessors can be inlined without any harm.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-06 06:37:00 +02:00
Marco Costalba 731a9f3806 RootMoveList sorting: be compatible with std::sort
sort() and sort_multipv() are almost the same, so
use only one implementation.

Also introduce the natural RootMove::operator<() to
compare the moves instead of compare_root_moves(),
this will allow to use std::sort instead of our
home grown bubble-sort.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-05 09:04:45 +02:00
Marco Costalba bd3fd6501b scan_for_easy_move: we don't need a loop here
Moves are already sorted, so just consider the best
and the second one.

Some trailing whitespace remove noise crept in due
to my editor removes it before to save.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-03 23:33:49 +02:00
Marco Costalba 9ec12da028 Better document RootMoveList c'tor
Also some code tidy-up.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-03 23:29:04 +02:00
Marco Costalba 973eb543a4 Fix a couple of bugs (fallout from previous patches)
After testing and comparing output with standard Glaurung
a couple of issues arised.

A default value was wrong and init_uci_options() missed a couple
of stringify() calls. Also storing bool values as "false" and "true"
needs some care.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 22:05:23 +02:00
Marco Costalba e5068c4734 ucioptions: Fix stringification of a bool
We want stringify a bool as "true" and "false",
not "1" and "0".

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 16:58:02 +02:00
Marco Costalba 35010b4938 Preserve options order when printed
Use a vector instead of a map so that options
are printed according to their original order.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 16:03:01 +02:00
Marco Costalba 6c64f68ccf Rewrite ucioptions.cpp to use C++
Instead of old-style C string functions use standard
library to greatly streamline the implementation.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 14:05:02 +02:00
Marco Costalba 6ef44d4c4e Finally remove UCIInputParser class altogether
Class UCIInputParser is now a typedef of a std::istringstream,
this greatly simplifies the code, especially the many conversions
from string to integer are now handled automatically by the
stream instead of relying on a chunk of C-style atoi() calls.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 08:16:17 +02:00
Marco Costalba d22aeb1cc0 Use a string stream in UCIInputParser
Use a std::istringstream instead of an home
grown string tokenizer code.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 08:06:34 +02:00
Marco Costalba b8e487ff9c Avoid casts to handle isspace() arguments
Use proper standard conversion to deal
with negative values of a char.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2008-09-01 08:03:21 +02:00
60 changed files with 5795 additions and 5913 deletions
+20 -249
View File
@@ -1,21 +1,14 @@
1. Introduction 1. Introduction
--------------- ---------------
Glaurung is a free UCI chess engine. It is not a complete chess Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is
program, but requires some UCI compatible GUI (like XBoard with not a complete chess program, but requires some UCI compatible GUI
PolyGlot, eboard, José, Arena, Sigma Chess, Shredder, Chess Partner, (like XBoard with PolyGlot, eboard, Jos, Arena, Sigma Chess, Shredder,
or Fritz) in order to be used comfortably. Read the documentation for Chess Partner, or Fritz) in order to be used comfortably. Read the
your GUI of choice for information about how to use Glaurung with your documentation for your GUI of choice for information about how to use
GUI. Stockfish with your GUI.
Glaurung 2 is a completely rewritten version of Glaurung. Apart from This version of Stockfish supports up to 8 CPUs, but has not been
the parallel search code, almost no code is shared with Glaurung
1.2.1, the previous stable version. The new program is clearly
stronger than the old, but has a less attractive style of play,
because there are still a few major holes in its evaluation function
(most notably space and development).
This version of Glaurung supports up to 8 CPUs, but has not been
tested thoroughly with more than 2. The program tries to detect the 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 number of CPUs on your computer and set the number of search threads
accordingly, but please be aware that the detection is not always accordingly, but please be aware that the detection is not always
@@ -27,7 +20,7 @@ cores on your computer.
2. Files 2. Files
-------- --------
This distribution of Glaurung consists of the following files: This distribution of Stockfish consists of the following files:
* Readme.txt, the file you are currently reading. * Readme.txt, the file you are currently reading.
@@ -35,57 +28,43 @@ This distribution of Glaurung consists of the following files:
License. License.
* src/, a subdirectory containing the full source code, including a * src/, a subdirectory containing the full source code, including a
Makefile that can be used to compile Glaurung on Unix-like Makefile that can be used to compile Stockfish on Unix-like
systems. For further information about how to compile Glaurung systems. For further information about how to compile Stockfish
yourself, read section 4 below. yourself, read section 4 below.
* MacOSX/, a subdirectory containing excutables for Apple Macintosh * polyglot.ini, for using Stockfish with Fabien Letouzey's PolyGlot
computers running Mac OS X 10.4 (Tiger) and newer. There are two
executables, one for OS X 10.4, and one for OS X 10.5. The
executable for OS X 10.4 will work in 10.5 as well, but the one
for 10.5 is faster.
* LinuxX86/, a subdirectory containing 32-bit and 64-bit x86 GNU/Linux
executables.
* Windows/, a subdirectory containing 32-bit and 64-bit Windows
executables.
* polyglot.ini, for using Glaurung with Fabien Letouzey's PolyGlot
adapter. adapter.
3. Opening books 3. Opening books
---------------- ----------------
This version of Glaurung has experimental support for PolyGlot opening This version of Stockfish has experimental support for PolyGlot opening
books. For information about how to create such books, consult the books. For information about how to create such books, consult the
PolyGlot documentation. The book file can be selected by setting the PolyGlot documentation. The book file can be selected by setting the
UCI parameter "Book File". UCI parameter "Book File".
A book file contributed by Salvo Spitaleri can be found on the
Glaurung web page.
4. Compiling it yourself 4. Compiling it yourself
------------------------ ------------------------
On Unix-like systems, it should usually be possible to compile On Unix-like systems, it should usually be possible to compile
Glaurung directly from the source code with the included Makefile. Stockfish directly from the source code with the included Makefile.
The exception is computer with big-endian CPUs, like PowerPC The exception is computer with big-endian CPUs, like PowerPC
Macintoshes. Some of the bitboard routines in the current version of Macintoshes. Some of the bitboard routines in the current version of
Glaurung are endianness-sensitive, and won't work on a big-endian CPU. Stockfish are endianness-sensitive, and won't work on a big-endian CPU.
Ensuring that the line with #define USE_32BIT_ATTACKS" near the top Ensuring that the line with #define USE_32BIT_ATTACKS" near the top
of bitboard.h is commented out should solve this problem. of bitboard.h is commented out should solve this problem.
Commenting out the line with "#define USE_32BIT_ATTACKS" near the Commenting out the line with "#define USE_32BIT_ATTACKS" near the
There is also a problem with compiling Glaurung on certain 64-bit There is also a problem with compiling Stockfish on certain 64-bit
systems, regardless of the endianness. If Glaurung segfaults systems, regardless of the endianness. If Stockfish segfaults
immediately after startup, try to comment out the line with immediately after startup, try to comment out the line with
"#define USE_FOLDED_BITSCAN" near the beginning of bitboard.h and "#define USE_FOLDED_BITSCAN" near the beginning of bitboard.h and
recompile. recompile.
Finally, even if Glaurung does work without any changes on your Finally, even if Stockfish does work without any changes on your
computer, it might be possible to improve the performance by changing computer, it might be possible to improve the performance by changing
some of the #define directives in bitboard.h. The default settings some of the #define directives in bitboard.h. The default settings
are optimized for 64-bit CPUs. On 32-bit CPUs, it is probably better are optimized for 64-bit CPUs. On 32-bit CPUs, it is probably better
@@ -95,224 +74,17 @@ handheld devices), it is possible to conserve memory by defining
USE_COMPACT_ROOK_ATTACKS. USE_COMPACT_ROOK_ATTACKS.
5. History
----------
2007-05-06: Glaurung 2 - epsilon
--------------------------------
The first public release, and the first version of my new program
which is able to match the old Glaurung 1.2.1 on a single CPU. Lots
of features and chess knowledge is still missing.
2007-05-10: Glaurung 2 - epsilon/2
----------------------------------
This version is very close to 2 - epsilon. The major changes are:
* A number of compatibility problems which appeared when trying to
compile Glaurung 2 - epsilon on various operating systems and CPUs
have been solved.
* Fixed a major bug in the detection of rooks trapped inside a
friendly king.
* Added knowledge about several types of drawn endgames.
* Fixed a few FRC related bugs. FRC now works, but because of
serious holes in the evaluation function the program plays very
badly.
* A slightly more sophisticated king safety evaluation.
2007-06-07: Glaurung 2 - epsilon/3
----------------------------------
The first public version with support for multiple CPUs. Unless you
have a dual-core (or better) computer, use Glaurung with a PolyGlot
book, or runs games with ponder on, you may want to skip this version,
which is almost certainly no stronger than 2 - epsilon/2 when running
on a single CPU. The main changes compared to the previous version
are:
* Parallel search, with support for 1-4 CPUs. The program currently
always allocates a separate pawn hash table and material hash
table for four threads, which is a pure waste of RAM if your
computer has just a single CPU. This will be fixed in a future
version.
* Fixed a bug in book randomization. When using Polyglot books, the
previous version would always select exactly the same move in the
same position after a restart of the program. Thanks to Pavel
Háse for pointing this out.
* Fixed a UCI pondering bug: Glaurung no longer instantly prints its
best move when the maximum depth is reached during a ponder
search, as the previous version did. According to the UCI
protocol, it is not allowed to print the best move before the
engine has received the "stop" or "quit" command.
* Additional search information: The new version displays hash
saturation and the current line(s) of search.
* Several minor bug fixes and optimizations in the search and
evaluation.
2007-06-08: Glaurung 2 - epsilon/4
----------------------------------
A bugfix release, with only a single important change:
* Fixed a very serious pondering bug. As pointed out by Marc
Lacrosse, the previous version would lose on time in almost every
single game with pondering enabled. The new version handles
pondering correctly (or so I hope). When playing with ponder
off, the new version is identical to version 2 - epsilon/3.
2007-06-25: Glaurung 2 - epsilon/5
----------------------------------
Another minor update, including the following improvements and bug
fixes:
* As Werner Schüle discovered, the previous version would sometimes
stop thinking and lose on time right before delivering checkmate
(which is of course a very unfortunate moment to lose on time).
I haven't been able to reproduce Werner's problem on my computer
(probably because I run a different OS), but I have fixed the bug
which I suspect caused the time losses. I hope the time losses
will no longer occur with 2 - epsilon/5.
* The program is now slightly less resource-hungry on computers
with less than 4 CPU cores: The previous version would always
allocated separate pawn and material hash tables for four
threads, even when running on a single-core CPU. The new version
only allocates pawn and material hash tables for the threads
which are actually used.
* A minor reorganization of the memory layout has made the parallel
search about 10% more efficient (at least on my computer, but the
results are likely to vary considerably on different systems).
* The Intel Mac OS X binary is much faster than before, thanks to
the Intel C++ compiler (previous versions were compiled with
GCC).
* A few other very minor bug fixes and enhancements.
2007-11-21: Glaurung 2.0
------------------------
The first stable (or so I hope) and feature-complete version of
Glaurung 2. The following are the main changes compared to the
previous version:
* The license has been changed from GPL version 2 to GPL version 3.
* MultiPV mode.
* Support for the "searchmoves" option in the UCI "go" command.
This means that it is possible to ask Glaurung to exclude some
moves from its analysis, or to restrict its analysis to just a
handful of moves selected by the user. This feature must also be
supported by the GUI under which Glaurung is run. Glaurung's own
GUI does currently not support this feature.
* Chess960 support now works. The program still plays this game
very badly, because of lack of opening knowledge.
* Much more aggressive pruning in the last few plies of the main
search.
* Somewhat better scaling on multi-CPU systems, and support for up
to 8 CPUs.
* Lots of new UCI parameters.
* Improved time managment, especially in games with pondering on
(i.e. when the engine is allowed to think when it's the
opponent's turn to move).
* Some evaluation improvements, and some new basic endgame
patterns.
* The program should no longer crash if the game lasts longer than
1000 plies.
* Many minor bug fixes and other tiny improvements throughout the
code.
* More generously commented code, and numerous cosmetic changes in
coding style.
2007-11-22: Glaurung 2.0.1
--------------------------
* Fixed (or so I hope) a bug which would occasionally cause one of
the search threads to get stuck forever in its idle loop.
2008-05-14: Glaurung 2.1
------------------------
This version contains far too many changes to list them all, but most
of them are minor and cosmetic. The most important and noticable
changes are a lot of new UCI parameters, and many improvements in the
evaluation function. The highlights are:
* Extensive changes in the evaluation function. The addition of
king safety is the most important improvement, but there are also
numerous little improvements elsewhere in the evaluation. There
is still much work left to do in the evaluation function, though.
Space and development are still missing, and the tuning is likely
to be very poor. Currently, the program is optimized for an
entertaining style rather than maximum strength.
* More accurate forward pruning. The previous version used the
null move refutation move to improve the pruning accuracy by
means of a very simple trick: It did not allow pruning of any
moves with the piece captured by the null move refutation move.
In Glaurung 2.1, this has been enhanced: It does not allow
pruning of moves which defend the destination square of the null
move refutation move, nor of moves which block the ray of the
piece in the case that the moving piece in the null move
refutation move is a slider.
* More conservative use of LMR at PV nodes. The previous version
searched the first 6 moves with full depth, 2.1 by default
searches the first 14 moves with full depth (but there is a new
UCI parameter for configuring this). I am not at all sure
whether this is an improvement. More thorough testing is
required.
* Feedback from the evaluation to the search. The search passes an
object of type 'EvalInfo' to the eval, and the eval fills this
struct with various potentially useful information (like the sets
of squares attacked by each piece type, the middle game and
endgame components of the eval, etc.). At the moment, almost
none of this information is actually used by the search. The
only exception is that the evaluation function is now used to
adjust the futility pruning margin in the quiescence search.
* Less extensions. This hurts the programs performance a lot in most
test suites, but I hope it improves the branching factor in deep
searches.
* A very long list of new UCI parameters, especially for tuning the
evaluation.
6. Terms of use 6. Terms of use
--------------- ---------------
Glaurung is free, and distributed under the GNU General Public License Stockfish is free, and distributed under the GNU General Public License
(GPL). Essentially, this means that you are free to do almost exactly (GPL). Essentially, this means that you are free to do almost exactly
what you want with the program, including distributing it among your what you want with the program, including distributing it among your
friends, making it available for download from your web site, selling friends, making it available for download from your web site, selling
it (either by itself or as part of some bigger software package), or 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. using it as the starting point for a software project of your own.
The only real limitation is that whenever you distribute Glaurung in The only real limitation is that whenever you distribute Stockfish in
some way, you must always include the full source code, or a pointer 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 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. source code, these changes must also be made available under the GPL.
@@ -324,5 +96,4 @@ Copying.txt.
7. Feedback 7. Feedback
----------- -----------
The author's e-mail address is tord@glaurungchess.com The author's e-mail address is mcostalba@gmail.com
+14 -9
View File
@@ -1,14 +1,15 @@
# Glaurung, a UCI chess playing engine. # Stockfish, a UCI chess playing engine derived from Glaurung 2.1
# Copyright (C) 2004-2007 Tord Romstad # Copyright (C) 2004-2007 Tord Romstad
# Copyright (C) 2008 Marco Costalba
# This file is part of Glaurung. # This file is part of Stockfish.
# #
# Glaurung is free software: you can redistribute it and/or modify # Stockfish is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Glaurung is distributed in the hope that it will be useful, # Stockfish is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
@@ -21,7 +22,7 @@
### Files ### Files
### ###
EXE = glaurung EXE = stockfish
OBJS = bitboard.o color.o pawns.o material.o endgame.o evaluate.o main.o \ OBJS = bitboard.o color.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 \ misc.o move.o movegen.o history.o movepick.o search.o piece.o \
@@ -43,9 +44,9 @@ clean:
### Compiler: ### Compiler:
### ###
CXX = g++ # CXX = g++
# CXX = g++-4.2 # CXX = g++-4.2
# CXX = icpc CXX = icpc
### ###
@@ -78,7 +79,11 @@ CXXFLAGS += -Wall -g
# General optimization flags. Note that -O2 might be faster than -O3 on some # General optimization flags. Note that -O2 might be faster than -O3 on some
# systems; this requires testing. # systems; this requires testing.
CXXFLAGS += -O3 -fno-exceptions -fomit-frame-pointer -fno-rtti -fstrict-aliasing CXXFLAGS += -O3 -fno-exceptions -fomit-frame-pointer -fno-rtti -fno-strict-aliasing
# Disable most annoying warnings for the Intel C++ compiler
CXXFLAGS += -wd383,869,981
# Compiler optimization flags for the Intel C++ compiler in Mac OS X: # Compiler optimization flags for the Intel C++ compiler in Mac OS X:
@@ -93,7 +98,7 @@ CXXFLAGS += -O3 -fno-exceptions -fomit-frame-pointer -fno-rtti -fstrict-aliasing
# wait 15 minutes for the benchmark to complete). Then do a 'make clean', and # wait 15 minutes for the benchmark to complete). Then do a 'make clean', and
# recompile with -prof_use. # recompile with -prof_use.
# CXXFLAGS += -prof_gen -prof_dir ./profdata # CXXFLAGS += -prof_gen -prof_dir profdata
# CXXFLAGS += -prof_use -prof_dir ./profdata # CXXFLAGS += -prof_use -prof_dir ./profdata
+64 -23
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -20,6 +21,9 @@
//// ////
//// Includes //// Includes
//// ////
#include <fstream>
#include <sstream>
#include <vector>
#include "benchmark.h" #include "benchmark.h"
#include "search.h" #include "search.h"
@@ -31,7 +35,8 @@
//// Variables //// Variables
//// ////
const std::string BenchmarkPositions[15] = { const std::string BenchmarkPositions[] = {
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
"r4rk1/1b2qppp/p1n1p3/1p6/1b1PN3/3BRN2/PP3PPP/R2Q2K1 b - - 7 16", "r4rk1/1b2qppp/p1n1p3/1p6/1b1PN3/3BRN2/PP3PPP/R2Q2K1 b - - 7 16",
"4r1k1/ppq3pp/3b4/2pP4/2Q1p3/4B1P1/PP5P/R5K1 b - - 0 20", "4r1k1/ppq3pp/3b4/2pP4/2Q1p3/4B1P1/PP5P/R5K1 b - - 0 20",
"4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19", "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19",
@@ -54,38 +59,74 @@ const std::string BenchmarkPositions[15] = {
//// Functions //// Functions
//// ////
/// benchmark() runs a simple benchmark by letting Glaurung analyze 15 /// benchmark() runs a simple benchmark by letting Stockfish analyze a set
/// positions for 60 seconds each. There are two parameters; the /// of positions for a given time each. There are four parameters; the
/// transposition table size and the number of search threads that should /// transposition table size, the number of search threads that should
/// be used. The analysis is written to a file named bench.txt. /// 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.
void benchmark(const std::string &ttSize, const std::string &threads) { void benchmark(const std::string& commandLine) {
Position pos;
Move moves[1] = {MOVE_NONE};
int i;
i = atoi(ttSize.c_str()); std::istringstream csVal(commandLine);
if(i < 4 || i > 1024) { std::istringstream csStr(commandLine);
std::string ttSize, threads, fileName;
int val, secsPerPos;
csStr >> ttSize;
csVal >> val;
if (val < 4 || val > 1024)
{
std::cerr << "The hash table size must be between 4 and 1024" << std::endl; std::cerr << "The hash table size must be between 4 and 1024" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
csStr >> threads;
i = atoi(threads.c_str()); csVal >> val;
if(i < 1 || i > THREAD_MAX) { if (val < 1 || val > THREAD_MAX)
{
std::cerr << "The number of threads must be between 1 and " << THREAD_MAX std::cerr << "The number of threads must be between 1 and " << THREAD_MAX
<< std::endl; << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
set_option_value("Hash", ttSize); set_option_value("Hash", ttSize);
set_option_value("Threads", threads); set_option_value("Threads", threads);
set_option_value("OwnBook", "false"); set_option_value("OwnBook", "false");
set_option_value("Use Search Log", "true"); set_option_value("Use Search Log", "true");
set_option_value("Search Log Filename", "bench.txt"); set_option_value("Search Log Filename", "bench.txt");
for(i = 0; i < 15; i++) { csVal >> secsPerPos;
pos.from_fen(BenchmarkPositions[i]); csVal >> fileName;
think(pos, true, false, 0, 0, 0, 0, 0, 60000, moves);
}
std::vector<std::string> positions;
if (fileName != "default")
{
std::ifstream fenFile(fileName.c_str());
if (!fenFile.is_open())
{
std::cerr << "Unable to open positions file " << fileName
<< std::endl;
exit(EXIT_FAILURE);
}
std::string pos;
while (fenFile.good())
{
std::getline(fenFile, pos);
if (!pos.empty())
positions.push_back(pos);
}
fenFile.close();
} else
for (int i = 0; i < 16; i++)
positions.push_back(std::string(BenchmarkPositions[i]));
std::vector<std::string>::iterator it;
for (it = positions.begin(); it != positions.end(); ++it)
{
Move moves[1] = {MOVE_NONE};
int dummy[2] = {0, 0};
Position pos(*it);
think(pos, true, false, 0, dummy, dummy, 0, 0, 0, secsPerPos * 1000, moves);
}
} }
+6 -6
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -31,7 +32,6 @@
//// Prototypes //// Prototypes
//// ////
extern void benchmark(const std::string &ttSize, const std::string &threads); extern void benchmark(const std::string& commandLine);
#endif // !defined(BENCHMARK_H_INCLUDED) #endif // !defined(BENCHMARK_H_INCLUDED)
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+55 -5
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -21,6 +22,16 @@
//// Includes //// Includes
//// ////
#ifdef _MSC_VER
#include <intrin.h>
#ifdef _WIN64
#pragma intrinsic(_BitScanForward64)
#else
#pragma intrinsic(_BitScanForward)
#endif
#define USING_INTRINSICS
#endif
#include <iostream> #include <iostream>
#include "bitboard.h" #include "bitboard.h"
@@ -274,7 +285,7 @@ namespace {
#if defined(USE_COMPACT_ROOK_ATTACKS) #if defined(USE_COMPACT_ROOK_ATTACKS)
void init_file_and_rank_attacks(); void init_file_and_rank_attacks();
#endif #endif
}; }
//// ////
@@ -339,6 +350,43 @@ Square first_1(Bitboard b) {
/// pop_1st_bit() finds and clears the least significant nonzero bit in a /// pop_1st_bit() finds and clears the least significant nonzero bit in a
/// nonzero bitboard. /// nonzero bitboard.
#if defined(USE_32BIT_ATTACKS)
// Use type-punning
union b_union {
Bitboard b;
struct {
uint32_t l;
uint32_t h;
};
};
// WARNING: Needs -fno-strict-aliasing compiler option
Square pop_1st_bit(Bitboard *bb) {
b_union u;
uint32_t b;
u.b = *bb;
if (u.l)
{
b = u.l;
*((uint32_t*)bb) = b & (b - 1);
b ^= (b - 1);
}
else
{
b = u.h;
*((uint32_t*)bb+1) = b & (b - 1); // Little endian only?
b = ~(b ^ (b - 1));
}
return Square(BitTable[(b * 0x783a9b23) >> 26]);
}
#else
Square pop_1st_bit(Bitboard *b) { Square pop_1st_bit(Bitboard *b) {
Bitboard bb = *b ^ (*b - 1); Bitboard bb = *b ^ (*b - 1);
uint32_t fold = int(bb) ^ int(bb >> 32); uint32_t fold = int(bb) ^ int(bb >> 32);
@@ -346,6 +394,8 @@ Square pop_1st_bit(Bitboard *b) {
return Square(BitTable[(fold * 0x783a9b23) >> 26]); return Square(BitTable[(fold * 0x783a9b23) >> 26]);
} }
#endif
#else #else
static const int BitTable[64] = { static const int BitTable[64] = {
+31 -17
View File
@@ -1,13 +1,15 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful,
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -25,6 +27,22 @@
//// Defines //// Defines
//// ////
// Comment following define if you prefer manually adjust
// platform macros defined below
#define AUTO_CONFIGURATION
// Quiet a warning on Intel compiler
#if !defined(__SIZEOF_INT__ )
#define __SIZEOF_INT__ 0
#endif
// Check for 64 bits for different compilers: Intel, MSVC and gcc
#if defined(__x86_64) || defined(_WIN64) || (__SIZEOF_INT__ > 4)
#define IS_64BIT
#endif
#if !defined(AUTO_CONFIGURATION) || defined(IS_64BIT)
//#define USE_COMPACT_ROOK_ATTACKS //#define USE_COMPACT_ROOK_ATTACKS
//#define USE_32BIT_ATTACKS //#define USE_32BIT_ATTACKS
#define USE_FOLDED_BITSCAN #define USE_FOLDED_BITSCAN
@@ -33,7 +51,13 @@
//#define BITCOUNT_SWAR_32 //#define BITCOUNT_SWAR_32
//#define BITCOUNT_LOOP //#define BITCOUNT_LOOP
#else
#define USE_32BIT_ATTACKS
#define USE_FOLDED_BITSCAN
#define BITCOUNT_SWAR_32
#endif
//// ////
//// Includes //// Includes
@@ -127,26 +151,16 @@ extern Bitboard QueenPseudoAttacks[64];
/// Functions for testing whether a given bit is set in a bitboard, and for /// Functions for testing whether a given bit is set in a bitboard, and for
/// setting and clearing bits. /// setting and clearing bits.
inline Bitboard set_mask_bb(Square s) {
// return 1ULL << s;
return SetMaskBB[s];
}
inline Bitboard clear_mask_bb(Square s) {
// return ~set_mask_bb(s);
return ClearMaskBB[s];
}
inline Bitboard bit_is_set(Bitboard b, Square s) { inline Bitboard bit_is_set(Bitboard b, Square s) {
return b & set_mask_bb(s); return b & SetMaskBB[s];
} }
inline void set_bit(Bitboard *b, Square s) { inline void set_bit(Bitboard *b, Square s) {
*b |= set_mask_bb(s); *b |= SetMaskBB[s];
} }
inline void clear_bit(Bitboard *b, Square s) { inline void clear_bit(Bitboard *b, Square s) {
*b &= clear_mask_bb(s); *b &= ClearMaskBB[s];
} }
+62 -48
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -29,7 +30,6 @@
//// ////
#include <cassert> #include <cassert>
#include <cstdio>
#include "book.h" #include "book.h"
#include "mersenne.h" #include "mersenne.h"
@@ -339,8 +339,9 @@ namespace {
uint64_t book_ep_key(const Position &pos); uint64_t book_ep_key(const Position &pos);
uint64_t book_color_key(const Position &pos); uint64_t book_color_key(const Position &pos);
uint64_t read_integer(FILE *file, int size); uint16_t read_integer16(std::ifstream& file);
uint64_t read_integer64(std::ifstream& file);
uint64_t read_integer(std::ifstream& file, int size);
} }
@@ -351,45 +352,44 @@ namespace {
/// Constructor /// Constructor
Book::Book() { Book::Book() : bookSize(0) {}
bookFile = NULL;
bookSize = 0;
}
/// Book::open() opens a book file with a given file name. /// Book::open() opens a book file with a given file name.
void Book::open(const std::string &fName) { void Book::open(const std::string &fName) {
fileName = fName; fileName = fName;
bookFile = fopen(fileName.c_str(), "rb"); bookFile.open(fileName.c_str(), std::ifstream::in | std::ifstream::binary);
if(bookFile != NULL) { if (!bookFile.is_open())
if(fseek(bookFile, 0, SEEK_END) == -1) { return;
bookFile.seekg(0, std::ios::end);
bookSize = bookFile.tellg() / 16;
bookFile.seekg(0, std::ios::beg);
if (!bookFile.good())
{
std::cerr << "Failed to open book file " << fileName << std::endl; std::cerr << "Failed to open book file " << fileName << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
bookSize = ftell(bookFile) / 16;
if(bookSize == -1) {
std::cerr << "Failed to open book file " << fileName << std::endl;
exit(EXIT_FAILURE);
}
}
} }
/// Book::close() closes the currently open book file. /// Book::close() closes the currently open book file.
void Book::close() { void Book::close() {
if(bookFile != NULL && fclose(bookFile) == EOF) {
std::cerr << "Failed to close book file" << std::endl; if (bookFile.is_open())
exit(EXIT_FAILURE); bookFile.close();
}
} }
/// Book::is_open() tests whether a book file has been opened. /// Book::is_open() tests whether a book file has been opened.
bool Book::is_open() const { bool Book::is_open() const {
return bookFile != NULL && bookSize != 0;
return bookFile.is_open() && bookSize != 0;
} }
@@ -397,7 +397,8 @@ bool Book::is_open() const {
/// or the empty string if no book is open. /// or the empty string if no book is open.
const std::string Book::file_name() const { const std::string Book::file_name() const {
return this->is_open()? fileName : "";
return bookFile.is_open() ? fileName : "";
} }
@@ -476,19 +477,21 @@ int Book::find_key(uint64_t key) const {
/// file. The book entry is copied to the first input parameter. /// file. The book entry is copied to the first input parameter.
void Book::read_entry(BookEntry& entry, int n) const { void Book::read_entry(BookEntry& entry, int n) const {
assert(n >= 0 && n < bookSize);
assert(bookFile != NULL);
if(fseek(bookFile, n*16, SEEK_SET) == -1) { assert(n >= 0 && n < bookSize);
assert(bookFile.is_open());
bookFile.seekg(n*16, std::ios_base::beg);
if (!bookFile.good())
{
std::cerr << "Failed to read book entry at index " << n << std::endl; std::cerr << "Failed to read book entry at index " << n << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
entry.key = read_integer64(bookFile);
entry.key = read_integer(bookFile, 8); entry.move = read_integer16(bookFile);
entry.move = read_integer(bookFile, 2); entry.count = read_integer16(bookFile);
entry.count = read_integer(bookFile, 2); entry.n = read_integer16(bookFile);
entry.n = read_integer(bookFile, 2); entry.sum = read_integer16(bookFile);
entry.sum = read_integer(bookFile, 2);
} }
@@ -554,25 +557,36 @@ namespace {
} }
uint64_t read_integer(FILE *file, int size) { uint16_t read_integer16(std::ifstream& file) {
uint64_t n = 0ULL;;
int i;
int b;
assert(file != NULL); uint64_t n = read_integer(file, 2);
assert(size > 0 && size <= 8); assert(n == (uint16_t)n);
return (uint16_t)n;
}
for(i = 0; i < size; i++) {
b = fgetc(file); uint64_t read_integer64(std::ifstream& file) {
if(b == EOF) {
return read_integer(file, 8);
}
uint64_t read_integer(std::ifstream& file, int size) {
char buf[8];
file.read(buf, size);
if (!file.good())
{
std::cerr << "Failed to read " << size << " bytes from book file" std::cerr << "Failed to read " << size << " bytes from book file"
<< std::endl; << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
assert(b >= 0 && b < 256); // Numbers are stored in little endian format
n = (n << 8) | b; uint64_t n = 0ULL;
} for (int i = 0; i < size; i++)
n = (n << 8) + (unsigned char)buf[i];
return n; return n;
} }
} }
+7 -5
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -32,6 +33,7 @@
//// Includes //// Includes
//// ////
#include <fstream>
#include <string> #include <string>
#include "move.h" #include "move.h"
@@ -74,7 +76,7 @@ private:
void read_entry(BookEntry &entry, int n) const; void read_entry(BookEntry &entry, int n) const;
std::string fileName; std::string fileName;
FILE *bookFile; mutable std::ifstream bookFile;
int bookSize; int bookSize;
}; };
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+84 -83
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -212,19 +213,19 @@ KPKPScalingFunction::KPKPScalingFunction(Color c) : ScalingFunction(c) { }
Value KXKEvaluationFunction::apply(const Position &pos) { Value KXKEvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.pawn_count(weakerSide) == Value(0)); assert(pos.piece_count(weakerSide, PAWN) == Value(0));
Square winnerKSq = pos.king_square(strongerSide); Square winnerKSq = pos.king_square(strongerSide);
Square loserKSq = pos.king_square(weakerSide); Square loserKSq = pos.king_square(weakerSide);
Value result = Value result =
pos.non_pawn_material(strongerSide) + pos.non_pawn_material(strongerSide) +
pos.pawn_count(strongerSide) * PawnValueEndgame + pos.piece_count(strongerSide, PAWN) * PawnValueEndgame +
mate_table(loserKSq) + mate_table(loserKSq) +
distance_bonus(square_distance(winnerKSq, loserKSq)); distance_bonus(square_distance(winnerKSq, loserKSq));
if(pos.queen_count(strongerSide) > 0 || pos.rook_count(strongerSide) > 0 || if(pos.piece_count(strongerSide, QUEEN) > 0 || pos.piece_count(strongerSide, ROOK) > 0 ||
pos.bishop_count(strongerSide) > 1) pos.piece_count(strongerSide, BISHOP) > 1)
// TODO: check for two equal-colored bishops! // TODO: check for two equal-colored bishops!
result += VALUE_KNOWN_WIN; result += VALUE_KNOWN_WIN;
@@ -238,16 +239,16 @@ Value KXKEvaluationFunction::apply(const Position &pos) {
Value KBNKEvaluationFunction::apply(const Position &pos) { Value KBNKEvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.pawn_count(weakerSide) == Value(0)); assert(pos.piece_count(weakerSide, PAWN) == Value(0));
assert(pos.non_pawn_material(strongerSide) == assert(pos.non_pawn_material(strongerSide) ==
KnightValueMidgame + BishopValueMidgame); KnightValueMidgame + BishopValueMidgame);
assert(pos.bishop_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, BISHOP) == 1);
assert(pos.knight_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, KNIGHT) == 1);
assert(pos.pawn_count(strongerSide) == 0); assert(pos.piece_count(strongerSide, PAWN) == 0);
Square winnerKSq = pos.king_square(strongerSide); Square winnerKSq = pos.king_square(strongerSide);
Square loserKSq = pos.king_square(weakerSide); Square loserKSq = pos.king_square(weakerSide);
Square bishopSquare = pos.bishop_list(strongerSide, 0); Square bishopSquare = pos.piece_list(strongerSide, BISHOP, 0);
if(square_color(bishopSquare) == BLACK) { if(square_color(bishopSquare) == BLACK) {
winnerKSq = flop_square(winnerKSq); winnerKSq = flop_square(winnerKSq);
@@ -268,8 +269,8 @@ Value KPKEvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == Value(0)); assert(pos.non_pawn_material(strongerSide) == Value(0));
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.pawn_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Square wksq, bksq, wpsq; Square wksq, bksq, wpsq;
Color stm; Color stm;
@@ -277,13 +278,13 @@ Value KPKEvaluationFunction::apply(const Position &pos) {
if(strongerSide == WHITE) { if(strongerSide == WHITE) {
wksq = pos.king_square(WHITE); wksq = pos.king_square(WHITE);
bksq = pos.king_square(BLACK); bksq = pos.king_square(BLACK);
wpsq = pos.pawn_list(WHITE, 0); wpsq = pos.piece_list(WHITE, PAWN, 0);
stm = pos.side_to_move(); stm = pos.side_to_move();
} }
else { else {
wksq = flip_square(pos.king_square(BLACK)); wksq = flip_square(pos.king_square(BLACK));
bksq = flip_square(pos.king_square(WHITE)); bksq = flip_square(pos.king_square(WHITE));
wpsq = flip_square(pos.pawn_list(BLACK, 0)); wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
stm = opposite_color(pos.side_to_move()); stm = opposite_color(pos.side_to_move());
} }
@@ -311,17 +312,17 @@ Value KPKEvaluationFunction::apply(const Position &pos) {
Value KRKPEvaluationFunction::apply(const Position &pos) { Value KRKPEvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.pawn_count(strongerSide) == 0); assert(pos.piece_count(strongerSide, PAWN) == 0);
assert(pos.non_pawn_material(weakerSide) == 0); assert(pos.non_pawn_material(weakerSide) == 0);
assert(pos.pawn_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, PAWN) == 1);
Square wksq, wrsq, bksq, bpsq; Square wksq, wrsq, bksq, bpsq;
int tempo = (pos.side_to_move() == strongerSide); int tempo = (pos.side_to_move() == strongerSide);
wksq = pos.king_square(strongerSide); wksq = pos.king_square(strongerSide);
wrsq = pos.rook_list(strongerSide, 0); wrsq = pos.piece_list(strongerSide, ROOK, 0);
bksq = pos.king_square(weakerSide); bksq = pos.king_square(weakerSide);
bpsq = pos.pawn_list(weakerSide, 0); bpsq = pos.piece_list(weakerSide, PAWN, 0);
if(strongerSide == BLACK) { if(strongerSide == BLACK) {
wksq = flip_square(wksq); wksq = flip_square(wksq);
@@ -366,10 +367,10 @@ Value KRKPEvaluationFunction::apply(const Position &pos) {
Value KRKBEvaluationFunction::apply(const Position &pos) { Value KRKBEvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.pawn_count(strongerSide) == 0); assert(pos.piece_count(strongerSide, PAWN) == 0);
assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame); assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
assert(pos.bishop_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, BISHOP) == 1);
Value result = mate_table(pos.king_square(weakerSide)); Value result = mate_table(pos.king_square(weakerSide));
return (pos.side_to_move() == strongerSide)? result : -result; return (pos.side_to_move() == strongerSide)? result : -result;
@@ -382,13 +383,13 @@ Value KRKBEvaluationFunction::apply(const Position &pos) {
Value KRKNEvaluationFunction::apply(const Position &pos) { Value KRKNEvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.pawn_count(strongerSide) == 0); assert(pos.piece_count(strongerSide, PAWN) == 0);
assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
assert(pos.knight_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, KNIGHT) == 1);
Square defendingKSq = pos.king_square(weakerSide); Square defendingKSq = pos.king_square(weakerSide);
Square nSq = pos.knight_list(weakerSide, 0); Square nSq = pos.piece_list(weakerSide, KNIGHT, 0);
Value result = Value(10) + mate_table(defendingKSq) + Value result = Value(10) + mate_table(defendingKSq) +
krkn_king_knight_distance_penalty(square_distance(defendingKSq, nSq)); krkn_king_knight_distance_penalty(square_distance(defendingKSq, nSq));
@@ -405,9 +406,9 @@ Value KRKNEvaluationFunction::apply(const Position &pos) {
Value KQKREvaluationFunction::apply(const Position &pos) { Value KQKREvaluationFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame); assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
assert(pos.pawn_count(strongerSide) == 0); assert(pos.piece_count(strongerSide, PAWN) == 0);
assert(pos.non_pawn_material(weakerSide) == RookValueMidgame); assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Square winnerKSq = pos.king_square(strongerSide); Square winnerKSq = pos.king_square(strongerSide);
Square loserKSq = pos.king_square(weakerSide); Square loserKSq = pos.king_square(weakerSide);
@@ -427,20 +428,20 @@ Value KQKREvaluationFunction::apply(const Position &pos) {
ScaleFactor KBPKScalingFunction::apply(const Position &pos) { ScaleFactor KBPKScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.bishop_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, BISHOP) == 1);
assert(pos.pawn_count(strongerSide) >= 1); assert(pos.piece_count(strongerSide, PAWN) >= 1);
// No assertions about the material of weakerSide, because we want draws to // No assertions about the material of weakerSide, because we want draws to
// be detected even when the weaker side has some pawns. // be detected even when the weaker side has some pawns.
Bitboard pawns = pos.pawns(strongerSide); Bitboard pawns = pos.pawns(strongerSide);
File pawnFile = square_file(pos.pawn_list(strongerSide, 0)); File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0));
if((pawnFile == FILE_A || pawnFile == FILE_H) && if((pawnFile == FILE_A || pawnFile == FILE_H) &&
(pawns & ~file_bb(pawnFile)) == EmptyBoardBB) { (pawns & ~file_bb(pawnFile)) == EmptyBoardBB) {
// All pawns are on a single rook file. // All pawns are on a single rook file.
Square bishopSq = pos.bishop_list(strongerSide, 0); Square bishopSq = pos.piece_list(strongerSide, BISHOP, 0);
Square queeningSq = Square queeningSq =
relative_square(strongerSide, make_square(pawnFile, RANK_8)); relative_square(strongerSide, make_square(pawnFile, RANK_8));
Square kingSq = pos.king_square(weakerSide); Square kingSq = pos.king_square(weakerSide);
@@ -464,7 +465,7 @@ ScaleFactor KBPKScalingFunction::apply(const Position &pos) {
// If the defending king has distance 1 to the promotion square or // If the defending king has distance 1 to the promotion square or
// is placed somewhere in front of the pawn, it's a draw. // is placed somewhere in front of the pawn, it's a draw.
if(square_distance(kingSq, queeningSq) <= 1 || if(square_distance(kingSq, queeningSq) <= 1 ||
pawn_rank(strongerSide, kingSq) >= rank) relative_rank(strongerSide, kingSq) >= rank)
return ScaleFactor(0); return ScaleFactor(0);
} }
} }
@@ -479,18 +480,18 @@ ScaleFactor KBPKScalingFunction::apply(const Position &pos) {
ScaleFactor KQKRPScalingFunction::apply(const Position &pos) { ScaleFactor KQKRPScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame); assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
assert(pos.queen_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, QUEEN) == 1);
assert(pos.pawn_count(strongerSide) == 0); assert(pos.piece_count(strongerSide, PAWN) == 0);
assert(pos.rook_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, ROOK) == 1);
assert(pos.pawn_count(weakerSide) >= 1); assert(pos.piece_count(weakerSide, PAWN) >= 1);
Square kingSq = pos.king_square(weakerSide); Square kingSq = pos.king_square(weakerSide);
if(pawn_rank(weakerSide, kingSq) <= RANK_2 && if(relative_rank(weakerSide, kingSq) <= RANK_2 &&
pawn_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4 &&
(pos.rooks(weakerSide) & relative_rank_bb(weakerSide, RANK_3)) && (pos.rooks(weakerSide) & relative_rank_bb(weakerSide, RANK_3)) &&
(pos.pawns(weakerSide) & relative_rank_bb(weakerSide, RANK_2)) && (pos.pawns(weakerSide) & relative_rank_bb(weakerSide, RANK_2)) &&
(pos.king_attacks(kingSq) & pos.pawns(weakerSide))) { (pos.piece_attacks<KING>(kingSq) & pos.pawns(weakerSide))) {
Square rsq = pos.rook_list(weakerSide, 0); Square rsq = pos.piece_list(weakerSide, ROOK, 0);
if(pos.pawn_attacks(strongerSide, rsq) & pos.pawns(weakerSide)) if(pos.pawn_attacks(strongerSide, rsq) & pos.pawns(weakerSide))
return ScaleFactor(0); return ScaleFactor(0);
} }
@@ -508,15 +509,15 @@ ScaleFactor KQKRPScalingFunction::apply(const Position &pos) {
ScaleFactor KRPKRScalingFunction::apply(const Position &pos) { ScaleFactor KRPKRScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.pawn_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1);
assert(pos.non_pawn_material(weakerSide) == RookValueMidgame); assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Square wksq = pos.king_square(strongerSide); Square wksq = pos.king_square(strongerSide);
Square wrsq = pos.rook_list(strongerSide, 0); Square wrsq = pos.piece_list(strongerSide, ROOK, 0);
Square wpsq = pos.pawn_list(strongerSide, 0); Square wpsq = pos.piece_list(strongerSide, PAWN, 0);
Square bksq = pos.king_square(weakerSide); Square bksq = pos.king_square(weakerSide);
Square brsq = pos.rook_list(weakerSide, 0); Square brsq = pos.piece_list(weakerSide, ROOK, 0);
// Orient the board in such a way that the stronger side is white, and the // Orient the board in such a way that the stronger side is white, and the
// pawn is on the left half of the board: // pawn is on the left half of the board:
@@ -613,12 +614,12 @@ ScaleFactor KRPKRScalingFunction::apply(const Position &pos) {
ScaleFactor KRPPKRPScalingFunction::apply(const Position &pos) { ScaleFactor KRPPKRPScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
assert(pos.pawn_count(strongerSide) == 2); assert(pos.piece_count(strongerSide, PAWN) == 2);
assert(pos.non_pawn_material(weakerSide) == RookValueMidgame); assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
assert(pos.pawn_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, PAWN) == 1);
Square wpsq1 = pos.pawn_list(strongerSide, 0); Square wpsq1 = pos.piece_list(strongerSide, PAWN, 0);
Square wpsq2 = pos.pawn_list(strongerSide, 1); Square wpsq2 = pos.piece_list(strongerSide, PAWN, 1);
Square bksq = pos.king_square(weakerSide); Square bksq = pos.king_square(weakerSide);
// Does the stronger side have a passed pawn? // Does the stronger side have a passed pawn?
@@ -626,10 +627,10 @@ ScaleFactor KRPPKRPScalingFunction::apply(const Position &pos) {
pos.pawn_is_passed(strongerSide, wpsq2)) pos.pawn_is_passed(strongerSide, wpsq2))
return SCALE_FACTOR_NONE; return SCALE_FACTOR_NONE;
Rank r = Max(pawn_rank(strongerSide, wpsq1), pawn_rank(strongerSide, wpsq2)); Rank r = Max(relative_rank(strongerSide, wpsq1), relative_rank(strongerSide, wpsq2));
if(file_distance(bksq, wpsq1) <= 1 && file_distance(bksq, wpsq2) <= 1 if(file_distance(bksq, wpsq1) <= 1 && file_distance(bksq, wpsq2) <= 1
&& pawn_rank(strongerSide, bksq) > r) { && relative_rank(strongerSide, bksq) > r) {
switch(r) { switch(r) {
case RANK_2: return ScaleFactor(10); case RANK_2: return ScaleFactor(10);
@@ -651,9 +652,9 @@ ScaleFactor KRPPKRPScalingFunction::apply(const Position &pos) {
ScaleFactor KPsKScalingFunction::apply(const Position &pos) { ScaleFactor KPsKScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == Value(0)); assert(pos.non_pawn_material(strongerSide) == Value(0));
assert(pos.pawn_count(strongerSide) >= 2); assert(pos.piece_count(strongerSide, PAWN) >= 2);
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Bitboard pawns = pos.pawns(strongerSide); Bitboard pawns = pos.pawns(strongerSide);
@@ -694,22 +695,22 @@ ScaleFactor KPsKScalingFunction::apply(const Position &pos) {
ScaleFactor KBPKBScalingFunction::apply(const Position &pos) { ScaleFactor KBPKBScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.bishop_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, BISHOP) == 1);
assert(pos.pawn_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1);
assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame); assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
assert(pos.bishop_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, BISHOP) == 1);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Square pawnSq = pos.pawn_list(strongerSide, 0); Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
Square strongerBishopSq = pos.bishop_list(strongerSide, 0); Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
Square weakerBishopSq = pos.bishop_list(weakerSide, 0); Square weakerBishopSq = pos.piece_list(weakerSide, BISHOP, 0);
Square weakerKingSq = pos.king_square(weakerSide); Square weakerKingSq = pos.king_square(weakerSide);
// Case 1: Defending king blocks the pawn, and cannot be driven away. // Case 1: Defending king blocks the pawn, and cannot be driven away.
if(square_file(weakerKingSq) == square_file(pawnSq) if(square_file(weakerKingSq) == square_file(pawnSq)
&& pawn_rank(strongerSide, pawnSq) < pawn_rank(strongerSide, weakerKingSq) && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
&& (square_color(weakerKingSq) != square_color(strongerBishopSq) && (square_color(weakerKingSq) != square_color(strongerBishopSq)
|| pawn_rank(strongerSide, weakerKingSq) <= RANK_6)) || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
return ScaleFactor(0); return ScaleFactor(0);
// Case 2: Opposite colored bishops. // Case 2: Opposite colored bishops.
@@ -725,14 +726,14 @@ ScaleFactor KBPKBScalingFunction::apply(const Position &pos) {
// These rules are probably not perfect, but in practice they work // These rules are probably not perfect, but in practice they work
// reasonably well. // reasonably well.
if(pawn_rank(strongerSide, pawnSq) <= RANK_5) if(relative_rank(strongerSide, pawnSq) <= RANK_5)
return ScaleFactor(0); return ScaleFactor(0);
else { else {
Bitboard ray = Bitboard ray =
ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S); ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S);
if(ray & pos.kings(weakerSide)) if(ray & pos.kings(weakerSide))
return ScaleFactor(0); return ScaleFactor(0);
if((pos.bishop_attacks(weakerBishopSq) & ray) if((pos.piece_attacks<BISHOP>(weakerBishopSq) & ray)
&& square_distance(weakerBishopSq, pawnSq) >= 3) && square_distance(weakerBishopSq, pawnSq) >= 3)
return ScaleFactor(0); return ScaleFactor(0);
} }
@@ -748,20 +749,20 @@ ScaleFactor KBPKBScalingFunction::apply(const Position &pos) {
ScaleFactor KBPKNScalingFunction::apply(const Position &pos) { ScaleFactor KBPKNScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.bishop_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, BISHOP) == 1);
assert(pos.pawn_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1);
assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
assert(pos.knight_count(weakerSide) == 1); assert(pos.piece_count(weakerSide, KNIGHT) == 1);
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Square pawnSq = pos.pawn_list(strongerSide, 0); Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
Square strongerBishopSq = pos.bishop_list(strongerSide, 0); Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
Square weakerKingSq = pos.king_square(weakerSide); Square weakerKingSq = pos.king_square(weakerSide);
if(square_file(weakerKingSq) == square_file(pawnSq) if(square_file(weakerKingSq) == square_file(pawnSq)
&& pawn_rank(strongerSide, pawnSq) < pawn_rank(strongerSide, weakerKingSq) && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
&& (square_color(weakerKingSq) != square_color(strongerBishopSq) && (square_color(weakerKingSq) != square_color(strongerBishopSq)
|| pawn_rank(strongerSide, weakerKingSq) <= RANK_6)) || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
return ScaleFactor(0); return ScaleFactor(0);
return SCALE_FACTOR_NONE; return SCALE_FACTOR_NONE;
@@ -774,12 +775,12 @@ ScaleFactor KBPKNScalingFunction::apply(const Position &pos) {
ScaleFactor KNPKScalingFunction::apply(const Position &pos) { ScaleFactor KNPKScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame); assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame);
assert(pos.knight_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, KNIGHT) == 1);
assert(pos.pawn_count(strongerSide) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1);
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.pawn_count(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Square pawnSq = pos.pawn_list(strongerSide, 0); Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
Square weakerKingSq = pos.king_square(weakerSide); Square weakerKingSq = pos.king_square(weakerSide);
if(pawnSq == relative_square(strongerSide, SQ_A7) && if(pawnSq == relative_square(strongerSide, SQ_A7) &&
@@ -804,8 +805,8 @@ ScaleFactor KNPKScalingFunction::apply(const Position &pos) {
ScaleFactor KPKPScalingFunction::apply(const Position &pos) { ScaleFactor KPKPScalingFunction::apply(const Position &pos) {
assert(pos.non_pawn_material(strongerSide) == Value(0)); assert(pos.non_pawn_material(strongerSide) == Value(0));
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.pawn_count(WHITE) == 1); assert(pos.piece_count(WHITE, PAWN) == 1);
assert(pos.pawn_count(BLACK) == 1); assert(pos.piece_count(BLACK, PAWN) == 1);
Square wksq, bksq, wpsq; Square wksq, bksq, wpsq;
Color stm; Color stm;
@@ -813,13 +814,13 @@ ScaleFactor KPKPScalingFunction::apply(const Position &pos) {
if(strongerSide == WHITE) { if(strongerSide == WHITE) {
wksq = pos.king_square(WHITE); wksq = pos.king_square(WHITE);
bksq = pos.king_square(BLACK); bksq = pos.king_square(BLACK);
wpsq = pos.pawn_list(WHITE, 0); wpsq = pos.piece_list(WHITE, PAWN, 0);
stm = pos.side_to_move(); stm = pos.side_to_move();
} }
else { else {
wksq = flip_square(pos.king_square(BLACK)); wksq = flip_square(pos.king_square(BLACK));
bksq = flip_square(pos.king_square(WHITE)); bksq = flip_square(pos.king_square(WHITE));
wpsq = flip_square(pos.pawn_list(BLACK, 0)); wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
stm = opposite_color(pos.side_to_move()); stm = opposite_color(pos.side_to_move());
} }
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+422 -442
View File
File diff suppressed because it is too large Load Diff
+23 -21
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -56,31 +57,32 @@ struct EvalInfo {
Bitboard attackedBy[2][8]; Bitboard attackedBy[2][8];
Bitboard attacked_by(Color c) const { return attackedBy[c][0]; } Bitboard attacked_by(Color c) const { return attackedBy[c][0]; }
Bitboard attacked_by(Color c, PieceType pt) const { return attackedBy[c][pt]; } Bitboard attacked_by(Color c, PieceType pt) const { return attackedBy[c][pt]; }
// attackZone[color] is the zone around the enemy king which is considered
// kingZone[color] is the zone around the enemy king which is considered
// by the king safety evaluation. This consists of the squares directly // 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) // 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 // squares two ranks in front of the king. For instance, if black's king
// is on g8, attackZone[WHITE] is a bitboard containing the squares f8, h8, // is on g8, kingZone[WHITE] is a bitboard containing the squares f8, h8,
// f7, g7, h7, f6, g6 and h6. // f7, g7, h7, f6, g6 and h6.
Bitboard attackZone[2]; Bitboard kingZone[2];
// attackCount[color] is the number of pieces of the given color which // kingAttackersCount[color] is the number of pieces of the given color
// attack a square adjacent to the enemy king. // which attack a square in the kingZone of the enemy king.
int attackCount[2]; int kingAttackersCount[2];
// attackWeight[color] is the sum of the "weight" of the pieces of the given // kingAttackersWeight[color] is the sum of the "weight" of the pieces of the
// color which attack a square adjacent to the enemy king. The weights of // given color which attack a square in the kingZone of the enemy king. The
// the individual piece types are given by the variables QueenAttackWeight, // weights of the individual piece types are given by the variables
// RookAttackWeight, BishopAttackWeight and KnightAttackWeight in // QueenAttackWeight, RookAttackWeight, BishopAttackWeight and
// evaluate.cpp. // KnightAttackWeight in evaluate.cpp
int attackWeight[2]; int kingAttackersWeight[2];
// attacked[color] is the number of enemy piece attacks to squares directly // kingAdjacentZoneAttacksCount[color] is the number of attacks to squares
// adjacent to the king of the given color. Pieces which attack more // directly adjacent to the king of the given color. Pieces which attack
// than one square are counted multiple times. For instance, if black's // 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 // king is on g8 and there's a white knight on g5, this knight adds
// 2 to attacked[BLACK]. // 2 to kingAdjacentZoneAttacksCount[BLACK].
int attacked[2]; int kingAdjacentZoneAttacksCount[2];
// mateThreat[color] is a move for the given side which gives a direct mate. // mateThreat[color] is a move for the given side which gives a direct mate.
Move mateThreat[2]; Move mateThreat[2];
+6 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -22,6 +23,7 @@
//// ////
#include <cassert> #include <cassert>
#include <cstring>
#include "history.h" #include "history.h"
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+19 -18
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -21,7 +22,6 @@
//// Includes //// Includes
//// ////
#include <cstdlib>
#include <iostream> #include <iostream>
#include "benchmark.h" #include "benchmark.h"
@@ -39,6 +39,7 @@
#include "uci.h" #include "uci.h"
#include "ucioption.h" #include "ucioption.h"
using std::string;
//// ////
//// Functions //// Functions
@@ -47,8 +48,6 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Disable IO buffering // Disable IO buffering
setbuf(stdin, NULL);
setbuf(stdout, NULL);
std::cout.rdbuf()->pubsetbuf(NULL, 0); std::cout.rdbuf()->pubsetbuf(NULL, 0);
std::cin.rdbuf()->pubsetbuf(NULL, 0); std::cin.rdbuf()->pubsetbuf(NULL, 0);
@@ -60,32 +59,34 @@ int main(int argc, char *argv[]) {
init_uci_options(); init_uci_options();
Position::init_zobrist(); Position::init_zobrist();
Position::init_piece_square_tables(); Position::init_piece_square_tables();
MaterialInfo::init();
MovePicker::init_phase_table(); MovePicker::init_phase_table();
init_eval(1); init_eval(1);
init_bitbases(); init_bitbases();
init_threads(); init_threads();
// Make random number generation less deterministic, for book moves // Make random number generation less deterministic, for book moves
int i = abs(get_system_time() % 10000); for (int i = abs(get_system_time() % 10000); i > 0; i--)
for(int j = 0; j < i; j++)
genrand_int32(); genrand_int32();
// Process command line arguments // Process command line arguments
if(argc >= 2) { if (argc >= 2 && string(argv[1]) == "bench")
if(std::string(argv[1]) == "bench") { {
if(argc != 4) { if (argc < 4 || argc > 6)
std::cout << "Usage: glaurung bench <hash> <threads>" << std::endl; {
std::cout << "Usage: glaurung bench <hash size> <threads> "
<< "[time = 60s] [fen positions file = default]"
<< std::endl;
exit(0); exit(0);
} }
benchmark(std::string(argv[2]), std::string(argv[3])); string time = argc > 4 ? argv[4] : "60";
string fen = argc > 5 ? argv[5] : "default";
benchmark(string(argv[2]) + " " + string(argv[3]) + " " + time + " " + fen);
return 0; return 0;
} }
}
// Print copyright notice // Print copyright notice
std::cout << engine_name() << ". " std::cout << engine_name() << ". Copyright (C) "
<< "Copyright (C) 2004-2008 Tord Romstad." << "2004-2008 Tord Romstad, Marco Costalba. "
<< std::endl; << std::endl;
// Enter UCI mode // Enter UCI mode
+197 -251
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -22,6 +23,8 @@
//// ////
#include <cassert> #include <cassert>
#include <cstring>
#include <map>
#include "material.h" #include "material.h"
@@ -35,20 +38,37 @@ namespace {
const Value BishopPairMidgameBonus = Value(100); const Value BishopPairMidgameBonus = Value(100);
const Value BishopPairEndgameBonus = Value(100); const Value BishopPairEndgameBonus = Value(100);
Key KPKMaterialKey, KKPMaterialKey;
Key KBNKMaterialKey, KKBNMaterialKey;
Key KRKPMaterialKey, KPKRMaterialKey;
Key KRKBMaterialKey, KBKRMaterialKey;
Key KRKNMaterialKey, KNKRMaterialKey;
Key KQKRMaterialKey, KRKQMaterialKey;
Key KRPKRMaterialKey, KRKRPMaterialKey;
Key KRPPKRPMaterialKey, KRPKRPPMaterialKey;
Key KNNKMaterialKey, KKNNMaterialKey; Key KNNKMaterialKey, KKNNMaterialKey;
Key KBPKBMaterialKey, KBKBPMaterialKey;
Key KBPKNMaterialKey, KNKBPMaterialKey;
Key KNPKMaterialKey, KKNPMaterialKey;
Key KPKPMaterialKey;
}
////
//// Classes
////
/// See header for a class description. It is declared here to avoid
/// to include <map> in the header file.
class EndgameFunctions {
public:
EndgameFunctions();
EndgameEvaluationFunction* getEEF(Key key) const;
ScalingFunction* getESF(Key key, Color* c) const;
private:
void add(Key k, EndgameEvaluationFunction* f);
void add(Key k, Color c, ScalingFunction* f);
struct ScalingInfo
{
Color col;
ScalingFunction* fun;
};
std::map<Key, EndgameEvaluationFunction*> EEFmap;
std::map<Key, ScalingInfo> ESFmap;
}; };
@@ -56,115 +76,30 @@ namespace {
//// Functions //// Functions
//// ////
/// MaterialInfo::init() is called during program initialization. It
/// precomputes material hash keys for a few basic endgames, in order
/// to make it easy to recognize such endgames when they occur.
void MaterialInfo::init() { /// Constructor for the MaterialInfoTable class
KPKMaterialKey = Position::zobMaterial[WHITE][PAWN][1];
KKPMaterialKey = Position::zobMaterial[BLACK][PAWN][1];
KBNKMaterialKey =
Position::zobMaterial[WHITE][BISHOP][1] ^
Position::zobMaterial[WHITE][KNIGHT][1];
KKBNMaterialKey =
Position::zobMaterial[BLACK][BISHOP][1] ^
Position::zobMaterial[BLACK][KNIGHT][1];
KRKPMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[BLACK][PAWN][1];
KPKRMaterialKey =
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[BLACK][ROOK][1];
KRKBMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[BLACK][BISHOP][1];
KBKRMaterialKey =
Position::zobMaterial[WHITE][BISHOP][1] ^
Position::zobMaterial[BLACK][ROOK][1];
KRKNMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[BLACK][KNIGHT][1];
KNKRMaterialKey =
Position::zobMaterial[WHITE][KNIGHT][1] ^
Position::zobMaterial[BLACK][ROOK][1];
KQKRMaterialKey =
Position::zobMaterial[WHITE][QUEEN][1] ^
Position::zobMaterial[BLACK][ROOK][1];
KRKQMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[BLACK][QUEEN][1];
KRPKRMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[BLACK][ROOK][1];
KRKRPMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[BLACK][ROOK][1] ^
Position::zobMaterial[BLACK][PAWN][1];
KRPPKRPMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[WHITE][PAWN][2] ^
Position::zobMaterial[BLACK][ROOK][1] ^
Position::zobMaterial[BLACK][PAWN][1];
KRPKRPPMaterialKey =
Position::zobMaterial[WHITE][ROOK][1] ^
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[BLACK][ROOK][1] ^
Position::zobMaterial[BLACK][PAWN][1] ^
Position::zobMaterial[BLACK][PAWN][2];
KNNKMaterialKey =
Position::zobMaterial[WHITE][KNIGHT][1] ^
Position::zobMaterial[WHITE][KNIGHT][2];
KKNNMaterialKey =
Position::zobMaterial[BLACK][KNIGHT][1] ^
Position::zobMaterial[BLACK][KNIGHT][2];
KBPKBMaterialKey =
Position::zobMaterial[WHITE][BISHOP][1] ^
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[BLACK][BISHOP][1];
KBKBPMaterialKey =
Position::zobMaterial[WHITE][BISHOP][1] ^
Position::zobMaterial[BLACK][BISHOP][1] ^
Position::zobMaterial[BLACK][PAWN][1];
KBPKNMaterialKey =
Position::zobMaterial[WHITE][BISHOP][1] ^
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[BLACK][KNIGHT][1];
KNKBPMaterialKey =
Position::zobMaterial[WHITE][KNIGHT][1] ^
Position::zobMaterial[BLACK][BISHOP][1] ^
Position::zobMaterial[BLACK][PAWN][1];
KNPKMaterialKey =
Position::zobMaterial[WHITE][KNIGHT][1] ^
Position::zobMaterial[WHITE][PAWN][1];
KKNPMaterialKey =
Position::zobMaterial[BLACK][KNIGHT][1] ^
Position::zobMaterial[BLACK][PAWN][1];
KPKPMaterialKey =
Position::zobMaterial[WHITE][PAWN][1] ^
Position::zobMaterial[BLACK][PAWN][1];
}
MaterialInfoTable::MaterialInfoTable(unsigned int numOfEntries) {
/// Constructor for the MaterialInfoTable class.
MaterialInfoTable::MaterialInfoTable(unsigned numOfEntries) {
size = numOfEntries; size = numOfEntries;
entries = new MaterialInfo[size]; entries = new MaterialInfo[size];
if(entries == NULL) { funcs = new EndgameFunctions();
if (!entries || !funcs)
{
std::cerr << "Failed to allocate " << (numOfEntries * sizeof(MaterialInfo)) std::cerr << "Failed to allocate " << (numOfEntries * sizeof(MaterialInfo))
<< " bytes for material hash table." << std::endl; << " bytes for material hash table." << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
this->clear(); clear();
} }
/// Destructor for the MaterialInfoTable class. /// Destructor for the MaterialInfoTable class
MaterialInfoTable::~MaterialInfoTable() { MaterialInfoTable::~MaterialInfoTable() {
delete [] entries; delete [] entries;
delete funcs;
} }
@@ -172,6 +107,7 @@ MaterialInfoTable::~MaterialInfoTable() {
/// all entries to 0. /// all entries to 0.
void MaterialInfoTable::clear() { void MaterialInfoTable::clear() {
memset(entries, 0, size * sizeof(MaterialInfo)); memset(entries, 0, size * sizeof(MaterialInfo));
} }
@@ -183,86 +119,45 @@ void MaterialInfoTable::clear() {
/// same material configuration occurs again. /// same material configuration occurs again.
MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) {
Key key = pos.get_material_key(); Key key = pos.get_material_key();
int index = key & (size - 1); int index = key & (size - 1);
MaterialInfo* mi = entries + index; MaterialInfo* mi = entries + index;
// If mi->key matches the position's material hash key, it means that we // If mi->key matches the position's material hash key, it means that we
// have analysed this material configuration before, and we can simply // have analysed this material configuration before, and we can simply
// return the information we found the last time instead of recomputing it: // return the information we found the last time instead of recomputing it.
if (mi->key == key) if (mi->key == key)
return mi; return mi;
// Clear the MaterialInfo object, and set its key: // Clear the MaterialInfo object, and set its key
mi->clear(); mi->clear();
mi->key = key; mi->key = key;
// A special case before looking for a specialized evaluation function: // A special case before looking for a specialized evaluation function
// KNN vs K is a draw: // KNN vs K is a draw.
if(key == KNNKMaterialKey || key == KKNNMaterialKey) { if (key == KNNKMaterialKey || key == KKNNMaterialKey)
{
mi->factor[WHITE] = mi->factor[BLACK] = 0; mi->factor[WHITE] = mi->factor[BLACK] = 0;
return mi; return mi;
} }
// Let's look if we have a specialized evaluation function for this // Let's look if we have a specialized evaluation function for this
// particular material configuration: // particular material configuration.
if(key == KPKMaterialKey) { if ((mi->evaluationFunction = funcs->getEEF(key)) != NULL)
mi->evaluationFunction = &EvaluateKPK;
return mi; return mi;
}
else if(key == KKPMaterialKey) { else if ( pos.non_pawn_material(BLACK) == Value(0)
mi->evaluationFunction = &EvaluateKKP; && pos.piece_count(BLACK, PAWN) == 0
return mi; && pos.non_pawn_material(WHITE) >= RookValueEndgame)
} {
else if(key == KBNKMaterialKey) {
mi->evaluationFunction = &EvaluateKBNK;
return mi;
}
else if(key == KKBNMaterialKey) {
mi->evaluationFunction = &EvaluateKKBN;
return mi;
}
else if(key == KRKPMaterialKey) {
mi->evaluationFunction = &EvaluateKRKP;
return mi;
}
else if(key == KPKRMaterialKey) {
mi->evaluationFunction = &EvaluateKPKR;
return mi;
}
else if(key == KRKBMaterialKey) {
mi->evaluationFunction = &EvaluateKRKB;
return mi;
}
else if(key == KBKRMaterialKey) {
mi->evaluationFunction = &EvaluateKBKR;
return mi;
}
else if(key == KRKNMaterialKey) {
mi->evaluationFunction = &EvaluateKRKN;
return mi;
}
else if(key == KNKRMaterialKey) {
mi->evaluationFunction = &EvaluateKNKR;
return mi;
}
else if(key == KQKRMaterialKey) {
mi->evaluationFunction = &EvaluateKQKR;
return mi;
}
else if(key == KRKQMaterialKey) {
mi->evaluationFunction = &EvaluateKRKQ;
return mi;
}
else if(pos.non_pawn_material(BLACK) == Value(0) &&
pos.pawn_count(BLACK) == 0 &&
pos.non_pawn_material(WHITE) >= RookValueEndgame) {
mi->evaluationFunction = &EvaluateKXK; mi->evaluationFunction = &EvaluateKXK;
return mi; return mi;
} }
else if(pos.non_pawn_material(WHITE) == Value(0) && else if ( pos.non_pawn_material(WHITE) == Value(0)
pos.pawn_count(WHITE) == 0 && && pos.piece_count(WHITE, PAWN) == 0
pos.non_pawn_material(BLACK) >= RookValueEndgame) { && pos.non_pawn_material(BLACK) >= RookValueEndgame)
{
mi->evaluationFunction = &EvaluateKKX; mi->evaluationFunction = &EvaluateKKX;
return mi; return mi;
} }
@@ -274,111 +169,92 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position &pos) {
// if we decide to add more special cases. We face problems when there // if we decide to add more special cases. We face problems when there
// are several conflicting applicable scaling functions and we need to // are several conflicting applicable scaling functions and we need to
// decide which one to use. // decide which one to use.
Color c;
ScalingFunction* sf;
if(key == KRPKRMaterialKey) { if ((sf = funcs->getESF(key, &c)) != NULL)
mi->scalingFunction[WHITE] = &ScaleKRPKR; {
return mi; mi->scalingFunction[c] = sf;
}
if(key == KRKRPMaterialKey) {
mi->scalingFunction[BLACK] = &ScaleKRKRP;
return mi;
}
if(key == KRPPKRPMaterialKey) {
mi->scalingFunction[WHITE] = &ScaleKRPPKRP;
return mi;
}
else if(key == KRPKRPPMaterialKey) {
mi->scalingFunction[BLACK] = &ScaleKRPKRPP;
return mi;
}
if(key == KBPKBMaterialKey) {
mi->scalingFunction[WHITE] = &ScaleKBPKB;
return mi;
}
if(key == KBKBPMaterialKey) {
mi->scalingFunction[BLACK] = &ScaleKBKBP;
return mi;
}
if(key == KBPKNMaterialKey) {
mi->scalingFunction[WHITE] = &ScaleKBPKN;
return mi;
}
if(key == KNKBPMaterialKey) {
mi->scalingFunction[BLACK] = &ScaleKNKBP;
return mi;
}
if(key == KNPKMaterialKey) {
mi->scalingFunction[WHITE] = &ScaleKNPK;
return mi;
}
if(key == KKNPMaterialKey) {
mi->scalingFunction[BLACK] = &ScaleKKNP;
return mi; return mi;
} }
if(pos.non_pawn_material(WHITE) == BishopValueMidgame && if ( pos.non_pawn_material(WHITE) == BishopValueMidgame
pos.bishop_count(WHITE) == 1 && pos.pawn_count(WHITE) >= 1) && pos.piece_count(WHITE, BISHOP) == 1
&& pos.piece_count(WHITE, PAWN) >= 1)
mi->scalingFunction[WHITE] = &ScaleKBPK; mi->scalingFunction[WHITE] = &ScaleKBPK;
if(pos.non_pawn_material(BLACK) == BishopValueMidgame &&
pos.bishop_count(BLACK) == 1 && pos.pawn_count(BLACK) >= 1) if ( pos.non_pawn_material(BLACK) == BishopValueMidgame
&& pos.piece_count(BLACK, BISHOP) == 1
&& pos.piece_count(BLACK, PAWN) >= 1)
mi->scalingFunction[BLACK] = &ScaleKKBP; mi->scalingFunction[BLACK] = &ScaleKKBP;
if(pos.pawn_count(WHITE) == 0 && if ( pos.piece_count(WHITE, PAWN) == 0
pos.non_pawn_material(WHITE) == QueenValueMidgame && && pos.non_pawn_material(WHITE) == QueenValueMidgame
pos.queen_count(WHITE) == 1 && && pos.piece_count(WHITE, QUEEN) == 1
pos.rook_count(BLACK) == 1 && pos.pawn_count(BLACK) >= 1) && pos.piece_count(BLACK, ROOK) == 1
&& pos.piece_count(BLACK, PAWN) >= 1)
mi->scalingFunction[WHITE] = &ScaleKQKRP; mi->scalingFunction[WHITE] = &ScaleKQKRP;
else if(pos.pawn_count(BLACK) == 0 &&
pos.non_pawn_material(BLACK) == QueenValueMidgame && else if ( pos.piece_count(BLACK, PAWN) == 0
pos.queen_count(BLACK) == 1 && && pos.non_pawn_material(BLACK) == QueenValueMidgame
pos.rook_count(WHITE) == 1 && pos.pawn_count(WHITE) >= 1) && pos.piece_count(BLACK, QUEEN) == 1
&& pos.piece_count(WHITE, ROOK) == 1
&& pos.piece_count(WHITE, PAWN) >= 1)
mi->scalingFunction[BLACK] = &ScaleKRPKQ; mi->scalingFunction[BLACK] = &ScaleKRPKQ;
if(pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) == Value(0)) { if (pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) == Value(0))
if(pos.pawn_count(BLACK) == 0) { {
assert(pos.pawn_count(WHITE) >= 2); if (pos.piece_count(BLACK, PAWN) == 0)
{
assert(pos.piece_count(WHITE, PAWN) >= 2);
mi->scalingFunction[WHITE] = &ScaleKPsK; mi->scalingFunction[WHITE] = &ScaleKPsK;
} }
else if(pos.pawn_count(WHITE) == 0) { else if (pos.piece_count(WHITE, PAWN) == 0)
assert(pos.pawn_count(BLACK) >= 2); {
assert(pos.piece_count(BLACK, PAWN) >= 2);
mi->scalingFunction[BLACK] = &ScaleKKPs; mi->scalingFunction[BLACK] = &ScaleKKPs;
} }
else if(pos.pawn_count(WHITE) == 1 && pos.pawn_count(BLACK) == 1) { else if (pos.piece_count(WHITE, PAWN) == 1 && pos.piece_count(BLACK, PAWN) == 1)
{
mi->scalingFunction[WHITE] = &ScaleKPKPw; mi->scalingFunction[WHITE] = &ScaleKPKPw;
mi->scalingFunction[BLACK] = &ScaleKPKPb; mi->scalingFunction[BLACK] = &ScaleKPKPb;
} }
} }
// Evaluate the material balance. // Evaluate the material balance
Color c;
int sign; int sign;
Value egValue = Value(0), mgValue = Value(0); Value egValue = Value(0);
Value mgValue = Value(0);
for(c = WHITE, sign = 1; c <= BLACK; c++, sign = -sign) { for (c = WHITE, sign = 1; c <= BLACK; c++, sign = -sign)
{
// No pawns makes it difficult to win, even with a material advantage: // No pawns makes it difficult to win, even with a material advantage
if(pos.pawn_count(c) == 0 && if ( pos.piece_count(c, PAWN) == 0
pos.non_pawn_material(c) - pos.non_pawn_material(opposite_color(c)) && pos.non_pawn_material(c) - pos.non_pawn_material(opposite_color(c)) <= BishopValueMidgame)
<= BishopValueMidgame) { {
if(pos.non_pawn_material(c) == pos.non_pawn_material(opposite_color(c))) if ( pos.non_pawn_material(c) == pos.non_pawn_material(opposite_color(c))
|| pos.non_pawn_material(c) < RookValueMidgame)
mi->factor[c] = 0; mi->factor[c] = 0;
else if(pos.non_pawn_material(c) < RookValueMidgame) else
mi->factor[c] = 0; {
else { switch (pos.piece_count(c, BISHOP)) {
switch(pos.bishop_count(c)) {
case 2: case 2:
mi->factor[c] = 32; break; mi->factor[c] = 32;
break;
case 1: case 1:
mi->factor[c] = 12; break; mi->factor[c] = 12;
break;
case 0: case 0:
mi->factor[c] = 6; break; mi->factor[c] = 6;
break;
} }
} }
} }
// Bishop pair: // Bishop pair
if(pos.bishop_count(c) >= 2) { if (pos.piece_count(c, BISHOP) >= 2)
{
mgValue += sign * BishopPairMidgameBonus; mgValue += sign * BishopPairMidgameBonus;
egValue += sign * BishopPairEndgameBonus; egValue += sign * BishopPairEndgameBonus;
} }
@@ -387,20 +263,90 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position &pos) {
// formula is taken from Larry Kaufman's paper "The Evaluation of Material // formula is taken from Larry Kaufman's paper "The Evaluation of Material
// Imbalances in Chess": // Imbalances in Chess":
// http://mywebpages.comcast.net/danheisman/Articles/evaluation_of_material_imbalance.htm // http://mywebpages.comcast.net/danheisman/Articles/evaluation_of_material_imbalance.htm
mgValue += sign * Value(pos.knight_count(c)*(pos.pawn_count(c)-5)*16); mgValue += sign * Value(pos.piece_count(c, KNIGHT)*(pos.piece_count(c, PAWN)-5)*16);
egValue += sign * Value(pos.knight_count(c)*(pos.pawn_count(c)-5)*16); egValue += sign * Value(pos.piece_count(c, KNIGHT)*(pos.piece_count(c, PAWN)-5)*16);
// Redundancy of major pieces, again based on Kaufman's paper: // Redundancy of major pieces, again based on Kaufman's paper:
if(pos.rook_count(c) >= 1) { if (pos.piece_count(c, ROOK) >= 1)
Value v = Value((pos.rook_count(c) - 1) * 32 + pos.queen_count(c) * 16); {
Value v = Value((pos.piece_count(c, ROOK) - 1) * 32 + pos.piece_count(c, QUEEN) * 16);
mgValue -= sign * v; mgValue -= sign * v;
egValue -= sign * v; egValue -= sign * v;
} }
} }
mi->mgValue = int16_t(mgValue); mi->mgValue = int16_t(mgValue);
mi->egValue = int16_t(egValue); mi->egValue = int16_t(egValue);
return mi; return mi;
} }
/// EndgameFunctions member definitions. This class is used to store the maps
/// of end game and scaling functions that MaterialInfoTable will query for
/// each key. The maps are constant and are populated only at construction,
/// but are per-thread instead of globals to avoid expensive locks.
EndgameFunctions::EndgameFunctions() {
typedef Key ZM[2][8][16];
const ZM& z = Position::zobMaterial;
static const Color W = WHITE;
static const Color B = BLACK;
KNNKMaterialKey = z[W][KNIGHT][1] ^ z[W][KNIGHT][2];
KKNNMaterialKey = z[B][KNIGHT][1] ^ z[B][KNIGHT][2];
add(z[W][PAWN][1], &EvaluateKPK);
add(z[B][PAWN][1], &EvaluateKKP);
add(z[W][BISHOP][1] ^ z[W][KNIGHT][1], &EvaluateKBNK);
add(z[B][BISHOP][1] ^ z[B][KNIGHT][1], &EvaluateKKBN);
add(z[W][ROOK][1] ^ z[B][PAWN][1], &EvaluateKRKP);
add(z[W][PAWN][1] ^ z[B][ROOK][1], &EvaluateKPKR);
add(z[W][ROOK][1] ^ z[B][BISHOP][1], &EvaluateKRKB);
add(z[W][BISHOP][1] ^ z[B][ROOK][1], &EvaluateKBKR);
add(z[W][ROOK][1] ^ z[B][KNIGHT][1], &EvaluateKRKN);
add(z[W][KNIGHT][1] ^ z[B][ROOK][1], &EvaluateKNKR);
add(z[W][QUEEN][1] ^ z[B][ROOK][1], &EvaluateKQKR);
add(z[W][ROOK][1] ^ z[B][QUEEN][1], &EvaluateKRKQ);
add(z[W][KNIGHT][1] ^ z[W][PAWN][1], W, &ScaleKNPK);
add(z[B][KNIGHT][1] ^ z[B][PAWN][1], B, &ScaleKKNP);
add(z[W][ROOK][1] ^ z[W][PAWN][1] ^ z[B][ROOK][1] , W, &ScaleKRPKR);
add(z[W][ROOK][1] ^ z[B][ROOK][1] ^ z[B][PAWN][1] , B, &ScaleKRKRP);
add(z[W][BISHOP][1] ^ z[W][PAWN][1] ^ z[B][BISHOP][1], W, &ScaleKBPKB);
add(z[W][BISHOP][1] ^ z[B][BISHOP][1] ^ z[B][PAWN][1] , B, &ScaleKBKBP);
add(z[W][BISHOP][1] ^ z[W][PAWN][1] ^ z[B][KNIGHT][1], W, &ScaleKBPKN);
add(z[W][KNIGHT][1] ^ z[B][BISHOP][1] ^ z[B][PAWN][1] , B, &ScaleKNKBP);
add(z[W][ROOK][1] ^ z[W][PAWN][1] ^ z[W][PAWN][2] ^ z[B][ROOK][1] ^ z[B][PAWN][1], W, &ScaleKRPPKRP);
add(z[W][ROOK][1] ^ z[W][PAWN][1] ^ z[B][ROOK][1] ^ z[B][PAWN][1] ^ z[B][PAWN][2], B, &ScaleKRPKRPP);
}
void EndgameFunctions::add(Key k, EndgameEvaluationFunction* f) {
EEFmap.insert(std::pair<Key, EndgameEvaluationFunction*>(k, f));
}
void EndgameFunctions::add(Key k, Color c, ScalingFunction* f) {
ScalingInfo s = {c, f};
ESFmap.insert(std::pair<Key, ScalingInfo>(k, s));
}
EndgameEvaluationFunction* EndgameFunctions::getEEF(Key key) const {
std::map<Key, EndgameEvaluationFunction*>::const_iterator it(EEFmap.find(key));
return (it != EEFmap.end() ? it->second : NULL);
}
ScalingFunction* EndgameFunctions::getESF(Key key, Color* c) const {
std::map<Key, ScalingInfo>::const_iterator it(ESFmap.find(key));
if (it == ESFmap.end())
return NULL;
*c = it->second.col;
return it->second.fun;
}
+27 -13
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -54,8 +55,6 @@ public:
bool specialized_eval_exists() const; bool specialized_eval_exists() const;
Value evaluate(const Position& pos) const; Value evaluate(const Position& pos) const;
static void init();
private: private:
void clear(); void clear();
@@ -68,6 +67,14 @@ private:
}; };
/// EndgameFunctions class stores the endgame evaluation functions std::map.
/// Because STL library is not thread safe even for read access, the maps,
/// although with identical content, are replicated for each thread. This
/// is faster then using locks with an unique set of global maps.
class EndgameFunctions;
/// The MaterialInfoTable class represents a pawn hash table. It is basically /// The MaterialInfoTable class represents a pawn hash table. It is basically
/// just an array of MaterialInfo objects and a few methods for accessing these /// 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 /// objects. The most important method is get_material_info, which looks up a
@@ -84,6 +91,7 @@ public:
private: private:
unsigned size; unsigned size;
MaterialInfo* entries; MaterialInfo* entries;
EndgameFunctions* funcs;
}; };
@@ -95,10 +103,12 @@ private:
/// material balance evaluation for the middle game and the endgame. /// material balance evaluation for the middle game and the endgame.
inline Value MaterialInfo::mg_value() const { inline Value MaterialInfo::mg_value() const {
return Value(mgValue); return Value(mgValue);
} }
inline Value MaterialInfo::eg_value() const { inline Value MaterialInfo::eg_value() const {
return Value(egValue); return Value(egValue);
} }
@@ -107,6 +117,7 @@ inline Value MaterialInfo::eg_value() const {
/// with all slots at their default values. /// with all slots at their default values.
inline void MaterialInfo::clear() { inline void MaterialInfo::clear() {
mgValue = egValue = 0; mgValue = egValue = 0;
factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL); factor[WHITE] = factor[BLACK] = uint8_t(SCALE_FACTOR_NORMAL);
evaluationFunction = NULL; evaluationFunction = NULL;
@@ -117,13 +128,14 @@ inline void MaterialInfo::clear() {
/// MaterialInfo::scale_factor takes a position and a color as input, and /// 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 /// 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 /// 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 /// 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 /// the position. For instance, in KBP vs K endgames, a scaling function
/// which checks for draws with rook pawns and wrong-colored bishops. /// which checks for draws with rook pawns and wrong-colored bishops.
inline ScaleFactor MaterialInfo::scale_factor(const Position &pos, Color c) inline ScaleFactor MaterialInfo::scale_factor(const Position& pos, Color c) const {
const {
if(scalingFunction[c] != NULL) { if (scalingFunction[c] != NULL)
{
ScaleFactor sf = scalingFunction[c]->apply(pos); ScaleFactor sf = scalingFunction[c]->apply(pos);
if (sf != SCALE_FACTOR_NONE) if (sf != SCALE_FACTOR_NONE)
return sf; return sf;
@@ -137,15 +149,17 @@ inline ScaleFactor MaterialInfo::scale_factor(const Position &pos, Color c)
/// or if the normal evaluation function should be used. /// or if the normal evaluation function should be used.
inline bool MaterialInfo::specialized_eval_exists() const { inline bool MaterialInfo::specialized_eval_exists() const {
return evaluationFunction != NULL; return evaluationFunction != NULL;
} }
/// MaterialInfo::evaluate applies a specialized evaluation function to a /// MaterialInfo::evaluate applies a specialized evaluation function
/// given position object. It should only be called when /// to a given position object. It should only be called when
/// this->specialized_eval_exists() returns 'true'. /// specialized_eval_exists() returns 'true'.
inline Value MaterialInfo::evaluate(const Position& pos) const { inline Value MaterialInfo::evaluate(const Position& pos) const {
return evaluationFunction->apply(pos); return evaluationFunction->apply(pos);
} }
+3 -2
View File
@@ -42,6 +42,7 @@
*/ */
#include "types.h" #include "types.h"
#include "mersenne.h"
/* Period parameters */ /* Period parameters */
#define N 624 #define N 624
@@ -54,7 +55,7 @@ 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 */ static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializes mt[N] with a seed */ /* initializes mt[N] with a seed */
void init_genrand(unsigned long s) static void init_genrand(unsigned long s)
{ {
mt[0]= s & 0xffffffffUL; mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) { for (mti=1; mti<N; mti++) {
@@ -73,7 +74,7 @@ void init_genrand(unsigned long s)
/* init_key is the array for initializing keys */ /* init_key is the array for initializing keys */
/* key_length is its length */ /* key_length is its length */
/* slight change for C++, 2004/2/26 */ /* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long init_key[], int key_length) static void init_by_array(unsigned long init_key[], int key_length)
{ {
int i, j, k; int i, j, k;
init_genrand(19650218UL); init_genrand(19650218UL);
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+63 -24
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -38,41 +39,63 @@ int gettimeofday(struct timeval * tp, struct timezone * tzp);
#include <cstdio> #include <cstdio>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <sstream> #include <sstream>
#include "misc.h" #include "misc.h"
////
//// Variables
////
long dbg_cnt0 = 0;
long dbg_cnt1 = 0;
bool dbg_show_mean = false;
bool dbg_show_hit_rate = false;
//// ////
//// Functions //// Functions
//// ////
/// engine_name() returns the full name of the current Glaurung version. void dbg_print_hit_rate() {
/// This will be either "Glaurung YYMMDD" (where YYMMDD is the date when the
/// program was compiled) or "Glaurung <version number>", depending on whether std::cout << "Total " << dbg_cnt0 << " Hit " << dbg_cnt1
<< " hit rate (%) " << (dbg_cnt1*100)/(dbg_cnt0 ? dbg_cnt0 : 1)
<< std::endl;
}
void dbg_print_mean() {
std::cout << "Total " << dbg_cnt0 << " Mean "
<< (float)dbg_cnt1 / (dbg_cnt0 ? dbg_cnt0 : 1) << std::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. /// the constant EngineVersion (defined in misc.h) is empty.
const std::string engine_name() { const std::string engine_name() {
if(EngineVersion == "") {
static const char monthNames[12][4] = { if (EngineVersion.empty())
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" {
}; std::string date(__DATE__); // From compiler, format is "Sep 21 2008"
const char *dateString = __DATE__; std::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;
std::stringstream s; std::stringstream s;
int month = 0, day = 0; std::string day = (date[4] == ' ' ? date.substr(5, 1) : date.substr(4, 2));
for(int i = 0; i < 12; i++) s << "Stockfish " << date.substr(date.length() - 2) << std::setfill('0')
if(strncmp(dateString, monthNames[i], 3) == 0) << std::setw(2) << mon << std::setw(2) << day;
month = i + 1;
day = atoi(dateString+4);
s << "Glaurung " << (dateString+9) << std::setfill('0') << std::setw(2)
<< month << std::setfill('0') << std::setw(2) << day;
return s.str(); return s.str();
} } else
else return "Stockfish " + EngineVersion;
return "Glaurung " + EngineVersion;
} }
@@ -162,8 +185,24 @@ int Bioskey()
return 1; return 1;
return dw; return dw;
} else { } else {
// Count the number of unread input records, including keyboard,
// mouse, and window-resizing input records.
GetNumberOfConsoleInputEvents(inh, &dw); GetNumberOfConsoleInputEvents(inh, &dw);
return dw <= 1 ? 0 : 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 #endif
+25 -5
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -36,7 +37,7 @@
/// Version number. If this is left empty, the current date (in the format /// Version number. If this is left empty, the current date (in the format
/// YYMMDD) is used as a version number. /// YYMMDD) is used as a version number.
const std::string EngineVersion = "2.1"; const std::string EngineVersion = "1.01";
//// ////
@@ -56,5 +57,24 @@ extern int get_system_time();
extern int cpu_count(); extern int cpu_count();
extern int Bioskey(); extern int Bioskey();
////
//// Debug
////
extern long dbg_cnt0;
extern long dbg_cnt1;
inline void dbg_hit_on(bool b) { dbg_cnt0++; if (b) dbg_cnt1++; }
inline void dbg_hit_on_c(bool c, bool b) { if (c) dbg_hit_on(b); }
inline void dbg_before() { dbg_cnt0++; }
inline void dbg_after() { dbg_cnt1++; }
inline void dbg_mean_of(int v) { dbg_cnt0++; dbg_cnt1 += v; }
extern void dbg_print_hit_rate();
extern void dbg_print_mean();
extern bool dbg_show_mean;
extern bool dbg_show_hit_rate;
#endif // !defined(MISC_H_INCLUDED) #endif // !defined(MISC_H_INCLUDED)
+46 -40
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -40,60 +41,65 @@
/// the input move is legal and correctly formatted. /// the input move is legal and correctly formatted.
Move move_from_string(const Position& pos, const std::string& str) { Move move_from_string(const Position& pos, const std::string& str) {
Square from, to; Square from, to;
Piece piece; Piece piece;
Color us = pos.side_to_move(); Color us = pos.side_to_move();
if(str.length() < 4) return MOVE_NONE; if (str.length() < 4)
return MOVE_NONE;
// Read the from and to squares: // Read the from and to squares
from = square_from_string(str.substr(0, 2)); from = square_from_string(str.substr(0, 2));
to = square_from_string(str.substr(2, 4)); to = square_from_string(str.substr(2, 4));
// Find the moving piece: // Find the moving piece
piece = pos.piece_on(from); piece = pos.piece_on(from);
// If the string has more than 4 characters, try to interpret the 5th // If the string has more than 4 characters, try to interpret the 5th
// character as a promotion: // character as a promotion
if(type_of_piece(piece) == PAWN && str.length() >= 5) { if (type_of_piece(piece) == PAWN && str.length() > 4)
switch(str[4]) { {
case 'n': case 'N': switch (tolower(str[4])) {
case 'n':
return make_promotion_move(from, to, KNIGHT); return make_promotion_move(from, to, KNIGHT);
case 'b': case 'B': case 'b':
return make_promotion_move(from, to, BISHOP); return make_promotion_move(from, to, BISHOP);
case 'r': case 'R': case 'r':
return make_promotion_move(from, to, ROOK); return make_promotion_move(from, to, ROOK);
case 'q': case 'Q': case 'q':
return make_promotion_move(from, to, QUEEN); return make_promotion_move(from, to, QUEEN);
} }
} }
if(piece == king_of_color(us)) { if (piece == king_of_color(us))
{
// Is this a castling move? A king move is assumed to be a castling // 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 // move if the destination square is occupied by a friendly rook, or
// if the distance between the source and destination squares is more // if the distance between the source and destination squares is more
// than 1. // than 1.
if (pos.piece_on(to) == rook_of_color(us)) if (pos.piece_on(to) == rook_of_color(us))
return make_castle_move(from, to); return make_castle_move(from, to);
else if(square_distance(from, to) > 1) {
else if (square_distance(from, to) > 1)
{
// This is a castling move, but we have to translate it to the // This is a castling move, but we have to translate it to the
// internal "king captures rook" representation. // internal "king captures rook" representation.
SquareDelta delta = (to > from)? DELTA_E : DELTA_W; SquareDelta delta = (to > from ? DELTA_E : DELTA_W);
Square s; Square s = from + delta;
for(s = from + delta; while (relative_rank(us, s) == RANK_1 && pos.piece_on(s) != rook_of_color(us))
pawn_rank(us, s) == RANK_1 && pos.piece_on(s) != rook_of_color(us); s += delta;
s += delta);
if(pawn_rank(us, s) == RANK_1 && pos.piece_on(s) == rook_of_color(us)) return (relative_rank(us, s) == RANK_1 ? make_castle_move(from, s) : MOVE_NONE);
return make_castle_move(from, s);
} }
} }
else if(piece == pawn_of_color(us)) { else if (piece == pawn_of_color(us))
{
// En passant move? We assume that a pawn move is an en passant move // En passant move? We assume that a pawn move is an en passant move
// without further testing if the destination square is epSquare. // without further testing if the destination square is epSquare.
if (to == pos.ep_square()) if (to == pos.ep_square())
return make_ep_move(from, to); return make_ep_move(from, to);
} }
return make_move(from, to); return make_move(from, to);
} }
@@ -104,28 +110,26 @@ Move move_from_string(const Position &pos, const std::string &str) {
/// Chess960 mode. /// Chess960 mode.
const std::string move_to_string(Move move) { const std::string move_to_string(Move move) {
std::string str; std::string str;
Square from = move_from(move);
Square to = move_to(move);
if (move == MOVE_NONE) if (move == MOVE_NONE)
str = "(none)"; str = "(none)";
else if (move == MOVE_NULL) else if (move == MOVE_NULL)
str = "0000"; str = "0000";
else { else
if(!Chess960) { {
if(move_from(move) == SQ_E1 && move_is_short_castle(move)) { if (!Chess960)
str = "e1g1"; return str; {
if (move_is_short_castle(move))
return (from == SQ_E1 ? "e1g1" : "e8g8");
if (move_is_long_castle(move))
return (from == SQ_E1 ? "e1c1" : "e8c8");
} }
else if(move_from(move) == SQ_E1 && move_is_long_castle(move)) { str = square_to_string(from) + square_to_string(to);
str = "e1c1"; return str;
}
if(move_from(move) == SQ_E8 && move_is_short_castle(move)) {
str = "e8g8"; return str;
}
else if(move_from(move) == SQ_E8 && move_is_long_castle(move)) {
str = "e8c8"; return str;
}
}
str = square_to_string(move_from(move)) + square_to_string(move_to(move));
if (move_promotion(move)) if (move_promotion(move))
str += piece_type_to_char(move_promotion(move), false); str += piece_type_to_char(move_promotion(move), false);
} }
@@ -136,6 +140,7 @@ const std::string move_to_string(Move move) {
/// Overload the << operator, to make it easier to print moves. /// Overload the << operator, to make it easier to print moves.
std::ostream &operator << (std::ostream &os, Move m) { std::ostream &operator << (std::ostream &os, Move m) {
return os << move_to_string(m); return os << move_to_string(m);
} }
@@ -143,5 +148,6 @@ std::ostream &operator << (std::ostream &os, Move m) {
/// move_is_ok(), for debugging. /// move_is_ok(), for debugging.
bool move_is_ok(Move m) { bool move_is_ok(Move m) {
return square_is_ok(move_from(m)) && square_is_ok(move_to(m)); return square_is_ok(move_from(m)) && square_is_ok(move_to(m));
} }
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+614 -905
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -36,7 +37,7 @@ extern int generate_noncaptures(const Position &pos, MoveStack *mlist);
extern int generate_checks(const Position &pos, MoveStack *mlist, Bitboard dc); extern int generate_checks(const Position &pos, MoveStack *mlist, Bitboard dc);
extern int generate_evasions(const Position &pos, MoveStack *mlist); extern int generate_evasions(const Position &pos, MoveStack *mlist);
extern int generate_legal_moves(const Position &pos, MoveStack *mlist); extern int generate_legal_moves(const Position &pos, MoveStack *mlist);
extern Move generate_move_if_legal(const Position &pos, Move m, extern bool move_is_legal(const Position &pos, const Move m, Bitboard pinned);
Bitboard pinned);
#endif // !defined(MOVEGEN_H_INCLUDED) #endif // !defined(MOVEGEN_H_INCLUDED)
+174 -179
View File
@@ -1,13 +1,15 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful,
Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -36,26 +38,9 @@
namespace { namespace {
/// Types
enum MovegenPhase {
PH_TT_MOVE, // Transposition table move
PH_MATE_KILLER, // Mate killer from the current ply
PH_GOOD_CAPTURES, // Queen promotions and captures with SEE values >= 0
PH_BAD_CAPTURES, // Queen promotions and captures with SEE valuse <= 0
PH_KILLER_1, // Killer move 1 from the current ply (not used yet).
PH_KILLER_2, // Killer move 2 from the current ply (not used yet).
PH_NONCAPTURES, // Non-captures and underpromotions
PH_EVASIONS, // Check evasions
PH_QCAPTURES, // Captures in quiescence search
PH_QCHECKS, // Checks in quiescence search
PH_STOP
};
/// Variables /// Variables
MovegenPhase PhaseTable[32]; MovePicker::MovegenPhase PhaseTable[32];
int MainSearchPhaseIndex; int MainSearchPhaseIndex;
int EvasionsPhaseIndex; int EvasionsPhaseIndex;
int QsearchWithChecksPhaseIndex; int QsearchWithChecksPhaseIndex;
@@ -64,6 +49,7 @@ namespace {
} }
//// ////
//// Functions //// Functions
//// ////
@@ -76,15 +62,14 @@ namespace {
/// search captures, promotions and some checks) and about how important good /// search captures, promotions and some checks) and about how important good
/// move ordering is at the current node. /// move ordering is at the current node.
MovePicker::MovePicker(Position &p, bool pvnode, Move ttm, Move mk, MovePicker::MovePicker(const Position& p, bool pvnode, Move ttm, Move mk,
Move k1, Move k2, Depth dpth) { Move k1, Move k2, Depth d) : pos(p) {
pos = &p;
pvNode = pvnode; pvNode = pvnode;
ttMove = ttm; ttMove = ttm;
mateKiller = (mk == ttm)? MOVE_NONE : mk; mateKiller = (mk == ttm)? MOVE_NONE : mk;
killer1 = k1; killer1 = k1;
killer2 = k2; killer2 = k2;
depth = dpth; depth = d;
movesPicked = 0; movesPicked = 0;
numOfMoves = 0; numOfMoves = 0;
numOfBadCaptures = 0; numOfBadCaptures = 0;
@@ -110,47 +95,45 @@ MovePicker::MovePicker(Position &p, bool pvnode, Move ttm, Move mk,
/// are no more moves left of the types we are interested in. /// are no more moves left of the types we are interested in.
Move MovePicker::get_next_move() { Move MovePicker::get_next_move() {
Move move; Move move;
while(true) { while (true)
{
// If we already have a list of generated moves, pick the best move from // If we already have a list of generated moves, pick the best move from
// the list, and return it: // the list, and return it.
move = this->pick_move_from_list(); move = pick_move_from_list();
if(move != MOVE_NONE) { if (move != MOVE_NONE)
{
assert(move_is_ok(move)); assert(move_is_ok(move));
return move; return move;
} }
// Next phase: // Next phase
phaseIndex++; phaseIndex++;
switch (PhaseTable[phaseIndex]) { switch (PhaseTable[phaseIndex]) {
case PH_TT_MOVE: case PH_TT_MOVE:
if(ttMove != MOVE_NONE) { if (ttMove != MOVE_NONE)
{
assert(move_is_ok(ttMove)); assert(move_is_ok(ttMove));
Move m = generate_move_if_legal(*pos, ttMove, pinned); if (move_is_legal(pos, ttMove, pinned))
if(m != MOVE_NONE) { return ttMove;
assert(m == ttMove);
return m;
}
} }
break; break;
case PH_MATE_KILLER: case PH_MATE_KILLER:
if(mateKiller != MOVE_NONE) { if (mateKiller != MOVE_NONE)
{
assert(move_is_ok(mateKiller)); assert(move_is_ok(mateKiller));
Move m = generate_move_if_legal(*pos, mateKiller, pinned); if (move_is_legal(pos, mateKiller, pinned))
if(m != MOVE_NONE) { return mateKiller;
assert(m == mateKiller);
return m;
}
} }
break; break;
case PH_GOOD_CAPTURES: case PH_GOOD_CAPTURES:
// pinned = pos->pinned_pieces(pos->side_to_move()); numOfMoves = generate_captures(pos, moves);
numOfMoves = generate_captures(*pos, moves); score_captures();
this->score_captures();
movesPicked = 0; movesPicked = 0;
break; break;
@@ -159,28 +142,26 @@ Move MovePicker::get_next_move() {
break; break;
case PH_NONCAPTURES: case PH_NONCAPTURES:
numOfMoves = generate_noncaptures(*pos, moves); numOfMoves = generate_noncaptures(pos, moves);
this->score_noncaptures(); score_noncaptures();
movesPicked = 0; movesPicked = 0;
break; break;
case PH_EVASIONS: case PH_EVASIONS:
assert(pos->is_check()); assert(pos.is_check());
// pinned = pos->pinned_pieces(pos->side_to_move()); numOfMoves = generate_evasions(pos, moves);
numOfMoves = generate_evasions(*pos, moves); score_evasions();
this->score_evasions();
movesPicked = 0; movesPicked = 0;
break; break;
case PH_QCAPTURES: case PH_QCAPTURES:
// pinned = pos->pinned_pieces(pos->side_to_move()); numOfMoves = generate_captures(pos, moves);
numOfMoves = generate_captures(*pos, moves); score_qcaptures();
this->score_qcaptures();
movesPicked = 0; movesPicked = 0;
break; break;
case PH_QCHECKS: case PH_QCHECKS:
numOfMoves = generate_checks(*pos, moves, dc); numOfMoves = generate_checks(pos, moves, dc);
movesPicked = 0; movesPicked = 0;
break; break;
@@ -192,10 +173,6 @@ Move MovePicker::get_next_move() {
return MOVE_NONE; return MOVE_NONE;
} }
} }
assert(false);
return MOVE_NONE;
} }
@@ -203,37 +180,26 @@ Move MovePicker::get_next_move() {
/// prevent multiple threads from picking the same move at a split point. /// prevent multiple threads from picking the same move at a split point.
Move MovePicker::get_next_move(Lock &lock) { Move MovePicker::get_next_move(Lock &lock) {
Move m;
lock_grab(&lock); lock_grab(&lock);
if(finished) { if (finished)
{
lock_release(&lock); lock_release(&lock);
return MOVE_NONE; return MOVE_NONE;
} }
m = this->get_next_move(); Move m = get_next_move();
if (m == MOVE_NONE) if (m == MOVE_NONE)
finished = true; finished = true;
lock_release(&lock); lock_release(&lock);
return m; return m;
} }
/// MovePicker::number_of_moves() simply returns the numOfMoves member
/// variable. 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.
int MovePicker::number_of_moves() const {
return numOfMoves;
}
/// MovePicker::score_captures(), MovePicker::score_noncaptures(), /// MovePicker::score_captures(), MovePicker::score_noncaptures(),
/// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a /// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
/// numerical move ordering score to each move in a move list. The moves /// numerical move ordering score to each move in a move list. The moves
/// with highest scores will be picked first by /// with highest scores will be picked first by pick_move_from_list().
/// MovePicker::pick_move_from_list().
void MovePicker::score_captures() { void MovePicker::score_captures() {
// Winning and equal captures in the main search are ordered by MVV/LVA. // Winning and equal captures in the main search are ordered by MVV/LVA.
@@ -245,62 +211,100 @@ void MovePicker::score_captures() {
// where it is possible to recapture with the hanging piece). Exchanging // where it is possible to recapture with the hanging piece). Exchanging
// big pieces before capturing a hanging piece probably helps to reduce // big pieces before capturing a hanging piece probably helps to reduce
// the subtree size. // the subtree size.
for(int i = 0; i < numOfMoves; i++) { Move m;
int seeValue = pos->see(moves[i].move); int seeValue;
if(seeValue >= 0) {
if(move_promotion(moves[i].move)) for (int i = 0; i < numOfMoves; i++)
{
m = moves[i].move;
seeValue = pos.see(m);
if (seeValue >= 0)
{
if (move_promotion(m))
moves[i].score = QueenValueMidgame; moves[i].score = QueenValueMidgame;
else else
moves[i].score = moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
int(pos->midgame_value_of_piece_on(move_to(moves[i].move))) - -int(pos.type_of_piece_on(move_from(m)));
int(pos->type_of_piece_on(move_from(moves[i].move))); } else
}
else
moves[i].score = seeValue; moves[i].score = seeValue;
} }
} }
void MovePicker::score_noncaptures() { void MovePicker::score_noncaptures() {
for(int i = 0; i < numOfMoves; i++) { // First score by history, when no history is available then use
Move m = moves[i].move; // 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;
int hs;
for (int i = 0; i < numOfMoves; i++)
{
m = moves[i].move;
if (m == killer1) if (m == killer1)
moves[i].score = HistoryMax + 2; hs = HistoryMax + 2;
else if (m == killer2) else if (m == killer2)
moves[i].score = HistoryMax + 1; hs = HistoryMax + 1;
else else
moves[i].score = H.move_ordering_score(pos->piece_on(move_from(m)), m); hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
// Ensure moves in history are always sorted as first
if (hs > 0)
hs += 1000;
moves[i].score = hs + pos.mg_pst_delta(m);
} }
} }
void MovePicker::score_evasions() { void MovePicker::score_evasions() {
for(int i = 0; i < numOfMoves; i++) {
for (int i = 0; i < numOfMoves; i++)
{
Move m = moves[i].move; Move m = moves[i].move;
if (m == ttMove) if (m == ttMove)
moves[i].score = 2*HistoryMax; moves[i].score = 2*HistoryMax;
else if(!pos->square_is_empty(move_to(m))) { else if (!pos.square_is_empty(move_to(m)))
int seeScore = pos->see(m); {
int seeScore = pos.see(m);
moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore; moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
} else
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
} }
else // FIXME try psqt also here
moves[i].score = H.move_ordering_score(pos->piece_on(move_from(m)), m);
}
} }
void MovePicker::score_qcaptures() { void MovePicker::score_qcaptures() {
// Use MVV/LVA ordering.
for(int i = 0; i < numOfMoves; i++) { // Use MVV/LVA ordering
for (int i = 0; i < numOfMoves; i++)
{
Move m = moves[i].move; Move m = moves[i].move;
if (move_promotion(m)) if (move_promotion(m))
moves[i].score = QueenValueMidgame; moves[i].score = QueenValueMidgame;
else else
moves[i].score = moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
int(pos->midgame_value_of_piece_on(move_to(m))) - -int(pos.type_of_piece_on(move_from(m)));
int(pos->midgame_value_of_piece_on(move_to(m))) / 64;
} }
} }
/// find_best_index() loops across the moves and returns index of
/// the highest scored one.
int MovePicker::find_best_index() {
int bestScore = -10000000, bestIndex = -1;
for (int i = movesPicked; i < numOfMoves; i++)
if (moves[i].score > bestScore)
{
bestIndex = i;
bestScore = moves[i].score;
}
return bestIndex;
}
/// MovePicker::pick_move_from_list() picks the move with the biggest score /// MovePicker::pick_move_from_list() picks the move with the biggest score
/// from a list of generated moves (moves[] or badCaptures[], depending on /// from a list of generated moves (moves[] or badCaptures[], depending on
/// the current move generation phase). It takes care not to return the /// the current move generation phase). It takes care not to return the
@@ -310,149 +314,131 @@ void MovePicker::score_qcaptures() {
/// negative SEE values to the badCaptures[] array. /// negative SEE values to the badCaptures[] array.
Move MovePicker::pick_move_from_list() { Move MovePicker::pick_move_from_list() {
int bestScore = -10000000;
int bestIndex; int bestIndex;
Move move; Move move;
switch (PhaseTable[phaseIndex]) { switch (PhaseTable[phaseIndex]) {
case PH_GOOD_CAPTURES: case PH_GOOD_CAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while(movesPicked < numOfMoves) {
bestScore = -10000000; while (movesPicked < numOfMoves)
{
int bestScore = -10000000;
bestIndex = -1; bestIndex = -1;
for(int i = movesPicked; i < numOfMoves; i++) { for (int i = movesPicked; i < numOfMoves; i++)
if(moves[i].score < 0) { {
if (moves[i].score < 0)
{
// Losing capture, move it to the badCaptures[] array // Losing capture, move it to the badCaptures[] array
assert(numOfBadCaptures < 63); assert(numOfBadCaptures < 63);
badCaptures[numOfBadCaptures++] = moves[i]; badCaptures[numOfBadCaptures++] = moves[i];
moves[i--] = moves[--numOfMoves]; moves[i--] = moves[--numOfMoves];
} }
else if(moves[i].score > bestScore) { else if (moves[i].score > bestScore)
{
bestIndex = i; bestIndex = i;
bestScore = moves[i].score; bestScore = moves[i].score;
} }
} }
if(bestIndex != -1) { // Found a good capture if (bestIndex != -1) // Found a good capture
MoveStack tmp = moves[movesPicked]; {
moves[movesPicked] = moves[bestIndex]; move = moves[bestIndex].move;
moves[bestIndex] = tmp; moves[bestIndex] = moves[movesPicked++];
move = moves[movesPicked++].move; if ( move != ttMove
if(move != ttMove && move != mateKiller && && move != mateKiller
pos->move_is_legal(move, pinned)) && pos.pl_move_is_legal(move, pinned))
return move; return move;
} }
} }
break; break;
case PH_NONCAPTURES: case PH_NONCAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while(movesPicked < numOfMoves) {
bestScore = -10000000;
while (movesPicked < numOfMoves)
{
// If this is a PV node or we have only picked a few moves, scan // If this is a PV node or we have only picked a few moves, scan
// the entire move list for the best move. If many moves have already // the entire move list for the best move. If many moves have already
// been searched and it is not a PV node, we are probably failing low // been searched and it is not a PV node, we are probably failing low
// anyway, so we just pick the first move from the list. // anyway, so we just pick the first move from the list.
if(pvNode || movesPicked < 12) { bestIndex = (pvNode || movesPicked < 12) ? find_best_index() : movesPicked;
bestIndex = -1;
for(int i = movesPicked; i < numOfMoves; i++)
if(moves[i].score > bestScore) {
bestIndex = i;
bestScore = moves[i].score;
}
}
else
bestIndex = movesPicked;
if(bestIndex != -1) { if (bestIndex != -1)
MoveStack tmp = moves[movesPicked]; {
moves[movesPicked] = moves[bestIndex]; move = moves[bestIndex].move;
moves[bestIndex] = tmp; moves[bestIndex] = moves[movesPicked++];
move = moves[movesPicked++].move; if ( move != ttMove
if(move != ttMove && move != mateKiller && && move != mateKiller
pos->move_is_legal(move, pinned)) && pos.pl_move_is_legal(move, pinned))
return move; return move;
} }
} }
break; break;
case PH_EVASIONS: case PH_EVASIONS:
assert(pos->is_check()); assert(pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while(movesPicked < numOfMoves) {
bestScore = -10000000;
bestIndex = -1;
for(int i = movesPicked; i < numOfMoves; i++)
if(moves[i].score > bestScore) {
bestIndex = i;
bestScore = moves[i].score;
}
if(bestIndex != -1) { while (movesPicked < numOfMoves)
MoveStack tmp = moves[movesPicked]; {
moves[movesPicked] = moves[bestIndex]; bestIndex = find_best_index();
moves[bestIndex] = tmp;
move = moves[movesPicked++].move; if (bestIndex != -1)
{
move = moves[bestIndex].move;
moves[bestIndex] = moves[movesPicked++];
return move; return move;
} }
} }
break; break;
case PH_BAD_CAPTURES: case PH_BAD_CAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(badCapturesPicked >= 0); assert(badCapturesPicked >= 0);
// It's probably a good idea to use SEE move ordering here, instead // It's probably a good idea to use SEE move ordering here, instead
// of just picking the first move. FIXME // of just picking the first move. FIXME
while(badCapturesPicked < numOfBadCaptures) { while (badCapturesPicked < numOfBadCaptures)
{
move = badCaptures[badCapturesPicked++].move; move = badCaptures[badCapturesPicked++].move;
if(move != ttMove && move != mateKiller && if ( move != ttMove
pos->move_is_legal(move, pinned)) && move != mateKiller
&& pos.pl_move_is_legal(move, pinned))
return move; return move;
} }
break; break;
case PH_QCAPTURES: case PH_QCAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while(movesPicked < numOfMoves) { while (movesPicked < numOfMoves)
bestScore = -10000000; {
if(movesPicked < 4) { bestIndex = (movesPicked < 4 ? find_best_index() : movesPicked);
bestIndex = -1;
for(int i = movesPicked; i < numOfMoves; i++)
if(moves[i].score > bestScore) {
bestIndex = i;
bestScore = moves[i].score;
}
}
else
bestIndex = movesPicked;
if(bestIndex != -1) { if (bestIndex != -1)
MoveStack tmp = moves[movesPicked]; {
moves[movesPicked] = moves[bestIndex]; move = moves[bestIndex].move;
moves[bestIndex] = tmp; moves[bestIndex] = moves[movesPicked++];
move = moves[movesPicked++].move;
// Remember to change the line below if we decide to hash the qsearch! // Remember to change the line below if we decide to hash the qsearch!
// Maybe also postpone the legality check until after futility pruning? // Maybe also postpone the legality check until after futility pruning?
if(/* move != ttMove && */ pos->move_is_legal(move, pinned)) if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
return move; return move;
} }
} }
break; break;
case PH_QCHECKS: case PH_QCHECKS:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
// Perhaps we should do something better than just picking the first // Perhaps we should do something better than just picking the first
// move here? FIXME // move here? FIXME
while(movesPicked < numOfMoves) { while (movesPicked < numOfMoves)
{
move = moves[movesPicked++].move; move = moves[movesPicked++].move;
// Remember to change the line below if we decide to hash the qsearch! // Remember to change the line below if we decide to hash the qsearch!
if(/* move != ttMove && */ pos->move_is_legal(move, pinned)) if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
return move; return move;
} }
break; break;
@@ -460,17 +446,26 @@ Move MovePicker::pick_move_from_list() {
default: default:
break; break;
} }
return MOVE_NONE; return MOVE_NONE;
} }
/// MovePicker::current_move_type() returns the type of the just
/// picked next move. It can be used in search to further differentiate
/// according to the current move type: capture, non capture, escape, etc.
MovePicker::MovegenPhase MovePicker::current_move_type() const {
return PhaseTable[phaseIndex];
}
/// MovePicker::init_phase_table() initializes the PhaseTable[], /// MovePicker::init_phase_table() initializes the PhaseTable[],
/// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex /// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
/// and QsearchWithoutChecksPhaseIndex variables. It is only called once /// and QsearchWithoutChecksPhaseIndex variables. It is only called once
/// during program startup, and never again while the program is running. /// during program startup, and never again while the program is running.
void MovePicker::init_phase_table() { void MovePicker::init_phase_table() {
int i = 0; int i = 0;
// Main search // Main search
+36 -9
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -44,13 +45,28 @@
class MovePicker { class MovePicker {
public: public:
MovePicker(Position &p, bool pvnode, Move ttm, Move mk, Move k1, Move k2,
Depth dpth); enum MovegenPhase {
PH_TT_MOVE, // Transposition table move
PH_MATE_KILLER, // Mate killer from the current ply
PH_GOOD_CAPTURES, // Queen promotions and captures with SEE values >= 0
PH_BAD_CAPTURES, // Queen promotions and captures with SEE values < 0
PH_KILLER_1, // Killer move 1 from the current ply (not used yet).
PH_KILLER_2, // Killer move 2 from the current ply (not used yet).
PH_NONCAPTURES, // Non-captures and underpromotions
PH_EVASIONS, // Check evasions
PH_QCAPTURES, // Captures in quiescence search
PH_QCHECKS, // Checks in quiescence search
PH_STOP
};
MovePicker(const Position& p, bool pvnode, Move ttm, Move mk, Move k1, Move k2, Depth d);
Move get_next_move(); Move get_next_move();
Move get_next_move(Lock &lock); Move get_next_move(Lock &lock);
int number_of_moves() const; int number_of_moves() const;
int current_move_score() const; int current_move_score() const;
Bitboard discovered_check_candidates(); MovegenPhase current_move_type() const;
Bitboard discovered_check_candidates() const;
static void init_phase_table(); static void init_phase_table();
@@ -60,8 +76,9 @@ private:
void score_evasions(); void score_evasions();
void score_qcaptures(); void score_qcaptures();
Move pick_move_from_list(); Move pick_move_from_list();
int find_best_index();
Position *pos; const Position& pos;
Move ttMove, mateKiller, killer1, killer2; Move ttMove, mateKiller, killer1, killer2;
Bitboard pinned, dc; Bitboard pinned, dc;
MoveStack moves[256], badCaptures[64]; MoveStack moves[256], badCaptures[64];
@@ -78,11 +95,21 @@ private:
//// Inline functions //// Inline functions
//// ////
/// MovePicker::number_of_moves() simply returns the numOfMoves member
/// variable. 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.
inline int MovePicker::number_of_moves() const {
return numOfMoves;
}
/// MovePicker::discovered_check_candidates() returns a bitboard containing /// MovePicker::discovered_check_candidates() returns a bitboard containing
/// all pieces which can possibly give discovered check. This bitboard is /// all pieces which can possibly give discovered check. This bitboard is
/// computed by the constructor function. /// computed by the constructor function.
inline Bitboard MovePicker::discovered_check_candidates() { inline Bitboard MovePicker::discovered_check_candidates() const {
return dc; return dc;
} }
+8 -6
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -22,6 +23,7 @@
//// ////
#include <cassert> #include <cassert>
#include <cstring>
#include "pawns.h" #include "pawns.h"
@@ -364,8 +366,8 @@ PawnInfo *PawnInfoTable::get_pawn_info(const Position &pos) {
ev += ChainEndgameBonus[f]; ev += ChainEndgameBonus[f];
} }
if(candidate) { if(candidate) {
mv += CandidateMidgameBonus[pawn_rank(us, s)]; mv += CandidateMidgameBonus[relative_rank(us, s)];
ev += CandidateEndgameBonus[pawn_rank(us, s)]; ev += CandidateEndgameBonus[relative_rank(us, s)];
} }
mgValue[us] += mv; mgValue[us] += mv;
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+794 -767
View File
File diff suppressed because it is too large Load Diff
+127 -171
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -20,6 +21,14 @@
#if !defined(POSITION_H_INCLUDED) #if !defined(POSITION_H_INCLUDED)
#define POSITION_H_INCLUDED #define POSITION_H_INCLUDED
// Disable a silly and noisy warning from MSVC compiler
#if defined(_MSC_VER)
// Forcing value to bool 'true' or 'false' (performance warning)
#pragma warning(disable: 4800)
#endif
//// ////
//// Includes //// Includes
//// ////
@@ -56,8 +65,10 @@ const int MaxGameLength = 220;
enum CastleRights { enum CastleRights {
NO_CASTLES = 0, NO_CASTLES = 0,
WHITE_OO = 1, BLACK_OO = 2, WHITE_OO = 1,
WHITE_OOO = 4, BLACK_OOO = 8, BLACK_OO = 2,
WHITE_OOO = 4,
BLACK_OOO = 8,
ALL_CASTLES = 15 ALL_CASTLES = 15
}; };
@@ -106,10 +117,11 @@ struct UndoInfo {
class Position { class Position {
friend class MaterialInfo; friend class MaterialInfo;
friend class EndgameFunctions;
public: public:
// Constructors // Constructors
Position(); Position() {};
Position(const Position &pos); Position(const Position &pos);
Position(const std::string &fen); Position(const std::string &fen);
@@ -161,11 +173,6 @@ public:
// Number of pieces of each color and type // Number of pieces of each color and type
int piece_count(Color c, PieceType pt) const; int piece_count(Color c, PieceType pt) const;
int pawn_count(Color c) const;
int knight_count(Color c) const;
int bishop_count(Color c) const;
int rook_count(Color c) const;
int queen_count(Color c) const;
// The en passant square: // The en passant square:
Square ep_square() const; Square ep_square() const;
@@ -184,13 +191,9 @@ public:
Bitboard sliding_attacks(Square s, Direction d) const; Bitboard sliding_attacks(Square s, Direction d) const;
Bitboard ray_attacks(Square s, SignedDirection d) const; Bitboard ray_attacks(Square s, SignedDirection d) const;
Bitboard pawn_attacks(Color c, Square s) const; Bitboard pawn_attacks(Color c, Square s) const;
Bitboard white_pawn_attacks(Square s) const;
Bitboard black_pawn_attacks(Square s) const; template<PieceType>
Bitboard knight_attacks(Square s) const; Bitboard piece_attacks(Square s) const;
Bitboard bishop_attacks(Square s) const;
Bitboard rook_attacks(Square s) const;
Bitboard queen_attacks(Square s) const;
Bitboard king_attacks(Square s) const;
// Bitboards for pinned pieces and discovered check candidates // Bitboards for pinned pieces and discovered check candidates
Bitboard discovered_check_candidates(Color c) const; Bitboard discovered_check_candidates(Color c) const;
@@ -199,34 +202,28 @@ public:
// Checking pieces // Checking pieces
Bitboard checkers() const; Bitboard checkers() const;
// Piece lists: // Piece lists
Square piece_list(Color c, PieceType pt, int index) const; Square piece_list(Color c, PieceType pt, int index) const;
Square pawn_list(Color c, int index) const;
Square knight_list(Color c, int index) const;
Square bishop_list(Color c, int index) const;
Square rook_list(Color c, int index) const;
Square queen_list(Color c, int index) const;
// Attack information for a given square // Attack information for a given square
bool square_is_attacked(Square s, Color c) const; bool square_is_attacked(Square s, Color c) const;
Bitboard attacks_to(Square s) const; Bitboard attacks_to(Square s) const;
Bitboard attacks_to(Square s, Color c) const; Bitboard attacks_to(Square s, Color c) const;
bool is_check() const; bool is_check() const;
bool piece_attacks_square(Square f, Square t) const; bool pawn_attacks_square(Color c, Square f, Square t) const;
bool white_pawn_attacks_square(Square f, Square t) const;
bool black_pawn_attacks_square(Square f, Square t) const; template<PieceType>
bool knight_attacks_square(Square f, Square t) const; Bitboard piece_attacks_square(Square f, Square t) const; // Dispatch at compile-time
bool bishop_attacks_square(Square f, Square t) const;
bool rook_attacks_square(Square f, Square t) const; bool piece_attacks_square(Square f, Square t) const; // Dispatch at run-time
bool queen_attacks_square(Square f, Square t) const;
bool king_attacks_square(Square f, Square t) const;
// Properties of moves // Properties of moves
bool move_is_legal(Move m) const; bool pl_move_is_legal(Move m) const;
bool move_is_legal(Move m, Bitboard pinned) const; bool pl_move_is_legal(Move m, Bitboard pinned) const;
bool move_is_check(Move m) const; bool move_is_check(Move m) const;
bool move_is_check(Move m, Bitboard dcCandidates) const; bool move_is_check(Move m, Bitboard dcCandidates) const;
bool move_is_capture(Move m) const; bool move_is_capture(Move m) const;
bool move_is_deep_pawn_push(Move m) const;
bool move_is_pawn_push_to_7th(Move m) const; bool move_is_pawn_push_to_7th(Move m) const;
bool move_is_passed_pawn_push(Move m) const; bool move_is_passed_pawn_push(Move m) const;
bool move_was_passed_pawn_push(Move m) const; bool move_was_passed_pawn_push(Move m) const;
@@ -267,6 +264,7 @@ public:
Value eg_value() const; Value eg_value() const;
Value non_pawn_material(Color c) const; Value non_pawn_material(Color c) const;
Phase game_phase() const; Phase game_phase() const;
Value mg_pst_delta(Move m) const;
// Game termination checks // Game termination checks
bool is_mate(); bool is_mate();
@@ -286,7 +284,7 @@ public:
void reset_game_ply(); void reset_game_ply();
// Position consistency check, for debugging // Position consistency check, for debugging
bool is_ok() const; bool is_ok(int* failedStep = NULL) const;
// Static member functions: // Static member functions:
static void init_zobrist(); static void init_zobrist();
@@ -300,6 +298,7 @@ private:
void allow_ooo(Color c); void allow_ooo(Color c);
// Helper functions for doing and undoing moves // Helper functions for doing and undoing moves
void do_capture_move(Move m, PieceType capture, Color them, Square to);
void do_castle_move(Move m); void do_castle_move(Move m);
void do_promotion_move(Move m, UndoInfo &u); void do_promotion_move(Move m, UndoInfo &u);
void do_ep_move(Move m); void do_ep_move(Move m);
@@ -308,6 +307,9 @@ private:
void undo_ep_move(Move m); void undo_ep_move(Move m);
void find_checkers(); void find_checkers();
template<PieceType Piece, bool FindPinned>
Bitboard hidden_checks(Color c, Square ksq) const;
// Computing hash keys from scratch (for initialization and debugging) // Computing hash keys from scratch (for initialization and debugging)
Key compute_key() const; Key compute_key() const;
Key compute_pawn_key() const; Key compute_pawn_key() const;
@@ -367,27 +369,27 @@ inline Piece Position::piece_on(Square s) const {
} }
inline Color Position::color_of_piece_on(Square s) const { inline Color Position::color_of_piece_on(Square s) const {
return color_of_piece(this->piece_on(s)); return color_of_piece(piece_on(s));
} }
inline PieceType Position::type_of_piece_on(Square s) const { inline PieceType Position::type_of_piece_on(Square s) const {
return type_of_piece(this->piece_on(s)); return type_of_piece(piece_on(s));
} }
inline bool Position::square_is_empty(Square s) const { inline bool Position::square_is_empty(Square s) const {
return this->piece_on(s) == EMPTY; return piece_on(s) == EMPTY;
} }
inline bool Position::square_is_occupied(Square s) const { inline bool Position::square_is_occupied(Square s) const {
return !this->square_is_empty(s); return !square_is_empty(s);
} }
inline Value Position::midgame_value_of_piece_on(Square s) const { inline Value Position::midgame_value_of_piece_on(Square s) const {
return piece_value_midgame(this->piece_on(s)); return piece_value_midgame(piece_on(s));
} }
inline Value Position::endgame_value_of_piece_on(Square s) const { inline Value Position::endgame_value_of_piece_on(Square s) const {
return piece_value_endgame(this->piece_on(s)); return piece_value_endgame(piece_on(s));
} }
inline Color Position::side_to_move() const { inline Color Position::side_to_move() const {
@@ -399,7 +401,7 @@ inline Bitboard Position::occupied_squares() const {
} }
inline Bitboard Position::empty_squares() const { inline Bitboard Position::empty_squares() const {
return ~(this->occupied_squares()); return ~(occupied_squares());
} }
inline Bitboard Position::pieces_of_color(Color c) const { inline Bitboard Position::pieces_of_color(Color c) const {
@@ -410,131 +412,90 @@ inline Bitboard Position::pieces_of_type(PieceType pt) const {
return byTypeBB[pt]; return byTypeBB[pt];
} }
inline Bitboard Position::pieces_of_color_and_type(Color c, PieceType pt) inline Bitboard Position::pieces_of_color_and_type(Color c, PieceType pt) const {
const { return pieces_of_color(c) & pieces_of_type(pt);
return this->pieces_of_color(c) & this->pieces_of_type(pt);
} }
inline Bitboard Position::pawns() const { inline Bitboard Position::pawns() const {
return this->pieces_of_type(PAWN); return pieces_of_type(PAWN);
} }
inline Bitboard Position::knights() const { inline Bitboard Position::knights() const {
return this->pieces_of_type(KNIGHT); return pieces_of_type(KNIGHT);
} }
inline Bitboard Position::bishops() const { inline Bitboard Position::bishops() const {
return this->pieces_of_type(BISHOP); return pieces_of_type(BISHOP);
} }
inline Bitboard Position::rooks() const { inline Bitboard Position::rooks() const {
return this->pieces_of_type(ROOK); return pieces_of_type(ROOK);
} }
inline Bitboard Position::queens() const { inline Bitboard Position::queens() const {
return this->pieces_of_type(QUEEN); return pieces_of_type(QUEEN);
} }
inline Bitboard Position::kings() const { inline Bitboard Position::kings() const {
return this->pieces_of_type(KING); return pieces_of_type(KING);
} }
inline Bitboard Position::rooks_and_queens() const { inline Bitboard Position::rooks_and_queens() const {
return this->rooks() | this->queens(); return rooks() | queens();
} }
inline Bitboard Position::bishops_and_queens() const { inline Bitboard Position::bishops_and_queens() const {
return this->bishops() | this->queens(); return bishops() | queens();
} }
inline Bitboard Position::sliders() const { inline Bitboard Position::sliders() const {
return this->bishops() | this->queens() | this->rooks(); return bishops() | queens() | rooks();
} }
inline Bitboard Position::pawns(Color c) const { inline Bitboard Position::pawns(Color c) const {
return this->pieces_of_color_and_type(c, PAWN); return pieces_of_color_and_type(c, PAWN);
} }
inline Bitboard Position::knights(Color c) const { inline Bitboard Position::knights(Color c) const {
return this->pieces_of_color_and_type(c, KNIGHT); return pieces_of_color_and_type(c, KNIGHT);
} }
inline Bitboard Position::bishops(Color c) const { inline Bitboard Position::bishops(Color c) const {
return this->pieces_of_color_and_type(c, BISHOP); return pieces_of_color_and_type(c, BISHOP);
} }
inline Bitboard Position::rooks(Color c) const { inline Bitboard Position::rooks(Color c) const {
return this->pieces_of_color_and_type(c, ROOK); return pieces_of_color_and_type(c, ROOK);
} }
inline Bitboard Position::queens(Color c) const { inline Bitboard Position::queens(Color c) const {
return this->pieces_of_color_and_type(c, QUEEN); return pieces_of_color_and_type(c, QUEEN);
} }
inline Bitboard Position::kings(Color c) const { inline Bitboard Position::kings(Color c) const {
return this->pieces_of_color_and_type(c, KING); return pieces_of_color_and_type(c, KING);
} }
inline Bitboard Position::rooks_and_queens(Color c) const { inline Bitboard Position::rooks_and_queens(Color c) const {
return this->rooks_and_queens() & this->pieces_of_color(c); return rooks_and_queens() & pieces_of_color(c);
} }
inline Bitboard Position::bishops_and_queens(Color c) const { inline Bitboard Position::bishops_and_queens(Color c) const {
return this->bishops_and_queens() & this->pieces_of_color(c); return bishops_and_queens() & pieces_of_color(c);
} }
inline Bitboard Position::sliders_of_color(Color c) const { inline Bitboard Position::sliders_of_color(Color c) const {
return this->sliders() & this->pieces_of_color(c); return sliders() & pieces_of_color(c);
} }
inline int Position::piece_count(Color c, PieceType pt) const { inline int Position::piece_count(Color c, PieceType pt) const {
return pieceCount[c][pt]; return pieceCount[c][pt];
} }
inline int Position::pawn_count(Color c) const {
return this->piece_count(c, PAWN);
}
inline int Position::knight_count(Color c) const {
return this->piece_count(c, KNIGHT);
}
inline int Position::bishop_count(Color c) const {
return this->piece_count(c, BISHOP);
}
inline int Position::rook_count(Color c) const {
return this->piece_count(c, ROOK);
}
inline int Position::queen_count(Color c) const {
return this->piece_count(c, QUEEN);
}
inline Square Position::piece_list(Color c, PieceType pt, int index) const { inline Square Position::piece_list(Color c, PieceType pt, int index) const {
return pieceList[c][pt][index]; return pieceList[c][pt][index];
} }
inline Square Position::pawn_list(Color c, int index) const {
return this->piece_list(c, PAWN, index);
}
inline Square Position::knight_list(Color c, int index) const {
return this->piece_list(c, KNIGHT, index);
}
inline Square Position::bishop_list(Color c, int index) const {
return this->piece_list(c, BISHOP, index);
}
inline Square Position::rook_list(Color c, int index) const {
return this->piece_list(c, ROOK, index);
}
inline Square Position::queen_list(Color c, int index) const {
return this->piece_list(c, QUEEN, index);
}
inline Square Position::ep_square() const { inline Square Position::ep_square() const {
return epSquare; return epSquare;
} }
@@ -567,31 +528,28 @@ inline Bitboard Position::pawn_attacks(Color c, Square s) const {
return StepAttackBB[pawn_of_color(c)][s]; return StepAttackBB[pawn_of_color(c)][s];
} }
inline Bitboard Position::white_pawn_attacks(Square s) const { template<>
return this->pawn_attacks(WHITE, s); inline Bitboard Position::piece_attacks<KNIGHT>(Square s) const {
}
inline Bitboard Position::black_pawn_attacks(Square s) const {
return this->pawn_attacks(BLACK, s);
}
inline Bitboard Position::knight_attacks(Square s) const {
return StepAttackBB[KNIGHT][s]; return StepAttackBB[KNIGHT][s];
} }
inline Bitboard Position::rook_attacks(Square s) const { template<>
return rook_attacks_bb(s, this->occupied_squares()); inline Bitboard Position::piece_attacks<BISHOP>(Square s) const {
return bishop_attacks_bb(s, occupied_squares());
} }
inline Bitboard Position::bishop_attacks(Square s) const { template<>
return bishop_attacks_bb(s, this->occupied_squares()); inline Bitboard Position::piece_attacks<ROOK>(Square s) const {
return rook_attacks_bb(s, occupied_squares());
} }
inline Bitboard Position::queen_attacks(Square s) const { template<>
return this->rook_attacks(s) | this->bishop_attacks(s); inline Bitboard Position::piece_attacks<QUEEN>(Square s) const {
return piece_attacks<ROOK>(s) | piece_attacks<BISHOP>(s);
} }
inline Bitboard Position::king_attacks(Square s) const { template<>
inline Bitboard Position::piece_attacks<KING>(Square s) const {
return StepAttackBB[KING][s]; return StepAttackBB[KING][s];
} }
@@ -600,59 +558,40 @@ inline Bitboard Position::checkers() const {
} }
inline bool Position::is_check() const { inline bool Position::is_check() const {
return this->checkers() != EmptyBoardBB; return checkersBB != EmptyBoardBB;
} }
inline bool Position::white_pawn_attacks_square(Square f, Square t) const { inline bool Position::pawn_attacks_square(Color c, Square f, Square t) const {
return bit_is_set(this->white_pawn_attacks(f), t); return bit_is_set(pawn_attacks(c, f), t);
} }
inline bool Position::black_pawn_attacks_square(Square f, Square t) const { template<PieceType Piece>
return bit_is_set(this->black_pawn_attacks(f), t); Bitboard Position::piece_attacks_square(Square f, Square t) const {
} return bit_is_set(piece_attacks<Piece>(f), t);
inline bool Position::knight_attacks_square(Square f, Square t) const {
return bit_is_set(this->knight_attacks(f), t);
}
inline bool Position::bishop_attacks_square(Square f, Square t) const {
return bit_is_set(this->bishop_attacks(f), t);
}
inline bool Position::rook_attacks_square(Square f, Square t) const {
return bit_is_set(this->rook_attacks(f), t);
}
inline bool Position::queen_attacks_square(Square f, Square t) const {
return bit_is_set(this->queen_attacks(f), t);
}
inline bool Position::king_attacks_square(Square f, Square t) const {
return bit_is_set(this->king_attacks(f), t);
} }
inline bool Position::pawn_is_passed(Color c, Square s) const { inline bool Position::pawn_is_passed(Color c, Square s) const {
return !(this->pawns(opposite_color(c)) & passed_pawn_mask(c, s)); return !(pawns(opposite_color(c)) & passed_pawn_mask(c, s));
} }
inline bool Position::pawn_is_isolated(Color c, Square s) const { inline bool Position::pawn_is_isolated(Color c, Square s) const {
return !(this->pawns(c) & neighboring_files_bb(s)); return !(pawns(c) & neighboring_files_bb(s));
} }
inline bool Position::pawn_is_doubled(Color c, Square s) const { inline bool Position::pawn_is_doubled(Color c, Square s) const {
return this->pawns(c) & squares_behind(c, s); return pawns(c) & squares_behind(c, s);
} }
inline bool Position::file_is_open(File f) const { inline bool Position::file_is_open(File f) const {
return !(this->pawns() & file_bb(f)); return !(pawns() & file_bb(f));
} }
inline bool Position::file_is_half_open(Color c, File f) const { inline bool Position::file_is_half_open(Color c, File f) const {
return !(this->pawns(c) & file_bb(f)); return !(pawns(c) & file_bb(f));
} }
inline bool Position::square_is_weak(Square s, Color c) const { inline bool Position::square_is_weak(Square s, Color c) const {
return !(this->pawns(c) & outpost_mask(opposite_color(c), s)); return !(pawns(c) & outpost_mask(opposite_color(c), s));
} }
inline Key Position::get_key() const { inline Key Position::get_key() const {
@@ -671,6 +610,11 @@ inline Value Position::mg_pst(Color c, PieceType pt, Square s) const {
return MgPieceSquareTable[piece_of_color_and_type(c, pt)][s]; return MgPieceSquareTable[piece_of_color_and_type(c, pt)][s];
} }
inline Value Position::mg_pst_delta(Move m) const {
return MgPieceSquareTable[piece_on(move_from(m))][move_to(m)]
-MgPieceSquareTable[piece_on(move_from(m))][move_from(m)];
}
inline Value Position::eg_pst(Color c, PieceType pt, Square s) const { inline Value Position::eg_pst(Color c, PieceType pt, Square s) const {
return EgPieceSquareTable[piece_of_color_and_type(c, pt)][s]; return EgPieceSquareTable[piece_of_color_and_type(c, pt)][s];
} }
@@ -692,11 +636,14 @@ inline Phase Position::game_phase() const {
// The purpose of the Value(325) terms below is to make sure the difference // The purpose of the Value(325) terms below is to make sure the difference
// between MidgameLimit and EndgameLimit is a power of 2, which should make // between MidgameLimit and EndgameLimit is a power of 2, which should make
// the division at the end of the function a bit faster. // the division at the end of the function a bit faster.
static const Value MidgameLimit = 2 * QueenValueMidgame
+ 2 * RookValueMidgame
+ 6 * BishopValueMidgame
+ Value(325);
static const Value MidgameLimit =
2*QueenValueMidgame+2*RookValueMidgame+6*BishopValueMidgame+Value(325);
static const Value EndgameLimit = 4 * RookValueMidgame - Value(325); static const Value EndgameLimit = 4 * RookValueMidgame - Value(325);
Value npm = this->non_pawn_material(WHITE) + this->non_pawn_material(BLACK);
Value npm = non_pawn_material(WHITE) + non_pawn_material(BLACK);
if (npm >= MidgameLimit) if (npm >= MidgameLimit)
return PHASE_MIDGAME; return PHASE_MIDGAME;
@@ -706,40 +653,49 @@ inline Phase Position::game_phase() const {
return Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit)); return Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
} }
inline bool Position::move_is_deep_pawn_push(Move m) const {
Color c = side_to_move();
return piece_on(move_from(m)) == pawn_of_color(c)
&& relative_rank(c, move_to(m)) > RANK_4;
}
inline bool Position::move_is_pawn_push_to_7th(Move m) const { inline bool Position::move_is_pawn_push_to_7th(Move m) const {
Color c = this->side_to_move();
return Color c = side_to_move();
this->piece_on(move_from(m)) == pawn_of_color(c) && return piece_on(move_from(m)) == pawn_of_color(c)
pawn_rank(c, move_to(m)) == RANK_7; && relative_rank(c, move_to(m)) == RANK_7;
} }
inline bool Position::move_is_passed_pawn_push(Move m) const { inline bool Position::move_is_passed_pawn_push(Move m) const {
Color c = this->side_to_move();
return Color c = side_to_move();
this->piece_on(move_from(m)) == pawn_of_color(c) && return piece_on(move_from(m)) == pawn_of_color(c)
this->pawn_is_passed(c, move_to(m)); && pawn_is_passed(c, move_to(m));
} }
inline bool Position::move_was_passed_pawn_push(Move m) const { inline bool Position::move_was_passed_pawn_push(Move m) const {
Color c = opposite_color(this->side_to_move());
return Color c = opposite_color(side_to_move());
this->piece_on(move_to(m)) == pawn_of_color(c) && return piece_on(move_to(m)) == pawn_of_color(c)
this->pawn_is_passed(c, move_to(m)); && pawn_is_passed(c, move_to(m));
} }
inline int Position::rule_50_counter() const { inline int Position::rule_50_counter() const {
return rule50; return rule50;
} }
inline bool Position::opposite_colored_bishops() const { inline bool Position::opposite_colored_bishops() const {
return
this->bishop_count(WHITE) == 1 && this->bishop_count(BLACK) == 1 && return piece_count(WHITE, BISHOP) == 1
square_color(this->bishop_list(WHITE, 0)) != && piece_count(BLACK, BISHOP) == 1
square_color(this->bishop_list(BLACK, 0)); && square_color(piece_list(WHITE, BISHOP, 0)) != square_color(piece_list(BLACK, BISHOP, 0));
} }
inline bool Position::has_pawn_on_7th(Color c) const { inline bool Position::has_pawn_on_7th(Color c) const {
return this->pawns(c) & relative_rank_bb(c, RANK_7);
return pawns(c) & relative_rank_bb(c, RANK_7);
} }
+106 -81
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -25,65 +26,78 @@
//// ////
#include "position.h" #include "position.h"
#include "value.h"
//// ////
//// Variables //// Variables
//// ////
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 int MgPST[][64] = {
{ }, { },
{// Pawn {// Pawn
// A B C D E F G H
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166, 192, 204, 216, 216, 204, 192, 166, MP-38, MP-12, MP- 0, MP+12, MP+12, MP- 0, MP-12, MP-38,
166, 192, 210, 242, 242, 210, 192, 166, MP-38, MP-12, MP+ 6, MP+38, MP+38, MP+ 6, MP-12, MP-38,
166, 192, 220, 268, 268, 220, 192, 166, MP-38, MP-12, MP+16, MP+64, MP+64, MP+16, MP-12, MP-38,
166, 192, 220, 242, 242, 220, 192, 166, MP-38, MP-12, MP+16, MP+38, MP+38, MP+16, MP-12, MP-38,
166, 192, 210, 216, 216, 210, 192, 166, MP-38, MP-12, MP+ 6, MP+12, MP+12, MP+ 6, MP-12, MP-38,
166, 192, 204, 216, 216, 204, 192, 166, MP-38, MP-12, MP- 0, MP+12, MP+12, MP- 0, MP-12, MP-38,
0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0
}, },
{// Knight {// Knight
704, 730, 756, 768, 768, 756, 730, 704, // A B C D E F G H
743, 768, 794, 807, 807, 794, 768, 743, MK-128, MK-102, MK-76, MK-64, MK-64, MK-76, MK-102, MK-128,
781, 807, 832, 844, 844, 832, 807, 781, MK- 89, MK- 64, MK-38, MK-25, MK-25, MK-38, MK- 64, MK- 89,
807, 832, 857, 870, 870, 857, 832, 807, MK- 51, MK- 25, MK- 0, MK+12, MK+12, MK- 0, MK- 25, MK- 51,
820, 844, 870, 883, 883, 870, 844, 820, MK- 25, MK- 0, MK+25, MK+38, MK+38, MK+25, MK- 0, MK- 25,
820, 844, 870, 883, 883, 870, 844, 820, MK- 12, MK+ 12, MK+38, MK+51, MK+51, MK+38, MK+ 12, MK- 12,
781, 807, 832, 844, 844, 832, 807, 781, MK- 12, MK+ 12, MK+38, MK+51, MK+51, MK+38, MK+ 12, MK- 12,
650, 768, 794, 807, 807, 794, 768, 650 MK- 51, MK- 25, MK- 0, MK+12, MK+12, MK- 0, MK- 25, MK- 51,
MK-182, MK- 64, MK-38, MK-25, MK-25, MK-38, MK- 64, MK-182
}, },
{// Bishop {// Bishop
786, 786, 792, 797, 797, 792, 786, 786, // A B C D E F G H
812, 832, 827, 832, 832, 827, 832, 812, MB-46, MB-46, MB-40, MB-35, MB-35, MB-40, MB-46, MB-46,
817, 827, 842, 837, 837, 842, 827, 817, MB-20, MB- 0, MB- 5, MB- 0, MB- 0, MB- 5, MB- 0, MB-20,
822, 832, 837, 852, 852, 837, 832, 822, MB-15, MB- 5, MB+10, MB+ 5, MB+ 5, MB+10, MB- 5, MB-15,
822, 832, 837, 852, 852, 837, 832, 822, MB-10, MB- 0, MB+ 5, MB+20, MB+20, MB+ 5, MB- 0, MB-10,
817, 827, 842, 837, 837, 842, 827, 817, MB-10, MB- 0, MB+ 5, MB+20, MB+20, MB+ 5, MB- 0, MB-10,
812, 832, 827, 832, 832, 827, 832, 812, MB-15, MB- 5, MB+10, MB+ 5, MB+ 5, MB+10, MB- 5, MB-15,
812, 812, 817, 822, 822, 817, 812, 812 MB-20, MB- 0, MB- 5, MB- 0, MB- 0, MB- 5, MB- 0, MB-20,
MB-20, MB-20, MB-15, MB-10, MB-10, MB-15, MB-20, MB-20
}, },
{// Rook {// Rook
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, // A B C D E F G H
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267, MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
1267, 1275, 1282, 1289, 1289, 1282, 1275, 1267 MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18,
MR-18, MR-10, MR-3, MR+4, MR+4, MR-3, MR-10, MR-18
}, },
{// Queen {// Queen
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, //A B C D E F G H
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560 MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ,
MQ, MQ, MQ, MQ, MQ, MQ, MQ, MQ
}, },
{// King {// King
//A B C D E F G H
302, 328, 276, 225, 225, 276, 328, 302, 302, 328, 276, 225, 225, 276, 328, 302,
276, 302, 251, 200, 200, 251, 302, 276, 276, 302, 251, 200, 200, 251, 302, 276,
225, 251, 200, 149, 149, 200, 251, 225, 225, 251, 200, 149, 149, 200, 251, 225,
@@ -91,64 +105,75 @@ static const int MgPST[][64] = {
175, 200, 149, 98, 98, 149, 200, 175, 175, 200, 149, 98, 98, 149, 200, 175,
149, 175, 124, 72, 72, 124, 175, 149, 149, 175, 124, 72, 72, 124, 175, 149,
124, 149, 98, 47, 47, 98, 149, 124, 124, 149, 98, 47, 47, 98, 149, 124,
98, 124, 72, 21, 21, 72, 124, 98, 98, 124, 72, 21, 21, 72, 124, 98
} }
}; };
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;
static const int EgPST[][64] = { static const int EgPST[][64] = {
{ }, { },
{// Pawn {// Pawn
//A B C D E F G H
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
256, 256, 256, 256, 256, 256, 256, 256, EP, EP, EP, EP, EP, EP, EP, EP,
256, 256, 256, 256, 256, 256, 256, 256, EP, EP, EP, EP, EP, EP, EP, EP,
256, 256, 256, 256, 256, 256, 256, 256, EP, EP, EP, EP, EP, EP, EP, EP,
256, 256, 256, 256, 256, 256, 256, 256, EP, EP, EP, EP, EP, EP, EP, EP,
256, 256, 256, 256, 256, 256, 256, 256, EP, EP, EP, EP, EP, EP, EP, EP,
256, 256, 256, 256, 256, 256, 256, 256, EP, EP, EP, EP, EP, EP, EP, EP,
0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0
}, },
{// Knight {// Knight
730, 756, 781, 794, 794, 781, 756, 730, // A B C D E F G H
756, 781, 807, 820, 820, 807, 781, 756, EK-102, EK-76, EK-51, EK-38, EK-38, EK-51, EK-76, EK-102,
781, 807, 832, 844, 844, 832, 807, 781, EK- 76, EK-51, EK-25, EK-12, EK-12, EK-25, EK-51, EK-76,
794, 820, 844, 857, 857, 844, 820, 794, EK- 51, EK-25, EK- 0, EK+12, EK+12, EK- 0, EK-25, EK-51,
794, 820, 844, 857, 857, 844, 820, 794, EK- 38, EK-12, EK+12, EK+25, EK+25, EK+12, EK-12, EK-38,
781, 807, 832, 844, 844, 832, 807, 781, EK- 38, EK-12, EK+12, EK+25, EK+25, EK+12, EK-12, EK-38,
756, 781, 807, 820, 820, 807, 781, 756, EK- 51, EK-25, EK- 0, EK+12, EK+12, EK- 0, EK-25, EK-51,
730, 756, 781, 794, 794, 781, 756, 730 EK- 76, EK-51, EK-25, EK-12, EK-12, EK-25, EK-51, EK-76,
EK-102, EK-76, EK-51, EK-38, EK-38, EK-51, EK-76, EK-102
}, },
{// Bishop {// Bishop
786, 802, 809, 817, 817, 809, 802, 786, // A B C D E F G H
802, 817, 825, 832, 832, 825, 817, 802, EB-46, EB-30, EB-23, EB-15, EB-15, EB-23, EB-30, EB-46,
809, 825, 832, 839, 839, 832, 825, 809, EB-30, EB-15, EB- 7, EB- 0, EB- 0, EB- 7, EB-15, EB-30,
817, 832, 839, 847, 847, 839, 832, 817, EB-23, EB- 7, EB- 0, EB+ 7, EB+ 7, EB- 0, EB- 7, EB-23,
817, 832, 839, 847, 847, 839, 832, 817, EB-15, EB- 0, EB+ 7, EB+15, EB+15, EB+ 7, EB- 0, EB-15,
809, 825, 832, 839, 839, 832, 825, 809, EB-15, EB- 0, EB+ 7, EB+15, EB+15, EB+ 7, EB- 0, EB-15,
802, 817, 825, 832, 832, 825, 817, 802, EB-23, EB- 7, EB- 0, EB+ 7, EB+ 7, EB- 0, EB- 7, EB-23,
786, 802, 809, 817, 817, 809, 802, 786 EB-30, EB-15, EB- 7, EB- 0, EB- 0, EB- 7, EB-15, EB-30,
EB-46, EB-30, EB-23, EB-15, EB-15, EB-23, EB-30, EB-46
}, },
{// Rook {// Rook
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, // A B C D E F G H
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3, ER-3,
1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282 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 {// Queen
2499, 2520, 2530, 2540, 2540, 2530, 2520, 2499, // A B C D E F G H
2520, 2540, 2550, 2560, 2560, 2550, 2540, 2520, EQ-61, EQ-40, EQ-30, EQ-20, EQ-20, EQ-30, EQ-40, EQ-61,
2530, 2550, 2560, 2570, 2570, 2560, 2550, 2530, EQ-40, EQ-20, EQ-10, EQ- 0, EQ- 0, EQ-10, EQ-20, EQ-40,
2540, 2560, 2570, 2580, 2580, 2570, 2560, 2540, EQ-30, EQ-10, EQ- 0, EQ+10, EQ+10, EQ- 0, EQ-10, EQ-30,
2540, 2560, 2570, 2580, 2580, 2570, 2560, 2540, EQ-20, EQ- 0, EQ+10, EQ+20, EQ+20, EQ+10, EQ- 0, EQ-20,
2530, 2550, 2560, 2570, 2570, 2560, 2550, 2530, EQ-20, EQ- 0, EQ+10, EQ+20, EQ+20, EQ+10, EQ- 0, EQ-20,
2520, 2540, 2550, 2560, 2560, 2550, 2540, 2520, EQ-30, EQ-10, EQ- 0, EQ+10, EQ+10, EQ- 0, EQ-10, EQ-30,
2499, 2520, 2530, 2540, 2540, 2530, 2520, 2499 EQ-40, EQ-20, EQ-10, EQ- 0, EQ- 0, EQ-10, EQ-20, EQ-40,
EQ-61, EQ-40, EQ-30, EQ-20, EQ-20, EQ-30, EQ-40, EQ-61
}, },
{// King {// King
//A B C D E F G H
16, 78, 108, 139, 139, 108, 78, 16, 16, 78, 108, 139, 139, 108, 78, 16,
78, 139, 170, 200, 200, 170, 139, 78, 78, 139, 170, 200, 200, 170, 139, 78,
108, 170, 200, 230, 230, 200, 170, 108, 108, 170, 200, 230, 230, 200, 170, 108,
+10 -9
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -160,14 +161,14 @@ Move move_from_san(Position &pos, const std::string &movestr) {
if(movestr == "O-O-O") { if(movestr == "O-O-O") {
Move m; Move m;
while((m = mp.get_next_move()) != MOVE_NONE) while((m = mp.get_next_move()) != MOVE_NONE)
if(move_is_long_castle(m) && pos.move_is_legal(m)) if(move_is_long_castle(m) && pos.pl_move_is_legal(m))
return m; return m;
return MOVE_NONE; return MOVE_NONE;
} }
else if(movestr == "O-O") { else if(movestr == "O-O") {
Move m; Move m;
while((m = mp.get_next_move()) != MOVE_NONE) while((m = mp.get_next_move()) != MOVE_NONE)
if(move_is_short_castle(m) && pos.move_is_legal(m)) if(move_is_short_castle(m) && pos.pl_move_is_legal(m))
return m; return m;
return MOVE_NONE; return MOVE_NONE;
} }
@@ -189,7 +190,7 @@ Move move_from_san(Position &pos, const std::string &movestr) {
} }
*cc = '\0'; *cc = '\0';
int left = 0, right = strlen(str) - 1; size_t left = 0, right = strlen(str) - 1;
PieceType pt = NO_PIECE_TYPE, promotion; PieceType pt = NO_PIECE_TYPE, promotion;
Square to; Square to;
File fromFile = FILE_NONE; File fromFile = FILE_NONE;
@@ -276,7 +277,7 @@ const std::string line_to_san(const Position &pos, Move line[], int startColumn,
UndoInfo u; UndoInfo u;
std::stringstream s; std::stringstream s;
std::string moveStr; std::string moveStr;
int length, maxLength; size_t length, maxLength;
length = 0; length = 0;
maxLength = 80 - startColumn; maxLength = 80 - startColumn;
@@ -357,7 +358,7 @@ namespace {
n = 0; n = 0;
while((mv = mp.get_next_move()) != MOVE_NONE) while((mv = mp.get_next_move()) != MOVE_NONE)
if(move_to(mv) == to && pos.piece_on(move_from(mv)) == pc if(move_to(mv) == to && pos.piece_on(move_from(mv)) == pc
&& pos.move_is_legal(mv)) && pos.pl_move_is_legal(mv))
moveList[n++] = mv; moveList[n++] = mv;
if(n == 1) if(n == 1)
return AMBIGUITY_NONE; return AMBIGUITY_NONE;
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+674 -492
View File
File diff suppressed because it is too large Load Diff
+8 -7
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -81,9 +82,9 @@ extern History H;
extern void init_threads(); extern void init_threads();
extern void stop_threads(); extern void stop_threads();
extern void think(const Position &pos, bool infinite, bool ponder, int time, extern void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
int increment, int movesToGo, int maxDepth, int maxNodes, int time[], int increment[], int movesToGo, int maxDepth,
int maxTime, Move searchMoves[]); int maxNodes, int maxTime, Move searchMoves[]);
extern int64_t nodes_searched(); extern int64_t nodes_searched();
+5 -5
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -22,7 +23,6 @@
//// ////
#include <cassert> #include <cassert>
#include <cstdio>
#include <string> #include <string>
#include "square.h" #include "square.h"
+7 -5
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -24,6 +25,7 @@
//// Includes //// Includes
//// ////
#include <cstdlib> // for abs()
#include <string> #include <string>
#include "color.h" #include "color.h"
@@ -129,7 +131,7 @@ inline Square relative_square(Color c, Square s) {
return Square(int(s) ^ (int(c) * FlipMask)); return Square(int(s) ^ (int(c) * FlipMask));
} }
inline Rank pawn_rank(Color c, Square s) { inline Rank relative_rank(Color c, Square s) {
return square_rank(relative_square(c, s)); return square_rank(relative_square(c, s));
} }
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+63 -76
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -23,6 +24,7 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <cstring>
#include "tt.h" #include "tt.h"
@@ -34,17 +36,19 @@
/// Constructor /// Constructor
TranspositionTable::TranspositionTable(unsigned mbSize) { TranspositionTable::TranspositionTable(unsigned mbSize) {
size = 0; size = 0;
generation = 0; generation = 0;
writes = 0; writes = 0;
entries = 0; entries = 0;
this->set_size(mbSize); set_size(mbSize);
} }
/// Destructor /// Destructor
TranspositionTable::~TranspositionTable() { TranspositionTable::~TranspositionTable() {
delete [] entries; delete [] entries;
} }
@@ -53,25 +57,28 @@ TranspositionTable::~TranspositionTable() {
/// measured in megabytes. /// measured in megabytes.
void TranspositionTable::set_size(unsigned mbSize) { void TranspositionTable::set_size(unsigned mbSize) {
unsigned newSize;
assert(mbSize >= 4 && mbSize <= 1024); assert(mbSize >= 4 && mbSize <= 1024);
for(newSize = 1024; newSize * 4 * (sizeof(TTEntry)) <= (mbSize << 20); unsigned newSize = 1024;
newSize *= 2);
newSize /= 2;
if(newSize != size) { // We store a cluster of 4 TTEntry for each position and newSize is
// the maximum number of storable positions
for ( ; newSize * 4 * (sizeof(TTEntry)) <= (mbSize << 20); newSize *= 2);
newSize /= 2;
if (newSize != size)
{
size = newSize; size = newSize;
delete [] entries; delete [] entries;
entries = new TTEntry[size * 4]; entries = new TTEntry[size * 4];
if(entries == NULL) { if (!entries)
{
std::cerr << "Failed to allocate " << mbSize std::cerr << "Failed to allocate " << mbSize
<< " MB for transposition table." << " MB for transposition table."
<< std::endl; << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
this->clear(); clear();
} }
} }
@@ -82,6 +89,7 @@ void TranspositionTable::set_size(unsigned mbSize) {
/// Perhaps we should also clear it when the "ucinewgame" command is recieved? /// Perhaps we should also clear it when the "ucinewgame" command is recieved?
void TranspositionTable::clear() { void TranspositionTable::clear() {
memset(entries, 0, size * 4 * sizeof(TTEntry)); memset(entries, 0, size * 4 * sizeof(TTEntry));
} }
@@ -99,21 +107,29 @@ void TranspositionTable::store(const Position &pos, Value v, Depth d,
Move m, ValueType type) { Move m, ValueType type) {
TTEntry *tte, *replace; TTEntry *tte, *replace;
tte = replace = entries + int(pos.get_key() & (size - 1)) * 4; tte = replace = first_entry(pos);
for(int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++)
if((tte+i)->key() == pos.get_key()) { {
if (!(tte+i)->key()) // still empty
{
*(tte+i) = TTEntry(pos.get_key(), v, type, d, m, generation);
writes++;
return;
}
if ((tte+i)->key() == pos.get_key()) // overwrite old
{
if (m == MOVE_NONE) if (m == MOVE_NONE)
m = (tte+i)->move(); m = (tte+i)->move();
*(tte+i) = TTEntry(pos.get_key(), v, type, d, m, generation); *(tte+i) = TTEntry(pos.get_key(), v, type, d, m, generation);
return; return;
} }
if(replace->generation() == generation) { if ( i == 0 // already is (replace == tte+i), common case
if((tte+i)->generation() != generation || || replace->generation() < (tte+i)->generation())
(tte+i)->depth() < replace->depth()) continue;
replace = tte+i;
} if ( replace->generation() > (tte+i)->generation()
else if((tte+i)->generation() != generation && || (tte+i)->depth() < replace->depth())
(tte+i)->depth() < replace->depth())
replace = tte+i; replace = tte+i;
} }
*replace = TTEntry(pos.get_key(), v, type, d, m, generation); *replace = TTEntry(pos.get_key(), v, type, d, m, generation);
@@ -122,42 +138,37 @@ void TranspositionTable::store(const Position &pos, Value v, Depth d,
/// TranspositionTable::retrieve looks up the current position in the /// TranspositionTable::retrieve looks up the current position in the
/// transposition table, and extracts the value, value type, depth and /// transposition table. Returns a pointer to the TTEntry or NULL
/// best move if the position is found. The return value is true if /// if position is not found.
/// the position is found, and false if it isn't.
bool TranspositionTable::retrieve(const Position &pos, Value *value, const TTEntry* TranspositionTable::retrieve(const Position &pos) const {
Depth *d, Move *move,
ValueType *type) const {
TTEntry *tte;
bool found = false;
tte = entries + int(pos.get_key() & (size - 1)) * 4; TTEntry *tte = first_entry(pos);
for(int i = 0; i < 4 && !found ; i++)
if((tte+i)->key() == pos.get_key()) { for (int i = 0; i < 4; i++, tte++)
tte = tte + i; {
found = true; if (tte->key() == pos.get_key())
return tte;
} }
if(!found) { return NULL;
*move = MOVE_NONE;
return false;
} }
*value = tte->value();
*type = tte->type();
*d = tte->depth();
*move = tte->move();
return true; /// TranspositionTable::first_entry returns a pointer to the first
/// entry of a cluster given a position.
inline TTEntry* TranspositionTable::first_entry(const Position &pos) const {
return entries + (int(pos.get_key() & (size - 1)) << 2);
} }
/// TranspositionTable::new_search() is called at the beginning of every new /// TranspositionTable::new_search() is called at the beginning of every new
/// search. It increments the "generation" variable, which is used to /// search. It increments the "generation" variable, which is used to
/// distinguish transposition table entries from previous searches from /// distinguish transposition table entries from previous searches from
/// entries from the current search. /// entries from the current search.
void TranspositionTable::new_search() { void TranspositionTable::new_search() {
generation++; generation++;
writes = 0; writes = 0;
} }
@@ -169,11 +180,13 @@ void TranspositionTable::new_search() {
/// overwritten. /// overwritten.
void TranspositionTable::insert_pv(const Position &pos, Move pv[]) { void TranspositionTable::insert_pv(const Position &pos, Move pv[]) {
UndoInfo u; UndoInfo u;
Position p(pos); Position p(pos);
for(int i = 0; pv[i] != MOVE_NONE; i++) { for (int i = 0; pv[i] != MOVE_NONE; i++)
this->store(p, VALUE_NONE, Depth(0), pv[i], VALUE_TYPE_NONE); {
store(p, VALUE_NONE, Depth(0), pv[i], VALUE_TYPE_NONE);
p.do_move(pv[i], u); p.do_move(pv[i], u);
} }
} }
@@ -184,6 +197,7 @@ void TranspositionTable::insert_pv(const Position &pos, Move pv[]) {
/// It is used to display the "info hashfull ..." information in UCI. /// It is used to display the "info hashfull ..." information in UCI.
int TranspositionTable::full() { int TranspositionTable::full() {
double N = double(size) * 4.0; double N = double(size) * 4.0;
return int(1000 * (1 - exp(writes * log(1.0 - 1.0/N)))); return int(1000 * (1 - exp(writes * log(1.0 - 1.0/N))));
} }
@@ -195,36 +209,9 @@ TTEntry::TTEntry() {
} }
TTEntry::TTEntry(Key k, Value v, ValueType t, Depth d, Move m, TTEntry::TTEntry(Key k, Value v, ValueType t, Depth d, Move m,
int generation) { int generation) :
key_ = k; key_ (k), data((m & 0x7FFFF) | (t << 20) | (generation << 23)),
data = (m & 0x7FFFF) | (t << 20) | (generation << 23); value_(v), depth_(int16_t(d)) {}
value_ = v;
depth_ = int16_t(d);
}
/// Functions for extracting data from TTEntry objects.
Key TTEntry::key() const {
return key_;
}
Depth TTEntry::depth() const {
return Depth(depth_);
}
Move TTEntry::move() const {
return Move(data & 0x7FFFF);
}
Value TTEntry::value() const {
return Value(value_);
}
ValueType TTEntry::type() const {
return ValueType((data >> 20) & 3);
}
int TTEntry::generation() const {
return (data >> 23);
}
+14 -13
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -40,12 +41,12 @@ class TTEntry {
public: public:
TTEntry(); TTEntry();
TTEntry(Key k, Value v, ValueType t, Depth d, Move m, int generation); TTEntry(Key k, Value v, ValueType t, Depth d, Move m, int generation);
Key key() const; Key key() const { return key_; }
Depth depth() const; Depth depth() const { return Depth(depth_); }
Move move() const; Move move() const { return Move(data & 0x7FFFF); }
Value value() const; Value value() const { return Value(value_); }
ValueType type() const; ValueType type() const { return ValueType((data >> 20) & 3); }
int generation() const; int generation() const { return (data >> 23); }
private: private:
Key key_; Key key_;
@@ -54,7 +55,6 @@ private:
int16_t depth_; int16_t depth_;
}; };
/// The transposition table class. This is basically just a huge array /// The transposition table class. This is basically just a huge array
/// containing TTEntry objects, and a few methods for writing new entries /// containing TTEntry objects, and a few methods for writing new entries
/// and reading new ones. /// and reading new ones.
@@ -67,13 +67,14 @@ public:
void set_size(unsigned mbSize); void set_size(unsigned mbSize);
void clear(); void clear();
void store(const Position &pos, Value v, Depth d, Move m, ValueType type); void store(const Position &pos, Value v, Depth d, Move m, ValueType type);
bool retrieve(const Position &pos, Value *value, Depth *d, Move *move, const TTEntry* retrieve(const Position &pos) const;
ValueType *type) const;
void new_search(); void new_search();
void insert_pv(const Position &pos, Move pv[]); void insert_pv(const Position &pos, Move pv[]);
int full(); int full();
private: private:
inline TTEntry* first_entry(const Position &pos) const;
unsigned size; unsigned size;
int writes; int writes;
TTEntry* entries; TTEntry* entries;
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+121 -185
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -22,6 +23,7 @@
//// ////
#include <iostream> #include <iostream>
#include <sstream>
#include <string> #include <string>
#include "book.h" #include "book.h"
@@ -42,30 +44,10 @@
namespace { namespace {
// UCIInputParser is a class for parsing UCI input. The class is // UCIInputParser is a class for parsing UCI input. The class
// very simple, and basically just consist of a constant input // is actually a string stream built on a given input string.
// string and a current location in the string. There are methods
// for checking if we are at the end of the line, for getting the
// next token (defined as any whitespace-delimited sequence of
// characters), and for getting the rest of the line as a single
// string.
class UCIInputParser {
public:
UCIInputParser(const std::string &line);
std::string get_next_token();
std::string get_rest_of_line();
bool at_end_of_line();
private:
const std::string &inputLine;
int length, currentIndex;
void skip_whitespace();
};
typedef std::istringstream UCIInputParser;
// The root position. This is set up when the user (or in practice, the GUI) // 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() // sends the "position" UCI command. The root position is sent to the think()
@@ -73,7 +55,7 @@ namespace {
Position RootPosition; Position RootPosition;
// Local functions // Local functions
void wait_for_command(); void get_command();
void handle_command(const std::string &command); void handle_command(const std::string &command);
void set_option(UCIInputParser &uip); void set_option(UCIInputParser &uip);
void set_position(UCIInputParser &uip); void set_position(UCIInputParser &uip);
@@ -91,8 +73,11 @@ namespace {
/// command. /// command.
void uci_main_loop() { void uci_main_loop() {
RootPosition.from_fen(StartPosition); RootPosition.from_fen(StartPosition);
while(1) wait_for_command();
while (1)
get_command();
} }
@@ -102,80 +87,19 @@ void uci_main_loop() {
namespace { namespace {
/// // get_command() waits for a command from the user, and passes
/// Implementation of the UCIInputParser class. // this command to handle_command. get_command also intercepts
///
// Constructor for the UCIInputParser class. The constructor takes a
// text string containing a single UCI command as input.
UCIInputParser::UCIInputParser(const std::string &line) : inputLine(line) {
this->currentIndex = 0;
this->length = line.length();
}
// UCIInputParser::skip_whitspace() skips any number of whitespace
// characters from the current location in an input string.
void UCIInputParser::skip_whitespace() {
while(isspace((int)(unsigned char)this->inputLine[this->currentIndex]))
this->currentIndex++;
}
// UCIInputParser::get_next_token() gets the next token in an UCI
// command. A 'token' in an UCI command is simply any
// whitespace-delimited sequence of characters.
std::string UCIInputParser::get_next_token() {
int i, j;
this->skip_whitespace();
for(i = j = this->currentIndex;
j < this->length && !isspace(this->inputLine[j]);
j++);
this->currentIndex = j;
this->skip_whitespace();
std::string str = this->inputLine.substr(i, j - i);
return str;
}
// UCIInputParser::get_rest_of_line() returns the rest of the input
// line (from the current location) as a single string.
std::string UCIInputParser::get_rest_of_line() {
this->skip_whitespace();
return this->inputLine.substr(this->currentIndex, this->length);
}
// UCIInputParser::at_end_of_line() tests whether we have reached the
// end of the input string, i.e. if any more input remains to be
// parsed.
bool UCIInputParser::at_end_of_line() {
return this->currentIndex == this->length;
}
///
/// Other functions
///
// wait_for_command() waits for a command from the user, and passes
// this command to handle_command. wait_for_command also intercepts
// EOF from stdin, by translating EOF to the "quit" command. This // EOF from stdin, by translating EOF to the "quit" command. This
// ensures that Glaurung exits gracefully if the GUI dies // ensures that Stockfish exits gracefully if the GUI dies
// unexpectedly. // unexpectedly.
void wait_for_command() { void get_command() {
std::string command; std::string command;
if(!std::getline(std::cin, command)) command = "quit";
if (!std::getline(std::cin, command))
command = "quit";
handle_command(command); handle_command(command);
} }
@@ -186,45 +110,54 @@ namespace {
// commands, the function also supports a few debug commands. // commands, the function also supports a few debug commands.
void handle_command(const std::string &command) { void handle_command(const std::string &command) {
UCIInputParser uip(command);
std::string s = uip.get_next_token();
if(s == "quit") { UCIInputParser uip(command);
std::string token;
uip >> token; // operator >> skips any whitespace
if (token == "quit")
{
OpeningBook.close(); OpeningBook.close();
stop_threads(); stop_threads();
quit_eval(); quit_eval();
exit(0); exit(0);
} }
else if(s == "uci") { else if (token == "uci")
std::cout << "id name " << engine_name() << std::endl; {
std::cout << "id author Tord Romstad" << std::endl; std::cout << "id name " << engine_name() << std::endl
<< "id author Tord Romstad, Marco Costalba"
<< std::endl;
print_uci_options(); print_uci_options();
std::cout << "uciok" << std::endl; std::cout << "uciok" << std::endl;
} }
else if(s == "ucinewgame") { else if (token == "ucinewgame")
{
TT.clear(); TT.clear();
Position::init_piece_square_tables(); Position::init_piece_square_tables();
RootPosition.from_fen(StartPosition); RootPosition.from_fen(StartPosition);
} }
else if(s == "isready") else if (token == "isready")
std::cout << "readyok" << std::endl; std::cout << "readyok" << std::endl;
else if(s == "position") else if (token == "position")
set_position(uip); set_position(uip);
else if(s == "setoption") else if (token == "setoption")
set_option(uip); set_option(uip);
else if(s == "go") else if (token == "go")
go(uip); go(uip);
// The remaining commands are for debugging purposes only. // The remaining commands are for debugging purposes only.
// Perhaps they should be removed later in order to reduce the // Perhaps they should be removed later in order to reduce the
// size of the program binary. // size of the program binary.
else if(s == "d") else if (token == "d")
RootPosition.print(); RootPosition.print();
else if(s == "flip") { else if (token == "flip")
{
Position p(RootPosition); Position p(RootPosition);
RootPosition.flipped_copy(p); RootPosition.flipped_copy(p);
} }
else if(s == "eval") { else if (token == "eval")
{
EvalInfo ei; EvalInfo ei;
std::cout << "Incremental mg: " << RootPosition.mg_value() std::cout << "Incremental mg: " << RootPosition.mg_value()
<< std::endl; << std::endl;
@@ -234,51 +167,62 @@ namespace {
<< evaluate(RootPosition, ei, 0) << evaluate(RootPosition, ei, 0)
<< std::endl; << std::endl;
} }
else if(s == "key") { else if (token == "key")
{
std::cout << "key: " << RootPosition.get_key() std::cout << "key: " << RootPosition.get_key()
<< " material key: " << RootPosition.get_material_key() << " material key: " << RootPosition.get_material_key()
<< " pawn key: " << RootPosition.get_pawn_key() << " pawn key: " << RootPosition.get_pawn_key()
<< std::endl; << std::endl;
} }
else { else
{
std::cout << "Unknown command: " << command << std::endl; std::cout << "Unknown command: " << command << std::endl;
while(!uip.at_end_of_line()) { while (!uip.eof())
std::cout << uip.get_next_token() << std::endl; {
uip >> token;
std::cout << token << std::endl;
} }
} }
} }
// set_position() is called when Glaurung receives the "position" UCI // set_position() is called when Stockfish receives the "position" UCI
// command. The input parameter is a UCIInputParser. It is assumed // command. The input parameter is a UCIInputParser. It is assumed
// that this parser has consumed the first token of the UCI command // that this parser has consumed the first token of the UCI command
// ("position"), and is ready to read the second token ("startpos" // ("position"), and is ready to read the second token ("startpos"
// or "fen", if the input is well-formed). // or "fen", if the input is well-formed).
void set_position(UCIInputParser &uip) { void set_position(UCIInputParser &uip) {
std::string token; std::string token;
token = uip.get_next_token(); uip >> token; // operator >> skips any whitespace
if (token == "startpos") if (token == "startpos")
RootPosition.from_fen(StartPosition); RootPosition.from_fen(StartPosition);
else if(token == "fen") { else if (token == "fen")
{
std::string fen; std::string fen;
while(token != "moves" && !uip.at_end_of_line()) { while (token != "moves" && !uip.eof())
token = uip.get_next_token(); {
uip >> token;
fen += token; fen += token;
fen += ' '; fen += ' ';
} }
RootPosition.from_fen(fen); RootPosition.from_fen(fen);
} }
if(!uip.at_end_of_line()) { if (!uip.eof())
{
if (token != "moves") if (token != "moves")
token = uip.get_next_token(); uip >> token;
if(token == "moves") { if (token == "moves")
{
Move move; Move move;
UndoInfo u; UndoInfo u;
while(!uip.at_end_of_line()) { while (!uip.eof())
token = uip.get_next_token(); {
uip >> token;
move = move_from_string(RootPosition, token); move = move_from_string(RootPosition, token);
RootPosition.do_move(move, u); RootPosition.do_move(move, u);
if (RootPosition.rule_50_counter() == 0) if (RootPosition.rule_50_counter() == 0)
@@ -289,32 +233,37 @@ namespace {
} }
// set_option() is called when Glaurung receives the "setoption" UCI // set_option() is called when Stockfish receives the "setoption" UCI
// command. The input parameter is a UCIInputParser. It is assumed // command. The input parameter is a UCIInputParser. It is assumed
// that this parser has consumed the first token of the UCI command // that this parser has consumed the first token of the UCI command
// ("setoption"), and is ready to read the second token ("name", if // ("setoption"), and is ready to read the second token ("name", if
// the input is well-formed). // the input is well-formed).
void set_option(UCIInputParser &uip) { void set_option(UCIInputParser &uip) {
std::string token;
if(!uip.at_end_of_line()) { std::string token, name;
token = uip.get_next_token();
if(token == "name" && !uip.at_end_of_line()) { uip >> token;
std::string name = uip.get_next_token(); if (token == "name")
std::string nextToken; {
while(!uip.at_end_of_line() uip >> name;
&& (nextToken = uip.get_next_token()) != "value") uip >> token;
name += (" " + nextToken); while (!uip.eof() && token != "value")
if(nextToken == "value") {
set_option_value(name, uip.get_rest_of_line()); name += (" " + token);
else uip >> token;
}
if (token == "value")
{
std::getline(uip, token); // reads until end of line
set_option_value(name, token);
} else
push_button(name); push_button(name);
} }
} }
}
// go() is called when Glaurung receives the "go" UCI command. The // go() is called when Stockfish receives the "go" UCI command. The
// input parameter is a UCIInputParser. It is assumed that this // input parameter is a UCIInputParser. It is assumed that this
// parser has consumed the first token of the UCI command ("go"), // parser has consumed the first token of the UCI command ("go"),
// and is ready to read the second token. The function sets the // and is ready to read the second token. The function sets the
@@ -323,57 +272,46 @@ namespace {
// parameters. // parameters.
void go(UCIInputParser &uip) { void go(UCIInputParser &uip) {
std::string token; std::string token;
int time[2] = {0, 0}, inc[2] = {0, 0}, movesToGo = 0, depth = 0, nodes = 0;
int moveTime = 0; int time[2] = {0, 0}, inc[2] = {0, 0};
int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
bool infinite = false, ponder = false; bool infinite = false, ponder = false;
Move searchMoves[500]; Move searchMoves[500];
searchMoves[0] = MOVE_NONE; searchMoves[0] = MOVE_NONE;
while(!uip.at_end_of_line()) { while (!uip.eof())
token = uip.get_next_token(); {
uip >> token;
if (token == "infinite") if (token == "infinite")
infinite = true; infinite = true;
else if (token == "ponder") else if (token == "ponder")
ponder = true; ponder = true;
else if(token == "wtime") { else if (token == "wtime")
if(!uip.at_end_of_line()) uip >> time[0];
time[0] = atoi(uip.get_next_token().c_str()); else if (token == "btime")
} uip >> time[1];
else if(token == "btime") { else if (token == "winc")
if(!uip.at_end_of_line()) uip >> inc[0];
time[1] = atoi(uip.get_next_token().c_str()); else if (token == "binc")
} uip >> inc[1];
else if(token == "winc") { else if (token == "movestogo")
if(!uip.at_end_of_line()) uip >> movesToGo;
inc[0] = atoi(uip.get_next_token().c_str()); else if (token == "depth")
} uip >> depth;
else if(token == "binc") { else if (token == "nodes")
if(!uip.at_end_of_line()) uip >> nodes;
inc[1] = atoi(uip.get_next_token().c_str()); else if (token == "movetime")
} uip >> moveTime;
else if(token == "movestogo") { else if (token == "searchmoves")
if(!uip.at_end_of_line()) {
movesToGo = atoi(uip.get_next_token().c_str());
}
else if(token == "depth") {
if(!uip.at_end_of_line())
depth = atoi(uip.get_next_token().c_str());
}
else if(token == "nodes") {
if(!uip.at_end_of_line())
nodes = atoi(uip.get_next_token().c_str());
}
else if(token == "movetime") {
if(!uip.at_end_of_line())
moveTime = atoi(uip.get_next_token().c_str());
}
else if(token == "searchmoves" && !uip.at_end_of_line()) {
int numOfMoves = 0; int numOfMoves = 0;
while(!uip.at_end_of_line()) { while (!uip.eof())
token = uip.get_next_token(); {
uip >> token;
searchMoves[numOfMoves++] = move_from_string(RootPosition, token); searchMoves[numOfMoves++] = move_from_string(RootPosition, token);
} }
searchMoves[numOfMoves] = MOVE_NONE; searchMoves[numOfMoves] = MOVE_NONE;
@@ -383,9 +321,7 @@ namespace {
if (moveTime) if (moveTime)
infinite = true; // HACK infinite = true; // HACK
think(RootPosition, infinite, ponder, time[RootPosition.side_to_move()], think(RootPosition, infinite, ponder, RootPosition.side_to_move(), time,
inc[RootPosition.side_to_move()], movesToGo, depth, nodes, moveTime, inc, movesToGo, depth, nodes, moveTime, searchMoves);
searchMoves);
} }
} }
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+214 -117
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -22,8 +23,9 @@
//// ////
#include <cassert> #include <cassert>
#include <cstdarg> #include <string>
#include <cstdio> #include <sstream>
#include <vector>
#include "misc.h" #include "misc.h"
#include "thread.h" #include "thread.h"
@@ -47,92 +49,157 @@ namespace {
/// Types /// Types
/// ///
enum OptionType { SPIN, COMBO, CHECK, STRING, BUTTON, OPTION_TYPE_NONE}; enum OptionType { SPIN, COMBO, CHECK, STRING, BUTTON };
typedef std::vector<std::string> ComboValues;
struct Option { struct Option {
char name[50], defaultValue[300], currentValue[300];
std::string name, defaultValue, currentValue;
OptionType type; OptionType type;
int minValue, maxValue; int minValue, maxValue;
char comboValues[8][64]; ComboValues comboValues;
Option(const char* name, const char* defaultValue, OptionType = STRING);
Option(const char* name, bool defaultValue, OptionType = CHECK);
Option(const char* name, int defaultValue, int minValue, int maxValue);
}; };
typedef std::vector<Option> Options;
///
/// Constants
///
// load_defaults populates the options vector with the hard
// coded names and default values.
void load_defaults(Options& o) {
o.push_back(Option("Use Search Log", false));
o.push_back(Option("Search Log Filename", "SearchLog.txt"));
o.push_back(Option("Book File", "book.bin"));
o.push_back(Option("Mobility (Middle Game)", 100, 0, 200));
o.push_back(Option("Mobility (Endgame)", 100, 0, 200));
o.push_back(Option("Pawn Structure (Middle Game)", 100, 0, 200));
o.push_back(Option("Pawn Structure (Endgame)", 100, 0, 200));
o.push_back(Option("Passed Pawns (Middle Game)", 100, 0, 200));
o.push_back(Option("Passed Pawns (Endgame)", 100, 0, 200));
o.push_back(Option("Aggressiveness", 100, 0, 200));
o.push_back(Option("Cowardice", 100, 0, 200));
o.push_back(Option("King Safety Curve", "Quadratic", COMBO));
o.back().comboValues.push_back("Quadratic");
o.back().comboValues.push_back("Linear"); /*, "From File"*/
o.push_back(Option("King Safety Coefficient", 40, 1, 100));
o.push_back(Option("King Safety X Intercept", 0, 0, 20));
o.push_back(Option("King Safety Max Slope", 30, 10, 100));
o.push_back(Option("King Safety Max Value", 500, 100, 1000));
o.push_back(Option("Queen Contact Check Bonus", 4, 0, 8));
o.push_back(Option("Rook Contact Check Bonus", 2, 0, 4));
o.push_back(Option("Queen Check Bonus", 2, 0, 4));
o.push_back(Option("Rook Check Bonus", 1, 0, 4));
o.push_back(Option("Bishop Check Bonus", 1, 0, 4));
o.push_back(Option("Knight Check Bonus", 1, 0, 4));
o.push_back(Option("Discovered Check Bonus", 3, 0, 8));
o.push_back(Option("Mate Threat Bonus", 3, 0, 8));
o.push_back(Option("Check Extension (PV nodes)", 2, 0, 2));
o.push_back(Option("Check Extension (non-PV nodes)", 1, 0, 2));
o.push_back(Option("Single Reply Extension (PV nodes)", 2, 0, 2));
o.push_back(Option("Single Reply Extension (non-PV nodes)", 2, 0, 2));
o.push_back(Option("Mate Threat Extension (PV nodes)", 0, 0, 2));
o.push_back(Option("Mate Threat Extension (non-PV nodes)", 0, 0, 2));
o.push_back(Option("Pawn Push to 7th Extension (PV nodes)", 1, 0, 2));
o.push_back(Option("Pawn Push to 7th Extension (non-PV nodes)", 1, 0, 2));
o.push_back(Option("Passed Pawn Extension (PV nodes)", 1, 0, 2));
o.push_back(Option("Passed Pawn Extension (non-PV nodes)", 0, 0, 2));
o.push_back(Option("Pawn Endgame Extension (PV nodes)", 2, 0, 2));
o.push_back(Option("Pawn Endgame Extension (non-PV nodes)", 2, 0, 2));
o.push_back(Option("Full Depth Moves (PV nodes)", 14, 1, 100));
o.push_back(Option("Full Depth Moves (non-PV nodes)", 3, 1, 100));
o.push_back(Option("Threat Depth", 5, 0, 100));
o.push_back(Option("Selective Plies", 7, 0, 10));
o.push_back(Option("Futility Pruning (Main Search)", true));
o.push_back(Option("Futility Pruning (Quiescence Search)", true));
o.push_back(Option("Futility Margin 0", 50, 0, 1000));
o.push_back(Option("Futility Margin 1", 100, 0, 1000));
o.push_back(Option("Futility Margin 2", 300, 0, 1000));
o.push_back(Option("Maximum Razoring Depth", 3, 0, 4));
o.push_back(Option("Razoring Margin", 300, 150, 600));
o.push_back(Option("LSN filtering", false));
o.push_back(Option("LSN Time Margin (sec)", 4, 1, 10));
o.push_back(Option("LSN Value Margin", 200, 100, 600));
o.push_back(Option("Randomness", 0, 0, 10));
o.push_back(Option("Minimum Split Depth", 4, 4, 7));
o.push_back(Option("Maximum Number of Threads per Split Point", 5, 4, 8));
o.push_back(Option("Threads", 1, 1, 8));
o.push_back(Option("Hash", 32, 4, 4096));
o.push_back(Option("Clear Hash", false, BUTTON));
o.push_back(Option("Ponder", true));
o.push_back(Option("OwnBook", true));
o.push_back(Option("MultiPV", 1, 1, 500));
o.push_back(Option("UCI_ShowCurrLine", false));
o.push_back(Option("UCI_Chess960", false));
}
/// ///
/// Variables /// Variables
/// ///
Option Options[] = { Options options;
{ "Use Search Log", "false", "false", CHECK, 0, 0, {""} },
{ "Search Log Filename", "SearchLog.txt", "SearchLog.txt", STRING, 0, 0, {""} },
{ "Book File", "book.bin", "book.bin", STRING, 0, 0, {""} },
{ "Mobility (Middle Game)", "100", "100", SPIN, 0, 200, {""} },
{ "Mobility (Endgame)", "100", "100", SPIN, 0, 200, {""} },
{ "Pawn Structure (Middle Game)", "100", "100", SPIN, 0, 200, {""} },
{ "Pawn Structure (Endgame)", "100", "100", SPIN, 0, 200, {""} },
{ "Passed Pawns (Middle Game)", "100", "100", SPIN, 0, 200, {""} },
{ "Passed Pawns (Endgame)", "100", "100", SPIN, 0, 200, {""} },
{ "Aggressiveness", "100", "100", SPIN, 0, 200, {""} },
{ "Cowardice", "100", "100", SPIN, 0, 200, {""} },
{ "King Safety Curve", "Quadratic", "Quadratic", COMBO, 0, 0,
{ "Quadratic", "Linear" /*, "From File"*/ } },
{ "King Safety Coefficient", "40", "40", SPIN, 1, 100 , {""} },
{ "King Safety X Intercept", "0", "0", SPIN, 0, 20, {""} },
{ "King Safety Max Slope", "30", "30", SPIN, 10, 100, {""} },
{ "King Safety Max Value", "500", "500", SPIN, 100, 1000, {""} },
{ "Queen Contact Check Bonus", "4", "4", SPIN, 0, 8, {""} },
{ "Rook Contact Check Bonus", "2", "2", SPIN, 0, 4, {""} },
{ "Queen Check Bonus", "2", "2", SPIN, 0, 4, {""} },
{ "Rook Check Bonus", "1", "1", SPIN, 0, 4, {""} },
{ "Bishop Check Bonus", "1", "1", SPIN, 0, 4, {""} },
{ "Knight Check Bonus", "1", "1", SPIN, 0, 4, {""} },
{ "Discovered Check Bonus", "3", "3", SPIN, 0, 8, {""} },
{ "Mate Threat Bonus", "3", "3", SPIN, 0, 8, {""} },
{ "Check Extension (PV nodes)", "2", "2", SPIN, 0, 2, {""} },
{ "Check Extension (non-PV nodes)", "1", "1", SPIN, 0, 2, {""} },
{ "Single Reply Extension (PV nodes)", "2", "2", SPIN, 0, 2, {""} },
{ "Single Reply Extension (non-PV nodes)", "2", "2", SPIN, 0, 2, {""} },
{ "Mate Threat Extension (PV nodes)", "0", "0", SPIN, 0, 2, {""} },
{ "Mate Threat Extension (non-PV nodes)", "0", "0", SPIN, 0, 2, {""} },
{ "Pawn Push to 7th Extension (PV nodes)", "1", "1", SPIN, 0, 2, {""} },
{ "Pawn Push to 7th Extension (non-PV nodes)", "1", "1", SPIN, 0, 2, {""} },
{ "Passed Pawn Extension (PV nodes)", "1", "1", SPIN, 0, 2, {""} },
{ "Passed Pawn Extension (non-PV nodes)", "0", "0", SPIN, 0, 2, {""} },
{ "Pawn Endgame Extension (PV nodes)", "2", "2", SPIN, 0, 2, {""} },
{ "Pawn Endgame Extension (non-PV nodes)", "2", "2", SPIN, 0, 2, {""} },
{ "Full Depth Moves (PV nodes)", "14", "14", SPIN, 1, 100, {""} },
{ "Full Depth Moves (non-PV nodes)", "3", "3", SPIN, 1, 100, {""} },
{ "Threat Depth", "5", "5", SPIN, 0, 100, {""} },
{ "Selective Plies", "7", "7", SPIN, 0, 10, {""} },
{ "Futility Pruning (Main Search)", "true", "true", CHECK, 0, 0, {""} },
{ "Futility Pruning (Quiescence Search)", "true", "true", CHECK, 0, 0, {""} },
{ "Futility Margin 0", "50", "50", SPIN, 0, 1000, {""} },
{ "Futility Margin 1", "100", "100", SPIN, 0, 1000, {""} },
{ "Futility Margin 2", "300", "300", SPIN, 0, 1000, {""} },
{ "Maximum Razoring Depth", "3", "3", SPIN, 0, 4, {""} },
{ "Razoring Margin", "300", "300", SPIN, 150, 600, {""} },
{ "Randomness", "0", "0", SPIN, 0, 10, {""} },
{ "Minimum Split Depth", "4", "4", SPIN, 4, 7, {""} },
{ "Maximum Number of Threads per Split Point", "5", "5", SPIN, 4, 8, {""} },
{ "Threads", "1", "1", SPIN, 1, 8, {""} },
{ "Hash", "32", "32", SPIN, 4, 4096, {""} },
{ "Clear Hash", "false", "false", BUTTON, 0, 0, {""} },
{ "Ponder", "true", "true", CHECK, 0, 0, {""} },
{ "OwnBook", "true", "true", CHECK, 0, 0, {""} },
{ "MultiPV", "1", "1", SPIN, 1, 500, {""} },
{ "UCI_ShowCurrLine", "false", "false", CHECK, 0, 0, {""} },
{ "UCI_Chess960", "false", "false", CHECK, 0, 0, {""} },
{ "", "", "", OPTION_TYPE_NONE, 0, 0, {""}}
};
// Local functions
Options::iterator option_with_name(const std::string& optionName);
/// // stringify converts a value of type T to a std::string
/// Functions template<typename T>
/// std::string stringify(const T& v) {
Option *option_with_name(const char *optionName);
std::ostringstream ss;
ss << v;
return ss.str();
} }
// We want conversion from a bool value to be "true" or "false",
// not "1" or "0", so add a specialization for bool type.
template<>
std::string stringify<bool>(const bool& v) {
return v ? "true" : "false";
}
// 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.
template<typename T>
T get_option_value(const std::string& optionName) {
T ret;
Options::iterator it = option_with_name(optionName);
if (it != options.end())
{
std::istringstream ss(it->currentValue);
ss >> ret;
}
return ret;
}
// Unfortunatly we need a specialization to convert "false" and "true"
// to proper bool values. The culprit is that we use a non standard way
// to store a bool value in a string, in particular we use "false" and
// "true" instead of "0" and "1" due to how UCI protocol works.
template<>
bool get_option_value<bool>(const std::string& optionName) {
Options::iterator it = option_with_name(optionName);
return it != options.end() && it->currentValue == "true";
}
}
//// ////
//// Functions //// Functions
@@ -143,26 +210,31 @@ namespace {
/// "Threads" parameter to the number of available CPU cores. /// "Threads" parameter to the number of available CPU cores.
void init_uci_options() { void init_uci_options() {
Option *o;
o = option_with_name("Threads"); load_defaults(options);
assert(o != NULL);
// Limit the default value of "Threads" to 7 even if we have 8 CPU cores. // 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 // 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 // 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. // why before I have a 8-core computer to experiment with myself.
sprintf(o->defaultValue, "%d", Min(cpu_count(), 7)); Options::iterator it = option_with_name("Threads");
sprintf(o->currentValue, "%d", Min(cpu_count(), 7));
assert(it != options.end());
it->defaultValue = stringify(Min(cpu_count(), 7));
it->currentValue = stringify(Min(cpu_count(), 7));
// Increase the minimum split depth when the number of CPUs is big. // Increase the minimum split depth when the number of CPUs is big.
// It would probably be better to let this depend on the number of threads // It would probably be better to let this depend on the number of threads
// instead. // instead.
o = option_with_name("Minimum Split Depth"); if(cpu_count() > 4)
assert(o != NULL); {
if(cpu_count() > 4) { it = option_with_name("Minimum Split Depth");
sprintf(o->defaultValue, "%d", 6);
sprintf(o->defaultValue, "%d", 6); assert(it != options.end());
it->defaultValue = "6";
it->currentValue = "6";
} }
} }
@@ -171,30 +243,39 @@ void init_uci_options() {
/// in the format defined by the UCI protocol. /// in the format defined by the UCI protocol.
void print_uci_options() { void print_uci_options() {
static const char optionTypeName[][16] = { static const char optionTypeName[][16] = {
"spin", "combo", "check", "string", "button" "spin", "combo", "check", "string", "button"
}; };
for(Option *o = Options; o->type != OPTION_TYPE_NONE; o++) {
printf("option name %s type %s", o->name, optionTypeName[o->type]);
if(o->type != BUTTON) {
printf(" default %s", o->defaultValue);
if(o->type == SPIN)
printf(" min %d max %d", o->minValue, o->maxValue);
else if(o->type == COMBO)
for(int i = 0; strlen(o->comboValues[i]) > 0; i++)
printf(" var %s", o->comboValues[i]);
}
printf("\n");
}
}
for (Options::iterator it = options.begin(); it != options.end(); ++it)
{
std::cout << "option name " << it->name
<< " type " << optionTypeName[it->type];
if (it->type != BUTTON)
{
std::cout << " default " << it->defaultValue;
if (it->type == SPIN)
std::cout << " min " << it->minValue
<< " max " << it->maxValue;
else if (it->type == COMBO)
for(ComboValues::iterator itc = it->comboValues.begin();
itc != it->comboValues.end(); ++itc)
std::cout << " var " << *itc;
}
std::cout << std::endl;
}
}
/// get_option_value_bool() returns the current value of a UCI parameter of /// get_option_value_bool() returns the current value of a UCI parameter of
/// type "check". /// type "check".
bool get_option_value_bool(const std::string& optionName) { bool get_option_value_bool(const std::string& optionName) {
Option *o = option_with_name(optionName.c_str());
return o != NULL && strcmp(o->currentValue, "true") == 0; return get_option_value<bool>(optionName);
} }
@@ -204,8 +285,8 @@ bool get_option_value_bool(const std::string &optionName) {
/// values are integers. /// values are integers.
int get_option_value_int(const std::string& optionName) { int get_option_value_int(const std::string& optionName) {
Option *o = option_with_name(optionName.c_str());
return atoi(o->currentValue); return get_option_value<int>(optionName);
} }
@@ -213,8 +294,8 @@ int get_option_value_int(const std::string &optionName) {
/// a string. It is used with parameters of type "combo" and "string". /// a string. It is used with parameters of type "combo" and "string".
const std::string get_option_value_string(const std::string& optionName) { const std::string get_option_value_string(const std::string& optionName) {
Option *o = option_with_name(optionName.c_str());
return o->currentValue; return get_option_value<std::string>(optionName);
} }
@@ -222,11 +303,13 @@ const std::string get_option_value_string(const std::string &optionName) {
/// been selected since the last time the function was called. /// been selected since the last time the function was called.
bool button_was_pressed(const std::string& buttonName) { bool button_was_pressed(const std::string& buttonName) {
if(get_option_value_bool(buttonName)) {
if (get_option_value<bool>(buttonName))
{
set_option_value(buttonName, "false"); set_option_value(buttonName, "false");
return true; return true;
} }
else
return false; return false;
} }
@@ -237,10 +320,11 @@ bool button_was_pressed(const std::string &buttonName) {
void set_option_value(const std::string& optionName, void set_option_value(const std::string& optionName,
const std::string& newValue) { const std::string& newValue) {
Option *o = option_with_name(optionName.c_str());
if(o != NULL) Options::iterator it = option_with_name(optionName);
strcpy(o->currentValue, newValue.c_str());
if (it != options.end())
it->currentValue = newValue;
else else
std::cout << "No such option: " << optionName << std::endl; std::cout << "No such option: " << optionName << std::endl;
} }
@@ -250,21 +334,34 @@ void set_option_value(const std::string &optionName,
/// "button" has been selected: /// "button" has been selected:
void push_button(const std::string& buttonName) { void push_button(const std::string& buttonName) {
set_option_value(buttonName, "true"); set_option_value(buttonName, "true");
} }
namespace { namespace {
// Define constructors of Option class.
Option::Option(const char* nm, const char* def, OptionType t)
: name(nm), defaultValue(def), currentValue(def), type(t), minValue(0), maxValue(0) {}
Option::Option(const char* nm, bool def, OptionType t)
: name(nm), defaultValue(stringify(def)), currentValue(stringify(def)), type(t), minValue(0), maxValue(0) {}
Option::Option(const char* nm, int def, int minv, int maxv)
: name(nm), defaultValue(stringify(def)), currentValue(stringify(def)), type(SPIN), minValue(minv), maxValue(maxv) {}
// option_with_name() tries to find a UCI option with a given // option_with_name() tries to find a UCI option with a given
// name. It returns a pointer to the UCI option or the null pointer, // name. It returns an iterator to the UCI option or to options.end(),
// depending on whether an option with the given name exists. // depending on whether an option with the given name exists.
Option *option_with_name(const char *optionName) { Options::iterator option_with_name(const std::string& optionName) {
for(Option *o = Options; o->type != OPTION_TYPE_NONE; o++)
if(strcmp(o->name, optionName) == 0)
return o;
return NULL;
}
for (Options::iterator it = options.begin(); it != options.end(); ++it)
if (it->name == optionName)
return it;
return options.end();
}
} }
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
+7 -6
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
@@ -59,7 +60,7 @@ Value value_from_tt(Value v, int ply) {
} }
/// value_to_centipawns() converts a value from Glaurung's somewhat unusual /// value_to_centipawns() converts a value from Stockfish's somewhat unusual
/// scale of pawn = 256 to the more conventional pawn = 100. /// scale of pawn = 256 to the more conventional pawn = 100.
int value_to_centipawns(Value v) { int value_to_centipawns(Value v) {
@@ -67,7 +68,7 @@ int value_to_centipawns(Value v) {
} }
/// value_from_centipawns() converts a centipawn value to Glaurung's internal /// value_from_centipawns() converts a centipawn value to Stockfish's internal
/// evaluation scale. It's used when reading the values of UCI options /// evaluation scale. It's used when reading the values of UCI options
/// containing material values (e.g. futility pruning margins). /// containing material values (e.g. futility pruning margins).
+5 -4
View File
@@ -1,13 +1,14 @@
/* /*
Glaurung, a UCI chess playing engine. Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba
Glaurung is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Glaurung is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.