RCS file: /sources/gnugo/gnugo/engine/aftermath.c,v
retrieving revision 1.61
diff -u -r1.61 aftermath.c
|
|
|
|
| 159 | 159 | reading_hotspots(reading_hotspot); |
| 160 | 160 | |
| 161 | 161 | /* As a preparation we compute a distance map to the invincible strings. */ |
| 162 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 163 | | if (!ON_BOARD(pos)) |
| 164 | | continue; |
| 165 | | else if (board[pos] == color && worm[pos].invincible) |
| | 162 | scan_board(pos, |
| | 163 | if (board[pos] == color && worm[pos].invincible) |
| 166 | 164 | distance[pos] = 0; |
| 167 | 165 | else if (!do_capture_dead_stones |
| 168 | 166 | && ((board[pos] == other |
| … |
… |
|
| 172 | 170 | distance[pos] = 0; |
| 173 | 171 | else |
| 174 | 172 | distance[pos] = -1; |
| 175 | | } |
| | 173 | ) |
| 176 | 174 | |
| 177 | 175 | d = 0; |
| 178 | 176 | do { |
| 179 | 177 | something_found = 0; |
| 180 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 181 | | if (ON_BOARD(pos) && distance[pos] == -1) { |
| | 178 | scan_board(pos, |
| | 179 | if (distance[pos] == -1) { |
| 182 | 180 | for (k = 0; k < 4; k++) { |
| 183 | 181 | int pos2 = pos + delta[k]; |
| 184 | 182 | if (!ON_BOARD(pos2)) |
| … |
… |
|
| 202 | 200 | break; |
| 203 | 201 | } |
| 204 | 202 | } |
| 205 | | } |
| 206 | | } |
| | 203 | } |
| | 204 | ) |
| 207 | 205 | d++; |
| 208 | 206 | } while (something_found); |
| 209 | 207 | |
| 210 | 208 | if (under_control) { |
| 211 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 212 | | if (!ON_BOARD(pos)) |
| 213 | | continue; |
| 214 | | else if (distance[pos] == -1) |
| | 209 | scan_board(pos, |
| | 210 | if (distance[pos] == -1) |
| 215 | 211 | under_control[pos] = 0; |
| 216 | 212 | else |
| 217 | 213 | under_control[pos] = 1; |
| 218 | | } |
| | 214 | ) |
| 219 | 215 | } |
| 220 | 216 | |
| 221 | 217 | if (debug & DEBUG_AFTERMATH) { |
| … |
… |
|
| 272 | 268 | */ |
| 273 | 269 | best_scoring_move = NO_MOVE; |
| 274 | 270 | best_score = 5; |
| 275 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 271 | scan_board(pos, |
| 276 | 272 | int libs; |
| 277 | 273 | if (board[pos] != EMPTY |
| 278 | 274 | || distance[pos] == 0) |
| … |
… |
|
| 304 | 300 | } |
| 305 | 301 | } |
| 306 | 302 | } |
| 307 | | } |
| | 303 | ) |
| 308 | 304 | |
| 309 | 305 | if (best_scoring_move != NO_MOVE |
| 310 | 306 | && safe_move(best_scoring_move, color) == WIN) { |
| … |
… |
|
| 313 | 309 | } |
| 314 | 310 | |
| 315 | 311 | /* Case 1. */ |
| 316 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 312 | scan_board(pos, |
| 317 | 313 | int lib; |
| 318 | 314 | if (board[pos] == other |
| 319 | 315 | && worm[pos].unconditional_status != DEAD |
| … |
… |
|
| 328 | 324 | return lib; |
| 329 | 325 | } |
| 330 | 326 | } |
| 331 | | } |
| | 327 | ) |
| 332 | 328 | |
| 333 | 329 | /* Cases 2--4. */ |
| 334 | 330 | if (closest_opponent != NO_MOVE || closest_own != NO_MOVE) { |
| … |
… |
|
| 345 | 341 | best_score = 0; |
| 346 | 342 | best_scoring_move = move; |
| 347 | 343 | |
| 348 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 344 | scan_board(pos, |
| 349 | 345 | int score = 0; |
| 350 | 346 | int move_ok = 0; |
| 351 | | if (!ON_BOARD(pos) || distance[pos] != 1) |
| | 347 | if (distance[pos] != 1) |
| 352 | 348 | continue; |
| 353 | 349 | mark++; |
| 354 | 350 | for (k = 0; k < 4; k++) { |
| … |
… |
|
| 397 | 393 | best_score = score; |
| 398 | 394 | best_scoring_move = pos; |
| 399 | 395 | } |
| 400 | | } |
| | 396 | ) |
| 401 | 397 | move = best_scoring_move; |
| 402 | 398 | } |
| 403 | 399 | |
| … |
… |
|
| 410 | 406 | move = pos2; |
| 411 | 407 | break; |
| 412 | 408 | } |
| 413 | | } |
| 414 | | } |
| | 409 | } |
| | 410 | } |
| 415 | 411 | return move; |
| 416 | 412 | } |
| 417 | 413 | |
| … |
… |
|
| 423 | 419 | * and with at least one alive but not invincible stone adjacent or |
| 424 | 420 | * diagonal. |
| 425 | 421 | */ |
| 426 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 422 | scan_board(pos, |
| 427 | 423 | int eyespace_neighbors = 0; |
| 428 | 424 | int own_neighbors = 0; |
| 429 | 425 | int own_diagonals = 0; |
| … |
… |
|
| 479 | 475 | bonus += 3; |
| 480 | 476 | } |
| 481 | 477 | mx[origin] = 1; |
| 482 | | } |
| | 478 | } |
| 483 | 479 | else if (board[pos2] == color) { |
| 484 | 480 | dragons[pos] = pos2; |
| 485 | 481 | |
| … |
… |
|
| 532 | 528 | else |
| 533 | 529 | own_diagonals++; |
| 534 | 530 | } |
| 535 | | } |
| | 531 | } |
| 536 | 532 | if (safety == DEAD || safety == UNKNOWN |
| 537 | 533 | || eyespace_neighbors == 0 |
| 538 | 534 | || (own_neighbors + own_diagonals) == 0) |
| … |
… |
|
| 573 | 569 | if (1 && (debug & DEBUG_AFTERMATH)) |
| 574 | 570 | gprintf("Score %1M = %d (hotspot bonus %d + %d)\n", pos, score[pos], |
| 575 | 571 | owl_hotspot_bonus, reading_hotspot_bonus); |
| 576 | | } |
| | 572 | } |
| 577 | 573 | |
| 578 | 574 | /* Avoid taking ko. */ |
| 579 | 575 | if (is_ko(pos, color, NULL)) |
| 580 | 576 | score[pos] = (score[pos] + 1) / 2; |
| 581 | | } |
| | 577 | ) |
| 582 | 578 | |
| 583 | 579 | while (1) { |
| 584 | 580 | int bb; |
| 585 | 581 | best_score = 0; |
| 586 | 582 | move = NO_MOVE; |
| 587 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 588 | | if (ON_BOARD(pos) && score[pos] > best_score) { |
| | 583 | scan_board(pos, |
| | 584 | if (score[pos] > best_score) { |
| 589 | 585 | best_score = score[pos]; |
| 590 | 586 | move = pos; |
| 591 | 587 | } |
| 592 | | } |
| | 588 | ) |
| 593 | 589 | |
| 594 | 590 | if (move == NO_MOVE) |
| 595 | 591 | break; |
| … |
… |
|
| 659 | 655 | * Finally we try to play on liberties of remaining DEAD opponent |
| 660 | 656 | * dragons, carefully checking against mistakes. |
| 661 | 657 | */ |
| 662 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 658 | scan_board(pos, |
| 663 | 659 | int target; |
| 664 | 660 | int cc = NO_MOVE; |
| 665 | 661 | int self_atari_ok = 0; |
| … |
… |
|
| 680 | 676 | target = pos2; |
| 681 | 677 | break; |
| 682 | 678 | } |
| 683 | | } |
| 684 | | } |
| | 679 | } |
| | 680 | } |
| 685 | 681 | if (target == NO_MOVE) |
| 686 | 682 | continue; |
| 687 | 683 | |
| … |
… |
|
| 722 | 718 | self_atari_ok = 0; |
| 723 | 719 | cc = pos + delta[k]; |
| 724 | 720 | break; |
| 725 | | } |
| 726 | | } |
| | 721 | } |
| | 722 | } |
| 727 | 723 | |
| 728 | 724 | /* Copy the potential move to (move). */ |
| 729 | 725 | move = pos; |
| … |
… |
|
| 739 | 735 | move = lib; |
| 740 | 736 | if (!trymove(move, color, "aftermath-B", target)) |
| 741 | 737 | break; |
| 742 | | } |
| | 738 | } |
| 743 | 739 | |
| 744 | 740 | if (countlib(pos) == 1) |
| 745 | 741 | move = NO_MOVE; |
| 746 | | } |
| | 742 | } |
| 747 | 743 | |
| 748 | 744 | while (stackp > 0) |
| 749 | 745 | popgo(); |
| … |
… |
|
| 768 | 764 | * verify that it remains safe. |
| 769 | 765 | */ |
| 770 | 766 | if (cc != NO_MOVE && !owl_does_defend(move, cc, NULL)) { |
| 771 | | int resulta, resultb; |
| | 767 | int resulta; |
| | 768 | int resultb; |
| 772 | 769 | owl_analyze_semeai_after_move(move, color, target, cc, |
| 773 | 770 | &resulta, &resultb, NULL, 1, NULL, 1); |
| 774 | 771 | if (resulta != 0) |
| 775 | 772 | continue; |
| 776 | | } |
| | 773 | } |
| 777 | 774 | |
| 778 | 775 | /* If we don't allow self atari, also call confirm safety to |
| 779 | 776 | * avoid setting up combination attacks. |
| … |
… |
|
| 783 | 780 | |
| 784 | 781 | DEBUG(DEBUG_AFTERMATH, "Filling opponent liberty at %1m\n", move); |
| 785 | 782 | return move; |
| 786 | | } |
| 787 | | } |
| | 783 | } |
| | 784 | ) |
| 788 | 785 | |
| 789 | 786 | /* Case 7. |
| 790 | 787 | * In very rare cases it turns out we need yet another pass. An |
| … |
… |
|
| 805 | 802 | * The solution is to look for tactically attackable opponent stones |
| 806 | 803 | * that still remain on the board but should be removed. |
| 807 | 804 | */ |
| 808 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 805 | scan_board(pos, |
| 809 | 806 | if (board[pos] == other |
| 810 | 807 | && (worm[pos].unconditional_status == UNKNOWN |
| 811 | 808 | || do_capture_dead_stones) |
| … |
… |
|
| 817 | 814 | pos, worm[pos].attack_points[0]); |
| 818 | 815 | return worm[pos].attack_points[0]; |
| 819 | 816 | } |
| 820 | | } |
| | 817 | ) |
| 821 | 818 | |
| 822 | 819 | /* No move found. */ |
| 823 | 820 | return PASS_MOVE; |
| … |
… |
|
| 954 | 951 | cached_board = 0; |
| 955 | 952 | } |
| 956 | 953 | |
| 957 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 958 | | if (ON_BOARD(pos) && board[pos] != current_board[pos]) { |
| | 954 | scan_board(pos, |
| | 955 | if (board[pos] != current_board[pos]) { |
| 959 | 956 | current_board[pos] = board[pos]; |
| 960 | 957 | cached_board = 0; |
| 961 | 958 | } |
| 962 | | } |
| | 959 | ) |
| 963 | 960 | |
| 964 | 961 | /* If this is exactly the same position as the one we analyzed the |
| 965 | 962 | * last time, the content of the aftermath struct is up to date. |
| … |
… |
|
| 980 | 977 | do_play_aftermath(color, a, aftermath_sgftree); |
| 981 | 978 | restore_board(&saved_board); |
| 982 | 979 | |
| 983 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 984 | | if (!ON_BOARD(pos)) |
| 985 | | continue; |
| | 980 | scan_board(pos, |
| 986 | 981 | if (a->black_control[pos]) { |
| 987 | 982 | a->black_area++; |
| 988 | 983 | if (board[pos] == WHITE) { |
| … |
… |
|
| 1022 | 1017 | a->black_area++; |
| 1023 | 1018 | } |
| 1024 | 1019 | } |
| 1025 | | } |
| | 1020 | ) |
| 1026 | 1021 | |
| 1027 | 1022 | if (debug & DEBUG_AFTERMATH) { |
| 1028 | 1023 | gprintf("White captured: %d\n", a->white_captured); |