| 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 | |
| 27 | #include <stdio.h> |
| 28 | #include <stdlib.h> |
| 29 | #include <string.h> |
| 30 | #include "liberty.h" |
| 31 | |
| 32 | static int find_backfilling_move(int move, int color, int *backfill_move, |
| 33 | int forbidden_moves[BOARDMAX]); |
| 34 | static int filllib_confirm_safety(int move, int color, int *defense_point); |
| 35 | |
| 36 | /* Determine whether a point is adjacent to at least one own string which |
| 37 | * isn't dead. |
| 38 | */ |
| 39 | static int |
| 40 | living_neighbor(int pos, int color) |
| 41 | { |
| 42 | int k; |
| 43 | for (k = 0; k < 4; k++) { |
| 44 | if (board[pos + delta[k]] == color |
| 45 | && dragon[pos + delta[k]].status != DEAD) |
| 46 | return 1; |
| 47 | } |
| 48 | |
| 49 | return 0; |
| 50 | } |
| 51 | |
| 52 | |
| 53 | /* Determine whether (pos) effectively is a black or white point. |
| 54 | * The test for inessentiality is to avoid filling the liberties |
| 55 | * around a killing nakade string. |
| 56 | */ |
| 57 | static void |
| 58 | analyze_neighbor(int pos, int *found_black, int *found_white) |
| 59 | { |
| 60 | switch (board[pos]) { |
| 61 | case EMPTY: |
| 62 | if (!(*found_black) |
| 63 | && living_neighbor(pos, BLACK) |
| 64 | && safe_move(pos, WHITE) != WIN) |
| 65 | *found_black = 1; |
| 66 | |
| 67 | if (!(*found_white) |
| 68 | && living_neighbor(pos, WHITE) |
| 69 | && safe_move(pos, BLACK) != WIN) |
| 70 | *found_white = 1; |
| 71 | |
| 72 | break; |
| 73 | |
| 74 | case BLACK: |
| 75 | if (!worm[pos].inessential && DRAGON2(pos).safety != INESSENTIAL) { |
| 76 | if (dragon[pos].status == ALIVE |
| 77 | || dragon[pos].status == UNKNOWN) |
| 78 | *found_black = 1; |
| 79 | else |
| 80 | *found_white = 1; |
| 81 | } |
| 82 | break; |
| 83 | |
| 84 | case WHITE: |
| 85 | if (!worm[pos].inessential && DRAGON2(pos).safety != INESSENTIAL) { |
| 86 | if (dragon[pos].status == ALIVE |
| 87 | || dragon[pos].status == UNKNOWN) |
| 88 | *found_white = 1; |
| 89 | else |
| 90 | *found_black = 1; |
| 91 | } |
| 92 | break; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | |
| 97 | /* If no move of value can be found to play, this seeks to fill a |
| 98 | * common liberty, backfilling or back-capturing if necessary. When |
| 99 | * backfilling we take care to start from the right end, in the case |
| 100 | * that several backfilling moves are ultimately necessary. |
| 101 | * |
| 102 | * If a move for color is found, return 1, otherwise return 0. |
| 103 | * The move is returned in (*move). |
| 104 | */ |
| 105 | |
| 106 | int |
| 107 | fill_liberty(int *move, int color) |
| 108 | { |
| 109 | int k; |
| 110 | int pos; |
| 111 | int other = OTHER_COLOR(color); |
| 112 | int defense_point; |
| 113 | int potential_color[BOARDMAX]; |
| 114 | |
| 115 | /* We first make a fast scan for intersections which are potential |
| 116 | * candidates for liberty filling. This is not very accurate, but it |
| 117 | * does filter out intersections which could never pass the real |
| 118 | * tests below but might still require a lot of tactical reading in |
| 119 | * the process. |
| 120 | */ |
| 121 | memset(potential_color, 0, sizeof(potential_color)); |
| 122 | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 123 | if (!IS_STONE(board[pos])) |
| 124 | continue; |
| 125 | |
| 126 | if (worm[pos].inessential || DRAGON2(pos).safety == INESSENTIAL) |
| 127 | continue; |
| 128 | |
| 129 | if (dragon[pos].status != ALIVE) { |
| 130 | for (k = 0; k < 4; k++) { |
| 131 | int pos2 = pos + delta[k]; |
| 132 | if (board[pos2] == EMPTY) |
| 133 | potential_color[pos2] |= OTHER_COLOR(board[pos]); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | if (dragon[pos].status != DEAD) { |
| 138 | for (k = 0; k < 12; k++) { |
| 139 | int d = delta[k%8]; |
| 140 | |
| 141 | if (k >= 8) { |
| 142 | if (board[pos + d] != EMPTY) |
| 143 | continue; |
| 144 | d *= 2; |
| 145 | } |
| 146 | if (board[pos + d] == EMPTY) |
| 147 | potential_color[pos + d] |= board[pos]; |
| 148 | } |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | |
| 153 | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 154 | /* It seems we can't trust an empty liberty to be gray-colored |
| 155 | * either as a cave or as a cavity. Instead we look for empty |
| 156 | * intersections with at least one neighbor of each color, where |
| 157 | * dead stones count as enemy stones. We also count empty |
| 158 | * neighbors to either color if the opponent can't play there. |
| 159 | */ |
| 160 | int found_white = 0; |
| 161 | int found_black = 0; |
| 162 | |
| 163 | if (board[pos] != EMPTY) |
| 164 | continue; |
| 165 | |
| 166 | /* Quick rejection based on preliminary test above. */ |
| 167 | if (potential_color[pos] != GRAY) |
| 168 | continue; |
| 169 | |
| 170 | /* Loop over the neighbors. */ |
| 171 | for (k = 0; k < 4; k++) { |
| 172 | int d = delta[k]; |
| 173 | if (ON_BOARD(pos + d)) |
| 174 | analyze_neighbor(pos + d, &found_black, &found_white); |
| 175 | } |
| 176 | |
| 177 | /* Do we have neighbors of both colors? */ |
| 178 | if (!(found_white && found_black)) |
| 179 | continue; |
| 180 | |
| 181 | /* Ok, we wish to play here, but maybe we can't. The following |
| 182 | * cases may occur: |
| 183 | * 1. Move is legal and safe. |
| 184 | * 2. Move is legal but not safe because it's in the middle of a seki. |
| 185 | * 3. Move is legal but not safe, can be played after backfilling. |
| 186 | * 4. Move is an illegal ko recapture. |
| 187 | * 5. Move is illegal but can be played after back-captures. |
| 188 | * 6. Move would violate confirm_safety. |
| 189 | */ |
| 190 | |
| 191 | DEBUG(DEBUG_FILLLIB, "Filllib: Considering move at %1m.\n", pos); |
| 192 | |
| 193 | /* Legal and tactically safe, play it if it passes |
| 194 | * confirm_safety test, i.e. that it isn't a blunder which |
| 195 | * causes problems for other strings. |
| 196 | */ |
| 197 | if (safe_move(pos, color) == WIN) { |
| 198 | DEBUG(DEBUG_FILLLIB, "Filllib: Tactically safe.\n"); |
| 199 | if (filllib_confirm_safety(pos, color, &defense_point)) { |
| 200 | /* Safety confirmed. */ |
| 201 | DEBUG(DEBUG_FILLLIB, "Filllib: Safety confirmed.\n"); |
| 202 | *move = pos; |
| 203 | return 1; |
| 204 | } |
| 205 | else if (defense_point != NO_MOVE && is_legal(defense_point, color)) { |
| 206 | /* Safety not confirmed because the move at (pos) would set |
| 207 | * up a double threat. (defense_point) is assumed to defend |
| 208 | * against this threat. |
| 209 | * |
| 210 | * FIXME: We should verify that (defense_point) really is effective. |
| 211 | */ |
| 212 | DEBUG(DEBUG_FILLLIB, |
| 213 | "Filllib: Safety not confirmed, but %1m defends.\n", |
| 214 | defense_point); |
| 215 | *move = defense_point; |
| 216 | return 1; |
| 217 | } |
| 218 | else { |
| 219 | /* The move causes problems somewhere else on the board, so |
| 220 | * we have to discard it. If everything works right this |
| 221 | * should not happen at this time. |
| 222 | */ |
| 223 | DEBUG(DEBUG_FILLLIB, "Filllib: Safety not confirmed, discarded.\n"); |
| 224 | TRACE("Warning: Blunder detected in fill_liberty().\n"); |
| 225 | continue; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | /* Try to play the move. */ |
| 230 | if (trymove(pos, color, "fill_liberty", NO_MOVE)) { |
| 231 | int forbidden_moves[BOARDMAX]; |
| 232 | popgo(); |
| 233 | /* Legal, but not safe. Look for backfilling move. */ |
| 234 | DEBUG(DEBUG_FILLLIB, |
| 235 | "Filllib: Legal but not safe, looking for backfilling move.\n"); |
| 236 | |
| 237 | memset(forbidden_moves, 0, sizeof(forbidden_moves)); |
| 238 | while (find_backfilling_move(pos, color, move, forbidden_moves)) { |
| 239 | /* Mark as forbidden in case we need another turn in the loop. */ |
| 240 | forbidden_moves[*move] = 1; |
| 241 | |
| 242 | DEBUG(DEBUG_FILLLIB, "Filllib: Backfilling move at %1m.\n", *move); |
| 243 | /* In certain positions it may happen that an illegal move |
| 244 | * is found. This probably only can happen if we try to play |
| 245 | * a move inside a lost semeai. Anyway we should discard the |
| 246 | * move. |
| 247 | */ |
| 248 | if (!is_legal(*move, color)) { |
| 249 | DEBUG(DEBUG_FILLLIB, "Filllib: Was illegal, discarded.\n"); |
| 250 | *move = NO_MOVE; |
| 251 | continue; |
| 252 | } |
| 253 | |
| 254 | /* If the move turns out to be strategically unsafe, or |
| 255 | * setting up a double threat elsewhere, also discard it. |
| 256 | */ |
| 257 | if (!filllib_confirm_safety(*move, color, &defense_point)) { |
| 258 | DEBUG(DEBUG_FILLLIB, |
| 259 | "Filllib: Safety not confirmed, discarded.\n"); |
| 260 | *move = NO_MOVE; |
| 261 | continue; |
| 262 | } |
| 263 | |
| 264 | /* Seems to be ok. */ |
| 265 | return 1; |
| 266 | } |
| 267 | |
| 268 | /* No acceptable backfilling move found. |
| 269 | * If we captured some stones, this move should be ok anyway. |
| 270 | */ |
| 271 | if (does_capture_something(pos, color)) { |
| 272 | DEBUG(DEBUG_FILLLIB, |
| 273 | "Filllib: Not tactically safe, but captures stones.\n"); |
| 274 | if (!filllib_confirm_safety(pos, color, &defense_point)) { |
| 275 | DEBUG(DEBUG_FILLLIB, |
| 276 | "Filllib: Safety not confirmed, discarded.\n"); |
| 277 | continue; |
| 278 | } |
| 279 | *move = pos; |
| 280 | return 1; |
| 281 | } |
| 282 | } |
| 283 | else { |
| 284 | /* Move is illegal. Look for an attack on one of the neighbor |
| 285 | * worms. If found, return that move for back-capture. |
| 286 | */ |
| 287 | DEBUG(DEBUG_FILLLIB, "Filllib: Illegal, looking for back-capture.\n"); |
| 288 | for (k = 0; k < 4; k++) { |
| 289 | int d = delta[k]; |
| 290 | if (board[pos + d] == other |
| 291 | && worm[pos + d].attack_codes[0] == WIN) { |
| 292 | *move = worm[pos + d].attack_points[0]; |
| 293 | DEBUG(DEBUG_FILLLIB, "Filllib: Found at %1m.\n", *move); |
| 294 | return 1; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | DEBUG(DEBUG_FILLLIB, |
| 299 | "Filllib: Nothing found, looking for ko back-capture.\n"); |
| 300 | for (k = 0; k < 4; k++) { |
| 301 | int d = delta[k]; |
| 302 | if (board[pos + d] == other |
| 303 | && worm[pos + d].attack_codes[0] != 0 |
| 304 | && is_legal(worm[pos + d].attack_points[0], color)) { |
| 305 | *move = worm[pos + d].attack_points[0]; |
| 306 | DEBUG(DEBUG_FILLLIB, "Filllib: Found at %1m.\n", *move); |
| 307 | return 1; |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | DEBUG(DEBUG_FILLLIB, |
| 312 | "Filllib: Nothing found, looking for threat to back-capture.\n"); |
| 313 | for (k = 0; k < 4; k++) { |
| 314 | int d = delta[k]; |
| 315 | if (board[pos + d] == other |
| 316 | && worm[pos + d].attack_codes[0] != 0) { |
| 317 | /* Just pick some other liberty. */ |
| 318 | /* FIXME: Something is odd about this code. */ |
| 319 | int libs[2]; |
| 320 | if (findlib(pos + d, 2, libs) > 1) { |
| 321 | if (is_legal(libs[0], color)) |
| 322 | *move = libs[0]; |
| 323 | else if (is_legal(libs[1], color)) |
| 324 | *move = libs[1]; |
| 325 | else |
| 326 | continue; |
| 327 | |
| 328 | DEBUG(DEBUG_FILLLIB, "Filllib: Found at %1m.\n", *move); |
| 329 | return 1; |
| 330 | } |
| 331 | } |
| 332 | } |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | /* Nothing found. */ |
| 337 | DEBUG(DEBUG_FILLLIB, "Filllib: No move found.\n"); |
| 338 | return 0; |
| 339 | } |
| 340 | |
| 341 | |
| 342 | /* The strategy for finding a backfilling move is to first identify |
| 343 | * moves that |
| 344 | * |
| 345 | * 1. defends the position obtained after playing (move). |
| 346 | * 2. captures a stone adjacent to our neighbors to (move), before |
| 347 | * (move) is played. |
| 348 | * |
| 349 | * Then we check which of these are legal before (move) is played. If |
| 350 | * there is at least one, we take one of these arbitrarily as a |
| 351 | * backfilling move. |
| 352 | * |
| 353 | * Now it may happen that (move) still isn't a safe move. In that case |
| 354 | * we recurse to find a new backfilling move. To do things really |
| 355 | * correctly we should also give the opponent the opportunity to keep |
| 356 | * up the balance of the position by letting him do a backfilling move |
| 357 | * of his own. Maybe this could also be arranged by recursing this |
| 358 | * function. Currently we only do a half-hearted attempt to find |
| 359 | * opponent moves. |
| 360 | * |
| 361 | * The purpose of the forbidden_moves[] array is to get a new |
| 362 | * backfilling move if the first one later was found to be unsafe, |
| 363 | * like backfilling for J5 at F9 in filllib:45. With F9 marked as |
| 364 | * forbidden the correct move at G9 is found. |
| 365 | */ |
| 366 | static int adjs[MAXCHAIN]; |
| 367 | static int libs[MAXLIBS]; |
| 368 | |
| 369 | static int |
| 370 | find_backfilling_move(int move, int color, int *backfill_move, |
| 371 | int forbidden_moves[BOARDMAX]) |
| 372 | { |
| 373 | int k; |
| 374 | int liberties; |
| 375 | int neighbors; |
| 376 | int found_one = 0; |
| 377 | int apos = NO_MOVE; |
| 378 | int bpos = NO_MOVE; |
| 379 | int extra_pop = 0; |
| 380 | int success = 0; |
| 381 | int acode; |
| 382 | int saved_move = NO_MOVE; |
| 383 | int opponent_libs; |
| 384 | |
| 385 | DEBUG(DEBUG_FILLLIB, "find_backfilling_move for %C %1m\n", color, move); |
| 386 | if (debug & DEBUG_FILLLIB) |
| 387 | dump_stack(); |
| 388 | |
| 389 | /* Play (move) and identify all liberties and adjacent strings. */ |
| 390 | if (!trymove(move, color, "find_backfilling_move", move)) |
| 391 | return 0; /* This shouldn't happen, I believe. */ |
| 392 | |
| 393 | /* The move wasn't safe, so there must be an attack for the |
| 394 | * opponent. Save it for later use. |
| 395 | */ |
| 396 | acode = attack(move, &apos); |
| 397 | gg_assert(acode != 0 && apos != NO_MOVE); |
| 398 | |
| 399 | /* Find liberties. */ |
| 400 | liberties = findlib(move, MAXLIBS, libs); |
| 401 | |
| 402 | /* Find neighbors. */ |
| 403 | neighbors = chainlinks(move, adjs); |
| 404 | |
| 405 | /* Remove (move) again. */ |
| 406 | popgo(); |
| 407 | |
| 408 | /* It's most fun to capture stones. Start by trying to take some |
| 409 | * neighbor off the board. If the attacking move does not directly |
| 410 | * reduce the number of liberties of the attacked string we don't |
| 411 | * trust it but keep it around if we don't find anything else. (See |
| 412 | * filllib:17 for a position where this matters.) |
| 413 | * |
| 414 | * It is also necessary to take care to first attack the string with |
| 415 | * the fewest liberties, which can probably be removed the fastest. |
| 416 | * See filllib:37 for an example (J5 tactically attacks K7 but the |
| 417 | * correct move is H5). |
| 418 | * |
| 419 | * FIXME: It seems we have to return immediately when we find an |
| 420 | * attacking move, because recursing for further backfilling might |
| 421 | * lead to moves which complete the capture but cannot be played |
| 422 | * before the attacking move itself. This is not ideal but probably |
| 423 | * good enough. |
| 424 | * |
| 425 | * In order to avoid losing unnecessary points while capturing dead |
| 426 | * stones, we try first to capture stones in atari, second defending |
| 427 | * at a liberty, and third capture stones with two or more |
| 428 | * liberties. See filllib:43 for a position where capturing dead |
| 429 | * stones (B10 or C8) loses a point compared to defending at a |
| 430 | * liberty (C6). |
| 431 | */ |
| 432 | for (opponent_libs = 1; opponent_libs <= 1; opponent_libs++) { |
| 433 | for (k = 0; k < neighbors; k++) { |
| 434 | if (opponent_libs < 5 && countlib(adjs[k]) != opponent_libs) |
| 435 | continue; |
| 436 | if (attack(adjs[k], &bpos) == WIN) { |
| 437 | if (forbidden_moves[bpos]) |
| 438 | continue; |
| 439 | if (liberty_of_string(bpos, adjs[k])) { |
| 440 | *backfill_move = bpos; |
| 441 | return 1; |
| 442 | } |
| 443 | else |
| 444 | saved_move = bpos; |
| 445 | } |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | /* Otherwise look for a safe move at a liberty. */ |
| 450 | if (!found_one) { |
| 451 | for (k = 0; k < liberties; k++) { |
| 452 | if (!forbidden_moves[libs[k]] && safe_move(libs[k], color) == WIN) { |
| 453 | *backfill_move = libs[k]; |
| 454 | found_one = 1; |
| 455 | break; |
| 456 | } |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | if (!found_one) { |
| 461 | for (opponent_libs = 2; opponent_libs <= 5; opponent_libs++) { |
| 462 | for (k = 0; k < neighbors; k++) { |
| 463 | if (opponent_libs < 5 && countlib(adjs[k]) != opponent_libs) |
| 464 | continue; |
| 465 | if (attack(adjs[k], &bpos) == WIN) { |
| 466 | if (forbidden_moves[bpos]) |
| 467 | continue; |
| 468 | if (liberty_of_string(bpos, adjs[k])) { |
| 469 | *backfill_move = bpos; |
| 470 | return 1; |
| 471 | } |
| 472 | else |
| 473 | saved_move = bpos; |
| 474 | } |
| 475 | } |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | /* If no luck so far, try with superstring liberties. */ |
| 480 | if (!found_one) { |
| 481 | trymove(move, color, "find_backfilling_move", move); |
| 482 | find_proper_superstring_liberties(move, &liberties, libs, 0); |
| 483 | popgo(); |
| 484 | for (k = 0; k < liberties; k++) { |
| 485 | if (!forbidden_moves[libs[k]] && safe_move(libs[k], color) == WIN) { |
| 486 | *backfill_move = libs[k]; |
| 487 | found_one = 1; |
| 488 | break; |
| 489 | } |
| 490 | } |
| 491 | } |
| 492 | |
| 493 | /* If no luck so far, try attacking superstring neighbors. */ |
| 494 | if (!found_one) { |
| 495 | trymove(move, color, "find_backfilling_move", move); |
| 496 | superstring_chainlinks(move, &neighbors, adjs, 4); |
| 497 | popgo(); |
| 498 | for (k = 0; k < neighbors; k++) { |
| 499 | if (attack(adjs[k], &bpos) == WIN) { |
| 500 | if (!forbidden_moves[bpos] && liberty_of_string(bpos, adjs[k])) { |
| 501 | *backfill_move = bpos; |
| 502 | return 1; |
| 503 | } |
| 504 | } |
| 505 | } |
| 506 | } |
| 507 | |
| 508 | if (found_one) { |
| 509 | ASSERT1(!forbidden_moves[*backfill_move], *backfill_move); |
| 510 | |
| 511 | if (!trymove(*backfill_move, color, "find_backfilling_move", move)) |
| 512 | return 0; /* This really shouldn't happen. */ |
| 513 | |
| 514 | /* Allow opponent to get a move in here. */ |
| 515 | if (trymove(apos, OTHER_COLOR(color), "find_backfilling_move", move)) |
| 516 | extra_pop = 1; |
| 517 | |
| 518 | /* If still not safe, recurse to find a new backfilling move. */ |
| 519 | if (safe_move(move, color) == WIN) |
| 520 | success = 1; |
| 521 | else |
| 522 | success = find_backfilling_move(move, color, backfill_move, |
| 523 | forbidden_moves); |
| 524 | |
| 525 | /* Pop move(s) and return. */ |
| 526 | if (extra_pop) |
| 527 | popgo(); |
| 528 | popgo(); |
| 529 | } |
| 530 | |
| 531 | if (!success && saved_move != NO_MOVE) { |
| 532 | ASSERT1(!forbidden_moves[saved_move], saved_move); |
| 533 | *backfill_move = saved_move; |
| 534 | success = 1; |
| 535 | } |
| 536 | |
| 537 | if (!success) |
| 538 | *backfill_move = NO_MOVE; |
| 539 | |
| 540 | return success; |
| 541 | } |
| 542 | |
| 543 | |
| 544 | /* Confirm that (move) is a safe move for color. In addition to |
| 545 | * calling the global confirm_safety(), this function also calls the |
| 546 | * owl code to verify the strategical viability of the move. |
| 547 | */ |
| 548 | static int |
| 549 | filllib_confirm_safety(int move, int color, int *defense_point) |
| 550 | { |
| 551 | int k; |
| 552 | int apos = NO_MOVE; |
| 553 | int save_verbose; |
| 554 | |
| 555 | gg_assert(stackp == 0); |
| 556 | gg_assert(defense_point != NULL); |
| 557 | *defense_point = NO_MOVE; |
| 558 | |
| 559 | /* Before we can call the owl code, we need to find a neighbor of |
| 560 | * our color. |
| 561 | */ |
| 562 | for (k = 0; k < 4; k++) |
| 563 | if (board[move + delta[k]] == color) { |
| 564 | apos = move + delta[k]; |
| 565 | break; |
| 566 | } |
| 567 | |
| 568 | /* If none found, look for a neighbor of an attacked adjacent string. */ |
| 569 | if (apos == NO_MOVE) |
| 570 | for (k = 0; k < 4; k++) { |
| 571 | int pos2 = move + delta[k]; |
| 572 | if (board[pos2] == OTHER_COLOR(color) |
| 573 | && !play_attack_defend_n(color, 0, 1, move, pos2)) { |
| 574 | int adj; |
| 575 | adj = chainlinks(pos2, adjs); |
| 576 | /* It seems unlikely that we would ever get no adjacent strings |
| 577 | * here, but if it should happen we simply give up and say the |
| 578 | * move is unsafe. |
| 579 | */ |
| 580 | if (adj == 0) |
| 581 | return 0; |
| 582 | |
| 583 | apos = adjs[0]; |
| 584 | break; |
| 585 | } |
| 586 | } |
| 587 | |
| 588 | /* Next attempt are diagonal neighbors. */ |
| 589 | if (apos == NO_MOVE) { |
| 590 | for (k = 4; k < 8; k++) |
| 591 | if (board[move + delta[k]] == color) { |
| 592 | apos = move + delta[k]; |
| 593 | break; |
| 594 | } |
| 595 | } |
| 596 | |
| 597 | /* And two steps away. */ |
| 598 | if (apos == NO_MOVE) { |
| 599 | for (k = 0; k < 4; k++) |
| 600 | if (board[move + 2 * delta[k]] == color) { |
| 601 | apos = move + 2 * delta[k]; |
| 602 | break; |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | /* We should have found something by now. If not something's |
| 607 | * probably broken elsewhere. Declare the move unsafe if it happens. |
| 608 | */ |
| 609 | if (apos == NO_MOVE) |
| 610 | return 0; |
| 611 | |
| 612 | /* Ask the owl code whether this move is strategically viable. */ |
| 613 | |
| 614 | save_verbose = verbose; |
| 615 | if (verbose > 0) |
| 616 | verbose--; |
| 617 | if (!owl_does_defend(move, apos, NULL)) |
| 618 | return 0; |
| 619 | verbose = save_verbose; |
| 620 | |
| 621 | return confirm_safety(move, color, defense_point, NULL); |
| 622 | } |
| 623 | |
| 624 | |
| 625 | /* |
| 626 | * Local Variables: |
| 627 | * tab-width: 8 |
| 628 | * c-basic-offset: 2 |
| 629 | * End: |
| 630 | */ |