Ticket #148: changes.diff
| File changes.diff, 142.0 kB (added by draqo, 20 months 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 }
