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