X-Git-Url: http://git.draconx.ca/gitweb/rrace.git/blobdiff_plain/2529a9651d160ab3a17118d778f5e5584d040765..a70b0ef8bf7cb26cc779e9b2da480295f5ebf2bd:/src/game.h diff --git a/src/game.h b/src/game.h index f4473a7..56fb442 100644 --- a/src/game.h +++ b/src/game.h @@ -1,6 +1,6 @@ /* * Slide puzzle core game logic - * Copyright © 2022 Nick Bowler + * Copyright © 2022-2023 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #define RRACE_GAME_H_ #include +#include enum { TILE_EMPTY, @@ -32,7 +33,10 @@ enum { TILE_MAX }; -enum { GOAL_SHIFT = 6 }; +#define GOAL_SHIFT 6 +#define GOAL_MASK 0x739c0ul +#define GAME_MASK 0x1fffffful + struct board { /* * Bit planes representing the current game area. @@ -42,11 +46,12 @@ struct board { * corresponds to position (0,0), bit 4 is position (4,0) and bit 25 * is position (4, 4). * - * game[0] - the board mask, all bits set except one indicating the - * absense of a tile at this position. - * game[1] - least significant bit of the tile's colour. - * game[2] - tile colour. - * game[3] - most significant bit of the tile's colour. + * game[0] - least significant bit of the tile's colour. + * game[1] - tile colour. + * game[2] - most significant bit of the tile's colour. + * game[3] - No internal meaning. The game_reset function will clear + * the bit at the empty position and set all others, and + * game_do_move will adjust it. */ uint_least32_t game[4]; @@ -62,8 +67,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 */ @@ -110,14 +117,82 @@ static inline uint_fast32_t board_mask_v(int x, int y0, int y1) return (col << 5*y1) & (col >> 5*(4-y0)); } +/* + * Return the board bitmap setting locations on or above row y. + */ +static inline uint_fast32_t board_above(int y) +{ + return ( 0x20ul << 5*y ) - 1; +} + +/* + * Return the board bitmap setting locations on or below row y. + */ +static inline uint_fast32_t board_below(int y) +{ + return ~( 1ul << 5*y ) + 1; +} + +/* + * Return the board bitmap setting locations on or left of column x. + */ +static inline uint_fast32_t board_left(int x) +{ + uint_fast32_t val = board_column(x); + + return val | (val - 0x108421); +} + +/* + * Return the board bitmap setting locations on or right of column x. + */ +static inline uint_fast32_t board_right(int x) +{ + uint_fast32_t val = board_column(x); + + return ~val + 0x108421; +} + +/* + * Return the board bitmap setting the rectangle of locations that are: + * + * - on or right of column x1, and + * - on or left of column x2, and + * - on or below row y1, and + * - on or above row y2. + * + * It must be the case that x2 >= x1 and y2 >= y1. + */ +static inline uint_fast32_t board_rect(int x1, int y1, int x2, int y2) +{ + return (board_left(x2-x1) << x1) & (board_above(y2-y1) << 5*y1); +} + +/* + * Extract the tile colour from a specific position of one of the + * arrays of tile bitmaps. The position is a bit index. So for + * example, game the tile at a given (x, y) position can be extracted + * by board_tile(board.game, 5*y+x). + */ +#define board_tile(planes, bit) (((0[planes]<<0) >> (bit)) & 1) \ + | (((1[planes]<<1) >> (bit)) & 2) \ + | (((2[planes]<<2) >> (bit)) & 4) + /* * Move the bits in the game bitmaps according to a move at position (x, y), * and update the location of the empty position which, if the move was valid * is now (x, y). * - * Returns 0 if the move was valid (and board has been updated), -1 otherwise. + * Returns the board bitmap indicating which positions changed. A return + * value of 0 therefore indicates an invalid move. */ -int game_do_move(struct board *board, int x, int y); +uint_fast32_t game_do_move(struct board *board, int x, int y); + +/* + * Returns the board bitmap setting game locations that differ from the goal. + * A return value of 0 therefore indicates a winning position. + */ +uint_fast32_t game_check_goal(struct board *board); /* * Initialize the game RNG such that the next call to game_reset will produce a @@ -130,4 +205,37 @@ void game_reseed(unsigned long long seed); */ void game_reset(struct board *board); +/* + * Reset the game start time. + */ +void game_begin(struct board *board); + +/* + * Return the total elapsed time (in ms) since the last call to game_begin. + */ +int_fast32_t game_elapsed(struct board *board); + +/* + * Disable new moves and clear all tile bits other than the 9 goal tiles. + * Returns the total elapsed time (in ms). + */ +int_fast32_t game_finish(struct board *board); + +/* + * Constructs a new set of game bitmaps into buf, with tiles in the + * objective area replaced by the goal tile colours, and returns buf. + */ +static inline uint_least32_t * +game_overlay_goal(struct board *board, uint_least32_t *buf) +{ + int i; + + for (i = 0; i < 3; i++) { + buf[i] = (unsigned long)board->goal[i] << GOAL_SHIFT; + buf[i] = (buf[i] & GOAL_MASK) | (board->game[i] & ~GOAL_MASK); + } + + return buf; +} + #endif