1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 01:03:09 +00:00

Second take at unifying bitboard representation access

This patch is built on Tord idea to use functions instead of
templates to access position's bitboards. This has the added advantage
that we don't need fallback functions for cases where the piece
type or the color is a variable and not a constant.

Also added Joona suggestion to workaround request for two types
of pieces like bishop_and_queens() and rook_and_queens().

No functionality or performance change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2009-09-02 11:57:38 +02:00
parent 76bed11f7b
commit 9f28d8a854
8 changed files with 106 additions and 100 deletions

View file

@ -329,7 +329,7 @@ Value EvaluationFunction<KBBKN>::apply(const Position& pos) {
assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame); assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame);
assert(pos.piece_count(weakerSide, KNIGHT) == 1); assert(pos.piece_count(weakerSide, KNIGHT) == 1);
assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
assert(pos.pieces<PAWN>() == EmptyBoardBB); assert(pos.pieces(PAWN) == EmptyBoardBB);
Value result = BishopValueEndgame; Value result = BishopValueEndgame;
Square wksq = pos.king_square(strongerSide); Square wksq = pos.king_square(strongerSide);
@ -376,7 +376,7 @@ ScaleFactor ScalingFunction<KBPsK>::apply(const Position& pos) {
// 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.pieces<PAWN>(strongerSide); Bitboard pawns = pos.pieces(PAWN, strongerSide);
File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0)); File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0));
// All pawns are on a single rook file ? // All pawns are on a single rook file ?
@ -432,12 +432,12 @@ ScaleFactor ScalingFunction<KQKRPs>::apply(const Position& pos) {
Square kingSq = pos.king_square(weakerSide); Square kingSq = pos.king_square(weakerSide);
if ( relative_rank(weakerSide, kingSq) <= RANK_2 if ( relative_rank(weakerSide, kingSq) <= RANK_2
&& relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4
&& (pos.pieces<ROOK>(weakerSide) & relative_rank_bb(weakerSide, RANK_3)) && (pos.pieces(ROOK, weakerSide) & relative_rank_bb(weakerSide, RANK_3))
&& (pos.pieces<PAWN>(weakerSide) & relative_rank_bb(weakerSide, RANK_2)) && (pos.pieces(PAWN, weakerSide) & relative_rank_bb(weakerSide, RANK_2))
&& (pos.piece_attacks<KING>(kingSq) & pos.pieces<PAWN>(weakerSide))) && (pos.piece_attacks<KING>(kingSq) & pos.pieces(PAWN, weakerSide)))
{ {
Square rsq = pos.piece_list(weakerSide, ROOK, 0); Square rsq = pos.piece_list(weakerSide, ROOK, 0);
if (pos.pawn_attacks(strongerSide, rsq) & pos.pieces<PAWN>(weakerSide)) if (pos.pawn_attacks(strongerSide, rsq) & pos.pieces(PAWN, weakerSide))
return ScaleFactor(0); return ScaleFactor(0);
} }
return SCALE_FACTOR_NONE; return SCALE_FACTOR_NONE;
@ -616,7 +616,7 @@ ScaleFactor ScalingFunction<KPsK>::apply(const Position &pos) {
assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.non_pawn_material(weakerSide) == Value(0));
assert(pos.piece_count(weakerSide, PAWN) == 0); assert(pos.piece_count(weakerSide, PAWN) == 0);
Bitboard pawns = pos.pieces<PAWN>(strongerSide); Bitboard pawns = pos.pieces(PAWN, strongerSide);
// Are all pawns on the 'a' file? // Are all pawns on the 'a' file?
if ((pawns & ~FileABB) == EmptyBoardBB) if ((pawns & ~FileABB) == EmptyBoardBB)
@ -694,7 +694,7 @@ ScaleFactor ScalingFunction<KBPKB>::apply(const Position &pos) {
else else
{ {
Bitboard ray = ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S); Bitboard ray = ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S);
if (ray & pos.pieces<KING>(weakerSide)) if (ray & pos.pieces(KING, weakerSide))
return ScaleFactor(0); return ScaleFactor(0);
if( (pos.piece_attacks<BISHOP>(weakerBishopSq) & ray) if( (pos.piece_attacks<BISHOP>(weakerBishopSq) & ray)
&& square_distance(weakerBishopSq, pawnSq) >= 3) && square_distance(weakerBishopSq, pawnSq) >= 3)
@ -761,13 +761,13 @@ ScaleFactor ScalingFunction<KBPPKB>::apply(const Position& pos) {
if ( ksq == blockSq1 if ( ksq == blockSq1
&& square_color(ksq) != square_color(wbsq) && square_color(ksq) != square_color(wbsq)
&& ( bbsq == blockSq2 && ( bbsq == blockSq2
|| (pos.piece_attacks<BISHOP>(blockSq2) & pos.pieces<BISHOP>(weakerSide)) || (pos.piece_attacks<BISHOP>(blockSq2) & pos.pieces(BISHOP, weakerSide))
|| rank_distance(r1, r2) >= 2)) || rank_distance(r1, r2) >= 2))
return ScaleFactor(0); return ScaleFactor(0);
else if ( ksq == blockSq2 else if ( ksq == blockSq2
&& square_color(ksq) != square_color(wbsq) && square_color(ksq) != square_color(wbsq)
&& ( bbsq == blockSq1 && ( bbsq == blockSq1
|| (pos.piece_attacks<BISHOP>(blockSq1) & pos.pieces<BISHOP>(weakerSide)))) || (pos.piece_attacks<BISHOP>(blockSq1) & pos.pieces(BISHOP, weakerSide))))
return ScaleFactor(0); return ScaleFactor(0);
else else
return SCALE_FACTOR_NONE; return SCALE_FACTOR_NONE;

View file

@ -348,8 +348,8 @@ Value do_evaluate(const Position& pos, EvalInfo& ei, int threadID) {
ei.kingZone[BLACK] = ei.attackedBy[WHITE][KING] | (ei.attackedBy[WHITE][KING] << 8); ei.kingZone[BLACK] = ei.attackedBy[WHITE][KING] | (ei.attackedBy[WHITE][KING] << 8);
// Initialize pawn attack bitboards for both sides // Initialize pawn attack bitboards for both sides
ei.attackedBy[WHITE][PAWN] = ((pos.pieces<PAWN>(WHITE) << 9) & ~FileABB) | ((pos.pieces<PAWN>(WHITE) << 7) & ~FileHBB); ei.attackedBy[WHITE][PAWN] = ((pos.pieces(PAWN, WHITE) << 9) & ~FileABB) | ((pos.pieces(PAWN, WHITE) << 7) & ~FileHBB);
ei.attackedBy[BLACK][PAWN] = ((pos.pieces<PAWN>(BLACK) >> 7) & ~FileABB) | ((pos.pieces<PAWN>(BLACK) >> 9) & ~FileHBB); ei.attackedBy[BLACK][PAWN] = ((pos.pieces(PAWN, BLACK) >> 7) & ~FileABB) | ((pos.pieces(PAWN, BLACK) >> 9) & ~FileHBB);
Bitboard b1 = ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING]; Bitboard b1 = ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING];
Bitboard b2 = ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING]; Bitboard b2 = ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING];
if (b1) if (b1)
@ -590,10 +590,10 @@ namespace {
// Increase bonus if supported by pawn, especially if the opponent has // Increase bonus if supported by pawn, especially if the opponent has
// no minor piece which can exchange the outpost piece // no minor piece which can exchange the outpost piece
if (bonus && (p.pawn_attacks(them, s) & p.pieces<PAWN>(us))) if (bonus && (p.pawn_attacks(them, s) & p.pieces(PAWN, us)))
{ {
if ( p.pieces<KNIGHT>(them) == EmptyBoardBB if ( p.pieces(KNIGHT, them) == EmptyBoardBB
&& (SquaresByColorBB[square_color(s)] & p.pieces<BISHOP>(them)) == EmptyBoardBB) && (SquaresByColorBB[square_color(s)] & p.pieces(BISHOP, them)) == EmptyBoardBB)
bonus += bonus + bonus / 2; bonus += bonus + bonus / 2;
else else
bonus += bonus / 2; bonus += bonus / 2;
@ -622,9 +622,9 @@ namespace {
if (Piece == KNIGHT || Piece == QUEEN) if (Piece == KNIGHT || Piece == QUEEN)
b = pos.piece_attacks<Piece>(s); b = pos.piece_attacks<Piece>(s);
else if (Piece == BISHOP) else if (Piece == BISHOP)
b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.pieces<QUEEN>(us)); b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(QUEEN, us));
else if (Piece == ROOK) else if (Piece == ROOK)
b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.pieces<ROOK_AND_QUEEN>(us)); b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(ROOK, QUEEN, us));
else else
assert(false); assert(false);
@ -787,8 +787,8 @@ namespace {
from = p.piece_list(them, QUEEN, i); from = p.piece_list(them, QUEEN, i);
if ( bit_is_set(p.piece_attacks<QUEEN>(from), to) if ( bit_is_set(p.piece_attacks<QUEEN>(from), to)
&& !bit_is_set(p.pinned_pieces(them), from) && !bit_is_set(p.pinned_pieces(them), from)
&& !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces<ROOK_AND_QUEEN>(us)) && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(ROOK, QUEEN, us))
&& !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces<BISHOP_AND_QUEEN>(us))) && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(BISHOP, QUEEN, us)))
ei.mateThreat[them] = make_move(from, to); ei.mateThreat[them] = make_move(from, to);
} }
@ -841,7 +841,7 @@ namespace {
// adding pawns later). // adding pawns later).
if (DiscoveredCheckBonus) if (DiscoveredCheckBonus)
{ {
b = p.discovered_check_candidates(them) & ~p.pieces<PAWN>(); b = p.discovered_check_candidates(them) & ~p.pieces(PAWN);
if (b) if (b)
attackUnits += DiscoveredCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente? 2 : 1); attackUnits += DiscoveredCheckBonus * count_1s_max_15<HasPopCnt>(b) * (sente? 2 : 1);
} }
@ -889,7 +889,7 @@ namespace {
Color them = opposite_color(us); Color them = opposite_color(us);
Square ourKingSq = pos.king_square(us); Square ourKingSq = pos.king_square(us);
Square theirKingSq = pos.king_square(them); Square theirKingSq = pos.king_square(them);
Bitboard b = ei.pi->passed_pawns() & pos.pieces<PAWN>(us), b2, b3, b4; Bitboard b = ei.pi->passed_pawns() & pos.pieces(PAWN, us), b2, b3, b4;
while (b) while (b)
{ {
@ -923,14 +923,14 @@ namespace {
// If there is an enemy rook or queen attacking the pawn from behind, // If there is an enemy rook or queen attacking the pawn from behind,
// add all X-ray attacks by the rook or queen. // add all X-ray attacks by the rook or queen.
if ( bit_is_set(ei.attacked_by(them,ROOK) | ei.attacked_by(them,QUEEN),s) if ( bit_is_set(ei.attacked_by(them,ROOK) | ei.attacked_by(them,QUEEN),s)
&& (squares_behind(us, s) & pos.pieces<ROOK_AND_QUEEN>(them))) && (squares_behind(us, s) & pos.pieces(ROOK, QUEEN, them)))
b3 = b2; b3 = b2;
// Squares attacked or occupied by enemy pieces // Squares attacked or occupied by enemy pieces
b3 |= (b2 & pos.pieces_of_color(them)); b3 |= (b2 & pos.pieces_of_color(them));
// There are no enemy pawns in the pawn's path // There are no enemy pawns in the pawn's path
assert((b2 & pos.pieces<PAWN>(them)) == EmptyBoardBB); assert((b2 & pos.pieces(PAWN, them)) == EmptyBoardBB);
// Are any of the squares in the pawn's path attacked or occupied by the enemy? // Are any of the squares in the pawn's path attacked or occupied by the enemy?
if (b3 == EmptyBoardBB) if (b3 == EmptyBoardBB)
@ -951,7 +951,7 @@ namespace {
} }
// If the pawn is supported by a friendly pawn, increase bonus // If the pawn is supported by a friendly pawn, increase bonus
b2 = pos.pieces<PAWN>(us) & neighboring_files_bb(s); b2 = pos.pieces(PAWN, us) & neighboring_files_bb(s);
if (b2 & rank_bb(s)) if (b2 & rank_bb(s))
ebonus += Value(r * 20); ebonus += Value(r * 20);
else if (pos.pawn_attacks(them, s) & b2) else if (pos.pawn_attacks(them, s) & b2)
@ -993,7 +993,7 @@ namespace {
if ( pos.non_pawn_material(them) <= KnightValueMidgame if ( pos.non_pawn_material(them) <= KnightValueMidgame
&& pos.piece_count(them, KNIGHT) <= 1) && pos.piece_count(them, KNIGHT) <= 1)
ebonus += ebonus / 4; ebonus += ebonus / 4;
else if (pos.pieces<ROOK_AND_QUEEN>(them)) else if (pos.pieces(ROOK, QUEEN, them))
ebonus -= ebonus / 4; ebonus -= ebonus / 4;
} }
@ -1115,13 +1115,13 @@ namespace {
// pawn, or if it is undefended and attacked by an enemy piece. // pawn, or if it is undefended and attacked by an enemy piece.
Bitboard safeSquares = SpaceMask[us] Bitboard safeSquares = SpaceMask[us]
& ~pos.pieces<PAWN>(us) & ~pos.pieces(PAWN, us)
& ~ei.attacked_by(them, PAWN) & ~ei.attacked_by(them, PAWN)
& ~(~ei.attacked_by(us) & ei.attacked_by(them)); & ~(~ei.attacked_by(us) & ei.attacked_by(them));
// Find all squares which are at most three squares behind some friendly // Find all squares which are at most three squares behind some friendly
// pawn. // pawn.
Bitboard behindFriendlyPawns = pos.pieces<PAWN>(us); Bitboard behindFriendlyPawns = pos.pieces(PAWN, us);
if (us == WHITE) if (us == WHITE)
{ {
behindFriendlyPawns |= (behindFriendlyPawns >> 8); behindFriendlyPawns |= (behindFriendlyPawns >> 8);

View file

@ -171,14 +171,14 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) {
mi->evaluationFunction = &EvaluateKKX; mi->evaluationFunction = &EvaluateKKX;
return mi; return mi;
} }
else if ( pos.pieces<PAWN>() == EmptyBoardBB else if ( pos.pieces(PAWN) == EmptyBoardBB
&& pos.pieces<ROOK>() == EmptyBoardBB && pos.pieces(ROOK) == EmptyBoardBB
&& pos.pieces<QUEEN>() == EmptyBoardBB) && pos.pieces(QUEEN) == EmptyBoardBB)
{ {
// Minor piece endgame with at least one minor piece per side and // Minor piece endgame with at least one minor piece per side and
// no pawns. Note that the case KmmK is already handled by KXK. // no pawns. Note that the case KmmK is already handled by KXK.
assert((pos.pieces<KNIGHT>(WHITE) | pos.pieces<BISHOP>(WHITE))); assert((pos.pieces(KNIGHT, WHITE) | pos.pieces(BISHOP, WHITE)));
assert((pos.pieces<KNIGHT>(BLACK) | pos.pieces<BISHOP>(BLACK))); assert((pos.pieces(KNIGHT, BLACK) | pos.pieces(BISHOP, BLACK)));
if ( pos.piece_count(WHITE, BISHOP) + pos.piece_count(WHITE, KNIGHT) <= 2 if ( pos.piece_count(WHITE, BISHOP) + pos.piece_count(WHITE, KNIGHT) <= 2
&& pos.piece_count(BLACK, BISHOP) + pos.piece_count(BLACK, KNIGHT) <= 2) && pos.piece_count(BLACK, BISHOP) + pos.piece_count(BLACK, KNIGHT) <= 2)

View file

@ -238,14 +238,14 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin
// and to be able to use square_is_attacked(). // and to be able to use square_is_attacked().
Bitboard checkers = pos.checkers(); Bitboard checkers = pos.checkers();
Bitboard checkersAttacks = EmptyBoardBB; Bitboard checkersAttacks = EmptyBoardBB;
Bitboard b = checkers & pos.pieces<BISHOP_AND_QUEEN>(); Bitboard b = checkers & pos.pieces(BISHOP, QUEEN);
while (b) while (b)
{ {
from = pop_1st_bit(&b); from = pop_1st_bit(&b);
checkersAttacks |= bishop_attacks_bb(from, b_noKing); checkersAttacks |= bishop_attacks_bb(from, b_noKing);
} }
b = checkers & pos.pieces<ROOK_AND_QUEEN>(); b = checkers & pos.pieces(ROOK, QUEEN);
while (b) while (b)
{ {
from = pop_1st_bit(&b); from = pop_1st_bit(&b);
@ -275,7 +275,7 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin
// Generate captures of the checking piece // Generate captures of the checking piece
// Pawn captures // Pawn captures
b1 = pos.pawn_attacks(them, checksq) & pos.pieces<PAWN>(us) & ~pinned; b1 = pos.pawn_attacks(them, checksq) & pos.pieces(PAWN, us) & ~pinned;
while (b1) while (b1)
{ {
from = pop_1st_bit(&b1); from = pop_1st_bit(&b1);
@ -290,9 +290,9 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin
} }
// Pieces captures // Pieces captures
b1 = ( (pos.piece_attacks<KNIGHT>(checksq) & pos.pieces<KNIGHT>(us)) b1 = ( (pos.piece_attacks<KNIGHT>(checksq) & pos.pieces(KNIGHT, us))
| (pos.piece_attacks<BISHOP>(checksq) & pos.pieces<BISHOP_AND_QUEEN>(us)) | (pos.piece_attacks<BISHOP>(checksq) & pos.pieces(BISHOP, QUEEN, us))
| (pos.piece_attacks<ROOK>(checksq) & pos.pieces<ROOK_AND_QUEEN>(us)) ) & ~pinned; | (pos.piece_attacks<ROOK>(checksq) & pos.pieces(ROOK, QUEEN, us)) ) & ~pinned;
while (b1) while (b1)
{ {
@ -302,7 +302,7 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin
// Blocking check evasions are possible only if the checking piece is // Blocking check evasions are possible only if the checking piece is
// a slider. // a slider.
if (checkers & (pos.pieces<BISHOP>() | pos.pieces<ROOK>() | pos.pieces<QUEEN>())) if (checkers & (pos.pieces(BISHOP) | pos.pieces(ROOK) | pos.pieces(QUEEN)))
{ {
Bitboard blockSquares = squares_between(checksq, ksq); Bitboard blockSquares = squares_between(checksq, ksq);
@ -323,10 +323,10 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin
// check. If pos.ep_square() is set, the last move made must have been // check. If pos.ep_square() is set, the last move made must have been
// a double pawn push. If, furthermore, the checking piece is a pawn, // a double pawn push. If, furthermore, the checking piece is a pawn,
// an en passant check evasion may be possible. // an en passant check evasion may be possible.
if (pos.ep_square() != SQ_NONE && (checkers & pos.pieces<PAWN>(them))) if (pos.ep_square() != SQ_NONE && (checkers & pos.pieces(PAWN, them)))
{ {
to = pos.ep_square(); to = pos.ep_square();
b1 = pos.pawn_attacks(them, to) & pos.pieces<PAWN>(us); b1 = pos.pawn_attacks(them, to) & pos.pieces(PAWN, us);
// The checking pawn cannot be a discovered (bishop) check candidate // The checking pawn cannot be a discovered (bishop) check candidate
// otherwise we were in check also before last double push move. // otherwise we were in check also before last double push move.
@ -675,7 +675,7 @@ namespace {
const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S); const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S);
Square to; Square to;
Bitboard pawns = pos.pieces<PAWN>(Us); Bitboard pawns = pos.pieces(PAWN, Us);
Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us)); Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us));
bool possiblePromotion = (pawns & TRank7BB); bool possiblePromotion = (pawns & TRank7BB);
@ -725,7 +725,7 @@ namespace {
Bitboard b1, b2; Bitboard b1, b2;
Square to; Square to;
Bitboard pawns = pos.pieces<PAWN>(Us); Bitboard pawns = pos.pieces(PAWN, Us);
Bitboard emptySquares = pos.empty_squares(); Bitboard emptySquares = pos.empty_squares();
if (pawns & TRank7BB) // There is some promotion candidate ? if (pawns & TRank7BB) // There is some promotion candidate ?
@ -786,7 +786,7 @@ namespace {
Square to; Square to;
Bitboard b1, b2, b3; Bitboard b1, b2, b3;
Bitboard pawns = pos.pieces<PAWN>(Us); Bitboard pawns = pos.pieces(PAWN, Us);
if (dc & pawns) if (dc & pawns)
{ {
@ -832,7 +832,7 @@ namespace {
MoveStack* generate_piece_checks(const Position& pos, MoveStack* mlist, Color us, MoveStack* generate_piece_checks(const Position& pos, MoveStack* mlist, Color us,
Bitboard dc, Square ksq) { Bitboard dc, Square ksq) {
Bitboard target = pos.pieces<Piece>(us); Bitboard target = pos.pieces(Piece, us);
// Discovered checks // Discovered checks
Bitboard b = target & dc; Bitboard b = target & dc;
@ -881,7 +881,7 @@ namespace {
Square to; Square to;
// Find non-pinned pawns and push them one square // Find non-pinned pawns and push them one square
Bitboard b1 = move_pawns<Us, DELTA_N>(pos.pieces<PAWN>(Us) & ~pinned); Bitboard b1 = move_pawns<Us, DELTA_N>(pos.pieces(PAWN, Us) & ~pinned);
// We don't have to AND with empty squares here, // We don't have to AND with empty squares here,
// because the blocking squares will always be empty. // because the blocking squares will always be empty.

View file

@ -197,8 +197,8 @@ PawnInfo* PawnInfoTable::get_pawn_info(const Position& pos) {
for (Color us = WHITE; us <= BLACK; us++) for (Color us = WHITE; us <= BLACK; us++)
{ {
Color them = opposite_color(us); Color them = opposite_color(us);
Bitboard ourPawns = pos.pieces<PAWN>(us); Bitboard ourPawns = pos.pieces(PAWN, us);
Bitboard theirPawns = pos.pieces<PAWN>(them); Bitboard theirPawns = pos.pieces(PAWN, them);
Bitboard pawns = ourPawns; Bitboard pawns = ourPawns;
// Initialize pawn storm scores by giving bonuses for open files // Initialize pawn storm scores by giving bonuses for open files
@ -392,7 +392,7 @@ PawnInfo* PawnInfoTable::get_pawn_info(const Position& pos) {
int PawnInfo::updateShelter(const Position& pos, Color c, Square ksq) { int PawnInfo::updateShelter(const Position& pos, Color c, Square ksq) {
unsigned shelter = 0; unsigned shelter = 0;
Bitboard pawns = pos.pieces<PAWN>(c) & this_and_neighboring_files_bb(ksq); Bitboard pawns = pos.pieces(PAWN, c) & this_and_neighboring_files_bb(ksq);
unsigned r = ksq & (7 << 3); unsigned r = ksq & (7 << 3);
for (int i = 1, k = (c ? -8 : 8); i < 4; i++) for (int i = 1, k = (c ? -8 : 8); i < 4; i++)
{ {

View file

@ -35,8 +35,7 @@
enum PieceType { enum PieceType {
NO_PIECE_TYPE = 0, NO_PIECE_TYPE = 0,
PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5, KING = 6, PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5, KING = 6
BISHOP_AND_QUEEN = 8, ROOK_AND_QUEEN = 9
}; };
enum Piece { enum Piece {

View file

@ -340,8 +340,8 @@ Bitboard Position::hidden_checkers(Color c) const {
// Pinners are sliders, not checkers, that give check when // Pinners are sliders, not checkers, that give check when
// candidate pinned is removed. // candidate pinned is removed.
pinners = (pieces<ROOK_AND_QUEEN>(FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq]) pinners = (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
| (pieces<BISHOP_AND_QUEEN>(FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]); | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
if (FindPinned && pinners) if (FindPinned && pinners)
pinners &= ~st->checkersBB; pinners &= ~st->checkersBB;
@ -384,12 +384,12 @@ Bitboard Position::discovered_check_candidates(Color c) const {
Bitboard Position::attacks_to(Square s) const { Bitboard Position::attacks_to(Square s) const {
return (pawn_attacks(BLACK, s) & pieces<PAWN>(WHITE)) return (pawn_attacks(BLACK, s) & pieces(PAWN, WHITE))
| (pawn_attacks(WHITE, s) & pieces<PAWN>(BLACK)) | (pawn_attacks(WHITE, s) & pieces(PAWN, BLACK))
| (piece_attacks<KNIGHT>(s) & pieces<KNIGHT>()) | (piece_attacks<KNIGHT>(s) & pieces(KNIGHT))
| (piece_attacks<ROOK>(s) & pieces<ROOK_AND_QUEEN>()) | (piece_attacks<ROOK>(s) & pieces(ROOK, QUEEN))
| (piece_attacks<BISHOP>(s) & pieces<BISHOP_AND_QUEEN>()) | (piece_attacks<BISHOP>(s) & pieces(BISHOP, QUEEN))
| (piece_attacks<KING>(s) & pieces<KING>()); | (piece_attacks<KING>(s) & pieces(KING));
} }
/// Position::piece_attacks_square() tests whether the piece on square f /// Position::piece_attacks_square() tests whether the piece on square f
@ -435,8 +435,8 @@ bool Position::move_attacks_square(Move m, Square s) const {
Color us = color_of_piece_on(f); Color us = color_of_piece_on(f);
clear_bit(&occ, f); clear_bit(&occ, f);
set_bit(&occ, t); set_bit(&occ, t);
Bitboard xray = ( (rook_attacks_bb(s, occ) & pieces<ROOK_AND_QUEEN>()) Bitboard xray = ( (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN))
|(bishop_attacks_bb(s, occ) & pieces<BISHOP_AND_QUEEN>())) & pieces_of_color(us); |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN))) & pieces_of_color(us);
// If we have attacks we need to verify that are caused by our move // If we have attacks we need to verify that are caused by our move
// and are not already existent ones. // and are not already existent ones.
@ -503,8 +503,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
clear_bit(&b, capsq); clear_bit(&b, capsq);
set_bit(&b, to); set_bit(&b, to);
return !(rook_attacks_bb(ksq, b) & pieces<ROOK_AND_QUEEN>(them)) return !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them))
&& !(bishop_attacks_bb(ksq, b) & pieces<BISHOP_AND_QUEEN>(them)); && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them));
} }
// If the moving piece is a king, check whether the destination // If the moving piece is a king, check whether the destination
@ -586,8 +586,8 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
clear_bit(&b, from); clear_bit(&b, from);
clear_bit(&b, capsq); clear_bit(&b, capsq);
set_bit(&b, to); set_bit(&b, to);
return (rook_attacks_bb(ksq, b) & pieces<ROOK_AND_QUEEN>(us)) return (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
||(bishop_attacks_bb(ksq, b) & pieces<BISHOP_AND_QUEEN>(us)); ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
} }
return false; return false;
@ -674,10 +674,10 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
if (Piece != QUEEN && bit_is_set(dcCandidates, from)) if (Piece != QUEEN && bit_is_set(dcCandidates, from))
{ {
if (Piece != ROOK) if (Piece != ROOK)
(*pCheckersBB) |= (piece_attacks<ROOK>(ksq) & pieces<ROOK_AND_QUEEN>(side_to_move())); (*pCheckersBB) |= (piece_attacks<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
if (Piece != BISHOP) if (Piece != BISHOP)
(*pCheckersBB) |= (piece_attacks<BISHOP>(ksq) & pieces<BISHOP_AND_QUEEN>(side_to_move())); (*pCheckersBB) |= (piece_attacks<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
} }
} }
@ -806,7 +806,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
// Set en passant square, only if moved pawn can be captured // Set en passant square, only if moved pawn can be captured
if (abs(int(to) - int(from)) == 16) if (abs(int(to) - int(from)) == 16)
{ {
if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pieces<PAWN>(them)) if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pieces(PAWN, them))
{ {
st->epSquare = Square((int(from) + int(to)) / 2); st->epSquare = Square((int(from) + int(to)) / 2);
key ^= zobEp[st->epSquare]; key ^= zobEp[st->epSquare];
@ -1366,12 +1366,12 @@ int Position::see(Square from, Square to) const {
while (true) while (true)
{ {
clear_bit(&occ, from); clear_bit(&occ, from);
attackers = (rook_attacks_bb(to, occ) & pieces<ROOK_AND_QUEEN>()) attackers = (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
| (bishop_attacks_bb(to, occ) & pieces<BISHOP_AND_QUEEN>()) | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN))
| (piece_attacks<KNIGHT>(to) & pieces<KNIGHT>()) | (piece_attacks<KNIGHT>(to) & pieces(KNIGHT))
| (piece_attacks<KING>(to) & pieces<KING>()) | (piece_attacks<KING>(to) & pieces(KING))
| (pawn_attacks(WHITE, to) & pieces<PAWN>(BLACK)) | (pawn_attacks(WHITE, to) & pieces(PAWN, BLACK))
| (pawn_attacks(BLACK, to) & pieces<PAWN>(WHITE)); | (pawn_attacks(BLACK, to) & pieces(PAWN, WHITE));
if (from != SQ_NONE) if (from != SQ_NONE)
break; break;
@ -1384,10 +1384,10 @@ int Position::see(Square from, Square to) const {
// and use it to initialize from square. // and use it to initialize from square.
stmAttackers = attackers & pieces_of_color(us); stmAttackers = attackers & pieces_of_color(us);
PieceType pt; PieceType pt;
for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++) for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
assert(pt < KING); assert(pt < KING);
from = first_1(stmAttackers & pieces_of_type(pt)); from = first_1(stmAttackers & pieces(pt));
piece = piece_on(from); piece = piece_on(from);
} }
@ -1415,15 +1415,15 @@ int Position::see(Square from, Square to) const {
// Locate the least valuable attacker for the side to move. The loop // Locate the least valuable attacker for the side to move. The loop
// below looks like it is potentially infinite, but it isn't. We know // below looks like it is potentially infinite, but it isn't. We know
// that the side to move still has at least one attacker left. // that the side to move still has at least one attacker left.
for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++) for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
assert(pt < KING); assert(pt < KING);
// Remove the attacker we just found from the 'attackers' bitboard, // Remove the attacker we just found from the 'attackers' bitboard,
// and scan for new X-ray attacks behind the attacker. // and scan for new X-ray attacks behind the attacker.
b = stmAttackers & pieces_of_type(pt); b = stmAttackers & pieces(pt);
occ ^= (b & (~b + 1)); occ ^= (b & (~b + 1));
attackers |= (rook_attacks_bb(to, occ) & pieces<ROOK_AND_QUEEN>()) attackers |= (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
| (bishop_attacks_bb(to, occ) & pieces<BISHOP_AND_QUEEN>()); | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
attackers &= occ; attackers &= occ;
@ -1589,7 +1589,7 @@ Key Position::compute_pawn_key() const {
for (Color c = WHITE; c <= BLACK; c++) for (Color c = WHITE; c <= BLACK; c++)
{ {
b = pieces<PAWN>(c); b = pieces(PAWN, c);
while(b) while(b)
{ {
s = pop_1st_bit(&b); s = pop_1st_bit(&b);
@ -1634,7 +1634,7 @@ Value Position::compute_value() const {
for (Color c = WHITE; c <= BLACK; c++) for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++) for (PieceType pt = PAWN; pt <= KING; pt++)
{ {
b = pieces_of_color(c) & pieces_of_type(pt); b = pieces(pt, c);
while(b) while(b)
{ {
s = pop_1st_bit(&b); s = pop_1st_bit(&b);
@ -1660,7 +1660,7 @@ Value Position::compute_non_pawn_material(Color c) const {
for (PieceType pt = KNIGHT; pt <= QUEEN; pt++) for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
{ {
Bitboard b = pieces_of_color(c) & pieces_of_type(pt); Bitboard b = pieces(pt, c);
while (b) while (b)
{ {
assert(piece_on(first_1(b)) == piece_of_color_and_type(c, pt)); assert(piece_on(first_1(b)) == piece_of_color_and_type(c, pt));
@ -1679,7 +1679,7 @@ Value Position::compute_non_pawn_material(Color c) const {
bool Position::is_draw() const { bool Position::is_draw() const {
// Draw by material? // Draw by material?
if ( !pieces<PAWN>() if ( !pieces(PAWN)
&& (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMidgame)) && (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMidgame))
return true; return true;
@ -1956,7 +1956,7 @@ bool Position::is_ok(int* failedStep) const {
// Separate piece type bitboards must have empty intersections // Separate piece type bitboards must have empty intersections
for (PieceType p1 = PAWN; p1 <= KING; p1++) for (PieceType p1 = PAWN; p1 <= KING; p1++)
for (PieceType p2 = PAWN; p2 <= KING; p2++) for (PieceType p2 = PAWN; p2 <= KING; p2++)
if (p1 != p2 && (pieces_of_type(p1) & pieces_of_type(p2))) if (p1 != p2 && (pieces(p1) & pieces(p2)))
return false; return false;
} }
@ -2012,7 +2012,7 @@ bool Position::is_ok(int* failedStep) const {
if (debugPieceCounts) if (debugPieceCounts)
for (Color c = WHITE; c <= BLACK; c++) for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++) for (PieceType pt = PAWN; pt <= KING; pt++)
if (pieceCount[c][pt] != count_1s(pieces_of_color(c) & pieces_of_type(pt))) if (pieceCount[c][pt] != count_1s(pieces(pt, c)))
return false; return false;
if (failedStep) (*failedStep)++; if (failedStep) (*failedStep)++;
@ -2022,7 +2022,7 @@ bool Position::is_ok(int* failedStep) const {
for(PieceType pt = PAWN; pt <= KING; pt++) for(PieceType pt = PAWN; pt <= KING; pt++)
for(int i = 0; i < pieceCount[c][pt]; i++) for(int i = 0; i < pieceCount[c][pt]; i++)
{ {
if (piece_on(piece_list(c, pt, i)) != (pieces_of_color(c) & pieces_of_type(pt))) if (piece_on(piece_list(c, pt, i)) != (pieces(pt, c)))
return false; return false;
if (index[piece_list(c, pt, i)] != i) if (index[piece_list(c, pt, i)] != i)

View file

@ -162,15 +162,10 @@ public:
Bitboard empty_squares() const; Bitboard empty_squares() const;
Bitboard occupied_squares() const; Bitboard occupied_squares() const;
Bitboard pieces_of_color(Color c) const; Bitboard pieces_of_color(Color c) const;
Bitboard pieces_of_type(PieceType pt) const; Bitboard pieces(PieceType pt) const;
Bitboard pieces(PieceType pt, Color c) const;
// Pieces by constant type of both colors Bitboard pieces(PieceType pt1, PieceType pt2) const;
template<PieceType Piece> Bitboard pieces() const { return byTypeBB[Piece]; } Bitboard pieces(PieceType pt1, PieceType pt2, Color c) const;
template<> Bitboard pieces<BISHOP_AND_QUEEN>() const { return byTypeBB[BISHOP] | byTypeBB[QUEEN]; }
template<> Bitboard pieces<ROOK_AND_QUEEN>() const { return byTypeBB[ROOK] | byTypeBB[QUEEN]; }
// Pieces by constant type of a given color
template<PieceType Piece> Bitboard pieces(Color c) const { return byColorBB[c] & pieces<Piece>(); }
// 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;
@ -399,10 +394,22 @@ inline Bitboard Position::pieces_of_color(Color c) const {
return byColorBB[c]; return byColorBB[c];
} }
inline Bitboard Position::pieces_of_type(PieceType pt) const { inline Bitboard Position::pieces(PieceType pt) const {
return byTypeBB[pt]; return byTypeBB[pt];
} }
inline Bitboard Position::pieces(PieceType pt, Color c) const {
return byTypeBB[pt] & byColorBB[c];
}
inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const {
return byTypeBB[pt1] | byTypeBB[pt2];
}
inline Bitboard Position::pieces(PieceType pt1, PieceType pt2, Color c) const {
return (byTypeBB[pt1] | byTypeBB[pt2]) & byColorBB[c];
}
inline 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];
} }
@ -496,7 +503,7 @@ inline bool Position::square_is_attacked(Square s, Color c) const {
} }
inline bool Position::pawn_is_passed(Color c, Square s) const { inline bool Position::pawn_is_passed(Color c, Square s) const {
return !(pieces<PAWN>(opposite_color(c)) & passed_pawn_mask(c, s)); return !(pieces(PAWN, opposite_color(c)) & passed_pawn_mask(c, s));
} }
inline bool Position::pawn_is_passed(Bitboard theirPawns, Color c, Square s) { inline bool Position::pawn_is_passed(Bitboard theirPawns, Color c, Square s) {
@ -512,7 +519,7 @@ inline bool Position::pawn_is_doubled(Bitboard ourPawns, Color c, Square s) {
} }
inline bool Position::square_is_weak(Square s, Color c) const { inline bool Position::square_is_weak(Square s, Color c) const {
return !(pieces<PAWN>(c) & outpost_mask(opposite_color(c), s)); return !(pieces(PAWN, c) & outpost_mask(opposite_color(c), s));
} }
inline Key Position::get_key() const { inline Key Position::get_key() const {
@ -588,7 +595,7 @@ inline bool Position::opposite_colored_bishops() const {
inline bool Position::has_pawn_on_7th(Color c) const { inline bool Position::has_pawn_on_7th(Color c) const {
return pieces<PAWN>(c) & relative_rank_bb(c, RANK_7); return pieces(PAWN, c) & relative_rank_bb(c, RANK_7);
} }
inline bool Position::move_is_capture(Move m) const { inline bool Position::move_is_capture(Move m) const {