That pawn_is_passed() function does not look correct to me. A white pawn on d5 is passed if no black pawns are present on c6, c7, d6, d7, e6, e7. The code above seems to test d6 and d7 only.tcusr wrote: ↑Fri Dec 24, 2021 1:40 amCode: Select all
bool pawn_is_passed(int square, int color) { return neighbor[square][relative_north(color)] == GUARD; } bool rook_on_open_file(int square) { return neighbor[square][north] == GUARD && neighbor[square][south] == GUARD; } bool is_doubled_pawn(int square, int color) { return neighbor[square][relative_north(color)] == PAWN + color; }
some questions about mailbox
Moderator: Ras
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: some questions about mailbox
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 325
- Joined: Tue Aug 31, 2021 10:32 pm
- Full name: tcusr
Re: some questions about mailbox
yeah you're right but that's not important, i quickly wrote it just to get the idea on how to use itSven wrote: ↑Fri Dec 24, 2021 7:57 pmThat pawn_is_passed() function does not look correct to me. A white pawn on d5 is passed if no black pawns are present on c6, c7, d6, d7, e6, e7. The code above seems to test d6 and d7 only.tcusr wrote: ↑Fri Dec 24, 2021 1:40 amCode: Select all
bool pawn_is_passed(int square, int color) { return neighbor[square][relative_north(color)] == GUARD; } bool rook_on_open_file(int square) { return neighbor[square][north] == GUARD && neighbor[square][south] == GUARD; } bool is_doubled_pawn(int square, int color) { return neighbor[square][relative_north(color)] == PAWN + color; }
-
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: some questions about mailbox
It is important because a correct implementation using a neighbor table is even more expensive.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
-
- Posts: 325
- Joined: Tue Aug 31, 2021 10:32 pm
- Full name: tcusr
Re: some questions about mailbox
hgm already answered why it is not important, anyway this should be correct
Code: Select all
bool pawn_is_passed(int square, int color)
{
if (!((square + 1) & 0x88))
if (neighbor[square + 1][relative_north(color)] != GUARD)
return false;
if (!((square - 1) & 0x88))
if (neighbor[square - 1][relative_north(color)] != GUARD)
return false;
return neighbor[square][relative_north(color)] == GUARD;
}
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: some questions about mailbox
Pawns that are blocked by pieces other than pawns are still passers, and your code would not see that.
Btw, there is a kind of in-between method, which keeps track of the most-backward pawn in each file not as a rank number, but as a 1-byte bitmap. The maps for all files together than are a sort of bitboard, but never used as a 64-bit int. Calculating the max/minimum then amounts to ORing the masks that belong to the ranks of the pawns (which have the bits corresponding to squares in the file in front of the pawns set to 1). Each pawn can the OR the bytes for neighboring rank, and test the bit corresponding to their own rank. Fruit uses this method.
Btw, there is a kind of in-between method, which keeps track of the most-backward pawn in each file not as a rank number, but as a 1-byte bitmap. The maps for all files together than are a sort of bitboard, but never used as a 64-bit int. Calculating the max/minimum then amounts to ORing the masks that belong to the ranks of the pawns (which have the bits corresponding to squares in the file in front of the pawns set to 1). Each pawn can the OR the bytes for neighboring rank, and test the bit corresponding to their own rank. Fruit uses this method.
-
- Posts: 440
- Joined: Thu Apr 26, 2012 1:51 am
- Location: Oak Park, IL, USA
- Full name: Erik Madsen
Re: some questions about mailbox
That’s true. Actually, that’s what I did in MadChess 1.x and 2.x.
I guess I like the simplicity of eval using bitboards. And less bookkeeping during move generation due to the “magic” of magic bitboard’s perfect hashing.
Erik Madsen | My C# chess engine: https://www.madchess.net
-
- Posts: 325
- Joined: Tue Aug 31, 2021 10:32 pm
- Full name: tcusr
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: some questions about mailbox
Indeed, you would need to maintain a second neighbor table which only sees pawns. (I do something like that in my Tenjiku Shogi engine Inferno, because that has to handle pieces that can jump over arbitrary many occupied squares, but not over each other, and these have their own table.) But this might not be competitive. Although you are only interested in vertical neighbors for this application. And in fact you are only interested in the neigbors of the promotion rank. Which is exactly the same as recording the backward-most pawn per file, as in the TSCP algorithm. As mentioned, this can easily be done incrementally. But when you have pawn hash that will be more expensive than calculating it from scratch in the rare case you do have a miss there.
There are so many other aspects of pawn-structure beside passers, which you need to evaluate too (backward, doubled, isolated pawns, (half-)open files, pawns per square shade, pawn-shield quality in each wing, closedness of the position) that hashing all that info is immensely beneficial. A pawn-hash is a must-have.
A refinement is that you could work castling rights into the pawn-hash key, so that you can evaluate the rights in the context of the pawn-shield quality in that direction, and include that in the tabulated score. Most of the game there will be no castling rights at all, so then it just acts like a normal pawn table. Only in the few moves before castling this will increase the number of distinct pawn structure / castling rights combinations, and thus reduce the hit rate somewhat. (But you will likely castle in book anyway, so that this never happens in practice.)
There are so many other aspects of pawn-structure beside passers, which you need to evaluate too (backward, doubled, isolated pawns, (half-)open files, pawns per square shade, pawn-shield quality in each wing, closedness of the position) that hashing all that info is immensely beneficial. A pawn-hash is a must-have.
A refinement is that you could work castling rights into the pawn-hash key, so that you can evaluate the rights in the context of the pawn-shield quality in that direction, and include that in the tabulated score. Most of the game there will be no castling rights at all, so then it just acts like a normal pawn table. Only in the few moves before castling this will increase the number of distinct pawn structure / castling rights combinations, and thus reduce the hit rate somewhat. (But you will likely castle in book anyway, so that this never happens in practice.)
-
- Posts: 529
- Joined: Sat Mar 02, 2013 11:31 pm
Re: some questions about mailbox
I doubt there's much Elo. This is Stockfish implementation. Some extra noise but pretty close to mine: https://github.com/official-stockfish/S ... .cpp#L1047hgm wrote: ↑Fri Dec 24, 2021 7:29 pmIt occurred to me that this could be done infinitely faster, as a completely free side effect of evaluating the castling rights: next to the 4 flags that indicate which castling rights exist, you add 4 flags for indicating which bishops are still trapped in a corner. The spoilers for the squares where bishops and the pawns that block those start would clear those bits when they move or get captured, just as moving king or rook clear castling rights. The flag word is than used to index a 256-entry table in which you can look up the applicable eval bonus (for castling rights) plus penalty (for the bishop trapping).JohnWoe wrote: ↑Fri Dec 24, 2021 11:58 am FRC code from Mayhem: https://github.com/SamuraiDangyo/mayhem ... .hpp#L1464
This is pretty much the fastest way to check bishops on corners.
In Stockfish 100% the same way.
Code: Select all
// Trapped bishop penalty in FRC // Bishop on a1/h1/a8/h8 blocked by own pawn int FixFRC() { // No bishop in corner -> Speedup constexpr std::uint64_t corners = Bit(0) | Bit(7) | Bit(56) | Bit(63); if (!((g_board->white[2] | g_board->black[2]) & corners)) return 0; auto s = 0; if (g_board->pieces[0] == +3 && g_board->pieces[9] == +1) s -= FRC_PENALTY; if (g_board->pieces[7] == +3 && g_board->pieces[14] == +1) s -= FRC_PENALTY; if (g_board->pieces[56] == -3 && g_board->pieces[49] == -1) s += FRC_PENALTY; if (g_board->pieces[63] == -3 && g_board->pieces[54] == -1) s += FRC_PENALTY; return s; }
Your idea would be faster. IIRC. To clear trapped flags when B2 pawns moves and bishop exist on A1. etc But this is so rare it doesn't matter. But w/o this fix bishops are trapped forever.
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: some questions about mailbox
Of course there is no measurable Elo in micro-optimalizations like this. But the reasoning "this only takes <small number> percent of the execution time, so it makes no sense to optimize it" is flawed: if you have 100 routines that each take only 1%, and make each of those twice as fast, your program is still twice faster. I also brought it up to falsify the idea "this is how Stockfish does it, so it is the best possible solution".
Btw, the more I think about it, the more I like the idea of working both castling rights and trapped bishops in the pawn hash key. The trapping condition can be accounted together with the castling rights, through the usual spoiler mechanism. The rights byte can then be used as index in a table of Zobrist keys, rather than indexing scores directly. The selected key can then be XORed with the pawn key before accessing the pawn hash table. That way the castling rights can be evaluated in the context of the pawn structure in the corresponding wing.
Btw, the more I think about it, the more I like the idea of working both castling rights and trapped bishops in the pawn hash key. The trapping condition can be accounted together with the castling rights, through the usual spoiler mechanism. The rights byte can then be used as index in a table of Zobrist keys, rather than indexing scores directly. The selected key can then be XORed with the pawn key before accessing the pawn hash table. That way the castling rights can be evaluated in the context of the pawn structure in the corresponding wing.