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