Belofte version 2.1.8
A promising chess program using the UCI or Winboard interface
usercmd.cpp
Go to the documentation of this file.
1/*---------------------------------------------------------------------+
2 * File: usercmd.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 std::string const& h)
14 : m_name(s)
15 , m_hint(h)
16{
17}
18
22
23void engineUserCommand::execute(std::string const& args)
24{
25 AppEI()->sendError("unimplemented command, not executing",
26 m_name + " <" + args + ">");
27}
28
29//-----------------------------------------------------------------------
30
32 std::string const& h)
33 : engineUserCommand(s, h)
34{
35}
36
40
42 std::string const& h)
43 : UCIengineCommand(s, h)
44{
45}
46
50
52 std::string const& h)
53 : engineUserCommand(s, h)
54{
55}
56
60
61Xboard2engineCommand::Xboard2engineCommand(std::string const& s, std::string const& h)
62 : engineUserCommand(s, h)
63{
64}
65
69
70dummyEngineCommand::dummyEngineCommand(std::string const& s, std::string const& h)
71 : engineUserCommand(s, h)
72{
73 m_isImplemented = false;
74}
75
79
80//-----------------------------------------------------------------------
81
83 : m_command("")
84 , m_args("")
85{
86}
87
91
92//-----------------------------------------------------------------------
93
94/**
95 * Send help on command or all commands
96 * @param args --all means all commands, '' or a single command
97 * unsupported means all plus unsupported commands
98 * hidden means all plus hidden commands
99 */
100void engineInterface::sendHelp(std::string const& args)
101{
102 belofte::stringList sParams = belofte::stringSplit(args, " ");
103 bool bUnsupported = std::any_of(sParams.begin(), sParams.end(),
104 [](std::string const& s)
105 { return s == "unsupported"; });
106 bool bUnpublished = std::any_of(sParams.begin(), sParams.end(),
107 [](std::string const& s)
108 { return s == "hidden"; });
109 if (bUnsupported || bUnpublished || args == "") {
110 // trigger all case
111 sParams.emplace_back("all");
112 }
113 if (std::any_of(sParams.begin(), sParams.end(),
114 [](std::string const& s)
115 { return ((s == "all") || (s == "--all")); })) {
116 App().bout << "Help for " MYNAME " - mode: " << m_name << "\n";
117 for (auto const& ec : engineInterface::m_engineCommands) {
119 bool bAllowed = m_allowedCommands.find(v->m_name) != m_allowedCommands.end();
120 if (bUnsupported && !v->m_isImplemented) {
121 App().bout << std::left << std::setw(10) << v->m_name
122 << " - " << v->m_hint
123 << (v->m_isImplemented ? "" : " (u)")
124 << "\n";
125 } else if ((bUnpublished || bAllowed) && v->m_isImplemented) {
126 App().bout << std::left << std::setw(10) << v->m_name
127 << " - " << v->m_hint
128 << (bAllowed ? "" : " (h)")
129 << "\n";
130 }
131 }
132 if (bUnsupported) App().bout << "\nu: Unsupported.";
133 if (bUnpublished) App().bout << "\nh: Hidden";
134 } else {
135 App().bout << "Help for " MYNAME << "\n";
139 App().bout << std::left << std::setw(10) << v->m_name
140 << " - " << v->m_hint << "\n";
141 if (!v->m_isImplemented)
142 App().bout << "\n** Unsupported **";
143 } else {
144 App().bout << "Unknown command [" << args << "]";
145 }
146 }
147 App().bout.endl();
148}
149
150void engineInterface::sendResponse(std::string const& response)
151{
152 App().bout << response;
153 App().bout.endl();
154}
155
156void engineInterface::sendError(std::string const& error, std::string const& description)
157{
158 App().bout(-2) << "ERROR: " << error;
159 if (!description.empty()) App().bout << " (" << description << ")";
160 App().bout.endl();
161}
162
163void XboardMode::sendInfo(std::string const& info)
164{
165 App().sout << "# "; // TOCHECK: line needs to be split for respecting tmplevel
166 App().sout << info;
167 App().sout.endl();
168}
169
170void XboardMode::sendDebug(int const l, std::string const& info)
171{
172 App().bout(l) << "# ";
173 App().bout << info; // TOFIX: why do we need to split in 2 lines?
174 App().bout.endl();
175}
176
177//-----------------------------------------------------------------------
178
179void UCIMode::sendMove(bBoard& b UNUSED, bMove const& m)
180{
181 std::stringstream sOut;
182 sOut << "bestmove " << bCoordMove(m);
183 // TODO: retrieve ponder out of board
184 // if (ponder != "") sOut << " ponder " << ponder;
185 App().sout(-2) << sOut.str();
186 App().sout.endl();
187}
188
189void UCIMode::sendInfo(std::string const& info)
190{
191 App().sout << "info string ";
192 App().sout << info;
193 App().sout.endl();
194}
195
196void UCIMode::sendDebug(int const l, std::string const& info)
197{
198 App().bout(l) << "info string ";
199 App().bout << info;
200 App().bout.endl();
201}
202
203void UCIMode::sendInfoDepth(int depth, int seldepth DEVUNUSED, int64_t nodes, int nps)
204{
205 if (depth <= App().sout.getLevel()) {
206 std::stringstream sOut;
207 sOut << "info depth " << depth
208#if !defined(_DEBUG)
209 << " seldepth " << seldepth
210#endif
211 << " nodes " << nodes
212 << " nps " << nps;
213 App().sout << sOut.str();
214 App().sout.endl();
215 }
216}
217
218void UCIMode::sendInfoScore(long long timems DEVUNUSED, bBoard const& b,
219 bScore const sc)
220{
221 if (0 <= App().sout.getLevel()) {
222 std::stringstream sOut;
223 bScore mateinx = 0;
224 if ((sc < SCORE_ALMOST_NORMAL) && (sc > SCORE_WINNING)) {
225 mateinx = SCORE_MATE + 1 - sc;
226 } else if ((sc > -SCORE_ALMOST_NORMAL) && (sc < -SCORE_WINNING)) {
227 mateinx = -SCORE_MATE - 1 + sc;
228 }
229 sOut << "info";
230 if (mateinx) {
231 sOut << " score mate " << mateinx;
232 } else if (sc == -SCORE_INFINITE) {
233 sOut << " score lowerbound";
234 } else if (sc == SCORE_INFINITE) {
235 sOut << " score upperbound";
236 } else if ((sc & SCORE_POSITIVE) == SCORE_PUNDEFINED) {
237 // skip output
238 } else {
239 sOut << " score cp " << belofte::scoreAsStr(sc);
240 }
241#if !defined(_DEBUG)
242 if (timems) {
243 sOut << " time " << belofte::prettyTime(timems);
244 }
245#endif
246 if (b.getVariation().size()) {
247 sOut << " pv";
248 for (std::string const& m : b.getPreviousMoves()) sOut << " " << m;
249 for (std::string const& m : b.getVariation()) sOut << " " << m;
250 }
251 App().sout << sOut.str();
252 App().sout.endl();
253 }
254}
255
256void UCIMode::sendInfoSearching(bBoard const& b, int const nLogDepth,
257 depth_t const nMaxDepth DEVUNUSED, std::string const& comment,
258 bScore const sc, int64_t const timems DEVUNUSED,
259 int64_t const nodes) const
260{
261 if (nLogDepth <= App().sout.getLevel()) {
262 int nVariationDepth = static_cast<int>(b.getVariation().size());
263 std::stringstream sOut;
264 sOut << "info";
265 if (nVariationDepth) sOut << " depth " << nVariationDepth;
266#if !defined(_DEBUG)
267 if (nVariationDepth != nMaxDepth) sOut << " seldepth " << static_cast<int>(nMaxDepth);
268 sOut << " time " << belofte::to_string(timems);
269 if (timems > 10) {
270 sOut << " nodes " << belofte::to_string(nodes)
271 << " nps " << belofte::to_string((nodes * 1000)/ timems);
272 }
273#else
274 sOut << " nodes " << belofte::to_string(nodes);
275#endif
276 if ((sc & SCORE_POSITIVE) == SCORE_PUNDEFINED) {
277 // skip output
278 } else if (sc >= SCORE_INFINITE) {
279 // TOCHECK: black scores inverted
280 sOut << " score upperbound";
281 } else if (sc <= -SCORE_INFINITE) {
282 // TOCHECK: black scores inverted
283 sOut << " score lowerbound";
284 } else {
285 sOut << " score cp " << belofte::scoreAsStr(sc);
286 }
287 if ((nLogDepth == 0) && nVariationDepth) {
288 sOut << " pv";
289 for (std::string const& m : b.getPreviousMoves()) sOut << " " << m;
290 for (std::string const& m : b.getVariation()) sOut << " " << m;
291 } else {
292 if (b.getPreviousMoves().size()) {
293 // TODO: only print currline in case requested by UI
294 sOut << " currline";
295 for (std::string const& m : b.getPreviousMoves()) sOut << " " << m;
296 }
297 if (nVariationDepth) {
298 sOut << " pv";
299 for (std::string const& m : b.getPreviousMoves()) sOut << " " << m;
300 for (std::string const& m : b.getVariation()) sOut << " " << m;
301 }
302 }
303 if (comment != "") sOut << " string " << comment;
304 sOut << "\n";
305 App().sout << sOut.str();
306 }
307}
308
309void UCIMode::sendInfoCurrMove(bBoard const& b, depth_t const nLogDepth,
310 depth_t const nMaxDepth DEVUNUSED, std::string const& comment DEVUNUSED,
311 bMove const& mv, movenum_t const moveid, int64_t const nodes) const
312{
313 if (nLogDepth <= App().sout.getLevel()) {
314 int nVariationDepth = static_cast<int>(b.getVariation().size());
315 std::stringstream sOut;
316 sOut << "info";
317 if (nVariationDepth) sOut << " depth " << nVariationDepth;
318#if !defined(_DEBUG)
319 if (nVariationDepth != nMaxDepth) sOut << " seldepth " << nMaxDepth;
320#endif
321 sOut << " nodes " << belofte::to_string(nodes);
322 sOut << " currmovenumber " << moveid;
323 sOut << " currmove ";
324 sOut << mv;
325#if !defined(_DEBUG)
326 if (nVariationDepth) {
327 // TODO: only print currline in case requested by UI
328 sOut << " currline";
329 for (std::string const& m : b.getPreviousMoves()) sOut << " " << m;
330 }
331 if (comment != "") sOut << " string " << comment;
332#endif
333 sOut << "\n";
334 App().sout << sOut.str();
335 }
336}
337
338//-----------------------------------------------------------------------
339
341{
342 App().bout << MYLCNAME << "> ";
343}
344
346{
347 App().sout(-2) << "move " << bPgnMove(b, m);
348 App().sout.endl();
349}
350
351void engineInterface::sendResult(bBoard const& b, gameResult_t const rs) const
352{
353 if (rs != GR_UNKNOWN) {
354 // end of game, so stop running
355 AppEI()->setRunning(false);
356 App().sout(-2) << Game()->getResult(rs);
357 if ((rs >= GR_DRAW_STALEMATE) && (rs <= GR_DRAW_OTHER)) {
358 gameResult_t nrs = Game()->EvalFinalScore(b);
359 if (nrs == GR_DRAW_STALEMATE) {
360 App().sout << " {Stalemate}";
361 } else if (nrs == GR_DRAW_LACKMATERIAL) {
362 App().sout << " {Draw by insufficient material}";
363 } else if (nrs == GR_DRAW_THREEFOLD) {
364 App().sout << " {Draw by repetition}";
365 } else if (nrs == GR_DRAW_50) {
366 App().sout << " {50 move rule}";
367 } else {
368 App().sout << " {Draw}";
369 }
370 } else if ((rs >= GR_WHITEMATES) && (rs <= GR_WHITEWINS_FLAG)) {
371 App().sout << " {White mates}";
372 } else {
373 App().sout << " {Black mates}";
374 }
375 App().sout.endl();
376 }
377}
378
379void XboardMode::sendInvalidMove(std::string const& mv, std::string const& reason)
380{
381 App().bout(-2) << "Illegal move: " << mv;
382 if (reason != "") App().bout << " (" << reason << ")";
383 App().bout.endl();
384}
385
386void XboardMode::sendInfoSearching(bBoard const& b, int const nLogDepth,
387 depth_t const nMaxDepth, std::string const& comment UNUSED,
388 bScore const sc, int64_t const t, int64_t const nodes) const
389{
390 if (nLogDepth <= App().sout.getLevel()) {
391 int nVariationDepth = static_cast<int>(b.getVariation().size());
392 if (((sc & SCORE_POSITIVE) != SCORE_PUNDEFINED)
393 && (nVariationDepth)) {
394 std::stringstream sNew;
395 for (std::string const& m : b.getPreviousMoves()) sNew << " " << m;
396 for (std::string const& m : b.getVariation()) sNew << " " << m;
397 if (sNew.str().size()) {
398 static std::string& sOld = *new std::string();
399 if (sNew.str() != sOld) {
400 // only post updates
401 sOld = sNew.str();
402 App().sout << " " << std::setw(3) << nVariationDepth
403 << (nVariationDepth == nMaxDepth ? " " : "&");
404 App().sout << " " << std::setw(8) << belofte::to_string(sc);
405 App().sout << " " << std::setw(6) << (t / 10);
406 App().sout << " " << std::setw(8) << nodes;
407 App().sout << sOld;
408 App().sout << "\n";
409 }
410 }
411 }
412 }
413}
414
415//-----------------------------------------------------------------------
416// command implementation
417
418void cmd_help::execute(std::string const& args)
419{
420 AppEI()->sendHelp(args);
421}
422
423void cmd_quit::execute(std::string const& args UNUSED)
424{
425 App().bout << "Bye\n";
426 throw quitCommandException();
427}
428
429void cmd_about::execute(std::string const& args UNUSED)
430{
431 App().bout << App().getConfig("enginename", "") << '\n'
432 << App().getConfig("author", "")
433 << std::endl;
434}
435
436void cmd_usage::execute(std::string const& args)
437{
438 App().bout << "Usage: " << args << " [options] [[@]script] \n"
439 << "\t--help\t\tThis help message\n"
440 << "\t--version\tShow version information\n"
441 << "\t--uci\t\tUse UCI interface\n"
442 << "\t--xboard\tUse Xboard/Winboard interface\n"
443 << "\t[script]\tcontaining commands to execute.";
444 App().bout.endl();
445}
446
447void cmd_uci::execute(std::string const& args UNUSED)
448{
449 App().setMode("uci");
450 AppEI()->sendResponse("");
451 AppEI()->sendResponse("id name " MYFULLNAME " (u)");
452 AppEI()->sendResponse("id author " MYAUTHOR);
453 AppEI()->sendResponse("option name alg type combo default AB "
454 "var Random var StaticEval var BruteForce "
455 "var SearchIterativeBF var AB var ABFS var ABFH");
456 AppEI()->sendResponse("option name evaltype type combo default PositionalBoard "
457 "var PiecesOnly var StaticBoard var PositionalBoard");
458 AppEI()->sendResponse("option name UCI_Variant type combo default normal "
459 "var normal");
460 AppEI()->sendResponse("option name UCI_EngineAbout type string default "
461 + App().getConfig("about", ""));
462 AppEI()->sendResponse("option name UCI_Opponent type string default <empty>");
463 // option name x type string default <empty>
464 // TODO: option name UCI_Chess960 type check default false
465 // setoption name UCI_Chess960 value true
466 // setoption name UCI_Variant value fischerandom
467 // TODO: option name UCI_AnalyseMode
468 AppEI()->sendResponse("uciok");
469}
470
471void cmd_xboard::execute(std::string const& args UNUSED)
472{
473 App().setMode("xboard");
474 App().bout.endl();
475}
476
477void cmd_belofte::execute(std::string const& args UNUSED)
478{
479 App().setMode("belofte");
480}
481
482/** execute command file with @ command
483 * @warning command will do noting but change mode
484 * @see commandReader::runner() for actual parsing
485 */
486void cmd_execat::execute(std::string const& args)
487{
488 if (args.substr(0,1) == "@") {
489 App().m_reader.attach(args.substr(1));
490 } else {
491 App().m_reader.attach(args);
492 }
493}
494
495/** execute command file with exec command
496 * @warning command will do noting but change mode
497 * @see commandReader::runner() for actual parsing
498 */
499void cmd_exec::execute(std::string const& args)
500{
501 App().m_reader.attach(args);
502}
503
504void cmd_echo::execute(std::string const& args)
505{
506 AppEI()->sendResponse(args);
507}
508
509/** check if engine still alive, doing delayed constructors
510 */
511void cmd_isready::execute(std::string const& args UNUSED)
512{
513 // readyok to be sent only after newgame has finished
514 AppEI()->sendResponse("readyok");
515}
516
517/** check if engine still alive, doing delayed constructors
518 */
519void cmd_ping::execute(std::string const& args)
520{
521 AppEI()->sendResponse("pong " + args);
522}
523
524void cmd_ucinewgame::execute(std::string const& args UNUSED)
525{
526 Game()->newGame();
527}
528
529void cmd_debug::execute(std::string const& args)
530{
532}
533
534/** Read setoption command
535 * @todo allow value parameter with space in it
536 */
537void cmd_setoption::execute(std::string const& args)
538{
539 belofte::stringList sOptions = belofte::stringSplit(args, " ");
540 if (sOptions.size() && sOptions[0] == "name") {
541 // if first element is 'name', suppress it (arena compatibility)
542 sOptions.erase(sOptions.begin());
543 }
544 if (sOptions.size() >= 2) {
545 /// @todo get array from initialisation
546 std::string const opt[] = {"alg", "evaltype", "UCI_Opponent",
547 "UCI_EngineAbout", "UCI_Variant"};
548 if (std::find(std::begin(opt), std::end(opt), sOptions[0])
549 != std::end(opt)) {
550 /// @todo change to specific setoption function
551 if (sOptions.size() == 2) {
552 AppEI()->execute(sOptions[0], "");
553 } else {
554 std::string sParams = std::accumulate(sOptions.begin() + 2, sOptions.end(), std::string(),
555 [](std::string result, std::string sElem) {
556 return std::move(result) + std::move(sElem) + " ";
557 });
558 AppEI()->execute(sOptions[0], sParams);
559 }
560 } else {
561 AppEI()->sendError("command not understood", args);
562 }
563 } else {
564 AppEI()->sendError("bad command parameters", args);
565 }
566}
567
568/** set start position, alternatives
569 * args = [fen 'fenstring' | startpos ] moves 'move1' .... 'movei'
570 * attention: should do noting if position set is identical to actual position
571 */
572void cmd_position::execute(std::string const& args)
573{
574 std::string startorfen = args.substr(0, args.find(' '));
575 std::size_t iMoves = args.find("moves ");
576 if (startorfen == "startpos" || startorfen == "") {
578 if (iMoves != std::string::npos) {
579 if (!Game()->playGameMoveSeries(args.substr(static_cast<unsigned long>(iMoves) + 6)))
580 AppEI()->sendInvalidMove(args.substr(static_cast<unsigned long>(iMoves) + 6), "");
581 }
582 } else if (startorfen == "fen") {
583 if (iMoves != std::string::npos) {
584 Game()->setFEN(args.substr(4, static_cast<unsigned long>(iMoves) - 4));
585 if (!Game()->playGameMoveSeries(args.substr(static_cast<unsigned long>(iMoves) + 6)))
586 AppEI()->sendInvalidMove(args.substr(static_cast<unsigned long>(iMoves) + 6), "");
587 } else {
588 Game()->setFEN(args.substr(4));
589 }
590 } else {
591 AppEI()->sendError("invalid parameter for position", args);
592 }
593}
594
595void cmd_bench::execute(std::string const& args)
596{
597 depth_t nDepth = 5;
598
599 if (args.size()) {
600 belofte::stringList goOptions = belofte::stringSplit(args, " ");
601 if (atoi(goOptions[0].c_str()) > 0) nDepth = static_cast<depth_t>(atoi(goOptions[0].c_str()));
602 }
603
604 { SearchPerft search; bel_debug::run_bench(search, nDepth); }
605 { SearchBruteForce search; bel_debug::run_bench(search, nDepth); }
606 { SearchAlphaBeta search; bel_debug::run_bench(search, nDepth); }
607
608 Game()->newGame();
610}
611
612void cmd_perft::execute(std::string const& args)
613{
614 belofte::stringList const goOptions = belofte::stringSplit(args, " ");
615 int perftdepth = 0;
616 if (!goOptions.empty()) perftdepth = atoi(goOptions[0].c_str());
617
618 SearchPerft search;
619 int64_t nNodes = Game()->DoPerft(search, perftdepth);
620 int64_t nNonLeafNodes = search.getNonLeafNodes();
621
622 std::string sNodes = belofte::to_string(nNodes);
623 std::string sTotalNodes = belofte::to_string(nNodes + nNonLeafNodes);
624 std::string sNPS = "0";
625 if ((nNodes + nNonLeafNodes) > 0LL) {
626 sNPS = belofte::to_string(static_cast<int64_t>(
627 (nNodes + nNonLeafNodes) * 1000000LL / search.getDurationMicroSec()));
628 }
629
630 if (Game()->isExpecting(sNodes)) {
631 std::stringstream ss;
632 ss << "perft " << args << " -> " << sNodes
633 << " (Total: " << sTotalNodes
634 << ") <- Execution time = " << search.getDuration()
635 << " NPS " << sNPS;
636 App().bout(-1) << ss.str();
637 App().bout.endl();
638 } else {
639 AppEI()->sendError("Expectation missed",
640 "perft " + args + " -> " + sNodes + " instead of <- "
641 + Game()->getExpecting());
642 }
643 // clear expect flag
644 Game()->setExpecting("");
645}
646
647/** Parse epd position or epd file
648 * e.g. epd pos fen-epd fen-params
649 * epd [file] 'filename'
650 */
651void cmd_epd::execute(std::string const& args)
652{
653 belofte::stringList sParams = belofte::stringSplit(args, " ");
655
656 // remove any modifier flags, -sts overrides -perf
657 if (std::any_of(sParams.begin(), sParams.end(),
658 [](std::string const& s)
659 { return s == "-perf"; })) {
660 sParams.erase(sParams.begin() + 1);
661 typeOfTest = tEpdTestType::EPD_PERF;
662 } else if (std::any_of(sParams.begin(), sParams.end(),
663 [](std::string const& s)
664 { return s == "-sts"; })) {
665 sParams.erase(sParams.begin() + 1);
666 typeOfTest = tEpdTestType::EPD_STS;
667 }
668
669 if (sParams.empty()) {
670 AppEI()->sendError("Parameter missing", "");
671 } else if (sParams[0] == "pos") {
672 sParams.erase(sParams.begin());
673 bEpdPos epd(sParams, typeOfTest);
674 epd.parse();
675 } else if (sParams[0] == "file") {
676 sParams.erase(sParams.begin());
677 bEpdFile epd(sParams, typeOfTest);
678 epd.parse();
679 } else {
680 // same as epd file
681 bEpdFile epd(args, typeOfTest);
682 epd.parse();
683 }
684}
685
686/** Parse epd position
687 * e.g. epdpos fen-epd fen-params
688 */
689void cmd_epdpos::execute(std::string const& args)
690{
692 epd.parse();
693}
694
695void cmd_go::execute(std::string const& args)
696{
697 belofte::stringList const goOptions = belofte::stringSplit(args, " ");
698 bLevel level;
699 int nDepth, nInf, nTime, nInc, nMoves, nMoveTime, nMate, nPonder;
700 int64_t nNodes;
701
702 nDepth = belofte::positionParamValue(goOptions, "depth", 1);
703 nInf = belofte::positionParamIndex(goOptions, "infinite");
704
705 if (Game()->getCurrentPosition().whiteToMove()) {
706 nTime = belofte::positionParamValue(goOptions, "wtime", 1);
707 nInc = belofte::positionParamValue(goOptions, "winc", 1);
708 } else {
709 nTime = belofte::positionParamValue(goOptions, "btime", 1);
710 nInc = belofte::positionParamValue(goOptions, "binc", 1);
711 }
712
713 nMoves = belofte::positionParamValue(goOptions, "movestogo", 1);
714 nMoveTime = belofte::positionParamValue(goOptions, "movetime", 1);
715
716 nNodes = belofte::positionParamValue(goOptions, "nodes", 1);
717 nMate = belofte::positionParamValue(goOptions, "mate", 1);
718 nPonder = belofte::positionParamIndex(goOptions, "ponder");
719
720 if (belofte::positionParamIndex(goOptions, "searchmoves") != -1) {
721 // TODO: add searchmoves
722 }
723
724 if (nDepth != -1) {
725 level.setDepthCommand(static_cast<depth_t>(nDepth));
726 } else if (nInf != -1) {
727 level.setInfinite();
728 } else if (nMoveTime != -1) {
729 level.setMoveTime(nMoveTime);
730 } else if (nTime != -1) {
731 if (nInc != -1) {
732 if (nMoves != -1) level.setMoveTime(nTime, nMoves, nInc);
733 else level.setGameTime(nTime, nInc);
734 } else {
735 if (nMoves != -1) level.setMoveTime(nTime, nMoves);
736 else level.setGameTime(nTime);
737 }
738 } else if (nMate != -1) {
739 level.setMateSearch(static_cast<depth_t>(nMate));
740 }
741
742 if (nNodes != -1) level.setNodes(nNodes);
743 if (nPonder != -1) level.setPondering();
744
745 if (args != "") Game()->setLevel(level);
746 AppEI()->setRunning(true);
747 Game()->DoSearch();
748}
749
750void cmd_again::execute(std::string const& args UNUSED)
751{
752 Game()->revertGameMove();
753 AppEI()->execute("go", "");
754}
755
756void cmd_usermove::execute(std::string const& args)
757{
758 if (!Game()->playGameMoveSeries(args)) {
759 AppEI()->sendInvalidMove(args, "");
760 return;
761 }
762 bBoard const& b = Game()->getCurrentPosition();
763 AppEI()->sendResult(b, Game()->getResult());
764
765 if (App().getMode() == "xboard") {
766 // xboard requires an update to number of moves remaining
767 if (AppEI()->isRunning()) {
768 // only decrease moves when about to move
770 AppEI()->execute("go", "");
771 } else if (b.whiteToMove()) {
772 // or decrease moves when white to move
774 }
775 }
776}
777
778void cmd_questionmark::execute(std::string const& args UNUSED)
779{
780 Game()->AbortSearch();
781}
782
783void cmd_stop::execute(std::string const& args UNUSED)
784{
785 Game()->AbortSearch();
786}
787
788void cmd_save::execute(std::string const& args UNUSED)
789{
790 App().bout << Game()->operator std::string() << "\n";
791}
792
793void cmd_game::execute(std::string const& args UNUSED)
794{
795 App().bout << Game()->operator std::string() << "\n";
796}
797
798void cmd_bd::execute(std::string const& args UNUSED)
799{
800 bBoard const& b = Game()->getCurrentPosition();
801 App().bout << b.operator std::string() << "\n";
802}
803
804void cmd_undo::execute(std::string const& args UNUSED)
805{
806 Game()->revertGameMove();
807}
808
809void cmd_easy::execute(std::string const& args UNUSED)
810{
812}
813
814void cmd_hard::execute(std::string const& args UNUSED)
815{
817}
818
819void cmd_ls::execute(std::string const& args)
820{
821 DIR *hDir;
822 std::string curdir = ".";
823 if (args.length()) curdir = args + ".";
824
825 hDir = opendir(curdir.c_str());
826 if (hDir) {
827 struct dirent *hFile;
828 while ((hFile = readdir(hDir)) != nullptr) {
829 std::string sFile(hFile->d_name);
830 if (sFile[0] == '.') continue;
831 App().bout << sFile
832#if !defined(NODIRENT)
833 << (hFile->d_type == DT_DIR ? "/" : "")
834#endif
835 << std::endl;
836 }
837 closedir(hDir);
838 }
839}
840
841void cmd_expect::execute(std::string const& args)
842{
843 Game()->setExpecting(args);
844}
845
846void cmd_new::execute(std::string const& args UNUSED)
847{
848 Game()->newGame();
850 AppEI()->setRunning(true);
851}
852
853void cmd_setboard::execute(std::string const& args)
854{
855 Game()->setFEN(args);
856}
857
858void cmd_random::execute(std::string const& args UNUSED)
859{
860 // toggle random setting, off by default
861 App().setConfig("random", App().getConfig("random", 0) ? 0 : 1);
862}
863
864void cmd_computer::execute(std::string const& args UNUSED)
865{
866 App().setConfig("computer", "computer");
867}
868
869void cmd_remove::execute(std::string const& args UNUSED)
870{
871 Game()->revertGameMove();
872 Game()->revertGameMove();
873}
874
875void cmd_protover::execute(std::string const& args UNUSED)
876{
877 if (App().getMode() != "xboard") {
878 AppEI()->execute("xboard", "");
879 }
880 AppEI()->sendResponse("feature done=0");
881 AppEI()->sendResponse("feature ping=1 setboard=1");
882 AppEI()->sendResponse("feature usermove=1 playother=1 colors=0 time=1");
883 AppEI()->sendResponse("feature draw=0 nps=0 memory=0 smp=0");
884 AppEI()->sendResponse("feature variants=\"normal\"");
885#if defined(BELOFTE_NOSIGNALS)
886 AppEI()->sendResponse("feature sigint=0 sigterm=0");
887#else
888 AppEI()->sendResponse("feature sigint=1 sigterm=1");
889#endif
890 AppEI()->sendResponse("feature analyze=0 debug=1 reuse=0 pause=0");
891 AppEI()->sendResponse("feature name=1");
892 AppEI()->sendResponse("feature myname=\"" MYFULLNAME " (wb)\"");
893 AppEI()->sendResponse("feature option=\"alg -combo AB /// Random /// StaticEval /// "
894 "BruteForce /// SearchIterativeBF /// ABFS /// ABFH\"");
895 AppEI()->sendResponse("feature option=\"evaltype -combo "
896 "PositionalBoard /// PiecesOnly /// StaticBoard\"");
897 AppEI()->sendResponse("feature done=1");
898}
899
900void cmd_playother::execute(std::string const& args UNUSED)
901{
902 AppEI()->setRunning(true);
903}
904
905void cmd_force::execute(std::string const& args UNUSED)
906{
907 AppEI()->setRunning(false);
908}
909
910void cmd_alg::execute(std::string const& args)
911{
912 Game()->setAlgorithm(args);
913}
914
915void cmd_evaltype::execute(std::string const& args)
916{
917 Game()->setEval(args);
918}
919
920void cmd_UCI_EngineAbout::execute(std::string const& args UNUSED)
921{
922}
923
924void cmd_UCI_Opponent::execute(std::string const& args)
925{
926 App().setConfig("opponent", args);
927 Game()->setPlayerName(args);
928}
929
930void cmd_name::execute(std::string const& args)
931{
932 App().setConfig("opponent", args);
933 Game()->setPlayerName(args);
934}
935
936void cmd_option::execute(std::string const& args)
937{
938 belofte::stringList const options = belofte::stringSplit(args, "=");
939 if (options.size() == 2) {
940 /// @todo get array from initialisation
941 std::string const opt[] = {"alg", "evaltype"};
942 if (std::find(std::begin(opt), std::end(opt), options[0])
943 != std::end(opt)) {
944 /// @todo change to specific setoption function
945 AppEI()->execute(options[0], options[1]);
946 } else {
947 AppEI()->sendError("option not understood", args);
948 }
949 } else {
950 AppEI()->sendError("bad option parameters", args);
951 }
952}
953
954void cmd_info::execute(std::string const& args UNUSED)
955{
957}
958
959void cmd_eval::execute(std::string const& args UNUSED)
960{
961 std::stringstream ss;
963
964 ss << "# Eval: (" << (b.minimizing() == 1 ? "maximizing) white" : "minimizing) black")
965 << " to move - " << Game()->getEval()->operator std::string();
966 #if !defined(BELOFTE_NORANDOM)
967 if (App().getConfig("random", 0)) ss << " +-Rnd";
968 #endif
969
970 if (b.getStage() == bGameStage::ST_OPENING) ss << " - Opening";
971 else if (b.getStage() == bGameStage::ST_ENDGAME) ss << " - Endgame";
972 else if (b.getStage() == bGameStage::ST_MATING) ss << " - Mating";
973 else if (b.getStage() == bGameStage::ST_PAWNENDING) ss << " - Pawnending";
974
975 bScore sc = Game()->EvalForPlayer(b);
976 ss << "\ninfo cp " << belofte::scoreAsStr(sc);
977
978 if (!App().getConfig("random", 0)) {
979 b.invertColours();
980 bScore isc = Game()->EvalForPlayer(b);
981 if (isc != sc) {
982 ss << " (inbalanced eval: "
983 << belofte::scoreAsStr(isc)
984 << ")";
985 }
986 b.invertColours();
987 }
988
989 App().bout << ss.str();
990 App().bout.endl();
991}
992
993//-----------------------------------------------------------------------
994// xboard implementation
995
996void cmd_sd::execute(std::string const& args)
997{
998 Game()->getLevel().setDepthCommand(static_cast<depth_t>(atoi(args.c_str())));
999}
1000
1001void cmd_fd::execute(std::string const& args)
1002{
1003 Game()->getLevel().setMateSearch(static_cast<depth_t>(atoi(args.c_str())));
1004}
1005
1006void cmd_level::execute(std::string const& args)
1007{
1008 belofte::stringList const levelOptions = belofte::stringSplit(args, " ");
1009 int nMovesPerPeriod = 0;
1010 int nTimePerPeriod = 0;
1011 int nIncrement = 0;
1013 if (levelOptions.size() == 3) {
1014 nMovesPerPeriod = atoi(levelOptions[0].c_str());
1015 nIncrement = atoi(levelOptions[2].c_str());
1016 belofte::stringList sPeriods = belofte::stringSplit(levelOptions[1], ":");
1017 if (sPeriods.size() == 2) {
1018 nTimePerPeriod = atoi(sPeriods[0].c_str()) * 60
1019 + atoi(sPeriods[1].c_str());
1020 } else {
1021 nTimePerPeriod = atoi(levelOptions[1].c_str()) * 60;
1022 }
1023 }
1024 // TODO: keep initial game time so that after move 35, all increment time is
1025 // used, currently, it is flapping around 10s left
1026 if (nMovesPerPeriod == 0) {
1027 if (nIncrement == 0) {
1028 Game()->getLevel().setGameTime(nTimePerPeriod * 1000);
1029 } else {
1030 Game()->getLevel().setGameTime(nTimePerPeriod * 1000,
1031 nIncrement * 1000);
1032 }
1033 } else {
1034 if (nIncrement == 0) {
1035 Game()->getLevel().setMoveTime(nTimePerPeriod * 1000,
1036 nMovesPerPeriod);
1037 } else {
1038 Game()->getLevel().setMoveTime(nTimePerPeriod * 1000,
1039 nMovesPerPeriod, nIncrement * 1000);
1040 }
1041 }
1042}
1043
1044void cmd_st::execute(std::string const& args)
1045{
1046 Game()->getLevel().setMoveTime(atoi(args.c_str())*1000);
1047}
1048
1049void cmd_time::execute(std::string const& args)
1050{
1051 // centiseconds to milliseconds conversion
1052 Game()->getLevel().setRemainingTime(atoi(args.c_str())*10);
1053}
1054
1055void cmd_post::execute(std::string const& args UNUSED)
1056{
1057 App().sout.setLevel(0);
1058}
1059
1060void cmd_nopost::execute(std::string const& args UNUSED)
1061{
1062 App().sout.setLevel(-1);
1063}
1064
1065// 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.
#define MYAUTHOR
Definition belofte.h:35
appInstance & App()
Definition belofte.cpp:480
#define MYLCNAME
Definition belofte.h:32
engineInterface * AppEI()
Definition belofte.cpp:486
bGame * Game()
Definition belofte.cpp:491
#define MYFULLNAME
Definition belofte.h:49
uint_fast8_t movenum_t
Definition belofte.h:109
#define MYNAME
Definition belofte.h:31
int_fast8_t depth_t
Definition belofte.h:112
int16_t bScore
void sendPrompt() override
Definition usercmd.cpp:340
std::string getDuration() const
Definition util.cpp:47
long long getDurationMicroSec() const
Definition util.cpp:61
void sendDebug(int const l, std::string const &info) override
Definition usercmd.cpp:196
void sendInfoScore(long long timems, bBoard const &b, bScore const cp) override
Definition usercmd.cpp:218
void sendInfoDepth(int depth, int seldepth, int64_t nodes, int nps) override
Definition usercmd.cpp:203
void sendMove(bBoard &b, bMove const &m) override
Definition usercmd.cpp:179
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 override
Definition usercmd.cpp:309
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 override
Definition usercmd.cpp:256
void sendInfo(std::string const &info) override
Definition usercmd.cpp:189
Sub-class to react uniformly on UCI interface specific stuff.
Definition usercmd.h:56
UCIengineCommand(std::string const &s, std::string const &h)
Definition usercmd.cpp:31
~UCIengineCommand() override
Definition usercmd.cpp:37
~UCIengineOption() override
Definition usercmd.cpp:47
UCIengineOption(std::string const &s, std::string const &h)
Definition usercmd.cpp:41
~Xboard1engineCommand() override
Definition usercmd.cpp:57
Xboard1engineCommand(std::string const &s, std::string const &h)
Definition usercmd.cpp:51
~Xboard2engineCommand() override
Definition usercmd.cpp:66
Xboard2engineCommand(std::string const &s, std::string const &h)
Definition usercmd.cpp:61
void sendDebug(int const l, std::string const &info) override
Definition usercmd.cpp:170
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 override
Definition usercmd.cpp:386
void sendInvalidMove(std::string const &info, std::string const &reason) override
Definition usercmd.cpp:379
void sendInfo(std::string const &info) override
Definition usercmd.cpp:163
outputWriter sout
normal output
Definition belofte.h:331
bel_debug m_debuginterface
Definition belofte.h:334
void setConfig(std::string const &s, int64_t v)
Definition belofte.cpp:433
outputWriter bout
Definition belofte.h:330
int64_t getConfig(std::string const &s, int64_t v)
Definition belofte.cpp:438
std::string const setMode(std::string const &iName)
Definition belofte.cpp:425
commandReader m_reader
searching output
Definition belofte.h:332
bool whiteToMove() const
Definition board.h:80
board
Definition board.h:147
bGameStage getStage() const
Definition board.h:177
void invertColours()
invert colours update kingpos, update colour to move, castle rights, ...
Definition board.cpp:764
movesequence_t const & getPreviousMoves() const
Definition board.h:186
movesequence_t const & getVariation() const
Definition board.h:189
bScore minimizing() const
Definition board.h:180
void setAlgorithm(std::string const &alg)
void setEval(std::string const &e)
bPositionEvaluation * getEval() const
simple coordmove, with 4 characters, or 5 characters in case of promotion mostly used for interface
Definition coordmove.h:14
virtual bEpdResult parse() final
Main epd parser for multiple lines of epd file Will calculate a total score and some statistics.
virtual bEpdResult parse()
bScore EvalForPlayer(bBoard const &b)
Definition game.cpp:151
void revertGameMove()
required for Winboard protocol, not supported in UCI (except debug)
Definition game.cpp:237
void setPlayerName(std::string const &n)
Definition game.cpp:62
std::string getResult(gameResult_t rs) const
Definition game.cpp:183
void setExpecting(std::string const &s)
Following command should return value as expected.
Definition game.cpp:164
void AbortSearch()
Definition game.cpp:100
void newGame()
Definition game.cpp:28
bLevel & getLevel()
Definition game.h:53
void DoSearch()
Start search thread and exit in case of batch mode, will wait until end of search.
Definition game.cpp:81
gameResult_t EvalFinalScore(bBoard const &b)
Definition game.cpp:156
void setFEN(std::string const &fenstr)
Definition game.cpp:54
int64_t DoPerft(bSearchAlgorithm &sa, int const d)
do perft search at depth
Definition game.cpp:126
bBoard & getCurrentPosition()
Definition game.cpp:73
void setLevel(bLevel const &l)
Definition game.h:52
void setFENInitialPos()
Definition game.cpp:46
Definition level.h:49
void clearPondering()
Definition level.cpp:294
void flagLevelChanged()
Definition level.cpp:27
void setGameTime(int const msPerGame)
new level or new game
Definition level.cpp:43
void setInfinite()
Definition level.cpp:32
void setRemainingTime(int const msPerGame)
xboard issues time command to update available time
Definition level.cpp:157
void setMovePlayed()
Definition level.cpp:167
void setMoveTime(int const msPerMove)
Definition level.cpp:81
void setMateSearch(depth_t const d)
Definition level.cpp:144
void setNodes(int64_t n)
Definition level.cpp:269
void setPondering()
Definition level.cpp:289
void setDepthCommand(depth_t const d)
Definition level.cpp:250
Definition move.h:69
PgnMove is for user-interface only.
Definition pgnmove.h:12
int64_t getNonLeafNodes() const
Definition search.h:93
void info() const
Definition bel_debug.cpp:79
static void run_bench(bSearchAlgorithm &search, depth_t const nDepth)
void execute(std::string const &args)
Definition bel_debug.cpp:16
void execute(std::string const &args) override
Definition usercmd.cpp:920
void execute(std::string const &args) override
Definition usercmd.cpp:924
void execute(std::string const &args) override
Definition usercmd.cpp:429
void execute(std::string const &args) override
Definition usercmd.cpp:750
void execute(std::string const &args) override
Definition usercmd.cpp:910
void execute(std::string const &args) override
Definition usercmd.cpp:798
void execute(std::string const &args) override
Definition usercmd.cpp:477
void execute(std::string const &args) override
Definition usercmd.cpp:595
void execute(std::string const &args) override
Definition usercmd.cpp:864
void execute(std::string const &args) override
Definition usercmd.cpp:529
void execute(std::string const &args) override
Definition usercmd.cpp:809
void execute(std::string const &args) override
Definition usercmd.cpp:504
void execute(std::string const &args) override
Parse epd position or epd file e.g.
Definition usercmd.cpp:651
void execute(std::string const &args) override
Parse epd position e.g.
Definition usercmd.cpp:689
void execute(std::string const &args) override
Definition usercmd.cpp:959
void execute(std::string const &args) override
Definition usercmd.cpp:915
void execute(std::string const &args) override
execute command file with exec command
Definition usercmd.cpp:499
void execute(std::string const &args) override
execute command file with @ command
Definition usercmd.cpp:486
void execute(std::string const &args) override
Definition usercmd.cpp:841
void execute(std::string const &args) override
Definition usercmd.cpp:1001
void execute(std::string const &args) override
Definition usercmd.cpp:905
void execute(std::string const &args) override
Definition usercmd.cpp:793
void execute(std::string const &args) override
Definition usercmd.cpp:695
void execute(std::string const &args) override
Definition usercmd.cpp:814
void execute(std::string const &args) override
Definition usercmd.cpp:418
void execute(std::string const &args) override
Definition usercmd.cpp:954
void execute(std::string const &args) override
check if engine still alive, doing delayed constructors
Definition usercmd.cpp:511
void execute(std::string const &args) override
Definition usercmd.cpp:1006
void execute(std::string const &args) override
Definition usercmd.cpp:819
void execute(std::string const &args) override
Definition usercmd.cpp:930
void execute(std::string const &args) override
Definition usercmd.cpp:846
void execute(std::string const &args) override
Definition usercmd.cpp:1060
void execute(std::string const &args) override
Definition usercmd.cpp:936
void execute(std::string const &args) override
Definition usercmd.cpp:612
void execute(std::string const &args) override
check if engine still alive, doing delayed constructors
Definition usercmd.cpp:519
void execute(std::string const &args) override
Definition usercmd.cpp:900
void execute(std::string const &args) override
set start position, alternatives args = [fen 'fenstring' | startpos ] moves 'move1' ....
Definition usercmd.cpp:572
void execute(std::string const &args) override
Definition usercmd.cpp:1055
void execute(std::string const &args) override
Definition usercmd.cpp:875
void execute(std::string const &args) override
Definition usercmd.cpp:778
void execute(std::string const &args) override
Definition usercmd.cpp:423
void execute(std::string const &args) override
Definition usercmd.cpp:858
void execute(std::string const &args) override
Definition usercmd.cpp:869
void execute(std::string const &args) override
Definition usercmd.cpp:788
void execute(std::string const &args) override
Definition usercmd.cpp:996
void execute(std::string const &args) override
Definition usercmd.cpp:853
void execute(std::string const &args) override
Read setoption command.
Definition usercmd.cpp:537
void execute(std::string const &args) override
Definition usercmd.cpp:1044
void execute(std::string const &args) override
Definition usercmd.cpp:783
void execute(std::string const &args) override
Definition usercmd.cpp:1049
void execute(std::string const &args) override
Definition usercmd.cpp:447
void execute(std::string const &args) override
Definition usercmd.cpp:524
void execute(std::string const &args) override
Definition usercmd.cpp:804
void execute(std::string const &args) override
Definition usercmd.cpp:436
void execute(std::string const &args) override
Definition usercmd.cpp:756
void execute(std::string const &args) override
Definition usercmd.cpp:471
~cmdParam()
Definition usercmd.cpp:88
bool attach(std::string const &ifile)
Definition belofte.cpp:270
~dummyEngineCommand() override
Definition usercmd.cpp:76
dummyEngineCommand(std::string const &s, std::string const &h)
Definition usercmd.cpp:70
virtual void sendResponse(std::string const &response)
Definition usercmd.cpp:150
virtual void sendResult(bBoard const &b, gameResult_t rs) const
Definition usercmd.cpp:351
virtual void sendInvalidMove(std::string const &info, std::string const &reason)
Definition belofte.h:203
static engineCommands_t m_engineCommands
Definition belofte.h:140
virtual void setRunning(bool const r)
Definition belofte.h:198
virtual void sendMove(bBoard &b, bMove const &m)
Definition usercmd.cpp:345
virtual void sendHelp(std::string const &args)
Send help on command or all commands.
Definition usercmd.cpp:100
void execute(std::string const &command, std::string const &params)
Definition belofte.cpp:145
virtual void sendError(std::string const &error, std::string const &description)
Definition usercmd.cpp:156
basic format for single command
Definition usercmd.h:13
std::string m_hint
Definition usercmd.h:28
virtual ~engineUserCommand()
Definition usercmd.cpp:19
virtual void execute(std::string const &args)
Definition usercmd.cpp:23
std::string m_name
Definition usercmd.h:27
engineUserCommand(std::string const &s, std::string const &h)
Definition usercmd.cpp:12
bool m_isImplemented
Definition usercmd.h:29
outputWriter & endl()
Definition bel_debug.h:60
void setLevel(int const l)
Definition bel_debug.h:46
enum tEpdTestType epdTest_t
@ EPD_STS
@ EPD_GENERIC
@ EPD_PERF
constexpr bScore SCORE_ALMOST_NORMAL
Definition eval.h:22
@ GR_DRAW_50
Definition eval.h:35
@ GR_DRAW_OTHER
Definition eval.h:36
@ GR_DRAW_STALEMATE
Definition eval.h:35
@ GR_WHITEWINS_FLAG
Definition eval.h:37
@ GR_UNKNOWN
Definition eval.h:34
@ GR_WHITEMATES
Definition eval.h:37
@ GR_DRAW_LACKMATERIAL
Definition eval.h:35
@ GR_DRAW_THREEFOLD
Definition eval.h:35
constexpr bScore SCORE_MATE
Definition eval.h:23
enum gameResult gameResult_t
Definition eval.h:41
constexpr bScore SCORE_PUNDEFINED
Definition eval.h:19
constexpr bScore SCORE_WINNING
Definition eval.h:24
constexpr bScore SCORE_POSITIVE
Definition eval.h:16
constexpr bScore SCORE_INFINITE
Definition eval.h:15
#define DEVUNUSED
Definition myplatform.h:125