Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.     Texel - A UCI chess engine.
  3.     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com
  4.  
  5.     This program is free software: you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation, either version 3 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /*
  20.  * tuigame.cpp
  21.  *
  22.  *  Created on: Mar 4, 2012
  23.  *      Author: petero
  24.  */
  25.  
  26. #include "tuigame.hpp"
  27. #include "uciprotocol.hpp"
  28. #include "textio.hpp"
  29. #include "evaluate.hpp"
  30. #include "computerPlayer.hpp"
  31.  
  32. #include <iostream>
  33. #include <fstream>
  34. #include <iomanip>
  35.  
  36. TUIGame::TUIGame(const std::shared_ptr<Player>& whitePlayer,
  37.                  const std::shared_ptr<Player>& blackPlayer)
  38.     : Game(whitePlayer, blackPlayer) {
  39. }
  40.  
  41. bool
  42. TUIGame::handleCommand(const std::string& moveStr) {
  43.     if (Game::handleCommand(moveStr))
  44.         return true;
  45.     if (startsWith(moveStr, "testsuite ")) {
  46.         std::string testSuiteCmd = moveStr.substr(moveStr.find_first_of(' ') + 1);
  47.         handleTestSuite(testSuiteCmd);
  48.         return true;
  49.     } else if (moveStr == "uci") {
  50.         whitePlayer.reset();
  51.         blackPlayer.reset();
  52.         UCIProtocol::main(true);
  53.         exit(0);
  54.         return false;
  55.     } else if (moveStr == "help") {
  56.         showHelp();
  57.         return true;
  58.     }
  59.  
  60.     return false;
  61. }
  62.  
  63. void
  64. TUIGame::showHelp() {
  65.     std::cout << "Enter a move, or one of the following special commands:" << std::endl;
  66.     std::cout << "  new             - Start a new game" << std::endl;
  67.     std::cout << "  undo            - Undo last half-move" << std::endl;
  68.     std::cout << "  redo            - Redo next half-move" << std::endl;
  69.     std::cout << "  swap            - Swap sides" << std::endl;
  70.     std::cout << "  go              - Same as swap" << std::endl;
  71.     std::cout << "  list            - List all moves in current game" << std::endl;
  72.     std::cout << "  setpos FEN      - Set a position using a FEN string" << std::endl;
  73.     std::cout << "  getpos          - Print current position in FEN notation" << std::endl;
  74.     std::cout << "  draw rep [move] - Claim draw by repetition" << std::endl;
  75.     std::cout << "  draw 50 [move]  - Claim draw by 50-move rule" << std::endl;
  76.     std::cout << "  draw offer move - Play move and offer draw" << std::endl;
  77.     std::cout << "  draw accept     - Accept a draw offer" << std::endl;
  78.     std::cout << "  resign          - Resign the current game" << std::endl;
  79.     std::cout << "  testsuite filename maxtime" << std::endl;
  80.     std::cout << "  book on|off     - Turn opening book on/off" << std::endl;
  81.     std::cout << "  time t          - Set computer thinking time, ms" << std::endl;
  82.     std::cout << "  perft d         - Run perft test to depth d" << std::endl;
  83.     std::cout << "  uci             - Switch to uci protocol." << std::endl;
  84.     std::cout << "  help            - Show this help" << std::endl;
  85.     std::cout << "  quit            - Terminate program" << std::endl;
  86. }
  87.  
  88. void
  89. TUIGame::handleTestSuite(const std::string& cmd) {
  90.     std::ifstream fr;
  91.     int lineNo = -1;
  92.     try {
  93.         size_t idx = cmd.find_first_of(' ');
  94.         if (idx == cmd.npos)
  95.             return;
  96.         std::string filename(cmd.substr(0, idx));
  97.         std::string timeStr(cmd.substr(idx + 1));
  98.         int timeLimit;
  99.         if (!str2Num(timeStr, timeLimit)) {
  100.             std::cout << "Error parsing number: " << timeStr << std::endl;
  101.             return;
  102.         }
  103. //        std::cout << "file:" << filename << " time:" << timeStr << " (" << timeLimit << ")" << std::endl;
  104.         fr.open(filename.c_str());
  105.         std::shared_ptr<Player> pl = whitePlayer->isHumanPlayer() ? blackPlayer : whitePlayer;
  106.         if (pl->isHumanPlayer()) {
  107.             std::cout << "No computer player available" << std::endl;
  108.             return;
  109.         }
  110.         std::shared_ptr<ComputerPlayer> cp = std::static_pointer_cast<ComputerPlayer>(pl);
  111.         int numRight = 0;
  112.         int numTotal = 0;
  113.         std::string line;
  114.         lineNo = 0;
  115.         while (getline(fr, line).good()) {
  116.             lineNo++;
  117.             if (startsWith(line, "#") || (line.length() == 0))
  118.                 continue;
  119.             size_t idx1 = line.find(" bm ");
  120.             if (idx1 == line.npos) {
  121.                 std::cout << "Parse error, line:" << lineNo << std::endl;
  122.                 return;
  123.             }
  124.             std::string fen = line.substr(0, idx1);
  125.             size_t idx2 = line.find(";", idx1);
  126.             if (idx2 == line.npos) {
  127.                 std::cout << "Parse error, line:" << lineNo << std::endl;
  128.                 return;
  129.             }
  130.             std::string bm = line.substr(idx1+4, idx2 - (idx1+4));
  131. //            std::cout << "Line " << std::setw(3) << lineNo << ": fen:" << fen << " bm:" << bm << std::endl;
  132.             Position testPos = TextIO::readFEN(fen);
  133.             cp->clearTT();
  134.             std::pair<Move, std::string> ret = cp->searchPosition(testPos, timeLimit);
  135.             Move sm = ret.first;
  136.             std::string PV = ret.second;
  137.             Move m(sm);
  138.             std::vector<std::string> answers;
  139.             splitString(bm, answers);
  140.             bool correct = false;
  141.             for (size_t i = 0; i < answers.size(); i++) {
  142.                 const std::string& a = answers[i];
  143.                 Move am(TextIO::stringToMove(testPos, a));
  144.                 if (am.isEmpty())
  145.                     throw ChessParseError("Invalid move " + a);
  146.                 if (am.equals(m)) {
  147.                     correct = true;
  148.                     break;
  149.                 }
  150.             }
  151.             if (correct)
  152.                 numRight++;
  153.             numTotal++;
  154.             std::cout << std::setw(3) << lineNo
  155.                       << ' ' << std::setw(6) << TextIO::moveToString(testPos, sm, false)
  156.                       << ' ' << std::setw(6) << sm.score()
  157.                       << ' ' << (correct ? 1 : 0)
  158.                       << ' ' << std::setw(3) << numRight
  159.                       << '/' << std::setw(3) << numTotal
  160.                       << ' ' << bm << " : " << PV << std::endl;
  161.         }
  162.         fr.close();
  163.     } catch (const std::ifstream::failure& ex) {
  164.         std::cout << "IO error: " << ex.what() << std::endl;
  165.     } catch (const ChessParseError& cpe) {
  166.         std::cout << "Parse error, line " << lineNo << ": " << cpe.what() << std::endl;
  167.     }
  168. }
  169.  
  170. void
  171. TUIGame::play() {
  172.     handleCommand("new");
  173.     while (true) {
  174.         // Print last move
  175.         if (currentMove > 0) {
  176.             Position prevPos(getPos());
  177.             prevPos.unMakeMove(moveList[currentMove - 1], uiInfoList[currentMove - 1]);
  178.             std::string moveStr= TextIO::moveToString(prevPos, moveList[currentMove - 1], false);
  179.             if (haveDrawOffer())
  180.                 moveStr += " (offer draw)";
  181.             std::cout << "Last move: " << prevPos.getFullMoveCounter()
  182.                     << (prevPos.isWhiteMove() ? "." : "...")
  183.                     << ' ' << moveStr << std::endl;
  184.         }
  185.         /*
  186.         {
  187.             std::stringstream ss;
  188.             ss << "Hash: " << std::hex << std::setw(16) << std::setfill('0') << pos.zobristHash();
  189.             std::cout << ss.str() << std::endl;
  190.         }
  191.         */
  192.         {
  193.             auto et = Evaluate::getEvalHashTables();
  194.             Evaluate eval(*et);
  195.             int evScore = eval.evalPos(getPos()) * (getPos().isWhiteMove() ? 1 : -1);
  196.             std::stringstream ss;
  197.             ss.precision(2);
  198.             ss << std::fixed << "Eval: " << (evScore / 100.0);
  199.             std::cout << ss.str() << std::endl;
  200.         }
  201.  
  202.         // Check game state
  203.         std::cout << TextIO::asciiBoard(getPos());
  204.         std::string stateStr = getGameStateString();
  205.         if (stateStr.length() > 0)
  206.             std::cout << stateStr << std::endl;
  207.         if (getGameState() != Game::ALIVE)
  208.             activateHumanPlayer();
  209.  
  210.         // Get command from current player and act on it
  211.         std::shared_ptr<Player> pl = getPos().isWhiteMove() ? whitePlayer : blackPlayer;
  212.         std::vector<Position> posList;
  213.         getHistory(posList);
  214.         std::string moveStr = pl->getCommand(getPos(), haveDrawOffer(), posList);
  215.         if (moveStr == "quit")
  216.             return;
  217.         bool ok = processString(moveStr);
  218.         if (!ok)
  219.             std::cout << "Invalid move: " << moveStr << std::endl;
  220.     }
  221. }
  222.