- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com 
-   
-     This program is free software: you can redistribute it and/or modify 
-     it under the terms of the GNU General Public License as published by 
-     the Free Software Foundation, either version 3 of the License, or 
-     (at your option) any later version. 
-   
-     This program is distributed in the hope that it will be useful, 
-     but WITHOUT ANY WARRANTY; without even the implied warranty of 
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-     GNU General Public License for more details. 
-   
-     You should have received a copy of the GNU General Public License 
-     along with this program.  If not, see <http://www.gnu.org/licenses/>. 
- */ 
-   
- /* 
-  * tuigame.cpp 
-  * 
-  *  Created on: Mar 4, 2012 
-  *      Author: petero 
-  */ 
-   
- #include "tuigame.hpp" 
- #include "uciprotocol.hpp" 
- #include "textio.hpp" 
- #include "evaluate.hpp" 
- #include "computerPlayer.hpp" 
-   
- #include <iostream> 
- #include <fstream> 
- #include <iomanip> 
-   
- TUIGame::TUIGame(const std::shared_ptr<Player>& whitePlayer, 
-                  const std::shared_ptr<Player>& blackPlayer) 
-     : Game(whitePlayer, blackPlayer) { 
- } 
-   
- bool 
- TUIGame::handleCommand(const std::string& moveStr) { 
-     if (Game::handleCommand(moveStr)) 
-         return true; 
-     if (startsWith(moveStr, "testsuite ")) { 
-         std::string testSuiteCmd = moveStr.substr(moveStr.find_first_of(' ') + 1); 
-         handleTestSuite(testSuiteCmd); 
-         return true; 
-     } else if (moveStr == "uci") { 
-         whitePlayer.reset(); 
-         blackPlayer.reset(); 
-         UCIProtocol::main(true); 
-         exit(0); 
-         return false; 
-     } else if (moveStr == "help") { 
-         showHelp(); 
-         return true; 
-     } 
-   
-     return false; 
- } 
-   
- void 
- TUIGame::showHelp() { 
-     std::cout << "Enter a move, or one of the following special commands:" << std::endl; 
-     std::cout << "  new             - Start a new game" << std::endl; 
-     std::cout << "  undo            - Undo last half-move" << std::endl; 
-     std::cout << "  redo            - Redo next half-move" << std::endl; 
-     std::cout << "  swap            - Swap sides" << std::endl; 
-     std::cout << "  go              - Same as swap" << std::endl; 
-     std::cout << "  list            - List all moves in current game" << std::endl; 
-     std::cout << "  setpos FEN      - Set a position using a FEN string" << std::endl; 
-     std::cout << "  getpos          - Print current position in FEN notation" << std::endl; 
-     std::cout << "  draw rep [move] - Claim draw by repetition" << std::endl; 
-     std::cout << "  draw 50 [move]  - Claim draw by 50-move rule" << std::endl; 
-     std::cout << "  draw offer move - Play move and offer draw" << std::endl; 
-     std::cout << "  draw accept     - Accept a draw offer" << std::endl; 
-     std::cout << "  resign          - Resign the current game" << std::endl; 
-     std::cout << "  testsuite filename maxtime" << std::endl; 
-     std::cout << "  book on|off     - Turn opening book on/off" << std::endl; 
-     std::cout << "  time t          - Set computer thinking time, ms" << std::endl; 
-     std::cout << "  perft d         - Run perft test to depth d" << std::endl; 
-     std::cout << "  uci             - Switch to uci protocol." << std::endl; 
-     std::cout << "  help            - Show this help" << std::endl; 
-     std::cout << "  quit            - Terminate program" << std::endl; 
- } 
-   
- void 
- TUIGame::handleTestSuite(const std::string& cmd) { 
-     std::ifstream fr; 
-     int lineNo = -1; 
-     try { 
-         size_t idx = cmd.find_first_of(' '); 
-         if (idx == cmd.npos) 
-             return; 
-         std::string filename(cmd.substr(0, idx)); 
-         std::string timeStr(cmd.substr(idx + 1)); 
-         int timeLimit; 
-         if (!str2Num(timeStr, timeLimit)) { 
-             std::cout << "Error parsing number: " << timeStr << std::endl; 
-             return; 
-         } 
- //        std::cout << "file:" << filename << " time:" << timeStr << " (" << timeLimit << ")" << std::endl; 
-         fr.open(filename.c_str()); 
-         std::shared_ptr<Player> pl = whitePlayer->isHumanPlayer() ? blackPlayer : whitePlayer; 
-         if (pl->isHumanPlayer()) { 
-             std::cout << "No computer player available" << std::endl; 
-             return; 
-         } 
-         std::shared_ptr<ComputerPlayer> cp = std::static_pointer_cast<ComputerPlayer>(pl); 
-         int numRight = 0; 
-         int numTotal = 0; 
-         std::string line; 
-         lineNo = 0; 
-         while (getline(fr, line).good()) { 
-             lineNo++; 
-             if (startsWith(line, "#") || (line.length() == 0)) 
-                 continue; 
-             size_t idx1 = line.find(" bm "); 
-             if (idx1 == line.npos) { 
-                 std::cout << "Parse error, line:" << lineNo << std::endl; 
-                 return; 
-             } 
-             std::string fen = line.substr(0, idx1); 
-             size_t idx2 = line.find(";", idx1); 
-             if (idx2 == line.npos) { 
-                 std::cout << "Parse error, line:" << lineNo << std::endl; 
-                 return; 
-             } 
-             std::string bm = line.substr(idx1+4, idx2 - (idx1+4)); 
- //            std::cout << "Line " << std::setw(3) << lineNo << ": fen:" << fen << " bm:" << bm << std::endl; 
-             Position testPos = TextIO::readFEN(fen); 
-             cp->clearTT(); 
-             std::pair<Move, std::string> ret = cp->searchPosition(testPos, timeLimit); 
-             Move sm = ret.first; 
-             std::string PV = ret.second; 
-             Move m(sm); 
-             std::vector<std::string> answers; 
-             splitString(bm, answers); 
-             bool correct = false; 
-             for (size_t i = 0; i < answers.size(); i++) { 
-                 const std::string& a = answers[i]; 
-                 Move am(TextIO::stringToMove(testPos, a)); 
-                 if (am.isEmpty()) 
-                     throw ChessParseError("Invalid move " + a); 
-                 if (am.equals(m)) { 
-                     correct = true; 
-                     break; 
-                 } 
-             } 
-             if (correct) 
-                 numRight++; 
-             numTotal++; 
-             std::cout << std::setw(3) << lineNo 
-                       << ' ' << std::setw(6) << TextIO::moveToString(testPos, sm, false) 
-                       << ' ' << std::setw(6) << sm.score() 
-                       << ' ' << (correct ? 1 : 0) 
-                       << ' ' << std::setw(3) << numRight 
-                       << '/' << std::setw(3) << numTotal 
-                       << ' ' << bm << " : " << PV << std::endl; 
-         } 
-         fr.close(); 
-     } catch (const std::ifstream::failure& ex) { 
-         std::cout << "IO error: " << ex.what() << std::endl; 
-     } catch (const ChessParseError& cpe) { 
-         std::cout << "Parse error, line " << lineNo << ": " << cpe.what() << std::endl; 
-     } 
- } 
-   
- void 
- TUIGame::play() { 
-     handleCommand("new"); 
-     while (true) { 
-         // Print last move 
-         if (currentMove > 0) { 
-             Position prevPos(getPos()); 
-             prevPos.unMakeMove(moveList[currentMove - 1], uiInfoList[currentMove - 1]); 
-             std::string moveStr= TextIO::moveToString(prevPos, moveList[currentMove - 1], false); 
-             if (haveDrawOffer()) 
-                 moveStr += " (offer draw)"; 
-             std::cout << "Last move: " << prevPos.getFullMoveCounter() 
-                     << (prevPos.isWhiteMove() ? "." : "...") 
-                     << ' ' << moveStr << std::endl; 
-         } 
-         /* 
-         { 
-             std::stringstream ss; 
-             ss << "Hash: " << std::hex << std::setw(16) << std::setfill('0') << pos.zobristHash(); 
-             std::cout << ss.str() << std::endl; 
-         } 
-         */ 
-         { 
-             auto et = Evaluate::getEvalHashTables(); 
-             Evaluate eval(*et); 
-             int evScore = eval.evalPos(getPos()) * (getPos().isWhiteMove() ? 1 : -1); 
-             std::stringstream ss; 
-             ss.precision(2); 
-             ss << std::fixed << "Eval: " << (evScore / 100.0); 
-             std::cout << ss.str() << std::endl; 
-         } 
-   
-         // Check game state 
-         std::cout << TextIO::asciiBoard(getPos()); 
-         std::string stateStr = getGameStateString(); 
-         if (stateStr.length() > 0) 
-             std::cout << stateStr << std::endl; 
-         if (getGameState() != Game::ALIVE) 
-             activateHumanPlayer(); 
-   
-         // Get command from current player and act on it 
-         std::shared_ptr<Player> pl = getPos().isWhiteMove() ? whitePlayer : blackPlayer; 
-         std::vector<Position> posList; 
-         getHistory(posList); 
-         std::string moveStr = pl->getCommand(getPos(), haveDrawOffer(), posList); 
-         if (moveStr == "quit") 
-             return; 
-         bool ok = processString(moveStr); 
-         if (!ok) 
-             std::cout << "Invalid move: " << moveStr << std::endl; 
-     } 
- } 
-