From: Fabian Fichter Date: Sat, 23 Feb 2019 13:50:16 +0000 (+0100) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=8cf65ff1abc0e36b5b7562448023ff17c2a76b21;p=fairystockfish.git Merge official-stockfish/master bench: 4439882 --- 8cf65ff1abc0e36b5b7562448023ff17c2a76b21 diff --cc src/bitboard.cpp index 872bd2b,4e2778a..a3f121d --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@@ -401,252 -116,46 +401,252 @@@ void Bitboards::init() if (s1 != s2) { SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); - DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2; + DistanceRingBB[s1][SquareDistance[s1][s2]] |= s2; } - int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } }; + // Piece moves + Direction RookDirections[5] = { NORTH, EAST, SOUTH, WEST }; + Direction BishopDirections[5] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }; + +#ifdef PRECOMPUTED_MAGICS + init_magics(RookTable, RookMagics, RookDirections, RookMagicInit); + init_magics(BishopTable, BishopMagics, BishopDirections, BishopMagicInit); +#else + init_magics(RookTable, RookMagics, RookDirections); + init_magics(BishopTable, BishopMagics, BishopDirections); +#endif + + int stepsCapture[][13] = { + {}, // NO_PIECE_TYPE + { NORTH_WEST, NORTH_EAST }, // pawn + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight + {}, // bishop + {}, // rook + {}, // queen + { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met + { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil + { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok + { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon + {}, // knibis + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // biskni + { NORTH }, // shogi pawn + {}, // lance + { 2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight + { WEST, EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight + { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold + { SOUTH, WEST, EAST, NORTH }, // horse + { SOUTH, WEST, EAST, NORTH }, // clobber + { NORTH_WEST, NORTH_EAST }, // breakthrough + {}, // immobile + { SOUTH, WEST, EAST, NORTH }, // wazir + { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner + { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king + }; + int stepsQuiet[][13] = { + {}, // NO_PIECE_TYPE + { NORTH }, // pawn + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight + {}, // bishop + {}, // rook + {}, // queen + { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met + { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil + { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok + { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon + { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST, + NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knibis + {}, // biskni + { NORTH }, // shogi pawn + {}, // lance + { 2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight + { WEST, EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight + { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold + { SOUTH, WEST, EAST, NORTH }, // horse + {}, // clobber + { NORTH_WEST, NORTH, NORTH_EAST }, // breakthrough + {}, // immobile + { SOUTH, WEST, EAST, NORTH }, // wazir + { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner + { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king + }; + Direction sliderCapture[][9] = { + {}, // NO_PIECE_TYPE + {}, // pawn + {}, // knight + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop + { NORTH, EAST, SOUTH, WEST }, // rook + { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen + {}, // fers/met + {}, // alfil + {}, // silver/khon + { NORTH, EAST, SOUTH, WEST }, // aiwok + { NORTH, EAST, SOUTH, WEST }, // bers/dragon + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop + { NORTH, EAST, SOUTH, WEST }, // chancellor + { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // knibis + {}, // biskni + {}, // shogi pawn + { NORTH }, // lance + {}, // shogi knight + {}, // euroshogi knight + {}, // gold + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse + {}, // clobber + {}, // breakthrough + {}, // immobile + {}, // wazir + {}, // commoner + {} // king + }; + Direction sliderQuiet[][9] = { + {}, // NO_PIECE_TYPE + {}, // pawn + {}, // knight + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop + { NORTH, EAST, SOUTH, WEST }, // rook + { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen + {}, // fers/met + {}, // alfil + {}, // silver/khon + { NORTH, EAST, SOUTH, WEST }, // aiwok + { NORTH, EAST, SOUTH, WEST }, // bers/dragon + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop + { NORTH, EAST, SOUTH, WEST }, // chancellor + { NORTH, EAST, SOUTH, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon + {}, // knibis + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // biskni + {}, // shogi pawn + { NORTH }, // lance + {}, // shogi knight + {}, // euroshogi knight + {}, // gold + { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse + {}, // clobber + {}, // breakthrough + {}, // immobile + {}, // wazir + {}, // commoner + {} // king + }; + int sliderDistCapture[] = { + 0, // NO_PIECE_TYPE + 0, // pawn + 0, // knight + FILE_MAX, // bishop + FILE_MAX, // rook + FILE_MAX, // queen + 0, // fers/met + 0, // alfil + 0, // silver/khon + FILE_MAX, // aiwok + FILE_MAX, // bers/dragon + FILE_MAX, // archbishop + FILE_MAX, // chancellor + FILE_MAX, // amazon + FILE_MAX, // knibis + 0, // biskni + 0, // shogi pawn + FILE_MAX, // lance + 0, // shogi knight + 0, // euroshogi knight + 0, // gold + FILE_MAX, // horse + 0, // clobber + 0, // breakthrough + 0, // immobile + 0, // wazir + 0, // commoner + 0 // king + }; + int sliderDistQuiet[] = { + 0, // NO_PIECE_TYPE + 0, // pawn + 0, // knight + FILE_MAX, // bishop + FILE_MAX, // rook + FILE_MAX, // queen + 0, // fers/met + 0, // alfil + 0, // silver/khon + FILE_MAX, // aiwok + FILE_MAX, // bers/dragon + FILE_MAX, // archbishop + FILE_MAX, // chancellor + FILE_MAX, // amazon + 0, // knibis + FILE_MAX, // biskni + 0, // shogi pawn + FILE_MAX, // lance + 0, // shogi knight + 0, // euroshogi knight + 0, // gold + FILE_MAX, // horse + 0, // clobber + 0, // breakthrough + 0, // immobile + 0, // wazir + 0, // commoner + 0 // king + }; for (Color c = WHITE; c <= BLACK; ++c) - for (PieceType pt : { PAWN, KNIGHT, KING }) - for (Square s = SQ_A1; s <= SQ_H8; ++s) - for (int i = 0; steps[pt][i]; ++i) + for (PieceType pt = PAWN; pt <= KING; ++pt) + for (Square s = SQ_A1; s <= SQ_MAX; ++s) + { + for (int i = 0; stepsCapture[pt][i]; ++i) { - Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]); + Square to = s + Direction(c == WHITE ? stepsCapture[pt][i] : -stepsCapture[pt][i]); - if (is_ok(to) && distance(s, to) < 3) + if (is_ok(to) && distance(s, to) < 4) { - if (pt == PAWN) - PawnAttacks[c][s] |= to; - else - PseudoAttacks[pt][s] |= to; + PseudoAttacks[c][pt][s] |= to; + LeaperAttacks[c][pt][s] |= to; } } + for (int i = 0; stepsQuiet[pt][i]; ++i) + { + Square to = s + Direction(c == WHITE ? stepsQuiet[pt][i] : -stepsQuiet[pt][i]); - 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); + if (is_ok(to) && distance(s, to) < 4) + { + PseudoMoves[c][pt][s] |= to; + LeaperMoves[c][pt][s] |= to; + } + } + PseudoAttacks[c][pt][s] |= sliding_attack(sliderCapture[pt], s, 0, sliderDistCapture[pt], c); + PseudoMoves[c][pt][s] |= sliding_attack(sliderQuiet[pt], s, 0, sliderDistQuiet[pt], c); + } - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) + for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1) { - 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) + for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2) { - if (!(PseudoAttacks[pt][s1] & s2)) + if (!(PseudoAttacks[WHITE][pt][s1] & s2)) continue; - LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2; - BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[s1]); + LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2; + BetweenBB[s1][s2] = attacks_bb(WHITE, pt, s1, SquareBB[s2]) & attacks_bb(WHITE, pt, s2, SquareBB[s1]); } } } diff --cc src/evaluate.cpp index 1b65bed,e36c19c..95ea180 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -474,20 -408,25 +473,29 @@@ namespace Score Evaluation::king() const { constexpr Color Them = (Us == WHITE ? BLACK : WHITE); - constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB - : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); + Rank r = relative_rank(Us, std::min(Rank((pos.max_rank() - 1) / 2 + 1), pos.max_rank()), pos.max_rank()); + Bitboard Camp = AllSquares ^ forward_ranks_bb(Us, r); + + if (!pos.count(Us) || !pos.checking_permitted()) + return SCORE_ZERO; const Square ksq = pos.square(Us); - Bitboard weak, b, b1, b2, safe, unsafeChecks; + Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks; // King shelter and enemy pawns storm Score score = pe->king_safety(pos, ksq); + // Find the squares that opponent attacks in our king flank, and the squares + // which are attacked twice in that flank but not defended by our pawns. - kingFlank = KingFlank[file_of(ksq)]; ++ File f = std::max(std::min(file_of(ksq), File(pos.max_file() - 1)), FILE_B); ++ kingFlank = pos.max_file() == FILE_H ? KingFlank[file_of(ksq)] : file_bb(f) | adjacent_files_bb(f); + b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp; - b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN]; ++ b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN] & ~attackedBy[Us][SHOGI_PAWN]; + + int tropism = popcount(b1) + popcount(b2); + // Main king safety evaluation - if (kingAttackersCount[Them] > 1 - pos.count(Them)) + if ((kingAttackersCount[Them] > 1 - pos.count(Them)) || pos.captures_to_hand()) { int kingDanger = 0; unsafeChecks = 0; @@@ -554,12 -474,13 +562,13 @@@ unsafeChecks &= mobilityArea[Them]; kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] - + 69 * kingAttacksCount[Them] - + 185 * popcount(kingRing[Us] & weak) + + 69 * kingAttacksCount[Them] * (1 + 2 * !!pos.max_check_count()) + + 185 * popcount(kingRing[Us] & weak) * (1 + pos.captures_to_hand() + !!pos.max_check_count()) - + 129 * popcount(pos.blockers_for_king(Us) | unsafeChecks) + + 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks) + + 4 * tropism - - 873 * !pos.count(Them) + - 873 * !(pos.count(Them) || pos.captures_to_hand()) / (1 + !!pos.max_check_count()) - 6 * mg_value(score) / 8 - - 2; + - 30; // Transform the kingDanger units into a Score, and subtract it from the evaluation if (kingDanger > 0) @@@ -570,24 -491,12 +579,16 @@@ } } - File f = std::max(std::min(file_of(ksq), File(pos.max_file() - 1)), FILE_B); - Bitboard kf = pos.max_file() == FILE_H ? KingFlank[f] : file_bb(f) | adjacent_files_bb(f); - // Penalty when our king is on a pawnless flank - if (!(pos.pieces(PAWN) & kf)) + if (!(pos.pieces(PAWN) & kingFlank)) score -= PawnlessFlank; - // Find the squares that opponent attacks in our king flank, and the squares - // which are attacked twice in that flank but not defended by our pawns. - b1 = attackedBy[Them][ALL_PIECES] & kf & Camp; - b2 = b1 & attackedBy2[Them] & ~(attackedBy[Us][PAWN] | attackedBy[Us][SHOGI_PAWN]); - - // King tropism, to anticipate slow motion attacks on our king - score -= CloseEnemies * (popcount(b1) + popcount(b2)) * (1 + pos.captures_to_hand() + !!pos.max_check_count()); + // King tropism bonus, to anticipate slow motion attacks on our king - score -= CloseEnemies * tropism; ++ score -= CloseEnemies * tropism * (1 + pos.captures_to_hand() + !!pos.max_check_count()); + + // For drop games, king danger is independent of game phase + if (pos.captures_to_hand()) + score = make_score(mg_value(score), mg_value(score)) / (1 + !pos.shogi_doubled_pawn()); if (T) Trace::add(KING, Us, score); @@@ -651,12 -542,8 +652,8 @@@ { Square s = pop_lsb(&b); score += ThreatByMinor[type_of(pos.piece_on(s))]; - - if (type_of(pos.piece_on(s)) != PAWN) - score += ThreatByRank * (int)relative_rank(Them, s); + if (type_of(pos.piece_on(s)) != PAWN && type_of(pos.piece_on(s)) != SHOGI_PAWN) + score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank()); - - else if (pos.blockers_for_king(Them) & s) - score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank()) / 2; } b = weak & attackedBy[Us][ROOK]; @@@ -664,11 -551,8 +661,8 @@@ { Square s = pop_lsb(&b); score += ThreatByRook[type_of(pos.piece_on(s))]; - if (type_of(pos.piece_on(s)) != PAWN) - score += ThreatByRank * (int)relative_rank(Them, s); + if (type_of(pos.piece_on(s)) != PAWN && type_of(pos.piece_on(s)) != SHOGI_PAWN) + score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank()); - - else if (pos.blockers_for_king(Them) & s) - score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank()) / 2; } if (weak & attackedBy[Us][KING]) @@@ -747,10 -631,7 +741,7 @@@ assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up))); - if (forward_file_bb(Us, s) & pos.pieces(Them)) - score -= HinderPassedPawn; - - int r = relative_rank(Us, s); + int r = relative_rank(Us, s, pos.max_rank()); int w = PassedDanger[r]; Score bonus = PassedRank[r]; @@@ -860,30 -706,23 +849,30 @@@ template template Score Evaluation::space() const { - constexpr Color Them = (Us == WHITE ? BLACK : WHITE); - constexpr Bitboard SpaceMask = - Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB) - : CenterFiles & (Rank7BB | Rank6BB | Rank5BB); - - if (pos.non_pawn_material() < SpaceThreshold) + bool pawnsOnly = !(pos.pieces(Us) ^ pos.pieces(Us, PAWN)); + + if (pos.non_pawn_material() < SpaceThreshold && !pos.captures_to_hand() && !pawnsOnly) return SCORE_ZERO; + constexpr Color Them = (Us == WHITE ? BLACK : WHITE); + constexpr Bitboard SpaceMask = + Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB) + : CenterFiles & (Rank7BB | Rank6BB | Rank5BB); + // Find the available squares for our pieces inside the area defined by SpaceMask Bitboard safe = SpaceMask - & ~pos.pieces(Us, PAWN) - & ~attackedBy[Them][PAWN]; + & ~pos.pieces(Us, PAWN, SHOGI_PAWN) + & ~attackedBy[Them][PAWN] + & ~attackedBy[Them][SHOGI_PAWN]; + + if (pawnsOnly) + safe = pos.pieces(Us, PAWN) & ~attackedBy[Them][ALL_PIECES]; // Find all squares which are at most three squares behind some friendly pawn - Bitboard behind = pos.pieces(Us, PAWN); - behind |= (Us == WHITE ? behind >> 8 : behind << 8); - behind |= (Us == WHITE ? behind >> 16 : behind << 16); + Bitboard behind = pos.pieces(Us, PAWN, SHOGI_PAWN); + behind |= (Us == WHITE ? behind >> NORTH : behind << NORTH); + behind |= (Us == WHITE ? behind >> (2 * NORTH) : behind << (2 * NORTH)); + int bonus = popcount(safe) + popcount(behind & safe); int weight = pos.count(Us) - 2 * pe->open_files(); diff --cc src/pawns.cpp index 11820dc,75b94c1..65f1160 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@@ -239,12 -211,10 +238,10 @@@ Value Entry::evaluate_shelter(const Pos Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); - Value safety = (ourPawns & file_bb(ksq)) ? Value(5) : Value(-5); - - if (shift(theirPawns) & (FileABB | FileHBB) & BlockRanks & ksq) - safety += Value(374); + Value safety = (shift(theirPawns) & (FileABB | FileHBB) & BlockRanks & ksq) ? + Value(374) : Value(5); - File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); + File center = std::max(FILE_B, std::min(File(pos.max_file() - 1), file_of(ksq))); for (File f = File(center - 1); f <= File(center + 1); ++f) { b = ourPawns & file_bb(f); diff --cc src/psqt.cpp index 2c502fd,d811930..9d998d0 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@@ -44,16 -35,16 +44,16 @@@ namespace PSQT // type on a given square a (middlegame, endgame) score pair is assigned. Table // is defined for files A..D and white side: it is symmetric for black side and // second half of the files. -constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = { +constexpr Score Bonus[PIECE_TYPE_NB][RANK_NB][int(FILE_NB) / 2] = { { }, { // Pawn - { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) }, - { S(-11, 7), S( 6,-4), S( 7, 8), S( 3,-2) }, - { S(-18,-4), S( -2,-5), S( 19, 5), S(24, 4) }, - { S(-17, 3), S( -9, 3), S( 20,-8), S(35,-3) }, - { S( -6, 8), S( 5, 9), S( 3, 7), S(21,-6) }, - { S( -6, 8), S( -8,-5), S( -6, 2), S(-2, 4) }, - { S( -4, 3), S( 20,-9), S( -8, 1), S(-4,18) } + { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) }, + { S(-11,-3), S( 7, -1), S( 7, 7), S(17, 2) }, + { S(-16,-2), S( -3, 2), S( 23, 6), S(23,-1) }, + { S(-14, 7), S( -7, -4), S( 20,-8), S(24, 2) }, + { S( -5,13), S( -2, 10), S( -1,-1), S(12,-8) }, + { S(-11,16), S(-12, 6), S( -2, 1), S( 4,16) }, + { S( -2, 1), S( 20,-12), S(-10, 6), S(-2,25) } }, { // Knight { S(-161,-105), S(-96,-82), S(-80,-46), S(-73,-14) }, @@@ -94,18 -85,17 +94,18 @@@ { S(-2,-40), S( 6,-16), S( 8,-10), S(10, 3) }, { S(-2,-55), S( 7,-30), S( 7,-21), S( 6, -6) }, { S(-1,-74), S(-4,-55), S(-1,-43), S( 0,-30) } - }, - { // King + } +}; + +constexpr Score KingBonus[RANK_NB][int(FILE_NB) / 2] = { - { S(267, 0), S(320, 48), S(270, 75), S(195, 84) }, - { S(264, 43), S(304, 92), S(238,143), S(180,132) }, - { S(200, 83), S(245,138), S(176,167), S(110,165) }, - { S(177,106), S(185,169), S(148,169), S(110,179) }, - { S(149,108), S(177,163), S(115,200), S( 66,203) }, - { S(118, 95), S(159,155), S( 84,176), S( 41,174) }, - { S( 87, 50), S(128, 99), S( 63,122), S( 20,139) }, - { S( 63, 9), S( 88, 55), S( 47, 80), S( 0, 90) } + { S(272, 0), S(325, 41), S(273, 80), S(190, 93) }, + { S(277, 57), S(305, 98), S(241,138), S(183,131) }, + { S(198, 86), S(253,138), S(168,165), S(120,173) }, + { S(169,103), S(191,152), S(136,168), S(108,169) }, + { S(145, 98), S(176,166), S(112,197), S(69, 194) }, + { S(122, 87), S(159,164), S(85, 174), S(36, 189) }, + { S(87, 40), S(120, 99), S(64, 128), S(25, 141) }, + { S(64, 5), S(87, 60), S(49, 75), S(0, 75) } - } }; #undef S diff --cc src/search.cpp index 9019f37,c78a71a..31fbdc9 --- a/src/search.cpp +++ b/src/search.cpp @@@ -567,14 -587,12 +589,15 @@@ namespace if (!rootNode) { + Value variantResult; + if (pos.is_game_end(variantResult, ss->ply)) + return variantResult; + // Step 2. Check for aborted search and immediate draw if ( Threads.stop.load(std::memory_order_relaxed) - || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) - return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) : VALUE_DRAW; + return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) + : value_draw(depth, pos.this_thread()); // Step 3. Mate distance pruning. Even if we mate at the next move our score // would be at best mate_in(ss->ply+1), but if alpha is already bigger because @@@ -711,27 -730,25 +735,28 @@@ } else { - ss->staticEval = eval = - (ss-1)->currentMove != MOVE_NULL ? evaluate(pos) - : -(ss-1)->staticEval + 2 * Eval::tempo_value(pos); + if ((ss-1)->currentMove != MOVE_NULL) + { + int p = (ss-1)->statScore; + int bonus = p > 0 ? (-p - 2500) / 512 : + p < 0 ? (-p + 2500) / 512 : 0; - tte->save(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, - ss->staticEval); + pureStaticEval = evaluate(pos); + ss->staticEval = eval = pureStaticEval + bonus; + } + else - ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::Tempo; ++ ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::tempo_value(pos); + + tte->save(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, pureStaticEval); } // Step 7. Razoring (~2 Elo) - if ( !PvNode - && depth < 3 * ONE_PLY + if ( depth < 2 * ONE_PLY + && !pos.must_capture() + && !pos.capture_the_flag_piece() + && !pos.max_check_count() - && eval <= alpha - RazorMargin[depth / ONE_PLY]) - { - Value ralpha = alpha - (depth >= 2 * ONE_PLY) * RazorMargin[depth / ONE_PLY]; - Value v = qsearch(pos, ss, ralpha, ralpha+1); - if (depth < 2 * ONE_PLY || v <= ralpha) - return v; - } + && eval <= alpha - RazorMargin) + return qsearch(pos, ss, alpha, beta); improving = ss->staticEval >= (ss-2)->staticEval || (ss-2)->staticEval == VALUE_NONE; @@@ -753,22 -763,20 +778,22 @@@ // Step 9. Null move search with verification search (~40 Elo) if ( !PvNode && (ss-1)->currentMove != MOVE_NULL - && (ss-1)->statScore < 22500 + && (ss-1)->statScore < 23200 && eval >= beta - && ss->staticEval >= beta - 36 * depth / ONE_PLY + 225 + && pureStaticEval >= beta - 36 * depth / ONE_PLY + 225 && !excludedMove && pos.non_pawn_material(us) + && (pos.pieces(~us) ^ pos.pieces(~us, PAWN)) + && (pos.pieces() ^ pos.pieces(BREAKTHROUGH_PIECE) ^ pos.pieces(CLOBBER_PIECE)) && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor)) { assert(eval - beta >= 0); // Null move dynamic reduction based on depth and value - Depth R = ((823 - 150 * !pos.checking_permitted() + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY; - Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min(int(eval - beta) / 200, 3)) * ONE_PLY; ++ Depth R = ((823 - 150 * !pos.checking_permitted() + 67 * depth / ONE_PLY) / 256 + std::min(int(eval - beta) / 200, 3)) * ONE_PLY; ss->currentMove = MOVE_NULL; - ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get(); + ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0]; pos.do_null_move(st); @@@ -926,13 -933,8 +951,12 @@@ moves_loop: // When in check, search st extension = ONE_PLY; } else if ( givesCheck // Check extension (~2 Elo) - && !moveCountPruning && pos.see_ge(move)) extension = ONE_PLY; + else if ( pos.must_capture() // Capture extension (all moves are captures) + && pos.capture(move) + && MoveList(pos).size() == 1) + extension = ONE_PLY; // Calculate new depth for this move newDepth = depth - ONE_PLY + extension; @@@ -1009,18 -1004,12 +1030,12 @@@ { Depth r = reduction(improving, depth, moveCount); - if (captureOrPromotion || (pos.must_capture() && MoveList(pos).size())) // (~5 Elo) - { - // Decrease reduction by comparing opponent's stat score - if ((ss-1)->statScore < 0) - r -= ONE_PLY; - } - else - { - // Decrease reduction if opponent's move count is high (~5 Elo) - if ((ss-1)->moveCount > 15) - r -= ONE_PLY; + // Decrease reduction if opponent's move count is high (~10 Elo) + if ((ss-1)->moveCount > 15) + r -= ONE_PLY; - if (!captureOrPromotion) ++ if (!captureOrPromotion && !(pos.must_capture() && MoveList(pos).size())) + { // Decrease reduction for exact PV nodes (~0 Elo) if (pvExact) r -= ONE_PLY; diff --cc src/types.h index 0618836,c9c988b..75b0831 --- a/src/types.h +++ b/src/types.h @@@ -205,32 -182,11 +205,32 @@@ enum Value : int VALUE_MATE_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY, VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY, - PawnValueMg = 171, PawnValueEg = 240, - KnightValueMg = 764, KnightValueEg = 848, - BishopValueMg = 826, BishopValueEg = 891, - RookValueMg = 1282, RookValueEg = 1373, - QueenValueMg = 2500, QueenValueEg = 2670, - PawnValueMg = 142, PawnValueEg = 207, - KnightValueMg = 784, KnightValueEg = 868, - BishopValueMg = 828, BishopValueEg = 916, - RookValueMg = 1286, RookValueEg = 1378, - QueenValueMg = 2528, QueenValueEg = 2698, ++ PawnValueMg = 142, PawnValueEg = 207, ++ KnightValueMg = 784, KnightValueEg = 868, ++ BishopValueMg = 828, BishopValueEg = 916, ++ RookValueMg = 1286, RookValueEg = 1378, ++ QueenValueMg = 2528, QueenValueEg = 2698, + FersValueMg = 400, FersValueEg = 400, + AlfilValueMg = 300, AlfilValueEg = 300, + SilverValueMg = 600, SilverValueEg = 600, + AiwokValueMg = 2500, AiwokValueEg = 2500, + BersValueMg = 2000, BersValueEg = 2000, + ArchbishopValueMg = 2000, ArchbishopValueEg = 2000, + ChancellorValueMg = 2300, ChancellorValueEg = 2300, + AmazonValueMg = 3000, AmazonValueEg = 3000, + KnibisValueMg = 800, KnibisValueEg = 800, + BiskniValueMg = 800, BiskniValueEg = 800, + ShogiPawnValueMg = 100, ShogiPawnValueEg = 100, + LanceValueMg = 300, LanceValueEg = 300, + ShogiKnightValueMg = 300, ShogiKnightValueEg = 300, + EuroShogiKnightValueMg = 400, EuroShogiKnightValueEg = 400, + GoldValueMg = 600, GoldValueEg = 600, + HorseValueMg = 1500, HorseValueEg = 1500, + ClobberPieceValueMg = 300, ClobberPieceValueEg = 300, + BreakthroughPieceValueMg = 300, BreakthroughPieceValueEg = 300, + ImmobilePieceValueMg = 100, ImmobilePieceValueEg = 100, + WazirValueMg = 400, WazirValueEg = 400, + CommonerValueMg = 600, CommonerValueEg = 600, MidgameLimit = 15258, EndgameLimit = 3915 };