2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /* forward declarations of functions */
24 static void init_protover_2(void);
25 static int parse_cmd(char *cmd
);
27 /* wait for a command */
36 char move_buf
[MAX_STRING
];
40 if (get_engine_value(&e
.side
) == brd
.wtm
&&
41 !get_engine_value(&e
.force_mode
)) {
42 /* start thinking in separate thread */
43 res
= pthread_create(&tid
, 0, process_turn
, 0);
47 fprintf(stderr
, "pthread error: %s\n", strerror(res
));
52 pthread_mutex_lock(&e
.mutex
);
55 pthread_mutex_unlock(&e
.mutex
);
58 engine_xboard
= get_engine_value(&e
.xboard_mode
);
59 if (!engine_xboard
&& !get_engine_value(&e
.thinking
))
60 fprintf(stdout
, "[%s]$ ", program_name
);
63 if (!fgets(cmd
, MAX_STRING
, stdin
)) {
68 if (!strcmp(cmd
, "\n"))
74 /* check if we have received a move */
75 sscanf(cmd
, "%s", move_buf
);
77 /* parse according to the notation we are using */
78 if (get_engine_value(&e
.san_notation
) || !engine_xboard
) {
79 if (!get_engine_value(&e
.pondering
))
80 move
= parse_move_san(move_buf
);
83 for (i
= 0; i
< pm
.count
; i
++)
84 if (strcmp(pm
.sans
[i
], move_buf
) == 0) {
90 move
= parse_move_coord(move_buf
);
93 fprintf(stdout
, "Error (unknown command): %s\n", move_buf
);
95 /* OK, it is a legal move - make it */
97 if (return_ponder
[0] && !strcmp(return_ponder
, move_buf
)) {
98 printf("[ Ponder Hit ]\n");
99 set_engine_value((int *)&e
.pondering
, 0);
100 set_engine_value((int *)&e
.ponderhit
, TRUE
);
101 pthread_cond_signal(&cond_exit
);
103 if (return_ponder
[0]) {
104 printf("[ Ponder Fail :( ]\n");
107 set_engine_value((int *)&e
.pondering
, 0);
108 set_engine_value((int *)&e
.ponderhit
, FALSE
);
109 set_engine_value((int *)&e
.stop_time
, 0);
110 set_engine_value((int *)&e
.max_stop_time
, 0);
111 pthread_cond_signal(&cond_exit
);
112 pthread_join(tid
, NULL
);
116 make_move(move
, FALSE
);
117 set_engine_value(&e
.side
, brd
.wtm
);
129 char total_time
[MAX_STRING
];
132 struct epd_info_t
*ei
;
133 struct moves_t moves
;
136 if (!strncmp(cmd
, "go", 2)) {
137 if (!get_engine_value(&e
.thinking
)) {
138 set_engine_value(&e
.force_mode
, FALSE
);
139 set_engine_value(&e
.side
, brd
.wtm
);
141 /* display current board to console */
142 } else if (!strncmp(cmd
, "board", 5))
145 /* xboard send this command */
146 else if (!strncmp(cmd
, "xboard", 6))
147 set_engine_value(&e
.xboard_mode
, TRUE
);
149 else if (!strncmp(cmd
, "force", 5)) {
150 set_engine_value(&e
.force_mode
, TRUE
);
151 set_engine_value(&e
.side
, NOBODY
);
152 set_engine_value((int *)&e
.stop_time
, 0);
153 set_engine_value((int *)&e
.max_stop_time
, 0);
155 val
= pthread_join(e
.tid
, 0);
157 fprintf(stderr
, "Error occured: %s\n", strerror(val
));
160 /* move now command */
161 } else if (!strncmp(cmd
, "?", 1)) {
162 set_engine_value((int *)&e
.stop_time
, 0);
163 set_engine_value((int *)&e
.max_stop_time
, 0);
164 /* the opponent is a computer */
165 } else if (!strncmp(cmd
, "computer", 8))
166 set_engine_value(&e
.play_computer
, TRUE
);
168 /* xboard support version protocol version 2. we should reply
169 by 'feature' command */
170 else if (!strncmp(cmd
, "protover 2", 10)) {
171 set_engine_value(&e
.san_notation
, TRUE
);
175 } else if (!strncmp(cmd
, "new", 3)) {
177 set_engine_value(&e
.play_computer
, FALSE
);
178 set_engine_value(&e
.force_mode
, FALSE
);
179 set_engine_value(&e
.max_depth
, MAX_PLY
);
180 set_engine_value(&e
.side
, BLACK
);
181 /* display thinking */
182 } else if (!strncmp(cmd
, "post", 4))
183 set_engine_value(&e
.post_mode
, TRUE
);
184 else if (!strncmp(cmd
, "easy", 4))
185 set_engine_value(&e
.ponder_allowed
, FALSE
);
186 /* do not display thinking */
187 else if (!strncmp(cmd
, "nopost", 6))
188 set_engine_value(&e
.post_mode
, FALSE
);
190 /* time remaining for the engine */
191 else if (sscanf(cmd
, "time %d", &val
) == 1) {
192 set_engine_value(&e
.max_time
, val
/ \
193 get_engine_value(&e
.time_div
));
194 set_engine_value(&e
.max_depth
, MAX_PLY
);
195 set_engine_value(&e
.fixed_time
, FALSE
);
196 pthread_cond_signal(&cond_exit
);
198 } else if (sscanf(cmd
, "otim %d", &val
) == 1) {
199 /* handle but skip this */
200 } else if (sscanf(cmd
, "st %d", &val
) == 1) {
201 set_engine_value(&e
.max_time
, val
);
202 set_engine_value(&e
.max_depth
, MAX_PLY
);
203 set_engine_value(&e
.fixed_time
, TRUE
);
205 /* set search depth */
206 } else if (sscanf(cmd
, "sd %d", &val
) == 1) {
207 set_engine_value(&e
.max_time
, 100000);
208 set_engine_value(&e
.max_depth
, val
);
209 } else if (sscanf(cmd
, "level %d %s %d", &val
, &total_time
, &inc
) == 3) {
210 set_engine_value(&e
.inc_time
, inc
* 100);
211 /* we can't change some parameters while searching */
212 /* enable/disable NULL move pruning (CLI command) */
213 } else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "null on", 7))
214 e
.null_pruning
= TRUE
;
215 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "null off", 8))
216 e
.null_pruning
= FALSE
;
218 /* enable/disable Late Move Reductions (CLI command) */
219 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "lmr on", 6))
221 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "lmr off", 7))
224 /* enable/disable Delta Pruning (CLI command) */
225 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "delta on", 8))
226 e
.delta_pruning
= TRUE
;
227 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "delta off", 9))
228 e
.delta_pruning
= FALSE
;
230 /* enable/disable Futility Pruning (CLI command) */
231 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "futil on", 8))
232 e
.futility_pruning
= TRUE
;
233 else if (!get_engine_value(&e
.thinking
) && !strncmp(cmd
, "futil off", 9))
234 e
.futility_pruning
= FALSE
;
236 else if (!strncmp(cmd
, "draw", 4)) {
237 } else if (!strncmp(cmd
, "epd", 3)) {
238 if (!get_engine_value(&e
.thinking
)) {
239 /* EPD - solve test positions */
240 ei
= malloc(sizeof(struct epd_info_t
));
241 filename
= malloc(MAX_STRING
);
243 sscanf(cmd
, "epd %s %d %d %d", filename
, &ei
->think_time
, \
244 &ei
->max_tests
, &ei
->first_test
);
246 ei
->filename
= filename
;
247 pthread_create(&tid
, 0, run_epd_test
, ei
);
249 /* setup board from FEN position */
250 } else if (!strncmp(cmd
, "setboard", 8)) {
251 if (!setup_board(cmd
+ 9))
252 fprintf(stdout
, "Invalid FEN position: %s\n", cmd
+ 9);
253 set_engine_value(&e
.side
, NOBODY
);
255 /* print FEN to stdout */
256 } else if (!strncmp(cmd
, "fen", 3))
257 fprintf(stdout
, "%s\n", current_fen_position(cmd
));
259 /* takeback last move */
260 else if (!strncmp(cmd
, "undo", 4)) {
261 set_engine_value(&e
.side
, NOBODY
);
262 if (game_history
.count
)
266 } else if (!strncmp(cmd
, "quit", 4)) {
270 /* reply with 'pong' command */
271 } else if (sscanf(cmd
, "ping %d", &val
) == 1)
272 fprintf(stdout
, "pong %d\n", val
);
274 /* print possible moves to stdout */
275 else if (!strncmp(cmd
, "moves", 5)) {
276 gen_legal_moves(&moves
);
277 print_moves_san(&moves
);
278 } else if (!strncmp(cmd
, "eval", 4))
279 printf("eval = %d\n", evaluate(-MATE_VALUE
, MATE_VALUE
));
281 /* invalid command, maybe it is a move */
287 /* default xboard parameters */
289 init_protover_2(void)
291 /* disable Unix signals SIGINT and SIGTERM and tell some of our
293 fprintf(stdout
, "feature myname \"%s\"\n" \
295 "feature colors=0\n" \
296 "feature setboard=1\n" \
297 "feature sigint=0\n" \
298 "feature sigterm=0\n" \
300 "feature done=1\n", program_name
);