From: Fabian Fichter Date: Tue, 25 Aug 2020 20:53:34 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=1431335bdd87e8379238ef2540a50fe58c7506f2;p=fairystockfish.git Merge official-stockfish/master --- 1431335bdd87e8379238ef2540a50fe58c7506f2 diff --cc src/bitboard.h index e0ac4d3,93f838f..9108d28 --- a/src/bitboard.h +++ b/src/bitboard.h @@@ -249,6 -176,12 +249,12 @@@ constexpr Bitboard pawn_attacks_bb(Bitb : shift(b) | shift(b); } + inline Bitboard pawn_attacks_bb(Color c, Square s) { + + assert(is_ok(s)); - return PawnAttacks[c][s]; ++ return PseudoAttacks[c][PAWN][s]; + } + /// pawn_double_attacks_bb() returns the squares doubly attacked by pawns of the /// given color from the squares in the given bitboard. @@@ -360,76 -269,49 +366,96 @@@ inline int edge_distance(Rank r, Rank m inline Bitboard safe_destination(Square s, int step) { Square to = Square(s + step); - return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0); + return is_ok(to) && distance(s, to) <= 3 ? square_bb(to) : Bitboard(0); +} + +template +inline Bitboard rider_attacks_bb(Square s, Bitboard occupied) { + + assert(R == RIDER_BISHOP || R == RIDER_ROOK_H || R == RIDER_ROOK_V || R == RIDER_CANNON_H || R == RIDER_CANNON_V + || R == RIDER_HORSE || R == RIDER_ELEPHANT || R == RIDER_JANGGI_ELEPHANT); + const Magic& m = R == RIDER_ROOK_H ? RookMagicsH[s] + : R == RIDER_ROOK_V ? RookMagicsV[s] + : R == RIDER_CANNON_H ? CannonMagicsH[s] + : R == RIDER_CANNON_V ? CannonMagicsV[s] + : R == RIDER_HORSE ? HorseMagics[s] + : R == RIDER_ELEPHANT ? ElephantMagics[s] + : R == RIDER_JANGGI_ELEPHANT ? JanggiElephantMagics[s] + : BishopMagics[s]; + return m.attacks[m.index(occupied)]; } - /// attacks_bb() returns a bitboard representing all the squares attacked by a - /// piece of type Pt (bishop or rook) placed on 's'. + /// attacks_bb(Square) returns the pseudo attacks of the give piece type + /// assuming an empty board. + + template + inline Bitboard attacks_bb(Square s) { + + assert((Pt != PAWN) && (is_ok(s))); + - return PseudoAttacks[Pt][s]; ++ return PseudoAttacks[WHITE][Pt][s]; + } + + /// attacks_bb(Square, Bitboard) returns the attacks by the given piece + /// assuming the board is occupied according to the passed Bitboard. + /// Sliding piece attacks do not continue passed an occupied square. template inline Bitboard attacks_bb(Square s, Bitboard occupied) { - assert(Pt == BISHOP || Pt == ROOK); - return Pt == BISHOP ? rider_attacks_bb(s, occupied) - : rider_attacks_bb(s, occupied) | rider_attacks_bb(s, occupied); + assert((Pt != PAWN) && (is_ok(s))); + + switch (Pt) + { - case BISHOP: return BishopMagics[s].attacks[BishopMagics[s].index(occupied)]; - case ROOK : return RookMagics[s].attacks[ RookMagics[s].index(occupied)]; ++ case BISHOP: return rider_attacks_bb(s, occupied); ++ case ROOK : return rider_attacks_bb(s, occupied) | rider_attacks_bb(s, occupied); + case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied); - default : return PseudoAttacks[Pt][s]; ++ default : return PseudoAttacks[WHITE][Pt][s]; + } } -inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) { + - assert((pt != PAWN) && (is_ok(s))); - - switch (pt) - { - case BISHOP: return attacks_bb(s, occupied); - case ROOK : return attacks_bb< ROOK>(s, occupied); - case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied); - default : return PseudoAttacks[pt][s]; - } +inline Bitboard attacks_bb(Color c, PieceType pt, Square s, Bitboard occupied) { + Bitboard b = LeaperAttacks[c][pt][s]; + if (AttackRiderTypes[pt] & RIDER_BISHOP) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_ROOK_H) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_ROOK_V) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_CANNON_H) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_CANNON_V) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_HORSE) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_ELEPHANT) + b |= rider_attacks_bb(s, occupied); + if (AttackRiderTypes[pt] & RIDER_JANGGI_ELEPHANT) + b |= rider_attacks_bb(s, occupied); + return b & PseudoAttacks[c][pt][s]; +} + ++ +inline Bitboard moves_bb(Color c, PieceType pt, Square s, Bitboard occupied) { + Bitboard b = LeaperMoves[c][pt][s]; + if (MoveRiderTypes[pt] & RIDER_BISHOP) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_ROOK_H) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_ROOK_V) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_CANNON_H) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_CANNON_V) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_HORSE) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_ELEPHANT) + b |= rider_attacks_bb(s, occupied); + if (MoveRiderTypes[pt] & RIDER_JANGGI_ELEPHANT) + b |= rider_attacks_bb(s, occupied); + return b & PseudoMoves[c][pt][s]; } diff --cc src/evaluate.cpp index f5fda1a,ad79db5..70f47dd --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -245,33 -232,18 +245,33 @@@ namespace // Squares occupied by those pawns, by our king or queen, by blockers to attacks on our king // or controlled by enemy pawns are excluded from the mobility area. - mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pos.blockers_for_king(Us) | pe->pawn_attacks(Them)); + if (pos.must_capture()) + mobilityArea[Us] = AllSquares; + else + mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pos.blockers_for_king(Us) | pe->pawn_attacks(Them) + | shift(pos.pieces(Them, SHOGI_PAWN, SOLDIER)) + | shift(pos.promoted_soldiers(Them)) + | shift(pos.promoted_soldiers(Them))); // Initialize attackedBy[] for king and pawns - attackedBy[Us][KING] = pos.count(Us) ? pos.attacks_from(ksq, Us) : Bitboard(0); - attackedBy[Us][KING] = attacks_bb(ksq); ++ attackedBy[Us][KING] = pos.count(Us) ? pos.attacks_from(Us, KING, ksq) : Bitboard(0); attackedBy[Us][PAWN] = pe->pawn_attacks(Us); - attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN]; - attackedBy2[Us] = dblAttackByPawn | (attackedBy[Us][KING] & attackedBy[Us][PAWN]); + attackedBy[Us][SHOGI_PAWN] = shift(pos.pieces(Us, SHOGI_PAWN)); + attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN] | attackedBy[Us][SHOGI_PAWN]; + attackedBy2[Us] = (attackedBy[Us][KING] & attackedBy[Us][PAWN]) + | (attackedBy[Us][KING] & attackedBy[Us][SHOGI_PAWN]) + | (attackedBy[Us][PAWN] & attackedBy[Us][SHOGI_PAWN]) + | dblAttackByPawn; // Init our king safety tables - Square s = make_square(Utility::clamp(file_of(ksq), FILE_B, FILE_G), - Utility::clamp(rank_of(ksq), RANK_2, RANK_7)); - kingRing[Us] = attacks_bb(s) | s; + if (!pos.count(Us)) + kingRing[Us] = Bitboard(0); + else + { + Square s = make_square(Utility::clamp(file_of(ksq), FILE_B, File(pos.max_file() - 1)), + Utility::clamp(rank_of(ksq), RANK_2, Rank(pos.max_rank() - 1))); - kingRing[Us] = PseudoAttacks[Us][KING][s] | s; ++ kingRing[Us] = attacks_bb(s) | s; + } kingAttackersCount[Them] = popcount(kingRing[Us] & pe->pawn_attacks(Them)); kingAttacksCount[Them] = kingAttackersWeight[Them] = 0; @@@ -304,10 -273,7 +304,10 @@@ // Find attacked squares, including x-ray attacks for bishops and rooks b = Pt == BISHOP ? attacks_bb(s, pos.pieces() ^ pos.pieces(QUEEN)) : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK)) - : attacks_bb(s, pos.pieces()); + : pos.attacks_from(Us, Pt, s); + + // Restrict mobility to actual squares of board - b &= pos.board_bb(); ++ b &= pos.board_bb(Us, Pt); if (pos.blockers_for_king(Us) & s) b &= LineBB[pos.square(Us)][s]; diff --cc src/movegen.cpp index aca70b2,81b8c92..3d3082f --- a/src/movegen.cpp +++ b/src/movegen.cpp @@@ -138,10 -82,10 +138,10 @@@ namespace b2 &= target; } - if (Type == QUIET_CHECKS) + if (Type == QUIET_CHECKS && pos.count(Them)) { - b1 &= pos.attacks_from(ksq, Them); - b2 &= pos.attacks_from(ksq, Them); + b1 &= pawn_attacks_bb(Them, ksq); + b2 &= pawn_attacks_bb(Them, ksq); // Add pawn pushes which give discovered check. This is possible only // if the pawn is not on the same file as the enemy king, because we @@@ -472,13 -303,13 +472,13 @@@ ExtMove* generate(const P Square from = pop_lsb(&dc); PieceType pt = type_of(pos.piece_on(from)); - Bitboard b = attacks_bb(pt, from, pos.pieces()) & ~pos.pieces(); + Bitboard b = pos.moves_from(us, pt, from) & ~pos.pieces(); - if (pt == KING) + if (pt == KING && pos.king_type() == KING) - b &= ~PseudoAttacks[~us][QUEEN][pos.square(~us)]; + b &= ~attacks_bb(pos.square(~us)); while (b) - *moveList++ = make_move(from, pop_lsb(&b)); + moveList = make_move_and_gating(pos, moveList, us, from, pop_lsb(&b)); } return us == WHITE ? generate_all(pos, moveList) diff --cc src/pawns.cpp index a40f393,467137b..2079912 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@@ -98,14 -98,14 +98,14 @@@ namespace // Flag the pawn opposed = theirPawns & forward_file_bb(Us, s); - blocked = theirPawns & (s + Up); + blocked = is_ok(s + Up) ? theirPawns & (s + Up) : Bitboard(0); stoppers = theirPawns & passed_pawn_span(Us, s); - lever = theirPawns & PseudoAttacks[Us][PAWN][s]; - leverPush = relative_rank(Them, s, pos.max_rank()) > RANK_1 ? theirPawns & PseudoAttacks[Us][PAWN][s + Up] : Bitboard(0); + lever = theirPawns & pawn_attacks_bb(Us, s); - leverPush = theirPawns & pawn_attacks_bb(Us, s + Up); - doubled = ourPawns & (s - Up); ++ leverPush = relative_rank(Them, s, pos.max_rank()) > RANK_1 ? theirPawns & pawn_attacks_bb(Us, s + Up) : Bitboard(0); + doubled = r > RANK_1 ? ourPawns & (s - Up) : Bitboard(0); neighbours = ourPawns & adjacent_files_bb(s); phalanx = neighbours & rank_bb(s); - support = neighbours & rank_bb(s - Up); + support = r > RANK_1 ? neighbours & rank_bb(s - Up) : Bitboard(0); // A pawn is backward when it is behind all pawns of the same color on // the adjacent files and cannot safely advance. diff --cc src/position.cpp index aebb073,d2e33b3..aee6282 --- a/src/position.cpp +++ b/src/position.cpp @@@ -176,13 -136,10 +176,13 @@@ void Position::init() std::memset(cuckoo, 0, sizeof(cuckoo)); std::memset(cuckooMove, 0, sizeof(cuckooMove)); int count = 0; - for (Piece pc : Pieces) - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) - for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2) - if ((type_of(pc) != PAWN) && (attacks_bb(type_of(pc), s1, 0) & s2)) + for (Color c : {WHITE, BLACK}) + for (PieceType pt = KNIGHT; pt <= QUEEN || pt == KING; pt != QUEEN ? ++pt : pt = KING) + { + Piece pc = make_piece(c, pt); + for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1) + for (Square s2 = Square(s1 + 1); s2 <= SQ_MAX; ++s2) - if (PseudoAttacks[WHITE][type_of(pc)][s1] & s2) ++ if ((type_of(pc) != PAWN) && (attacks_bb(c, type_of(pc), s1, 0) & s2)) { Move move = make_move(s1, s2); Key key = Zobrist::psq[pc][s1] ^ Zobrist::psq[pc][s2] ^ Zobrist::side; @@@ -1029,26 -585,20 +1029,26 @@@ bool Position::pseudo_legal(const Move { // We have already handled promotion moves, so destination // cannot be on the 8th/1st rank. - if ((Rank8BB | Rank1BB) & to) + if (mandatory_pawn_promotion() && rank_of(to) == relative_rank(us, promotion_rank(), max_rank())) return false; - if ( !(attacks_from(from, us) & pieces(~us) & to) // Not a capture + if ( !(pawn_attacks_bb(us, from) & pieces(~us) & to) // Not a capture && !((from + pawn_push(us) == to) && empty(to)) // Not a single push && !( (from + 2 * pawn_push(us) == to) // Not a double push - && (relative_rank(us, from) == RANK_2) + && (rank_of(from) == relative_rank(us, double_step_rank(), max_rank()) + || (first_rank_double_steps() && rank_of(from) == relative_rank(us, RANK_1, max_rank()))) && empty(to) - && empty(to - pawn_push(us)))) + && empty(to - pawn_push(us)) + && double_step_enabled())) return false; } - else if (!(attacks_bb(type_of(pc), from, pieces()) & to)) + else if (!((capture(m) ? attacks_from(us, type_of(pc), from) : moves_from(us, type_of(pc), from)) & to)) return false; + // Janggi cannon + if (type_of(pc) == JANGGI_CANNON && (pieces(JANGGI_CANNON) & (between_bb(from, to) | to))) + return false; + // Evasions generator already takes care to avoid some kind of illegal moves // and legal() relies on this. We therefore have to take care that the same // kind of moves are filtered out here. @@@ -1386,9 -793,8 +1386,9 @@@ void Position::do_move(Move m, StateInf if (type_of(pc) == PAWN) { // Set en-passant square if the moved pawn can be captured - if ( (int(to) ^ int(from)) == 16 + if ( std::abs(int(to) - int(from)) == 2 * NORTH + && relative_rank(us, rank_of(from), max_rank()) == double_step_rank() - && (attacks_from(to - pawn_push(us), us) & pieces(them, PAWN))) + && (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN))) { st->epSquare = to - pawn_push(us); k ^= Zobrist::enpassant[file_of(st->epSquare)]; diff --cc src/position.h index 4afd049,8f8c8f7..bfbb063 --- a/src/position.h +++ b/src/position.h @@@ -210,14 -111,8 +210,13 @@@ public // Attacks to/from a given square Bitboard attackers_to(Square s) const; + Bitboard attackers_to(Square s, Color c) const; Bitboard attackers_to(Square s, Bitboard occupied) const; - Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const; + Bitboard attackers_to(Square s, Bitboard occupied, Color c) const; + Bitboard attackers_to(Square s, Bitboard occupied, Color c, Bitboard janggiCannons) const; + Bitboard attacks_from(Color c, PieceType pt, Square s) const; - template Bitboard attacks_from(Square s, Color c) const; + Bitboard moves_from(Color c, PieceType pt, Square s) const; + Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners, Color c) const; // Properties of moves bool legal(Move m) const; @@@ -902,67 -281,6 +901,62 @@@ inline Square Position::castling_rook_s return castlingRookSquare[cr]; } - template - inline Bitboard Position::attacks_from(Square s, Color c) const { - return attacks_from(c, Pt, s); - } - +inline Bitboard Position::attacks_from(Color c, PieceType pt, Square s) const { + PieceType movePt = pt == KING ? king_type() : pt; + Bitboard b = attacks_bb(c, movePt, s, byTypeBB[ALL_PIECES]); + // Xiangqi soldier + if (pt == SOLDIER && !(promoted_soldiers(c) & s)) + b &= file_bb(file_of(s)); + // Janggi cannon restrictions + if (pt == JANGGI_CANNON) + { + b &= ~pieces(pt); + b &= attacks_bb(c, pt, s, pieces() ^ pieces(pt)); + } + // Janggi palace moves + if (diagonal_lines() & s) + { + PieceType diagType = movePt == WAZIR ? FERS : movePt == SOLDIER ? PAWN : movePt == ROOK ? BISHOP : NO_PIECE_TYPE; + if (diagType) + b |= attacks_bb(c, diagType, s, pieces()) & diagonal_lines(); + else if (movePt == JANGGI_CANNON) + // TODO: fix for longer diagonals + b |= attacks_bb(c, ALFIL, s, pieces()) + & ~attacks_bb(c, ELEPHANT, s, pieces() ^ pieces(pt)) + & ~pieces(pt) + & diagonal_lines(); + } + return b & board_bb(c, pt); +} + +inline Bitboard Position::moves_from(Color c, PieceType pt, Square s) const { + PieceType movePt = pt == KING ? king_type() : pt; + Bitboard b = moves_bb(c, movePt, s, byTypeBB[ALL_PIECES]); + // Xiangqi soldier + if (pt == SOLDIER && !(promoted_soldiers(c) & s)) + b &= file_bb(file_of(s)); + // Janggi cannon restrictions + if (pt == JANGGI_CANNON) + { + b &= ~pieces(pt); + b &= attacks_bb(c, pt, s, pieces() ^ pieces(pt)); + } + // Janggi palace moves + if (diagonal_lines() & s) + { + PieceType diagType = movePt == WAZIR ? FERS : movePt == SOLDIER ? PAWN : movePt == ROOK ? BISHOP : NO_PIECE_TYPE; + if (diagType) + b |= attacks_bb(c, diagType, s, pieces()) & diagonal_lines(); + else if (movePt == JANGGI_CANNON) + // TODO: fix for longer diagonals + b |= attacks_bb(c, ALFIL, s, pieces()) + & ~attacks_bb(c, ELEPHANT, s, pieces() ^ pieces(pt)) + & ~pieces(pt) + & diagonal_lines(); + } + return b & board_bb(c, pt); +} + inline Bitboard Position::attackers_to(Square s) const { return attackers_to(s, pieces()); }