RCS file: /sources/gnugo/gnugo/engine/optics.c,v
retrieving revision 1.105
diff -u -r1.105 optics.c
|
|
|
|
| 118 | 118 | memset(w_eye, 0, BOARDMAX * sizeof(w_eye[0])); |
| 119 | 119 | |
| 120 | 120 | /* Initialize eye data and compute the lively array. */ |
| 121 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 122 | | if (ON_BOARD(pos)) |
| 123 | | lively[pos] = is_lively(owl_call, pos); |
| | 121 | scan_board(pos, |
| | 122 | lively[pos] = is_lively(owl_call, pos); |
| | 123 | ) |
| 124 | 124 | |
| 125 | 125 | /* Compute the domains of influence of each color. */ |
| 126 | 126 | compute_primary_domains(BLACK, black_domain, lively, false_margins, 1); |
| … |
… |
|
| 130 | 130 | * each eye shape. |
| 131 | 131 | */ |
| 132 | 132 | |
| 133 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 134 | | if (!ON_BOARD(pos)) |
| 135 | | continue; |
| | 133 | scan_board(pos, |
| 136 | 134 | |
| 137 | 135 | if (board[pos] == EMPTY || !lively[pos]) { |
| 138 | 136 | if (black_domain[pos] == 0 && white_domain[pos] == 0) { |
| … |
… |
|
| 191 | 189 | } |
| 192 | 190 | } |
| 193 | 191 | } |
| 194 | | } |
| | 192 | ) |
| 195 | 193 | |
| 196 | 194 | /* The eye spaces are all found. Now we need to find the origins. */ |
| 197 | 195 | partition_eyespaces(b_eye, BLACK); |
| … |
… |
|
| 207 | 205 | if (!eye) |
| 208 | 206 | return; |
| 209 | 207 | |
| 210 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 211 | | if (ON_BOARD(pos)) |
| 212 | | eye[pos].origin = NO_MOVE; |
| | 208 | scan_board(pos, |
| | 209 | eye[pos].origin = NO_MOVE; |
| | 210 | ) |
| | 211 | |
| | 212 | scan_board(pos, |
| 213 | 213 | |
| 214 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 215 | | if (!ON_BOARD(pos)) |
| 216 | | continue; |
| 217 | 214 | if (eye[pos].origin == NO_MOVE && eye[pos].color == color) { |
| 218 | 215 | int esize = 0; |
| 219 | 216 | int msize = 0; |
| … |
… |
|
| 222 | 219 | eye[pos].esize = esize; |
| 223 | 220 | eye[pos].msize = msize; |
| 224 | 221 | } |
| 225 | | } |
| | 222 | ) |
| 226 | 223 | |
| 227 | 224 | /* Now we count the number of neighbors and marginal neighbors |
| 228 | 225 | * of each vertex. |
| … |
… |
|
| 302 | 299 | * (Cases (1) and (2) above.) |
| 303 | 300 | * 2. Fill influence[] and threshold[] arrays with initial values. |
| 304 | 301 | */ |
| 305 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 306 | | if (!ON_BOARD(pos)) |
| 307 | | continue; |
| | 302 | scan_board(pos, |
| 308 | 303 | |
| 309 | 304 | if (lively[pos]) { |
| 310 | 305 | if (board[pos] == color) { |
| … |
… |
|
| 356 | 351 | } |
| 357 | 352 | else if (is_edge_vertex(pos)) |
| 358 | 353 | influence[pos]--; |
| 359 | | } |
| | 354 | ) |
| 360 | 355 | |
| 361 | 356 | /* Now we loop over the board until no more vertices can be added to |
| 362 | 357 | * the domain through case (3) above. |
| … |
… |
|
| 410 | 405 | int pos; |
| 411 | 406 | int k; |
| 412 | 407 | |
| 413 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 414 | | if (!ON_BOARD(pos) || eyedata[pos].origin == NO_MOVE) |
| | 408 | scan_board(pos, |
| | 409 | if (eyedata[pos].origin == NO_MOVE) |
| 415 | 410 | continue; |
| 416 | 411 | |
| 417 | 412 | eyedata[pos].esize = eyedata[eyedata[pos].origin].esize; |
| … |
… |
|
| 427 | 422 | eyedata[pos].marginal_neighbors++; |
| 428 | 423 | } |
| 429 | 424 | } |
| 430 | | } |
| | 425 | ) |
| 431 | 426 | } |
| 432 | 427 | |
| 433 | 428 | |
| … |
… |
|
| 565 | 560 | { |
| 566 | 561 | int pos; |
| 567 | 562 | |
| 568 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 569 | | if (ON_BOARD(pos) && eye[pos].origin == origin) { |
| | 563 | scan_board(pos, |
| | 564 | if (eye[pos].origin == origin) { |
| 570 | 565 | eye[pos].color = eye[origin].color; |
| 571 | 566 | eye[pos].esize = eye[origin].esize; |
| 572 | 567 | eye[pos].msize = eye[origin].msize; |
| 573 | 568 | eye[pos].origin = eye[origin].origin; |
| 574 | 569 | eye[pos].value = eye[origin].value; |
| 575 | 570 | } |
| | 571 | ) |
| 576 | 572 | } |
| 577 | 573 | |
| 578 | 574 | |
| … |
… |
|
| 591 | 587 | |
| 592 | 588 | memset(mx, 0, sizeof(mx)); |
| 593 | 589 | DEBUG(DEBUG_MISCELLANEOUS, "find_eye_dragons: %1m %C\n", origin, eye_color); |
| 594 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 590 | scan_board(pos, |
| 595 | 591 | if (board[pos] == eye_color |
| 596 | 592 | && mx[dragon[pos].origin] == 0 |
| 597 | 593 | && ((ON_BOARD(SOUTH(pos)) |
| … |
… |
|
| 613 | 609 | dragons[num_dragons] = dragon[pos].origin; |
| 614 | 610 | num_dragons++; |
| 615 | 611 | } |
| 616 | | } |
| | 612 | ) |
| 617 | 613 | |
| 618 | 614 | return num_dragons; |
| 619 | 615 | } |
| … |
… |
|
| 634 | 630 | gprintf("Eyespace at %1m: color=%C, esize=%d, msize=%d\n", |
| 635 | 631 | pos, eye[pos].color, eye[pos].esize, eye[pos].msize); |
| 636 | 632 | |
| 637 | | for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) { |
| 638 | | if (!ON_BOARD(pos2)) |
| 639 | | continue; |
| | 633 | scan_board(pos2, |
| 640 | 634 | |
| 641 | 635 | if (eye[pos2].origin != pos) |
| 642 | 636 | continue; |
| … |
… |
|
| 663 | 657 | } |
| 664 | 658 | else |
| 665 | 659 | gprintf("%1m\n", pos2); |
| 666 | | } |
| | 660 | ) |
| 667 | 661 | gprintf("\n"); |
| 668 | 662 | |
| 669 | 663 | /* Determine the size of the eye. */ |
| … |
… |
|
| 789 | 783 | |
| 790 | 784 | memset(chainlinks, 0, BOARDMAX); |
| 791 | 785 | |
| 792 | | for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) { |
| | 786 | scan_board(pos2, |
| 793 | 787 | int k; |
| 794 | 788 | |
| 795 | | if (!ON_BOARD(pos2) || eye[pos2].origin != pos) |
| | 789 | if (eye[pos2].origin != pos) |
| 796 | 790 | continue; |
| 797 | 791 | |
| 798 | 792 | if (eye[pos2].marginal || is_halfeye(heye, pos2)) { |
| … |
… |
|
| 819 | 813 | else if (!ON_BOARD(neighbor)) |
| 820 | 814 | bulk_score += 2; |
| 821 | 815 | } |
| 822 | | } |
| | 816 | ) |
| 823 | 817 | |
| 824 | 818 | /* This is a measure based on the simplified assumption that both |
| 825 | 819 | * players only cares about playing the marginal eye spaces. It is |
| … |
… |
|
| 891 | 885 | int best_defense_point = NO_MOVE; |
| 892 | 886 | float score = 0.0; |
| 893 | 887 | |
| 894 | | for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) { |
| 895 | | if (ON_BOARD(pos2) && eye[pos2].origin == pos) { |
| | 888 | scan_board(pos2, |
| | 889 | if (eye[pos2].origin == pos) { |
| 896 | 890 | float this_score = 0.0; |
| 897 | 891 | int this_attack_point = NO_MOVE; |
| 898 | 892 | int this_defense_point = NO_MOVE; |
| … |
… |
|
| 922 | 916 | score = this_score; |
| 923 | 917 | } |
| 924 | 918 | } |
| 925 | | } |
| | 919 | ) |
| 926 | 920 | |
| 927 | 921 | if (score > 0.0) { |
| 928 | 922 | if (defense_point) |
| 929 | 923 | *defense_point = best_defense_point; |
| 930 | 924 | if (attack_point) |
| 931 | 925 | *attack_point = best_attack_point; |
| 932 | | } |
| | 926 | } |
| 933 | 927 | } |
| 934 | 928 | |
| 935 | 929 | if (defense_point && *defense_point != NO_MOVE) { |
| … |
… |
|
| 1048 | 1042 | return 0; |
| 1049 | 1043 | |
| 1050 | 1044 | /* Find ko half eyes and "combination" half eyes if any. */ |
| 1051 | | for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) { |
| 1052 | | if (ON_BOARD(pos2) |
| 1053 | | && eye[pos2].origin == pos |
| | 1045 | scan_board(pos2, |
| | 1046 | if (eye[pos2].origin == pos |
| 1054 | 1047 | && heye[pos2].type == HALF_EYE) { |
| 1055 | 1048 | if (combination_halfeye == NO_MOVE) { |
| 1056 | 1049 | int apos = NO_MOVE; |
| … |
… |
|
| 1082 | 1075 | ko_halfeye = pos2; |
| 1083 | 1076 | } |
| 1084 | 1077 | } |
| 1085 | | } |
| | 1078 | ) |
| 1086 | 1079 | |
| 1087 | 1080 | /* In case we have a "combination" half eye, turn it into a proper eye |
| 1088 | 1081 | * vertex for a while and see what happens. |
| … |
… |
|
| 1230 | 1223 | return 0; |
| 1231 | 1224 | |
| 1232 | 1225 | /* Create list of eye vertices */ |
| 1233 | | for (pos2 = BOARDMIN; pos2 < BOARDMAX; pos2++) { |
| 1234 | | if (!ON_BOARD(pos2)) |
| 1235 | | continue; |
| | 1226 | scan_board(pos2, |
| 1236 | 1227 | if (eye[pos2].origin == pos) { |
| 1237 | 1228 | vpos[eye_size] = pos2; |
| 1238 | 1229 | marginal[eye_size] = eye[pos2].marginal; |
| … |
… |
|
| 1271 | 1262 | |
| 1272 | 1263 | eye_size++; |
| 1273 | 1264 | } |
| 1274 | | } |
| | 1265 | ) |
| 1275 | 1266 | |
| 1276 | 1267 | /* We attempt to construct a map from the graph to the eyespace |
| 1277 | 1268 | * preserving the adjacency structure. If this can be done, we've |
| … |
… |
|
| 1686 | 1677 | int pos; |
| 1687 | 1678 | float sum; |
| 1688 | 1679 | |
| 1689 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 1680 | scan_board(pos, |
| 1690 | 1681 | /* skip eyespaces which owl doesn't want to be searched */ |
| 1691 | | if (!ON_BOARD(pos) || (find_mask && find_mask[eye[pos].origin] <= 1)) |
| | 1682 | if (find_mask && find_mask[eye[pos].origin] <= 1) |
| 1692 | 1683 | continue; |
| 1693 | 1684 | |
| 1694 | 1685 | /* skip every vertex which can't be a false or half eye */ |
| … |
… |
|
| 1714 | 1705 | ASSERT1(heye[pos].num_defenses > 0, pos); |
| 1715 | 1706 | ASSERT_ON_BOARD1(heye[pos].defense_point[0]); |
| 1716 | 1707 | } |
| 1717 | | } |
| | 1708 | ) |
| 1718 | 1709 | } |
| 1719 | 1710 | |
| 1720 | 1711 | |
| … |
… |
|
| 2386 | 2377 | } |
| 2387 | 2378 | |
| 2388 | 2379 | /* Play white stones surrounding the eyespace, including diagonals. */ |
| 2389 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 2390 | | if (!ON_BOARD(pos) || mx[pos] == 1) |
| | 2380 | scan_board(pos, |
| | 2381 | if (mx[pos] == 1) |
| 2391 | 2382 | continue; |
| 2392 | 2383 | for (k = 0; k < 8; k++) { |
| 2393 | 2384 | if (ON_BOARD(pos + delta[k]) && mx[pos + delta[k]] == 1) { |
| … |
… |
|
| 2396 | 2387 | break; |
| 2397 | 2388 | } |
| 2398 | 2389 | } |
| 2399 | | } |
| | 2390 | ) |
| 2400 | 2391 | |
| 2401 | 2392 | /* Play black stones surrounding the white group, but leaving all |
| 2402 | 2393 | * liberties empty. |
| 2403 | 2394 | */ |
| 2404 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 2395 | scan_board(pos, |
| 2405 | 2396 | if (mx[pos] == 1 || board[pos] != EMPTY || liberty_of_string(pos, str)) |
| 2406 | 2397 | continue; |
| 2407 | 2398 | for (k = 0; k < 8; k++) { |
| … |
… |
|
| 2411 | 2402 | break; |
| 2412 | 2403 | } |
| 2413 | 2404 | } |
| 2414 | | } |
| | 2405 | ) |
| 2415 | 2406 | |
| 2416 | 2407 | /* Show the board if verbose is on. Then turn off traces so we don't |
| 2417 | 2408 | * get any from make_worms(), make_dragons(), or the owl reading. |
| … |
… |
|
| 3515 | 3506 | /* Mark the eyespace in the mx array. We construct the position in |
| 3516 | 3507 | * the mx array and copy it to the actual board later. |
| 3517 | 3508 | */ |
| 3518 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 3519 | | if (ON_BOARD(pos)) |
| 3520 | | mx[pos] = WHITE; |
| | 3509 | scan_board(pos, |
| | 3510 | mx[pos] = WHITE; |
| | 3511 | ) |
| 3521 | 3512 | |
| 3522 | 3513 | /* Find out the size of the eye graph pattern so that we can center |
| 3523 | 3514 | * it properly. |
| … |
… |
|
| 3632 | 3623 | |
| 3633 | 3624 | /* Copy the mx array over to the board. */ |
| 3634 | 3625 | clear_board(); |
| 3635 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 3636 | | if (ON_BOARD(pos)) { |
| | 3626 | scan_board(pos, |
| 3637 | 3627 | if (mx[pos] == WHITE) |
| 3638 | 3628 | add_stone(pos, WHITE); |
| 3639 | 3629 | else if (mx[pos] == BLACK) |
| 3640 | 3630 | add_stone(pos, BLACK); |
| 3641 | | } |
| | 3631 | ) |
| 3642 | 3632 | |
| 3643 | 3633 | if (verbose) |
| 3644 | 3634 | showboard(0); |
| … |
… |
|
| 3646 | 3636 | /* If there are any isolated O stones, those should also be added to |
| 3647 | 3637 | * the playable vertices. |
| 3648 | 3638 | */ |
| 3649 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| | 3639 | scan_board(pos, |
| 3650 | 3640 | if (board[pos] == WHITE && !same_string(pos, POS(1, 0))) { |
| 3651 | 3641 | vertices[num_vertices] = vertices[num_vertices - 1]; |
| 3652 | 3642 | vertices[num_vertices - 1] = vertices[num_vertices - 2]; |
| 3653 | 3643 | vertices[num_vertices - 2] = vertices[num_vertices - 3]; |
| 3654 | 3644 | vertices[num_vertices - 3] = pos; |
| 3655 | 3645 | num_vertices++; |
| 3656 | | } |
| | 3646 | } |
| | 3647 | ) |
| 3657 | 3648 | |
| 3658 | 3649 | if (verbose) { |
| 3659 | 3650 | int k; |