Ticket #148: changes.diff
| File changes.diff, 142.0 KB (added by draqo, 4 years ago) |
|---|
-
gnugo/config.h.in
RCS file: /sources/gnugo/gnugo/config.h.in,v retrieving revision 1.43 diff -u -r1.43 config.h.in
12 12 /* Center oriented influence. Disabled by default. */ 13 13 #undef COSMIC_GNUGO 14 14 15 /* Default level (strength). Up to 1 0 supported*/15 /* Default level (strength). Up to 12 is recommended. */ 16 16 #undef DEFAULT_LEVEL 17 17 18 18 /* Default hash table size in megabytes */ … … 27 27 /* GAIN/LOSS codes. Disabled by default. */ 28 28 #undef EXPERIMENTAL_OWL_EXT 29 29 30 /* Disable unneeded things. 0 standard. */ 31 #undef FINAL_RELEASE 32 30 33 /* The concatenation of the strings "GNU ", and PACKAGE. */ 31 34 #undef GNU_PACKAGE 32 35 … … 103 106 /* Semeai Variations. 500 default */ 104 107 #undef SEMEAI_NODE_LIMIT 105 108 109 /* The size of a `int', as computed by sizeof. */ 110 #undef SIZEOF_INT 111 106 112 /* The size of a `long', as computed by sizeof. */ 107 113 #undef SIZEOF_LONG 108 114 -
gnugo/configure
RCS file: /sources/gnugo/gnugo/configure,v retrieving revision 1.125 diff -u -r1.125 configure
2 2 # Guess values for system-dependent variables and create Makefiles. 3 3 # Generated by Autoconf 2.52. 4 4 # 5 # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 5 # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2006 6 6 # Free Software Foundation, Inc. 7 7 # This configure script is free software; the Free Software Foundation 8 8 # gives unlimited permission to copy, distribute and modify it. … … 673 673 analysis (default) 674 674 --disable-socket-support don't compile GTP over TCP/IP support 675 675 --enable-socket-support compile TCP/IP support (default) 676 --enable-final-release turn off additional chekcs, stats, etc. 677 --disable-final-release turn on additional chekcs, stats, etc. 676 678 677 679 Optional Packages: 678 680 --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] … … 1444 1446 1445 1447 fi; 1446 1448 1449 # Check whether --enable-final-release or --disable-final-release was given. 1450 if test "${enable-final-release+set}" = set; then 1451 enableval="$enable_final_release" 1452 1453 fi; 1454 1447 1455 ac_ext=c 1448 1456 ac_cpp='$CPP $CPPFLAGS' 1449 1457 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' … … 3377 3385 #define SIZEOF_LONG $ac_cv_sizeof_long 3378 3386 EOF 3379 3387 3388 echo "$as_me:3181: checking size of int" >&5 3389 echo $ECHO_N "checking size of int... $ECHO_C" >&6 3390 cat >conftest.$ac_ext <<_ACEOF 3391 #line 3391 "configure" 3392 #include "confdefs.h" 3393 #include <stdio.h> 3394 3395 int 3396 main () 3397 { 3398 FILE *f = fopen ("conftest.val", "w"); 3399 if (!f) 3400 exit (1); 3401 fprintf (f, "%d", (sizeof (int))); 3402 fclose (f); 3403 ; 3404 return 0; 3405 } 3406 _ACEOF 3407 rm -f conftest$ac_exeext 3408 if { (eval echo "$as_me:3408: \"$ac_link\"") >&5 3409 (eval $ac_link) 2>&5 3410 ac_status=$? 3411 echo "$as_me:3411: \$? = $ac_status" >&5 3412 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' 3413 { (eval echo "$as_me:3413: \"$ac_try\"") >&5 3414 (eval $ac_try) 2>&5 3415 ac_status=$? 3416 echo "$as_me:3416: \$? = $ac_status" >&5 3417 (exit $ac_status); }; }; then 3418 ac_cv_sizeof_int=`cat conftest.val` 3419 else 3420 echo "$as_me: program exited with status $ac_status" >&5 3421 echo "$as_me: failed program was:" >&5 3422 cat conftest.$ac_ext >&5 3423 fi 3424 rm -f conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext 3425 rm -f conftest.val 3426 echo "$as_me:3426: result: $ac_cv_sizeof_int" >&5 3427 echo "${ECHO_T}$ac_cv_sizeof_int" >&6 3428 cat >>confdefs.h <<EOF 3429 #define SIZEOF_INT $ac_cv_sizeof_int 3430 EOF 3431 3380 3432 for ac_func in vsnprintf gettimeofday usleep times 3381 3433 do 3382 3434 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` … … 4104 4156 4105 4157 fi 4106 4158 4159 if test "$enable_final_release" = "yes" ; then 4160 cat >>confdefs.h <<\EOF 4161 #define FINAL_RELEASE 1 4162 EOF 4163 4164 else 4165 cat >>confdefs.h <<\EOF 4166 #define FINAL_RELEASE 0 4167 EOF 4168 4169 fi 4170 4107 4171 if test "$enable_cosmic_gnugo" = "yes" ; then 4108 4172 cat >>confdefs.h <<\EOF 4109 4173 #define COSMIC_GNUGO 1 -
gnugo/configure.in
RCS file: /sources/gnugo/gnugo/configure.in,v retrieving revision 1.136 diff -u -r1.136 configure.in
124 124 AC_ARG_ENABLE(socket-support, 125 125 [ --disable-socket-support don't compile GTP over TCP/IP support 126 126 --enable-socket-support compile TCP/IP support (default)]) 127 128 AC_ARG_ENABLE(final-release, 129 [ --enable-final-release turn off additional chekcs, stats, etc. 130 --disable-final-release turn on additional chekcs, stats, etc. (default)]) 127 131 128 132 AC_PROG_CC 129 133 … … 178 182 term_header="no" 179 183 fi 180 184 185 AC_CHECK_SIZEOF(int,,[#include <stdio.h>]) 181 186 AC_CHECK_SIZEOF(long,,[#include <stdio.h>]) 182 187 183 188 dnl vsnprintf not universally available … … 338 343 dnl ------------ set default level ---------- 339 344 340 345 AH_TEMPLATE([DEFAULT_LEVEL], 341 [Default level (strength). Up to 1 0 supported])346 [Default level (strength). Up to 12 is recommended.]) 342 347 343 348 if test "$enable_level" ; then 344 349 AC_DEFINE_UNQUOTED(DEFAULT_LEVEL, $enable_level) … … 491 496 AC_DEFINE(OWL_THREATS, 0) 492 497 fi 493 498 499 dnl ------------ Final release ------------------- 500 501 AH_TEMPLATE([FINAL_RELEASE], 502 [Disable unneeded things. 0 standard.]) 503 504 if test "$enable_final_release" = "yes" ; then 505 AC_DEFINE(FINAL_RELEASE, 1) 506 else 507 AC_DEFINE(FINAL_RELEASE, 0) 508 fi 509 494 510 dnl ------------ additional valgrind macros ------ 495 511 496 512 AH_TEMPLATE([USE_VALGRIND], -
gnugo/engine/aftermath.c
RCS file: /sources/gnugo/gnugo/engine/aftermath.c,v retrieving revision 1.61 diff -u -r1.61 aftermath.c
288 288 for (k = 0; k < 4; k++) { 289 289 int dir = delta[k]; 290 290 int right = delta[(k+1)%4]; 291 int checked_pos = pos + dir; 292 291 293 if (!ON_BOARD(pos - dir) 292 && board[pos + dir] == color 293 && board[pos + dir + right] == other 294 && board[pos + dir - right] == other 295 && (libs > countlib(pos + dir) 296 || (libs > 4 297 && libs == countlib(pos + dir))) 298 && (DRAGON2(pos + dir).safety == INVINCIBLE 299 || DRAGON2(pos + dir).safety == STRONGLY_ALIVE)) { 300 int this_score = 20 * (owl_hotspot[pos] + reading_hotspot[pos]); 301 if (this_score > best_score) { 302 best_score = this_score; 303 best_scoring_move = pos; 304 } 294 && board[checked_pos] == color 295 && board[checked_pos + right] == other 296 && board[checked_pos - right] == other) { 297 298 int count_lib = countlib(checked_pos); 299 int safety; 300 301 if ((libs > count_lib 302 || (libs > 4 && libs == count_lib)) 303 && ((safety = DRAGON2(checked_pos).safety) == INVINCIBLE 304 || safety == STRONGLY_ALIVE)) { 305 306 int this_score = 20 * (owl_hotspot[pos] + reading_hotspot[pos]); 307 if (this_score > best_score) { 308 best_score = this_score; 309 best_scoring_move = pos; 310 } 311 } 305 312 } 306 313 } 307 314 } … … 363 370 score--; 364 371 else { 365 372 if (board[pos2] == color) { 373 int count_stones = countstones(pos2); 374 int count_lib = countlib(pos2); 366 375 move_ok = 1; 367 376 score += 7; 368 if (count stones(pos2) > 2)369 score ++;370 if (countstones(pos2) > 4)377 if (count_stones > 4) 378 score += 2; 379 else if (count_stones > 2) 371 380 score++; 372 if (count lib(pos2) < 4)373 score ++;374 if (countlib(pos2) < 3)381 if (count_lib < 3) 382 score += 2; 383 else if (count_lib < 4) 375 384 score++; 376 385 } 377 else { 386 else { /* board[pos2] == other */ 378 387 int deltalib = (approxlib(pos, other, MAXLIBS, NULL) 379 388 - countlib(pos2)); 380 389 move_ok = 1; 381 390 score++; 382 if (deltalib >= 0)383 score++;384 391 if (deltalib > 0) 392 score += 2; 393 else if (deltalib >= 0) 385 394 score++; 386 395 } 387 396 mark_string(pos2, mx, mark); … … 470 479 471 480 if (!mx[origin] && dragon[pos2].status == DEAD) { 472 481 bonus++; 473 if (k < 4 474 && countlib(pos2) <= 2 475 && countstones(pos2) >= 3) 476 bonus++; 482 if (k < 4) { 483 int count_lib = countlib(pos2); 484 if (count_lib <= 2 485 && countstones(pos2) >= 3) 486 bonus++; 477 487 478 if (k < 4 && countlib(pos2) == 1) 479 bonus += 3; 488 if (count_lib == 1) 489 bonus += 3; 490 } 480 491 } 481 492 mx[origin] = 1; 482 }493 } 483 494 else if (board[pos2] == color) { 484 495 dragons[pos] = pos2; 485 496 … … 491 502 492 503 if (k < 4) { 493 504 int apos = worm[pos2].origin; 505 int count_lib = countlib(apos); 494 506 495 507 if (!mx[apos]) { 496 508 own_worms++; 497 509 if (countstones(apos) == 1) 498 510 bonus += 2; 499 if (count lib(apos)< 6500 && approxlib(pos, color, 5, NULL) < count lib(apos))511 if (count_lib < 6 512 && approxlib(pos, color, 5, NULL) < count_lib) 501 513 bonus -= 5; 502 514 mx[apos] = 1; 503 515 } 504 516 505 if (count lib(apos)<= 2) {517 if (count_lib <= 2) { 506 518 int r; 507 519 int important = 0; 508 520 int safe_atari = 0; … … 612 624 int move_ok = 1; 613 625 if (libs < 5) { 614 626 for (k = 0; k < 4; k++) { 615 if (board[move + delta[k]] == color 616 && countlib(move + delta[k]) > libs) 627 int checked_pos = move + delta[k]; 628 if (board[checked_pos] == color 629 && countlib(checked_pos) > libs) 617 630 break; 618 631 } 619 632 if (k < 4) { … … 681 694 break; 682 695 } 683 696 } 684 }697 } 685 698 if (target == NO_MOVE) 686 699 continue; 687 700 … … 723 736 cc = pos + delta[k]; 724 737 break; 725 738 } 726 }739 } 727 740 728 741 /* Copy the potential move to (move). */ 729 742 move = pos; … … 733 746 * potential move possible. 734 747 */ 735 748 if (!self_atari_ok) { 736 while (countlib(pos) == 1) { 749 int count_lib; 750 while ((count_lib = countlib(pos)) == 1) { 737 751 int lib; 738 752 findlib(pos, 1, &lib); 739 753 move = lib; … … 741 755 break; 742 756 } 743 757 744 if (count lib(pos)== 1)758 if (count_lib == 1) 745 759 move = NO_MOVE; 746 760 } 747 761 -
gnugo/engine/board.c
RCS file: /sources/gnugo/gnugo/engine/board.c,v retrieving revision 1.119 diff -u -r1.119 board.c
32 32 #include "hash.h" 33 33 #include "sgftree.h" 34 34 #include "gg_utils.h" 35 #include "gnugo.h" 35 36 36 37 #include <stdio.h> 37 38 #include <string.h> … … 91 92 * exceeds 40. But since we have no way to recover from running out of 92 93 * stack space, we allocate with a substantial safety margin. 93 94 */ 95 #ifdef INT_INTERSECTION 96 #define STACK_SIZE 2 * 80 * MAXSTACK 97 #else 94 98 #define STACK_SIZE 80 * MAXSTACK 99 #endif 100 101 #ifdef INT_INTERSECTION 102 103 #define CLEAR_STACKS() do { \ 104 change_stack_pointer = change_stack; \ 105 VALGRIND_MAKE_WRITABLE(change_stack, sizeof(change_stack)); \ 106 } while (0) 107 108 /* Begin a record : address == NULL */ 109 #define BEGIN_CHANGE_RECORD()\ 110 ((change_stack_pointer++)->address = NULL) 111 112 /* PUSH_VERTEX should be the same as PUSH_VALUE when Intersection is 113 * int type */ 114 115 /* Save a value : store the address and the value in the stack */ 116 #define PUSH_VALUE(v)\ 117 (change_stack_pointer->address = &(v),\ 118 (change_stack_pointer++)->value = (v)) 119 120 /* Save a board value : store the address and the value in the stack */ 121 #define PUSH_VERTEX(v)\ 122 (change_stack_pointer->address = &(v),\ 123 (change_stack_pointer++)->value = (v)) 124 125 #define POP_MOVE()\ 126 while ((--change_stack_pointer)->address)\ 127 *(change_stack_pointer->address) =\ 128 change_stack_pointer->value 95 129 130 #else 96 131 97 132 #define CLEAR_STACKS() do { \ 98 133 change_stack_pointer = change_stack; \ … … 119 154 #define POP_MOVE()\ 120 155 while ((--change_stack_pointer)->address)\ 121 156 *(change_stack_pointer->address) =\ 122 change_stack_pointer->value 123 124 125 #define POP_VERTICES()\ 157 change_stack_pointer->value; 126 158 while ((--vertex_stack_pointer)->address)\ 127 159 *(vertex_stack_pointer->address) =\ 128 160 vertex_stack_pointer->value 161 #endif 129 162 130 163 131 164 /* ================================================================ */ … … 138 171 static struct string_liberties_data string_libs[MAX_STRINGS]; 139 172 static struct string_neighbors_data string_neighbors[MAX_STRINGS]; 140 173 141 /* Stacks and stack pointers. */174 /* Stacks and stack pointers. Used for undoing changes on the board */ 142 175 static struct change_stack_entry change_stack[STACK_SIZE]; 143 176 static struct change_stack_entry *change_stack_pointer; 144 177 178 #ifndef INT_INTERSECTION 145 179 static struct vertex_stack_entry vertex_stack[STACK_SIZE]; 146 180 static struct vertex_stack_entry *vertex_stack_pointer; 181 #endif 147 182 148 183 149 184 /* Index into list of strings. The index is only valid if there is a … … 164 199 /* Macros to traverse the stones of a string. 165 200 * 166 201 * Usage: 167 * int s, pos; 168 * s = find_the_string() 169 * pos = FIRST_STONE(s); 202 * int first, s, pos; 203 * s = find_the_string(); 204 * first = FIRST_STONE(s); 205 * pos = first; 170 206 * do { 171 207 * use_stone(pos); 172 208 * pos = NEXT_STONE(pos); 173 * } while ( !BACK_TO_FIRST_STONE(s, pos));209 * } while (pos != first); 174 210 */ 175 211 #define FIRST_STONE(s) \ 176 212 (string[s].origin) … … 178 214 #define NEXT_STONE(pos) \ 179 215 (next_stone[pos]) 180 216 181 #define BACK_TO_FIRST_STONE(s, pos) \182 ((pos) == string[s].origin)183 184 217 185 218 /* Assorted useful macros. 186 219 * … … 197 230 #define MARK_LIBERTY(pos) \ 198 231 ml[pos] = liberty_mark 199 232 200 #define UNMARKED_STRING( pos) \201 (string[str ing_number[pos]].mark != string_mark)233 #define UNMARKED_STRING(str_nr) \ 234 (string[str_nr].mark != string_mark) 202 235 203 236 /* Note that these two macros are not complementary. Both return 204 237 * false if board[pos] != color. … … 211 244 (board[pos] == color\ 212 245 && string[string_number[pos]].mark == string_mark) 213 246 214 #define MARK_STRING( pos) string[string_number[pos]].mark = string_mark247 #define MARK_STRING(str_nr) string[str_nr].mark = string_mark 215 248 216 249 #define STRING_AT_VERTEX(pos, s, color)\ 217 ((board[pos] == color) && string_number[pos] == (s))250 ((board[pos] == (color)) && string_number[pos] == (s)) 218 251 219 252 #define NEIGHBOR_OF_STRING(pos, s, color)\ 220 253 (STRING_AT_VERTEX(SOUTH(pos), s, color)\ … … 245 278 (STRING_AT_VERTEX(EAST(pos), s, color)\ 246 279 || STRING_AT_VERTEX(SOUTH(pos), s, color)\ 247 280 || STRING_AT_VERTEX(NORTH(pos), s, color)) 248 249 #define LIBERTIES(pos)\250 string[string_number[pos]].liberties251 281 252 #define COUNTSTONES(pos) \ 253 string[string_number[pos]].size 282 #define LIBERTIES(str_nr)\ 283 string[str_nr].liberties 284 285 #define COUNTSTONES(str_nr) \ 286 string[str_nr].size 254 287 255 288 #define ADD_LIBERTY(s, pos)\ 256 289 do {\ … … 267 300 ml[pos] = liberty_mark;\ 268 301 } while (0) 269 302 270 #define ADD_NEIGHBOR(s , pos)\271 string_neighbors[s ].list[string[s].neighbors++] = string_number[pos]303 #define ADD_NEIGHBOR(s1, s2)\ 304 string_neighbors[s1].list[string[s1].neighbors++] = s2 272 305 273 306 #define DO_ADD_STONE(pos, color)\ 274 307 do {\ … … 304 337 static int do_trymove(int pos, int color, int ignore_ko); 305 338 static void undo_trymove(void); 306 339 307 static int do_approxlib(int pos, int color, int maxlib, int *libs); 308 static int slow_approxlib(int pos, int color, int maxlib, int *libs); 309 static int do_accuratelib(int pos, int color, int maxlib, int *libs); 340 341 struct board_cache_entry { 342 int threshold; /* a number of checked, possible liberties 343 * (liberties <= threshold) */ 344 int liberties; /* number of liberties (if liberties == threshold 345 * there is maybe more liberties) */ 346 Hash_data position_hash; 347 }; 348 349 inline static int do_approxlib(int pos, int color, int maxlib, int *libs, 350 struct board_cache_entry *entry); 351 inline static int slow_approxlib(int pos, int color, int maxlib, int *libs, 352 struct board_cache_entry *entry); 353 inline static int do_accuratelib(int pos, int color, int maxlib, int *libs, 354 struct board_cache_entry *entry); 310 355 311 356 static int is_superko_violation(int pos, int color, enum ko_rules type); 312 357 313 358 static void new_position(void); 314 static int propagate_string(int stone , int str);315 static void find_liberties_and_neighbors(int s );316 static int do_remove_string(int s );359 static int propagate_string(int stone_pos, int str_pos, int color); 360 static void find_liberties_and_neighbors(int str_nr); 361 static int do_remove_string(int str_nr); 317 362 static void do_commit_suicide(int pos, int color); 318 363 static void do_play_move(int pos, int color); 319 364 … … 326 371 /* Coordinates for the eight directions, ordered 327 372 * south, west, north, east, southwest, northwest, northeast, southeast. 328 373 */ 329 int deltai[8] = { 1, 0, -1, 0, 1, -1, -1, 1};330 int deltaj[8] = { 0, -1, 0, 1, -1, -1, 1, 1};331 int delta[8] = { NS, -1, -NS, 1, NS-1, -NS-1, -NS+1, NS+1};374 const int deltai[8] = { 1, 0, -1, 0, 1, -1, -1, 1}; 375 const int deltaj[8] = { 0, -1, 0, 1, -1, -1, 1, 1}; 376 const int delta[8] = { NS, -WE, -NS, WE, NS-WE, -NS-WE, -NS+WE, NS+WE}; 332 377 333 378 334 379 /* ================================================================ */ … … 448 493 449 494 handicap = 0; 450 495 451 hashdata_recalc(&board_hash, board, board_ko_pos);496 hashdata_recalc(&board_hash, board, NO_MOVE); 452 497 new_position(); 453 498 } 454 499 … … 496 541 * } 497 542 * 498 543 * The message can be written as a comment to an sgf file using 499 * sgfdump(). str can be NO_MOVE if it is not needed but otherwise500 * the location of str is included in the comment.544 * sgfdump(). 545 * str_pos is currently not used by function 501 546 */ 502 547 503 548 int 504 trymove(int pos, int color, const char *message, int str )549 trymove(int pos, int color, const char *message, int str_pos) 505 550 { 506 UNUSED(str); 551 UNUSED(str_pos); 552 507 553 /* Do the real work elsewhere. */ 508 554 if (!do_trymove(pos, color, 0)) 509 555 return 0; 510 556 557 #ifndef GG_TURN_OFF_TRACES 511 558 /* Store the move in an sgf tree if one is available. */ 512 559 if (sgf_dumptree) { 513 560 char buf[100]; … … 540 587 sgftreeAddPlayLast(sgf_dumptree, color, I(pos), J(pos)); 541 588 sgftreeAddComment(sgf_dumptree, buf); 542 589 } 543 590 #else 591 UNUSED(message); 592 #endif 593 544 594 if (count_variations) 545 595 count_variations++; 596 597 #ifndef GG_TURN_OFF_STATS 546 598 stats.nodes++; 599 #endif 547 600 548 601 return 1; 549 602 } … … 567 620 if (!do_trymove(pos, color, 1)) 568 621 return 0; 569 622 623 #ifndef GG_TURN_OFF_TRACES 570 624 if (sgf_dumptree) { 571 625 char buf[100]; 572 626 if (message == NULL) 573 627 message = "UNKNOWN"; 574 628 if (komaster != EMPTY) 575 gg_snprintf(buf, 100, "tryko: %s (variation %d, %s, komaster %s:%s)", 576 message, count_variations, hashdata_to_string(&board_hash), 629 gg_snprintf(buf, 100, "tryko: %s at %s (variation %d, hash %s, komaster %s:%s)", 630 message, location_to_string(pos), count_variations, 631 hashdata_to_string(&board_hash), 577 632 color_to_string(komaster), location_to_string(kom_pos)); 578 633 else 579 gg_snprintf(buf, 100, "tryko: %s (variation %d, %s)", message, 634 gg_snprintf(buf, 100, "tryko: %s at %s (variation %d, hash %s)", message, 635 location_to_string(pos), 580 636 count_variations, hashdata_to_string(&board_hash)); 581 637 582 638 /* Add two pass moves to the SGF output to simulate the ko threat … … 595 651 sgftreeAddPlayLast(sgf_dumptree, color, I(pos), J(pos)); 596 652 sgftreeAddComment(sgf_dumptree, buf); 597 653 } 654 #else 655 UNUSED(message); 656 #endif 598 657 599 658 if (count_variations) 600 659 count_variations++; 660 661 #ifndef GG_TURN_OFF_STATS 601 662 stats.nodes++; 663 #endif 664 665 return 1; 666 } 667 668 /* 669 * This function is used by komaster_trymove(). It performs checks made by trymove() 670 * and tryko(), so these functions have not to be called twice. It works like 671 * trymove() and it returns (by ko_move_allowed) the result of tryko(), but it 672 * doesn't call really_do_trymove() - we have to call it ourselves and function 673 * trykomaster_move does it for us. 674 */ 675 676 inline static int 677 check_komaster_move(int pos, int color, int *ko_move_allowed) 678 { 679 *ko_move_allowed = 0; 680 681 /* 1. The color must be BLACK or WHITE. */ 682 gg_assert(color == BLACK || color == WHITE); 683 684 if (pos != PASS_MOVE) { 685 /* 2. Unless pass, the move must be inside the board. */ 686 ASSERT_ON_BOARD1(pos); 687 688 /* Update the reading tree shadow. */ 689 shadow[pos] = 1; 690 691 /* 3. The location must be empty. */ 692 if (board[pos] != EMPTY) 693 return 0; 694 695 /* 4. Test if the location is the ko point. */ 696 if (pos == board_ko_pos) { 697 /* The ko position is guaranteed to have all neighbors of the 698 * same color, or off board. If that color is the same as the 699 * move the ko is being filled, it is always allowed. This 700 * could be tested with has_neighbor() but here a faster test 701 * suffices. 702 */ 703 if (board[WEST(pos)] == OTHER_COLOR(color) 704 || board[EAST(pos)] == OTHER_COLOR(color)) 705 *ko_move_allowed = 1; 706 } 707 708 /* 5. Test for suicide. */ 709 if (is_suicide(pos, color)) { 710 *ko_move_allowed = 0; 711 return 0; 712 } 713 } 714 715 /* Check for stack overflow. */ 716 if (stackp >= MAXSTACK-2) { 717 fprintf(stderr, 718 "gnugo: Truncating search. This is beyond my reading ability!\n"); 719 /* FIXME: Perhaps it's best to just assert here and be done with it? */ 720 #if 0 721 ASSERT1(0 && "check_komaster_move stack overflow", pos); 722 #endif 723 #if 0 724 if (verbose > 0) { 725 showboard(0); 726 dump_stack(); 727 } 728 #endif 729 fflush(stderr); 730 *ko_move_allowed = 0; 731 return 0; 732 } 733 734 if (*ko_move_allowed) 735 return 0; 602 736 603 737 return 1; 604 738 } 605 739 740 /* 741 * Function calls really_do_trymove, counts stats and does all traces. 742 * It is called by komaster_trymove after check_komaster_move checks 743 * if the move is possible. 744 */ 745 746 static void 747 really_do_komastermove(int pos, int color, const char *message, int ko_move) 748 { 749 #ifndef GG_TURN_OFF_STATS 750 /* Only count trymove when we do create a new position. */ 751 trymove_counter++; 752 #endif 753 754 /* So far, so good. Now push the move on the move stack. These are 755 * needed for dump_stack(). 756 */ 757 stack[stackp] = pos; 758 move_color[stackp] = color; 759 760 really_do_trymove(pos, color); 761 762 #ifndef GG_TURN_OFF_TRACES 763 if (sgf_dumptree) { 764 char buf[100]; 765 766 if (message == NULL) 767 message = "UNKNOWN"; 768 769 if (pos == NO_MOVE) { 770 if (komaster != EMPTY) 771 gg_snprintf(buf, 100, "komaster_trymove: %s (variation %d, hash %s, komaster %s:%s)", 772 message, count_variations, hashdata_to_string(&board_hash), 773 color_to_string(komaster), location_to_string(kom_pos)); 774 else 775 gg_snprintf(buf, 100, "komaster_trymove: %s (variation %d, hash %s)", message, 776 count_variations, hashdata_to_string(&board_hash)); 777 } 778 else { 779 if (komaster != EMPTY) 780 gg_snprintf(buf, 100, 781 "komaster_trymove: %s at %s (variation %d, hash %s, komaster %s:%s)", 782 message, location_to_string(pos), count_variations, 783 hashdata_to_string(&board_hash), 784 color_to_string(komaster), 785 location_to_string(kom_pos)); 786 else 787 gg_snprintf(buf, 100, "komaster_trymove: %s at %s (variation %d, hash %s)", 788 message, location_to_string(pos), count_variations, 789 hashdata_to_string(&board_hash)); 790 } 791 792 /* Add two pass moves to the SGF output to simulate the ko threat 793 * and the answer. 794 * 795 * The reason we add these is that certain SGF viewers, including 796 * Cgoban 1, won't properly display variations with illegal ko 797 * captures. SGF FF[4] compliant browsers should have no problem 798 * with this, though. 799 */ 800 if (ko_move) { 801 sgftreeAddPlayLast(sgf_dumptree, color, -1, -1); 802 sgftreeAddComment(sgf_dumptree, "tenuki (ko threat)"); 803 sgftreeAddPlayLast(sgf_dumptree, OTHER_COLOR(color), -1, -1); 804 sgftreeAddComment(sgf_dumptree, "tenuki (answers ko threat)"); 805 } 806 807 sgftreeAddPlayLast(sgf_dumptree, color, I(pos), J(pos)); 808 sgftreeAddComment(sgf_dumptree, buf); 809 } 810 #else 811 UNUSED(message); 812 UNUSED(ko_move); 813 #endif 814 815 if (count_variations) 816 count_variations++; 817 818 #ifndef GG_TURN_OFF_STATS 819 stats.nodes++; 820 #endif 821 } 822 823 606 824 /* Really, really make a temporary move. It is assumed that all 607 825 * necessary checks have already been made and likewise that various 608 826 * administrative bookkeeping outside of the actual board logic has … … 614 832 BEGIN_CHANGE_RECORD(); 615 833 PUSH_VALUE(board_ko_pos); 616 834 617 /* 618 * FIXME: Do we really have to store board_hash in a stack? 619 * 620 * Answer: No, we don't. But for every stone that we add 621 * or remove, we must call hashdata_invert_stone(). This is 622 * not difficult per se, but the whole board.c 623 * will have to be checked, and there is lots of room 624 * for mistakes. 625 * 626 * At the same time, profiling shows that storing the 627 * hashdata in a stack doesn't take a lot of time, so 628 * this is not an urgent FIXME. 629 */ 835 /* Restoring a hash value is faster than xoring hash codes of all 836 * undone stones */ 630 837 memcpy(&board_hash_stack[stackp], &board_hash, sizeof(board_hash)); 631 838 632 839 if (board_ko_pos != NO_MOVE) … … 667 874 return 0; 668 875 669 876 /* 4. The location must not be the ko point, unless ignore_ko == 1. */ 670 if (!ignore_ko && pos == board_ko_pos) { 877 if (!ignore_ko && pos == board_ko_pos) { 878 /* The ko position is guaranteed to have all neighbors of the 879 * same color, or off board. If that color is the same as the 880 * move the ko is being filled, it is always allowed. This 881 * could be tested with has_neighbor() but here a faster test 882 * suffices. 883 */ 671 884 if (board[WEST(pos)] == OTHER_COLOR(color) 672 || board[EAST(pos)] == OTHER_COLOR(color)) { 673 return 0; 674 } 675 } 885 || board[EAST(pos)] == OTHER_COLOR(color)) 886 return 0; 887 } 676 888 677 889 /* 5. Test for suicide. */ 678 890 if (is_suicide(pos, color)) … … 684 896 fprintf(stderr, 685 897 "gnugo: Truncating search. This is beyond my reading ability!\n"); 686 898 /* FIXME: Perhaps it's best to just assert here and be done with it? */ 687 if (0) { 899 #if 0 688 900 ASSERT1(0 && "trymove stack overflow", pos); 689 } 901 #endif 690 902 #if 0 691 903 if (verbose > 0) { 692 904 showboard(0); … … 698 910 } 699 911 700 912 913 #ifndef GG_TURN_OFF_STATS 701 914 /* Only count trymove when we do create a new position. */ 702 915 trymove_counter++; 916 #endif 703 917 704 918 /* So far, so good. Now push the move on the move stack. These are 705 919 * needed for dump_stack(). … … 722 936 { 723 937 undo_trymove(); 724 938 939 #ifndef GG_TURN_OFF_TRACES 725 940 if (sgf_dumptree) { 726 941 char buf[100]; 727 942 int is_tryko = 0; … … 742 957 if (is_tryko) 743 958 sgf_dumptree->lastnode = sgf_dumptree->lastnode->parent->parent; 744 959 } 960 #endif 745 961 } 746 962 747 963 … … 760 976 { 761 977 gg_assert(change_stack_pointer - change_stack <= STACK_SIZE); 762 978 763 if (0) { 764 gprintf("Change stack size = %d\n", change_stack_pointer - change_stack); 765 gprintf("Vertex stack size = %d\n", vertex_stack_pointer - vertex_stack); 766 } 979 #if 0 980 gprintf("Change stack size = %d\n", change_stack_pointer - change_stack); 981 #ifdef INT_INTERSECTION 982 gprintf("Intersection is int, so we don't use vertex stack (all is on change stack)\n"); 983 #else 984 gprintf("Vertex stack size = %d\n", vertex_stack_pointer - vertex_stack); 985 #endif 986 #endif 767 987 768 988 POP_MOVE(); 769 POP_VERTICES();770 989 771 990 stackp--; 772 991 memcpy(&board_hash, &(board_hash_stack[stackp]), sizeof(board_hash)); … … 1015 1234 get_last_opponent_move(int color) 1016 1235 { 1017 1236 int k; 1237 const int other = OTHER_COLOR(color); 1018 1238 1019 1239 for (k = move_history_pointer - 1; k >= 0; k--) 1020 if (move_history_color[k] == OTHER_COLOR(color))1240 if (move_history_color[k] == other) 1021 1241 return move_history_pos[k]; 1022 1242 1023 1243 return PASS_MOVE; … … 1026 1246 /* Return the last move done by anyone. Both if no move was found or 1027 1247 * if the last move was a pass, PASS_MOVE is returned. 1028 1248 */ 1029 in t1249 inline int 1030 1250 get_last_move() 1031 1251 { 1032 1252 if (move_history_pointer == 0) … … 1038 1258 /* Return the color of the player doing the last move. If no move was 1039 1259 * found, EMPTY is returned. 1040 1260 */ 1041 in t1261 inline int 1042 1262 get_last_player() 1043 1263 { 1044 1264 if (move_history_pointer == 0) … … 1057 1277 * Test if the move is a pass or not. Return 1 if it is. 1058 1278 */ 1059 1279 1060 in t1280 inline int 1061 1281 is_pass(int pos) 1062 1282 { 1063 return pos == 0;1283 return pos == PASS_MOVE; 1064 1284 } 1065 1285 1066 1286 … … 1078 1298 is_legal(int pos, int color) 1079 1299 { 1080 1300 /* 0. A pass move is always legal. */ 1081 if (pos == 0)1301 if (pos == PASS_MOVE) 1082 1302 return 1; 1083 1303 1084 1304 /* 1. The move must be inside the board. */ … … 1092 1312 if (pos == board_ko_pos) { 1093 1313 /* The ko position is guaranteed to have all neighbors of the 1094 1314 * same color, or off board. If that color is the same as the 1095 * move the ko is being filled, whichis always allowed. This1315 * move the ko is being filled, it is always allowed. This 1096 1316 * could be tested with has_neighbor() but here a faster test 1097 1317 * suffices. 1098 1318 */ 1099 if (board[WEST(pos)] == OTHER_COLOR(color) 1100 || board[EAST(pos)] == OTHER_COLOR(color)) { 1319 if (board[WEST(pos)] == OTHER_COLOR(color) 1320 || board[EAST(pos)] == OTHER_COLOR(color)) 1101 1321 return 0; 1102 }1103 1322 } 1104 1323 1105 1324 /* Check for stack overflow. */ … … 1107 1326 fprintf(stderr, 1108 1327 "gnugo: Truncating search. This is beyond my reading ability!\n"); 1109 1328 /* FIXME: Perhaps it's best to just assert here and be done with it? */ 1110 if (0) { 1329 #if 0 1111 1330 ASSERT1(0 && "is_legal stack overflow", pos); 1112 } 1331 #endif 1113 1332 return 0; 1114 1333 } 1115 1334 … … 1133 1352 int 1134 1353 is_suicide(int pos, int color) 1135 1354 { 1355 int checked_pos; 1356 int stone; 1136 1357 ASSERT_ON_BOARD1(pos); 1137 1358 ASSERT1(board[pos] == EMPTY, pos); 1138 1359 1139 1360 /* Check for suicide. */ 1140 if (LIBERTY(SOUTH(pos)) 1141 || (ON_BOARD(SOUTH(pos)) 1142 && ((board[SOUTH(pos)] == color) ^ (LIBERTIES(SOUTH(pos)) == 1)))) 1361 checked_pos = SOUTH(pos); 1362 stone = board[checked_pos]; 1363 if (stone == EMPTY 1364 || (ON_BOARD(checked_pos) 1365 && ((stone == color) ^ (LIBERTIES(string_number[checked_pos]) == 1)))) 1143 1366 return 0; 1144 1367 1145 if (LIBERTY(WEST(pos)) 1146 || (ON_BOARD(WEST(pos)) 1147 && ((board[WEST(pos)] == color) ^ (LIBERTIES(WEST(pos)) == 1)))) 1368 checked_pos = WEST(pos); 1369 stone = board[checked_pos]; 1370 if (stone == EMPTY 1371 || (ON_BOARD(checked_pos) 1372 && ((stone == color) ^ (LIBERTIES(string_number[checked_pos]) == 1)))) 1148 1373 return 0; 1149 1374 1150 if (LIBERTY(NORTH(pos)) 1151 || (ON_BOARD(NORTH(pos)) 1152 && ((board[NORTH(pos)] == color) ^ (LIBERTIES(NORTH(pos)) == 1)))) 1375 checked_pos = NORTH(pos); 1376 stone = board[checked_pos]; 1377 if (stone == EMPTY 1378 || (ON_BOARD(checked_pos) 1379 && ((stone == color) ^ (LIBERTIES(string_number[checked_pos]) == 1)))) 1153 1380 return 0; 1154 1381 1155 if (LIBERTY(EAST(pos)) 1156 || (ON_BOARD(EAST(pos)) 1157 && ((board[EAST(pos)] == color) ^ (LIBERTIES(EAST(pos)) == 1)))) 1382 checked_pos = EAST(pos); 1383 stone = board[checked_pos]; 1384 if (stone == EMPTY 1385 || (ON_BOARD(checked_pos) 1386 && ((stone == color) ^ (LIBERTIES(string_number[checked_pos]) == 1)))) 1158 1387 return 0; 1159 1388 1160 1389 return 1; … … 1165 1394 * is_illegal_ko_capture(pos, color) determines whether the move 1166 1395 * (color) at (pos) would be an illegal ko capture. 1167 1396 */ 1168 in t1397 inline int 1169 1398 is_illegal_ko_capture(int pos, int color) 1170 1399 { 1171 1400 ASSERT_ON_BOARD1(pos); 1172 1401 ASSERT1(board[pos] == EMPTY, pos); 1173 1402 1174 1403 return (pos == board_ko_pos 1404 /* The ko position is guaranteed to have all neighbors of the 1405 * same color, or off board. If that color is the same as the 1406 * move the ko is being filled, it is always allowed. This 1407 * could be tested with has_neighbor() but here a faster test 1408 * suffices. 1409 */ 1175 1410 && ((board[WEST(pos)] == OTHER_COLOR(color)) 1176 1411 || (board[EAST(pos)] == OTHER_COLOR(color)))); 1177 1412 } … … 1209 1444 * suffices. 1210 1445 */ 1211 1446 if (ko_rule != NONE 1212 && pos == board_ko_pos 1213 && (board[WEST(pos)] == OTHER_COLOR(color) 1214 || board[EAST(pos)] == OTHER_COLOR(color))) 1215 return 0; 1447 && pos == board_ko_pos) { 1448 /* The ko position is guaranteed to have all neighbors of the 1449 * same color, or off board. If that color is the same as the 1450 * move the ko is being filled, it is always allowed. This 1451 * could be tested with has_neighbor() but here a faster test 1452 * suffices. 1453 */ 1454 if (board[WEST(pos)] == OTHER_COLOR(color) 1455 || board[EAST(pos)] == OTHER_COLOR(color)) 1456 return 0; 1457 } 1216 1458 1217 1459 /* 5. Check for suicide. Suicide rule options: 1218 1460 * FORBIDDEN - No suicides allowed. … … 1231 1473 * SSK - Repetition of a previous position with the same 1232 1474 * player to move forbidden. 1233 1475 */ 1234 if (is_superko_violation(pos, color, ko_rule)) 1235 return 0; 1476 if (ko_rule != SIMPLE && ko_rule != NONE) 1477 if (is_superko_violation(pos, color, ko_rule)) 1478 return 0; 1236 1479 1237 1480 return 1; 1238 1481 } … … 1265 1508 * 3.5.1 four of them were removed to simplify the code and because it 1266 1509 * no longer seemed interesting to be able to switch. The remaining 1267 1510 * komaster scheme was previously known as komaster scheme 5 (or V). 1268 *1269 * FIXME: This function could be optimized by integrating the1270 * trymove()/tryko() code.1271 1511 */ 1272 1512 1273 1513 /* V. Complex scheme, O to move. … … 1284 1524 * 2. Komaster is O: 1285 1525 * 2a) Only nested ko captures are allowed. Kom_pos is moved to the 1286 1526 * new removed stone. 1287 * 2b) If komaster fills the ko at kom_pos then komaster reverts to 1288 * EMPTY. 1527 * 2b) If the ko has been resolved in favor of the komaster (when the ko is 1528 * filled or kom_pos is no longer a ko because of some capture) then the 1529 * komaster reverts to EMPTY. 1289 1530 * 1290 1531 * 3. Komaster is X: 1291 * Play at kom_pos is not allowed . Any other ko capture1292 * is allowed. If O takes another ko, komaster becomes GRAY_X.1532 * Play at kom_pos is not allowed if it is the ko recapture. Any other 1533 * ko capture is allowed. If O takes another ko, komaster becomes GRAY_X. 1293 1534 * 1294 1535 * 4. Komaster is GRAY_O or GRAY_X: 1295 * Ko captures are not allowed. If the ko at kom_pos is 1296 * filled then the komaster reverts to EMPTY. 1536 * Ko captures are not allowed. If the ko has been resolved in favor of 1537 * the komaster (when the ko is filled or kom_pos is no longer a ko because 1538 * of some capture) then the komaster reverts to EMPTY. 1297 1539 * 1298 1540 * 5. Komaster is WEAK_KO: 1299 1541 * 5a) After a non-ko move komaster reverts to EMPTY. 1300 1542 * 5b) Unconditional ko capture is only allowed if it is nested ko capture. 1301 * Komaster is changed to WEAK_X and kom_pos to the old value of 1302 * board_ko_pos. 1543 * Kom_pos is moved to the old value of board_ko_pos. 1303 1544 * 5c) Conditional ko capture is allowed according to the rules of 1b. 1304 1545 */ 1305 1546 int 1306 1547 komaster_trymove(int pos, int color, const char *message, int str, 1307 1548 int *is_conditional_ko, int consider_conditional_ko) 1308 1549 { 1309 int other = OTHER_COLOR(color);1310 1550 int ko_move; 1311 1551 int kpos; 1312 int previous_board_ko_pos = board_ko_pos; 1552 int previous_board_ko_pos; 1553 int ko_move_allowed; 1554 1555 UNUSED(str); 1313 1556 1314 1557 *is_conditional_ko = 0; 1315 1558 ko_move = is_ko(pos, color, &kpos); 1316 1559 1317 1560 if (ko_move) { 1318 /* If opponent is komaster we may not capture his ko. */ 1319 if (komaster == other && pos == kom_pos) 1320 return 0; 1321 1322 /* If komaster is gray we may not capture ko at all. */ 1323 if (komaster == GRAY_WHITE || komaster == GRAY_BLACK) 1324 return 0; 1325 1326 /* If we are komaster, we may only do nested captures. */ 1327 if (komaster == color && !DIAGONAL_NEIGHBORS(kpos, kom_pos)) 1328 return 0; 1329 1330 /* If komaster is WEAK_KO, we may only do nested ko capture or 1331 * conditional ko capture. 1332 */ 1333 if (komaster == WEAK_KO) { 1334 if (pos != board_ko_pos && !DIAGONAL_NEIGHBORS(kpos, kom_pos)) 1335 return 0; 1561 switch (komaster) { 1562 case EMPTY: 1563 break; 1564 1565 case GRAY_WHITE: 1566 case GRAY_BLACK: 1567 /* If komaster is gray we may not capture ko at all. */ 1568 return 0; 1569 1570 case WEAK_KO: 1571 /* If komaster is WEAK_KO, we may only do nested ko capture or 1572 * conditional ko capture. 1573 */ 1574 if (pos != board_ko_pos && !DIAGONAL_NEIGHBORS(kpos, kom_pos)) 1575 return 0; 1576 break; 1577 1578 default: 1579 if (komaster == color) { 1580 /* If we are komaster, we may only do nested captures. */ 1581 if (!DIAGONAL_NEIGHBORS(kpos, kom_pos)) 1582 return 0; 1583 } 1584 else { // komaster == OTHER_COLOR(color) 1585 /* If opponent is komaster we may not capture his ko. */ 1586 if (pos == kom_pos) 1587 return 0; 1588 } 1589 break; 1336 1590 } 1337 1591 } 1338 1592 1339 if (!trymove(pos, color, message, str)) { 1593 previous_board_ko_pos = board_ko_pos; 1594 1595 if (check_komaster_move(pos, color, &ko_move_allowed)) 1596 really_do_komastermove(pos, color, message, 0); 1597 else { 1598 /* Conditional ko capture */ 1340 1599 if (!consider_conditional_ko) 1341 1600 return 0; 1342 1601 1343 if (! tryko(pos, color, message))1602 if (!ko_move_allowed) 1344 1603 return 0; /* Suicide. */ 1604 1605 really_do_komastermove(pos, color, message, 1); 1345 1606 1346 1607 *is_conditional_ko = 1; 1347 1608 1348 /* Conditional ko capture, set komaster parameters . */1609 /* Conditional ko capture, set komaster parameters (1b and 5c). */ 1349 1610 if (komaster == EMPTY || komaster == WEAK_KO) { 1350 1611 set_new_komaster(color); 1351 1612 set_new_kom_pos(kpos); … … 1355 1616 1356 1617 if (!ko_move) { 1357 1618 /* If we are komaster, check whether the ko was resolved by the 1358 * current move. If that is the case, revert komaster to EMPTY .1619 * current move. If that is the case, revert komaster to EMPTY (2b and 4). 1359 1620 * 1360 1621 * The ko has been resolved in favor of the komaster if it has 1361 * been filled, or if it is no longer a ko and an opponent move1362 * there is suicide.1622 * been filled, or if an opponent move there is suicide (it is no 1623 * longer a ko then). 1363 1624 */ 1364 if (( (komaster == color1625 if ((komaster == color 1365 1626 || (komaster == GRAY_WHITE && color == WHITE) 1366 1627 || (komaster == GRAY_BLACK && color == BLACK)) 1367 && ( IS_STONE(board[kom_pos])1368 || ( !is_ko(kom_pos, other, NULL)1369 && is_suicide(kom_pos, other))))) {1628 && (board[kom_pos] == color 1629 || (board[kom_pos] == EMPTY 1630 && is_suicide(kom_pos, OTHER_COLOR(color))))) { 1370 1631 set_new_komaster(EMPTY); 1371 1632 set_new_kom_pos(NO_MOVE); 1372 1633 } 1373 1374 if (komaster == WEAK_KO) {1634 /* After the non-ko move set the komaster to EMPTY (5a). */ 1635 else if (komaster == WEAK_KO) { 1375 1636 set_new_komaster(EMPTY); 1376 1637 set_new_kom_pos(NO_MOVE); 1377 1638 } … … 1379 1640 return 1; 1380 1641 } 1381 1642 1382 if (komaster == other) { 1643 if (komaster == OTHER_COLOR(color)) { 1644 /* After a ko capture set komaster to GRAY_X (3). */ 1383 1645 if (color == WHITE) 1384 1646 set_new_komaster(GRAY_BLACK); 1385 1647 else 1386 1648 set_new_komaster(GRAY_WHITE); 1387 1649 } 1388 1650 else if (komaster == color) { 1389 /* This is where we update kom_pos after a nested capture . */1651 /* This is where we update kom_pos after a nested capture (2a). */ 1390 1652 set_new_kom_pos(kpos); 1391 1653 } 1392 1654 else { 1393 1655 /* We can reach here when komaster is EMPTY or WEAK_KO. If previous 1394 * move was also a ko capture, we now set komaster to WEAK_KO .1656 * move was also a ko capture, we now set komaster to WEAK_KO (1a and 5b). 1395 1657 */ 1396 1658 if (previous_board_ko_pos != NO_MOVE) { 1397 1659 set_new_komaster(WEAK_KO); … … 1402 1664 return 1; 1403 1665 } 1404 1666 1405 in t1667 inline int 1406 1668 get_komaster() 1407 1669 { 1408 1670 return komaster; 1409 1671 } 1410 1672 1411 in t1673 inline int 1412 1674 get_kom_pos() 1413 1675 { 1414 1676 return kom_pos; … … 1416 1678 1417 1679 1418 1680 /* Determine whether vertex is on the edge. */ 1419 in t1681 inline int 1420 1682 is_edge_vertex(int pos) 1421 1683 { 1422 1684 ASSERT_ON_BOARD1(pos); … … 1428 1690 } 1429 1691 1430 1692 /* Distance to the edge. */ 1431 in t1693 inline int 1432 1694 edge_distance(int pos) 1433 1695 { 1434 1696 int i = I(pos); … … 1439 1701 1440 1702 1441 1703 /* Determine whether vertex is a corner. */ 1442 in t1704 inline int 1443 1705 is_corner_vertex(int pos) 1444 1706 { 1445 1707 ASSERT_ON_BOARD1(pos); … … 1451 1713 } 1452 1714 1453 1715 1454 /* Returns true if the empty vertex respectivelythe string at pos1 is1455 * adjacent to the empty vertex respectivelythe string at pos2.1716 /* Returns true if the empty vertex or the string at pos1 is 1717 * adjacent to the empty vertex or the string at pos2. 1456 1718 */ 1457 1719 int 1458 1720 are_neighbors(int pos1, int pos2) … … 1471 1733 } 1472 1734 } 1473 1735 1474 1475 /* Count the number of liberties of the string at pos. pos must not be 1476 * empty. 1736 /* Count the number of liberties of the string at str_pos. 1737 * str_pos must not be empty 1477 1738 */ 1478 in t1479 countlib(int str )1739 inline int 1740 countlib(int str_pos) 1480 1741 { 1481 ASSERT1(IS_STONE(board[str ]), str);1482 1742 ASSERT1(IS_STONE(board[str_pos]), str_pos); 1743 1483 1744 /* We already know the number of liberties. Just look it up. */ 1484 return string[string_number[str ]].liberties;1745 return string[string_number[str_pos]].liberties; 1485 1746 } 1486 1747 1487 1748 1488 /* Find the liberties of the string at str . strmust not be1749 /* Find the liberties of the string at str_pos. str_pos must not be 1489 1750 * empty. The locations of up to maxlib liberties are written into 1490 1751 * libs[]. The full number of liberties is returned. 1491 1752 * … … 1495 1756 */ 1496 1757 1497 1758 int 1498 findlib(int str , int maxlib, int *libs)1759 findlib(int str_pos, int maxlib, int *libs) 1499 1760 { 1500 1761 int k; 1501 1762 int liberties; 1502 int s; 1503 1504 ASSERT1(IS_STONE(board[str]), str); 1505 ASSERT1(libs != NULL, str); 1506 1763 int to_copy; 1764 int str_nr; 1765 1766 ASSERT1(IS_STONE(board[str_pos]), str_pos); 1767 ASSERT1(libs != NULL, str_pos); 1768 1507 1769 /* We already have the list of liberties and only need to copy it to 1508 1770 * libs[]. 1509 1771 * … … 1512 1774 * we have to traverse the stones in the string in order to find 1513 1775 * where the liberties are. 1514 1776 */ 1515 s = string_number[str]; 1516 liberties = string[s].liberties; 1777 str_nr = string_number[str_pos]; 1778 liberties = string[str_nr].liberties; 1779 to_copy = maxlib > liberties ? liberties : maxlib; 1517 1780 1518 1781 if (liberties <= MAX_LIBERTIES || maxlib <= MAX_LIBERTIES) { 1519 1782 /* The easy case, it suffices to copy liberty locations from the 1520 1783 * incrementally updated list. 1521 1784 */ 1522 for (k = 0; k < maxlib && k < liberties; k++)1523 libs[k] = string_libs[s ].list[k];1785 for (k = 0; k < to_copy; k++) 1786 libs[k] = string_libs[str_nr].list[k]; 1524 1787 } 1525 1788 else { 1526 1789 /* The harder case, where we have to traverse the stones in the … … 1528 1791 * the start of the chain since we will run out of liberties 1529 1792 * before that happens. 1530 1793 */ 1531 int pos ;1794 int pos, checked_pos; 1532 1795 liberty_mark++; 1533 for (k = 0, pos = FIRST_STONE(s );1534 k < maxlib && k < liberties;1796 for (k = 0, pos = FIRST_STONE(str_nr); 1797 k < to_copy; 1535 1798 pos = NEXT_STONE(pos)) { 1536 if (UNMARKED_LIBERTY(SOUTH(pos))) { 1537 libs[k++] = SOUTH(pos); 1538 MARK_LIBERTY(SOUTH(pos)); 1539 if (k >= maxlib) 1799 checked_pos = SOUTH(pos); 1800 if (UNMARKED_LIBERTY(checked_pos)) { 1801 libs[k++] = checked_pos; 1802 MARK_LIBERTY(checked_pos); 1803 if (k >= to_copy) 1540 1804 break; 1541 1805 } 1542 1806 1543 if (UNMARKED_LIBERTY(WEST(pos))) { 1544 libs[k++] = WEST(pos); 1545 MARK_LIBERTY(WEST(pos)); 1546 if (k >= maxlib) 1807 checked_pos = WEST(pos); 1808 if (UNMARKED_LIBERTY(checked_pos)) { 1809 libs[k++] = checked_pos; 1810 MARK_LIBERTY(checked_pos); 1811 if (k >= to_copy) 1547 1812 break; 1548 1813 } 1549 1814 1550 if (UNMARKED_LIBERTY(NORTH(pos))) { 1551 libs[k++] = NORTH(pos); 1552 MARK_LIBERTY(NORTH(pos)); 1553 if (k >= maxlib) 1815 checked_pos = NORTH(pos); 1816 if (UNMARKED_LIBERTY(checked_pos)) { 1817 libs[k++] = checked_pos; 1818 MARK_LIBERTY(checked_pos); 1819 if (k >= to_copy) 1554 1820 break; 1555 1821 } 1556 1822 1557 if (UNMARKED_LIBERTY(EAST(pos))) { 1558 libs[k++] = EAST(pos); 1559 MARK_LIBERTY(EAST(pos)); 1560 if (k >= maxlib) 1823 checked_pos = EAST(pos); 1824 if (UNMARKED_LIBERTY(checked_pos)) { 1825 libs[k++] = checked_pos; 1826 MARK_LIBERTY(checked_pos); 1827 if (k >= to_copy) 1561 1828 break; 1562 1829 } 1563 1830 } … … 1588 1855 int ally1 = -1; 1589 1856 int ally2 = -1; 1590 1857 int fast_liberties = 0; 1858 int checked_pos; 1859 int str_nr; 1591 1860 1592 1861 ASSERT1(board[pos] == EMPTY, pos); 1593 1862 ASSERT1(IS_STONE(color), pos); … … 1599 1868 ally1 = string_number[SOUTH(pos)]; 1600 1869 1601 1870 if (board[WEST(pos)] == color 1602 && string_number[WEST(pos)]!= ally1) {1603 ally2 = str ing_number[WEST(pos)];1871 && (str_nr = string_number[WEST(pos)]) != ally1) { 1872 ally2 = str_nr; 1604 1873 1605 1874 if (board[NORTH(pos)] == color 1606 && string_number[NORTH(pos)]!= ally11607 && str ing_number[NORTH(pos)]!= ally2)1875 && (str_nr = string_number[NORTH(pos)]) != ally1 1876 && str_nr != ally2) 1608 1877 return -1; 1609 1878 } 1610 1879 else if (board[NORTH(pos)] == color 1611 && string_number[NORTH(pos)]!= ally1)1612 ally2 = str ing_number[NORTH(pos)];1880 && (str_nr = string_number[NORTH(pos)]) != ally1) 1881 ally2 = str_nr; 1613 1882 1614 if (board[ EAST(pos)] == color1615 && string_number[ EAST(pos)] != ally1) {1883 if (board[checked_pos = EAST(pos)] == color 1884 && string_number[checked_pos] != ally1) { 1616 1885 if (ally2 < 0) 1617 ally2 = string_number[ EAST(pos)];1618 else if (string_number[ EAST(pos)] != ally2)1886 ally2 = string_number[checked_pos]; 1887 else if (string_number[checked_pos] != ally2) 1619 1888 return -1; 1620 1889 } 1621 1890 } … … 1623 1892 ally1 = string_number[WEST(pos)]; 1624 1893 1625 1894 if (board[NORTH(pos)] == color 1626 && string_number[NORTH(pos)]!= ally1) {1627 ally2 = str ing_number[NORTH(pos)];1895 && (str_nr = string_number[NORTH(pos)]) != ally1) { 1896 ally2 = str_nr; 1628 1897 1629 1898 if (board[EAST(pos)] == color 1630 && string_number[EAST(pos)]!= ally11631 && str ing_number[EAST(pos)]!= ally2)1899 && (str_nr = string_number[EAST(pos)]) != ally1 1900 && str_nr != ally2) 1632 1901 return -1; 1633 1902 } 1634 1903 else if (board[EAST(pos)] == color 1635 && string_number[EAST(pos)]!= ally1)1636 ally2 = str ing_number[EAST(pos)];1904 && (str_nr = string_number[EAST(pos)]) != ally1) 1905 ally2 = str_nr; 1637 1906 } 1638 1907 else if (board[NORTH(pos)] == color) { 1639 1908 ally1 = string_number[NORTH(pos)]; 1640 1909 1641 1910 if (board[EAST(pos)] == color 1642 && string_number[EAST(pos)]!= ally1)1643 ally2 = str ing_number[EAST(pos)];1911 && (str_nr = string_number[EAST(pos)]) != ally1) 1912 ally2 = str_nr; 1644 1913 } 1645 1914 else if (board[EAST(pos)] == color) 1646 1915 ally1 = string_number[EAST(pos)]; … … 1674 1943 fast_liberties += string[ally1].liberties - 1; 1675 1944 } 1676 1945 else { /* Two allies */ 1677 if (LIBERTY(SOUTH(pos)) 1678 && !NON_SOUTH_NEIGHBOR_OF_STRING(SOUTH(pos), ally1, color) 1679 && !NON_SOUTH_NEIGHBOR_OF_STRING(SOUTH(pos), ally2, color)) 1946 int checked_pos = SOUTH(pos); 1947 if (LIBERTY(checked_pos) 1948 && !NON_SOUTH_NEIGHBOR_OF_STRING(checked_pos, ally1, color) 1949 && !NON_SOUTH_NEIGHBOR_OF_STRING(checked_pos, ally2, color)) 1680 1950 fast_liberties++; 1681 if (LIBERTY(WEST(pos)) 1682 && !NON_WEST_NEIGHBOR_OF_STRING(WEST(pos), ally1, color) 1683 && !NON_WEST_NEIGHBOR_OF_STRING(WEST(pos), ally2, color)) 1951 checked_pos = WEST(pos); 1952 if (LIBERTY(checked_pos) 1953 && !NON_WEST_NEIGHBOR_OF_STRING(checked_pos, ally1, color) 1954 && !NON_WEST_NEIGHBOR_OF_STRING(checked_pos, ally2, color)) 1684 1955 fast_liberties++; 1685 if (LIBERTY(NORTH(pos)) 1686 && !NON_NORTH_NEIGHBOR_OF_STRING(NORTH(pos), ally1, color) 1687 && !NON_NORTH_NEIGHBOR_OF_STRING(NORTH(pos), ally2, color)) 1956 checked_pos = NORTH(pos); 1957 if (LIBERTY(checked_pos) 1958 && !NON_NORTH_NEIGHBOR_OF_STRING(checked_pos, ally1, color) 1959 && !NON_NORTH_NEIGHBOR_OF_STRING(checked_pos, ally2, color)) 1688 1960 fast_liberties++; 1689 if (LIBERTY(EAST(pos)) 1690 && !NON_EAST_NEIGHBOR_OF_STRING(EAST(pos), ally1, color) 1691 && !NON_EAST_NEIGHBOR_OF_STRING(EAST(pos), ally2, color)) 1961 checked_pos = EAST(pos); 1962 if (LIBERTY(checked_pos) 1963 && !NON_EAST_NEIGHBOR_OF_STRING(checked_pos, ally1, color) 1964 && !NON_EAST_NEIGHBOR_OF_STRING(checked_pos, ally2, color)) 1692 1965 fast_liberties++; 1693 1966 1694 1967 fast_liberties += string[ally1].liberties + string[ally2].liberties … … 1700 1973 */ 1701 1974 else { 1702 1975 int k; 1976 int other = OTHER_COLOR(color); 1703 1977 1704 1978 for (k = 0; k < 4; k++) { 1705 int neighbor = pos + delta[k];1979 int neighbor_pos = pos + delta[k]; 1706 1980 1707 if (LIBERTY(neighbor )1708 && (ally1 < 0 || !NEIGHBOR_OF_STRING(neighbor , ally1, color))1709 && (ally2 < 0 || !NEIGHBOR_OF_STRING(neighbor , ally2, color)))1981 if (LIBERTY(neighbor_pos) 1982 && (ally1 < 0 || !NEIGHBOR_OF_STRING(neighbor_pos, ally1, color)) 1983 && (ally2 < 0 || !NEIGHBOR_OF_STRING(neighbor_pos, ally2, color))) 1710 1984 fast_liberties++; 1711 else if (board[neighbor ] == OTHER_COLOR(color) /* A capture */1712 && LIBERTIES(neighbor) == 1) { 1713 int neighbor_size = COUNTSTONES( neighbor);1985 else if (board[neighbor_pos] == other 1986 && LIBERTIES(string_number[neighbor_pos]) == 1) { /* A capture */ 1987 int neighbor_size = COUNTSTONES(string_number[neighbor_pos]); 1714 1988 1715 1989 if (neighbor_size == 1 || (neighbor_size == 2 && ally1 < 0)) 1716 1990 fast_liberties++; … … 1722 1996 if (ally1 >= 0) { 1723 1997 fast_liberties += string[ally1].liberties - 1; 1724 1998 if (ally2 >= 0) 1725 fast_liberties += string[ally2].liberties1999 fast_liberties += string[ally2].liberties 1726 2000 - count_common_libs(string[ally1].origin, string[ally2].origin); 1727 2001 } 1728 2002 } … … 1730 2004 return fast_liberties; 1731 2005 } 1732 2006 2007 #define USE_BOARD_CACHES 1 1733 2008 1734 /* Effectively true unless we store full position in hash. */ 1735 #define USE_BOARD_CACHES (NUM_HASHVALUES <= 4) 1736 1737 struct board_cache_entry { 1738 int threshold; 1739 int liberties; 1740 Hash_data position_hash; 1741 }; 1742 1743 1744 /* approxlib() cache. */ 2009 /* approxlib() cache. Stores data for both colors */ 1745 2010 static struct board_cache_entry approxlib_cache[BOARDMAX][2]; 1746 2011 1747 2012 1748 2013 /* Clears approxlib() cache. This function should be called only once 1749 2014 * during engine initialization. Sets thresholds to zero. 1750 2015 */ 1751 void2016 inline void 1752 2017 clear_approxlib_cache(void) 1753 2018 { 1754 int pos; 1755 1756 for (pos = BOARDMIN; pos < BOARDMAX; pos++) { 1757 approxlib_cache[pos][0].threshold = 0; 1758 approxlib_cache[pos][1].threshold = 0; 1759 } 2019 memset(approxlib_cache, 0, sizeof(approxlib_cache)); 1760 2020 } 1761 2021 1762 2022 … … 1778 2038 1779 2039 #ifdef USE_BOARD_CACHES 1780 2040 1781 struct board_cache_entry *entry = &approxlib_cache[pos][color - 1];2041 struct board_cache_entry *entry = &approxlib_cache[pos][color - WHITE]; 1782 2042 1783 2043 ASSERT1(board[pos] == EMPTY, pos); 1784 2044 ASSERT1(IS_STONE(color), pos); … … 1812 2072 entry->threshold = maxlib; 1813 2073 1814 2074 if (maxlib <= MAX_LIBERTIES) 1815 liberties = do_approxlib(pos, color, maxlib, libs );2075 liberties = do_approxlib(pos, color, maxlib, libs, entry); 1816 2076 else 1817 liberties = slow_approxlib(pos, color, maxlib, libs );2077 liberties = slow_approxlib(pos, color, maxlib, libs, entry); 1818 2078 1819 2079 entry->liberties = liberties; 1820 2080 entry->position_hash = board_hash; … … 1842 2102 1843 2103 1844 2104 /* Does the real work of approxlib(). */ 1845 static int 1846 do_approxlib(int pos, int color, int maxlib, int *libs) 2105 inline static int 2106 do_approxlib(int pos, int color, int maxlib, int *libs, 2107 struct board_cache_entry *entry) 1847 2108 { 1848 2109 int k; 1849 2110 int liberties = 0; 2111 int checked_pos, str_nr, str_libs, checked_lib; 1850 2112 1851 2113 /* Look for empty neighbors and the liberties of the adjacent 1852 2114 * strings of the given color. The algorithm below won't work … … 1862 2124 liberty_mark++; 1863 2125 MARK_LIBERTY(pos); 1864 2126 1865 if (UNMARKED_LIBERTY(SOUTH(pos))) { 1866 if (libs != NULL) 1867 libs[liberties] = SOUTH(pos); 1868 liberties++; 1869 /* Stop counting if we reach maxlib. */ 1870 if (liberties >= maxlib) 1871 return liberties; 1872 MARK_LIBERTY(SOUTH(pos)); 2127 checked_pos = SOUTH(pos); 2128 if (board[checked_pos] == EMPTY) { 2129 if (ml[checked_pos] != liberty_mark) { 2130 if (libs != NULL) 2131 libs[liberties] = checked_pos; 2132 liberties++; 2133 /* Stop counting if we reach maxlib. */ 2134 if (liberties >= maxlib) 2135 return liberties; 2136 MARK_LIBERTY(checked_pos); 2137 } 1873 2138 } 1874 else if (board[SOUTH(pos)] == color) { 1875 int s = string_number[SOUTH(pos)]; 1876 for (k = 0; k < string[s].liberties; k++) { 1877 int lib = string_libs[s].list[k]; 1878 if (UNMARKED_LIBERTY(lib)) { 2139 else if (board[checked_pos] == color) { 2140 str_nr = string_number[checked_pos]; 2141 str_libs = string[str_nr].liberties; 2142 for (k = 0; k < str_libs; k++) { 2143 checked_lib = string_libs[str_nr].list[k]; 2144 if (UNMARKED_LIBERTY(checked_lib)) { 1879 2145 if (libs != NULL) 1880 libs[liberties] = lib;2146 libs[liberties] = checked_lib; 1881 2147 liberties++; 1882 2148 if (liberties >= maxlib) 1883 2149 return liberties; 1884 MARK_LIBERTY( lib);2150 MARK_LIBERTY(checked_lib); 1885 2151 } 1886 2152 } 1887 2153 } 1888 2154 1889 if (UNMARKED_LIBERTY(WEST(pos))) { 1890 if (libs != NULL) 1891 libs[liberties] = WEST(pos); 1892 liberties++; 1893 /* Stop counting if we reach maxlib. */ 1894 if (liberties >= maxlib) 1895 return liberties; 1896 MARK_LIBERTY(WEST(pos)); 2155 checked_pos = WEST(pos); 2156 if (board[checked_pos] == EMPTY) { 2157 if (ml[checked_pos] != liberty_mark) { 2158 if (libs != NULL) 2159 libs[liberties] = checked_pos; 2160 liberties++; 2161 /* Stop counting if we reach maxlib. */ 2162 if (liberties >= maxlib) 2163 return liberties; 2164 MARK_LIBERTY(checked_pos); 2165 } 1897 2166 } 1898 else if (board[WEST(pos)] == color) { 1899 int s = string_number[WEST(pos)]; 1900 for (k = 0; k < string[s].liberties; k++) { 1901 int lib = string_libs[s].list[k]; 1902 if (UNMARKED_LIBERTY(lib)) { 2167 else if (board[checked_pos] == color) { 2168 str_nr = string_number[checked_pos]; 2169 str_libs = string[str_nr].liberties; 2170 for (k = 0; k < str_libs; k++) { 2171 checked_lib = string_libs[str_nr].list[k]; 2172 if (UNMARKED_LIBERTY(checked_lib)) { 1903 2173 if (libs != NULL) 1904 libs[liberties] = lib;2174 libs[liberties] = checked_lib; 1905 2175 liberties++; 1906 2176 if (liberties >= maxlib) 1907 2177 return liberties; 1908 MARK_LIBERTY( lib);2178 MARK_LIBERTY(checked_lib); 1909 2179 } 1910 2180 } 1911 2181 } 1912 2182 1913 if (UNMARKED_LIBERTY(NORTH(pos))) { 1914 if (libs != NULL) 1915 libs[liberties] = NORTH(pos); 1916 liberties++; 1917 /* Stop counting if we reach maxlib. */ 1918 if (liberties >= maxlib) 1919 return liberties; 1920 MARK_LIBERTY(NORTH(pos)); 2183 checked_pos = NORTH(pos); 2184 if (board[checked_pos] == EMPTY) { 2185 if (ml[checked_pos] != liberty_mark) { 2186 if (libs != NULL) 2187 libs[liberties] = checked_pos; 2188 liberties++; 2189 /* Stop counting if we reach maxlib. */ 2190 if (liberties >= maxlib) 2191 return liberties; 2192 MARK_LIBERTY(checked_pos); 2193 } 1921 2194 } 1922 else if (board[NORTH(pos)] == color) { 1923 int s = string_number[NORTH(pos)]; 1924 for (k = 0; k < string[s].liberties; k++) { 1925 int lib = string_libs[s].list[k]; 1926 if (UNMARKED_LIBERTY(lib)) { 2195 else if (board[checked_pos] == color) { 2196 str_nr = string_number[checked_pos]; 2197 str_libs = string[str_nr].liberties; 2198 for (k = 0; k < str_libs; k++) { 2199 checked_lib = string_libs[str_nr].list[k]; 2200 if (UNMARKED_LIBERTY(checked_lib)) { 1927 2201 if (libs != NULL) 1928 libs[liberties] = lib;2202 libs[liberties] = checked_lib; 1929 2203 liberties++; 1930 2204 if (liberties >= maxlib) 1931 2205 return liberties; 1932 MARK_LIBERTY( lib);2206 MARK_LIBERTY(checked_lib); 1933 2207 } 1934 2208 } 1935 2209 } 1936 1937 if (UNMARKED_LIBERTY(EAST(pos))) { 1938 if (libs != NULL) 1939 libs[liberties] = EAST(pos); 1940 liberties++; 1941 /* Unneeded since we're about to leave. */ 2210 2211 checked_pos = EAST(pos); 2212 if (board[checked_pos] == EMPTY) { 2213 if (ml[checked_pos] != liberty_mark) { 2214 if (libs != NULL) 2215 libs[liberties] = checked_pos; 2216 liberties++; 2217 /* Unneeded since we're about to leave. */ 1942 2218 #if 0 1943 if (liberties >= maxlib)1944 return liberties;1945 MARK_LIBERTY(EAST(pos));2219 if (liberties >= maxlib) 2220 return liberties; 2221 MARK_LIBERTY(checked_pos); 1946 2222 #endif 2223 } 1947 2224 } 1948 else if (board[EAST(pos)] == color) { 1949 int s = string_number[EAST(pos)]; 1950 for (k = 0; k < string[s].liberties; k++) { 1951 int lib = string_libs[s].list[k]; 1952 if (UNMARKED_LIBERTY(lib)) { 2225 else if (board[checked_pos] == color) { 2226 str_nr = string_number[checked_pos]; 2227 str_libs = string[str_nr].liberties; 2228 for (k = 0; k < str_libs; k++) { 2229 checked_lib = string_libs[str_nr].list[k]; 2230 if (UNMARKED_LIBERTY(checked_lib)) { 1953 2231 if (libs != NULL) 1954 libs[liberties] = lib;2232 libs[liberties] = checked_lib; 1955 2233 liberties++; 1956 2234 if (liberties >= maxlib) 1957 2235 return liberties; 1958 MARK_LIBERTY( lib);2236 MARK_LIBERTY(checked_lib); 1959 2237 } 1960 2238 } 1961 } 2239 } 1962 2240 1963 2241 #if USE_BOARD_CACHES 1964 2242 /* If we reach here, then we have counted _all_ the liberties, so 1965 2243 * we set threshold to MAXLIBS (the result is the same regardless 1966 2244 * of `maxlib' value). 1967 2245 */ 1968 if (!libs) 1969 approxlib_cache[pos][color - 1].threshold = MAXLIBS; 2246 entry->threshold = MAXLIBS; 1970 2247 #endif 2248 1971 2249 return liberties; 1972 2250 } 1973 2251 … … 1977 2255 * strings. This is a fallback used by approxlib() when a faster 1978 2256 * algorithm can't be used. 1979 2257 */ 1980 static int 1981 slow_approxlib(int pos, int color, int maxlib, int *libs) 2258 inline static int 2259 slow_approxlib(int pos, int color, int maxlib, int *libs, 2260 struct board_cache_entry *entry) 1982 2261 { 1983 2262 int k; 1984 2263 int liberties = 0; 2264 int checked_pos, checked_pos2; 2265 int pos2, str_nr, first_stone; 1985 2266 1986 2267 liberty_mark++; 1987 2268 MARK_LIBERTY(pos); 1988 2269 string_mark++; 2270 1989 2271 for (k = 0; k < 4; k++) { 1990 int d = delta[k]; 1991 if (UNMARKED_LIBERTY(pos + d)) { 1992 if (libs) 1993 libs[liberties] = pos + d; 1994 liberties++; 1995 if (liberties == maxlib) 1996 return liberties; 1997 MARK_LIBERTY(pos + d); 1998 } 1999 else if (board[pos + d] == color 2000 && UNMARKED_STRING(pos + d)) { 2001 int s = string_number[pos + d]; 2002 int pos2; 2003 pos2 = FIRST_STONE(s); 2272 checked_pos = pos + delta[k]; 2273 if (board[checked_pos] == EMPTY) { 2274 if (ml[checked_pos] != liberty_mark) { 2275 if (libs) 2276 libs[liberties] = checked_pos; 2277 liberties++; 2278 if (liberties >= maxlib) 2279 return liberties; 2280 MARK_LIBERTY(checked_pos); 2281 } 2282 } 2283 else if (board[checked_pos] == color 2284 && UNMARKED_STRING(str_nr = string_number[checked_pos])) { 2285 first_stone = FIRST_STONE(str_nr); 2286 pos2 = first_stone; 2004 2287 do { 2005 2288 int l; 2006 2289 for (l = 0; l < 4; l++) { 2007 int d2 =delta[l];2008 if (UNMARKED_LIBERTY( pos2 + d2)) {2290 checked_pos2 = pos2 + delta[l]; 2291 if (UNMARKED_LIBERTY(checked_pos2)) { 2009 2292 if (libs) 2010 libs[liberties] = pos2 + d2;2293 libs[liberties] = checked_pos2; 2011 2294 liberties++; 2012 if (liberties == maxlib)2295 if (liberties >= maxlib) 2013 2296 return liberties; 2014 MARK_LIBERTY( pos2 + d2);2297 MARK_LIBERTY(checked_pos2); 2015 2298 } 2016 2299 } 2017 2300 2018 2301 pos2 = NEXT_STONE(pos2); 2019 } while ( !BACK_TO_FIRST_STONE(s, pos2));2020 MARK_STRING( pos + d);2302 } while (pos2 != first_stone); 2303 MARK_STRING(str_nr); 2021 2304 } 2022 2305 } 2023 2306 … … 2026 2309 * we set threshold to MAXLIBS (the result is the same regardless 2027 2310 * of `maxlib' value). 2028 2311 */ 2029 if (!libs) 2030 approxlib_cache[pos][color - 1].threshold = MAXLIBS; 2312 entry->threshold = MAXLIBS; 2031 2313 #endif 2032 2314 return liberties; 2033 2315 } 2034 2316 2035 2317 2036 /* accuratelib() cache. */2318 /* accuratelib() cache. Stores data for both colors */ 2037 2319 static struct board_cache_entry accuratelib_cache[BOARDMAX][2]; 2038 2320 2039 2321 2040 2322 /* Clears accuratelib() cache. This function should be called only once 2041 2323 * during engine initialization. Sets thresholds to zero. 2042 2324 */ 2043 void2325 inline void 2044 2326 clear_accuratelib_cache(void) 2045 2327 { 2046 int pos; 2047 2048 for (pos = BOARDMIN; pos < BOARDMAX; pos++) { 2049 accuratelib_cache[pos][0].threshold = 0; 2050 accuratelib_cache[pos][1].threshold = 0; 2051 } 2328 memset(accuratelib_cache, 0, sizeof(accuratelib_cache)); 2052 2329 } 2053 2330 2054 2331 … … 2076 2353 2077 2354 #ifdef USE_BOARD_CACHES 2078 2355 2079 struct board_cache_entry *entry = &accuratelib_cache[pos][color - 1];2356 struct board_cache_entry *entry = &accuratelib_cache[pos][color - WHITE]; 2080 2357 2081 2358 ASSERT1(board[pos] == EMPTY, pos); 2082 2359 ASSERT1(IS_STONE(color), pos); … … 2102 2379 } 2103 2380 } 2104 2381 2105 liberties = do_accuratelib(pos, color, maxlib, libs); 2106 2107 /* If accuratelib() found less than `maxlib' liberties, then its 2108 * result is certainly independent of `maxlib' and we set threshold 2109 * to MAXLIBS. 2382 /* We initialize the cache entry threshold to `maxlib'. If do_accuratelib() 2383 * finds all the liberties (that is, it doesn't use `maxlib' value for 2384 * an early return), it will set threshold to MAXLIBS itself. 2110 2385 */ 2111 entry->threshold = liberties < maxlib ? MAXLIBS : maxlib; 2386 entry->threshold = maxlib; 2387 2388 liberties = do_accuratelib(pos, color, maxlib, libs, entry); 2389 2112 2390 entry->liberties = liberties; 2113 2391 entry->position_hash = board_hash; 2114 2392 … … 2132 2410 2133 2411 2134 2412 /* Does the real work of accuratelib(). */ 2135 static int 2136 do_accuratelib(int pos, int color, int maxlib, int *libs) 2413 inline static int 2414 do_accuratelib(int pos, int color, int maxlib, int *libs, 2415 struct board_cache_entry *entry) 2137 2416 { 2138 2417 int k, l; 2139 int lib erties= 0;2418 int lib_count = 0; 2140 2419 int lib; 2141 2420 int captured[4]; 2142 2421 int captures = 0; 2422 int first_stone; 2423 int stone_pos; 2424 int checked_lib; 2143 2425 2144 2426 string_mark++; 2145 2427 liberty_mark++; 2146 2428 MARK_LIBERTY(pos); 2147 2429 2148 2430 for (k = 0; k < 4; k++) { 2149 int pos2 = pos + delta[k]; 2150 if (UNMARKED_LIBERTY(pos2)) { 2151 /* A trivial liberty */ 2152 if (libs) 2153 libs[liberties] = pos2; 2154 liberties++; 2155 if (liberties >= maxlib) 2156 return liberties; 2431 int checked_pos = pos + delta[k]; 2432 if (board[checked_pos] == EMPTY) { 2433 if (ml[checked_pos] != liberty_mark) { 2434 /* A trivial liberty */ 2435 if (libs) 2436 libs[lib_count] = checked_pos; 2437 lib_count++; 2438 if (lib_count >= maxlib) 2439 return lib_count; 2157 2440 2158 MARK_LIBERTY(pos2); 2159 } 2160 else if (UNMARKED_COLOR_STRING(pos2, color)) { 2161 /* An own neighbor string */ 2162 struct string_data *s = &string[string_number[pos2]]; 2163 struct string_liberties_data *sl = &string_libs[string_number[pos2]]; 2164 2165 if (s->liberties <= MAX_LIBERTIES || maxlib <= MAX_LIBERTIES - 1) { 2166 /* The easy case - we already have all (necessary) liberties of 2167 * the string listed 2168 */ 2169 for (l = 0; l < s->liberties; l++) { 2170 lib = sl->list[l]; 2171 if (UNMARKED_LIBERTY(lib)) { 2172 if (libs) 2173 libs[liberties] = lib; 2174 liberties++; 2175 if (liberties >= maxlib) 2176 return liberties; 2177 2178 MARK_LIBERTY(lib); 2179 } 2180 } 2441 MARK_LIBERTY(checked_pos); 2181 2442 } 2182 else { 2183 /* The harder case - we need to find all the liberties of the 2184 * string by traversing its stones. We stop as soon as we have 2185 * traversed all the stones or have reached maxlib. Unfortunately, 2186 * we cannot use the trick from findlib() since some of the 2187 * liberties may already have been marked. 2188 */ 2189 int stone = pos2; 2190 do { 2191 if (UNMARKED_LIBERTY(SOUTH(stone))) { 2192 if (libs) 2193 libs[liberties] = SOUTH(stone); 2194 liberties++; 2195 if (liberties >= maxlib) 2196 return liberties; 2197 2198 MARK_LIBERTY(SOUTH(stone)); 2199 } 2200 2201 if (UNMARKED_LIBERTY(WEST(stone))) { 2202 if (libs) 2203 libs[liberties] = WEST(stone); 2204 liberties++; 2205 if (liberties >= maxlib) 2206 return liberties; 2207 2208 MARK_LIBERTY(WEST(stone)); 2209 } 2210 2211 if (UNMARKED_LIBERTY(NORTH(stone))) { 2212 if (libs) 2213 libs[liberties] = NORTH(stone); 2214 liberties++; 2215 if (liberties >= maxlib) 2216 return liberties; 2217 2218 MARK_LIBERTY(NORTH(stone)); 2219 } 2220 2221 if (UNMARKED_LIBERTY(EAST(stone))) { 2222 if (libs) 2223 libs[liberties] = EAST(stone); 2224 liberties++; 2225 if (liberties >= maxlib) 2226 return liberties; 2443 } 2444 else if (board[checked_pos] == color) { 2445 int neighbor_nr = string_number[checked_pos]; 2446 if (UNMARKED_STRING(neighbor_nr)) { 2447 /* An own neighbor string */ 2448 int liberties = string[neighbor_nr].liberties; 2449 2450 if (liberties <= MAX_LIBERTIES || maxlib <= MAX_LIBERTIES - 1) { 2451 /* The easy case - we already have all (necessary) liberties of 2452 * the string listed 2453 */ 2454 struct string_liberties_data *sl = string_libs + neighbor_nr; 2455 for (l = 0; l < liberties; l++) { 2456 lib = sl->list[l]; 2457 if (UNMARKED_LIBERTY(lib)) { 2458 if (libs) 2459 libs[lib_count] = lib; 2460 lib_count++; 2461 if (lib_count >= maxlib) 2462 return lib_count; 2227 2463 2228 MARK_LIBERTY(EAST(stone)); 2464 MARK_LIBERTY(lib); 2465 } 2229 2466 } 2467 } 2468 else { 2469 /* The harder case - we need to find all the liberties of the 2470 * string by traversing its stones. We stop as soon as we have 2471 * traversed all the stones or have reached maxlib. 2472 */ 2473 stone_pos = checked_pos; 2474 do { 2475 checked_lib = SOUTH(stone_pos); 2476 if (UNMARKED_LIBERTY(checked_lib)) { 2477 if (libs) 2478 libs[lib_count] = checked_lib; 2479 lib_count++; 2480 if (lib_count >= maxlib) 2481 return lib_count; 2482 2483 MARK_LIBERTY(checked_lib); 2484 } 2485 2486 checked_lib = WEST(stone_pos); 2487 if (UNMARKED_LIBERTY(checked_lib)) { 2488 if (libs) 2489 libs[lib_count] = checked_lib; 2490 lib_count++; 2491 if (lib_count >= maxlib) 2492 return lib_count; 2493 2494 MARK_LIBERTY(checked_lib); 2495 } 2496 2497 checked_lib = NORTH(stone_pos); 2498 if (UNMARKED_LIBERTY(checked_lib)) { 2499 if (libs) 2500 libs[lib_count] = checked_lib; 2501 lib_count++; 2502 if (lib_count >= maxlib) 2503 return lib_count; 2504 2505 MARK_LIBERTY(checked_lib); 2506 } 2507 2508 checked_lib = EAST(stone_pos); 2509 if (UNMARKED_LIBERTY(checked_lib)) { 2510 if (libs) 2511 libs[lib_count] = checked_lib; 2512 lib_count++; 2513 if (lib_count >= maxlib) 2514 return lib_count; 2515 2516 MARK_LIBERTY(checked_lib); 2517 } 2518 2519 stone_pos = NEXT_STONE(stone_pos); 2520 } while (stone_pos != checked_pos); 2521 } 2230 2522 2231 stone = NEXT_STONE(stone); 2232 } while (stone != pos2); 2523 MARK_STRING(neighbor_nr); 2233 2524 } 2234 2235 MARK_STRING(pos2);2236 2525 } 2237 else if (board[ pos2] == OTHER_COLOR(color)2238 && string[string_number[pos2]].liberties == 1) {2526 else if (board[checked_pos] == OTHER_COLOR(color) 2527 && string[string_number[checked_pos]].liberties == 1) { 2239 2528 /* A capture. */ 2240 captured[captures++] = pos2;2529 captured[captures++] = checked_pos; 2241 2530 } 2242 2531 } 2243 2532 2244 2533 /* Now we look at all the captures found in the previous step */ 2245 2534 for (k = 0; k < captures; k++) { 2246 lib = captured[k]; 2535 int capture_nr; 2536 first_stone = captured[k]; 2247 2537 2248 2538 /* Add the stone adjacent to (pos) to the list of liberties if 2249 2539 * it is not also adjacent to an own marked string (otherwise, 2250 2540 * it will be added later). 2251 2541 */ 2252 if (!MARKED_COLOR_STRING(SOUTH( lib), color)2253 && !MARKED_COLOR_STRING(WEST( lib), color)2254 && !MARKED_COLOR_STRING(NORTH( lib), color)2255 && !MARKED_COLOR_STRING(EAST( lib), color)) {2542 if (!MARKED_COLOR_STRING(SOUTH(first_stone), color) 2543 && !MARKED_COLOR_STRING(WEST(first_stone), color) 2544 && !MARKED_COLOR_STRING(NORTH(first_stone), color) 2545 && !MARKED_COLOR_STRING(EAST(first_stone), color)) { 2256 2546 if (libs) 2257 libs[liberties] = lib; 2258 liberties++; 2259 if (liberties >= maxlib) 2260 return liberties; 2547 libs[lib_count] = first_stone; 2548 lib_count++; 2549 if (lib_count >= maxlib) 2550 return lib_count; 2551 stone_pos = NEXT_STONE(first_stone); 2552 if (stone_pos == first_stone) 2553 continue; 2261 2554 } 2555 else 2556 stone_pos = first_stone; 2262 2557 2263 2558 /* Check if we already know of this capture. */ 2559 capture_nr = string_number[stone_pos]; 2264 2560 for (l = 0; l < k; l++) 2265 if (string_number[captured[l]] == string_number[lib])2561 if (string_number[captured[l]] == capture_nr) 2266 2562 break; 2267 2563 2268 2564 if (l == k) { … … 2271 2567 * marked string. 2272 2568 */ 2273 2569 do { 2274 if (MARKED_COLOR_STRING(SOUTH( lib), color)2275 || MARKED_COLOR_STRING(WEST( lib), color)2276 || MARKED_COLOR_STRING(NORTH( lib), color)2277 || MARKED_COLOR_STRING(EAST( lib), color)) {2570 if (MARKED_COLOR_STRING(SOUTH(stone_pos), color) 2571 || MARKED_COLOR_STRING(WEST(stone_pos), color) 2572 || MARKED_COLOR_STRING(NORTH(stone_pos), color) 2573 || MARKED_COLOR_STRING(EAST(stone_pos), color)) { 2278 2574 if (libs) 2279 libs[lib erties] = lib;2280 lib erties++;2281 if (lib erties>= maxlib)2282 return lib erties;2575 libs[lib_count] = stone_pos; 2576 lib_count++; 2577 if (lib_count >= maxlib) 2578 return lib_count; 2283 2579 } 2284 2580 2285 lib = NEXT_STONE(lib);2286 } while ( lib != captured[k]);2581 stone_pos = NEXT_STONE(stone_pos); 2582 } while (stone_pos != first_stone); 2287 2583 } 2288 2584 } 2289 2585 2290 return liberties; 2291 } 2586 #if USE_BOARD_CACHES 2587 /* If we reach here, then we have counted _all_ the liberties, so 2588 * we set threshold to MAXLIBS (the result is the same regardless 2589 * of `maxlib' value). 2590 */ 2591 entry->threshold = MAXLIBS; 2592 #endif 2292 2593 2594 return lib_count; 2595 } 2293 2596 2294 /* Find the number of common liberties of the two strings at str1 and str2. 2597 /* Find the number of common liberties of the two strings at 2598 * str1_pos and str2_pos. 2295 2599 */ 2296 2600 2297 2601 int 2298 count_common_libs(int str1 , int str2)2602 count_common_libs(int str1_pos, int str2_pos) 2299 2603 { 2300 2604 int all_libs1[MAXLIBS], *libs1; 2301 2605 int liberties1, liberties2; 2606 int str1_nr, str2_nr; 2302 2607 int commonlibs = 0; 2303 int k, n, tmp; 2304 2305 ASSERT_ON_BOARD1(str1); 2306 ASSERT_ON_BOARD1(str2); 2307 ASSERT1(IS_STONE(board[str1]), str1); 2308 ASSERT1(IS_STONE(board[str2]), str2); 2309 2310 n = string_number[str1]; 2311 liberties1 = string[n].liberties; 2312 2313 if (liberties1 > string[string_number[str2]].liberties) { 2314 n = string_number[str2]; 2315 liberties1 = string[n].liberties; 2316 tmp = str1; 2317 str1 = str2; 2318 str2 = tmp; 2608 int k; 2609 int color; 2610 2611 ASSERT_ON_BOARD1(str1_pos); 2612 ASSERT_ON_BOARD1(str2_pos); 2613 ASSERT1(IS_STONE(board[str1_pos]), str1_pos); 2614 ASSERT1(IS_STONE(board[str2_pos]), str2_pos); 2615 2616 str1_nr = string_number[str1_pos]; 2617 str2_nr = string_number[str2_pos]; 2618 liberties1 = string[str1_nr].liberties; 2619 liberties2 = string[str2_nr].liberties; 2620 2621 if (liberties1 > liberties2) { 2622 int tmp; 2623 tmp = liberties1; 2624 liberties1 = liberties2; 2625 liberties2 = tmp; 2626 tmp = str1_nr; 2627 str1_nr = str2_nr; 2628 str2_nr = tmp; 2319 2629 } 2320 2630 2321 2631 if (liberties1 <= MAX_LIBERTIES) { 2322 2632 /* Speed optimization: don't copy liberties with findlib */ 2323 libs1 = string_libs[n].list; 2324 n = string_number[str2]; 2325 liberties2 = string[n].liberties; 2633 libs1 = string_libs[str1_nr].list; 2326 2634 2327 2635 if (liberties2 <= MAX_LIBERTIES) { 2328 2636 /* Speed optimization: NEIGHBOR_OF_STRING is quite expensive */ … … 2331 2639 for (k = 0; k < liberties1; k++) 2332 2640 MARK_LIBERTY(libs1[k]); 2333 2641 2334 libs1 = string_libs[ n].list;2642 libs1 = string_libs[str2_nr].list; 2335 2643 for (k = 0; k < liberties2; k++) 2336 if ( !UNMARKED_LIBERTY(libs1[k]))2644 if (ml[libs1[k]] == liberty_mark) 2337 2645 commonlibs++; 2338 2646 2339 2647 return commonlibs; 2340 2648 } 2341 2649 } 2342 2650 else { 2343 findlib(str1 , MAXLIBS, all_libs1);2651 findlib(str1_pos, MAXLIBS, all_libs1); 2344 2652 libs1 = all_libs1; 2345 2653 } 2346 2654 2655 color = string[str2_nr].color; 2347 2656 for (k = 0; k < liberties1; k++) 2348 if (NEIGHBOR_OF_STRING(libs1[k], str ing_number[str2], board[str2]))2657 if (NEIGHBOR_OF_STRING(libs1[k], str2_nr, color)) 2349 2658 commonlibs++; 2350 2659 2351 2660 return commonlibs; 2352 2661 } 2353 2662 2354 2355 /* Find the common liberties of the two strings at str1 and str2. The 2356 * locations of up to maxlib common liberties are written into libs[]. 2357 * The full number of common liberties is returned. 2663 /* Find the common liberties of the two strings at str1_pos and 2664 * str2_pos. The locations of up to maxlib common liberties are 2665 * written into libs[]. The full number of common liberties is returned. 2358 2666 * 2359 2667 * If you want the locations of all common liberties, whatever their 2360 2668 * number, you should pass MAXLIBS as the value for maxlib and … … 2362 2670 */ 2363 2671 2364 2672 int 2365 find_common_libs(int str1 , int str2, int maxlib, int *libs)2673 find_common_libs(int str1_pos, int str2_pos, int maxlib, int *libs) 2366 2674 { 2367 2675 int all_libs1[MAXLIBS], *libs1; 2368 2676 int liberties1, liberties2; 2677 int str1_nr, str2_nr; 2369 2678 int commonlibs = 0; 2370 int k, n, tmp; 2371 2372 ASSERT_ON_BOARD1(str1); 2373 ASSERT_ON_BOARD1(str2); 2374 ASSERT1(IS_STONE(board[str1]), str1); 2375 ASSERT1(IS_STONE(board[str2]), str2); 2376 ASSERT1(libs != NULL, str1); 2377 2378 n = string_number[str1]; 2379 liberties1 = string[n].liberties; 2380 2381 if (liberties1 > string[string_number[str2]].liberties) { 2382 n = string_number[str2]; 2383 liberties1 = string[n].liberties; 2384 tmp = str1; 2385 str1 = str2; 2386 str2 = tmp; 2679 int k; 2680 int color; 2681 2682 ASSERT_ON_BOARD1(str1_pos); 2683 ASSERT_ON_BOARD1(str2_pos); 2684 ASSERT1(IS_STONE(board[str1_pos]), str1_pos); 2685 ASSERT1(IS_STONE(board[str2_pos]), str2_pos); 2686 ASSERT1(libs != NULL, str1_pos); 2687 2688 str1_nr = string_number[str1_pos]; 2689 str2_nr = string_number[str2_pos]; 2690 liberties1 = string[str1_nr].liberties; 2691 liberties2 = string[str2_nr].liberties; 2692 2693 if (liberties1 > liberties2) { 2694 int tmp; 2695 tmp = liberties1; 2696 liberties1 = liberties2; 2697 liberties2 = tmp; 2698 tmp = str1_nr; 2699 str1_nr = str2_nr; 2700 str2_nr = tmp; 2387 2701 } 2388 2702 2389 2703 if (liberties1 <= MAX_LIBERTIES) { 2390 2704 /* Speed optimization: don't copy liberties with findlib */ 2391 libs1 = string_libs[n].list; 2392 n = string_number[str2]; 2393 liberties2 = string[n].liberties; 2705 libs1 = string_libs[str1_nr].list; 2394 2706 2395 2707 if (liberties2 <= MAX_LIBERTIES) { 2396 2708 /* Speed optimization: NEIGHBOR_OF_STRING is quite expensive */ … … 2399 2711 for (k = 0; k < liberties1; k++) 2400 2712 MARK_LIBERTY(libs1[k]); 2401 2713 2402 libs1 = string_libs[ n].list;2714 libs1 = string_libs[str2_nr].list; 2403 2715 for (k = 0; k < liberties2; k++) 2404 if ( !UNMARKED_LIBERTY(libs1[k])) {2716 if (ml[libs1[k]] == liberty_mark) { 2405 2717 if (commonlibs < maxlib) 2406 2718 libs[commonlibs] = libs1[k]; 2407 2719 commonlibs++; … … 2411 2723 } 2412 2724 } 2413 2725 else { 2414 findlib(str1 , MAXLIBS, all_libs1);2726 findlib(str1_pos, MAXLIBS, all_libs1); 2415 2727 libs1 = all_libs1; 2416 2728 } 2417 2729 2730 color = string[str2_nr].color; 2418 2731 for (k = 0; k < liberties1; k++) 2419 if (NEIGHBOR_OF_STRING(libs1[k], str ing_number[str2], board[str2])) {2732 if (NEIGHBOR_OF_STRING(libs1[k], str2_nr, color)) { 2420 2733 if (commonlibs < maxlib) 2421 2734 libs[commonlibs] = libs1[k]; 2422 2735 commonlibs++; … … 2430 2743 * If they do and lib != NULL, one common liberty is returned in *lib. 2431 2744 */ 2432 2745 int 2433 have_common_lib(int str1 , int str2, int *lib)2746 have_common_lib(int str1_pos, int str2_pos, int *lib) 2434 2747 { 2435 2748 int all_libs1[MAXLIBS], *libs1; 2436 int liberties1; 2437 int k, n, tmp; 2438 2439 ASSERT_ON_BOARD1(str1); 2440 ASSERT_ON_BOARD1(str2); 2441 ASSERT1(IS_STONE(board[str1]), str1); 2442 ASSERT1(IS_STONE(board[str2]), str2); 2443 2444 n = string_number[str1]; 2445 liberties1 = string[n].liberties; 2446 2447 if (liberties1 > string[string_number[str2]].liberties) { 2448 n = string_number[str2]; 2449 liberties1 = string[n].liberties; 2450 tmp = str1; 2451 str1 = str2; 2452 str2 = tmp; 2749 int liberties1, liberties2; 2750 int str1_nr, str2_nr; 2751 int k; 2752 int color; 2753 2754 ASSERT_ON_BOARD1(str1_pos); 2755 ASSERT_ON_BOARD1(str2_pos); 2756 ASSERT1(IS_STONE(board[str1_pos]), str1_pos); 2757 ASSERT1(IS_STONE(board[str2_pos]), str2_pos); 2758 2759 str1_nr = string_number[str1_pos]; 2760 str2_nr = string_number[str2_pos]; 2761 liberties1 = string[str1_nr].liberties; 2762 liberties2 = string[str2_nr].liberties; 2763 2764 if (liberties1 > liberties2) { 2765 int tmp; 2766 tmp = liberties1; 2767 liberties1 = liberties2; 2768 liberties2 = tmp; 2769 tmp = str1_nr; 2770 str1_nr = str2_nr; 2771 str2_nr = tmp; 2453 2772 } 2454 2773 2455 2774 if (liberties1 <= MAX_LIBERTIES) 2456 2775 /* Speed optimization: don't copy liberties with findlib */ 2457 libs1 = string_libs[ n].list;2776 libs1 = string_libs[str1_nr].list; 2458 2777 else { 2459 findlib(str1 , MAXLIBS, all_libs1);2778 findlib(str1_pos, MAXLIBS, all_libs1); 2460 2779 libs1 = all_libs1; 2461 2780 } 2462 2781 2782 color = string[str2_nr].color; 2463 2783 for (k = 0; k < liberties1; k++) { 2464 if (NEIGHBOR_OF_STRING(libs1[k], str ing_number[str2], board[str2])) {2784 if (NEIGHBOR_OF_STRING(libs1[k], str2_nr, color)) { 2465 2785 if (lib) 2466 2786 *lib = libs1[k]; 2467 2787 return 1; … … 2477 2797 * Report the number of stones in a string. 2478 2798 */ 2479 2799 2480 in t2481 countstones(int str )2800 inline int 2801 countstones(int str_pos) 2482 2802 { 2483 ASSERT_ON_BOARD1(str );2484 ASSERT1(IS_STONE(board[str ]), str);2803 ASSERT_ON_BOARD1(str_pos); 2804 ASSERT1(IS_STONE(board[str_pos]), str_pos); 2485 2805 2486 return COUNTSTONES(str );2806 return COUNTSTONES(string_number[str_pos]); 2487 2807 } 2488 2808 2489 2809 2490 /* Find the stones of the string at str . strmust not be2810 /* Find the stones of the string at str_pos. str_pos must not be 2491 2811 * empty. The locations of up to maxstones stones are written into 2492 2812 * stones[]. The full number of stones is returned. 2493 2813 */ 2494 2814 2495 2815 int 2496 findstones(int str , int maxstones, int *stones)2816 findstones(int str_pos, int maxstones, int *stones) 2497 2817 { 2498 int s ;2818 int str_nr; 2499 2819 int size; 2500 2820 int pos; 2501 2821 int k; 2502 2503 ASSERT_ON_BOARD1(str); 2504 ASSERT1(IS_STONE(board[str]), str); 2822 int limit; 2823 2824 ASSERT_ON_BOARD1(str_pos); 2825 ASSERT1(IS_STONE(board[str_pos]), str_pos); 2505 2826 2506 s = string_number[str];2507 size = string[s ].size;2827 str_nr = string_number[str_pos]; 2828 size = string[str_nr].size; 2508 2829 2509 2830 /* Traverse the stones of the string, by following the cyclic chain. */ 2510 pos = FIRST_STONE(s); 2511 for (k = 0; k < maxstones && k < size; k++) { 2831 pos = FIRST_STONE(str_nr); 2832 limit = maxstones > size ? size : maxstones; 2833 for (k = 0; k < limit; k++) { 2512 2834 stones[k] = pos; 2513 2835 pos = NEXT_STONE(pos); 2514 2836 } … … 2517 2839 } 2518 2840 2519 2841 2520 /* Counts how many stones in str1 are directly adjacent to str2.2521 * A limit can be given in the maxstones parameter so that the2522 * function returns immediately. See fast_defense() in reading.c2842 /* Counts how many stones in one string are directly adjacent to 2843 * the second string. A limit can be given in the maxstones parameter 2844 * so that the function returns immediately. 2523 2845 */ 2524 2846 2525 2847 int 2526 count_adjacent_stones(int str1 , int str2, int maxstones)2848 count_adjacent_stones(int str1_pos, int str2_pos, int maxstones) 2527 2849 { 2528 int s 1, s2;2850 int str1_nr, str2_nr; 2529 2851 int size; 2530 2852 int pos; 2531 2853 int k; 2532 2854 int count = 0; 2855 int color2; 2533 2856 2534 ASSERT_ON_BOARD1(str1 );2535 ASSERT1(IS_STONE(board[str1 ]), str1);2536 ASSERT_ON_BOARD1(str2 );2537 ASSERT1(IS_STONE(board[str2 ]), str2);2538 2539 s 1 = string_number[str1];2540 s 2 = string_number[str2];2541 size = string[s 1].size;2857 ASSERT_ON_BOARD1(str1_pos); 2858 ASSERT1(IS_STONE(board[str1_pos]), str1_pos); 2859 ASSERT_ON_BOARD1(str2_pos); 2860 ASSERT1(IS_STONE(board[str2_pos]), str2_pos); 2861 2862 str1_nr = string_number[str1_pos]; 2863 str2_nr = string_number[str2_pos]; 2864 size = string[str1_nr].size; 2542 2865 2543 2866 /* Traverse the stones of the string, by following the cyclic chain. */ 2544 pos = FIRST_STONE(s1); 2545 for (k = 0; k < size && count < maxstones; k++) { 2546 if (NEIGHBOR_OF_STRING(pos, s2, board[str2])) 2867 color2 = board[str2_pos]; 2868 pos = FIRST_STONE(str1_nr); 2869 for (k = 0; k < size; k++) { 2870 if (NEIGHBOR_OF_STRING(pos, str2_nr, color2)) { 2547 2871 count++; 2872 if (count >= maxstones) 2873 return count; 2874 } 2548 2875 pos = NEXT_STONE(pos); 2549 2876 } 2550 2877 … … 2553 2880 2554 2881 2555 2882 /* chainlinks returns (in the (adj) array) the chains surrounding 2556 * the string at (str ). The number of chains is returned.2883 * the string at (str_pos). The number of chains is returned. 2557 2884 */ 2558 2885 2559 2886 int 2560 chainlinks(int str , int adj[MAXCHAIN])2887 chainlinks(int str_pos, int adj[MAXCHAIN]) 2561 2888 { 2562 struct string_data *s;2563 2889 struct string_neighbors_data *sn; 2564 2890 int k; 2891 int neighbors; 2565 2892 2566 ASSERT1(IS_STONE(board[str ]), str);2893 ASSERT1(IS_STONE(board[str_pos]), str_pos); 2567 2894 2568 2895 /* We already have the list ready, just copy it and fill in the 2569 2896 * desired information. 2570 2897 */ 2571 s = &string[string_number[str]];2572 sn = &string_neighbors[string_number[str]];2573 for (k = 0; k < s->neighbors; k++)2898 neighbors = string[string_number[str_pos]].neighbors; 2899 sn = string_neighbors + string_number[str_pos]; 2900 for (k = 0; k < neighbors; k++) 2574 2901 adj[k] = string[sn->list[k]].origin; 2575 2902 2576 return s->neighbors;2903 return neighbors; 2577 2904 } 2578 2905 2579 2906 2580 2907 /* chainlinks2 returns (in adj array) those chains surrounding 2581 * the string at str which have exactly lib liberties. The number2582 * of such chains is returned.2908 * the string at str_pos which have exactly lib liberties. 2909 * The number of such chains is returned. 2583 2910 */ 2584 2911 2585 2912 int 2586 chainlinks2(int str , int adj[MAXCHAIN], int lib)2913 chainlinks2(int str_pos, int adj[MAXCHAIN], int lib) 2587 2914 { 2588 struct string_data *s, *t;2589 2915 struct string_neighbors_data *sn; 2590 2916 int k; 2591 int neighbors ;2917 int neighbors, max_neighbors; 2592 2918 2593 ASSERT1(IS_STONE(board[str ]), str);2919 ASSERT1(IS_STONE(board[str_pos]), str_pos); 2594 2920 2595 2921 /* We already have the list ready, just copy the strings with the 2596 2922 * right number of liberties. 2597 2923 */ 2598 2924 neighbors = 0; 2599 s = &string[string_number[str]]; 2600 sn = &string_neighbors[string_number[str]]; 2601 for (k = 0; k < s->neighbors; k++) { 2602 t = &string[sn->list[k]]; 2603 if (t->liberties == lib) 2604 adj[neighbors++] = t->origin; 2925 max_neighbors = string[string_number[str_pos]].neighbors; 2926 sn = string_neighbors + string_number[str_pos]; 2927 for (k = 0; k < max_neighbors; k++) { 2928 if (string[sn->list[k]].liberties == lib) 2929 adj[neighbors++] = string[sn->list[k]].origin; 2605 2930 } 2606 2931 return neighbors; 2607 2932 } 2608 2933 2609 2934 2610 2935 /* chainlinks3 returns (in adj array) those chains surrounding 2611 * the string at str , which have less or equal lib liberties.2936 * the string at str_pos, which have less or equal lib liberties. 2612 2937 * The number of such chains is returned. 2613 2938 */ 2614 2939 2615 2940 int 2616 chainlinks3(int str , int adj[MAXCHAIN], int lib)2941 chainlinks3(int str_pos, int adj[MAXCHAIN], int lib) 2617 2942 { 2618 struct string_data *s, *t;2619 2943 struct string_neighbors_data *sn; 2620 2944 int k; 2621 int neighbors ;2945 int neighbors, max_neighbors; 2622 2946 2623 ASSERT1(IS_STONE(board[str ]), str);2947 ASSERT1(IS_STONE(board[str_pos]), str_pos); 2624 2948 2625 2949 /* We already have the list ready, just copy the strings with the 2626 2950 * right number of liberties. 2627 2951 */ 2628 2952 neighbors = 0; 2629 s = &string[string_number[str]]; 2630 sn = &string_neighbors[string_number[str]]; 2631 for (k = 0; k < s->neighbors; k++) { 2632 t = &string[sn->list[k]]; 2633 if (t->liberties <= lib) 2634 adj[neighbors++] = t->origin; 2953 max_neighbors = string[string_number[str_pos]].neighbors; 2954 sn = string_neighbors + string_number[str_pos]; 2955 for (k = 0; k < max_neighbors; k++) { 2956 if (string[sn->list[k]].liberties <= lib) 2957 adj[neighbors++] = string[sn->list[k]].origin; 2635 2958 } 2636 2959 return neighbors; 2637 2960 } 2638 2961 2639 2962 2640 2963 /* extended_chainlinks() returns (in the (adj) array) the opponent 2641 * strings being directly adjacent to (str) or having a common liberty 2642 * with (str). The number of such strings is returned. 2964 * strings being directly adjacent to string at (str_pos) or having 2965 * a common liberty with that string. The number of such strings is 2966 * returned. 2643 2967 * 2644 2968 * If the both_colors parameter is true, also own strings sharing a 2645 2969 * liberty are returned. 2646 2970 */ 2647 2971 2648 2972 int 2649 extended_chainlinks(int str , int adj[MAXCHAIN], int both_colors)2973 extended_chainlinks(int str_pos, int adj[MAXCHAIN], int both_colors) 2650 2974 { 2651 struct string_data *s;2652 2975 struct string_neighbors_data *sn; 2653 2976 int n; 2654 int k;2655 2977 int r; 2656 2978 int libs[MAXLIBS]; 2657 2979 int liberties; 2980 int checked_pos; 2981 int color; 2982 int other; 2983 int neighbors; 2984 int str_nr; 2658 2985 2659 ASSERT1(IS_STONE(board[str]), str); 2986 ASSERT1(IS_STONE(board[str_pos]), str_pos); 2987 2988 str_nr = string_number[str_pos]; 2989 color = string[str_nr].color; 2990 other = OTHER_COLOR(color); 2991 sn = string_neighbors + str_nr; 2992 string_mark++; 2660 2993 2661 2994 /* We already have the list of directly adjacent strings ready, just 2662 * copy it and mark the strings. 2995 * copy it and mark the strings. We also mark ourselves in case 2996 * both_colors is true. 2663 2997 */ 2664 s = &string[string_number[str]];2665 sn = &string_neighbors[string_number[str]]; 2666 string_mark++;2667 for (n = 0; n < s->neighbors; n++) {2998 MARK_STRING(str_nr); 2999 3000 neighbors = string[str_nr].neighbors; 3001 for (n = 0; n < neighbors; n++) { 2668 3002 adj[n] = string[sn->list[n]].origin; 2669 MARK_STRING( adj[n]);3003 MARK_STRING(sn->list[n]); 2670 3004 } 2671 3005 2672 3006 /* Get the liberties. */ 2673 liberties = findlib(str , MAXLIBS, libs);3007 liberties = findlib(str_pos, MAXLIBS, libs); 2674 3008 2675 /* Look for unmarked opponentstrings next to a liberty and add the3009 /* Look for unmarked strings next to a liberty and add the 2676 3010 * ones which are found to the output. 2677 3011 */ 2678 3012 for (r = 0; r < liberties; r++) { 2679 for (k = 0; k < 4; k++) { 2680 if ((board[libs[r] + delta[k]] == OTHER_COLOR(board[str]) 2681 || (both_colors && board[libs[r] + delta[k]] == board[str])) 2682 && UNMARKED_STRING(libs[r] + delta[k])) { 2683 adj[n] = string[string_number[libs[r] + delta[k]]].origin; 2684 MARK_STRING(adj[n]); 2685 n++; 3013 checked_pos = SOUTH(libs[r]); 3014 if (board[checked_pos] == other 3015 || (both_colors && board[checked_pos] == color)) { 3016 str_nr = string_number[checked_pos]; 3017 if (UNMARKED_STRING(str_nr)) { 3018 MARK_STRING(str_nr); 3019 adj[n++] = string[str_nr].origin; 3020 } 3021 } 3022 3023 checked_pos = WEST(libs[r]); 3024 if (board[checked_pos] == other 3025 || (both_colors && board[checked_pos] == color)) { 3026 str_nr = string_number[checked_pos]; 3027 if (UNMARKED_STRING(str_nr)) { 3028 MARK_STRING(str_nr); 3029 adj[n++] = string[str_nr].origin; 3030 } 3031 } 3032 3033 checked_pos = NORTH(libs[r]); 3034 &n
