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

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <algorithm>
       4              : #include <array>
       5              : #include <atomic>
       6              : #include <bitset>
       7              : #include <cassert>
       8              : #include <cctype>
       9              : #include <chrono>
      10              : #include <climits>
      11              : #include <cmath>
      12              : #include <condition_variable>
      13              : #include <cstdint>
      14              : #include <cstdlib>
      15              : #include <cstring>
      16              : #include <fstream>
      17              : #include <functional>
      18              : #include <future>
      19              : #include <iomanip>
      20              : #include <iostream>
      21              : #include <iterator>
      22              : #include <list>
      23              : #include <map>
      24              : #include <mutex>
      25              : #include <optional>
      26              : #include <random>
      27              : #include <regex>
      28              : #include <set>
      29              : #include <span>
      30              : #include <sstream>
      31              : #include <string>
      32              : #include <string_view>
      33              : #include <thread>
      34              : #include <type_traits>
      35              : #include <unordered_map>
      36              : #include <utility>
      37              : #include <vector>
      38              : #ifdef _WIN32
      39              : #include <intrin.h>
      40              : #include <process.h>
      41              : #include <stdlib.h>
      42              : typedef uint64_t u_int64_t;
      43              : #else
      44              : #include <unistd.h>
      45              : #endif
      46              : 
      47              : #include "config.hpp"
      48              : 
      49              : #ifdef WITH_FMTLIB
      50              : #include <fmt/color.h>
      51              : #endif
      52              : 
      53              : #ifdef WITH_EVAL_TUNING
      54              : #define CONST_EVAL_TUNING
      55              : #undef WITH_EVALSCORE_AS_INT
      56              : #else
      57              : #define CONST_EVAL_TUNING const
      58              : #endif
      59              : 
      60              : #ifdef WITH_SEARCH_TUNING
      61              : #define CONST_SEARCH_TUNING
      62              : #define CONSTEXPR_SEARCH_TUNING
      63              : #else
      64              : #define CONST_SEARCH_TUNING const
      65              : #define CONSTEXPR_SEARCH_TUNING constexpr
      66              : #endif
      67              : 
      68              : #ifdef WITH_PIECE_TUNING
      69              : #define CONST_PIECE_TUNING
      70              : #else
      71              : #define CONST_PIECE_TUNING const
      72              : #endif
      73              : 
      74              : inline constexpr size_t NNUEALIGNMENT = 64; // AVX512 compatible ...
      75              : inline constexpr auto NNUEALIGNMENT_STD = std::align_val_t{ NNUEALIGNMENT };
      76              : 
      77              : #ifdef __clang__
      78              : #define CONSTEXPR
      79              : #else
      80              : #define CONSTEXPR constexpr
      81              : #endif
      82              : 
      83              : #if _WIN32 || _WIN64
      84              :    #if _WIN64
      85              :      #define ENV64BIT
      86              :   #else
      87              :     #define ENV32BIT
      88              :   #endif
      89              : #endif
      90              : 
      91              : #if __GNUC__
      92              :   #if __x86_64__ || __ppc64__
      93              :     #define ENV64BIT
      94              :   #else
      95              :     #define ENV32BIT
      96              :   #endif
      97              : #endif
      98              : 
      99              : #ifdef _MSC_VER
     100              : #pragma warning(disable:4996)
     101              : #pragma warning(disable:4068)
     102              : #endif
     103              : 
     104              : #if !defined(__PRETTY_FUNCTION__) && !defined(__GNUC__)
     105              : #define __PRETTY_FUNCTION__ __FUNCSIG__
     106              : #endif
     107              : 
     108              : #if defined(WITH_SMALL_MEMORY)
     109              : constexpr size_t SIZE_MULTIPLIER = 1024ull; // Kb
     110              : #else
     111              : constexpr size_t SIZE_MULTIPLIER = 1024ull * 1024ull; // Mb
     112              : #endif
     113              : 
     114              : #if defined(_MSC_VER)
     115              : #define FORCE_INLINE __inline
     116              : #elif defined(__GNUC__)
     117              : #if defined(__STRICT_ANSI__)
     118              : #define FORCE_INLINE __inline__
     119              : #else
     120              : #define FORCE_INLINE inline
     121              : #endif
     122              : #else
     123              : #define FORCE_INLINE
     124              : #endif
     125              : 
     126              : #ifdef _MSC_VER
     127              : #define FORCE_FINLINE __forceinline
     128              : #define RESTRICT __restrict
     129              : #elif defined(__GNUC__)
     130              : #define FORCE_FINLINE FORCE_INLINE __attribute__((always_inline))
     131              : #define RESTRICT __restrict__
     132              : #else
     133              : #define FORCE_FINLINE 
     134              : #endif
     135              : 
     136   1936513225 : template<typename T> [[nodiscard]] constexpr inline T Abs(const T& s) { 
     137              :    static_assert(T(-1) < T(0));
     138              :    if constexpr (std::is_enum_v<T>){
     139   1075626717 :       assert(s != std::numeric_limits<std::underlying_type_t<T>>::min());
     140              :    }
     141              :    else{
     142    860886508 :       assert(s != std::numeric_limits<T>::min());
     143              :    }
     144   2137275923 :    const T ret = s >= T(0) ? s : T(-s);
     145   1936513225 :    assert(ret == std::abs(s));
     146   1936513225 :    return ret;
     147              : }
     148              : 
     149              : #define ENABLE_INCR_OPERATORS_ON(T) \
     150              : constexpr T& operator++(T& d) { return d = static_cast<T>(static_cast<std::underlying_type_t<T>>(d) + 1); } \
     151              : constexpr T& operator--(T& d) { return d = static_cast<T>(static_cast<std::underlying_type_t<T>>(d) - 1); }
     152              : 
     153              : using Clock          = std::chrono::system_clock;
     154              : using DepthType      = int8_t;
     155              : using Move           = int32_t;  // invalid if < 0
     156              : using MiniMove       = int16_t;  // invalid if < 0
     157              : using Square         = int8_t;   // invalid if < 0, MUST be signed because also used as negative delta sometimes (like in computeAttacks)
     158              : using Hash           = uint64_t; // invalid if == nullHash
     159              : using MiniHash       = uint32_t; // invalid if == 0
     160              : using Counter        = uint64_t;
     161              : using BitBoard       = uint64_t;
     162              : using ScoreType      = int16_t;
     163              : using TimeType       = int64_t;
     164              : using GenerationType = uint8_t;
     165              : 
     166              : enum File : uint8_t { File_a = 0, File_b, File_c, File_d, File_e, File_f, File_g, File_h };
     167            0 : ENABLE_INCR_OPERATORS_ON(File)
     168              : 
     169              : enum Rank : uint8_t { Rank_1 = 0, Rank_2, Rank_3, Rank_4, Rank_5, Rank_6, Rank_7, Rank_8 };
     170       892524 : ENABLE_INCR_OPERATORS_ON(Rank)
     171              : 
     172              : enum Sq : uint8_t { Sq_a1  = 0,Sq_b1,Sq_c1,Sq_d1,Sq_e1,Sq_f1,Sq_g1,Sq_h1,
     173              :                     Sq_a2,Sq_b2,Sq_c2,Sq_d2,Sq_e2,Sq_f2,Sq_g2,Sq_h2,
     174              :                     Sq_a3,Sq_b3,Sq_c3,Sq_d3,Sq_e3,Sq_f3,Sq_g3,Sq_h3,
     175              :                     Sq_a4,Sq_b4,Sq_c4,Sq_d4,Sq_e4,Sq_f4,Sq_g4,Sq_h4,
     176              :                     Sq_a5,Sq_b5,Sq_c5,Sq_d5,Sq_e5,Sq_f5,Sq_g5,Sq_h5,
     177              :                     Sq_a6,Sq_b6,Sq_c6,Sq_d6,Sq_e6,Sq_f6,Sq_g6,Sq_h6,
     178              :                     Sq_a7,Sq_b7,Sq_c7,Sq_d7,Sq_e7,Sq_f7,Sq_g7,Sq_h7,
     179              :                     Sq_a8,Sq_b8,Sq_c8,Sq_d8,Sq_e8,Sq_f8,Sq_g8,Sq_h8};
     180              : 
     181              : template<typename T, int N>
     182              : using array1d = std::array<T,N>;
     183              : 
     184              : template<typename T, int N, int M>
     185              : using array2d = array1d<array1d<T,M>,N>;
     186              : 
     187              : template<typename T, int N, int M, int L>
     188              : using array3d = array1d<array1d<array1d<T,L>,M>,N>;
     189              : 
     190              : template<typename T>
     191              : using colored = array1d<T,2>;
     192              : 
     193              : inline constexpr array1d<Rank,2> PromRank = {Rank_8, Rank_1};
     194              : inline constexpr array1d<Rank,2> EPRank   = {Rank_6, Rank_3};
     195              : 
     196              : inline constexpr Hash nullHash          = 0ull; //std::numeric_limits<MiniHash>::max(); // use MiniHash to allow same "null" value for Hash(64) and MiniHash(32)
     197              : inline constexpr BitBoard emptyBitBoard = 0ull;
     198              : inline constexpr auto INFINITETIME      = static_cast<TimeType>(60ull * 60ull * 1000ull * 24ull * 30ull); // 1 month ...
     199              : inline constexpr auto STOPSCORE         = static_cast<ScoreType>(-20000);
     200              : inline constexpr auto INFSCORE          = static_cast<ScoreType>(15000);
     201              : inline constexpr auto MATE              = static_cast<ScoreType>(10000);
     202              : inline constexpr auto WIN               = static_cast<ScoreType>(3000);
     203              : inline constexpr auto INVALIDMOVE       = static_cast<int32_t>(0xFFFF0002);
     204              : inline constexpr auto INVALIDMINIMOVE   = static_cast<int16_t>(0x0002);
     205              : inline constexpr auto NULLMOVE          = static_cast<int16_t>(0x1112);
     206              : 
     207              : inline constexpr Square INVALIDSQUARE   = -1;
     208              : inline constexpr uint16_t MAX_PLY       = 2048; // same type as Position::halfmoves
     209              : inline constexpr int MAX_MOVE           = 256; // 256 is enough I guess/hope ...
     210              : inline constexpr auto MAX_DEPTH         = static_cast<DepthType>(127); // if DepthType is a char, !!!do not go above 127!!!
     211              : inline constexpr auto HISTORY_POWER     = 10;
     212              : inline constexpr ScoreType HISTORY_MAX  = (1 << HISTORY_POWER);
     213              : inline constexpr size_t MAX_THREADS     = 1024; // same type as Searcher::id()
     214              : 
     215              : constexpr ScoreType HISTORY_DIV(const int x) {
     216      3598807 :    const int ret = x >> HISTORY_POWER;
     217      2484635 :    assert (Abs(ret) < std::numeric_limits<ScoreType>::max());
     218              :    return ret;
     219              : }
     220      1147496 : constexpr ScoreType SQR(const ScoreType x)        { return x * x;}
     221      1147496 : constexpr ScoreType HSCORE(const DepthType depth) {
     222      1147496 :    const int ret = SQR(std::min(static_cast<int>(depth), 32)) * 4;
     223      1147496 :    assert (ret < std::numeric_limits<ScoreType>::max());
     224      1147496 :    return static_cast<ScoreType>(ret);}
     225              : 
     226              : enum Color : uint8_t { Co_White = 0, Co_Black = 1, Co_None = 2, Co_End = Co_None };
     227   2788290872 : [[nodiscard]] constexpr Color operator~(Color c) { return static_cast<Color>(c ^ Co_Black); } // switch Color
     228      6328278 : ENABLE_INCR_OPERATORS_ON(Color)
     229              : 
     230      5873305 : constexpr auto SQFILE(const Square s)                          { return static_cast<File>(s & 7);}
     231     17164827 : constexpr auto SQRANK(const Square s)                          { return static_cast<Rank>(s >> 3);}
     232        22176 : constexpr auto ISOUTERFILE(const Square x)                     { return (SQFILE(x) == 0 || SQFILE(x) == 7);}
     233    113000448 : constexpr auto ISNEIGHBOUR(const Square x, const Square y)     { return (x >= 0 && x < 64 && y >= 0 && y < 64 && Abs(SQRANK(x) - SQRANK(y)) <= 1 && Abs(SQFILE(x) - SQFILE(y)) <= 1);}
     234      5810116 : constexpr auto PROMOTION_RANK(const Square x)                  { return (SQRANK(x) == 0 || SQRANK(x) == 7);}
     235              : constexpr auto PROMOTION_RANK_C(const Square x, const Square c){ return ((c == Co_Black && SQRANK(x) == 0) || (c == Co_White && SQRANK(x) == 7));}
     236      4325376 : constexpr auto MakeSquare(const File f, const Rank r)          { return static_cast<Square>((r << 3) + f);}
     237            0 : constexpr auto VFlip(const Square s)                           { return static_cast<Square>(s ^ Sq_a8);}
     238    860236920 : constexpr auto HFlip(const Square s)                           { return static_cast<Square>(s ^ Sq_h1);}
     239              : constexpr auto MFlip(const Square s)                           { return static_cast<Square>(s ^ Sq_h8);}
     240              : 
     241              : #define TO_STR2(x)                 #x
     242              : #define TO_STR(x)                  TO_STR2(x)
     243              : #define LINE_NAME(prefix, suffix)  JOIN(JOIN(prefix, __LINE__), suffix)
     244              : #define JOIN(symbol1, symbol2)     _DO_JOIN(symbol1, symbol2)
     245              : #define _DO_JOIN(symbol1, symbol2) symbol1##symbol2
     246              : 
     247              : #define DISCARD [[maybe_unused]] const auto LINE_NAME(_tmp,_) =
     248              : 
     249              : #ifdef _WIN32
     250              : #define GETPID _getpid
     251              : #else
     252              : #define GETPID ::getpid
     253              : #endif
     254              : 
     255              : template<typename T>
     256              : [[nodiscard]] FORCE_FINLINE
     257              : T asLeastOne(const T &t){
     258         7278 :    return std::max(static_cast<std::remove_const_t<decltype(t)>>(1), t);
     259              : }
     260              : 
     261              : [[nodiscard]] FORCE_FINLINE
     262              : TimeType getTimeDiff(const Clock::time_point & reference){
     263         6441 :    const auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - reference).count();
     264              :    return static_cast<TimeType>(asLeastOne(diff));
     265              : }
     266              : 
     267              : [[nodiscard]] FORCE_FINLINE
     268              : TimeType getTimeDiff(const Clock::time_point & current, const Clock::time_point & reference){
     269          307 :    const auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(current - reference).count();
     270              :    return static_cast<TimeType>(asLeastOne(diff));
     271              : }
     272              : 
     273              : [[nodiscard]] FORCE_FINLINE double msec2sec(TimeType periodInMsec){
     274              :    using fpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>;
     275              :    using fpSeconds = std::chrono::duration<float, std::chrono::seconds::period>;
     276          274 :    return fpSeconds(fpMilliseconds(periodInMsec)).count();
     277              : }
     278              : 
     279              : template<typename OT, typename IT>
     280              : [[nodiscard]] FORCE_FINLINE
     281              : OT clampInt(IT t){
     282            3 :    return static_cast<OT>(std::min(std::numeric_limits<IT>::max(), std::max(std::numeric_limits<IT>::min(), t)));
     283              : }
     284              : 
     285              : template<typename OT, typename IT>
     286              : [[nodiscard]] FORCE_FINLINE
     287              : OT clampIntU(IT t){
     288           15 :    return static_cast<OT>(std::min(std::numeric_limits<IT>::max(), std::max(0, t)));
     289              : }
     290              : 
     291              : template<typename T>
     292              : [[nodiscard]] FORCE_FINLINE
     293              : DepthType clampDepth(const T & d){
     294           15 :    return static_cast<DepthType>(std::max(static_cast<T>(0), std::min(static_cast<T>(MAX_DEPTH),d)));
     295              : }
     296              : 
     297              : template<typename T>
     298              : [[nodiscard]] constexpr ScoreType clampScore(T s) {
     299      5848896 :    return static_cast<ScoreType>(std::clamp(s, (T)(-MATE + 2 * MAX_DEPTH), (T)(MATE - 2 * MAX_DEPTH)));
     300              : }
     301              : 
     302              : enum GamePhase { MG = 0, EG = 1, GP_MAX = 2 };
     303  28603116924 : ENABLE_INCR_OPERATORS_ON(GamePhase)
     304              : 
     305     11955124 : template<typename T, int SIZE> struct OptList : public std::vector<T> {
     306     11955124 :    OptList(): std::vector<T>() { std::vector<T>::reserve(SIZE); }
     307              : };
     308              : using MoveList = OptList<Move, MAX_MOVE / 4>; ///@todo tune this ?
     309              : using PVList = std::vector<Move>;
     310              : 
     311     10573614 : [[nodiscard]] constexpr MiniHash Hash64to32(Hash h) { return static_cast<MiniHash>((h >> 32) & 0xFFFFFFFF); }
     312    927449034 : [[nodiscard]] constexpr MiniMove Move2MiniMove(Move m) { return static_cast<MiniMove>(m & 0xFFFF); } // skip score
     313              : 
     314              : // sameMove is not comparing score part of the Move, only the MiniMove part !
     315     58075372 : [[nodiscard]] constexpr bool sameMove(const Move& a, const Move& b) { return Move2MiniMove(a) == Move2MiniMove(b); }
     316    213087129 : [[nodiscard]] constexpr bool sameMove(const Move& a, const MiniMove& b) { return Move2MiniMove(a) == b; }
     317              : 
     318   1457223021 : [[nodiscard]] constexpr bool isValidMove(const Move& m) { return !sameMove(m, NULLMOVE) && !sameMove(m, INVALIDMOVE); }
     319     36487079 : [[nodiscard]] constexpr bool isValidMove(const MiniMove& m) { return m != INVALIDMINIMOVE && m != NULLMOVE; }
     320              : 
     321              : inline constexpr std::string_view startPosition = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
     322              : inline constexpr std::string_view fine70        = "8/k7/3p4/p2P1p2/P2P1P2/8/8/K7 w - - 0 1";
     323              : inline constexpr std::string_view shirov        = "6r1/2rp1kpp/2qQp3/p3Pp1P/1pP2P2/1P2KP2/P5R1/6R1 w - - 0 1";
     324              : inline constexpr std::string_view shirov2       = "8/2rp1krp/2qQp3/p3Pp1P/1pP2P2/1P2KP2/P7/6R1 w - - 0 2";
     325              : inline constexpr std::string_view mate4         = "r1bnk2r/pppp1ppp/1b4q1/4P3/2B1N3/Q1Pp1N2/P4PPP/R3R1K1 w - - 1 1";
     326              : 
     327              : enum Piece : signed char {
     328              :    P_bk   = -6,
     329              :    P_bq   = -5,
     330              :    P_br   = -4,
     331              :    P_bb   = -3,
     332              :    P_bn   = -2,
     333              :    P_bp   = -1,
     334              :    P_none = 0,
     335              :    P_wp   = 1,
     336              :    P_wn   = 2,
     337              :    P_wb   = 3,
     338              :    P_wr   = 4,
     339              :    P_wq   = 5,
     340              :    P_wk   = 6,
     341              :    P_end
     342              : };
     343     53015896 : ENABLE_INCR_OPERATORS_ON(Piece)
     344              : 
     345        80230 : constexpr Piece operator~(Piece pp) { return static_cast<Piece>(-pp); } // switch piece Color
     346              : constexpr int PieceShift = 6;
     347              : constexpr int NbPiece    = 2 * PieceShift + 1;
     348              : 
     349    591022153 : [[nodiscard]] constexpr int PieceIdx(Piece p) { return p + PieceShift; } ///@todo use it everywhere !
     350              : 
     351              : enum Mat : uint8_t { M_t = 0, M_p, M_n, M_b, M_r, M_q, M_k, M_bl, M_bd, M_M, M_m };
     352   3343826772 : ENABLE_INCR_OPERATORS_ON(Mat)
     353              : 
     354              : extern CONST_PIECE_TUNING array1d<ScoreType,NbPiece> Values;
     355              : extern CONST_PIECE_TUNING array1d<ScoreType,NbPiece> ValuesEG;
     356              : extern CONST_PIECE_TUNING array1d<ScoreType,NbPiece> ValuesGP;
     357              : extern CONST_PIECE_TUNING array1d<ScoreType,NbPiece> ValuesSEE;
     358              : 
     359         1667 : [[nodiscard]] FORCE_FINLINE ScoreType value(Piece pp)      { return Values[pp + PieceShift]; }
     360            3 : [[nodiscard]] FORCE_FINLINE ScoreType valueEG(Piece pp)    { return ValuesEG[pp + PieceShift]; }
     361              : [[nodiscard]] FORCE_FINLINE ScoreType valueGP(Piece pp)    { return ValuesGP[pp + PieceShift]; }
     362     10637631 : [[nodiscard]] FORCE_FINLINE ScoreType valueSEE(Piece pp)   { return ValuesSEE[pp + PieceShift]; }
     363              : 
     364              : #ifdef WITH_PIECE_TUNING
     365              : FORCE_FINLINE void SymetrizeValue() {
     366              :    for (Piece pp = P_wp; pp <= P_wk; ++pp) {
     367              :       Values[-pp + PieceShift]   = Values[pp + PieceShift];
     368              :       ValuesEG[-pp + PieceShift] = ValuesEG[pp + PieceShift];
     369              :       ValuesGP[-pp + PieceShift] = ValuesGP[pp + PieceShift];
     370              :       ValuesSEE[-pp + PieceShift] = ValuesSEE[pp + PieceShift];
     371              :     }
     372              : }
     373              : #endif
     374              : 
     375              : const ScoreType dummyScore = 0;
     376              : 
     377              : inline array1d<const ScoreType* const,7> absValues_    = {&dummyScore,
     378              :                                                           &Values[P_wp + PieceShift],
     379              :                                                           &Values[P_wn + PieceShift],
     380              :                                                           &Values[P_wb + PieceShift],
     381              :                                                           &Values[P_wr + PieceShift],
     382              :                                                           &Values[P_wq + PieceShift],
     383              :                                                           &Values[P_wk + PieceShift]};
     384              : 
     385              : inline array1d<const ScoreType* const,7> absValuesEG_    = {&dummyScore,
     386              :                                                             &ValuesEG[P_wp + PieceShift],
     387              :                                                             &ValuesEG[P_wn + PieceShift],
     388              :                                                             &ValuesEG[P_wb + PieceShift],
     389              :                                                             &ValuesEG[P_wr + PieceShift],
     390              :                                                             &ValuesEG[P_wq + PieceShift],
     391              :                                                             &ValuesEG[P_wk + PieceShift]};
     392              : 
     393              : inline array1d<const ScoreType* const,7> absValuesGP_    = {&dummyScore,
     394              :                                                             &ValuesGP[P_wp + PieceShift],
     395              :                                                             &ValuesGP[P_wn + PieceShift],
     396              :                                                             &ValuesGP[P_wb + PieceShift],
     397              :                                                             &ValuesGP[P_wr + PieceShift],
     398              :                                                             &ValuesGP[P_wq + PieceShift],
     399              :                                                             &ValuesGP[P_wk + PieceShift]};
     400              : 
     401              : inline array1d<const ScoreType* const,7> absValuesSEE_    = {&dummyScore,
     402              :                                                              &ValuesSEE[P_wp + PieceShift],
     403              :                                                              &ValuesSEE[P_wn + PieceShift],
     404              :                                                              &ValuesSEE[P_wb + PieceShift],
     405              :                                                              &ValuesSEE[P_wr + PieceShift],
     406              :                                                              &ValuesSEE[P_wq + PieceShift],
     407              :                                                              &ValuesSEE[P_wk + PieceShift]};
     408              : 
     409    105226167 : [[nodiscard]] FORCE_FINLINE ScoreType absValue(Piece pp)   { return *absValues_[pp]; }
     410    105226163 : [[nodiscard]] FORCE_FINLINE ScoreType absValueEG(Piece pp) { return *absValuesEG_[pp]; }
     411    105562816 : [[nodiscard]] FORCE_FINLINE ScoreType absValueGP(Piece pp) { return *absValuesGP_[pp]; }
     412              : [[nodiscard]] FORCE_FINLINE ScoreType absValueSEE(Piece pp){ return *absValuesSEE_[pp]; }
     413              : 
     414      5309420 : template<typename T> [[nodiscard]] constexpr int sgn(T val) { return (T(0) < val) - (val < T(0)); }
     415              : 
     416              : inline constexpr array1d<std::string_view,NbPiece> PieceNames = {"k", "q", "r", "b", "n", "p", " ", "P", "N", "B", "R", "Q", "K"};
     417              : inline constexpr array1d<std::string_view,NbPiece> PieceNamesUTF = {"♔", "♕", "♖", "♗", "♘", "♙", " ", "♟︎", "♞", "♝", "♜", "♛", "♚" };
     418              : 
     419              : inline constexpr Square NbSquare = 64;
     420              : 
     421              : inline constexpr array1d<std::string_view,NbSquare> SquareNames = { "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
     422              :                                                                     "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
     423              :                                                                     "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
     424              :                                                                     "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
     425              :                                                                     "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
     426              :                                                                     "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
     427              :                                                                     "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
     428              :                                                                     "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8" };
     429              : 
     430              : inline constexpr array1d<std::string_view,8> FileNames = {"a", "b", "c", "d", "e", "f", "g", "h"};
     431              : inline constexpr array1d<std::string_view,8> RankNames = {"1", "2", "3", "4", "5", "6", "7", "8"};
     432              : 
     433              : template<Color C> [[nodiscard]] constexpr ScoreType ColorSignHelper() { return C == Co_White ? +1 : -1; }
     434         4736 : template<Color C> [[nodiscard]] constexpr Square    PromotionSquare(const Square k) { return C == Co_White ? (SQFILE(k) + 56) : SQFILE(k); }
     435       542115 : template<Color C> [[nodiscard]] constexpr Rank      ColorRank(const Square k) { return Rank(C == Co_White ? SQRANK(k) : (7 - SQRANK(k))); }
     436              : 
     437              : enum CastlingTypes : uint8_t { CT_OOO = 0, CT_OO = 1 };
     438              : enum CastlingRights : uint8_t {
     439              :    C_none        = 0,
     440              :    C_wks         = 1,
     441              :    C_wqs         = 2,
     442              :    C_w_all       = 3,
     443              :    C_all_but_b   = 3,
     444              :    C_bks         = 4,
     445              :    C_all_but_bqs = 7,
     446              :    C_bqs         = 8,
     447              :    C_all_but_bks = 11,
     448              :    C_b_all       = 12,
     449              :    C_all_but_w   = 12,
     450              :    C_all_but_wqs = 13,
     451              :    C_all_but_wks = 14,
     452              :    C_all         = 15
     453              : };
     454     14456026 : constexpr CastlingRights operator&(const CastlingRights& a, const CastlingRights& b) { return CastlingRights(char(a) & char(b)); }
     455          263 : constexpr CastlingRights operator|(const CastlingRights& a, const CastlingRights& b) { return CastlingRights(char(a) | char(b)); }
     456              : constexpr CastlingRights operator~(const CastlingRights& a) { return CastlingRights(~char(a)); }
     457     10059028 : constexpr void           operator&=(CastlingRights& a, const CastlingRights& b) { a = a & b; }
     458          377 : constexpr void           operator|=(CastlingRights& a, const CastlingRights& b) { a = a | b; }
     459              : 
     460           18 : [[nodiscard]] FORCE_FINLINE Square stringToSquare(const std::string& str) { return static_cast<Square>((str.at(1) - 49) * 8 + (str.at(0) - 97)); }
     461              : 
     462              : enum MType : uint8_t {
     463              :    T_std      = 0,
     464              :    T_capture  = 1,
     465              :    T_reserved = 2,
     466              :    T_ep       = 3, // binary    0 to   11
     467              :    T_promq    = 4,
     468              :    T_promr    = 5,
     469              :    T_promb    = 6,
     470              :    T_promn    = 7, // binary  100 to  111
     471              :    T_cappromq = 8,
     472              :    T_cappromr = 9,
     473              :    T_cappromb = 10,
     474              :    T_cappromn = 11, // binary 1000 to 1011
     475              :    T_wks      = 12,
     476              :    T_wqs      = 13,
     477              :    T_bks      = 14,
     478              :    T_bqs      = 15, // binary 1100 to 1111
     479              :    T_max      = 16
     480              : };
     481              : 
     482              : // castling are encoded with to Square being initial rook position
     483              : // this allows to change it to king destination square
     484              : const array1d<Square,T_bqs+1> correctedKingDestSq = { INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE,
     485              :                                                       INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE,
     486              :                                                       INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE,
     487              :                                                       Sq_g1, Sq_c1, Sq_g8, Sq_c8};
     488              : // this allows to change it to rook destination square
     489              : const array1d<Square,T_bqs+1> correctedRookDestSq = { INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE,
     490              :                                                       INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE,
     491              :                                                       INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE, INVALIDSQUARE,
     492              :                                                       Sq_f1, Sq_d1, Sq_f8, Sq_d8};
     493              : 
     494              : [[nodiscard]] constexpr bool isValidMoveType(const MType m)      { return m <= T_bqs; }
     495   1516250672 : [[nodiscard]] constexpr bool isValidSquare(const Square s)       { return s >= 0 && s < NbSquare; }
     496    327274169 : [[nodiscard]] constexpr bool isValidPiece(const Piece pp)        { return pp >= P_bk && pp <= P_wk; }
     497    308914269 : [[nodiscard]] constexpr bool isValidPieceNotNone(const Piece pp) { return isValidPiece(pp) && pp != P_none; }
     498              : [[nodiscard]] constexpr bool isNotEmpty(const BitBoard bb)       { return bb != emptyBitBoard; }
     499              : 
     500       853449 : [[nodiscard]] constexpr Piece promShift(const MType mt) {
     501       853449 :    assert(mt >= T_promq);
     502       853449 :    assert(mt <= T_cappromn);
     503       853449 :    return static_cast<Piece>(P_wq - (mt % 4));
     504              : } // awfull hack
     505              : 
     506              : // previous best root 20000
     507              : // ttmove 15000
     508              : // ~~king evasion 10000~~
     509              : // good cap +7000 +SEE (or MVA and cap history)
     510              : // killers 1900-1700-1500
     511              : // counter 1300
     512              : // standard move use -1024 < history < 1024
     513              : // leaving threat +512
     514              : // MVV-LVA [0 400]
     515              : // recapture +512
     516              : inline constexpr array1d<ScoreType,16> MoveScoring    = {   0,                   // standard
     517              :                                                          7000,                   // cap (bad cap will be *=-1)
     518              :                                                             0,                   // reserved
     519              :                                                          7000,                   // ep
     520              :                                                          3950, 3500, 3350, 3300, // prom
     521              :                                                          7950, 7500, 7350, 7300, // prom+cap
     522              :                                                           256,  256,  256,  256  // castling bonus
     523              :                                                         };
     524              : 
     525              : [[nodiscard]] FORCE_FINLINE bool isSkipMove(const Move& a, const std::vector<MiniMove>* skipMoves) {
     526     13570389 :    return skipMoves && std::ranges::find(*skipMoves, Move2MiniMove(a)) != skipMoves->end();
     527              : }
     528              : 
     529              : [[nodiscard]] constexpr ScoreType Move2Score(const Move m) {
     530            0 :    assert(isValidMove(m));
     531    335850110 :    return static_cast<ScoreType>((m >> 16) & 0xFFFF);
     532              : }
     533    250441789 : [[nodiscard]] constexpr Square Move2From(const Move m) {
     534            0 :    assert(isValidMove(m));
     535    250441789 :    return static_cast<Square>((m >> 10) & 0x3F);
     536              : }
     537    263601354 : [[nodiscard]] constexpr Square Move2To(const Move m) {
     538            0 :    assert(isValidMove(m));
     539    263601354 :    return static_cast<Square>((m >> 4) & 0x3F);
     540              : }
     541              : [[nodiscard]] constexpr MType Move2Type(const Move m) {
     542            0 :    assert(isValidMove(m));
     543    419525936 :    return static_cast<MType>(m & 0xF);
     544              : }
     545           13 : [[nodiscard]] constexpr MiniMove ToMove(const Square from, const Square to, const MType type) {
     546           13 :    assert(isValidSquare(from));
     547           13 :    assert(isValidSquare(to));
     548           13 :    return static_cast<MiniMove>((from << 10) | (to << 4) | type);
     549              : }
     550    222430664 : [[nodiscard]] constexpr Move ToMove(const Square from, const Square to, const MType type, const ScoreType score) {
     551    222430664 :    assert(isValidSquare(from));
     552    222430664 :    assert(isValidSquare(to));
     553    222430664 :    return static_cast<Move>((score << 16) | (from << 10) | (to << 4) | type);
     554              : }
     555              : 
     556      6233158 : [[nodiscard]] constexpr ScoreType matingScore  (const DepthType in) { return static_cast<ScoreType>(MATE - in); }
     557      7892220 : [[nodiscard]] constexpr ScoreType matedScore   (const DepthType in) { return static_cast<ScoreType>(-MATE + in); }
     558              : 
     559              : [[nodiscard]] constexpr bool isMatingScore(const ScoreType s) { return (s >= MATE - MAX_DEPTH); }
     560              : [[nodiscard]] constexpr bool isMatedScore (const ScoreType s) { return (s <= matedScore(MAX_DEPTH)); }
     561     14380040 : [[nodiscard]] constexpr bool isMateScore  (const ScoreType s) { return (Abs(s) >= MATE - MAX_DEPTH); }
     562              : 
     563              : [[nodiscard]] constexpr bool isPromotionStd(const MType mt) {
     564              :    assert(isValidMoveType(mt));
     565    499313357 :    return (mt >> 2 == 0x1);
     566              : }
     567              : [[nodiscard]] constexpr bool isPromotionStd(const Move m) { return isPromotionStd(Move2Type(m)); }
     568              : [[nodiscard]] constexpr bool isPromotionCap(const MType mt) {
     569              :    assert(isValidMoveType(mt));
     570    186973736 :    return (mt >> 2 == 0x2);
     571              : }
     572              : [[nodiscard]] constexpr bool isPromotionCap(const Move m) { return isPromotionCap(Move2Type(m)); }
     573              : 
     574    499313357 : [[nodiscard]] constexpr bool isPromotion(const MType mt) {
     575    499313357 :    assert(isValidMoveType(mt));
     576    499313357 :    return isPromotionStd(mt) || isPromotionCap(mt);
     577              : }
     578      4134170 : [[nodiscard]] constexpr bool isPromotion(const Move m) { return isPromotion(Move2Type(m)); }
     579              : 
     580              : [[nodiscard]] constexpr bool isCastling(const MType mt) {
     581      8492635 :    assert(isValidMoveType(mt));
     582    250370205 :    return (mt >> 2) == 0x3;
     583              : }
     584     45760546 : [[nodiscard]] constexpr bool isCastling(const Move m) { return isCastling(Move2Type(m)); }
     585              : 
     586    202562284 : [[nodiscard]] constexpr bool isCapture(const MType mt) {
     587    202562284 :    assert(isValidMoveType(mt));
     588    202562284 :    return mt == T_capture || mt == T_ep || isPromotionCap(mt);
     589              : }
     590     25141832 : [[nodiscard]] constexpr bool isCapture(const Move m) { return isCapture(Move2Type(m)); }
     591              : 
     592      1349207 : [[nodiscard]] constexpr bool isCaptureNoEP(const MType mt) {
     593      1349207 :    assert(isValidMoveType(mt));
     594      1349207 :    return mt == T_capture || isPromotionCap(mt);
     595              : }
     596      1326896 : [[nodiscard]] constexpr bool isCaptureNoEP(const Move m) { return isCaptureNoEP(Move2Type(m)); }
     597              : 
     598              : 
     599    175492987 : [[nodiscard]] constexpr bool isCaptureOrProm(const MType mt) {
     600    175492987 :    assert(isValidMoveType(mt));
     601    175492987 :    return mt == T_capture || mt == T_ep || isPromotion(mt);
     602              : }
     603              : [[nodiscard]] constexpr bool isCaptureOrProm(const Move m) { return isCaptureOrProm(Move2Type(m)); }
     604              : 
     605              : [[nodiscard]] constexpr bool isEnPassant(const MType mt) {
     606              :    assert(isValidMoveType(mt));
     607      4152185 :    return mt == T_ep;
     608              : }
     609      8304370 : [[nodiscard]] constexpr bool isEnPassant(const Move m) { return isEnPassant(Move2Type(m)); }
     610              : 
     611      2002004 : [[nodiscard]] constexpr ScoreType badCapScore(const Move m) { return Move2Score(m) + MoveScoring[T_capture]; }
     612              : 
     613      5768601 : [[nodiscard]] constexpr Square chebyshevDistance(const Square sq1, const Square sq2) {
     614      5768601 :    return std::max(Abs(static_cast<Square>(SQRANK(sq2) - SQRANK(sq1))), Abs(static_cast<Square>(SQFILE(sq2) - SQFILE(sq1))));
     615              : }
     616              : [[nodiscard]] constexpr Square manatthanDistance(const Square sq1, const Square sq2) {
     617              :    return Abs(static_cast<Square>(SQRANK(sq2) - SQRANK(sq1))) + Abs(static_cast<Square>(SQFILE(sq2) - SQFILE(sq1)));
     618              : }
     619              : [[nodiscard]] constexpr Square minDistance(const Square sq1, const Square sq2) {
     620              :    return std::min(Abs(static_cast<Square>(SQRANK(sq2) - SQRANK(sq1))), Abs(static_cast<Square>(SQFILE(sq2) - SQFILE(sq1))));
     621              : }
     622              : 
     623              : [[nodiscard]] FORCE_FINLINE Square correctedMove2ToKingDest(const Move m) {
     624            0 :    assert(isValidMove(m));
     625              :    const MType mtype = Move2Type(m);
     626    235389856 :    return (!isCastling(mtype)) ? Move2To(m) : correctedKingDestSq[mtype];
     627              : }
     628              : 
     629              : [[nodiscard]] FORCE_FINLINE Square correctedMove2ToRookDest(const Move m) {
     630              :    assert(isValidMove(m));
     631              :    const MType mtype = Move2Type(m);
     632              :    return (!isCastling(mtype)) ? Move2To(m) : correctedRookDestSq[mtype];
     633              : }
     634              : 
     635              : namespace MoveDifficultyUtil {
     636              :     enum MoveDifficulty { 
     637              :       MD_forced = 0, 
     638              :       MD_easy, 
     639              :       MD_std, 
     640              :       MD_moobDefenceIID, 
     641              :       MD_moobAttackIID
     642              :     };
     643              : 
     644              :     enum PositionEvolution{
     645              :       PE_none = 0,
     646              :       PE_std,
     647              :       PE_moobingAttack,
     648              :       PE_moobingDefence,
     649              :       PE_boomingAttack,
     650              :       PE_boomingDefence,
     651              :     };
     652              : 
     653              :     const DepthType emergencyMinDepth          = 14;
     654              :     const ScoreType emergencyMargin            = 64;
     655              :     const ScoreType emergencyAttackThreshold   = 130;
     656              :     const ScoreType easyMoveMargin             = 180;
     657              :     const int       emergencyFactorIID         = 3;
     658              :     const int       emergencyFactorIIDGood     = 3;
     659              :     const int       emergencyFactorMoobHistory = 2;
     660              :     const int       emergencyFactorBoomHistory = 1;
     661              :     const int       maxStealDivisor            = 5; // 1/maxStealDivisor of remaining time
     662              : 
     663              :    extern float variability;
     664         5099 :    [[nodiscard]] FORCE_FINLINE float variabilityFactor() { return 2.f / (1.f + std::exp(1.f - MoveDifficultyUtil::variability)); } // inside [0.5 .. 2]
     665              : 
     666              : } // namespace MoveDifficultyUtil
     667              : 
     668              : template<typename T, int seed> [[nodiscard]] FORCE_FINLINE T randomInt(T m, T M) {
     669              :    ///@todo this is slow because the static here implies a guard variable !!
     670        20080 :    static std::mt19937 mt(seed); // fixed seed for ZHash for instance !!!
     671        20080 :    static std::uniform_int_distribution<T> dist(m, M);
     672        20080 :    return dist(mt);
     673              : }
     674              : 
     675              : template<typename T> [[nodiscard]] FORCE_FINLINE T randomInt(T m, T M) {
     676              :    ///@todo this is slow because the static here implies a guard variable !!
     677            0 :    static std::random_device r;
     678            0 :    static std::seed_seq seed {r(), r(), r(), r(), r(), r(), r(), r()};
     679            0 :    static std::mt19937 mt(seed);
     680            0 :    static std::uniform_int_distribution<T> dist(m, M);
     681              :    return dist(mt);
     682              : }
     683              : 
     684              : template<class T> [[nodiscard]] constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
     685              :     assert(!(hi < lo));
     686              :     return (v < lo) ? lo : (hi < v) ? hi : v;
     687              : }
     688              : 
     689     22595351 : [[nodiscard]] constexpr Square relative_square(const Color c, const Square s) { return static_cast<Square>(s ^ (c * 56)); }
     690              : 
     691              : template<Color C> [[nodiscard]] constexpr Square ColorSquarePstHelper(const Square k) { return relative_square(~C, k); }
     692              : 
     693              : [[nodiscard]] constexpr uint64_t powerFloor(const uint64_t x) {
     694              :    uint64_t power = 1;
     695         1081 :    while (power <= x) power *= 2;
     696           50 :    return power / 2;
     697              : }
     698              : 
     699              : FORCE_FINLINE void* std_aligned_alloc(const size_t alignment, const size_t size) {
     700              : #ifdef __ANDROID__
     701              :   return malloc(size);
     702              : #elif defined(__EMSCRIPTEN__)
     703              :   return malloc(size);
     704              : #elif defined(__APPLE__)
     705              :   return aligned_alloc(alignment, size);
     706              : #elif defined(_WIN32)
     707              :   return _mm_malloc(size, alignment);
     708              : #elif defined(ARDUINO) || defined(ESP32)
     709              :   return malloc(size);
     710              : #else
     711           24 :    void* ret = std::aligned_alloc(alignment, size);
     712              : #ifdef MADV_HUGEPAGE
     713              :   madvise(ret, size, MADV_HUGEPAGE);
     714              : #endif
     715              :   return ret;
     716              : #endif
     717              : }
     718              : 
     719              : FORCE_FINLINE void std_aligned_free(void* ptr) {
     720              : #ifdef __ANDROID__
     721              :   return free(ptr);
     722              : #elif defined(__EMSCRIPTEN__)
     723              :   return free(ptr);
     724              : #elif defined(__APPLE__)
     725              :   free(ptr);
     726              : #elif defined(_WIN32)
     727              :   _mm_free(ptr);
     728              : #else
     729           24 :   free(ptr);
     730              : #endif
     731              : }
     732              : 
     733              : FORCE_FINLINE std::string toHexString(const uint32_t i) {
     734           44 :   std::stringstream s;
     735              :   s << "0x" << std::hex << i;
     736              :   return s.str();
     737           44 : }
        

Generated by: LCOV version 2.0-1