11 #define WIN32_LEAN_AND_MEAN 
   19 #define ANSI_CSI "\033[" 
   21 #define ANSI_SGR_RESET "0" 
   22 #define ANSI_SGR_BOLD "1" 
   23 #define ANSI_SGR_FORE_COLOR "3" 
   24 #define ANSI_SGR_BACK_COLOR "4" 
   25 #define ANSI_SGR_BLACK "0" 
   26 #define ANSI_SGR_RED "1" 
   27 #define ANSI_SGR_GREEN "2" 
   28 #define ANSI_SGR_YELLOW "3" 
   29 #define ANSI_SGR_BLUE "4" 
   30 #define ANSI_SGR_MAGENTA "5" 
   31 #define ANSI_SGR_CYAN "6" 
   32 #define ANSI_SGR_WHITE "7" 
   34 #define ANSI_RESET ANSI_CSI ANSI_SGR_RESET ANSI_SGR 
   36 #define PLAYER_COLORS_COUNT 5 
   41   "red", 
"green", 
"yellow", 
"blue", 
"magenta" 
   60     printf(
"%3d|", y + 1);
 
   99   printf(
"\n%s\n", message);
 
  103   printf(
"id\t| name\t| score\n");
 
  117   bool ok = scanf(
"%d %d", &out->
x, &out->
y) != 2;
 
  118   out->
x -= 1, out->
y -= 1;
 
  139   HANDLE out_handle = GetStdHandle(STD_OUTPUT_HANDLE);
 
  141   GetConsoleMode(out_handle, &out_mode);
 
  142   out_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
 
  143   SetConsoleMode(out_handle, out_mode);
 
  152   printf(
"Please input number of players:\n");
 
  153   scanf(
"%d", &players_count);
 
  156   for (
int i = 0; i < players_count; i++) {
 
  160     printf(
"Player %d, please input name:\n", i + 1);
 
  164     printf(
"Player %d, select your color:\n", i + 1);
 
  175       scanf(
"%d", &color_choice);
 
  177     player->
color = color_choice - 1;
 
  181   printf(
"Please input number of penguins per player:\n");
 
  182   scanf(
"%d", &penguin_count);
 
  187   printf(
"Please specify width and height of the board\n");
 
  188   printf(
"E.g.: 10 5 -> width=10, height=5\n");
 
  189   scanf(
"%d %d", &board_width, &board_height);
 
  211       return "Inputted coordinates are outside the bounds of the board";
 
  217   return "ERROR: what on god's green earth did you just select???";
 
  225     if (result < 0) 
break;
 
  236     "Player %d, please input x and y coordinates to place the penguin:\n",
 
  269   Coords penguin = { 0, 0 };
 
  273     if (result < 0) 
break;
 
  284     printf(
"Chose a penguin\n");
 
  294     printf(
"Where do you want to move?\n");
 
void generate_board_random(Game *game, Rng *rng)
Generates the board by setting every tile purely randomly. The resulting board will look sort of like...
 
Functions for working with the game board (and the specifics of its encoding)
 
#define is_fish_tile(tile)
 
#define is_penguin_tile(tile)
 
#define is_water_tile(tile)
 
#define get_tile_player_id(tile)
 
#define get_tile_fish(tile)
 
The core of the unified game logic library, contains the Game struct.
 
void print_game_state(const Game *game)
 
static const char *const PLAYER_COLOR_NAMES[PLAYER_COLORS_COUNT]
 
static void display_error_message(const char *message)
 
#define ANSI_SGR_BACK_COLOR
 
void handle_placement_input(Game *game, Coords *selected)
 
int run_interactive_mode(void)
 
void interactive_movement(Game *game)
 
static const char * describe_movement_result(MovementError result)
 
static void clear_screen(void)
 
#define ANSI_SGR_FORE_COLOR
 
static bool scan_coords(Coords *out)
 
static const char *const PLAYER_ANSI_COLORS[PLAYER_COLORS_COUNT]
 
#define PLAYER_COLORS_COUNT
 
static void display_new_turn_message(Game *game)
 
static const char * describe_placement_result(PlacementError result)
 
void print_board(const Game *game)
 
static void update_game_state_display(const Game *game)
 
void interactive_placement(Game *game)
 
void print_player_stats(const Game *game)
 
void handle_movement_input(Game *game, Coords *penguin, Coords *target)
 
The interactive-mode text user interface.
 
Movement phase functions.
 
@ MOVEMENT_OVER_EMPTY_TILE
 
@ MOVEMENT_PENGUIN_BLOCKED
 
@ MOVEMENT_NOT_YOUR_PENGUIN
 
@ MOVEMENT_CURRENT_LOCATION
 
@ MOVEMENT_ONTO_EMPTY_TILE
 
Placement phase functions.
 
@ PLACEMENT_MULTIPLE_FISH
 
@ PLACEMENT_ENEMY_PENGUIN
 
@ PLACEMENT_OUT_OF_BOUNDS
 
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...
 
int movement_switch_player(Game *game)
Performs the player switching logic for the movement phase.
 
Player * game_get_current_player(const Game *self)
A shorthand for calling game_get_player with Game::current_player_index.
 
int game_find_player_by_id(const Game *self, short id)
Returns an index of the player or -1 if no such player was found.
 
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_begin_setup(Game *self)
Switches to the GAME_PHASE_SETUP phase, can only be called in GAME_PHASE_NONE. Should be called right...
 
void game_end(Game *self)
Switches to the GAME_PHASE_END phase.
 
int board_width
Use setup_board for setting this.
 
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...
 
void game_end_setup(Game *self)
Verifies that all fields have been initialized and configured and switches the phase from GAME_PHASE_...
 
void placement_begin(Game *game)
Enters the GAME_PHASE_PLACEMENT phase, can only be called in GAME_PHASE_SETUP_DONE.
 
int board_height
Use setup_board for setting this.
 
PlacementError validate_placement(const Game *game, Coords target)
 
int placement_switch_player(Game *game)
Performs the player switching logic for the placement phase.
 
void movement_begin(Game *game)
Enters the GAME_PHASE_MOVEMENT phase, can only be called in GAME_PHASE_SETUP_DONE.
 
int current_player_index
A negative value means that there is no current player selected. Use game_set_current_player for sett...
 
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.
 
int players_count
Use game_set_players_count for setting this.
 
MovementError validate_movement(const Game *game, Coords start, Coords target, Coords *fail)
 
void place_penguin(Game *game, Coords target)
Creates a GameLogPlacement entry. The requested placement must be valid.
 
MovementError validate_movement_start(const Game *game, Coords start)
 
void movement_end(Game *game)
Exits the GAME_PHASE_MOVEMENT phase and switches to GAME_PHASE_SETUP_DONE.
 
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...
 
void placement_end(Game *game)
Exits the GAME_PHASE_PLACEMENT phase and switches to GAME_PHASE_SETUP_DONE.
 
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.
 
char * name
Use game_set_player_name to set this.
 
int color
The color of the penguins, currently used only in the TUI.
 
int points
The score of the player, i.e. the number of collected fish.
 
A wrapper around random number generators.
 
Rng init_stdlib_rng(void)
Returns an RNG implementation based on the rand function from <stdlib.h> (and seeds it with srand).