Пример #1
0
/* Full board matching in database for fuseki moves. Return 1 if any
 * pattern found.
 */
static int
search_fuseki_database(int color)
{
  struct fullboard_pattern *database;
  int q;
  int k;
  int best_fuseki_value;

  /* Disable matching after a certain number of stones are placed on
   * the board.
   */
  if (stones_on_board(BLACK | WHITE) > MAX_FUSEKI_DATABASE_STONES)
    return 0;

  /* We only have databases for 9x9, 13x13 and 19x19. */
  if (board_size == 9)
    database = fuseki9;
  else if (board_size == 13)
    database = fuseki13;
  else if (board_size == 19)
    database = fuseki19;
  else
    return 0;

  /* Do the matching. */
  num_fuseki_moves = 0;
  fuseki_total_value = 0;
  fullboard_matchpat(fuseki_callback, color, database);

  /* No match. */
  if (num_fuseki_moves == 0)
    return 0;

  /* Choose randomly with respect to relative weights for matched moves. */
  /* Do not choose moves with less value than 20% of the best move */
  best_fuseki_value = fuseki_value[0];
  q = gg_rand() % fuseki_total_value;
  for (k = 0; k < num_fuseki_moves; k++) {
    if (fuseki_value[k] < (best_fuseki_value / 5))
      break;
    q -= fuseki_value[k];
    if (q < 0)
      break;
  }

  gg_assert(k < num_fuseki_moves);
  /* Give this move an arbitrary value of 75. The actual value doesn't
   * matter much since the intention is that we should play this move
   * whatever the rest of the analysis thinks.
   */
  announce_move(fuseki_moves[k], 75, color);

  /* Also make sure the other considered moves can be seen in the
   * traces and in the output file.
   */
  for (k = 0; k < num_fuseki_moves; k++)
    set_minimum_move_value(fuseki_moves[k], 74);

  return 1;
}
Пример #2
0
static int uniform_rand_10(void)
{
	uint8_t rval;

	do {
		if (gg_rand(&rval, sizeof(rval)) != 0)
			exit(-1);
	} while (rval >= 250);

	return (rval % 10);
}
Пример #3
0
static void
choose_corner_move(struct board_lib_state_struct *internal_state,
                   int corner, int *m, int *n)
{
  int *table = 0;
  int sum_of_weights = 0;
  int i;
  int q;
  
  if (internal_state->board_size <= 11)
    table = small_board;
  else if (internal_state->board_size <= 15)
    table = medium_board;
  else 
    table = large_board;

  for (i = 0; i < 8; i++)
    sum_of_weights += table[i];

  q = gg_rand() % sum_of_weights;
  for (i = 0; i < 8; i++) {
    q -= table[i];
    if (q < 0)
      break;
  }
  
  *m = corners[i][0];
  *n = corners[i][1];

  switch (corner) {
  case UPPER_LEFT:
    *m = *m - 1;
    *n = *n - 1;
    break;
  case UPPER_RIGHT:
    *m = *m - 1;
    *n = internal_state->board_size - *n;
    break;
  case LOWER_LEFT:
    *m = internal_state->board_size - *m;
    *n = *n - 1;
    break;
  case LOWER_RIGHT:
    *m = internal_state->board_size - *m;
    *n = internal_state->board_size - *n;
    break;
  }
}
Пример #4
0
static int
find_free_handicap_pattern()
{
  int k;
  int highest_value = -1;
  int sum_values = 0;
  int r;
  int anchor;
  struct pattern *pattern;
  int ll;
  int move;

  number_of_matches = 0;
  matchpat(free_handicap_callback, BLACK, &handipat_db, NULL, NULL);

  if (number_of_matches == 0)
    return 0;

  /* Find the highest value among the matched patterns. */
  for (k = 0; k < number_of_matches; k++)
    if (highest_value < handicap_matches[k].value)
      highest_value = handicap_matches[k].value;

  /* Replace the values by 2^(value - highest_value + 10) and compute
   * the sum of these values. Fractional values are discarded.
   */
  for (k = 0; k < number_of_matches; k++) {
    if (handicap_matches[k].value < highest_value - 10)
      handicap_matches[k].value = 0;
    else
      handicap_matches[k].value = 1 << (handicap_matches[k].value
					- highest_value + 10);
    sum_values += handicap_matches[k].value;
  }

  /* Pick a random number between 0 and sum_values. Don't bother with
   * the fact that lower numbers will tend to be very slightly
   * overrepresented.
   */
  r = gg_rand() % sum_values;
  
  /* Find the chosen pattern. */
  for (k = 0; k < number_of_matches; k++) {
    r -= handicap_matches[k].value;
    if (r < 0)
      break;
  }

  /* Place handicap stones according to pattern k. */
  anchor = handicap_matches[k].anchor;
  pattern = handicap_matches[k].pattern;
  ll = handicap_matches[k].ll;
  
  /* Pick up the location of the move */
  move = AFFINE_TRANSFORM(pattern->move_offset, ll, anchor);
  add_stone(move, BLACK);
  remaining_handicap_stones--;

  /* Add stones at all '!' in the pattern. */
  for (k = 0; k < pattern->patlen; k++) { 
    if (pattern->patn[k].att == ATT_not) {
      int pos = AFFINE_TRANSFORM(pattern->patn[k].offset, ll, anchor);
      add_stone(pos, BLACK);
      remaining_handicap_stones--;
    }
  }

  return 1;
}
void
play_solo(Gameinfo *gameinfo, int moves)
{
  SGFTree sgftree;
  int passes = 0; /* num. consecutive passes */
  int move_val;
  double t1, t2;
  int save_moves = moves;
  int boardsize = gnugo_get_boardsize();

  struct stats_data totalstats;
  int total_owl_count = 0;

  /* It tends not to be very imaginative in the opening,
   * so we scatter a few stones randomly to start with.
   * We add two random numbers to reduce the probability
   * of playing stones near the edge.
   */
  
  int n = 6 + 2*gg_rand()%5;
  int i, j;

  gnugo_set_komi(5.5);

  sgftree_clear(&sgftree);
  sgftreeCreateHeaderNode(&sgftree, gnugo_get_boardsize(), gnugo_get_komi());
  sgf_write_header(sgftree.root, 1, random_seed, 5.5, level, chinese_rules);
 
  /* Generate some random moves. */
  if (boardsize > 6) {
    do {
      do {
	i = (gg_rand() % 4) + (gg_rand() % (boardsize - 4));
	j = (gg_rand() % 4) + (gg_rand() % (boardsize - 4));
      } while (!gnugo_is_legal(i, j, gameinfo->to_move));

      gnugo_play_move(i, j, gameinfo->to_move);
      sgftreeAddPlay(&sgftree, gameinfo->to_move, i, j);
      sgftreeAddComment(&sgftree, "random move");
      gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);
    } while (--n > 0);
  }
  
  t1 = gg_cputime();
  memset(&totalstats, '\0', sizeof(totalstats));
  while (passes < 2 && --moves >= 0) {
    reset_owl_node_counter();
    move_val = gnugo_genmove(&i, &j, gameinfo->to_move);

    gnugo_play_move(i, j, gameinfo->to_move);
    sgffile_add_debuginfo(sgftree.lastnode, move_val);
    sgftreeAddPlay(&sgftree, gameinfo->to_move, i, j);
    sgffile_output(&sgftree);
    gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);

    if (move_val < 0) {
      ++passes;
      printf("%s(%d): Pass\n", gameinfo->to_move == BLACK ? "Black" : "White",
	     movenum);
    }
    else {
      passes = 0;
      gprintf("%s(%d): %m\n", gameinfo->to_move == BLACK ? "Black" : "White",
	      movenum, i, j);
    }

    totalstats.nodes               += stats.nodes;
    totalstats.position_entered    += stats.position_entered;
    totalstats.position_hits       += stats.position_hits;
    totalstats.read_result_entered += stats.read_result_entered;
    totalstats.hash_collisions     += stats.hash_collisions;
    total_owl_count                += get_owl_node_counter();
  }
  t2 = gg_cputime();
  
  /* Two passes and it's over. (EMPTY == BOTH) */
  gnugo_who_wins(EMPTY, stdout);

  score = gnugo_estimate_score(&lower_bound, &upper_bound);
  sgfWriteResult(sgftree.root, score, 1);
  sgffile_output(&sgftree);

#if 0
  if (t2 == t1)
    printf("%.3f moves played\n", (double) (save_moves-moves));
  else
    printf("%.3f moves/sec\n", (save_moves-moves)/(t2-t1));
#else
  printf("%10d moves played in %0.3f seconds\n", save_moves-moves, t2-t1);
  if (save_moves != moves)
    printf("%10.3f seconds/move\n", (t2-t1)/(save_moves-moves));
  printf("%10d nodes\n", totalstats.nodes);
  printf("%10d positions entered\n", totalstats.position_entered);
  printf("%10d position hits\n", totalstats.position_hits);
  printf("%10d read results entered\n", totalstats.read_result_entered);
  printf("%10d hash collisions\n", totalstats.hash_collisions);
  printf("%10d owl nodes\n", total_owl_count);
#endif
}
Пример #6
0
/* dfa_patterns_optimize_variations() tries to reduce the size of DFA by
 * altering pattern variations (in fact, transformations). The algorithm
 * is to change several patterns' variations and if this happens to give
 * size reduction, to keep the change, otherwise, revert.
 *
 * This function contains many heuristically chosen values for variation
 * changing probability etc. They have been chosen by observing algorithm
 * effectiveness and seem to be very good.
 *
 * Note that we subtract 1 from the number of nodes to be consistent with
 * the standard builder, which doesn't count error state.
 */
int *
dfa_patterns_optimize_variations(dfa_patterns *patterns, int iterations)
{
  int k = 0;
  int failed_iterations = 0;
  int min_nodes_so_far;
  int num_nodes_original;
  int *best_variations;
  double lower_limit = 2.0 / patterns->num_patterns;
  double upper_limit = 6.0 / patterns->num_patterns;
  double change_probability = 4.0 / patterns->num_patterns;
  dfa_pattern *pattern;

  best_variations = malloc(patterns->num_patterns * sizeof(*best_variations));
  assert(best_variations);
  for (pattern = patterns->patterns; pattern; pattern = pattern->next, k++)
    best_variations[k] = pattern->current_variation;

  dfa_patterns_build_graph(patterns);
  num_nodes_original = patterns->graph.num_nodes;
  min_nodes_so_far = num_nodes_original;

  fprintf(stderr, "Original number of DFA states: %d\n", min_nodes_so_far - 1);
  fprintf(stderr, "Trying to optimize in %d iterations\n", iterations);

  gg_srand(num_nodes_original + patterns->num_patterns);

  while (iterations--) {
    int changed_variations = 0;
    int k = 0;
    
    /* Randomly change some variations. */
    for (pattern = patterns->patterns; pattern; pattern = pattern->next, k++) {
      if (gg_drand() < change_probability && pattern->num_variations > 1) {
	int new_variation = gg_rand() % (pattern->num_variations - 1);
	if (new_variation >= pattern->current_variation)
	  new_variation++;
	pattern->current_variation = new_variation;
	changed_variations++;
      }
      else
	pattern->current_variation = best_variations[k];
    }

    if (changed_variations == 0) {
      iterations++;
      continue;
    }

    fprintf(stderr, ".");
    dfa_patterns_build_graph(patterns);

    if (patterns->graph.num_nodes < min_nodes_so_far) {
      /* If the new set of variations produces smaller dfa, save it. */
      int k = 0;
      for (pattern = patterns->patterns; pattern; pattern = pattern->next, k++)
	best_variations[k] = pattern->current_variation;

      fprintf(stderr, "\nOptimized: %d => %d states (%d iterations left)\n",
	      min_nodes_so_far - 1, patterns->graph.num_nodes - 1, iterations);
      min_nodes_so_far = patterns->graph.num_nodes;
      failed_iterations = 0;
    }
    else
      failed_iterations++;

    if (failed_iterations >= 30) {
      /* If haven't succeded in 30 last iterations, try to alter variation
       * change probability.
       */
      double delta = gg_drand() / patterns->num_patterns;
      if (change_probability > upper_limit
	  || (change_probability >= lower_limit && gg_rand() % 2 == 0))
	delta = -delta;

      change_probability += delta;
      failed_iterations = 0;
    }
  }

  fprintf(stderr, "\nTotal optimization result: %d => %d states\n",
	  num_nodes_original - 1, min_nodes_so_far - 1);

  dfa_graph_clear(&(patterns->graph));
  return best_variations;
}
Пример #7
0
void
play_solo(Gameinfo *gameinfo, int moves)
{
  SGFTree sgftree;
  int passes = 0; /* num. consecutive passes */
  float move_value;
  double t1, t2;
  int save_moves = moves;

  struct stats_data totalstats;
  int total_owl_count = 0;

  /* It tends not to be very imaginative in the opening,
   * so we scatter a few stones randomly to start with.
   * We add two random numbers to reduce the probability
   * of playing stones near the edge.
   */
  
  int n = 6 + 2*gg_rand()%5;
  int i, j;

  komi = 5.5;

  sgftree_clear(&sgftree);
  sgftreeCreateHeaderNode(&sgftree, board_size, komi, handicap);
  sgf_write_header(sgftree.root, 1, get_random_seed(), 5.5, handicap,
                   get_level(), chinese_rules);
 
  /* Generate some random moves. */
  if (board_size > 6) {
    do {
      do {
	i = (gg_rand() % 4) + (gg_rand() % (board_size - 4));
	j = (gg_rand() % 4) + (gg_rand() % (board_size - 4));
      } while (!is_allowed_move(POS(i, j), gameinfo->to_move));

      gnugo_play_move(POS(i, j), gameinfo->to_move);
      sgftreeAddPlay(&sgftree, gameinfo->to_move, i, j);
      sgftreeAddComment(&sgftree, "random move");
      gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);
    } while (--n > 0);
  }
  
  t1 = gg_cputime();
  memset(&totalstats, '\0', sizeof(totalstats));
  while (passes < 2 && --moves >= 0) {
    int move;
    reset_owl_node_counter();
    move = genmove(gameinfo->to_move, &move_value, NULL);

    gnugo_play_move(move, gameinfo->to_move);
    sgffile_add_debuginfo(sgftree.lastnode, move_value);
    sgftreeAddPlay(&sgftree, gameinfo->to_move, I(move), J(move));
    sgffile_output(&sgftree);
    gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);

    if (move == PASS_MOVE) {
      passes++;
      printf("%s(%d): Pass\n", gameinfo->to_move == BLACK ? "Black" : "White",
	     movenum);
    }
    else {
      passes = 0;
      gprintf("%s(%d): %1m\n", gameinfo->to_move == BLACK ? "Black" : "White",
	      movenum, move);
    }

    totalstats.nodes                    += stats.nodes;
    totalstats.read_result_entered      += stats.read_result_entered;
    totalstats.read_result_hits         += stats.read_result_hits;
    totalstats.trusted_read_result_hits += stats.trusted_read_result_hits;
    total_owl_count                     += get_owl_node_counter();
  }
  t2 = gg_cputime();
  
  /* Two passes and it's over. (EMPTY == BOTH) */
  who_wins(EMPTY, stdout);

  {
    float score = gnugo_estimate_score(NULL, NULL);
    sgfWriteResult(sgftree.root, score, 1);
  }
  sgffile_output(&sgftree);

  printf("%10d moves played in %0.3f seconds\n", save_moves-moves, t2-t1);
  if (save_moves != moves)
    printf("%10.3f seconds/move\n", (t2-t1)/(save_moves-moves));
  
  printf("%10d nodes\n", totalstats.nodes);
  printf("%10d read results entered\n", totalstats.read_result_entered);
  printf("%10d read result hits\n", totalstats.read_result_hits);
  printf("%10d trusted read result hits\n",
	 totalstats.trusted_read_result_hits);
  printf("%10d owl nodes\n", total_owl_count);
}