예제 #1
0
/**
 * @brief Recursive function used to traverse the game tree.
 *
 * @param [in] result a reference to the exact solution data structure
 * @param [in] gp     the game position to traverse
 * @return            a pointer to a new serch node structure
 */
static SearchNode *
game_position_solve_impl (      ExactSolution * const result,
                          const GamePosition  * const gp_old)
{
  SearchNode *node;
  SearchNode *node2;

  node  = NULL;
  node2 = NULL;
  result->node_count++;
 
  NodeInfo * const node_info = &stack->nodes[++stack->fill_point];
  //NodeInfo * const next_node_info = &stack->nodes[stack->fill_point];
  LegalMoveList * const moves = &node_info->moves;
  const SquareSet move_set = game_position_legal_moves(gp_old);
  legal_move_list_from_set(move_set, moves);
  //GamePositionX * const gp = &node_info->gp;
  //GamePositionX * const next_gp = &next_node_info->gp;
  /*
  GamePosition  gp;   
  uint64        hash; 
  */

  if (move_set == empty_square_set) {
    GamePosition *flipped_players = game_position_pass(gp_old);
    const int previous_move_count = stack->nodes[stack->fill_point - 1].moves.move_count;
    const SquareSet empties = board_empties(gp_old->board);
    if (empties != empty_square_set && previous_move_count != 0) {
      node = search_node_negated(game_position_solve_impl(result, flipped_players));
    } else {
      result->leaf_count++;
      node = search_node_new((Square) -1, game_position_final_value(gp_old));
    }
    flipped_players = game_position_free(flipped_players);
  } else {
    node = search_node_new((Square) -1, -65);
    for (int i = 0; i < moves->move_count; i++) {
      const Square move = moves->squares[i];
      GamePosition *gp2 = game_position_make_move(gp_old, move);
      node2 = search_node_negated(game_position_solve_impl(result, gp2));
      gp2 = game_position_free(gp2);
      if (node2->value > node->value) {
        search_node_free(node);
        node = node2;
        node->move = move;
        node2 = NULL;
      } else {
        node2 = search_node_free(node2);
      }
    }
  }

  stack->fill_point--;
  return node;
}
예제 #2
0
static void
game_position_make_move_test (GamePositionDbFixture *fixture,
                              gconstpointer          test_data)
{
  GamePositionDb *db = fixture->db;

  GamePosition *after_make_move;


  GamePosition *initial = get_gp_from_db(db, "initial");
  after_make_move = game_position_make_move(initial, D3);
  GamePosition *first_move_d3 = get_gp_from_db(db, "first-move-d3");
  g_assert(0 == game_position_compare(first_move_d3, after_make_move));
  game_position_free(after_make_move);


  GamePosition *early_game_b_9_moves = get_gp_from_db(db, "early-game-b-9-moves");
  after_make_move = game_position_make_move(early_game_b_9_moves, C3);
  GamePosition *early_game_bc3_10_moves = get_gp_from_db(db, "early-game-bc3-10-moves");
  g_assert(0 == game_position_compare(early_game_bc3_10_moves, after_make_move));
  game_position_free(after_make_move);

  after_make_move = game_position_make_move(early_game_b_9_moves, C6);
  GamePosition *early_game_bc6_10_moves = get_gp_from_db(db, "early-game-bc6-10-moves");
  g_assert(0 == game_position_compare(early_game_bc6_10_moves, after_make_move));
  game_position_free(after_make_move);


  GamePosition *before;
  GamePosition *expected;

  before = get_gp_from_db(db, "make-move-test-case-a-before");
  after_make_move = game_position_make_move(before, D4);
  expected = get_gp_from_db(db, "make-move-test-case-a-after");
  g_assert(0 == game_position_compare(expected, after_make_move));
  game_position_free(after_make_move);

  before = get_gp_from_db(db, "make-move-test-case-b-before");
  after_make_move = game_position_make_move(before, D4);
  expected = get_gp_from_db(db, "make-move-test-case-b-after");
  g_assert(0 == game_position_compare(expected, after_make_move));
  game_position_free(after_make_move);

  before = get_gp_from_db(db, "make-move-test-case-c-before");
  after_make_move = game_position_make_move(before, D4);
  expected = get_gp_from_db(db, "make-move-test-case-c-after");
  g_assert(0 == game_position_compare(expected, after_make_move));
  game_position_free(after_make_move);

  before = get_gp_from_db(db, "make-move-test-case-d-before");
  after_make_move = game_position_make_move(before, B4);
  expected = get_gp_from_db(db, "make-move-test-case-d-after");
  g_assert(0 == game_position_compare(expected, after_make_move));
  game_position_free(after_make_move);
}
예제 #3
0
파일: exact_solver.c 프로젝트: rcrr/reversi
/*
 * Sorts moves in ascending order of mobility.
 */
static void
sort_moves_by_mobility_count (MoveList *move_list,
                              const GamePosition *const gp)
{
    MoveListElement *curr = NULL;
    int move_index = 0;
    const SquareSet moves = game_position_legal_moves(gp);
    SquareSet moves_to_search = moves;
    for (int i = 0; i < legal_moves_priority_cluster_count; i++) {
        moves_to_search = legal_moves_priority_mask[i] & moves;
        while (moves_to_search) {
            curr = &move_list->elements[move_index];
            const Square move = bit_works_bitscanLS1B_64(moves_to_search);
            moves_to_search &= ~(1ULL << move);
            GamePosition *next_gp = game_position_make_move(gp, move);
            const SquareSet next_moves = game_position_legal_moves(next_gp);
            game_position_free(next_gp);
            const int next_move_count = bit_works_bitcount_64(next_moves);
            curr->sq = move;
            curr->mobility = next_move_count;
            for (MoveListElement *element = move_list->head.succ; element != NULL; element = element->succ) {
                if (curr->mobility < element->mobility) { /* Insert current before element. */
                    MoveListElement *left  = element->pred;
                    MoveListElement *right = element;
                    curr->pred  = left;
                    curr->succ  = right;
                    left->succ  = curr;
                    right->pred = curr;
                    goto out;
                }
            }
out:
            move_index++;
        }
    }
    return;
}
예제 #4
0
파일: exact_solver.c 프로젝트: rcrr/reversi
/*
 * Main recursive search function.
 */
static SearchNode *
game_position_solve_impl (ExactSolution *const result,
                          const GamePosition  *const gp,
                          const int achievable,
                          const int cutoff,
                          PVCell ***pve_parent_line_p)
{
    result->node_count++;
    SearchNode *node  = NULL;
    SearchNode *node2 = NULL;
    PVCell **pve_line = NULL;

    if (log_env->log_is_on) {
        call_count++;
        gp_hash_stack_fill_point++;
        LogDataH log_data;
        log_data.sub_run_id = 0;
        log_data.call_id = call_count;
        log_data.hash = game_position_hash(gp);
        gp_hash_stack[gp_hash_stack_fill_point] = log_data.hash;
        log_data.parent_hash = gp_hash_stack[gp_hash_stack_fill_point - 1];
        log_data.blacks = (gp->board)->blacks;
        log_data.whites = (gp->board)->whites;
        log_data.player = gp->player;
        gchar *json_doc = game_tree_log_data_h_json_doc(gp_hash_stack_fill_point, gp);
        log_data.json_doc = json_doc;
        log_data.json_doc_len = strlen(json_doc);
        game_tree_log_write_h(log_env, &log_data);
        g_free(json_doc);
    }

    const SquareSet moves = game_position_legal_moves(gp);
    if (0ULL == moves) {
        pve_line = pve_line_create(pve);
        GamePosition *flipped_players = game_position_pass(gp);
        if (game_position_has_any_legal_move(flipped_players)) {
            node = search_node_negated(game_position_solve_impl(result, flipped_players, -cutoff, -achievable, &pve_line));
        } else {
            result->leaf_count++;
            node = search_node_new(pass_move, game_position_final_value(gp));
        }
        pve_line_add_move(pve, pve_line, pass_move, flipped_players);
        pve_line_delete(pve, *pve_parent_line_p);
        *pve_parent_line_p = pve_line;
        game_position_free(flipped_players);
    } else {
        MoveList move_list;
        bool branch_is_active = false;
        move_list_init(&move_list);
        sort_moves_by_mobility_count(&move_list, gp);
        for (MoveListElement *element = move_list.head.succ; element != &move_list.tail; element = element->succ) {
            const Square move = element->sq;
            if (!node) node = search_node_new(move, (pv_full_recording) ? achievable - 1 : achievable);
            GamePosition *gp2 = game_position_make_move(gp, move);
            pve_line = pve_line_create(pve);
            node2 = search_node_negated(game_position_solve_impl(result, gp2, -cutoff, -node->value, &pve_line));
            if (node2->value > node->value || (!branch_is_active && node2->value == node->value)) {
                branch_is_active = true;
                search_node_free(node);
                node = node2;
                node->move = move;
                node2 = NULL;
                pve_line_add_move(pve, pve_line, move, gp2);
                game_position_free(gp2);
                pve_line_delete(pve, *pve_parent_line_p);
                *pve_parent_line_p = pve_line;
                if (node->value > cutoff) goto out;
                if (!pv_full_recording && node->value == cutoff) goto out;
            } else {
                if (pv_full_recording && node2->value == node->value) {
                    pve_line_add_move(pve, pve_line, move, gp2);
                    pve_line_add_variant(pve, *pve_parent_line_p, pve_line);
                } else {
                    pve_line_delete(pve, pve_line);
                }
                search_node_free(node2);
                game_position_free(gp2);
            }
        }
    }
out:
    if (log_env->log_is_on) {
        gp_hash_stack_fill_point--;
    }
    return node;
}