Updated README: Equal sign not required with `--mode` flag.
[sgk-go] / engine / endgame.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
25#include "gnugo.h"
26#include "liberty.h"
27
28
29static void endgame_analyze_worm_liberties(int pos, int color);
30static void endgame_find_backfilling_dame(int str, int color);
31static int endgame_find_liberties(int str, int *essential_liberties,
32 int essential_libs[MAXLIBS],
33 int *inessential_liberties,
34 int inessential_libs[MAXLIBS],
35 int *false_eye_liberties,
36 int false_eye_libs[MAXLIBS]);
37
38
39/* Generate endgame moves. These are typically moves in settled positions,
40 * they aren't worth many points. Currently, we generate such moves using
41 * patterns in endgames.db and this algorithmic move generator. It is only
42 * called when no move of value higher than 6.0 has been found on board.
43 */
44void
45endgame(int color)
46{
47 int pos;
48
49 TRACE("\nEndgame move generator tries to look for additional moves...\n");
50
51 /* Try to generate some moves using endgame_analyze_worm_liberties(). See
52 * the description of that function to find what moves it generates.
53 */
54 for (pos = BOARDMIN; pos < BOARDMAX; pos++) {
55 /* We are only interested in alive, but not invincible worms which are
56 * parts of alive dragons. That is, the position must be stable.
57 */
58 if (IS_STONE(board[pos])
59 && worm[pos].origin == pos
60 && dragon[pos].status == ALIVE
61 && !worm[pos].invincible
62 && !worm[pos].inessential
63 && worm[pos].attack_codes[0] == 0) {
64 endgame_analyze_worm_liberties(pos, color);
65 endgame_find_backfilling_dame(pos, color);
66 }
67 }
68}
69
70
71/* This function handles two cases of endgame moves. Consider these two
72 * positions (from endgame:301,302 and endgame:801,802 respectively):
73 *
74 * OOOOOOO XXXXXO.|
75 * O.XXX.O X.O.O*.|
76 * OOX.XXO X.OOOX.|
77 * .O*X.OX XXXXOX.|
78 * .OXX..X X..XOOO|
79 * .OOOXX. XXXXXXX|
80 *
81 * The two marked with `*' moves are worth one point in gote each (for
82 * both colors). The first one is obvious - once black runs short on
83 * liberties, he'll have to defend in his own eyespace, wasting one
84 * point. In the second position, although black sacrifices one point
85 * by playing in white's territory, he forces white to eventually
86 * capture the black string, losing three points. However, white has
87 * to play at `*' sooner or later if black doesn't take that vertex, so
88 * the move is worth 3 - 1 - 1 = 1 point only, not two.
89 *
90 * This function is able to find such moves. The algorithm is based on
91 * finding so called "inessential liberties". These are defined as
92 * liberties, which satisfy five conditions:
93 *
94 * 1) they are not within an eye (not in someone's territory),
95 * 2) all their adjacent worms and dragons are alive,
96 * 3) they have adjacent worms of both colors,
97 * 4) they have no other adjacent worms of the same color as the worm
98 * under consideration,
99 * 5) they are safe to fill with stones of other than the worm's color.
100 *
101 * Such liberties are supposed to never become territory (they can't become
102 * an additional eye for the worm under consideration), the worm cannot
103 * connect to something via such a liberty and they will (or at least can)
104 * eventually be filled by either of the players.
105 *
106 * FIXME: This function can probably be improved to handle more cases.
107 */
108static void
109endgame_analyze_worm_liberties(int pos, int color)
110{
111 int k;
112 int worm_color = board[pos];
113 int other = OTHER_COLOR(worm_color);
114 int essential_liberties;
115 int essential_libs[MAXLIBS];
116 int inessential_liberties;
117 int inessential_libs[MAXLIBS];
118 int false_eye_liberties;
119 int false_eye_libs[MAXLIBS];
120 int num_attacks;
121 int num_attacks2;
122 int attacks[MAXLIBS];
123 int defenses[MAXLIBS];
124 int apos;
125 int value;
126
127 if (!endgame_find_liberties(pos, &essential_liberties, essential_libs,
128 &inessential_liberties, inessential_libs,
129 &false_eye_liberties, false_eye_libs))
130 return;
131
132 apos = NO_MOVE;
133 num_attacks = 0;
134
135 /* Now, try to predict the final state of the position. We fill all
136 * inessential liberties by stones of other than the current worm's
137 * color. This is just a guess, we'll have to check the results later.
138 */
139 for (k = 0; k < inessential_liberties; k++) {
140 if (!safe_move(inessential_libs[k], other)
141 || !trymove(inessential_libs[k], other, "endgame", pos))
142 break;
143 }
144
145 /* If we haven't eaten the worm accidentally, look if any attacks on the
146 * worm have appeared.
147 */
148 if (k == inessential_liberties && board[pos] != EMPTY) {
149 /* Try to look for moves as in position 1. If the worm still has
150 * more than one liberty, try to play on every essential liberty
151 * and see if an attack appears.
152 */
153 if (countlib(pos) > 1) {
154 for (k = 0; k < essential_liberties; k++) {
155 int lib = essential_libs[k];
156
157 if (safe_move(lib, worm_color) && safe_move(lib, other)
158 && trymove(lib, other, "endgame", pos)) {
159 if (attack(pos, NULL) != 0) {
160 int dpos;
161
162 if (find_defense(pos, &dpos) && is_proper_eye_space(dpos)) {
163 int i;
164
165 /* If the attack cannot be defended against by playing on
166 * another essential liberty, filling a pure false eye (an
167 * eye which can't become territory) or capturing an opponent
168 * string in atari, keep it for now.
169 */
170 for (i = 0; i < essential_liberties; i++) {
171 if (i != k && essential_libs[i] != dpos
172 && does_defend(essential_libs[i], pos))
173 break;
174 }
175
176 if (i == essential_liberties) {
177 for (i = 0; i < false_eye_liberties; i++) {
178 if (does_defend(false_eye_libs[i], pos))
179 break;
180 }
181
182 if (i == false_eye_liberties) {
183 int adj[MAXCHAIN];
184 int adjs;
185
186 adjs = chainlinks2(pos, adj, 1);
187 for (i = 0; i < adjs; i++) {
188 int lib2;
189 findlib(adj[i], 1, &lib2);
190 if (lib2 != dpos && !is_proper_eye_space(lib2)
191 && does_defend(lib2, pos))
192 break;
193 }
194
195 if (i == adjs) {
196 attacks[num_attacks] = lib;
197 defenses[num_attacks] = dpos;
198 num_attacks++;
199 }
200 }
201 }
202 }
203 }
204
205 popgo();
206 }
207 }
208 }
209 else if (essential_liberties > 0) {
210 /* If the only remaining liberty is essential, it is an attack. */
211 attacks[num_attacks] = essential_libs[0];
212 defenses[num_attacks] = NO_MOVE;
213 num_attacks++;
214 }
215
216 /* Try to find moves as in position 2. */
217 if (attack(pos, &apos) != 0) {
218 if (is_proper_eye_space(apos)) {
219 /* The attack point is in someone's eye (must be an eye which the worm
220 * bounds). This looks promising. If this attack cannot be averted by
221 * playing on an essential liberty, keep it for further analyzis.
222 */
223 for (k = 0; k < essential_liberties; k++) {
224 if (does_defend(essential_libs[k], pos)) {
225 apos = NO_MOVE;
226 break;
227 }
228 }
229
230 if (apos != NO_MOVE && worm_color == color && !does_defend(apos, pos))
231 apos = NO_MOVE;
232 }
233 else
234 apos = NO_MOVE;
235 }
236 }
237 else {
238 /* We were unable to fill all the liberties. Modify
239 * `inessential_liberties' in order to undo the right number of
240 * moves.
241 */
242 inessential_liberties = k;
243 }
244
245 /* Undo all the moves made to fill inessential liberties. */
246 for (k = 0; k < inessential_liberties; k++)
247 popgo();
248 ASSERT1(stackp == 0, pos);
249
250 num_attacks2 = 0;
251 for (k = 0; k < num_attacks; k++) {
252 /* These moves must be safe for the other color, otherwise they are
253 * pointless. Note that checks for safety on previous step were not
254 * sufficient since we had additional stones on board then.
255 */
256 if (safe_move(attacks[k], other)) {
257 if (defenses[k] != NO_MOVE) {
258 int i;
259
260 /* Consider this position:
261 *
262 * .X...OO The move at `*' satisfies the conditions above.
263 * .X*OO.O However, it is pointless, since black has a miai
264 * X.OX..O move at `a' to force white to play `b'. That is,
265 * XXObOOO no matter if white plays `*' or `a', black takes
266 * .XXaOXO the other point and white has to fill `b'. So, if
267 * ...XXXX there is a point, adjacent to defense point, safe
268 * for "other" color, we discard the attack.
269 *
270 * Also, in some positions, defense point is adjacent to worm
271 * inessential liberty. In such cases we discard the attack too.
272 */
273 for (i = 0; i < 4; i++) {
274 int pos2 = defenses[k] + delta[i];
275
276 if (board[pos2] == EMPTY) {
277 int m;
278
279 if (!is_proper_eye_space(pos2) && safe_move(pos2, other))
280 break;
281
282 for (m = 0; m < inessential_liberties; m++) {
283 if (inessential_libs[m] == pos2)
284 break;
285 }
286
287 if (m < inessential_liberties)
288 break;
289 }
290 }
291
292 /* If this is not the case, the attack is kept for the final trial. */
293 if (i == 4)
294 attacks[num_attacks2++] = attacks[k];
295 }
296 else {
297 /* This must be the only attack (filling all inessential liberties
298 * gives an atari).
299 */
300 ASSERT1(num_attacks == 1, pos);
301 attacks[num_attacks2++] = attacks[k];
302 }
303 }
304 }
305
306 value = 0;
307 if (apos != NO_MOVE) {
308 /* We use the number of string's liberties minus 2 as the value of
309 * the move. Minus 2 is explained in the comment before the
310 * function. In some rare cases the value may differ, but this
311 * should be a good guess.
312 */
313 value = accuratelib(apos, other, MAXLIBS, NULL) - 2;
314 }
315
316 /* If we haven't found anything interesting or have already dropped it,
317 * there is no point trying more moves, so we return now.
318 */
319 if (value <= 0 && num_attacks2 == 0)
320 return;
321
322 /* We filled the liberties with stones of "other" color. That could lead to
323 * some strange attacks, since inessential liberties are not always really
324 * inessential (see trevorb:320 and trevorb:940 for examples where this step
325 * is necessary). Now we fill the liberties with stones of the same color as
326 * the current worm. If the results remain unchanged, then we can probably
327 * trust them.
328 */
329 for (k = 0; k < inessential_liberties; k++) {
330 if (!trymove(inessential_libs[k], worm_color, "endgame", pos))
331 break;
332 }
333
334 /* GNU Go currently doesn't allow suicide, but let's assume it does. */
335 if (k == inessential_liberties && board[pos] != EMPTY) {
336 if (countlib(pos) > 1) {
337 for (k = 0; k < num_attacks2; k++) {
338 if (trymove(attacks[k], other, "endgame", pos)) {
339 if (attack(pos, NULL) != 0) {
340 TRACE(" endgame move with territorial value %d.0 found at %1m\n",
341 1, attacks[k]);
342 add_expand_territory_move(attacks[k]);
343 /* FIXME: We just guess the value here. Find a way to calculate it
344 * (more) precisely.
345 */
346 set_minimum_territorial_value(attacks[k], 1.0);
347 }
348
349 popgo();
350 }
351 }
352 }
353 else if (essential_liberties > 0 && essential_libs[0] == attacks[0]) {
354 TRACE(" endgame move with territorial value %d.0 found at %1m\n",
355 1, attacks[k]);
356 add_expand_territory_move(attacks[0]);
357 /* FIXME: We just guess the value here. Find a way to calculate it
358 * (more) precisely.
359 */
360 set_minimum_territorial_value(attacks[0], 1.0);
361 }
362
363 if (value > 0 && does_attack(apos, pos)) {
364 TRACE(" endgame move with territorial value %d.0 found at %1m\n",
365 value, apos);
366 add_expand_territory_move(apos);
367 set_minimum_territorial_value(apos, (float) value);
368 }
369 }
370 else {
371 /* Don't undo moves we didn't play. */
372 inessential_liberties = k;
373 }
374
375 /* Undo all the moves made at the third step. */
376 for (k = 0; k < inessential_liberties; k++)
377 popgo();
378 ASSERT1(stackp == 0, pos);
379}
380
381/* A backfilling dame is a defense move, usually within potential own
382 * territory, which does not have to be played immediately but after
383 * outer liberties of some string have been filled. If those outer
384 * liberties are dame points (here inessential liberties), it is
385 * usually better to play the backfilling moves before filling the
386 * dame points. If nothing else it reduces the risk for making stupid
387 * blunders while filling dame.
388 */
389static void
390endgame_find_backfilling_dame(int str, int color_to_move)
391{
392 int k;
393 int color = board[str];
394 int other = OTHER_COLOR(color);
395 int essential_liberties;
396 int essential_libs[MAXLIBS];
397 int inessential_liberties;
398 int inessential_libs[MAXLIBS];
399 int false_eye_liberties;
400 int false_eye_libs[MAXLIBS];
401 int dpos;
402 int loop_again = 1;
403 int potential_moves[BOARDMAX];
404 int num_potential_moves = 0;
405 int move = NO_MOVE;
406
407 while (loop_again) {
408 loop_again = 0;
409 if (!endgame_find_liberties(str, &essential_liberties, essential_libs,
410 &inessential_liberties, inessential_libs,
411 &false_eye_liberties, false_eye_libs))
412 break;
413 for (k = 0; k < inessential_liberties; k++) {
414 if (!safe_move(inessential_libs[k], other)
415 || !trymove(inessential_libs[k], other, "endgame", str))
416 continue;
417 increase_depth_values();
418 if (board[str] == EMPTY)
419 break;
420 if (attack_and_defend(str, NULL, NULL, NULL, &dpos)) {
421 if (worm[dpos].color == EMPTY) {
422 potential_moves[num_potential_moves] = dpos;
423 num_potential_moves++;
424 }
425 forced_backfilling_moves[dpos] = 1;
426 if (trymove(dpos, color, "endgame", str))
427 increase_depth_values();
428 loop_again = 1;
429 break;
430 }
431 }
432 }
433
434 while (stackp > 0) {
435 popgo();
436 decrease_depth_values();
437 }
438
439 for (k = num_potential_moves - 1; k >= 0; k--)
440 if (safe_move(potential_moves[k], color)) {
441 move = potential_moves[k];
442 TRACE(" backfilling dame found at %1m for string %1m\n", move, str);
443 if (color == color_to_move) {
444 add_expand_territory_move(move);
445 set_minimum_territorial_value(move, 0.1);
446 }
447 break;
448 }
449}
450
451/* Find liberties of the string str with various characteristics. See
452 * the comments above endgame_analyze_worm_liberties() for more
453 * information.
454 */
455static int
456endgame_find_liberties(int str,
457 int *essential_liberties, int essential_libs[MAXLIBS],
458 int *inessential_liberties,
459 int inessential_libs[MAXLIBS],
460 int *false_eye_liberties, int false_eye_libs[MAXLIBS])
461{
462 int liberties;
463 int libs[MAXLIBS];
464 int k;
465
466 ASSERT1(IS_STONE(board[str]), str);
467
468 *essential_liberties = 0;
469 *inessential_liberties = 0;
470 *false_eye_liberties = 0;
471
472 /* Find all string liberties. */
473 liberties = findlib(str, MAXLIBS, libs);
474
475 /* Loop over the liberties and find inessential and essential ones. The
476 * latter are defined as those, which are not inside an eye space, but
477 * don't otherwise qualify as inessential. If we find a non-alive (dead
478 * or critical) worm or dragon around, we stop looking for liberties and
479 * skip the current worm (position is unstable).
480 */
481 for (k = 0; k < liberties; k++) {
482 int lib = libs[k];
483
484 if (!is_proper_eye_space(lib)) {
485 int i;
486 int essential = 0;
487 int found_other = 0;
488
489 for (i = 0; i < 4; i++) {
490 int pos = lib + delta[i];
491
492 if (!IS_STONE(board[pos]) || !IS_STONE(worm[pos].color))
493 continue;
494
495 if (worm[pos].attack_codes[0] != 0 || dragon[pos].status != ALIVE)
496 return 0;
497
498 if (board[pos] == board[str]) {
499 if (find_origin(pos) != find_origin(str))
500 essential = 1;
501 }
502 else
503 found_other = 1;
504 }
505
506 if (i < 4)
507 break;
508
509 if (found_other) {
510 if (essential)
511 essential_libs[(*essential_liberties)++] = lib;
512 else
513 inessential_libs[(*inessential_liberties)++] = lib;
514 }
515 else if (is_false_eye(half_eye, lib) && !false_eye_territory[lib])
516 false_eye_libs[(*false_eye_liberties)++] = lib;
517 }
518 }
519 return 1;
520}
521
522/*
523 * Local Variables:
524 * tab-width: 8
525 * c-basic-offset: 2
526 * End:
527 */