]> git.sesse.net Git - stockfish/blob - src/uci.cpp
Move uci move parsing under san.cpp
[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-2010 Marco Costalba, Joona Kiiski, Tord Romstad
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 <cctype>
27 #include <iostream>
28 #include <sstream>
29 #include <string>
30
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 "ucioption.h"
39
40 using namespace std;
41
42
43 namespace {
44
45   // FEN string for the initial position
46   const string StartPositionFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
47
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;
51
52   // Local functions
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 }
58
59
60 /// execute_uci_command() takes a string as input, uses a UCIParser
61 /// object to parse this text string as a UCI command, and calls
62 /// the appropriate functions. In addition to the UCI commands,
63 /// the function also supports a few debug commands.
64
65 bool execute_uci_command(const string& cmd) {
66
67   static Position pos(StartPositionFEN, false, 0); // The root position
68   UCIParser up(cmd);
69   string token;
70
71   if (!(up >> token)) // operator>>() skips any whitespace
72       return true;
73
74   if (token == "quit")
75       return false;
76
77   if (token == "go")
78       return go(pos, up);
79
80   if (token == "uci")
81   {
82       cout << "id name " << engine_name()
83            << "\nid author Tord Romstad, Marco Costalba, Joona Kiiski\n";
84       print_uci_options();
85       cout << "uciok" << endl;
86   }
87   else if (token == "ucinewgame")
88       pos.from_fen(StartPositionFEN, false);
89
90   else if (token == "isready")
91       cout << "readyok" << endl;
92
93   else if (token == "position")
94       set_position(pos, up);
95
96   else if (token == "setoption")
97       set_option(up);
98
99   // The remaining commands are for debugging purposes only
100   else if (token == "d")
101       pos.print();
102
103   else if (token == "flip")
104   {
105       Position p(pos, pos.thread());
106       pos.flipped_copy(p);
107   }
108   else if (token == "eval")
109   {
110       Value evalMargin;
111       cout << "Incremental mg: "   << mg_value(pos.value())
112            << "\nIncremental eg: " << eg_value(pos.value())
113            << "\nFull eval: "      << evaluate(pos, evalMargin) << endl;
114   }
115   else if (token == "key")
116       cout << "key: " << hex << pos.get_key()
117            << "\nmaterial key: " << pos.get_material_key()
118            << "\npawn key: " << pos.get_pawn_key() << endl;
119
120   else if (token == "perft")
121       perft(pos, up);
122
123   else
124       cout << "Unknown command: " << cmd << endl;
125
126   return true;
127 }
128
129
130 ////
131 //// Local functions
132 ////
133
134 namespace {
135
136   // set_position() is called when Stockfish receives the "position" UCI
137   // command. The input parameter is a UCIParser. It is assumed
138   // that this parser has consumed the first token of the UCI command
139   // ("position"), and is ready to read the second token ("startpos"
140   // or "fen", if the input is well-formed).
141
142   void set_position(Position& pos, UCIParser& up) {
143
144     string token;
145
146     if (!(up >> token) || (token != "startpos" && token != "fen"))
147         return;
148
149     if (token == "startpos")
150     {
151         pos.from_fen(StartPositionFEN, false);
152         if (!(up >> token))
153             return;
154     }
155     else // fen
156     {
157         string fen;
158         while (up >> token && token != "moves")
159         {
160             fen += token;
161             fen += ' ';
162         }
163         pos.from_fen(fen, Options["UCI_Chess960"].value<bool>());
164     }
165
166     if (token != "moves")
167         return;
168
169     // Parse optional move list
170     Move move;
171     StateInfo st;
172     while (up >> token)
173     {
174         move = move_from_uci(pos, token);
175         pos.do_setup_move(move, st);
176     }
177     // Our StateInfo st is about going out of scope so copy
178     // its content inside pos before it disappears.
179     pos.detach();
180   }
181
182
183   // set_option() is called when Stockfish receives the "setoption" UCI
184   // command. The input parameter is a UCIParser. It is assumed
185   // that this parser has consumed the first token of the UCI command
186   // ("setoption"), and is ready to read the second token ("name", if
187   // the input is well-formed).
188
189   void set_option(UCIParser& up) {
190
191     string token, name, value;
192
193     if (!(up >> token) || token != "name") // operator>>() skips any whitespace
194         return;
195
196     if (!(up >> name))
197         return;
198
199     // Handle names with included spaces
200     while (up >> token && token != "value")
201         name += (" " + token);
202
203     if (Options.find(name) == Options.end())
204     {
205         cout << "No such option: " << name << endl;
206         return;
207     }
208
209     // Is a button ?
210     if (token != "value")
211     {
212         Options[name].set_value("true");
213         return;
214     }
215
216     if (!(up >> value))
217         return;
218
219     // Handle values with included spaces
220     while (up >> token)
221         value += (" " + token);
222
223     Options[name].set_value(value);
224   }
225
226
227   // go() is called when Stockfish receives the "go" UCI command. The
228   // input parameter is a UCIParser. It is assumed that this
229   // parser has consumed the first token of the UCI command ("go"),
230   // and is ready to read the second token. The function sets the
231   // thinking time and other parameters from the input string, and
232   // calls think() (defined in search.cpp) with the appropriate
233   // parameters. Returns false if a quit command is received while
234   // thinking, returns true otherwise.
235
236   bool go(Position& pos, UCIParser& up) {
237
238     string token;
239
240     int time[2] = {0, 0}, inc[2] = {0, 0};
241     int movesToGo = 0, depth = 0, nodes = 0, moveTime = 0;
242     bool infinite = false, ponder = false;
243     Move searchMoves[MOVES_MAX];
244
245     searchMoves[0] = MOVE_NONE;
246
247     while (up >> token)
248     {
249         if (token == "infinite")
250             infinite = true;
251         else if (token == "ponder")
252             ponder = true;
253         else if (token == "wtime")
254             up >> time[0];
255         else if (token == "btime")
256             up >> time[1];
257         else if (token == "winc")
258             up >> inc[0];
259         else if (token == "binc")
260             up >> inc[1];
261         else if (token == "movestogo")
262             up >> movesToGo;
263         else if (token == "depth")
264             up >> depth;
265         else if (token == "nodes")
266             up >> nodes;
267         else if (token == "movetime")
268             up >> moveTime;
269         else if (token == "searchmoves")
270         {
271             int numOfMoves = 0;
272             while (up >> token)
273                 searchMoves[numOfMoves++] = move_from_uci(pos, token);
274
275             searchMoves[numOfMoves] = MOVE_NONE;
276         }
277     }
278
279     assert(pos.is_ok());
280
281     return think(pos, infinite, ponder, time, inc, movesToGo,
282                  depth, nodes, moveTime, searchMoves);
283   }
284
285   void perft(Position& pos, UCIParser& up) {
286
287     int depth, tm;
288     int64_t n;
289
290     if (!(up >> depth))
291         return;
292
293     tm = get_system_time();
294
295     n = perft(pos, depth * ONE_PLY);
296
297     tm = get_system_time() - tm;
298     std::cout << "\nNodes " << n
299               << "\nTime (ms) " << tm
300               << "\nNodes/second " << int(n / (tm / 1000.0)) << std::endl;
301   }
302 }