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).