Add simple debug hit rate counter
[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     else if (token == "isready")
139         std::cout << "readyok" << std::endl;
140     else if (token == "position")
141         set_position(uip);
142     else if (token == "setoption")
143         set_option(uip);
144     else if (token == "go")
145         go(uip);
146
147     // The remaining commands are for debugging purposes only.
148     // Perhaps they should be removed later in order to reduce the
149     // size of the program binary.
150     else if (token == "d")
151         RootPosition.print();
152     else if (token == "flip")
153     {
154         Position p(RootPosition);
155         RootPosition.flipped_copy(p);
156     }
157     else if (token == "eval")
158     {
159         EvalInfo ei;
160         std::cout << "Incremental mg: " << RootPosition.mg_value()
161                   << std::endl;
162         std::cout << "Incremental eg: " << RootPosition.eg_value()
163                   << std::endl;
164         std::cout << "Full eval: "
165                   << evaluate(RootPosition, ei, 0)
166                   << std::endl;
167     }
168     else if (token == "key")
169     {
170         std::cout << "key: " << RootPosition.get_key()
171                   << " material key: " << RootPosition.get_material_key()
172                   << " pawn key: " << RootPosition.get_pawn_key()
173                   << std::endl;
174     }
175     else
176     {
177         std::cout << "Unknown command: " << command << std::endl;
178         while (!uip.eof())
179         {
180             uip >> token;
181             std::cout << token << std::endl;
182         }
183     }
184   }
185
186
187   // set_position() is called when Glaurung receives the "position" UCI
188   // command.  The input parameter is a UCIInputParser.  It is assumed
189   // that this parser has consumed the first token of the UCI command
190   // ("position"), and is ready to read the second token ("startpos"
191   // or "fen", if the input is well-formed).
192
193   void set_position(UCIInputParser &uip) {
194
195     std::string token;
196
197     uip >> token; // operator >> skips any whitespace
198
199     if (token == "startpos")
200         RootPosition.from_fen(StartPosition);
201     else if (token == "fen")
202     {
203         std::string fen;
204         while (token != "moves" && !uip.eof())
205         {
206           uip >> token;
207           fen += token;
208           fen += ' ';
209         }
210         RootPosition.from_fen(fen);
211     }
212
213     if (!uip.eof())
214     {
215         if (token != "moves")
216           uip >> token;
217         if (token == "moves")
218         {
219             Move move;
220             UndoInfo u;
221             while (!uip.eof())
222             {
223                 uip >> token;
224                 move = move_from_string(RootPosition, token);
225                 RootPosition.do_move(move, u);
226                 if (RootPosition.rule_50_counter() == 0)
227                     RootPosition.reset_game_ply();
228             }
229         }
230     }
231   }
232
233
234   // set_option() is called when Glaurung receives the "setoption" UCI
235   // command.  The input parameter is a UCIInputParser.  It is assumed
236   // that this parser has consumed the first token of the UCI command
237   // ("setoption"), and is ready to read the second token ("name", if
238   // the input is well-formed).
239
240   void set_option(UCIInputParser &uip) {
241
242     std::string token, name;
243
244     uip >> token;
245     if (token == "name")
246     {
247         uip >> name;
248         uip >> token;
249         while (!uip.eof() && token != "value")
250         {
251           name += (" " + token);
252           uip >> token;
253         }
254         if (token == "value")
255         {
256             std::getline(uip, token); // reads until end of line
257             set_option_value(name, token);
258         } else
259             push_button(name);
260     }
261   }
262
263
264   // go() is called when Glaurung receives the "go" UCI command.  The
265   // input parameter is a UCIInputParser.  It is assumed that this
266   // parser has consumed the first token of the UCI command ("go"),
267   // and is ready to read the second token.  The function sets the
268   // thinking time and other parameters from the input string, and
269   // calls think() (defined in search.cpp) with the appropriate
270   // parameters.
271
272   void go(UCIInputParser &uip) {
273
274     std::string token;
275
276     int time[2] = {0, 0}, inc[2] = {0, 0};
277     int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
278     bool infinite = false, ponder = false;
279     Move searchMoves[500];
280
281     searchMoves[0] = MOVE_NONE;
282
283     while (!uip.eof())
284     {
285         uip >> token;
286
287         if (token == "infinite")
288             infinite = true;
289         else if (token == "ponder")
290             ponder = true;
291         else if (token == "wtime")
292             uip >> time[0];
293         else if (token == "btime")
294             uip >> time[1];
295         else if (token == "winc")
296             uip >> inc[0];
297         else if (token == "binc")
298             uip >> inc[1];
299         else if (token == "movestogo")
300             uip >> movesToGo;
301         else if (token == "depth")
302             uip >> depth;
303         else if (token == "nodes")
304             uip >> nodes;
305         else if (token == "movetime")
306             uip >> moveTime;
307         else if (token == "searchmoves")
308         {
309             int numOfMoves = 0;
310             while (!uip.eof())
311             {
312                 uip >> token;
313                 searchMoves[numOfMoves++] = move_from_string(RootPosition, token);
314             }
315             searchMoves[numOfMoves] = MOVE_NONE;
316         }
317     }
318
319     if (moveTime)
320         infinite = true;  // HACK
321
322     think(RootPosition, infinite, ponder, time[RootPosition.side_to_move()],
323           inc[RootPosition.side_to_move()], movesToGo, depth, nodes, moveTime,
324           searchMoves);
325   }
326 }