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.