From: Fabian Fichter Date: Sat, 8 Aug 2020 21:07:38 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=3ea748a8d1ecf500d17b8c90afc6ecf4d02f13ff;p=fairystockfish.git Merge official-stockfish/master No functional change. --- 3ea748a8d1ecf500d17b8c90afc6ecf4d02f13ff diff --cc src/bitboard.cpp index 436a48e,69bbc77..a1f8993 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@@ -250,76 -71,37 +250,69 @@@ void Bitboards::init() for (unsigned i = 0; i < (1 << 16); ++i) PopCnt16[i] = std::bitset<16>(i).count(); - for (Square s = SQ_A1; s <= SQ_H8; ++s) - SquareBB[s] = (1ULL << s); - - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) - for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) - SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); - - Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST }; - Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }; - - init_magics(RookTable, RookMagics, RookDirections); - init_magics(BishopTable, BishopMagics, BishopDirections); - - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) + for (Square s = SQ_A1; s <= SQ_MAX; ++s) + SquareBB[s] = make_bitboard(s); + + for (File f = FILE_A; f <= FILE_MAX; ++f) + for (Rank r = RANK_1; r <= RANK_MAX; ++r) + BoardSizeBB[f][r] = forward_file_bb(BLACK, make_square(f, r)) | SquareBB[make_square(f, r)] | (f > FILE_A ? BoardSizeBB[f - 1][r] : Bitboard(0)); + + for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1) + for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2) + SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); + +#ifdef PRECOMPUTED_MAGICS + init_magics(RookTableH, RookMagicsH, RookDirectionsH, RookMagicHInit); + init_magics(RookTableV, RookMagicsV, RookDirectionsV, RookMagicVInit); + init_magics(BishopTable, BishopMagics, BishopDirections, BishopMagicInit); + init_magics(CannonTableH, CannonMagicsH, RookDirectionsH, CannonMagicHInit); + init_magics(CannonTableV, CannonMagicsV, RookDirectionsV, CannonMagicVInit); + init_magics(HorseTable, HorseMagics, HorseDirections, HorseMagicInit); + init_magics(ElephantTable, ElephantMagics, ElephantDirections, ElephantMagicInit); + init_magics(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections, JanggiElephantMagicInit); +#else + init_magics(RookTableH, RookMagicsH, RookDirectionsH); + init_magics(RookTableV, RookMagicsV, RookDirectionsV); + init_magics(BishopTable, BishopMagics, BishopDirections); + init_magics(CannonTableH, CannonMagicsH, RookDirectionsH); + init_magics(CannonTableV, CannonMagicsV, RookDirectionsV); + init_magics(HorseTable, HorseMagics, HorseDirections); + init_magics(ElephantTable, ElephantMagics, ElephantDirections); + init_magics(JanggiElephantTable, JanggiElephantMagics, JanggiElephantDirections); +#endif + - // Helper returning the target bitboard of a step from a square - auto landing_square_bb = [&](Square s, int step) - { - Square to = Square(s + step); - return is_ok(to) && distance(s, to) < 4 ? square_bb(to) : Bitboard(0); - }; - + for (Color c : { WHITE, BLACK }) + for (PieceType pt = PAWN; pt <= KING; ++pt) + { + const PieceInfo* pi = pieceMap.find(pt)->second; + + for (Square s = SQ_A1; s <= SQ_MAX; ++s) + { + for (Direction d : pi->stepsCapture) + { - PseudoAttacks[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d); ++ PseudoAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d); + if (!pi->lameLeaper) - LeaperAttacks[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d); ++ LeaperAttacks[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d); + } + for (Direction d : pi->stepsQuiet) + { - PseudoMoves[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d); ++ PseudoMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d); + if (!pi->lameLeaper) - LeaperMoves[c][pt][s] |= landing_square_bb(s, c == WHITE ? d : -d); ++ LeaperMoves[c][pt][s] |= safe_destination(s, c == WHITE ? d : -d); + } + PseudoAttacks[c][pt][s] |= sliding_attack(pi->sliderCapture, s, 0, c); + PseudoAttacks[c][pt][s] |= sliding_attack(pi->hopperCapture, s, 0, c); + PseudoMoves[c][pt][s] |= sliding_attack(pi->sliderQuiet, s, 0, c); + PseudoMoves[c][pt][s] |= sliding_attack(pi->hopperQuiet, s, 0, c); + } + } + + for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1) { - PawnAttacks[WHITE][s1] = pawn_attacks_bb(square_bb(s1)); - PawnAttacks[BLACK][s1] = pawn_attacks_bb(square_bb(s1)); - - for (int step : {-9, -8, -7, -1, 1, 7, 8, 9} ) - PseudoAttacks[KING][s1] |= safe_destination(s1, step); - - for (int step : {-17, -15, -10, -6, 6, 10, 15, 17} ) - PseudoAttacks[KNIGHT][s1] |= safe_destination(s1, step); - - PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(s1, 0); - PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0); - for (PieceType pt : { BISHOP, ROOK }) - for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) - if (PseudoAttacks[pt][s1] & s2) - LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2; + for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2) + if (PseudoAttacks[WHITE][pt][s1] & s2) + LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2; } } diff --cc src/bitboard.h index 426fe22,9252c3d..e0ac4d3 --- a/src/bitboard.h +++ b/src/bitboard.h @@@ -140,24 -102,11 +140,24 @@@ struct Magic } }; -extern Magic RookMagics[SQUARE_NB]; +extern Magic RookMagicsH[SQUARE_NB]; +extern Magic RookMagicsV[SQUARE_NB]; extern Magic BishopMagics[SQUARE_NB]; +extern Magic CannonMagicsH[SQUARE_NB]; +extern Magic CannonMagicsV[SQUARE_NB]; +extern Magic HorseMagics[SQUARE_NB]; +extern Magic ElephantMagics[SQUARE_NB]; +extern Magic JanggiElephantMagics[SQUARE_NB]; + +constexpr Bitboard make_bitboard() { return 0; } + +template +constexpr Bitboard make_bitboard(Square s, Squares... squares) { + return (Bitboard(1) << s) | make_bitboard(squares...); +} inline Bitboard square_bb(Square s) { - assert(s >= SQ_A1 && s <= SQ_MAX); + assert(is_ok(s)); return SquareBB[s]; } @@@ -292,22 -209,8 +292,22 @@@ inline Bitboard between_bb(Square s1, S /// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2. inline Bitboard forward_ranks_bb(Color c, Square s) { - return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * (rank_of(s) - RANK_1) - : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * (RANK_MAX - rank_of(s)); - return c == WHITE ? ~Rank1BB << 8 * relative_rank(WHITE, s) - : ~Rank8BB >> 8 * relative_rank(BLACK, s); ++ return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * relative_rank(WHITE, s, RANK_MAX) ++ : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * relative_rank(BLACK, s, RANK_MAX); +} + +inline Bitboard forward_ranks_bb(Color c, Rank r) { + return c == WHITE ? (AllSquares ^ Rank1BB) << FILE_NB * (r - RANK_1) + : (AllSquares ^ rank_bb(RANK_MAX)) >> FILE_NB * (RANK_MAX - r); +} + + +/// promotion_zone_bb() returns a bitboard representing the squares on all the ranks +/// in front of and on the given relative rank, from the point of view of the given color. +/// For instance, promotion_zone_bb(BLACK, RANK_7) will return the 16 squares on ranks 1 and 2. + +inline Bitboard promotion_zone_bb(Color c, Rank r, Rank maxRank) { + return forward_ranks_bb(c, relative_rank(c, r, maxRank)) | rank_bb(relative_rank(c, r, maxRank)); } @@@ -352,24 -255,15 +352,31 @@@ template<> inline int distance(Sq template<> inline int distance(Square x, Square y) { return std::abs(rank_of(x) - rank_of(y)); } template<> inline int distance(Square x, Square y) { return SquareDistance[x][y]; } - inline File edge_distance(File f, File maxFile = FILE_H) { return std::min(f, File(maxFile - f)); } - inline Rank edge_distance(Rank r, Rank maxRank = RANK_8) { return std::min(r, Rank(maxRank - r)); } -inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); } -inline int edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); } ++inline int edge_distance(File f, File maxFile = FILE_H) { return std::min(f, File(maxFile - f)); } ++inline int edge_distance(Rank r, Rank maxRank = RANK_8) { return std::min(r, Rank(maxRank - r)); } + /// Return the target square bitboard if we do not step off the board, empty otherwise + + 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 diff --cc src/evaluate.cpp index 057525c,a2e5ef7..8193cfd --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -1104,9 -746,9 +1104,9 @@@ namespace { if ( pos.opposite_bishops() && pos.non_pawn_material() == 2 * BishopValueMg) - sf = 22 ; + sf = 22; else - sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * pos.count(strongSide)); + sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * (pos.count(strongSide) + pos.count(strongSide))); sf = std::max(0, sf - (pos.rule50_count() - 12) / 4); } diff --cc src/movegen.cpp index 8cd7312,a3abcde..6714a7c --- a/src/movegen.cpp +++ b/src/movegen.cpp @@@ -432,20 -284,17 +432,17 @@@ ExtMove* generate(const P Square from = pop_lsb(&dc); PieceType pt = type_of(pos.piece_on(from)); - if (pt == PAWN) - continue; // Will be generated together with direct checks - - Bitboard b = pos.attacks_from(pt, from) & ~pos.pieces(); + Bitboard b = pos.moves_from(us, pt, from) & ~pos.pieces(); - if (pt == KING) - b &= ~PseudoAttacks[QUEEN][pos.square(~us)]; + if (pt == KING && pos.king_type() == KING) + b &= ~PseudoAttacks[~us][QUEEN][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, ~pos.pieces()) - : generate_all(pos, moveList, ~pos.pieces()); + return us == WHITE ? generate_all(pos, moveList, ~pos.pieces() & pos.board_bb()) + : generate_all(pos, moveList, ~pos.pieces() & pos.board_bb()); } diff --cc src/pawns.cpp index 68175ee,0017b80..dbf375a --- a/src/pawns.cpp +++ b/src/pawns.cpp @@@ -222,14 -199,13 +222,14 @@@ Score Entry::evaluate_shelter(const Pos for (File f = File(center - 1); f <= File(center + 1); ++f) { b = ourPawns & file_bb(f); - int ourRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : 0; + int ourRank = b ? relative_rank(Us, frontmost_sq(Them, b), pos.max_rank()) : 0; b = theirPawns & file_bb(f); - int theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : 0; + int theirRank = b ? relative_rank(Us, frontmost_sq(Them, b), pos.max_rank()) : 0; - int d = std::min(edge_distance(f, pos.max_file()), FILE_D); - File d = File(edge_distance(f)); - bonus += make_score(ShelterStrength[d][ourRank], 0); ++ File d = std::min(File(edge_distance(f, pos.max_file())), FILE_D); + bonus += make_score(ShelterStrength[d][ourRank], 0) * (1 + (pos.captures_to_hand() && ourRank <= RANK_2) + + (pos.check_counting() && d == 0 && ourRank == RANK_2)); if (ourRank && (ourRank == theirRank - 1)) bonus -= BlockedStorm * int(theirRank == RANK_3); diff --cc src/psqt.cpp index f853dbf,7fa36ac..df2f2ed --- a/src/psqt.cpp +++ b/src/psqt.cpp @@@ -107,99 -104,19 +107,99 @@@ Score psq[PIECE_NB][SQUARE_NB + 1] // init() initializes piece-square tables: the white halves of the tables are // copied from Bonus[] adding the piece value, then the black halves of the // tables are initialized by flipping and changing the sign of the white scores. -void init() { +void init(const Variant* v) { - for (Piece pc = W_PAWN; pc <= W_KING; ++pc) + PieceType strongestPiece = NO_PIECE_TYPE; + for (PieceType pt : v->pieceTypes) + if (PieceValue[MG][pt] > PieceValue[MG][strongestPiece]) + strongestPiece = pt; + + Value maxPromotion = VALUE_ZERO; + for (PieceType pt : v->promotionPieceTypes) + maxPromotion = std::max(maxPromotion, PieceValue[EG][pt]); + + for (PieceType pt = PAWN; pt <= KING; ++pt) { + Piece pc = make_piece(WHITE, pt); + Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]); - for (Square s = SQ_A1; s <= SQ_H8; ++s) + // Consider promotion types in pawn score + if (pt == PAWN) + score -= make_score(0, (QueenValueEg - maxPromotion) / 100); + + // Scale slider piece values with board size + const PieceInfo* pi = pieceMap.find(pt)->second; + bool isSlider = pi->sliderQuiet.size() || pi->sliderCapture.size() || pi->hopperQuiet.size() || pi->hopperCapture.size(); + bool isPawn = !isSlider && pi->stepsQuiet.size() && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](Direction d) { return d < SOUTH / 2; }); + bool isSlowLeaper = !isSlider && !std::any_of(pi->stepsQuiet.begin(), pi->stepsQuiet.end(), [](Direction d) { return dist(d) > 1; }); + + if (isSlider) + { + constexpr int lc = 5; + constexpr int rm = 5; + constexpr int r0 = rm + RANK_8; + int r1 = rm + (v->maxRank + v->maxFile) / 2; + int leaper = pi->stepsQuiet.size() + pi->stepsCapture.size(); + int slider = pi->sliderQuiet.size() + pi->sliderCapture.size() + pi->hopperQuiet.size() + pi->hopperCapture.size(); + score = make_score(mg_value(score) * (lc * leaper + r1 * slider) / (lc * leaper + r0 * slider), + eg_value(score) * (lc * leaper + r1 * slider) / (lc * leaper + r0 * slider)); + } + + // Increase leapers' value in makpong + if (v->makpongRule) + { + if (std::any_of(pi->stepsCapture.begin(), pi->stepsCapture.end(), [](Direction d) { return dist(d) > 1; }) + && !pi->lameLeaper) + score = make_score(mg_value(score) * 4200 / (3500 + mg_value(score)), + eg_value(score) * 4700 / (3500 + mg_value(score))); + } + + // For drop variants, halve the piece values + if (v->capturesToHand) + score = make_score(mg_value(score) * 3500 / (7000 + mg_value(score)), + eg_value(score) * 3500 / (7000 + eg_value(score))); + else if (!v->checking) + score = make_score(mg_value(score) * 2000 / (3500 + mg_value(score)), + eg_value(score) * 2200 / (3500 + eg_value(score))); + else if (v->twoBoards) + score = make_score(mg_value(score) * 7000 / (7000 + mg_value(score)), + eg_value(score) * 7000 / (7000 + eg_value(score))); + else if (v->checkCounting) + score = make_score(mg_value(score) * (40000 + mg_value(score)) / 41000, + eg_value(score) * (30000 + eg_value(score)) / 31000); + else if (pt == strongestPiece) + score += make_score(std::max(QueenValueMg - PieceValue[MG][pt], VALUE_ZERO) / 20, + std::max(QueenValueEg - PieceValue[EG][pt], VALUE_ZERO) / 20); + + // For antichess variants, use negative piece values + if ( v->extinctionValue == VALUE_MATE + && v->extinctionPieceTypes.find(ALL_PIECES) != v->extinctionPieceTypes.end()) + score = -make_score(mg_value(score) / 8, eg_value(score) / 8 / (1 + !pi->sliderCapture.size())); + + for (Square s = SQ_A1; s <= SQ_MAX; ++s) { - File f = std::max(edge_distance(file_of(s), v->maxFile), FILE_A); - File f = File(edge_distance(file_of(s))); - psq[ pc][ s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)] - : Bonus[pc][rank_of(s)][f]); - psq[~pc][flip_rank(s)] = -psq[pc][s]; ++ File f = std::max(File(edge_distance(file_of(s), v->maxFile)), FILE_A); + Rank r = rank_of(s); + psq[ pc][ s] = score + ( pt == PAWN ? PBonus[std::min(r, RANK_8)][std::min(file_of(s), FILE_H)] + : pt == KING ? KingBonus[std::min(r, RANK_8)][std::min(f, FILE_D)] * (1 + v->capturesToHand) + : pt <= QUEEN ? Bonus[pc][std::min(r, RANK_8)][std::min(f, FILE_D)] + : pt == HORSE ? Bonus[KNIGHT][std::min(r, RANK_8)][std::min(f, FILE_D)] + : isSlider ? make_score(5, 5) * (2 * f + std::max(std::min(r, Rank(v->maxRank - r)), RANK_1) - v->maxFile - 1) + : isPawn ? make_score(5, 5) * (2 * f - v->maxFile) + : make_score(10, 10) * (1 + isSlowLeaper) * (f + std::max(std::min(r, Rank(v->maxRank - r)), RANK_1) - v->maxFile / 2)); + if (pt == SOLDIER && r < v->soldierPromotionRank) + psq[pc][s] -= score * (v->soldierPromotionRank - r) / (4 + f); + if (v->enclosingDrop == REVERSI) + { + if (f == FILE_A && (r == RANK_1 || r == v->maxRank)) + psq[pc][s] += make_score(1000, 1000); + } + psq[~pc][rank_of(s) <= v->maxRank ? flip_rank(s, v->maxRank) : s] = -psq[pc][s]; } + // pieces in pocket + psq[ pc][SQ_NONE] = score + make_score(45, 10); + psq[~pc][SQ_NONE] = -psq[pc][SQ_NONE]; } } diff --cc src/search.cpp index 93f8948,4abc606..74312dc --- a/src/search.cpp +++ b/src/search.cpp @@@ -463,13 -433,13 +463,13 @@@ void Thread::search() // Reset aspiration window starting size if (rootDepth >= 4) { - Value previousScore = rootMoves[pvIdx].previousScore; + Value prev = rootMoves[pvIdx].previousScore; - delta = Value(21); + delta = Value(21 * (1 + rootPos.captures_to_hand())); - alpha = std::max(previousScore - delta,-VALUE_INFINITE); - beta = std::min(previousScore + delta, VALUE_INFINITE); + alpha = std::max(prev - delta,-VALUE_INFINITE); + beta = std::min(prev + delta, VALUE_INFINITE); // Adjust contempt based on root move's previousScore (dynamic contempt) - int dct = ct + (102 - ct / 2) * previousScore / (abs(previousScore) + 157); + int dct = ct + (102 - ct / 2) * prev / (abs(prev) + 157); contempt = (us == WHITE ? make_score(dct, dct / 2) : -make_score(dct, dct / 2)); @@@ -974,7 -901,8 +975,8 @@@ namespace && depth >= 5 && abs(beta) < VALUE_TB_WIN_IN_MAX_PLY) { - Value raisedBeta = std::min(beta + (189 + 20 * !!pos.capture_the_flag_piece()) * (1 + pos.check_counting() + (pos.extinction_value() != VALUE_NONE)) - 45 * improving, VALUE_INFINITE); - Value raisedBeta = beta + 189 - 45 * improving; ++ Value raisedBeta = beta + (189 + 20 * !!pos.capture_the_flag_piece()) * (1 + pos.check_counting() + (pos.extinction_value() != VALUE_NONE)) - 45 * improving; + assert(raisedBeta < VALUE_INFINITE); MovePicker mp(pos, ttMove, raisedBeta - ss->staticEval, &captureHistory); int probCutCount = 0; @@@ -1122,7 -1046,8 +1124,8 @@@ moves_loop: // When in check, search st && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0) continue; + // See based pruning - if (!pos.see_ge(move, Value(-194) * depth)) // (~25 Elo) + if (!pos.see_ge(move, Value(-194 - 120 * pos.captures_to_hand()) * depth)) // (~25 Elo) continue; } }