X-Git-Url: https://git.draconx.ca/gitweb/rrace.git/blobdiff_plain/2529a9651d160ab3a17118d778f5e5584d040765..ec2e7b448d7d0d404c0b3102c5b25ac9464d9fc5:/src/game.c diff --git a/src/game.c b/src/game.c index bd1fef9..c478eef 100644 --- a/src/game.c +++ b/src/game.c @@ -1,12 +1,30 @@ /* + * Slide puzzle core game logic + * Copyright © 2022 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * * The RNG implementation is adapted from xoshiro256** and splitmix64 * by David Blackman and Sebastiano Vigna, originally distributed under * the Creative Commons Zero public domain dedication. */ + #include #include #include #include +#include #include "game.h" #define B64(x) ((x) & 0xffffffffffffffff) @@ -106,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; @@ -117,36 +142,30 @@ void game_reset(struct board *board) memset(board->goal, 0, sizeof board->goal); for (i = 0; i < 9; i++) { - uint_fast32_t position = board_position(i/3+1, i%3+1); - - if (tiles[i] & 1) - board->goal[0] |= position >> 6; - if (tiles[i] & 2) - board->goal[1] |= position >> 6; - if (tiles[i] & 4) - board->goal[2] |= position >> 6; + uint_fast32_t position = board_position(i/3+1, i%3+1) >> 6; + + if (tiles[i] & 1) board->goal[0] |= position; + if (tiles[i] & 2) board->goal[1] |= position; + if (tiles[i] & 4) board->goal[2] |= position; } tiles[24] = TILE_EMPTY; shuffle(tiles, 25); - memset(board->game, 0, sizeof board->game); + memset(board->game, 0, sizeof board->game); for (i = 0; i < 25; i++) { unsigned x = i/5, y = i%5; uint_fast32_t position; position = board_position(x, y); - if (tiles[i] == TILE_EMPTY) { - board->game[0] = 0x1ffffff ^ position; + if (tiles[i] != TILE_EMPTY) { + if (tiles[i] & 1) board->game[0] |= position; + if (tiles[i] & 2) board->game[1] |= position; + if (tiles[i] & 4) board->game[2] |= position; + } else { + board->game[3] = ~position; board->x = x; board->y = y; - } else { - if (tiles[i] & 1) - board->game[1] |= position; - if (tiles[i] & 2) - board->game[2] |= position; - if (tiles[i] & 4) - board->game[3] |= position; } } } @@ -179,3 +198,40 @@ int game_do_move(struct board *board, int x, int y) board->y = y; return 0; } + +int game_check_goal(struct board *board) +{ + int i, ret = 1; + + for (i = 0; i < 3; i++) + ret &= ((board->game[i] & GOAL_MASK) >> 6) == board->goal[i]; + return ret; +} + +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++) { + 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; +}