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