+
+ return mask & ret;
+}
+
+uint_fast32_t game_check_goal(struct board *board)
+{
+ uint_least32_t *game = board->game;
+ uint_least16_t *goal = board->goal;
+ uint_least32_t mask = 0;
+ int i;
+
+ for (i = 0; i < 3; i++)
+ mask |= goal[i] ^ (game[i] >> GOAL_SHIFT);
+ return (mask << GOAL_SHIFT) & GOAL_MASK;
+}
+
+void game_begin(struct board *board)
+{
+ board->time_start = gethrxtime();
+}
+
+int_fast32_t game_elapsed(struct board *board)
+{
+ return (gethrxtime() - board->time_start) / 1000000;
+}
+
+int_fast32_t game_finish(struct board *board)
+{
+ int_fast32_t t = game_elapsed(board);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ board->game[i] &= GOAL_MASK;
+ }
+
+ /*
+ * Setting both x and y hole location to a bogus value will effectively
+ * disable the game since there will be no valid moves.
+ */
+ board->x = board->y = -1;
+
+ return t;