diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 3d5d606e..68301404 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -102,7 +102,12 @@ void NNUE::verify() { // Returns a static, purely materialistic evaluation of the position from // the point of view of the given color. It can be divided by PawnValue to get // an approximation of the material advantage on the board in terms of pawns. -Value Eval::simple_eval(const Position& pos, Color c) { return pos.material(c) - pos.material(~c); } +Value Eval::simple_eval(const Position& pos, Color c) { + return PawnValue * (pos.count(c) - pos.count(~c)) + + AdvisorValue * (pos.count(c) - pos.count(~c)) + + BishopValue * (pos.count(c) - pos.count(~c)) + + (pos.major_material(c) - pos.major_material(~c)); +} // Evaluate is the evaluator for the outer world. It returns a static // evaluation of the position from the point of view of the side to move. @@ -118,14 +123,14 @@ Value Eval::evaluate(const Position& pos) { int nnueComplexity; Value nnue = NNUE::evaluate(pos, true, &nnueComplexity); - int material = pos.material() / 42; Value optimism = pos.this_thread()->optimism[stm]; // Blend optimism and eval with nnue complexity and material imbalance optimism += optimism * (nnueComplexity + abs(simpleEval - nnue)) / 708; nnue -= nnue * (nnueComplexity + abs(simpleEval - nnue)) / 32858; - v = (nnue * (545 + material) + optimism * (128 + material)) / 1312; + int mm = pos.major_material() / 42; + v = (nnue * (545 + mm) + optimism * (128 + mm)) / 1312; // Damp down the evaluation linearly when shuffling v = v * (263 - shuffling) / 192; diff --git a/src/position.cpp b/src/position.cpp index 0e382bbb..a0256ff7 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -201,26 +201,26 @@ void Position::set_check_info() const { // The function is only used when a new position is set up void Position::set_state() const { - st->key = 0; - st->pawnKey = Zobrist::noPawns; - st->material[WHITE] = st->material[BLACK] = VALUE_ZERO; - st->checkersBB = checkers_to(~sideToMove, square(sideToMove)); - st->move = MOVE_NONE; + st->key = 0; + st->pawnKey = Zobrist::noPawns; + st->majorMaterial[WHITE] = st->majorMaterial[BLACK] = VALUE_ZERO; + st->checkersBB = checkers_to(~sideToMove, square(sideToMove)); + st->move = MOVE_NONE; set_check_info(); for (Bitboard b = pieces(); b;) { - Square s = pop_lsb(b); - Piece pc = piece_on(s); + Square s = pop_lsb(b); + Piece pc = piece_on(s); + PieceType pt = type_of(pc); st->key ^= Zobrist::psq[pc][s]; - if (type_of(pc) != KING) - { - st->material[color_of(pc)] += PieceValue[pc]; - if (type_of(pc) == PAWN) - st->pawnKey ^= Zobrist::psq[pc][s]; - } + if (pt == PAWN) + st->pawnKey ^= Zobrist::psq[pc][s]; + + else if (pt & 1) + st->majorMaterial[color_of(pc)] += PieceValue[pc]; } if (sideToMove == BLACK) @@ -461,7 +461,12 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { { Square capsq = to; - st->material[them] -= PieceValue[captured]; + // If the captured piece is a pawn, update pawn hash key, otherwise + // update major material. + if (type_of(captured) == PAWN) + st->pawnKey ^= Zobrist::psq[captured][capsq]; + else if (type_of(captured) & 1) + st->majorMaterial[them] -= PieceValue[captured]; dp.dirty_num = 2; // 1 piece moved, 1 piece captured dp.piece[1] = captured; @@ -476,9 +481,6 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { // Update hash key k ^= Zobrist::psq[captured][capsq]; - // If the captured piece is a pawn, update pawn hash key. - if (type_of(captured) == PAWN) - st->pawnKey ^= Zobrist::psq[captured][capsq]; // Reset rule 60 counter st->check10[WHITE] = st->check10[BLACK] = st->rule60 = 0; @@ -488,7 +490,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { k ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to]; // If the moving piece is a pawn, update pawn hash key. if (type_of(pc) == PAWN) - st->pawnKey ^= Zobrist::psq[pc][to]; + st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to]; // Move the piece. dp.piece[0] = pc; diff --git a/src/position.h b/src/position.h index 77136c17..87ac8df5 100644 --- a/src/position.h +++ b/src/position.h @@ -43,7 +43,7 @@ struct StateInfo { // Copied when making a move Key pawnKey; - Value material[COLOR_NB]; + Value majorMaterial[COLOR_NB]; int16_t check10[COLOR_NB]; int rule60; int pliesFromNull; @@ -154,8 +154,8 @@ class Position { int rule60_count() const; bool has_mate_threat(Depth d = -1); uint16_t chased(Color c); - Value material(Color c) const; - Value material() const; + Value major_material(Color c) const; + Value major_material() const; // Position consistency check, for debugging bool pos_is_ok() const; @@ -277,9 +277,11 @@ inline Key Position::adjust_key60(Key k) const { inline Key Position::pawn_key() const { return st->pawnKey; } -inline Value Position::material(Color c) const { return st->material[c]; } +inline Value Position::major_material(Color c) const { return st->majorMaterial[c]; } -inline Value Position::material() const { return material(WHITE) + material(BLACK); } +inline Value Position::major_material() const { + return major_material(WHITE) + major_material(BLACK); +} inline int Position::game_ply() const { return gamePly; } diff --git a/src/search.cpp b/src/search.cpp index dd579775..afb96c60 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -671,7 +671,8 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo // Step 8. Null move search with verification search (~35 Elo) if (!PvNode && (ss - 1)->currentMove != MOVE_NULL && (ss - 1)->statScore < 12731 && eval >= beta && eval >= ss->staticEval && ss->staticEval >= beta - 14 * depth + 138 && !excludedMove - && ss->ply >= thisThread->nmpMinPly && beta > VALUE_MATED_IN_MAX_PLY) + && pos.major_material(us) && ss->ply >= thisThread->nmpMinPly + && beta > VALUE_MATED_IN_MAX_PLY) { assert(eval - beta >= 0); @@ -840,9 +841,9 @@ Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, boo Depth r = reduction(improving, depth, moveCount, delta, thisThread->rootDelta); - // Step 13. Pruning at shallow depth (~98 Elo). + // Step 13. Pruning at shallow depth (~120 Elo). // Depth conditions are important for mate finding. - if (!rootNode && bestValue > VALUE_MATED_IN_MAX_PLY) + if (!rootNode && pos.major_material(us) && bestValue > VALUE_MATED_IN_MAX_PLY) { // Skip quiet moves if movecount exceeds our FutilityMoveCount threshold (~8 Elo) if (!moveCountPruning) @@ -1252,6 +1253,7 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { Value bestValue, value, ttValue, futilityValue, futilityBase; bool pvHit, givesCheck, capture; int moveCount; + Color us = pos.side_to_move(); // Step 1. Initialize node if (PvNode) @@ -1358,7 +1360,7 @@ Value qsearch(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth) { moveCount++; // Step 6. Pruning. - if (bestValue > VALUE_MATED_IN_MAX_PLY) + if (bestValue > VALUE_MATED_IN_MAX_PLY && pos.major_material(us)) { // Futility pruning and moveCount pruning (~5 Elo) if (!givesCheck && to_sq(move) != prevSq && futilityBase > VALUE_MATED_IN_MAX_PLY)