Skip to content

Commit

Permalink
Introduce bad outpost penalty
Browse files Browse the repository at this point in the history
In some French games, Stockfish likes to bring the Knight to a bad outpost spot. This is evident in TCEC S18 Superfinal Game 63, where there is a Knight outpost on the queenside but is actually useless. Stockfish is effectively playing a piece down while holding ground against Leela's break on the kingside.

This patch turns the +56 mg bonus for a Knight outpost into a -7 mg penalty if it satisfies the following conditions:

* The outpost square is not on the CenterFiles (i.e. not on files C,D,E and F)
* The knight is not attacking non pawn enemies.
* The side where the outpost is located contains only few enemies, with a particular conditional_more_than_two() implementation

Thank you to apospa...@gmail.com for bringing this to our attention and for providing insights.
See https://groups.google.com/forum/?fromgroups=#!topic/fishcooking/dEXNzSIBgZU
Reference game: https://tcec-chess.com/#div=sf&game=63&season=18

Passed STC:
LLR: 2.93 (-2.94,2.94) {-0.50,1.50}
Total: 6960 W: 1454 L: 1247 D: 4259
Ptnml(0-2): 115, 739, 1610, 856, 160
https://tests.stockfishchess.org/tests/view/5f08221059f6f0353289477e

Passed LTC:
LLR: 2.98 (-2.94,2.94) {0.25,1.75}
Total: 21440 W: 2767 L: 2543 D: 16130
Ptnml(0-2): 122, 1904, 6462, 2092, 140
https://tests.stockfishchess.org/tests/view/5f0838ed59f6f035328947a2

various related tests show strong test results, but so far no generalizations or simplifications of conditional_more_than_two() are found. See PR for details.

closes #2803

Bench: 4366686
  • Loading branch information
SFisGOD authored and vondele committed Jul 11, 2020
1 parent 5e91c5d commit 1f3bd96
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/bitboard.h
Expand Up @@ -130,6 +130,13 @@ constexpr bool more_than_one(Bitboard b) {
return b & (b - 1);
}

/// Counts the occupation of the bitboard depending on the occupation of SQ_A1
/// as in `b & (1ULL << SQ_A1) ? more_than_two(b) : more_than_one(b)`

constexpr bool conditional_more_than_two(Bitboard b) {
return b & (b - 1) & (b - 2);
}

constexpr bool opposite_colors(Square s1, Square s2) {
return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
}
Expand Down
9 changes: 8 additions & 1 deletion src/evaluate.cpp
Expand Up @@ -134,6 +134,7 @@ namespace {
};

// Assorted bonuses and penalties
constexpr Score BadOutpost = S( -7, 36);
constexpr Score BishopOnKingRing = S( 24, 0);
constexpr Score BishopPawns = S( 3, 7);
constexpr Score BishopXRayPawns = S( 4, 5);
Expand Down Expand Up @@ -310,7 +311,13 @@ namespace {
{
// Bonus if piece is on an outpost square or can reach one
bb = OutpostRanks & attackedBy[Us][PAWN] & ~pe->pawn_attacks_span(Them);
if (bb & s)
if ( Pt == KNIGHT
&& bb & s & ~CenterFiles
&& !(b & pos.pieces(Them) & ~pos.pieces(PAWN))
&& !conditional_more_than_two(
pos.pieces(Them) & ~pos.pieces(PAWN) & (s & QueenSide ? QueenSide : KingSide)))
score += BadOutpost;
else if (bb & s)
score += Outpost[Pt == BISHOP];
else if (Pt == KNIGHT && bb & b & ~pos.pieces(Us))
score += ReachableOutpost;
Expand Down

1 comment on commit 1f3bd96

@hxim
Copy link

@hxim hxim commented on 1f3bd96 Jul 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of conditional_more_than_two being not symetric now when you flip position you will not get opposite of original eval for positions like this:
2r1nrk1/p2q1ppp/bp1p4/n1pPp3/P1P1P3/2PBB1N1/4QPPP/R4RK1 w - - =
b4r1r/3kq1p1/p1p1p1p1/NpPpPP2/1P1P2P1/4Q2p/1K5P/4R2R w - - =
R7/2k5/2p2p2/4p3/1pp1P1b1/n7/6P1/2R2K2 b - - =
1r4k1/4qpp1/r1b4p/pp1pPB2/n1pP3P/2P2N2/R1P3P1/R3Q1K1 b - - =

Please sign in to comment.