RCS file: /sources/gnugo/gnugo/engine/dragon.c,v
retrieving revision 1.162
diff -u -r1.162 dragon.c
|
|
|
|
| 144 | 144 | compute_dragon_genus(dragon2[d].origin, &dragon2[d].genus, NO_MOVE); |
| 145 | 145 | |
| 146 | 146 | /* Compute the escape route measure. */ |
| 147 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| | 147 | scan_board(str, |
| 148 | 148 | if (IS_STONE(board[str]) && dragon[str].origin == str) |
| 149 | 149 | DRAGON2(str).escape_route = compute_escape(str, 0); |
| | 150 | ) |
| 150 | 151 | |
| 151 | 152 | /* Set dragon weaknesses according to initial_influence. */ |
| 152 | 153 | compute_refined_dragon_weaknesses(); |
| … |
… |
|
| 154 | 155 | dragon2[d].weakness_pre_owl = dragon2[d].weakness; |
| 155 | 156 | |
| 156 | 157 | /* Determine status: ALIVE, DEAD, CRITICAL or UNKNOWN */ |
| 157 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 158 | | if (ON_BOARD(str)) |
| 159 | | if (dragon[str].origin == str && board[str]) |
| 160 | | dragon[str].crude_status = compute_crude_status(str); |
| | 158 | scan_board(str, |
| | 159 | if (dragon[str].origin == str && board[str]) |
| | 160 | dragon[str].crude_status = compute_crude_status(str); |
| | 161 | ) |
| 161 | 162 | |
| 162 | 163 | /* We must update the dragon status at every intersection before we |
| 163 | 164 | * call the owl code. This updates all fields. |
| 164 | 165 | */ |
| 165 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 166 | | if (ON_BOARD(str) && board[str] != EMPTY) |
| | 166 | scan_board(str, |
| | 167 | if (board[str] != EMPTY) |
| 167 | 168 | dragon[str] = dragon[dragon[str].origin]; |
| | 169 | ) |
| 168 | 170 | |
| 169 | 171 | find_neighbor_dragons(); |
| 170 | 172 | |
| … |
… |
|
| 191 | 193 | * if necessary. |
| 192 | 194 | */ |
| 193 | 195 | start_timer(2); |
| 194 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 195 | | if (ON_BOARD(str)) { |
| | 196 | scan_board(str, |
| 196 | 197 | int attack_point = NO_MOVE; |
| 197 | 198 | int defense_point = NO_MOVE; |
| 198 | 199 | struct eyevalue no_eyes; |
| … |
… |
|
| 287 | 288 | |
| 288 | 289 | } |
| 289 | 290 | } |
| 290 | | } |
| | 291 | ) |
| 291 | 292 | time_report(2, " owl reading", NO_MOVE, 1.0); |
| 292 | 293 | |
| 293 | 294 | /* Compute the status to be used by the matcher. We most trust the |
| … |
… |
|
| 295 | 296 | * already confident that the dragon is alive, regardless of |
| 296 | 297 | * crude_status. |
| 297 | 298 | */ |
| 298 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| | 299 | scan_board(str, |
| 299 | 300 | if (IS_STONE(board[str])) { |
| 300 | 301 | if (DRAGON2(str).owl_status != UNCHECKED) |
| 301 | 302 | dragon[str].status = DRAGON2(str).owl_status; |
| 302 | 303 | else |
| 303 | 304 | dragon[str].status = ALIVE; |
| 304 | 305 | } |
| | 306 | ) |
| 305 | 307 | |
| 306 | 308 | /* The dragon data is now correct at the origin of each dragon but |
| 307 | 309 | * we need to copy it to every vertex. |
| 308 | 310 | */ |
| 309 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 310 | | if (ON_BOARD(str) && board[str] != EMPTY) |
| | 311 | scan_board(str, |
| | 312 | if (board[str] != EMPTY) |
| 311 | 313 | dragon[str] = dragon[dragon[str].origin]; |
| | 314 | ) |
| 312 | 315 | |
| 313 | 316 | identify_thrashing_dragons(); |
| 314 | 317 | |
| 315 | 318 | /* Owl threats. */ |
| 316 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 317 | | if (ON_BOARD(str) |
| 318 | | && board[str] != EMPTY |
| | 319 | scan_board(str, |
| | 320 | if (board[str] != EMPTY |
| 319 | 321 | && dragon[str].origin == str) { |
| 320 | 322 | struct eyevalue no_eyes; |
| 321 | 323 | set_eyevalue(&no_eyes, 0, 0, 0, 0); |
| … |
… |
|
| 330 | 332 | else { |
| 331 | 333 | int acode = DRAGON2(str).owl_attack_code; |
| 332 | 334 | int dcode = DRAGON2(str).owl_defense_code; |
| 333 | | int defense_point, second_defense_point; |
| | 335 | int defense_point; |
| | 336 | int second_defense_point; |
| 334 | 337 | |
| 335 | 338 | if (get_level() >= 8 |
| 336 | 339 | && !disable_threat_computation |
| … |
… |
|
| 347 | 350 | DRAGON2(str).owl_threat_status = DEAD; |
| 348 | 351 | } |
| 349 | 352 | else if (!acode) { |
| 350 | | int attack_point, second_attack_point; |
| | 353 | int attack_point; |
| | 354 | int second_attack_point; |
| 351 | 355 | if (owl_threaten_attack(str, |
| 352 | 356 | &attack_point, &second_attack_point)) { |
| 353 | 357 | DRAGON2(str).owl_threat_status = CAN_THREATEN_ATTACK; |
| … |
… |
|
| 359 | 363 | } |
| 360 | 364 | } |
| 361 | 365 | } |
| 362 | | } |
| | 366 | } |
| | 367 | ) |
| 363 | 368 | |
| 364 | 369 | /* Once again, the dragon data is now correct at the origin of each dragon |
| 365 | 370 | * but we need to copy it to every vertex. |
| 366 | 371 | */ |
| 367 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 368 | | if (ON_BOARD(str) && board[str] != EMPTY) |
| | 372 | scan_board(str, |
| | 373 | if (board[str] != EMPTY) |
| 369 | 374 | dragon[str] = dragon[dragon[str].origin]; |
| | 375 | ) |
| 370 | 376 | |
| 371 | 377 | time_report(2, " owl threats ", NO_MOVE, 1.0); |
| 372 | 378 | |
| … |
… |
|
| 410 | 416 | /* The status is now correct at the origin of each dragon |
| 411 | 417 | * but we need to copy it to every vertex. |
| 412 | 418 | */ |
| 413 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 414 | | if (ON_BOARD(str)) |
| 415 | | dragon[str].status = dragon[dragon[str].origin].status; |
| | 419 | scan_board(str, |
| | 420 | dragon[str].status = dragon[dragon[str].origin].status; |
| | 421 | ) |
| 416 | 422 | |
| 417 | 423 | /* Revise inessentiality of critical worms and dragons. */ |
| 418 | 424 | revise_inessentiality(); |
| … |
… |
|
| 438 | 444 | find_lunches() |
| 439 | 445 | { |
| 440 | 446 | int str; |
| 441 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 442 | | if (ON_BOARD(str)) { |
| | 447 | scan_board(str, |
| 443 | 448 | int food; |
| 444 | 449 | |
| 445 | 450 | if (worm[str].origin != str |
| … |
… |
|
| 475 | 480 | worm[food].origin, worm[food].cutstone); |
| 476 | 481 | } |
| 477 | 482 | } |
| 478 | | } |
| | 483 | ) |
| 479 | 484 | } |
| 480 | 485 | |
| 481 | 486 | |
| … |
… |
|
| 488 | 493 | { |
| 489 | 494 | int str; |
| 490 | 495 | |
| 491 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| 492 | | if (!ON_BOARD(str)) |
| 493 | | continue; |
| 494 | | |
| | 496 | scan_board(str, |
| 495 | 497 | if (black_eye[str].color == BLACK |
| 496 | 498 | && black_eye[str].origin == str) { |
| 497 | 499 | struct eyevalue value; |
| 498 | | int attack_point, defense_point; |
| | 500 | int attack_point; |
| | 501 | int defense_point; |
| 499 | 502 | |
| 500 | 503 | compute_eyes(str, &value, &attack_point, &defense_point, |
| 501 | 504 | black_eye, half_eye, 1); |
| … |
… |
|
| 508 | 511 | if (white_eye[str].color == WHITE |
| 509 | 512 | && white_eye[str].origin == str) { |
| 510 | 513 | struct eyevalue value; |
| 511 | | int attack_point, defense_point; |
| | 514 | int attack_point; |
| | 515 | int defense_point; |
| 512 | 516 | |
| 513 | 517 | compute_eyes(str, &value, &attack_point, &defense_point, |
| 514 | 518 | white_eye, half_eye, 1); |
| … |
… |
|
| 517 | 521 | white_eye[str].value = value; |
| 518 | 522 | propagate_eye(str, white_eye); |
| 519 | 523 | } |
| 520 | | } |
| | 524 | ) |
| 521 | 525 | } |
| 522 | 526 | |
| 523 | 527 | |
| … |
… |
|
| 570 | 574 | * not dead, is considered inessential. |
| 571 | 575 | */ |
| 572 | 576 | |
| 573 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 574 | | if (ON_BOARD(str)) { |
| | 577 | scan_board(str, |
| 575 | 578 | if (is_worm_origin(str, str) |
| 576 | 579 | && worm[str].attack_codes[0] != 0 |
| 577 | 580 | && worm[str].defense_codes[0] != 0 |
| … |
… |
|
| 594 | 597 | propagate_worm(str); |
| 595 | 598 | } |
| 596 | 599 | } |
| 597 | | } |
| | 600 | ) |
| 598 | 601 | |
| 599 | 602 | /* Revise essentiality of critical dragons. Specifically, a critical |
| 600 | 603 | * dragon consisting entirely of inessential worms is considered |
| 601 | 604 | * INESSENTIAL. |
| 602 | 605 | */ |
| 603 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| 604 | | if (ON_BOARD(str) |
| 605 | | && board[str] != EMPTY |
| | 606 | scan_board(str, |
| | 607 | if (board[str] != EMPTY |
| 606 | 608 | && dragon[str].origin == str |
| 607 | 609 | && DRAGON2(str).safety == CRITICAL) { |
| 608 | 610 | int w; |
| … |
… |
|
| 617 | 619 | DRAGON2(str).safety = INESSENTIAL; |
| 618 | 620 | } |
| 619 | 621 | } |
| 620 | | } |
| | 622 | ) |
| 621 | 623 | } |
| 622 | 624 | |
| 623 | 625 | /* Initialize the dragon[] array. */ |
| … |
… |
|
| 627 | 629 | { |
| 628 | 630 | int str; |
| 629 | 631 | /* VALGRIND_MAKE_WRITABLE(dragon, BOARDMAX * sizeof(struct dragon_data)); */ |
| 630 | | for (str = BOARDMIN; str < BOARDMAX; str++) |
| 631 | | if (ON_BOARD(str)) { |
| 632 | | |
| | 632 | scan_board(str, |
| 633 | 633 | dragon[str].id = -1; |
| 634 | 634 | dragon[str].size = worm[str].size; |
| 635 | 635 | dragon[str].effective_size = worm[str].effective_size; |
| … |
… |
|
| 644 | 644 | DEBUG(DEBUG_DRAGONS, |
| 645 | 645 | "Initializing dragon from worm at %1m, size %d\n", |
| 646 | 646 | str, worm[str].size); |
| 647 | | } |
| | 647 | ) |
| 648 | 648 | memset(next_worm_list, 0, sizeof(next_worm_list)); |
| 649 | 649 | |
| 650 | 650 | /* We need to reset this to avoid trouble on an empty board when |
| … |
… |
|
| 673 | 673 | * the dragon2 array. After this the DRAGON2 macro can be used. |
| 674 | 674 | */ |
| 675 | 675 | number_of_dragons = 0; |
| 676 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| 677 | | if (!ON_BOARD(str)) |
| 678 | | continue; |
| | 676 | scan_board(str, |
| 679 | 677 | origin = dragon[str].origin; |
| 680 | 678 | |
| 681 | 679 | if (board[str] == EMPTY) |
| … |
… |
|
| 684 | 682 | if (dragon[origin].id == -1) |
| 685 | 683 | dragon[origin].id = number_of_dragons++; |
| 686 | 684 | dragon[str].id = dragon[origin].id; |
| 687 | | } |
| | 685 | ) |
| 688 | 686 | |
| 689 | 687 | /* Now number_of_dragons contains the number of dragons and we can |
| 690 | 688 | * allocate a dragon2 array of the appropriate size. First throw |
| … |
… |
|
| 702 | 700 | /* Find the origins of the dragons to establish the mapping back to |
| 703 | 701 | * the board. After this the DRAGON macro can be used. |
| 704 | 702 | */ |
| 705 | | for (str = BOARDMIN; str < BOARDMAX; str++) { |
| 706 | | if (!ON_BOARD(str)) |
| 707 | | continue; |
| | 703 | scan_board(str, |
| 708 | 704 | if (IS_STONE(board[str]) |
| 709 | 705 | && dragon[str].origin == str) { |
| 710 | 706 | DRAGON2(str).origin = str; |
| 711 | 707 | } |
| 712 | | } |
| | 708 | ) |
| 713 | 709 | |
| 714 | 710 | /* Initialize the rest of the dragon2 data. */ |
| 715 | 711 | for (d = 0; d < number_of_dragons; d++) { |
| … |
… |
|
| 772 | 768 | gg_assert(dragon2_initialized); |
| 773 | 769 | |
| 774 | 770 | /* Initialize the arrays. */ |
| 775 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 771 | scan_board(pos, |
| 776 | 772 | if (IS_STONE(board[pos])) { |
| 777 | 773 | dragons[pos] = dragon[pos].id; |
| 778 | 774 | distances[pos] = 0; |
| 779 | 775 | } |
| 780 | | else if (ON_BOARD(pos)) { |
| | 776 | else { |
| 781 | 777 | dragons[pos] = -1; |
| 782 | 778 | distances[pos] = -1; |
| 783 | 779 | } |
| 784 | | } |
| | 780 | ) |
| 785 | 781 | |
| 786 | 782 | /* Expand from dist-1 to dist. Break out of the loop at the end if |
| 787 | 783 | * we couldn't expand anything. Never expand more than five steps. |
| … |
… |
|
| 789 | 785 | for (dist = 1; dist <= 5; dist++) { |
| 790 | 786 | int found_one = 0; |
| 791 | 787 | |
| 792 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 793 | | if (!ON_BOARD(pos)) |
| 794 | | continue; |
| | 788 | scan_board(pos, |
| 795 | 789 | |
| 796 | 790 | if (distances[pos] != dist-1 || dragons[pos] < 0) |
| 797 | 791 | continue; |
| … |
… |
|
| 829 | 823 | } |
| 830 | 824 | } |
| 831 | 825 | } |
| 832 | | } |
| | 826 | ) |
| 833 | 827 | if (!found_one) |
| 834 | 828 | break; |
| 835 | 829 | } |
| … |
… |
|
| 855 | 849 | * where dragons==-2 we set all the neighbors of this intersection |
| 856 | 850 | * as adjacent to each other. |
| 857 | 851 | */ |
| 858 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 859 | | if (!ON_BOARD(pos)) |
| 860 | | continue; |
| | 852 | scan_board(pos, |
| 861 | 853 | if (dragons[pos] == -2) { |
| 862 | 854 | int neighbors = 0; |
| 863 | 855 | int adjacent[4]; |
| … |
… |
|
| 884 | 876 | add_adjacent_dragons(dragons[pos], dragons[EAST(pos)]); |
| 885 | 877 | } |
| 886 | 878 | } |
| 887 | | } |
| | 879 | ) |
| 888 | 880 | |
| 889 | 881 | if (0) { |
| 890 | 882 | for (d = 0; d < number_of_dragons; d++) { |
| … |
… |
|
| 957 | 949 | ASSERT1(IS_STONE(board[dr]), dr); |
| 958 | 950 | |
| 959 | 951 | /* First look for invincible strings in the dragon. */ |
| 960 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 961 | | if (ON_BOARD(pos) && is_same_dragon(pos, dr) && worm[pos].invincible) |
| | 952 | scan_board(pos, |
| | 953 | if (is_same_dragon(pos, dr) && worm[pos].invincible) |
| 962 | 954 | return 1; |
| 963 | | } |
| | 955 | ) |
| 964 | 956 | |
| 965 | 957 | /* Can the dragon be owl attacked? */ |
| 966 | 958 | if (DRAGON2(dr).owl_status != UNCHECKED && DRAGON2(dr).owl_status != ALIVE) |
| … |
… |
|
| 978 | 970 | |
| 979 | 971 | memset(mx, 0, sizeof(mx)); |
| 980 | 972 | |
| 981 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 973 | scan_board(pos, |
| 982 | 974 | if (board[pos] == board[dr] && is_same_dragon(pos, dr)) { |
| 983 | 975 | for (k = 0; k < 4; k++) { |
| 984 | 976 | int pos2 = pos + delta[k]; |
| … |
… |
|
| 997 | 989 | } |
| 998 | 990 | } |
| 999 | 991 | } |
| 1000 | | } |
| | 992 | ) |
| 1001 | 993 | |
| 1002 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 994 | scan_board(pos, |
| 1003 | 995 | /* Necessary to check eye margins here since the loop above only |
| 1004 | 996 | * considers margins which are directly adjacent to some stone of |
| 1005 | 997 | * the dragon. |
| … |
… |
|
| 1007 | 999 | if (mx[pos] == 1 |
| 1008 | 1000 | && eye[pos].msize == 0) |
| 1009 | 1001 | strong_eyes++; |
| 1010 | | } |
| | 1002 | ) |
| 1011 | 1003 | |
| 1012 | 1004 | if (strong_eyes >= 2) |
| 1013 | 1005 | return 1; |
| … |
… |
|
| 1117 | 1109 | |
| 1118 | 1110 | for (dist = 1; dist < 5; dist++) { |
| 1119 | 1111 | int pos; |
| 1120 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 1112 | scan_board(pos, |
| 1121 | 1113 | if (board[pos] != color |
| 1122 | 1114 | || dragon[pos].origin != pos |
| 1123 | 1115 | || thrashing_stone[pos] != dist) |
| … |
… |
|
| 1135 | 1127 | (signed char)(dist + 1)); |
| 1136 | 1128 | } |
| 1137 | 1129 | } |
| 1138 | | } |
| | 1130 | ) |
| 1139 | 1131 | } |
| 1140 | 1132 | } |
| 1141 | 1133 | |
| … |
… |
|
| 1144 | 1136 | set_dragon_strengths(const signed char safe_stones[BOARDMAX], |
| 1145 | 1137 | float strength[BOARDMAX]) |
| 1146 | 1138 | { |
| 1147 | | int ii; |
| 1148 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) |
| 1149 | | if (ON_BOARD(ii)) { |
| 1150 | | if (safe_stones[ii]) { |
| 1151 | | ASSERT1(IS_STONE(board[ii]), ii); |
| 1152 | | strength[ii] = DEFAULT_STRENGTH |
| 1153 | | * (1.0 - 0.3 * DRAGON2(ii).weakness_pre_owl); |
| 1154 | | } |
| | 1139 | int pos; |
| | 1140 | scan_board(pos, |
| | 1141 | if (safe_stones[pos]) { |
| | 1142 | ASSERT1(IS_STONE(board[pos]), pos); |
| | 1143 | strength[pos] = DEFAULT_STRENGTH |
| | 1144 | * (1.0 - 0.3 * DRAGON2(pos).weakness_pre_owl); |
| | 1145 | } |
| 1155 | 1146 | else |
| 1156 | | strength[ii] = 0.0; |
| 1157 | | } |
| | 1147 | strength[pos] = 0.0; |
| | 1148 | ) |
| 1158 | 1149 | } |
| 1159 | 1150 | |
| 1160 | 1151 | /* Marks all inessential stones with INFLUENCE_SAFE_STONE, leaves |
| … |
… |
|
| 1163 | 1154 | void |
| 1164 | 1155 | mark_inessential_stones(int color, signed char safe_stones[BOARDMAX]) |
| 1165 | 1156 | { |
| 1166 | | int ii; |
| 1167 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) |
| 1168 | | if (IS_STONE(board[ii]) |
| 1169 | | && (DRAGON2(ii).safety == INESSENTIAL |
| 1170 | | || (worm[ii].inessential |
| | 1157 | int pos; |
| | 1158 | scan_board(pos, |
| | 1159 | if (IS_STONE(board[pos]) |
| | 1160 | && (DRAGON2(pos).safety == INESSENTIAL |
| | 1161 | || (worm[pos].inessential |
| 1171 | 1162 | /* FIXME: Why is the check below needed? |
| 1172 | 1163 | * Why does it use .safety, not .status? /ab |
| 1173 | 1164 | */ |
| 1174 | | && ((DRAGON2(ii).safety != DEAD |
| 1175 | | && DRAGON2(ii).safety != TACTICALLY_DEAD |
| 1176 | | && DRAGON2(ii).safety != CRITICAL) |
| 1177 | | || (DRAGON2(ii).safety == CRITICAL |
| 1178 | | && board[ii] == color))))) |
| 1179 | | safe_stones[ii] = INFLUENCE_SAFE_STONE; |
| | 1165 | && ((DRAGON2(pos).safety != DEAD |
| | 1166 | && DRAGON2(pos).safety != TACTICALLY_DEAD |
| | 1167 | && DRAGON2(pos).safety != CRITICAL) |
| | 1168 | || (DRAGON2(pos).safety == CRITICAL |
| | 1169 | && board[pos] == color))))) |
| | 1170 | safe_stones[pos] = INFLUENCE_SAFE_STONE; |
| | 1171 | ) |
| 1180 | 1172 | } |
| 1181 | 1173 | |
| 1182 | 1174 | void |
| … |
… |
|
| 1224 | 1216 | set_eyevalue(genus, 0, 0, 0, 0); |
| 1225 | 1217 | |
| 1226 | 1218 | if (board[d] == BLACK) { |
| 1227 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 1228 | | if (!ON_BOARD(pos)) |
| 1229 | | continue; |
| | 1219 | scan_board(pos, |
| 1230 | 1220 | |
| 1231 | 1221 | if (black_eye[pos].color == BLACK |
| 1232 | 1222 | && black_eye[pos].origin == pos |
| … |
… |
|
| 1244 | 1234 | |
| 1245 | 1235 | add_eyevalues(genus, &black_eye[pos].value, genus); |
| 1246 | 1236 | } |
| 1247 | | } |
| | 1237 | ) |
| 1248 | 1238 | } |
| 1249 | 1239 | else { |
| 1250 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 1251 | | if (!ON_BOARD(pos)) |
| 1252 | | continue; |
| | 1240 | scan_board(pos, |
| 1253 | 1241 | |
| 1254 | 1242 | if (white_eye[pos].color == WHITE |
| 1255 | 1243 | && white_eye[pos].origin == pos |
| … |
… |
|
| 1267 | 1255 | |
| 1268 | 1256 | add_eyevalues(genus, &white_eye[pos].value, genus); |
| 1269 | 1257 | } |
| 1270 | | } |
| | 1258 | ) |
| 1271 | 1259 | } |
| 1272 | 1260 | } |
| 1273 | 1261 | |
| … |
… |
|
| 1307 | 1295 | struct eye_data *eye; |
| 1308 | 1296 | int k; |
| 1309 | 1297 | |
| 1310 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 1311 | | if (!ON_BOARD(pos)) |
| 1312 | | continue; |
| 1313 | | |
| | 1298 | scan_board(pos, |
| 1314 | 1299 | false_eye_territory[pos] = 0; |
| 1315 | 1300 | |
| 1316 | 1301 | /* The analysis only applies to false and half eyes. */ |
| … |
… |
|
| 1363 | 1348 | if (0) |
| 1364 | 1349 | gprintf("False eye territory at %1m\n", pos); |
| 1365 | 1350 | } |
| 1366 | | } |
| | 1351 | ) |
| 1367 | 1352 | |
| 1368 | 1353 | /* FIXME: This initialization doesn't really belong here but must be |
| 1369 | 1354 | * done somewhere within examine_position(). |
| 1370 | 1355 | * The array is eventually filled by the endgame() function. |
| 1371 | 1356 | */ |
| 1372 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 1373 | | if (ON_BOARD(pos)) |
| 1374 | | forced_backfilling_moves[pos] = 0; |
| | 1357 | scan_board(pos, |
| | 1358 | forced_backfilling_moves[pos] = 0; |
| | 1359 | ) |
| 1375 | 1360 | } |
| 1376 | 1361 | |
| 1377 | 1362 | /* |
| … |
… |
|
| 1473 | 1458 | int pos; |
| 1474 | 1459 | int k; |
| 1475 | 1460 | |
| 1476 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 1461 | scan_board(pos, |
| 1477 | 1462 | struct worm_data *w = &(worm[pos]); |
| 1478 | 1463 | if (!IS_STONE(board[pos])) |
| 1479 | 1464 | continue; |
| … |
… |
|
| 1539 | 1524 | if (is_ko_point(pos)) |
| 1540 | 1525 | gprintf("- is a ko stone\n"); |
| 1541 | 1526 | } |
| 1542 | | } |
| | 1527 | ) |
| 1543 | 1528 | |
| 1544 | 1529 | gprintf("%o\n"); |
| 1545 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 1530 | scan_board(pos, |
| 1546 | 1531 | struct dragon_data *dd = &(dragon[pos]); |
| 1547 | 1532 | struct dragon_data2 *d2; |
| 1548 | 1533 | |
| … |
… |
|
| 1592 | 1577 | if (d2->lunch != NO_MOVE) |
| 1593 | 1578 | gprintf("... adjacent worm %1m is lunch\n", d2->lunch); |
| 1594 | 1579 | } |
| 1595 | | } |
| | 1580 | ) |
| 1596 | 1581 | } |
| 1597 | 1582 | |
| 1598 | 1583 | |
| … |
… |
|
| 1616 | 1601 | |
| 1617 | 1602 | memcpy(saved_cutting_points, cutting_points, sizeof(cutting_points)); |
| 1618 | 1603 | memset(cutting_points, 0, sizeof(cutting_points)); |
| 1619 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 1620 | | if (ON_BOARD(pos)) { |
| | 1604 | scan_board(pos, |
| 1621 | 1605 | if (board[pos] == EMPTY) |
| 1622 | 1606 | new_dragon_origins[pos] = NO_MOVE; |
| 1623 | 1607 | else |
| 1624 | 1608 | new_dragon_origins[pos] = find_origin(pos); |
| 1625 | | } |
| | 1609 | ) |
| 1626 | 1610 | |
| 1627 | 1611 | find_cuts(); |
| 1628 | 1612 | find_connections(); |
| … |
… |
|
| 1651 | 1635 | ASSERT1(IS_STONE(board[d1]), d1); |
| 1652 | 1636 | |
| 1653 | 1637 | /* Don't bother to do anything fancy with dragon origins. */ |
| 1654 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) |
| 1655 | | if (ON_BOARD(pos) && new_dragon_origins[pos] == d2) |
| | 1638 | scan_board(pos, |
| | 1639 | if (new_dragon_origins[pos] == d2) |
| 1656 | 1640 | new_dragon_origins[pos] = d1; |
| | 1641 | ) |
| 1657 | 1642 | } |
| 1658 | 1643 | |
| 1659 | 1644 | /* |
| … |
… |
|
| 1717 | 1702 | next_worm_list[last_worm_origin_dragon] = d1; |
| 1718 | 1703 | } |
| 1719 | 1704 | |
| 1720 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) { |
| 1721 | | if (ON_BOARD(ii) |
| 1722 | | && (dragon[ii].origin == d1 || dragon[ii].origin == d2)) |
| | 1705 | scan_board(ii, |
| | 1706 | if (dragon[ii].origin == d1 || dragon[ii].origin == d2) |
| 1723 | 1707 | dragon[ii].origin = origin; |
| 1724 | | } |
| | 1708 | ) |
| 1725 | 1709 | } |
| 1726 | 1710 | |
| 1727 | 1711 | |
| … |
… |
|
| 1852 | 1836 | } |
| 1853 | 1837 | |
| 1854 | 1838 | /* Enter the stones of the dragon in the queue. */ |
| 1855 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) |
| 1856 | | if (ON_BOARD(ii) && goal[ii]) |
| | 1839 | scan_board(ii, |
| | 1840 | if (goal[ii]) |
| 1857 | 1841 | ENQUEUE(ii); |
| | 1842 | ) |
| 1858 | 1843 | |
| 1859 | 1844 | /* Find points at increasing distances from the dragon. At distance |
| 1860 | 1845 | * four, sum the escape values at those points to get the escape |
| … |
… |
|
| 1991 | 1976 | |
| 1992 | 1977 | ASSERT1(IS_STONE(board[pos]), pos); |
| 1993 | 1978 | |
| 1994 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) |
| 1995 | | if (ON_BOARD(ii)) |
| 1996 | | goal[ii] = is_same_dragon(ii, pos); |
| | 1979 | scan_board(ii, |
| | 1980 | goal[ii] = is_same_dragon(ii, pos); |
| | 1981 | ) |
| 1997 | 1982 | |
| 1998 | 1983 | /* Compute escape_value array. Points are awarded for moyo (4), |
| 1999 | 1984 | * area (2) or EMPTY (1). Values may change without notice. |
| … |
… |
|
| 2002 | 1987 | compute_escape_influence(board[pos], safe_stones, NULL, 0, escape_value); |
| 2003 | 1988 | |
| 2004 | 1989 | /* If we can reach a live group, award 6 points. */ |
| 2005 | | for (ii = BOARDMIN; ii < BOARDMAX; ii++) { |
| 2006 | | if (!ON_BOARD(ii)) |
| 2007 | | continue; |
| | 1990 | scan_board(ii, |
| 2008 | 1991 | |
| 2009 | 1992 | if (dragon_status_known) { |
| 2010 | 1993 | if (dragon[ii].crude_status == ALIVE) |
| … |
… |
|
| 2020 | 2003 | && worm[ii].attack_codes[0] == 0) |
| 2021 | 2004 | escape_value[ii] = 2; |
| 2022 | 2005 | } |
| 2023 | | } |
| | 2006 | ) |
| 2024 | 2007 | |
| 2025 | 2008 | return dragon_escape(goal, board[pos], escape_value); |
| 2026 | 2009 | } |
| … |
… |
|
| 2051 | 2034 | float moyo_values[BOARDMAX]; |
| 2052 | 2035 | |
| 2053 | 2036 | |
| 2054 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| | 2037 | scan_board(pos, |
| 2055 | 2038 | moyo_sizes[pos] = 0.0; |
| 2056 | 2039 | moyo_values[pos] = 0.0; |
| 2057 | | } |
| | 2040 | ) |
| 2058 | 2041 | |
| 2059 | | for (pos = BOARDMIN; pos < BOARDMAX; pos++) { |
| 2060 | | if (!ON_BOARD(pos)) |
| 2061 | | continue; |
| | 2042 | scan_board(pos, |
| 2062 | 2043 | moyo_color = whose_moyo_restricted(q, pos); |
| 2063 | 2044 | |
| 2064 | 2045 | if (moyo_color == board[pos]) |