From: Fabian Fichter Date: Sat, 27 Jul 2019 11:35:33 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=a447f63df7a765969dc30bbe8ec504e4068a985a;p=fairystockfish.git Merge official-stockfish/master bench: 3559377 --- a447f63df7a765969dc30bbe8ec504e4068a985a diff --cc src/bitboard.cpp index 094f4c1,2afd376..c0e0960 --- a/src/bitboard.cpp +++ b/src/bitboard.cpp @@@ -353,67 -71,46 +353,67 @@@ 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 s = SQ_A1; s <= SQ_MAX; ++s) + SquareBB[s] = make_bitboard(s); - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) - for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) + 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)); - int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } }; + // Piece moves + std::vector RookDirections = { NORTH, EAST, SOUTH, WEST }; + std::vector BishopDirections = { 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 - for (Color c = WHITE; c <= BLACK; ++c) + for (Color c : { WHITE, BLACK }) - 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) + { + const PieceInfo* pi = pieceMap.find(pt)->second; + + for (Square s = SQ_A1; s <= SQ_MAX; ++s) + { + for (Direction d : pi->stepsCapture) { - Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]); + Square to = s + Direction(c == WHITE ? d : -d); - 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 (Direction d : pi->stepsQuiet) + { + Square to = s + Direction(c == WHITE ? d : -d); - 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(pi->sliderCapture, s, 0, c); + PseudoMoves[c][pt][s] |= sliding_attack(pi->sliderQuiet, s, 0, 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) - 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/evaluate.cpp index d2f1c13,7359eb9..cb78ca7 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -131,20 -123,10 +131,13 @@@ namespace // PassedRank[Rank] contains a bonus according to the rank of a passed pawn constexpr Score PassedRank[RANK_NB] = { - S(0, 0), S(5, 18), S(12, 23), S(10, 31), S(57, 62), S(163, 167), S(271, 250) - }; - - // PassedFile[File] contains a bonus according to the file of a passed pawn - constexpr Score PassedFile[FILE_NB] = { - S( -1, 7), S( 0, 9), S(-9, -8), S(-30,-14), - S(-30,-14), S(-9, -8), S( 0, 9), S( -1, 7) + S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260) }; + // KingProximity contains a penalty according to distance from king + constexpr Score KingProximity = S(1, 3); + // Assorted bonuses and penalties - constexpr Score AttacksOnSpaceArea = S( 4, 0); constexpr Score BishopPawns = S( 3, 7); constexpr Score CorneredBishop = S( 50, 50); constexpr Score FlankAttacks = S( 8, 0); @@@ -674,7 -555,7 +668,7 @@@ b &= ~attackedBy[Them][PAWN] & safe; // Bonus for safe pawn threats on the next move - b = (pawn_attacks_bb(b) | shift(shift(pos.pieces(Us, SHOGI_PAWN)))) & pos.pieces(Them); - b = pawn_attacks_bb(b) & nonPawnEnemies; ++ b = (pawn_attacks_bb(b) | shift(shift(pos.pieces(Us, SHOGI_PAWN)))) & nonPawnEnemies; score += ThreatByPawnPush * popcount(b); // Our safe or protected pawns @@@ -715,10 -596,10 +709,10 @@@ constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH); auto king_proximity = [&](Color c, Square s) { - return std::min(distance(pos.square(c), s), 5); + return pos.count(c) ? std::min(distance(pos.square(c), s), 5) : 5; }; - Bitboard b, bb, squaresToQueen, defendedSquares, unsafeSquares; + Bitboard b, bb, squaresToQueen, unsafeSquares; Score score = SCORE_ZERO; b = pe->passed_pawns(Us); @@@ -729,26 -610,23 +723,27 @@@ assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up))); - int r = relative_rank(Us, s); + int r = std::max(RANK_8 - std::max(pos.promotion_rank() - relative_rank(Us, s, pos.max_rank()), 0), 0); + File f = file_of(s); Score bonus = PassedRank[r]; if (r > RANK_3) { - int w = (r-2) * (r-2) + 2; + int w = 5 * r - 13; Square blockSq = s + Up; - // Adjust bonus based on the king's proximity - bonus += make_score(0, ( king_proximity(Them, blockSq) * 5 - - king_proximity(Us, blockSq) * 2) * w); + // Skip bonus for antichess variants + if (pos.extinction_value() != VALUE_MATE) + { + // Adjust bonus based on the king's proximity + bonus += make_score(0, ( king_proximity(Them, blockSq) * 5 + - king_proximity(Us, blockSq) * 2) * w); - // If blockSq is not the queening square then consider also a second push - if (r != RANK_7) - bonus -= make_score(0, king_proximity(Us, blockSq + Up) * w); + // If blockSq is not the queening square then consider also a second push + if (r != RANK_7) + bonus -= make_score(0, king_proximity(Us, blockSq + Up) * w); + } // If the pawn is free to advance, then increase the bonus if (pos.empty(blockSq)) @@@ -783,39 -658,10 +775,39 @@@ // Scale down bonus for candidate passers which need more than one // pawn push to become passed, or have a pawn in front of them. if ( !pos.pawn_passed(Us, s + Up) - || (pos.pieces(PAWN) & forward_file_bb(Us, s))) + || (pos.pieces(PAWN) & (s + Up))) bonus = bonus / 2; - score += bonus + PassedFile[file_of(s)]; - score += bonus - PassedFile * std::min(f, ~f); ++ score += bonus - PassedFile * std::min(f, File(pos.max_file() - f)); + } + + // 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) @@@ -857,13 -700,7 +849,12 @@@ behind |= shift(behind); behind |= shift(behind); + if (pawnsOnly) + { + safe = behind & ~attackedBy[Them][ALL_PIECES]; + behind = 0; + } - - int bonus = popcount(safe) + popcount(behind & safe); + int bonus = popcount(safe) + popcount(behind & safe & ~attackedBy[Them][ALL_PIECES]); int weight = pos.count(Us) - 1; Score score = make_score(bonus * weight * weight / 16, 0); diff --cc src/material.cpp index 915593c,11d4c68..2d08a26 --- a/src/material.cpp +++ b/src/material.cpp @@@ -164,14 -140,7 +164,14 @@@ Entry* probe(const Position& pos) if ((e->evaluationFunction = Endgames::probe(key)) != nullptr) return e; - for (Color c = WHITE; c <= BLACK; ++c) + for (Color c : { WHITE, BLACK }) + if (is_KFsPsK(pos, c)) + { + e->evaluationFunction = &EvaluateKFsPsK[c]; + return e; + } + - for (Color c = WHITE; c <= BLACK; ++c) ++ for (Color c : { WHITE, BLACK }) if (is_KXK(pos, c)) { e->evaluationFunction = &EvaluateKXK[c]; diff --cc src/pawns.cpp index 5fc5dd9,9755c2e..e26f75a --- a/src/pawns.cpp +++ b/src/pawns.cpp @@@ -101,48 -98,45 +98,47 @@@ namespace // Flag the pawn opposed = theirPawns & forward_file_bb(Us, s); stoppers = theirPawns & passed_pawn_span(Us, s); - lever = theirPawns & PawnAttacks[Us][s]; - leverPush = theirPawns & PawnAttacks[Us][s + Up]; - doubled = ourPawns & (s - Up); + lever = theirPawns & PseudoAttacks[Us][PAWN][s]; + leverPush = relative_rank(Them, s, pos.max_rank()) > RANK_1 ? theirPawns & PseudoAttacks[Us][PAWN][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 be safely advanced. - backward = relative_rank(Them, s, pos.max_rank()) > RANK_1 - && !(ourPawns & pawn_attack_span(Them, s + Up)) + // A pawn is backward when it is behind all pawns of the same color on + // the adjacent files and cannot safely advance. Phalanx and isolated + // pawns will be excluded when the pawn is scored. + backward = !(neighbours & forward_ranks_bb(Them, s)) ++ && is_ok(s + Up) && (stoppers & (leverPush | (s + Up))); - // Passed pawns will be properly scored in evaluation because we need - // full attack info to evaluate them. Include also not passed pawns - // which could become passed after one or two pawn pushes when are - // not attacked more times than defended. - if ( !(stoppers ^ lever) || - (!(stoppers ^ leverPush) && popcount(phalanx) >= popcount(leverPush))) + // A pawn is passed if one of the three following conditions is true: + // (a) there is no stoppers except some levers + // (b) the only stoppers are the leverPush, but we outnumber them + // (c) there is only one front stopper which can be levered. + passed = !(stoppers ^ lever) + || ( !(stoppers ^ leverPush) + && popcount(phalanx) >= popcount(leverPush)) - || ( stoppers == square_bb(s + Up) && r >= RANK_5 ++ || ( is_ok(s + Up) && stoppers == square_bb(s + Up) && r >= RANK_5 + && (shift(support) & ~(theirPawns | doubleAttackThem))); + + // Passed pawns will be properly scored later in evaluation when we have + // full attack info. + if (passed) e->passedPawns[Us] |= s; // Score this pawn if (support | phalanx) { - int v = Connected[r] * (phalanx ? 3 : 2) / (opposed ? 2 : 1) + int v = Connected[r] * (phalanx ? 3 : 2) * (r == RANK_2 && pos.captures_to_hand() ? 3 : 1) / (opposed ? 2 : 1) + 17 * popcount(support); - + if (r >= RANK_4 && pos.count(Us) > popcount(pos.board_bb()) / 4) + v = std::max(v, popcount(support | phalanx) * 50) / (opposed ? 2 : 1); score += make_score(v, v * (r - 2) / 4); } + else if (!neighbours) - score -= Isolated + WeakUnopposed * int(!opposed); + score -= Isolated * (1 + 2 * pos.must_capture()) + WeakUnopposed * int(!opposed); else if (backward) score -= Backward + WeakUnopposed * int(!opposed); @@@ -151,26 -145,12 +147,32 @@@ score -= Doubled; } + // Penalize the unsupported and non passed pawns attacked twice by the enemy + b = ourPawns + & doubleAttackThem + & ~(e->pawnAttacks[Us] | e->passedPawns[Us]); + score -= WeakLever * popcount(b); + + // Double pawn evaluation if there are no non-pawn pieces + if (pos.count(Us) == pos.count(Us)) + score = score * 2; + + const Square* pl_shogi = pos.squares(Us); + + ourPawns = pos.pieces(Us, SHOGI_PAWN); + theirPawns = pos.pieces(Them, SHOGI_PAWN); + + // Loop through all shogi pawns of the current color and score each one + while ((s = *pl_shogi++) != SQ_NONE) + { + assert(pos.piece_on(s) == make_piece(Us, SHOGI_PAWN)); + + neighbours = ourPawns & adjacent_files_bb(s); + + if (!neighbours) + score -= Isolated / 2; + } + return score; } @@@ -205,34 -185,34 +207,34 @@@ Entry* probe(const Position& pos) template void Entry::evaluate_shelter(const Position& pos, Square ksq, Score& shelter) { - constexpr Color Them = (Us == WHITE ? BLACK : WHITE); + constexpr Color Them = (Us == WHITE ? BLACK : WHITE); - Bitboard b = pos.pieces(PAWN) & ~forward_ranks_bb(Them, ksq); + Bitboard b = pos.pieces(PAWN, SHOGI_PAWN) & ~forward_ranks_bb(Them, ksq); Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); - Value bonus[] = { Value(5), Value(5) }; + Score bonus = make_score(5, 5); - File center = clamp(file_of(ksq), FILE_B, FILE_G); + File center = clamp(file_of(ksq), FILE_B, File(pos.max_file() - 1)); for (File f = File(center - 1); f <= File(center + 1); ++f) { b = ourPawns & file_bb(f); - Rank ourRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; + Rank ourRank = b ? relative_rank(Us, frontmost_sq(Them, b), pos.max_rank()) : RANK_1; b = theirPawns & file_bb(f); - Rank theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; + Rank theirRank = b ? relative_rank(Us, frontmost_sq(Them, b), pos.max_rank()) : RANK_1; - int d = std::min(f, ~f); - bonus += make_score(ShelterStrength[d][ourRank], 0); + int d = std::min(std::min(f, File(pos.max_file() - f)), FILE_D); - bonus[MG] += ShelterStrength[d][ourRank] * (1 + (pos.captures_to_hand() && ourRank <= RANK_2)); ++ bonus += make_score(ShelterStrength[d][ourRank], 0) * (1 + (pos.captures_to_hand() && ourRank <= RANK_2)); if (ourRank && (ourRank == theirRank - 1)) - bonus[MG] -= 82 * (theirRank == RANK_3), bonus[EG] -= 82 * (theirRank == RANK_3); + bonus -= make_score(82 * (theirRank == RANK_3), 82 * (theirRank == RANK_3)); else - bonus[MG] -= UnblockedStorm[d][theirRank]; + bonus -= make_score(UnblockedStorm[d][theirRank], 0); } - if (bonus[MG] > mg_value(shelter)) - shelter = make_score(bonus[MG], bonus[EG]); + if (mg_value(bonus) > mg_value(shelter)) + shelter = bonus; } diff --cc src/position.cpp index 7956b7a,fbde810..37bbfc8 --- a/src/position.cpp +++ b/src/position.cpp @@@ -159,12 -146,11 +159,12 @@@ void Position::init() PRNG rng(1070372); - for (Color c = WHITE; c <= BLACK; ++c) - for (Piece pc : Pieces) - for (Square s = SQ_A1; s <= SQ_H8; ++s) - Zobrist::psq[pc][s] = rng.rand(); ++ for (Color c : {WHITE, BLACK}) + for (PieceType pt = PAWN; pt <= KING; ++pt) + for (Square s = SQ_A1; s <= SQ_MAX; ++s) + Zobrist::psq[make_piece(c, pt)][s] = rng.rand(); - for (File f = FILE_A; f <= FILE_H; ++f) + for (File f = FILE_A; f <= FILE_MAX; ++f) Zobrist::enpassant[f] = rng.rand(); for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr) @@@ -181,26 -167,14 +181,26 @@@ Zobrist::side = rng.rand(); Zobrist::noPawns = rng.rand(); - for (Color c = WHITE; c <= BLACK; ++c) ++ for (Color c : {WHITE, BLACK}) + for (int n = 0; n < CHECKS_NB; ++n) + Zobrist::checks[c][n] = rng.rand(); + - for (Color c = WHITE; c <= BLACK; ++c) ++ for (Color c : {WHITE, BLACK}) + for (PieceType pt = PAWN; pt <= KING; ++pt) + for (int n = 0; n < SQUARE_NB; ++n) + Zobrist::inHand[make_piece(c, pt)][n] = rng.rand(); + // Prepare the cuckoo tables std::memset(cuckoo, 0, sizeof(cuckoo)); std::memset(cuckooMove, 0, sizeof(cuckooMove)); int count = 0; - for (Color c = WHITE; c <= BLACK; ++c) - for (Piece pc : Pieces) - for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) - for (Square s2 = Square(s1 + 1); s2 <= SQ_H8; ++s2) - if (PseudoAttacks[type_of(pc)][s1] & 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) { Move move = make_move(s1, s2); Key key = Zobrist::psq[pc][s1] ^ Zobrist::psq[pc][s2] ^ Zobrist::side; @@@ -518,21 -399,9 +518,21 @@@ void Position::set_state(StateInfo* si si->key ^= Zobrist::castling[si->castlingRights]; - for (Color c = WHITE; c <= BLACK; ++c) - for (Piece pc : Pieces) - for (int cnt = 0; cnt < pieceCount[pc]; ++cnt) - si->materialKey ^= Zobrist::psq[pc][cnt]; ++ for (Color c : {WHITE, BLACK}) + for (PieceType pt = PAWN; pt <= KING; ++pt) + { + Piece pc = make_piece(c, pt); + + for (int cnt = 0; cnt < pieceCount[pc]; ++cnt) + si->materialKey ^= Zobrist::psq[pc][cnt]; + + if (piece_drops()) + si->key ^= Zobrist::inHand[pc][pieceCountInHand[c][pt]]; + } + + if (max_check_count()) - for (Color c = WHITE; c <= BLACK; ++c) ++ for (Color c : {WHITE, BLACK}) + si->key ^= Zobrist::checks[c][si->checksGiven[c]]; } @@@ -596,16 -452,6 +596,16 @@@ const string Position::fen() const ss << '/'; } + // pieces in hand + if (piece_drops()) + { + ss << '['; - for (Color c = WHITE; c <= BLACK; ++c) ++ for (Color c : {WHITE, BLACK}) + for (PieceType pt = KING; pt >= PAWN; --pt) + ss << std::string(pieceCountInHand[c][pt], piece_to_char()[make_piece(c, pt)]); + ss << ']'; + } + ss << (sideToMove == WHITE ? " w " : " b "); if (can_castle(WHITE_OO)) @@@ -1940,21 -1288,19 +1940,21 @@@ bool Position::pos_is_ok() const if (std::memcmp(&si, st, sizeof(StateInfo))) assert(0 && "pos_is_ok: State"); - for (Color c = WHITE; c <= BLACK; ++c) - for (Piece pc : Pieces) - { - if ( pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))) - || pieceCount[pc] != std::count(board, board + SQUARE_NB, pc)) - assert(0 && "pos_is_ok: Pieces"); - - for (int i = 0; i < pieceCount[pc]; ++i) - if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i) - assert(0 && "pos_is_ok: Index"); - } ++ for (Color c : {WHITE, BLACK}) + for (PieceType pt = PAWN; pt <= KING; ++pt) + { + Piece pc = make_piece(c, pt); + if ( pieceCount[pc] != popcount(pieces(c, pt)) + || pieceCount[pc] != std::count(board, board + SQUARE_NB, pc)) + assert(0 && "pos_is_ok: Pieces"); + + for (int i = 0; i < pieceCount[pc]; ++i) + if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i) + assert(0 && "pos_is_ok: Index"); + } - for (Color c = WHITE; c <= BLACK; ++c) - for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1)) + for (Color c : { WHITE, BLACK }) + for (CastlingSide s : {KING_SIDE, QUEEN_SIDE}) { if (!can_castle(c | s)) continue; diff --cc src/position.h index 846a919,2106414..793fdb3 --- a/src/position.h +++ b/src/position.h @@@ -724,6 -317,10 +725,10 @@@ inline Bitboard Position::check_squares return st->checkSquares[pt]; } + inline bool Position::is_discovery_check_on_king(Color c, Move m) const { - return st->blockersForKing[c] & from_sq(m); ++ return is_ok(from_sq(m)) && st->blockersForKing[c] & from_sq(m); + } + inline bool Position::pawn_passed(Color c, Square s) const { return !(pieces(~c, PAWN) & passed_pawn_span(c, s)); } diff --cc src/search.cpp index d72e749,eda7f2f..4a98a4a --- a/src/search.cpp +++ b/src/search.cpp @@@ -1020,6 -1012,6 +1030,12 @@@ moves_loop: // When in check, search st && pos.pawn_passed(us, to_sq(move))) extension = ONE_PLY; ++ // Losing chess capture extension ++ else if ( pos.must_capture() ++ && pos.capture(move) ++ && MoveList(pos).size() == 1) ++ extension = ONE_PLY; ++ // Calculate new depth for this move newDepth = depth - ONE_PLY + extension; @@@ -1033,10 -1025,9 +1049,10 @@@ if ( !captureOrPromotion && !givesCheck - && (!pos.advanced_pawn_push(move) || pos.non_pawn_material(~us) > BishopValueMg)) + && (!pos.must_capture() || !pos.attackers_to(to_sq(move), ~us)) + && (!pos.advanced_pawn_push(move) || pos.non_pawn_material(~us) > BishopValueMg || pos.count(us) == pos.count(us))) { - // Move count based pruning (~30 Elo) + // Move count based pruning if (moveCountPruning) continue; @@@ -1059,12 -1048,11 +1075,12 @@@ continue; // Prune moves with negative SEE (~10 Elo) - if (!pos.must_capture() && !pos.see_ge(move, Value(-29 * lmrDepth * lmrDepth))) - if (!pos.see_ge(move, Value(-(31 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth))) ++ if (!pos.must_capture() && !pos.see_ge(move, Value(-(31 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth))) continue; } - else if ((!givesCheck || !extension) - && !pos.must_capture() - && !pos.see_ge(move, -(PawnValueEg + 120 * pos.captures_to_hand()) * (depth / ONE_PLY))) // (~20 Elo) + else if ( (!givesCheck || !extension) - && !pos.see_ge(move, -PawnValueEg * (depth / ONE_PLY))) // (~20 Elo) ++ && !pos.must_capture() ++ && !pos.see_ge(move, -(PawnValueEg + 120 * pos.captures_to_hand()) * (depth / ONE_PLY))) // (~20 Elo) continue; } @@@ -1129,11 -1116,18 +1145,18 @@@ r -= 2 * ONE_PLY; ss->statScore = thisThread->mainHistory[us][from_to(move)] - + (*contHist[0])[movedPiece][to_sq(move)] - + (*contHist[1])[movedPiece][to_sq(move)] - + (*contHist[3])[movedPiece][to_sq(move)] + + (*contHist[0])[history_slot(movedPiece)][to_sq(move)] + + (*contHist[1])[history_slot(movedPiece)][to_sq(move)] + + (*contHist[3])[history_slot(movedPiece)][to_sq(move)] - 4000; + // Reset statScore to zero if negative and most stats shows >= 0 + if ( ss->statScore < 0 - && (*contHist[0])[movedPiece][to_sq(move)] >= 0 - && (*contHist[1])[movedPiece][to_sq(move)] >= 0 ++ && (*contHist[0])[history_slot(movedPiece)][to_sq(move)] >= 0 ++ && (*contHist[1])[history_slot(movedPiece)][to_sq(move)] >= 0 + && thisThread->mainHistory[us][from_to(move)] >= 0) + ss->statScore = 0; + // Decrease/increase reduction by comparing opponent's stat score (~10 Elo) if (ss->statScore >= 0 && (ss-1)->statScore < 0) r -= ONE_PLY; diff --cc src/ucioption.cpp index 779626d,23c0c48..86b0410 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@@ -91,8 -73,9 +91,10 @@@ void init(OptionsMap& o) o["Slow Mover"] << Option(84, 10, 1000); o["nodestime"] << Option(0, 0, 10000); o["UCI_Chess960"] << Option(false); + o["UCI_Variant"] << Option("chess", variants.get_keys(), on_variant_change); o["UCI_AnalyseMode"] << Option(false); + o["UCI_LimitStrength"] << Option(false); + o["UCI_Elo"] << Option(1350, 1350, 2850); o["SyzygyPath"] << Option("", on_tb_path); o["SyzygyProbeDepth"] << Option(1, 1, 100); o["Syzygy50MoveRule"] << Option(true);