Example #1
0
 UInt64 virtual_size() const {
   return sizeof(Header)
       + (sizeof(Entry) * num_keys())
       + (sizeof(Block) * num_blocks())
       + (sizeof(Node) * num_nodes())
       + total_key_length();
 }
Example #2
0
int main() {
  Hash_map hash_map;
  Data data= (Data) 123;
  Key key= (Key) 456;

  mcheck_pedantic(NULL);

  hash_map= create_example_hash_map();

  /* calling some of the functions with an empty Hash_map */
  if (!get(&hash_map, (Key) (long) 1, &data) &&
      !get_smallest(hash_map, &key, &data) &&  num_keys(hash_map, 0) == 0 &&
      index_of(hash_map, (Key) (long) 5) == -1 && data == (Data) 123 &&
      key == (Key) 456)
    printf("Your functions can handle an empty hash_map correctly!\n");
  else printf("Oops!  Error in handling anempty hash_map.\n");

  clear(&hash_map);

  if (mallinfo().uordblks != 0)
    printf("Memory leak of %d bytes. :(\n", mallinfo().uordblks);
  else printf("No memory leak detected. :)\n");

  return 0;
}
Example #3
0
void iterate(solution *sol, char *filename) {
    size_t num_states = num_keys(sol->d);

    int changed = 1;
    while (changed) {
        changed = 0;
        for (size_t j = 0; j < sol->num_layers; j++) {
            size_t key;
            size_t i;
            int tid;
            int num_threads;
            #pragma omp parallel private(i, key, tid, num_threads)
            {
                num_threads = omp_get_num_threads();
                state s_;
                state *s = &s_;
                tid = omp_get_thread_num();
                key = sol->d->min_key;
                for (i = 0; i < num_states; i++) {
                    if (i % num_threads == tid) {
                        assert(from_key_s(sol, s, key, j));
                        node_value new_v = negamax_node(sol, s, key, j, 1);
                        assert(new_v.low >= sol->base_nodes[j][i].low);
                        assert(new_v.high <= sol->base_nodes[j][i].high);
                        changed = changed || !equal(sol->base_nodes[j][i], new_v);
                        sol->base_nodes[j][i] = new_v;
                    }
                    key = next_key(sol->d, key);
                }
                #pragma omp for
                for (i = 0; i < sol->ko_ld->num_keys; i++) {
                    key = sol->ko_ld->keys[i];
                    assert(from_key_ko(sol, s, key, j));
                    node_value new_v = negamax_node(sol, s, key, j, 1);
                    assert(new_v.low >= sol->ko_nodes[j][i].low);
                    assert(new_v.high <= sol->ko_nodes[j][i].high);
                    changed = changed || !equal(sol->ko_nodes[j][i], new_v);
                    sol->ko_nodes[j][i] = new_v;
                }
            }
        }
        size_t base_layer;
        size_t base_key = to_key_s(sol, sol->base_state, &base_layer);

        printf("Saving...\n");  // TODO: Prevent data corruption by catching Ctrl+C.
        FILE *f = fopen(filename, "wb");
        save_solution(sol, f);
        fclose(f);
        print_node(negamax_node(sol, sol->base_state, base_key, base_layer, 0));
        // Verify solution integrity. For debugging only. Leaks memory.
        // char *buffer = file_to_buffer(filename);
        // buffer = load_solution(sol, buffer, 0);
    }
}
Example #4
0
void upgrade(int argc, char *argv[]) {
    parse_args(argc - 1, argv + 1);

    solution sol_;
    solution *sol = &sol_;
    char *buffer = file_to_buffer(tsumego_name);  // Not really a tsumego name. Needs extension too.
    buffer = load_solution(sol, buffer, 1);

    if (sol->si->color_symmetry) {
        num_layers = 2 * abs(ko_threats) + 1;
    }
    else if (num_layers <= 0) {
        num_layers = abs(ko_threats) + 1;
    }

    sol->base_nodes = (node_value**) realloc(sol->base_nodes, sol->num_layers * sizeof(node_value*));
    sol->ko_nodes = (node_value**) realloc(sol->ko_nodes, sol->num_layers * sizeof(node_value*));

    size_t zero_layer = abs(sol->base_state->ko_threats);
    size_t new_zero_layer = abs(ko_threats);

    sol->base_nodes[new_zero_layer] = sol->base_nodes[zero_layer];
    sol->ko_nodes[new_zero_layer] = sol->ko_nodes[zero_layer];

    sol->base_state->ko_threats = ko_threats;
    sol->num_layers = num_layers;

    size_t num_states = num_keys(sol->d);
    for (size_t k = 0; k < sol->num_layers; k++) {
        if (k == new_zero_layer) {
            continue;
        }
        sol->base_nodes[k] = (node_value*) malloc(num_states * sizeof(node_value));
        for (size_t i = 0; i < num_states; i++) {
            (sol->base_nodes[k])[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        }
    }

    for (size_t k = 0; k < sol->num_layers; k++) {
        if (k == new_zero_layer) {
            continue;
        }
        sol->ko_nodes[k] = (node_value*) malloc(sol->ko_ld->num_keys * sizeof(node_value));
        for (size_t i = 0; i < sol->ko_ld->num_keys; i++) {
            sol->ko_nodes[k][i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        }
    }

    FILE *f = fopen(tsumego_name, "wb");
    save_solution(sol, f);
    fclose(f);
    printf("Done!\n");
}
Example #5
0
int main(int argc, char *argv[]) {
    num_solutions = argc - 2;
    solution_names = argv + 2;
    sols = (solution**) malloc(num_solutions * sizeof(solution*));
    for (int i = 0; i < num_solutions; i++) {
        sols[i] = mmap_solution(solution_names[i]);
        #ifdef DEBUG
            printf("%s\n", solution_names[i]);
            printf("Number of unique positions: %zu\n", num_keys(sols[i]->d));
            printf("Number of positions with ko: %zu\n", sols[i]->ko_ld->num_keys);
        #endif
        repr_state(sols[i]->base_state);
        printf("%zu\n", sols[i]->num_layers);
    }

    printf("Solutions loaded.\n");

    serve(argv[1]);
    // TODO: Cleanup.
    return 0;
}
 /// Return iterator to the ending+1 value with key == id 
 inline const_iterator end(size_t id) const {
   return (id+1) < num_keys() ? value_ptrs[id+1] : values.end();
 }
  /// Return iterator to the begining value with key == id 
  inline const_iterator begin(size_t id) const {
 	 //logstream(LOG_INFO) << "disk debug. vid in mem=" << id << std::endl;
    return id < num_keys() ? value_ptrs[id] : values.end();
  } 
  /// Return iterator to the ending+1 value with key == id 
  inline iterator end(size_t id) {
 	 //logstream(LOG_INFO) << "disk debug. id=" << id << std::endl;
    return (id+1) < num_keys() ? value_ptrs[id+1] : values.end();
  }
 /// Return iterator to the begining value with key == id
 inline iterator begin(size_t id) {
   return id < num_keys() ? value_ptrs[id] : values.end();
 }
Example #10
0
int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage: %s width height\n", argv[0]);
        return 0;
    }
    int width = atoi(argv[1]);
    int height = atoi(argv[2]);
    if (width <= 0) {
        printf("Width must be larger than 0.\n");
        return 0;
    }
    if (width >= 7) {
        printf("Width must be less than 7.\n");
        return 0;
    }
    if (height <= 0) {
        printf("Height must be larger than 0.\n");
        return 0;
    }
    if (height >= 6) {
        printf("Height must be less than 6.\n");
        return 0;
    }

    state s_ = (state) {rectangle(width, height), 0, 0, 0, 0};
    state *s = &s_;

    dict d_;
    dict *d = &d_;

    size_t max_k = max_key(s);
    init_dict(d, max_k);

    size_t key_min = ~0;
    size_t key_max = 0;

    size_t total_legal = 0;
    for (size_t k = 0; k < max_k; k++) {
        if (!from_key(s, k)){
            continue;
        }
        total_legal++;
        canonize(s);
        size_t key = to_key(s);
        add_key(d, key);
        if (key < key_min) {
            key_min = key;
        }
        if (key > key_max) {
            key_max = key;
        }
    }
    resize_dict(d, key_max);
    finalize_dict(d);
    size_t num_states = num_keys(d);

    printf("Total legal positions %zu\n", total_legal);
    printf("Total unique positions %zu\n", num_states);

    node_value *base_nodes = (node_value*) malloc(num_states * sizeof(node_value));
    node_value *pass_nodes = (node_value*) malloc(num_states * sizeof(node_value));
    value_t *leaf_nodes = (value_t*) malloc(num_states * sizeof(value_t));

    lin_dict ko_ld_ = (lin_dict) {0, 0, 0, NULL};
    lin_dict *ko_ld = &ko_ld_;

    state child_;
    state *child = &child_;
    size_t child_key;
    size_t key = key_min;
    for (size_t i = 0; i < num_states; i++) {
        assert(from_key(s, key));
        value_t score = liberty_score(s);
        leaf_nodes[i] = score;
        pass_nodes[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        base_nodes[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        for (int j = 0; j < STATE_SIZE; j++) {
            *child = *s;
            if (make_move(child, 1UL << j)) {
                if (child->ko) {
                    canonize(child);
                    child_key = to_key(child) * STATE_SIZE + bitscan(child->ko);
                    add_lin_key(ko_ld, child_key);
                }
            }
        }
        key = next_key(d, key);
    }

    finalize_lin_dict(ko_ld);

    node_value *ko_nodes = (node_value*) malloc(ko_ld->num_keys * sizeof(node_value));
    printf("Unique positions with ko %zu\n", ko_ld->num_keys);

    for (size_t i = 0; i < ko_ld->num_keys; i++) {
        ko_nodes[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
    }

    #ifndef PRELOAD
    printf("Negamax with Chinese rules.\n");
    iterate(
        d, ko_ld,
        base_nodes, pass_nodes, ko_nodes, leaf_nodes,
        s, key_min, 0
    );
    #endif

    char dir_name[16];
    sprintf(dir_name, "%dx%d", width, height);
    struct stat sb;
    if (stat(dir_name, &sb) == -1) {
        mkdir(dir_name, 0700);
    }
    assert(chdir(dir_name) == 0);
    FILE *f;

    #ifndef PRELOAD
    f = fopen("d_slots.dat", "wb");
    fwrite((void*) d->slots, sizeof(slot_t), d->num_slots, f);
    fclose(f);
    f = fopen("d_checkpoints.dat", "wb");
    fwrite((void*) d->checkpoints, sizeof(size_t), (d->num_slots >> 4) + 1, f);
    fclose(f);
    f = fopen("ko_ld_keys.dat", "wb");
    fwrite((void*) ko_ld->keys, sizeof(size_t), ko_ld->num_keys, f);
    fclose(f);

    f = fopen("base_nodes.dat", "wb");
    fwrite((void*) base_nodes, sizeof(node_value), num_states, f);
    fclose(f);
    f = fopen("pass_nodes.dat", "wb");
    fwrite((void*) pass_nodes, sizeof(node_value), num_states, f);
    fclose(f);
    f = fopen("leaf_nodes.dat", "wb");
    fwrite((void*) leaf_nodes, sizeof(value_t), num_states, f);
    fclose(f);
    f = fopen("ko_nodes.dat", "wb");
    fwrite((void*) ko_nodes, sizeof(node_value), ko_ld->num_keys, f);
    fclose(f);
    #endif

    #ifdef PRELOAD
    f = fopen("base_nodes.dat", "rb");
    fread((void*) base_nodes, sizeof(node_value), num_states, f);
    fclose(f);
    f = fopen("pass_nodes.dat", "rb");
    fread((void*) pass_nodes, sizeof(node_value), num_states, f);
    fclose(f);
    f = fopen("leaf_nodes.dat", "rb");
    fread((void*) leaf_nodes, sizeof(value_t), num_states, f);
    fclose(f);
    f = fopen("ko_nodes.dat", "rb");
    fread((void*) ko_nodes, sizeof(node_value), ko_ld->num_keys, f);
    fclose(f);
    #endif

    // Japanese leaf state calculation.
    state new_s_;
    state *new_s = &new_s_;
    key = key_min;
    for (size_t i = 0; i < num_states; i++) {
        assert(from_key(s, key));
        stones_t empty = s->playing_area & ~(s->player | s->opponent);

        *new_s = *s;
        endstate(
            d, ko_ld,
            base_nodes, pass_nodes, ko_nodes,
            new_s, base_nodes[i], 0, 1
        );

        stones_t player_controlled = new_s->player | liberties(new_s->player, new_s->playing_area & ~new_s->opponent);
        stones_t opponent_controlled = new_s->opponent | liberties(new_s->opponent, new_s->playing_area & ~new_s->player);
        value_t score = popcount(player_controlled & empty) - popcount(opponent_controlled & empty);
        score += 2 * (popcount(player_controlled & s->opponent) - popcount(opponent_controlled & s->player));
        leaf_nodes[i] = score;

        *new_s = *s;
        endstate(
            d, ko_ld,
            base_nodes, pass_nodes, ko_nodes,
            new_s, base_nodes[i], 0, 0
        );

        player_controlled = new_s->player | liberties(new_s->player, new_s->playing_area & ~new_s->opponent);
        opponent_controlled = new_s->opponent | liberties(new_s->opponent, new_s->playing_area & ~new_s->player);
        score = popcount(player_controlled & empty) - popcount(opponent_controlled & empty);
        score += 2 * (popcount(player_controlled & s->opponent) - popcount(opponent_controlled & s->player));
        leaf_nodes[i] += score;

        key = next_key(d, key);
    }

    // Clear the rest of the tree.
    for (size_t i = 0; i < num_states; i++) {
        pass_nodes[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        base_nodes[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
    }
    for (size_t i = 0; i < ko_ld->num_keys; i++) {
        ko_nodes[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
    }

    printf("Negamax with Japanese rules.\n");
    iterate(
        d, ko_ld,
        base_nodes, pass_nodes, ko_nodes, leaf_nodes,
        s, key_min, 1
    );

    f = fopen("base_nodes_j.dat", "wb");
    fwrite((void*) base_nodes, sizeof(node_value), num_states, f);
    fclose(f);
    f = fopen("pass_nodes_j.dat", "wb");
    fwrite((void*) pass_nodes, sizeof(node_value), num_states, f);
    fclose(f);
    f = fopen("leaf_nodes_j.dat", "wb");
    fwrite((void*) leaf_nodes, sizeof(value_t), num_states, f);
    fclose(f);
    f = fopen("ko_nodes_j.dat", "wb");
    fwrite((void*) ko_nodes, sizeof(node_value), ko_ld->num_keys, f);
    fclose(f);

    return 0;
}
Example #11
0
void iterate(
        dict *d, lin_dict *ko_ld,
        node_value *base_nodes, node_value *pass_nodes, node_value *ko_nodes, value_t *leaf_nodes,
        state *s, size_t key_min, int japanese_rules
    ) {
    state child_;
    state *child = &child_;

    size_t num_states = num_keys(d);

    int changed = 1;
    while (changed) {
        changed = 0;
        size_t key = key_min;
        for (size_t i = 0; i < 2 * num_states + ko_ld->num_keys; i++) {
            if (i < 2 * num_states) {
                assert(from_key(s, key));
                if (i % 2 == 1) {
                    s->passes = 1;
                }
            }
            else {
                key = ko_ld->keys[i - 2 * num_states];
                size_t ko_pos = key % STATE_SIZE;
                key /= STATE_SIZE;
                assert(from_key(s, key));
                s->ko = 1UL << ko_pos;
            }
            node_value new_v = (node_value) {VALUE_MIN, VALUE_MIN, DISTANCE_MAX, 0};
            for (int j = -1; j < STATE_SIZE; j++) {
                size_t child_key;
                node_value child_v;
                *child = *s;
                stones_t move;
                if (j == -1){
                    move = 0;
                }
                else {
                    move = 1UL << j;
                }
                if (make_move(child, move)) {
                    canonize(child);
                    child_key = to_key(child);
                    if (child->passes == 2){
                        value_t score = leaf_nodes[key_index(d, child_key)];
                        child_v = (node_value) {score, score, 0, 0};
                    }
                    else if (child->passes == 1) {
                        child_v = pass_nodes[key_index(d, child_key)];
                    }
                    else if (child->ko) {
                        child_key = child_key * STATE_SIZE + bitscan(child->ko);
                        child_v = ko_nodes[lin_key_index(ko_ld, child_key)];
                    }
                    else {
                        child_v = base_nodes[key_index(d, child_key)];
                    }
                    if (japanese_rules) {
                        int prisoners = (popcount(s->opponent) - popcount(child->player)) * PRISONER_VALUE;
                        if (child_v.low > VALUE_MIN) {
                            child_v.low = child_v.low - prisoners;
                        }
                        if (child_v.high < VALUE_MAX) {
                            child_v.high = child_v.high - prisoners;
                        }
                    }
                    new_v = negamax(new_v, child_v);
                }
            }
            assert(new_v.high_distance > 0);
            if (i < 2 * num_states) {
                if (i % 2 == 0) {
                    assert(new_v.low_distance > 1);
                    assert(new_v.high_distance > 1);
                    assert(new_v.low >= base_nodes[i / 2].low);
                    assert(new_v.high <= base_nodes[i / 2].high);
                    changed = changed || !equal(base_nodes[i / 2], new_v);
                    base_nodes[i / 2] = new_v;
                }
                else {
                    changed = changed || !equal(pass_nodes[i / 2], new_v);
                    pass_nodes[i / 2] = new_v;
                    key = next_key(d, key);
                }
            }
            else {
                changed = changed || !equal(ko_nodes[i - 2 * num_states], new_v);
                ko_nodes[i - 2 * num_states] = new_v;
            }
        }
        print_node(base_nodes[0]);
    }
    for (size_t i = 0; i < ko_ld->num_keys; i++) {
        assert(ko_nodes[i].low_distance > 2);
        assert(ko_nodes[i].high_distance > 2);
    }

    for (size_t i = 0; i < num_states; i++) {
        assert(base_nodes[i].low_distance > 1);
        assert(base_nodes[i].high_distance > 1);
        assert(pass_nodes[i].low_distance > 0);
        assert(pass_nodes[i].high_distance > 0);
    }
}
Example #12
0
int main(int argc, char **argv) {
    char *list_in;
    char *file_out;
    double ratio;

    if (argc != 3 && argc != 4) {
        printf("Usage: %s <list.txt> <outfile> [window_radius]\n", argv[0]);
        return EXIT_FAILURE;
    }

    list_in = argv[1];
    ratio = 0.6;
    file_out = argv[2];

    int window_radius = -1;
    if (argc == 4) {
        window_radius = atoi(argv[3]);
    }

    clock_t start = clock();

    /* Read the list of files */
    std::vector<std::string> key_files;
    if (ReadFileList(list_in, key_files) != 0) return EXIT_FAILURE;

    FILE *f;
    if ((f = fopen(file_out, "w")) == NULL) {
        printf("Could not open %s for writing.\n", file_out);
        return EXIT_FAILURE;
    }

    int num_images = (int) key_files.size();

    std::vector<unsigned char*> keys(num_images);
    std::vector<int> num_keys(num_images);

    /* Read all keys */
    for (int i = 0; i < num_images; i++) {
        keys[i] = NULL;
        num_keys[i] = ReadKeyFile(key_files[i].c_str(), &keys[i]);
    }

    clock_t end = clock();
    printf("[KeyMatchFull] Reading keys took %0.3fs\n", 
           (end - start) / ((double) CLOCKS_PER_SEC));

    for (int i = 0; i < num_images; i++) {
        if (num_keys[i] == 0)
            continue;

        printf("[KeyMatchFull] Matching to image %d\n", i);

        start = clock();

        /* Create a tree from the keys */
        ANNkd_tree *tree = CreateSearchTree(num_keys[i], keys[i]);

        /* Compute the start index */
        int start_idx = 0;
        if (window_radius > 0) 
            start_idx = std::max(i - window_radius, 0);

        for (int j = start_idx; j < i; j++) {
            if (num_keys[j] == 0)
                continue;

            /* Compute likely matches between two sets of keypoints */
            std::vector<KeypointMatch> matches = 
                MatchKeys(num_keys[j], keys[j], tree, ratio);

            int num_matches = (int) matches.size();

            if (num_matches >= 16) {
                /* Write the pair */
                fprintf(f, "%d %d\n", j, i);

                /* Write the number of matches */
                fprintf(f, "%d\n", (int) matches.size());

                for (int i = 0; i < num_matches; i++) {
                    fprintf(f, "%d %d\n", 
                            matches[i].m_idx1, matches[i].m_idx2);
                }
            }
        }

        end = clock();
        printf("[KeyMatchFull] Matching took %0.3fs\n", 
               (end - start) / ((double) CLOCKS_PER_SEC));
        fflush(stdout);

        delete tree;
    }

    /* Free keypoints */
    for (int i = 0; i < num_images; i++) {
        if (keys[i] != NULL)
            delete [] keys[i];
    }

    fclose(f);
    return EXIT_SUCCESS;
}
Example #13
0
 UInt32 max_key_id() const {
   return num_keys();
 }
Example #14
0
int main(int argc, char *argv[]) {
    #ifdef TEST
        test();
        return 0;
    #endif
    #ifdef REPAIR
        repair(argc, argv);
        return 0;
    #endif
    #ifdef UPGRADE
        upgrade(argc, argv);
        return 0;
    #endif

    int load_sol = 0;
    int resume_sol = 0;
    if (strcmp(argv[argc - 1], "load") == 0) {
        load_sol = 1;
        argc--;
    }
    if (strcmp(argv[argc - 1], "resume") == 0) {
        resume_sol = 1;
        argc--;
    }
    parse_args(argc - 1, argv + 1);

    int width = board_width;
    int height = board_height;
    if (board_width >= 10) {
        fprintf(stderr, "Width must be less than 10.\n");
        exit(EXIT_FAILURE);
    }
    if (board_height >= 8) {
        fprintf(stderr, "Height must be less than 8.\n");
        exit(EXIT_FAILURE);
    }

    #include "tsumego.c"

    state base_state_;
    state *base_state = &base_state_;

    char sol_name[64] = "unknown";
    char temp_filename[128];
    char filename[128];
    if (board_width > 0) {
        *base_state = (state) {rectangle(width, height), 0, 0, 0, 0};
        sprintf(sol_name, "%dx%d", width, height);
    }
    else {
        int i;
        int found = 0;

        for (i = 0; tsumego_infos[i].name; ++i) {
            if (!strcmp(tsumego_name, tsumego_infos[i].name)) {
                *base_state = *(tsumego_infos[i].state);
                strcpy(sol_name, tsumego_name);
                found = 1;
                break;
            }
        }
        if (!found) {
            fprintf(stderr, "unknown tsumego: `%s'\n", tsumego_name);
            exit(EXIT_FAILURE);
        }
    }
    base_state->ko_threats = ko_threats;

    sprintf(temp_filename, "%s_temp.dat", sol_name);


    state_info si_;
    state_info *si = &si_;
    init_state(base_state, si);

    if (si->color_symmetry) {
        num_layers = 2 * abs(base_state->ko_threats) + 1;
    }
    else if (num_layers <= 0) {
        num_layers = abs(base_state->ko_threats) + 1;
    }
    else {
        assert(num_layers >= abs(base_state->ko_threats) + 1);
    }

    print_state(base_state);
    for (int i = 0; i < si->num_external; i++) {
        print_stones(si->externals[i]);
    }
    printf(
        "width=%d height=%d c=%d v=%d h=%d d=%d\n",
        si->width,
        si->height,
        si->color_symmetry,
        si->mirror_v_symmetry,
        si->mirror_h_symmetry,
        si->mirror_d_symmetry
    );

    state s_;
    state *s = &s_;

    dict d_;
    dict *d = &d_;

    solution sol_;
    solution *sol = &sol_;
    sol->base_state = base_state;
    sol->si = si;
    sol->d = d;
    sol->num_layers = num_layers;
    size_t num_states;

    // Re-used at frontend. TODO: Allocate a different pointer.
    state child_;
    state *child = &child_;

    if (load_sol) {
        goto frontend;
    }

    if (resume_sol) {
        char *buffer = file_to_buffer(temp_filename);
        buffer = load_solution(sol, buffer, 1);
        num_states = num_keys(sol->d);
        if (sol->leaf_rule == japanese_double_liberty) {
            goto iterate_capture;
        }
        else {
            goto iterate_japanese;
        }
    }

    size_t k_size = key_size(sol->si);
    if (!sol->si->color_symmetry) {
        k_size *= 2;
    }
    init_dict(sol->d, k_size);

    size_t total_legal = 0;
    for (size_t k = 0; k < k_size; k++) {
        if (!from_key_s(sol, s, k, 0)){
            continue;
        }
        total_legal++;
        size_t layer;
        size_t key = to_key_s(sol, s, &layer);
        assert(layer == 0);
        add_key(sol->d, key);
    }
    finalize_dict(sol->d);
    num_states = num_keys(sol->d);

    printf("Total positions %zu\n", total_legal);
    printf("Total unique positions %zu\n", num_states);

    node_value **base_nodes = (node_value**) malloc(sol->num_layers * sizeof(node_value*));
    for (size_t i = 0; i < sol->num_layers; i++) {
        base_nodes[i] = (node_value*) malloc(num_states * sizeof(node_value));
    }
    value_t *leaf_nodes = (value_t*) malloc(num_states * sizeof(value_t));

    lin_dict ko_ld_ = (lin_dict) {0, 0, 0, NULL};
    lin_dict *ko_ld = &ko_ld_;

    sol->base_nodes = base_nodes;
    sol->leaf_nodes = leaf_nodes;
    sol->ko_ld = ko_ld;

    size_t child_key;
    size_t key = sol->d->min_key;
    for (size_t i = 0; i < num_states; i++) {
        assert(from_key_s(sol, s, key, 0));
        // size_t layer;
        // assert(to_key_s(sol, s, &layer) == key);
        sol->leaf_nodes[i] = 0;
        for (size_t k = 0; k < sol->num_layers; k++) {
            (sol->base_nodes[k])[i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        }
        for (int j = 0; j < STATE_SIZE; j++) {
            *child = *s;
            int prisoners;
            if (make_move(child, 1ULL << j, &prisoners)) {
                if (target_dead(child)) {
                    continue;
                }
                if (child->ko) {
                    size_t child_layer;
                    child_key = to_key_s(sol, child, &child_layer);
                    add_lin_key(sol->ko_ld, child_key);
                }
            }
        }
        key = next_key(sol->d, key);
    }

    finalize_lin_dict(sol->ko_ld);

    node_value **ko_nodes = (node_value**) malloc(sol->num_layers * sizeof(node_value*));
    sol->ko_nodes = ko_nodes;
    for (size_t i = 0; i < sol->num_layers; i++) {
        sol->ko_nodes[i] = (node_value*) malloc(sol->ko_ld->num_keys * sizeof(node_value));
    }
    printf("Unique positions with ko %zu\n", sol->ko_ld->num_keys);

    for (size_t i = 0; i < sol->ko_ld->num_keys; i++) {
        for (size_t k = 0; k < sol->num_layers; k++) {
            sol->ko_nodes[k][i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        }
    }

    #ifdef CHINESE
    printf("Negamax with Chinese rules.\n");
    sol->count_prisoners = 0;
    sol->leaf_rule = chinese_liberty;
    iterate(sol, temp_filename);
    #endif

    // NOTE: Capture rules may refuse to kill stones when the needed nakade sacrifices exceed triple the number of stones killed.
    printf("Negamax with capture rules.\n");
    sol->count_prisoners = 1;
    sol->leaf_rule = japanese_double_liberty;
    iterate_capture:
    iterate(sol, temp_filename);

    sprintf(filename, "%s_capture.dat", sol_name);
    FILE *f = fopen(filename, "wb");
    save_solution(sol, f);
    fclose(f);


    calculate_leaves(sol);

    // Clear the rest of the tree.
    for (size_t j = 0; j < sol->num_layers; j++) {
        for (size_t i = 0; i < num_states; i++) {
            sol->base_nodes[j][i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        }
        for (size_t i = 0; i < sol->ko_ld->num_keys; i++) {
            sol->ko_nodes[j][i] = (node_value) {VALUE_MIN, VALUE_MAX, DISTANCE_MAX, DISTANCE_MAX};
        }
    }

    printf("Negamax with Japanese rules.\n");
    sol->count_prisoners = 1;
    sol->leaf_rule = precalculated;
    iterate_japanese:
    iterate(sol, temp_filename);

    sprintf(filename, "%s_japanese.dat", sol_name);
    f = fopen(filename, "wb");
    save_solution(sol, f);
    fclose(f);

    frontend:
    if (load_sol) {
        sprintf(filename, "%s_japanese.dat", sol_name);
        char *buffer = file_to_buffer(filename);
        buffer = load_solution(sol, buffer, 1);
    }

    *s = *sol->base_state;

    char coord1;
    int coord2;

    int total_prisoners = 0;
    int turn = 0;

    while (1) {
        size_t layer;
        size_t key = to_key_s(sol, s, &layer);
        node_value v = negamax_node(sol, s, key, layer, 0);
        print_state(s);
        if (turn) {
            print_node((node_value) {total_prisoners - v.high, total_prisoners - v.low, v.high_distance, v.low_distance});
        }
        else {
            print_node((node_value) {total_prisoners + v.low, total_prisoners + v.high, v.low_distance, v.high_distance});
        }
        if (target_dead(s) || s->passes >= 2) {
            break;
        }
        for (int j = -1; j < STATE_SIZE; j++) {
            *child = *s;
            stones_t move;
            if (j == -1){
                move = 0;
            }
            else {
                move = 1ULL << j;
            }
            char c1 = 'A' + (j % WIDTH);
            char c2 = '0' + (j / WIDTH);
            int prisoners;
            if (make_move(child, move, &prisoners)) {
                size_t child_layer;
                size_t child_key = to_key_s(sol, child, &child_layer);
                node_value child_v = negamax_node(sol, child, child_key, child_layer, 0);
                if (sol->count_prisoners) {
                    if (child_v.low > VALUE_MIN && child_v.low < VALUE_MAX) {
                        child_v.low = child_v.low - prisoners;
                    }
                    if (child_v.high > VALUE_MIN && child_v.high < VALUE_MAX) {
                        child_v.high = child_v.high - prisoners;
                    }
                }
                if (move) {
                    printf("%c%c", c1, c2);
                }
                else {
                    printf("pass");
                }
                if (-child_v.high == v.low) {
                    printf("-");
                    if (child_v.high_distance + 1 == v.low_distance) {
                        printf("L");
                    }
                    else {
                        printf("l");
                    }
                }
                if (-child_v.high == v.low) {
                    printf("-");
                    if (child_v.low_distance + 1 == v.high_distance) {
                        printf("H");
                    }
                    else {
                        printf("h");
                    }
                }
                printf(" ");
            }
        }
        printf("\n");
        printf("Enter coordinates:\n");
        assert(scanf("%c %d", &coord1, &coord2));
        int c;
        while ((c = getchar()) != '\n' && c != EOF);
        coord1 = tolower(coord1) - 'a';
        stones_t move;
        if (coord1 < 0 || coord1 >= WIDTH) {
            // printf("%d, %d\n", coord1, coord2);
            move = 0;
        }
        else {
            move = 1ULL << (coord1 + V_SHIFT * coord2);
        }
        int prisoners;
        if (make_move(s, move, &prisoners)) {
            if (turn) {
                total_prisoners -= prisoners;
            }
            else {
                total_prisoners += prisoners;
            }
            turn = !turn;
        }
    }

    return 0;
}
Example #15
0
// Japanese leaf state calculation from capture data.
// We could store territory for the UI, it takes too much space.
void calculate_leaves(solution *sol) {
    state s_;
    state *s = &s_;
    size_t key;
    size_t zero_layer = abs(sol->base_state->ko_threats);
    state new_s_;
    state *new_s = &new_s_;
    key = sol->d->min_key;
    size_t num_states = num_keys(sol->d);
    for (size_t i = 0; i < num_states; i++) {
        assert(from_key_s(sol, s, key, zero_layer));

        *new_s = *s;
        node_value v = negamax_node(sol, s, key, zero_layer, 0);
        node_value v_b = sol->base_nodes[zero_layer][i];
        assert(equal(v, v_b));
        endstate(sol, new_s, v, 0, 1);

        // Use a flood of life so that partially dead nakade won't give extra points.
        // Note while this won't mark dead groups as alive, it can treat living nakade stones as dead.
        stones_t player_alive = flood(new_s->player, s->player);
        stones_t opponent_alive = flood(new_s->opponent, s->opponent);

        int score;

        // First check if a target is not alive.
        stones_t player_target = s->player & s->target;
        stones_t opponent_target = s->opponent & s->target;
        if (opponent_target & ~opponent_alive) {
            // Make sure that both aren't dead.
            assert(!(player_target & ~player_alive));
            score = TARGET_SCORE;
        }
        else if (player_target & ~player_alive) {
            score = -TARGET_SCORE;
        }
        else {
            stones_t player_territory = 0;
            stones_t opponent_territory = 0;
            stones_t player_region_space = s->playing_area & ~player_alive;
            stones_t opponent_region_space = s->playing_area & ~opponent_alive;
            for (int j = 0; j < STATE_SIZE; j++) {
                stones_t p = 1ULL << j;
                stones_t region = flood(p, player_region_space);
                player_region_space ^= region;
                if (!(region & opponent_alive)) {
                    player_territory |= region;
                }
                region = flood(p, opponent_region_space);
                opponent_region_space ^= region;
                if (!(region & player_alive)) {
                    opponent_territory |= region;
                }
            }
            // Subtract friendly stones on the board from territory.
            player_territory &= ~s->player;
            opponent_territory &= ~s->opponent;
            score = popcount(player_territory) + popcount(player_territory & s->opponent) - popcount(opponent_territory) - popcount(opponent_territory & s->player);
        }

        sol->leaf_nodes[i] = score;

        key = next_key(sol->d, key);
    }
}