From: Fabian Fichter Date: Sat, 18 Jul 2020 10:44:36 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=eb348095418f46aa14c15bb3b9d453c0922a2263;p=fairystockfish.git Merge official-stockfish/master bench: 5126336 --- eb348095418f46aa14c15bb3b9d453c0922a2263 diff --cc src/bitboard.h index 6e5b2ed,f1d1460..9e85bd4 --- a/src/bitboard.h +++ b/src/bitboard.h @@@ -352,23 -255,8 +352,25 @@@ 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) { return std::min(f, File(FILE_H - f)); } -inline Rank edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); } ++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)); } + + +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'. diff --cc src/endgame.cpp index 14bbb90,0a2b02a..0bf1493 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@@ -28,44 -28,17 +28,24 @@@ using std::string namespace { - // Table used to drive the king towards the edge of the board + // Used to drive the king towards the edge of the board // in KX vs K and KQ vs KR endgames. - constexpr int PushToEdges[SQUARE_NB] = { - 100, 90, 80, 70, 70, 80, 90, 100, - 90, 70, 60, 50, 50, 60, 70, 90, - 80, 60, 40, 30, 30, 40, 60, 80, - 70, 50, 30, 20, 20, 30, 50, 70, - 70, 50, 30, 20, 20, 30, 50, 70, - 80, 60, 40, 30, 30, 40, 60, 80, - 90, 70, 60, 50, 50, 60, 70, 90, - 100, 90, 80, 70, 70, 80, 90, 100 - }; - - // Table used to drive the king towards a corner square of the - // right color in KBN vs K endgames. - constexpr int PushToCorners[SQUARE_NB] = { - 6400, 6080, 5760, 5440, 5120, 4800, 4480, 4160, - 6080, 5760, 5440, 5120, 4800, 4480, 4160, 4480, - 5760, 5440, 4960, 4480, 4480, 4000, 4480, 4800, - 5440, 5120, 4480, 3840, 3520, 4480, 4800, 5120, - 5120, 4800, 4480, 3520, 3840, 4480, 5120, 5440, - 4800, 4480, 4000, 4480, 4480, 4960, 5440, 5760, - 4480, 4160, 4480, 4800, 5120, 5440, 5760, 6080, - 4160, 4480, 4800, 5120, 5440, 5760, 6080, 6400 - }; - - // Table used to drive the king towards the edge of the board - inline int push_to_edge(Square s) { - int rd = edge_distance(rank_of(s)), fd = edge_distance(file_of(s)); ++ inline int push_to_edge(Square s, const Position& pos) { ++ int rd = edge_distance(rank_of(s), pos.max_rank()), fd = edge_distance(file_of(s), pos.max_file()); + return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2); + } + + // Used to drive the king towards A1H8 corners in KBN vs K endgames. - inline int push_to_corner(Square s) { - return abs(7 - rank_of(s) - file_of(s)); ++ inline int push_to_corner(Square s, const Position& pos) { ++ return abs((pos.max_file() + pos.max_rank()) / 2 - rank_of(s) - file_of(s)); ++ } ++ ++ // Used to drive the king towards the edge of the board + // in KSF vs K. - constexpr int PushToOpposingSideEdges[SQUARE_NB] = { - 20, 10, 5, 0, 0, 5, 10, 20, - 20, 10, 5, 0, 0, 5, 10, 20, - 30, 20, 10, 0, 0, 10, 20, 30, - 50, 40, 20, 10, 10, 20, 40, 50, - 60, 50, 40, 30, 30, 40, 50, 60, - 70, 60, 50, 40, 40, 50, 60, 70, - 90, 70, 60, 50, 50, 60, 70, 90, - 100, 90, 80, 70, 70, 80, 90, 100 - }; ++ inline int push_to_opposing_edge(Square s, const Position& pos) { ++ int rd = rank_of(s), fd = edge_distance(file_of(s), pos.max_file()); ++ return 20 - (7 * fd * fd / 2 - 7 * rd * rd / 4); + } // Drive a piece close to or away from another piece inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); } @@@ -83,19 -56,12 +63,12 @@@ assert(pos.count(strongSide) == 1); - if (file_of(pos.square(strongSide)) >= FILE_E) - sq = flip_file(sq); + if (file_of(pos.square(strongSide)) > pos.max_file() / 2) + sq = flip_file(sq, pos.max_file()); - return strongSide == WHITE ? sq : flip_rank(sq); + return strongSide == WHITE ? sq : flip_rank(sq, pos.max_rank()); } - // Map the square to an 8x8 board - Square map_to_standard_board(const Position& pos, Square s) { - File f = file_of(s) > pos.max_file() / 2 ? File(FILE_H - pos.max_file() + file_of(s)) : file_of(s); - Rank r = rank_of(s) > pos.max_rank() / 2 ? Rank(RANK_8 - pos.max_rank() + rank_of(s)) : rank_of(s); - return Square(r * 8 + f); - } - } // namespace @@@ -154,7 -112,7 +127,7 @@@ Value Endgame::operator()(const Po Value result = pos.non_pawn_material(strongSide) + pos.count(strongSide) * PawnValueEg - + PushToEdges[map_to_standard_board(pos, loserKSq)] - + push_to_edge(loserKSq) ++ + push_to_edge(loserKSq, pos) + push_close(winnerKSq, loserKSq); if ( pos.count(strongSide) @@@ -190,9 -141,9 +163,9 @@@ Value Endgame::operator()(const P // If our bishop does not attack A1/H8, we flip the enemy king square // to drive to opposite corners (A8/H1). - Value result = VALUE_KNOWN_WIN + Value result = (VALUE_KNOWN_WIN + 3520) + push_close(winnerKSq, loserKSq) - + PushToCorners[map_to_standard_board(pos, relative_square(opposite_colors(bishopSq, SQ_A1) ? BLACK : WHITE, loserKSq, pos.max_rank()))]; - + 420 * push_to_corner(opposite_colors(bishopSq, SQ_A1) ? flip_file(loserKSq) : loserKSq); ++ + 420 * push_to_corner(opposite_colors(bishopSq, SQ_A1) ? flip_file(loserKSq, pos.max_file()) : loserKSq, pos); assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY); return strongSide == pos.side_to_move() ? result : -result; @@@ -286,7 -226,7 +259,7 @@@ Value Endgame::operator()(const P assert(verify_material(pos, strongSide, RookValueMg, 0)); assert(verify_material(pos, weakSide, BishopValueMg, 0)); - Value result = Value(PushToEdges[map_to_standard_board(pos, pos.square(weakSide))]); - Value result = Value(push_to_edge(pos.square(weakSide))); ++ Value result = Value(push_to_edge(pos.square(weakSide), pos)); return strongSide == pos.side_to_move() ? result : -result; } @@@ -301,7 -241,7 +274,7 @@@ Value Endgame::operator()(const P Square bksq = pos.square(weakSide); Square bnsq = pos.square(weakSide); - Value result = Value(PushToEdges[map_to_standard_board(pos, bksq)] + push_away(bksq, bnsq)); - Value result = Value(push_to_edge(bksq) + push_away(bksq, bnsq)); ++ Value result = Value(push_to_edge(bksq, pos) + push_away(bksq, bnsq)); return strongSide == pos.side_to_move() ? result : -result; } @@@ -346,7 -286,7 +319,7 @@@ Value Endgame::operator()(const P Value result = QueenValueEg - RookValueEg - + PushToEdges[map_to_standard_board(pos, loserKSq)] - + push_to_edge(loserKSq) ++ + push_to_edge(loserKSq, pos) + push_close(winnerKSq, loserKSq); return strongSide == pos.side_to_move() ? result : -result; @@@ -362,7 -302,7 +335,7 @@@ Value Endgame::operator()(const assert(verify_material(pos, weakSide, VALUE_ZERO, 1)); Value result = PawnValueEg - + 2 * PushToEdges[map_to_standard_board(pos, pos.square(weakSide))] - + 2 * push_to_edge(pos.square(weakSide)) ++ + 2 * push_to_edge(pos.square(weakSide), pos) - 10 * relative_rank(weakSide, pos.square(weakSide)); return strongSide == pos.side_to_move() ? result : -result; @@@ -373,169 -313,6 +346,169 @@@ template<> Value Endgame::operator()(const Position&) const { return VALUE_DRAW; } +/// KFsPs vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = pos.non_pawn_material(strongSide) + + pos.count(strongSide) * PawnValueEg - + PushToEdges[map_to_standard_board(pos, loserKSq)] ++ + push_to_edge(loserKSq, pos) + + push_close(winnerKSq, loserKSq); + + if ( pos.count(strongSide) >= 3 + && ( DarkSquares & pos.pieces(strongSide, FERS)) + && (~DarkSquares & pos.pieces(strongSide, FERS))) + result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1); + else if (pos.count(strongSide) + pos.count(strongSide) < 3) + return VALUE_DRAW; + else + { + bool dark = DarkSquares & pos.pieces(strongSide, FERS); + bool light = ~DarkSquares & pos.pieces(strongSide, FERS); + + // Determine the color of ferzes from promoting pawns + Bitboard b = pos.pieces(strongSide, PAWN); + while (b && (!dark || !light)) + { + if (file_of(pop_lsb(&b)) % 2 != relative_rank(strongSide, pos.promotion_rank(), pos.max_rank()) % 2) + light = true; + else + dark = true; + } + if (!dark || !light) + return VALUE_DRAW; // we can not checkmate with same colored ferzes + } + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// Mate with KNS vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = VALUE_KNOWN_WIN + + push_close(winnerKSq, loserKSq) - + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; ++ + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos); + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// KNF vs K. Can only be won if the weaker side's king +/// is close to a corner of the same color as the fers. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, KnightValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + Square fersSq = pos.square(strongSide); + + // tries to drive toward corners A1 or H8. If we have a + // fers that cannot reach the above squares, we flip the kings in order + // to drive the enemy toward corners A8 or H1. + if (opposite_colors(fersSq, SQ_A1)) + { + winnerKSq = relative_square(BLACK, winnerKSq, pos.max_rank()); + loserKSq = relative_square(BLACK, loserKSq, pos.max_rank()); + } + + Value result = Value(push_close(winnerKSq, loserKSq)) - + (PushToCorners[map_to_standard_board(pos, loserKSq)] - 3000) / 10; ++ + 50 * push_to_corner(loserKSq, pos); + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// KNSFKR vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, RookValueMg, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = KnightValueEg + SilverValueEg + FersValueEg - RookValueEg + + push_close(winnerKSq, loserKSq) - + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; ++ + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos); + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// Mate with KSF vs K. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, VALUE_ZERO, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = VALUE_KNOWN_WIN + + push_close(winnerKSq, loserKSq) - + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; ++ + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos); + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// Mate with KSF vs KF. +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0)); + assert(verify_material(pos, weakSide, FersValueMg, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + Square fersSq = pos.square(weakSide); + + Value result = SilverValueEg + + push_close(winnerKSq, loserKSq) + + push_away(fersSq, loserKSq) - + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))]; ++ + push_to_opposing_edge(relative_square(strongSide, loserKSq, pos.max_rank()), pos); + + return strongSide == pos.side_to_move() ? result : -result; +} + + +/// KR vs KS +template<> +Value Endgame::operator()(const Position& pos) const { + + assert(verify_material(pos, strongSide, RookValueMg, 0)); + assert(verify_material(pos, weakSide, SilverValueMg, 0)); + + Square winnerKSq = pos.square(strongSide); + Square loserKSq = pos.square(weakSide); + + Value result = RookValueEg + - SilverValueEg - + PushToEdges[map_to_standard_board(pos, loserKSq)] ++ + push_to_edge(loserKSq, pos) + + push_close(winnerKSq, loserKSq); + + return strongSide == pos.side_to_move() ? result : -result; +} + + /// KB and one or more pawns vs K. It checks for draws with rook pawns and /// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW /// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling diff --cc src/evaluate.cpp index 00742f5,40630d2..dedb6d4 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -820,36 -643,7 +820,36 @@@ namespace || (pos.pieces(PAWN) & (s + Up))) bonus = bonus / 2; - score += bonus - PassedFile * std::min(file_of(s), File(pos.max_file() - file_of(s))); - score += bonus - PassedFile * edge_distance(file_of(s)); ++ score += bonus - PassedFile * edge_distance(file_of(s), pos.max_file()); + } + + // Scale by maximum promotion piece value + Value maxMg = VALUE_ZERO, maxEg = VALUE_ZERO; + for (PieceType pt : pos.promotion_piece_types()) + { + maxMg = std::max(maxMg, PieceValue[MG][pt]); + maxEg = std::max(maxEg, PieceValue[EG][pt]); + } + score = make_score(mg_value(score) * int(maxMg - PawnValueMg) / (QueenValueMg - PawnValueMg), + eg_value(score) * int(maxEg - PawnValueEg) / (QueenValueEg - PawnValueEg)); + + // Score passed shogi pawns + const Square* pl = pos.squares(Us, SHOGI_PAWN); + Square s; + + PieceType pt = pos.promoted_piece_type(SHOGI_PAWN); + if (pt != NO_PIECE_TYPE) + { + while ((s = *pl++) != SQ_NONE) + { + if ((pos.pieces(Them, SHOGI_PAWN) & forward_file_bb(Us, s)) || relative_rank(Us, s, pos.max_rank()) == pos.max_rank()) + continue; + + Square blockSq = s + Up; + int d = std::max(pos.promotion_rank() - relative_rank(Us, s, pos.max_rank()), 1); + d += !!(attackedBy[Them][ALL_PIECES] & ~attackedBy2[Us] & blockSq); + score += make_score(PieceValue[MG][pt], PieceValue[EG][pt]) / (4 * d * d); + } } if (T) diff --cc src/pawns.cpp index b0bd461,560fd76..abecfba --- a/src/pawns.cpp +++ b/src/pawns.cpp @@@ -220,14 -197,13 +220,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(std::min(f, File(pos.max_file() - f)), FILE_D); - File d = edge_distance(f); - bonus += make_score(ShelterStrength[d][ourRank], 0); ++ int d = std::min(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 d416e71,d86e98e..2c8aabf --- a/src/psqt.cpp +++ b/src/psqt.cpp @@@ -21,8 -21,7 +21,9 @@@ #include #include "types.h" + #include "bitboard.h" +#include "piece.h" +#include "variant.h" namespace PSQT { @@@ -106,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(std::min(file_of(s), File(v->maxFile - file_of(s))), FILE_A); - File f = 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(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) + { + 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/types.h index eb24300,71893c0..1b9f3c9 --- a/src/types.h +++ b/src/types.h @@@ -656,13 -367,9 +656,9 @@@ constexpr Square flip_file(Square s, Fi } constexpr Piece operator~(Piece pc) { - return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT + return Piece(pc ^ PIECE_TYPE_NB); // Swap color of piece BLACK KNIGHT -> WHITE KNIGHT } - inline File map_to_queenside(File f) { - return std::min(f, File(FILE_H - f)); // Map files ABCDEFGH to files ABCDDCBA - } - constexpr CastlingRights operator&(Color c, CastlingRights cr) { return CastlingRights((c == WHITE ? WHITE_CASTLING : BLACK_CASTLING) & cr); }