RCS file: /sources/gnugo/gnugo/engine/worm.c,v
retrieving revision 1.72
diff -u -r1.72 worm.c
|
|
|
|
| 106 | 106 | gg_assert(stackp == 0); |
| 107 | 107 | |
| 108 | 108 | /* Count liberties of different orders and initialize cutstone fields. */ |
| 109 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 109 | scan_board(pos, |
| 110 | 110 | if (IS_STONE(board[pos]) && is_worm_origin(pos, pos)) { |
| 111 | | int lib1, lib2, lib3, lib4; |
| | 111 | int lib1; |
| | 112 | int lib2; |
| | 113 | int lib3; |
| | 114 | int lib4; |
| 112 | 115 | |
| 113 | 116 | ping_cave(pos, &lib1, &lib2, &lib3, &lib4); |
| 114 | 117 | ASSERT1(worm[pos].liberties == lib1, pos); |
| … |
… |
|
| 119 | 122 | worm[pos].cutstone2 = 0; |
| 120 | 123 | propagate_worm(pos); |
| 121 | 124 | } |
| 122 | | } |
| | 125 | ) |
| 123 | 126 | |
| 124 | 127 | gg_assert(stackp == 0); |
| 125 | 128 | |
| … |
… |
|
| 172 | 175 | * possible we also need the old concept for correct handling of lunches. |
| 173 | 176 | */ |
| 174 | 177 | |
| 175 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 178 | scan_board(pos, |
| 176 | 179 | int w1 = NO_MOVE; |
| 177 | 180 | int w2 = NO_MOVE; |
| 178 | 181 | int k; |
| … |
… |
|
| 187 | 190 | /* Try to find two adjacent worms (w1) and (w2) |
| 188 | 191 | * of opposite colour from (pos). |
| 189 | 192 | */ |
| 190 | | for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) { |
| | 193 | scan_board(pos2, |
| 191 | 194 | /* Work only with the opposite color from (pos). */ |
| 192 | 195 | if (board[pos2] != OTHER_COLOR(board[pos])) |
| 193 | 196 | continue; |
| … |
… |
|
| 207 | 210 | else if (!is_same_worm(pos2, w1)) |
| 208 | 211 | w2 = worm[pos2].origin; |
| 209 | 212 | } |
| 210 | | } |
| | 213 | ) |
| 211 | 214 | |
| 212 | 215 | /* |
| 213 | 216 | * We now verify the definition of cutting stones. We have |
| … |
… |
|
| 225 | 228 | DEBUG(DEBUG_WORMS, "Worm at %1m has w1 %1m and w2 %1m, cutstone %d\n", |
| 226 | 229 | pos, w1, w2, worm[pos].cutstone); |
| 227 | 230 | } |
| 228 | | } |
| | 231 | ) |
| 229 | 232 | |
| 230 | 233 | gg_assert(stackp == 0); |
| 231 | 234 | |
| 232 | 235 | /* Set the genus of all worms. */ |
| 233 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 236 | scan_board(pos, |
| 234 | 237 | if (IS_STONE(board[pos]) && is_worm_origin(pos, pos)) { |
| 235 | 238 | worm[pos].genus = genus(pos); |
| 236 | 239 | propagate_worm(pos); |
| 237 | 240 | } |
| 238 | | } |
| | 241 | ) |
| 239 | 242 | gg_assert(stackp == 0); |
| 240 | 243 | |
| 241 | 244 | /* Now we try to improve the values of worm.attack and worm.defend. |
| … |
… |
|
| 251 | 254 | memset(moves_to_try, 0, sizeof(moves_to_try)); |
| 252 | 255 | |
| 253 | 256 | /* Find which colors to try at what points. */ |
| 254 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| | 257 | scan_board(str, |
| 255 | 258 | if (IS_STONE(board[str]) && is_worm_origin(str, str)) { |
| 256 | 259 | color = board[str]; |
| 257 | 260 | moves_to_try[worm[str].defense_points[0]] |= color; |
| 258 | 261 | moves_to_try[worm[str].attack_points[0]] |= OTHER_COLOR(color); |
| 259 | 262 | } |
| 260 | | } |
| | 263 | ) |
| 261 | 264 | |
| 262 | 265 | /* Loop over the board and over the colors and try the moves found |
| 263 | 266 | * in the previous loop. |
| 264 | 267 | */ |
| 265 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 266 | | if (!ON_BOARD(pos)) |
| 267 | | continue; |
| | 268 | scan_board(pos, |
| 268 | 269 | |
| 269 | 270 | for (color = WHITE; color <= BLACK; color++) { |
| 270 | 271 | if (!(moves_to_try[pos] & color)) |
| … |
… |
|
| 286 | 287 | /* Now we try to find a group which is saved or attacked as well |
| 287 | 288 | * by this move. |
| 288 | 289 | */ |
| 289 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| | 290 | scan_board(str, |
| 290 | 291 | if (!IS_STONE(board[str]) |
| 291 | 292 | || !is_worm_origin(str, str)) |
| 292 | 293 | continue; |
| … |
… |
|
| 376 | 377 | } |
| 377 | 378 | } |
| 378 | 379 | } |
| 379 | | } |
| | 380 | ) |
| 380 | 381 | decrease_depth_values(); |
| 381 | 382 | popgo(); |
| 382 | 383 | } |
| 383 | | } |
| | 384 | ) |
| 384 | 385 | } |
| 385 | 386 | |
| 386 | 387 | gg_assert(stackp == 0); |
| … |
… |
|
| 403 | 404 | */ |
| 404 | 405 | |
| 405 | 406 | /* First look for vertical neighbors. */ |
| 406 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 407 | scan_board(pos, |
| 407 | 408 | if (IS_STONE(board[pos]) |
| 408 | 409 | && IS_STONE(board[SOUTH(pos)]) |
| 409 | 410 | && !is_same_worm(pos, SOUTH(pos))) { |
| … |
… |
|
| 421 | 422 | } |
| 422 | 423 | } |
| 423 | 424 | } |
| 424 | | } |
| | 425 | ) |
| 425 | 426 | |
| 426 | 427 | /* Then look for horizontal neighbors. */ |
| 427 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 428 | scan_board(pos, |
| 428 | 429 | if (IS_STONE(board[pos]) |
| 429 | 430 | && IS_STONE(board[EAST(pos)]) |
| 430 | 431 | && !is_same_worm(pos, EAST(pos))) { |
| … |
… |
|
| 442 | 443 | } |
| 443 | 444 | } |
| 444 | 445 | } |
| 445 | | } |
| | 446 | ) |
| 446 | 447 | |
| 447 | 448 | gg_assert(stackp == 0); |
| 448 | 449 | |
| 449 | 450 | /* Find adjacent worms that can be easily captured, aka lunches. */ |
| 450 | 451 | |
| 451 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 452 | scan_board(pos, |
| 452 | 453 | int lunch; |
| 453 | 454 | |
| 454 | 455 | if (!IS_STONE(board[pos]) || !is_worm_origin(pos, pos)) |
| … |
… |
|
| 464 | 465 | worm[pos].lunch = NO_MOVE; |
| 465 | 466 | |
| 466 | 467 | propagate_worm(pos); |
| 467 | | } |
| | 468 | ) |
| 468 | 469 | |
| 469 | 470 | if (!disable_threat_computation) |
| 470 | 471 | find_worm_threats(); |
| … |
… |
|
| 492 | 493 | * opponent's eye space. |
| 493 | 494 | */ |
| 494 | 495 | |
| 495 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 496 | scan_board(pos, |
| 496 | 497 | if (IS_STONE(board[pos]) |
| 497 | 498 | && worm[pos].origin == pos |
| 498 | 499 | && worm[pos].genus == 0 |
| … |
… |
|
| 507 | 508 | propagate_worm(pos); |
| 508 | 509 | } |
| 509 | 510 | } |
| 510 | | } |
| | 511 | ) |
| 511 | 512 | } |
| 512 | 513 | |
| 513 | 514 | |
| … |
… |
|
| 526 | 527 | memset(worm, 0 , sizeof(worm)); |
| 527 | 528 | |
| 528 | 529 | /* Initialize the worm data for each worm. */ |
| 529 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 530 | | if (ON_BOARD(pos)) |
| 531 | | worm[pos].origin = NO_MOVE; |
| | 530 | scan_board(pos, |
| | 531 | worm[pos].origin = NO_MOVE; |
| | 532 | ) |
| 532 | 533 | |
| 533 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 534 | | if (!ON_BOARD(pos) || worm[pos].origin != NO_MOVE) |
| | 534 | scan_board(pos, |
| | 535 | if (worm[pos].origin != NO_MOVE) |
| 535 | 536 | continue; |
| 536 | 537 | worm[pos].color = board[pos]; |
| 537 | 538 | worm[pos].origin = pos; |
| … |
… |
|
| 544 | 545 | worm[pos].size = countstones(pos); |
| 545 | 546 | propagate_worm(pos); |
| 546 | 547 | } |
| 547 | | } |
| | 548 | ) |
| 548 | 549 | } |
| 549 | 550 | |
| 550 | 551 | |
| … |
… |
|
| 596 | 597 | int r; |
| 597 | 598 | |
| 598 | 599 | /* Initialize arrays. */ |
| 599 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 600 | | if (!ON_BOARD(pos)) |
| 601 | | continue; |
| | 600 | scan_board(pos, |
| 602 | 601 | |
| 603 | 602 | for (k = 0; k < 2*(board_size-1); k++) |
| 604 | 603 | worms[pos][k] = NO_MOVE; |
| … |
… |
|
| 612 | 611 | } |
| 613 | 612 | else |
| 614 | 613 | distance[pos] = -1; |
| 615 | | } |
| | 614 | ) |
| 616 | 615 | |
| 617 | 616 | dist = 0; |
| 618 | 617 | found_one = 1; |
| 619 | 618 | while (found_one && dist <= max_distance) { |
| 620 | 619 | found_one = 0; |
| 621 | 620 | dist++; |
| 622 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 623 | | if (!ON_BOARD(pos) || distance[pos] != -1) |
| | 621 | scan_board(pos, |
| | 622 | if (distance[pos] != -1) |
| 624 | 623 | continue; /* already claimed */ |
| 625 | 624 | |
| 626 | 625 | for (r = 0; r < 4; r++) { |
| … |
… |
|
| 644 | 643 | } |
| 645 | 644 | } |
| 646 | 645 | } |
| 647 | | } |
| | 646 | ) |
| 648 | 647 | } |
| 649 | 648 | |
| 650 | 649 | /* Compute the effective sizes but only when all worms are considered. */ |
| 651 | 650 | if (color == (BLACK | WHITE)) { |
| 652 | 651 | /* Distribute (fractional) contributions to the worms. */ |
| 653 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 654 | | if (!ON_BOARD(pos)) |
| 655 | | continue; |
| | 652 | scan_board(pos, |
| 656 | 653 | |
| 657 | 654 | for (k = 0; k < nworms[pos]; k++) { |
| 658 | 655 | int w = worms[pos][k]; |
| … |
… |
|
| 661 | 658 | else |
| 662 | 659 | worm[w].effective_size += 1.0; |
| 663 | 660 | } |
| 664 | | } |
| | 661 | ) |
| 665 | 662 | |
| 666 | 663 | /* Propagate the effective size values all over the worms. */ |
| 667 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| | 664 | scan_board(pos, |
| 668 | 665 | if (IS_STONE(board[pos]) && is_worm_origin(pos, pos)) |
| 669 | | propagate_worm(pos); |
| | 666 | propagate_worm(pos); |
| | 667 | ) |
| 670 | 668 | } |
| 671 | 669 | |
| 672 | 670 | /* Fill in the appropriate close_*_worms (cw) and |
| 673 | 671 | * number_close_*_worms (ncw) arrays. |
| 674 | 672 | */ |
| 675 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 676 | | if (!ON_BOARD(pos)) |
| 677 | | continue; |
| 678 | | |
| | 673 | scan_board(pos, |
| 679 | 674 | if (nworms[pos] > MAX_CLOSE_WORMS) |
| 680 | 675 | ncw[pos] = 0; |
| 681 | 676 | else |
| … |
… |
|
| 683 | 678 | |
| 684 | 679 | for (k = 0; k < ncw[pos]; k++) |
| 685 | 680 | cw[pos][k] = worms[pos][k]; |
| 686 | | } |
| | 681 | ) |
| 687 | 682 | } |
| 688 | 683 | |
| 689 | 684 | /* Identify worms which are unconditionally uncapturable in the |
| … |
… |
|
| 702 | 697 | for (color = WHITE; color <= BLACK; color++) { |
| 703 | 698 | unconditional_life(unconditional_territory, color); |
| 704 | 699 | |
| 705 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 706 | | if (!ON_BOARD(pos) || !unconditional_territory[pos]) |
| | 700 | scan_board(pos, |
| | 701 | if (!unconditional_territory[pos]) |
| 707 | 702 | continue; |
| 708 | 703 | |
| 709 | 704 | if (board[pos] == color) { |
| … |
… |
|
| 719 | 714 | } |
| 720 | 715 | else |
| 721 | 716 | worm[pos].unconditional_status = DEAD; |
| 722 | | } |
| | 717 | ) |
| 723 | 718 | } |
| 724 | 719 | gg_assert(stackp == 0); |
| 725 | 720 | } |
| … |
… |
|
| 742 | 737 | int other; |
| 743 | 738 | |
| 744 | 739 | /* 1. Start with finding attack points. */ |
| 745 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| | 740 | scan_board(str, |
| 746 | 741 | if (!IS_STONE(board[str]) || !is_worm_origin(str, str)) |
| 747 | 742 | continue; |
| 748 | 743 | |
| … |
… |
|
| 762 | 757 | str, attack_point); |
| 763 | 758 | change_attack(str, attack_point, acode); |
| 764 | 759 | } |
| 765 | | } |
| | 760 | ) |
| 766 | 761 | gg_assert(stackp == 0); |
| 767 | 762 | |
| 768 | 763 | /* 2. Use pattern matching to find a few more attacks. */ |
| … |
… |
|
| 770 | 765 | gg_assert(stackp == 0); |
| 771 | 766 | |
| 772 | 767 | /* 3. Now find defense moves. */ |
| 773 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| | 768 | scan_board(str, |
| 774 | 769 | if (!IS_STONE(board[str]) || !is_worm_origin(str, str)) |
| 775 | 770 | continue; |
| 776 | 771 | |
| … |
… |
|
| 801 | 796 | } |
| 802 | 797 | } |
| 803 | 798 | } |
| 804 | | } |
| | 799 | ) |
| 805 | 800 | gg_assert(stackp == 0); |
| 806 | 801 | |
| 807 | 802 | /* 4. Use pattern matching to find a few more defense moves. */ |
| … |
… |
|
| 814 | 809 | * matching and by trying whether each attack or defense point |
| 815 | 810 | * attacks or defends other strings. |
| 816 | 811 | */ |
| 817 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| | 812 | scan_board(str, |
| 818 | 813 | color = board[str]; |
| 819 | 814 | if (!IS_STONE(color) || !is_worm_origin(str, str)) |
| 820 | 815 | continue; |
| … |
… |
|
| 860 | 855 | } |
| 861 | 856 | } |
| 862 | 857 | } |
| 863 | | } |
| | 858 | ) |
| 864 | 859 | gg_assert(stackp == 0); |
| 865 | 860 | } |
| 866 | 861 | |
| … |
… |
|
| 880 | 875 | int l; |
| 881 | 876 | int color; |
| 882 | 877 | |
| 883 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| | 878 | scan_board(str, |
| 884 | 879 | color = board[str]; |
| 885 | 880 | if (!IS_STONE(color) || !is_worm_origin(str, str)) |
| 886 | 881 | continue; |
| … |
… |
|
| 969 | 964 | |
| 970 | 965 | /* FIXME: Try other moves also (patterns?). */ |
| 971 | 966 | } |
| 972 | | } |
| | 967 | ) |
| 973 | 968 | } |
| 974 | 969 | |
| 975 | 970 | |
| … |
… |
|
| 990 | 985 | ASSERT1(stackp == 0, str); |
| 991 | 986 | |
| 992 | 987 | *lunch = NO_MOVE; |
| 993 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 988 | scan_board(pos, |
| 994 | 989 | if (board[pos] != OTHER_COLOR(board[str])) |
| 995 | 990 | continue; |
| 996 | 991 | for (k = 0; k < 8; k++) { |
| … |
… |
|
| 1013 | 1008 | break; |
| 1014 | 1009 | } |
| 1015 | 1010 | } |
| 1016 | | } |
| | 1011 | ) |
| 1017 | 1012 | |
| 1018 | 1013 | if (*lunch != NO_MOVE) |
| 1019 | 1014 | return 1; |
| … |
… |
|
| 1221 | 1216 | ASSERT_ON_BOARD1(str); |
| 1222 | 1217 | ASSERT1(IS_STONE(worm[str].color), str); |
| 1223 | 1218 | |
| 1224 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| | 1219 | scan_board(pos, |
| 1225 | 1220 | if (board[pos] == board[str] && is_same_worm(pos, str) |
| 1226 | 1221 | && pos != str) |
| 1227 | 1222 | worm[pos] = worm[str]; |
| | 1223 | ) |
| 1228 | 1224 | } |
| 1229 | 1225 | |
| 1230 | 1226 | |
| … |
… |
|
| 1237 | 1233 | int pos; |
| 1238 | 1234 | int k; |
| 1239 | 1235 | |
| 1240 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 1241 | | if (!ON_BOARD(pos) || board[pos] == EMPTY) |
| | 1236 | scan_board(pos, |
| | 1237 | if (board[pos] == EMPTY) |
| 1242 | 1238 | continue; |
| 1243 | 1239 | |
| 1244 | 1240 | if (!is_worm_origin(pos, pos)) |
| … |
… |
|
| 1266 | 1262 | worm[pos].defense_threat_codes[k]); |
| 1267 | 1263 | } |
| 1268 | 1264 | } |
| 1269 | | } |
| | 1265 | ) |
| 1270 | 1266 | } |
| 1271 | 1267 | |
| 1272 | 1268 | |
| … |
… |
|
| 1323 | 1319 | * opposite color, or one stone and the edge. |
| 1324 | 1320 | */ |
| 1325 | 1321 | |
| 1326 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 1327 | | if (ON_BOARD(pos) |
| 1328 | | && mse[pos] |
| | 1322 | scan_board(pos, |
| | 1323 | if (mse[pos] |
| 1329 | 1324 | && ((( !ON_BOARD(SOUTH(pos)) || board[SOUTH(pos)] == other) |
| 1330 | 1325 | && ( !ON_BOARD(NORTH(pos)) || board[NORTH(pos)] == other)) |
| 1331 | 1326 | || (( !ON_BOARD(WEST(pos)) || board[WEST(pos)] == other) |
| 1332 | 1327 | && (!ON_BOARD(EAST(pos)) || board[EAST(pos)] == other)))) |
| 1333 | 1328 | mse[pos] = 0; |
| | 1329 | ) |
| 1334 | 1330 | |
| 1335 | 1331 | *lib2 = 0; |
| 1336 | 1332 | memset(mrc, 0, sizeof(mrc)); |
| … |
… |
|
| 1408 | 1404 | int gen = -1; |
| 1409 | 1405 | |
| 1410 | 1406 | memset(mg, 0, sizeof(mg)); |
| 1411 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 1412 | | if (ON_BOARD(pos) |
| 1413 | | && !mg[pos] |
| | 1407 | scan_board(pos, |
| | 1408 | if (!mg[pos] |
| 1414 | 1409 | && (board[pos] == EMPTY || !is_same_worm(pos, str))) { |
| 1415 | 1410 | markcomponent(str, pos, mg); |
| 1416 | 1411 | gen++; |
| 1417 | 1412 | } |
| 1418 | | } |
| | 1413 | ) |
| 1419 | 1414 | |
| 1420 | 1415 | return gen; |
| 1421 | 1416 | } |
| … |
… |
|
| 1707 | 1702 | get_lively_stones(int color, signed char safe_stones[BOARDMAX]) |
| 1708 | 1703 | { |
| 1709 | 1704 | int ii; |
| 1710 | | memset(safe_stones, 0, BOARDMAX * sizeof(*safe_stones)); |
| 1711 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) |
| 1712 | | ASSERT1(safe_stones[ii] == 0, ii); |
| 1713 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) |
| | 1705 | memset(safe_stones, 0, BOARDMAX * sizeof(signed char)); |
| | 1706 | |
| | 1707 | scan_board(ii, |
| 1714 | 1708 | if (IS_STONE(board[ii]) |
| 1715 | 1709 | && worm[ii].origin == ii) { |
| 1716 | 1710 | if (worm[ii].attack_codes[0] == 0 |
| 1717 | 1711 | || (board[ii] == color |
| 1718 | 1712 | && worm[ii].defense_codes[0] != 0)) |
| 1719 | 1713 | mark_string(ii, safe_stones, 1); |
| 1720 | | } |
| | 1714 | } |
| | 1715 | ) |
| 1721 | 1716 | } |
| 1722 | 1717 | |
| 1723 | 1718 | |