31 int penguins_per_player,
38 const char* board_data
43 for (
int i = 0; i < players_count; i++) {
44 char name[] = {
'A' + i,
'\0' };
48 for (
int y = 0; y < board_height; y++) {
49 for (
int x = 0; x < board_width; x++) {
51 char tile = *board_data;
52 if (
'1' <= tile && tile <=
'9') {
53 short fish = tile -
'0';
55 }
else if (
'A' <= tile && tile <=
'Z') {
56 int player_idx = tile -
'A';
74 const char* board =
"~12"
85 const char* board =
"~~2"
97 const char* board =
"B~A"
109 const char* board =
"B~A"
120 const char* board =
"A13";
134 const char* board =
"1A~3";
147 const char* board =
"1AB3";
161 const char* board =
"A13";
176 .name =
"/cloning the Game produces a deep copy",
180 .name =
"/detects that a placeable spot exists somewhere on the board",
184 .options = MUNIT_TEST_OPTION_NONE,
188 .name =
"/detects that there are no valid placement slots on the board",
192 .options = MUNIT_TEST_OPTION_NONE,
196 .name =
"/detects that there are valid movement options for a player",
200 .options = MUNIT_TEST_OPTION_NONE,
204 .name =
"/detects that there are no valid movement options for a player",
208 .options = MUNIT_TEST_OPTION_NONE,
212 .name =
"/detects that a move is going to be valid",
216 .options = MUNIT_TEST_OPTION_NONE,
220 .name =
"/detects that a move over an empty space is going to be invalid",
224 .options = MUNIT_TEST_OPTION_NONE,
228 .name =
"/detects that a move over a penguin is going to be invalid",
232 .options = MUNIT_TEST_OPTION_NONE,
236 .name =
"/updates the board and returns number of fish captured during a movement",
240 .options = MUNIT_TEST_OPTION_NONE,
244 { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
252 .options = MUNIT_SUITE_OPTION_NONE,
255 int main(
int argc,
char* argv[]) {
256 return munit_suite_main(&
board_suite, NULL, argc, argv);
Functions for working with the game board (and the specifics of its encoding)
#define PENGUIN_TILE(player_id)
The core of the unified game logic library, contains the Game struct.
Movement phase functions.
@ MOVEMENT_OVER_EMPTY_TILE
Placement phase functions.
A pair of 2D coordinates, used for addressing the Game::board_grid.
The central struct of the application, holds the game data and settings.
void game_set_penguins_per_player(Game *self, int value)
Sets Game::penguins_per_player (the value mustn't be negative) and allocates Player::penguins lists o...
ALWAYS_INLINE void set_tile(Game *game, Coords coords, short value)
Sets the value of the tile at coords (and also sets the attribute TILE_DIRTY). Fails if coords are ou...
void move_penguin(Game *game, Coords start, Coords target)
Creates a GameLogMovement entry. The requested move must be valid.
ALWAYS_INLINE short get_tile(const Game *game, Coords coords)
Returns the value of the tile at coords. Fails if coords are outside the bounds.
void game_add_player_penguin(Game *self, int idx, Coords coords)
void game_set_current_player(Game *self, int idx)
Sets Game::current_player_index and creates a GameLogPlayerChange log entry.
void game_begin_setup(Game *self)
Switches to the GAME_PHASE_SETUP phase, can only be called in GAME_PHASE_NONE. Should be called right...
bool any_valid_player_move_exists(const Game *game, int player_idx)
void setup_board(Game *game, int width, int height)
Sets Game::board_width and Game::board_height and allocates Game::board_grid and Game::tile_attribute...
bool any_valid_placement_exists(const Game *game)
void game_end_setup(Game *self)
Verifies that all fields have been initialized and configured and switches the phase from GAME_PHASE_...
Game * game_clone(const Game *other)
Creates a (deep) copy of another Game.
void movement_begin(Game *game)
Enters the GAME_PHASE_MOVEMENT phase, can only be called in GAME_PHASE_SETUP_DONE.
void game_set_player_name(Game *self, int idx, const char *name)
Sets the Player::name of a player at the given index. Only available in the GAME_PHASE_SETUP phase.
MovementError validate_movement(const Game *game, Coords start, Coords target, Coords *fail)
Player * game_get_player(const Game *self, int idx)
Returns a pointer to the player at the given index. Fails if the index isn't within the bounds of the...
Game * game_new(void)
Constructs a Game. Allocates memory for storing the struct itself, setting all fields to default valu...
void game_free(Game *self)
Destroys a Game, freeing the memory allocated for the struct itself and all associated internal lists...
void game_set_players_count(Game *self, int count)
Sets Game::players_count (the value mustn't be negative) and allocates the Game::players list....
Holds the data of the players of the Game.
short id
The unique ID, usually (but not necessarily) is just index + 1.
int main(int argc, char *argv[])
static MunitResult test_movement_over_empty_space_invalid(const MunitParameter *params, void *data)
static void setup_test_game(Game *game, int players_count, int penguins_per_player, int board_width, int board_height, const char *board_data)
static MunitResult test_move_penguin_and_calculate_points(const MunitParameter *params, void *data)
static MunitResult test_placeable_spot_does_not_exist(const MunitParameter *params, void *data)
static MunitResult test_placeable_spot_exists(const MunitParameter *params, void *data)
static MunitResult test_detect_valid_movement(const MunitParameter *params, void *data)
static MunitResult test_no_valid_movement_exists_for_player(const MunitParameter *params, void *data)
static MunitResult test_valid_movement_exists_for_player(const MunitParameter *params, void *data)
static MunitResult test_game_clone(const MunitParameter *params, void *data)
static MunitTest board_suite_tests[]
static const MunitSuite board_suite
static MunitResult test_movement_over_penguin_invalid(const MunitParameter *params, void *data)
#define UNUSED(var)
Helper for silencing warnings about unused variables.