mjlef wrote:I use a 16 bit value for each side, which has fields for the number of each piece type (other than king, of course):
QQQRRRBBBNNNPPPP
This handles up to 15 pawns, 7 bishops, 7 knights, 7 rooks and 7 queens. I know it is possible to have lots of promotions and end up with 10 rooks or something, but I just ignore that. When it comes time to apply the material table you can just use a test like this:
if (((pieces[white]& MagicMask)==0) && (pieces[black]& MagicMask)==0))
{
//add in the material bonus
}
You just set the bits in MagicMask to handle the cases where the material array would not handle them. Say more than one queen:
MagicMask = 0xc0000;
You can set other bits if you cannot hanlde say 4 rooks and 4 bishops and 4 knights, for example.
These bit fields have lots of uses in things like detecting specific endgames:
if (pieces[white]==RookPawn) .... handle rook and pawn ending...
just define RookPawn to be 0x401
Old NOW had a very small material bonus array, and only handled up tp 1 queen, 2 rooks, 2 bishops, 2 knights and 3 pawns. This was to keep it to 1024 elements (2^10) because it had to run in 640 k DOS. You can still pack a lot of endgame knowledge even in a small array like this. And if you do not want to use the Rybka/Strelka multiplication index, the array index can be quickly calculated from AND and shifts of these 16 bit materail words.
Mark
The Thinker code has exactly what you just described. I actually got the idea from Amy. But in Amy, its just 12 bits, instead of 32. Each bit simply tells you whether such a piece is present on the board.
In the 32-bit value, I call 'profile', the counts of the pieces are encoded just as you have described.
I use this in two ways:
1. To quickly detect obvious draws and wins. I just have a short table of known draw and win profiles. If the current board profile is there, no further eval is needed.
As a result, the endgame recognizer code is very short.
I don't have those complex code that compares the counts of minors vs majors vs pawns.
2. To hash material eval (PST, end-game values that may not be draw, etc). The material hash table is small, so I do an integer hashing of the 32-bit profile value and end-up with index to the material hash table.
The other good thing about this is that I don't need a 10-item array for keeping the piece counts. This 4-byte integer does the job.
Code: Select all
#define MaterialProfile_Pawn (0x000f << 0)
#define MaterialProfile_Knight (0x0003 << 4)
#define MaterialProfile_Bishop (0x0003 << 7)
#define MaterialProfile_Rook (0x0003 << 10)
#define MaterialProfile_Queen (0x0003 << 13)
#define MaterialProfile_Side(color_) ( 0xffff << ((color_) << 4) )
#define MaterialProfile_White MaterialProfile_Side (White)
#define MaterialProfile_Black MaterialProfile_Side (Black)
#define MaterialProfile_WhitePawn ( (0x000f << 0) << (White * 16) )
#define MaterialProfile_WhiteKnight ( (0x0003 << 4) << (White * 16) )
#define MaterialProfile_WhiteBishop ( (0x0003 << 7) << (White * 16) )
#define MaterialProfile_WhiteRook ( (0x0003 << 10) << (White * 16) )
#define MaterialProfile_WhiteQueen ( (0x0003 << 13) << (White * 16) )
#define MaterialProfile_BlackPawn ( (0x000f << 0) << (Black * 16) )
#define MaterialProfile_BlackKnight ( (0x0003 << 4) << (Black * 16) )
#define MaterialProfile_BlackBishop ( (0x0003 << 7) << (Black * 16) )
#define MaterialProfile_BlackRook ( (0x0003 << 10) << (Black * 16) )
#define MaterialProfile_BlackQueen ( (0x0003 << 13) << (Black * 16) )
#define MaterialProfile_WhiteNonPawns ( MaterialProfile_WhiteMinors | MaterialProfile_WhiteMajors )
#define MaterialProfile_BlackNonPawns ( MaterialProfile_BlackMinors | MaterialProfile_BlackMajors )
#define MaterialProfile_AllNonPawns ( MaterialProfile_WhiteNonPawns | MaterialProfile_BlackNonPawns )
#define MaterialProfile_WhiteMinors ( MaterialProfile_WhiteKnight | MaterialProfile_WhiteBishop )
#define MaterialProfile_BlackMinors ( MaterialProfile_BlackKnight | MaterialProfile_BlackBishop )
#define MaterialProfile_AllMinors ( MaterialProfile_WhiteMinors | MaterialProfile_BlackMinors )
#define MaterialProfile_WhiteMajors ( MaterialProfile_WhiteRook | MaterialProfile_WhiteQueen )
#define MaterialProfile_BlackMajors ( MaterialProfile_BlackRook | MaterialProfile_BlackQueen )
#define MaterialProfile_AllMajors ( MaterialProfile_WhiteMajors | MaterialProfile_BlackMajors )
#define MaterialProfile_AllPawns ( MaterialProfile_WhitePawn | MaterialProfile_BlackPawn )
#define MaterialProfile_AllKnights ( MaterialProfile_WhiteKnight | MaterialProfile_BlackKnight )
#define MaterialProfile_AllBishops ( MaterialProfile_WhiteBishop | MaterialProfile_BlackBishop )
#define MaterialProfile_AllRooks ( MaterialProfile_WhiteRook | MaterialProfile_BlackRook )
#define MaterialProfile_AllQueens ( MaterialProfile_WhiteQueen | MaterialProfile_BlackQueen )
#define MaterialProfile_AllMajorsAndPawns ( MaterialProfile_AllMajors | MaterialProfile_AllPawns )
#define MaterialProfile_Count_WhitePawn(prof_) ( ( (prof_) >> ( 0 + (White * 16) ) ) & 0x000f )
#define MaterialProfile_Count_WhiteKnight(prof_) ( ( (prof_) >> ( 4 + (White * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_WhiteBishop(prof_) ( ( (prof_) >> ( 7 + (White * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_WhiteRook(prof_) ( ( (prof_) >> ( 10 + (White * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_WhiteQueen(prof_) ( ( (prof_) >> ( 13 + (White * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_BlackPawn(prof_) ( ( (prof_) >> ( 0 + (Black * 16) ) ) & 0x000f )
#define MaterialProfile_Count_BlackKnight(prof_) ( ( (prof_) >> ( 4 + (Black * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_BlackBishop(prof_) ( ( (prof_) >> ( 7 + (Black * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_BlackRook(prof_) ( ( (prof_) >> ( 10 + (Black * 16) ) ) & 0x0003 )
#define MaterialProfile_Count_BlackQueen(prof_) ( ( (prof_) >> ( 13 + (Black * 16) ) ) & 0x0003 )
#define MaterialProfile_Count(pbrd_,pc_type_,color_) \
( (pc_type_) == Pawn ? ((pbrd_)->material_profile >> ((color_) << 4)) & 0x0f : \
((pbrd_)->material_profile >> (1 + (((pc_type_) - 1) * 3) + ((color_) << 4))) & 0x07 )
#define MaterialProfileInc_Piece(pc_type_,color_) ((1 << (((pc_type_) * 3) - 2)) << ((color_) * 16)) // only for Knight, Bishop, Rook or Queen
#define MaterialProfileInc_Pawn (1 << 0)
#define MaterialProfileInc_Knight (1 << 4)
#define MaterialProfileInc_Bishop (1 << 7)
#define MaterialProfileInc_Rook (1 << 10)
#define MaterialProfileInc_Queen (1 << 13)
#define MaterialProfileInc_WhitePawn ( (1 << 0) << (White * 16) )
#define MaterialProfileInc_WhiteKnight ( (1 << 4) << (White * 16) )
#define MaterialProfileInc_WhiteBishop ( (1 << 7) << (White * 16) )
#define MaterialProfileInc_WhiteRook ( (1 << 10) << (White * 16) )
#define MaterialProfileInc_WhiteQueen ( (1 << 13) << (White * 16) )
#define MaterialProfileInc_BlackPawn ( (1 << 0) << (Black * 16) )
#define MaterialProfileInc_BlackKnight ( (1 << 4) << (Black * 16) )
#define MaterialProfileInc_BlackBishop ( (1 << 7) << (Black * 16) )
#define MaterialProfileInc_BlackRook ( (1 << 10) << (Black * 16) )
#define MaterialProfileInc_BlackQueen ( (1 << 13) << (Black * 16) )
#define MaterialProfile_KQKP ( MaterialProfileInc_WhiteQueen | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KPKQ ( MaterialProfileInc_WhitePawn | MaterialProfileInc_BlackQueen )
#define MaterialProfile_KRKP ( MaterialProfileInc_WhiteRook | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KPKR ( MaterialProfileInc_WhitePawn | MaterialProfileInc_BlackRook )
#define MaterialProfile_KBKP ( MaterialProfileInc_WhiteBishop | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KPKB ( MaterialProfileInc_WhitePawn | MaterialProfileInc_BlackBishop )
#define MaterialProfile_KNKP ( MaterialProfileInc_WhiteKnight | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KPKN ( MaterialProfileInc_WhitePawn | MaterialProfileInc_BlackKnight )
#define MaterialProfile_KNPK ( MaterialProfileInc_WhiteKnight | MaterialProfileInc_WhitePawn )
#define MaterialProfile_KKNP ( MaterialProfileInc_BlackKnight | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KRPKR ( MaterialProfileInc_WhiteRook | MaterialProfileInc_WhitePawn | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KRKRP ( MaterialProfileInc_WhiteRook | MaterialProfileInc_BlackRook | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KBPKB ( MaterialProfileInc_WhiteBishop | MaterialProfileInc_WhitePawn | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KBKBP ( MaterialProfileInc_WhiteBishop | MaterialProfileInc_BlackBishop | MaterialProfileInc_BlackPawn )
#define MaterialProfile_NONE ( 0xffffffff )
#define MaterialProfile_KPK MaterialProfileInc_WhitePawn
#define MaterialProfile_KKP MaterialProfileInc_BlackPawn
#define MaterialProfile_KRK MaterialProfileInc_WhiteRook
#define MaterialProfile_KKR MaterialProfileInc_BlackRook
#define MaterialProfile_KNK MaterialProfileInc_WhiteKnight
#define MaterialProfile_KKN MaterialProfileInc_BlackKnight
#define MaterialProfile_KNNK (MaterialProfileInc_WhiteKnight * 2)
#define MaterialProfile_KKNN (MaterialProfileInc_BlackKnight * 2)
#define MaterialProfile_KBBKN ( (MaterialProfileInc_WhiteBishop * 2) | MaterialProfileInc_BlackKnight )
#define MaterialProfile_KNKBB ( MaterialProfileInc_WhiteKnight | (MaterialProfileInc_BlackBishop * 2) )
#define MaterialProfile_KQKQ ( MaterialProfileInc_WhiteQueen | MaterialProfileInc_BlackQueen )
#define MaterialProfile_KRKR ( MaterialProfileInc_WhiteRook | MaterialProfileInc_BlackRook )
#define MaterialProfile_KBKB ( MaterialProfileInc_WhiteBishop | MaterialProfileInc_BlackBishop )
#define MaterialProfile_KNKN ( MaterialProfileInc_WhiteKnight | MaterialProfileInc_BlackKnight )
#define MaterialProfile_KBPK ( MaterialProfileInc_WhiteBishop | MaterialProfileInc_WhitePawn )
#define MaterialProfile_KKBP ( MaterialProfileInc_BlackBishop | MaterialProfileInc_BlackPawn )
#define MaterialProfile_KK 0