static void game_position_solve_test (GamePositionDbFixture *fixture, gconstpointer test_data) { GamePositionDb *db = fixture->db; /* * FFO position #05: * * a b c d e f g h * 1 . O O O O O . . * 2 . . O @ @ O . @ * 3 @ @ O @ O @ @ . * 4 @ @ O @ O @ @ O * 5 @ @ O O @ O O O * 6 @ @ @ @ O O . O * 7 @ . @ O O O . . * 8 . @ @ @ @ @ . . * Player to move: BLACK * * Move values: G8:+32. G2:+12. B2:-20. G6:-26. G1:-32. G7:-34. * * Principal Variation, PV: g8 g7 h8 g2 b2 a2 a1 g6 h7 b7 a8 -- h3 * Final score is +32 */ GamePosition *ffo_05 = get_gp_from_db(db, "ffo-05"); g_assert(TRUE == game_position_has_any_legal_move(ffo_05)); ExactSolution *solution = game_position_solve(ffo_05); g_assert(+32 == solution->outcome); g_assert(G8 == solution->principal_variation[0]); }
/** * @brief Main entry to the Reversi C endgame solver implementation. * * @todo Documentation has to be completly developed. */ int main (int argc, char *argv[]) { GamePositionDb *db; GamePositionDbSyntaxErrorLog *syntax_error_log; FILE *fp; GError *error; gchar *source; int number_of_errors; GOptionContext *context; GOptionGroup *option_group; GamePositionDbEntry *entry; int solver_index; error = NULL; entry = NULL; solver_index = -1; /* GLib command line options and argument parsing. */ option_group = g_option_group_new("name", "description", "help_description", NULL, NULL); context = g_option_context_new("- Solve an endgame position"); g_option_context_add_main_entries(context, entries, NULL); g_option_context_add_group(context, option_group); g_option_context_set_description(context, program_documentation_string); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_print("Option parsing failed: %s\n", error->message); return -1; } /* Checks command line options for consistency. */ if (input_file) { source = g_strdup(input_file); } else { g_print("Option -f, --file is mandatory.\n."); return -2; } if (solver) { for (int index = 0; index < solvers_count; index++) { if (g_strcmp0(solver, solvers[index]) == 0) solver_index = index; } if (solver_index == -1) { g_print("Option -s, --solver is out of range.\n."); return -8; } if (solver_index == 2) { // solver == random if (repeats < 1) { g_print("Option -n, --repeats is out of range.\n."); return -9; } } } else { g_print("Option -s, --solver is mandatory.\n."); return -5; } /* Opens the source file for reading. */ fp = fopen(source, "r"); if (!fp) { g_print("Unable to open database resource for reading, file \"%s\" does not exist.\n", source); return -3; } /* Loads the game position database. */ db = gpdb_new(g_strdup(source)); syntax_error_log = NULL; error = NULL; gpdb_load(fp, source, db, &syntax_error_log, &error); fclose(fp); /* Compute the number of errors logged. */ number_of_errors = gpdb_syntax_error_log_length(syntax_error_log); if (number_of_errors != 0) { g_print("The database resource, file \"%s\" contains errors, debug it using the gpdb_verify utility.\n", source); return -4; } /* Lookup for a given key. */ if (lookup_entry) { entry = gpdb_lookup(db, lookup_entry); if (entry) { gchar *tmp = gpdb_entry_print(entry); g_print("%s", tmp); g_free(tmp); } else { g_print("Entry %s not found in file %s.\n", lookup_entry, source); return -6; } } else { g_print("No entry provided.\n"); return -7; } /* Initialize the board module. */ board_module_init(); /* Solving the position. */ GamePosition *gp = entry->game_position; ExactSolution *solution = NULL; g_print("Solving game position %s, from source %s, using solver %s ...\n", entry->id, source, solvers[solver_index]); switch (solver_index) { case 0: solution = game_position_solve(gp, log_file); break; case 1: solution = game_position_ifes_solve(gp, log_file); break; case 2: solution = game_position_random_sampler(gp, log_file, repeats); break; case 3: solution = game_position_minimax_solve(gp, log_file); break; case 4: solution = game_position_rab_solve(gp, log_file, repeats); break; case 5: solution = game_position_ab_solve(gp, log_file); break; default: g_print("This should never happen! solver_index = %d. Aborting ...\n", solver_index); return -9; } /* Printing results. */ gchar *solution_to_string = exact_solution_to_string(solution); printf("\n%s\n", solution_to_string); g_free(solution_to_string); /* Frees the resources. */ g_free(error); gpdb_free(db, TRUE); if (syntax_error_log) gpdb_syntax_error_log_free(syntax_error_log); g_option_context_free(context); g_free(source); exact_solution_free(solution); return 0; }