2 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3 Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4 Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
6 Stockfish is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 Stockfish is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
38 #include "ucioption.h"
45 // FEN string for the initial position
46 const string StartPositionFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
48 // UCIParser is a class for parsing UCI input. The class
49 // is actually a string stream built on a given input string.
50 typedef istringstream UCIParser;
53 void set_option(UCIParser& up);
54 void set_position(Position& pos, UCIParser& up);
55 bool go(Position& pos, UCIParser& up);
56 void perft(Position& pos, UCIParser& up);
57 Move parse_uci_move(const Position& pos, const std::string &str);
61 /// execute_uci_command() takes a string as input, uses a UCIParser
62 /// object to parse this text string as a UCI command, and calls
63 /// the appropriate functions. In addition to the UCI commands,
64 /// the function also supports a few debug commands.
66 bool execute_uci_command(const string& cmd) {
68 static Position pos(StartPositionFEN, false, 0); // The root position
72 if (!(up >> token)) // operator>>() skips any whitespace
83 cout << "id name " << engine_name()
84 << "\nid author Tord Romstad, Marco Costalba, Joona Kiiski\n";
86 cout << "uciok" << endl;
88 else if (token == "ucinewgame")
89 pos.from_fen(StartPositionFEN, false);
91 else if (token == "isready")
92 cout << "readyok" << endl;
94 else if (token == "position")
95 set_position(pos, up);
97 else if (token == "setoption")
100 // The remaining commands are for debugging purposes only
101 else if (token == "d")
104 else if (token == "flip")
106 Position p(pos, pos.thread());
109 else if (token == "eval")
112 cout << "Incremental mg: " << mg_value(pos.value())
113 << "\nIncremental eg: " << eg_value(pos.value())
114 << "\nFull eval: " << evaluate(pos, evalMargin) << endl;
116 else if (token == "key")
117 cout << "key: " << hex << pos.get_key()
118 << "\nmaterial key: " << pos.get_material_key()
119 << "\npawn key: " << pos.get_pawn_key() << endl;
121 else if (token == "perft")
125 cout << "Unknown command: " << cmd << endl;
137 // parse_uci_move() takes a position and a string as input, and attempts to
138 // convert the string to a move, using simple coordinate notation (g1f3,
139 // a7a8q, etc.). In order to correctly parse en passant captures and castling
140 // moves, we need the position. This function is not robust, and expects that
141 // the input move is legal and correctly formatted.
143 Move parse_uci_move(const Position& pos, const std::string& str) {
147 Color us = pos.side_to_move();
149 if (str.length() < 4)
152 // Read the from and to squares
153 from = make_square(file_from_char(str[0]), rank_from_char(str[1]));
154 to = make_square(file_from_char(str[2]), rank_from_char(str[3]));
156 // Find the moving piece
157 piece = pos.piece_on(from);
159 // If the string has more than 4 characters, try to interpret the 5th
160 // character as a promotion.
161 if (str.length() > 4 && piece == piece_of_color_and_type(us, PAWN))
163 switch (tolower(str[4])) {
165 return make_promotion_move(from, to, KNIGHT);
167 return make_promotion_move(from, to, BISHOP);
169 return make_promotion_move(from, to, ROOK);
171 return make_promotion_move(from, to, QUEEN);
175 // En passant move? We assume that a pawn move is an en passant move
176 // if the destination square is epSquare.
177 if (to == pos.ep_square() && piece == piece_of_color_and_type(us, PAWN))
178 return make_ep_move(from, to);
180 // Is this a castling move? A king move is assumed to be a castling move
181 // if the destination square is occupied by a friendly rook, or if the
182 // distance between the source and destination squares is more than 1.
183 if (piece == piece_of_color_and_type(us, KING))
185 if (pos.piece_on(to) == piece_of_color_and_type(us, ROOK))
186 return make_castle_move(from, to);
188 if (square_distance(from, to) > 1)
190 // This is a castling move, but we have to translate it to the
191 // internal "king captures rook" representation.
192 SquareDelta delta = (to > from ? DELTA_E : DELTA_W);
196 while ( pos.piece_on(s) != piece_of_color_and_type(us, ROOK)
197 && relative_rank(us, s) == RANK_1);
199 return relative_rank(us, s) == RANK_1 ? make_castle_move(from, s) : MOVE_NONE;
203 return make_move(from, to);
206 // set_position() is called when Stockfish receives the "position" UCI
207 // command. The input parameter is a UCIParser. It is assumed
208 // that this parser has consumed the first token of the UCI command
209 // ("position"), and is ready to read the second token ("startpos"
210 // or "fen", if the input is well-formed).
212 void set_position(Position& pos, UCIParser& up) {
216 if (!(up >> token) || (token != "startpos" && token != "fen"))
219 if (token == "startpos")
221 pos.from_fen(StartPositionFEN, false);
228 while (up >> token && token != "moves")
233 pos.from_fen(fen, Options["UCI_Chess960"].value<bool>());
236 if (token != "moves")
239 // Parse optional move list
244 move = parse_uci_move(pos, token);
245 pos.do_setup_move(move, st);
247 // Our StateInfo st is about going out of scope so copy
248 // its content inside pos before it disappears.
253 // set_option() is called when Stockfish receives the "setoption" UCI
254 // command. The input parameter is a UCIParser. It is assumed
255 // that this parser has consumed the first token of the UCI command
256 // ("setoption"), and is ready to read the second token ("name", if
257 // the input is well-formed).
259 void set_option(UCIParser& up) {
261 string token, name, value;
263 if (!(up >> token) || token != "name") // operator>>() skips any whitespace
269 // Handle names with included spaces
270 while (up >> token && token != "value")
271 name += (" " + token);
273 if (Options.find(name) == Options.end())
275 cout << "No such option: " << name << endl;
280 if (token != "value")
282 Options[name].set_value("true");
289 // Handle values with included spaces
291 value += (" " + token);
293 Options[name].set_value(value);
297 // go() is called when Stockfish receives the "go" UCI command. The
298 // input parameter is a UCIParser. It is assumed that this
299 // parser has consumed the first token of the UCI command ("go"),
300 // and is ready to read the second token. The function sets the
301 // thinking time and other parameters from the input string, and
302 // calls think() (defined in search.cpp) with the appropriate
303 // parameters. Returns false if a quit command is received while
304 // thinking, returns true otherwise.
306 bool go(Position& pos, UCIParser& up) {
310 int time[2] = {0, 0}, inc[2] = {0, 0};
311 int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
312 bool infinite = false, ponder = false;
313 Move searchMoves[MOVES_MAX];
315 searchMoves[0] = MOVE_NONE;
319 if (token == "infinite")
321 else if (token == "ponder")
323 else if (token == "wtime")
325 else if (token == "btime")
327 else if (token == "winc")
329 else if (token == "binc")
331 else if (token == "movestogo")
333 else if (token == "depth")
335 else if (token == "nodes")
337 else if (token == "movetime")
339 else if (token == "searchmoves")
343 searchMoves[numOfMoves++] = parse_uci_move(pos, token);
345 searchMoves[numOfMoves] = MOVE_NONE;
351 return think(pos, infinite, ponder, time, inc, movesToGo,
352 depth, nodes, moveTime, searchMoves);
355 void perft(Position& pos, UCIParser& up) {
363 tm = get_system_time();
365 n = perft(pos, depth * ONE_PLY);
367 tm = get_system_time() - tm;
368 std::cout << "\nNodes " << n
369 << "\nTime (ms) " << tm
370 << "\nNodes/second " << int(n / (tm / 1000.0)) << std::endl;