Ticket #150: gunnar_7_12.14.diff

File gunnar_7_12.14.diff, 81.4 kB (added by gunnar, 6 months ago)

Tunable local patterns for random playouts.

  • patterns/patterns.h

     
    293293}; 
    294294 
    295295 
     296/* Monte Carlo local patterns. */ 
     297struct mc_pattern_database { 
     298  const char *name; 
     299  const unsigned int *values; 
     300}; 
    296301 
    297302 
    298303/* helper functions */ 
     
    352357extern struct fullboard_pattern fuseki13[]; 
    353358extern struct fullboard_pattern fuseki9[]; 
    354359 
     360extern struct mc_pattern_database mc_pattern_databases[]; 
     361 
    355362struct corner_db; 
    356363struct corner_variation; 
    357364struct corner_pattern; 
  • patterns/Makefile.am

     
    1 noinst_PROGRAMS = mkpat joseki mkeyes uncompress_fuseki 
     1noinst_PROGRAMS = mkpat joseki mkeyes uncompress_fuseki mkmcpat 
    22EXTRA_PROGRAMS = extract_fuseki compress_fuseki 
    33 
    44DSP = dfa.dsp patterns.dsp joseki.dsp mkeyes.dsp mkpat.dsp fuseki.dsp 
     
    5151joseki_AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/sgf 
    5252mkeyes_SOURCES = mkeyes.c 
    5353mkeyes_LDADD = ../utils/libutils.a 
     54mkmcpat_SOURCES  = mkmcpat.c 
     55mkmcpat_LDADD = ../engine/libengine.a ../sgf/libsgf.a ../utils/libutils.a 
     56mkmcpat_AM_CPPFLAGS = $(GNU_GO_WARNINGS) 
    5457extract_fuseki_SOURCES  = extract_fuseki.c 
    5558# Yes, we currently need duplicate libengine.a and libpatterns.a. 
    5659extract_fuseki_LDADD = ../engine/libengine.a libpatterns.a\ 
     
    6972                 owl_attackpat.c\ 
    7073                 owl_vital_apat.c owl_defendpat.c fusekipat.c\ 
    7174                 fuseki9.c fuseki13.c fuseki19.c josekidb.c\ 
    72                  handipat.c oraclepat.c 
     75                 handipat.c oraclepat.c mcpat.c 
    7376 
    7477DBBUILT = gogo.db hoshi_keima.db hoshi_other.db komoku.db sansan.db \ 
    7578          mokuhazushi.db takamoku.db 
     
    7780DBBUILT_INPUT = -i gogo.db -i hoshi_keima.db -i hoshi_other.db -i komoku.db \ 
    7881               -i sansan.db -i mokuhazushi.db -i takamoku.db 
    7982 
     83MC_DB = $(srcdir)/mc_montegnu_classic.db $(srcdir)/mc_mogo_classic.db \ 
     84        $(srcdir)/mc_uniform.db 
     85 
    8086DB_TO_TAG = aa_attackpats.db attack.db barriers.db conn.db defense.db\ 
    8187            endgame.db eyes.db fuseki.db fuseki9.dbz fuseki13.dbz fuseki19.dbz\ 
    8288            handicap.db influence.db oracle.db owl_attackpats.db\ 
     
    183189handipat.c : $(srcdir)/handicap.db mkpat$(EXEEXT) 
    184190        ./mkpat -b handipat -i $(srcdir)/handicap.db -o handipat.c 
    185191 
     192mcpat.c : $(MC_DB) mkmcpat$(EXEEXT) 
     193        ./mkmcpat $(MC_DB) > mcpat.c 
    186194 
     195 
    187196ETAGS_ARGS = --language none --regex '/^Pattern[ \t]+[a-zA-Z0-9]+/' $(DB_TO_TAG)\ 
    188197             --language auto --no-regex 
    189198TAGS_DEPENDENCIES = $(DB_TO_TAG) 
  • patterns/Makefile.in

     
    1 # Makefile.in generated by automake 1.9.5 from Makefile.am. 
     1# Makefile.in generated by automake 1.9.6 from Makefile.am. 
    22# @configure_input@ 
    33 
    44# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 
     
    1616 
    1717 
    1818 
    19 SOURCES = $(libpatterns_a_SOURCES) $(compress_fuseki_SOURCES) $(extract_fuseki_SOURCES) $(joseki_SOURCES) $(mkeyes_SOURCES) $(mkpat_SOURCES) $(uncompress_fuseki_SOURCES) 
    20  
    2119srcdir = @srcdir@ 
    2220top_srcdir = @top_srcdir@ 
    2321VPATH = @srcdir@ 
     
    3937PRE_UNINSTALL = : 
    4038POST_UNINSTALL = : 
    4139noinst_PROGRAMS = mkpat$(EXEEXT) joseki$(EXEEXT) mkeyes$(EXEEXT) \ 
    42         uncompress_fuseki$(EXEEXT) 
     40        uncompress_fuseki$(EXEEXT) mkmcpat$(EXEEXT) 
    4341EXTRA_PROGRAMS = extract_fuseki$(EXEEXT) compress_fuseki$(EXEEXT) 
    4442subdir = patterns 
    4543DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ 
     
    6260        owl_attackpat.$(OBJEXT) owl_vital_apat.$(OBJEXT) \ 
    6361        owl_defendpat.$(OBJEXT) fusekipat.$(OBJEXT) fuseki9.$(OBJEXT) \ 
    6462        fuseki13.$(OBJEXT) fuseki19.$(OBJEXT) josekidb.$(OBJEXT) \ 
    65         handipat.$(OBJEXT) oraclepat.$(OBJEXT) 
     63        handipat.$(OBJEXT) oraclepat.$(OBJEXT) mcpat.$(OBJEXT) 
    6664am_libpatterns_a_OBJECTS = connections.$(OBJEXT) helpers.$(OBJEXT) \ 
    6765        transform.$(OBJEXT) $(am__objects_1) 
    6866libpatterns_a_OBJECTS = $(am_libpatterns_a_OBJECTS) 
     
    8280am_mkeyes_OBJECTS = mkeyes.$(OBJEXT) 
    8381mkeyes_OBJECTS = $(am_mkeyes_OBJECTS) 
    8482mkeyes_DEPENDENCIES = ../utils/libutils.a 
     83am_mkmcpat_OBJECTS = mkmcpat.$(OBJEXT) 
     84mkmcpat_OBJECTS = $(am_mkmcpat_OBJECTS) 
     85mkmcpat_DEPENDENCIES = ../engine/libengine.a ../sgf/libsgf.a \ 
     86        ../utils/libutils.a 
    8587am_mkpat_OBJECTS = mkpat.$(OBJEXT) transform.$(OBJEXT) dfa.$(OBJEXT) 
    8688mkpat_OBJECTS = $(am_mkpat_OBJECTS) 
    8789mkpat_DEPENDENCIES = ../utils/libutils.a 
     
    98100LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ 
    99101SOURCES = $(libpatterns_a_SOURCES) $(compress_fuseki_SOURCES) \ 
    100102        $(extract_fuseki_SOURCES) $(joseki_SOURCES) $(mkeyes_SOURCES) \ 
    101         $(mkpat_SOURCES) $(uncompress_fuseki_SOURCES) 
     103        $(mkmcpat_SOURCES) $(mkpat_SOURCES) \ 
     104        $(uncompress_fuseki_SOURCES) 
    102105DIST_SOURCES = $(libpatterns_a_SOURCES) $(compress_fuseki_SOURCES) \ 
    103106        $(extract_fuseki_SOURCES) $(joseki_SOURCES) $(mkeyes_SOURCES) \ 
    104         $(mkpat_SOURCES) $(uncompress_fuseki_SOURCES) 
     107        $(mkmcpat_SOURCES) $(mkpat_SOURCES) \ 
     108        $(uncompress_fuseki_SOURCES) 
    105109HEADERS = $(noinst_HEADERS) 
    106110ETAGS = etags 
    107111CTAGS = ctags 
     
    134138GCC_ONLY_FALSE = @GCC_ONLY_FALSE@ 
    135139GCC_ONLY_TRUE = @GCC_ONLY_TRUE@ 
    136140GNU_GO_WARNINGS = @GNU_GO_WARNINGS@ 
     141GREP = @GREP@ 
    137142INSTALL_DATA = @INSTALL_DATA@ 
    138143INSTALL_PROGRAM = @INSTALL_PROGRAM@ 
    139144INSTALL_SCRIPT = @INSTALL_SCRIPT@ 
     
    160165STRIP = @STRIP@ 
    161166VERSION = @VERSION@ 
    162167ac_ct_CC = @ac_ct_CC@ 
    163 ac_ct_RANLIB = @ac_ct_RANLIB@ 
    164 ac_ct_STRIP = @ac_ct_STRIP@ 
    165168am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ 
    166169am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ 
    167170am__include = @am__include@ 
     
    172175bindir = @bindir@ 
    173176build_alias = @build_alias@ 
    174177datadir = @datadir@ 
     178datarootdir = @datarootdir@ 
     179docdir = @docdir@ 
     180dvidir = @dvidir@ 
    175181exec_prefix = @exec_prefix@ 
    176182glibconfig = @glibconfig@ 
    177183host_alias = @host_alias@ 
     184htmldir = @htmldir@ 
    178185includedir = @includedir@ 
    179186infodir = @infodir@ 
    180187install_sh = @install_sh@ 
    181188libdir = @libdir@ 
    182189libexecdir = @libexecdir@ 
     190localedir = @localedir@ 
    183191localstatedir = @localstatedir@ 
    184192mandir = @mandir@ 
    185193mkdir_p = @mkdir_p@ 
    186194oldincludedir = @oldincludedir@ 
     195pdfdir = @pdfdir@ 
    187196prefix = @prefix@ 
    188197program_transform_name = @program_transform_name@ 
     198psdir = @psdir@ 
    189199sbindir = @sbindir@ 
    190200sharedstatedir = @sharedstatedir@ 
    191201sysconfdir = @sysconfdir@ 
     
    234244joseki_AM_CPPFLAGS = $(GNU_GO_WARNINGS) -I$(top_srcdir)/sgf 
    235245mkeyes_SOURCES = mkeyes.c 
    236246mkeyes_LDADD = ../utils/libutils.a 
     247mkmcpat_SOURCES = mkmcpat.c 
     248mkmcpat_LDADD = ../engine/libengine.a ../sgf/libsgf.a ../utils/libutils.a 
     249mkmcpat_AM_CPPFLAGS = $(GNU_GO_WARNINGS) 
    237250extract_fuseki_SOURCES = extract_fuseki.c 
    238251# Yes, we currently need duplicate libengine.a and libpatterns.a. 
    239252extract_fuseki_LDADD = ../engine/libengine.a libpatterns.a\ 
     
    250263                 owl_attackpat.c\ 
    251264                 owl_vital_apat.c owl_defendpat.c fusekipat.c\ 
    252265                 fuseki9.c fuseki13.c fuseki19.c josekidb.c\ 
    253                  handipat.c oraclepat.c 
     266                 handipat.c oraclepat.c mcpat.c 
    254267 
    255268DBBUILT = gogo.db hoshi_keima.db hoshi_other.db komoku.db sansan.db \ 
    256269          mokuhazushi.db takamoku.db 
     
    258271DBBUILT_INPUT = -i gogo.db -i hoshi_keima.db -i hoshi_other.db -i komoku.db \ 
    259272               -i sansan.db -i mokuhazushi.db -i takamoku.db 
    260273 
     274MC_DB = $(srcdir)/mc_montegnu_classic.db $(srcdir)/mc_mogo_classic.db \ 
     275        $(srcdir)/mc_uniform.db 
     276 
    261277DB_TO_TAG = aa_attackpats.db attack.db barriers.db conn.db defense.db\ 
    262278            endgame.db eyes.db fuseki.db fuseki9.dbz fuseki13.dbz fuseki19.dbz\ 
    263279            handicap.db influence.db oracle.db owl_attackpats.db\ 
     
    336352mkeyes$(EXEEXT): $(mkeyes_OBJECTS) $(mkeyes_DEPENDENCIES)  
    337353        @rm -f mkeyes$(EXEEXT) 
    338354        $(LINK) $(mkeyes_LDFLAGS) $(mkeyes_OBJECTS) $(mkeyes_LDADD) $(LIBS) 
     355mkmcpat$(EXEEXT): $(mkmcpat_OBJECTS) $(mkmcpat_DEPENDENCIES)  
     356        @rm -f mkmcpat$(EXEEXT) 
     357        $(LINK) $(mkmcpat_LDFLAGS) $(mkmcpat_OBJECTS) $(mkmcpat_LDADD) $(LIBS) 
    339358mkpat$(EXEEXT): $(mkpat_OBJECTS) $(mkpat_DEPENDENCIES)  
    340359        @rm -f mkpat$(EXEEXT) 
    341360        $(LINK) $(mkpat_LDFLAGS) $(mkpat_OBJECTS) $(mkpat_LDADD) $(LIBS) 
     
    369388@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/influence.Po@am__quote@ 
    370389@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joseki.Po@am__quote@ 
    371390@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/josekidb.Po@am__quote@ 
     391@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcpat.Po@am__quote@ 
    372392@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkeyes.Po@am__quote@ 
     393@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkmcpat.Po@am__quote@ 
    373394@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkpat.Po@am__quote@ 
    374395@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oraclepat.Po@am__quote@ 
    375396@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/owl_attackpat.Po@am__quote@ 
     
    648669 
    649670handipat.c : $(srcdir)/handicap.db mkpat$(EXEEXT) 
    650671        ./mkpat -b handipat -i $(srcdir)/handicap.db -o handipat.c 
     672 
     673mcpat.c : $(MC_DB) mkmcpat$(EXEEXT) 
     674        ./mkmcpat $(MC_DB) > mcpat.c 
    651675# Tell versions [3.59,3.63) of GNU make to not export all variables. 
    652676# Otherwise a system limit (for SysV at least) may be exceeded. 
    653677.NOEXPORT: 
  • interface/main.c

     
    159159      OPT_RESIGN_ALLOWED, 
    160160      OPT_NEVER_RESIGN, 
    161161      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 
    163166}; 
    164167 
    165168/* names of playing modes */ 
     
    309312  {"never-resign",   no_argument,       0, OPT_NEVER_RESIGN}, 
    310313  {"monte-carlo",    no_argument,       0, OPT_MONTE_CARLO}, 
    311314  {"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}, 
    312318  {NULL, 0, NULL, 0} 
    313319}; 
    314320 
     
    344350  FILE *output_check; 
    345351  int orientation = 0; 
    346352 
     353  char mc_pattern_name[40] = ""; 
     354  char mc_pattern_filename[320] = ""; 
     355 
    347356  float memory = (float) DEFAULT_MEMORY; /* Megabytes used for hash table. */ 
    348357 
    349358  /* If seed is zero, GNU Go will play a different game each time. If 
     
    645654        mc_games_per_level = atoi(gg_optarg); 
    646655        break; 
    647656 
     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 
    648678      case OPT_MODE:  
    649679        if (strcmp(gg_optarg, "ascii") == 0) 
    650680          playmode = MODE_ASCII; 
     
    9871017  /* Initialize the GNU Go engine. */ 
    9881018  init_gnugo(memory, seed); 
    9891019 
     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 
    9901037  /* Read the infile if there is one. Also play up the position. */ 
    9911038  if (infilename) { 
    9921039    if (!sgftree_readfile(&sgftree, infilename)) { 
     
    15361583   --mirror-limit <n>      stop mirroring when n stones on board\n\n\ 
    15371584   --monte-carlo           enable Monte Carlo move generation (9x9 or smaller)\n\ 
    15381585   --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\ 
    15391589   --alternate-connections\n\ 
    15401590   --experimental-connections\n\ 
    15411591   --experimental-owl-ext\n\ 
  • engine/interface.c

     
    5252 
    5353  transformation_init(); 
    5454  dfa_match_init(); 
     55  choose_mc_patterns(NULL); 
    5556 
    5657  clear_approxlib_cache(); 
    5758  clear_accuratelib_cache(); 
  • engine/utils.c

     
    3333#include "sgftree.h" 
    3434#include "random.h" 
    3535#include "gg_utils.h" 
     36#include "patterns.h" 
    3637 
    37  
    3838/* 
    3939 * Change the status of all the stones in the dragon at (dr). 
    4040 */ 
     
    19591959} 
    19601960 
    19611961 
     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 */ 
     1969int 
     1970choose_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. */ 
     1984void 
     1985list_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 
    19621999/* 
    19632000 * Local Variables: 
    19642001 * tab-width: 8 
  • engine/liberty.h

     
    497497                      int allowed_moves[BOARDMAX]); 
    498498enum dragon_status aftermath_final_status(int color, int pos); 
    499499 
     500int mc_get_size_of_pattern_values_table(void); 
     501int mc_load_patterns_from_db(const char *filename, unsigned int *values); 
     502void mc_init_patterns(const unsigned int *values); 
     503int choose_mc_patterns(char *name); 
     504void list_mc_patterns(void); 
     505 
    500506void uct_genmove(int color, int *move, int *forbidden_moves, 
    501507                 int *allowed_moves, int nodes, float *move_values, 
    502508                 int *move_frequencies); 
  • engine/montecarlo.c

    <
     
    3737/* FIXME: Replace with a DEBUG_MC symbol for use with -d. */ 
    3838static int mc_debug = 0; 
    3939 
    40 #define CACHE_CAPTURE_MOVES 1 
     40#define TURN_OFF_ASSERTIONS 1 
    4141 
     42 
    4243/* Special board code for Monte Carlo simulations. 
    4344 * 
    4445 * A liberty edge is the combination of the position of the liberty 
     
    5859 * origin in the global board. The reference stone is the only one 
    5960 * which is guaranteed to have a valid pointer to the "first" liberty 
    6061 * 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. 
    61117 */ 
    62118 
     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 
    63128 
    64129struct mc_board { 
    65130  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; 
    66141  int board_ko_pos; 
    67142  int reference_stone[BOARDMAX]; 
    68143  int next_stone[BOARDMAX]; 
     
    72147  Hash_data hash; 
    73148}; 
    74149 
     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 
    75158#define MC_ON_BOARD(pos) (mc->board[pos] != GRAY) 
    76159 
    77 /* FIXME: In principle same a MAXCHAIN but we don't need to care about 
    78  * such high numbers. 
    79  */ 
    80 #define MAX_NEIGHBORS 20 
    81  
    82160/* Add a liberty edge for a string at pos with liberty at lib and 
    83161 * direction dir. 
    84162 */ 
     
    89167  int reference = mc->reference_stone[pos]; 
    90168  int first_liberty_edge = mc->first_liberty_edge[reference]; 
    91169 
     170#if !TURN_OFF_ASSERTIONS 
    92171  gg_assert(lib + delta[dir] == pos); 
     172#endif 
    93173   
    94174  if (first_liberty_edge) { 
    95175    int second_liberty_edge = mc->next_liberty_edge[first_liberty_edge]; 
     
    117197  int next = mc->next_liberty_edge[this_liberty_edge]; 
    118198  int previous = mc->previous_liberty_edge[this_liberty_edge]; 
    119199   
     200#if !TURN_OFF_ASSERTIONS 
    120201  gg_assert(lib + delta[dir] == pos); 
     202#endif 
    121203   
    122204  if (next == this_liberty_edge) { 
    123205    mc->first_liberty_edge[reference] = 0; 
     
    174256} 
    175257 
    176258 
     259/* Does the string at str have at most two liberties? In that case, 
     260 * add them to the update queue. 
     261 */ 
     262static void 
     263mc_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 
    177295/* Remove the string at str from the board. */ 
    178296static int 
    179297mc_remove_string(struct mc_board *mc, int str) 
     
    185303  int k; 
    186304   
    187305  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]); 
    190309        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    } 
    191314    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; 
    192323    hashdata_invert_stone(&(mc->hash), pos, color); 
     324    MC_ADD_TO_UPDATE_QUEUE(mc, pos); 
    193325    num_removed_stones++; 
    194326    pos = mc->next_stone[pos]; 
    195327  } while (pos != str); 
     
    211343  memcpy(mc->board, board, sizeof(mc->board)); 
    212344  mc->board_ko_pos = board_ko_pos; 
    213345  mc->hash = board_hash; 
     346  memset(mc->queue, 0, sizeof(mc->queue)); 
     347  mc->queue[0] = 1; 
    214348 
    215349  memset(mc->next_stone, 0, sizeof(mc->next_stone)); 
    216350  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     
    217388    if (IS_STONE(board[pos]) && mc->next_stone[pos] == 0) { 
    218389      num_stones = findstones(pos, BOARDMAX, stones); 
    219390      mc->first_liberty_edge[pos] = 0; 
     
    288459#endif 
    289460 
    290461 
    291 /* Write the Monte Carlo board to outfile. 
    292  */ 
     462/* Write the Monte Carlo board to outfile. */ 
    293463static void 
    294464mc_showboard(struct mc_board *mc, FILE *outfile) 
    295465{ 
     
    329499  return num_stones; 
    330500} 
    331501 
    332 /* Is a move at pos by color suicide? */ 
    333 static int 
    334 mc_is_suicide(struct mc_board *mc, int pos, int color) 
    335 { 
    336   int k; 
    337    
    338   if (mc->board[SOUTH(pos)] == EMPTY 
    339       || mc->board[WEST(pos)] == EMPTY 
    340       || mc->board[NORTH(pos)] == EMPTY 
    341       || mc->board[EAST(pos)] == EMPTY) 
    342     return 0; 
    343502 
    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) 
    350506 
    351     first_liberty_edge = (pos << 2) | k; 
    352     liberty_edge = mc->next_liberty_edge[first_liberty_edge]; 
    353