Belofte version 2.1.8
A promising chess program using the UCI or Winboard interface
search.cpp
Go to the documentation of this file.
1/*---------------------------------------------------------------------+
2 * File: search.cpp
3 * Project: part of belofte - A Promising Chess Program
4 * Author: yves
5 * SPDX-License-Identifier: GPL-2.0-only
6+----------------------------------------------------------------------*/
7
8#include "belofte.h"
9
10//-----------------------------------------------------------------------
11
13 : m_score{sc.m_score}
14 , m_type{sc.m_type}
15{
16}
17
19 : m_score{std::move(sc.m_score)}
20 , m_type{std::move(sc.m_type)}
21{
22}
23
25 : m_score{sc}
26{
27}
28
29bSearchScore::bSearchScore(bScore const& sc, scoretype_t const& st) noexcept
30 : m_score{sc}
31 , m_type{st}
32{
33}
34
36{
37 m_score = std::move(sc.m_score);
38 m_type = std::move(sc.m_type);
39
40 return *this;
41}
42
44{
45 m_score = sc;
46
47 return *this;
48}
49
51{
52 m_score = std::move(sc);
53
54 return *this;
55}
56
60
62{
63 if (!m_type) {
64 bSearchScore(-m_score);
65 } else if (m_type == tScoreType::SC_ALPHA) {
66 return bSearchScore(-m_score, tScoreType::SC_BETA);
67 } else if (m_type == tScoreType::SC_BETA) {
68 return bSearchScore(-m_score, tScoreType::SC_ALPHA);
69 }
70 return bSearchScore(-m_score, m_type);
71}
72
73std::string const operator+(std::string const& lhs, bSearchScore const& sc)
74{
75 return lhs + sc.operator std::string();
76}
77
78std::string const operator+(bSearchScore const& sc, std::string const& rhs)
79{
80 return sc.operator std::string() + rhs;
81}
82
83bool operator>(bScore const& lhsc, bSearchScore const& rhsc)
84{
85 return lhsc > rhsc.getRealScore();
86}
87
88bool operator>=(bScore const& lhsc, bSearchScore const& rhsc)
89{
90 return lhsc >= rhsc.getRealScore();
91}
92
93bool operator>(bSearchScore const& lhsc, bScore const& rhsc)
94{
95 return lhsc.getRealScore() > rhsc;
96}
97
98bool operator>(bSearchScore const& lhsc, bSearchScore const& rhsc)
99{
100 return lhsc.getRealScore() > rhsc.getRealScore();
101}
102
103bSearchScore::operator std::string() const
104{
105 if (!m_type) {
106 return belofte::scoreAsStr(m_score);
107#if defined(BELOFTE_NOUNICODE)
108 } else if (m_type == tScoreType::SC_ALPHA) {
109 return "alpha: " + belofte::scoreAsStr(m_score);
110 } else if (m_type == tScoreType::SC_BETA) {
111 return "beta: " + belofte::scoreAsStr(m_score);
112 } else if (m_type == tScoreType::SC_CHILD) {
113 return "search: " + belofte::scoreAsStr(m_score);
114 } else if (m_type == tScoreType::SC_BEST) {
115 return "best: " + belofte::scoreAsStr(m_score);
116#else
117 } else if (m_type == tScoreType::SC_ALPHA) {
118 return "𝛼: " + belofte::scoreAsStr(m_score);
119 } else if (m_type == tScoreType::SC_BETA) {
120 return "𝛽: " + belofte::scoreAsStr(m_score);
121 } else if (m_type == tScoreType::SC_CHILD) {
122 return "⅀: " + belofte::scoreAsStr(m_score);
123 } else if (m_type == tScoreType::SC_BEST) {
124 return "↑: " + belofte::scoreAsStr(m_score);
125#endif
126 }
127 return belofte::scoreAsStr(m_score);
128}
129
130//-----------------------------------------------------------------------
131
133 : m_aborting{false}
134 , m_name{n}
135 , m_levelptr{nullptr}
136{
137}
138
140{
141 m_levelptr = nullptr;
142 m_name = "";
143}
144
145//-----------------------------------------------------------------------
146
147/**
148 * Generic search, will call (non-)recursive method per algorithm
149 * only when there are moves to be played
150 * @param b initial board
151 */
153{
155 bBestMoveInfo result;
156
157 // TODO: Add debug manipulator
158 std::stringstream ss;
159 ss << "Searching started: " << this->operator std::string() << " "
160 << getLevel()->operator std::string()
161 << (b.whiteToMove() ? " For white" : " For Black");
162 AppEI()->sendInfo(ss.str());
163
164 b.clearVariation();
165 b.setPreviousMoves({});
166
167 bMoveList& ml = b.getMoveListRef();
168 movenum_t n_moves = ml.generateMoves(b);
169 ml.sortMoves();
171 m_nodes = 0LL;
172 m_nonleafnodes = 0LL;
173 m_maxDepth = 0;
174
175 if (n_moves) {
177 && (getLevel()->getType() != LevelType::MateSearch)) {
178 result = SearchBestMoveIterative(b);
179 } else {
180 CalcBestMove(b);
181 }
182 } else {
183 StopSearch();
184 AppEI()->sendError("no move found", getDuration());
185
186 throw noMoveFoundException();
187 }
188
189 result.moveid = ml.sortMoves(); // TODO: retrieve best move id without sorting it on top
190 dumpMoveList(b, 0);
191
192 result.score = ml[result.moveid].getScore();
193 //sendInfoScore(b, 0, result.score);
194 return result;
195}
196
197//-----------------------------------------------------------------------
198
199bBestMoveInfo bSearchAlgorithm::SearchBestMoveIterative(bBoard& b)
200{
201 depth_t iCurrentDepth = 1;
202 bBestMoveInfo result;
203
204 bMoveList& ml = b.getMoveListRef();
205 ml.generateMoves(b);
206
207 while (iCurrentDepth <= getLevel()->getMaxDepth()) {
208 getLevel()->setSearchDepth(iCurrentDepth);
209
210 std::string sDepth = "(depth " + belofte::to_string(iCurrentDepth) + ")";
211 AppEI()->sendDebug(1, "Iterative Depth Search " + sDepth);
212
213 try {
214 result.score = CalcBestMove(b);
215 sendInfoSearching(b, 0, sDepth + " done", result.score);
216 int64_t nNodes = m_nodes + m_nonleafnodes;
217 int64_t nDuration = getDurationMicroSec();
218 if (nDuration < 1) nDuration = 1;
219 long nNPS = nNodes * 1000000 / nDuration;
220 AppEI()->sendInfoDepth(iCurrentDepth, m_maxDepth, nNodes, static_cast<int>(nNPS));
221 } catch (const searchAbortedException&) {
222 sendInfoSearching(b, 0, "abort search " + sDepth, result.score);
223 break;
224 } catch (...) { throw; // push other exceptions down
225 }
226
227 if ((result.score & SCORE_POSITIVE) != SCORE_PUNDEFINED) {
228 // quit loop in case of absolute score
229 if (belofte::realScore(result.score) > SCORE_WINNING) {
230 sendInfoSearching(b, 0, "winning " + sDepth, result.score);
231 break;
232 }
233 // quit loop in case of getting mated
234 if (belofte::realScore(result.score) < -SCORE_WINNING) {
235 sendInfoSearching(b, 0, "getting mated " + sDepth, result.score);
236 break;
237 }
238 }
239
240 // quit loop if not enough time left for another iteration
241 if (!getLevel()->stillTimeLeft(iCurrentDepth, getDurationMilliSec())) {
242 sendInfoSearching(b, 0, "not enough time left " + sDepth, result.score);
243 break;
244 }
245
246 iCurrentDepth++;
247 if (iCurrentDepth <= getLevel()->getMaxDepth()) {
248 dumpMoveList(b, iCurrentDepth - 1);
249 //sendInfoScore(b, 0, result.score);
250 ml.sortMoves();
251 }
252 }
253 return result;
254}
255
256//-----------------------------------------------------------------------
257
259{
260 m_aborting = false;
261 ClockStart();
262 m_minimizing = m;
263 m_postlevel = App().sout.getLevel(); // cache value
264 setLevel(&(Game()->getLevel())); // copy level from game-level to search
265}
266
268{
269 m_aborting = false;
270 ClockEnd();
271}
272
274{
275 m_aborting = true;
276}
277
279{
280 // TODO: limit calls to getDurationMilliSec
281 if (m_aborting
282 || m_levelptr->stoppingSearch(getDurationMilliSec()))
284}
285
286//-----------------------------------------------------------------------
287
289{
290 // TOCHECK: if we stream to sout, last element does not use outputWriter
291 // but ostream, this is why we stream to stringstream first
292 bPgnMoveList ml(b);
293 std::stringstream ss;
294 if (iDepth) ss << "depth " << belofte::to_string(iDepth) << " ";
295 ss << "ml " << ml;
296 AppEI()->sendDebug(51, ss.str());
297}
298
299//-----------------------------------------------------------------------
300
302 depth_t const nDepth, std::string const& c,
303 bScore const sc) const
304{
305 if (nDepth <= m_postlevel) { // speedup
306 AppEI()->sendInfoSearching(b, nDepth, m_maxDepth,
307#if !defined(_DEBUG)
308 this->operator std::string() + " " +
309#endif
310 c, sc * m_minimizing * b.minimizing(), getDurationMilliSec(),
312 }
313 return sc;
314}
315
317 depth_t const nDepth,
318 bScore const sc) const
319{
320 if (nDepth <= m_postlevel) { // speedup
322 sc * m_minimizing * b.minimizing());
323 }
324 return sc;
325}
326
328 movenum_t const moveid) const
329{
330 if (nDepth < m_postlevel) {
331 // speedup
332 AppEI()->sendInfoCurrMove(b, nDepth, m_maxDepth, this->operator std::string(),
333 b.getMove(moveid), moveid, m_nodes + m_nonleafnodes);
334 }
335}
336
337//-----------------------------------------------------------------------
338
339/**
340 * Cache score of board
341 * @param b board
342 */
344{
345 bScore sc = b.getBoardEvaluation();
346 if (sc == SCORE_UNDEFINED) {
347 sc = Game()->EvalForPlayer(b);
348 b.setBoardEvaluation(sc);
349 }
350 return sc;
351}
352
353/** converge score towards zero in order to force immediate best move
354 * first
355 */
357{
358 // make sure theoretic draw does not oscillate
360 if ((sc & SCORE_POSITIVE) == SCORE_PUNDEFINED) return SCORE_UNDEFINED;
361
362 // special score values are kept
363 if ((sc & SCORE_POSITIVE) > SCORE_ALMOST_NORMAL) return sc;
364 // do not converge if close to zero
365 if ((sc & SCORE_POSITIVE) < SCORE_ALMOST_DRAW) return sc;
366
367 if (sc > 0) return sc - SCORE_CONVERGE_BYDEPTH;
368 return sc + SCORE_CONVERGE_BYDEPTH;
369}
370
371//-----------------------------------------------------------------------
372
373// eof
appInstance & App()
Definition belofte.cpp:480
engineInterface * AppEI()
Definition belofte.cpp:486
bGame * Game()
Definition belofte.cpp:491
This is the main include file, needs to be included before any other include.
uint_fast8_t movenum_t
Definition belofte.h:109
int_fast8_t depth_t
Definition belofte.h:112
int16_t bScore
void ClockEnd()
Definition util.cpp:37
std::string getDuration() const
Definition util.cpp:47
long long getDurationMilliSec() const
Definition util.cpp:83
void ClockStart()
Definition util.cpp:27
long long getDurationMicroSec() const
Definition util.cpp:61
outputWriter sout
normal output
Definition belofte.h:331
bool whiteToMove() const
Definition board.h:80
movenum_t moveid
board
Definition board.h:147
void clearVariation()
Definition board.cpp:974
bMove const & getMove(movenum_t const moveid) const
Definition board.cpp:967
bMoveList & getMoveListRef()
return reference to movelist
Definition board.cpp:954
void setBoardEvaluation(bScore const s)
Definition board.h:179
bScore minimizing() const
Definition board.h:180
bScore getBoardEvaluation() const
Definition board.h:178
void setPreviousMoves(movesequence_t const &v)
Definition board.h:187
bScore EvalForPlayer(bBoard const &b)
Definition game.cpp:151
void setSearchDepth(depth_t const d)
Definition level.cpp:259
bool stoppingSearch(long const nTimeElapsed) const
Stop search required ?
Definition level.cpp:321
movenum_t sortMoves()
Definition movelist.cpp:225
movenum_t generateMoves(bBoard const &b)
generate moves if not yet generated
Definition movelist.cpp:259
void sendInfoCurrMove(bBoard const &b, depth_t const nDepth, movenum_t const moveid) const
Definition search.cpp:327
bScore attenuateScore(bScore const sc) const
converge score towards zero in order to force immediate best move first
Definition search.cpp:356
depth_t m_maxDepth
Definition search.h:106
bScore RetrieveBoardEvaluation(bBoard &b) const
Cache score of board.
Definition search.cpp:343
void StopSearch()
Definition search.cpp:267
bool m_iterativesearch
Definition search.h:109
void InterruptSearch()
Definition search.cpp:273
~bSearchAlgorithm() override
Definition search.cpp:139
virtual bScore CalcBestMove(bBoard &b)=0
bScore sendInfoScore(bBoard const &b, depth_t const nDepth, bScore const) const
Definition search.cpp:316
bLevel * getLevel()
Definition search.h:117
int64_t m_nonleafnodes
Definition search.h:108
bScore sendInfoSearching(bBoard const &b, depth_t const nDepth, std::string const &c, bScore const sc) const
Definition search.cpp:301
bSearchAlgorithm(std::string const &n)
Definition search.cpp:132
int64_t m_nodes
Definition search.h:107
void setLevel(bLevel *l)
Definition search.h:116
void CheckIfAbortingSearch() const
Definition search.cpp:278
bBestMoveInfo SearchBestMove(bBoard &b)
Generic search, will call (non-)recursive method per algorithm only when there are moves to be played...
Definition search.cpp:152
void StartSearch(bScore const m)
Definition search.cpp:258
void dumpMoveList(bBoard &b, depth_t const iDepth) const
Definition search.cpp:288
bSearchScore operator-() const
Definition search.cpp:61
bSearchScore & operator=(bSearchScore &&sc) noexcept
Definition search.cpp:35
bScore getRealScore() const
Definition search.h:63
bSearchScore(bSearchScore const &sc) noexcept
Definition search.cpp:12
virtual void sendInfoSearching(bBoard const &b, int const nLogDepth, depth_t const nMaxDepth, std::string const &comment, bScore const sc, int64_t const t, int64_t const nodes) const
Definition belofte.h:217
virtual void sendInfoCurrMove(bBoard const &b, depth_t const nLogDepth, depth_t const nMaxDepth, std::string const &comment, bMove const &m, movenum_t const moveid, int64_t const nodes) const
Definition belofte.h:220
virtual void sendDebug(int const l, std::string const &info)
Definition belofte.h:209
virtual void sendInfoScore(long long timems, bBoard const &b, bScore const cp)
Definition belofte.h:215
virtual void sendInfo(std::string const &info)
Definition belofte.h:208
virtual void sendError(std::string const &error, std::string const &description)
Definition usercmd.cpp:156
virtual void sendInfoDepth(int depth, int seldepth, int64_t nodes, int nps)
Definition belofte.h:213
int getLevel() const
Definition bel_debug.h:47
constexpr bScore SCORE_ALMOST_NORMAL
Definition eval.h:22
constexpr bScore SCORE_PUNDEFINED
Definition eval.h:19
constexpr bScore SCORE_ALMOST_DRAW
Definition eval.h:26
constexpr bScore SCORE_CONVERGE_BYDEPTH
Definition eval.h:29
constexpr bScore SCORE_WINNING
Definition eval.h:24
constexpr bScore SCORE_POSITIVE
Definition eval.h:16
constexpr bScore SCORE_UNDEFINED
Definition eval.h:20
constexpr bScore SCORE_THEORETIC_DRAW
Definition eval.h:17
bScore realScore(bScore const sc)
Definition eval.cpp:23
std::string const operator+(std::string const &lhs, bSearchScore const &sc)
Definition search.cpp:73
bool operator>(bScore const &lhsc, bSearchScore const &rhsc)
Definition search.cpp:83
bool operator>=(bScore const &lhsc, bSearchScore const &rhsc)
Definition search.cpp:88
@ SC_BETA
Definition search.h:40
@ SC_BEST
Definition search.h:40
@ SC_CHILD
Definition search.h:40
@ SC_ALPHA
Definition search.h:40
enum tScoreType scoretype_t
Definition search.h:44