aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-04-11 00:36:45 +0300
committereug-vs <eugene@eug-vs.xyz>2022-04-11 00:36:45 +0300
commita6dc21034a55be0a9c1910787d615b5bca7131c6 (patch)
tree90dd29b77d2cd27b7a3f72754b7bfccc6577d88f
parentca745926cf181e1aee026c48335543610f60770e (diff)
downloadcarcassonne-engine-c-a6dc21034a55be0a9c1910787d615b5bca7131c6.tar.gz
refactor: divide code into modules
-rw-r--r--src/board.c129
-rw-r--r--src/board.h43
-rw-r--r--src/carcassonne.h31
-rw-r--r--src/config.h4
-rw-r--r--src/main.c31
-rw-r--r--src/meeple.c36
-rw-r--r--src/meeple.h6
-rw-r--r--src/structure.c55
-rw-r--r--src/structure.h8
-rw-r--r--src/tile.c41
-rw-r--r--src/tile.h12
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
+
+
diff --git a/src/main.c b/src/main.c
index 888763d..34524a6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);