Belofte version 2.1.8
A promising chess program using the UCI or Winboard interface
epd_testsuite.cpp
Go to the documentation of this file.
1/*---------------------------------------------------------------------+
2 * File: epd_testsuite.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
15bEpd::bEpd(epdTest_t const typeOfTest)
16 : m_typeOfTest{typeOfTest}
17{
18}
19
21{
22}
23
24#if defined(__GNUC__)
25#pragma GCC diagnostic pop
26#endif
27
28bEpd::operator std::string() const
29{
30 std::stringstream ss;
31 ss << m_Fen << " => ";
32 for (const auto &m : m_Keys)
33 ss << "[" << m.first << "] = " << m.second << "; ";
34 ss << "\n";
35 return ss.str();
36}
37
39{
41 return Game()->evalPerftResult(bFen(m_Fen), m_Keys);
42 }
43
44 // check if any D[1-99] is in list
45 bool bPerft = false;
46 for (int i = 1; i <= EPD_PERFTMAXDEPTH; i++) {
47 std::string sOp = "D" + belofte::to_string(i);
48 if (m_Keys.find(sOp) != m_Keys.end()) { bPerft = true; break; }
49 }
50 if (bPerft) {
51 return Game()->evalPerftResult(bFen(m_Fen), m_Keys);
52 }
53
54 return Game()->evalEpdPosition(bFen(m_Fen), m_Keys);
55}
56
57/** EPD pos is fen-board fen-tomove fen-castling fen-ep [50moves] [move#] cmdsection*
58 * cmdsection is bm SanMove! | am SanMove! | id=["]identification["]
59 * id ["]identification["] | D[1-99] n | n[,n[,n]...]
60 */
61void bEpd::setPos(std::string const& s)
62{
63 belofte::stringList sFenSgmt = belofte::stringSplit(s, " ");
64 if (sFenSgmt.size() >= 4) {
65 // decompose perft elements, splitting -,20,400 into list["-","20","400"]
66 belofte::stringList sPerftCommaElem = belofte::stringSplit(sFenSgmt[3], ",");
67 if (sPerftCommaElem.size() > 1) {
68 sFenSgmt[3] = sPerftCommaElem[0];
69 }
70 // compose FEN part
71 m_Fen = sFenSgmt[0] + " " + sFenSgmt[1] + " "
72 + sFenSgmt[2] + " " + sFenSgmt[3];
73 sFenSgmt.erase(sFenSgmt.begin(), sFenSgmt.begin() + 4);
74
75 // 50 move counter
76 if (belofte::is_number(sFenSgmt[0])) {
77 m_Fen += " " + sFenSgmt[0];
78 sFenSgmt.erase(sFenSgmt.begin());
79 } else {
80 m_Fen += " 0";
81 }
82
83 // move number
84 if (belofte::is_number(sFenSgmt[0])) {
85 m_Fen += " " + sFenSgmt[0];
86 sFenSgmt.erase(sFenSgmt.begin());
87 } else {
88 m_Fen += " 1";
89 }
90
91 // compose command part based on remainder of line
92 if (sPerftCommaElem.size() > 1) {
93 // convert list["-","20","400"] to D1 20 ;D2 400 ;D3 8902 ;
94 std::stringstream sPerftSection;
95 for (unsigned long i = 1; (i < EPD_PERFTMAXDEPTH) && (sPerftCommaElem.size() > i); ++i) {
96 sPerftSection << "D" << belofte::to_string(static_cast<int32_t>(i)) << " "
97 << sPerftCommaElem[i] << ";";
98 }
99 sFenSgmt.push_back(sPerftSection.str());
100 }
101
102 // make sure FEN extension starts with ;
103 std::string sCmd = ";" + std::accumulate(sFenSgmt.begin(), sFenSgmt.end(), std::string(),
104 [](std::string result, std::string sElem) {
105 return std::move(result) + std::move(sElem) + " ";
106 });
107 belofte::stringList sCmdSgmt = belofte::stringSplit(sCmd, ";");
108
109 // remove leading - trailing space(s) on opcodes
110 for (auto it = sCmdSgmt.begin(); it != sCmdSgmt.end(); ++it) {
111 *it = belofte::alltrim(*it);
112 }
113
114 m_Keys.clear();
115 // split each command in between opcode and info
116 // remove quotes from info
117 for (const auto &sElem : sCmdSgmt) {
118 if (sElem.length() > 0) {
119 // TODO: do only consider opcode starting with letter
120 if (sElem.substr(0,3) == "id=") {
121 /// @deprecated backwards compatibility with belofte 0.9.x, which has testfiles where
122 /// id is followed by = sign instead of space
123 std::pair<std::string, std::string> sCmdOpcode = belofte::decompose(sElem, "=");
124 m_Keys[sCmdOpcode.first] = belofte::alltrim(sCmdOpcode.second, "\"");
125 } else {
126 // any other command followed by space, e.g. bm | am | id | D[1-99] |
127 // c[0-9] | acs | dm
128 std::pair<std::string, std::string> sCmdOpcode = belofte::decompose(sElem, " ");
129 m_Keys[sCmdOpcode.first] = belofte::alltrim(sCmdOpcode.second, "\"");
130 }
131 }
132 }
133
134 m_valid = true;
135 }
136}
137
138//-----------------------------------------------------------------------
139
140bEpdPos::bEpdPos(std::string const& s, epdTest_t const typeOfTest)
141 : bEpd(typeOfTest)
142{
143 setPos(s);
144}
145
146bEpdPos::bEpdPos(bEpdParamList const& sParams, epdTest_t const typeOfTest)
147 : bEpd(typeOfTest)
148{
149 std::string s;
150 for (const auto &sElem : sParams) s += sElem + " ";
151 setPos(s);
152}
153
157
158//-----------------------------------------------------------------------
159
160#if defined(__GNUC__)
161#pragma GCC diagnostic push
162#pragma GCC diagnostic ignored "-Weffc++"
163#endif
164
165bEpdFile::bEpdFile(std::string const& sFileName, epdTest_t const typeOfTest)
166 : bEpd(typeOfTest)
167{
168 handleFile(sFileName);
169}
170
171bEpdFile::bEpdFile(bEpdParamList const& sParams, epdTest_t const typeOfTest)
172 : bEpd(typeOfTest)
173{
174 if (!sParams.empty()) {
175 handleFile(sParams[0]);
176 }
177}
178
179#if defined(__GNUC__)
180#pragma GCC diagnostic pop
181#endif
182
184{
185 if (m_sEpdFile.is_open()) m_sEpdFile.close();
186}
187
188void bEpdFile::handleFile(std::string const& sFileName)
189{
190 if (sFileName.empty()) {
191 AppEI()->sendError("Filename missing", sFileName);
192 } else {
193 m_sEpdFile.open(sFileName.c_str(), std::ios::in );
194 if (!m_sEpdFile.is_open()) {
195 AppEI()->sendError("Could not open file", sFileName);
196 } else {
197 AppEI()->sendDebug(1, "Reading " + sFileName);
198 }
199 }
200}
201
202/** Main epd parser for multiple lines of epd file
203 * Will calculate a total score and some statistics
204 */
206{
207 int nGoods = 0;
208 int nTotal = 0;
209 if (!m_sEpdFile.is_open()) return bEpd::tReturn::EPD_ERROR;
210 std::string line;
211 while(getline(m_sEpdFile,line)) {
212 if ((line.length() < 6)
213 || (line.substr(0,1) == ";")
214 || (line.substr(0,1) == "#")) {
215 /// @remark consider other prefixes to be skipped (e.g. //, %)
216 // skip
217 } else {
218 setPos(line);
219 bEpdResult result = bEpd::parse();
220 if (result == bEpd::tReturn::EPD_ERROR) {
221 App().bout << "Error : " << std::string(*this);
223 } else if (result >= bEpd::tReturn::PERFT_OK) {
224 App().bout << "Perft OK : " << std::string(*this);
225 nGoods += bEpd::tReturn::BM_OK;
226 } else if (result == bEpd::tReturn::EPD_OK) {
227 continue; // skip
228 } else if (result > bEpd::tReturn::BM_OK) {
229 // AM_OK, MATE_OK, ... are equal to maximum score
230 nGoods += bEpd::tReturn::BM_OK;
231 } else if (result > bEpd::tReturn::EPD_OK) {
232 // STS can return fraction of total score
233 nGoods += result;
234 } else if (result == bEpd::tReturn::NOT_RESOLVED) {
235 App().bout << "Not resolved : " << std::string(*this);
236 } else if (result == bEpd::tReturn::NO_MOVE_FOUND) {
237 App().bout << "No move found : " << std::string(*this);
238 }
239 nTotal += bEpd::tReturn::BM_OK;
240 }
241 }
242 m_sEpdFile.close();
243
245 // score of STS test is relative to total value
246 App().bout << "Result " << nGoods << "/" << nTotal;
247 } else {
248 App().bout << "Result " << nGoods / bEpd::tReturn::BM_OK
249 << "/" << nTotal / bEpd::tReturn::BM_OK;
250 }
251 if (nTotal > 0) App().bout << " = " << (nGoods * 100) / nTotal << "%\n";
252 App().bout.endl();
253
255}
256
257// eof
258
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.
outputWriter bout
Definition belofte.h:330
bEpdFile(std::string const &sFileName, epdTest_t const typeOfTest)
virtual ~bEpdFile() override
virtual bEpdResult parse() final
Main epd parser for multiple lines of epd file Will calculate a total score and some statistics.
virtual bEpdResult parse()
virtual ~bEpd()
void setPos(std::string const &s)
EPD pos is fen-board fen-tomove fen-castling fen-ep [50moves] [move#] cmdsection* cmdsection is bm Sa...
bEpd(epdTest_t const typeOfTest)
@ NO_MOVE_FOUND
@ NOT_RESOLVED
@ EPD_ERROR
epdTest_t m_typeOfTest
bEpdPos(std::string const &sEpd, epdTest_t const typeOfTest)
virtual ~bEpdPos() override
FEN string.
Definition fen.h:14
bEpdResult evalPerftResult(bFen const &fen, bEpdOpCodes &opcodes)
check perft result for different depths D[1-99] # perft test - nodes
Definition game.cpp:304
bEpdResult evalEpdPosition(bFen const &fen, bEpdOpCodes &opcodes)
do actual epd position test
Definition game.cpp:246
virtual void sendDebug(int const l, std::string const &info)
Definition belofte.h:209
virtual void sendError(std::string const &error, std::string const &description)
Definition usercmd.cpp:156
outputWriter & endl()
Definition bel_debug.h:60
std::vector< std::string > bEpdParamList
enum tEpdTestType epdTest_t
@ EPD_STS
@ EPD_PERF
int bEpdResult
#define EPD_PERFTMAXDEPTH