Updated README: Equal sign not required with `--mode` flag.
[sgk-go] / engine / readconnect.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 <stdlib.h>
28#include <stdarg.h>
29#include <string.h>
30#include <math.h>
31
32#include "liberty.h"
33#include "cache.h"
34#include "gg_utils.h"
35#include "readconnect.h"
36
37/* Size of array where candidate moves are stored. */
38#define MAX_MOVES 362
39
40/* trace of a search */
41
42typedef struct _zone {
43 int array[BOARDMAX];
44 unsigned int bits[1+BOARDMAX/32];
45 int i;
46} zone;
47
48static int recursive_connect2(int str1, int str2, int *move,
49 int has_passed);
50static int recursive_disconnect2(int str1, int str2, int *move,
51 int has_passed);
52static int recursive_break(int str, const signed char goal[BOARDMAX],
53 int *move, int has_passed, Hash_data *goal_hash);
54static int recursive_block(int str, const signed char goal[BOARDMAX],
55 int *move, int has_passed, Hash_data *goal_hash);
56
57static int add_array(int *array, int elt);
58static int element_array(int *array, int elt);
59static void intersection_array(int *array1, int *array2);
60static int snapback(int str);
61static int connection_one_move(int str1, int str2);
62static int prevent_connection_one_move(int *moves, int str1, int str2);
63static int connected_one_move(int str1, int str2);
64static int moves_to_connect_in_two_moves(int *moves, int str1, int str2);
65static int connection_two_moves(int str1, int str2);
66static int prevent_connection_two_moves(int *moves, int str1, int str2);
67#if 0
68static int connected_two_moves(int str1, int str2);
69#endif
70static int moves_to_connect_in_three_moves(int *moves, int str1, int str2,
71 int does_connect);
72#if 0
73static int simple_connection_three_moves(int str1, int str2);
74static int prevent_simple_connection_three_moves(int *moves,
75 int str1, int str2);
76#endif
77
78static int recursive_connect(int str1, int str2, int *move);
79static int recursive_disconnect(int str1, int str2, int *move);
80
81static int quiescence_connect(int str1, int str2, int *move);
82static int quiescence_capture(int str, int *move);
83/* static int capture_one_move(int str); */
84static int prevent_capture_one_move(int *moves, int str1);
85static int recursive_transitivity(int str1, int str2, int str3, int *move);
86static int recursive_non_transitivity(int str1, int str2, int str3, int *move);
87static void order_connection_moves(int *moves, int str1, int str2,
88 int color_to_move, const char *funcname);
89
90static int nodes_connect = 0;
91
92/* Used by alternate connections. */
93static signed char connection_shadow[BOARDMAX];
94
95static signed char breakin_shadow[BOARDMAX];
96
97/* Statistics. */
98static int global_connection_node_counter = 0;
99
100static void
101init_zone(zone *zn)
102{
103 zn->array[0] = 0;
104 memset(zn->bits, 0, 1 + BOARDMAX / 8);
105}
106
107/* send back 1 if the intersection is in the zone
108 */
109
110#if 0
111static int
112elt_zone(zone *zn, int elt)
113{
114 if ((zn->bits[elt >> 5] >> (elt & 31)) & 1)
115 return 1;
116 return 0;
117}
118#endif
119
120/* Adds an intersection to a zone
121 */
122
123static void
124add_zone(zone *zn, int elt)
125{
126 if (((zn->bits[elt >> 5] >> (elt & 31)) & 1) == 0) {
127 zn->bits[elt >> 5] |= (1 << (elt & 31));
128 zn->array[0]++;
129 zn->array[zn->array[0]] = elt;
130 }
131}
132
133/* start to loop over a zone
134 */
135
136#if 0
137static int
138start_zone(zone *zn)
139{
140 if (zn->array[0] < 1)
141 return -1;
142 zn->i = 1;
143 return zn->array[1];
144}
145#endif
146
147/* continue to loop over a zone
148 */
149
150#if 0
151static int
152next_zone(zone *zn)
153{
154 zn->i++;
155 if (zn->i > zn->array[0])
156 return -1;
157 return zn->array[zn->i];
158}
159#endif
160
161/* only keep the elements of zn1 which are also in zn2 */
162
163#if 0
164static void
165intersection_zone(zone *zn1, zone *zn2)
166{
167 int r, s;
168
169 for (r = start_zone(zn1); r > -1; r = next_zone(zn1))
170 if (!elt_zone(zn2, r)) {
171 for (s = r; s < zn1->array[0]; s++)
172 zn1->array[s] = zn1->array[s+1];
173 zn1->bits[r >> 5] &= ~ (1 << (r & 31));
174 zn1->array[0]--;
175 zn1->i--;
176 }
177}
178#endif
179
180/* Adds an integer to an array of integers if it is not already there.
181 * The number of elements of the array is in array[0].
182 */
183
184static int
185add_array(int *array, int elt)
186{
187 int r;
188
189 for (r = 1; r < array[0] + 1; r++)
190 if (array[r] == elt)
191 return 0;
192
193 array[0]++;
194 array[array[0]] = elt;
195 return 1;
196}
197
198/* test if an element is part of an array */
199
200static int
201element_array(int *array, int elt)
202{
203 int r;
204 for (r = 1; r < array[0] + 1; r++)
205 if (array[r] == elt)
206 return 1;
207 return 0;
208}
209
210/* only keep the elements of array1 which are also in array2 */
211
212static void
213intersection_array(int *array1, int *array2)
214{
215 int r, s;
216
217 for (r = 1; r < array1[0] + 1; r++)
218 if (!element_array(array2, array1[r])) {
219 for (s = r; s < array1[0]; s++)
220 array1[s] = array1[s+1];
221 array1[0]--;
222 r--;
223 }
224}
225
226/* verifies that capturing the stone at str is not a snapback */
227
228static int
229snapback(int str)
230{
231 int stones, liberties, lib;
232 SGFTree *save_sgf_dumptree = sgf_dumptree;
233
234 /* if more than one stone captured, not a snapback */
235 stones = countstones(str);
236 if (stones > 1)
237 return 0;
238
239 /* if more than one liberty, not a snapback */
240 liberties = findlib(str, 1, &lib);
241 if (liberties > 1)
242 return 0;
243
244 /* turn off the sgf traces
245 */
246 sgf_dumptree = NULL;
247
248 /* if only one liberty after capture */
249 if (trymove(lib, OTHER_COLOR(board[str]), "snapback", str)) {
250 liberties = 0;
251 if (IS_STONE(board[lib]))
252 liberties = countlib(lib);
253 popgo();
254 sgf_dumptree = save_sgf_dumptree;
255 if (liberties > 1)
256 return 0;
257 return WIN;
258 }
259
260 /* Turn the sgf traces back on. */
261 sgf_dumptree = save_sgf_dumptree;
262
263 return 0;
264}
265
266/* connection by playing and finding a ponnuki after play */
267
268static int
269ponnuki_connect(int *moves, int str1, int str2, zone *zn)
270{
271 int r, s, k, res = 0;
272 int liberties, libs[MAXLIBS];
273 int adj, adjs[MAXCHAIN];
274 int neighb, neighbs[MAXCHAIN];
275
276 /* finds connection through two forbidden liberties for
277 * the opponent
278 * + + + + + + +
279 * + + @ O O @ +
280 * + @ + @ @ x +
281 * + + @ + + + +
282 * - - - - - - -
283 *
284 * + + + + + + +
285 * + + @ O O @ +
286 * + @ + @ @ O @
287 * + + @ + + x +
288 * - - - - - - -
289 */
290 liberties = findlib(str1, MAXLIBS, libs);
291 for (r = 0; r < liberties; r++)
292 if (is_self_atari(libs[r], OTHER_COLOR(board[str1])))
293 for (k = 0; k < 4; k++) {
294 int pos = libs[r] + delta[k];
295 if (board[pos] == board[str1]
296 && !same_string(pos, str1)
297 && !same_string(pos, str2)) {
298 /* try to connect pos to str2 in one move */
299 /* play a common liberty */
300 neighb = findlib(pos, MAXLIBS, neighbs);
301 for (s = 0; s < neighb; s++)
302 if (liberty_of_string(neighbs[s], str2)) {
303 res = 1;
304 add_zone(zn, libs[r]);
305 add_zone(zn, neighbs[s]);
306 add_array(moves, neighbs[s]);
307 }
308 /* or capture a common adjacent string */
309 adj = chainlinks2(pos, adjs, 1);
310 for (s = 0; s < adj; s++)
311 if (adjacent_strings(adjs[s], str2)
312 && !snapback(adjs[s])) {
313 res = 1;
314 neighb = findlib(adjs[s], 1, neighbs);
315 add_zone(zn, libs[r]);
316 add_zone(zn, neighbs[0]);
317 add_array(moves, neighbs[0]);
318 }
319 }
320 }
321
322 return res;
323}
324
325/* connection in one move, finds all moves and memorizes intersections
326 * involved in the connection.
327 */
328
329static int
330moves_connection_one_move(int *moves, int str1, int str2, zone *zn)
331{
332 int r;
333 int adj, adjs[MAXCHAIN];
334
335 /* If one string is missing we have already failed. */
336 if (board[str1] == EMPTY || board[str2] == EMPTY)
337 return 0;
338
339 /* Common liberties. */
340 if (have_common_lib(str1, str2, NULL))
341 return WIN;
342
343 /* Common adjacent string in atari, more than one stone, no snapback. */
344 adj = chainlinks2(str1, adjs, 1);
345 for (r = 0; r < adj; r++)
346 if (adjacent_strings(adjs[r], str2)
347 && !snapback(adjs[r]))
348 return WIN;
349
350 /* Connections through a ponnuki */
351 if (ponnuki_connect(moves, str1, str2, zn))
352 return WIN;
353 if (ponnuki_connect(moves, str2, str1, zn))
354 return WIN;
355
356 return 0;
357}
358
359/* Verifies that the strings str1 and str2 can be connected
360 * directly by playing one move, either by playing a common liberty
361 * of the two strings, or by capturing a common adjacent string.
362 *
363 * This is the gi1 game function.
364 */
365
366static int
367connection_one_move(int str1, int str2)
368{
369 int moves[BOARDMAX];
370 zone zn;
371 init_zone(&zn);
372 moves[0] = 0;
373 return moves_connection_one_move(moves, str1, str2, &zn);
374}
375
376/* If the two strings str1 and str2 can be connected sends back WIN fill the
377 * array moves with the only move that can prevent a connection in one move
378 * (common liberties, liberties of common adjacent strings in atari).
379 *
380 * This is the ip1 game function. */
381
382static int
383prevent_connection_one_move(int *moves, int str1, int str2)
384{
385 int r, s;
386 int libs[MAXLIBS];
387 int adj, adjs[MAXCHAIN];
388 int adjadj, adjadjs[MAXCHAIN];
389
390 /* Common liberties. */
391 if (have_common_lib(str1, str2, libs)) {
392 add_array(moves, libs[0]);
393 return WIN;
394 }
395
396 /* Save a common adjacent string in atari, more than one stone, no snapback.
397 */
398 adj = chainlinks2(str1, adjs, 1);
399 for (r = 0; r < adj; r++)
400 if (adjacent_strings(adjs[r], str2)
401 && !snapback(adjs[r])) {
402 findlib(adjs[r], MAXLIBS, libs);
403 add_array(moves, libs[0]);
404 adjadj = chainlinks2(adjs[r], adjadjs, 1);
405 for (s = 0; s < adjadj; s++) {
406 findlib(adjadjs[s], MAXLIBS, libs);
407 add_array(moves, libs[0]);
408 }
409 return WIN;
410 }
411
412 return 0;
413}
414
415/* Returns WIN if str1 and str2 are connected in at most
416 * one move even if the opponent plays first.
417 * Verify that the strings are connectable in one move
418 * and find the only possible moves that can prevent
419 * using prevent_connection_one_move. If none of these
420 * moves works, the two strings are connected.
421 *
422 * This is the g1 game function.
423 */
424
425static int
426connected_one_move(int str1, int str2)
427{
428 int r, res = 0;
429 int moves[MAX_MOVES];
430 SGFTree *save_sgf_dumptree = sgf_dumptree;
431
432 /* turn off the sgf traces
433 */
434 sgf_dumptree = NULL;
435
436 moves[0] = 0;
437 if (prevent_connection_one_move(moves, str1, str2)) {
438 order_connection_moves(moves, str1, str2, OTHER_COLOR(board[str1]),
439 "connected_one_move");
440 res = WIN;
441 for (r = 1; ((r < moves[0] + 1) && res); r++) {
442 if (trymove(moves[r], OTHER_COLOR(board[str1]),
443 "connected_one_move", str1)) {
444 if (!connection_one_move(str1, str2))
445 res = 0;
446 popgo();
447 }
448 }
449 }
450
451 /* Turn the sgf traces back on. */
452 sgf_dumptree = save_sgf_dumptree;
453
454 return res;
455}
456
457/* Find the moves that might be able to connect in less than three plies.
458 * That is moves that can connect the strings if another move of the same
459 * color is played just after:
460 * - common liberties of the two strings;
461 * - moves on the liberties of an opponent string with less than two
462 * liberties adjacent to both strings, or adjacent to one string and
463 * that has a common liberty with the second string;
464 * - liberties of one string that are second order liberties of the
465 * other string.
466 *
467 * Returns WIN if a direct connection has been found. Returns 0
468 * otherwise.
469 */
470
471static int
472moves_to_connect_in_two_moves(int *moves, int str1, int str2)
473{
474 int r, s, common_adj_liberty;
475 int liberties, libs[MAXLIBS];
476 int adj, adjs[MAXCHAIN];
477 int adjadj, adjadjs[MAXCHAIN];
478 int k;
479 int color = board[str1];
480 int move;
481
482 /* Common liberties. */
483 if (have_common_lib(str1, str2, libs)) {
484 add_array(moves, libs[0]);
485 return 1;
486 }
487
488 /* Capture a common adjacent string or an adjacent liberty of str1
489 * that has a common liberty with str2...
490 */
491 adj = chainlinks3(str1, adjs, 2);
492 for (r = 0; r < adj; r++) {
493 liberties = findlib(adjs[r], MAXLIBS, libs);
494 common_adj_liberty = 0;
495 for (s = 0; s < liberties; s++)
496 if (liberty_of_string(libs[s], str2))
497 common_adj_liberty = 1;
498 if (common_adj_liberty || adjacent_strings(adjs[r], str2)) {
499 for (s = 0; s < liberties; s++)
500 add_array(moves, libs[s]);
501 adjadj = chainlinks2(adjs[r], adjadjs, 1);
502 for (s = 0; s < adjadj; s++) {
503 findlib(adjadjs[s], MAXLIBS, libs);
504 add_array(moves, libs[0]);
505 }
506 }
507 }
508
509 /* ...and vice versa. */
510 adj = chainlinks3(str2, adjs, 2);
511 for (r = 0; r < adj; r++) {
512 liberties = findlib(adjs[r], MAXLIBS, libs);
513 common_adj_liberty = 0;
514 for (s = 0; s < liberties; s++)
515 if (liberty_of_string(libs[s], str1))
516 common_adj_liberty = 1;
517 if (common_adj_liberty || adjacent_strings(adjs[r], str1)) {
518 for (s = 0; s < liberties; s++)
519 add_array(moves, libs[s]);
520 adjadj = chainlinks2(adjs[r], adjadjs, 1);
521 for (s = 0; s < adjadj; s++) {
522 findlib(adjadjs[s], MAXLIBS, libs);
523 add_array(moves, libs[0]);
524 }
525 }
526 }
527
528 /* Liberties of str1 that are second order liberties of str2 and
529 * vice versa.
530 */
531 liberties = findlib(str1, MAXLIBS, libs);
532 for (r = 0; r < liberties; r++) {
533 if (board[SOUTH(libs[r])] == EMPTY) {
534 if (liberty_of_string(SOUTH(libs[r]), str2)) {
535 add_array(moves, libs[r]);
536 add_array(moves, SOUTH(libs[r]));
537 }
538 }
539
540 if (board[WEST(libs[r])] == EMPTY) {
541 if (liberty_of_string(WEST(libs[r]), str2)) {
542 add_array(moves, libs[r]);
543 add_array(moves, WEST(libs[r]));
544 }
545 }
546
547 if (board[NORTH(libs[r])] == EMPTY) {
548 if (liberty_of_string(NORTH(libs[r]), str2)) {
549 add_array(moves, libs[r]);
550 add_array(moves, NORTH(libs[r]));
551 }
552 }
553
554 if (board[EAST(libs[r])] == EMPTY) {
555 if (liberty_of_string(EAST(libs[r]), str2)) {
556 add_array(moves, libs[r]);
557 add_array(moves, EAST(libs[r]));
558 }
559 }
560 }
561
562 /* Liberties of str1 which are adjacent to a friendly string with
563 * common liberty with str2.
564 */
565 liberties = findlib(str1, MAXLIBS, libs);
566 for (r = 0; r < liberties; r++) {
567 for (k = 0; k < 4; k++) {
568 int pos = libs[r] + delta[k];
569 if (board[pos] == color
570 && !same_string(pos, str1)
571 && quiescence_connect(pos, str2, &move)) {
572 add_array(moves, libs[r]);
573 add_array(moves, move);
574 }
575 }
576 }
577
578 /* And vice versa. */
579 liberties = findlib(str2, MAXLIBS, libs);
580 for (r = 0; r < liberties; r++) {
581 for (k = 0; k < 4; k++) {
582 int pos = libs[r] + delta[k];
583 if (board[pos] == color
584 && !same_string(pos, str2)
585 && quiescence_connect(pos, str1, &move)) {
586 add_array(moves, libs[r]);
587 add_array(moves, move);
588 }
589 }
590 }
591
592 return 0;
593}
594
595/* Tests if the strings can be connected in three plies starts
596 * with finding the possible moves that can connect. If two
597 * moves in a row are played, then try them and stops at the
598 * first working move. The strings are connected in two moves
599 * if the function connected_one_move is verified after a move.
600 *
601 * This is the gi2 game function.
602 */
603
604static int
605connection_two_moves(int str1, int str2)
606{
607 int r, res = 0, moves[MAX_MOVES];
608 SGFTree *save_sgf_dumptree = sgf_dumptree;
609
610 /* If one string is missing we have already failed. */
611 if (board[str1] == EMPTY || board[str2] == EMPTY)
612 return 0;
613
614 moves[0] = 0;
615 if (moves_to_connect_in_two_moves(moves, str1, str2))
616 return WIN;
617 order_connection_moves(moves, str1, str2, board[str1],
618 "connection_two_moves");
619
620 /* turn off the sgf traces
621 */
622 sgf_dumptree = NULL;
623
624 for (r = 1; ((r < moves[0] + 1) && !res); r++) {
625 if (trymove(moves[r], board[str1], "connection_two_moves", str1)) {
626 if (connected_one_move(str1, str2))
627 res = WIN;
628 popgo();
629 }
630 }
631
632 sgf_dumptree = save_sgf_dumptree;
633
634 return res;
635}
636
637/* Find the complete set of possible moves that can prevent
638 * a connection in three plies.
639 *
640 * The function is not yet written, but moves_to_connect_in_two_moves does
641 * a similar job, so it is called temporarly.
642 */
643
644static int
645moves_to_prevent_connection_in_two_moves(int *moves, int str1, int str2)
646{
647 if (moves_to_connect_in_two_moves(moves, str1, str2))
648 return 1;
649 return 0;
650}
651
652/* Find all the moves that prevent to connect in a three plies
653 * deep search and put them in the moves array. Returns 0 if
654 * there is no three plies connection, or else it tries all the
655 * possible preventing moves. If after a possible preventing
656 * moves, there no connection in one move and no connection in
657 * two moves, then the moves prevents a three plies deep
658 * connection, and it is added to the moves array.
659 *
660 * this is the ip2 game function */
661
662static int
663prevent_connection_two_moves(int *moves, int str1, int str2)
664{
665 int r, res = 0;
666 int possible_moves[MAX_MOVES];
667 SGFTree *save_sgf_dumptree = sgf_dumptree;
668
669 /* turn off the sgf traces
670 */
671 sgf_dumptree = NULL;
672
673 if (connection_two_moves(str1, str2)) {
674 res = WIN;
675 possible_moves[0] = 0;
676 moves_to_prevent_connection_in_two_moves(possible_moves, str1, str2);
677 order_connection_moves(possible_moves, str1, str2,
678 OTHER_COLOR(board[str1]),
679 "prevent_connection_two_moves");
680 for (r = 1; r < possible_moves[0] + 1; r++) {
681 if (trymove(possible_moves[r], OTHER_COLOR(board[str1]),
682 "prevent_connection_two_moves", str1)) {
683 if (!connection_one_move(str1, str2))
684 if (!connection_two_moves(str1, str2))
685 add_array(moves, possible_moves[r]);
686 popgo();
687 }
688 }
689 }
690
691 sgf_dumptree = save_sgf_dumptree;
692
693 return res;
694}
695
696/* Only partially written.
697 *
698 * Find all the moves than can connect if two subsequent
699 * moves of the same color are played after
700 * - common liberties;
701 * - liberties of common adjacent strings with 3 liberties or less;
702 * - liberties of adjacent strings with 2 liberties or less that have
703 * liberties that are second order liberties of the other string;
704 * - liberties of one string that are second order liberties of the
705 * other string;
706 * - second order liberties of the first string that are second order
707 * liberties of the other string;
708 *
709 * A function that computes the second order liberties of a string is
710 * needed as well as a function that checks efficiently if an
711 * intersection is a second order liberty of a given string.
712 *
713 * If does_connect is 1, generate moves to connect, otherwise generate
714 * moves to disconnect.
715 */
716
717static int
718moves_to_connect_in_three_moves(int *moves, int str1, int str2,
719 int does_connect)
720{
721 int r, s;
722 int liberties, libs[MAXLIBS];
723 int liberties2, libs2[MAXLIBS];
724 int adj, adjs[MAXCHAIN];
725 int adjadj, adjadjs[MAXCHAIN];
726 int move;
727 int k;
728 int pos;
729 int secondlib1[BOARDMAX];
730 int secondlib2[BOARDMAX];
731
732 if (moves_to_connect_in_two_moves(moves, str1, str2))
733 return 1;
734
735 /* Find second order liberties of str1. */
736 memset(secondlib1, 0, sizeof(secondlib1));
737 liberties = findlib(str1, MAXLIBS, libs);
738 for (r = 0; r < liberties; r++)
739 for (k = 0; k < 4; k++) {
740 pos = libs[r] + delta[k];
741 if (board[pos] == EMPTY)
742 secondlib1[pos] = 1;
743 else if (board[pos] == board[str1]) {
744 liberties2 = findlib(pos, MAXLIBS, libs2);
745 for (s = 0; s < liberties2; s++)
746 secondlib1[libs2[s]] = 1;
747 }
748 }
749
750 /* Find second order liberties of str2.
751 */
752 memset(secondlib2, 0, sizeof(secondlib2));
753 liberties = findlib(str2, MAXLIBS, libs);
754 for (r = 0; r < liberties; r++)
755 for (k = 0; k < 4; k++) {
756 pos = libs[r] + delta[k];
757 if (board[pos] == EMPTY)
758 secondlib2[pos] = 1;
759 else if (board[pos] == board[str2]) {
760 liberties2 = findlib(pos, MAXLIBS, libs2);
761 for (s = 0; s < liberties2; s++)
762 secondlib2[libs2[s]] = 1;
763 }
764 }
765
766 /* Second order liberties of str1 that are second order liberties
767 * of str2 and vice versa.
768 */
769 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
770 if (secondlib1[pos] && secondlib2[pos])
771 add_array(moves, pos);
772 }
773
774 /* Capture a neighbor of str1 which is in atari. The captured string
775 * must in turn have a neighbor which can connect to str2 easily.
776 */
777 adj = chainlinks2(str1, adjs, 1);
778 for (r = 0; r < adj; r++) {
779 adjadj = chainlinks(adjs[r], adjadjs);
780 for (s = 0; s < adjadj; s++) {
781 if (!same_string(adjadjs[s], str1)
782 && quiescence_connect(adjadjs[s], str2, &move)) {
783 findlib(adjs[r], 1, libs);
784 add_array(moves, libs[0]);
785 add_array(moves, move);
786 }
787 }
788 }
789
790 /* And vice versa. */
791 adj = chainlinks2(str2, adjs, 1);
792 for (r = 0; r < adj; r++) {
793 adjadj = chainlinks(adjs[r], adjadjs);
794 for (s = 0; s < adjadj; s++) {
795 if (!same_string(adjadjs[s], str2)
796 && quiescence_connect(adjadjs[s], str1, &move)) {
797 findlib(adjs[r], 1, libs);
798 add_array(moves, libs[0]);
799 add_array(moves, move);
800 }
801 }
802 }
803
804 /* Liberties of neighbor of str1 with at most two liberties, which
805 * are second order liberties of str2.
806 */
807 adj = chainlinks3(str1, adjs, 2);
808 for (r = 0; r < adj; r++) {
809 liberties = findlib(adjs[r], 2, libs);
810 for (s = 0; s < liberties; s++)
811 if (second_order_liberty_of_string(libs[s], str2))
812 add_array(moves, libs[s]);
813 }
814
815 /* And vice versa. */
816 adj = chainlinks3(str2, adjs, 2);
817 for (r = 0; r < adj; r++) {
818 liberties = findlib(adjs[r], 2, libs);
819 for (s = 0; s < liberties; s++)
820 if (second_order_liberty_of_string(libs[s], str1))
821 add_array(moves, libs[s]);
822 }
823
824 /* Move in on a three liberty opponent string which is adjacent to
825 * str1 and has a liberty in common with str2.
826 */
827 adj = chainlinks2(str1, adjs, 3);
828 for (r = 0; r < adj; r++) {
829 if (have_common_lib(adjs[r], str2, NULL)) {
830 liberties = findlib(adjs[r], 3, libs);
831 for (s = 0; s < liberties; s++) {
832 /* If generating a connecting move, require the liberty to be
833 * no further than diagonal to a second order liberty of one
834 * of the strings.
835 */
836 for (k = 0; k < 8; k++) {
837 if (!does_connect
838 || (ON_BOARD(libs[s] + delta[k])
839 && (secondlib1[libs[s] + delta[k]]
840 || secondlib2[libs[s] + delta[k]]))) {
841 add_array(moves, libs[s]);
842 break;
843 }
844 }
845 }
846 }
847 }
848
849 /* And vice versa. */
850 adj = chainlinks2(str2, adjs, 3);
851 for (r = 0; r < adj; r++) {
852 if (have_common_lib(adjs[r], str1, NULL)) {
853 liberties = findlib(adjs[r], 3, libs);
854 for (s = 0; s < liberties; s++) {
855 /* If generating a connecting move, require the liberty to be
856 * no further than diagonal to a second order liberty of one
857 * of the strings.
858 */
859 for (k = 0; k < 8; k++) {
860 if (!does_connect
861 || (ON_BOARD(libs[s] + delta[k])
862 && (secondlib1[libs[s] + delta[k]]
863 || secondlib2[libs[s] + delta[k]]))) {
864 add_array(moves, libs[s]);
865 break;
866 }
867 }
868 }
869 }
870 }
871
872 return 0;
873}
874
875
876/* Not yet written.
877 *
878 * Find the complete set of possible moves that can prevent
879 * a connection in 5 plies.
880 */
881
882static int
883moves_to_prevent_connection_in_three_moves(int *moves, int str1, int str2)
884{
885 if (moves_to_connect_in_three_moves(moves, str1, str2, 0))
886 return 1;
887 return 0;
888}
889
890/*
891 * The simplest depth 4 connection:
892 *
893 * If there are forced moves to prevent connection in one move,
894 * try them, and verify that they all lead to a depth 1 or
895 * depth 3 connection.
896 *
897 * This is the g211 game function.
898 */
899
900static int
901simply_connected_two_moves(int str1, int str2)
902{
903 int r, res = 0;
904 int moves[MAX_MOVES];
905 SGFTree *save_sgf_dumptree = sgf_dumptree;
906
907 /* turn off the sgf traces
908 */
909 sgf_dumptree = NULL;
910
911
912 /* If one string is missing we have already failed. */
913 if (board[str1] == EMPTY || board[str2] == EMPTY)
914 return 0;
915
916 moves[0] = 0;
917 if (prevent_connection_one_move(moves, str1, str2)) {
918 res = WIN;
919 order_connection_moves(moves, str1, str2, OTHER_COLOR(board[str1]),
920 "simply_connected_two_moves");
921 for (r = 1; ((r < moves[0] + 1) && res); r++) {
922 if (trymove(moves[r], OTHER_COLOR(board[str1]),
923 "simply_connected_two_moves", str1)) {
924 if (!connection_one_move(str1, str2))
925 if (!connection_two_moves(str1, str2))
926 res = 0;
927 popgo();
928 }
929 }
930 }
931
932 sgf_dumptree = save_sgf_dumptree;
933
934 return res;
935}
936
937/* Test if a move is a simple depth 5 connection.
938 *
939 * This is the gi311 game function.
940 */
941
942static int
943simple_connection_three_moves(int str1, int str2)
944{
945 int r, res = 0, moves[MAX_MOVES];
946 SGFTree *save_sgf_dumptree = sgf_dumptree;
947
948 /* turn off the sgf traces
949 */
950 sgf_dumptree = NULL;
951
952
953 moves[0] = 0;
954 if (moves_to_connect_in_two_moves(moves, str1, str2))
955 return WIN;
956 order_connection_moves(moves, str1, str2, board[str1],
957 "simple_connection_three_moves");
958 for (r = 1; ((r < moves[0] + 1) && !res); r++) {
959 if (trymove(moves[r], board[str1],
960 "simple_connection_three_moves", str1)) {
961 if (simply_connected_two_moves(str1, str2))
962 res = WIN;
963 popgo();
964 }
965 }
966
967 sgf_dumptree = save_sgf_dumptree;
968
969 return res;
970}
971
972/* Find the forced moves that prevent a simple depth 5 connection.
973 * Fills the array moves with the forced moves.
974 *
975 * This is the ip311 game function.
976 *
977 * It finds moves in very important situations such as:
978 *
979 * + + + O + +
980 * + @ @ O + +
981 * + @ O @ @ +
982 * + @ O + + +
983 * + + + + + +
984 * - - - - - -
985 *
986 * and enables recursive_disconnect to prove the two black
987 * strings are connected in these situations.
988 */
989
990static int
991prevent_simple_connection_three_moves(int *moves, int str1, int str2)
992{
993 int r, res = 0;
994 int possible_moves[MAX_MOVES];
995 SGFTree *save_sgf_dumptree = sgf_dumptree;
996
997 /* turn off the sgf traces
998 */
999 sgf_dumptree = NULL;
1000
1001
1002 if (simple_connection_three_moves(str1, str2)) {
1003 res = WIN;
1004 possible_moves[0] = 0;
1005 moves_to_prevent_connection_in_three_moves(possible_moves, str1, str2);
1006 order_connection_moves(moves, str1, str2, OTHER_COLOR(board[str1]),
1007 "prevent_simple_connection_three_moves");
1008 for (r = 1; r < possible_moves[0] + 1; r++) {
1009 if (trymove(possible_moves[r], OTHER_COLOR(board[str1]),
1010 "prevent_simple_connection_three_moves", str1)) {
1011 if (!connection_one_move(str1, str2))
1012 if (!connection_two_moves(str1, str2))
1013 if (!simple_connection_three_moves(str1, str2))
1014 add_array(moves, possible_moves[r]);
1015 popgo();
1016 }
1017 }
1018 }
1019
1020 sgf_dumptree = save_sgf_dumptree;
1021
1022 return res;
1023}
1024
1025/* Find simple connections by looking at common liberties
1026 * or directly capturing a common adjacent string without a snapback
1027 * or looking at a ladder for a common adjacent string.
1028 */
1029
1030static int
1031quiescence_connect(int str1, int str2, int *move)
1032{
1033 int r;
1034 int lib;
1035 int adj, adjs[MAXCHAIN];
1036
1037 /* Common liberties. */
1038 if (have_common_lib(str1, str2, &lib)) {
1039 *move = lib;
1040 return WIN;
1041 }
1042
1043 /* Common adjacent string in atari, more than one stone, no snapback. */
1044 adj = chainlinks2(str1, adjs, 1);
1045 for (r = 0; r < adj; r++)
1046 if (adjacent_strings(adjs[r], str2)
1047 && !snapback(adjs[r])) {
1048 findlib(adjs[r], 1, move);
1049 return WIN;
1050 }
1051
1052 /* Common adjacent string two liberties, read ladder. */
1053 adj = chainlinks2(str1, adjs, 2);
1054 for (r = 0; r < adj; r++)
1055 if (adjacent_strings(adjs[r], str2))
1056 if (quiescence_capture(adjs[r], move))
1057 return WIN;
1058
1059 return 0;
1060}
1061
1062
1063/* A persistent connection cache has been implemented, but currently
1064 * (3.3.15) it does not have much impact on performance. Possible
1065 * explanations for this include:
1066 * 1. The active area is too often unnecessarily large.
1067 * 2. Between the persistent caches of tactical reading and owl
1068 * reading, there is not much to gain from also caching the
1069 * connection results.
1070 * 3. There is some bug in the implementation.
1071 *
1072 * In order to simplify testing of code modifications, the caching
1073 * code has been made conditional. Setting
1074 * USE_PERSISTENT_CONNECTION_CACHE to 0, 1, or 2 has the following
1075 * effects.
1076 * 0 - Completely turned off.
1077 * 1 - Results are stored in the cache but retrieved results are only
1078 * compared to the non-cached result. Deviations are reported.
1079 * 2 - Fully turned on.
1080 */
1081#define USE_PERSISTENT_CONNECTION_CACHE 0
1082
1083
1084/* Externally callable frontend to recursive_connect().
1085 * Returns WIN if str1 and str2 can be connected.
1086 */
1087int
1088string_connect(int str1, int str2, int *move)
1089{
1090 int dummy_move;
1091 int save_verbose;
1092 int result;
1093
1094 if (move == NULL)
1095 move = &dummy_move;
1096
1097 nodes_connect = 0;
1098 *move = PASS_MOVE;
1099
1100 if (alternate_connections) {
1101 int reading_nodes_when_called = get_reading_node_counter();
1102 double start = 0;
1103 int tactical_nodes;
1104 int save_connection_node_limit = connection_node_limit;
1105#if USE_PERSISTENT_CONNECTION_CACHE == 1
1106 int result2 = -1;
1107 int move2;
1108#endif
1109 if (board[str1] == EMPTY || board[str2] == EMPTY)
1110 return 0;
1111 str1 = find_origin(str1);
1112 str2 = find_origin(str2);
1113 if (str1 > str2) {
1114 int tmp = str1;
1115 str1 = str2;
1116 str2 = tmp;
1117 }
1118
1119
1120#if USE_PERSISTENT_CONNECTION_CACHE == 1
1121 if (!search_persistent_connection_cache(CONNECT, str1, str2,
1122 &result2, &move2))
1123 result2 = -1;
1124 else if (0)
1125 gprintf("Persistent cache found connect %1m %1m: %d %1m\n",
1126 str1, str2, result2, move2);
1127#endif
1128#if USE_PERSISTENT_CONNECTION_CACHE == 2
1129 if (search_persistent_connection_cache(CONNECT, str1, str2, &result, move))
1130 return result;
1131#endif
1132
1133 connection_node_limit *= pow(1.45, -stackp + get_depth_modification());
1134 save_verbose = verbose;
1135 if (verbose > 0)
1136 verbose--;
1137 start = gg_cputime();
1138 memset(connection_shadow, 0, sizeof(connection_shadow));
1139 result = recursive_connect2(str1, str2, move, 0);
1140 verbose = save_verbose;
1141 tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
1142 connection_node_limit = save_connection_node_limit;
1143
1144#if USE_PERSISTENT_CONNECTION_CACHE == 1
1145 if (result2 != -1
1146 && result2 != result
1147 && *move != move2)
1148 gprintf("Persistent cache failure connect %1m %1m: %d %1m != %d %1m\n",
1149 str1, str2, result, *move, result2, move2);
1150#endif
1151
1152 if (0) {
1153 gprintf("%oconnect %1M %1M, result %d %1M (%d, %d nodes, %f seconds)\n",
1154 str1, str2, result, *move,
1155 nodes_connect, tactical_nodes, gg_cputime() - start);
1156 dump_stack();
1157 }
1158 if (0) {
1159 gprintf("%oconnect %1m %1m %d %1m ", str1, str2, result, *move);
1160 dump_stack();
1161 }
1162
1163#if USE_PERSISTENT_CONNECTION_CACHE > 0
1164 store_persistent_connection_cache(CONNECT, str1, str2, result, *move,
1165 tactical_nodes, connection_shadow);
1166#endif
1167
1168 return result;
1169 }
1170
1171 return recursive_connect(str1, str2, move);
1172}
1173
1174
1175/* returns WIN if str1 and str2 can be connected. */
1176
1177static int
1178recursive_connect(int str1, int str2, int *move)
1179{
1180 int i, res = 0, Moves[MAX_MOVES], ForcedMoves[MAX_MOVES];
1181 SETUP_TRACE_INFO2("recursive_connect", str1, str2);
1182
1183 if (board[str1] == EMPTY || board[str2] == EMPTY) {
1184 SGFTRACE2(PASS_MOVE, 0, "one string already captured");
1185 return 0;
1186 }
1187
1188 if (same_string(str1, str2)) {
1189 SGFTRACE2(PASS_MOVE, WIN, "already connected");
1190 return WIN;
1191 }
1192
1193 if (nodes_connect > connection_node_limit) {
1194 SGFTRACE2(PASS_MOVE, 0, "connection node limit reached");
1195 return 0;
1196 }
1197
1198 if (stackp == connect_depth) {
1199 SGFTRACE2(PASS_MOVE, 0, "connection depth limit reached");
1200 return 0;
1201 }
1202
1203 nodes_connect++;
1204 global_connection_node_counter++;
1205
1206 if (quiescence_connect (str1, str2, move)) {
1207 SGFTRACE2(*move, WIN, "quiescence_connect");
1208 return WIN;
1209 }
1210
1211 ForcedMoves[0] = 0;
1212 Moves[0] = 0;
1213 /* if one of the strings to connect can be captured
1214 * and there are forced moves to prevent the capture
1215 * then the only moves to try are the moves that
1216 * defend the string: all the other moves will
1217 * lead to the capture of the string
1218 */
1219 if (!prevent_capture_one_move(ForcedMoves, str1))
1220 prevent_capture_one_move(ForcedMoves, str2);
1221#if 0
1222 else if (prevent_capture_two_moves(ForcedMoves, str1))
1223 ;
1224 else if (prevent_capture_two_moves(ForcedMoves, str2))
1225 ;
1226#endif
1227
1228 /* We are at a max node, so any move we can find
1229 * is ok. Try moves that can connect in three moves
1230 * because the function that prevent connection in one
1231 * and two moves are called at AND nodes.
1232 */
1233 moves_to_connect_in_three_moves(Moves, str1, str2, 1);
1234
1235 /* if there are some forced moves to prevent the capture
1236 * of one of the two strings, then we only look at
1237 * the moves that prevent capture and that might also
1238 * connect
1239 */
1240 if (ForcedMoves[0] != 0 && Moves[0] != 0)
1241 intersection_array(Moves, ForcedMoves);
1242
1243 order_connection_moves(Moves, str1, str2, board[str1],
1244 "recursive_connect");
1245 for (i = 1; ((i < Moves[0] + 1) && (res == 0)); i++) {
1246 if (trymove(Moves[i], board[str1], "recursive_connect", str1)) {
1247 if (!recursive_disconnect(str1, str2, move)) {
1248 *move = Moves[i];
1249 res = WIN;
1250 }
1251 popgo();
1252 }
1253 }
1254
1255 if (res == WIN) {
1256 SGFTRACE2(*move, WIN, "success");
1257 }
1258 else {
1259 SGFTRACE2(PASS_MOVE, 0, "failure");
1260 }
1261
1262 return res;
1263}
1264
1265
1266/* Externally callable frontend to recursive_disconnect().
1267 * Returns WIN if str1 and str2 can be disconnected.
1268 */
1269int
1270disconnect(int str1, int str2, int *move)
1271{
1272 int i;
1273 int res = WIN;
1274 int Moves[MAX_MOVES];
1275 int dummy_move;
1276 int result;
1277 int save_verbose;
1278
1279 if (move == NULL)
1280 move = &dummy_move;
1281
1282 nodes_connect = 0;
1283 *move = PASS_MOVE;
1284
1285 if (alternate_connections) {
1286 int reading_nodes_when_called = get_reading_node_counter();
1287 int save_connection_node_limit = connection_node_limit;
1288 double start = 0;
1289 int tactical_nodes;
1290#if USE_PERSISTENT_CONNECTION_CACHE == 1
1291 int result2 = -1;
1292 int move2;
1293#endif
1294 if (board[str1] == EMPTY || board[str2] == EMPTY)
1295 return WIN;
1296 str1 = find_origin(str1);
1297 str2 = find_origin(str2);
1298 if (str1 > str2) {
1299 int tmp = str1;
1300 str1 = str2;
1301 str2 = tmp;
1302 }
1303
1304#if USE_PERSISTENT_CONNECTION_CACHE == 1
1305 if (!search_persistent_connection_cache(DISCONNECT, str1, str2,
1306 &result2, &move2))
1307 result2 = -1;
1308 else if (0)
1309 gprintf("Persistent cache found disconnect %1m %1m: %d %1m\n",
1310 str1, str2, result2, move2);
1311#endif
1312#if USE_PERSISTENT_CONNECTION_CACHE == 2
1313 if (search_persistent_connection_cache(DISCONNECT, str1, str2,
1314 &result, move))
1315 return result;
1316#endif
1317
1318 connection_node_limit *= pow(1.5, -stackp + get_depth_modification());
1319 save_verbose = verbose;
1320 if (verbose > 0)
1321 verbose--;
1322 start = gg_cputime();
1323 memset(connection_shadow, 0, sizeof(connection_shadow));
1324 result = recursive_disconnect2(str1, str2, move, 0);
1325 verbose = save_verbose;
1326 tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
1327 connection_node_limit = save_connection_node_limit;
1328
1329#if USE_PERSISTENT_CONNECTION_CACHE == 1
1330 if (result2 != -1
1331 && result2 != result
1332 && *move != move2)
1333 gprintf("Persistent cache failure disconnect %1m %1m: %d %1m != %d %1m\n",
1334 str1, str2, result, *move, result2, move2);
1335#endif
1336
1337 if (0) {
1338 gprintf("%odisconnect %1m %1m, result %d %1m (%d, %d nodes, %f seconds)\n",
1339 str1, str2, result, *move,
1340 nodes_connect, tactical_nodes, gg_cputime() - start);
1341 dump_stack();
1342 }
1343 if (0) {
1344 gprintf("%odisconnect %1m %1m %d %1m ", str1, str2, result, *move);
1345 dump_stack();
1346 }
1347
1348#if USE_PERSISTENT_CONNECTION_CACHE > 0
1349 store_persistent_connection_cache(DISCONNECT, str1, str2, result, *move,
1350 tactical_nodes, connection_shadow);
1351#endif
1352
1353 return result;
1354 }
1355
1356 Moves[0] = 0;
1357 moves_to_prevent_connection_in_three_moves(Moves, str1, str2);
1358 if (Moves[0] > 0)
1359 res = 0;
1360 order_connection_moves(Moves, str1, str2, OTHER_COLOR(board[str1]),
1361 "disconnect");
1362 for (i = 1; ((i < Moves[0] + 1) && (res == 0)); i++)
1363 if (trymove(Moves[i], OTHER_COLOR(board[str1]),
1364 "disconnect", str1)) {
1365 if (!recursive_connect(str1, str2, move)) {
1366 *move = Moves[i];
1367 res = WIN;
1368 }
1369 popgo();
1370 }
1371 return res;
1372}
1373
1374/* Externally callable frontend to recursive_disconnect().
1375 * Returns WIN if str1 and str2 can be disconnected.
1376 *
1377 * Uses much lower node and depths limits.
1378 */
1379int
1380fast_disconnect(int str1, int str2, int *move)
1381{
1382 int result;
1383 int save_limit = connection_node_limit;
1384 int save_verbose = verbose;
1385
1386 if (board[str1] == EMPTY || board[str2] == EMPTY)
1387 return WIN;
1388 str1 = find_origin(str1);
1389 str2 = find_origin(str2);
1390 if (str1 > str2) {
1391 int tmp = str1;
1392 str1 = str2;
1393 str2 = tmp;
1394 }
1395
1396 modify_depth_values(-3);
1397 connection_node_limit /= 4;
1398
1399 if (verbose > 0)
1400 verbose--;
1401 result = recursive_disconnect2(str1, str2, move, 0);
1402 verbose = save_verbose;
1403
1404 connection_node_limit = save_limit;
1405 modify_depth_values(3);
1406
1407 return result;
1408}
1409
1410
1411
1412/* Returns WIN if str1 and str2 can be disconnected. */
1413
1414static int
1415recursive_disconnect(int str1, int str2, int *move)
1416{
1417 int i, res = WIN, Moves[MAX_MOVES];
1418
1419 SETUP_TRACE_INFO2("recursive_disconnect", str1, str2);
1420
1421 if (board[str1] == EMPTY || board[str2] == EMPTY) {
1422 SGFTRACE2(PASS_MOVE, WIN, "one string already captured");
1423 return WIN;
1424 }
1425
1426 if (quiescence_capture(str1, move)) {
1427 SGFTRACE2(*move, WIN, "first string capturable");
1428 return WIN;
1429 }
1430 if (quiescence_capture(str2, move)) {
1431 SGFTRACE2(*move, WIN, "second string capturable");
1432 return WIN;
1433 }
1434
1435 if (same_string(str1, str2)) {
1436 SGFTRACE2(PASS_MOVE, 0, "already connected");
1437 return 0;
1438 }
1439
1440 if (nodes_connect > connection_node_limit) {
1441 SGFTRACE2(PASS_MOVE, WIN, "connection node limit reached");
1442 return WIN;
1443 }
1444
1445 if (stackp == connect_depth) {
1446 SGFTRACE2(PASS_MOVE, WIN, "connection depth limit reached");
1447 return WIN;
1448 }
1449
1450 nodes_connect++;
1451 global_connection_node_counter++;
1452
1453 /* we are at an and node
1454 * only look at forced moves here,
1455 * it ensures that the result of recursive_disconnect
1456 * is proved if it returns 0 (that is connections are proved)
1457 */
1458 Moves[0] = 0;
1459
1460 if (prevent_connection_one_move(Moves, str1, str2))
1461 res = 0;
1462 else if (prevent_connection_two_moves(Moves, str1, str2))
1463 res = 0;
1464 else if (prevent_simple_connection_three_moves(Moves, str1, str2))
1465 res = 0;
1466
1467 if (res == 0)
1468 order_connection_moves(Moves, str1, str2, OTHER_COLOR(board[str1]),
1469 "recursive_disconnect");
1470 for (i = 1; ((i < Moves[0] + 1) && (res == 0)); i++)
1471 if (trymove(Moves[i], OTHER_COLOR(board[str1]),
1472 "recursive_disconnect", str1)) {
1473 if (!recursive_connect(str1, str2, move)) {
1474 *move = Moves[i];
1475 res = WIN;
1476 }
1477 popgo();
1478 }
1479
1480 if (res == WIN) {
1481 SGFTRACE2(*move, WIN, "success");
1482 }
1483 else {
1484 SGFTRACE2(PASS_MOVE, 0, "failure");
1485 }
1486
1487 return res;
1488}
1489
1490/* Reads simple ladders.
1491 */
1492
1493static int
1494quiescence_capture(int str, int *move)
1495{
1496 SGFTree *save_sgf_dumptree = sgf_dumptree;
1497 int save_count_variations = count_variations;
1498 int result = 0;
1499
1500 /* We turn off the sgf traces here to avoid cluttering them up with
1501 * naive_ladder moves.
1502 */
1503 sgf_dumptree = NULL;
1504 count_variations = 0;
1505
1506 if (countlib(str) == 1) {
1507 findlib(str, 1, move);
1508 result = WIN;
1509 }
1510 else if (countlib(str) == 2)
1511 result = simple_ladder(str, move);
1512
1513 /* Turn the sgf traces back on. */
1514 sgf_dumptree = save_sgf_dumptree;
1515 count_variations = save_count_variations;
1516
1517 return result;
1518}
1519
1520#if 0
1521static int
1522capture_one_move(int str)
1523{
1524 if (countlib(str) == 1)
1525 return 1;
1526 return 0;
1527}
1528#endif
1529
1530/* Find all the possible moves that can prevent the capture
1531 * of a string in atari.
1532 *
1533 * The ip1 game function.
1534 */
1535
1536static int
1537prevent_capture_one_move(int *moves, int str1)
1538{
1539 int r, res = 0;
1540 int liberties, libs[MAXLIBS];
1541 int adj, adjs[MAXCHAIN];
1542
1543 liberties = findlib(str1, MAXLIBS, libs);
1544 if (liberties == 1) {
1545 add_array(moves, libs[0]);
1546 res = WIN;
1547 adj = chainlinks2(str1, adjs, 1);
1548 for (r = 0; r < adj; r++) {
1549 findlib(adjs[r], 1, libs);
1550 add_array(moves, libs[0]);
1551 }
1552 }
1553 return res;
1554}
1555
1556
1557/* Returns WIN if str1, str2 and str3 can be connected. */
1558
1559static int
1560recursive_transitivity(int str1, int str2, int str3, int *move)
1561{
1562 int i, res = 0, Moves[MAX_MOVES], ForcedMoves[MAX_MOVES];
1563
1564 SETUP_TRACE_INFO2("recursive_transitivity", str1, str3);
1565
1566 if (board[str1] == EMPTY || board[str2] == EMPTY || board[str3] == EMPTY) {
1567 SGFTRACE2(PASS_MOVE, 0, "one string already captured");
1568 return 0;
1569 }
1570
1571 if (same_string(str1, str2) && same_string(str1, str3)) {
1572 SGFTRACE2(PASS_MOVE, WIN, "already connected");
1573 return WIN;
1574 }
1575
1576 if (nodes_connect > connection_node_limit) {
1577 SGFTRACE2(PASS_MOVE, 0, "connection node limit reached");
1578 return 0;
1579 }
1580
1581 if (stackp == connect_depth) {
1582 SGFTRACE2(PASS_MOVE, 0, "connection depth limit reached");
1583 return 0;
1584 }
1585
1586 nodes_connect++;
1587 global_connection_node_counter++;
1588
1589 if (same_string(str1, str2))
1590 if (quiescence_connect (str1, str3, move)) {
1591 SGFTRACE2(*move, WIN, "quiescence_connect");
1592 return WIN;
1593 }
1594
1595 if (same_string(str2, str3))
1596 if (quiescence_connect (str1, str2, move)) {
1597 SGFTRACE2(*move, WIN, "quiescence_connect");
1598 return WIN;
1599 }
1600
1601 ForcedMoves[0] = 0;
1602 Moves[0] = 0;
1603 /* If one of the strings to connect can be captured
1604 * and there are forced moves to prevent the capture
1605 * then the only moves to try are the moves that
1606 * defend the string. All the other moves will
1607 * lead to the capture of the string.
1608 */
1609 if (!prevent_capture_one_move(ForcedMoves, str1))
1610 if (!prevent_capture_one_move(ForcedMoves, str2))
1611 prevent_capture_one_move(ForcedMoves, str3);
1612
1613 /* We are at a max node, so any move we can find
1614 * is ok. Try moves that can connect in two moves
1615 * because the function that prevents connection in one
1616 * move is called at and nodes.
1617 */
1618 moves_to_connect_in_two_moves(Moves, str1, str2);
1619 moves_to_connect_in_two_moves(Moves, str2, str3);
1620
1621 /* If there are some forced moves to prevent the capture
1622 * of one of the two strings, then we only look at
1623 * the moves that prevent capture and that might also
1624 * connect.
1625 */
1626 if ((ForcedMoves[0] != 0) && (Moves[0] != 0))
1627 intersection_array(Moves, ForcedMoves);
1628
1629 order_connection_moves(Moves, str1, str2, board[str1],
1630 "recursive_transitivity");
1631 for (i = 1; ((i < Moves[0] + 1) && (res == 0)); i++) {
1632 if (trymove(Moves[i], board[str1], "recursive_transitivity", str1)) {
1633 if (!recursive_non_transitivity(str1, str2, str3, move)) {
1634 *move = Moves[i];
1635 res = WIN;
1636 }
1637 popgo();
1638 }
1639 }
1640
1641 if (res == WIN) {
1642 SGFTRACE2(*move, WIN, "success");
1643 }
1644 else {
1645 SGFTRACE2(PASS_MOVE, 0, "failure");
1646 }
1647
1648 return res;
1649}
1650
1651/* It is often assumed that if str1 connects to str2 and str2
1652 * connects to str3 then str1 connects to str3. This is called
1653 * TRANSITIVITY. However there are exceptions such as this
1654 * situation:
1655 *
1656 * XXXXX XXXXX
1657 * OO.OO AA*CC
1658 * ..O.. ..B..
1659 * XXXXX XXXXX
1660 *
1661 * Although strings A and B are connected, and strings B and C
1662 * are connected, a move at * disconnects strings A and C.
1663 *
1664 * This function is a public frontend to recursive_non_transitivity().
1665 * Returns WIN if str1, str2 and str3 can be disconnected.
1666*/
1667
1668int
1669non_transitivity(int str1, int str2, int str3, int *move)
1670{
1671 int i, res = WIN, Moves[MAX_MOVES];
1672
1673 nodes_connect = 0;
1674 *move = PASS_MOVE;
1675 moves_to_prevent_connection_in_three_moves(Moves, str1, str3);
1676 if (Moves[0] > 0)
1677 res = 0;
1678 order_connection_moves(Moves, str1, str2, OTHER_COLOR(board[str1]),
1679 "non_transitivity");
1680 for (i = 1; ((i < Moves[0] + 1) && (res == 0)); i++)
1681 if (trymove(Moves[i], OTHER_COLOR(board[str1]),
1682 "non_transitivity", str1)) {
1683 if (!recursive_transitivity(str1, str2, str3, move)) {
1684 *move = Moves[i];
1685 res = WIN;
1686 }
1687 popgo();
1688 }
1689 return res;
1690}
1691
1692/* Returns WIN if str1, str2 and str3 can be disconnected. */
1693
1694static int
1695recursive_non_transitivity(int str1, int str2, int str3, int *move)
1696{
1697 int i, res = WIN, Moves[MAX_MOVES];
1698
1699 SETUP_TRACE_INFO2("recursive_non_transitivity", str1, str3);
1700
1701 if (board[str1] == EMPTY || board[str2] == EMPTY
1702 || board[str3] == EMPTY) {
1703 SGFTRACE2(PASS_MOVE, WIN, "one string already captured");
1704 return WIN;
1705 }
1706
1707 if (quiescence_capture(str1, move)) {
1708 SGFTRACE2(*move, WIN, "first string capturable");
1709 return WIN;
1710 }
1711 if (quiescence_capture(str2, move)) {
1712 SGFTRACE2(*move, WIN, "second string capturable");
1713 return WIN;
1714 }
1715 if (quiescence_capture(str3, move)) {
1716 SGFTRACE2(*move, WIN, "third string capturable");
1717 return WIN;
1718 }
1719
1720 if (same_string(str1, str2) && same_string(str1, str3)) {
1721 SGFTRACE2(PASS_MOVE, 0, "already connected");
1722 return 0;
1723 }
1724
1725 if (nodes_connect > connection_node_limit) {
1726 SGFTRACE2(PASS_MOVE, WIN, "connection node limit reached");
1727 return WIN;
1728 }
1729
1730 if (stackp == connect_depth) {
1731 SGFTRACE2(PASS_MOVE, WIN, "connection depth limit reached");
1732 return WIN;
1733 }
1734
1735 nodes_connect++;
1736 global_connection_node_counter++;
1737
1738 /* We are at an and node. Only look at forced moves. */
1739 Moves[0] = 0;
1740 if (prevent_connection_one_move(Moves, str1, str3))
1741 res = 0;
1742 else if (prevent_connection_two_moves(Moves, str1, str3))
1743 res = 0;
1744 else if (prevent_simple_connection_three_moves(Moves, str1, str3))
1745 res = 0;
1746
1747 if (res == 0)
1748 order_connection_moves(Moves, str1, str2, OTHER_COLOR(board[str1]),
1749 "recursive_non_transitivity");
1750 for (i = 1; ((i < Moves[0] + 1) && (res == 0)); i++)
1751 if (trymove(Moves[i], OTHER_COLOR(board[str1]),
1752 "recursive_non_transitivity", str1)) {
1753 if (!recursive_transitivity(str1, str2, str3, move)) {
1754 *move = Moves[i];
1755 res = WIN;
1756 }
1757 popgo();
1758 }
1759
1760 if (res == WIN) {
1761 SGFTRACE2(*move, WIN, "success");
1762 }
1763 else {
1764 SGFTRACE2(PASS_MOVE, 0, "failure");
1765 }
1766
1767 return res;
1768}
1769
1770
1771/* Order the moves so that we try the ones likely to succeed early. */
1772static void
1773order_connection_moves(int *moves, int str1, int str2, int color_to_move,
1774 const char *funcname)
1775{
1776 int scores[MAX_MOVES];
1777 int r;
1778 int i, j;
1779 UNUSED(str2);
1780 UNUSED(color_to_move);
1781
1782 for (r = 1; r <= moves[0]; r++) {
1783 int move = moves[r];
1784
1785 /* Look at the neighbors of this move and count the things we
1786 * find. Friendly and opponent stones are related to color, i.e.
1787 * the player to move, not to the color of the string.
1788 *
1789 * We don't use all these values. They are only here so we can
1790 * reuse incremental_order_moves() which was developed for the
1791 * tactical reading.
1792 */
1793 int number_edges = 0; /* outside board */
1794 int number_same_string = 0; /* the string being attacked */
1795 int number_own = 0; /* friendly stone */
1796 int number_opponent = 0; /* opponent stone */
1797 int captured_stones = 0; /* number of stones captured by this move */
1798 int threatened_stones = 0; /* number of stones threatened by this move */
1799 int saved_stones = 0; /* number of stones in atari saved */
1800 int number_open = 0; /* empty intersection */
1801 int libs;
1802
1803 /* We let the incremental board code do the heavy work. */
1804 incremental_order_moves(move, color_to_move, str1, &number_edges,
1805 &number_same_string, &number_own,
1806 &number_opponent, &captured_stones,
1807 &threatened_stones, &saved_stones, &number_open);
1808
1809 if (0)
1810 gprintf("%o %1m values: %d %d %d %d %d %d %d %d\n", move, number_edges,
1811 number_same_string, number_own, number_opponent,
1812 captured_stones, threatened_stones, saved_stones, number_open);
1813
1814 scores[r] = 0;
1815 libs = approxlib(move, color_to_move, 10, NULL);
1816
1817 /* Avoid self atari. */
1818 if (libs == 1 && captured_stones == 0)
1819 scores[r] -= 10;
1820
1821 /* Good to get many liberties. */
1822 if (libs < 4)
1823 scores[r] += libs;
1824 else
1825 scores[r] += 4;
1826
1827 /* Very good to capture opponent stones. */
1828 if (captured_stones > 0)
1829 scores[r] += 5 + captured_stones;
1830
1831 /* Good to threaten opponent stones. */
1832 if (threatened_stones > 0)
1833 scores[r] += 3;
1834
1835 /* Extremely good to save own stones. */
1836 if (saved_stones > 0)
1837 scores[r] += 10 + saved_stones;
1838 }
1839
1840 /* Now sort the moves. We use selection sort since this array will
1841 * probably never be more than 10 moves long. In this case, the
1842 * overhead imposed by quicksort will probably overshadow the gains
1843 * given by the O(n*log(n)) behaviour over the O(n^2) behaviour of
1844 * selection sort.
1845 */
1846 for (i = 1; i <= moves[0]; i++) {
1847 /* Find the move with the biggest score. */
1848 int maxscore = scores[i];
1849 int max_at = i;
1850 for (j = i+1; j <= moves[0]; j++) {
1851 if (scores[j] > maxscore) {
1852 maxscore = scores[j];
1853 max_at = j;
1854 }
1855 }
1856
1857 /* Now exchange the move at i with the move at max_at.
1858 * Don't forget to exchange the scores as well.
1859 */
1860 if (max_at != i) {
1861 int temp = moves[i];
1862 int tempmax = scores[i];
1863
1864 moves[i] = moves[max_at];
1865 scores[i] = scores[max_at];
1866
1867 moves[max_at] = temp;
1868 scores[max_at] = tempmax;
1869 }
1870 }
1871
1872 if (0) {
1873 gprintf("%oVariation %d:\n", count_variations);
1874 for (i = 1; i <= moves[0]; i++)
1875 gprintf("%o %1M %d\n", moves[i], scores[i]);
1876 }
1877
1878 if (sgf_dumptree) {
1879 char buf[500];
1880 char *pos;
1881 int chars;
1882 sprintf(buf, "Move order for %s: %n", funcname, &chars);
1883 pos = buf + chars;
1884 for (i = 1; i <= moves[0]; i++) {
1885 sprintf(pos, "%c%d (%d) %n", J(moves[i]) + 'A' + (J(moves[i]) >= 8),
1886 board_size - I(moves[i]), scores[i], &chars);
1887 pos += chars;
1888 }
1889 sgftreeAddComment(sgf_dumptree, buf);
1890 }
1891}
1892
1893/* Clear statistics. */
1894void
1895reset_connection_node_counter()
1896{
1897 global_connection_node_counter = 0;
1898}
1899
1900
1901/* Retrieve statistics. */
1902int
1903get_connection_node_counter()
1904{
1905 return global_connection_node_counter;
1906}
1907
1908
1909/*********************************************************
1910 *
1911 * Alternate connection reading algorithm.
1912 *
1913 * This code is enabled with the --enable-alternate-connections
1914 * configure flag at build time or toggled with the
1915 * --alternate-connections option at run time.
1916 *
1917 *********************************************************/
1918
1919/* This has been copied from reading.c and modified.
1920 */
1921
1922#define ADD_CANDIDATE_MOVE(move, distance, moves, distances, num_moves)\
1923 do {\
1924 int l;\
1925 for (l = 0; l < num_moves; l++)\
1926 if (moves[l] == (move)) {\
1927 if (distances[l] > distance)\
1928 distances[l] = distance;\
1929 break;\
1930 }\
1931 if ((l == num_moves) && (num_moves < MAX_MOVES)) {\
1932 moves[num_moves] = move;\
1933 distances[num_moves] = distance;\
1934 (num_moves)++;\
1935 }\
1936 } while (0)
1937
1938
1939static int find_string_connection_moves(int str1, int str2, int color_to_move,
1940 int moves[MAX_MOVES],
1941 int *total_distance);
1942static void clear_connection_data(struct connection_data *conn);
1943static int trivial_connection(int str1, int str2, int *move);
1944static int does_secure_through_ladder(int color, int move, int pos);
1945static int ladder_capture(int str, int *move);
1946static int ladder_capturable(int pos, int color);
1947static int no_escape_from_atari(int str);
1948static int no_escape_from_ladder(int str);
1949static int check_self_atari(int pos, int color_to_move);
1950static int common_vulnerabilities(int a1, int a2, int b1, int b2, int color);
1951static int common_vulnerability(int apos, int bpos, int color);
1952
1953/* Try to connect two strings. This function is called in a mutual
1954 * recursion with recursive_disconnect2(). Return codes is identical to
1955 * the tactical reading functions. For the has_passed parameter, see the
1956 * documentation of recursive_disconnect2().
1957 *
1958 * The algorithm is
1959 * 1. Check if the strings are trivially connected or disconnected or
1960 * the result is already cached.
1961 * 2. Find connection moves.
1962 * 3. Try one move at a time and call recursive_disconnect2() to see
1963 * whether we were successful.
1964 * 4. If no move was found we assume success if the connection
1965 * distance was small and failure otherwise.
1966 */
1967static int
1968recursive_connect2(int str1, int str2, int *move, int has_passed)
1969{
1970 int color = board[str1];
1971 int moves[MAX_MOVES];
1972 int num_moves;
1973 int distance = FP(0.0);
1974 int k;
1975 int xpos;
1976 int savemove = NO_MOVE;
1977 int savecode = 0;
1978 int tried_moves = 0;
1979 int value;
1980
1981 SETUP_TRACE_INFO2("recursive_connect2", str1, str2);
1982
1983 if (move)
1984 *move = NO_MOVE;
1985
1986 nodes_connect++;
1987 global_connection_node_counter++;
1988
1989 if (board[str1] == EMPTY || board[str2] == EMPTY) {
1990 SGFTRACE2(PASS_MOVE, 0, "one string already captured");
1991 return 0;
1992 }
1993
1994 if (same_string(str1, str2)) {
1995 SGFTRACE2(PASS_MOVE, WIN, "already connected");
1996 return WIN;
1997 }
1998
1999 if (nodes_connect > connection_node_limit) {
2000 SGFTRACE2(PASS_MOVE, 0, "connection node limit reached");
2001 return 0;
2002 }
2003
2004 if (stackp > connect_depth2) {
2005 SGFTRACE2(PASS_MOVE, 0, "connection depth limit reached");
2006 return 0;
2007 }
2008
2009 str1 = find_origin(str1);
2010 str2 = find_origin(str2);
2011
2012 if (stackp <= depth && !has_passed
2013 && tt_get(&ttable, CONNECT, str1, str2, depth - stackp, NULL,
2014 &value, NULL, &xpos) == 2) {
2015 TRACE_CACHED_RESULT2(value, value, xpos);
2016 if (value != 0)
2017 if (move)
2018 *move = xpos;
2019
2020 SGFTRACE2(xpos, value, "cached");
2021 return value;
2022 }
2023
2024 if (trivial_connection(str1, str2, &xpos) == WIN) {
2025 SGFTRACE2(xpos, WIN, "trivial connection");
2026 READ_RETURN_CONN(CONNECT, str1, str2, depth - stackp, move, xpos, WIN);
2027 }
2028
2029 num_moves = find_string_connection_moves(str1, str2, color,
2030 moves, &distance);
2031
2032 for (k = 0; k < num_moves; k++) {
2033 int ko_move;
2034 xpos = moves[k];
2035
2036 if (komaster_trymove(xpos, color, "recursive_connect2", str1,
2037 &ko_move, stackp <= ko_depth && savecode == 0)) {
2038 tried_moves++;
2039 if (!ko_move) {
2040 int acode = recursive_disconnect2(str1, str2, NULL,
2041
2042 has_passed);
2043 popgo();
2044 if (acode == 0) {
2045 SGFTRACE2(xpos, WIN, "connection effective");
2046 READ_RETURN_CONN(CONNECT, str1, str2, depth - stackp,
2047 move, xpos, WIN);
2048 }
2049 /* if the move works with ko we save it, then look for something
2050 * better.
2051 */
2052 UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, xpos);
2053 }
2054 else {
2055 if (recursive_disconnect2(str1, str2, NULL,
2056
2057 has_passed) != WIN) {
2058 savemove = xpos;
2059 savecode = KO_B;
2060 }
2061 popgo();
2062 }
2063 }
2064 }
2065
2066 if (tried_moves == 0 && distance < FP(1.0)) {
2067 SGFTRACE2(NO_MOVE, WIN, "no move, probably connected");
2068 READ_RETURN_CONN(CONNECT, str1, str2, depth - stackp, move, NO_MOVE, WIN);
2069 }
2070
2071 if (savecode != 0) {
2072 SGFTRACE2(savemove, savecode, "saved move");
2073 READ_RETURN_CONN(CONNECT, str1, str2, depth - stackp,
2074 move, savemove, savecode);
2075 }
2076
2077 SGFTRACE2(0, 0, NULL);
2078 READ_RETURN_CONN(CONNECT, str1, str2, depth - stackp, move, NO_MOVE, 0);
2079}
2080
2081
2082/* Try to disconnect two strings. This function is called in a mutual
2083 * recursion with recursive_connect2(). Return codes is identical to
2084 * the tactical reading functions.
2085 *
2086 * The algorithm is
2087 * 1. Check if the strings are trivially connected or disconnected or
2088 * the result is already cached.
2089 * 2. Find disconnection moves.
2090 * 3. Try one move at a time and call recursive_connect2() to see
2091 * whether we were successful.
2092 * 4. If no move was found we assume failure if the connection
2093 * distance was small. Otherwise we pass and let
2094 * recursive_connect2() try to connect. However, if we already have
2095 * passed once we just declare success. Whether a pass already has
2096 * been made is indicated by the has_passed parameter.
2097 */
2098static int
2099recursive_disconnect2(int str1, int str2, int *move, int has_passed)
2100{
2101 int color = board[str1];
2102 int other = OTHER_COLOR(color);
2103 int moves[MAX_MOVES];
2104 int num_moves;
2105 int distance = FP(0.0);
2106 int k;
2107 int xpos;
2108 int savemove = NO_MOVE;
2109 int savecode = 0;
2110 int tried_moves = 0;
2111 int attack_code1;
2112 int attack_pos1;
2113 int attack_code2;
2114 int attack_pos2;
2115 SGFTree *save_sgf_dumptree = sgf_dumptree;
2116 int save_count_variations = count_variations;
2117 int value;
2118
2119 SETUP_TRACE_INFO2("recursive_disconnect2", str1, str2);
2120
2121 nodes_connect++;
2122 global_connection_node_counter++;
2123
2124 if (move)
2125 *move = NO_MOVE;
2126
2127 if (board[str1] == EMPTY || board[str2] == EMPTY) {
2128 SGFTRACE2(PASS_MOVE, WIN, "one string already captured");
2129 return WIN;
2130 }
2131
2132 if (same_string(str1, str2)) {
2133 SGFTRACE2(PASS_MOVE, 0, "already connected");
2134 return 0;
2135 }
2136
2137 if (nodes_connect > connection_node_limit) {
2138 SGFTRACE2(PASS_MOVE, WIN, "connection node limit reached");
2139 return WIN;
2140 }
2141
2142 if (stackp > connect_depth2) {
2143 SGFTRACE2(PASS_MOVE, WIN, "connection depth limit reached");
2144 return WIN;
2145 }
2146
2147 sgf_dumptree = NULL;
2148 count_variations = 0;
2149
2150 str1 = find_origin(str1);
2151 str2 = find_origin(str2);
2152
2153 attack_code1 = attack(str1, &attack_pos1);
2154 if (attack_code1 == WIN) {
2155 sgf_dumptree = save_sgf_dumptree;
2156 count_variations = save_count_variations;
2157
2158 SGFTRACE2(attack_pos1, WIN, "one string is capturable");
2159 if (move)
2160 *move = attack_pos1;
2161
2162 return WIN;
2163 }
2164
2165 attack_code2 = attack(str2, &attack_pos2);
2166 if (attack_code2 == WIN) {
2167 sgf_dumptree = save_sgf_dumptree;
2168 count_variations = save_count_variations;
2169
2170 SGFTRACE2(attack_pos2, WIN, "one string is capturable");
2171 if (move)
2172 *move = attack_pos2;
2173
2174 return WIN;
2175 }
2176
2177 sgf_dumptree = save_sgf_dumptree;
2178 count_variations = save_count_variations;
2179
2180 if (stackp <= depth
2181 && tt_get(&ttable, DISCONNECT, str1, str2,
2182 depth - stackp, NULL,
2183 &value, NULL, &xpos) == 2) {
2184 TRACE_CACHED_RESULT2(value, value, xpos);
2185 if (value != 0)
2186 if (move)
2187 *move = xpos;
2188
2189 SGFTRACE2(xpos, value, "cached");
2190 return value;
2191 }
2192
2193 if (ladder_capture(str1, &xpos) == WIN) {
2194 SGFTRACE2(xpos, WIN, "first string capturable");
2195 READ_RETURN_CONN(DISCONNECT, str1, str2, depth - stackp, move, xpos, WIN);
2196 }
2197
2198 if (ladder_capture(str2, &xpos) == WIN) {
2199 SGFTRACE2(xpos, WIN, "second string capturable");
2200 READ_RETURN_CONN(DISCONNECT, str1, str2, depth - stackp, move, xpos, WIN);
2201 }
2202
2203 num_moves = find_string_connection_moves(str1, str2, other,
2204 moves, &distance);
2205
2206 if (attack_code1 != 0 && num_moves < MAX_MOVES) {
2207 for (k = 0; k < num_moves; k++) {
2208 if (moves[k] == attack_pos1)
2209 break;
2210 }
2211
2212 if (k == num_moves)
2213 moves[num_moves++] = attack_pos1;
2214 }
2215
2216 if (attack_code2 != 0 && num_moves < MAX_MOVES) {
2217 for (k = 0; k < num_moves; k++) {
2218 if (moves[k] == attack_pos2)
2219 break;
2220 }
2221
2222 if (k == num_moves)
2223 moves[num_moves++] = attack_pos2;
2224 }
2225
2226 for (k = 0; k < num_moves; k++) {
2227 int ko_move;
2228 xpos = moves[k];
2229
2230 if (komaster_trymove(xpos, other, "recursive_disconnect2", str1,
2231 &ko_move, stackp <= ko_depth && savecode == 0)) {
2232 tried_moves++;
2233 if (!ko_move) {
2234 int dcode = recursive_connect2(str1, str2, NULL,
2235 has_passed);
2236 popgo();
2237 if (dcode == 0) {
2238 SGFTRACE2(xpos, WIN, "disconnection effective");
2239 READ_RETURN_CONN(DISCONNECT, str1, str2, depth - stackp,
2240 move, xpos, WIN);
2241 }
2242 /* if the move works with ko we save it, then look for something
2243 * better.
2244 */
2245 UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, xpos);
2246 }
2247 else {
2248 if (recursive_connect2(str1, str2, NULL,
2249
2250 has_passed) != WIN) {
2251 savemove = xpos;
2252 savecode = KO_B;
2253 }
2254 popgo();
2255 }
2256 }
2257 }
2258
2259 if (tried_moves == 0
2260 && distance >= FP(1.0)
2261 && (has_passed
2262 || !recursive_connect2(str1, str2, NULL, 1))) {
2263 SGFTRACE2(NO_MOVE, WIN, "no move, probably disconnected");
2264 READ_RETURN_CONN(DISCONNECT, str1, str2, depth - stackp,
2265 move, NO_MOVE, WIN);
2266 }
2267
2268 if (savecode != 0) {
2269 SGFTRACE2(savemove, savecode, "saved move");
2270 READ_RETURN_CONN(DISCONNECT, str1, str2, depth - stackp,
2271 move, savemove, savecode);
2272 }
2273
2274 SGFTRACE2(0, 0, NULL);
2275 READ_RETURN_CONN(DISCONNECT, str1, str2, depth - stackp, move, NO_MOVE, 0);
2276}
2277
2278
2279/* Find moves to connect or disconnect the two strings str1 and str2.
2280 * If color_to_move equals the color of the strings we search for
2281 * connecting moves and otherwise disconnecting moves. The moves are
2282 * returned in the moves[] array and the number of moves is the return
2283 * value of the function. The parameter *total_distance is set to the
2284 * approximated connection distance between the two strings. This is
2285 * most useful when no moves are found. If *total_distance is small
2286 * they are probably already effectively connected and if it is huge
2287 * they are probably disconnected.
2288 *
2289 * The algorithm is to compute connection distances around each string
2290 * and find points where the sum of the distances is small, or more
2291 * exactly where the sum of the distances after the move would be
2292 * small. This can be done with help of delta values returned together
2293 * with distance values from the function
2294 * compute_connection_distances(). This "distance after move" measure
2295 * is modified with various bonuses and then used to order the found
2296 * moves.
2297 */
2298static int
2299find_connection_moves(int str1, int str2, int color_to_move,
2300 struct connection_data *conn1,
2301 struct connection_data *conn2,
2302 int max_dist1, int max_dist2,
2303 int moves[MAX_MOVES], int total_distance,
2304 int cutoff)
2305{
2306 int color = board[str1];
2307 int other = OTHER_COLOR(color);
2308 int connect_move = (color_to_move == color);
2309 int r;
2310 int distances[MAX_MOVES];
2311 int num_moves = 0;
2312 int acode = 0;
2313 int attack_move = NO_MOVE;
2314 int dcode = 0;
2315 int defense_move = NO_MOVE;
2316 int k;
2317 int i, j;
2318 SGFTree *save_sgf_dumptree = sgf_dumptree;
2319 int save_count_variations = count_variations;
2320 int distance_limit;
2321
2322 /* We turn off the sgf traces here to avoid cluttering them up with
2323 * tactical reading moves.
2324 */
2325 sgf_dumptree = NULL;
2326 count_variations = 0;
2327
2328 /* Loop through the points with smallish distance from str1 and look
2329 * for ones also having a small distance to str2.
2330 */
2331 for (r = 0; r < conn1->queue_end; r++) {
2332 int pos = conn1->queue[r];
2333 int dist1 = conn1->distances[pos];
2334 int deltadist1 = conn1->deltas[pos];
2335 int dist2 = conn2->distances[pos];
2336 int deltadist2 = conn2->deltas[pos];
2337 int d1;
2338 int d2;
2339 int distance;
2340
2341 if (dist1 - deltadist1 + dist2 - deltadist2 > FP(2.5)
2342 || dist1 > max_dist1 + FP(0.2)
2343 || dist2 > max_dist2 + FP(0.2))
2344 continue;
2345
2346 if (verbose > 0)
2347 gprintf("%oMove %1m, (%f, %f, %f, %f)\n", pos,
2348 FIXED_TO_FLOAT(dist1), FIXED_TO_FLOAT(deltadist1),
2349 FIXED_TO_FLOAT(dist2), FIXED_TO_FLOAT(deltadist2));
2350
2351 /* The basic quality of the move is the sum of the distances to
2352 * each string minus the two delta values. This distance value
2353 * will subsequently be modified to take other factors into
2354 * account.
2355 */
2356 d1 = dist1 - deltadist1;
2357 d2 = dist2 - deltadist2;
2358 distance = d1 + d2;
2359 if (verbose > 0)
2360 gprintf("%o %f, primary distance\n", FIXED_TO_FLOAT(distance));
2361
2362 /* Bonus if d1 and d2 are well balanced. */
2363 if ((3 * d1) / 2 > d2 && (3 * d2) / 2 > d1) {
2364 distance -= FP(0.1);
2365 if (verbose > 0)
2366 gprintf("%o -0.1, well balanced\n");
2367 }
2368
2369 /* Check whether the move is "between" the two strings. */
2370 if (conn1->coming_from[pos] != NO_MOVE
2371 && conn1->coming_from[pos] == conn2->coming_from[pos]) {
2372 if (verbose > 0)
2373 gprintf("%o discarded, not between strings\n");
2374 continue;
2375 }
2376
2377 if (board[pos] == EMPTY) {
2378 if (check_self_atari(pos, color_to_move)) {
2379 ADD_CANDIDATE_MOVE(pos, distance, moves, distances, num_moves);
2380 }
2381 else {
2382 if (verbose > 0)
2383 gprintf("%o discarded, self atari\n");
2384 }
2385 }
2386 else if (board[pos] == other) {
2387 attack_and_defend(pos, &acode, &attack_move, &dcode, &defense_move);
2388 if (verbose > 0)
2389 gprintf("%o attack with code %d at %1m, defense with code %d at %1m\n",
2390 acode, attack_move, dcode, defense_move);
2391
2392 if (connect_move && acode != 0) {
2393 if (dcode == 0) {
2394 distance += FP(0.5);
2395 if (verbose > 0)
2396 gprintf("%o +0.5, no defense\n");
2397 }
2398 else {
2399 if (conn1->distances[attack_move]
2400 + conn2->distances[attack_move] > dist1 + dist2) {
2401 distance += FP(0.5);
2402 if (verbose > 0)
2403 gprintf("%o +0.5, attack point not on shortest path\n");
2404 }
2405 }
2406 ADD_CANDIDATE_MOVE(attack_move, distance - FP(0.15), moves, distances,
2407 num_moves);
2408 if (verbose > 0)
2409 gprintf("%o -0.15 at %1m, capturing a string\n", attack_move);
2410 }
2411 else if (!connect_move && acode != 0 && dcode != 0) {
2412 ADD_CANDIDATE_MOVE(defense_move, distance - FP(0.5), moves, distances,
2413 num_moves);
2414 if (verbose > 0)
2415 gprintf("%o -0.5 at %1m, defending a string\n", defense_move);
2416 }
2417 }
2418 else if (board[pos] == color) {
2419 /* Check whether there are common vulnerable points. */
2420 for (k = 0; k < 4; k++) {
2421 int apos, bpos;
2422 if (k & 1)
2423 apos = conn1->vulnerable1[pos];
2424 else
2425 apos = conn1->vulnerable2[pos];
2426
2427 if (k & 2)
2428 bpos = conn2->vulnerable1[pos];
2429 else
2430 bpos = conn2->vulnerable2[pos];
2431
2432 if (common_vulnerability(apos, bpos, color)) {
2433 if (check_self_atari(apos, color_to_move)) {
2434 ADD_CANDIDATE_MOVE(apos, distance, moves, distances, num_moves);
2435 if (verbose > 0)
2436 gprintf("%o +0.0 at %1m, vulnerability\n", apos);
2437 }
2438
2439 if (bpos != apos
2440 && check_self_atari(bpos, color_to_move)) {
2441 ADD_CANDIDATE_MOVE(bpos, distance, moves, distances, num_moves);
2442 if (verbose > 0)
2443 gprintf("%o +0.0 at %1m, vulnerability\n", bpos);
2444 }
2445 }
2446 }
2447 }
2448 }
2449
2450 /* Modify the distance values for the moves with various bonuses. */
2451 for (r = 0; r < num_moves; r++) {
2452 int move = moves[r];
2453 int adjacent_to_attacker = 0;
2454 int bonus_given = 0;
2455
2456 for (k = 0; k < 4; k++) {
2457 int pos = move + delta[k];
2458 if (board[pos] == other) {
2459 adjacent_to_attacker = 1;
2460 distances[r] -= FP(0.15);
2461 if (verbose > 0)
2462 gprintf("%o%1M -0.15, adjacent to attacker string\n", move);
2463 if (countlib(pos) <= 2) {
2464 distances[r] -= FP(0.2);
2465 if (verbose > 0)
2466 gprintf("%o%1M -0.2, adjacent to attacker string with at most two liberties\n", move);
2467 if ((connect_move || !bonus_given)
2468 && (conn1->distances[move] - conn1->deltas[move] <= FP(0.5)
2469 || conn1->distances[pos] - conn1->deltas[pos] <= FP(0.5))
2470 && (conn2->distances[move] - conn2->deltas[move] <= FP(0.5)
2471 || conn2->distances[pos] - conn2->deltas[pos] <= FP(0.5))
2472 && conn1->distances[pos] < total_distance
2473 && conn2->distances[pos] < total_distance) {
2474 bonus_given = 1;
2475 distances[r] -= FP(0.7);
2476 if (verbose > 0)
2477 gprintf("%o%1M -0.7, capture or atari of immediately connecting string\n", move);
2478 }
2479 }
2480 }
2481 else if (board[pos] == color) {
2482 if (countlib(pos) <= 2) {
2483 distances[r] -= FP(0.2);
2484 if (verbose > 0)
2485 gprintf("%o%1M -0.2, adjacent to defender string with at most two liberties\n", move);
2486 }
2487 /* The code above (in the 'board[pos] == other' branch) makes
2488 * perfect sense for the defender, but has a tendency to
2489 * overestimate solid connection defenses when the attacker's
2490 * stones happen to be in atari, specially when capturing some
2491 * defender stones instead would help just as well, if not better.
2492 * The following code compensates in such kind of situations.
2493 * See connection:111 and gunnar:53 for example.
2494 */
2495 if (!connect_move && countlib(pos) == 1
2496 /* let's avoid ko and snapbacks */
2497 && accuratelib(move, other, 2, NULL) > 1) {
2498 int adjs[MAXCHAIN];
2499 int bonus;
2500 bonus = FP(0.1) * chainlinks2(pos, adjs, 2);
2501 bonus += FP(0.5) * chainlinks2(pos, adjs, 1);
2502 distances[r] -= bonus;
2503 if (verbose > 0)
2504 gprintf("%o%1M -%f, capture of defender string\n",
2505 move, FIXED_TO_FLOAT(bonus));
2506 }
2507 }
2508 }
2509 if (adjacent_to_attacker
2510 && !connect_move
2511 && is_edge_vertex(move)) {
2512 distances[r] -= FP(0.1);
2513 if (verbose > 0)
2514 gprintf("%o%1M -0.1, disconnect move on edge\n", move);
2515 }
2516
2517 if (ladder_capturable(move, color_to_move)) {
2518 distances[r] += FP(0.3);
2519 if (verbose > 0)
2520 gprintf("%o%1M +0.3, can be captured in a ladder\n", move);
2521 }
2522
2523 /* Bonus for moves adjacent to endpoint strings with 3 liberties.
2524 * Neighbor strings with less than 3 liberties have already
2525 * generated a bonus above.
2526 */
2527 if ((liberty_of_string(move, str1)
2528 && countlib(str1) == 3)
2529 || (ON_BOARD(str2) && liberty_of_string(move, str2)
2530 && countlib(str2) == 3)) {
2531 distances[r] -= FP(0.1);
2532 if (verbose > 0)
2533 gprintf("%o%1M -0.1, liberty of endpoint string with 3 libs\n", move);
2534 }
2535 }
2536
2537 /* Turn the sgf traces back on. */
2538 sgf_dumptree = save_sgf_dumptree;
2539 count_variations = save_count_variations;
2540
2541 /* Now sort the moves. We use selection sort since this array will
2542 * probably never be more than 10 moves long. In this case, the
2543 * overhead imposed by quicksort will probably overshadow the gains
2544 * given by the O(n*log(n)) behaviour over the O(n^2) behaviour of
2545 * selection sort.
2546 */
2547 for (i = 0; i < num_moves; i++) {
2548 /* Find the move with the smallest distance. */
2549 int mindistance = distances[i];
2550 int min_at = i;
2551 for (j = i + 1; j < num_moves; j++) {
2552 if (distances[j] < mindistance) {
2553 mindistance = distances[j];
2554 min_at = j;
2555 }
2556 }
2557
2558 /* Now exchange the move at i with the move at min_at.
2559 * Don't forget to exchange the distances as well.
2560 */
2561 if (min_at != i) {
2562 int temp = moves[i];
2563 int tempmin = distances[i];
2564
2565 moves[i] = moves[min_at];
2566 distances[i] = distances[min_at];
2567
2568 moves[min_at] = temp;
2569 distances[min_at] = tempmin;
2570 }
2571 }
2572
2573 if (verbose > 0) {
2574 gprintf("%oSorted moves:\n");
2575 for (i = 0; i < num_moves; i++)
2576 gprintf("%o%1M %f\n", moves[i], FIXED_TO_FLOAT(distances[i]));
2577 }
2578
2579 if (sgf_dumptree) {
2580 char buf[500];
2581 char *pos;
2582 int chars;
2583 sprintf(buf, "Move order for %sconnect: %n",
2584 connect_move ? "" : "dis", &chars);
2585 pos = buf + chars;
2586 for (i = 0; i < num_moves; i++) {
2587 sprintf(pos, "%c%d (%4.2f) %n", J(moves[i]) + 'A' + (J(moves[i]) >= 8),
2588 board_size - I(moves[i]), FIXED_TO_FLOAT(distances[i]),
2589 &chars);
2590 pos += chars;
2591 }
2592 if (cutoff < HUGE_CONNECTION_DISTANCE) {
2593 sprintf(pos, "(cutoff %f)%n", FIXED_TO_FLOAT(cutoff), &chars);
2594 pos += chars;
2595 }
2596 sgftreeAddComment(sgf_dumptree, buf);
2597 }
2598
2599 if (num_moves == 0)
2600 return num_moves;
2601
2602 /* Filter out moves with distance at least 1.5 more than the best
2603 * move, or with distance higher than the cutoff specified.
2604 *
2605 * In order to further reduce the branching factor, a decreasing
2606 * cutoff is applied between candidates. For instance, in this case
2607 * 1. d 2. d+0.5 3. d+1.0 4. d+1.5
2608 * the 4th candidate will be tested, while in following one
2609 * 1. d 2. d+0.1 3. d+0.2 4. d+1.5
2610 * it will be discarded.
2611 */
2612 if (num_moves <= 1 || !is_ko(moves[0], color_to_move, NULL))
2613 distance_limit = distances[0] + FP(1.5);
2614 else
2615 distance_limit = distances[1] + FP(1.5);
2616
2617 /* Special case: If the second best move has a distance less than 1,
2618 * include it if even if the best move has a very low distance.
2619 */
2620 if (num_moves > 1
2621 && distances[1] < FP(1.0)
2622 && distances[1] > distance_limit)
2623 distance_limit = distances[1];
2624
2625 for (r = 0; r < num_moves; r++) {
2626 if (r > 1
2627 && distances[r] > distances[r-1]
2628 && distances[r] - distances[r-1] > (8 - r) * FP(0.2))
2629 break;
2630 if (distances[r] > distance_limit
2631 || distances[r] > cutoff)
2632 break;
2633 }
2634 num_moves = r;
2635
2636 return num_moves;
2637}
2638
2639static int
2640find_string_connection_moves(int str1, int str2, int color_to_move,
2641 int moves[MAX_MOVES], int *total_distance)
2642{
2643 struct connection_data conn1;
2644 struct connection_data conn2;
2645 int max_dist1;
2646 int max_dist2;
2647 int num_moves;
2648 int lib;
2649 SGFTree *save_sgf_dumptree = sgf_dumptree;
2650 int save_count_variations = count_variations;
2651
2652 /* We turn off the sgf traces here to avoid cluttering them up with
2653 * tactical reading moves.
2654 */
2655 sgf_dumptree = NULL;
2656 count_variations = 0;
2657
2658 compute_connection_distances(str1, str2, FP(3.051), &conn1, 1);
2659 compute_connection_distances(str2, str1, FP(3.051), &conn2, 1);
2660
2661 if (findlib(str1, 1, &lib) == 1) {
2662 conn1.distances[lib] = 0;
2663 conn1.coming_from[lib] = NO_MOVE;
2664 conn2.distances[lib] = conn2.distances[str1];
2665 conn2.coming_from[lib] = conn1.coming_from[str1];
2666 }
2667
2668 if (findlib(str2, 1, &lib) == 1) {
2669 conn2.distances[lib] = 0;
2670 conn1.distances[lib] = conn1.distances[str2];
2671 }
2672
2673 max_dist1 = conn1.distances[str2];
2674 max_dist2 = conn2.distances[str1];
2675
2676 *total_distance = gg_min(max_dist1, max_dist2);
2677
2678 if (verbose > 0) {
2679 gprintf("%oVariation %d\n", save_count_variations);
2680 dump_stack();
2681 showboard(0);
2682 print_connection_distances(&conn1);
2683 print_connection_distances(&conn2);
2684 }
2685
2686 sgf_dumptree = save_sgf_dumptree;
2687 count_variations = save_count_variations;
2688
2689 num_moves = find_connection_moves(str1, str2, color_to_move,
2690 &conn1, &conn2, max_dist1, max_dist2,
2691 moves, *total_distance,
2692 HUGE_CONNECTION_DISTANCE);
2693 return num_moves;
2694}
2695
2696
2697static void
2698add_to_start_queue(int pos, int dist, struct connection_data *conn)
2699{
2700 conn->queue[conn->queue_end++] = pos;
2701 conn->distances[pos] = dist;
2702 conn->deltas[pos] = dist;
2703 conn->coming_from[pos] = NO_MOVE;
2704 conn->vulnerable1[pos] = NO_MOVE;
2705 conn->vulnerable2[pos] = NO_MOVE;
2706}
2707
2708
2709void
2710init_connection_data(int color, const signed char goal[BOARDMAX],
2711 int target, int cutoff,
2712 struct connection_data *conn, int speculative)
2713{
2714 int pos;
2715 signed char mark[BOARDMAX];
2716
2717 memset(mark, 0, BOARDMAX);
2718 VALGRIND_MAKE_WRITABLE(conn, sizeof(conn));
2719 clear_connection_data(conn);
2720
2721 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
2722 if (goal[pos]) {
2723 if (board[pos] == color) {
2724 int origin = find_origin(pos);
2725
2726 if (!mark[origin]) {
2727 add_to_start_queue(origin, FP(0.0), conn);
2728 mark[origin] = 1;
2729 }
2730 }
2731 else if (board[pos] == EMPTY)
2732 add_to_start_queue(pos, FP(1.0), conn);
2733 }
2734 }
2735
2736 conn->target = target;
2737 conn->cutoff_distance = cutoff;
2738 conn->speculative = speculative;
2739}
2740
2741static int
2742find_break_moves(int str, const signed char goal[BOARDMAX], int color_to_move,
2743 int moves[MAX_MOVES], int *total_distance)
2744{
2745 struct connection_data conn1;
2746 struct connection_data conn2;
2747 int max_dist1 = HUGE_CONNECTION_DISTANCE;
2748 int max_dist2;
2749 int num_moves;
2750 int str2 = NO_MOVE;
2751 int color = board[str];
2752 int lib;
2753 int k;
2754 SGFTree *save_sgf_dumptree = sgf_dumptree;
2755 int save_count_variations = count_variations;
2756
2757 /* We turn off the sgf traces here to avoid cluttering them up with
2758 * tactical reading moves.
2759 */
2760 sgf_dumptree = NULL;
2761 count_variations = 0;
2762
2763 compute_connection_distances(str, NO_MOVE, FP(2.501), &conn1, 1);
2764 for (k = 0; k < conn1.queue_end; k++)
2765 if (board[conn1.queue[k]] == color) {
2766 int stones[MAX_BOARD * MAX_BOARD];
2767 int num_stones = findstones(conn1.queue[k],
2768 MAX_BOARD * MAX_BOARD, stones);
2769 int i;
2770 for (i = 0; i < num_stones; i++) {
2771 if (goal[stones[i]]) {
2772 str2 = find_origin(stones[i]);
2773 TRACE("%oUsing %1m as secondary target.\n", str2);
2774 mark_string(str2, breakin_shadow, 1);
2775 break;
2776 }
2777 }
2778 if (i < num_stones)
2779 break;
2780 }
2781
2782 /* Add all stones in the goal to the queue. */
2783 init_connection_data(color, goal, str, FP(2.501), &conn2, 1);
2784
2785 for (k = 0; k < conn2.queue_end; k++) {
2786 if (max_dist1 > conn1.distances[conn2.queue[k]])
2787 max_dist1 = conn1.distances[conn2.queue[k]];
2788 }
2789
2790 spread_connection_distances(color, &conn2);
2791
2792 if (findlib(str, 1, &lib) == 1) {
2793 conn1.distances[lib] = 0;
2794 conn1.coming_from[lib] = NO_MOVE;
2795 conn2.distances[lib] = conn2.distances[str];
2796 conn2.coming_from[lib] = conn1.coming_from[str];
2797 }
2798
2799 max_dist2 = conn2.distances[str];
2800 *total_distance = gg_min(max_dist1, max_dist2);
2801
2802 /* Turn the sgf traces back on. */
2803 sgf_dumptree = save_sgf_dumptree;
2804 count_variations = save_count_variations;
2805
2806 if (verbose > 0) {
2807 gprintf("%oVariation %d\n", save_count_variations);
2808 dump_stack();
2809 showboard(0);
2810 print_connection_distances(&conn1);
2811 print_connection_distances(&conn2);
2812 }
2813
2814 {
2815 int cutoff = HUGE_CONNECTION_DISTANCE;
2816 if (breakin_depth - stackp <= 5)
2817 cutoff = FP(1.101) + (breakin_depth - stackp) * FP(0.15);
2818 num_moves = find_connection_moves(str, str2, color_to_move,
2819 &conn1, &conn2, max_dist1, max_dist2,
2820 moves, *total_distance, cutoff);
2821 }
2822
2823 if (color_to_move != board[str]) {
2824 int move;
2825 if (num_moves < MAX_MOVES
2826 && ON_BOARD(str2)
2827 && ladder_capture(str2, &move)) {
2828 moves[num_moves++] = move;
2829 }
2830 }
2831
2832 for (k = 0; k < num_moves; k++)
2833 breakin_shadow[moves[k]] = 1;
2834
2835 return num_moves;
2836}
2837
2838
2839/* Can (str) connect to goal[] if the other color moves first? */
2840static int
2841recursive_break(int str, const signed char goal[BOARDMAX], int *move,
2842 int has_passed,
2843 Hash_data *goal_hash)
2844{
2845 int color = board[str];
2846 int moves[MAX_MOVES];
2847 int num_moves;
2848 int distance = FP(0.0);
2849 int k;
2850 int xpos;
2851 int savemove = NO_MOVE;
2852 int savecode = 0;
2853 int tried_moves = 0;
2854 int retval;
2855
2856 SETUP_TRACE_INFO("recursive_break", str);
2857
2858 if (move)
2859 *move = NO_MOVE;
2860
2861 nodes_connect++;
2862 global_connection_node_counter++;
2863
2864 if (board[str] == EMPTY) {
2865 SGFTRACE(PASS_MOVE, 0, "one string already captured");
2866 return 0;
2867 }
2868
2869 if (nodes_connect > breakin_node_limit) {
2870 SGFTRACE(PASS_MOVE, 0, "connection node limit reached");
2871 return 0;
2872 }
2873
2874 if (stackp > breakin_depth) {
2875 SGFTRACE(PASS_MOVE, 0, "connection depth limit reached");
2876 return 0;
2877 }
2878
2879 str = find_origin(str);
2880 if (stackp <= depth && !has_passed
2881 && tt_get(&ttable, BREAK_IN, str, NO_MOVE, depth - stackp, goal_hash,
2882 &retval, NULL, &xpos) == 2) {
2883 /* FIXME: Use move for move ordering if tt_get() returned 1 */
2884 TRACE_CACHED_RESULT(retval, xpos);
2885 SGFTRACE(xpos, retval, "cached");
2886 if (move)
2887 *move = xpos;
2888 return retval;
2889 }
2890
2891#if 0
2892 if (trivial_connection(str1, str2, &xpos) == WIN) {
2893 SGFTRACE2(xpos, WIN, "trivial connection");
2894 READ_RETURN_HASH(BREAK_IN, str, depth - stackp, goal_hash,
2895 move, xpos, WIN);
2896 }
2897#endif
2898
2899 num_moves = find_break_moves(str, goal, color, moves, &distance);
2900
2901 for (k = 0; k < num_moves; k++) {
2902 int ko_move;
2903 xpos = moves[k];
2904
2905 if (komaster_trymove(xpos, color, "recursive_break", str,
2906 &ko_move, stackp <= ko_depth && savecode == 0)) {
2907 tried_moves++;
2908 if (!ko_move) {
2909 int acode = recursive_block(str, goal, NULL, has_passed, goal_hash);
2910 popgo();
2911 if (acode == 0) {
2912 SGFTRACE(xpos, WIN, "break effective");
2913 READ_RETURN_HASH(BREAK_IN, str, depth - stackp, goal_hash,
2914 move, xpos, WIN);
2915 }
2916 /* if the move works with ko we save it, then look for something
2917 * better.
2918 */
2919 UPDATE_SAVED_KO_RESULT(savecode, savemove, acode, xpos);
2920 }
2921 else {
2922 if (recursive_block(str, goal, NULL, has_passed, goal_hash) != WIN) {
2923 savemove = xpos;
2924 savecode = KO_B;
2925 }
2926 popgo();
2927 }
2928 }
2929 }
2930
2931 /* Because of a couple differences between the break-in and the
2932 * connection reading code, we can't afford to be as optimistic
2933 * as in recursive_connect2() here. See nando:32
2934 */
2935 if (tried_moves == 0 && distance < FP(0.89)) {
2936 SGFTRACE(NO_MOVE, WIN, "no move, probably connected");
2937 READ_RETURN_HASH(BREAK_IN, str, depth - stackp, goal_hash,
2938 move, NO_MOVE, WIN);
2939 }
2940
2941 if (savecode != 0) {
2942 SGFTRACE(savemove, savecode, "saved move");
2943 READ_RETURN_HASH(BREAK_IN, str, depth - stackp, goal_hash,
2944 move, savemove, savecode);
2945 }
2946
2947 SGFTRACE(0, 0, NULL);
2948 READ_RETURN_HASH(BREAK_IN, str, depth - stackp, goal_hash, move, NO_MOVE, 0);
2949}
2950
2951
2952/* Can (str) connect to goal[] if the other color moves first? */
2953static int
2954recursive_block(int str, const signed char goal[BOARDMAX], int *move,
2955 int has_passed, Hash_data *goal_hash)
2956{
2957 int color = board[str];
2958 int other = OTHER_COLOR(color);
2959 int moves[MAX_MOVES];
2960 int num_moves;
2961 int distance = FP(0.0);
2962 int k;
2963 int xpos;
2964 int savemove = NO_MOVE;
2965 int savecode = 0;
2966 int tried_moves = 0;
2967 int retval;
2968 SETUP_TRACE_INFO("recursive_block", str);
2969
2970 nodes_connect++;
2971 global_connection_node_counter++;
2972
2973 if (move)
2974 *move = NO_MOVE;
2975
2976 if (board[str] == EMPTY) {
2977 SGFTRACE(PASS_MOVE, WIN, "string already captured");
2978 return WIN;
2979 }
2980
2981#if 0
2982 if (same_string(str1, str2)) {
2983 SGFTRACE(PASS_MOVE, 0, "already connected");
2984 return 0;
2985 }
2986#endif
2987
2988 if (nodes_connect > breakin_node_limit) {
2989 SGFTRACE(PASS_MOVE, WIN, "connection node limit reached");
2990 return WIN;
2991 }
2992
2993 if (stackp > breakin_depth) {
2994 SGFTRACE(PASS_MOVE, WIN, "connection depth limit reached");
2995 return WIN;
2996 }
2997
2998 str = find_origin(str);
2999 if (stackp <= depth
3000 && tt_get(&ttable, BLOCK_OFF, str, NO_MOVE,
3001 depth - stackp, goal_hash, &retval, NULL, &xpos) == 2) {
3002 TRACE_CACHED_RESULT(retval, xpos);
3003 SGFTRACE(xpos, retval, "cached");
3004 if (move)
3005 *move = xpos;
3006 return retval;
3007 }
3008
3009 if (ladder_capture(str, &xpos) == WIN) {
3010 SGFTRACE(xpos, WIN, "string capturable");
3011 READ_RETURN_HASH(BLOCK_OFF, str, depth - stackp, goal_hash,
3012 move, xpos, WIN);
3013 }
3014
3015 num_moves = find_break_moves(str, goal, other, moves, &distance);
3016
3017 for (k = 0; k < num_moves; k++) {
3018 int ko_move;
3019 xpos = moves[k];
3020
3021 if (komaster_trymove(xpos, other, "recursive_block", str,
3022 &ko_move, stackp <= ko_depth && savecode == 0)) {
3023 tried_moves++;
3024 if (!ko_move) {
3025 int dcode = recursive_break(str, goal, NULL, has_passed, goal_hash);
3026 popgo();
3027 if (dcode == 0) {
3028 SGFTRACE(xpos, WIN, "block effective");
3029 READ_RETURN_HASH(BLOCK_OFF, str, depth - stackp, goal_hash,
3030 move, xpos, WIN);
3031 }
3032 /* if the move works with ko we save it, then look for something
3033 * better.
3034 */
3035 UPDATE_SAVED_KO_RESULT(savecode, savemove, dcode, xpos);
3036 }
3037 else {
3038 if (recursive_break(str, goal, NULL,
3039 has_passed, goal_hash) != WIN) {
3040 savemove = xpos;
3041 savecode = KO_B;
3042 }
3043 popgo();
3044 }
3045 }
3046 }
3047
3048 if (tried_moves == 0
3049 && distance >= FP(1.0)
3050 && (has_passed
3051 || !recursive_break(str, goal, NULL, 1,
3052 goal_hash))) {
3053 SGFTRACE(NO_MOVE, WIN, "no move, probably disconnected");
3054 READ_RETURN_HASH(BLOCK_OFF, str, depth - stackp, goal_hash,
3055 move, NO_MOVE, WIN);
3056 }
3057
3058 if (savecode != 0) {
3059 SGFTRACE(savemove, savecode, "saved move");
3060 READ_RETURN_HASH(BLOCK_OFF, str, depth - stackp, goal_hash,
3061 move, savemove, savecode);
3062 }
3063
3064 SGFTRACE(0, 0, NULL);
3065 READ_RETURN_HASH(BLOCK_OFF, str, depth - stackp, goal_hash,
3066 move, NO_MOVE, 0);
3067}
3068
3069
3070
3071/* Externally callable frontend to recursive_break.
3072 * Returns WIN if (str) can connect to the area goal[] (which may or may
3073 * not contain stones), if he gets the first move.
3074 */
3075int
3076break_in(int str, const signed char goal[BOARDMAX], int *move)
3077{
3078 int dummy_move;
3079 int save_verbose;
3080 int result;
3081 int reading_nodes_when_called = get_reading_node_counter();
3082 double start = 0;
3083 int tactical_nodes;
3084 Hash_data goal_hash = goal_to_hashvalue(goal);
3085
3086 if (move == NULL)
3087 move = &dummy_move;
3088
3089 nodes_connect = 0;
3090 *move = PASS_MOVE;
3091
3092 if (board[str] == EMPTY)
3093 return 0;
3094 str = find_origin(str);
3095
3096 if (search_persistent_breakin_cache(BREAK_IN, str, &goal_hash,
3097 breakin_node_limit, &result, move)) {
3098 if (debug & DEBUG_BREAKIN) {
3099 gprintf("Break-in from %1m to:\n", str);
3100 goaldump(goal);
3101 gprintf("Result cached: %s %1m\n", result_to_string(result), *move);
3102 }
3103 return result;
3104 }
3105
3106 save_verbose = verbose;
3107 if (verbose > 0)
3108 verbose--;
3109 start = gg_cputime();
3110 memcpy(breakin_shadow, goal, sizeof(breakin_shadow));
3111 result = recursive_break(str, goal, move, 0, &goal_hash);
3112 verbose = save_verbose;
3113 tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
3114 if (debug & DEBUG_BREAKIN) {
3115 gprintf("%obreak_in %1M, result %s %1M (%d, %d nodes, %f seconds)\n",
3116 str, result_to_string(result), *move,
3117 nodes_connect, tactical_nodes, gg_cputime() - start);
3118 goaldump(goal);
3119 dump_stack();
3120 }
3121 if (0) {
3122 gprintf("%obreak_in %1m %d %1m ", str, result, *move);
3123 dump_stack();
3124 goaldump(goal);
3125 }
3126 store_persistent_breakin_cache(BREAK_IN, str, &goal_hash, result, *move,
3127 tactical_nodes, breakin_node_limit,
3128 breakin_shadow);
3129
3130 return result;
3131}
3132
3133
3134/* Externably callable frontend to recursive_block_off.
3135 * Returns WIN if (str) cannot connect to the area goal[] (which may or may
3136 * not contain stones), if the other color moves first.
3137 */
3138int
3139block_off(int str, const signed char goal[BOARDMAX], int *move)
3140{
3141 int dummy_move;
3142 int result;
3143 int save_verbose;
3144 int reading_nodes_when_called = get_reading_node_counter();
3145 double start = 0;
3146 int tactical_nodes;
3147 Hash_data goal_hash = goal_to_hashvalue(goal);
3148
3149 if (move == NULL)
3150 move = &dummy_move;
3151
3152 nodes_connect = 0;
3153 *move = PASS_MOVE;
3154
3155 str = find_origin(str);
3156 if (search_persistent_breakin_cache(BLOCK_OFF, str, &goal_hash,
3157 breakin_node_limit, &result, move)) {
3158 if (debug & DEBUG_BREAKIN) {
3159 gprintf("Blocking off %1m from:\n", str);
3160 goaldump(goal);
3161 gprintf("Result cached: %s %1m\n", result_to_string(result), *move);
3162 }
3163 return result;
3164 }
3165
3166 save_verbose = verbose;
3167 if (verbose > 0)
3168 verbose--;
3169 start = gg_cputime();
3170 memcpy(breakin_shadow, goal, sizeof(breakin_shadow));
3171 result = recursive_block(str, goal, move, 0, &goal_hash);
3172 verbose = save_verbose;
3173 tactical_nodes = get_reading_node_counter() - reading_nodes_when_called;
3174
3175 if (debug & DEBUG_BREAKIN) {
3176 gprintf("%oblock_off %1m, result %s %1m (%d, %d nodes, %f seconds)\n",
3177 str, result_to_string(result), *move,
3178 nodes_connect, tactical_nodes, gg_cputime() - start);
3179 goaldump(goal);
3180 dump_stack();
3181 }
3182 if (0) {
3183 gprintf("%oblock_off %1m %d %1m ", str, result, *move);
3184 goaldump(goal);
3185 dump_stack();
3186 }
3187 store_persistent_breakin_cache(BLOCK_OFF, str, &goal_hash, result, *move,
3188 tactical_nodes, breakin_node_limit,
3189 breakin_shadow);
3190
3191 return result;
3192}
3193
3194
3195/* Store a possibly expensive decision for later evaluation. The
3196 * data getting stored should be self-explanatory.
3197 * The job of the helper function is to
3198 * - decide whether the spreading step will be allowed (typically
3199 * depending on a latter)
3200 * - add the relevant positions to the connection queue in case the test
3201 * was successful.
3202 *
3203 * Elements in the heap are kept sorted according to smallest distance.
3204 */
3205static void
3206push_connection_heap_entry(struct connection_data *conn, int distance,
3207 int coming_from, int target,
3208 connection_helper_fn_ptr helper)
3209{
3210 int k;
3211 int parent;
3212 struct heap_entry *new_entry = &conn->heap_data[conn->heap_data_size];
3213
3214 gg_assert(conn->heap_data_size < 4 * BOARDMAX);
3215 gg_assert(conn->heap_size < BOARDMAX);
3216
3217 /* Create new heap entry. */
3218 new_entry->distance = distance;
3219 new_entry->coming_from = coming_from;
3220 new_entry->target = target;
3221 new_entry->helper = helper;
3222
3223 /* And insert it into the heap. */
3224 conn->heap_data_size++;
3225
3226 for (k = conn->heap_size++; k > 0; k = parent) {
3227 parent = (k - 1) / 2;
3228 if (conn->heap[parent]->distance <= distance)
3229 break;
3230
3231 conn->heap[k] = conn->heap[parent];
3232 }
3233
3234 conn->heap[k] = new_entry;
3235}
3236
3237
3238/* Delete the first entry from the heap. */
3239static void
3240pop_connection_heap_entry(struct connection_data *conn)
3241{
3242 int k;
3243 int child;
3244
3245 conn->heap_size--;
3246 for (k = 0; 2 * k + 1 < conn->heap_size; k = child) {
3247 child = 2 * k + 1;
3248 if (conn->heap[child]->distance > conn->heap[child + 1]->distance)
3249 child++;
3250 if (conn->heap[child]->distance >= conn->heap[conn->heap_size]->distance)
3251 break;
3252
3253 conn->heap[k] = conn->heap[child];
3254 }
3255
3256 conn->heap[k] = conn->heap[conn->heap_size];
3257}
3258
3259
3260#define ENQUEUE(conn, from, pos, dist, delta, v1, v2) \
3261 do { \
3262 if (dist < conn->distances[pos]) { \
3263 if (conn->distances[pos] == HUGE_CONNECTION_DISTANCE) \
3264 conn->queue[conn->queue_end++] = pos; \
3265 conn->distances[pos] = dist; \
3266 conn->deltas[pos] = delta; \
3267 conn->coming_from[pos] = from; \
3268 conn->vulnerable1[pos] = v1; \
3269 conn->vulnerable2[pos] = v2; \
3270 } \
3271 } while(0)
3272
3273#define ENQUEUE_STONE(conn, from, pos, dist, delta, v1, v2) \
3274 do { \
3275 int origin = find_origin(pos); \
3276 if (dist < conn->distances[origin]) { \
3277 if (conn->distances[origin] == HUGE_CONNECTION_DISTANCE) \
3278 conn->queue[conn->queue_end++] = origin; \
3279 conn->distances[origin] = dist; \
3280 conn->deltas[origin] = delta; \
3281 conn->coming_from[origin] = from; \
3282 conn->vulnerable1[origin] = v1; \
3283 conn->vulnerable2[origin] = v2; \
3284 if (origin == conn->target && dist < conn->cutoff_distance) \
3285 conn->cutoff_distance = dist - FP(0.0001); \
3286 } \
3287 } while(0)
3288
3289
3290static void
3291case_6_7_helper(struct connection_data *conn, int color)
3292{
3293 struct heap_entry *data = conn->heap[0];
3294 int pos = data->coming_from;
3295 int apos = data->target;
3296 int other = OTHER_COLOR(color);
3297
3298 if (ladder_capturable(apos, other))
3299 ENQUEUE(conn, pos, apos, data->distance, FP(0.6), apos, NO_MOVE);
3300 else {
3301 int this_delta
3302 = FP(0.85) + FP(0.05) * gg_min(approxlib(apos, other, 5, NULL), 5);
3303 ENQUEUE(conn, pos, apos, data->distance + this_delta - FP(0.6), this_delta,
3304 NO_MOVE, NO_MOVE);
3305 }
3306}
3307
3308
3309static void
3310case_9_10_helper(struct connection_data *conn, int color)
3311{
3312 struct heap_entry *data = conn->heap[0];
3313 int pos = data->coming_from;
3314 int apos = data->target;
3315
3316 UNUSED(color);
3317
3318 if (no_escape_from_ladder(apos))
3319 ENQUEUE_STONE(conn, pos, apos, data->distance, FP(0.3), NO_MOVE, NO_MOVE);
3320 else {
3321 if (conn->speculative) {
3322 ENQUEUE_STONE(conn, pos, apos, data->distance + FP(0.7), FP(1.0),
3323 NO_MOVE, NO_MOVE);
3324 }
3325 else {
3326 ENQUEUE_STONE(conn, pos, apos, data->distance + FP(0.8), FP(1.1),
3327 NO_MOVE, NO_MOVE);
3328 }
3329 }
3330}
3331
3332
3333static void
3334case_16_17_18_helper(struct connection_data *conn, int color)
3335{
3336 struct heap_entry *data = conn->heap[0];
3337 int pos = data->coming_from;
3338 int bpos = data->target;
3339 int apos = SOUTH(gg_min(pos, bpos));
3340 int gpos = NORTH(gg_max(pos, bpos));
3341 int other = OTHER_COLOR(color);
3342
3343 if (board[apos] == EMPTY
3344 && does_secure_through_ladder(color, bpos, apos))
3345 ENQUEUE(conn, pos, bpos, data->distance, FP(1.0), apos, NO_MOVE);
3346 else if (board[gpos] == EMPTY
3347 && does_secure_through_ladder(color, bpos, gpos))
3348 ENQUEUE(conn, pos, bpos, data->distance, FP(1.0), gpos, NO_MOVE);
3349 else if (conn->distances[bpos] > data->distance + FP(0.3)) {
3350 if (board[apos] == EMPTY
3351 && board[gpos] == other
3352 && countlib(gpos) <= 3)
3353 ENQUEUE(conn, pos, bpos, data->distance + FP(0.3), FP(1.0),
3354 apos, NO_MOVE);
3355 else if (board[gpos] == EMPTY
3356 && board[apos] == other
3357 && countlib(apos) <= 3)
3358 ENQUEUE(conn, pos, bpos, data->distance + FP(0.3), FP(1.0),
3359 gpos, NO_MOVE);
3360 else
3361 ENQUEUE(conn, pos, bpos, data->distance + FP(0.6), FP(0.9),
3362 NO_MOVE, NO_MOVE);
3363 }
3364}
3365
3366
3367/* Do the real work of computing connection distances.
3368 * This is a rough approximation of the number of moves required to secure
3369 * a connection. We also compute delta values which are intended to tell how
3370 * big difference a particular move locally has on the connection
3371 * distance. However, remember that this is only a heuristic with the
3372 * sole purpose of helping to find relevant moves for connection
3373 * problems.
3374 *
3375 * The algorithm is to propagate connection values outwards using a
3376 * breadth-first searching strategy, implemented through an implicitly
3377 * sorted queue. The propagation to new vertices depends on
3378 * geometrical features with significance for connections. E.g. a
3379 * bamboo joint is recognized and the distance added when passing
3380 * through it is small. New points are added to the queue through the
3381 * ENQUEUE macro above. This checks whether the point has already been
3382 * entered on the queue and updates the distance and delta values if
3383 * the previous ones were worse. When a stone is entered, all stones
3384 * of the string are added to the queue simultaneously.
3385 *
3386 * (target) is the other string when called from find_connection_moves().
3387 * (It can be set to NO_MOVE otherwise.)
3388 *
3389 * The propagation is inhibited when the distance becomes too large,
3390 * or larger than the shortest path found to the target so far.
3391 *
3392 *
3393 * The purpose of the fields called vulnerable is to keep track of
3394 * points where the attacker can threaten an individual
3395 * connection. For example the diagonal formation
3396 *
3397 * .O
3398 * O.
3399 *
3400 * is considered a small distance link but both the empty vertices are
3401 * marked as vulnerable. Thus if we are computing connection distance
3402 * from the lower left O in this diagram,
3403 *
3404 * XXX XXX
3405 * .O. .O.
3406 * O.O OaO
3407 * .X. .X.
3408 *
3409 * the distance to the middle O is small but the second diagonal link
3410 * to the lower right O stone is not given a small distance since a
3411 * had already been marked as vulnerable.
3412 *
3413 * It should also be pointed out that this reasoning is not relevant
3414 * in this position where X has no cutting potential,
3415 *
3416 * XXX XXX
3417 * .O. .O.
3418 * O.O OaO
3419 * ... ...
3420 *
3421 * That is because there is a pattern directly recognizing the safe
3422 * link between the two lower stones, without taking the longer road
3423 * over the two diagonal links.
3424 *
3425 * (color) is the color for which we are computing connection distances,
3426 * (target) the position we want to reach (can be set to NO_MOVE),
3427 * (*conn) has to have the queue initialized with the positions
3428 * from which we want to know the distances,
3429 * (cutoff_distance) is the highest distance before we give up,
3430 * (speculative) controls some special cases in the propagation rules
3431 * below.
3432 *
3433 * As an optimization, new points are either added directly via the ENQUEUE
3434 * macro if the necessary test is an immediate (usually purely geometric)
3435 * check, or if the decision is more expensive (usually depending on a
3436 * ladder), it gets postponed and stored via push_connection_heap_entry()
3437 * for later evaluation.
3438 */
3439
3440void
3441spread_connection_distances(int color, struct connection_data *conn)
3442{
3443 int other = OTHER_COLOR(color);
3444 int stones[MAX_BOARD * MAX_BOARD];
3445 int num_stones = 0;
3446 int stone = 0;
3447
3448 /* Loop until we reach the end of the queue. */
3449 while (conn->queue_start < conn->queue_end || conn->heap_size > 0) {
3450 int k;
3451 int pos;
3452 int distance;
3453
3454 /* Delete heap entries for positions that have already been reached
3455 * with smaller distance.
3456 */
3457 while (conn->heap_size > 0
3458 && conn->heap[0]->distance >= conn->distances[conn->heap[0]->target])
3459 pop_connection_heap_entry(conn);
3460
3461 if (stone == num_stones) {
3462 int best_index = -1;
3463 int smallest_dist = HUGE_CONNECTION_DISTANCE;
3464
3465 if (conn->queue_start == conn->queue_end) {
3466 if (conn->heap_size > 0) {
3467 conn->heap[0]->helper(conn, color);
3468 pop_connection_heap_entry(conn);
3469 }
3470
3471 continue;
3472 }
3473
3474 gg_assert(conn->queue_end <= MAX_BOARD * MAX_BOARD);
3475
3476 /* Find the smallest distance among the queued points. */
3477 for (k = conn->queue_start; k < conn->queue_end; k++) {
3478 if (conn->distances[conn->queue[k]] < smallest_dist) {
3479 smallest_dist = conn->distances[conn->queue[k]];
3480 best_index = k;
3481 }
3482 }
3483
3484 /* Exchange the best point with the first element in the queue. */
3485 if (best_index != conn->queue_start) {
3486 int temp = conn->queue[conn->queue_start];
3487 conn->queue[conn->queue_start] = conn->queue[best_index];
3488 conn->queue[best_index] = temp;
3489 }
3490
3491 /* If the first element in heap has smaller distance than the
3492 * smallest we have found so far, call the relevant helper function
3493 * now, and delete the heap entry.
3494 */
3495 if (conn->heap_size > 0 && conn->heap[0]->distance < smallest_dist) {
3496 conn->heap[0]->helper(conn, color);
3497 pop_connection_heap_entry(conn);
3498 continue;
3499 }
3500
3501 /* Now we are ready to pick the first element in the queue and
3502 * process it.
3503 */
3504 pos = conn->queue[conn->queue_start++];
3505 if (board[pos] != EMPTY) {
3506 num_stones = findstones(pos, MAX_BOARD * MAX_BOARD, stones);
3507 pos = stones[0];
3508 stone = 1;
3509 }
3510 }
3511 else {
3512 pos = stones[stone++];
3513 conn->distances[pos] = conn->distances[stones[0]];
3514 conn->deltas[pos] = conn->deltas[stones[0]];
3515 conn->coming_from[pos] = conn->coming_from[stones[0]];
3516 conn->vulnerable1[pos] = conn->vulnerable1[stones[0]];
3517 conn->vulnerable2[pos] = conn->vulnerable2[stones[0]];
3518 }
3519
3520 /* No further propagation if the distance is too large. */
3521 distance = conn->distances[pos];
3522 if (distance > conn->cutoff_distance)
3523 break;
3524
3525 /* Search for new vertices to propagate to. */
3526 if (board[pos] == color) {
3527 for (k = 0; k < 4; k++) {
3528 /* List of relative coordinates. (pos) is marked by *.
3529 *
3530 * jef.
3531 * igb.
3532 * kh*ac
3533 * ....
3534 *
3535 */
3536 int right = delta[k];
3537 int up = delta[(k+1)%4];
3538
3539 /* FIXME: Compactify this list. */
3540 int apos = pos + right;
3541 int bpos = pos + right + up;
3542 int cpos = pos + 2 * right;
3543 int epos = pos + 2*up;
3544 int fpos = pos + right + 2*up;
3545 int gpos = pos + up;
3546 int hpos = pos - right;
3547 int ipos = pos - right + up;
3548 int jpos = pos - right + 2 * up;
3549 int kpos = pos - 2 * right;
3550
3551 /* Case 1. "a" is empty and would be suicide for the opponent. */
3552 if (board[apos] == EMPTY && is_suicide(apos, other))
3553 ENQUEUE(conn, pos, apos, distance, FP(0.0), apos, NO_MOVE);
3554
3555 /* Case 2. "a" is empty and would be self atari for the opponent. */
3556 if (board[apos] == EMPTY
3557 && conn->distances[apos] > distance + FP(0.1)
3558 && is_self_atari(apos, other)) {
3559 int lib;
3560 int vulnerable1 = NO_MOVE;
3561 int vulnerable2 = NO_MOVE;
3562 if (approxlib(apos, other, 1, &lib) >= 1) {
3563 if (approxlib(lib, other, 2, NULL) > 2)
3564 vulnerable1 = lib;
3565 if (countlib(pos) == 2) {
3566 int i;
3567 for (i = 0; i < 4; i++) {
3568 if (board[lib + delta[i]] == EMPTY
3569 && lib + delta[i] != apos
3570 && trymove(lib + delta[i], other,
3571 "compute_connection_distances", pos)) {
3572 if (ladder_capture(pos, NULL)) {
3573 vulnerable2 = lib + delta[i];
3574 popgo();
3575 break;
3576 }
3577 popgo();
3578 }
3579 }
3580 }
3581 }
3582
3583 if (!common_vulnerabilities(conn->vulnerable1[pos],
3584 conn->vulnerable2[pos],
3585 vulnerable1, vulnerable2, color)) {
3586 ENQUEUE(conn, pos, apos, distance + FP(0.1), FP(0.1),
3587 vulnerable1, vulnerable2);
3588 }
3589 }
3590
3591 /* Case 3. Bamboo joint of "*" + "a" to "e" + "f" through "b" and "g".
3592 * Notice that the order of these tests is significant. We must
3593 * check bpos before fpos and epos to avoid accessing memory
3594 * outside the board array. (Notice that fpos is two steps away
3595 * from pos, which we know is on the board.)
3596 */
3597 if (board[apos] == color && board[bpos] == EMPTY
3598 && board[fpos] == color && board[epos] == color
3599 && board[gpos] == EMPTY) {
3600 ENQUEUE(conn, pos, bpos, distance + FP(0.1), FP(0.1),
3601 NO_MOVE, NO_MOVE);
3602 ENQUEUE(conn, pos, gpos, distance + FP(0.1), FP(0.1),
3603 NO_MOVE, NO_MOVE);
3604 }
3605
3606 /* Case 4. Diagonal connection to another stone "b" through
3607 * empty vertices "a" and "g".
3608 */
3609 if (board[bpos] == color
3610 && board[apos] == EMPTY
3611 && board[gpos] == EMPTY
3612 && !common_vulnerabilities(conn->vulnerable1[pos],
3613 conn->vulnerable2[pos],
3614 apos, gpos, color)
3615 && conn->distances[bpos] > distance + FP(0.1)) {
3616#if 0
3617 ENQUEUE(conn, pos, apos, distance + FP(0.2), FP(0.2),
3618 NO_MOVE, NO_MOVE);
3619 ENQUEUE(conn, pos, gpos, distance + FP(0.2), FP(0.2),
3620 NO_MOVE, NO_MOVE);
3621#endif
3622 ENQUEUE_STONE(conn, pos, bpos, distance + FP(0.1), FP(0.1),
3623 apos, gpos);
3624 }
3625
3626 /* Case 5. Almost bamboo joint.
3627 *
3628 */
3629 if (board[gpos] == EMPTY
3630 && board[epos] == color
3631 && conn->distances[epos] > distance + FP(0.2)
3632 && approxlib(gpos, other, 3, NULL) <= 2) {
3633 if (board[bpos] == EMPTY
3634 && approxlib(bpos, color, 3, NULL) >= 3
3635 && (board[apos] == color
3636 || (board[apos] == EMPTY
3637 && countlib(pos) > 2
3638 && !common_vulnerabilities(conn->vulnerable1[pos],
3639 conn->vulnerable2[pos],
3640 apos, gpos, color)
3641 && approxlib(apos, other, 3, NULL) <= 2))
3642 && (board[fpos] == color
3643 || (board[fpos] == EMPTY
3644 && countlib(epos) > 2
3645 && !common_vulnerabilities(conn->vulnerable1[pos],
3646 conn->vulnerable2[pos],
3647 fpos, gpos, color)
3648 && approxlib(fpos, other, 3, NULL) <= 2))) {
3649 if (board[apos] == EMPTY && board[fpos] == EMPTY) {
3650 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3651 apos, fpos);
3652 }
3653 else if (board[apos] == EMPTY && board[fpos] != EMPTY) {
3654 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3655 apos, NO_MOVE);
3656 }
3657 else if (board[apos] != EMPTY && board[fpos] == EMPTY) {
3658 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3659 fpos, NO_MOVE);
3660 }
3661 else if (board[apos] != EMPTY && board[fpos] != EMPTY) {
3662 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3663 NO_MOVE, NO_MOVE);
3664 }
3665 }
3666
3667 if (board[ipos] == EMPTY
3668 && approxlib(ipos, color, 3, NULL) >= 3
3669 && (board[hpos] == color
3670 || (board[hpos] == EMPTY
3671 && countlib(pos) > 2
3672 && !common_vulnerabilities(conn->vulnerable1[pos],
3673 conn->vulnerable2[pos],
3674 hpos, gpos, color)
3675 && approxlib(hpos, other, 3, NULL) <= 2))
3676 && (board[jpos] == color
3677 || (board[jpos] == EMPTY
3678 && countlib(epos) > 2
3679 && !common_vulnerabilities(conn->vulnerable1[pos],
3680 conn->vulnerable2[pos],
3681 jpos, gpos, color)
3682 && approxlib(jpos, other, 3, NULL) <= 2))) {
3683 if (board[hpos] == EMPTY && board[jpos] == EMPTY) {
3684 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3685 hpos, jpos);
3686 }
3687 else if (board[hpos] == EMPTY && board[jpos] != EMPTY) {
3688 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3689 hpos, NO_MOVE);
3690 }
3691 else if (board[hpos] != EMPTY && board[jpos] == EMPTY) {
3692 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3693 jpos, NO_MOVE);
3694 }
3695 else if (board[hpos] != EMPTY && board[jpos] != EMPTY) {
3696 ENQUEUE_STONE(conn, pos, epos, distance + FP(0.2), FP(0.2),
3697 NO_MOVE, NO_MOVE);
3698 }
3699 }
3700 }
3701
3702 /* Case 6. "a" is empty and an opponent move can be captured
3703 * in a ladder.
3704 *
3705 * Case 7. "a" is empty.
3706 */
3707 if (board[apos] == EMPTY && conn->distances[apos] > distance + FP(0.6)) {
3708 push_connection_heap_entry(conn, distance + FP(0.6), pos, apos,
3709 case_6_7_helper);
3710 }
3711
3712 /* Case 8. Adjacent opponent stone at "a" which can't avoid atari.
3713 */
3714 if (board[apos] == other
3715 && conn->distances[apos] > distance + FP(0.1)
3716 && no_escape_from_atari(apos)) {
3717 ENQUEUE_STONE(conn, pos, apos, distance + FP(0.1), FP(0.1),
3718 NO_MOVE, NO_MOVE);
3719 }
3720
3721 /* Case 9. Adjacent opponent stone at "a" which can't avoid
3722 * ladder capture.
3723 *
3724 * Case 10. "a" is occupied by opponent.
3725 */
3726 if (board[apos] == other && conn->distances[apos] > distance + FP(0.3)) {
3727 push_connection_heap_entry(conn, distance + FP(0.3), pos, apos,
3728 case_9_10_helper);
3729 }
3730
3731 /* Case 11. Diagonal connection to empty vertex "b" through
3732 * empty vertex "a" or "g", which makes "a" or "g" self-atari
3733 * for opponent.
3734 */
3735 if (board[bpos] == EMPTY
3736 && board[apos] == EMPTY
3737 && conn->distances[bpos] > distance + FP(1.1)
3738 && does_secure(color, bpos, apos)) {
3739 ENQUEUE(conn, pos, bpos, distance + FP(1.1), FP(1.0), apos, NO_MOVE);
3740 }
3741
3742 if (board[bpos] == EMPTY
3743 && board[gpos] == EMPTY
3744 && conn->distances[bpos] > distance + FP(1.1)
3745 && does_secure(color, bpos, gpos)) {
3746 ENQUEUE(conn, pos, bpos, distance + FP(1.1), FP(1.0), gpos, NO_MOVE);
3747 }
3748
3749 /* Case 12. One-space jump to empty vertex "e" through empty
3750 * vertex "g", which makes "g" self-atari for opponent.
3751 */
3752 if (board[gpos] == EMPTY
3753 && board[epos] == EMPTY
3754 && conn->distances[epos] > distance + FP(1.1)
3755 && does_secure(color, epos, gpos)) {
3756 ENQUEUE(conn, pos, epos, distance + FP(1.1), FP(1.0), gpos, NO_MOVE);
3757 }
3758
3759 /* Case 13. One-space jump to empty vertex "e" through empty
3760 * vertex "g", making a bamboo joint.
3761 */
3762 if (board[gpos] == EMPTY
3763 && board[epos] == EMPTY
3764 && conn->distances[epos] > distance + FP(1.1)
3765 && ((board[apos] == color && board[fpos] == color
3766 && board[bpos] == EMPTY)
3767 || (board[hpos] == color && board[jpos] == color
3768 && board[ipos] == EMPTY))) {
3769 ENQUEUE(conn, pos, epos, distance + FP(1.1), FP(1.0), gpos, NO_MOVE);
3770 }
3771
3772 /* Case 14. Diagonal connection to empty vertex "b" through
3773 * empty vertices "a" and "g".
3774 */
3775 if (board[bpos] == EMPTY
3776 && board[apos] == EMPTY && board[gpos] == EMPTY
3777 && conn->distances[bpos] > distance + FP(1.3)) {
3778 ENQUEUE(conn, pos, bpos, distance + FP(1.3), FP(1.0), apos, gpos);
3779 }
3780
3781 /* Case 15. Keima to "f" or "j" on edge. and one space jump on
3782 * first or second line.
3783 */
3784 if (board[apos] == EMPTY
3785 && board[bpos] == EMPTY
3786 && board[gpos] == EMPTY
3787 && board[epos] == EMPTY
3788 && board[fpos] == EMPTY
3789 && (conn->distances[fpos] > distance + FP(1.3)
3790 || conn->distances[epos] > distance + FP(1.3))
3791 && countlib(pos) >= 3
3792 && (!ON_BOARD(cpos) || !ON_BOARD(hpos))) {
3793 ENQUEUE(conn, pos, fpos, distance + FP(1.3), FP(1.0),
3794 NO_MOVE, NO_MOVE);
3795 ENQUEUE(conn, pos, epos, distance + FP(1.3), FP(1.0),
3796 NO_MOVE, NO_MOVE);
3797 }
3798
3799 if (board[hpos] == EMPTY
3800 && board[ipos] == EMPTY
3801 && board[gpos] == EMPTY
3802 && board[epos] == EMPTY
3803 && board[jpos] == EMPTY
3804 && (conn->distances[jpos] > distance + FP(1.3)
3805 || conn->distances[epos] > distance + FP(1.3))
3806 && countlib(pos) >= 3
3807 && (!ON_BOARD(apos) || !ON_BOARD(kpos))) {
3808 ENQUEUE(conn, pos, jpos, distance + FP(1.3), FP(1.0),
3809 NO_MOVE, NO_MOVE);
3810 ENQUEUE(conn, pos, epos, distance + FP(1.3), FP(1.0),
3811 NO_MOVE, NO_MOVE);
3812 }
3813
3814 /* Case 16. Diagonal connection to empty vertex "b" through
3815 * empty vertex "a" or "g", which allows opponent move at "a"
3816 * or "g" to be captured in a ladder.
3817 *
3818 * Case 17. Diagonal connection to empty vertex "b" through
3819 * one empty and one opponent vertex "a" and "g", where
3820 * the opponent stone is short of liberties.
3821 *
3822 * Case 18. Diagonal connection to empty vertex "b" through
3823 * empty vertex "a" or "g", with no particular properties.
3824 */
3825 if (board[bpos] == EMPTY
3826 && (board[apos] == EMPTY || board[gpos] == EMPTY)
3827 && conn->distances[bpos] > distance + FP(1.2)) {
3828 push_connection_heap_entry(conn, distance + FP(1.2), pos, bpos,
3829 case_16_17_18_helper);
3830 }
3831
3832 /* Case 19. Clamp at "e" of single stone at "g". */
3833 if (board[gpos] == other
3834 && board[epos] == EMPTY
3835 && conn->distances[epos] > distance + FP(2.0)
3836 && countstones(gpos) == 1) {
3837 ENQUEUE(conn, pos, epos, distance + FP(2.0), FP(1.0),
3838 NO_MOVE, NO_MOVE);
3839 }
3840
3841 /* Case 20. Diagonal connection to empty vertex "b" through
3842 * opponent stones "a" or "g" with few liberties.
3843 */
3844 if (board[bpos] == EMPTY
3845 && board[apos] == other
3846 && board[gpos] == other
3847 && conn->distances[bpos] > distance + FP(2.0)
3848 && (countlib(apos) + countlib(gpos) <= 6)) {
3849 ENQUEUE(conn, pos, bpos, distance + FP(2.0), FP(1.0),
3850 NO_MOVE, NO_MOVE);
3851 }
3852
3853 /* Case 21. Diagonal connection to own stone "b" through
3854 * opponent stones "a" or "g" with few liberties.
3855 */
3856 if (board[bpos] == color
3857 && board[apos] == other
3858 && board[gpos] == other
3859 && conn->distances[bpos] > distance + FP(2.0)
3860 && (countlib(apos) + countlib(gpos) <= 5)) {
3861 ENQUEUE_STONE(conn, pos, bpos, distance + FP(2.0), FP(1.0),
3862 NO_MOVE, NO_MOVE);
3863 }
3864 }
3865 }
3866 else if (board[pos] == EMPTY
3867 || (board[pos] == other
3868 && countlib(pos) <= 2
3869 && no_escape_from_ladder(pos))) {
3870 for (k = 0; k < 4; k++) {
3871 /* List of relative coordinates. (pos) is marked by *.
3872 *
3873 * jef.
3874 * igb.
3875 * kh*ac
3876 * .d.
3877 *
3878 */
3879 int right = delta[k];
3880 int up = delta[(k+1)%4];
3881
3882 /* FIXME: Compactify this list. */
3883 int apos = pos + right;
3884 int bpos = pos + right + up;
3885#if 0
3886 int cpos = pos + 2 * right;
3887 int epos = pos + 2*up;
3888 int fpos = pos + right + 2*up;
3889#endif
3890 int gpos = pos + up;
3891#if 0
3892 int hpos = pos - right;
3893 int ipos = pos - right + up;
3894 int jpos = pos - right + 2 * up;
3895 int kpos = pos - 2 * right;
3896#endif
3897
3898 if (board[apos] == color) {
3899 ENQUEUE_STONE(conn, pos, apos, distance, FP(0.0),
3900 conn->vulnerable1[pos], conn->vulnerable2[pos]);
3901 }
3902 else if (board[apos] == EMPTY) {
3903 int this_delta
3904 = FP(0.8) + FP(0.05) * gg_min(approxlib(apos, other, 6, NULL), 6);
3905 ENQUEUE(conn, pos, apos, distance + this_delta, this_delta,
3906 NO_MOVE, NO_MOVE);
3907 }
3908 else if (board[apos] == other) {
3909 ENQUEUE_STONE(conn, pos, apos, distance + FP(1.0), FP(1.0),
3910 NO_MOVE, NO_MOVE);
3911 }
3912
3913 /* Case 1. Diagonal connection to empty vertex "b" through
3914 * empty vertices "a" and "g".
3915 */
3916 if (board[bpos] == EMPTY
3917 && board[apos] == EMPTY
3918 && board[gpos] == EMPTY
3919 && conn->distances[bpos] > distance + FP(1.5)) {
3920 ENQUEUE(conn, pos, bpos, distance + FP(1.5), FP(1.0),
3921 NO_MOVE, NO_MOVE);
3922 }
3923
3924 /* Case 2. Diagonal connection to friendly stone at "b" through
3925 * empty vertices "a" and "g".
3926 */
3927 if (board[bpos] == color
3928 && board[apos] == EMPTY
3929 && board[gpos] == EMPTY
3930 && conn->distances[bpos] > distance + FP(1.3)) {
3931 ENQUEUE_STONE(conn, pos, bpos, distance + FP(1.3), FP(1.0),
3932 NO_MOVE, NO_MOVE);
3933 }
3934 }
3935 }
3936 }
3937}
3938
3939
3940void
3941sort_connection_queue_tail(struct connection_data *conn)
3942{
3943 int k;
3944
3945 for (k = conn->queue_start; k < conn->queue_end - 1; k++) {
3946 int i;
3947 int best_index = k;
3948 int smallest_dist = conn->distances[conn->queue[k]];
3949
3950 for (i = k + 1; i < conn->queue_end; i++) {
3951 if (conn->distances[conn->queue[i]] < smallest_dist) {
3952 best_index = i;
3953 smallest_dist = conn->distances[conn->queue[i]];
3954 }
3955 }
3956
3957 if (best_index != k) {
3958 int temp = conn->queue[k];
3959 conn->queue[k] = conn->queue[best_index];
3960 conn->queue[best_index] = temp;
3961 }
3962 }
3963}
3964
3965
3966/* Replace string origins in a connection queue with complete sets of
3967 * corresponding string stones.
3968 */
3969void
3970expand_connection_queue(struct connection_data *conn)
3971{
3972 int k;
3973 int full_queue[BOARDMAX];
3974 int full_queue_position = 0;
3975 int full_queue_start = 0;
3976
3977 for (k = 0; k < conn->queue_end; k++) {
3978 if (k == conn->queue_start)
3979 full_queue_start = full_queue_position;
3980
3981 if (board[conn->queue[k]] == EMPTY)
3982 full_queue[full_queue_position++] = conn->queue[k];
3983 else {
3984 full_queue_position += findstones(conn->queue[k],
3985 MAX_BOARD * MAX_BOARD,
3986 full_queue + full_queue_position);
3987 }
3988 }
3989
3990 conn->queue_start = full_queue_start;
3991 conn->queue_end = full_queue_position;
3992 memcpy(conn->queue, full_queue, conn->queue_end * sizeof(int));
3993}
3994
3995
3996/* Initialize distance and delta values so that the former are
3997 * everywhere huge and the latter everywhere zero.
3998 */
3999static void
4000clear_connection_data(struct connection_data *conn)
4001{
4002 int pos;
4003
4004 conn->queue_start = 0;
4005 conn->queue_end = 0;
4006 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
4007 conn->distances[pos] = HUGE_CONNECTION_DISTANCE;
4008 conn->deltas[pos] = FP(0.0);
4009 conn->coming_from[pos] = NO_MOVE;
4010 conn->vulnerable1[pos] = NO_MOVE;
4011 conn->vulnerable2[pos] = NO_MOVE;
4012 }
4013
4014 conn->heap_data_size = 0;
4015 conn->heap_size = 0;
4016}
4017
4018
4019/* Compute the connection distances from string (str) to nearby
4020 * vertices, until we reach target or the distance gets too high.
4021 */
4022void
4023compute_connection_distances(int str, int target, int cutoff,
4024 struct connection_data *conn,
4025 int speculative)
4026{
4027 int color = board[str];
4028
4029 clear_connection_data(conn);
4030
4031 /* Add the origin of the initial string to the queue. */
4032 add_to_start_queue(find_origin(str), FP(0.0), conn);
4033
4034 conn->target = target;
4035 conn->cutoff_distance = cutoff;
4036 conn->speculative = speculative;
4037
4038 spread_connection_distances(color, conn);
4039}
4040
4041
4042/* Print the connection distances in a struct connection_data. */
4043void
4044print_connection_distances(struct connection_data *conn)
4045{
4046 int i, j;
4047 int ch;
4048 int pos;
4049
4050 fprintf(stderr, " ");
4051 for (j = 0, ch = 'A'; j < board_size; j++, ch++) {
4052 if (ch == 'I')
4053 ch++;
4054 fprintf(stderr, " %c ", ch);
4055 }
4056 fprintf(stderr, "\n");
4057
4058 for (i = 0; i < board_size; i++) {
4059 fprintf(stderr, "%2d ", board_size - i);
4060 for (j = 0; j < board_size; j++) {
4061 pos = POS(i, j);
4062 if (conn->distances[pos] == HUGE_CONNECTION_DISTANCE) {
4063 if (board[pos] == WHITE)
4064 fprintf(stderr, " O ");
4065 if (board[pos] == BLACK)
4066 fprintf(stderr, " X ");
4067 if (board[pos] == EMPTY)
4068 fprintf(stderr, " . ");
4069 }
4070 else {
4071 fprintf(stderr, "%3.1f ", FIXED_TO_FLOAT(conn->distances[pos]));
4072 }
4073 }
4074 fprintf(stderr, "\n");
4075 }
4076 fprintf(stderr, "\n");
4077
4078 fprintf(stderr, "Vulnerable:\n");
4079 for (pos = BOARDMIN; pos < BOARDMAX; pos++)
4080 if (conn->distances[pos] < HUGE_CONNECTION_DISTANCE
4081 && (conn->vulnerable1[pos] != NO_MOVE
4082 || conn->vulnerable2[pos] != NO_MOVE)) {
4083 gprintf(" %1m:", pos);
4084 if (conn->vulnerable1[pos] != NO_MOVE)
4085 gprintf(" %1m", conn->vulnerable1[pos]);
4086 if (conn->vulnerable2[pos] != NO_MOVE)
4087 gprintf(" %1m", conn->vulnerable2[pos]);
4088 gprintf("\n", pos);
4089 }
4090}
4091
4092
4093/* Test whether there is a trivial connection between str1 and str2
4094 * and if so return the connecting move in *move. By trivial
4095 * connection we mean that they either have a common liberty or a
4096 * common neighbor which can be tactically attacked.
4097 */
4098static int
4099trivial_connection(int str1, int str2, int *move)
4100{
4101 SGFTree *save_sgf_dumptree = sgf_dumptree;
4102 int save_count_variations = count_variations;
4103 int adj, adjs[MAXCHAIN];
4104 int r;
4105 int result = 0;
4106
4107 if (have_common_lib(str1, str2, move))
4108 return WIN;
4109
4110 adj = chainlinks(str1, adjs);
4111
4112 /* We turn off the sgf traces here to avoid cluttering them up with
4113 * tactical reading moves.
4114 */
4115 sgf_dumptree = NULL;
4116 count_variations = 0;
4117
4118 for (r = 0; r < adj; r++)
4119 if (adjacent_strings(adjs[r], str2) && attack(adjs[r], move) == WIN) {
4120 result = WIN;
4121 break;
4122 }
4123
4124 /* Turn the sgf traces back on. */
4125 sgf_dumptree = save_sgf_dumptree;
4126 count_variations = save_count_variations;
4127
4128 return result;
4129}
4130
4131
4132/* True if a move by color makes an opponent move at pos a self atari
4133 * or possible to capture in a ladder.
4134 */
4135static int
4136does_secure_through_ladder(int color, int move, int pos)
4137{
4138 int result = 0;
4139
4140 if (trymove(move, color, NULL, NO_MOVE)) {
4141 if (ladder_capturable(pos, OTHER_COLOR(color)))
4142 result = 1;
4143 popgo();
4144 }
4145
4146 return result;
4147}
4148
4149/* Test whether the string str can be immediately taken off the board
4150 * or captured in a ladder. If so the capturing move is returned in
4151 * *move.
4152 */
4153static int
4154ladder_capture(int str, int *move)
4155{
4156 int result;
4157 SGFTree *save_sgf_dumptree = sgf_dumptree;
4158 int save_count_variations = count_variations;
4159 int liberties = countlib(str);
4160
4161 /* We turn off the sgf traces here to avoid cluttering them up with
4162 * tactical reading moves.
4163 */
4164 sgf_dumptree = NULL;
4165 count_variations = 0;
4166
4167 if (liberties == 1)
4168 result = attack(str, move);
4169 else if (liberties == 2)
4170 result = simple_ladder(str, move);
4171 else
4172 result = 0;
4173
4174 /* Turn the sgf traces back on. */
4175 sgf_dumptree = save_sgf_dumptree;
4176 count_variations = save_count_variations;
4177
4178 return result;
4179}
4180
4181/* Test whether a move at pos by color can be captured in a ladder. */
4182static int
4183ladder_capturable(int pos, int color)
4184{
4185 int result = 0;
4186
4187 if (trymove(pos, color, NULL, NO_MOVE)) {
4188 int liberties = countlib(pos);
4189 if (liberties == 1 && attack(pos, NULL) == WIN)
4190 result = 1;
4191 else if (liberties == 2 && simple_ladder(pos, NULL) == WIN)
4192 result = 1;
4193 popgo();
4194 }
4195 else
4196 result = 1;
4197
4198 return result;
4199}
4200
4201
4202/* Test whether the string str with one liberty is stuck with at most
4203 * one liberty. This function trivially returns false if the string
4204 * has more than one liberty to start with.
4205 */
4206static int
4207no_escape_from_atari(int str)
4208{
4209 int lib;
4210 int adj[MAXCHAIN];
4211
4212 if (findlib(str, 1, &lib) > 1)
4213 return 0;
4214
4215 if (accuratelib(lib, board[str], 2, NULL) > 1)
4216 return 0;
4217
4218 /* FIXME: Should exclude snapback. */
4219 if (chainlinks2(str, adj, 1) > 0)
4220 return 0;
4221
4222 return 1;
4223}
4224
4225
4226/* Test whether the string str with one liberty is captured in a
4227 * ladder. This function trivially returns false if the string has
4228 * more than one liberty to start with, except for one special case.
4229 * FIXME: Needs a simple_ladder_defense().
4230 */
4231static int
4232no_escape_from_ladder(int str)
4233{
4234 int result = 0;
4235 SGFTree *save_sgf_dumptree = sgf_dumptree;
4236 int save_count_variations = count_variations;
4237 int adj[MAXCHAIN];
4238 int libs[2];
4239
4240 /* We turn off the sgf traces here to avoid cluttering them up with
4241 * tactical reading moves.
4242 */
4243 sgf_dumptree = NULL;
4244 count_variations = 0;
4245
4246 if (countlib(str) == 1 && find_defense(str, NULL) == 0)
4247 result = 1;
4248
4249 if (countlib(str) == 2
4250 && chainlinks2(str, adj, 1) == 0
4251 && findlib(str, 2, libs) == 2
4252 && approxlib(libs[0], board[str], 2, NULL) == 1
4253 && approxlib(libs[1], board[str], 2, NULL) == 1
4254 && ladder_capture(str, NULL)
4255 && !find_defense(str, NULL))
4256 result = 1;
4257
4258
4259 /* Turn the sgf traces back on. */
4260 sgf_dumptree = save_sgf_dumptree;
4261 count_variations = save_count_variations;
4262
4263 return result;
4264}
4265
4266/* We usually don't want to spend time with moves which are
4267 * self-atari, unless the stone is involved in a ko.
4268 */
4269static int
4270check_self_atari(int pos, int color_to_move)
4271{
4272#if 1
4273 int lib;
4274#endif
4275
4276 if (!is_self_atari(pos, color_to_move))
4277 return 1;
4278
4279 if (is_ko(pos, color_to_move, NULL))
4280 return 1;
4281
4282#if 1
4283 /* FIXME: At some time I added this exceptional case but I can no
4284 * longer see how it would be useful. It might still be, however, so
4285 * I leave the code in for a while. /gf
4286 *
4287 * Code reactivated, see nando:31. /nn
4288 *
4289 * Added requirement that no additional stones are sacrificed in the
4290 * self atari. /gf
4291 *
4292 * FIXME: Add a function in board.c to check how big the string
4293 * becomes when playing a move and use for the isolated stone
4294 * test below.
4295 */
4296 if (approxlib(pos, color_to_move, 1, &lib) >= 1
4297 && approxlib(lib, OTHER_COLOR(color_to_move), 3, NULL) <= 2
4298 && ladder_capturable(lib, OTHER_COLOR(color_to_move))) {
4299 int k;
4300 for (k = 0; k < 4; k++) {
4301 if (board[pos + delta[k]] == color_to_move)
4302 break;
4303 }
4304 if (k == 4)
4305 return 1;
4306 }
4307#endif
4308
4309 return 0;
4310}
4311
4312/* Check for overlap between (a1, a2) and (b1, b2). */
4313static int
4314common_vulnerabilities(int a1, int a2, int b1, int b2, int color)
4315{
4316 return (common_vulnerability(a1, b1, color)
4317 || common_vulnerability(a1, b2, color)
4318 || common_vulnerability(a2, b1, color)
4319 || common_vulnerability(a2, b2, color));
4320}
4321
4322/* Check if apos and bpos are the same or if they are both liberties
4323 * of a string of the given color with at most three liberties.
4324 */
4325static int
4326common_vulnerability(int apos, int bpos, int color)
4327{
4328 int k;
4329
4330 if (apos == NO_MOVE || bpos == NO_MOVE)
4331 return 0;
4332
4333 if (apos == bpos)
4334 return 1;
4335
4336 for (k = 0; k < 4; k++)
4337 if (board[apos + delta[k]] == color
4338 && countlib(apos + delta[k]) <= 3
4339 && liberty_of_string(bpos, apos + delta[k]))
4340 return 1;
4341
4342 return 0;
4343}
4344
4345/*
4346 * Local Variables:
4347 * tab-width: 8
4348 * c-basic-offset: 2
4349 * End:
4350 */