LCOV - code coverage report
Current view: top level - Source - searcher.hpp (source / functions) Coverage Total Hit
Test: coverage Lines: 100.0 % 8 8
Test Date: 2026-03-02 16:42:41 Functions: - 0 0

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include "definition.hpp"
       4              : #include "evalDef.hpp"
       5              : #include "material.hpp"
       6              : #include "score.hpp"
       7              : #include "stats.hpp"
       8              : #include "tables.hpp"
       9              : #include "threading.hpp"
      10              : 
      11              : /*!
      12              :  * Searcher struct store all the information needed by a search thread
      13              :  * Implements main search function (driver, pvs, qsearch, see, display to GUI, ...)
      14              :  * This was inspired from the former thread Stockfish style management
      15              :  *
      16              :  * Many things are templates here, so other hpp file are included at the bottom of this one.
      17              :  */
      18              : struct Searcher {
      19              :    bool stopFlag = true;
      20              : 
      21       159967 :    struct StackData {
      22              :       Position  p;
      23              :       Hash      h      = nullHash;
      24              :       //EvalData  data;
      25              :       ScoreType eval   = 0;
      26              :       MiniMove  threat = INVALIDMINIMOVE;
      27              :    };
      28              : 
      29              :    struct PVSData{
      30              :       // CMH
      31              :       CMHPtrArray cmhPtr;
      32              : 
      33              :       // move counting
      34              :       int validMoveCount      {0};
      35              :       int validQuietMoveCount {0};
      36              :       int validNonPrunedCount {0};
      37              : 
      38              :       // from call
      39              :       ScoreType alpha {0};
      40              :       ScoreType beta  {0};
      41              :       bool isInCheck              {false};
      42              :       bool cutNode                {false};
      43              :       bool pvnode                 {false};
      44              :       bool rootnode               {false};
      45              :       bool theirTurn              {false};
      46              :       bool withoutSkipMove        {true};
      47              :       bool previousMoveIsNullMove {false};
      48              : 
      49              :       // tt related stuff
      50              :       DepthType marginDepth       {0};
      51              :       TT::Bound bound             {TT::B_none};
      52              :       bool ttMoveIsCapture        {false};
      53              :       bool ttMoveSingularExt      {false};
      54              :       bool ttMoveTried            {false};
      55              :       bool validTTmove            {false};
      56              :       bool ttHit                  {false};
      57              :       bool ttPV                   {false};
      58              :       bool ttIsCheck              {false};
      59              :       bool formerPV               {false};
      60              :       bool evalScoreIsHashScore   {false};
      61              : 
      62              :       // context
      63              :       bool improving              {false};
      64              :       bool isEmergencyDefence     {false};
      65              :       bool isEmergencyAttack      {false};
      66              :       bool isBoomingAttack        {false};
      67              :       bool isBoomingDefend        {false};
      68              :       bool isMoobingAttack        {false};
      69              :       bool isMoobingDefend        {false};
      70              :       bool isNotPawnEndGame       {false};
      71              :       bool lessZugzwangRisk       {false};
      72              :       bool isKnownEndGame         {false};
      73              : 
      74              :       // situation
      75              :       bool bestMoveIsCheck        {false};
      76              :       bool mateThreat             {false};
      77              :       bool alphaUpdated           {false};
      78              : 
      79              :       // current move
      80              :       bool isCheck                {false};
      81              :       bool isQuiet                {false};
      82              :       bool isAdvancedPawnPush     {false};
      83              :       bool earlyMove              {false};
      84              :       bool isTTMove               {false};
      85              : 
      86              :       // pruning and extension triggers
      87              :       bool futility               {false};
      88              :       bool lmp                    {false};
      89              :       bool historyPruning         {false};
      90              :       bool capHistoryPruning      {false};
      91              :       bool CMHPruning             {false};
      92              :       bool BMextension            {false};
      93              :    };
      94              : 
      95              :    MoveDifficultyUtil::MoveDifficulty moveDifficulty = MoveDifficultyUtil::MD_std;
      96              :    MoveDifficultyUtil::PositionEvolution positionEvolution = MoveDifficultyUtil::PE_std;
      97              : 
      98              :    TimeType currentMoveMs  = 777;
      99              :    TimeType getCurrentMoveMs()const; // use this (and not the variable) to take emergency time into account !
     100              : 
     101              :    array1d<StackData, MAX_PLY> stack;
     102              :    [[nodiscard]] bool isBooming(uint16_t halfmove); // from stack
     103              :    [[nodiscard]] bool isMoobing(uint16_t halfmove); // from stack
     104              : 
     105              :    mutable Stats stats;
     106              : 
     107              :    // beta cut more refined statistics are possible and gather using this function
     108              :    void updateStatBetaCut(const Position & p, const Move m, const DepthType height);
     109              : 
     110              :    FORCE_FINLINE void updatePV(PVList& pv, const Move& m, const PVList& childPV) {
     111              :       stats.incr(Stats::sid_PVupdate);
     112              :       pv.clear();
     113        13477 :       pv.emplace_back(m);
     114        13477 :       std::ranges::copy(childPV, std::back_inserter(pv));
     115        13477 :    }
     116              : 
     117              :    void displayStats() const {
     118              :       for (size_t k = 0; k < Stats::sid_maxid; ++k) {
     119              :          Logging::LogIt(Logging::logInfo) << Stats::Names[k] << " " << stats.counters[(Stats::StatId)k];
     120              :       }
     121              :    }
     122              : 
     123              :    std::vector<RootScores> rootScores;
     124              : 
     125              :    // used for move ordering
     126              :    Move previousBest = INVALIDMOVE;
     127              : 
     128              :    KillerT   killerT;
     129              :    HistoryT  historyT;
     130              :    CounterT  counterT;
     131              :    DepthType nullMoveMinPly = 0;
     132              :    Color     nullMoveVerifColor = Co_None;
     133              :    EvalScore contempt       = 0;
     134              :    bool      subSearch      = false;
     135              :    bool      isStoppableCoSearcher = false; 
     136              :    DepthType height_        = 0; ///@todo use this everywhere, instead of passing height in pvs and qsearch call ?
     137              : 
     138              : #ifdef WITH_GENFILE
     139              :    std::ofstream genStream;
     140              :    void          writeToGenFile(const Position& p, bool getQuietPos, const ThreadData & d, const std::optional<int> result);
     141              : #endif
     142              :    std::ofstream pgnStream;
     143              : 
     144              :    static Position getQuiet(const Position& p, Searcher* searcher = nullptr, ScoreType* qScore = nullptr);
     145              : 
     146              :    static Searcher& getCoSearcher(size_t id);
     147              : 
     148              :    void                    getCMHPtr(const unsigned int ply, CMHPtrArray& cmhPtr);
     149              :    [[nodiscard]] ScoreType getCMHScore(const Position& p, const Square from, const Square to, const CMHPtrArray& cmhPtr) const;
     150              : 
     151              :    [[nodiscard]] bool isCMHGood(const Position& p, const Square from, const Square to, const CMHPtrArray& cmhPtr, const ScoreType threshold) const;
     152              :    [[nodiscard]] bool isCMHBad (const Position& p, const Square from, const Square to, const CMHPtrArray& cmhPtr, const ScoreType threshold) const;
     153              : 
     154              :    [[nodiscard]] ScoreType drawScore(const Position& p, DepthType height) const;
     155              : 
     156              :    std::tuple<DepthType, DepthType, DepthType> depthPolicy(const Position & p, DepthType depth, DepthType height, Move m, const PVSData & pvsData, const EvalData & evalData, ScoreType evalScore, DepthType extensions, bool isReductible) const;
     157              : 
     158              :    void timeCheck();
     159              : 
     160              :    template<bool pvnode>
     161              :    [[nodiscard]]
     162              :    ScoreType pvs(ScoreType                    alpha,
     163              :                  ScoreType                    beta,
     164              :                  const Position&              p,
     165              :                  DepthType                    depth,
     166              :                  DepthType                    height,
     167              :                  PVList&                      pv,
     168              :                  DepthType&                   seldepth,
     169              :                  DepthType                    extensions,
     170              :                  bool                         isInCheck,
     171              :                  bool                         cutNode,
     172              :                  const std::vector<MiniMove>* skipMoves = nullptr);
     173              : 
     174              :    [[nodiscard]] ScoreType qsearch(ScoreType       alpha,
     175              :                                    ScoreType       beta,
     176              :                                    const Position& p,
     177              :                                    DepthType       height,
     178              :                                    DepthType&      seldepth,
     179              :                                    DepthType       qply,
     180              :                                    bool            qRoot,
     181              :                                    bool            pvnode,
     182              :                                    int8_t          isInCheckHint = -1);
     183              : 
     184              :    // used for tuning not search !
     185              :    [[nodiscard]] ScoreType qsearchNoPruning(ScoreType       alpha,
     186              :                                             ScoreType       beta,
     187              :                                             const Position& p,
     188              :                                             DepthType       height,
     189              :                                             DepthType&      seldepth,
     190              :                                             PVList*         pv = nullptr);
     191              : 
     192              :    [[nodiscard]] static bool SEE_GE(const Position& p, const Move& m, ScoreType threshold);
     193              : 
     194              :    [[nodiscard]] static ScoreType SEE(const Position& p, const Move& m);
     195              : 
     196              :    void searchDriver(bool postMove = true);
     197              : 
     198              :    template<bool isPv = true>
     199              :    [[nodiscard]] std::optional<ScoreType> interiorNodeRecognizer(const Position& p, DepthType height) const;
     200              : 
     201              :    [[nodiscard]] bool isRep(const Position& p, bool isPv) const;
     202              :    [[nodiscard]] bool isMaterialDraw(const Position& p) const;
     203              :    [[nodiscard]] bool is50moves(const Position& p, bool afterMoveLoop) const;
     204              : 
     205              :    void displayGUI(DepthType          depth,
     206              :                    DepthType          seldepth,
     207              :                    ScoreType          bestScore,
     208              :                    unsigned int       ply,
     209              :                    const PVList&      pv,
     210              :                    int                multipv,
     211              :                    const std::string& mark = "");
     212              : 
     213              :    void idleLoop();
     214              : 
     215              :    void startThread();
     216              : 
     217              :    void wait();
     218              : 
     219              :    void searchLauncher();
     220              : 
     221              :    [[nodiscard]] size_t id() const;
     222              :    [[nodiscard]] bool   isMainThread() const;
     223              : 
     224              :    explicit Searcher(size_t n);
     225              :    ~Searcher();
     226              :    // non copyable
     227              :    Searcher(const Searcher&) = delete;
     228              :    Searcher(const Searcher&&) = delete;
     229              :    Searcher& operator=(const Searcher&) = delete;
     230              :    Searcher& operator=(const Searcher&&) = delete;
     231              : 
     232              :    void                            setData(const ThreadData& d);
     233              :    [[nodiscard]] const ThreadData& getData() const;
     234              :    [[nodiscard]] ThreadData&       getData();
     235              :    [[nodiscard]] const SearchData& getSearchData() const;
     236              :    [[nodiscard]] SearchData&       getSearchData();
     237              : 
     238              :    static std::atomic<bool> startLock;
     239              : 
     240              :    std::chrono::time_point<Clock> startTime;
     241              : 
     242              :    [[nodiscard]] bool searching() const;
     243              : 
     244              :    void clearGame();
     245              :    
     246              :    void clearSearch(bool forceHistoryClear = false);
     247              : 
     248      3014656 :    struct PawnEntry {
     249              :       colored<BitBoard>  pawnTargets   = {emptyBitBoard, emptyBitBoard};
     250              :       colored<BitBoard>  holes         = {emptyBitBoard, emptyBitBoard};
     251              :       colored<BitBoard>  semiOpenFiles = {emptyBitBoard, emptyBitBoard};
     252              :       colored<BitBoard>  passed        = {emptyBitBoard, emptyBitBoard};
     253              :       BitBoard           openFiles     = emptyBitBoard;
     254              :       EvalScore          score         = {0, 0};
     255              :       MiniHash           h             = nullHash;
     256              :       colored<ScoreType> danger        = {0, 0};
     257              : 
     258              :       FORCE_FINLINE void reset() {
     259       148754 :          score            = {0, 0};
     260       148754 :          danger[Co_White] = 0;
     261       148754 :          danger[Co_Black] = 0;
     262              :       }
     263              :    };
     264              : 
     265              :    std::unique_ptr<Searcher::PawnEntry[]> tablePawn = nullptr;
     266              :    uint64_t ttSizePawn = 0;
     267              : 
     268              :    void initPawnTable();
     269              : 
     270              :    void clearPawnTT();
     271              : 
     272              :    [[nodiscard]] bool getPawnEntry(Hash h, PawnEntry*& pe);
     273              : 
     274              :    void prefetchPawn(Hash h);
     275              : 
     276              :   private:
     277              :    ThreadData              _data;
     278              :    std::mutex              _mutexPV;
     279              :    size_t                  _index;
     280              :    std::mutex              _mutex;
     281              :    std::condition_variable _cv;
     282              :    // next two MUST be initialized BEFORE _stdThread
     283              :    bool        _exit;
     284              :    bool        _searching;
     285              :    std::thread _stdThread;
     286              : };
     287              : 
     288              : #include "searcherDraw.hpp"
     289              : #include "searcherPVS.hpp"
        

Generated by: LCOV version 2.0-1