LCOV - code coverage report
Current view: top level - Source - tools.cpp (source / functions) Coverage Total Hit
Test: coverage Lines: 40.3 % 154 62
Test Date: 2026-03-02 16:42:41 Functions: 53.8 % 13 7

            Line data    Source code
       1              : #include "tools.hpp"
       2              : 
       3              : #include "dynamicConfig.hpp"
       4              : #include "evalDef.hpp"
       5              : #include "hash.hpp"
       6              : #include "logging.hpp"
       7              : #include "moveApply.hpp"
       8              : #include "pieceTools.hpp"
       9              : #include "position.hpp"
      10              : #include "positionTools.hpp"
      11              : #include "searcher.hpp"
      12              : #include "score.hpp"
      13              : #include "threading.hpp"
      14              : 
      15           19 : std::string trim(const std::string& str, const std::string& whitespace) {
      16              :    const auto strBegin = str.find_first_not_of(whitespace);
      17           19 :    if (strBegin == std::string::npos) return ""; // no content
      18              :    const auto strEnd   = str.find_last_not_of(whitespace);
      19           19 :    const auto strRange = strEnd - strBegin + 1;
      20           19 :    return str.substr(strBegin, strRange);
      21              : }
      22              : 
      23            1 : void tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters) {
      24              :    std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
      25              :    std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
      26            3 :    while (std::string::npos != pos || std::string::npos != lastPos) {
      27            4 :       tokens.push_back(str.substr(lastPos, pos - lastPos));
      28              :       lastPos = str.find_first_not_of(delimiters, pos);
      29              :       pos     = str.find_first_of(delimiters, lastPos);
      30              :    }
      31            1 : }
      32              : 
      33            0 : std::vector<std::string> tokenize(const std::string& str, const std::string& delimiters) {
      34            0 :    std::vector<std::string> tokens;
      35            0 :    tokenize(str,tokens,delimiters);
      36            0 :    return tokens;
      37            0 : }
      38              : 
      39              : #ifdef DEBUG_KING_CAP
      40              : void debug_king_cap(const Position& p) {
      41              :    if (!p.whiteKing() || !p.blackKing()) {
      42              :       std::cout << "no more king" << std::endl;
      43              :       std::cout << ToString(p) << std::endl;
      44              :       std::cout << ToString(p.lastMove) << std::endl;
      45              :       Distributed::finalize();
      46              :       exit(1);
      47              :    }
      48              : }
      49              : #else
      50      8064674 : void debug_king_cap(const Position&) { ; }
      51              : #endif
      52              : 
      53            0 : std::string ToString(const MiniMove& m) { return ToString(static_cast<Move>(m), false); }
      54              : 
      55         5398 : std::string ToString(const Move& m, bool withScore) {
      56         5398 :    if (sameMove(m, INVALIDMOVE)) return "invalid move"; ///@todo 0000 ?
      57         5382 :    if (sameMove(m, NULLMOVE)) return "null move"; ///@todo 0000 ?
      58              : 
      59         5422 :    const std::string score = (withScore ? " (" + std::to_string(Move2Score(m)) + ")" : "");
      60              :    // FRC castling is encoded king takes rook
      61              :    // standard chess castling is encoded with Smith notation
      62         5382 :    if (!DynamicConfig::FRC) { 
      63        10750 :       switch (Move2Type(m)) {
      64           10 :          case T_bks: return "e8g8" + score;
      65           18 :          case T_wks: return "e1g1" + score;
      66            0 :          case T_bqs: return "e8c8" + score;
      67            0 :          case T_wqs: return "e1c1" + score;
      68              :          default:
      69              :          break;
      70              :       }
      71              :    }
      72              :    static constexpr array1d<std::string_view,T_max> promSuffixe = {"", "", "", "", "q", "r", "b", "n", "q", "r", "b", "n", "", "", "", ""};
      73        10708 :    const std::string_view & prom = promSuffixe[Move2Type(m)];
      74              :    ///@todo remove string CTOR here in C++26 ;-)
      75        21416 :    return std::string(SquareNames[Move2From(m)]) + std::string(SquareNames[Move2To(m)]) + std::string(prom) + score; 
      76              : }
      77              : 
      78          475 : std::string ToString(const PVList& moves) {
      79          475 :    std::stringstream ss;
      80         4594 :    for (const auto &m : moves) {
      81         4119 :       if (m == INVALIDMOVE) break;
      82        12357 :       ss << ToString(m) << " ";
      83              :    }
      84          475 :    return ss.str();
      85          475 : }
      86              : 
      87            0 : std::string ToString(const Position::Material& mat) {
      88            0 :    std::stringstream str;
      89              :    str << "\n"
      90            0 :        << Logging::_protocolComment[Logging::ct] << "K  :" << static_cast<int>(mat[Co_White][M_k]) << "\n"
      91            0 :        << Logging::_protocolComment[Logging::ct] << "Q  :" << static_cast<int>(mat[Co_White][M_q]) << "\n"
      92            0 :        << Logging::_protocolComment[Logging::ct] << "R  :" << static_cast<int>(mat[Co_White][M_r]) << "\n"
      93            0 :        << Logging::_protocolComment[Logging::ct] << "B  :" << static_cast<int>(mat[Co_White][M_b]) << "\n"
      94            0 :        << Logging::_protocolComment[Logging::ct] << "L  :" << static_cast<int>(mat[Co_White][M_bl]) << "\n"
      95            0 :        << Logging::_protocolComment[Logging::ct] << "D  :" << static_cast<int>(mat[Co_White][M_bd]) << "\n"
      96            0 :        << Logging::_protocolComment[Logging::ct] << "N  :" << static_cast<int>(mat[Co_White][M_n]) << "\n"
      97            0 :        << Logging::_protocolComment[Logging::ct] << "P  :" << static_cast<int>(mat[Co_White][M_p]) << "\n"
      98            0 :        << Logging::_protocolComment[Logging::ct] << "Ma :" << static_cast<int>(mat[Co_White][M_M]) << "\n"
      99            0 :        << Logging::_protocolComment[Logging::ct] << "Mi :" << static_cast<int>(mat[Co_White][M_m]) << "\n"
     100            0 :        << Logging::_protocolComment[Logging::ct] << "T  :" << static_cast<int>(mat[Co_White][M_t]) << "\n";
     101              :    str << "\n"
     102            0 :        << Logging::_protocolComment[Logging::ct] << "k  :" << static_cast<int>(mat[Co_Black][M_k]) << "\n"
     103            0 :        << Logging::_protocolComment[Logging::ct] << "q  :" << static_cast<int>(mat[Co_Black][M_q]) << "\n"
     104            0 :        << Logging::_protocolComment[Logging::ct] << "r  :" << static_cast<int>(mat[Co_Black][M_r]) << "\n"
     105            0 :        << Logging::_protocolComment[Logging::ct] << "b  :" << static_cast<int>(mat[Co_Black][M_b]) << "\n"
     106            0 :        << Logging::_protocolComment[Logging::ct] << "l  :" << static_cast<int>(mat[Co_Black][M_bl]) << "\n"
     107            0 :        << Logging::_protocolComment[Logging::ct] << "d  :" << static_cast<int>(mat[Co_Black][M_bd]) << "\n"
     108            0 :        << Logging::_protocolComment[Logging::ct] << "n  :" << static_cast<int>(mat[Co_Black][M_n]) << "\n"
     109            0 :        << Logging::_protocolComment[Logging::ct] << "p  :" << static_cast<int>(mat[Co_Black][M_p]) << "\n"
     110            0 :        << Logging::_protocolComment[Logging::ct] << "ma :" << static_cast<int>(mat[Co_Black][M_M]) << "\n"
     111            0 :        << Logging::_protocolComment[Logging::ct] << "mi :" << static_cast<int>(mat[Co_Black][M_m]) << "\n"
     112            0 :        << Logging::_protocolComment[Logging::ct] << "t  :" << static_cast<int>(mat[Co_Black][M_t]) << "\n";
     113            0 :    return str.str();
     114            0 : }
     115              : 
     116          442 : std::string ToString(const Position& p, bool noEval) {
     117          442 :    std::stringstream ss;
     118              :    ss << "Position" << std::endl;
     119         3978 :    for (Square j = 7; j >= 0; --j) {
     120         3536 :       ss << Logging::_protocolComment[Logging::ct] << " +-+-+-+-+-+-+-+-+" << std::endl;
     121         3536 :       ss << Logging::_protocolComment[Logging::ct] << " |";
     122        31824 :       for (Square i = 0; i < 8; ++i) ss << PieceTools::getName/*UTF*/(p, static_cast<Square>(i + j * 8)) << '|';
     123              :       ss << std::endl;
     124              :    }
     125          442 :    ss << Logging::_protocolComment[Logging::ct] << " +-+-+-+-+-+-+-+-+" << std::endl;
     126          442 :    if (p.ep >= 0) ss << Logging::_protocolComment[Logging::ct] << " ep " << SquareNames[p.ep] << std::endl;
     127              :    //ss << Logging::_protocolComment[Logging::ct] << " wk " << (p.king[Co_White]!=INVALIDSQUARE?SquareNames[p.king[Co_White]]:"none") << std::endl;
     128              :    //ss << Logging::_protocolComment[Logging::ct] << " bk " << (p.king[Co_Black]!=INVALIDSQUARE?SquareNames[p.king[Co_Black]]:"none") << std::endl;
     129         1094 :    ss << Logging::_protocolComment[Logging::ct] << " Turn " << (p.c == Co_White ? "white" : "black") << std::endl;
     130              :    ScoreType sc = 0;
     131          442 :    if (!noEval) {
     132          442 :       EvalData data;
     133              : #ifdef WITH_NNUE
     134          442 :       NNUEEvaluator evaluator;
     135          442 :       if (!p.associatedEvaluator) {
     136            0 :          p.associatedEvaluator = &evaluator;
     137            0 :          p.resetNNUEEvaluator(evaluator);
     138              :       }
     139              : #endif
     140          442 :       const bool tmp = DynamicConfig::forceNNUE;
     141          442 :       if (DynamicConfig::useNNUE) DynamicConfig::forceNNUE = true;
     142          442 :       sc = eval(p, data, ThreadPool::instance().main(), true);
     143          442 :       if (DynamicConfig::useNNUE) DynamicConfig::forceNNUE = tmp;
     144          884 :       ss << Logging::_protocolComment[Logging::ct] << " Phase " << data.gp << std::endl;
     145          884 :       ss << Logging::_protocolComment[Logging::ct] << " Static score " << sc << std::endl;
     146          884 :       ss << Logging::_protocolComment[Logging::ct] << " Hash " << computeHash(p) << std::endl;
     147              :    }
     148         1326 :    ss << Logging::_protocolComment[Logging::ct] << " FEN " << GetFEN(p);
     149              :    //ss << ToString(p.mat);
     150          442 :    return ss.str();
     151          442 : }
     152              : 
     153            2 : std::string ToString(const BitBoard& b) {
     154            2 :    std::bitset<64> bs(b);
     155            2 :    std::stringstream ss;
     156           18 :    for (int j = 7; j >= 0; --j) {
     157           16 :       ss << "\n";
     158           16 :       ss << Logging::_protocolComment[Logging::ct] << "+-+-+-+-+-+-+-+-+"
     159           16 :          << "\n";
     160           16 :       ss << Logging::_protocolComment[Logging::ct] << "|";
     161          144 :       for (int i = 0; i < 8; ++i) ss << (bs[i + j * 8] ? "X" : " ") << '|';
     162              :    }
     163            2 :    ss << "\n";
     164            2 :    ss << Logging::_protocolComment[Logging::ct] << "+-+-+-+-+-+-+-+-+";
     165            2 :    return ss.str();
     166            2 : }
     167              : 
     168            0 : bool checkEval(const Position & p, ScoreType e, Searcher & context, const std::string & txt){
     169            0 :    EvalData data;
     170            0 :    const ScoreType f = eval(p, data, context, true, true);
     171              : #ifdef DEBUG_EVALSYM
     172              :    Position p2 = p;
     173              :    p2.c = ~p2.c;
     174              :    const ScoreType g = eval(p2, data, context, true, false);
     175              :    if ( Abs(f + g - 2*EvalConfig::tempo) > 2){
     176              :       std::cout << "*********************" << std::endl;
     177              :       std::cout << ToString(p) << std::endl;
     178              :       std::cout << f << std::endl;
     179              :       std::cout << g - 2*EvalConfig::tempo << std::endl;
     180              :       std::cout << "EVALSYMERROR" << std::endl;
     181              :    }
     182              : #endif
     183            0 :    if ( Abs(e - f) > std::max(Abs(e)/20,10)){
     184              :       std::cout << "*********************" << std::endl;
     185            0 :       std::cout << ToString(p) << std::endl;
     186            0 :       std::cout << e << std::endl;
     187            0 :       std::cout << f << std::endl;
     188              :       std::cout << "EVALERROR : " << txt << std::endl;
     189            0 :       return false;
     190              :    }
     191              :    else {
     192              :       std::cout << "EVALOK : " << txt << std::endl;
     193            0 :       return true;
     194              :    }
     195              : }
     196              : 
     197              : namespace {
     198            0 : uint64_t numberOf(const Position &p, Piece t) { return BB::countBit(p.pieces_const(t)); }
     199              : } // namespace
     200              : 
     201            0 : std::string showAlgAbr(const Move m, const Position &p) {
     202            0 :    const Square from  = Move2From(m);
     203            0 :    const Square to    = Move2To(m);
     204              :    const MType  mtype = Move2Type(m);
     205              :    if (m == INVALIDMOVE) return "xx";
     206              : 
     207              :    bool     isCheck    = false;
     208              :    bool     isNotLegal = false;
     209            0 :    Position p2         = p;
     210              : #ifdef WITH_NNUE
     211            0 :    NNUEEvaluator evaluator = p.evaluator();
     212              :    p2.associateEvaluator(evaluator);
     213              : #endif
     214            0 :    if (const MoveInfo moveInfo(p2,m); applyMove(p2, moveInfo)) {
     215            0 :       if (isPosInCheck(p2)) isCheck = true;
     216              :    }
     217              :    else {
     218              :       isNotLegal = true;
     219              :    }
     220              : 
     221            0 :    if (mtype == T_wks || mtype == T_bks) return std::string("0-0") + (isCheck ? "+" : "") + (isNotLegal ? "~" : "");
     222            0 :    if (mtype == T_wqs || mtype == T_bqs) return std::string("0-0-0") + (isCheck ? "+" : "") + (isNotLegal ? "~" : "");
     223              : 
     224              :    std::string s;
     225            0 :    Piece t = p.board_const(from);
     226              : 
     227              :    // add piece type if not pawn
     228            0 :    s += PieceNames[PieceIdx(static_cast<Piece>(Abs(t)))];
     229            0 :    if (t == P_wp || t == P_bp) s.clear(); // no piece symbol for pawn
     230              : 
     231              :    // ensure move is not ambiguous
     232              :    bool isSamePiece = false;
     233              :    bool isSameFile  = false;
     234              :    bool isSameRank  = false;
     235            0 :    if (numberOf(p, t) > 1) {
     236            0 :       std::vector<Square> v;
     237            0 :       BitBoard b = p.pieces_const(t);
     238            0 :       while (b) v.emplace_back(BB::popBit(b));
     239            0 :       for (const auto & sq : v) {
     240            0 :          if (sq == from) continue; // to not compare to myself ...
     241            0 :          MoveList l;
     242            0 :          MoveGen::generateSquare<MoveGen::GP_all>(p, l, sq);
     243            0 :          for (const auto & m2 : l) {
     244            0 :             if (m2 == m) continue; // to not compare to myself ... should no happend thanks to previous verification
     245            0 :             Position p3 = p;
     246            0 :             const MoveInfo moveInfo2(p3, m2);
     247            0 :             if (applyMove(p3, moveInfo2)) { // only if move is legal
     248            0 :                if (Move2To(m2) == to &&
     249            0 :                    (t == p.board_const(Move2From(m2)))) { // another move is landing on the same square with the same piece type
     250              :                   isSamePiece = true;
     251            0 :                   if (SQFILE(Move2From(m2)) == SQFILE(from)) { isSameFile = true; }
     252            0 :                   if (SQRANK(Move2From(m2)) == SQRANK(from)) { isSameRank = true; }
     253              :                }
     254              :             }
     255            0 :          }
     256              :       }
     257            0 :    }
     258              : 
     259            0 :    if ((t == P_wp || t == P_bp) && isCapture(m)) s += FileNames[SQFILE(from)];
     260            0 :    else if (isSamePiece) {
     261            0 :       if (!isSameFile) s += FileNames[SQFILE(from)];
     262            0 :       else if (isSameFile && !isSameRank)
     263            0 :          s += RankNames[SQRANK(from)];
     264              :       else if (isSameFile && isSameRank) {
     265            0 :          s += FileNames[SQFILE(from)];
     266            0 :          s += RankNames[SQRANK(from)];
     267              :       }
     268              :    }
     269              : 
     270              :    // add 'x' if capture
     271            0 :    if (isCapture(m)) { s += "x"; }
     272              : 
     273              :    // add landing position
     274            0 :    s += SquareNames[to];
     275              : 
     276              :    // and promotion to
     277            0 :    if (isPromotion(m)) {
     278            0 :       switch (mtype) {
     279              :          case T_cappromq:
     280              :          case T_promq:
     281              :             s += "=";
     282              :             s += "Q";
     283              :             break;
     284              :          case T_cappromr:
     285              :          case T_promr:
     286              :             s += "=";
     287              :             s += "R";
     288              :             break;
     289              :          case T_cappromb:
     290              :          case T_promb:
     291              :             s += "=";
     292              :             s += "B";
     293              :             break;
     294              :          case T_cappromn:
     295              :          case T_promn:
     296              :             s += "=";
     297              :             s += "N";
     298              :             break;
     299              :          default: break;
     300              :       }
     301              :    }
     302              : 
     303            0 :    if (isCheck) s += "+";
     304            0 :    if (isNotLegal) s += "~";
     305              : 
     306            0 :    return s;
     307            0 : }
        

Generated by: LCOV version 2.0-1