From 9f28d8a854d05c6c6edcd6f8911b352477f82c91 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Wed, 2 Sep 2009 11:57:38 +0200 Subject: [PATCH] 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 --- src/endgame.cpp | 20 +++++++------- src/evaluate.cpp | 34 +++++++++++------------ src/material.cpp | 10 +++---- src/movegen.cpp | 28 +++++++++---------- src/pawns.cpp | 6 ++-- src/piece.h | 3 +- src/position.cpp | 72 ++++++++++++++++++++++++------------------------ src/position.h | 33 +++++++++++++--------- 8 files changed, 106 insertions(+), 100 deletions(-) diff --git a/src/endgame.cpp b/src/endgame.cpp index 69d0df51..882c07cb 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -329,7 +329,7 @@ Value EvaluationFunction::apply(const Position& pos) { assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame); assert(pos.piece_count(weakerSide, KNIGHT) == 1); assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); - assert(pos.pieces() == EmptyBoardBB); + assert(pos.pieces(PAWN) == EmptyBoardBB); Value result = BishopValueEndgame; Square wksq = pos.king_square(strongerSide); @@ -376,7 +376,7 @@ ScaleFactor ScalingFunction::apply(const Position& pos) { // No assertions about the material of weakerSide, because we want draws to // be detected even when the weaker side has some pawns. - Bitboard pawns = pos.pieces(strongerSide); + Bitboard pawns = pos.pieces(PAWN, strongerSide); File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0)); // All pawns are on a single rook file ? @@ -432,12 +432,12 @@ ScaleFactor ScalingFunction::apply(const Position& pos) { Square kingSq = pos.king_square(weakerSide); if ( relative_rank(weakerSide, kingSq) <= RANK_2 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4 - && (pos.pieces(weakerSide) & relative_rank_bb(weakerSide, RANK_3)) - && (pos.pieces(weakerSide) & relative_rank_bb(weakerSide, RANK_2)) - && (pos.piece_attacks(kingSq) & pos.pieces(weakerSide))) + && (pos.pieces(ROOK, weakerSide) & relative_rank_bb(weakerSide, RANK_3)) + && (pos.pieces(PAWN, weakerSide) & relative_rank_bb(weakerSide, RANK_2)) + && (pos.piece_attacks(kingSq) & pos.pieces(PAWN, weakerSide))) { Square rsq = pos.piece_list(weakerSide, ROOK, 0); - if (pos.pawn_attacks(strongerSide, rsq) & pos.pieces(weakerSide)) + if (pos.pawn_attacks(strongerSide, rsq) & pos.pieces(PAWN, weakerSide)) return ScaleFactor(0); } return SCALE_FACTOR_NONE; @@ -616,7 +616,7 @@ ScaleFactor ScalingFunction::apply(const Position &pos) { assert(pos.non_pawn_material(weakerSide) == Value(0)); assert(pos.piece_count(weakerSide, PAWN) == 0); - Bitboard pawns = pos.pieces(strongerSide); + Bitboard pawns = pos.pieces(PAWN, strongerSide); // Are all pawns on the 'a' file? if ((pawns & ~FileABB) == EmptyBoardBB) @@ -694,7 +694,7 @@ ScaleFactor ScalingFunction::apply(const Position &pos) { else { Bitboard ray = ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S); - if (ray & pos.pieces(weakerSide)) + if (ray & pos.pieces(KING, weakerSide)) return ScaleFactor(0); if( (pos.piece_attacks(weakerBishopSq) & ray) && square_distance(weakerBishopSq, pawnSq) >= 3) @@ -761,13 +761,13 @@ ScaleFactor ScalingFunction::apply(const Position& pos) { if ( ksq == blockSq1 && square_color(ksq) != square_color(wbsq) && ( bbsq == blockSq2 - || (pos.piece_attacks(blockSq2) & pos.pieces(weakerSide)) + || (pos.piece_attacks(blockSq2) & pos.pieces(BISHOP, weakerSide)) || rank_distance(r1, r2) >= 2)) return ScaleFactor(0); else if ( ksq == blockSq2 && square_color(ksq) != square_color(wbsq) && ( bbsq == blockSq1 - || (pos.piece_attacks(blockSq1) & pos.pieces(weakerSide)))) + || (pos.piece_attacks(blockSq1) & pos.pieces(BISHOP, weakerSide)))) return ScaleFactor(0); else return SCALE_FACTOR_NONE; diff --git a/src/evaluate.cpp b/src/evaluate.cpp index a1015edf..7fbe9af5 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -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); // Initialize pawn attack bitboards for both sides - ei.attackedBy[WHITE][PAWN] = ((pos.pieces(WHITE) << 9) & ~FileABB) | ((pos.pieces(WHITE) << 7) & ~FileHBB); - ei.attackedBy[BLACK][PAWN] = ((pos.pieces(BLACK) >> 7) & ~FileABB) | ((pos.pieces(BLACK) >> 9) & ~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); Bitboard b1 = ei.attackedBy[WHITE][PAWN] & ei.attackedBy[BLACK][KING]; Bitboard b2 = ei.attackedBy[BLACK][PAWN] & ei.attackedBy[WHITE][KING]; if (b1) @@ -590,10 +590,10 @@ namespace { // Increase bonus if supported by pawn, especially if the opponent has // no minor piece which can exchange the outpost piece - if (bonus && (p.pawn_attacks(them, s) & p.pieces(us))) + if (bonus && (p.pawn_attacks(them, s) & p.pieces(PAWN, us))) { - if ( p.pieces(them) == EmptyBoardBB - && (SquaresByColorBB[square_color(s)] & p.pieces(them)) == EmptyBoardBB) + if ( p.pieces(KNIGHT, them) == EmptyBoardBB + && (SquaresByColorBB[square_color(s)] & p.pieces(BISHOP, them)) == EmptyBoardBB) bonus += bonus + bonus / 2; else bonus += bonus / 2; @@ -622,9 +622,9 @@ namespace { if (Piece == KNIGHT || Piece == QUEEN) b = pos.piece_attacks(s); else if (Piece == BISHOP) - b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(us)); + b = bishop_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(QUEEN, us)); else if (Piece == ROOK) - b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(us)); + b = rook_attacks_bb(s, pos.occupied_squares() & ~pos.pieces(ROOK, QUEEN, us)); else assert(false); @@ -787,8 +787,8 @@ namespace { from = p.piece_list(them, QUEEN, i); if ( bit_is_set(p.piece_attacks(from), to) && !bit_is_set(p.pinned_pieces(them), from) - && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(us)) - && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(us))) + && !(rook_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(ROOK, QUEEN, us)) + && !(bishop_attacks_bb(to, occ & ClearMaskBB[from]) & p.pieces(BISHOP, QUEEN, us))) ei.mateThreat[them] = make_move(from, to); } @@ -841,7 +841,7 @@ namespace { // adding pawns later). if (DiscoveredCheckBonus) { - b = p.discovered_check_candidates(them) & ~p.pieces(); + b = p.discovered_check_candidates(them) & ~p.pieces(PAWN); if (b) attackUnits += DiscoveredCheckBonus * count_1s_max_15(b) * (sente? 2 : 1); } @@ -889,7 +889,7 @@ namespace { Color them = opposite_color(us); Square ourKingSq = pos.king_square(us); Square theirKingSq = pos.king_square(them); - Bitboard b = ei.pi->passed_pawns() & pos.pieces(us), b2, b3, b4; + Bitboard b = ei.pi->passed_pawns() & pos.pieces(PAWN, us), b2, b3, b4; while (b) { @@ -923,14 +923,14 @@ namespace { // If there is an enemy rook or queen attacking the pawn from behind, // 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) - && (squares_behind(us, s) & pos.pieces(them))) + && (squares_behind(us, s) & pos.pieces(ROOK, QUEEN, them))) b3 = b2; // Squares attacked or occupied by enemy pieces b3 |= (b2 & pos.pieces_of_color(them)); // There are no enemy pawns in the pawn's path - assert((b2 & pos.pieces(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? if (b3 == EmptyBoardBB) @@ -951,7 +951,7 @@ namespace { } // If the pawn is supported by a friendly pawn, increase bonus - b2 = pos.pieces(us) & neighboring_files_bb(s); + b2 = pos.pieces(PAWN, us) & neighboring_files_bb(s); if (b2 & rank_bb(s)) ebonus += Value(r * 20); else if (pos.pawn_attacks(them, s) & b2) @@ -993,7 +993,7 @@ namespace { if ( pos.non_pawn_material(them) <= KnightValueMidgame && pos.piece_count(them, KNIGHT) <= 1) ebonus += ebonus / 4; - else if (pos.pieces(them)) + else if (pos.pieces(ROOK, QUEEN, them)) ebonus -= ebonus / 4; } @@ -1115,13 +1115,13 @@ namespace { // pawn, or if it is undefended and attacked by an enemy piece. Bitboard safeSquares = SpaceMask[us] - & ~pos.pieces(us) + & ~pos.pieces(PAWN, us) & ~ei.attacked_by(them, PAWN) & ~(~ei.attacked_by(us) & ei.attacked_by(them)); // Find all squares which are at most three squares behind some friendly // pawn. - Bitboard behindFriendlyPawns = pos.pieces(us); + Bitboard behindFriendlyPawns = pos.pieces(PAWN, us); if (us == WHITE) { behindFriendlyPawns |= (behindFriendlyPawns >> 8); diff --git a/src/material.cpp b/src/material.cpp index 9a20292b..a3d9f7c8 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -171,14 +171,14 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { mi->evaluationFunction = &EvaluateKKX; return mi; } - else if ( pos.pieces() == EmptyBoardBB - && pos.pieces() == EmptyBoardBB - && pos.pieces() == EmptyBoardBB) + else if ( pos.pieces(PAWN) == EmptyBoardBB + && pos.pieces(ROOK) == EmptyBoardBB + && pos.pieces(QUEEN) == EmptyBoardBB) { // Minor piece endgame with at least one minor piece per side and // no pawns. Note that the case KmmK is already handled by KXK. - assert((pos.pieces(WHITE) | pos.pieces(WHITE))); - assert((pos.pieces(BLACK) | pos.pieces(BLACK))); + assert((pos.pieces(KNIGHT, WHITE) | pos.pieces(BISHOP, WHITE))); + assert((pos.pieces(KNIGHT, BLACK) | pos.pieces(BISHOP, BLACK))); if ( pos.piece_count(WHITE, BISHOP) + pos.piece_count(WHITE, KNIGHT) <= 2 && pos.piece_count(BLACK, BISHOP) + pos.piece_count(BLACK, KNIGHT) <= 2) diff --git a/src/movegen.cpp b/src/movegen.cpp index 41f5b077..0b052e5b 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -238,14 +238,14 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin // and to be able to use square_is_attacked(). Bitboard checkers = pos.checkers(); Bitboard checkersAttacks = EmptyBoardBB; - Bitboard b = checkers & pos.pieces(); + Bitboard b = checkers & pos.pieces(BISHOP, QUEEN); while (b) { from = pop_1st_bit(&b); checkersAttacks |= bishop_attacks_bb(from, b_noKing); } - b = checkers & pos.pieces(); + b = checkers & pos.pieces(ROOK, QUEEN); while (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 // Pawn captures - b1 = pos.pawn_attacks(them, checksq) & pos.pieces(us) & ~pinned; + b1 = pos.pawn_attacks(them, checksq) & pos.pieces(PAWN, us) & ~pinned; while (b1) { from = pop_1st_bit(&b1); @@ -290,9 +290,9 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin } // Pieces captures - b1 = ( (pos.piece_attacks(checksq) & pos.pieces(us)) - | (pos.piece_attacks(checksq) & pos.pieces(us)) - | (pos.piece_attacks(checksq) & pos.pieces(us)) ) & ~pinned; + b1 = ( (pos.piece_attacks(checksq) & pos.pieces(KNIGHT, us)) + | (pos.piece_attacks(checksq) & pos.pieces(BISHOP, QUEEN, us)) + | (pos.piece_attacks(checksq) & pos.pieces(ROOK, QUEEN, us)) ) & ~pinned; 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 // a slider. - if (checkers & (pos.pieces() | pos.pieces() | pos.pieces())) + if (checkers & (pos.pieces(BISHOP) | pos.pieces(ROOK) | pos.pieces(QUEEN))) { 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 // a double pawn push. If, furthermore, the checking piece is a pawn, // an en passant check evasion may be possible. - if (pos.ep_square() != SQ_NONE && (checkers & pos.pieces(them))) + if (pos.ep_square() != SQ_NONE && (checkers & pos.pieces(PAWN, them))) { to = pos.ep_square(); - b1 = pos.pawn_attacks(them, to) & pos.pieces(us); + b1 = pos.pawn_attacks(them, to) & pos.pieces(PAWN, us); // The checking pawn cannot be a discovered (bishop) check candidate // 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); Square to; - Bitboard pawns = pos.pieces(Us); + Bitboard pawns = pos.pieces(PAWN, Us); Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us)); bool possiblePromotion = (pawns & TRank7BB); @@ -725,7 +725,7 @@ namespace { Bitboard b1, b2; Square to; - Bitboard pawns = pos.pieces(Us); + Bitboard pawns = pos.pieces(PAWN, Us); Bitboard emptySquares = pos.empty_squares(); if (pawns & TRank7BB) // There is some promotion candidate ? @@ -786,7 +786,7 @@ namespace { Square to; Bitboard b1, b2, b3; - Bitboard pawns = pos.pieces(Us); + Bitboard pawns = pos.pieces(PAWN, Us); if (dc & pawns) { @@ -832,7 +832,7 @@ namespace { MoveStack* generate_piece_checks(const Position& pos, MoveStack* mlist, Color us, Bitboard dc, Square ksq) { - Bitboard target = pos.pieces(us); + Bitboard target = pos.pieces(Piece, us); // Discovered checks Bitboard b = target & dc; @@ -881,7 +881,7 @@ namespace { Square to; // Find non-pinned pawns and push them one square - Bitboard b1 = move_pawns(pos.pieces(Us) & ~pinned); + Bitboard b1 = move_pawns(pos.pieces(PAWN, Us) & ~pinned); // We don't have to AND with empty squares here, // because the blocking squares will always be empty. diff --git a/src/pawns.cpp b/src/pawns.cpp index 1d8b082e..71b1738c 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -197,8 +197,8 @@ PawnInfo* PawnInfoTable::get_pawn_info(const Position& pos) { for (Color us = WHITE; us <= BLACK; us++) { Color them = opposite_color(us); - Bitboard ourPawns = pos.pieces(us); - Bitboard theirPawns = pos.pieces(them); + Bitboard ourPawns = pos.pieces(PAWN, us); + Bitboard theirPawns = pos.pieces(PAWN, them); Bitboard pawns = ourPawns; // 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) { unsigned shelter = 0; - Bitboard pawns = pos.pieces(c) & this_and_neighboring_files_bb(ksq); + Bitboard pawns = pos.pieces(PAWN, c) & this_and_neighboring_files_bb(ksq); unsigned r = ksq & (7 << 3); for (int i = 1, k = (c ? -8 : 8); i < 4; i++) { diff --git a/src/piece.h b/src/piece.h index 5b93ea7d..48e26c39 100644 --- a/src/piece.h +++ b/src/piece.h @@ -35,8 +35,7 @@ enum PieceType { NO_PIECE_TYPE = 0, - PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5, KING = 6, - BISHOP_AND_QUEEN = 8, ROOK_AND_QUEEN = 9 + PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5, KING = 6 }; enum Piece { diff --git a/src/position.cpp b/src/position.cpp index aa07cd51..770d47f5 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -340,8 +340,8 @@ Bitboard Position::hidden_checkers(Color c) const { // Pinners are sliders, not checkers, that give check when // candidate pinned is removed. - pinners = (pieces(FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq]) - | (pieces(FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]); + pinners = (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq]) + | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]); if (FindPinned && pinners) pinners &= ~st->checkersBB; @@ -384,12 +384,12 @@ Bitboard Position::discovered_check_candidates(Color c) const { Bitboard Position::attacks_to(Square s) const { - return (pawn_attacks(BLACK, s) & pieces(WHITE)) - | (pawn_attacks(WHITE, s) & pieces(BLACK)) - | (piece_attacks(s) & pieces()) - | (piece_attacks(s) & pieces()) - | (piece_attacks(s) & pieces()) - | (piece_attacks(s) & pieces()); + return (pawn_attacks(BLACK, s) & pieces(PAWN, WHITE)) + | (pawn_attacks(WHITE, s) & pieces(PAWN, BLACK)) + | (piece_attacks(s) & pieces(KNIGHT)) + | (piece_attacks(s) & pieces(ROOK, QUEEN)) + | (piece_attacks(s) & pieces(BISHOP, QUEEN)) + | (piece_attacks(s) & pieces(KING)); } /// 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); clear_bit(&occ, f); set_bit(&occ, t); - Bitboard xray = ( (rook_attacks_bb(s, occ) & pieces()) - |(bishop_attacks_bb(s, occ) & pieces())) & pieces_of_color(us); + Bitboard xray = ( (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN)) + |(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 // 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); set_bit(&b, to); - return !(rook_attacks_bb(ksq, b) & pieces(them)) - && !(bishop_attacks_bb(ksq, b) & pieces(them)); + return !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them)) + && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them)); } // 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, capsq); set_bit(&b, to); - return (rook_attacks_bb(ksq, b) & pieces(us)) - ||(bishop_attacks_bb(ksq, b) & pieces(us)); + return (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us)) + ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us)); } 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 != ROOK) - (*pCheckersBB) |= (piece_attacks(ksq) & pieces(side_to_move())); + (*pCheckersBB) |= (piece_attacks(ksq) & pieces(ROOK, QUEEN, side_to_move())); if (Piece != BISHOP) - (*pCheckersBB) |= (piece_attacks(ksq) & pieces(side_to_move())); + (*pCheckersBB) |= (piece_attacks(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 if (abs(int(to) - int(from)) == 16) { - if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pieces(them)) + if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pieces(PAWN, them)) { st->epSquare = Square((int(from) + int(to)) / 2); key ^= zobEp[st->epSquare]; @@ -1366,12 +1366,12 @@ int Position::see(Square from, Square to) const { while (true) { clear_bit(&occ, from); - attackers = (rook_attacks_bb(to, occ) & pieces()) - | (bishop_attacks_bb(to, occ) & pieces()) - | (piece_attacks(to) & pieces()) - | (piece_attacks(to) & pieces()) - | (pawn_attacks(WHITE, to) & pieces(BLACK)) - | (pawn_attacks(BLACK, to) & pieces(WHITE)); + attackers = (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN)) + | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN)) + | (piece_attacks(to) & pieces(KNIGHT)) + | (piece_attacks(to) & pieces(KING)) + | (pawn_attacks(WHITE, to) & pieces(PAWN, BLACK)) + | (pawn_attacks(BLACK, to) & pieces(PAWN, WHITE)); if (from != SQ_NONE) break; @@ -1384,10 +1384,10 @@ int Position::see(Square from, Square to) const { // and use it to initialize from square. stmAttackers = attackers & pieces_of_color(us); PieceType pt; - for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++) + for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++) assert(pt < KING); - from = first_1(stmAttackers & pieces_of_type(pt)); + from = first_1(stmAttackers & pieces(pt)); 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 // 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. - for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++) + for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++) assert(pt < KING); // Remove the attacker we just found from the 'attackers' bitboard, // and scan for new X-ray attacks behind the attacker. - b = stmAttackers & pieces_of_type(pt); + b = stmAttackers & pieces(pt); occ ^= (b & (~b + 1)); - attackers |= (rook_attacks_bb(to, occ) & pieces()) - | (bishop_attacks_bb(to, occ) & pieces()); + attackers |= (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN)) + | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN)); attackers &= occ; @@ -1589,7 +1589,7 @@ Key Position::compute_pawn_key() const { for (Color c = WHITE; c <= BLACK; c++) { - b = pieces(c); + b = pieces(PAWN, c); while(b) { s = pop_1st_bit(&b); @@ -1634,7 +1634,7 @@ Value Position::compute_value() const { for (Color c = WHITE; c <= BLACK; c++) for (PieceType pt = PAWN; pt <= KING; pt++) { - b = pieces_of_color(c) & pieces_of_type(pt); + b = pieces(pt, c); while(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++) { - Bitboard b = pieces_of_color(c) & pieces_of_type(pt); + Bitboard b = pieces(pt, c); while (b) { 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 { // Draw by material? - if ( !pieces() + if ( !pieces(PAWN) && (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMidgame)) return true; @@ -1956,7 +1956,7 @@ bool Position::is_ok(int* failedStep) const { // Separate piece type bitboards must have empty intersections for (PieceType p1 = PAWN; p1 <= KING; p1++) 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; } @@ -2012,7 +2012,7 @@ bool Position::is_ok(int* failedStep) const { if (debugPieceCounts) for (Color c = WHITE; c <= BLACK; c++) 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; if (failedStep) (*failedStep)++; @@ -2022,7 +2022,7 @@ bool Position::is_ok(int* failedStep) const { for(PieceType pt = PAWN; pt <= KING; pt++) 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; if (index[piece_list(c, pt, i)] != i) diff --git a/src/position.h b/src/position.h index b3d0cd0a..0006fbc7 100644 --- a/src/position.h +++ b/src/position.h @@ -162,15 +162,10 @@ public: Bitboard empty_squares() const; Bitboard occupied_squares() const; Bitboard pieces_of_color(Color c) const; - Bitboard pieces_of_type(PieceType pt) const; - - // Pieces by constant type of both colors - template Bitboard pieces() const { return byTypeBB[Piece]; } - template<> Bitboard pieces() const { return byTypeBB[BISHOP] | byTypeBB[QUEEN]; } - template<> Bitboard pieces() const { return byTypeBB[ROOK] | byTypeBB[QUEEN]; } - - // Pieces by constant type of a given color - template Bitboard pieces(Color c) const { return byColorBB[c] & pieces(); } + Bitboard pieces(PieceType pt) const; + Bitboard pieces(PieceType pt, Color c) const; + Bitboard pieces(PieceType pt1, PieceType pt2) const; + Bitboard pieces(PieceType pt1, PieceType pt2, Color c) const; // Number of pieces of each color and type int piece_count(Color c, PieceType pt) const; @@ -399,10 +394,22 @@ inline Bitboard Position::pieces_of_color(Color c) const { return byColorBB[c]; } -inline Bitboard Position::pieces_of_type(PieceType pt) const { +inline Bitboard Position::pieces(PieceType pt) const { 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 { 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 { - return !(pieces(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) { @@ -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 { - return !(pieces(c) & outpost_mask(opposite_color(c), s)); + return !(pieces(PAWN, c) & outpost_mask(opposite_color(c), s)); } 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 { - return pieces(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 { -- 2.39.2