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  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.  * uciprotocol.cpp
  21.  *
  22.  *  Created on: Mar 4, 2012
  23.  *      Author: petero
  24.  */
  25.  
  26. #include "uciprotocol.hpp"
  27. #include "searchparams.hpp"
  28. #include "computerPlayer.hpp"
  29. #include "textio.hpp"
  30.  
  31. #include <iostream>
  32.  
  33.  
  34. void
  35. UCIProtocol::main(bool autoStart) {
  36.     UCIProtocol uciProt;
  37.     uciProt.mainLoop(std::cin, std::cout, autoStart);
  38. }
  39.  
  40. UCIProtocol::UCIProtocol()
  41.     : pos(TextIO::readFEN(TextIO::startPosFEN)),
  42.       quit(false)
  43. {
  44. }
  45.  
  46. void
  47. UCIProtocol::mainLoop(std::istream& is, std::ostream& os, bool autoStart) {
  48.     if (autoStart)
  49.         handleCommand("uci", os);
  50.     std::string line;
  51.     while (true) {
  52.         getline(is, line);
  53.         if (!is.good()) {
  54.             if (engine)
  55.                 engine->stopSearch();
  56.             break;
  57.         }
  58.         handleCommand(line, os);
  59.         if (quit)
  60.             break;
  61.     }
  62. }
  63.  
  64. void
  65. UCIProtocol::handleCommand(const std::string& cmdLine, std::ostream& os) {
  66.     std::vector<std::string> tokens;
  67.     tokenize(cmdLine, tokens);
  68.     const int nTok = (int)tokens.size();
  69.     if (nTok == 0)
  70.         return;
  71.     try {
  72.         std::string cmd = tokens[0];
  73.         if (cmd == "uci") {
  74.             os << "id name " << ComputerPlayer::engineName << std::endl;
  75.             os << "id author Peter Osterlund" << std::endl;
  76.             EngineControl::printOptions(os);
  77.             os << "uciok" << std::endl;
  78.         } else if (cmd == "isready") {
  79.             initEngine(os);
  80.             os << "readyok" << std::endl;
  81.         } else if (cmd == "setoption") {
  82.             initEngine(os);
  83.             std::string optionName;
  84.             std::string optionValue;
  85.             if (nTok < 2)
  86.                 return;
  87.             if (tokens[1] == "name") {
  88.                 int idx = 2;
  89.                 while ((idx < nTok) && (tokens[idx] != "value")) {
  90.                     optionName += toLowerCase(tokens[idx++]);
  91.                     optionName += ' ';
  92.                 }
  93.                 if ((idx < nTok) && (tokens[idx++] == "value")) {
  94.                     while ((idx < nTok)) {
  95.                         optionValue += toLowerCase(tokens[idx++]);
  96.                         optionValue += ' ';
  97.                     }
  98.                 }
  99.                 engine->setOption(trim(optionName), trim(optionValue), true);
  100.             }
  101.         } else if (cmd == "ucinewgame") {
  102.             if (engine)
  103.                 engine->newGame();
  104.         } else if (cmd ==  "position") {
  105.             std::string fen;
  106.             int idx = 1;
  107.             if (nTok < 2)
  108.                 return;
  109.             if (tokens[idx] == "startpos") {
  110.                 idx++;
  111.                 fen = TextIO::startPosFEN;
  112.             } else if (tokens[idx] == "fen") {
  113.                 idx++;
  114.                 std::string sb;
  115.                 while ((idx < nTok) && (tokens[idx] != "moves")) {
  116.                     sb += tokens[idx++];
  117.                     sb += ' ';
  118.                 }
  119.                 fen = trim(sb);
  120.             }
  121.             if (fen.length() > 0) {
  122.                 pos = TextIO::readFEN(fen);
  123.                 moves.clear();
  124.                 if ((idx < nTok) && (tokens[idx++] == "moves")) {
  125.                     for (int i = idx; i < nTok; i++) {
  126.                         Move m = TextIO::uciStringToMove(tokens[i]);
  127.                         if (m.isEmpty())
  128.                             break;
  129.                         moves.push_back(m);
  130.                     }
  131.                 }
  132.             }
  133.         } else if (cmd == "go") {
  134.             initEngine(os);
  135.             int idx = 1;
  136.             SearchParams sPar;
  137.             bool ponder = false;
  138.             while (idx < nTok) {
  139.                 std::string subCmd = tokens[idx++];
  140.                 if (subCmd == "searchmoves") {
  141.                     while (idx < nTok) {
  142.                         Move m = TextIO::uciStringToMove(tokens[idx]);
  143.                         if (m.isEmpty())
  144.                             break;
  145.                         sPar.searchMoves.push_back(m);
  146.                         idx++;
  147.                     }
  148.                 } else if (subCmd == "ponder") {
  149.                     ponder = true;
  150.                 } else if (subCmd == "wtime") {
  151.                     if (idx < nTok)
  152.                         str2Num(tokens[idx++], sPar.wTime);
  153.                 } else if (subCmd == "btime") {
  154.                     if (idx < nTok)
  155.                         str2Num(tokens[idx++], sPar.bTime);
  156.                 } else if (subCmd == "winc") {
  157.                     if (idx < nTok)
  158.                         str2Num(tokens[idx++], sPar.wInc);
  159.                 } else if (subCmd == "binc") {
  160.                     if (idx < nTok)
  161.                         str2Num(tokens[idx++], sPar.bInc);
  162.                 } else if (subCmd == "movestogo") {
  163.                     if (idx < nTok)
  164.                         str2Num(tokens[idx++], sPar.movesToGo);
  165.                 } else if (subCmd == "depth") {
  166.                     if (idx < nTok)
  167.                         str2Num(tokens[idx++], sPar.depth);
  168.                 } else if (subCmd == "nodes") {
  169.                     if (idx < nTok)
  170.                         str2Num(tokens[idx++], sPar.nodes);
  171.                 } else if (subCmd == "mate") {
  172.                     if (idx < nTok)
  173.                         str2Num(tokens[idx++], sPar.mate);
  174.                 } else if (subCmd == "movetime") {
  175.                     if (idx < nTok)
  176.                         str2Num(tokens[idx++], sPar.moveTime);
  177.                 } else if (subCmd == "infinite") {
  178.                     sPar.infinite = true;
  179.                 }
  180.             }
  181.             if (ponder) {
  182.                 engine->startPonder(pos, moves, sPar);
  183.             } else {
  184.                 engine->startSearch(pos, moves, sPar);
  185.             }
  186.         } else if (cmd == "stop") {
  187.             if (engine)
  188.                 engine->stopSearch();
  189.         } else if (cmd == "ponderhit") {
  190.             engine->ponderHit();
  191.         } else if (cmd == "quit") {
  192.             if (engine)
  193.                 engine->stopSearch();
  194.             quit = true;
  195.         }
  196.     } catch (const ChessParseError&) {
  197.     }
  198. }
  199.  
  200. void
  201. UCIProtocol::initEngine(std::ostream& os) {
  202.     if (!engine)
  203.         engine = std::make_shared<EngineControl>(os);
  204. }
  205.  
  206. /** Convert a string to tokens by splitting at whitespace characters. */
  207. void
  208. UCIProtocol::tokenize(const std::string& cmdLine, std::vector<std::string>& tokens) {
  209.     tokens.clear();
  210.     std::string tmp = trim(cmdLine);
  211.     int start = 0;
  212.     bool inWord = true;
  213.     for (int i = 0; i < (int)tmp.size(); i++) {
  214.         if (inWord) {
  215.             if (isspace(tmp[i])) {
  216.                 tokens.push_back(tmp.substr(start, i - start));
  217.                 inWord = false;
  218.             }
  219.         } else {
  220.             if (!isspace(tmp[i])) {
  221.                 start = i;
  222.                 inWord = true;
  223.             }
  224.         }
  225.     }
  226.     if (inWord)
  227.         tokens.push_back(tmp.substr(start, tmp.size() - start));
  228. }
  229.