Added ai modes. Altered output of highscores to allow possible parsing with tools easier

This commit is contained in:
Tiehuis 2015-02-25 14:51:48 +13:00
parent 2d9f89f339
commit cf1a147078
7 changed files with 67 additions and 23 deletions

View File

@ -32,6 +32,8 @@ enabled.
-c Enable color support if supported. -c Enable color support if supported.
-a Enable animations (default). -a Enable animations (default).
-A Disable animations. -A Disable animations.
-i Enable ai without displaying game.
-I Enable ai and display game.
-r Reset highscore. Will prompt user. -r Reset highscore. Will prompt user.
-s SIZE Set the size of the playing field. -s SIZE Set the size of the playing field.
-b RATE Set the rate at which blocks spawn per turn. -b RATE Set the rate at which blocks spawn per turn.

View File

@ -40,6 +40,12 @@ Enable animations (default).
.BR \-A .BR \-A
Disable animations. Disable animations.
.TP .TP
.BR \-i
Enable ai without displaying game.
.TP
.BR \-I
Enable ai and display game.
.TP
.BR \-r .BR \-r
Reset highscore. Will prompt user. Reset highscore. Will prompt user.
.TP .TP

View File

@ -78,23 +78,28 @@ reset_scores:;
fclose(fd); fclose(fd);
} }
void highscore_load(struct gamestate *g) long highscore_load(struct gamestate *g)
{ {
const char *hsfile = highscore_retrieve_file(); const char *hsfile = highscore_retrieve_file();
long result = 0;
FILE *fd = fopen(hsfile, "r"); FILE *fd = fopen(hsfile, "r");
if (fd == NULL) if (fd == NULL)
fd = fopen(hsfile, "w+"); fd = fopen(hsfile, "w+");
fscanf(fd, "%ld", &g->score_high); fscanf(fd, "%ld", &result);
fclose(fd); fclose(fd);
if (g) g->score_high = result;
return result;
} }
void highscore_save(struct gamestate *g) void highscore_save(struct gamestate *g)
{ {
/* Someone could make their own merge rules for highscores and this could be meaningless, /* 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 */ * 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; return;
const char *hsfile = highscore_retrieve_file(); const char *hsfile = highscore_retrieve_file();

View File

@ -2,7 +2,7 @@
#define HIGHSCORE_H #define HIGHSCORE_H
void highscore_reset(void); void highscore_reset(void);
void highscore_load(struct gamestate *g); long highscore_load(struct gamestate *g);
void highscore_save(struct gamestate *g); void highscore_save(struct gamestate *g);
#endif #endif

View File

@ -1,5 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include "ai.h"
#include "engine.h" #include "engine.h"
#include "gfx.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) int main(int argc, char **argv)
{ {
struct gamestate *g = gamestate_init(argc, 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; int game_running = true;
while (game_running) { while (game_running) {
gfx_draw(s, g);
if (g->opts->interactive)
gfx_draw(s, g);
get_new_key:; get_new_key:;
int direction = dir_invalid; int direction = dir_invalid;
switch (gfx_getch(s)) { int value = !g->opts->ai ? gfx_getch(s) : ai_move(g);
switch (value) {
case 'h': case 'h':
case 'a': case 'a':
direction = dir_left; direction = dir_left;
@ -46,7 +53,8 @@ get_new_key:;
/* Game will only end if 0 moves available */ /* Game will only end if 0 moves available */
if (game_running) { 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; int spawned;
for (spawned = 0; spawned < g->opts->spawn_rate; spawned++) for (spawned = 0; spawned < g->opts->spawn_rate; spawned++)
@ -58,9 +66,13 @@ get_new_key:;
} }
} }
gfx_destroy(s); if (g->opts->interactive) {
printf("Highscore: %ld\n", g->score_high); // gfx_getch(s); // getch here would be good,
printf(" Score: %ld\n", g->score); // need an exit message for each graphical output
gfx_destroy(s);
}
printf("%ld\n", g->score);
gamestate_clear(g); gamestate_clear(g);
return 0; return 0;
} }

View File

@ -1,11 +1,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "highscore.h" #include "highscore.h"
#include "options.h" #include "options.h"
void print_usage(void) 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->grid_width = DEFAULT_GRID_WIDTH;
opt->spawn_value = DEFAULT_SPAWN_VALUE; opt->spawn_value = DEFAULT_SPAWN_VALUE;
opt->spawn_rate = DEFAULT_SPAWN_RATE; opt->spawn_rate = DEFAULT_SPAWN_RATE;
opt->enable_color = DEFAULT_COLOR_TOGGLE; opt->enable_color = DEFAULT_COLOR_FLAG;
opt->animate = DEFAULT_ANIMATE_TOGGLE; opt->animate = DEFAULT_ANIMATE_FLAG;
opt->ai = DEFAULT_AI_FLAG;
opt->interactive = DEFAULT_INTERACTIVE_FLAG;
return opt; return opt;
} }
@ -33,19 +36,27 @@ void gameoptions_destroy(struct gameoptions *opt)
struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv) struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv)
{ {
int c; int c;
while ((c = getopt(argc, argv, "aArcCh:s:b:")) != -1) { while ((c = getopt(argc, argv, "aArcCiIhHs:b:")) != -1) {
switch (c) { switch (c) {
case 'a': case 'a':
opt->animate = 1; opt->animate = true;
break; break;
case 'A': case 'A':
opt->animate = 0; opt->animate = false;
break; break;
case 'c': case 'c':
opt->enable_color = 1; opt->enable_color = true;
break; break;
case 'C': 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; break;
case 's':; case 's':;
/* Stick with square for now */ /* Stick with square for now */
@ -64,6 +75,9 @@ struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv
case 'h': case 'h':
print_usage(); print_usage();
exit(0); exit(0);
case 'H':
printf("%ld\n", highscore_load(NULL));
exit(0);
} }
} }

View File

@ -1,6 +1,7 @@
#ifndef OPTIONS_H #ifndef OPTIONS_H
#define OPTIONS_H #define OPTIONS_H
#include <stdbool.h>
#include <getopt.h> #include <getopt.h>
#define CONSTRAINT_GRID_MIN 4 #define CONSTRAINT_GRID_MIN 4
@ -9,16 +10,20 @@
#define DEFAULT_GRID_WIDTH 4 #define DEFAULT_GRID_WIDTH 4
#define DEFAULT_SPAWN_VALUE 2 #define DEFAULT_SPAWN_VALUE 2
#define DEFAULT_SPAWN_RATE 1 #define DEFAULT_SPAWN_RATE 1
#define DEFAULT_COLOR_TOGGLE 0 #define DEFAULT_COLOR_FLAG false
#define DEFAULT_ANIMATE_TOGGLE 1 #define DEFAULT_ANIMATE_FLAG true
#define DEFAULT_AI_FLAG false
#define DEFAULT_INTERACTIVE_FLAG true
struct gameoptions { struct gameoptions {
int grid_height; int grid_height;
int grid_width; int grid_width;
long spawn_value; long spawn_value;
int spawn_rate; int spawn_rate;
int enable_color; bool enable_color;
int animate; bool animate;
bool ai;
bool interactive;
}; };
void print_usage(void); void print_usage(void);