X-Git-Url: https://git.draconx.ca/gitweb/rrace.git/blobdiff_plain/2529a9651d160ab3a17118d778f5e5584d040765..26fb4b6902a32be6e9f504bee44724a0dd4292f7:/src/game.c diff --git a/src/game.c b/src/game.c index bd1fef9..f7cc2bb 100644 --- a/src/game.c +++ b/src/game.c @@ -1,8 +1,25 @@ /* + * 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 @@ -117,36 +134,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 +190,27 @@ 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_finish(struct board *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; +}