Belofte  version 2.1.5
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 
16 {
17 }
18 
20 {
21 }
22 
23 #if defined(__GNUC__)
24 #pragma GCC diagnostic pop
25 #endif
26 
27 bEpd::operator std::string() const
28 {
29  std::stringstream ss;
30  ss << m_Fen << " => ";
31  for (const auto &m : m_Keys)
32  ss << "[" << m.first << "] = " << m.second << "; ";
33  ss << '\n';
34  return ss.str();
35 }
36 
37 bEpdResult bEpd::parse(epdTest_t const typeOfTest)
38 {
39  if (typeOfTest == tEpdTestType::EPD_PERF) {
40  return Game()->evalPerftResult(bFen(m_Fen), m_Keys);
41  }
42 
43  // check if any D[1-99] is in list
44  bool bPerft = false;
45  for (int i = 1; i <= 99; i++) {
46  std::string sOp = "D" + belofte::to_string(i);
47  if (m_Keys.find(sOp) != m_Keys.end()) { bPerft = true; break; }
48  }
49  if (bPerft) {
50  return Game()->evalPerftResult(bFen(m_Fen), m_Keys);
51  }
52 
53  return Game()->evalEpdPosition(bFen(m_Fen), m_Keys, typeOfTest);
54 }
55 
56 /** set EPD position composed of (simplified) FEN and EPD opcodes
57  * @param pos is fen-board fen-tomove fen-castling fen-ep [50moves] [move#] [;]cmdsection*
58  * cmdsection is bm SanMove; [|] am SanMove; | D[1-99] n;
59  * id ["]identification["]; c[0-9] "comments";
60  * dm n; acs n; noop
61  */
62 void bEpd::setPos(std::string const& pos)
63 {
64  belofte::stringList sFenSgmt = belofte::stringSplit(pos, " ");
65  if (sFenSgmt.size() > 4) {
66  // compose FEN part
67  m_Fen = sFenSgmt[0] + " " + sFenSgmt[1] + " "
68  + sFenSgmt[2] + " " + sFenSgmt[3];
69  sFenSgmt.erase(sFenSgmt.begin(), sFenSgmt.begin() + 4);
70 
71  // 50 move counter
72  if (belofte::is_number(sFenSgmt[0])) {
73  m_Fen += " " + sFenSgmt[0];
74  sFenSgmt.erase(sFenSgmt.begin());
75  } else {
76  m_Fen += " 0";
77  }
78 
79  // move number
80  if (belofte::is_number(sFenSgmt[0])) {
81  m_Fen += " " + sFenSgmt[0];
82  sFenSgmt.erase(sFenSgmt.begin());
83  } else {
84  m_Fen += " 1";
85  }
86 
87  // compose command part based on remainder of line
88  std::string sCmd = ";" + std::accumulate(sFenSgmt.begin(), sFenSgmt.end(), std::string(),
89  [](std::string result, std::string sElem) {
90  return std::move(result) + std::move(sElem) + " ";
91  });
92  belofte::stringList sCmdSgmt = belofte::stringSplit(sCmd, ";");
93 
94  // remove leading - trailing space(s) on opcodes
95  for (auto it = sCmdSgmt.begin(); it != sCmdSgmt.end(); ++it) {
96  *it = belofte::alltrim(*it);
97  }
98 
99  m_Keys.clear();
100  // split each command in between opcode and info
101  // remove quotes from info
102  for (const auto &sElem : sCmdSgmt) {
103  if (sElem.length() > 0) {
104  // TODO: do only consider opcode starting with letter
105  if (sElem.substr(0,3) == "id=") {
106  /// @deprecated backwards compatibility with belofte 0.9.x, which has testfiles where
107  /// id is followed by = sign instead of space
108  std::pair<std::string, std::string> sCmdOpcode = belofte::decompose(sElem, "=");
109  m_Keys[sCmdOpcode.first] = belofte::alltrim(sCmdOpcode.second, "\"");
110  } else {
111  // any other command followed by space, e.g. bm | am | id | D[1-99] |
112  // c[0-9] | acs | dm
113  std::pair<std::string, std::string> sCmdOpcode = belofte::decompose(sElem, " ");
114  m_Keys[sCmdOpcode.first] = belofte::alltrim(sCmdOpcode.second, "\"");
115  }
116  }
117  }
118  }
119 }
120 
121 //-----------------------------------------------------------------------
122 
123 bEpdPos::bEpdPos(std::string const& s)
124 {
125  setPos(s);
126 }
127 
129 {
130  std::string s = std::accumulate(sParams.begin(), sParams.end(), std::string(),
131  [](std::string result, std::string sElem) {
132  return std::move(result) + std::move(sElem) + " ";
133  });
134  setPos(s);
135 }
136 
138 {
139 }
140 
141 //-----------------------------------------------------------------------
142 
143 #if defined(__GNUC__)
144 #pragma GCC diagnostic push
145 #pragma GCC diagnostic ignored "-Weffc++"
146 #endif
147 
148 bEpdFile::bEpdFile(std::string const& sFileName)
149 {
150  attachFile(sFileName);
151 }
152 
154 {
155  attachFile(sParams[0]);
156 }
157 
158 #if defined(__GNUC__)
159 #pragma GCC diagnostic pop
160 #endif
161 
163 {
164  if (m_sEpdFile.is_open()) m_sEpdFile.close();
165 }
166 
167 void bEpdFile::attachFile(std::string const& sFileName)
168 {
169  m_sEpdFile.open(sFileName.c_str(), std::ios::in );
170  if (!m_sEpdFile.is_open()) {
171  AppEI()->sendError("Could not open file", sFileName);
172  } else {
173  AppEI()->sendDebug(1, "Reading " + sFileName);
174  }
175 }
176 
177 /** Main epd parser for multiple line epd file
178  * Will calculate a total score and some statistics
179  * @param typeOfTest Type for test to be run
180  */
182 {
183  int nGoods = 0;
184  int nTotal = 0;
185  if (!m_sEpdFile.is_open()) return bEpd::tReturn::EPD_ERROR;
186  std::string line;
187  while(getline(m_sEpdFile,line)) {
188  if (line.length() < 6) {
189  // skip
190  } else if ((line.substr(0,1) == ";")
191  || (line.substr(0,1) == "#")) {
192  /// @remark consider other prefixes to be skipped (e.g. //, %)
193  // skip
194  } else {
195  setPos(line);
196  bEpdResult result = bEpd::parse(typeOfTest);
197  if (result == bEpd::tReturn::EPD_ERROR) {
198  App().bout << "Error : " << std::string(*this);
199  return bEpd::tReturn::EPD_ERROR;
200  } else if (result >= bEpd::tReturn::PERFT_OK) {
201  App().bout << "Perft OK : " << std::string(*this);
202  nGoods += bEpd::tReturn::BM_OK;
203  } else if (result == bEpd::tReturn::EPD_OK) {
204  continue; // skip
205  } else if (result > bEpd::tReturn::BM_OK) {
206  // AM_OK, MATE_OK, ... are equal to maximum score
207  nGoods += bEpd::tReturn::BM_OK;
208  } else if (result > bEpd::tReturn::EPD_OK) {
209  // STS can return fraction of total score
210  nGoods += result;
211  } else if (result == bEpd::tReturn::NOT_RESOLVED) {
212  App().bout << "Not resolved : " << std::string(*this);
213  } else if (result == bEpd::tReturn::NO_MOVE_FOUND) {
214  App().bout << "No move found : " << std::string(*this);
215  }
216  nTotal += bEpd::tReturn::BM_OK;
217  }
218  }
219  m_sEpdFile.close();
220 
221  if (typeOfTest == tEpdTestType::EPD_STS) {
222  // score of STS test is relative to total value
223  App().bout << "Result " << nGoods << "/" << nTotal;
224  } else {
225  App().bout << "Result " << nGoods / bEpd::tReturn::BM_OK
226  << "/" << nTotal / bEpd::tReturn::BM_OK;
227  }
228  if (nTotal > 0) App().bout << " =" << (nGoods * 100) / nTotal << "%\n";
229  App().bout << std::endl;
230 
231  return bEpd::tReturn::EPD_OK;
232 }
233 
234 // eof
235 
appInstance & App()
Definition: belofte.cpp:494
bGameWithTest * Game()
Definition: belofte.cpp:505
engineInterface * AppEI()
Definition: belofte.cpp:500
This is the main include file, needs to be included before any other include.
outputWriter bout
Definition: belofte.h:298
virtual ~bEpdFile() override
bEpdFile(std::string const &sFileName)
virtual bEpdResult parse(epdTest_t const typeOfTest) override
Main epd parser for multiple line epd file Will calculate a total score and some statistics.
virtual ~bEpd()
void setPos(std::string const &pos)
set EPD position composed of (simplified) FEN and EPD opcodes
virtual bEpdResult parse(epdTest_t const typeOfTest)
bEpdPos(std::string const &fen)
virtual ~bEpdPos() override
FEN string.
Definition: board.h:17
bEpdResult evalPerftResult(bFen const &fen, bEpdOpCodes &opcodes)
check perft result for different depths D[1-99] # perft test - nodes
Definition: game.cpp:377
bEpdResult evalEpdPosition(bFen const &fen, bEpdOpCodes &opcodes, epdTest_t const typeOfTest)
do actual epd position test change level if any of following set acs # set search seconds dm # set di...
Definition: game.cpp:313
virtual void sendDebug(int const l, std::string const &info)
Definition: usercmd.cpp:142
virtual void sendError(std::string const &error, std::string const &description)
Definition: usercmd.cpp:134
std::vector< std::string > bEpdParamList
Definition: epd_testsuite.h:11
enum tEpdTestType epdTest_t
Definition: epd_testsuite.h:21
@ EPD_STS
Definition: epd_testsuite.h:17
@ EPD_PERF
Definition: epd_testsuite.h:18
int bEpdResult
Definition: epd_testsuite.h:12
std::string alltrim(std::string s, std::string const &delim=" ")
trim left and right spaces or delim from string
Definition: util.cpp:177
std::pair< std::string, std::string > decompose(std::string const &src, std::string const &delim)
Split delimited long string into a pair based on delimiter e.g.
Definition: util.cpp:150
std::vector< std::string > stringList
Definition: util.h:46
bool is_number(std::string const &s)
Definition: util.cpp:188
std::string to_string(long value)
std::to_string not compatible on Mac OS (Apple LLVM version 5.0) provide generic utility function
Definition: util.cpp:168
stringList stringSplit(std::string src, std::string delim)
Split delimited long string into a vector.
Definition: util.cpp:132