diff --git a/README.md b/README.md index a34da74..1b22b1c 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ enabled. -c Enable color support if supported. -a Enable animations (default). -A Disable animations. + -i Enable ai without displaying game. + -I Enable ai and display game. -r Reset highscore. Will prompt user. -s SIZE Set the size of the playing field. -b RATE Set the rate at which blocks spawn per turn. diff --git a/man/2048.1 b/man/2048.1 index 5848cf7..1e9c598 100644 --- a/man/2048.1 +++ b/man/2048.1 @@ -40,6 +40,12 @@ Enable animations (default). .BR \-A Disable animations. .TP +.BR \-i +Enable ai without displaying game. +.TP +.BR \-I +Enable ai and display game. +.TP .BR \-r Reset highscore. Will prompt user. .TP diff --git a/src/highscore.c b/src/highscore.c index 1f3fec6..b5446a2 100644 --- a/src/highscore.c +++ b/src/highscore.c @@ -78,23 +78,28 @@ reset_scores:; fclose(fd); } -void highscore_load(struct gamestate *g) +long highscore_load(struct gamestate *g) { const char *hsfile = highscore_retrieve_file(); + long result = 0; FILE *fd = fopen(hsfile, "r"); if (fd == NULL) fd = fopen(hsfile, "w+"); - fscanf(fd, "%ld", &g->score_high); + fscanf(fd, "%ld", &result); fclose(fd); + + if (g) g->score_high = result; + return result; } void highscore_save(struct gamestate *g) { /* Someone could make their own merge rules for highscores and this could be meaningless, * howeverhighscores are in plaintext, so that isn't that much of a concern */ - if (g->score < g->score_high || g->opts->grid_width != 4 || g->opts->grid_height != 4) + if (g->score < g->score_high || g->opts->grid_width != 4 || + g->opts->grid_height != 4 || g->opts->ai == true) return; const char *hsfile = highscore_retrieve_file(); diff --git a/src/highscore.h b/src/highscore.h index fe2c542..de62a5a 100644 --- a/src/highscore.h +++ b/src/highscore.h @@ -2,7 +2,7 @@ #define HIGHSCORE_H void highscore_reset(void); -void highscore_load(struct gamestate *g); +long highscore_load(struct gamestate *g); void highscore_save(struct gamestate *g); #endif diff --git a/src/main.c b/src/main.c index a8b1774..6cb13a7 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,6 @@ #include #include +#include "ai.h" #include "engine.h" #include "gfx.h" @@ -12,15 +13,21 @@ void draw_then_sleep(struct gfx_state *s, struct gamestate *g) int main(int argc, char **argv) { struct gamestate *g = gamestate_init(argc, argv); - struct gfx_state *s = gfx_init(g); + struct gfx_state *s; + + if (g->opts->interactive) + s = gfx_init(g); int game_running = true; while (game_running) { - gfx_draw(s, g); + + if (g->opts->interactive) + gfx_draw(s, g); get_new_key:; int direction = dir_invalid; - switch (gfx_getch(s)) { + int value = !g->opts->ai ? gfx_getch(s) : ai_move(g); + switch (value) { case 'h': case 'a': direction = dir_left; @@ -46,7 +53,8 @@ get_new_key:; /* Game will only end if 0 moves available */ if (game_running) { - gamestate_tick(s, g, direction, g->opts->animate ? draw_then_sleep : NULL); + gamestate_tick(s, g, direction, g->opts->animate && g->opts->interactive + ? draw_then_sleep : NULL); int spawned; for (spawned = 0; spawned < g->opts->spawn_rate; spawned++) @@ -58,9 +66,13 @@ get_new_key:; } } - gfx_destroy(s); - printf("Highscore: %ld\n", g->score_high); - printf(" Score: %ld\n", g->score); + if (g->opts->interactive) { + // gfx_getch(s); // getch here would be good, + // need an exit message for each graphical output + gfx_destroy(s); + } + + printf("%ld\n", g->score); gamestate_clear(g); return 0; } diff --git a/src/options.c b/src/options.c index d3974e0..053f498 100644 --- a/src/options.c +++ b/src/options.c @@ -1,11 +1,12 @@ #include #include +#include #include "highscore.h" #include "options.h" void print_usage(void) { - printf("usage: 2048 [-cCaArh] [-s SIZE] [-b RATE]\n"); + printf("usage: 2048 [-cCaAiIrh] [-s SIZE] [-b RATE]\n"); } @@ -19,8 +20,10 @@ struct gameoptions* gameoptions_default(void) opt->grid_width = DEFAULT_GRID_WIDTH; opt->spawn_value = DEFAULT_SPAWN_VALUE; opt->spawn_rate = DEFAULT_SPAWN_RATE; - opt->enable_color = DEFAULT_COLOR_TOGGLE; - opt->animate = DEFAULT_ANIMATE_TOGGLE; + opt->enable_color = DEFAULT_COLOR_FLAG; + opt->animate = DEFAULT_ANIMATE_FLAG; + opt->ai = DEFAULT_AI_FLAG; + opt->interactive = DEFAULT_INTERACTIVE_FLAG; return opt; } @@ -33,19 +36,27 @@ void gameoptions_destroy(struct gameoptions *opt) struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv) { int c; - while ((c = getopt(argc, argv, "aArcCh:s:b:")) != -1) { + while ((c = getopt(argc, argv, "aArcCiIhHs:b:")) != -1) { switch (c) { case 'a': - opt->animate = 1; + opt->animate = true; break; case 'A': - opt->animate = 0; + opt->animate = false; break; case 'c': - opt->enable_color = 1; + opt->enable_color = true; break; case 'C': - opt->enable_color = 0; + opt->enable_color = false; + break; + case 'i': + opt->ai = true; + opt->interactive = false; + break; + case 'I': + opt->ai = true; + opt->interactive = true; break; case 's':; /* Stick with square for now */ @@ -64,6 +75,9 @@ struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv case 'h': print_usage(); exit(0); + case 'H': + printf("%ld\n", highscore_load(NULL)); + exit(0); } } diff --git a/src/options.h b/src/options.h index f5e36e1..2126cd3 100644 --- a/src/options.h +++ b/src/options.h @@ -1,6 +1,7 @@ #ifndef OPTIONS_H #define OPTIONS_H +#include #include #define CONSTRAINT_GRID_MIN 4 @@ -9,16 +10,20 @@ #define DEFAULT_GRID_WIDTH 4 #define DEFAULT_SPAWN_VALUE 2 #define DEFAULT_SPAWN_RATE 1 -#define DEFAULT_COLOR_TOGGLE 0 -#define DEFAULT_ANIMATE_TOGGLE 1 +#define DEFAULT_COLOR_FLAG false +#define DEFAULT_ANIMATE_FLAG true +#define DEFAULT_AI_FLAG false +#define DEFAULT_INTERACTIVE_FLAG true struct gameoptions { int grid_height; int grid_width; long spawn_value; int spawn_rate; - int enable_color; - int animate; + bool enable_color; + bool animate; + bool ai; + bool interactive; }; void print_usage(void);