Belofte version 2.1.9
A promising chess program using the UCI or Winboard interface
game.cpp
Go to the documentation of this file.
1/*---------------------------------------------------------------------+
2 * File: game.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#if defined(__GNUC__)
11#pragma GCC diagnostic push
12#pragma GCC diagnostic ignored "-Weffc++"
13#endif
14
16{
17 newGame();
18}
19
20#if defined(__GNUC__)
21#pragma GCC diagnostic pop
22#endif
23
25{
26 m_result = GR_UNKNOWN;
27 m_pgnTags.clear();
28 m_pgnTags["Event"] = "Running on " MYOS " " MYPLATFORM;
29 m_pgnTags["Site"] = "";
30 m_pgnTags["Date"] = belofte::currentDate();
31 m_pgnTags["Round"] = "";
32 m_pgnTags["White"] = MYNAME " " MYVERSION " build " MYRELEASEDATE;
33 m_pgnTags["Black"] = MYNAME " " MYVERSION " build " MYRELEASEDATE;
34 m_pgnTags["Result"] = getResult(m_result);
35 m_optTags.clear();
36 m_optTags["eloWhite"] = "";
37 m_optTags["eloBlack"] = "";
38 m_positions.clear();
40}
41
43{
44 m_positions.clear();
45 m_positions.emplace_back(bFen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"));
46 m_optTags.erase("SetUp");
47 m_optTags.erase("FEN");
48}
49
50void bGame::setFEN(std::string const& fenstr)
51{
52 m_positions.clear();
53 m_positions.emplace_back(bFen(fenstr));
54 m_optTags["SetUp"] = "1";
55 m_optTags["FEN"] = fenstr;
56}
57
58void bGame::setPlayerName(std::string const& n)
59{
60 if (getCurrentPosition().whiteToMove()) {
61 m_pgnTags["White"] = n;
62 } else {
63 m_pgnTags["Black"] = n;
64 }
65}
66
67/**
68 * Start search thread and exit
69 * in case of batch mode, will wait until end of search
70 */
72{
73 if (App().m_reader.isBatchMode()) {
74 /// in case of batch mode, do not start separate thread for searching
75 /// @todo allow for cancel search with ? / stop command
77 } else {
78 if (getCurrentPosition().whiteToMove()) {
79 m_pgnTags["White"] = App().getConfig("enginename", "");
80 m_pgnTags["Black"] = App().getConfig("opponent", "");
81 } else {
82 m_pgnTags["White"] = App().getConfig("opponent", "");
83 m_pgnTags["Black"] = App().getConfig("enginename", "");
84 }
85 std::thread th(&bGame::WaitForSearchEnd, std::ref(*this));
86 th.detach();
87 }
88}
89
94
95/**
96 * Called in separate thread, sure to terminate normally
97 */
99{
101 try {
102 bMoveList ml;
104 bMove m(ml[ml.getBestMoveId()]);
105 AppEI()->sendMove(b, m);
107 AppEI()->sendResult(b, getResult());
108 } catch (const noMoveFoundException&) {
109 // ignore error
110 AppEI()->sendError("no move found", "Wait for search");
111 } catch (const gameEndException&) {
112 // we already sent result earlier
113 /// @todo handle sending result here
114 } catch (...) { throw; // push other exceptions down
115 }
116}
117
118/**
119 * do perft search using SearchPerft algorithm at depth
120 */
122{
123 SearchPerft search;
124 return DoPerft(search, d);
125}
126
127/**
128 * do perft search at depth
129 * in case of Perft algorithm, temporarily set evaltype to None
130 */
131int64_t bGame::DoPerft(bSearchAlgorithm& search, depth_t const d)
132{
133 bLevel oldLevel = m_level;
135 m_level.setDepthCommand(d);
136
137 std::string sAlgName = getAlgorithm()->operator std::string();
138 std::string sEval = getEval()->operator std::string();
139
140 if (sAlgName == "Perft") setEval("None");
141
142 int iSearchVerbose = App().sout.getLevel();
143 App().sout.setLevel(-2);
144 int iOutputVerbose = App().bout.getLevel();
145 App().bout.setLevel(-1);
146
147 try {
148 bMoveList ml;
149 search.setBench();
150 search.SearchBestMove(b, ml);
151 search.clearBench();
152 } catch (const noMoveFoundException&) {
153 // ignore error
154 } catch (...) { throw; // push other exceptions down
155 }
156
157 App().bout.setLevel(iOutputVerbose);
158 App().sout.setLevel(iSearchVerbose);
159
160 if (sAlgName == "Perft") setEval(sEval);
161
162 m_level = oldLevel;
163 return search.getNodes();
164}
165
167{
168 return getEval()->getEvaluation(b) * b.minimizing();
169}
170
171std::string bGame::getResult(gameResult_t gr) const
172{
173 if (gr == GR_UNKNOWN) return "*";
174 if (bPositionEvaluation::isDrawResult(gr)) return "1/2-1/2";
175 if ((gr >= GR_WHITEMATES) && (gr <= GR_WHITEWINS_FLAG)) return "1-0";
176 return "0-1";
177}
178
180{
181 m_result = gr;
182 m_pgnTags["Result"] = getResult(m_result);
183}
184
185/**
186 * all moves in a single string
187 * @return false if one move cannot be played
188 */
189bool bGame::playGameMoveSeries(std::string const& coordmoves)
190{
191 std::vector<std::string> vstrings = belofte::stringSplit(coordmoves, " ");
192
193 return std::all_of(vstrings.begin(), vstrings.end(),
194 [this](std::string const& s){ return this->playGameMove(bCoordMove(s)); });
195}
196
197/**
198 * apply move, it will change the current board by updating the move played
199 * it will also add the new board to the game positions list
200 */
201bool bGame::playGameMove(bCoordMove const& coordmove)
202{
203 bBoard const& b = getCurrentPosition();
204 bMoveList ml;
205 ml.clearNeedSorted();
206 ml.clearKeepScores();
207 ml.generateMoves(b);
208 movenum_t n_moves = ml.getNumberOfMoves();
209 for (movenum_t moveid = 1; moveid <= n_moves; ++moveid) {
210 bMove m(ml[moveid]);
211 bCoordMove cm(m);
212 if (cm == coordmove) {
213 bBoard newboard(b);
214 newboard.applyMove(m);
215 newboard.setMove(m.getFromTo());
216 newboard.calcGameStage();
217 m_positions.push_back(newboard);
218 bScore sc = Game()->EvalForPlayer(newboard);
221 } else if (bSearchScore::isUndefinedScore(sc)) {
222 // skip
223 } else if (sc == -SCORE_MATE) {
225 } else if (sc == SCORE_MATE) {
227 }
228 return true;
229 }
230 }
231 return false;
232}
233
234/**
235 * required for Winboard protocol, not supported in UCI (except debug)
236 */
237void bGame::revertGameMove(std::string const& reason)
238{
239 if (m_positions.size() > 1) {
240 m_positions.pop_back();
243 } else {
244 AppEI()->sendError("cannot undo move", reason);
245 }
246}
247
248/**
249 * do actual epd position test
250 */
252{
253 bMove m;
254
255 int iOldSoutLevel = App().sout.getLevel();
256 App().sout.setLevel(-2);
257
258 newGame();
259 setFEN(fen);
261 try {
262 bMoveList ml;
264 m = ml[ml.getBestMoveId()];
265 } catch (const noMoveFoundException&) {
266 // not returning no move found
267 } catch (...) { throw; // push other exceptions down
268 }
269
270 App().sout.setLevel(iOldSoutLevel);
271 return m;
272}
273
274/// @todo Look at using stream and << operator instead of string
275std::string bGame::movesinpgnformat() const
276{
277 std::stringstream sMoves;
278 std::stringstream sMovePrefix;
279
280 if (m_positions.size() > 1) {
281 if (m_positions[0].blackToMove()) {
282 sMovePrefix << m_positions[0].getMoveNumber() << "... ";
283 }
284
285 for (unsigned int i = 1; i < m_positions.size(); ++i) {
286 bBoard newboard(m_positions[i]);
287 bBoard ob(m_positions[i - 1]);
288 if (newboard.getMove()) {
289 if (ob.whiteToMove()) {
290 sMovePrefix << newboard.getMoveNumber() << ". ";
291 }
292 bPgnMove pm(ob, newboard.getMove());
293 sMoves << sMovePrefix.str() << pm << " ";
294 sMovePrefix.str("");
295 }
296 }
297 }
298
299 sMoves << getResult(getResult());
300 return sMoves.str();
301}
302
303/// @todo Look at using stream and << operator instead of std::string
304bGame::operator std::string() const
305{
306 std::string sGameHeader = "";
307
308 // Export tags (7-tag roster)
309 for (auto const& x : m_pgnTags) {
310 sGameHeader += "[" + x.first + " \"" + x.second + "\"]" + "\n";
311 }
312
313 // only in extended PGN format, for values that are present
314 for (auto const& x : m_optTags) {
315 if (x.second.size()) {
316 sGameHeader += "[" + x.first + " \"" + x.second + "\"]" + "\n";
317 }
318 }
319 return sGameHeader + "\n" + movesinpgnformat();
320}
321
322// 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.
#define MYRELEASEDATE
Definition belofte.h:44
uint_fast8_t movenum_t
Definition belofte.h:100
#define MYVERSION
Definition belofte.h:33
#define MYNAME
Definition belofte.h:31
int_fast8_t depth_t
Definition belofte.h:103
outputWriter sout
normal output
Definition belofte.h:174
outputWriter bout
Definition belofte.h:173
int64_t getConfig(std::string const &s, int64_t v)
Definition belofte.cpp:183
constexpr bool whiteToMove() const
Definition basicboard.h:156
constexpr bScore minimizing() const
Definition basicboard.h:166
constexpr fromto_t getFromTo() const
Definition basicmove.h:70
board
Definition board.h:45
void clearMove()
Definition board.h:80
boardInfo_t applyMove(bMove const &m) override
modification of board move is kept on previous board newboard does not have move stored and has flag ...
Definition board.cpp:217
void setMove(bmove_t const bmt)
Definition board.h:82
void calcGameStage()
calculate stage of game to assist in evaluation
Definition board.cpp:139
void setEval(std::string const &e)
bSearchAlgorithm * getAlgorithm() const
bPositionEvaluation * getEval() const
simple coordmove, with 4 characters, or 5 characters in case of promotion mostly used for interface
Definition coordmove.h:15
FEN string.
Definition fen.h:14
bMove getEpdMoveInPosition(bFen const &fen)
do actual epd position test
Definition game.cpp:251
bScore EvalForPlayer(bBoard const &b)
Definition game.cpp:166
bool playGameMove(bCoordMove const &coordmove)
apply move, it will change the current board by updating the move played it will also add the new boa...
Definition game.cpp:201
void setResult(gameResult_t gr)
Definition game.cpp:179
void setPlayerName(std::string const &n)
Definition game.cpp:58
int64_t DoPerft(bSearchAlgorithm &sa, depth_t const d)
do perft search at depth in case of Perft algorithm, temporarily set evaltype to None
Definition game.cpp:131
void WaitForSearchEnd()
Called in separate thread, sure to terminate normally.
Definition game.cpp:98
void AbortSearch()
Definition game.cpp:90
void newGame()
Definition game.cpp:24
void revertGameMove(std::string const &reason)
required for Winboard protocol, not supported in UCI (except debug)
Definition game.cpp:237
bLevel & getLevel()
Definition game.h:59
void DoSearch()
Start search thread and exit in case of batch mode, will wait until end of search.
Definition game.cpp:71
bGame()
Definition game.cpp:15
bool playGameMoveSeries(std::string const &coordmoves)
all moves in a single string
Definition game.cpp:189
void setFEN(std::string const &fenstr)
Definition game.cpp:50
int64_t DoPerftCommand(depth_t const d)
do perft search using SearchPerft algorithm at depth
Definition game.cpp:121
gameResult_t getResult() const
Definition game.h:41
bBoard & getCurrentPosition()
Definition game.h:54
void setFENInitialPos()
Definition game.cpp:42
Definition level.h:48
void flagLevelChanged()
Definition level.h:68
Definition move.h:13
void clearNeedSorted()
Definition movelist.h:75
movenum_t generateMoves(bBasicBoard const &b)
generate moves if not yet generated
Definition movelist.cpp:340
void clearKeepScores()
Definition movelist.h:79
constexpr movenum_t getBestMoveId() const
Definition movelist.h:66
constexpr movenum_t getNumberOfMoves() const
Definition movelist.h:34
static bool isDrawResult(gameResult_t const gr)
Definition eval.h:70
virtual bScore getEvaluation(bBoard const &b) const
get final score or 0
Definition eval.cpp:433
constexpr int64_t getNodes() const
Definition search.h:91
void clearBench()
Definition search.h:118
void InterruptSearch()
Definition search.h:101
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
void setBench()
Definition search.h:116
static constexpr bool isDrawScore(bScore const score)
static constexpr bool isUndefinedScore(bScore const score)
virtual void sendResult(bBoard const &b, gameResult_t const gr) const
virtual void sendMove(bBoard &b, bMove const &m)
virtual void sendError(std::string const &error, std::string const &description)
int getLevel() const
Definition bel_debug.h:51
void setLevel(int const l)
Definition bel_debug.h:49
@ GR_DRAW_OTHER
Definition eval.h:38
@ GR_WHITEWINS_FLAG
Definition eval.h:39
@ GR_UNKNOWN
Definition eval.h:36
@ GR_WHITEMATES
Definition eval.h:39
@ GR_BLACKMATES
Definition eval.h:40
constexpr bScore SCORE_MATE
Definition eval.h:24
enum gameResult gameResult_t
Definition eval.h:43
int16_t bScore
Definition eval.h:11
#define MYPLATFORM
no matching platform
Definition myplatform.h:73
#define MYOS
no matching OS
Definition myplatform.h:117
stringList const stringSplit(std::string src, std::string const &delim)
Split delimited long string into a vector.
Definition util.cpp:133
std::string currentDate()
Definition util.cpp:279