Before starting to tinker, ran clang-format on files that seem like relevant starting...
[sgk-go] / interface / play_gtp.c
CommitLineData
7eeb782e
AT
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * This is GNU Go, a Go program. Contact gnugo@gnu.org, or see *
3 * http://www.gnu.org/software/gnugo/ for more information. *
4 * *
5 * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
6 * 2008 and 2009 by the Free Software Foundation. *
7 * *
8 * This program is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU General Public License as *
10 * published by the Free Software Foundation - version 3 or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License in file COPYING for more details. *
17 * *
18 * You should have received a copy of the GNU General Public *
19 * License along with this program; if not, write to the Free *
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
21 * Boston, MA 02111, USA. *
22\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
23
24#include "gnugo.h"
25
7eeb782e
AT
26#include <assert.h>
27#include <ctype.h>
7eeb782e 28#include <math.h>
c150f57c
AT
29#include <stdio.h>
30#include <string.h>
7eeb782e 31
c150f57c
AT
32#include "gg_utils.h"
33#include "gtp.h"
7eeb782e
AT
34#include "interface.h"
35#include "liberty.h"
7eeb782e
AT
36
37/* Internal state that's not part of the engine. */
38static int report_uncertainty = 0;
39static int gtp_orientation = 0;
40
41static void gtp_print_code(int c);
c150f57c
AT
42static void gtp_print_vertices2(int n, int* moves);
43static void rotate_on_input(int ai, int aj, int* bi, int* bj);
44static void rotate_on_output(int ai, int aj, int* bi, int* bj);
7eeb782e 45
c150f57c 46#define DECLARE(func) static int func(char* s)
7eeb782e
AT
47
48DECLARE(gtp_aa_confirm_safety);
49DECLARE(gtp_accurate_approxlib);
50DECLARE(gtp_accuratelib);
51DECLARE(gtp_advance_random_seed);
52DECLARE(gtp_all_legal);
53DECLARE(gtp_all_move_values);
54DECLARE(gtp_analyze_eyegraph);
55DECLARE(gtp_analyze_semeai);
56DECLARE(gtp_analyze_semeai_after_move);
57DECLARE(gtp_attack);
58DECLARE(gtp_attack_either);
59DECLARE(gtp_block_off);
60DECLARE(gtp_break_in);
61DECLARE(gtp_captures);
62DECLARE(gtp_clear_board);
63DECLARE(gtp_clear_cache);
64DECLARE(gtp_combination_attack);
65DECLARE(gtp_combination_defend);
66DECLARE(gtp_connect);
67DECLARE(gtp_countlib);
68DECLARE(gtp_cputime);
69DECLARE(gtp_decrease_depths);
70DECLARE(gtp_defend);
71DECLARE(gtp_defend_both);
72DECLARE(gtp_disconnect);
73DECLARE(gtp_does_attack);
74DECLARE(gtp_does_defend);
75DECLARE(gtp_does_surround);
76DECLARE(gtp_dragon_data);
77DECLARE(gtp_dragon_status);
78DECLARE(gtp_dragon_stones);
79DECLARE(gtp_draw_search_area);
80DECLARE(gtp_dump_stack);
81DECLARE(gtp_echo);
82DECLARE(gtp_echo_err);
83DECLARE(gtp_estimate_score);
84DECLARE(gtp_eval_eye);
85DECLARE(gtp_experimental_score);
86DECLARE(gtp_eye_data);
87DECLARE(gtp_final_score);
88DECLARE(gtp_final_status);
89DECLARE(gtp_final_status_list);
90DECLARE(gtp_findlib);
91DECLARE(gtp_finish_sgftrace);
92DECLARE(gtp_fixed_handicap);
93DECLARE(gtp_followup_influence);
94DECLARE(gtp_genmove);
95DECLARE(gtp_genmove_black);
96DECLARE(gtp_genmove_white);
97DECLARE(gtp_get_connection_node_counter);
98DECLARE(gtp_get_handicap);
99DECLARE(gtp_get_komi);
100DECLARE(gtp_get_life_node_counter);
101DECLARE(gtp_get_owl_node_counter);
102DECLARE(gtp_get_random_seed);
103DECLARE(gtp_get_reading_node_counter);
104DECLARE(gtp_get_trymove_counter);
105DECLARE(gtp_gg_genmove);
106DECLARE(gtp_gg_undo);
107DECLARE(gtp_half_eye_data);
108DECLARE(gtp_increase_depths);
109DECLARE(gtp_initial_influence);
110DECLARE(gtp_invariant_hash);
111DECLARE(gtp_invariant_hash_for_moves);
112DECLARE(gtp_is_legal);
113DECLARE(gtp_is_surrounded);
114DECLARE(gtp_kgs_genmove_cleanup);
115DECLARE(gtp_known_command);
116DECLARE(gtp_ladder_attack);
117DECLARE(gtp_last_move);
118DECLARE(gtp_limit_search);
119DECLARE(gtp_list_commands);
120DECLARE(gtp_list_stones);
121DECLARE(gtp_loadsgf);
122DECLARE(gtp_move_influence);
123DECLARE(gtp_move_probabilities);
124DECLARE(gtp_move_reasons);
125DECLARE(gtp_move_uncertainty);
126DECLARE(gtp_move_history);
127DECLARE(gtp_name);
128DECLARE(gtp_owl_attack);
129DECLARE(gtp_owl_connection_defends);
130DECLARE(gtp_owl_defend);
131DECLARE(gtp_owl_does_attack);
132DECLARE(gtp_owl_does_defend);
133DECLARE(gtp_owl_substantial);
134DECLARE(gtp_owl_threaten_attack);
135DECLARE(gtp_owl_threaten_defense);
136DECLARE(gtp_place_free_handicap);
137DECLARE(gtp_play);
138DECLARE(gtp_playblack);
139DECLARE(gtp_playwhite);
140DECLARE(gtp_popgo);
141DECLARE(gtp_printsgf);
142DECLARE(gtp_program_version);
143DECLARE(gtp_protocol_version);
144DECLARE(gtp_query_boardsize);
145DECLARE(gtp_query_orientation);
146DECLARE(gtp_quit);
147DECLARE(gtp_reg_genmove);
148DECLARE(gtp_report_uncertainty);
149DECLARE(gtp_reset_connection_node_counter);
150DECLARE(gtp_reset_life_node_counter);
151DECLARE(gtp_reset_owl_node_counter);
152DECLARE(gtp_reset_reading_node_counter);
153DECLARE(gtp_reset_search_mask);
154DECLARE(gtp_reset_trymove_counter);
155DECLARE(gtp_restricted_genmove);
156DECLARE(gtp_same_dragon);
157DECLARE(gtp_set_boardsize);
158DECLARE(gtp_set_free_handicap);
159DECLARE(gtp_set_komi);
160DECLARE(gtp_set_level);
161DECLARE(gtp_set_orientation);
162DECLARE(gtp_set_random_seed);
163DECLARE(gtp_set_search_diamond);
164DECLARE(gtp_set_search_limit);
165DECLARE(gtp_showboard);
166DECLARE(gtp_start_sgftrace);
167DECLARE(gtp_surround_map);
168DECLARE(gtp_tactical_analyze_semeai);
169DECLARE(gtp_test_eyeshape);
170DECLARE(gtp_time_left);
171DECLARE(gtp_time_settings);
172DECLARE(gtp_top_moves);
173DECLARE(gtp_top_moves_black);
174DECLARE(gtp_top_moves_white);
175DECLARE(gtp_tryko);
176DECLARE(gtp_trymove);
177DECLARE(gtp_tune_move_ordering);
178DECLARE(gtp_unconditional_status);
179DECLARE(gtp_undo);
180DECLARE(gtp_what_color);
181DECLARE(gtp_worm_cutstone);
182DECLARE(gtp_worm_data);
183DECLARE(gtp_worm_stones);
184
185/* List of known commands. */
186static struct gtp_command commands[] = {
c150f57c
AT
187 { "aa_confirm_safety", gtp_aa_confirm_safety },
188 { "accurate_approxlib", gtp_accurate_approxlib },
189 { "accuratelib", gtp_accuratelib },
190 { "advance_random_seed", gtp_advance_random_seed },
191 { "all_legal", gtp_all_legal },
192 { "all_move_values", gtp_all_move_values },
193 { "analyze_eyegraph", gtp_analyze_eyegraph },
194 { "analyze_semeai", gtp_analyze_semeai },
195 { "analyze_semeai_after_move", gtp_analyze_semeai_after_move },
196 { "attack", gtp_attack },
197 { "attack_either", gtp_attack_either },
198 { "black", gtp_playblack },
199 { "block_off", gtp_block_off },
200 { "boardsize", gtp_set_boardsize },
201 { "break_in", gtp_break_in },
202 { "captures", gtp_captures },
203 { "clear_board", gtp_clear_board },
204 { "clear_cache", gtp_clear_cache },
205 { "color", gtp_what_color },
206 { "combination_attack", gtp_combination_attack },
207 { "combination_defend", gtp_combination_defend },
208 { "connect", gtp_connect },
209 { "countlib", gtp_countlib },
210 { "cputime", gtp_cputime },
211 { "decrease_depths", gtp_decrease_depths },
212 { "defend", gtp_defend },
213 { "defend_both", gtp_defend_both },
214 { "disconnect", gtp_disconnect },
215 { "does_attack", gtp_does_attack },
216 { "does_defend", gtp_does_defend },
217 { "does_surround", gtp_does_surround },
218 { "dragon_data", gtp_dragon_data },
219 { "dragon_status", gtp_dragon_status },
220 { "dragon_stones", gtp_dragon_stones },
221 { "draw_search_area", gtp_draw_search_area },
222 { "dump_stack", gtp_dump_stack },
223 { "echo", gtp_echo },
224 { "echo_err", gtp_echo_err },
225 { "estimate_score", gtp_estimate_score },
226 { "eval_eye", gtp_eval_eye },
227 { "experimental_score", gtp_experimental_score },
228 { "eye_data", gtp_eye_data },
229 { "final_score", gtp_final_score },
230 { "final_status", gtp_final_status },
231 { "final_status_list", gtp_final_status_list },
232 { "findlib", gtp_findlib },
233 { "finish_sgftrace", gtp_finish_sgftrace },
234 { "fixed_handicap", gtp_fixed_handicap },
235 { "followup_influence", gtp_followup_influence },
236 { "genmove", gtp_genmove },
237 { "genmove_black", gtp_genmove_black },
238 { "genmove_white", gtp_genmove_white },
239 { "get_connection_node_counter", gtp_get_connection_node_counter },
240 { "get_handicap", gtp_get_handicap },
241 { "get_komi", gtp_get_komi },
242 { "get_life_node_counter", gtp_get_life_node_counter },
243 { "get_owl_node_counter", gtp_get_owl_node_counter },
244 { "get_random_seed", gtp_get_random_seed },
245 { "get_reading_node_counter", gtp_get_reading_node_counter },
246 { "get_trymove_counter", gtp_get_trymove_counter },
247 { "gg-undo", gtp_gg_undo },
248 { "gg_genmove", gtp_gg_genmove },
249 { "half_eye_data", gtp_half_eye_data },
250 { "help", gtp_list_commands },
251 { "increase_depths", gtp_increase_depths },
252 { "initial_influence", gtp_initial_influence },
253 { "invariant_hash_for_moves", gtp_invariant_hash_for_moves },
254 { "invariant_hash", gtp_invariant_hash },
255 { "is_legal", gtp_is_legal },
256 { "is_surrounded", gtp_is_surrounded },
257 { "kgs-genmove_cleanup", gtp_kgs_genmove_cleanup },
258 { "known_command", gtp_known_command },
259 { "komi", gtp_set_komi },
260 { "ladder_attack", gtp_ladder_attack },
261 { "last_move", gtp_last_move },
262 { "level", gtp_set_level },
263 { "limit_search", gtp_limit_search },
264 { "list_commands", gtp_list_commands },
265 { "list_stones", gtp_list_stones },
266 { "loadsgf", gtp_loadsgf },
267 { "move_influence", gtp_move_influence },
268 { "move_probabilities", gtp_move_probabilities },
269 { "move_reasons", gtp_move_reasons },
270 { "move_uncertainty", gtp_move_uncertainty },
271 { "move_history", gtp_move_history },
272 { "name", gtp_name },
273 { "new_score", gtp_estimate_score },
274 { "orientation", gtp_set_orientation },
275 { "owl_attack", gtp_owl_attack },
276 { "owl_connection_defends", gtp_owl_connection_defends },
277 { "owl_defend", gtp_owl_defend },
278 { "owl_does_attack", gtp_owl_does_attack },
279 { "owl_does_defend", gtp_owl_does_defend },
280 { "owl_substantial", gtp_owl_substantial },
281 { "owl_threaten_attack", gtp_owl_threaten_attack },
282 { "owl_threaten_defense", gtp_owl_threaten_defense },
283 { "place_free_handicap", gtp_place_free_handicap },
284 { "play", gtp_play },
285 { "popgo", gtp_popgo },
286 { "printsgf", gtp_printsgf },
287 { "protocol_version", gtp_protocol_version },
288 { "query_boardsize", gtp_query_boardsize },
289 { "query_orientation", gtp_query_orientation },
290 { "quit", gtp_quit },
291 { "reg_genmove", gtp_reg_genmove },
292 { "report_uncertainty", gtp_report_uncertainty },
293 { "reset_connection_node_counter", gtp_reset_connection_node_counter },
294 { "reset_life_node_counter", gtp_reset_life_node_counter },
295 { "reset_owl_node_counter", gtp_reset_owl_node_counter },
296 { "reset_reading_node_counter", gtp_reset_reading_node_counter },
297 { "reset_search_mask", gtp_reset_search_mask },
298 { "reset_trymove_counter", gtp_reset_trymove_counter },
299 { "restricted_genmove", gtp_restricted_genmove },
300 { "same_dragon", gtp_same_dragon },
301 { "set_free_handicap", gtp_set_free_handicap },
302 { "set_random_seed", gtp_set_random_seed },
303 { "set_search_diamond", gtp_set_search_diamond },
304 { "set_search_limit", gtp_set_search_limit },
305 { "showboard", gtp_showboard },
306 { "start_sgftrace", gtp_start_sgftrace },
307 { "surround_map", gtp_surround_map },
308 { "tactical_analyze_semeai", gtp_tactical_analyze_semeai },
309 { "test_eyeshape", gtp_test_eyeshape },
310 { "time_left", gtp_time_left },
311 { "time_settings", gtp_time_settings },
312 { "top_moves", gtp_top_moves },
313 { "top_moves_black", gtp_top_moves_black },
314 { "top_moves_white", gtp_top_moves_white },
315 { "tryko", gtp_tryko },
316 { "trymove", gtp_trymove },
317 { "tune_move_ordering", gtp_tune_move_ordering },
318 { "unconditional_status", gtp_unconditional_status },
319 { "undo", gtp_undo },
320 { "version", gtp_program_version },
321 { "white", gtp_playwhite },
322 { "worm_cutstone", gtp_worm_cutstone },
323 { "worm_data", gtp_worm_data },
324 { "worm_stones", gtp_worm_stones },
325 { NULL, NULL }
7eeb782e
AT
326};
327
7eeb782e 328/* Start playing using the Go Text Protocol. */
c150f57c
AT
329void play_gtp(FILE* gtp_input, FILE* gtp_output, FILE* gtp_dump_commands,
330 int gtp_initial_orientation)
7eeb782e 331{
c150f57c 332 /* Make sure `gtp_output' is unbuffered. (Line buffering is also
7eeb782e
AT
333 * okay but not necessary. Block buffering breaks GTP mode.)
334 *
335 * FIXME: Maybe should go to `gtp.c'?
336 */
c150f57c
AT
337 setbuf(gtp_output, NULL);
338
339 /* Inform the GTP utility functions about the board size. */
340 gtp_internal_set_boardsize(board_size);
341 gtp_orientation = gtp_initial_orientation;
342 gtp_set_vertex_transform_hooks(rotate_on_input, rotate_on_output);
343
344 /* Initialize time handling. */
345 init_timers();
346
347 /* Prepare pattern matcher and reading code. */
348 reset_engine();
349 clearstats();
350 gtp_main_loop(commands, gtp_input, gtp_output, gtp_dump_commands);
351 if (showstatistics)
352 showstats();
7eeb782e
AT
353}
354
7eeb782e
AT
355/****************************
356 * Administrative commands. *
357 ****************************/
358
359/* Function: Quit
360 * Arguments: none
361 * Fails: never
362 * Returns: nothing
363 *
364 * Status: GTP version 2 standard command.
365 */
366static int
c150f57c 367gtp_quit(char* s)
7eeb782e 368{
c150f57c
AT
369 UNUSED(s);
370 gtp_success("");
371 return GTP_QUIT;
7eeb782e
AT
372}
373
7eeb782e
AT
374/* Function: Report protocol version.
375 * Arguments: none
376 * Fails: never
377 * Returns: protocol version number
378 *
379 * Status: GTP version 2 standard command.
380 */
381static int
c150f57c 382gtp_protocol_version(char* s)
7eeb782e 383{
c150f57c
AT
384 UNUSED(s);
385 return gtp_success("%d", gtp_version);
7eeb782e
AT
386}
387
7eeb782e
AT
388/****************************
389 * Program identity. *
390 ****************************/
391
392/* Function: Report the name of the program.
393 * Arguments: none
394 * Fails: never
395 * Returns: program name
396 *
397 * Status: GTP version 2 standard command.
398 */
399static int
c150f57c 400gtp_name(char* s)
7eeb782e 401{
c150f57c
AT
402 UNUSED(s);
403 return gtp_success("GNU Go");
7eeb782e
AT
404}
405
7eeb782e
AT
406/* Function: Report the version number of the program.
407 * Arguments: none
408 * Fails: never
409 * Returns: version number
410 *
411 * Status: GTP version 2 standard command.
412 */
413static int
c150f57c 414gtp_program_version(char* s)
7eeb782e 415{
c150f57c
AT
416 UNUSED(s);
417 return gtp_success(VERSION);
7eeb782e
AT
418}
419
7eeb782e
AT
420/***************************
421 * Setting the board size. *
422 ***************************/
423
424/* Function: Set the board size to NxN and clear the board.
425 * Arguments: integer
426 * Fails: board size outside engine's limits
427 * Returns: nothing
428 *
429 * Status: GTP version 2 standard command.
430 */
431static int
c150f57c 432gtp_set_boardsize(char* s)
7eeb782e 433{
c150f57c 434 int boardsize;
7eeb782e 435
c150f57c
AT
436 if (sscanf(s, "%d", &boardsize) < 1)
437 return gtp_failure("boardsize not an integer");
438
439 if (!check_boardsize(boardsize, NULL)) {
440 if (gtp_version == 1)
441 return gtp_failure("unacceptable boardsize");
442 else
443 return gtp_failure("unacceptable size");
444 }
7eeb782e 445
c150f57c 446 /* If this is called with a non-empty board, we assume that a new
7eeb782e
AT
447 * game will be started, for which we want a new random seed.
448 */
c150f57c
AT
449 if (stones_on_board(BLACK | WHITE) > 0)
450 update_random_seed();
7eeb782e 451
c150f57c
AT
452 board_size = boardsize;
453 clear_board();
454 gtp_internal_set_boardsize(boardsize);
455 reset_engine();
456 return gtp_success("");
7eeb782e
AT
457}
458
459/* Function: Find the current boardsize
460 * Arguments: none
461 * Fails: never
462 * Returns: board_size
463 */
464static int
c150f57c 465gtp_query_boardsize(char* s)
7eeb782e 466{
c150f57c 467 UNUSED(s);
7eeb782e 468
c150f57c 469 return gtp_success("%d", board_size);
7eeb782e
AT
470}
471
472/***********************
473 * Clearing the board. *
474 ***********************/
475
476/* Function: Clear the board.
477 * Arguments: none
478 * Fails: never
479 * Returns: nothing
480 *
481 * Status: GTP version 2 standard command.
482 */
483static int
c150f57c 484gtp_clear_board(char* s)
7eeb782e 485{
c150f57c 486 UNUSED(s);
7eeb782e 487
c150f57c 488 /* If this is called with a non-empty board, we assume that a new
7eeb782e
AT
489 * game will be started, for which we want a new random seed.
490 */
c150f57c
AT
491 if (stones_on_board(BLACK | WHITE) > 0)
492 update_random_seed();
493
494 clear_board();
495 init_timers();
7eeb782e 496
c150f57c 497 return gtp_success("");
7eeb782e
AT
498}
499
500/****************************
501 * Setting the orientation. *
502 ****************************/
503
504/* Function: Set the orienation to N and clear the board
505 * Arguments: integer
506 * Fails: illegal orientation
507 * Returns: nothing
508 */
509static int
c150f57c 510gtp_set_orientation(char* s)
7eeb782e 511{
c150f57c
AT
512 int orientation;
513 if (sscanf(s, "%d", &orientation) < 1)
514 return gtp_failure("orientation not an integer");
515
516 if (orientation < 0 || orientation > 7)
517 return gtp_failure("unacceptable orientation");
7eeb782e 518
c150f57c
AT
519 clear_board();
520 gtp_orientation = orientation;
521 gtp_set_vertex_transform_hooks(rotate_on_input, rotate_on_output);
522 return gtp_success("");
7eeb782e
AT
523}
524
525/* Function: Find the current orientation
526 * Arguments: none
527 * Fails: never
528 * Returns: orientation
529 */
530static int
c150f57c 531gtp_query_orientation(char* s)
7eeb782e 532{
c150f57c 533 UNUSED(s);
7eeb782e 534
c150f57c 535 return gtp_success("%d", gtp_orientation);
7eeb782e
AT
536}
537
538/***************************
539 * Setting komi. *
540 ***************************/
541
542/* Function: Set the komi.
543 * Arguments: float
544 * Fails: incorrect argument
545 * Returns: nothing
546 *
547 * Status: GTP version 2 standard command.
548 */
549static int
c150f57c 550gtp_set_komi(char* s)
7eeb782e 551{
c150f57c
AT
552 if (sscanf(s, "%f", &komi) < 1)
553 return gtp_failure("komi not a float");
7eeb782e 554
c150f57c
AT
555 return gtp_success("");
556}
7eeb782e
AT
557
558/***************************
559 * Getting komi *
560 ***************************/
561
562/* Function: Get the komi
563 * Arguments: none
564 * Fails: never
565 * Returns: Komi
566 */
567static int
c150f57c 568gtp_get_komi(char* s)
7eeb782e 569{
c150f57c
AT
570 UNUSED(s);
571 return gtp_success("%4.1f", komi);
7eeb782e
AT
572}
573
7eeb782e
AT
574/******************
575 * Playing moves. *
576 ******************/
577
578/* Function: Play a black stone at the given vertex.
579 * Arguments: vertex
580 * Fails: invalid vertex, illegal move
581 * Returns: nothing
582 *
583 * Status: Obsolete GTP version 1 command.
584 */
585static int
c150f57c 586gtp_playblack(char* s)
7eeb782e 587{
c150f57c
AT
588 int i, j;
589 char* c;
7eeb782e 590
c150f57c
AT
591 for (c = s; *c; c++)
592 *c = tolower((int)*c);
7eeb782e 593
c150f57c
AT
594 if (strncmp(s, "pass", 4) == 0) {
595 i = -1;
596 j = -1;
597 } else if (!gtp_decode_coord(s, &i, &j))
598 return gtp_failure("invalid coordinate");
7eeb782e 599
c150f57c
AT
600 if (!is_allowed_move(POS(i, j), BLACK))
601 return gtp_failure("illegal move");
7eeb782e 602
c150f57c
AT
603 gnugo_play_move(POS(i, j), BLACK);
604 return gtp_success("");
7eeb782e
AT
605}
606
7eeb782e
AT
607/* Function: Play a white stone at the given vertex.
608 * Arguments: vertex
609 * Fails: invalid vertex, illegal move
610 * Returns: nothing
611 *
612 * Status: Obsolete GTP version 1 command.
613 */
614static int
c150f57c 615gtp_playwhite(char* s)
7eeb782e 616{
c150f57c
AT
617 int i, j;
618 char* c;
7eeb782e 619
c150f57c
AT
620 for (c = s; *c; c++)
621 *c = tolower((int)*c);
7eeb782e 622
c150f57c
AT
623 if (strncmp(s, "pass", 4) == 0) {
624 i = -1;
625 j = -1;
626 } else if (!gtp_decode_coord(s, &i, &j))
627 return gtp_failure("invalid coordinate");
7eeb782e 628
c150f57c
AT
629 if (!is_allowed_move(POS(i, j), WHITE))
630 return gtp_failure("illegal move");
7eeb782e 631
c150f57c
AT
632 gnugo_play_move(POS(i, j), WHITE);
633 return gtp_success("");
634}
7eeb782e
AT
635
636/* Function: Play a stone of the given color at the given vertex.
637 * Arguments: color, vertex
638 * Fails: invalid vertex, illegal move
639 * Returns: nothing
640 *
641 * Status: GTP version 2 standard command.
642 */
643static int
c150f57c 644gtp_play(char* s)
7eeb782e 645{
c150f57c
AT
646 int i, j;
647 int color;
7eeb782e 648
c150f57c
AT
649 if (!gtp_decode_move(s, &color, &i, &j))
650 return gtp_failure("invalid color or coordinate");
7eeb782e 651
c150f57c
AT
652 if (!is_allowed_move(POS(i, j), color))
653 return gtp_failure("illegal move");
7eeb782e 654
c150f57c
AT
655 gnugo_play_move(POS(i, j), color);
656 return gtp_success("");
7eeb782e
AT
657}
658
7eeb782e
AT
659/* Function: Set up fixed placement handicap stones.
660 * Arguments: number of handicap stones
661 * Fails: invalid number of stones for the current boardsize
662 * Returns: list of vertices with handicap stones
663 *
664 * Status: GTP version 2 standard command.
665 */
666static int
c150f57c 667gtp_fixed_handicap(char* s)
7eeb782e 668{
c150f57c
AT
669 int m, n;
670 int first = 1;
671 int this_handicap;
7eeb782e 672
c150f57c
AT
673 if (gtp_version == 1)
674 clear_board();
675 else if (stones_on_board(BLACK | WHITE) > 0)
676 return gtp_failure("board not empty");
7eeb782e 677
c150f57c
AT
678 if (sscanf(s, "%d", &this_handicap) < 1)
679 return gtp_failure("handicap not an integer");
7eeb782e 680
c150f57c
AT
681 if (this_handicap < 2 && (gtp_version > 1 || this_handicap != 0))
682 return gtp_failure("invalid handicap");
7eeb782e 683
c150f57c
AT
684 if (place_fixed_handicap(this_handicap) != this_handicap) {
685 clear_board();
686 return gtp_failure("invalid handicap");
687 }
7eeb782e 688
c150f57c 689 handicap = this_handicap;
7eeb782e 690
c150f57c 691 gtp_start_response(GTP_SUCCESS);
7eeb782e 692
c150f57c
AT
693 for (m = 0; m < board_size; m++)
694 for (n = 0; n < board_size; n++)
695 if (BOARD(m, n) != EMPTY) {
696 if (!first)
697 gtp_printf(" ");
698 else
699 first = 0;
700 gtp_mprintf("%m", m, n);
701 }
702
703 return gtp_finish_response();
704}
7eeb782e
AT
705
706/* Function: Choose free placement handicap stones and put them on the board.
707 * Arguments: number of handicap stones
708 * Fails: invalid number of stones
709 * Returns: list of vertices with handicap stones
710 *
711 * Status: GTP version 2 standard command.
712 */
713static int
c150f57c 714gtp_place_free_handicap(char* s)
7eeb782e 715{
c150f57c
AT
716 int m, n;
717 int first = 1;
718 int this_handicap;
719 if (sscanf(s, "%d", &this_handicap) < 1)
720 return gtp_failure("handicap not an integer");
7eeb782e 721
c150f57c
AT
722 if (stones_on_board(BLACK | WHITE) > 0)
723 return gtp_failure("board not empty");
7eeb782e 724
c150f57c
AT
725 if (this_handicap < 2)
726 return gtp_failure("invalid handicap");
7eeb782e 727
c150f57c 728 handicap = place_free_handicap(this_handicap);
7eeb782e 729
c150f57c 730 gtp_start_response(GTP_SUCCESS);
7eeb782e 731
c150f57c
AT
732 for (m = 0; m < board_size; m++)
733 for (n = 0; n < board_size; n++)
734 if (BOARD(m, n) != EMPTY) {
735 if (!first)
736 gtp_printf(" ");
737 else
738 first = 0;
739 gtp_mprintf("%m", m, n);
740 }
741
742 return gtp_finish_response();
743}
7eeb782e
AT
744
745/* Function: Put free placement handicap stones on the board.
746 * Arguments: list of vertices with handicap stones
747 * Fails: board not empty, bad list of vertices
748 * Returns: nothing
749 *
750 * Status: GTP version 2 standard command.
751 */
752static int
c150f57c
AT
753gtp_set_free_handicap(char* s)
754{
755 int n;
756 int i, j;
757 int k;
758
759 if (stones_on_board(BLACK | WHITE) > 0)
760 return gtp_failure("board not empty");
761
762 for (k = 0; k < MAX_BOARD * MAX_BOARD; k++) {
763 n = gtp_decode_coord(s, &i, &j);
764 if (n > 0) {
765 if (board[POS(i, j)] != EMPTY) {
766 clear_board();
767 return gtp_failure("repeated vertex");
768 }
769 add_stone(POS(i, j), BLACK);
770 s += n;
771 } else if (sscanf(s, "%*s") != EOF)
772 return gtp_failure("invalid coordinate");
773 else
774 break;
775 }
7eeb782e 776
c150f57c
AT
777 if (k < 2) {
778 clear_board();
779 return gtp_failure("invalid handicap");
7eeb782e 780 }
7eeb782e 781
c150f57c 782 handicap = k;
7eeb782e 783
c150f57c 784 return gtp_success("");
7eeb782e
AT
785}
786
7eeb782e
AT
787/* Function: Get the handicap
788 * Arguments: none
789 * Fails: never
790 * Returns: handicap
791 */
792static int
c150f57c 793gtp_get_handicap(char* s)
7eeb782e 794{
c150f57c
AT
795 UNUSED(s);
796 return gtp_success("%d", handicap);
7eeb782e
AT
797}
798
7eeb782e
AT
799/* Function: Load an sgf file, possibly up to a move number or the first
800 * occurence of a move.
801 * Arguments: filename + move number, vertex, or nothing
802 * Fails: missing filename or failure to open or parse file
803 * Returns: color to play
804 *
805 * Status: GTP version 2 standard command.
806 */
807static int
c150f57c 808gtp_loadsgf(char* s)
7eeb782e 809{
c150f57c
AT
810 char filename[GTP_BUFSIZE];
811 char untilstring[GTP_BUFSIZE];
812 SGFTree sgftree;
813 Gameinfo gameinfo;
814 int nread;
815 int color_to_move;
7eeb782e 816
c150f57c
AT
817 nread = sscanf(s, "%s %s", filename, untilstring);
818 if (nread < 1)
819 return gtp_failure("missing filename");
7eeb782e 820
c150f57c
AT
821 sgftree_clear(&sgftree);
822 if (!sgftree_readfile(&sgftree, filename))
823 return gtp_failure("cannot open or parse '%s'", filename);
7eeb782e 824
c150f57c
AT
825 if (nread == 1)
826 color_to_move = gameinfo_play_sgftree_rot(&gameinfo, &sgftree, NULL,
827 gtp_orientation);
828 else
829 color_to_move = gameinfo_play_sgftree_rot(&gameinfo, &sgftree, untilstring,
830 gtp_orientation);
7eeb782e 831
c150f57c
AT
832 if (color_to_move == EMPTY)
833 return gtp_failure("cannot load '%s'", filename);
7eeb782e 834
c150f57c
AT
835 gtp_internal_set_boardsize(board_size);
836 reset_engine();
837 init_timers();
7eeb782e 838
c150f57c
AT
839 sgfFreeNode(sgftree.root);
840
841 gtp_start_response(GTP_SUCCESS);
842 gtp_mprintf("%C", color_to_move);
843 return gtp_finish_response();
844}
7eeb782e
AT
845
846/*****************
847 * Board status. *
848 *****************/
849
850/* Function: Return the color at a vertex.
851 * Arguments: vertex
852 * Fails: invalid vertex
853 * Returns: "black", "white", or "empty"
854 */
855static int
c150f57c 856gtp_what_color(char* s)
7eeb782e 857{
c150f57c
AT
858 int i, j;
859 if (!gtp_decode_coord(s, &i, &j))
860 return gtp_failure("invalid coordinate");
7eeb782e 861
c150f57c
AT
862 return gtp_success(color_to_string(BOARD(i, j)));
863}
7eeb782e
AT
864
865/* Function: List vertices with either black or white stones.
866 * Arguments: color
867 * Fails: invalid color
868 * Returns: list of vertices
869 */
870static int
c150f57c 871gtp_list_stones(char* s)
7eeb782e 872{
c150f57c
AT
873 int i, j;
874 int color = EMPTY;
875 int vertexi[MAX_BOARD * MAX_BOARD];
876 int vertexj[MAX_BOARD * MAX_BOARD];
877 int vertices = 0;
7eeb782e 878
c150f57c
AT
879 if (!gtp_decode_color(s, &color))
880 return gtp_failure("invalid color");
7eeb782e 881
c150f57c
AT
882 for (i = 0; i < board_size; i++)
883 for (j = 0; j < board_size; j++)
884 if (BOARD(i, j) == color) {
885 vertexi[vertices] = i;
886 vertexj[vertices++] = j;
887 }
7eeb782e 888
c150f57c
AT
889 gtp_start_response(GTP_SUCCESS);
890 gtp_print_vertices(vertices, vertexi, vertexj);
891 return gtp_finish_response();
892}
7eeb782e
AT
893
894/* Function: Count number of liberties for the string at a vertex.
895 * Arguments: vertex
896 * Fails: invalid vertex, empty vertex
897 * Returns: Number of liberties.
898 */
899static int
c150f57c 900gtp_countlib(char* s)
7eeb782e 901{
c150f57c
AT
902 int i, j;
903 if (!gtp_decode_coord(s, &i, &j))
904 return gtp_failure("invalid coordinate");
7eeb782e 905
c150f57c
AT
906 if (BOARD(i, j) == EMPTY)
907 return gtp_failure("vertex must not be empty");
7eeb782e 908
c150f57c 909 return gtp_success("%d", countlib(POS(i, j)));
7eeb782e
AT
910}
911
7eeb782e
AT
912/* Function: Return the positions of the liberties for the string at a vertex.
913 * Arguments: vertex
914 * Fails: invalid vertex, empty vertex
915 * Returns: Sorted space separated list of vertices.
916 */
917static int
c150f57c 918gtp_findlib(char* s)
7eeb782e 919{
c150f57c
AT
920 int i, j;
921 int libs[MAXLIBS];
922 int liberties;
7eeb782e 923
c150f57c
AT
924 if (!gtp_decode_coord(s, &i, &j))
925 return gtp_failure("invalid coordinate");
7eeb782e 926
c150f57c
AT
927 if (BOARD(i, j) == EMPTY)
928 return gtp_failure("vertex must not be empty");
7eeb782e 929
c150f57c
AT
930 liberties = findlib(POS(i, j), MAXLIBS, libs);
931 gtp_start_response(GTP_SUCCESS);
932 gtp_print_vertices2(liberties, libs);
933 return gtp_finish_response();
934}
7eeb782e
AT
935
936/* Function: Determine which liberties a stone of given color
937 * will get if played at given vertex.
938 * Arguments: move (color + vertex)
939 * Fails: invalid color, invalid vertex, occupied vertex
940 * Returns: Sorted space separated list of liberties
941 */
942static int
c150f57c 943gtp_accuratelib(char* s)
7eeb782e 944{
c150f57c
AT
945 int i, j;
946 int color;
947 int libs[MAXLIBS];
948 int liberties;
7eeb782e 949
c150f57c
AT
950 if (!gtp_decode_move(s, &color, &i, &j))
951 return gtp_failure("invalid color or coordinate");
7eeb782e 952
c150f57c
AT
953 if (BOARD(i, j) != EMPTY)
954 return gtp_failure("vertex must be empty");
7eeb782e 955
c150f57c 956 liberties = accuratelib(POS(i, j), color, MAXLIBS, libs);
7eeb782e 957
c150f57c
AT
958 gtp_start_response(GTP_SUCCESS);
959 gtp_print_vertices2(liberties, libs);
960 return gtp_finish_response();
7eeb782e
AT
961}
962
7eeb782e
AT
963/* Function: Determine which liberties a stone of given color
964 * will get if played at given vertex.
965 * Arguments: move (color + vertex)
966 * Fails: invalid color, invalid vertex, occupied vertex
967 * Returns: Sorted space separated list of liberties
968 *
969 * Supposedly identical in behavior to the above function and
970 * can be retired when this is confirmed.
971 */
972static int
c150f57c 973gtp_accurate_approxlib(char* s)
7eeb782e 974{
c150f57c
AT
975 int i, j;
976 int color;
977 int libs[MAXLIBS];
978 int liberties;
7eeb782e 979
c150f57c
AT
980 if (!gtp_decode_move(s, &color, &i, &j))
981 return gtp_failure("invalid color or coordinate");
7eeb782e 982
c150f57c
AT
983 if (BOARD(i, j) != EMPTY)
984 return gtp_failure("vertex must be empty");
7eeb782e 985
c150f57c 986 liberties = accuratelib(POS(i, j), color, MAXLIBS, libs);
7eeb782e 987
c150f57c
AT
988 gtp_start_response(GTP_SUCCESS);
989 gtp_print_vertices2(liberties, libs);
990 return gtp_finish_response();
7eeb782e
AT
991}
992
7eeb782e
AT
993/* Function: Tell whether a move is legal.
994 * Arguments: move
995 * Fails: invalid move
996 * Returns: 1 if the move is legal, 0 if it is not.
997 */
998static int
c150f57c 999gtp_is_legal(char* s)
7eeb782e 1000{
c150f57c
AT
1001 int i, j;
1002 int color;
7eeb782e 1003
c150f57c
AT
1004 if (!gtp_decode_move(s, &color, &i, &j))
1005 return gtp_failure("invalid color or coordinate");
7eeb782e 1006
c150f57c
AT
1007 return gtp_success("%d", is_allowed_move(POS(i, j), color));
1008}
7eeb782e
AT
1009
1010/* Function: List all legal moves for either color.
1011 * Arguments: color
1012 * Fails: invalid color
1013 * Returns: Sorted space separated list of vertices.
1014 */
1015static int
c150f57c 1016gtp_all_legal(char* s)
7eeb782e 1017{
c150f57c
AT
1018 int i, j;
1019 int color;
1020 int movei[MAX_BOARD * MAX_BOARD];
1021 int movej[MAX_BOARD * MAX_BOARD];
1022 int moves = 0;
7eeb782e 1023
c150f57c
AT
1024 if (!gtp_decode_color(s, &color))
1025 return gtp_failure("invalid color");
7eeb782e 1026
c150f57c
AT
1027 for (i = 0; i < board_size; i++)
1028 for (j = 0; j < board_size; j++)
1029 if (BOARD(i, j) == EMPTY && is_allowed_move(POS(i, j), color)) {
1030 movei[moves] = i;
1031 movej[moves++] = j;
1032 }
7eeb782e 1033
c150f57c
AT
1034 gtp_start_response(GTP_SUCCESS);
1035 gtp_print_vertices(moves, movei, movej);
1036 return gtp_finish_response();
1037}
7eeb782e
AT
1038
1039/* Function: List the number of captures taken by either color.
1040 * Arguments: color
1041 * Fails: invalid color
1042 * Returns: Number of captures.
1043 */
1044static int
c150f57c 1045gtp_captures(char* s)
7eeb782e 1046{
c150f57c 1047 int color;
7eeb782e 1048
c150f57c
AT
1049 if (!gtp_decode_color(s, &color))
1050 return gtp_failure("invalid color");
7eeb782e 1051
c150f57c
AT
1052 if (color == BLACK)
1053 return gtp_success("%d", white_captured);
1054 else
1055 return gtp_success("%d", black_captured);
1056}
7eeb782e
AT
1057
1058/* Function: Return the last move.
1059 * Arguments: none
1060 * Fails: no previous move known
1061 * Returns: Color and vertex of last move.
1062 */
1063static int
c150f57c 1064gtp_last_move(char* s)
7eeb782e 1065{
c150f57c
AT
1066 int pos;
1067 int color;
1068 UNUSED(s);
1069
1070 if (move_history_pointer <= 0)
1071 return gtp_failure("no previous move known");
1072
1073 pos = move_history_pos[move_history_pointer - 1];
1074 color = move_history_color[move_history_pointer - 1];
1075
1076 gtp_start_response(GTP_SUCCESS);
1077 gtp_mprintf("%C %m", color, I(pos), J(pos));
1078 return gtp_finish_response();
7eeb782e
AT
1079}
1080
1081/* Function: Print the move history in reverse order
1082 * Arguments: none
1083 * Fails: never
1084 * Returns: List of moves played in reverse order in format:
1085 * color move (one move per line)
1086 */
1087static int
c150f57c 1088gtp_move_history(char* s)
7eeb782e 1089{
c150f57c
AT
1090 int k, pos, color;
1091 UNUSED(s);
1092
1093 gtp_start_response(GTP_SUCCESS);
1094 if (move_history_pointer > 0)
1095 for (k = move_history_pointer - 1; k >= 0; k--) {
1096 color = move_history_color[k];
1097 pos = move_history_pos[k];
1098 gtp_mprintf("%C %m\n", color, I(pos), J(pos));
1099 }
1100 else
1101 gtp_printf("\n");
7eeb782e 1102 gtp_printf("\n");
c150f57c 1103 return GTP_OK;
7eeb782e
AT
1104}
1105
7eeb782e
AT
1106/* Function: Return the rotation/reflection invariant board hash.
1107 * Arguments: none
1108 * Fails: never
1109 * Returns: Invariant hash for the board as a hexadecimal number.
1110 */
1111static int
c150f57c 1112gtp_invariant_hash(char* s)
7eeb782e 1113{
c150f57c
AT
1114 Hash_data hash;
1115 UNUSED(s);
1116 hashdata_calc_orientation_invariant(&hash, board, board_ko_pos);
1117 return gtp_success("%s", hashdata_to_string(&hash));
7eeb782e
AT
1118}
1119
7eeb782e
AT
1120/* Function: Return the rotation/reflection invariant board hash
1121 * obtained by playing all the possible moves for the
1122 * given color.
1123 * Arguments: color
1124 * Fails: invalid color
1125 * Returns: List of moves + invariant hash as a hexadecimal number,
1126 * one pair of move + hash per line.
1127 */
1128static int
c150f57c 1129gtp_invariant_hash_for_moves(char* s)
7eeb782e 1130{
c150f57c
AT
1131 Hash_data hash;
1132 int color;
1133 int pos;
1134 int move_found = 0;
1135
1136 if (!gtp_decode_color(s, &color))
1137 return gtp_failure("invalid color");
7eeb782e 1138
c150f57c 1139 gtp_start_response(GTP_SUCCESS);
7eeb782e 1140
c150f57c
AT
1141 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
1142 if (board[pos] == EMPTY
1143 && trymove(pos, color, "gtp_invariant_hash_for_moves", NO_MOVE)) {
1144 hashdata_calc_orientation_invariant(&hash, board, board_ko_pos);
1145 gtp_mprintf("%m %s\n", I(pos), J(pos), hashdata_to_string(&hash));
1146 popgo();
1147 move_found = 1;
1148 }
7eeb782e 1149 }
7eeb782e 1150
c150f57c
AT
1151 if (!move_found)
1152 gtp_printf("\n");
1153
7eeb782e 1154 gtp_printf("\n");
c150f57c 1155 return GTP_OK;
7eeb782e
AT
1156}
1157
7eeb782e
AT
1158/**********************
1159 * Retractable moves. *
1160 **********************/
1161
1162/* Function: Play a stone of the given color at the given vertex.
1163 * Arguments: move (color + vertex)
1164 * Fails: invalid color, invalid vertex, illegal move
1165 * Returns: nothing
1166 */
1167static int
c150f57c 1168gtp_trymove(char* s)
7eeb782e 1169{
c150f57c
AT
1170 int i, j;
1171 int color;
1172 if (!gtp_decode_move(s, &color, &i, &j))
1173 return gtp_failure("invalid color or coordinate");
7eeb782e 1174
c150f57c
AT
1175 if (!trymove(POS(i, j), color, "gtp_trymove", NO_MOVE))
1176 return gtp_failure("illegal move");
7eeb782e 1177
c150f57c 1178 return gtp_success("");
7eeb782e
AT
1179}
1180
1181/* Function: Play a stone of the given color at the given vertex,
1182 * allowing illegal ko capture.
1183 * Arguments: move (color + vertex)
1184 * Fails: invalid color, invalid vertex, illegal move
1185 * Returns: nothing
1186 */
1187static int
c150f57c 1188gtp_tryko(char* s)
7eeb782e 1189{
c150f57c
AT
1190 int i, j;
1191 int color;
1192 if (!gtp_decode_move(s, &color, &i, &j) || POS(i, j) == PASS_MOVE)
1193 return gtp_failure("invalid color or coordinate");
7eeb782e 1194
c150f57c
AT
1195 if (!tryko(POS(i, j), color, "gtp_tryko"))
1196 return gtp_failure("illegal move");
7eeb782e 1197
c150f57c 1198 return gtp_success("");
7eeb782e
AT
1199}
1200
7eeb782e
AT
1201/* Function: Undo a trymove or tryko.
1202 * Arguments: none
1203 * Fails: stack empty
1204 * Returns: nothing
1205 */
1206static int
c150f57c 1207gtp_popgo(char* s)
7eeb782e 1208{
c150f57c 1209 UNUSED(s);
7eeb782e 1210
c150f57c
AT
1211 if (stackp == 0)
1212 return gtp_failure("Stack empty.");
7eeb782e 1213
c150f57c
AT
1214 popgo();
1215 return gtp_success("");
7eeb782e
AT
1216}
1217
1218/*********************
1219 * Caching *
1220 *********************/
1221
1222/* Function: clear the caches.
1223 * Arguments: none.
1224 * Fails: never.
1225 * Returns: nothing.
1226 */
1227
1228static int
c150f57c 1229gtp_clear_cache(char* s)
7eeb782e 1230{
c150f57c
AT
1231 UNUSED(s);
1232 clear_persistent_caches();
1233 reading_cache_clear();
1234 return gtp_success("");
7eeb782e
AT
1235}
1236
1237/*********************
1238 * Tactical reading. *
1239 *********************/
1240
1241/* Function: Try to attack a string.
1242 * Arguments: vertex
1243 * Fails: invalid vertex, empty vertex
1244 * Returns: attack code followed by attack point if attack code nonzero.
1245 */
1246static int
c150f57c 1247gtp_attack(char* s)
7eeb782e 1248{
c150f57c
AT
1249 int i, j;
1250 int apos;
1251 int attack_code;
7eeb782e 1252
c150f57c
AT
1253 if (!gtp_decode_coord(s, &i, &j))
1254 return gtp_failure("invalid coordinate");
7eeb782e 1255
c150f57c
AT
1256 if (BOARD(i, j) == EMPTY)
1257 return gtp_failure("vertex must not be empty");
7eeb782e 1258
c150f57c
AT
1259 attack_code = attack(POS(i, j), &apos);
1260 gtp_start_response(GTP_SUCCESS);
1261 gtp_print_code(attack_code);
1262 if (attack_code > 0) {
1263 gtp_printf(" ");
1264 gtp_print_vertex(I(apos), J(apos));
1265 }
1266 return gtp_finish_response();
1267}
7eeb782e
AT
1268
1269/* Function: Try to attack either of two strings
1270 * Arguments: two vertices
1271 * Fails: invalid vertex, empty vertex
1272 * Returns: attack code against the strings. Guarantees there
1273 * exists a move which will attack one of the two
1274 * with attack_code, but does not return the move.
1275 */
1276static int
c150f57c 1277gtp_attack_either(char* s)
7eeb782e 1278{
c150f57c
AT
1279 int ai, aj;
1280 int bi, bj;
1281 int n;
1282 int acode;
7eeb782e 1283
c150f57c
AT
1284 n = gtp_decode_coord(s, &ai, &aj);
1285 if (n == 0)
1286 return gtp_failure("invalid coordinate");
7eeb782e 1287
c150f57c
AT
1288 if (BOARD(ai, aj) == EMPTY)
1289 return gtp_failure("string vertex must be empty");
7eeb782e 1290
c150f57c
AT
1291 n = gtp_decode_coord(s + n, &bi, &bj);
1292 if (n == 0)
1293 return gtp_failure("invalid coordinate");
7eeb782e 1294
c150f57c
AT
1295 if (BOARD(bi, bj) == EMPTY)
1296 return gtp_failure("string vertex must not be empty");
7eeb782e 1297
c150f57c 1298 acode = attack_either(POS(ai, aj), POS(bi, bj));
7eeb782e 1299
c150f57c
AT
1300 gtp_start_response(GTP_SUCCESS);
1301 gtp_print_code(acode);
1302 return gtp_finish_response();
7eeb782e
AT
1303}
1304
7eeb782e
AT
1305/* Function: Try to defend a string.
1306 * Arguments: vertex
1307 * Fails: invalid vertex, empty vertex
1308 * Returns: defense code followed by defense point if defense code nonzero.
1309 */
1310static int
c150f57c 1311gtp_defend(char* s)
7eeb782e 1312{
c150f57c
AT
1313 int i, j;
1314 int dpos;
1315 int defend_code;
7eeb782e 1316
c150f57c
AT
1317 if (!gtp_decode_coord(s, &i, &j))
1318 return gtp_failure("invalid coordinate");
7eeb782e 1319
c150f57c
AT
1320 if (BOARD(i, j) == EMPTY)
1321 return gtp_failure("vertex must not be empty");
7eeb782e 1322
c150f57c
AT
1323 defend_code = find_defense(POS(i, j), &dpos);
1324 gtp_start_response(GTP_SUCCESS);
1325 gtp_print_code(defend_code);
1326 if (defend_code > 0) {
1327 gtp_printf(" ");
1328 gtp_print_vertex(I(dpos), J(dpos));
1329 }
1330 return gtp_finish_response();
1331}
7eeb782e
AT
1332
1333/* Function: Examine whether a specific move attacks a string tactically.
1334 * Arguments: vertex (move), vertex (dragon)
1335 * Fails: invalid vertex, empty vertex
1336 * Returns: attack code
1337 */
1338static int
c150f57c 1339gtp_does_attack(char* s)
7eeb782e 1340{
c150f57c
AT
1341 int i, j;
1342 int ti, tj;
1343 int attack_code;
1344 int n;
7eeb782e 1345
c150f57c
AT
1346 n = gtp_decode_coord(s, &ti, &tj);
1347 if (n == 0)
1348 return gtp_failure("invalid coordinate");
7eeb782e 1349
c150f57c
AT
1350 if (BOARD(ti, tj) != EMPTY)
1351 return gtp_failure("move vertex must be empty");
7eeb782e 1352
c150f57c
AT
1353 n = gtp_decode_coord(s + n, &i, &j);
1354 if (n == 0)
1355 return gtp_failure("invalid coordinate");
7eeb782e 1356
c150f57c
AT
1357 if (BOARD(i, j) == EMPTY)
1358 return gtp_failure("string vertex must not be empty");
7eeb782e 1359
c150f57c
AT
1360 /* to get the variations into the sgf file, clear the reading cache */
1361 if (sgf_dumptree)
1362 reading_cache_clear();
7eeb782e 1363
c150f57c
AT
1364 attack_code = does_attack(POS(ti, tj), POS(i, j));
1365 gtp_start_response(GTP_SUCCESS);
1366 gtp_print_code(attack_code);
1367 return gtp_finish_response();
1368}
7eeb782e
AT
1369
1370/* Function: Examine whether a specific move defends a string tactically.
1371 * Arguments: vertex (move), vertex (dragon)
1372 * Fails: invalid vertex, empty vertex
1373 * Returns: attack code
1374 */
1375static int
c150f57c 1376gtp_does_defend(char* s)
7eeb782e 1377{
c150f57c
AT
1378 int i, j;
1379 int ti, tj;
1380 int defense_code;
1381 int n;
7eeb782e 1382
c150f57c
AT
1383 n = gtp_decode_coord(s, &ti, &tj);
1384 if (n == 0)
1385 return gtp_failure("invalid coordinate");
7eeb782e 1386
c150f57c
AT
1387 if (BOARD(ti, tj) != EMPTY)
1388 return gtp_failure("move vertex must be empty");
7eeb782e 1389
c150f57c
AT
1390 n = gtp_decode_coord(s + n, &i, &j);
1391 if (n == 0)
1392 return gtp_failure("invalid coordinate");
7eeb782e 1393
c150f57c
AT
1394 if (BOARD(i, j) == EMPTY)
1395 return gtp_failure("string vertex must not be empty");
7eeb782e 1396
c150f57c
AT
1397 /* to get the variations into the sgf file, clear the reading cache */
1398 if (sgf_dumptree)
1399 reading_cache_clear();
7eeb782e 1400
c150f57c
AT
1401 defense_code = does_defend(POS(ti, tj), POS(i, j));
1402 gtp_start_response(GTP_SUCCESS);
1403 gtp_print_code(defense_code);
1404 return gtp_finish_response();
1405}
7eeb782e
AT
1406
1407/* Function: Try to attack a string strictly in a ladder.
1408 * Arguments: vertex
1409 * Fails: invalid vertex, empty vertex
1410 * Returns: attack code followed by attack point if attack code nonzero.
1411 */
1412static int
c150f57c 1413gtp_ladder_attack(char* s)
7eeb782e 1414{
c150f57c
AT
1415 int i, j;
1416 int apos;
1417 int attack_code;
7eeb782e 1418
c150f57c
AT
1419 if (!gtp_decode_coord(s, &i, &j))
1420 return gtp_failure("invalid coordinate");
7eeb782e 1421
c150f57c
AT
1422 if (BOARD(i, j) == EMPTY)
1423 return gtp_failure("vertex must not be empty");
7eeb782e 1424
c150f57c
AT
1425 if (countlib(POS(i, j)) != 2)
1426 return gtp_failure("string must have exactly 2 liberties");
7eeb782e 1427
c150f57c
AT
1428 attack_code = simple_ladder(POS(i, j), &apos);
1429 gtp_start_response(GTP_SUCCESS);
1430 gtp_print_code(attack_code);
1431 if (attack_code > 0) {
1432 gtp_printf(" ");
1433 gtp_print_vertex(I(apos), J(apos));
1434 }
1435 return gtp_finish_response();
1436}
7eeb782e
AT
1437
1438/* Function: Increase depth values by one.
1439 * Arguments: none
1440 * Fails: never
1441 * Returns: nothing
1442 */
1443static int
c150f57c 1444gtp_increase_depths(char* s)
7eeb782e 1445{
c150f57c
AT
1446 UNUSED(s);
1447 increase_depth_values();
1448 return gtp_success("");
1449}
7eeb782e
AT
1450
1451/* Function: Decrease depth values by one.
1452 * Arguments: none
1453 * Fails: never
1454 * Returns: nothing
1455 */
1456static int
c150f57c 1457gtp_decrease_depths(char* s)
7eeb782e 1458{
c150f57c
AT
1459 UNUSED(s);
1460 decrease_depth_values();
1461 return gtp_success("");
1462}
7eeb782e
AT
1463
1464/******************
1465 * owl reading. *
1466 ******************/
1467
1468/* Function: Try to attack a dragon.
1469 * Arguments: vertex
1470 * Fails: invalid vertex, empty vertex
1471 * Returns: attack code followed by attack point if attack code nonzero.
1472 */
1473static int
c150f57c 1474gtp_owl_attack(char* s)
7eeb782e 1475{
c150f57c
AT
1476 int i, j;
1477 int attack_point;
1478 int attack_code;
1479 int result_certain;
1480 int kworm;
7eeb782e 1481
c150f57c
AT
1482 if (!gtp_decode_coord(s, &i, &j))
1483 return gtp_failure("invalid coordinate");
7eeb782e 1484
c150f57c
AT
1485 if (BOARD(i, j) == EMPTY)
1486 return gtp_failure("vertex must not be empty");
7eeb782e 1487
c150f57c 1488 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1489
c150f57c
AT
1490 /* to get the variations into the sgf file, clear the reading cache */
1491 if (sgf_dumptree)
1492 reading_cache_clear();
1493
1494 attack_code = owl_attack(POS(i, j), &attack_point, &result_certain, &kworm);
1495 gtp_start_response(GTP_SUCCESS);
1496 gtp_print_code(attack_code);
1497 if (attack_code > 0) {
1498 gtp_printf(" ");
1499 gtp_print_vertex(I(attack_point), J(attack_point));
1500 }
1501 if (!result_certain && report_uncertainty)
1502 gtp_printf(" uncertain");
1503 return gtp_finish_response();
1504}
7eeb782e
AT
1505
1506/* Function: Try to defend a dragon.
1507 * Arguments: vertex
1508 * Fails: invalid vertex, empty vertex
1509 * Returns: defense code followed by defense point if defense code nonzero.
1510 */
1511static int
c150f57c 1512gtp_owl_defend(char* s)
7eeb782e 1513{
c150f57c
AT
1514 int i, j;
1515 int defense_point;
1516 int defend_code;
1517 int result_certain;
1518 int kworm;
7eeb782e 1519
c150f57c
AT
1520 if (!gtp_decode_coord(s, &i, &j))
1521 return gtp_failure("invalid coordinate");
7eeb782e 1522
c150f57c
AT
1523 if (BOARD(i, j) == EMPTY)
1524 return gtp_failure("vertex must not be empty");
7eeb782e 1525
c150f57c
AT
1526 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
1527
1528 /* to get the variations into the sgf file, clear the reading cache */
1529 if (sgf_dumptree)
1530 reading_cache_clear();
1531
1532 defend_code = owl_defend(POS(i, j), &defense_point, &result_certain, &kworm);
1533 gtp_start_response(GTP_SUCCESS);
1534 gtp_print_code(defend_code);
1535 if (defend_code > 0) {
1536 gtp_printf(" ");
1537 gtp_print_vertex(I(defense_point), J(defense_point));
1538 }
1539 if (!result_certain && report_uncertainty)
1540 gtp_printf(" uncertain");
1541 return gtp_finish_response();
1542}
7eeb782e
AT
1543
1544/* Function: Try to attack a dragon in 2 moves.
1545 * Arguments: vertex
1546 * Fails: invalid vertex, empty vertex
1547 * Returns: attack code followed by the two attack points if
1548 * attack code nonzero.
1549 */
1550static int
c150f57c 1551gtp_owl_threaten_attack(char* s)
7eeb782e 1552{
c150f57c
AT
1553 int i, j;
1554 int attack_point1;
1555 int attack_point2;
1556 int attack_code;
7eeb782e 1557
c150f57c
AT
1558 if (!gtp_decode_coord(s, &i, &j))
1559 return gtp_failure("invalid coordinate");
7eeb782e 1560
c150f57c
AT
1561 if (BOARD(i, j) == EMPTY)
1562 return gtp_failure("vertex must not be empty");
7eeb782e 1563
c150f57c 1564 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1565
c150f57c
AT
1566 /* to get the variations into the sgf file, clear the reading cache */
1567 if (sgf_dumptree)
1568 reading_cache_clear();
1569
1570 attack_code = owl_threaten_attack(POS(i, j), &attack_point1, &attack_point2);
1571 gtp_start_response(GTP_SUCCESS);
1572 gtp_print_code(attack_code);
1573 if (attack_code > 0) {
1574 gtp_printf(" ");
1575 gtp_print_vertex(I(attack_point1), J(attack_point1));
1576 gtp_printf(" ");
1577 gtp_print_vertex(I(attack_point2), J(attack_point2));
1578 }
1579 return gtp_finish_response();
1580}
7eeb782e
AT
1581
1582/* Function: Try to defend a dragon with 2 moves.
1583 * Arguments: vertex
1584 * Fails: invalid vertex, empty vertex
1585 * Returns: defense code followed by the 2 defense points if
1586 * defense code nonzero.
1587 */
1588static int
c150f57c 1589gtp_owl_threaten_defense(char* s)
7eeb782e 1590{
c150f57c
AT
1591 int i, j;
1592 int defense_point1;
1593 int defense_point2;
1594 int defend_code;
7eeb782e 1595
c150f57c
AT
1596 if (!gtp_decode_coord(s, &i, &j))
1597 return gtp_failure("invalid coordinate");
7eeb782e 1598
c150f57c
AT
1599 if (BOARD(i, j) == EMPTY)
1600 return gtp_failure("vertex must not be empty");
7eeb782e 1601
c150f57c 1602 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1603
c150f57c
AT
1604 /* to get the variations into the sgf file, clear the reading cache */
1605 if (sgf_dumptree)
1606 reading_cache_clear();
1607
1608 defend_code = owl_threaten_defense(POS(i, j), &defense_point1,
1609 &defense_point2);
1610 gtp_start_response(GTP_SUCCESS);
1611 gtp_print_code(defend_code);
1612 if (defend_code > 0) {
1613 gtp_printf(" ");
1614 gtp_print_vertex(I(defense_point1), J(defense_point1));
1615 gtp_printf(" ");
1616 gtp_print_vertex(I(defense_point2), J(defense_point2));
1617 }
1618 return gtp_finish_response();
1619}
7eeb782e
AT
1620
1621/* Function: Examine whether a specific move attacks a dragon.
1622 * Arguments: vertex (move), vertex (dragon)
1623 * Fails: invalid vertex, empty vertex
1624 * Returns: attack code
1625 */
1626static int
c150f57c 1627gtp_owl_does_attack(char* s)
7eeb782e 1628{
c150f57c
AT
1629 int i, j;
1630 int ti, tj;
1631 int attack_code;
1632 int kworm;
1633 int n;
7eeb782e 1634
c150f57c
AT
1635 n = gtp_decode_coord(s, &ti, &tj);
1636 if (n == 0)
1637 return gtp_failure("invalid coordinate");
7eeb782e 1638
c150f57c
AT
1639 if (BOARD(ti, tj) != EMPTY)
1640 return gtp_failure("move vertex must be empty");
7eeb782e 1641
c150f57c
AT
1642 n = gtp_decode_coord(s + n, &i, &j);
1643 if (n == 0)
1644 return gtp_failure("invalid coordinate");
7eeb782e 1645
c150f57c
AT
1646 if (BOARD(i, j) == EMPTY)
1647 return gtp_failure("dragon vertex must not be empty");
7eeb782e 1648
c150f57c 1649 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1650
c150f57c
AT
1651 /* to get the variations into the sgf file, clear the reading cache */
1652 if (sgf_dumptree)
1653 reading_cache_clear();
1654
1655 attack_code = owl_does_attack(POS(ti, tj), POS(i, j), &kworm);
1656 gtp_start_response(GTP_SUCCESS);
1657 gtp_print_code(attack_code);
1658 return gtp_finish_response();
1659}
7eeb782e
AT
1660
1661/* Function: Examine whether a specific move defends a dragon.
1662 * Arguments: vertex (move), vertex (dragon)
1663 * Fails: invalid vertex, empty vertex
1664 * Returns: defense code
1665 */
1666static int
c150f57c 1667gtp_owl_does_defend(char* s)
7eeb782e 1668{
c150f57c
AT
1669 int i, j;
1670 int ti, tj;
1671 int defense_code;
1672 int kworm;
1673 int n;
7eeb782e 1674
c150f57c
AT
1675 n = gtp_decode_coord(s, &ti, &tj);
1676 if (n == 0)
1677 return gtp_failure("invalid coordinate");
7eeb782e 1678
c150f57c
AT
1679 if (BOARD(ti, tj) != EMPTY)
1680 return gtp_failure("move vertex must be empty");
7eeb782e 1681
c150f57c
AT
1682 n = gtp_decode_coord(s + n, &i, &j);
1683 if (n == 0)
1684 return gtp_failure("invalid coordinate");
7eeb782e 1685
c150f57c
AT
1686 if (BOARD(i, j) == EMPTY)
1687 return gtp_failure("dragon vertex must not be empty");
7eeb782e 1688
c150f57c 1689 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1690
c150f57c
AT
1691 /* to get the variations into the sgf file, clear the reading cache */
1692 if (sgf_dumptree)
1693 reading_cache_clear();
1694
1695 defense_code = owl_does_defend(POS(ti, tj), POS(i, j), &kworm);
1696 gtp_start_response(GTP_SUCCESS);
1697 gtp_print_code(defense_code);
1698 return gtp_finish_response();
1699}
7eeb782e
AT
1700
1701/* Function: Examine whether a connection defends involved dragons.
1702 * Arguments: vertex (move), vertex (dragon1), vertex (dragon2)
1703 * Fails: invalid vertex, empty vertex
1704 * Returns: defense code
1705 */
1706static int
c150f57c 1707gtp_owl_connection_defends(char* s)
7eeb782e 1708{
c150f57c
AT
1709 int ai, aj;
1710 int bi, bj;
1711 int ti, tj;
1712 int defense_code;
1713 int n;
7eeb782e 1714
c150f57c
AT
1715 n = gtp_decode_coord(s, &ti, &tj);
1716 if (n == 0)
1717 return gtp_failure("invalid coordinate");
7eeb782e 1718
c150f57c
AT
1719 if (BOARD(ti, tj) != EMPTY)
1720 return gtp_failure("move vertex must be empty");
7eeb782e 1721
c150f57c
AT
1722 s += n;
1723 n = gtp_decode_coord(s, &ai, &aj);
1724 if (n == 0)
1725 return gtp_failure("invalid coordinate");
7eeb782e 1726
c150f57c
AT
1727 s += n;
1728 n = gtp_decode_coord(s, &bi, &bj);
1729 if (n == 0)
1730 return gtp_failure("invalid coordinate");
7eeb782e 1731
c150f57c
AT
1732 if (BOARD(ai, aj) == EMPTY || BOARD(bi, bj) == EMPTY)
1733 return gtp_failure("dragon vertex must not be empty");
7eeb782e 1734
c150f57c
AT
1735 if (BOARD(ai, aj) != BOARD(bi, bj))
1736 return gtp_failure("dragon vertices must have the same color");
7eeb782e 1737
c150f57c 1738 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1739
c150f57c
AT
1740 /* to get the variations into the sgf file, clear the reading cache */
1741 if (sgf_dumptree)
1742 reading_cache_clear();
1743
1744 defense_code = owl_connection_defends(POS(ti, tj), POS(ai, aj), POS(bi, bj));
1745 gtp_start_response(GTP_SUCCESS);
1746 gtp_print_code(defense_code);
1747 return gtp_finish_response();
1748}
7eeb782e
AT
1749
1750/* Function: Try to defend both of two strings
1751 * Arguments: two vertices
1752 * Fails: invalid vertex, empty vertex
1753 * Returns: defend code for the strings. Guarantees there
1754 * exists a move which will defend both of the two
1755 * with defend_code, but does not return the move.
1756 */
1757static int
c150f57c 1758gtp_defend_both(char* s)
7eeb782e 1759{
c150f57c
AT
1760 int ai, aj;
1761 int bi, bj;
1762 int n;
1763 int dcode;
7eeb782e 1764
c150f57c
AT
1765 n = gtp_decode_coord(s, &ai, &aj);
1766 if (n == 0)
1767 return gtp_failure("invalid coordinate");
7eeb782e 1768
c150f57c
AT
1769 if (BOARD(ai, aj) == EMPTY)
1770 return gtp_failure("string vertex must be empty");
7eeb782e 1771
c150f57c
AT
1772 n = gtp_decode_coord(s + n, &bi, &bj);
1773 if (n == 0)
1774 return gtp_failure("invalid coordinate");
7eeb782e 1775
c150f57c
AT
1776 if (BOARD(bi, bj) == EMPTY)
1777 return gtp_failure("string vertex must not be empty");
7eeb782e 1778
c150f57c 1779 dcode = defend_both(POS(ai, aj), POS(bi, bj));
7eeb782e 1780
c150f57c
AT
1781 gtp_start_response(GTP_SUCCESS);
1782 gtp_print_code(dcode);
1783 return gtp_finish_response();
7eeb782e
AT
1784}
1785
7eeb782e
AT
1786/* Function: Determine whether capturing a string gives a living dragon
1787 * Arguments: vertex
1788 * Fails: invalid vertex, empty vertex
1789 * Returns: 1 if dragon can live, 0 otherwise
1790 */
1791static int
c150f57c 1792gtp_owl_substantial(char* s)
7eeb782e 1793{
c150f57c
AT
1794 int i, j;
1795 int result;
7eeb782e 1796
c150f57c
AT
1797 if (!gtp_decode_coord(s, &i, &j))
1798 return gtp_failure("invalid coordinate");
7eeb782e 1799
c150f57c
AT
1800 if (BOARD(i, j) == EMPTY)
1801 return gtp_failure("vertex must not be empty");
1802
1803 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 1804
c150f57c
AT
1805 /* to get the variations into the sgf file, clear the reading cache */
1806 if (sgf_dumptree)
1807 reading_cache_clear();
7eeb782e 1808
c150f57c
AT
1809 result = owl_substantial(POS(i, j));
1810 return gtp_success("%d", result);
1811}
7eeb782e
AT
1812
1813/* Function: Analyze a semeai
1814 * Arguments: dragona, dragonb
1815 * Fails: invalid vertices, empty vertices
1816 * Returns: semeai defense result, semeai attack result, semeai move
1817 */
1818static int
c150f57c 1819gtp_analyze_semeai(char* s)
7eeb782e 1820{
c150f57c
AT
1821 int i, j;
1822 int k;
1823 int dragona, dragonb;
1824 int resulta, resultb, move, result_certain;
7eeb782e 1825
c150f57c 1826 k = gtp_decode_coord(s, &i, &j);
7eeb782e 1827
c150f57c
AT
1828 if (k == 0)
1829 return gtp_failure("invalid coordinate");
1830 dragona = POS(i, j);
1831 if (BOARD(i, j) == EMPTY)
1832 return gtp_failure("vertex must not be empty");
7eeb782e 1833
c150f57c
AT
1834 if (!gtp_decode_coord(s + k, &i, &j))
1835 return gtp_failure("invalid coordinate");
1836 dragonb = POS(i, j);
1837 if (BOARD(i, j) == EMPTY)
1838 return gtp_failure("vertex must not be empty");
7eeb782e 1839
c150f57c
AT
1840 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
1841 /* to get the variations into the sgf file, clear the reading cache */
1842 if (sgf_dumptree)
1843 reading_cache_clear();
7eeb782e 1844
c150f57c
AT
1845 owl_analyze_semeai(dragona, dragonb, &resulta, &resultb, &move, 1,
1846 &result_certain);
1847 gtp_start_response(GTP_SUCCESS);
1848 gtp_print_code(resulta);
1849 gtp_printf(" ");
1850 gtp_print_code(resultb);
1851 gtp_mprintf(" %m", I(move), J(move));
1852 if (!result_certain && report_uncertainty)
1853 gtp_printf(" uncertain");
7eeb782e 1854
c150f57c
AT
1855 return gtp_finish_response();
1856}
7eeb782e
AT
1857
1858/* Function: Analyze a semeai after a move have been made.
1859 * Arguments: color, vertex, dragona, dragonb
1860 * Fails: invalid vertices
1861 * Returns: semeai defense result, semeai attack result, semeai move
1862 */
1863static int
c150f57c
AT
1864gtp_analyze_semeai_after_move(char* s)
1865{
1866 int i, j;
1867 int color;
1868 int move;
1869 int k;
1870 int dragona, dragonb;
1871 int resulta, resultb, semeai_move, result_certain;
1872
1873 k = gtp_decode_move(s, &color, &i, &j);
1874 move = POS(i, j);
1875 if (k == 0 || move == NO_MOVE)
1876 return gtp_failure("invalid color or coordinate");
1877 if (board[move] != EMPTY)
1878 return gtp_failure("move vertex is not empty");
1879 s += k;
1880
1881 k = gtp_decode_coord(s, &i, &j);
1882 if (k == 0)
1883 return gtp_failure("invalid coordinate");
1884 dragona = POS(i, j);
1885 if (board[dragona] == EMPTY)
1886 return gtp_failure("dragon vertex must not be empty");
1887 s += k;
1888
1889 if (!gtp_decode_coord(s, &i, &j))
1890 return gtp_failure("invalid coordinate");
1891 dragonb = POS(i, j);
1892 if (board[dragonb] == EMPTY)
1893 return gtp_failure("dragon vertex must not be empty");
1894
1895 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
1896 /* to get the variations into the sgf file, clear the reading cache */
1897 if (sgf_dumptree)
1898 reading_cache_clear();
1899
1900 owl_analyze_semeai_after_move(move, color, dragona, dragonb,
1901 &resulta, &resultb, &semeai_move, 1,
1902 &result_certain, 0);
1903 gtp_start_response(GTP_SUCCESS);
1904 gtp_print_code(resulta);
1905 gtp_printf(" ");
1906 gtp_print_code(resultb);
1907 gtp_mprintf(" %m", I(semeai_move), J(semeai_move));
1908 if (!result_certain && report_uncertainty)
1909 gtp_printf(" uncertain");
7eeb782e 1910
c150f57c
AT
1911 return gtp_finish_response();
1912}
7eeb782e
AT
1913
1914/* Function: Analyze a semeai, not using owl
1915 * Arguments: dragona, dragonb
1916 * Fails: invalid vertices, empty vertices
1917 * Returns: status of dragona, dragonb assuming dragona moves first
1918 */
1919static int
c150f57c 1920gtp_tactical_analyze_semeai(char* s)
7eeb782e 1921{
c150f57c
AT
1922 int i, j;
1923 int k;
1924 int dragona, dragonb;
1925 int resulta, resultb, move, result_certain;
7eeb782e 1926
c150f57c 1927 k = gtp_decode_coord(s, &i, &j);
7eeb782e 1928
c150f57c
AT
1929 if (k == 0)
1930 return gtp_failure("invalid coordinate");
1931 dragona = POS(i, j);
1932 if (BOARD(i, j) == EMPTY)
1933 return gtp_failure("vertex must not be empty");
7eeb782e 1934
c150f57c
AT
1935 if (!gtp_decode_coord(s + k, &i, &j))
1936 return gtp_failure("invalid coordinate");
1937 dragonb = POS(i, j);
1938 if (BOARD(i, j) == EMPTY)
1939 return gtp_failure("vertex must not be empty");
7eeb782e 1940
c150f57c
AT
1941 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
1942 /* to get the variations into the sgf file, clear the reading cache */
1943 if (sgf_dumptree)
1944 reading_cache_clear();
7eeb782e 1945
c150f57c
AT
1946 owl_analyze_semeai(dragona, dragonb, &resulta, &resultb, &move, 0,
1947 &result_certain);
1948 gtp_start_response(GTP_SUCCESS);
1949 gtp_print_code(resulta);
1950 gtp_printf(" ");
1951 gtp_print_code(resultb);
1952 gtp_mprintf(" %m", I(move), J(move));
1953 if (!result_certain && report_uncertainty)
1954 gtp_printf(" uncertain");
7eeb782e 1955
c150f57c
AT
1956 return gtp_finish_response();
1957}
7eeb782e
AT
1958
1959/***********************
1960 * Connection reading. *
1961 ***********************/
1962
1963/* Function: Try to connect two strings.
1964 * Arguments: vertex, vertex
1965 * Fails: invalid vertex, empty vertex, vertices of different colors
1966 * Returns: connect result followed by connect point if successful.
1967 */
1968static int
c150f57c 1969gtp_connect(char* s)
7eeb782e 1970{
c150f57c
AT
1971 int ai, aj;
1972 int bi, bj;
1973 int connect_move = PASS_MOVE;
1974 int result;
1975 int n;
7eeb782e 1976
c150f57c
AT
1977 n = gtp_decode_coord(s, &ai, &aj);
1978 if (n == 0)
1979 return gtp_failure("invalid coordinate");
7eeb782e 1980
c150f57c
AT
1981 if (!gtp_decode_coord(s + n, &bi, &bj))
1982 return gtp_failure("invalid coordinate");
7eeb782e 1983
c150f57c
AT
1984 if (BOARD(ai, aj) == EMPTY || BOARD(bi, bj) == EMPTY)
1985 return gtp_failure("vertex must not be empty");
7eeb782e 1986
c150f57c
AT
1987 if (BOARD(ai, aj) != BOARD(bi, bj))
1988 return gtp_failure("vertices must have same color");
7eeb782e 1989
c150f57c
AT
1990 result = string_connect(POS(ai, aj), POS(bi, bj), &connect_move);
1991 gtp_start_response(GTP_SUCCESS);
1992 gtp_print_code(result);
1993 if (result != 0)
1994 gtp_mprintf(" %m", I(connect_move), J(connect_move));
7eeb782e 1995
c150f57c
AT
1996 return gtp_finish_response();
1997}
7eeb782e
AT
1998
1999/* Function: Try to disconnect two strings.
2000 * Arguments: vertex, vertex
2001 * Fails: invalid vertex, empty vertex, vertices of different colors
2002 * Returns: disconnect result followed by disconnect point if successful.
2003 */
2004static int
c150f57c 2005gtp_disconnect(char* s)
7eeb782e 2006{
c150f57c
AT
2007 int ai, aj;
2008 int bi, bj;
2009 int disconnect_move = PASS_MOVE;
2010 int result;
2011 int n;
7eeb782e 2012
c150f57c
AT
2013 n = gtp_decode_coord(s, &ai, &aj);
2014 if (n == 0)
2015 return gtp_failure("invalid coordinate");
7eeb782e 2016
c150f57c
AT
2017 if (!gtp_decode_coord(s + n, &bi, &bj))
2018 return gtp_failure("invalid coordinate");
7eeb782e 2019
c150f57c
AT
2020 if (BOARD(ai, aj) == EMPTY || BOARD(bi, bj) == EMPTY)
2021 return gtp_failure("vertex must not be empty");
7eeb782e 2022
c150f57c
AT
2023 if (BOARD(ai, aj) != BOARD(bi, bj))
2024 return gtp_failure("vertices must have same color");
7eeb782e 2025
c150f57c
AT
2026 result = disconnect(POS(ai, aj), POS(bi, bj), &disconnect_move);
2027 gtp_start_response(GTP_SUCCESS);
2028 gtp_print_code(result);
2029 if (result != 0)
2030 gtp_mprintf(" %m", I(disconnect_move), J(disconnect_move));
7eeb782e 2031
c150f57c
AT
2032 return gtp_finish_response();
2033}
7eeb782e
AT
2034
2035/* Function: Try to break from string into area.
2036 * Arguments: vertex, vertices
2037 * Fails: invalid vertex, empty vertex.
2038 * Returns: result followed by break in point if successful.
2039 */
2040static int
c150f57c 2041gtp_break_in(char* s)
7eeb782e 2042{
c150f57c
AT
2043 int ai, aj;
2044 int i, j;
2045 signed char goal[BOARDMAX];
2046 int break_move = PASS_MOVE;
2047 int result;
2048 int n;
2049 int k;
7eeb782e 2050
c150f57c
AT
2051 n = gtp_decode_coord(s, &ai, &aj);
2052 if (n == 0)
2053 return gtp_failure("invalid coordinate");
7eeb782e 2054
c150f57c
AT
2055 memset(goal, 0, BOARDMAX);
2056 s += n;
2057
2058 for (k = 0; k < MAX_BOARD * MAX_BOARD; k++) {
2059 n = gtp_decode_coord(s, &i, &j);
2060 if (n > 0) {
2061 goal[POS(i, j)] = 1;
2062 s += n;
2063 } else if (sscanf(s, "%*s") != EOF)
2064 return gtp_failure("invalid coordinate");
2065 else
2066 break;
7eeb782e 2067 }
7eeb782e 2068
c150f57c
AT
2069 if (BOARD(ai, aj) == EMPTY)
2070 return gtp_failure("vertex must not be empty");
7eeb782e 2071
c150f57c
AT
2072 result = break_in(POS(ai, aj), goal, &break_move);
2073 gtp_start_response(GTP_SUCCESS);
2074 gtp_print_code(result);
2075 if (result != 0)
2076 gtp_mprintf(" %m", I(break_move), J(break_move));
7eeb782e 2077
c150f57c 2078 return gtp_finish_response();
7eeb782e
AT
2079}
2080
2081/* Function: Try to block string from area.
2082 * Arguments: vertex, vertices
2083 * Fails: invalid vertex, empty vertex.
2084 * Returns: result followed by block point if successful.
2085 */
2086static int
c150f57c 2087gtp_block_off(char* s)
7eeb782e 2088{
c150f57c
AT
2089 int ai, aj;
2090 int i, j;
2091 signed char goal[BOARDMAX];
2092 int block_move = PASS_MOVE;
2093 int result;
2094 int n;
2095 int k;
7eeb782e 2096
c150f57c
AT
2097 n = gtp_decode_coord(s, &ai, &aj);
2098 if (n == 0)
2099 return gtp_failure("invalid coordinate");
7eeb782e 2100
c150f57c
AT
2101 memset(goal, 0, BOARDMAX);
2102 s += n;
2103
2104 for (k = 0; k < MAX_BOARD * MAX_BOARD; k++) {
2105 n = gtp_decode_coord(s, &i, &j);
2106 if (n > 0) {
2107 goal[POS(i, j)] = 1;
2108 s += n;
2109 } else if (sscanf(s, "%*s") != EOF)
2110 return gtp_failure("invalid coordinate");
2111 else
2112 break;
7eeb782e 2113 }
7eeb782e 2114
c150f57c
AT
2115 if (BOARD(ai, aj) == EMPTY)
2116 return gtp_failure("vertex must not be empty");
7eeb782e 2117
c150f57c
AT
2118 result = block_off(POS(ai, aj), goal, &block_move);
2119 gtp_start_response(GTP_SUCCESS);
2120 gtp_print_code(result);
2121 if (result != 0)
2122 gtp_mprintf(" %m", I(block_move), J(block_move));
7eeb782e 2123
c150f57c 2124 return gtp_finish_response();
7eeb782e
AT
2125}
2126
7eeb782e
AT
2127/********
2128 * eyes *
2129 ********/
2130
2131/* Function: Evaluate an eye space
2132 * Arguments: vertex
2133 * Fails: invalid vertex
2134 * Returns: Minimum and maximum number of eyes. If these differ an
2135 * attack and a defense point are additionally returned.
2136 * If the vertex is not an eye space or not of unique color,
2137 * a single -1 is returned.
2138 */
2139
2140static int
c150f57c
AT
2141gtp_eval_eye(char* s)
2142{
2143 int m, n;
2144 struct eyevalue value;
2145 int attack_point;
2146 int defense_point;
2147 int pos;
7eeb782e 2148
c150f57c
AT
2149 if (!gtp_decode_coord(s, &m, &n))
2150 return gtp_failure("invalid coordinate");
2151
2152 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
2153
2154 if (black_eye[POS(m, n)].color == BLACK) {
2155 pos = black_eye[POS(m, n)].origin;
2156 compute_eyes(pos, &value, &attack_point, &defense_point,
2157 black_eye, half_eye, 0);
2158 } else if (white_eye[POS(m, n)].color == WHITE) {
2159 pos = white_eye[POS(m, n)].origin;
2160 compute_eyes(pos, &value, &attack_point, &defense_point,
2161 white_eye, half_eye, 0);
2162 } else
2163 /* Not an eye or not of unique color. */
2164 return gtp_success("-1");
2165
2166 gtp_start_response(GTP_SUCCESS);
2167 gtp_printf("%d %d", min_eyes(&value), max_eyes(&value));
2168 if (eye_move_urgency(&value) > 0) {
2169 gtp_printf(" ");
2170 gtp_print_vertex(I(attack_point), J(attack_point));
2171 gtp_printf(" ");
2172 gtp_print_vertex(I(defense_point), J(defense_point));
2173 }
2174 return gtp_finish_response();
2175}
7eeb782e
AT
2176
2177/*****************
2178 * dragon status *
2179 *****************/
2180
2181/* Function: Determine status of a dragon.
2182 * Arguments: optional vertex
2183 * Fails: invalid vertex, empty vertex
2184 * Returns: status ("alive", "critical", "dead", or "unknown"),
2185 * attack point, defense point. Points of attack and
2186 * defense are only given if the status is critical.
2187 * If no vertex is given, the status is listed for all
2188 * dragons, one per row in the format "A4: alive".
2189 *
2190 * FIXME: Should be able to distinguish between life in seki
2191 * and independent life. Should also be able to identify ko.
2192 */
2193
2194static int
c150f57c
AT
2195gtp_dragon_status(char* s)
2196{
2197 int i, j;
2198 int str = NO_MOVE;
2199 int pos;
2200 int empty_response = 1;
2201
2202 if (gtp_decode_coord(s, &i, &j)) {
2203 str = POS(i, j);
2204 if (board[str] == EMPTY)
2205 return gtp_failure("vertex must not be empty");
2206 } else if (sscanf(s, "%*s") != EOF)
2207 return gtp_failure("invalid coordinate");
2208
2209 silent_examine_position(EXAMINE_DRAGONS);
2210
2211 gtp_start_response(GTP_SUCCESS);
2212
2213 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
2214 if (ON_BOARD(pos)
2215 && (pos == str
2216 || (str == NO_MOVE
2217 && board[pos] != EMPTY
2218 && dragon[pos].origin == pos))) {
2219 if (str == NO_MOVE)
2220 gtp_mprintf("%m: ", I(pos), J(pos));
2221
2222 if (dragon[pos].status == ALIVE)
2223 gtp_printf("alive\n");
2224 else if (dragon[pos].status == DEAD)
2225 gtp_printf("dead\n");
2226 else if (dragon[pos].status == UNKNOWN)
2227 gtp_printf("unknown\n");
2228 else {
2229 /* Only remaining possibility. */
2230 assert(dragon[pos].status == CRITICAL);
2231 /* Status critical, need to return attack and defense point as well. */
2232 gtp_mprintf("critical %m %m\n",
2233 I(DRAGON2(pos).owl_attack_point),
2234 J(DRAGON2(pos).owl_attack_point),
2235 I(DRAGON2(pos).owl_defense_point),
2236 J(DRAGON2(pos).owl_defense_point));
2237 }
2238 empty_response = 0;
2239 }
7eeb782e 2240 }
7eeb782e 2241
c150f57c
AT
2242 if (empty_response)
2243 gtp_printf("\n");
7eeb782e 2244
c150f57c
AT
2245 gtp_printf("\n");
2246 return GTP_OK;
7eeb782e
AT
2247}
2248
7eeb782e
AT
2249/* Function: Determine whether two stones belong to the same dragon.
2250 * Arguments: vertex, vertex
2251 * Fails: invalid vertex, empty vertex
2252 * Returns: 1 if the vertices belong to the same dragon, 0 otherwise
2253 */
2254
2255static int
c150f57c 2256gtp_same_dragon(char* s)
7eeb782e 2257{
c150f57c
AT
2258 int ai, aj;
2259 int bi, bj;
2260 int n;
7eeb782e 2261
c150f57c
AT
2262 n = gtp_decode_coord(s, &ai, &aj);
2263 if (n == 0)
2264 return gtp_failure("invalid coordinate");
7eeb782e 2265
c150f57c
AT
2266 if (!gtp_decode_coord(s + n, &bi, &bj))
2267 return gtp_failure("invalid coordinate");
7eeb782e 2268
c150f57c
AT
2269 if (BOARD(ai, aj) == EMPTY || BOARD(bi, bj) == EMPTY)
2270 return gtp_failure("vertex must not be empty");
7eeb782e 2271
c150f57c 2272 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 2273
c150f57c
AT
2274 return gtp_success("%d", dragon[POS(ai, aj)].id == dragon[POS(bi, bj)].id);
2275}
7eeb782e
AT
2276
2277/************************
2278 * Unconditional status *
2279 ************************/
2280
2281/* Function: Determine the unconditional status of a vertex.
2282 * Arguments: vertex
2283 * Fails: invalid vertex
2284 * Returns: unconditional status ("undecided", "alive", "dead",
2285 * "white_territory", "black_territory"). Occupied vertices can
2286 * be undecided, alive, or dead. Empty vertices can be
2287 * undecided, white territory, or black territory.
2288 */
2289
2290static int
c150f57c 2291gtp_unconditional_status(char* s)
7eeb782e 2292{
c150f57c
AT
2293 int i, j;
2294 enum dragon_status status;
7eeb782e 2295
c150f57c
AT
2296 if (!gtp_decode_coord(s, &i, &j))
2297 return gtp_failure("invalid coordinate");
7eeb782e 2298
c150f57c 2299 silent_examine_position(EXAMINE_WORMS);
7eeb782e 2300
c150f57c
AT
2301 status = worm[POS(i, j)].unconditional_status;
2302 if (status == UNKNOWN)
2303 return gtp_success("undecided");
2304 return gtp_success("%s", status_to_string(status));
2305}
7eeb782e
AT
2306
2307/***********************
2308 * combination attacks *
2309 ***********************/
2310
2311/* Function: Find a move by color capturing something through a
2312 * combination attack.
2313 * Arguments: color
2314 * Fails: invalid color
2315 * Returns: Recommended move, PASS if no move found
2316 */
2317
2318static int
c150f57c 2319gtp_combination_attack(char* s)
7eeb782e 2320{
c150f57c
AT
2321 int color;
2322 int attack_point;
2323 int n;
2324
2325 n = gtp_decode_color(s, &color);
2326 if (!n)
2327 return gtp_failure("invalid color");
7eeb782e 2328
c150f57c 2329 silent_examine_position(EXAMINE_ALL);
7eeb782e 2330
c150f57c
AT
2331 if (!atari_atari(color, &attack_point, NULL, verbose))
2332 attack_point = NO_MOVE;
7eeb782e 2333
c150f57c
AT
2334 gtp_start_response(GTP_SUCCESS);
2335 gtp_print_vertex(I(attack_point), J(attack_point));
2336 return gtp_finish_response();
7eeb782e
AT
2337}
2338
2339/* Function: If color can capture something through a
2340 * combination attack, list moves by the opponent of color
2341 * to defend against this attack.
2342 * Arguments: color
2343 * Fails: invalid color
2344 * Returns: Recommended moves, PASS if no combination attack found.
2345 */
2346
2347static int
c150f57c 2348gtp_combination_defend(char* s)
7eeb782e 2349{
c150f57c
AT
2350 int color;
2351 signed char defense_points[BOARDMAX];
2352 int pos;
2353 int first = 1;
2354 int n;
7eeb782e 2355
c150f57c
AT
2356 n = gtp_decode_color(s, &color);
2357 if (!n)
2358 return gtp_failure("invalid color");
7eeb782e 2359
c150f57c 2360 silent_examine_position(EXAMINE_ALL);
7eeb782e 2361
c150f57c
AT
2362 memset(defense_points, 0, sizeof(defense_points));
2363 if (!atari_atari(color, NULL, defense_points, verbose))
2364 return gtp_success("PASS");
2365
2366 gtp_start_response(GTP_SUCCESS);
2367 for (pos = BOARDMIN; pos < BOARDMAX; pos++)
2368 if (ON_BOARD(pos) && defense_points[pos]) {
2369 if (!first)
2370 gtp_printf(" ");
2371 else
2372 first = 0;
2373 gtp_print_vertex(I(pos), J(pos));
2374 }
2375
2376 return gtp_finish_response();
7eeb782e
AT
2377}
2378
2379/* Function: Run atari_atari_confirm_safety().
2380 * Arguments: move, optional int
2381 * Fails: invalid move
2382 * Returns: success code, if failure also defending move
2383 */
2384
2385static int
c150f57c 2386gtp_aa_confirm_safety(char* s)
7eeb782e 2387{
c150f57c
AT
2388 int color;
2389 int i, j;
2390 int n;
2391 int minsize = 0;
2392 int result;
2393 int defense_point = NO_MOVE;
2394 signed char saved_dragons[BOARDMAX];
2395 signed char saved_worms[BOARDMAX];
7eeb782e 2396
c150f57c
AT
2397 n = gtp_decode_move(s, &color, &i, &j);
2398 if (n == 0 || POS(i, j) == NO_MOVE)
2399 return gtp_failure("invalid color or coordinate");
7eeb782e 2400
c150f57c 2401 sscanf(s + n, "%d", &minsize);
7eeb782e 2402
c150f57c
AT
2403 genmove(color, NULL, NULL);
2404 get_saved_dragons(POS(i, j), saved_dragons);
2405 get_saved_worms(POS(i, j), saved_worms);
7eeb782e 2406
c150f57c
AT
2407 result = atari_atari_confirm_safety(color, POS(i, j),
2408 &defense_point, minsize,
2409 saved_dragons, saved_worms);
2410
2411 gtp_start_response(GTP_SUCCESS);
2412 gtp_mprintf("%d", result);
2413 if (result == 0)
2414 gtp_mprintf(" %m", I(defense_point), J(defense_point));
2415
2416 return gtp_finish_response();
2417}
7eeb782e
AT
2418
2419/********************
2420 * generating moves *
2421 ********************/
2422
2423/* Function: Generate and play the supposedly best black move.
2424 * Arguments: none
2425 * Fails: never
2426 * Returns: a move coordinate or "PASS"
2427 *
2428 * Status: Obsolete GTP version 1 command.
2429 */
2430static int
c150f57c 2431gtp_genmove_black(char* s)
7eeb782e 2432{
c150f57c
AT
2433 int move;
2434 UNUSED(s);
7eeb782e 2435
c150f57c
AT
2436 if (stackp > 0)
2437 return gtp_failure("genmove cannot be called when stackp > 0");
7eeb782e 2438
c150f57c 2439 move = genmove(BLACK, NULL, NULL);
7eeb782e 2440
c150f57c 2441 gnugo_play_move(move, BLACK);
7eeb782e 2442
c150f57c
AT
2443 gtp_start_response(GTP_SUCCESS);
2444 gtp_print_vertex(I(move), J(move));
2445 return gtp_finish_response();
7eeb782e
AT
2446}
2447
2448/* Function: Generate and play the supposedly best white move.
2449 * Arguments: none
2450 * Fails: never
2451 * Returns: a move coordinate or "PASS"
2452 *
2453 * Status: Obsolete GTP version 1 command.
2454 */
2455static int
c150f57c 2456gtp_genmove_white(char* s)
7eeb782e 2457{
c150f57c
AT
2458 int move;
2459 UNUSED(s);
7eeb782e 2460
c150f57c
AT
2461 if (stackp > 0)
2462 return gtp_failure("genmove cannot be called when stackp > 0");
7eeb782e 2463
c150f57c 2464 move = genmove(WHITE, NULL, NULL);
7eeb782e 2465
c150f57c 2466 gnugo_play_move(move, WHITE);
7eeb782e 2467
c150f57c
AT
2468 gtp_start_response(GTP_SUCCESS);
2469 gtp_print_vertex(I(move), J(move));
2470 return gtp_finish_response();
7eeb782e
AT
2471}
2472
2473/* Function: Generate and play the supposedly best move for either color.
2474 * Arguments: color to move
2475 * Fails: invalid color
2476 * Returns: a move coordinate or "PASS" (or "resign" if resignation_allowed)
2477 *
2478 * Status: GTP version 2 standard command.
2479 */
2480static int
c150f57c 2481gtp_genmove(char* s)
7eeb782e 2482{
c150f57c
AT
2483 int move;
2484 int resign;
2485 int color;
2486 int n;
7eeb782e 2487
c150f57c
AT
2488 n = gtp_decode_color(s, &color);
2489 if (!n)
2490 return gtp_failure("invalid color");
7eeb782e 2491
c150f57c
AT
2492 if (stackp > 0)
2493 return gtp_failure("genmove cannot be called when stackp > 0");
7eeb782e 2494
c150f57c
AT
2495 adjust_level_offset(color);
2496 move = genmove(color, NULL, &resign);
7eeb782e 2497
c150f57c
AT
2498 if (resign)
2499 return gtp_success("resign");
7eeb782e 2500
c150f57c 2501 gnugo_play_move(move, color);
7eeb782e 2502
c150f57c
AT
2503 gtp_start_response(GTP_SUCCESS);
2504 gtp_print_vertex(I(move), J(move));
2505 return gtp_finish_response();
7eeb782e
AT
2506}
2507
7eeb782e
AT
2508/* Function: Generate the supposedly best move for either color.
2509 * Arguments: color to move
2510 * Fails: invalid color
2511 * Returns: a move coordinate (or "PASS")
2512 *
2513 * Status: GTP version 2 standard command.
2514 */
2515static int
c150f57c 2516gtp_reg_genmove(char* s)
7eeb782e 2517{
c150f57c
AT
2518 int move;
2519 int color;
2520 int n;
2521 unsigned int saved_random_seed = get_random_seed();
7eeb782e 2522
c150f57c
AT
2523 n = gtp_decode_color(s, &color);
2524 if (!n)
2525 return gtp_failure("invalid color");
7eeb782e 2526
c150f57c
AT
2527 if (stackp > 0)
2528 return gtp_failure("genmove cannot be called when stackp > 0");
7eeb782e 2529
c150f57c 2530 /* This is intended for regression purposes and should therefore be
7eeb782e
AT
2531 * deterministic. The best way to ensure this is to reset the random
2532 * number generator before calling genmove(). It is always seeded by
2533 * 0.
2534 */
c150f57c
AT
2535 set_random_seed(0);
2536
2537 move = genmove_conservative(color, NULL);
7eeb782e 2538
c150f57c
AT
2539 set_random_seed(saved_random_seed);
2540 gtp_start_response(GTP_SUCCESS);
2541 gtp_print_vertex(I(move), J(move));
2542 return gtp_finish_response();
7eeb782e
AT
2543}
2544
2545/* Function: Generate the supposedly best move for either color.
2546 * Arguments: color to move, optionally a random seed
2547 * Fails: invalid color
2548 * Returns: a move coordinate (or "PASS")
2549 *
2550 * This differs from reg_genmove in the optional random seed.
2551 */
2552static int
c150f57c 2553gtp_gg_genmove(char* s)
7eeb782e 2554{
c150f57c
AT
2555 int move;
2556 int color;
2557 int n;
2558 unsigned int saved_random_seed = get_random_seed();
2559 unsigned int seed;
7eeb782e 2560
c150f57c
AT
2561 n = gtp_decode_color(s, &color);
2562 if (!n)
2563 return gtp_failure("invalid color");
7eeb782e 2564
c150f57c
AT
2565 if (stackp > 0)
2566 return gtp_failure("genmove cannot be called when stackp > 0");
7eeb782e 2567
c150f57c 2568 /* This is intended for regression purposes and should therefore be
7eeb782e
AT
2569 * deterministic. The best way to ensure this is to reset the random
2570 * number generator before calling genmove(). By default it is
2571 * seeded with 0, but if an optional unsigned integer is given in
2572 * the command after the color, this is used as seed instead.
2573 */
c150f57c
AT
2574 seed = 0;
2575 sscanf(s + n, "%u", &seed);
2576 set_random_seed(seed);
7eeb782e 2577
c150f57c
AT
2578 move = genmove_conservative(color, NULL);
2579 set_random_seed(saved_random_seed);
2580 gtp_start_response(GTP_SUCCESS);
2581 gtp_print_vertex(I(move), J(move));
2582 return gtp_finish_response();
2583}
7eeb782e
AT
2584
2585/* Function: Generate the supposedly best move for either color from a
2586 * choice of allowed vertices.
2587 * Arguments: color to move, allowed vertices
2588 * Fails: invalid color, invalid vertex, no vertex listed
2589 * Returns: a move coordinate (or "PASS")
2590 */
2591static int
c150f57c 2592gtp_restricted_genmove(char* s)
7eeb782e 2593{
c150f57c
AT
2594 int move;
2595 int i, j;
2596 int color;
2597 int n;
2598 unsigned int saved_random_seed = get_random_seed();
2599 int allowed_moves[BOARDMAX];
2600 int number_allowed_moves = 0;
2601 memset(allowed_moves, 0, sizeof(allowed_moves));
7eeb782e 2602
c150f57c
AT
2603 n = gtp_decode_color(s, &color);
2604 if (!n)
2605 return gtp_failure("invalid color");
7eeb782e 2606
c150f57c
AT
2607 s += n;
2608 while (1) {
2609 n = gtp_decode_coord(s, &i, &j);
2610 if (n > 0) {
2611 allowed_moves[POS(i, j)] = 1;
2612 number_allowed_moves++;
2613 s += n;
2614 } else if (sscanf(s, "%*s") != EOF)
2615 return gtp_failure("invalid coordinate");
2616 else
2617 break;
7eeb782e 2618 }
7eeb782e 2619
c150f57c
AT
2620 if (number_allowed_moves == 0)
2621 return gtp_failure("no allowed vertex");
7eeb782e 2622
c150f57c
AT
2623 if (stackp > 0)
2624 return gtp_failure("genmove cannot be called when stackp > 0");
7eeb782e 2625
c150f57c 2626 /* This is intended for regression purposes and should therefore be
7eeb782e
AT
2627 * deterministic. The best way to ensure this is to reset the random
2628 * number generator before calling genmove(). It is always seeded by
2629 * 0.
2630 */
c150f57c 2631 set_random_seed(0);
7eeb782e 2632
c150f57c
AT
2633 move = genmove_restricted(color, allowed_moves);
2634 set_random_seed(saved_random_seed);
2635 gtp_start_response(GTP_SUCCESS);
2636 gtp_print_vertex(I(move), J(move));
2637 return gtp_finish_response();
2638}
7eeb782e
AT
2639
2640/* Function: Generate and play the supposedly best move for either color,
2641 * not passing until all dead opponent stones have been removed.
2642 * Arguments: color to move
2643 * Fails: invalid color
2644 * Returns: a move coordinate (or "PASS")
2645 *
2646 * Status: KGS specific command.
2647 *
2648 * A similar command, but possibly somewhat different, will likely be added
2649 * to GTP version 3 at a later time.
2650 */
2651static int
c150f57c 2652gtp_kgs_genmove_cleanup(char* s)
7eeb782e 2653{
c150f57c
AT
2654 int move;
2655 int color;
2656 int n;
2657 int save_capture_all_dead = capture_all_dead;
7eeb782e 2658
c150f57c
AT
2659 n = gtp_decode_color(s, &color);
2660 if (!n)
2661 return gtp_failure("invalid color");
7eeb782e 2662
c150f57c
AT
2663 if (stackp > 0)
2664 return gtp_failure("kgs-genmove_cleanup cannot be called when stackp > 0");
7eeb782e 2665
c150f57c 2666 /* Turn on the capture_all_dead option to force removal of dead
7eeb782e
AT
2667 * opponent stones.
2668 */
c150f57c 2669 capture_all_dead = 1;
7eeb782e 2670
c150f57c
AT
2671 adjust_level_offset(color);
2672 move = genmove(color, NULL, NULL);
7eeb782e 2673
c150f57c 2674 capture_all_dead = save_capture_all_dead;
7eeb782e 2675
c150f57c
AT
2676 gnugo_play_move(move, color);
2677
2678 gtp_start_response(GTP_SUCCESS);
2679 gtp_print_vertex(I(move), J(move));
2680 return gtp_finish_response();
2681}
7eeb782e
AT
2682
2683/* Function : List the move reasons for a move.
2684 * Arguments: vertex
2685 * Fails: : invalid vertex, occupied vertex
2686 * Returns : list of move reasons (may be empty)
2687 */
2688
2689static int
c150f57c 2690gtp_move_reasons(char* s)
7eeb782e 2691{
c150f57c
AT
2692 int i, j;
2693 if (!gtp_decode_coord(s, &i, &j))
2694 return gtp_failure("invalid coordinate");
7eeb782e 2695
c150f57c
AT
2696 if (BOARD(i, j) != EMPTY)
2697 return gtp_failure("vertex must not be occupied");
7eeb782e 2698
c150f57c
AT
2699 gtp_start_response(GTP_SUCCESS);
2700 if (list_move_reasons(gtp_output_file, POS(i, j)) == 0)
2701 gtp_printf("\n");
7eeb782e 2702 gtp_printf("\n");
c150f57c 2703 return GTP_OK;
7eeb782e
AT
2704}
2705
2706/* Function : Generate a list of all moves with values larger than zero in
2707 * the previous genmove command.
2708 * If no previous genmove command has been issued, the result
2709 * of this command will be meaningless.
2710 * Arguments: none
2711 * Fails: : never
2712 * Returns : list of moves with values
2713 */
2714
2715static int
c150f57c 2716gtp_all_move_values(char* s)
7eeb782e 2717{
c150f57c
AT
2718 UNUSED(s);
2719 gtp_start_response(GTP_SUCCESS);
2720 print_all_move_values(gtp_output_file);
2721 gtp_printf("\n");
2722 return GTP_OK;
7eeb782e
AT
2723}
2724
2725/* Function : Generate a sorted list of the best moves in the previous genmove
2726 * command.
2727 * If no previous genmove command has been issued, the result
2728 * of this command will be meaningless.
2729 * Arguments: none
2730 * Fails: : never
2731 * Returns : list of moves with weights
2732 */
2733
2734/* FIXME: Don't we want the moves one per row? */
2735static int
c150f57c 2736gtp_top_moves(char* s)
7eeb782e 2737{
c150f57c
AT
2738 int k;
2739 UNUSED(s);
2740 gtp_start_response(GTP_SUCCESS);
2741 for (k = 0; k < 10; k++)
2742 if (best_move_values[k] > 0.0) {
2743 gtp_print_vertex(I(best_moves[k]), J(best_moves[k]));
2744 gtp_printf(" %.2f ", best_move_values[k]);
2745 }
2746 gtp_printf("\n\n");
2747 return GTP_OK;
7eeb782e
AT
2748}
2749
2750/* Function : Generate a list of the best moves for white with weights
2751 * Arguments: none
2752 * Fails: : never
2753 * Returns : list of moves with weights
2754 */
2755
2756static int
c150f57c 2757gtp_top_moves_white(char* s)
7eeb782e 2758{
c150f57c
AT
2759 int k;
2760 UNUSED(s);
2761 genmove(WHITE, NULL, NULL);
2762 gtp_start_response(GTP_SUCCESS);
2763 for (k = 0; k < 10; k++)
2764 if (best_move_values[k] > 0.0) {
2765 gtp_print_vertex(I(best_moves[k]), J(best_moves[k]));
2766 gtp_printf(" %.2f ", best_move_values[k]);
2767 }
2768 return gtp_finish_response();
7eeb782e
AT
2769}
2770
2771/* Function : Generate a list of the best moves for black with weights
2772 * Arguments: none
2773 * Fails: : never
2774 * Returns : list of moves with weights
2775 */
2776
2777static int
c150f57c 2778gtp_top_moves_black(char* s)
7eeb782e 2779{
c150f57c
AT
2780 int k;
2781 UNUSED(s);
2782 genmove(BLACK, NULL, NULL);
2783 gtp_start_response(GTP_SUCCESS);
2784 for (k = 0; k < 10; k++)
2785 if (best_move_values[k] > 0.0) {
2786 gtp_print_vertex(I(best_moves[k]), J(best_moves[k]));
2787 gtp_printf(" %.2f ", best_move_values[k]);
2788 }
2789 return gtp_finish_response();
7eeb782e
AT
2790}
2791
7eeb782e
AT
2792/* Function: Set the playing level.
2793 * Arguments: int
2794 * Fails: incorrect argument
2795 * Returns: nothing
2796 */
2797static int
c150f57c 2798gtp_set_level(char* s)
7eeb782e 2799{
c150f57c
AT
2800 int new_level;
2801 if (sscanf(s, "%d", &new_level) < 1)
2802 return gtp_failure("level not an integer");
2803
2804 set_level(new_level);
2805 return gtp_success("");
7eeb782e
AT
2806}
2807
2808/* Function: Undo one move
2809 * Arguments: none
2810 * Fails: If move history is too short.
2811 * Returns: nothing
2812 *
2813 * Status: GTP version 2 standard command.
2814 */
2815
2816static int
c150f57c 2817gtp_undo(char* s)
7eeb782e 2818{
c150f57c 2819 UNUSED(s);
7eeb782e 2820
c150f57c
AT
2821 if (stackp > 0 || !undo_move(1))
2822 return gtp_failure("cannot undo");
7eeb782e 2823
c150f57c 2824 reset_engine();
7eeb782e 2825
c150f57c
AT
2826 return gtp_success("");
2827}
7eeb782e
AT
2828
2829/* Function: Undo a number of moves
2830 * Arguments: optional int
2831 * Fails: If move history is too short.
2832 * Returns: nothing
2833 */
2834
2835static int
c150f57c 2836gtp_gg_undo(char* s)
7eeb782e 2837{
c150f57c 2838 int number_moves = 1;
7eeb782e 2839
c150f57c 2840 sscanf(s, "%d", &number_moves);
7eeb782e 2841
c150f57c
AT
2842 if (number_moves < 0)
2843 return gtp_failure("can't undo a negative number of moves");
7eeb782e 2844
c150f57c
AT
2845 if (stackp > 0 || !undo_move(number_moves))
2846 return gtp_failure("cannot undo");
7eeb782e 2847
c150f57c 2848 reset_engine();
7eeb782e 2849
c150f57c
AT
2850 return gtp_success("");
2851}
7eeb782e
AT
2852
2853/*****************
2854 * time handling *
2855 *****************/
2856
2857/* Function: Set time allowance
2858 * Arguments: int main_time, int byo_yomi_time, int byo_yomi_stones
2859 * Fails: syntax error
2860 * Returns: nothing
2861 *
2862 * Status: GTP version 2 standard command.
2863 */
2864
2865static int
c150f57c 2866gtp_time_settings(char* s)
7eeb782e 2867{
c150f57c 2868 int main_time, byoyomi_time, byoyomi_stones;
7eeb782e 2869
c150f57c
AT
2870 if (sscanf(s, "%d %d %d", &main_time, &byoyomi_time, &byoyomi_stones) < 3)
2871 return gtp_failure("not three integers");
7eeb782e 2872
c150f57c
AT
2873 clock_settings(main_time, byoyomi_time, byoyomi_stones);
2874 return gtp_success("");
2875}
7eeb782e
AT
2876
2877/* Function: Report remaining time
2878 * Arguments: color color, int time, int stones
2879 * Fails: syntax error
2880 * Returns: nothing
2881 *
2882 * Status: GTP version 2 standard command.
2883 */
2884
2885static int
c150f57c 2886gtp_time_left(char* s)
7eeb782e 2887{
c150f57c
AT
2888 int color;
2889 int time;
2890 int stones;
2891 int n;
7eeb782e 2892
c150f57c
AT
2893 n = gtp_decode_color(s, &color);
2894 if (!n)
2895 return gtp_failure("invalid color");
7eeb782e 2896
c150f57c
AT
2897 if (sscanf(s + n, "%d %d", &time, &stones) < 2)
2898 return gtp_failure("time and stones not two integers");
7eeb782e 2899
c150f57c
AT
2900 update_time_left(color, time, stones);
2901
2902 return gtp_success("");
2903}
7eeb782e
AT
2904
2905/***********
2906 * scoring *
2907 ***********/
2908
2909static float final_score;
2910static enum dragon_status final_status[MAX_BOARD][MAX_BOARD];
c150f57c
AT
2911static enum dragon_status status_numbers[6] = { ALIVE, DEAD, ALIVE_IN_SEKI,
2912 WHITE_TERRITORY,
2913 BLACK_TERRITORY, DAME };
2914static const char* status_names[6] = { "alive", "dead", "seki",
2915 "white_territory", "black_territory",
2916 "dame" };
7eeb782e
AT
2917
2918/* Helper function. */
2919static void
2920finish_and_score_game(int seed)
2921{
c150f57c
AT
2922 int move;
2923 int i, j;
2924 int next;
2925 int pass = 0;
2926 int moves = 0;
2927 int saved_board[MAX_BOARD][MAX_BOARD];
2928 struct board_state saved_pos;
2929 static int current_board[MAX_BOARD][MAX_BOARD];
2930 static int current_seed = -1;
2931 int cached_board = 1;
2932
2933 if (current_seed != seed) {
2934 current_seed = seed;
2935 cached_board = 0;
2936 }
2937
2938 for (i = 0; i < board_size; i++)
2939 for (j = 0; j < board_size; j++)
2940 if (BOARD(i, j) != current_board[i][j]) {
2941 current_board[i][j] = BOARD(i, j);
2942 cached_board = 0;
2943 }
2944
2945 /* If this is exactly the same position as the one we analyzed the
7eeb782e
AT
2946 * last time, the contents of final_score and final_status are up to date.
2947 */
c150f57c
AT
2948 if (cached_board)
2949 return;
7eeb782e 2950
c150f57c
AT
2951 doing_scoring = 1;
2952 store_board(&saved_pos);
7eeb782e 2953
c150f57c 2954 /* Let black start if we have no move history. Otherwise continue
7eeb782e
AT
2955 * alternation.
2956 */
c150f57c
AT
2957 if (get_last_player() == EMPTY)
2958 next = BLACK;
7eeb782e 2959 else
c150f57c
AT
2960 next = OTHER_COLOR(get_last_player());
2961
2962 do {
2963 move = genmove_conservative(next, NULL);
2964 gnugo_play_move(move, next);
2965 if (move != PASS_MOVE) {
2966 pass = 0;
2967 moves++;
2968 } else
2969 pass++;
2970
2971 next = OTHER_COLOR(next);
2972 } while (pass < 2 && moves < board_size * board_size);
2973
2974 final_score = aftermath_compute_score(next, NULL);
2975 for (i = 0; i < board_size; i++)
2976 for (j = 0; j < board_size; j++) {
2977 final_status[i][j] = aftermath_final_status(next, POS(i, j));
2978 saved_board[i][j] = BOARD(i, j);
2979 }
2980
2981 restore_board(&saved_pos);
2982 doing_scoring = 0;
2983
2984 /* Update the status for vertices which were changed while finishing
7eeb782e
AT
2985 * the game, up to filling dame.
2986 */
c150f57c
AT
2987 for (i = 0; i < board_size; i++)
2988 for (j = 0; j < board_size; j++) {
2989 if (BOARD(i, j) == saved_board[i][j])
2990 continue;
2991
2992 if (BOARD(i, j) == EMPTY) {
2993 if (final_status[i][j] == ALIVE
2994 || final_status[i][j] == ALIVE_IN_SEKI)
2995 final_status[i][j] = DAME;
2996 else if (final_status[i][j] == DEAD) {
2997 if (saved_board[i][j] == BLACK)
2998 final_status[i][j] = WHITE_TERRITORY;
2999 else
3000 final_status[i][j] = BLACK_TERRITORY;
3001 }
3002 } else if (BOARD(i, j) == BLACK) {
3003 if (final_status[i][j] == WHITE_TERRITORY)
3004 final_status[i][j] = DEAD;
3005 else if (final_status[i][j] == DAME)
3006 final_status[i][j] = ALIVE_IN_SEKI;
3007 else if (final_status[i][j] == BLACK_TERRITORY)
3008 final_status[i][j] = ALIVE;
3009 else
3010 final_status[i][j] = DEAD;
3011 } else if (BOARD(i, j) == WHITE) {
3012 if (final_status[i][j] == BLACK_TERRITORY)
3013 final_status[i][j] = DEAD;
3014 else if (final_status[i][j] == DAME)
3015 final_status[i][j] = ALIVE_IN_SEKI;
3016 else if (final_status[i][j] == WHITE_TERRITORY)
3017 final_status[i][j] = ALIVE;
3018 else
3019 final_status[i][j] = DEAD;
3020 }
3021 }
7eeb782e
AT
3022}
3023
7eeb782e
AT
3024/* Function: Compute the score of a finished game.
3025 * Arguments: Optional random seed
3026 * Fails: never
3027 * Returns: Score in SGF format (RE property).
3028 *
3029 * Status: GTP version 2 standard command.
3030 */
3031static int
c150f57c 3032gtp_final_score(char* s)
7eeb782e 3033{
c150f57c
AT
3034 unsigned int saved_random_seed = get_random_seed();
3035 int seed;
3036 /* This is intended for regression purposes and should therefore be
7eeb782e
AT
3037 * deterministic. The best way to ensure this is to reset the random
3038 * number generator before calling genmove(). By default it is
3039 * seeded with 0, but if an optional unsigned integer is given in
3040 * the command after the color, this is used as seed instead.
3041 */
c150f57c
AT
3042 seed = 0;
3043 sscanf(s, "%d", &seed);
3044 set_random_seed(seed);
7eeb782e 3045
c150f57c 3046 finish_and_score_game(seed);
7eeb782e 3047
c150f57c 3048 set_random_seed(saved_random_seed);
7eeb782e 3049
c150f57c
AT
3050 gtp_start_response(GTP_SUCCESS);
3051 if (final_score > 0.0)
3052 gtp_printf("W+%3.1f", final_score);
3053 else if (final_score < 0.0)
3054 gtp_printf("B+%3.1f", -final_score);
3055 else
3056 gtp_printf("0");
3057 return gtp_finish_response();
7eeb782e
AT
3058}
3059
7eeb782e
AT
3060/* Function: Report the final status of a vertex in a finished game.
3061 * Arguments: Vertex, optional random seed
3062 * Fails: invalid vertex
3063 * Returns: Status in the form of one of the strings "alive", "dead",
3064 * "seki", "white_territory", "black_territory", or "dame".
3065 */
3066static int
c150f57c 3067gtp_final_status(char* s)
7eeb782e 3068{
c150f57c
AT
3069 int seed;
3070 int n;
3071 int ai, aj;
3072 int k;
3073 unsigned int saved_random_seed = get_random_seed();
3074 const char* result = NULL;
7eeb782e 3075
c150f57c
AT
3076 n = gtp_decode_coord(s, &ai, &aj);
3077 if (n == 0)
3078 return gtp_failure("invalid coordinate");
7eeb782e 3079
c150f57c 3080 /* This is intended for regression purposes and should therefore be
7eeb782e
AT
3081 * deterministic. The best way to ensure this is to reset the random
3082 * number generator before calling genmove(). By default it is
3083 * seeded with 0, but if an optional unsigned integer is given in
3084 * the command after the color, this is used as seed instead.
3085 */
c150f57c
AT
3086 seed = 0;
3087 sscanf(s + n, "%d", &seed);
3088 set_random_seed(seed);
7eeb782e 3089
c150f57c 3090 finish_and_score_game(seed);
7eeb782e 3091
c150f57c
AT
3092 set_random_seed(saved_random_seed);
3093 for (k = 0; k < 6; k++)
3094 if (final_status[ai][aj] == status_numbers[k]) {
3095 result = status_names[k];
3096 break;
3097 }
3098 assert(result != NULL);
7eeb782e 3099
c150f57c 3100 return gtp_success(result);
7eeb782e
AT
3101}
3102
7eeb782e
AT
3103/* Function: Report vertices with a specific final status in a finished game.
3104 * Arguments: Status in the form of one of the strings "alive", "dead",
3105 * "seki", "white_territory", "black_territory", or "dame".
3106 * An optional random seed can be added.
3107 * Fails: missing or invalid status string
3108 * Returns: Vertices having the specified status. These are split with
3109 * one string on each line if the vertices are nonempty (i.e.
3110 * for "alive", "dead", and "seki").
3111 *
3112 * Status: GTP version 2 standard command.
3113 * However, "dame", "white_territory", and "black_territory"
3114 * are private extensions.
3115 */
3116static int
c150f57c 3117gtp_final_status_list(char* s)
7eeb782e 3118{
c150f57c
AT
3119 int seed;
3120 int n;
3121 int i, j;
3122 enum dragon_status status = UNKNOWN;
3123 int k;
3124 char status_string[GTP_BUFSIZE];
3125 int first;
3126 unsigned int saved_random_seed = get_random_seed();
3127
3128 if (sscanf(s, "%s %n", status_string, &n) != 1)
3129 return gtp_failure("missing status");
7eeb782e 3130
c150f57c
AT
3131 for (k = 0; k < 6; k++) {
3132 if (strcmp(status_string, status_names[k]) == 0)
3133 status = status_numbers[k];
3134 }
7eeb782e 3135
c150f57c
AT
3136 if (status == UNKNOWN)
3137 return gtp_failure("invalid status");
7eeb782e 3138
c150f57c 3139 /* This is intended for regression purposes and should therefore be
7eeb782e
AT
3140 * deterministic. The best way to ensure this is to reset the random
3141 * number generator before calling genmove(). By default it is
3142 * seeded with 0, but if an optional unsigned integer is given in
3143 * the command after the color, this is used as seed instead.
3144 */
c150f57c
AT
3145 seed = 0;
3146 sscanf(s + n, "%d", &seed);
3147 set_random_seed(seed);
3148
3149 finish_and_score_game(seed);
3150
3151 set_random_seed(saved_random_seed);
7eeb782e 3152
c150f57c
AT
3153 gtp_start_response(GTP_SUCCESS);
3154
3155 first = 1;
3156 for (i = 0; i < board_size; i++)
3157 for (j = 0; j < board_size; j++) {
3158 if (final_status[i][j] != status)
3159 continue;
3160 if (BOARD(i, j) == EMPTY) {
3161 if (!first)
3162 gtp_printf(" ");
3163 else
3164 first = 0;
3165 gtp_print_vertex(i, j);
3166 } else {
3167 int num_stones;
3168 int stones[MAX_BOARD * MAX_BOARD];
3169 if (find_origin(POS(i, j)) != POS(i, j))
3170 continue;
3171 if (!first)
3172 gtp_printf("\n");
3173 else
3174 first = 0;
3175 num_stones = findstones(POS(i, j), board_size * board_size, stones);
3176 gtp_print_vertices2(num_stones, stones);
3177 }
3178 }
3179
3180 return gtp_finish_response();
7eeb782e
AT
3181}
3182
3183/* Function: Estimate the score
3184 * Arguments: None
3185 * Fails: never
3186 * Returns: upper and lower bounds for the score
3187 */
3188
3189static int
c150f57c 3190gtp_estimate_score(char* s)
7eeb782e 3191{
c150f57c
AT
3192 float score;
3193 float upper_bound, lower_bound;
3194 UNUSED(s);
7eeb782e 3195
c150f57c
AT
3196 score = gnugo_estimate_score(&upper_bound, &lower_bound);
3197 gtp_start_response(GTP_SUCCESS);
3198 /* Traditionally W wins jigo */
3199 if (score >= 0.0)
3200 gtp_printf("W+%3.1f (upper bound: %3.1f, lower: %3.1f)",
3201 score, upper_bound, lower_bound);
3202 else if (score < 0.0)
3203 gtp_printf("B+%3.1f (upper bound: %3.1f, lower: %3.1f)",
3204 -score, upper_bound, lower_bound);
3205 return gtp_finish_response();
3206}
7eeb782e
AT
3207
3208/* Function: Estimate the score, taking into account which player moves next
3209 * Arguments: Color to play
3210 * Fails: Invalid color
3211 * Returns: Score.
3212 *
3213 * This function generates a move for color, then adds the
3214 * value of the move generated to the value of the position.
3215 * Critical dragons are awarded to the opponent since the
3216 * value of rescuing a critical dragon is taken into account
3217 * in the value of the move generated.
3218 */
3219
3220static int
c150f57c 3221gtp_experimental_score(char* s)
7eeb782e 3222{
c150f57c
AT
3223 float upper_bound, lower_bound, score;
3224 int color;
7eeb782e 3225
c150f57c
AT
3226 if (!gtp_decode_color(s, &color)
3227 || (color != BLACK && color != WHITE))
3228 return gtp_failure("invalid color");
7eeb782e 3229
c150f57c
AT
3230 genmove_conservative(color, NULL);
3231 gnugo_estimate_score(&upper_bound, &lower_bound);
7eeb782e 3232
c150f57c
AT
3233 if (debug & DEBUG_SCORING)
3234 fprintf(stderr, "upper = %3.1f, lower = %3.1f, best = %3.1f\n",
3235 upper_bound, lower_bound, best_move_values[0]);
3236 if (color == WHITE)
3237 score = lower_bound + best_move_values[0];
3238 else
3239 score = upper_bound - best_move_values[0];
7eeb782e 3240
c150f57c
AT
3241 return gtp_success("%3.1f", score);
3242}
7eeb782e
AT
3243
3244/**************
3245 * statistics *
3246 **************/
3247
3248/* Function: Reset the count of life nodes.
3249 * Arguments: none
3250 * Fails: never
3251 * Returns: nothing
3252 *
3253 * Note: This function is obsolete and only remains for backwards
3254 * compatibility.
3255 */
3256static int
c150f57c 3257gtp_reset_life_node_counter(char* s)
7eeb782e 3258{
c150f57c
AT
3259 UNUSED(s);
3260 return gtp_success("");
7eeb782e
AT
3261}
3262
7eeb782e
AT
3263/* Function: Retrieve the count of life nodes.
3264 * Arguments: none
3265 * Fails: never
3266 * Returns: number of life nodes
3267 *
3268 * Note: This function is obsolete and only remains for backwards
3269 * compatibility.
3270 */
3271static int
c150f57c 3272gtp_get_life_node_counter(char* s)
7eeb782e 3273{
c150f57c
AT
3274 UNUSED(s);
3275 return gtp_success("0");
7eeb782e
AT
3276}
3277
7eeb782e
AT
3278/* Function: Reset the count of owl nodes.
3279 * Arguments: none
3280 * Fails: never
3281 * Returns: nothing
3282 */
3283static int
c150f57c 3284gtp_reset_owl_node_counter(char* s)
7eeb782e 3285{
c150f57c
AT
3286 UNUSED(s);
3287 reset_owl_node_counter();
3288 return gtp_success("");
7eeb782e
AT
3289}
3290
7eeb782e
AT
3291/* Function: Retrieve the count of owl nodes.
3292 * Arguments: none
3293 * Fails: never
3294 * Returns: number of owl nodes
3295 */
3296static int
c150f57c 3297gtp_get_owl_node_counter(char* s)
7eeb782e 3298{
c150f57c
AT
3299 int nodes = get_owl_node_counter();
3300 UNUSED(s);
3301 return gtp_success("%d", nodes);
7eeb782e
AT
3302}
3303
7eeb782e
AT
3304/* Function: Reset the count of reading nodes.
3305 * Arguments: none
3306 * Fails: never
3307 * Returns: nothing
3308 */
3309static int
c150f57c 3310gtp_reset_reading_node_counter(char* s)
7eeb782e 3311{
c150f57c
AT
3312 UNUSED(s);
3313 reset_reading_node_counter();
3314 return gtp_success("");
7eeb782e
AT
3315}
3316
7eeb782e
AT
3317/* Function: Retrieve the count of reading nodes.
3318 * Arguments: none
3319 * Fails: never
3320 * Returns: number of reading nodes
3321 */
3322static int
c150f57c 3323gtp_get_reading_node_counter(char* s)
7eeb782e 3324{
c150f57c
AT
3325 int nodes = get_reading_node_counter();
3326 UNUSED(s);
3327 return gtp_success("%d", nodes);
7eeb782e
AT
3328}
3329
7eeb782e
AT
3330/* Function: Reset the count of trymoves/trykos.
3331 * Arguments: none
3332 * Fails: never
3333 * Returns: nothing
3334 */
3335static int
c150f57c 3336gtp_reset_trymove_counter(char* s)
7eeb782e 3337{
c150f57c
AT
3338 UNUSED(s);
3339 reset_trymove_counter();
3340 return gtp_success("");
7eeb782e
AT
3341}
3342
7eeb782e
AT
3343/* Function: Retrieve the count of trymoves/trykos.
3344 * Arguments: none
3345 * Fails: never
3346 * Returns: number of trymoves/trykos
3347 */
3348static int
c150f57c 3349gtp_get_trymove_counter(char* s)
7eeb782e 3350{
c150f57c
AT
3351 int nodes = get_trymove_counter();
3352 UNUSED(s);
3353 return gtp_success("%d", nodes);
7eeb782e
AT
3354}
3355
7eeb782e
AT
3356/* Function: Reset the count of connection nodes.
3357 * Arguments: none
3358 * Fails: never
3359 * Returns: nothing
3360 */
3361static int
c150f57c 3362gtp_reset_connection_node_counter(char* s)
7eeb782e 3363{
c150f57c
AT
3364 UNUSED(s);
3365 reset_connection_node_counter();
3366 return gtp_success("");
7eeb782e
AT
3367}
3368
7eeb782e
AT
3369/* Function: Retrieve the count of connection nodes.
3370 * Arguments: none
3371 * Fails: never
3372 * Returns: number of connection nodes
3373 */
3374static int
c150f57c 3375gtp_get_connection_node_counter(char* s)
7eeb782e 3376{
c150f57c
AT
3377 int nodes = get_connection_node_counter();
3378 UNUSED(s);
3379 return gtp_success("%d", nodes);
7eeb782e
AT
3380}
3381
7eeb782e
AT
3382/*********
3383 * debug *
3384 *********/
3385
7eeb782e
AT
3386/* Function: Test an eyeshape for inconsistent evaluations
3387 * Arguments: Eyeshape vertices
3388 * Fails: Bad vertices
3389 * Returns: Failure reports on stderr.
3390 */
3391static int
c150f57c 3392gtp_test_eyeshape(char* s)
7eeb782e 3393{
c150f57c
AT
3394 int n;
3395 int i, j;
3396 int eye_vertices[MAX_BOARD * MAX_BOARD];
3397 int eyesize = 0;
7eeb782e 3398
7eeb782e 3399 n = gtp_decode_coord(s, &i, &j);
c150f57c
AT
3400 while (n > 0) {
3401 eye_vertices[eyesize] = POS(i, j);
3402 eyesize++;
3403 s += n;
3404 n = gtp_decode_coord(s, &i, &j);
3405 }
7eeb782e 3406
c150f57c
AT
3407 if (eyesize == 0)
3408 return gtp_failure("invalid coordinate");
7eeb782e 3409
c150f57c 3410 test_eyeshape(eyesize, eye_vertices);
7eeb782e 3411
c150f57c
AT
3412 return gtp_success("");
3413}
7eeb782e
AT
3414
3415/* Function: Compute an eyevalue and vital points for an eye graph
3416 * Arguments: Eyeshape encoded in string
3417 * Fails: Bad eyeshape, analysis failed
3418 * Returns: Eyevalue, vital points
3419 */
3420static int
c150f57c 3421gtp_analyze_eyegraph(char* s)
7eeb782e 3422{
c150f57c
AT
3423 struct eyevalue value;
3424 char analyzed_eyegraph[1024];
3425 int result = analyze_eyegraph(s, &value, analyzed_eyegraph);
7eeb782e 3426
c150f57c
AT
3427 if (result == 0)
3428 return gtp_failure("failed to analyze");
7eeb782e 3429
c150f57c 3430 return gtp_success("%s\n%s", eyevalue_to_string(&value), analyzed_eyegraph);
7eeb782e
AT
3431}
3432
7eeb782e
AT
3433/* Function: Returns elapsed CPU time in seconds.
3434 * Arguments: none
3435 * Fails: never
3436 * Returns: Total elapsed (user + system) CPU time in seconds.
3437 */
3438static int
c150f57c 3439gtp_cputime(char* s)
7eeb782e 3440{
c150f57c
AT
3441 UNUSED(s);
3442 return gtp_success("%.3f", gg_cputime());
7eeb782e
AT
3443}
3444
7eeb782e
AT
3445/* Function: Write the position to stdout.
3446 * Arguments: none
3447 * Fails: never
3448 * Returns: nothing
3449 *
3450 * Status: GTP version 2 standard command.
3451 */
3452static int
c150f57c 3453gtp_showboard(char* s)
7eeb782e 3454{
c150f57c 3455 UNUSED(s);
7eeb782e 3456
c150f57c
AT
3457 gtp_start_response(GTP_SUCCESS);
3458 gtp_printf("\n");
3459 simple_showboard(gtp_output_file);
3460 return gtp_finish_response();
3461}
7eeb782e
AT
3462
3463/* Function: Dump stack to stderr.
3464 * Arguments: none
3465 * Fails: never
3466 * Returns: nothing
3467 */
3468static int
c150f57c 3469gtp_dump_stack(char* s)
7eeb782e 3470{
c150f57c
AT
3471 UNUSED(s);
3472 dump_stack();
3473 return gtp_success("");
7eeb782e
AT
3474}
3475
3476/* Determine whether a string starts with a specific substring. */
3477static int
c150f57c
AT
3478has_prefix(const char* s, const char* prefix)
3479{
3480 return strncmp(s, prefix, strlen(prefix)) == 0;
3481}
3482
3483static int
3484print_influence_data(struct influence_data* q, char* what_data)
3485{
3486 float white_influence[BOARDMAX];
3487 float black_influence[BOARDMAX];
3488 float white_strength[BOARDMAX];
3489 float black_strength[BOARDMAX];
3490 float white_attenuation[BOARDMAX];
3491 float black_attenuation[BOARDMAX];
3492 float white_permeability[BOARDMAX];
3493 float black_permeability[BOARDMAX];
3494 float territory_value[BOARDMAX];
3495 int influence_regions[BOARDMAX];
3496 int non_territory[BOARDMAX];
3497 int m, n;
3498
3499 float* float_pointer = NULL;
3500 int* int_pointer = NULL;
3501
3502 while (*what_data == ' ')
3503 what_data++;
3504
3505 get_influence(q, white_influence, black_influence,
3506 white_strength, black_strength,
3507 white_attenuation, black_attenuation,
3508 white_permeability, black_permeability,
3509 territory_value, influence_regions, non_territory);
3510
3511 if (has_prefix(what_data, "white_influence"))
3512 float_pointer = white_influence;
3513 else if (has_prefix(what_data, "black_influence"))
3514 float_pointer = black_influence;
3515 else if (has_prefix(what_data, "white_strength"))
3516 float_pointer = white_strength;
3517 else if (has_prefix(what_data, "black_strength"))
3518 float_pointer = black_strength;
3519 else if (has_prefix(what_data, "white_attenuation"))
3520 float_pointer = white_attenuation;
3521 else if (has_prefix(what_data, "black_attenuation"))
3522 float_pointer = black_attenuation;
3523 else if (has_prefix(what_data, "white_permeability"))
3524 float_pointer = white_permeability;
3525 else if (has_prefix(what_data, "black_permeability"))
3526 float_pointer = black_permeability;
3527 else if (has_prefix(what_data, "territory_value"))
3528 float_pointer = territory_value;
3529 else if (has_prefix(what_data, "influence_regions"))
3530 int_pointer = influence_regions;
3531 else if (has_prefix(what_data, "non_territory"))
3532 int_pointer = non_territory;
3533 else
3534 return gtp_failure("unknown influence data");
3535
3536 gtp_start_response(GTP_SUCCESS);
3537 for (m = 0; m < board_size; m++) {
3538 for (n = 0; n < board_size; n++) {
3539 if (float_pointer)
3540 gtp_printf("%6.2f ", float_pointer[POS(m, n)]);
3541 else
3542 gtp_printf("%2d ", int_pointer[POS(m, n)]);
3543 }
3544 gtp_printf("\n");
7eeb782e 3545 }
c150f57c
AT
3546
3547 /* We already have one newline and thus can't use gtp_finish_response(). */
7eeb782e 3548 gtp_printf("\n");
c150f57c 3549 return GTP_OK;
7eeb782e
AT
3550}
3551
3552/* Function: Return information about the initial influence function.
3553 * Arguments: color to move, what information
3554 * Fails: never
3555 * Returns: Influence data formatted like:
3556 *
3557 * 0.51 1.34 3.20 6.60 9.09 8.06 1.96 0.00 0.00
3558 * 0.45 1.65 4.92 12.19 17.47 15.92 4.03 0.00 0.00
3559 * .
3560 * .
3561 * .
3562 * 0.00 0.00 0.00 0.00 0.00 100.00 75.53 41.47 23.41
3563 *
3564 * The available choices of information are:
3565 *
3566 * white_influence (float)
3567 * black_influence (float)
3568 * white_strength (float)
3569 * black_strength (float)
3570 * white_attenuation (float)
3571 * black_attenuation (float)
3572 * white_permeability (float)
3573 * black_permeability (float)
3574 * territory_value (float)
3575 * influence_regions (int)
3576 * non_territory (int)
3577 *
3578 * The encoding of influence_regions is as follows:
3579 * 4 white stone
3580 * 3 white territory
3581 * 2 white moyo
3582 * 1 white area
3583 * 0 neutral
3584 * -1 black area
3585 * -2 black moyo
3586 * -3 black territory
3587 * -4 black stone
3588 */
3589static int
c150f57c 3590gtp_initial_influence(char* s)
7eeb782e 3591{
c150f57c
AT
3592 int color;
3593 struct influence_data* q;
3594 int n;
7eeb782e 3595
c150f57c
AT
3596 n = gtp_decode_color(s, &color);
3597 if (n == 0)
3598 return gtp_failure("invalid color");
7eeb782e 3599
c150f57c 3600 q = INITIAL_INFLUENCE(color);
7eeb782e 3601
c150f57c 3602 silent_examine_position(EXAMINE_ALL);
7eeb782e 3603
c150f57c
AT
3604 return print_influence_data(q, s + n);
3605}
7eeb782e
AT
3606
3607/* Function: Return information about the influence function after a move.
3608 * Arguments: move, what information
3609 * Fails: never
3610 * Returns: Influence data formatted like for initial_influence.
3611 */
3612static int
c150f57c 3613gtp_move_influence(char* s)
7eeb782e 3614{
c150f57c
AT
3615 int color;
3616 int i, j;
3617 int n;
7eeb782e 3618
c150f57c
AT
3619 n = gtp_decode_move(s, &color, &i, &j);
3620 if (n == 0)
3621 return gtp_failure("invalid move");
7eeb782e 3622
c150f57c 3623 prepare_move_influence_debugging(POS(i, j), color);
7eeb782e 3624
c150f57c
AT
3625 return print_influence_data(&move_influence, s + n);
3626}
7eeb782e
AT
3627
3628/* Function: List probabilities of each move being played (when non-zero).
3629 * If no previous genmove command has been issued, the result
3630 * of this command will be meaningless.
3631 * Arguments: none
3632 * Fails: never
3633 * Returns: Move, probabilty pairs, one per row.
3634 */
3635static int
c150f57c 3636gtp_move_probabilities(char* s)
7eeb782e 3637{
c150f57c
AT
3638 float probabilities[BOARDMAX];
3639 int pos;
3640 int any_moves_printed = 0;
7eeb782e 3641
c150f57c 3642 UNUSED(s);
7eeb782e 3643
c150f57c 3644 compute_move_probabilities(probabilities);
7eeb782e 3645
c150f57c
AT
3646 gtp_start_response(GTP_SUCCESS);
3647 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
3648 if (ON_BOARD(pos) && probabilities[pos] != 0.0) {
3649 gtp_mprintf("%m ", I(pos), J(pos));
3650 gtp_printf("%.4f\n", probabilities[pos]);
3651 any_moves_printed = 1;
3652 }
7eeb782e 3653 }
7eeb782e 3654
c150f57c
AT
3655 if (!any_moves_printed)
3656 gtp_printf("\n");
7eeb782e 3657 gtp_printf("\n");
7eeb782e 3658
c150f57c 3659 return GTP_OK;
7eeb782e
AT
3660}
3661
7eeb782e
AT
3662/* Function: Return the number of bits of uncertainty in the move.
3663 * If no previous genmove command has been issued, the result
3664 * of this command will be meaningless.
3665 * Arguments: none
3666 * Fails: never
3667 * Returns: bits of uncertainty
3668 */
3669static int
c150f57c 3670gtp_move_uncertainty(char* s)
7eeb782e 3671{
c150f57c
AT
3672 float probabilities[BOARDMAX];
3673 int pos;
3674 double uncertainty = 0.0;
7eeb782e 3675
c150f57c 3676 UNUSED(s);
7eeb782e 3677
c150f57c 3678 compute_move_probabilities(probabilities);
7eeb782e 3679
c150f57c
AT
3680 gtp_start_response(GTP_SUCCESS);
3681 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
3682 if (ON_BOARD(pos) && probabilities[pos] > 0.0) {
3683 /* Shannon's formula */
3684 uncertainty += -1 * ((double)probabilities[pos]) * log((double)probabilities[pos]) / log(2.0);
3685 }
7eeb782e 3686 }
7eeb782e 3687
c150f57c 3688 gtp_printf("%.4f\n\n", uncertainty);
7eeb782e 3689
c150f57c 3690 return GTP_OK;
7eeb782e
AT
3691}
3692
7eeb782e
AT
3693/* Function: Return information about the followup influence after a move.
3694 * Arguments: move, what information
3695 * Fails: never
3696 * Returns: Influence data formatted like for initial_influence.
3697 */
3698static int
c150f57c 3699gtp_followup_influence(char* s)
7eeb782e 3700{
c150f57c
AT
3701 int color;
3702 int i, j;
3703 int n;
7eeb782e 3704
c150f57c
AT
3705 n = gtp_decode_move(s, &color, &i, &j);
3706 if (n == 0)
3707 return gtp_failure("invalid move");
7eeb782e 3708
c150f57c 3709 prepare_move_influence_debugging(POS(i, j), color);
7eeb782e 3710
c150f57c
AT
3711 return print_influence_data(&followup_influence, s + n);
3712}
7eeb782e
AT
3713
3714/* Function: Return the information in the worm data structure.
3715 * Arguments: optional vertex
3716 * Fails: never
3717 * Returns: Worm data formatted like:
3718 *
3719 * A19:
3720 * color black
3721 * size 10
3722 * effective_size 17.83
3723 * origin A19
3724 * liberties 8
3725 * liberties2 15
3726 * liberties3 10
3727 * liberties4 8
3728 * attack PASS
3729 * attack_code 0
3730 * lunch B19
3731 * defend PASS
3732 * defend_code 0
3733 * cutstone 2
3734 * cutstone2 0
3735 * genus 0
3736 * inessential 0
3737 * B19:
3738 * color white
3739 * .
3740 * .
3741 * .
3742 * inessential 0
3743 * C19:
3744 * ...
3745 *
3746 * If an intersection is specified, only data for this one will be returned.
3747 */
3748static int
c150f57c
AT
3749gtp_worm_data(char* s)
3750{
3751 int i = -1;
3752 int j = -1;
3753 int m, n;
3754
3755 if (sscanf(s, "%*c") >= 0 && !gtp_decode_coord(s, &i, &j))
3756 return gtp_failure("invalid color or coordinate");
3757
3758 silent_examine_position(EXAMINE_WORMS);
3759
3760 gtp_start_response(GTP_SUCCESS);
3761
3762 for (m = 0; m < board_size; m++)
3763 for (n = 0; n < board_size; n++)
3764 if (i == -1 || (m == i && n == j)) {
3765 struct worm_data* w = &worm[POS(m, n)];
3766 gtp_print_vertex(m, n);
3767 gtp_printf(":\n");
3768 gtp_mprintf("origin %m\n", I(w->origin), J(w->origin));
3769 gtp_mprintf("color %C\n", w->color);
3770 gtp_printf("size %d\n", w->size);
3771 gtp_printf("effective_size %.2f\n", w->effective_size);
3772 gtp_printf("liberties %d\n", w->liberties);
3773 gtp_printf("liberties2 %d\n", w->liberties2);
3774 gtp_printf("liberties3 %d\n", w->liberties3);
3775 gtp_printf("liberties4 %d\n", w->liberties4);
3776 gtp_printf("attack_code %d\n", w->attack_codes[0]);
3777 gtp_mprintf("attack_point %m\n",
3778 I(w->attack_points[0]), J(w->attack_points[0]));
3779 gtp_printf("defense_code %d\n", w->defense_codes[0]);
3780 gtp_mprintf("defense_point %m\n",
3781 I(w->defense_points[0]), J(w->defense_points[0]));
3782 gtp_mprintf("lunch %m\n",
3783 I(w->lunch), J(w->lunch));
3784 gtp_printf("cutstone %d\n", w->cutstone);
3785 gtp_printf("cutstone2 %d\n", w->cutstone2);
3786 gtp_printf("genus %d\n", w->genus);
3787 gtp_printf("inessential %d\n", w->inessential);
3788 gtp_printf("invincible %d\n", w->invincible);
3789 gtp_printf("unconditional_status %s\n",
3790 status_to_string(w->unconditional_status));
3791 }
3792
3793 gtp_printf("\n");
3794 return GTP_OK;
7eeb782e
AT
3795}
3796
3797/* Function: List the stones of a worm
3798 * Arguments: the location, "BLACK" or "WHITE"
3799 * Fails: if called on an empty or off-board location
3800 * Returns: list of stones
3801 */
3802static int
c150f57c
AT
3803gtp_worm_stones(char* s)
3804{
3805 int i = -1;
3806 int j = -1;
3807 int color = EMPTY;
3808 int m, n;
3809 int u, v;
3810 int board_empty = 1;
3811
3812 if (sscanf(s, "%*c") >= 0) {
3813 if (!gtp_decode_coord(s, &i, &j)
3814 && !gtp_decode_color(s, &color))
3815 return gtp_failure("invalid coordinate");
7eeb782e 3816 }
7eeb782e 3817
c150f57c
AT
3818 if (BOARD(i, j) == EMPTY)
3819 return gtp_failure("worm_stones called on an empty vertex");
7eeb782e 3820
c150f57c
AT
3821 gtp_start_response(GTP_SUCCESS);
3822
3823 for (u = 0; u < board_size; u++)
3824 for (v = 0; v < board_size; v++) {
3825 if (BOARD(u, v) == EMPTY
3826 || (color != EMPTY && BOARD(u, v) != color))
3827 continue;
3828 board_empty = 0;
3829 if (find_origin(POS(u, v)) != POS(u, v))
3830 continue;
3831 if (ON_BOARD2(i, j)
3832 && !same_string(POS(u, v), POS(i, j)))
3833 continue;
3834 for (m = 0; m < board_size; m++)
3835 for (n = 0; n < board_size; n++)
3836 if (BOARD(m, n) != EMPTY
3837 && same_string(POS(m, n), POS(u, v)))
3838 gtp_mprintf("%m ", m, n);
3839 gtp_printf("\n");
3840 }
3841
3842 if (board_empty)
3843 gtp_printf("\n"); /* in case no stones have been printed */
3844 gtp_printf("\n");
3845 return GTP_OK;
3846}
7eeb782e
AT
3847
3848/* Function: Return the cutstone field in the worm data structure.
3849 * Arguments: non-empty vertex
3850 * Fails: never
3851 * Returns: cutstone
3852 */
3853static int
c150f57c 3854gtp_worm_cutstone(char* s)
7eeb782e
AT
3855{
3856
c150f57c
AT
3857 int i, j;
3858 if (!gtp_decode_coord(s, &i, &j))
3859 return gtp_failure("invalid coordinate");
7eeb782e 3860
c150f57c
AT
3861 if (BOARD(i, j) == EMPTY)
3862 return gtp_failure("vertex must not be empty");
7eeb782e 3863
c150f57c 3864 silent_examine_position(EXAMINE_WORMS);
7eeb782e 3865
c150f57c 3866 return gtp_success(" %d", worm[POS(i, j)].cutstone);
7eeb782e
AT
3867}
3868
3869/* Function: Return the information in the dragon data structure.
3870 * Arguments: optional intersection
3871 * Fails: never
3872 * Returns: Dragon data formatted in the corresponding way to gtp_worm_data.
3873 */
3874static int
c150f57c 3875gtp_dragon_data(char* s)
7eeb782e 3876{
c150f57c
AT
3877 int i = -1;
3878 int j = -1;
3879 int m, n;
3880 int newline_needed = 0;
7eeb782e 3881
c150f57c
AT
3882 if (sscanf(s, "%*c") >= 0 && !gtp_decode_coord(s, &i, &j))
3883 return gtp_failure("invalid coordinate");
7eeb782e 3884
c150f57c
AT
3885 if (stackp > 0)
3886 return gtp_failure("dragon data unavailable when stackp > 0");
7eeb782e 3887
c150f57c 3888 silent_examine_position(FULL_EXAMINE_DRAGONS);
7eeb782e 3889
c150f57c 3890 gtp_start_response(GTP_SUCCESS);
7eeb782e 3891
c150f57c
AT
3892 if (ON_BOARD2(i, j) && BOARD(i, j) == EMPTY)
3893 gtp_mprintf("%m empty\n", i, j);
3894 else {
3895 newline_needed = 1;
3896 for (m = 0; m < board_size; m++)
3897 for (n = 0; n < board_size; n++)
3898 if ((m == i && n == j)
3899 || (i == -1
3900 && BOARD(m, n) != EMPTY
3901 && dragon[POS(m, n)].origin == POS(m, n))) {
3902 gtp_print_vertex(m, n);
3903 gtp_printf(":\n");
3904 report_dragon(gtp_output_file, POS(m, n));
3905 newline_needed = 0;
3906 }
3907 }
3908 if (newline_needed)
3909 gtp_printf("\n");
7eeb782e 3910 gtp_printf("\n");
c150f57c 3911 return GTP_OK;
7eeb782e
AT
3912}
3913
3914/* Function: List the stones of a dragon
3915 * Arguments: the location
3916 * Fails: if called on an empty or off-board location
3917 * Returns: list of stones
3918 */
3919static int
c150f57c
AT
3920gtp_dragon_stones(char* s)
3921{
3922 int i = -1;
3923 int j = -1;
3924 int color = EMPTY;
3925 int m, n;
3926 int u, v;
3927
3928 if (sscanf(s, "%*c") >= 0) {
3929 if (!gtp_decode_coord(s, &i, &j)
3930 && !gtp_decode_color(s, &color))
3931 return gtp_failure("invalid coordinate");
7eeb782e 3932 }
c150f57c
AT
3933
3934 if (BOARD(i, j) == EMPTY)
3935 return gtp_failure("dragon_stones called on an empty vertex");
3936
3937 silent_examine_position(EXAMINE_DRAGONS);
3938
3939 gtp_start_response(GTP_SUCCESS);
3940
3941 for (u = 0; u < board_size; u++)
3942 for (v = 0; v < board_size; v++) {
3943 if (BOARD(u, v) == EMPTY
3944 || (color != EMPTY && BOARD(u, v) != color))
3945 continue;
3946 if (dragon[POS(u, v)].origin != POS(u, v))
3947 continue;
3948 if (ON_BOARD2(i, j) && dragon[POS(i, j)].origin != POS(u, v))
3949 continue;
3950 for (m = 0; m < board_size; m++)
3951 for (n = 0; n < board_size; n++)
3952 if (dragon[POS(m, n)].origin == POS(u, v))
3953 gtp_mprintf("%m ", m, n);
3954 gtp_printf("\n");
3955 }
3956
3957 gtp_printf("\n");
3958 return GTP_OK;
7eeb782e
AT
3959}
3960
3961/* Function: Return the information in the eye data structure.
3962 * Arguments: color, vertex
3963 * Fails: never
3964 * Returns: eye data fields and values, one pair per row
3965 */
3966static int
c150f57c 3967gtp_eye_data(char* s)
7eeb782e 3968{
c150f57c
AT
3969 int color = EMPTY;
3970 int i = -1;
3971 int j = -1;
3972 struct eye_data* e;
7eeb782e 3973
c150f57c
AT
3974 if (!gtp_decode_move(s, &color, &i, &j))
3975 return gtp_failure("invalid color or coordinate");
7eeb782e 3976
c150f57c
AT
3977 if (stackp > 0)
3978 return gtp_failure("eye data unavailable when stackp > 0");
7eeb782e 3979
c150f57c 3980 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 3981
c150f57c 3982 gtp_start_response(GTP_SUCCESS);
7eeb782e 3983
c150f57c
AT
3984 if (color == BLACK)
3985 e = &black_eye[POS(i, j)];
3986 else
3987 e = &white_eye[POS(i, j)];
7eeb782e 3988
c150f57c
AT
3989 gtp_mprintf("origin %m\n", I(e->origin), J(e->origin));
3990 gtp_mprintf("color %C\n", e->color);
3991 gtp_printf("esize %d\n", e->esize);
3992 gtp_printf("msize %d\n", e->msize);
3993 gtp_printf("value %s\n", eyevalue_to_string(&e->value));
3994 gtp_printf("marginal %d\n", e->marginal);
3995 gtp_printf("neighbors %d\n", e->neighbors);
3996 gtp_printf("marginal_neighbors %d\n", e->marginal_neighbors);
3997
3998 gtp_printf("\n");
3999 return GTP_OK;
4000}
7eeb782e
AT
4001
4002/* Function: Return the information in the half eye data structure.
4003 * Arguments: vertex
4004 * Fails: never
4005 * Returns: half eye data fields and values, one pair per row
4006 */
4007static int
c150f57c 4008gtp_half_eye_data(char* s)
7eeb782e 4009{
c150f57c
AT
4010 int i = -1;
4011 int j = -1;
4012 struct half_eye_data* h;
4013 int k;
7eeb782e 4014
c150f57c
AT
4015 if (!gtp_decode_coord(s, &i, &j))
4016 return gtp_failure("invalid coordinate");
7eeb782e 4017
c150f57c
AT
4018 if (stackp > 0)
4019 return gtp_failure("half eye data unavailable when stackp > 0");
7eeb782e 4020
c150f57c 4021 silent_examine_position(EXAMINE_DRAGONS_WITHOUT_OWL);
7eeb782e 4022
c150f57c 4023 gtp_start_response(GTP_SUCCESS);
7eeb782e 4024
c150f57c 4025 h = &half_eye[POS(i, j)];
7eeb782e 4026
c150f57c
AT
4027 gtp_printf("value %.2f\n", h->value);
4028 if (h->type == HALF_EYE)
4029 gtp_printf("type HALF_EYE\n");
4030 else if (h->type == FALSE_EYE)
4031 gtp_printf("type FALSE_EYE\n");
4032 else
4033 gtp_printf("type %d\n", h->type);
4034 gtp_printf("num_attacks %d\n", h->num_attacks);
4035 for (k = 0; k < h->num_attacks; k++)
4036 gtp_mprintf("attack_point[%d] %m\n", k, I(h->attack_point[k]),
4037 J(h->attack_point[k]));
4038 gtp_printf("num_defenses %d\n", h->num_defenses);
4039 for (k = 0; k < h->num_defenses; k++)
4040 gtp_mprintf("defense_point[%d] %m\n", k, I(h->defense_point[k]),
4041 J(h->defense_point[k]));
4042
4043 gtp_printf("\n");
4044 return GTP_OK;
4045}
7eeb782e
AT
4046
4047static SGFTree gtp_sgftree;
4048
4049/* Function: Start storing moves executed during reading in an sgf
4050 * tree in memory.
4051 * Arguments: none
4052 * Fails: never
4053 * Returns: nothing
4054 *
4055 * Warning: You had better know what you're doing if you try to use this
4056 * command.
4057 */
4058static int
c150f57c 4059gtp_start_sgftrace(char* s)
7eeb782e 4060{
c150f57c
AT
4061 UNUSED(s);
4062 sgffile_begindump(&gtp_sgftree);
4063 count_variations = 1;
4064 return gtp_success("");
7eeb782e
AT
4065}
4066
7eeb782e
AT
4067/* Function: Finish storing moves in an sgf tree and write it to file.
4068 * Arguments: filename
4069 * Fails: never
4070 * Returns: nothing
4071 *
4072 * Warning: You had better know what you're doing if you try to use this
4073 * command.
4074 */
4075static int
c150f57c 4076gtp_finish_sgftrace(char* s)
7eeb782e 4077{
c150f57c
AT
4078 char filename[GTP_BUFSIZE];
4079 int nread;
7eeb782e 4080
c150f57c
AT
4081 nread = sscanf(s, "%s", filename);
4082 if (nread < 1)
4083 return gtp_failure("missing filename");
7eeb782e 4084
c150f57c
AT
4085 sgffile_enddump(filename);
4086 count_variations = 0;
4087 return gtp_success("");
4088}
7eeb782e
AT
4089
4090/* Function: Dump the current position as a static sgf file to filename,
4091 * or as output if filename is missing or "-"
4092 * Arguments: optional filename
4093 * Fails: never
4094 * Returns: nothing if filename, otherwise the sgf
4095 */
4096static int
c150f57c 4097gtp_printsgf(char* s)
7eeb782e 4098{
c150f57c
AT
4099 char filename[GTP_BUFSIZE];
4100 int nread;
4101 int next;
7eeb782e 4102
c150f57c
AT
4103 if (get_last_player() == EMPTY)
4104 next = BLACK;
4105 else
4106 next = OTHER_COLOR(get_last_player());
7eeb782e 4107
c150f57c 4108 nread = sscanf(s, "%s", filename);
7eeb782e 4109
c150f57c
AT
4110 if (nread < 1)
4111 gg_snprintf(filename, GTP_BUFSIZE, "%s", "-");
7eeb782e 4112
c150f57c
AT
4113 if (strcmp(filename, "-") == 0) {
4114 gtp_start_response(GTP_SUCCESS);
4115 sgffile_printsgf(next, filename);
4116 gtp_printf("\n");
4117 return GTP_OK;
4118 } else {
4119 sgffile_printsgf(next, filename);
4120 return gtp_success("");
4121 }
4122}
7eeb782e
AT
4123
4124/* Function: Tune the parameters for the move ordering in the tactical
4125 * reading.
4126 * Arguments: MOVE_ORDERING_PARAMETERS integers
4127 * Fails: incorrect arguments
4128 * Returns: nothing
4129 */
4130static int
c150f57c 4131gtp_tune_move_ordering(char* s)
7eeb782e 4132{
c150f57c
AT
4133 int params[MOVE_ORDERING_PARAMETERS];
4134 int k;
4135 int p;
4136 int n;
7eeb782e 4137
c150f57c
AT
4138 for (k = 0; k < MOVE_ORDERING_PARAMETERS; k++) {
4139 if (sscanf(s, "%d%n", &p, &n) == 0)
4140 return gtp_failure("incorrect arguments, expected %d integers",
4141 MOVE_ORDERING_PARAMETERS);
4142 params[k] = p;
4143 s += n;
4144 }
7eeb782e 4145
c150f57c
AT
4146 tune_move_ordering(params);
4147 return gtp_success("");
7eeb782e
AT
4148}
4149
4150/* Function: Echo the parameter
4151 * Arguments: string
4152 * Fails: never
4153 * Returns: nothing
4154 */
4155static int
c150f57c 4156gtp_echo(char* s)
7eeb782e 4157{
c150f57c 4158 return gtp_success("%s", s);
7eeb782e
AT
4159}
4160
7eeb782e
AT
4161/* Function: Echo the parameter to stdout AND stderr
4162 * Arguments: string
4163 * Fails: never
4164 * Returns: nothing
4165 */
4166static int
c150f57c 4167gtp_echo_err(char* s)
7eeb782e 4168{
c150f57c
AT
4169 fprintf(stderr, "%s", s);
4170 fflush(gtp_output_file);
4171 fflush(stderr);
4172 return gtp_success("%s", s);
7eeb782e
AT
4173}
4174
4175/* Function: List all known commands
4176 * Arguments: none
4177 * Fails: never
4178 * Returns: list of known commands, one per line
4179 *
4180 * Status: GTP version 2 standard command.
4181 */
4182static int
c150f57c 4183gtp_list_commands(char* s)
7eeb782e 4184{
c150f57c
AT
4185 int k;
4186 UNUSED(s);
7eeb782e 4187
c150f57c 4188 gtp_start_response(GTP_SUCCESS);
7eeb782e 4189
c150f57c
AT
4190 for (k = 0; commands[k].name != NULL; k++)
4191 gtp_printf("%s\n", commands[k].name);
7eeb782e 4192
c150f57c
AT
4193 gtp_printf("\n");
4194 return GTP_OK;
7eeb782e
AT
4195}
4196
7eeb782e
AT
4197/* Function: Tell whether a command is known.
4198 * Arguments: command name
4199 * Fails: never
4200 * Returns: "true" if command exists, "false" if not
4201 *
4202 * Status: GTP version 2 standard command.
4203 */
4204static int
c150f57c 4205gtp_known_command(char* s)
7eeb782e 4206{
c150f57c
AT
4207 int k;
4208 char command[GTP_BUFSIZE];
7eeb782e 4209
c150f57c
AT
4210 if (sscanf(s, "%s", command) == 1) {
4211 for (k = 0; commands[k].name != NULL; k++)
4212 if (strcmp(command, commands[k].name) == 0)
4213 return gtp_success("true");
4214 }
7eeb782e 4215
c150f57c 4216 return gtp_success("false");
7eeb782e
AT
4217}
4218
7eeb782e
AT
4219/* Function: Turn uncertainty reports from owl_attack
4220 * and owl_defend on or off.
4221 * Arguments: "on" or "off"
4222 * Fails: invalid argument
4223 * Returns: nothing
4224 */
4225static int
c150f57c 4226gtp_report_uncertainty(char* s)
7eeb782e 4227{
c150f57c
AT
4228 if (!strncmp(s, "on", 2)) {
4229 report_uncertainty = 1;
4230 return gtp_success("");
4231 }
4232 if (!strncmp(s, "off", 3)) {
4233 report_uncertainty = 0;
4234 return gtp_success("");
4235 }
4236 return gtp_failure("invalid argument");
7eeb782e 4237}
7eeb782e
AT
4238
4239static void
4240gtp_print_code(int c)
4241{
c150f57c
AT
4242 static int conversion[6] = {
4243 0, /* LOSE */
4244 3, /* KO_B */
4245 5, /* LOSS */
4246 4, /* GAIN */
4247 2, /* KO_A */
4248 1, /* WIN */
4249 };
4250 gtp_printf("%d", conversion[c]);
7eeb782e
AT
4251}
4252
4253static void
c150f57c 4254gtp_print_vertices2(int n, int* moves)
7eeb782e 4255{
c150f57c
AT
4256 int movei[MAX_BOARD * MAX_BOARD];
4257 int movej[MAX_BOARD * MAX_BOARD];
4258 int k;
4259
4260 for (k = 0; k < n; k++) {
4261 movei[k] = I(moves[k]);
4262 movej[k] = J(moves[k]);
4263 }
7eeb782e 4264
c150f57c 4265 gtp_print_vertices(n, movei, movej);
7eeb782e
AT
4266}
4267
4268/*************
4269 * transform *
4270 *************/
4271
4272static void
c150f57c 4273rotate_on_input(int ai, int aj, int* bi, int* bj)
7eeb782e 4274{
c150f57c 4275 rotate(ai, aj, bi, bj, board_size, gtp_orientation);
7eeb782e
AT
4276}
4277
4278static void
c150f57c 4279rotate_on_output(int ai, int aj, int* bi, int* bj)
7eeb782e 4280{
c150f57c 4281 inv_rotate(ai, aj, bi, bj, board_size, gtp_orientation);
7eeb782e
AT
4282}
4283
7eeb782e
AT
4284/***************
4285 * random seed *
4286 ***************/
4287
4288/* Function: Get the random seed
4289 * Arguments: none
4290 * Fails: never
4291 * Returns: random seed
4292 */
4293static int
c150f57c 4294gtp_get_random_seed(char* s)
7eeb782e 4295{
c150f57c
AT
4296 UNUSED(s);
4297 return gtp_success("%d", get_random_seed());
7eeb782e
AT
4298}
4299
4300/* Function: Set the random seed
4301 * Arguments: integer
4302 * Fails: invalid data
4303 * Returns: nothing
4304 */
4305static int
c150f57c 4306gtp_set_random_seed(char* s)
7eeb782e 4307{
c150f57c
AT
4308 int seed;
4309 if (sscanf(s, "%d", &seed) < 1)
4310 return gtp_failure("invalid seed");
7eeb782e 4311
c150f57c
AT
4312 set_random_seed(seed);
4313 return gtp_success("");
4314}
7eeb782e
AT
4315
4316/* Function: Advance the random seed by a number of games.
4317 * Arguments: integer
4318 * Fails: invalid data
4319 * Returns: New random seed.
4320 */
4321static int
c150f57c 4322gtp_advance_random_seed(char* s)
7eeb782e 4323{
c150f57c
AT
4324 int i;
4325 int games;
4326 if (sscanf(s, "%d", &games) < 1
4327 || games < 0)
4328 return gtp_failure("invalid number of games");
4329
4330 for (i = 0; i < games; i++)
4331 update_random_seed();
7eeb782e 4332
c150f57c 4333 return gtp_success("%d", get_random_seed());
7eeb782e
AT
4334}
4335
4336/***************
4337 * surrounding *
4338 ***************/
4339
4340/* Function: Determine if a dragon is surrounded
4341 * Arguments: vertex (dragon)
4342 * Fails: invalid vertex, empty vertex
4343 * Returns: 1 if surrounded, 2 if weakly surrounded, 0 if not
4344 */
4345static int
c150f57c 4346gtp_is_surrounded(char* s)
7eeb782e 4347{
c150f57c
AT
4348 int i, j;
4349 int n;
7eeb782e 4350
c150f57c
AT
4351 n = gtp_decode_coord(s, &i, &j);
4352 if (n == 0)
4353 return gtp_failure("invalid coordinate");
7eeb782e 4354
c150f57c
AT
4355 if (BOARD(i, j) == EMPTY)
4356 return gtp_failure("dragon vertex must be nonempty");
7eeb782e 4357
c150f57c
AT
4358 silent_examine_position(EXAMINE_DRAGONS);
4359 return gtp_success("%d", DRAGON2(POS(i, j)).surround_status);
7eeb782e
AT
4360}
4361
4362/* Function: Determine if a move surrounds a dragon
4363 * Arguments: vertex (move), vertex (dragon)
4364 * Fails: invalid vertex, empty (dragon, nonempty (move)
4365 * Returns: 1 if (move) surrounds (dragon)
4366 */
4367static int
c150f57c 4368gtp_does_surround(char* s)
7eeb782e 4369{
c150f57c
AT
4370 int si, sj, di, dj;
4371 int n;
7eeb782e 4372
c150f57c
AT
4373 n = gtp_decode_coord(s, &si, &sj);
4374 if (n == 0)
4375 return gtp_failure("invalid coordinate");
7eeb782e 4376
c150f57c
AT
4377 if (BOARD(si, sj) != EMPTY)
4378 return gtp_failure("move vertex must be empty");
7eeb782e 4379
c150f57c
AT
4380 n = gtp_decode_coord(s + n, &di, &dj);
4381 if (n == 0)
4382 return gtp_failure("invalid coordinate");
7eeb782e 4383
c150f57c
AT
4384 if (BOARD(di, dj) == EMPTY)
4385 return gtp_failure("dragon vertex must be nonempty");
7eeb782e 4386
c150f57c
AT
4387 silent_examine_position(EXAMINE_DRAGONS);
4388 return gtp_success("%d", does_surround(POS(si, sj), POS(di, dj)));
7eeb782e
AT
4389}
4390
4391/* Function: Report the surround map for dragon at a vertex
4392 * Arguments: vertex (dragon), vertex (mapped location)
4393 * Fails: invalid vertex, empty dragon
4394 * Returns: value of surround map at (mapped location), or -1 if
4395 * dragon not surrounded.
4396 */
4397
4398static int
c150f57c 4399gtp_surround_map(char* s)
7eeb782e 4400{
c150f57c
AT
4401 int di, dj, mi, mj;
4402 int n;
7eeb782e 4403
c150f57c
AT
4404 n = gtp_decode_coord(s, &di, &dj);
4405 if (n == 0)
4406 return gtp_failure("invalid coordinate");
7eeb782e 4407
c150f57c
AT
4408 if (BOARD(di, dj) == EMPTY)
4409 return gtp_failure("dragon vertex must not be empty");
7eeb782e 4410
c150f57c
AT
4411 n = gtp_decode_coord(s + n, &mi, &mj);
4412 if (n == 0)
4413 return gtp_failure("invalid coordinate");
7eeb782e 4414
c150f57c
AT
4415 silent_examine_position(EXAMINE_DRAGONS);
4416 return gtp_success("%d", surround_map(POS(di, dj), POS(mi, mj)));
7eeb782e
AT
4417}
4418
4419/***************
4420 * search area *
4421 ***************/
4422
4423/* Function: limit search, and establish a search diamond
4424 * Arguments: pos
4425 * Fails: invalid value
4426 * Returns: nothing
4427 */
4428static int
c150f57c 4429gtp_set_search_diamond(char* s)
7eeb782e 4430{
c150f57c
AT
4431 int i, j;
4432
4433 if (!gtp_decode_coord(s, &i, &j))
4434 return gtp_failure("invalid coordinate");
7eeb782e 4435
c150f57c
AT
4436 set_limit_search(1);
4437 set_search_diamond(POS(i, j));
4438 return gtp_success("");
7eeb782e
AT
4439}
4440
4441/* Function: unmark the entire board for limited search
4442 * Arguments: none
4443 * Fails: never
4444 * Returns: nothing
4445 */
4446static int
c150f57c 4447gtp_reset_search_mask(char* s)
7eeb782e 4448{
c150f57c 4449 UNUSED(s);
7eeb782e 4450
c150f57c
AT
4451 reset_search_mask();
4452 return gtp_success("");
7eeb782e 4453}
c150f57c 4454
7eeb782e
AT
4455/* Function: sets the global variable limit_search
4456 * Arguments: value
4457 * Fails: invalid arguments
4458 * Returns: nothing
4459 */
4460static int
c150f57c 4461gtp_limit_search(char* s)
7eeb782e 4462{
c150f57c 4463 int value;
7eeb782e 4464
c150f57c
AT
4465 if (sscanf(s, "%d", &value) < 1)
4466 return gtp_failure("invalid value for search limit");
4467 set_limit_search(value);
4468 return gtp_success("");
7eeb782e
AT
4469}
4470
4471/* Function: mark a vertex for limited search
4472 * Arguments: position
4473 * Fails: invalid arguments
4474 * Returns: nothing
4475 */
4476static int
c150f57c 4477gtp_set_search_limit(char* s)
7eeb782e 4478{
c150f57c 4479 int i, j;
7eeb782e 4480
c150f57c
AT
4481 gtp_decode_coord(s, &i, &j);
4482 set_search_mask(POS(i, j), 1);
4483 return gtp_success("");
7eeb782e 4484}
c150f57c 4485
7eeb782e
AT
4486/* Function: Draw search area. Writes to stderr.
4487 * Arguments: none
4488 * Fails: never
4489 * Returns: nothing
4490 */
4491static int
c150f57c 4492gtp_draw_search_area(char* s)
7eeb782e 4493{
c150f57c 4494 UNUSED(s);
7eeb782e 4495
c150f57c
AT
4496 gtp_start_response(GTP_SUCCESS);
4497 gtp_printf("\n");
4498 draw_search_area();
4499 return gtp_finish_response();
7eeb782e
AT
4500}
4501
7eeb782e
AT
4502/*
4503 * Local Variables:
c150f57c
AT
4504 * tab-width: 4
4505 * c-basic-offset: 4
7eeb782e
AT
4506 * End:
4507 */