Belofte version 2.1.9
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
12/**
13 * Generic search, will call (non-)recursive method per algorithm
14 * only when there are moves to be played
15 * @param b initial board
16 * @param ml movelist of this position
17 */
19{
21
22 /// @todo Add debug manipulator
23 std::stringstream ss;
24 ss << "Searching started: " << this->operator std::string() << " "
25 << getLevel()->operator std::string()
26 << (b.whiteToMove() ? " For white" : " For Black");
27 m_appei->sendInfoSearchStart(ss.str());
28
30 b.setPreviousMoves({});
32 b.calcGameStage();
33
34 m_leafnodes = 0LL;
35 m_nonleafnodes = 0LL;
37
39 if (gr != GR_UNKNOWN && isNoBench()) {
40 m_appei->sendInfo("engine should not have started searching as position is final");
41 m_appei->sendResult(b, gr);
42 throw gameEndException();
43 }
44
45 if (ml.atLeastOneMovePossible(b)) {
47 && (getLevel()->getType() != LevelType::MateSearch)) {
48 SearchBestMoveIterative(b, ml);
49 } else {
50 CalcBestMove(b, ml);
51 }
52 } else {
53 StopSearch();
54 if (isNoBench())
55 m_appei->sendError("no move found", getDuration());
56 if (!m_iterativesearch) return;
57
59 }
60
61 dumpMoveList(b, 0);
62}
63
64//-----------------------------------------------------------------------
65
66void bSearchAlgorithm::SearchBestMoveIterative(bBoard& b, bMoveList& ml)
67{
68 int8_t nFluctuations = 0;
69 depth_t iCurrentDepth = 1;
70 bScore score;
71
72 ml.generateMoves(b);
73
74 std::string sPreviousBestMove, sNewBestMove;
75
76 while (iCurrentDepth <= getLevel()->getMaxDepth()) {
77 getLevel()->setSearchDepth(iCurrentDepth);
78
79 std::string sDepth = "(depth " + belofte::to_string(iCurrentDepth) + ")";
80 m_appei->sendDebug(1, "Iterative Depth Search " + sDepth);
81
82 // clear search variation of previous searches in current position
84
85 try {
86 score = CalcBestMove(b, ml);
87 {
88 int64_t nNodes = m_leafnodes + m_nonleafnodes;
89 #if defined(NPS_LOG)
90 int64_t nDuration = getDurationMicroSec();
91 if (nDuration < 1) nDuration = 1;
92 long nNPS = nNodes * 1000000 / nDuration;
93 m_appei->sendInfoDepth(iCurrentDepth, m_maxDepth, nNodes, static_cast<int>(nNPS));
94 #else
95 m_appei->sendInfoDepth(iCurrentDepth, m_maxDepth, nNodes, 0);
96 #endif
97 }
98 } catch (const searchAbortedException&) {
99 sendInfoSearching(b, 0, "abort search " + sDepth, score);
100 break;
101 } catch (...) { throw; // push other exceptions down
102 }
103
104 if (!bSearchScore::isUndefinedScore(score)) {
105 // quit loop in case of absolute score
107 sendInfoSearching(b, 0, "winning " + sDepth, score);
108 break;
109 }
110 // quit loop in case of getting mated
112 sendInfoSearching(b, 0, "getting mated " + sDepth, score);
113 break;
114 }
115 }
116
117 // retrieve bestmove
118 if (!b.getVariation().empty()) {
119 sNewBestMove = b.getVariation()[0];
120 }
121
122 if (!sPreviousBestMove.empty()
123 && (sNewBestMove != sPreviousBestMove)
124 && iCurrentDepth > 3) {
125 // there is an update to the bestmove found in this iteration
126 // so increase time for allowing a further iteration
127 ++nFluctuations;
129 bBoard nb(b);
130 sendInfoSearching(nb, 0, "increase time for search");
131 }
132
133 // quit loop if not enough time left for another iteration
134 if (!getLevel()->stillTimeLeft(iCurrentDepth, getDurationMilliSec())) {
135 sendInfoSearching(b, 0, "no more search time allotted " + sDepth, score);
136 break;
137 } else if (sPreviousBestMove.empty() && !sNewBestMove.empty()) {
138 sendInfoSearching(b, 0, "bestmove set " + sDepth + " done", score);
139 sPreviousBestMove = sNewBestMove;
140 } else if (sNewBestMove != sPreviousBestMove) {
141 sendInfoSearching(b, 0, "bestmove updated " + sDepth + " done", score);
142 sPreviousBestMove = sNewBestMove;
143 } else {
144 sendInfoSearching(b, 0, sDepth + " done", score);
145 }
146
147 if (iCurrentDepth < getLevel()->getMaxDepth()) {
148 dumpMoveList(b, iCurrentDepth);
149 ml.sortMoves();
150 }
151 ++iCurrentDepth;
152 }
153}
154
155//-----------------------------------------------------------------------
156
158{
159 m_aborting = false;
160 ClockStart();
161 m_minimizing = sc;
162 m_postlevel = App().sout.getLevel(); // cache value
163 setLevel(&(Game()->getLevel())); // copy level from game-level to search
164 m_appei = AppEI();
165 m_evalptr = Game()->getEval();
166}
167
169{
170 /// @todo: limit calls to getDurationMilliSec
171 if (m_aborting
172 || m_levelptr->stoppingSearch(getDurationMilliSec()))
174}
175
176//-----------------------------------------------------------------------
177
178void bSearchAlgorithm::dumpMoveList(bBoard const& b, depth_t const iDepth) const
179{
180 /// @todo check if we stream to sout, last element does not use outputWriter
181 /// but ostream, this is why we stream to stringstream first
182 bPgnMoveList ml(b);
183 std::stringstream ss;
184 if (iDepth) ss << "depth " << belofte::to_string(iDepth) << " ";
185 ss << "ml " << ml;
186 m_appei->sendDebug(51, ss.str());
187}
188
189//-----------------------------------------------------------------------
190
192 depth_t const nDepth, std::string const& comment) const
193{
194 if (nDepth <= m_postlevel) { // speedup
195 if (comment != "") {
196 m_appei->sendInfoSearching(b, nDepth, m_maxDepth, comment, SCORE_UNDEFINED,
198 } else {
199 m_appei->sendInfoSearching(b, nDepth, m_maxDepth, SCORE_UNDEFINED,
201 }
202 }
203}
204
206 depth_t const nDepth, std::string const& comment,
207 bScore const sc) const
208{
209 if (nDepth <= m_postlevel) { // speedup
210 if (comment != "") {
211 m_appei->sendInfoSearching(b, nDepth, m_maxDepth,
212 comment, sc * m_minimizing * b.minimizing(), getDurationMilliSec(),
214 } else {
215 m_appei->sendInfoSearching(b, nDepth, m_maxDepth,
216 sc * m_minimizing * b.minimizing(), getDurationMilliSec(),
218 }
219 }
220 return sc;
221}
222
224 depth_t const nCurDepth,
225 bMove const& m,
226 movenum_t const moveid) const
227{
228 if (nCurDepth < m_postlevel) {
229 m_appei->sendInfoCurrMove(b, nCurDepth,
230 m, moveid, m_leafnodes + m_nonleafnodes);
231 }
232}
233
234//-----------------------------------------------------------------------
235
236/**
237 * Get score of board, eventually from cache
238 * @param b board
239 * @param gr previous gameresult
240 * @return score of board, either from cache, from gr or caclulated
241 */
243{
244 if (gr == GR_UNSET) {
246 }
247 if (gr != GR_UNKNOWN) {
248 // gr is a forced end
250 }
251 return m_evalptr->getEvaluation(b) * b.minimizing();
252}
253
254//-----------------------------------------------------------------------
255
256// eof
appInstance & App()
Definition belofte.cpp:225
engineInterface * AppEI()
Definition belofte.cpp:231
bGame * Game()
Definition belofte.cpp:236
This is the main include file, needs to be included before any other include.
uint_fast8_t movenum_t
Definition belofte.h:100
int_fast8_t depth_t
Definition belofte.h:103
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:174
constexpr bool whiteToMove() const
Definition basicboard.h:156
constexpr bScore minimizing() const
Definition basicboard.h:166
board
Definition board.h:45
void clearVariation()
Definition board.h:91
void calcMinorPieces(bool const bForceRecalc=false)
Recalculate minor pieces, used for evaluation and end of game condition in case of less than 5 pieces...
Definition board.cpp:68
movesequence_t const & getVariation() const
Definition board.h:89
void calcGameStage()
calculate stage of game to assist in evaluation
Definition board.cpp:139
void setPreviousMoves(movesequence_t const &v)
Definition board.h:87
bPositionEvaluation * getEval() const
void setMoreTimeRequired()
increase gradually the allowed time for move, first move to max time for move, then move to abort tim...
Definition level.cpp:297
void setSearchDepth(depth_t const d)
Definition level.cpp:232
Definition move.h:13
movenum_t generateMoves(bBasicBoard const &b)
generate moves if not yet generated
Definition movelist.cpp:340
void sortMoves()
sort moves and update bestmove id if less than 5 moves, sort all if more than 5 moves,...
Definition movelist.cpp:293
bool atLeastOneMovePossible(bBasicBoard &b)
see if at least one move can be played e.g.
Definition movelist.cpp:404
static bScore resultToScoreFlag(gameResult_t const gr)
Class static function convert all draw scores to SCORE_THEORETIC_DRAW.
Definition eval.cpp:77
static gameResult_t gameEndedResult(bBoard const &b)
Class static function See if board is in finite state, meaning game is ended.
Definition eval.cpp:42
void StartSearch(bScore const sc)
Definition search.cpp:157
void sendInfoCurrMove(bBoard const &b, depth_t const nCurDepth, bMove const &m, movenum_t const moveid) const
Definition search.cpp:223
void StopSearch()
Definition search.h:97
bool m_iterativesearch
Definition search.h:126
void initMaxSearchedDepth()
Definition search.h:136
constexpr bool isNoBench() const
Definition search.h:114
void SearchBestMove(bBoard &b, bMoveList &ml)
Generic search, will call (non-)recursive method per algorithm only when there are moves to be played...
Definition search.cpp:18
bLevel * getLevel()
Definition search.h:141
int64_t m_nonleafnodes
Definition search.h:125
int64_t m_leafnodes
Definition search.h:124
void setLevel(bLevel *l)
Definition search.h:139
bScore RetrieveBoardEvaluation(bBoard &b, gameResult_t const gr=GR_UNSET) const
Get score of board, eventually from cache.
Definition search.cpp:242
void CheckIfAbortingSearch() const
Definition search.cpp:168
void sendInfoSearching(bBoard const &b, depth_t const nDepth, std::string const &comment) const
Definition search.cpp:191
virtual bScore CalcBestMove(bBoard &b, bMoveList &ml)=0
constexpr bScore realScore() const
Definition searchscore.h:66
static constexpr bool isUndefinedScore(bScore const score)
virtual void sendDebug(int const l, std::string const &info)
virtual void sendInfoDepth(int depth, int seldepth, int64_t nodes, int nps)
int getLevel() const
Definition bel_debug.h:51
@ GR_UNSET
Definition eval.h:35
@ GR_UNKNOWN
Definition eval.h:36
enum gameResult gameResult_t
Definition eval.h:43
int16_t bScore
Definition eval.h:11
constexpr bScore SCORE_WINNING
Definition eval.h:25
constexpr bScore SCORE_UNDEFINED
Definition eval.h:21
@ MateSearch
Definition level.h:46
std::string to_string(int16_t value)
std::to_string not compatible on Mac OS (Apple LLVM version 5.0) provide generic utility function
Definition util.cpp:171