From: Nick Bowler Date: Thu, 10 Mar 2022 04:44:39 +0000 (-0500) Subject: Track elapsed time of the game. X-Git-Url: http://git.draconx.ca/gitweb/rrace.git/commitdiff_plain/ec2e7b448d7d0d404c0b3102c5b25ac9464d9fc5 Track elapsed time of the game. Since this is a speed solving game, it is kind of important to know how much time it took to solve the puzzle. Start by adding a timer to the game state so we can print elapsed time at the end. Related GUI elements will be coming later. The game will no longer start immediately. When the program is launched, it will begin in a winning state. --- diff --git a/Makefile.am b/Makefile.am index fba2274..60ec476 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,7 +25,8 @@ endif rrace_motif_SOURCES = src/game.c src/x11.c src/game.h src/motif.h \ src/colour.h src/ewmhicon.c src/ewmhicon.h rrace_motif_LDADD = $(libmotifmain_a_OBJECTS) $(libmotifui_a_OBJECTS) \ - $(libglohelp_a_OBJECTS) libgnu.a $(MOTIF_LIBS) + $(libglohelp_a_OBJECTS) libgnu.a $(MOTIF_LIBS) \ + $(LIB_CLOCK_GETTIME) $(LIB_GETHRXTIME) $(rrace_motif_OBJECTS): $(gnulib_headers) EXTRA_LIBRARIES += libmotifmain.a @@ -72,7 +73,7 @@ check_PROGRAMS = t/boardmove t/boardbit t/ewmhicon t/rng-test EXTRA_DIST += t/xos256ss.c t_boardmove_SOURCES = t/boardmove.c src/game.c -t_boardmove_LDADD = libgnu.a +t_boardmove_LDADD = libgnu.a $(LIB_CLOCK_GETTIME) $(LIB_GETHRXTIME) $(t_boardmove_OBJECTS): $(gnulib_headers) t_boardbit_SOURCES = t/boardbit.c diff --git a/m4/.gitignore b/m4/.gitignore index ff430e2..a671356 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -1,8 +1,12 @@ /00gnulib.m4 /absolute-header.m4 +/clock_time.m4 /extensions.m4 /extern-inline.m4 +/gethrxtime.m4 /getopt.m4 +/gettime.m4 +/gettimeofday.m4 /gnulib-common.m4 /gnulib-comp.m4 /gnulib-tool.m4 @@ -18,7 +22,11 @@ /pid_t.m4 /ssize_t.m4 /stddef_h.m4 +/sys_socket_h.m4 +/sys_time_h.m4 /sys_types_h.m4 +/time_h.m4 +/timespec.m4 /unistd_h.m4 /vararrays.m4 /warn-on-use.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index d1c7383..165069a 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -39,12 +39,14 @@ # --no-libtool \ # --macro-prefix=gl \ # --no-vc-files \ +# gethrxtime \ # getopt-gnu \ # inline # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ + gethrxtime getopt-gnu inline ]) diff --git a/src/game.c b/src/game.c index f7cc2bb..c478eef 100644 --- a/src/game.c +++ b/src/game.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "game.h" #define B64(x) ((x) & 0xffffffffffffffff) @@ -123,8 +124,15 @@ void game_reset(struct board *board) unsigned char tiles[25]; unsigned i; - if (!rng_is_seeded()) - game_reseed(time(NULL)); + if (!rng_is_seeded()) { + unsigned long long seed; + + seed = time(NULL); + seed += gethrxtime(); + seed += seed << 32; + + game_reseed(seed); + } for (i = 0; i < 24; i++) { tiles[i] = (i%6) + 1; @@ -200,8 +208,19 @@ int game_check_goal(struct board *board) return ret; } -void game_finish(struct board *board) +void game_begin(struct board *board) +{ + board->time_start = gethrxtime(); +} + +static int_fast32_t elapsed(struct board *board) { + return (gethrxtime() - board->time_start) / 1000000; +} + +int_fast32_t game_finish(struct board *board) +{ + int_fast32_t t = elapsed(board); int i; for (i = 0; i < 4; i++) { @@ -213,4 +232,6 @@ void game_finish(struct board *board) * disable the game since there will be no valid moves. */ board->x = board->y = -1; + + return t; } diff --git a/src/game.h b/src/game.h index 6a02a42..99b5133 100644 --- a/src/game.h +++ b/src/game.h @@ -20,6 +20,7 @@ #define RRACE_GAME_H_ #include +#include enum { TILE_EMPTY, @@ -65,8 +66,10 @@ struct board { */ uint_least16_t goal[3]; - /* (x, y) position of the current empty position. */ + /* (x, y) position of the current empty space. */ uint_least8_t x, y; + + xtime_t time_start; }; /* Return the board bitmap with all bits in column x set */ @@ -178,9 +181,15 @@ void game_reseed(unsigned long long seed); */ void game_reset(struct board *board); +/* + * Reset the game start time. + */ +void game_begin(struct board *board); + /* * Disable new moves and clear all tile bits other than the 9 goal tiles. + * Returns the total elapsed time (in ms). */ -void game_finish(struct board *board); +int_fast32_t game_finish(struct board *board); #endif diff --git a/src/motif.c b/src/motif.c index d7eb5e8..12959f7 100644 --- a/src/motif.c +++ b/src/motif.c @@ -140,9 +140,12 @@ static void proc_new_game(Widget w, XEvent *e, String *argv, Cardinal *argc) shell = XtParent(shell); game_reset(&state.board); + x11_redraw_goal(&state, -1); x11_redraw_game(&state, -1); x11_redraw_icon(&state, shell); + + game_begin(&state.board); } static const XtActionsRec menu_actions[] = { @@ -154,6 +157,7 @@ static XtAppContext app_initialize(int argc, char **argv) { XtAppContext app; Widget shell; + int i; if (argc > 0) progname = argv[0]; @@ -162,7 +166,13 @@ static XtAppContext app_initialize(int argc, char **argv) XtAppAddActions(app, (void *)menu_actions, XtNumber(menu_actions)); ui_initialize(&state, shell); x11_initialize(&state, shell); + + /* Begin with the game in winning state */ game_reset(&state.board); + for (i = 0; i < 3; i++) + state.board.game[i] = state.board.goal[i] << GOAL_SHIFT; + game_finish(&state.board); + state.use_ewmh_icons = ewmh_probe_wm_icon(shell); XtRealizeWidget(shell); diff --git a/src/motif_ui.c b/src/motif_ui.c index eca3e79..c31d839 100644 --- a/src/motif_ui.c +++ b/src/motif_ui.c @@ -224,8 +224,18 @@ static void do_input_move(struct app_state *state, int x, int y) uint_least32_t mask; if (game_check_goal(&state->board)) { - printf("You win!\n"); - game_finish(&state->board); + int_fast32_t ms = game_finish(&state->board); + unsigned min, sec; + + /* Negative time just means clock jumps and + * display headaches. */ + if (ms < 0) + ms = 0; + + sec = ms / 1000, ms %= 1000; + min = sec / 60, sec %= 60; + printf("You won! Time was %u:%.2u:%.3u\n", + min, sec, (unsigned)ms); } /* Figure out which tiles changed */