diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-04-11 00:36:45 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-04-11 00:36:45 +0300 |
commit | a6dc21034a55be0a9c1910787d615b5bca7131c6 (patch) | |
tree | 90dd29b77d2cd27b7a3f72754b7bfccc6577d88f | |
parent | ca745926cf181e1aee026c48335543610f60770e (diff) | |
download | carcassonne-engine-c-a6dc21034a55be0a9c1910787d615b5bca7131c6.tar.gz |
refactor: divide code into modules
-rw-r--r-- | src/board.c | 129 | ||||
-rw-r--r-- | src/board.h | 43 | ||||
-rw-r--r-- | src/carcassonne.h | 31 | ||||
-rw-r--r-- | src/config.h | 4 | ||||
-rw-r--r-- | src/main.c | 31 | ||||
-rw-r--r-- | src/meeple.c | 36 | ||||
-rw-r--r-- | src/meeple.h | 6 | ||||
-rw-r--r-- | src/structure.c | 55 | ||||
-rw-r--r-- | src/structure.h | 8 | ||||
-rw-r--r-- | src/tile.c | 41 | ||||
-rw-r--r-- | src/tile.h | 12 |
11 files changed, 204 insertions, 192 deletions
diff --git a/src/board.c b/src/board.c index 95b8738..8e17357 100644 --- a/src/board.c +++ b/src/board.c @@ -1,4 +1,3 @@ -#include <stdio.h> #include "board.h" void initialize_board(BoardUnit* board) { @@ -13,136 +12,8 @@ int is_center_index(int index) { return ((index / BOARD_ROW_UNITS) % 2 == 1) && ((index % BOARD_ROW_UNITS) % 2 == 1); } -int is_allowed_placement(Tile tile, int index, BoardUnit* board) { - if (board[index].feature != EMPTY) return 0; - - int neighbor_count = 0; - - for (int i = 0; i < 4; i++) { - char neighbor = board[index + NEIGHBOR_INCREMENTS[i]].feature; - if (neighbor != EMPTY) { - if (neighbor != tile.edges[i]) return 0; - neighbor_count++; - } - } - - return neighbor_count > 0; -} - -int place_tile(Tile tile, int index, BoardUnit* board, int force) { - if (!is_center_index(index)) return 0; - if (!force && !is_allowed_placement(tile, index, board)) return 0; - - board[index].feature = tile.center; - for (int i = 0; i < 4; i++) { - board[index + NEIGHBOR_INCREMENTS[i]].feature = tile.edges[i]; - } - - return 1; -} - -void rotate_tile(Tile* tile, int increment) { - char buffer[8]; - for (int i = 0; i < 8; i++) { - buffer[i] = tile->edges[i % 4]; - } - - for (int i = 0; i < 4; i++) { - tile->edges[i] = buffer[i + (increment % 4)]; - } -} - -void traverse_structure(int group, int index, BoardUnit* board) { - board[index].structure_group = group; - for (int i = 0; i < 4; i++) { - int new_unit = index + NEIGHBOR_INCREMENTS[i]; - if (board[new_unit].feature == board[index].feature && board[new_unit].structure_group == 0) { - traverse_structure(group, new_unit, board); - } else if (board[new_unit].feature == ANY && board[new_unit].structure_group != board[index].structure_group) { - board[new_unit].feature = board[index].feature; - traverse_structure(group, new_unit, board); - board[new_unit].feature = ANY; - } - } -} - -void refresh_structure_groups(BoardUnit* board) { - for (int i = 0; i < BOARD_UNITS; i++) board[i].structure_group = 0; - - int structure_group = 1; - for (int i = 0; i < BOARD_UNITS; i++) { - if ( - board[i].structure_group == 0 - && board[i].feature != EMPTY - && board[i].feature != SEPARATOR - && board[i].feature != 'F' - ) { - traverse_structure(structure_group, i, board); - structure_group += 1; - } - } -} - int translate_coordinate(int center_index) { return (2 * (center_index / BOARD_WIDTH) + 1) * (2 * BOARD_WIDTH + 1) + (2 * (center_index % BOARD_WIDTH) + 1); } - -int evaluate_structure(int index, BoardUnit* board) { - int value = 0; - - char feature = board[index].feature; - int structure_group = board[index].structure_group; - - for (int i = 0; i < BOARD_WIDTH; i++) { - for (int j = 0; j < BOARD_WIDTH; j++) { - int index = translate_coordinate(i * BOARD_WIDTH + j); - if (board[index].feature != EMPTY) { // Empty tiles doesn't count - for (int k = 0; k < 4; k++) { - if (board[index + NEIGHBOR_INCREMENTS[k]].structure_group == structure_group) { - value++; - break; - } - } - } - } - } - - return value; -} - -void refresh_meeple_map(BoardUnit* board, int* meeple_map) { - for (int i = 0; i < MAX_STRUCTURES * PLAYERS; i++) meeple_map[i] = 0; - - for (int i = 0; i < BOARD_UNITS; i++) { - if (board[i].meeple) { - meeple_map[board[i].structure_group * PLAYERS + (board[i].meeple - 1)]++; - } - } -} - -int is_allowed_meeple(int meeple, int index, BoardUnit* board, int* meeple_map) { - if (board[index].meeple - || board[index].feature == 'F' - || board[index].feature == ANY - || board[index].feature == SEPARATOR - ) return 0; - - int dominator = get_structure_dominator(board[index].structure_group, meeple_map); - return dominator == meeple || dominator == 0; -} - -int get_structure_dominator(int structure_group, int* meeple_map) { - int dominator = 0; - int dominator_meeples = 0; - - for (int player = 0; player < PLAYERS; player++) { - int meeples = meeple_map[structure_group * PLAYERS + player]; - if (meeples > dominator_meeples) { - dominator_meeples = meeples; - dominator = player + 1; - } - } - return dominator; -} diff --git a/src/board.h b/src/board.h index cd78901..3d3fdc2 100644 --- a/src/board.h +++ b/src/board.h @@ -1,22 +1,8 @@ -#define BOARD_WIDTH 9 +#pragma once +#include "config.h" + #define BOARD_ROW_UNITS ((BOARD_WIDTH * 2) + 1) #define BOARD_UNITS BOARD_ROW_UNITS * BOARD_ROW_UNITS -#define PLAYERS 2 -#define MAX_STRUCTURES 100 - -/* constants */ -const char EMPTY = ' '; -const char ANY = '*'; -const char SEPARATOR = '+'; - -const int NEIGHBOR_INCREMENTS[] = { -BOARD_ROW_UNITS, 1, BOARD_ROW_UNITS, -1 }; - -/* structs */ -typedef struct { - char edges[4]; - char center; - int shield; -} Tile; typedef struct { char feature; @@ -24,23 +10,12 @@ typedef struct { int structure_group; } BoardUnit; -/* board */ +static const char EMPTY = ' '; +static const char ANY = '*'; +static const char SEPARATOR = '+'; + +static const int NEIGHBOR_INCREMENTS[] = { -BOARD_ROW_UNITS, 1, BOARD_ROW_UNITS, -1 }; + void initialize_board(BoardUnit* board); int translate_coordinate(int index); int is_center_index(int index); - -/* tiles */ -int is_allowed_placement(Tile tile, int index, BoardUnit* board); -int place_tile(Tile tile, int index, BoardUnit* board, int force); -void rotate_tile(Tile* tile, int increment); - -/* structures */ -void traverse_structure(int group, int index, BoardUnit* board); -void refresh_structure_groups(BoardUnit* board); -int evaluate_structure(int index, BoardUnit* board); - - -/* meeples */ -int is_allowed_meeple(int meeple, int index, BoardUnit* board, int* meeple_map); -void refresh_meeple_map(BoardUnit* board, int* meeple_map); -int get_structure_dominator(int structure_group, int* meeple_map); diff --git a/src/carcassonne.h b/src/carcassonne.h new file mode 100644 index 0000000..2bb136c --- /dev/null +++ b/src/carcassonne.h @@ -0,0 +1,31 @@ +#include "board.h" +#include "tile.h" +#include "meeple.h" +#include "structure.h" + +static const Tile TILESET[19] = { + /* cities */ + { "FFFF", 'F', 0 }, + { "CFFF", 'F', 0 }, + { "FCFC", 'C', 0 }, + { "FCFC", 'F', 0 }, + { "CCFF", 'C', 0 }, + { "CCFF", 'F', 0 }, + { "CCCF", 'C', 0 }, + { "CCCC", 'C', 0 }, + + /* roads */ + { "FFFR", 'R', 0 }, + { "FRFR", 'R', 0 }, + { "FFRR", 'R', 0 }, + { "FRRR", '+', 0 }, + { "RRRR", '+', 0 }, + + /* mix */ + { "CRFR", 'R', 0 }, + { "CFRR", 'R', 0 }, + { "CRRF", 'R', 0 }, + { "CRRR", '+', 0 }, + { "CCRR", '*', 0 }, + { "CCCR", 'C', 0 }, +}; diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..12fbcad --- /dev/null +++ b/src/config.h @@ -0,0 +1,4 @@ +#define BOARD_WIDTH 9 +#define PLAYERS 2 + + @@ -2,7 +2,7 @@ #include <stdlib.h> #include <curses.h> #include <time.h> -#include "board.h" +#include "carcassonne.h" int get_player_color(int player) { return player ? COLOR_PAIR(player + 2) : COLOR_PAIR(0); @@ -57,33 +57,6 @@ int main() { Tile tile = { "FRCR", 'R', 0 }; place_tile(tile, translate_coordinate(BOARD_WIDTH * BOARD_WIDTH / 2), board, 1); - Tile tileset[19] = { - /* cities */ - { "FFFF", 'F', 0 }, - { "CFFF", 'F', 0 }, - { "FCFC", 'C', 0 }, - { "FCFC", 'F', 0 }, - { "CCFF", 'C', 0 }, - { "CCFF", 'F', 0 }, - { "CCCF", 'C', 0 }, - { "CCCC", 'C', 0 }, - - /* roads */ - { "FFFR", 'R', 0 }, - { "FRFR", 'R', 0 }, - { "FFRR", 'R', 0 }, - { "FRRR", '+', 0 }, - { "RRRR", '+', 0 }, - - /* mix */ - { "CRFR", 'R', 0 }, - { "CFRR", 'R', 0 }, - { "CRRF", 'R', 0 }, - { "CRRR", '+', 0 }, - { "CCRR", '*', 0 }, - { "CCCR", 'C', 0 }, - }; - /* main loop */ char input_key; for (int move = 0; ; move++) { @@ -93,7 +66,7 @@ int main() { draw_board(board, meeple_map, board_win); /* tile placement */ - tile = tileset[rand() % 19]; + tile = TILESET[rand() % 19]; int position = 0; BoardUnit board_preview[BOARD_UNITS]; diff --git a/src/meeple.c b/src/meeple.c new file mode 100644 index 0000000..b9df686 --- /dev/null +++ b/src/meeple.c @@ -0,0 +1,36 @@ +#include "meeple.h" + +void refresh_meeple_map(BoardUnit* board, int* meeple_map) { + for (int i = 0; i < MAX_STRUCTURES * PLAYERS; i++) meeple_map[i] = 0; + + for (int i = 0; i < BOARD_UNITS; i++) { + if (board[i].meeple) { + meeple_map[board[i].structure_group * PLAYERS + (board[i].meeple - 1)]++; + } + } +} + +int is_allowed_meeple(int meeple, int index, BoardUnit* board, int* meeple_map) { + if (board[index].meeple + || board[index].feature == 'F' + || board[index].feature == ANY + || board[index].feature == SEPARATOR + ) return 0; + + int dominator = get_structure_dominator(board[index].structure_group, meeple_map); + return dominator == meeple || dominator == 0; +} + +int get_structure_dominator(int structure_group, int* meeple_map) { + int dominator = 0; + int dominator_meeples = 0; + + for (int player = 0; player < PLAYERS; player++) { + int meeples = meeple_map[structure_group * PLAYERS + player]; + if (meeples > dominator_meeples) { + dominator_meeples = meeples; + dominator = player + 1; + } + } + return dominator; +} diff --git a/src/meeple.h b/src/meeple.h new file mode 100644 index 0000000..5a7df20 --- /dev/null +++ b/src/meeple.h @@ -0,0 +1,6 @@ +#pragma once +#include "structure.h" + +int is_allowed_meeple(int meeple, int index, BoardUnit* board, int* meeple_map); +void refresh_meeple_map(BoardUnit* board, int* meeple_map); +int get_structure_dominator(int structure_group, int* meeple_map); diff --git a/src/structure.c b/src/structure.c new file mode 100644 index 0000000..a3039e7 --- /dev/null +++ b/src/structure.c @@ -0,0 +1,55 @@ +#include "structure.h" + +void traverse_structure(int group, int index, BoardUnit* board) { + board[index].structure_group = group; + for (int i = 0; i < 4; i++) { + int new_unit = index + NEIGHBOR_INCREMENTS[i]; + if (board[new_unit].feature == board[index].feature && board[new_unit].structure_group == 0) { + traverse_structure(group, new_unit, board); + } else if (board[new_unit].feature == ANY && board[new_unit].structure_group != board[index].structure_group) { + board[new_unit].feature = board[index].feature; + traverse_structure(group, new_unit, board); + board[new_unit].feature = ANY; + } + } +} + +void refresh_structure_groups(BoardUnit* board) { + for (int i = 0; i < BOARD_UNITS; i++) board[i].structure_group = 0; + + int structure_group = 1; + for (int i = 0; i < BOARD_UNITS; i++) { + if ( + board[i].structure_group == 0 + && board[i].feature != EMPTY + && board[i].feature != SEPARATOR + && board[i].feature != 'F' + ) { + traverse_structure(structure_group, i, board); + structure_group += 1; + } + } +} + +int evaluate_structure(int index, BoardUnit* board) { + int value = 0; + + char feature = board[index].feature; + int structure_group = board[index].structure_group; + + for (int i = 0; i < BOARD_WIDTH; i++) { + for (int j = 0; j < BOARD_WIDTH; j++) { + int index = translate_coordinate(i * BOARD_WIDTH + j); + if (board[index].feature != EMPTY) { // Empty tiles doesn't count + for (int k = 0; k < 4; k++) { + if (board[index + NEIGHBOR_INCREMENTS[k]].structure_group == structure_group) { + value++; + break; + } + } + } + } + } + + return value; +} diff --git a/src/structure.h b/src/structure.h new file mode 100644 index 0000000..420c705 --- /dev/null +++ b/src/structure.h @@ -0,0 +1,8 @@ +#pragma once +#include "tile.h" + +#define MAX_STRUCTURES 100 + +void traverse_structure(int group, int index, BoardUnit* board); +void refresh_structure_groups(BoardUnit* board); +int evaluate_structure(int index, BoardUnit* board); diff --git a/src/tile.c b/src/tile.c new file mode 100644 index 0000000..2688c2a --- /dev/null +++ b/src/tile.c @@ -0,0 +1,41 @@ +#include "tile.h" + +int is_allowed_placement(Tile tile, int index, BoardUnit* board) { + if (board[index].feature != EMPTY) return 0; + + int neighbor_count = 0; + + for (int i = 0; i < 4; i++) { + char neighbor = board[index + NEIGHBOR_INCREMENTS[i]].feature; + if (neighbor != EMPTY) { + if (neighbor != tile.edges[i]) return 0; + neighbor_count++; + } + } + + return neighbor_count > 0; +} + +int place_tile(Tile tile, int index, BoardUnit* board, int force) { + if (!is_center_index(index)) return 0; + if (!force && !is_allowed_placement(tile, index, board)) return 0; + + board[index].feature = tile.center; + for (int i = 0; i < 4; i++) { + board[index + NEIGHBOR_INCREMENTS[i]].feature = tile.edges[i]; + } + + return 1; +} + +void rotate_tile(Tile* tile, int increment) { + char buffer[8]; + for (int i = 0; i < 8; i++) { + buffer[i] = tile->edges[i % 4]; + } + + for (int i = 0; i < 4; i++) { + tile->edges[i] = buffer[i + (increment % 4)]; + } +} + diff --git a/src/tile.h b/src/tile.h new file mode 100644 index 0000000..721630e --- /dev/null +++ b/src/tile.h @@ -0,0 +1,12 @@ +#pragma once +#include "board.h" + +typedef struct { + char edges[5]; + char center; + int shield; +} Tile; + +int is_allowed_placement(Tile tile, int index, BoardUnit* board); +int place_tile(Tile tile, int index, BoardUnit* board, int force); +void rotate_tile(Tile* tile, int increment); |