Add pawn ending restriction on null move pruning
[purplehaze.git] / src / xboard.cpp
blob928873ea9a24a96ba988e4706a1b7b26ff8fb4b7
1 /* Copyright (C) 2007-2011 Vincent Ollivier
3 * Purple Haze is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * Purple Haze is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include <assert.h>
18 #include <iostream>
19 #include <sstream>
20 #include <string>
21 #include <signal.h>
23 #include "xboard.h"
25 Xboard::Xboard()
27 force_mode = true;
28 debug_mode = false;
29 verbosity = 1;
32 void Xboard::think()
34 if (get_verbosity() > 1) std::cout << game.board << std::endl;
36 std::string move = search_move();
37 std::string output = "";
38 if (move == "LOST") {
39 output = "result ";
40 if (game.current_position().get_turn_color() == WHITE) {
41 output += "0-1 {Black mates}";
42 } else {
43 output += "1-0 {White mates}";
45 } else if (move == "DRAW") {
46 output = "result 1/2-1/2";
47 } else if (!force_mode) {
48 play_move(move);
49 if (debug_mode) {
50 log << std::endl << " DEBUG: "
51 << game.time.get_elapsed_time() / 100.0f
52 << " of " << game.time.get_allocated_time() / 100.0f
53 << " seconds used to play";
55 if (get_verbosity() > 1) {
56 std::cout << std::endl;
57 game.print_tt_stats();
59 output = "move " + move;
61 std::cout << output << std::endl;
62 if (debug_mode) {
63 log << std::endl << "< " << output;
67 void Xboard::loop()
69 signal(SIGINT, SIG_IGN);
70 std::cout << std::endl; // Acknowledge Xboard mode
72 std::string cmd;
73 std::cin >> cmd;
74 while (cmd != "quit") {
75 if (debug_mode) {
76 log << "> " << cmd;
78 if (cmd == "protover") {
79 int n;
80 std::cin >> n;
81 if (debug_mode) {
82 log << " " << n;
84 if (n == 2) {
85 for (int i = 0; i < XBOARD_NB_FEATURES; ++i) {
86 std::cout << "feature " << XBOARD_FEATURES[i][0];
87 if (debug_mode) {
88 log << std::endl
89 << "< feature " << XBOARD_FEATURES[i][0];
91 std::string value = XBOARD_FEATURES[i][1];
92 if (value == "0" || value == "1") {
93 std::cout << "=" << value << std::endl;
94 if (debug_mode) {
95 log << "=" << value;
97 } else {
98 std::cout << "=\"" << value << "\"" << std::endl;
99 if (debug_mode) {
100 log << "=\"" << value << "\"";
103 std::string reply, feature;
104 std::cin >> reply;
105 std::cin >> feature;
106 if (debug_mode) {
107 log << std::endl << "> " << reply << " " << feature;
109 assert(feature == XBOARD_FEATURES[i][0]);
110 if (reply == "accepted") continue;
111 if (reply == "rejected") assert(false); // FIXME
112 assert(false); // FIXME
115 } else if (cmd == "debug") {
116 if (!debug_mode) {
117 debug_mode = true;
118 log.open("game.log", std::ios::app);
119 log << " DEBUG: Starting log" << std::endl;
121 } else if (cmd == "new") {
122 new_game();
123 set_board(DEFAULT_FEN);
124 force_mode = false;
125 } else if (cmd == "setboard") {
126 std::string fen;
127 getline(std::cin, fen);
128 fen.erase(0, 1); // Remove the first whitespace
129 new_game();
130 set_board(fen);
131 if (debug_mode) {
132 log << " " << fen;
134 force_mode = false;
135 } else if (cmd == "go") {
136 force_mode = false;
137 think();
138 } else if (cmd == "force") {
139 force_mode = true;
140 } else if (cmd == "ping") {
141 int n;
142 std::cin >> n;
143 std::cout << "pong " << n << std::endl;
144 } else if (cmd == "level") {
145 // Number of moves
146 int moves;
147 std::cin >> moves;
148 if (debug_mode) {
149 log << " " << moves;
152 // TODO "level 0 m 0" means play the entire game in 'm' minutes,
153 // but the current time management don't support it.
154 if (moves == 0) moves = 60;
156 // Time interval in minutes or minutes:seconds
157 int time;
158 std::string str_time;
159 std::cin >> str_time;
160 if (debug_mode) {
161 log << " " << str_time;
163 size_t sep = str_time.find(":");
164 if (sep == std::string::npos) {
165 std::istringstream minutes(str_time);
166 minutes >> time;
167 time *= 60;
168 } else {
169 std::istringstream minutes(str_time.substr(0, sep));
170 std::istringstream seconds(str_time.substr(sep + 1));
171 seconds >> time;
172 int tmp;
173 minutes >> tmp;
174 time += 60 * tmp;
177 // Control character
178 int control;
179 std::cin >> control;
180 if (debug_mode) {
181 log << " " << control;
183 if (control == 0) {
184 set_time(moves, time);
185 } else { // Not in Xboard protocol
186 // TODO If not zero, control is a time increment,
187 // but currently this time is not directly used
188 set_time(moves, time);
190 } else if (cmd == "time") {
191 int time = 0;
192 std::cin >> time;
193 if (debug_mode) {
194 log << " " << time;
196 set_remaining_time(time);
197 } else if (cmd == "otim") {
198 int time = 0;
199 std::cin >> time;
200 if (debug_mode) {
201 log << " " << time;
203 } else if (cmd == "sd") {
204 int d = 0;
205 std::cin >> d;
206 if (debug_mode) {
207 log << " " << d;
209 set_depth(d);
210 } else if (cmd == "undo") {
211 undo_move();
212 } else if (cmd == "remove") {
213 undo_move();
214 undo_move();
215 } else if (cmd == "post") {
216 set_output_thinking(true);
217 } else if (cmd == "nopost") {
218 set_output_thinking(false);
219 } else if (cmd == "hard") {
221 } else if (4 <= cmd.size() && cmd.size() <= 5 &&
222 'a' <= cmd[0] && cmd[0] <= 'h' &&
223 '1' <= cmd[1] && cmd[1] <= '8' &&
224 'a' <= cmd[2] && cmd[2] <= 'h' &&
225 '1' <= cmd[3] && cmd[3] <= '8' &&
226 !parse_move(cmd).is_null()) {
227 if (debug_mode) {
228 log << std::endl << " DEBUG: move '" << cmd << "' successfully parsed";
230 if (!play_move(cmd)) {
231 std::cout << "Illegal move: " << cmd << std::endl;
232 if (debug_mode) {
233 log << std::endl << "< Illegal move: " << cmd;
236 if (!force_mode) think();
237 } else if (cmd == "verbose") { // Debug mode
238 verbosity = 2;
239 } else {
240 if (debug_mode) {
241 log << std::endl << " DEBUG: unrecognized command:" << cmd;
244 if (debug_mode) {
245 log << std::endl;
247 std::cin >> cmd;
249 if (debug_mode) {
250 log << "> " << cmd << std::endl;
251 log << " DEBUG: Closing log" << std::endl;
252 log.close();