Esempio n. 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;
}
Esempio n. 2
0
int exomizer(unsigned char *srcbuf, int len, int load, int start, unsigned char *destbuf)
{
    int destlen;
    int max_offset = 65536;
    int max_passes = 65536;
    static match_ctx ctx;
    encode_match_data emd;
    encode_match_priv optimal_priv;
    search_nodep snp;

    match_ctx_init(ctx, srcbuf, len, max_offset);

    emd->out = NULL;
    emd->priv = optimal_priv;

    optimal_init(emd);

    snp = do_compress(ctx, emd, max_passes);

    destlen = generate_output(ctx, snp, sfx_c64ne, optimal_encode, emd,
                              load, len, start, destbuf);
    optimal_free(emd);

#if 0 /* RH */
    search_node_free(snp);
#endif /* RH */
    match_ctx_free(ctx);

    return destlen;
}
Esempio n. 3
0
void crunch_backwards(struct membuf *inbuf,
                      struct membuf *outbuf,
                      struct crunch_options *options, /* IN */
                      struct crunch_info *info) /* OUT */
{
    static match_ctx ctx;
    encode_match_data emd;
    search_nodep snp;
    int outlen;
    int safety;
    int copy_used;

    if(options == NULL)
    {
        options = default_options;
    }

    outlen = membuf_memlen(outbuf);
    emd->out = NULL;
    optimal_init(emd);

    LOG(LOG_NORMAL,
        ("\nPhase 1: Instrumenting file"
         "\n-----------------------------\n"));
    LOG(LOG_NORMAL, (" Length of indata: %d bytes.\n", membuf_memlen(inbuf)));

    match_ctx_init(ctx, inbuf, options->max_len, options->max_offset,
                   options->use_imprecise_rle);

    LOG(LOG_NORMAL, (" Instrumenting file, done.\n"));

    emd->out = NULL;
    optimal_init(emd);

    LOG(LOG_NORMAL,
        ("\nPhase 2: Calculating encoding"
         "\n-----------------------------\n"));
    snp = do_compress(ctx, emd, options->exported_encoding,
                      options->max_passes, options->use_literal_sequences);
    LOG(LOG_NORMAL, (" Calculating encoding, done.\n"));

    LOG(LOG_NORMAL,
        ("\nPhase 3: Generating output file"
         "\n------------------------------\n"));
    LOG(LOG_NORMAL, (" Encoding: %s\n", optimal_encoding_export(emd)));
    safety = do_output(ctx, snp, emd, optimal_encode, outbuf, &copy_used);
    LOG(LOG_NORMAL, (" Length of crunched data: %d bytes.\n",
                     membuf_memlen(outbuf) - outlen));

    optimal_free(emd);
    search_node_free(snp);
    match_ctx_free(ctx);

    if(info != NULL)
    {
        info->literal_sequences_used = copy_used;
        info->needed_safety_offset = safety;
    }
}
Esempio n. 4
0
/**
 * @brief Solves the game position returning a new exact solution pointer.
 *
 * @param [in] root the starting game position to be solved
 * @return          a pointer to a new exact solution structure
 */
ExactSolution *
game_position_rab_solve (const GamePosition * const root)
{
  ExactSolution *result; 
  SearchNode    *sn;

  game_tree_stack_init();
  
  result = exact_solution_new();

  result->solved_game_position = game_position_clone(root);

  sn = game_position_solve_impl(result, result->solved_game_position);

  result->principal_variation[0] = sn->move;
  result->outcome = sn->value;
  sn = search_node_free(sn);

  return result;
}
Esempio n. 5
0
/*
 * 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;
}
Esempio n. 6
0
/**
 * @brief Solves the game position returning a new exact solution pointer.
 *
 * @invariant Parameters `root` and `env` must be not `NULL`.
 *             The invariants are guarded by assertions.
 *
 * @param [in] root     the starting game position to be solved
 * @param [in] env      parameter envelope
 * @return              a pointer to a new exact solution structure
 */
ExactSolution *
game_position_es_solve (const GamePositionX *const root,
                        const endgame_solver_env_t *const env)
{
    g_assert(root);
    g_assert(env);

    ExactSolution *result;
    SearchNode    *sn;
    int            alpha;
    int            beta;

    pv_full_recording = env->pv_full_recording;

    log_env = game_tree_log_init(env->log_file);

    //GamePositionX *rootx = game_position_x_gp_to_gpx(root);
    pve = pve_new(root);
    //game_position_x_free(rootx);

    if (log_env->log_is_on) {
        gp_hash_stack[0] = 0;
        game_tree_log_open_h(log_env);
    }

    if (pv_full_recording) {
        alpha = out_of_range_defeat_score;
        beta = out_of_range_win_score;
    } else {
        alpha = worst_score;
        beta = best_score;
    }

    result = exact_solution_new();

    result->solved_game_position = game_position_clone(game_position_x_gpx_to_gp(root));

    sn = game_position_solve_impl(result,
                                  result->solved_game_position,
                                  alpha,
                                  beta,
                                  &(pve->root_line));


    if (sn) {
        result->pv[0] = sn->move;
        result->outcome = sn->value;
        pve_line_copy_to_exact_solution(pve, (const PVCell **const) pve->root_line, result);
        exact_solution_compute_final_board(result);
    }

    if (pv_full_recording && !env->pv_no_print) {
        printf("\n --- --- pve_line_with_variants_to_string() START --- ---\n");
        pve_line_with_variants_to_stream(pve, stdout);
        printf("\n --- --- pve_line_with_variants_to_string() COMPLETED --- ---\n");
    }

    if (pv_internals_to_stream) {
        printf("\nThe constant \"pv_internals_to_stream\", in source file \"exact_solver.c\", is TRUE. Printing PVE internals:\n");
        printf(" --- --- pve_is_invariant_satisfied() START --- ---\n");
        pve_error_code_t error_code = 0;
        pve_is_invariant_satisfied(pve, &error_code, 0xFF);
        if (error_code) {
            printf("error_code=%d\n", error_code);
            abort();
        }
        printf(" --- --- pve_is_invariant_satisfied() COMPLETED --- ---\n");

        printf("\n --- --- pve_internals_to_stream() START --- ---\n");
        switches_t shown_sections = 0x0000;
        shown_sections |= pve_internals_header_section;
        shown_sections |= pve_internals_index_section;
        shown_sections |= pve_internals_properties_section;
        shown_sections |= pve_internals_structure_section;
        shown_sections |= pve_internals_computed_properties_section;
        //shown_sections |= pve_internals_active_lines_section;
        shown_sections |= pve_internals_cells_segments_section;
        shown_sections |= pve_internals_sorted_cells_segments_section;
        shown_sections |= pve_internals_cells_section;
        shown_sections |= pve_internals_cells_stack_section;
        shown_sections |= pve_internals_lines_segments_section;
        shown_sections |= pve_internals_sorted_lines_segments_section;
        shown_sections |= pve_internals_lines_section;
        shown_sections |= pve_internals_lines_stack_section;
        pve_internals_to_stream(pve, stdout, shown_sections);
        printf("\n --- --- pve_internals_to_stream() COMPLETED --- ---\n");
    }

    if (env->pve_dump_file) {
        printf("\n --- --- pve_dump_to_binary_file() START --- ---\n");
        pve_dump_to_binary_file(pve, env->pve_dump_file);
        printf(" --- --- pve_dump_to_binary_file() COMPLETED --- ---\n");
    }

    search_node_free(sn);
    pve_free(pve);

    game_tree_log_close(log_env);

    return result;
}
Esempio n. 7
0
search_nodep
do_compress(match_ctx ctx, encode_match_data emd,
            const char *exported_encoding,
            int max_passes,
            int use_literal_sequences)
{
    matchp_cache_enum mpce;
    matchp_snp_enum snpe;
    search_nodep snp;
    search_nodep best_snp;
    int pass;
    float size;
    float old_size;
    char prev_enc[100];
    const char *curr_enc;

    pass = 1;
    prev_enc[0] = '\0';

    LOG(LOG_NORMAL, (" pass %d: ", pass));
    if(exported_encoding != NULL)
    {
        LOG(LOG_NORMAL, ("importing %s\n", exported_encoding));
        optimal_encoding_import(emd, exported_encoding);
    }
    else
    {
        LOG(LOG_NORMAL, ("optimizing ..\n"));
        matchp_cache_get_enum(ctx, mpce);
        optimal_optimize(emd, matchp_cache_enum_get_next, mpce);
    }

    best_snp = NULL;
    old_size = 100000000.0;

    for (;;)
    {
        snp = search_buffer(ctx, optimal_encode, emd,
                            use_literal_sequences);
        if (snp == NULL)
        {
            LOG(LOG_ERROR, ("error: search_buffer() returned NULL\n"));
            exit(-1);
        }

        size = snp->total_score;
        LOG(LOG_NORMAL, ("  size %0.1f bits ~%d bytes\n",
                         size, (((int) size) + 7) >> 3));

        if (size >= old_size)
        {
            search_node_free(snp);
            break;
        }

        if (best_snp != NULL)
        {
            search_node_free(best_snp);
        }
        best_snp = snp;
        old_size = size;
        ++pass;

        if(pass > max_passes)
        {
            break;
        }

        optimal_free(emd);
        optimal_init(emd);

        LOG(LOG_NORMAL, (" pass %d: optimizing ..\n", pass));

        matchp_snp_get_enum(snp, snpe);
        optimal_optimize(emd, matchp_snp_enum_get_next, snpe);

        curr_enc = optimal_encoding_export(emd);
        if (strcmp(curr_enc, prev_enc) == 0)
        {
            break;
        }
        strcpy(prev_enc, curr_enc);
    }

    return best_snp;
}
Esempio n. 8
0
static
search_nodep
do_compress(match_ctx ctx, encode_match_data emd, int max_passes)
{
    matchp_cache_enum mpce;
    matchp_snp_enum snpe;
    search_nodep snp;
    search_nodep best_snp;
    int pass;
    float old_size;

    pass = 1;

    matchp_cache_get_enum(ctx, mpce);
    optimal_optimize(emd, matchp_cache_enum_get_next, mpce);

    best_snp = NULL;
    old_size = 1000000.0;

    for (;;)
    {
        snp = search_buffer(ctx, optimal_encode, emd);
        if (snp == NULL)
        {
            fprintf(stderr, "error: search_buffer() returned NULL\n");
            exit(-1);
        }

        float size = snp->total_score;
        if (size >= old_size)
        {
#if 0 /* RH */
            search_node_free(snp);
#endif /* RH */
            break;
        }

#if 0 /* RH */
        if (best_snp != NULL)
        {
            search_node_free(best_snp);
        }
#endif /* RH */
        best_snp = snp;
        old_size = size;
        ++pass;

        if (pass > max_passes)
        {
            break;
        }

        optimal_free(emd);
        optimal_init(emd);

        matchp_snp_get_enum(snp, snpe);
        optimal_optimize(emd, matchp_snp_enum_get_next, snpe);
    }

    return best_snp;
}