]> git.sesse.net Git - stockfish/blob - src/uci.cpp
48459757dda217aaf117fc5fbc60211722555488
[stockfish] / src / uci.cpp
1 /*
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 Marco Costalba
5
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.
10
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.
15
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/>.
18 */
19
20
21 ////
22 //// Includes
23 ////
24
25 #include <cassert>
26 #include <iostream>
27 #include <sstream>
28 #include <string>
29
30 #include "book.h"
31 #include "evaluate.h"
32 #include "misc.h"
33 #include "move.h"
34 #include "movegen.h"
35 #include "position.h"
36 #include "san.h"
37 #include "search.h"
38 #include "uci.h"
39 #include "ucioption.h"
40
41
42 ////
43 //// Local definitions:
44 ////
45
46 namespace {
47
48   // UCIInputParser is a class for parsing UCI input.  The class
49   // is actually a string stream built on a given input string.
50
51   typedef std::istringstream UCIInputParser;
52
53   // The root position.  This is set up when the user (or in practice, the GUI)
54   // sends the "position" UCI command.  The root position is sent to the think()
55   // function when the program receives the "go" command.
56   Position RootPosition;
57
58   // Local functions
59   void get_command();
60   void handle_command(const std::string &command);
61   void set_option(UCIInputParser &uip);
62   void set_position(UCIInputParser &uip);
63   void go(UCIInputParser &uip);
64 }
65
66
67 ////
68 //// Functions
69 ////
70
71 /// uci_main_loop() is the only global function in this file.  It is
72 /// called immediately after the program has finished initializing.
73 /// The program remains in this loop until it receives the "quit" UCI
74 /// command.
75
76 void uci_main_loop() {
77
78   RootPosition.from_fen(StartPosition);
79
80   while (1)
81       get_command();
82 }
83
84
85 ////
86 //// Local functions
87 ////
88
89 namespace {
90
91   // get_command() waits for a command from the user, and passes
92   // this command to handle_command.  get_command also intercepts
93   // EOF from stdin, by translating EOF to the "quit" command.  This
94   // ensures that Stockfish exits gracefully if the GUI dies
95   // unexpectedly.
96
97   void get_command() {
98
99     std::string command;
100
101     if (!std::getline(std::cin, command))
102         command = "quit";
103
104     handle_command(command);
105   }
106
107
108   // handle_command() takes a text string as input, uses a
109   // UCIInputParser object to parse this text string as a UCI command,
110   // and calls the appropriate functions.  In addition to the UCI
111   // commands, the function also supports a few debug commands.
112
113   void handle_command(const std::string &command) {
114
115     UCIInputParser uip(command);
116     std::string token;
117
118     uip >> token; // operator >> skips any whitespace
119
120     if (token == "quit")
121     {
122         OpeningBook.close();
123         stop_threads();
124         quit_eval();
125         exit(0);
126     }
127     else if (token == "uci")
128     {
129         std::cout << "id name " << engine_name() << std::endl
130                   << "id author Tord Romstad, Marco Costalba"
131                   << std::endl;
132         print_uci_options();
133         std::cout << "uciok" << std::endl;
134     }
135     else if (token == "ucinewgame")
136     {
137         TT.clear();
138         Position::init_piece_square_tables();
139         RootPosition.from_fen(StartPosition);
140     }
141     else if (token == "isready")
142         std::cout << "readyok" << std::endl;
143     else if (token == "position")
144         set_position(uip);
145     else if (token == "setoption")
146         set_option(uip);
147     else if (token == "go")
148         go(uip);
149
150     // The remaining commands are for debugging purposes only.
151     // Perhaps they should be removed later in order to reduce the
152     // size of the program binary.
153     else if (token == "d")
154         RootPosition.print();
155     else if (token == "flip")
156     {
157         Position p(RootPosition);
158         RootPosition.flipped_copy(p);
159     }
160     else if (token == "eval")
161     {
162         EvalInfo ei;
163         std::cout << "Incremental mg: " << RootPosition.mg_value()
164                   << std::endl;
165         std::cout << "Incremental eg: " << RootPosition.eg_value()
166                   << std::endl;
167         std::cout << "Full eval: "
168                   << evaluate(RootPosition, ei, 0)
169                   << std::endl;
170     }
171     else if (token == "key")
172     {
173         std::cout << "key: " << std::hex << RootPosition.get_key()
174                   << " material key: " << RootPosition.get_material_key()
175                   << " pawn key: " << RootPosition.get_pawn_key()
176                   << std::endl;
177     }
178     else
179     {
180         std::cout << "Unknown command: " << command << std::endl;
181         while (!uip.eof())
182         {
183             uip >> token;
184             std::cout << token << std::endl;
185         }
186     }
187   }
188
189
190   // set_position() is called when Stockfish receives the "position" UCI
191   // command.  The input parameter is a UCIInputParser.  It is assumed
192   // that this parser has consumed the first token of the UCI command
193   // ("position"), and is ready to read the second token ("startpos"
194   // or "fen", if the input is well-formed).
195
196   void set_position(UCIInputParser &uip) {
197
198     std::string token;
199
200     uip >> token; // operator >> skips any whitespace
201
202     if (token == "startpos")
203         RootPosition.from_fen(StartPosition);
204     else if (token == "fen")
205     {
206         std::string fen;
207         while (token != "moves" && !uip.eof())
208         {
209           uip >> token;
210           fen += token;
211           fen += ' ';
212         }
213         RootPosition.from_fen(fen);
214     }
215
216     if (!uip.eof())
217     {
218         if (token != "moves")
219           uip >> token;
220         if (token == "moves")
221         {
222             Move move;
223             StateInfo st;
224             while (!uip.eof())
225             {
226                 uip >> token;
227                 move = move_from_string(RootPosition, token);
228                 RootPosition.do_move(move, st);
229                 if (RootPosition.rule_50_counter() == 0)
230                     RootPosition.reset_game_ply();
231             }
232             // Our StateInfo st is about going out of scope,
233             // so save its content before they disappear.
234             RootPosition.setStartState(st);
235         }
236     }
237   }
238
239
240   // set_option() is called when Stockfish receives the "setoption" UCI
241   // command.  The input parameter is a UCIInputParser.  It is assumed
242   // that this parser has consumed the first token of the UCI command
243   // ("setoption"), and is ready to read the second token ("name", if
244   // the input is well-formed).
245
246   void set_option(UCIInputParser &uip) {
247
248     std::string token, name;
249
250     uip >> token;
251     if (token == "name")
252     {
253         uip >> name;
254         uip >> token;
255         while (!uip.eof() && token != "value")
256         {
257           name += (" " + token);
258           uip >> token;
259         }
260         if (token == "value")
261         {
262             std::getline(uip, token); // reads until end of line
263             set_option_value(name, token);
264         } else
265             push_button(name);
266     }
267   }
268
269
270   // go() is called when Stockfish receives the "go" UCI command.  The
271   // input parameter is a UCIInputParser.  It is assumed that this
272   // parser has consumed the first token of the UCI command ("go"),
273   // and is ready to read the second token.  The function sets the
274   // thinking time and other parameters from the input string, and
275   // calls think() (defined in search.cpp) with the appropriate
276   // parameters.
277
278   void go(UCIInputParser &uip) {
279
280     std::string token;
281
282     int time[2] = {0, 0}, inc[2] = {0, 0};
283     int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
284     bool infinite = false, ponder = false;
285     Move searchMoves[500];
286
287     searchMoves[0] = MOVE_NONE;
288
289     while (!uip.eof())
290     {
291         uip >> token;
292
293         if (token == "infinite")
294             infinite = true;
295         else if (token == "ponder")
296             ponder = true;
297         else if (token == "wtime")
298             uip >> time[0];
299         else if (token == "btime")
300             uip >> time[1];
301         else if (token == "winc")
302             uip >> inc[0];
303         else if (token == "binc")
304             uip >> inc[1];
305         else if (token == "movestogo")
306             uip >> movesToGo;
307         else if (token == "depth")
308             uip >> depth;
309         else if (token == "nodes")
310             uip >> nodes;
311         else if (token == "movetime")
312             uip >> moveTime;
313         else if (token == "searchmoves")
314         {
315             int numOfMoves = 0;
316             while (!uip.eof())
317             {
318                 uip >> token;
319                 searchMoves[numOfMoves++] = move_from_string(RootPosition, token);
320             }
321             searchMoves[numOfMoves] = MOVE_NONE;
322         }
323     }
324
325     if (moveTime)
326         infinite = true;  // HACK
327
328     assert(RootPosition.is_ok());
329
330     think(RootPosition, infinite, ponder, RootPosition.side_to_move(), time,
331           inc, movesToGo, depth, nodes, moveTime, searchMoves);
332   }
333 }