Ticket #150: gunnar_7_12.14.diff
| File gunnar_7_12.14.diff, 81.4 kB (added by gunnar, 6 months ago) |
|---|
-
patterns/patterns.h
293 293 }; 294 294 295 295 296 /* Monte Carlo local patterns. */ 297 struct mc_pattern_database { 298 const char *name; 299 const unsigned int *values; 300 }; 296 301 297 302 298 303 /* helper functions */ … … 352 357 extern struct fullboard_pattern fuseki13[]; 353 358 extern struct fullboard_pattern fuseki9[]; 354 359 360 extern struct mc_pattern_database mc_pattern_databases[]; 361 355 362 struct corner_db; 356 363 struct corner_variation; 357 364 struct corner_pattern; -
patterns/Makefile.am
1 noinst_PROGRAMS = mkpat joseki mkeyes uncompress_fuseki 1 noinst_PROGRAMS = mkpat joseki mkeyes uncompress_fuseki mkmcpat 2 2 EXTRA_PROGRAMS = extract_fuseki compress_fuseki 3 3 4 4 DSP = dfa.dsp patterns.dsp joseki.dsp mkeyes.dsp mkpat.dsp fuseki.dsp … … 51 51 joseki_AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/sgf 52 52 mkeyes_SOURCES = mkeyes.c 53 53 mkeyes_LDADD = ../utils/libutils.a 54 mkmcpat_SOURCES = mkmcpat.c 55 mkmcpat_LDADD = ../engine/libengine.a ../sgf/libsgf.a ../utils/libutils.a 56 mkmcpat_AM_CPPFLAGS = $(GNU_GO_WARNINGS) 54 57 extract_fuseki_SOURCES = extract_fuseki.c 55 58 # Yes, we currently need duplicate libengine.a and libpatterns.a. 56 59 extract_fuseki_LDADD = ../engine/libengine.a libpatterns.a\ … … 69 72 owl_attackpat.c\ 70 73 owl_vital_apat.c owl_defendpat.c fusekipat.c\ 71 74 fuseki9.c fuseki13.c fuseki19.c josekidb.c\ 72 handipat.c oraclepat.c 75 handipat.c oraclepat.c mcpat.c 73 76 74 77 DBBUILT = gogo.db hoshi_keima.db hoshi_other.db komoku.db sansan.db \ 75 78 mokuhazushi.db takamoku.db … … 77 80 DBBUILT_INPUT = -i gogo.db -i hoshi_keima.db -i hoshi_other.db -i komoku.db \ 78 81 -i sansan.db -i mokuhazushi.db -i takamoku.db 79 82 83 MC_DB = $(srcdir)/mc_montegnu_classic.db $(srcdir)/mc_mogo_classic.db \ 84 $(srcdir)/mc_uniform.db 85 80 86 DB_TO_TAG = aa_attackpats.db attack.db barriers.db conn.db defense.db\ 81 87 endgame.db eyes.db fuseki.db fuseki9.dbz fuseki13.dbz fuseki19.dbz\ 82 88 handicap.db influence.db oracle.db owl_attackpats.db\ … … 183 189 handipat.c : $(srcdir)/handicap.db mkpat$(EXEEXT) 184 190 ./mkpat -b handipat -i $(srcdir)/handicap.db -o handipat.c 185 191 192 mcpat.c : $(MC_DB) mkmcpat$(EXEEXT) 193 ./mkmcpat $(MC_DB) > mcpat.c 186 194 195 187 196 ETAGS_ARGS = --language none --regex '/^Pattern[ \t]+[a-zA-Z0-9]+/' $(DB_TO_TAG)\ 188 197 --language auto --no-regex 189 198 TAGS_DEPENDENCIES = $(DB_TO_TAG) -
patterns/Makefile.in
1 # Makefile.in generated by automake 1.9. 5from Makefile.am.1 # Makefile.in generated by automake 1.9.6 from Makefile.am. 2 2 # @configure_input@ 3 3 4 4 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, … … 16 16 17 17 18 18 19 SOURCES = $(libpatterns_a_SOURCES) $(compress_fuseki_SOURCES) $(extract_fuseki_SOURCES) $(joseki_SOURCES) $(mkeyes_SOURCES) $(mkpat_SOURCES) $(uncompress_fuseki_SOURCES)20 21 19 srcdir = @srcdir@ 22 20 top_srcdir = @top_srcdir@ 23 21 VPATH = @srcdir@ … … 39 37 PRE_UNINSTALL = : 40 38 POST_UNINSTALL = : 41 39 noinst_PROGRAMS = mkpat$(EXEEXT) joseki$(EXEEXT) mkeyes$(EXEEXT) \ 42 uncompress_fuseki$(EXEEXT) 40 uncompress_fuseki$(EXEEXT) mkmcpat$(EXEEXT) 43 41 EXTRA_PROGRAMS = extract_fuseki$(EXEEXT) compress_fuseki$(EXEEXT) 44 42 subdir = patterns 45 43 DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ … … 62 60 owl_attackpat.$(OBJEXT) owl_vital_apat.$(OBJEXT) \ 63 61 owl_defendpat.$(OBJEXT) fusekipat.$(OBJEXT) fuseki9.$(OBJEXT) \ 64 62 fuseki13.$(OBJEXT) fuseki19.$(OBJEXT) josekidb.$(OBJEXT) \ 65 handipat.$(OBJEXT) oraclepat.$(OBJEXT) 63 handipat.$(OBJEXT) oraclepat.$(OBJEXT) mcpat.$(OBJEXT) 66 64 am_libpatterns_a_OBJECTS = connections.$(OBJEXT) helpers.$(OBJEXT) \ 67 65 transform.$(OBJEXT) $(am__objects_1) 68 66 libpatterns_a_OBJECTS = $(am_libpatterns_a_OBJECTS) … … 82 80 am_mkeyes_OBJECTS = mkeyes.$(OBJEXT) 83 81 mkeyes_OBJECTS = $(am_mkeyes_OBJECTS) 84 82 mkeyes_DEPENDENCIES = ../utils/libutils.a 83 am_mkmcpat_OBJECTS = mkmcpat.$(OBJEXT) 84 mkmcpat_OBJECTS = $(am_mkmcpat_OBJECTS) 85 mkmcpat_DEPENDENCIES = ../engine/libengine.a ../sgf/libsgf.a \ 86 ../utils/libutils.a 85 87 am_mkpat_OBJECTS = mkpat.$(OBJEXT) transform.$(OBJEXT) dfa.$(OBJEXT) 86 88 mkpat_OBJECTS = $(am_mkpat_OBJECTS) 87 89 mkpat_DEPENDENCIES = ../utils/libutils.a … … 98 100 LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ 99 101 SOURCES = $(libpatterns_a_SOURCES) $(compress_fuseki_SOURCES) \ 100 102 $(extract_fuseki_SOURCES) $(joseki_SOURCES) $(mkeyes_SOURCES) \ 101 $(mkpat_SOURCES) $(uncompress_fuseki_SOURCES) 103 $(mkmcpat_SOURCES) $(mkpat_SOURCES) \ 104 $(uncompress_fuseki_SOURCES) 102 105 DIST_SOURCES = $(libpatterns_a_SOURCES) $(compress_fuseki_SOURCES) \ 103 106 $(extract_fuseki_SOURCES) $(joseki_SOURCES) $(mkeyes_SOURCES) \ 104 $(mkpat_SOURCES) $(uncompress_fuseki_SOURCES) 107 $(mkmcpat_SOURCES) $(mkpat_SOURCES) \ 108 $(uncompress_fuseki_SOURCES) 105 109 HEADERS = $(noinst_HEADERS) 106 110 ETAGS = etags 107 111 CTAGS = ctags … … 134 138 GCC_ONLY_FALSE = @GCC_ONLY_FALSE@ 135 139 GCC_ONLY_TRUE = @GCC_ONLY_TRUE@ 136 140 GNU_GO_WARNINGS = @GNU_GO_WARNINGS@ 141 GREP = @GREP@ 137 142 INSTALL_DATA = @INSTALL_DATA@ 138 143 INSTALL_PROGRAM = @INSTALL_PROGRAM@ 139 144 INSTALL_SCRIPT = @INSTALL_SCRIPT@ … … 160 165 STRIP = @STRIP@ 161 166 VERSION = @VERSION@ 162 167 ac_ct_CC = @ac_ct_CC@ 163 ac_ct_RANLIB = @ac_ct_RANLIB@164 ac_ct_STRIP = @ac_ct_STRIP@165 168 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ 166 169 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ 167 170 am__include = @am__include@ … … 172 175 bindir = @bindir@ 173 176 build_alias = @build_alias@ 174 177 datadir = @datadir@ 178 datarootdir = @datarootdir@ 179 docdir = @docdir@ 180 dvidir = @dvidir@ 175 181 exec_prefix = @exec_prefix@ 176 182 glibconfig = @glibconfig@ 177 183 host_alias = @host_alias@ 184 htmldir = @htmldir@ 178 185 includedir = @includedir@ 179 186 infodir = @infodir@ 180 187 install_sh = @install_sh@ 181 188 libdir = @libdir@ 182 189 libexecdir = @libexecdir@ 190 localedir = @localedir@ 183 191 localstatedir = @localstatedir@ 184 192 mandir = @mandir@ 185 193 mkdir_p = @mkdir_p@ 186 194 oldincludedir = @oldincludedir@ 195 pdfdir = @pdfdir@ 187 196 prefix = @prefix@ 188 197 program_transform_name = @program_transform_name@ 198 psdir = @psdir@ 189 199 sbindir = @sbindir@ 190 200 sharedstatedir = @sharedstatedir@ 191 201 sysconfdir = @sysconfdir@ … … 234 244 joseki_AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/sgf 235 245 mkeyes_SOURCES = mkeyes.c 236 246 mkeyes_LDADD = ../utils/libutils.a 247 mkmcpat_SOURCES = mkmcpat.c 248 mkmcpat_LDADD = ../engine/libengine.a ../sgf/libsgf.a ../utils/libutils.a 249 mkmcpat_AM_CPPFLAGS = $(GNU_GO_WARNINGS) 237 250 extract_fuseki_SOURCES = extract_fuseki.c 238 251 # Yes, we currently need duplicate libengine.a and libpatterns.a. 239 252 extract_fuseki_LDADD = ../engine/libengine.a libpatterns.a\ … … 250 263 owl_attackpat.c\ 251 264 owl_vital_apat.c owl_defendpat.c fusekipat.c\ 252 265 fuseki9.c fuseki13.c fuseki19.c josekidb.c\ 253 handipat.c oraclepat.c 266 handipat.c oraclepat.c mcpat.c 254 267 255 268 DBBUILT = gogo.db hoshi_keima.db hoshi_other.db komoku.db sansan.db \ 256 269 mokuhazushi.db takamoku.db … … 258 271 DBBUILT_INPUT = -i gogo.db -i hoshi_keima.db -i hoshi_other.db -i komoku.db \ 259 272 -i sansan.db -i mokuhazushi.db -i takamoku.db 260 273 274 MC_DB = $(srcdir)/mc_montegnu_classic.db $(srcdir)/mc_mogo_classic.db \ 275 $(srcdir)/mc_uniform.db 276 261 277 DB_TO_TAG = aa_attackpats.db attack.db barriers.db conn.db defense.db\ 262 278 endgame.db eyes.db fuseki.db fuseki9.dbz fuseki13.dbz fuseki19.dbz\ 263 279 handicap.db influence.db oracle.db owl_attackpats.db\ … … 336 352 mkeyes$(EXEEXT): $(mkeyes_OBJECTS) $(mkeyes_DEPENDENCIES) 337 353 @rm -f mkeyes$(EXEEXT) 338 354 $(LINK) $(mkeyes_LDFLAGS) $(mkeyes_OBJECTS) $(mkeyes_LDADD) $(LIBS) 355 mkmcpat$(EXEEXT): $(mkmcpat_OBJECTS) $(mkmcpat_DEPENDENCIES) 356 @rm -f mkmcpat$(EXEEXT) 357 $(LINK) $(mkmcpat_LDFLAGS) $(mkmcpat_OBJECTS) $(mkmcpat_LDADD) $(LIBS) 339 358 mkpat$(EXEEXT): $(mkpat_OBJECTS) $(mkpat_DEPENDENCIES) 340 359 @rm -f mkpat$(EXEEXT) 341 360 $(LINK) $(mkpat_LDFLAGS) $(mkpat_OBJECTS) $(mkpat_LDADD) $(LIBS) … … 369 388 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/influence.Po@am__quote@ 370 389 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joseki.Po@am__quote@ 371 390 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/josekidb.Po@am__quote@ 391 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcpat.Po@am__quote@ 372 392 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkeyes.Po@am__quote@ 393 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkmcpat.Po@am__quote@ 373 394 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkpat.Po@am__quote@ 374 395 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oraclepat.Po@am__quote@ 375 396 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/owl_attackpat.Po@am__quote@ … … 648 669 649 670 handipat.c : $(srcdir)/handicap.db mkpat$(EXEEXT) 650 671 ./mkpat -b handipat -i $(srcdir)/handicap.db -o handipat.c 672 673 mcpat.c : $(MC_DB) mkmcpat$(EXEEXT) 674 ./mkmcpat $(MC_DB) > mcpat.c 651 675 # Tell versions [3.59,3.63) of GNU make to not export all variables. 652 676 # Otherwise a system limit (for SysV at least) may be exceeded. 653 677 .NOEXPORT: -
interface/main.c
159 159 OPT_RESIGN_ALLOWED, 160 160 OPT_NEVER_RESIGN, 161 161 OPT_MONTE_CARLO, 162 OPT_MC_GAMES_PER_LEVEL 162 OPT_MC_GAMES_PER_LEVEL, 163 OPT_MC_PATTERNS, 164 OPT_MC_LIST_PATTERNS, 165 OPT_MC_LOAD_PATTERNS 163 166 }; 164 167 165 168 /* names of playing modes */ … … 309 312 {"never-resign", no_argument, 0, OPT_NEVER_RESIGN}, 310 313 {"monte-carlo", no_argument, 0, OPT_MONTE_CARLO}, 311 314 {"mc-games-per-level", required_argument, 0, OPT_MC_GAMES_PER_LEVEL}, 315 {"mc-patterns", required_argument, 0, OPT_MC_PATTERNS}, 316 {"mc-list-patterns", no_argument, 0, OPT_MC_LIST_PATTERNS}, 317 {"mc-load-patterns", required_argument, 0, OPT_MC_LOAD_PATTERNS}, 312 318 {NULL, 0, NULL, 0} 313 319 }; 314 320 … … 344 350 FILE *output_check; 345 351 int orientation = 0; 346 352 353 char mc_pattern_name[40] = ""; 354 char mc_pattern_filename[320] = ""; 355 347 356 float memory = (float) DEFAULT_MEMORY; /* Megabytes used for hash table. */ 348 357 349 358 /* If seed is zero, GNU Go will play a different game each time. If … … 645 654 mc_games_per_level = atoi(gg_optarg); 646 655 break; 647 656 657 case OPT_MC_PATTERNS: 658 if (strlen(gg_optarg) >= sizeof(mc_pattern_name)) { 659 fprintf(stderr, "Too long name given as value to --mc-patterns option.\n"); 660 exit(EXIT_FAILURE); 661 } 662 strcpy(mc_pattern_name, gg_optarg); 663 break; 664 665 case OPT_MC_LIST_PATTERNS: 666 list_mc_patterns(); 667 return EXIT_SUCCESS; 668 break; 669 670 case OPT_MC_LOAD_PATTERNS: 671 if (strlen(gg_optarg) >= sizeof(mc_pattern_filename)) { 672 fprintf(stderr, "Too long name given as value to --mc-load-patterns option.\n"); 673 exit(EXIT_FAILURE); 674 } 675 strcpy(mc_pattern_filename, gg_optarg); 676 break; 677 648 678 case OPT_MODE: 649 679 if (strcmp(gg_optarg, "ascii") == 0) 650 680 playmode = MODE_ASCII; … … 987 1017 /* Initialize the GNU Go engine. */ 988 1018 init_gnugo(memory, seed); 989 1019 1020 /* Load Monte Carlo patterns if one has been specified. Either 1021 * choose one of the compiled in ones or load directly from a 1022 * database file. 1023 */ 1024 if (strlen(mc_pattern_filename) > 0) { 1025 if (!mc_load_patterns_from_db(mc_pattern_filename, NULL)) 1026 return EXIT_FAILURE; 1027 } 1028 else if (strlen(mc_pattern_name) > 0) { 1029 if (!choose_mc_patterns(mc_pattern_name)) { 1030 fprintf(stderr, "Unknown Monte Carlo pattern database name %s.\n", 1031 mc_pattern_name); 1032 fprintf(stderr, "Use \"--mc-list-patterns\" to list the available databases.\n"); 1033 return EXIT_FAILURE; 1034 } 1035 } 1036 990 1037 /* Read the infile if there is one. Also play up the position. */ 991 1038 if (infilename) { 992 1039 if (!sgftree_readfile(&sgftree, infilename)) { … … 1536 1583 --mirror-limit <n> stop mirroring when n stones on board\n\n\ 1537 1584 --monte-carlo enable Monte Carlo move generation (9x9 or smaller)\n\ 1538 1585 --mc-games-per-level <n> number of Monte Carlo simulations per level\n\ 1586 --mc-list-patterns list names of builtin Monte Carlo patterns\n\ 1587 --mc-patterns <name> choose a built in Monte Carlo pattern database\n\ 1588 --mc-load-patterns <filename> read Monte Carlo patterns from file\n\ 1539 1589 --alternate-connections\n\ 1540 1590 --experimental-connections\n\ 1541 1591 --experimental-owl-ext\n\ -
engine/interface.c
52 52 53 53 transformation_init(); 54 54 dfa_match_init(); 55 choose_mc_patterns(NULL); 55 56 56 57 clear_approxlib_cache(); 57 58 clear_accuratelib_cache(); -
engine/utils.c
33 33 #include "sgftree.h" 34 34 #include "random.h" 35 35 #include "gg_utils.h" 36 #include "patterns.h" 36 37 37 38 38 /* 39 39 * Change the status of all the stones in the dragon at (dr). 40 40 */ … … 1959 1959 } 1960 1960 1961 1961 1962 /* Set up a compiled in pattern database for use by the Monte Carlo 1963 * code. If name is NULL, the first pattern database is used. 1964 * 1965 * The reason why this function and the next are placed here rather 1966 * than in montecarlo.c is to keep that file free from dependency on 1967 * patterns.h. 1968 */ 1969 int 1970 choose_mc_patterns(char *name) 1971 { 1972 int k; 1973 for (k = 0; mc_pattern_databases[k].name; k++) { 1974 if (!name || strcmp(name, mc_pattern_databases[k].name) == 0) { 1975 mc_init_patterns(mc_pattern_databases[k].values); 1976 return 1; 1977 } 1978 } 1979 1980 return 0; 1981 } 1982 1983 /* List compiled in Monte Carlo pattern databases. */ 1984 void 1985 list_mc_patterns(void) 1986 { 1987 int k; 1988 printf("Available builtin Monte Carlo local patterns:\n\n"); 1989 for (k = 0; mc_pattern_databases[k].name; k++) { 1990 if (k == 0) 1991 printf("* %s (default)\n", mc_pattern_databases[k].name); 1992 else 1993 printf("* %s\n", mc_pattern_databases[k].name); 1994 } 1995 printf("\nUse \"--mc-patterns name\" to choose one of these.\n"); 1996 printf("Use \"--mc-load-patterns filename\" to directly load a pattern database.\n"); 1997 } 1998 1962 1999 /* 1963 2000 * Local Variables: 1964 2001 * tab-width: 8 -
engine/liberty.h
497 497 int allowed_moves[BOARDMAX]); 498 498 enum dragon_status aftermath_final_status(int color, int pos); 499 499 500 int mc_get_size_of_pattern_values_table(void); 501 int mc_load_patterns_from_db(const char *filename, unsigned int *values); 502 void mc_init_patterns(const unsigned int *values); 503 int choose_mc_patterns(char *name); 504 void list_mc_patterns(void); 505 500 506 void uct_genmove(int color, int *move, int *forbidden_moves, 501 507 int *allowed_moves, int nodes, float *move_values, 502 508 int *move_frequencies); -
engine/montecarlo.c
37 37 /* FIXME: Replace with a DEBUG_MC symbol for use with -d. */ 38 38 static int mc_debug = 0; 39 39 40 #define CACHE_CAPTURE_MOVES 140 #define TURN_OFF_ASSERTIONS 1 41 41 42 42 43 /* Special board code for Monte Carlo simulations. 43 44 * 44 45 * A liberty edge is the combination of the position of the liberty … … 58 59 * origin in the global board. The reference stone is the only one 59 60 * which is guaranteed to have a valid pointer to the "first" liberty 60 61 * edge (just an arbitrary element in the circular list). 62 * 63 * The local_context field contains information about the surrounding 64 * 8 points. The bit layout is 65 * 66 * 23 : Black suicide. 67 * 22 : White suicide. 68 * 21 : Black self-atari. 69 * 20 : White self-atari. 70 * 19,18: Number of stones captured by black move. 71 * 17,16: Number of stones captured by white move. 72 * 15,14: Color to the southeast. 73 * 13,12: Color to the northeast. 74 * 11,10: Color to the northwest. 75 * 9, 8: Color to the southwest. 76 * 7, 6: Color to the east. 77 * 5, 4: Color to the north. 78 * 3, 2: Color to the west. 79 * 1, 0: Color to the south. 80 * 81 * The number of stones in atari is 0 if empty or not atari, 1 if one 82 * stone in atari, 2 if two stones in atari, and 3 if three or more stones 83 * in atari. 84 * 85 * The queue array is used to form a linked single list data structure 86 * with O(1) add, O(1) lookup, and O(n) delete operations. The 87 * assumption is that v1 = queue[0] points to the first board vertex 88 * in the list, v2 = queue[v1] points to the second vertex and so on. 89 * The list ends when the next vertex is the off-board point 1. Board 90 * vertices not included in the list have queue[v1] = 0. Thus an empty 91 * list is characterized by queue[0] = 1 and queue[v] = 0 for all 92 * vertices on the board. Generally queue[v] can be used to test for 93 * membership in the list. The list is used to keep track of points 94 * needing updated local context or value information. 95 * 96 * The move_values_*, partitioned_move_value_sums_*, 97 * move_partition_lists_*, and move_value_sum_* fields are together 98 * used to track move values and quickly sample according the 99 * distribution determined by the move values. 100 * 101 * The move_values_* arrays naturally hold the values of each move. 102 * 103 * The move_partition_lists_* arrays form a two-level access to the 104 * legal moves of respective color. Depending on the MAX_BOARD size, 105 * the vertices are split into 2, 4, 8, or 16 partitions (see below) 106 * where the partition number of each vertex is given by the 1, 2, 3, 107 * or 4 least significant bits of the vertex index respectively. The 108 * legal moves in each partition are linked together just like the 109 * queue array described above. The only difference is that multiple 110 * partition linked lists are represented in the same array by 111 * starting from out of board indices 0..1, 0..3, 0..7, and 0..15 112 * respectively. 113 * 114 * The partitioned_move_value_sums_* arrays are simply the sums of 115 * move values in each partition and the move_value_sum_white_* fields 116 * are the sum of the values of all legal moves. 61 117 */ 62 118 119 #if MAX_BOARD < 4 120 #define NUM_MOVE_PARTITIONS 2 121 #elif MAX_BOARD < 8 122 #define NUM_MOVE_PARTITIONS 4 123 #elif MAX_BOARD < 16 124 #define NUM_MOVE_PARTITIONS 8 125 #else 126 #define NUM_MOVE_PARTITIONS 16 127 #endif 63 128 64 129 struct mc_board { 65 130 Intersection board[BOARDSIZE]; 131 int local_context[BOARDSIZE]; 132 int queue[BOARDMAX]; 133 unsigned int move_values_white[BOARDMAX]; 134 unsigned int move_values_black[BOARDMAX]; 135 unsigned int partitioned_move_value_sums_white[NUM_MOVE_PARTITIONS]; 136 unsigned int partitioned_move_value_sums_black[NUM_MOVE_PARTITIONS]; 137 int move_partition_lists_white[BOARDMAX]; 138 int move_partition_lists_black[BOARDMAX]; 139 unsigned int move_value_sum_white; 140 unsigned int move_value_sum_black; 66 141 int board_ko_pos; 67 142 int reference_stone[BOARDMAX]; 68 143 int next_stone[BOARDMAX]; … … 72 147 Hash_data hash; 73 148 }; 74 149 150 #define MC_ADD_TO_UPDATE_QUEUE(mc, pos) \ 151 do { \ 152 if (!mc->queue[pos]) { \ 153 mc->queue[pos] = mc->queue[0]; \ 154 mc->queue[0] = pos; \ 155 } \ 156 } while (0) 157 75 158 #define MC_ON_BOARD(pos) (mc->board[pos] != GRAY) 76 159 77 /* FIXME: In principle same a MAXCHAIN but we don't need to care about78 * such high numbers.79 */80 #define MAX_NEIGHBORS 2081 82 160 /* Add a liberty edge for a string at pos with liberty at lib and 83 161 * direction dir. 84 162 */ … … 89 167 int reference = mc->reference_stone[pos]; 90 168 int first_liberty_edge = mc->first_liberty_edge[reference]; 91 169 170 #if !TURN_OFF_ASSERTIONS 92 171 gg_assert(lib + delta[dir] == pos); 172 #endif 93 173 94 174 if (first_liberty_edge) { 95 175 int second_liberty_edge = mc->next_liberty_edge[first_liberty_edge]; … … 117 197 int next = mc->next_liberty_edge[this_liberty_edge]; 118 198 int previous = mc->previous_liberty_edge[this_liberty_edge]; 119 199 200 #if !TURN_OFF_ASSERTIONS 120 201 gg_assert(lib + delta[dir] == pos); 202 #endif 121 203 122 204 if (next == this_liberty_edge) { 123 205 mc->first_liberty_edge[reference] = 0; … … 174 256 } 175 257 176 258 259 /* Does the string at str have at most two liberties? In that case, 260 * add them to the update queue. 261 */ 262 static void 263 mc_queue_max_two_liberties(struct mc_board *mc, int str) 264 { 265 int reference = mc->reference_stone[str]; 266 int first_liberty_edge = mc->first_liberty_edge[reference]; 267 int first_liberty = first_liberty_edge >> 2; 268 int liberty_edge = mc->next_liberty_edge[first_liberty_edge]; 269 int second_liberty; 270 #if !TURN_OFF_ASSERTIONS 271 ASSERT1(IS_STONE(mc->board[str]), str); 272 #endif 273 if (first_liberty == NO_MOVE) 274 return; 275 while (liberty_edge != first_liberty_edge) { 276 if ((liberty_edge >> 2) != first_liberty) { 277 second_liberty = liberty_edge >> 2; 278 while (liberty_edge != first_liberty_edge) { 279 if ((liberty_edge >> 2) != first_liberty 280 && (liberty_edge >> 2) != second_liberty) 281 return; 282 liberty_edge = mc->next_liberty_edge[liberty_edge]; 283 } 284 MC_ADD_TO_UPDATE_QUEUE(mc, first_liberty); 285 MC_ADD_TO_UPDATE_QUEUE(mc, second_liberty); 286 return; 287 } 288 liberty_edge = mc->next_liberty_edge[liberty_edge]; 289 } 290 291 MC_ADD_TO_UPDATE_QUEUE(mc, first_liberty); 292 } 293 294 177 295 /* Remove the string at str from the board. */ 178 296 static int 179 297 mc_remove_string(struct mc_board *mc, int str) … … 185 303 int k; 186 304 187 305 do { 188 for (k = 0; k < 4; k++) 189 if (mc->board[pos + delta[k]] == other) 306 for (k = 0; k < 8; k++) { 307 if (k < 4 && mc->board[pos + delta[k]] == other) { 308 mc_queue_max_two_liberties(mc, pos + delta[k]); 190 309 mc_add_liberty_edge(mc, pos + delta[k], pos, k); 310 } 311 if (mc->board[pos + delta[k]] == EMPTY) 312 MC_ADD_TO_UPDATE_QUEUE(mc, pos + delta[k]); 313 } 191 314 mc->board[pos] = EMPTY; 315 mc->local_context[NW(pos)] ^= color << 14; 316 mc->local_context[SW(pos)] ^= color << 12; 317 mc->local_context[SE(pos)] ^= color << 10; 318 mc->local_context[NE(pos)] ^= color << 8; 319 mc->local_context[WEST(pos)] ^= color << 6; 320 mc->local_context[SOUTH(pos)] ^= color << 4; 321 mc->local_context[EAST(pos)] ^= color << 2; 322 mc->local_context[NORTH(pos)] ^= color; 192 323 hashdata_invert_stone(&(mc->hash), pos, color); 324 MC_ADD_TO_UPDATE_QUEUE(mc, pos); 193 325 num_removed_stones++; 194 326 pos = mc->next_stone[pos]; 195 327 } while (pos != str); … … 211 343 memcpy(mc->board, board, sizeof(mc->board)); 212 344 mc->board_ko_pos = board_ko_pos; 213 345 mc->hash = board_hash; 346 memset(mc->queue, 0, sizeof(mc->queue)); 347 mc->queue[0] = 1; 214 348 215 349 memset(mc->next_stone, 0, sizeof(mc->next_stone)); 216 350 for (pos = BOARDMIN; pos < BOARDMAX; pos++) { 351 int geometry = ((mc->board[SE(pos)] << 14) 352 | (mc->board[NE(pos)] << 12) 353 | (mc->board[NW(pos)] << 10) 354 | (mc->board[SW(pos)] << 8) 355 | (mc->board[EAST(pos)] << 6) 356 | (mc->board[NORTH(pos)] << 4) 357 | (mc->board[WEST(pos)] << 2) 358 | mc->board[SOUTH(pos)]); 359 mc->local_context[pos] = geometry; 360 if (board[pos] == EMPTY) { 361 int s; 362 int captured_black_stones = 0; 363 int captured_white_stones = 0; 364 if (is_self_atari(pos, WHITE)) 365 mc->local_context[pos] |= 1 << 20; 366 if (is_self_atari(pos, BLACK)) 367 mc->local_context[pos] |= 1 << 21; 368 if (is_suicide(pos, WHITE)) 369 mc->local_context[pos] |= 1 << 22; 370 if (is_suicide(pos, BLACK)) 371 mc->local_context[pos] |= 1 << 23; 372 for (s = 0; s < 4; s++) { 373 if (board[pos + delta[s]] == BLACK 374 && countlib(pos + delta[s]) == 1) 375 captured_black_stones += countstones(pos + delta[s]); 376 else if (board[pos + delta[s]] == WHITE 377 && countlib(pos + delta[s]) == 1) 378 captured_white_stones += countstones(pos + delta[s]); 379 } 380 if (captured_black_stones > 3) 381 captured_black_stones = 3; 382 if (captured_white_stones > 3) 383 captured_white_stones = 3; 384 mc->local_context[pos] |= captured_black_stones << 16; 385 mc->local_context[pos] |= captured_white_stones << 18; 386 } 387 217 388 if (IS_STONE(board[pos]) && mc->next_stone[pos] == 0) { 218 389 num_stones = findstones(pos, BOARDMAX, stones); 219 390 mc->first_liberty_edge[pos] = 0; … … 288 459 #endif 289 460 290 461 291 /* Write the Monte Carlo board to outfile. 292 */ 462 /* Write the Monte Carlo board to outfile. */ 293 463 static void 294 464 mc_showboard(struct mc_board *mc, FILE *outfile) 295 465 { … … 329 499 return num_stones; 330 500 } 331 501 332 /* Is a move at pos by color suicide? */333 static int334 mc_is_suicide(struct mc_board *mc, int pos, int color)335 {336 int k;337 338 if (mc->board[SOUTH(pos)] == EMPTY339 || mc->board[WEST(pos)] == EMPTY340 || mc->board[NORTH(pos)] == EMPTY341 || mc->board[EAST(pos)] == EMPTY)342 return 0;343 502 344 for (k = 0; k < 4; k++) { 345 int first_liberty_edge; 346 int liberty_edge; 347 int additional_liberty = 0; 348 if (!ON_BOARD(pos + delta[k])) 349 continue; 503 /* Suicide is incrementally tracked by the local context information. */ 504 #define mc_is_suicide(mc, pos, color) \ 505 ((mc->local_context[pos] >> (21 + color)) & 1) 350 506 351 first_liberty_edge = (pos << 2) | k;352 liberty_edge = mc->next_liberty_edge[first_liberty_edge];353 <
