static void gpdb_fixture_setup (GamePositionDbFixture *fixture, gconstpointer test_data) { gchar *source = g_strdup("db/gpdb-sample-games.txt"); GamePositionDb *db; GamePositionDbSyntaxErrorLog *syntax_error_log; FILE *fp; GError *error; /* Loads the game position database. */ fp = fopen(source, "r"); if (!fp) { printf("Unable to open database test file \"%s\" for reading.\n", source); g_test_fail(); } db = gpdb_new(g_strdup("Testing Database")); syntax_error_log = NULL; error = NULL; gpdb_load(fp, source, db, &syntax_error_log, &error); fclose(fp); g_free(source); /* Removes the tmp file, frees the resources. */ g_free(error); if (syntax_error_log) gpdb_syntax_error_log_free(syntax_error_log); fixture->db = db; g_assert (fixture->db != NULL); }
/** * Verifies a database file of game positions. */ 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; error = NULL; /* GLib command line options and argument parsing. */ option_group = g_option_group_new("name", "description", "help_description", NULL, NULL); context = g_option_context_new ("- Verify a database of game positions"); g_option_context_add_main_entries (context, entries, NULL); g_option_context_add_group (context, option_group); 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; } /* 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); g_free(source); fclose(fp); /* Compute the number of errors logged. */ number_of_errors = gpdb_syntax_error_log_length(syntax_error_log); /* Prints the database summary if the OPTION -p is turned on. */ if (print_summary) { gchar *summary = gpdb_print_summary(db); g_print("%s", summary); g_free(summary); g_print("Number of errors: %d\n", number_of_errors); } /* Prints the error log if the OPTION -e is turned on. */ if (log_errors) { gchar *syntax_error_log_to_string = gpdb_syntax_error_log_print(syntax_error_log); g_print("%s", syntax_error_log_to_string); g_free(syntax_error_log_to_string); } /* Prints the entry list if the OPTION -l is turned on. */ if (log_entries) { gchar *gpdb_to_string = gpdb_print(db); g_print("%s", gpdb_to_string); g_free(gpdb_to_string); } /* Lookup for a given key. */ if (lookup_entry) { GamePositionDbEntry *entry = gpdb_lookup(db, lookup_entry); if (entry) { gchar *tmp = gpdb_entry_print(entry); g_print("%s", tmp); g_free(tmp); } } /* 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); return 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; }
/** * @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; GamePositionDbEntry *entry = NULL; int solver_index = -1; endgame_solver_env_t env = { .log_file = NULL, .pve_dump_file = NULL, .repeats = 0, .pv_recording = false, .pv_full_recording = false, .pv_no_print = false }; /* GLib command line options and argument parsing. */ GError *error = NULL; GOptionGroup *option_group = g_option_group_new("name", "description", "help_description", NULL, NULL); GOptionContext *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, and selects the solver. */ if (!input_file) { g_print("Option -f, --file is mandatory.\n"); return -2; } if (solver_id) { solver_index = egs_select_solver(solver_id); if (solver_index == -1) { g_print("Option -s, --solver is out of range.\n"); return -8; } if (strcmp(solvers[solver_index].id, "rand") == 0) { 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; } const endgame_solver_t *const solver = &solvers[solver_index]; if (pv_rec && !(!strcmp(solver->id, "es") || !strcmp(solver->id, "es2"))) { g_print("Option --pv-rec can be used only with solver \"es\" or \"es2\".\n"); return -10; } if (pv_full_rec && !(!strcmp(solver->id, "es") || !strcmp(solver->id, "es2"))) { g_print("Option --pv-full-rec can be used only with solver \"es\" or \"es2\".\n"); return -10; } if (pv_no_print && (strcmp(solver->id, "es") || !pv_full_rec)) { g_print("Option --pv-no-print can be used only with solver \"es\", and when option --pv-full-rec is turned on.\n"); return -11; } /* Opens the source file for reading. */ fp = fopen(input_file, "r"); if (!fp) { g_print("Unable to open database resource for reading, file \"%s\" does not exist.\n", input_file); return -3; } /* Loads the game position database. */ db = gpdb_new(g_strdup(input_file)); syntax_error_log = NULL; error = NULL; gpdb_load(fp, input_file, db, &syntax_error_log, &error); fclose(fp); /* Compute the number of errors logged. */ const int 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", input_file); 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, input_file); return -6; } } else { g_print("No entry provided.\n"); return -7; } /* Initializes the board module. */ board_module_init(); /* Sets env structure. */ env.log_file = log_file; env.pve_dump_file = pve_dump_file; env.repeats = repeats; env.pv_recording = pv_rec || pv_full_rec; env.pv_full_recording = pv_full_rec; env.pv_no_print = pv_no_print; /* Solves the position. */ //GamePosition *gp = entry->game_position; GamePositionX *gpx = game_position_x_gp_to_gpx(entry->game_position); ExactSolution *solution = NULL; g_print("Solving game position %s, from source %s, using solver %s (%s) ...\n", entry->id, input_file, solver->id, solver->description); solution = solver->fn(gpx, &env); /* Prints 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); exact_solution_free(solution); free(gpx); return 0; } /** * @cond */ /* * Internal functions. */ /** * @brief Ruturns the index in the solvers arry of the endgame solver identified by `id`. * * @details Compares the `id` parameter with the values in the solvers static array, * if the `id` parameter matches with the solver id field then the solver * position is returned. If no solver matches, a `-1` value is returned. * * @param [in] id the label of the solver * @return the solver index */ static int egs_select_solver (const char *const id) { g_assert(id); for (size_t i = 0; i < solvers_count; i++) { endgame_solver_t egs = solvers[i]; if (strcmp(id, egs.id) == 0) return i; } return -1; }