diff --git a/README.md b/README.md
index e0a7da2..e5c2fff 100755
--- a/README.md
+++ b/README.md
@@ -147,12 +147,15 @@ Below are some features/functions we need someone helps too:
Working
---------
- Improve interface
+- Support opening info ECO
+- Support endgame adjudication, using tablebases
- Support some different tournament types: swiss
- Support other chess variants (not soon event it is designed for multi-variants)
History
--------
+- 20 July 2019: v2.6, more info and more ways to control logs, improve engine managements
- 16 July 2019: v2.5, multiple ways to select openings: new for each match, same for a pair, one for all matches; override options for central controlling; match statistics LOS & error margin
- 14 July 2019: v2.2, knockout tournament and resumable the last tournament
- 12 July 2019: v2.0, auto generating JSON files
@@ -165,7 +168,7 @@ History
Terms of use
---------------
-The project is released under the liberal [MIT license](http://en.wikipedia.org/wiki/MIT_License), so basically you can use it with almost no restrictions.
+All codes and data in the folder 3rdparty are 3rd party libraries, copyrighted and released under their terms of use. Banksia code and data is released under the GPLv3+ license.
Credits
diff --git a/projects/banksia.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate b/projects/banksia.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate
index b96af0a..2f60530 100755
Binary files a/projects/banksia.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate and b/projects/banksia.xcodeproj/project.xcworkspace/xcuserdata/nguyenpham.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/projects/banksia.xcodeproj/xcshareddata/xcschemes/Banksia.xcscheme b/projects/banksia.xcodeproj/xcshareddata/xcschemes/Banksia.xcscheme
index f5bf68a..4b66082 100755
--- a/projects/banksia.xcodeproj/xcshareddata/xcschemes/Banksia.xcscheme
+++ b/projects/banksia.xcodeproj/xcshareddata/xcschemes/Banksia.xcscheme
@@ -67,6 +67,10 @@
argument = "-u -c 16"
isEnabled = "NO">
+
+
diff --git a/projects/banksia.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/projects/banksia.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
index 50264bd..c0d1ff8 100755
--- a/projects/banksia.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ b/projects/banksia.xcodeproj/xcuserdata/nguyenpham.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -104,7 +104,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/playermng.cpp"
- timestampString = "585155568.3086621"
+ timestampString = "585303695.216538"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "142"
@@ -120,7 +120,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/playermng.cpp"
- timestampString = "585155568.30871"
+ timestampString = "585303695.21659"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "153"
@@ -136,7 +136,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/configmng.h"
- timestampString = "585155568.308745"
+ timestampString = "585289246.194873"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "94"
@@ -168,7 +168,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/base/comm.h"
- timestampString = "585155568.309171"
+ timestampString = "585303695.216666"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "98"
@@ -184,7 +184,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/wbengine.cpp"
- timestampString = "585155568.309248"
+ timestampString = "585303695.216942"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "406"
@@ -200,7 +200,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/wbengine.cpp"
- timestampString = "585155568.3093179"
+ timestampString = "585303695.216979"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "433"
@@ -216,7 +216,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/wbengine.cpp"
- timestampString = "585155568.309348"
+ timestampString = "585303695.21701"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "444"
@@ -232,7 +232,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/wbengine.cpp"
- timestampString = "585155568.309378"
+ timestampString = "585303695.2170399"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "457"
@@ -248,7 +248,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/wbengine.cpp"
- timestampString = "585155568.309407"
+ timestampString = "585303695.21707"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "407"
@@ -264,12 +264,12 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/chess/chess.cpp"
- timestampString = "585155568.309525"
+ timestampString = "585303695.2171"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "1217"
- endingLineNumber = "1217"
- landmarkName = "ChessBoard::toMoveListString(MoveNotation notation, int itemPerLine, bool moveCounter)"
+ startingLineNumber = "1218"
+ endingLineNumber = "1218"
+ landmarkName = "ChessBoard::toMoveListString(MoveNotation notation, int itemPerLine, bool moveCounter, bool computingInfo)"
landmarkType = "7">
@@ -280,11 +280,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/chess/chess.cpp"
- timestampString = "585155568.309795"
+ timestampString = "585303695.217132"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "1115"
- endingLineNumber = "1115"
+ startingLineNumber = "1116"
+ endingLineNumber = "1116"
landmarkName = "ChessBoard::checkMake(int from, int dest, PieceType promotion)"
landmarkType = "7">
@@ -296,11 +296,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/chess/chess.cpp"
- timestampString = "585155568.309974"
+ timestampString = "585303695.21716"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "1116"
- endingLineNumber = "1116"
+ startingLineNumber = "1117"
+ endingLineNumber = "1117"
landmarkName = "ChessBoard::checkMake(int from, int dest, PieceType promotion)"
landmarkType = "7">
@@ -312,7 +312,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/wbengine.cpp"
- timestampString = "585155568.31015"
+ timestampString = "585303695.217189"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "412"
@@ -328,11 +328,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.91804"
+ timestampString = "585303695.2172199"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "518"
- endingLineNumber = "518"
+ startingLineNumber = "515"
+ endingLineNumber = "515"
landmarkName = "BookMng::getRandomBook(int pairId, std::string& fenString, std::vector<Move>& moves)"
landmarkType = "7">
@@ -344,11 +344,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.918545"
+ timestampString = "585303695.217473"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "407"
- endingLineNumber = "407"
+ startingLineNumber = "404"
+ endingLineNumber = "404"
landmarkName = "BookMng::load(const Json::Value& obj)"
landmarkType = "7">
@@ -360,11 +360,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/chess/chess.cpp"
- timestampString = "585155568.310249"
+ timestampString = "585303695.217652"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "1333"
- endingLineNumber = "1333"
+ startingLineNumber = "1349"
+ endingLineNumber = "1349"
landmarkName = "ChessBoard::fromSanString(const std::string& str)"
landmarkType = "7">
@@ -376,11 +376,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/chess/chess.cpp"
- timestampString = "585155568.310426"
+ timestampString = "585303695.217685"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "1353"
- endingLineNumber = "1353"
+ startingLineNumber = "1369"
+ endingLineNumber = "1369"
landmarkName = "ChessBoard::fromSanString(const std::string& str)"
landmarkType = "7">
@@ -392,7 +392,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/main.cpp"
- timestampString = "585157095.918952"
+ timestampString = "585303695.217718"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "48"
@@ -408,7 +408,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/tourmng.h"
- timestampString = "585155568.310829"
+ timestampString = "585303695.217957"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "106"
@@ -424,11 +424,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.919193"
+ timestampString = "585303695.218208"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "463"
- endingLineNumber = "463"
+ startingLineNumber = "460"
+ endingLineNumber = "460"
landmarkName = "BookMng::loadSingle(const Json::Value& obj)"
landmarkType = "7">
@@ -440,7 +440,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.919556"
+ timestampString = "585303695.2183861"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "107"
@@ -456,7 +456,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.919894"
+ timestampString = "585303695.2185611"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "106"
@@ -472,7 +472,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.9202271"
+ timestampString = "585303695.218735"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "93"
@@ -488,11 +488,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/chess/chess.cpp"
- timestampString = "585155568.311058"
+ timestampString = "585303695.218907"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "1401"
- endingLineNumber = "1401"
+ startingLineNumber = "1417"
+ endingLineNumber = "1417"
landmarkName = "ChessBoard::fromSanMoveList(const std::string& str)"
landmarkType = "7">
@@ -504,11 +504,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.920579"
+ timestampString = "585303695.218941"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "293"
- endingLineNumber = "293"
+ startingLineNumber = "290"
+ endingLineNumber = "290"
landmarkName = "BookPolyglot::getRandomBook(std::string& fenString, std::vector<Move>& moveList)"
landmarkType = "7">
@@ -520,11 +520,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.9209189"
+ timestampString = "585303695.219116"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "294"
- endingLineNumber = "294"
+ startingLineNumber = "291"
+ endingLineNumber = "291"
landmarkName = "BookPolyglot::getRandomBook(std::string& fenString, std::vector<Move>& moveList)"
landmarkType = "7">
@@ -536,11 +536,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.921252"
+ timestampString = "585303695.219378"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "513"
- endingLineNumber = "513"
+ startingLineNumber = "510"
+ endingLineNumber = "510"
landmarkName = "BookMng::getRandomBook(int pairId, std::string& fenString, std::vector<Move>& moves)"
landmarkType = "7">
@@ -552,11 +552,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.921591"
+ timestampString = "585303695.219614"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "540"
- endingLineNumber = "540"
+ startingLineNumber = "537"
+ endingLineNumber = "537"
landmarkName = "BookMng::getRandomBook(int pairId, std::string& fenString, std::vector<Move>& moves)"
landmarkType = "7">
@@ -568,11 +568,11 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.9219199"
+ timestampString = "585303695.219802"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "291"
- endingLineNumber = "291"
+ startingLineNumber = "288"
+ endingLineNumber = "288"
landmarkName = "BookPolyglot::getRandomBook(std::string& fenString, std::vector<Move>& moveList)"
landmarkType = "7">
@@ -584,14 +584,126 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/game/book.cpp"
- timestampString = "585157095.922245"
+ timestampString = "585303695.219985"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "511"
- endingLineNumber = "511"
+ startingLineNumber = "508"
+ endingLineNumber = "508"
landmarkName = "BookMng::getRandomBook(int pairId, std::string& fenString, std::vector<Move>& moves)"
landmarkType = "7">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/base/base.h b/src/base/base.h
index bc57cd8..6826095 100755
--- a/src/base/base.h
+++ b/src/base/base.h
@@ -248,7 +248,8 @@ namespace banksia {
int8_t castleRights[2];
u64 hashKey;
int quietCnt;
- double elapsed;
+ int score = 0, depth = 0;
+ double elapsed = 0;
std::string moveString, comment;
void set(const MoveFull& _move) {
@@ -270,7 +271,7 @@ namespace banksia {
int status;
Result result;
-
+
public:
void reset() {
for (auto && p : pieces) {
diff --git a/src/base/comm.cpp b/src/base/comm.cpp
index 11b6c7d..289c145 100755
--- a/src/base/comm.cpp
+++ b/src/base/comm.cpp
@@ -35,6 +35,8 @@
#include
#include // for full path
+#include // for isRunning
+
#else
#include
@@ -42,13 +44,16 @@
#include
#include
+#include
+#include
+
#endif
#include "comm.h"
namespace banksia {
- bool banksiaVerbose = false;
+ bool banksiaVerbose = true;
extern const char* pieceTypeName;
extern const char* reasonStrings[11];
@@ -63,6 +68,13 @@ namespace banksia {
"*", "1-0", "1/2-1/2", "0-1", nullptr
};
+ const char* sideStrings[] = {
+ "black", "white", "none", nullptr
+ };
+ const char* shortSideStrings[] = {
+ "b", "w", "n", nullptr
+ };
+
static std::mutex consoleMutex;
std::string resultType2String(ResultType type) {
@@ -95,6 +107,25 @@ namespace banksia {
return ReasonType::noreason;
}
+ std::string side2String(Side side, bool shortFrom)
+ {
+ auto sd = static_cast(side);
+ if (sd < 0 || sd > 1) sd = 2;
+ return shortFrom ? shortSideStrings[sd] : sideStrings[sd];
+ }
+
+ Side string2Side(std::string s)
+ {
+ toLower(s);
+ for(int i = 0; sideStrings[i]; i++) {
+ if (sideStrings[i] == s || shortSideStrings[i] == s) {
+ return static_cast(i);
+ }
+ }
+ return Side::none;
+
+ }
+
void printText(const std::string& str)
{
std::lock_guard dolock(consoleMutex);
@@ -332,6 +363,29 @@ namespace banksia {
return path.find(".exe") != std::string::npos;
}
+ bool isRunning(int pid)
+ {
+ HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
+
+ PROCESSENTRY32 pe = { 0 };
+ pe.dwSize = sizeof(pe);
+
+ if (Process32First(pss, &pe))
+ {
+ do
+ {
+ // pe.szExeFile can also be useful
+ if (pe.th32ProcessID == pid)
+ return true;
+ }
+ while(Process32Next(pss, &pe));
+ }
+
+ CloseHandle(pss);
+
+ return false;
+ }
+
#else
std::vector listdir(std::string dirname) {
@@ -383,6 +437,11 @@ namespace banksia {
return !access(path.c_str(), X_OK);
}
+ bool isRunning(int pid)
+ {
+ return 0 == kill(pid, 0);
+ }
+
#endif
diff --git a/src/base/comm.h b/src/base/comm.h
index 6427a53..98c6c6f 100755
--- a/src/base/comm.h
+++ b/src/base/comm.h
@@ -40,7 +40,7 @@
namespace banksia {
- const int BANKSIA_VERSION = (2 << 8) + 52;
+ const int BANKSIA_VERSION = (2 << 8) + 6;
#ifdef _WIN32
const std::string folderSlash = "\\";
@@ -178,6 +178,7 @@ namespace banksia {
std::vector listdir(std::string dirname);
i64 getFileSize(const std::string& path);
bool isExecutable(const std::string& path);
+ bool isRunning(int pid);
std::vector splitString(const std::string& string, const std::string& regexString);
std::vector splitString(const std::string &s, char delim);
@@ -187,6 +188,9 @@ namespace banksia {
std::string reasonType2String(ReasonType type);
ReasonType string2ReasonType(const std::string& s);
+ std::string side2String(Side side, bool shortFrom = true);
+ Side string2Side(const std::string& s);
+
} // namespace banksia
#endif /* Board_hpp */
diff --git a/src/chess/chess.cpp b/src/chess/chess.cpp
index 3f7e129..40d5e96 100755
--- a/src/chess/chess.cpp
+++ b/src/chess/chess.cpp
@@ -23,6 +23,7 @@
*/
#include
+#include // for setprecision
#include "chess.h"
@@ -1209,7 +1210,7 @@ bool ChessBoard::createStringForLastMove(const MoveList& moveList)
return true;
}
-std::string ChessBoard::toMoveListString(MoveNotation notation, int itemPerLine, bool moveCounter) const
+std::string ChessBoard::toMoveListString(MoveNotation notation, int itemPerLine, bool moveCounter, bool computingInfo) const
{
std::ostringstream stringStream;
@@ -1235,10 +1236,25 @@ std::string ChessBoard::toMoveListString(MoveNotation notation, int itemPerLine,
}
// Comment
+ auto haveComment = false;
+ if (computingInfo && hist.depth > 0) {
+ haveComment = true;
+ stringStream << " {" << (hist.score > 0 ? "+" : "")
+ << std::setprecision(2) << ((float)hist.score / 100.0) << "/"
+ << hist.depth
+ << " " << std::setprecision(2) << hist.elapsed;
+ }
if (!hist.comment.empty() && moveCounter) {
- stringStream << " {" << hist.comment << "} ";
+ stringStream << (haveComment ? "; " : " {");
+
+ haveComment = true;
+ stringStream << hist.comment ;
}
-
+
+ if (haveComment) {
+ stringStream << "} ";
+ }
+
c++;
if (itemPerLine > 0 && c >= itemPerLine) {
c = 0;
diff --git a/src/chess/chess.h b/src/chess/chess.h
index ca9b209..62d925d 100755
--- a/src/chess/chess.h
+++ b/src/chess/chess.h
@@ -80,7 +80,7 @@ namespace banksia {
bool checkMake(int from, int dest, PieceType promotion);
- std::string toMoveListString(MoveNotation notation, int itemPerLine, bool moveCounter) const;
+ std::string toMoveListString(MoveNotation notation, int itemPerLine, bool moveCounter, bool computingInfo) const;
Move fromSanString(const std::string&);
bool fromSanMoveList(const std::string&);
diff --git a/src/game/book.cpp b/src/game/book.cpp
index ffaa562..d92055c 100755
--- a/src/game/book.cpp
+++ b/src/game/book.cpp
@@ -227,9 +227,6 @@ void BookPolyglot::load(const std::string& _path, int _maxPly, int _top100)
for(int i = 0; i < itemCnt; i++) {
items[i].convertToLittleEndian();
}
-
- std::cout << "BookPolyglot::load " << path << ", itemCnt: " << itemCnt << std::endl;
-
}
bool BookPolyglot::isValid() const
diff --git a/src/game/configmng.cpp b/src/game/configmng.cpp
index 150baf3..cd17c82 100755
--- a/src/game/configmng.cpp
+++ b/src/game/configmng.cpp
@@ -249,7 +249,7 @@ void Option::setDefaultValue(const std::string& val, const std::vectorjoinable()) {
+ std::cout << "Warning 2: a chess engine/program refuses to stop, it may be still running, " << name << std::endl;
+ pThread->join();
+ }
+
}
void Engine::tickWork()
@@ -60,7 +70,7 @@ void Engine::tickWork()
if (tick_being_kill == 0) {
TinyProcessLib::Process::kill(processId, true);
process = nullptr;
- deleteThread();
+// deleteThread();
setState(PlayerState::stopped);
finished();
}
@@ -186,17 +196,6 @@ void Engine::parseLine(const std::string& line)
parseLine(it->second, cmdString, line);
}
-void Engine::deleteThread()
-{
- if (pThread && pThread->joinable()) {
-#ifndef _WIN32
- pthread_cancel(pThread->native_handle());
-#endif
- pThread = nullptr;
- std::cout << "Warning: thread is still resident " << name << std::endl;
- }
-}
-
bool Engine::kickStart()
{
resetPing();
@@ -244,6 +243,7 @@ bool Engine::kickStart()
pThread = nullptr;
});
+ native_handle = processThread.native_handle();
pThread = &processThread;
processThread.detach();
return true;
@@ -258,6 +258,10 @@ void Engine::attach(ChessBoard* board, const GameTimeController* timeController,
Player::attach(board, timeController, moveFunc, resignFunc);
tick_deattach = -1;
tick_idle = 0;
+
+ if (board == nullptr) {
+ messageLogger = nullptr;
+ }
}
bool Engine::isSafeToDeattach() const
diff --git a/src/game/engine.h b/src/game/engine.h
index c607c86..d972bef 100755
--- a/src/game/engine.h
+++ b/src/game/engine.h
@@ -113,7 +113,6 @@ namespace banksia {
int tick_ping, tick_idle, tick_being_kill = -1; //, tick_stopping = 0;
std::function messageLogger = nullptr;
- void deleteThread();
int correctCmdCnt = 0;
private:
@@ -122,6 +121,10 @@ namespace banksia {
TinyProcessLib::Process::id_type processId = 0;
TinyProcessLib::Process* process = nullptr;
std::thread* pThread = nullptr;
+
+#ifndef _WIN32
+ std::thread::native_handle_type native_handle = 0;
+#endif
};
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 6d616ac..c596f86 100755
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -196,18 +196,21 @@ void Game::moveFromPlayer(const Move& move, const std::string& moveString, const
}
assert(board.side == side);
+ auto sd = static_cast(board.side);
+
if (oldState == EngineComputingState::thinking) {
if (make(move, moveString)) {
assert(board.side != side);
- auto lastHist = board.histList.back();
+ auto& lastHist = board.histList.back();
lastHist.elapsed = timeConsumed;
+ lastHist.score = players[sd]->getScore();
+ lastHist.depth = players[sd]->getDepth();
timeController.udateClockAfterMove(timeConsumed, lastHist.move.piece.side, int(board.histList.size()));
startThinking(ponderMode ? ponderMove : Move::illegalMove);
}
} else if (oldState == EngineComputingState::pondering) { // missed ponderhit, stop called
- auto sd = static_cast(board.side);
players[sd]->go();
}
}
@@ -257,15 +260,24 @@ void Game::gameOver(const Result& result)
Player* Game::getPlayer(Side side)
{
- auto sd = static_cast(side);
- return players[sd];
+ return players[static_cast(side)];
+}
+
+const Player* Game::getPlayer(Side side) const
+{
+ return players[static_cast(side)];
}
-std::string Game::getGameTitleString() const
+std::string Game::getGameTitleString(bool includeResult) const
{
std::string str;
str += players[W] ? players[W]->getName() : "*";
- str += " vs " + (players[B] ? players[B]->getName() : "*");
+ if (includeResult) {
+ str += " (" + board.result.toShortString() + ") ";
+ } else {
+ str += " vs ";
+ }
+ str += (players[B] ? players[B]->getName() : "*");
return str;
}
@@ -396,7 +408,7 @@ void Game::tickWork()
}
-std::string Game::toPgn(std::string event, std::string site, int round, int gameIdx) const
+std::string Game::toPgn(std::string event, std::string site, int round, int gameIdx, bool richMode) const
{
std::ostringstream stringStream;
@@ -441,7 +453,7 @@ std::string Game::toPgn(std::string event, std::string site, int round, int game
}
// Move text
- stringStream << board.toMoveListString(MoveNotation::san, 8, true);
+ stringStream << board.toMoveListString(MoveNotation::san, 8, true, richMode);
if (board.result.result != ResultType::noresult) {
if (board.histList.size() % 8 != 0) stringStream << " ";
diff --git a/src/game/game.h b/src/game/game.h
index cfae871..5f8fb6b 100755
--- a/src/game/game.h
+++ b/src/game/game.h
@@ -54,7 +54,6 @@ namespace banksia {
void newGame();
void kickStart();
-// void startPlaying();
void pause();
void stop();
bool make(const Move& move, const std::string& moveString);
@@ -72,7 +71,8 @@ namespace banksia {
virtual void tickWork() override;
Player* getPlayer(Side side);
-
+ const Player* getPlayer(Side side) const;
+
GameState getState() const { return state; }
void setState(GameState st);
@@ -80,9 +80,9 @@ namespace banksia {
int getIdx() const;
int getStateTick() const { return stateTick; }
- std::string toPgn(std::string event = "", std::string site = "", int round = -1, int gameIdx = -1) const;
+ std::string toPgn(std::string event = "", std::string site = "", int round = -1, int gameIdx = -1, bool richMode = false) const;
- std::string getGameTitleString() const;
+ std::string getGameTitleString(bool includeResult = false) const;
public:
ChessBoard board;
diff --git a/src/game/player.cpp b/src/game/player.cpp
index f6b17c3..9283fa5 100755
--- a/src/game/player.cpp
+++ b/src/game/player.cpp
@@ -62,6 +62,7 @@ void Player::setState(PlayerState st)
state = st;
tick_state = 0;
}
+
void Player::attach(ChessBoard* _board, const GameTimeController* _timeController,
std::function _moveReceiver,
std::function _resignFunc)
@@ -91,6 +92,7 @@ bool Player::goPonder(const Move& pondermove)
bool Player::go()
{
setState(PlayerState::playing);
+ score = depth = 0;
return true;
}
diff --git a/src/game/player.h b/src/game/player.h
index ad68b74..82b3039 100755
--- a/src/game/player.h
+++ b/src/game/player.h
@@ -79,13 +79,21 @@ namespace banksia {
virtual bool go();
virtual bool oppositeMadeMove(const Move& move, const std::string& sanMoveString);
+ int getScore() const {
+ return score;
+ }
+
+ int getDepth() const {
+ return depth;
+ }
+
protected:
int idNumber; // a random number, main purpose for debugging
std::string name;
PlayerType type;
PlayerState state;
- int tick_state = 0;
+ int tick_state = 0, score, depth;
bool ponderMode = false;
diff --git a/src/game/playermng.cpp b/src/game/playermng.cpp
index 40fe34c..f601d63 100755
--- a/src/game/playermng.cpp
+++ b/src/game/playermng.cpp
@@ -61,7 +61,7 @@ void PlayerMng::tickWork()
if (it != playerList.end()) {
playerList.erase(it);
}
- killPlayer(player);
+ removePlayer(player);
}
}
@@ -117,11 +117,11 @@ bool PlayerMng::returnPlayer(Player* player)
return true;
}
- return killPlayer(player);
+ return removePlayer(player);
}
-bool PlayerMng::killPlayer(Player* player)
+bool PlayerMng::removePlayer(Player* player)
{
if (player == nullptr) return false;
diff --git a/src/game/playermng.h b/src/game/playermng.h
index 5468697..e6b394d 100755
--- a/src/game/playermng.h
+++ b/src/game/playermng.h
@@ -55,7 +55,7 @@ namespace banksia {
void shutdown();
private:
- bool killPlayer(Player* player);
+ bool removePlayer(Player* player);
private:
std::mutex thelock;
diff --git a/src/game/tourmng.cpp b/src/game/tourmng.cpp
index 43583eb..5d2b1b0 100755
--- a/src/game/tourmng.cpp
+++ b/src/game/tourmng.cpp
@@ -70,9 +70,11 @@ bool MatchRecord::load(const Json::Value& obj)
}
auto s = obj["result"].asString();
- resultType = string2ResultType(s);
-
- state = resultType == ResultType::noresult ? MatchState::none : MatchState::completed;
+ result.result = string2ResultType(s);
+ s = obj["reason"].asString();
+ result.reason= string2ReasonType(s);
+
+ state = result.result == ResultType::noresult ? MatchState::none : MatchState::completed;
gameIdx = obj["gameIdx"].asInt();
round = obj["round"].asInt();
@@ -103,7 +105,8 @@ Json::Value MatchRecord::saveToJson() const
obj["startMoves"] = moves;
}
- obj["result"] = resultType2String(resultType);
+ obj["result"] = resultType2String(result.result);
+ obj["reason"] = reasonType2String(result.reason);
obj["gameIdx"] = gameIdx;
obj["round"] = round;
obj["pairId"] = pairId;
@@ -208,7 +211,7 @@ void TourMng::fixJson(Json::Value& d, const std::string& path)
d[s] = v;
}
- s = "opening books";
+ s = "openings";
if (!d.isMember(s)) {
const static std::string obString =
"{ \"base\" : { \"allone fen\" : \"\", \"allone san moves\" : \"\", \"seed\" : -1, \"select type\" : \"allnew\",\
@@ -256,25 +259,32 @@ void TourMng::fixJson(Json::Value& d, const std::string& path)
if (!a.isMember(s)) {
Json::Value v;
v["mode"] = true;
+ v["one file"] = true;
+ v["rich info"] = false;
+ v["game title surfix"] = true;
+ v["guide"] = "one file: if false, games are stored in multi files using game indexes as surfix; game title surfix: use players names, results for file name surfix, affective only when 'one file' is false; rich info: log more info such as scores, depths, elapses";
v["path"] = path + folderSlash + "games.pgn";
a[s] = v;
}
- s = "result";
+ s = "engine";
if (!a.isMember(s)) {
Json::Value v;
v["mode"] = true;
- v["path"] = path + folderSlash + "logresult.txt";
+ v["show time"] = true;
+ v["one file"] = false;
+ v["game title surfix"] = true;
+ v["separate by sides"] = false;
+ v["guide"] = "one file: if false, games are stored in multi files using game indexes as surfix; game title surfix: use players names, results for file name surfix, affective only when 'one file' is false; separate by sides: each side has different logs";
+ v["path"] = path + folderSlash + "logengine.txt";
a[s] = v;
}
- s = "engine";
+ s = "result";
if (!a.isMember(s)) {
Json::Value v;
v["mode"] = true;
- v["show time"] = true;
- v["all in one"] = false;
- v["path"] = path + folderSlash + "logengine.txt";
+ v["path"] = path + folderSlash + "logresult.txt";
a[s] = v;
}
@@ -394,12 +404,18 @@ bool TourMng::parseJsonAfterLoading(Json::Value& d)
//
// Less inportance
//
- s = "opening books";
- if (d.isMember(s)) {
- auto obj = d[s];
+ s = "openings";
+ if (d.isMember(s) || d.isMember("opening books")) {
+ auto obj = d[d.isMember(s) ? s : "opening books"];
bookMng.load(obj);
}
-
+
+ // TODO: endgames
+// s = "endgames";
+// if (d.isMember(s)) {
+// auto obj = d[s];
+// }
+
s = "logs";
if (d.isMember(s)) {
auto a = d[s];
@@ -408,8 +424,23 @@ bool TourMng::parseJsonAfterLoading(Json::Value& d)
auto v = a[s];
pgnPathMode = v["mode"].asBool();
pgnPath = v["path"].asString();
+ logPgnAllInOneMode = !v.isMember("one file") || v["one file"].asBool();
+ logPgnGameTitleSurfix = v.isMember("game title surfix") && v["game title surfix"].asBool();
+ logPgnRichMode = v.isMember("rich info") && v["rich info"].asBool();
}
+ s = "engine";
+ if (a.isMember(s)) {
+ auto v = a[s];
+ logEngineMode = v["mode"].asBool();
+ logEngineAllInOneMode = v.isMember("one file") && v["one file"].asBool();
+ logEngineBySides = v.isMember("separate by sides") && v["separate by sides"].asBool();
+
+ logEngineGameTitleSurfix = v.isMember("game title surfix") && v["game title surfix"].asBool();
+ logEngineShowTime = v.isMember("show time") && v["show time"].asBool();
+ logEnginePath = v["path"].asString();
+ }
+
s = "result";
if (a.isMember(s)) {
auto v = a[s];
@@ -417,14 +448,6 @@ bool TourMng::parseJsonAfterLoading(Json::Value& d)
logResultPath = v["path"].asString();
}
- s = "engine";
- if (a.isMember(s)) {
- auto v = a[s];
- logEngineInOutMode = v["mode"].asBool();
- logEngineAllInOneMode = v.isMember("all in one") && v["all in one"].asBool();
- logEngineInOutShowTime = v.isMember("show time") && v["show time"].asBool();
- logEngineInOutPath = v["path"].asString();
- }
}
return true;
@@ -447,8 +470,18 @@ void TourMng::tickWork()
break;
case GameState::ended:
+ {
+ for(int sd = 0; sd < 2; sd++) {
+ auto side = static_cast(sd);
+ auto player = game->getPlayer(side);
+ if (player) {
+ player->quit();
+ }
+ }
+
stoppedGameList.push_back(game);
break;
+ }
default:
break;
}
@@ -501,11 +534,11 @@ void TourMng::startTournament()
+ ", ponder: " + bool2OnOffString(ponderMode)
+ ", book: " + bool2OnOffString(!bookMng.isEmpty());
- matchLog(info);
+ matchLog(info, true);
showPathInfo("pgn", pgnPath, pgnPathMode);
showPathInfo("result", logResultPath, logResultMode);
- showPathInfo("engines", logEngineInOutPath, logEngineInOutMode);
+ showPathInfo("engines", logEnginePath, logEngineMode);
std::cout << std::endl;
// tickWork will start the matches
@@ -521,11 +554,11 @@ void TourMng::finishTournament()
if (!matchRecordList.empty()) {
auto str = createTournamentStats();
- matchLog(str);
+ matchLog(str, true);
}
auto str = "Tournamemt finished! Elapsed: " + formatPeriod(elapsed_secs);
- matchLog(str);
+ matchLog(str, true);
removeMatchRecordFile();
@@ -538,8 +571,9 @@ std::string TourMng::createTournamentStats()
{
std::map resultMap;
+ auto abnormalCnt = 0;
for(auto && m : matchRecordList) {
- if (m.resultType == ResultType::noresult) { // hm
+ if (m.result.result == ResultType::noresult) { // hm
continue;
}
@@ -556,8 +590,9 @@ std::string TourMng::createTournamentStats()
r = it->second; assert(r.name == name);
}
+ auto lossCnt = r.lossCnt;
r.gameCnt++;
- switch (m.resultType) {
+ switch (m.result.result) {
case ResultType::win:
if (sd == W) r.winCnt++; else r.lossCnt++;
break;
@@ -571,6 +606,13 @@ std::string TourMng::createTournamentStats()
assert(false);
break;
}
+
+ if (lossCnt < r.lossCnt) {
+ if (m.result.reason == ReasonType::illegalmove || m.result.reason == ReasonType::crash || m.result.reason == ReasonType::timeout) {
+ r.abnormalCnt++;
+ abnormalCnt++;
+ }
+ }
resultMap[name] = r;
}
}
@@ -591,7 +633,7 @@ std::string TourMng::createTournamentStats()
std::stringstream stringStream;
- auto separateLineSz = maxNameLen + 68;
+ auto separateLineSz = maxNameLen + 68 + (abnormalCnt ? 20 : 0);
for(int i = 0; i < separateLineSz; i++) {
stringStream << "-";
}
@@ -599,8 +641,10 @@ std::string TourMng::createTournamentStats()
stringStream << " # "
<< std::left << std::setw(maxNameLen + 2) << "name"
- << "games wins% draws% losses% score los% elo+/-" << std::endl;
-
+ << "games wins% draws% losses% score los% elo+/-"
+ << (abnormalCnt ? " fails" : "")
+ << std::endl;
+
for(int i = 0; i < resultList.size(); i++) {
auto r = resultList.at(i);
@@ -609,6 +653,7 @@ std::string TourMng::createTournamentStats()
double score = double(r.winCnt) + double(r.drawCnt) / 2;
Elo elo(r.winCnt, r.drawCnt, r.lossCnt);
+
stringStream
<< std::right << std::setw(3) << (i + 1) << ". "
<< std::left << std::setw(maxNameLen + 2) << r.name
@@ -619,15 +664,22 @@ std::string TourMng::createTournamentStats()
<< std::right << std::setw(9) << loss // << std::left << std::setw(0) << "%"
<< std::right << std::setw(9) << score
<< std::right << std::setw(9) << elo.los * 100
- << std::right << std::setw(9) << elo.elo_difference
- << std::left << std::setw(0)
- << std::endl;
+ << std::right << std::setw(9) << elo.elo_difference;
+
+ if (r.abnormalCnt) {
+ stringStream << std::right << std::setw(9) << r.abnormalCnt;
+ }
+
+ stringStream << std::left << std::setw(0) << std::endl;
}
for(int i = 0; i < separateLineSz; i++) {
stringStream << "-";
}
- stringStream << std::endl << std::endl;
+
+ if (abnormalCnt) {
+ stringStream << std::endl << "Failed games (timeout, crashed, illegal moves): " << abnormalCnt << " of " << matchRecordList.size();
+ }
return stringStream.str();
}
@@ -715,10 +767,10 @@ void TourMng::checkToExtendMatches(int gIdx)
if (rcd.state != MatchState::completed) {
return;
}
- if (rcd.resultType != ResultType::win && rcd.resultType != ResultType::loss) {
+ if (rcd.result.result != ResultType::win && rcd.result.result != ResultType::loss) {
continue;
}
- auto winnerName = rcd.playernames[(rcd.resultType == ResultType::win ? W : B)];
+ auto winnerName = rcd.playernames[(rcd.result.result == ResultType::win ? W : B)];
playerPair.pair[playerPair.pair[W].name == winnerName ? W : B].winCnt++;
auto whiteIdx = playerPair.pair[W].name == rcd.playernames[W] ? W : B;
@@ -728,12 +780,12 @@ void TourMng::checkToExtendMatches(int gIdx)
// It is a tie if two players have same wins and same times to play white
if (playerPair.pair[0].winCnt == playerPair.pair[1].winCnt && playerPair.pair[0].whiteCnt == playerPair.pair[1].whiteCnt) {
MatchRecord record = r;
- record.resultType = ResultType::noresult;
+ record.result.result = ResultType::noresult;
record.state = MatchState::none;
addMatchRecord_simple(record);
auto str = "* Tied! Add one more game for " + record.playernames[W] + " vs " + record.playernames[B];
- matchLog(str);
+ matchLog(str, banksiaVerbose);
}
break;
}
@@ -772,9 +824,9 @@ std::vector TourMng::getKnockoutWinnerList()
thePair.pair[1].name = r.playernames[1];
}
- if (r.resultType == ResultType::win || r.resultType == ResultType::loss) {
+ if (r.result.result == ResultType::win || r.result.result == ResultType::loss) {
auto idxW = thePair.pair[W].name == r.playernames[W] ? W : B;
- auto winIdx = r.resultType == ResultType::win ? idxW : (1 - idxW);
+ auto winIdx = r.result.result == ResultType::win ? idxW : (1 - idxW);
thePair.pair[winIdx].winCnt++;
}
auto whiteSd = thePair.pair[W].name == r.playernames[W] ? W : B;
@@ -820,7 +872,7 @@ bool TourMng::createKnockoutMatchList(std::vector playerVec, int rou
if (playerVec.size() < 2) {
if (playerVec.size() == 1) {
auto str = "\n* The winner is " + playerVec.front().name;
- matchLog(str);
+ matchLog(str, true);
}
return false;
}
@@ -857,12 +909,12 @@ bool TourMng::createKnockoutMatchList(std::vector playerVec, int rou
MatchRecord record(luckPlayer.name, "", false);
record.round = round;
record.state = MatchState::completed;
- record.resultType = ResultType::win; // win
+ record.result.result = ResultType::win; // win
record.pairId = std::rand();
addMatchRecord_simple(record);
auto str = "\n* Player " + luckPlayer.name + " is an odd (no opponent in " + std::to_string(playerVec.size()) + " players) and set won for round " + std::to_string(round + 1);
- matchLog(str);
+ matchLog(str, banksiaVerbose);
}
std::sort(playerVec.begin(), playerVec.end(), [](const TourPlayer& lhs, const TourPlayer& rhs)
@@ -886,7 +938,7 @@ bool TourMng::createKnockoutMatchList(std::vector playerVec, int rou
auto str = "\nKnockout round: " + std::to_string(round + 1) + ", pairs: " + std::to_string(n) + ", matches: " + std::to_string(uncompletedMatches());
- matchLog(str);
+ matchLog(str, true);
return addCnt > 0;
}
@@ -989,14 +1041,21 @@ bool TourMng::createMatch(int gameIdx, const std::string& whiteName, const std::
if (addGame(game)) {
game->setMessageLogger([=](const std::string& name, const std::string& line, LogType logType) {
- engineLog(gameIdx, name, line, logType);
+ auto white = game->getPlayer(Side::white);
+ auto fromSide = white && white->getName() == name ? Side::white : Side::black;
+ engineLog(game, name, line, logType, fromSide);
});
game->kickStart();
std::string infoString = std::to_string(gameIdx + 1) + ". " + game->getGameTitleString();
- printText(infoString);
- engineLog(gameIdx, getAppName(), "\n" + infoString + "\n", LogType::system);
+ if (banksiaVerbose) {
+ printText(infoString);
+ }
+
+ if (!logEngineBySides) {
+ engineLog(game, getAppName(), "\n" + infoString + "\n", LogType::system);
+ }
return true;
}
@@ -1009,6 +1068,31 @@ bool TourMng::createMatch(int gameIdx, const std::string& whiteName, const std::
return false;
}
+std::string TourMng::createLogPath(std::string opath, bool onefile, bool usesurfix, bool includeGameResult, const Game* game, Side forSide)
+{
+ if (onefile || game == nullptr) return opath;
+
+ std::string s = (usesurfix ? ", " : "-") + std::to_string(game->getIdx() + 1);
+ if (usesurfix) {
+ if (!game->getPlayer(Side::white) || !game->getPlayer(Side::black)) {
+ return "";
+ }
+ s += ") " + game->getGameTitleString(includeGameResult);
+ }
+
+ if (forSide != Side::none) {
+ s += ", " + side2String(forSide, true);
+ }
+
+ auto p = opath.rfind(".");
+ if (p == std::string::npos) {
+ opath += s;
+ } else {
+ opath = opath.substr(0, p) + s + opath.substr(p);
+ }
+ return opath;
+}
+
void TourMng::matchCompleted(Game* game)
{
if (game == nullptr) return;
@@ -1018,26 +1102,28 @@ void TourMng::matchCompleted(Game* game)
auto record = &matchRecordList[gIdx];
assert(record->state == MatchState::playing);
record->state = MatchState::completed;
- record->resultType = game->board.result.result;
- assert(matchRecordList[gIdx].resultType == game->board.result.result);
+ record->result = game->board.result;
if (pgnPathMode && !pgnPath.empty()) {
- auto pgnString = game->toPgn(eventName, siteName, record->round, record->gameIdx);
- append2TextFile(pgnPath, pgnString);
+ auto pgnString = game->toPgn(eventName, siteName, record->round, record->gameIdx, logPgnRichMode);
+ auto path = createLogPath(pgnPath, logPgnAllInOneMode, logPgnGameTitleSurfix, true, game);
+ if (!path.empty()) {
+ append2TextFile(path, pgnString);
+ }
}
}
- if (logResultMode || banksiaVerbose) { // log
- auto wplayer = game->getPlayer(Side::white), bplayer = game->getPlayer(Side::black);
- if (wplayer && bplayer) {
- std::string infoString = std::to_string(gIdx + 1) + ") " + game->getGameTitleString() + ", #" + std::to_string(game->board.histList.size()) + ", " + game->board.result.toString();
-
- matchLog(infoString);
- // Add extra info to help understanding log
- engineLog(game->getIdx(), getAppName(), infoString, LogType::system);
+ auto wplayer = game->getPlayer(Side::white), bplayer = game->getPlayer(Side::black);
+ if (wplayer && bplayer) {
+ std::string infoString = std::to_string(gIdx + 1) + ") " + game->getGameTitleString() + ", #" + std::to_string(game->board.histList.size()) + ", " + game->board.result.toString();
+
+ matchLog(infoString, banksiaVerbose);
+ // Add extra info to help understanding log
+ if (!logEngineBySides) {
+ engineLog(game, getAppName(), infoString, LogType::system);
}
}
-
+
checkToExtendMatches(gIdx);
saveMatchRecords();
@@ -1057,17 +1143,19 @@ bool TourMng::addGame(Game* game)
void TourMng::setEngineLogMode(bool enabled)
{
- logEngineInOutMode = enabled;
+ logEngineMode = enabled;
}
void TourMng::setEngineLogPath(const std::string& path)
{
- logEngineInOutPath = path;
+ logEnginePath = path;
}
-void TourMng::matchLog(const std::string& infoString)
+void TourMng::matchLog(const std::string& infoString, bool verbose)
{
- printText(infoString);
+ if (verbose) {
+ printText(infoString);
+ }
if (logResultMode && !logResultPath.empty()) {
std::lock_guard dolock(matchMutex);
@@ -1080,21 +1168,27 @@ void TourMng::showEgineInOutToScreen(bool enabled)
logScreenEngineInOutMode = enabled;
}
-void TourMng::engineLog(int gameIdx, const std::string& name, const std::string& line, LogType logType)
+void TourMng::engineLog(const Game* game, const std::string& name, const std::string& line, LogType logType, Side bySide)
{
- if (line.empty() || !logEngineInOutMode || logEngineInOutPath.empty()) return;
+ if (line.empty() || !logEngineMode || logEnginePath.empty()) return;
std::ostringstream stringStream;
+ auto gameIdx = game ? game->getIdx() : -1;
if (logEngineAllInOneMode && gameIdx >= 0 && gameConcurrency > 1) {
stringStream << (gameIdx + 1) << ".";
}
- if (logEngineInOutShowTime) {
+ if (logEngineShowTime) {
auto tm = localtime_xp(std::time(0));
stringStream << std::put_time(&tm, "%H:%M:%S ");
}
- stringStream << name << (logType == LogType::toEngine ? "< " : "> ") << line;
+
+ if (!logEngineBySides && bySide != Side::none) {
+ stringStream << name;
+ }
+
+ stringStream << (logType == LogType::toEngine ? "< " : "> ") << line;
auto str = stringStream.str();
@@ -1102,18 +1196,16 @@ void TourMng::engineLog(int gameIdx, const std::string& name, const std::string&
printText(str);
}
- auto path = logEngineInOutPath;
- if (!logEngineAllInOneMode) {
- auto s = "-" + std::to_string(gameIdx + 1);
- auto p = path.rfind(".");
- if (p == std::string::npos) {
- path += s;
- } else {
- path = path.substr(0, p) + s + path.substr(p);
- }
+ auto forSide = Side::none;
+ if (logEngineBySides) {
+ forSide = bySide;
+ }
+ auto path = createLogPath(logEnginePath, logEngineAllInOneMode, logEngineGameTitleSurfix, false, game, forSide);
+
+ if (!path.empty()) {
+ std::lock_guard dolock(logMutex);
+ append2TextFile(path, str);
}
- std::lock_guard dolock(logMutex);
- append2TextFile(path, str);
}
void TourMng::append2TextFile(const std::string& path, const std::string& str)
diff --git a/src/game/tourmng.h b/src/game/tourmng.h
index 4bf8374..9a70031 100755
--- a/src/game/tourmng.h
+++ b/src/game/tourmng.h
@@ -71,7 +71,7 @@ namespace banksia {
std::string startFen;
std::vector startMoves;
- ResultType resultType = ResultType::noresult;
+ Result result;
int gameIdx = 0, round = 0, pairId;
};
@@ -83,7 +83,7 @@ namespace banksia {
{
public:
std::string name;
- int gameCnt = 0, winCnt = 0, drawCnt = 0, lossCnt = 0, elo = 0;
+ int gameCnt = 0, winCnt = 0, drawCnt = 0, lossCnt = 0, abnormalCnt = 0, elo = 0;
int whiteCnt = 0; // for knockdown
virtual const char* className() const override { return "TourPlayer"; }
@@ -159,7 +159,7 @@ namespace banksia {
void finishTournament();
- void engineLog(int gameIdx, const std::string& name, const std::string& line, LogType logType);
+ void engineLog(const Game* game, const std::string& name, const std::string& line, LogType logType, Side bySide = Side::none);
bool createNextRoundMatches();
@@ -176,7 +176,7 @@ namespace banksia {
virtual void tickWork() override;
- void matchLog(const std::string& line);
+ void matchLog(const std::string& line, bool verbose);
int uncompletedMatches();
protected:
@@ -207,7 +207,8 @@ namespace banksia {
static void showPathInfo(const std::string& name, const std::string& path, bool mode);
private:
-
+ static std::string createLogPath(std::string opath, bool onefile, bool usesurfix, bool includeGameResult, const Game* game, Side forSide = Side::none);
+
int previousElapsed = 0;
time_t startTime;
@@ -215,15 +216,16 @@ namespace banksia {
std::mutex matchMutex, logMutex;
std::string pgnPath;
- bool pgnPathMode = true;
+ bool pgnPathMode = true, logPgnAllInOneMode = false;
+ bool logPgnRichMode = false, logPgnGameTitleSurfix = false;
std::string logResultPath;
bool logResultMode = false;
- std::string logEngineInOutPath;
- bool logEngineAllInOneMode = false;
- bool logEngineInOutMode = false;
- bool logEngineInOutShowTime = false;
+ std::string logEnginePath;
+ bool logEngineAllInOneMode = false, logEngineMode = false;
+ bool logEngineShowTime = false, logEngineGameTitleSurfix = false;
+ bool logEngineBySides = false;
bool logScreenEngineInOutMode = false;
};
diff --git a/src/game/uciengine.cpp b/src/game/uciengine.cpp
index d772cc5..b162540 100755
--- a/src/game/uciengine.cpp
+++ b/src/game/uciengine.cpp
@@ -57,7 +57,7 @@ bool UciEngine::sendOptions()
if (!isWritable()) {
return false;
}
-
+
auto o = ConfigMng::instance->checkOverrideOption(option);
if (o.isDefaultValue()) {
continue;
@@ -234,6 +234,12 @@ void UciEngine::parseLine(int cmdInt, const std::string& cmdString, const std::s
}
break;
+ case UciEngineCmd::info:
+ if (computingState == EngineComputingState::thinking) {
+ parseInfo(line);
+ }
+ break;
+
case UciEngineCmd::bestmove:
{
auto timeCtrl = timeController;
@@ -265,13 +271,12 @@ void UciEngine::parseLine(int cmdInt, const std::string& cmdString, const std::s
if (!moveString.empty() && moveReceiver != nullptr) {
auto move = board->moveFromCoordiateString(moveString);
auto ponderMove = board->moveFromCoordiateString(ponderMoveString);
-
(moveRecv)(move, moveString, ponderMove, period, oldComputingState);
}
break;
}
-
+
case UciEngineCmd::uciok:
{
setState(PlayerState::ready);
@@ -280,6 +285,7 @@ void UciEngine::parseLine(int cmdInt, const std::string& cmdString, const std::s
sendPing();
break;
}
+
case UciEngineCmd::theId:
{
auto vec = splitString(line, ' ');
@@ -417,4 +423,45 @@ bool UciEngine::parseOption(const std::string& s)
return false;
}
+bool UciEngine::parseInfo(const std::string& line)
+{
+ assert(!line.empty());
+
+ std::string str;
+ auto p = line.find(" pv ");
+ if (p != std::string::npos) {
+ str = line.substr(5, p);
+ } else {
+ str = line.substr(5);
+ }
+
+ auto vec = splitString(str, ' ');
+ for(int i = 0; i < vec.size() - 1; i++) {
+ auto name = vec.at(i);
+ if (name == "depth") {
+ ++i;
+ auto s = vec.at(i);
+ depth = std::atoi(s.c_str());
+ continue;
+ }
+
+ if (name == "score") {
+ ++i;
+ auto s = vec.at(i);
+
+ auto iscpscore = false;
+ if (s == "cp") {
+ iscpscore = true;
+ ++i;
+ s = vec.at(i);
+ }
+ score = std::atoi(s.c_str());
+ if (!iscpscore) score *= 100;
+ continue;
+ }
+
+ }
+
+ return false;
+}
diff --git a/src/game/uciengine.h b/src/game/uciengine.h
index 20a405e..ac5d632 100755
--- a/src/game/uciengine.h
+++ b/src/game/uciengine.h
@@ -72,6 +72,7 @@ namespace banksia {
private:
std::string timeControlString() const;
bool parseOption(const std::string& str);
+ bool parseInfo(const std::string& line);
bool expectingBestmove = false;
Move ponderingMove;
diff --git a/src/game/wbengine.cpp b/src/game/wbengine.cpp
index e33fca6..1d77831 100644
--- a/src/game/wbengine.cpp
+++ b/src/game/wbengine.cpp
@@ -528,10 +528,26 @@ void WbEngine::parseLine(int cmdInt, const std::string& cmdString, const std::st
if (state != PlayerState::playing) {
return;
}
+
+ if (computingState != EngineComputingState::thinking) {
+ return;
+ }
auto ch = line.front();
if (isdigit(ch)) { // it may be thinking output -> ignore
// 9 156 1084 48000 Nf3 Nc6 Nc3 Nf6
- engineSentCorrectCmds();
+ // ply score time nodes pv
+ auto vec = splitString(line, ' ');
+ if (vec.size() > 2) {
+ auto scoreStr = vec.at(1);
+ if (!scoreStr.empty()) {
+ auto c = scoreStr[0];
+ if (isdigit(c) || c == '-' || c == '+') {
+ engineSentCorrectCmds();
+ score = std::atoi(scoreStr.c_str());
+ depth = std::atoi(vec[0].c_str());
+ }
+ }
+ }
}
return;
}
diff --git a/src/main.cpp b/src/main.cpp
index ff9272e..2f19d11 100755
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -60,7 +60,7 @@ int main(int argc, const char * argv[])
std::string str = arg;
auto ok = true;
- if (arg == "-jsonpath" || arg == "-d" || arg == "-c") {
+ if (arg == "-jsonpath" || arg == "-d" || arg == "-c" || arg == "-v") {
if (i + 1 < argc) {
i++;
str = argv[i];
@@ -81,6 +81,10 @@ int main(int argc, const char * argv[])
mainJsonPath = argmap["-jsonpath"];
}
+ if (argmap.find("-v") != argmap.end()) {
+ banksia::banksiaVerbose = argmap["-v"] == "on";
+ }
+
banksia::JsonMaker maker;
banksia::TourMng tourMng;
@@ -141,9 +145,10 @@ int main(int argc, const char * argv[])
std::cout << tourMng.createTournamentStats() << std::endl;
continue;
}
- if (cmd == "engineverbose" || cmd == "ev") {
+ if (cmd == "v") {
std::string str = vec.size() > 1 ? vec[1] : "";
- tourMng.showEgineInOutToScreen(str == "on");
+ //tourMng.showEgineInOutToScreen(str == "on");
+ banksia::banksiaVerbose = str == "on";
continue;
}
@@ -173,6 +178,7 @@ void show_usage(std::string name)
<< " -u update\n"
<< " -c concurrency (for updating only)\n"
<< " -d PATH main engines' folder, may have subfolder (for updating only)\n"
+ << " -v on|off turn on/off verbose (default on)\n"
<< "\n"
<< "Examples:\n"
<< " " << name << " -jsonpath c:\\tour.json\n"
@@ -189,7 +195,7 @@ void show_help()
<< "Usage:\n"
<< " help show this help message\n"
<< " status current result\n"
- << " ev [on|off] Show/not to screen engine's input / output (engineverbose)\n"
+ << " v [on|off] verbose on/off. Show/Don't show individual match (default on)\n"
<< " quit quit\n"
<< std::endl;
}