// Ignores target and immortal int kill_group(state *s) { stones_t chain, p; stones_t opponent = s->opponent; for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j += 2) { p = (1ULL | (1ULL << V_SHIFT)) << (i + j * V_SHIFT); chain = flood(p, opponent); opponent ^= chain; stones_t libs = liberties(chain, s->playing_area & ~s->player); if (popcount(libs) == 1) { int prisoners; make_move(s, libs, &prisoners); return 1; } } } return 0; }
void testFindStonesAdjacentLiberties() { int boardWidth = 9; BitBoard liberties(boardWidth); BitBoard defender(boardWidth); defender.putStone(9, 'a'); BitBoard* stonesAdjLibs = complexOpps::findStonesAdjacentLiberties(&liberties, &defender); if (stonesAdjLibs->bitCount()>0) { cout << "fail: testFindStonesAdjacentLiberties" << endl; } else { cout << "pass: testFindStonesAdjacentLiberties" << endl; } delete stonesAdjLibs; }
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; }