/** * 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[]) { int opt; int oindex = -1; mop_init(&options, argc, argv); while ((opt = mop_parse_long(&options, olist, &oindex)) != -1) { switch (opt) { case 'h': h_flag = true; break; case 'f': f_flag = true; f_arg = options.optarg; break; case 'q': q_flag = true; q_arg = options.optarg; break; case 's': s_flag = true; s_arg = options.optarg; break; case 'n': n_flag = true; n_arg = options.optarg; break; case 'r': r_flag = true; r_arg = options.optarg; break; case 'P': P_flag = true; P_arg = options.optarg; break; case 'l': l_flag = true; l_arg = options.optarg; break; case 'd': d_flag = true; d_arg = options.optarg; break; case 'R': R_flag = true; break; case 'F': F_flag = true; break; case 'N': N_flag = true; break; case ':': fprintf(stderr, "Option parsing failed: %s\n", options.errmsg); return -1; case '?': fprintf(stderr, "Option parsing failed: %s\n", options.errmsg); return -2; default: fprintf(stderr, "Unexpectd error. Aborting ...\n"); abort(); } } /* Prints documentation and returns, when help option is active. */ if (h_flag) { fprintf(stderr, "%s", documentation); return 0; } /* * Checks command line options for consistency. */ if (!f_flag) { fprintf(stderr, "Option -f, --file is mandatory.\n"); return -2; } else { input_file = f_arg; } if (!s_flag) { fprintf(stderr, "Option -s, --solver is mandatory.\n"); return -4; } else { solver_index = egs_select_solver(s_arg); if (solver_index == -1) { fprintf(stderr, "Option -s, --solver is out of range.\n"); return -5; } } const endgame_solver_t *const solver = &solvers[solver_index]; if (!q_flag) { fprintf(stderr, "Option -q, --lookup-entry is mandatory.\n"); return -6; } else { lookup_entry = q_arg; } if (n_flag) { if ((strcmp("rand", solver->id) != 0) && (strcmp("rab", solver->id) != 0)) { // solver is not rab or rand ... fprintf(stderr, "Option -n, --repeats can be used only with solvers \"rab\" or \"rand\".\n"); return -7; } char *endptr; long long int n_arg_to_int = strtoll(n_arg, &endptr, 10); if (endptr - n_arg != strlen(n_arg)) { fprintf(stderr, "Argument for option -n, --repeats: %s is invalid.\n", n_arg); return -8; } if (n_arg_to_int < 1) { fprintf(stderr, "Argument for option -n, --repeats is %lld, it must be a positive integer.\n", n_arg_to_int); return -9; } repeats = n_arg_to_int; } else { repeats = 1; } if (r_flag) { if ((strcmp("rand", solver->id) != 0) && (strcmp("rab", solver->id) != 0)) { // solver is not rab or rand ... fprintf(stderr, "Option -r, --prng-seed can be used only with solvers \"rab\" or \"rand\".\n"); return EXIT_FAILURE; } char *endptr; long int r_arg_to_int = strtol(r_arg, &endptr, 10); if (endptr - r_arg != strlen(r_arg)) { fprintf(stderr, "Argument for option -r, --prng-seed: %s is invalid.\n", r_arg); return EXIT_FAILURE; } if (r_arg_to_int < 1) { fprintf(stderr, "Argument for option -r, --prng-seed is %ld, it must be a positive integer.\n", r_arg_to_int); return EXIT_FAILURE; } prng_seed = r_arg_to_int; prng_seed_is_set = true; } if (P_flag) { if (strcmp("rand", solver->id) != 0) { // solver is not rab ... fprintf(stderr, "Option -P, --pattern can be used only with solver \"rand\".\n"); return EXIT_FAILURE; } board_pattern_index = egs_select_pattern(P_arg); if (board_pattern_index == -1) { fprintf(stderr, "Option -P, --pattern is out of range.\n"); return EXIT_FAILURE; } } if (l_flag) { log_file = l_arg; if (gtl_touch_log_file(l_arg)) log_file = l_arg; else { fprintf(stderr, "Unable to open log files with prefix \"%s\".\n", l_arg); return -10; } } if (d_flag) { if (fut_touch_file(d_arg)) pve_dump_file = d_arg; else { fprintf(stderr, "Unable to open dump file \"%s\".\n", d_arg); return -11; } } if (R_flag) { if (!(strcmp("es", solver->id) == 0)) { fprintf(stderr, "Option -R, --pv-rec can be used only with solver \"es\".\n"); return -12; } pv_rec = true; } if (F_flag) { if (!(strcmp("es", solver->id) == 0)) { fprintf(stderr, "Option -F, --pv-full-rec can be used only with solver \"es\".\n"); return -13; } if (pv_rec) { fprintf(stderr, "Option -F, --pv-full-rec and option -R, cannot be used together.\n"); return -14; } pv_full_rec = true; } if (N_flag) { if (!(strcmp("es", solver->id) == 0) || !pv_full_rec) { fprintf(stderr, "Option -N, --pv-no-print can be used only with solver \"es\", and when option -F, --pv-full-rec is turned on.\n"); return -15; } pv_no_print = true; } /* Verifies that the database input file is available for reading. */ FILE *fp = fopen(input_file, "r"); if (!fp) { fprintf(stderr, "Unable to open database resource for reading, file \"%s\" does not exist.\n", input_file); return -16; } fclose(fp); /* * Checks on command line options ends here. */ gpdb_dictionary_t *db; gpdb_syntax_err_log_t *syntax_error_log; gpdb_entry_t *entry = NULL; 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, .board_pattern_index = board_pattern_index, .prng_seed_is_set = prng_seed_is_set, .prng_seed = prng_seed }; /* Loads the game position database. */ db = gpdb_dictionary_new(input_file); syntax_error_log = gpdb_syntax_err_log_new(); gpdb_dictionary_load(db, syntax_error_log, input_file, true, false, true); /* Compute the number of errors logged. */ const int number_of_errors = gpdb_syntax_err_log_length(syntax_error_log); gpdb_syntax_err_log_free(syntax_error_log); if (number_of_errors != 0) { fprintf(stderr, "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_dictionary_find_entry(db, lookup_entry); if (entry) { gpdb_entry_print(entry, stdout, true); } else { fprintf(stderr, "Entry %s not found in file %s.\n", lookup_entry, input_file); return -6; } } else { printf("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. */ GamePositionX *gpx = gpdb_entry_get_gpx(entry); ExactSolution *solution = NULL; fprintf(stdout, "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. */ printf("\n"); exact_solution_to_stream(stdout, solution); printf("\n"); /* Frees the resources. */ gpdb_dictionary_free(db); exact_solution_free(solution); 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) { 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; }
/** * @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; }