diff options
| -rw-r--r-- | include/enums.h | 7 | ||||
| -rw-r--r-- | include/ptn.c | 18 | ||||
| -rw-r--r-- | include/ptn.h | 7 | ||||
| -rw-r--r-- | include/state.c | 106 | ||||
| -rw-r--r-- | include/state.h | 10 | ||||
| -rw-r--r-- | include/tak.c | 29 | ||||
| -rw-r--r-- | include/tak.h | 7 |
7 files changed, 145 insertions, 39 deletions
diff --git a/include/enums.h b/include/enums.h index 3f1e172..752c678 100644 --- a/include/enums.h +++ b/include/enums.h @@ -3,6 +3,9 @@ enum COLOUR { C_WHITE, C_BLACK }; enum STONE_VARIANT { STONE_FLAT, STONE_STANDING, STONE_CAPSTONE }; enum MOVE_DIRECTION { M_UP, M_DOWN, M_LEFT, M_RIGHT }; -enum ACTION_RESULT { A_OK, A_ILLEGAL, A_OVERFLOW }; -enum WIN_RESULT { W_NONE, W_ROAD_WHITE, W_ROAD_BLACK, W_FLAT_WHITE, W_FLAT_BLACK }; +enum E_RESULT { A_OK, A_ILLEGAL, A_OVERFLOW, + PTN_VALID, PTN_INVALID, + W_NONE, W_DRAW, W_DRAGON, + W_ROAD_WHITE, W_ROAD_BLACK, + W_FLAT_WHITE, W_FLAT_BLACK }; #endif diff --git a/include/ptn.c b/include/ptn.c index 66b4ad8..3d9c0a5 100644 --- a/include/ptn.c +++ b/include/ptn.c @@ -3,7 +3,21 @@ #define ASSERT_NONEMPTY { if (ptn == 0 || *ptn == 0) return PTN_INVALID; } #define ASSERT_MORE { if (*ptn == 0) return PTN_INVALID; } -enum PTN_PARSE_RESULT +uint8_t +likely_move(char *ptn) { + if (ptn == 0) return 0; + for (;;ptn++) { + switch (*ptn) { + case '+': + case '-': + case '>': + case '<': return 1; + case 0: return 0; + } + } +} + +enum E_RESULT parse_place(const uint8_t board_size, char *ptn, uint8_t *out_location, enum STONE_VARIANT *out_stone) { @@ -33,7 +47,7 @@ parse_place(const uint8_t board_size, char *ptn, return PTN_VALID; } -enum PTN_PARSE_RESULT +enum E_RESULT parse_move(const uint8_t board_size, char *ptn, uint8_t *out_location, enum MOVE_DIRECTION *out_direction, uint8_t *out_steps, uint8_t out_drops[5]) { diff --git a/include/ptn.h b/include/ptn.h index 0baed01..fd154f9 100644 --- a/include/ptn.h +++ b/include/ptn.h @@ -1,13 +1,14 @@ #include <stdint.h> #include "enums.h" -enum PTN_PARSE_RESULT { PTN_VALID, PTN_INVALID }; +uint8_t +likely_move(char *ptn); -enum PTN_PARSE_RESULT +enum E_RESULT parse_place(const uint8_t board_size, char *ptn, uint8_t *out_location, enum STONE_VARIANT *out_stone); -enum PTN_PARSE_RESULT +enum E_RESULT parse_move(const uint8_t board_size, char *ptn, uint8_t *out_location, enum MOVE_DIRECTION *out_direction, uint8_t *out_steps, uint8_t out_drops[5]); diff --git a/include/state.c b/include/state.c index 3708792..dfdd02b 100644 --- a/include/state.c +++ b/include/state.c @@ -18,7 +18,8 @@ // ------------------------------------------------------------------- // Game management -void reset_state(const uint8_t new_board_size) { +void +reset_state(const uint8_t new_board_size) { if (new_board_size == 6) { board_size = 6; white_flats = 30; black_flats = 30; @@ -30,16 +31,39 @@ void reset_state(const uint8_t new_board_size) { black_caps = 1; turn = 0; + current_colour = C_BLACK; for (uint8_t k = 0; k < board_size * board_size; k++ ) { celldat[k] = 0; } } +void +next_turn(void) { + /* + + StartType::CPS(c) => { + if ply / 2 >= (*c as usize) { + if ply % 2 == 0 { + (Player::White, TurnOrder::Normal) + } else { + (Player::Black, TurnOrder::Normal) + } + } else { + if ply % 2 == 0 { + (Player::White, TurnOrder::WhitePlacesBlack) + } else { + (Player::Black, TurnOrder::BlackPlacesWhite) + } + } + } + */ +} + // ------------------------------------------------------------------- // Place stone -enum ACTION_RESULT +enum E_RESULT try_place(const int8_t location, const enum COLOUR colour, const enum STONE_VARIANT stone) { @@ -95,7 +119,7 @@ drop_stones(const int8_t location, const uint8_t count) { celldat[location] = dec_count & NUM_MASK; } -enum ACTION_RESULT +enum E_RESULT try_move(const int8_t location, const enum MOVE_DIRECTION direction, const uint8_t steps, const uint8_t drops[5]) { // Can't do this @@ -225,34 +249,16 @@ dfs_road(uint8_t dfs_stack[board_size*board_size], uint8_t dfs_pntr, return 0; } -enum WIN_RESULT -check_win(const enum COLOUR colour) { - // Do we do a flat count? - if (black_flats == 0 || white_flats == 0 || board_full()) { - int8_t total = 0; - for (uint8_t k = 0; k < board_size * board_size; k++) { - if (STONE_AT(k) == STONE_FLAT) { - total += ((colours[k] & 1) == C_BLACK) ? +1 : -1 ; - } - } - if (total > 0) return W_FLAT_BLACK; - else return W_FLAT_WHITE; - } - - // Road? +enum E_RESULT +check_road_colour(const enum COLOUR colour) { uint8_t dfs_stack[board_size * board_size]; uint8_t dfs_pntr = 0; // Prime the depth-first-search stack with all boundary cells of - // colour COLOUR, we're using the two left-over bits in data_t to - // track whether we've seen it. Reset those before anything. + // colour COLOUR. - for (uint8_t k=0; k<board_size*board_size; k++) { - celldat[k] &= USED_MASK; - } - - enum WIN_RESULT res = (colour == C_BLACK) ? - W_ROAD_BLACK : W_ROAD_WHITE; + const enum E_RESULT winner = + (colour == C_BLACK) ? W_ROAD_BLACK : W_ROAD_WHITE; // First left-to-right for (uint8_t y=0; y<board_size; y++) { @@ -261,7 +267,7 @@ check_win(const enum COLOUR colour) { celldat[THE_COORDS(0, y)] |= DFS_MASK; } } - if (dfs_road(dfs_stack, dfs_pntr, colour, 0)) return res; + if (dfs_road(dfs_stack, dfs_pntr, colour, 0)) return winner; // Then top-to-bottom for (uint8_t x=1; x+1<board_size; x++) { @@ -270,7 +276,51 @@ check_win(const enum COLOUR colour) { celldat[THE_COORDS(x, 0)] |= DFS_MASK; } } - if (dfs_road(dfs_stack, dfs_pntr, colour, 1)) return res; + if (dfs_road(dfs_stack, dfs_pntr, colour, 1)) return winner; return W_NONE; } + +enum E_RESULT +check_win(void) { + // Do we do a flat count? + if (black_flats == 0 || white_flats == 0 || board_full()) { + int8_t total = 0; + for (uint8_t k = 0; k < board_size * board_size; k++) { + if (STONE_AT(k) == STONE_FLAT) { + total += ((colours[k] & 1) == C_BLACK) ? +1 : -1 ; + } + } + if (total > 0) { + return W_FLAT_BLACK; + } else if (total < 0) { + return W_FLAT_WHITE; + } else { + return W_DRAW; + } + } + + // Road? + + // We're using the two left-over bits in data_t to track whether + // we've seen it. Reset those before anything. No need to do it + // between checks, however, as pieces are black XOR white. + + for (uint8_t k=0; k<board_size*board_size; k++) { + celldat[k] &= USED_MASK; + } + + enum E_RESULT rb, rw; + rb = check_road_colour(C_BLACK); + rw = check_road_colour(C_WHITE); + + if (rb == W_ROAD_BLACK) { + if (rw == W_ROAD_WHITE) { + return W_DRAGON; + } else { + return W_ROAD_BLACK; + } + } else { + return rw; + } +} diff --git a/include/state.h b/include/state.h index 17d705a..218bf71 100644 --- a/include/state.h +++ b/include/state.h @@ -7,17 +7,19 @@ typedef uint8_t data_t; static uint8_t board_size; static data_t celldat[36]; static colour_stack_t colours[36]; +static enum COLOUR current_colour; static uint8_t white_flats, black_flats, white_caps, black_caps, turn; void reset_state(const uint8_t new_board_size); +void next_turn(void); -enum ACTION_RESULT +enum E_RESULT try_place(const int8_t location, const enum COLOUR colour, const enum STONE_VARIANT stone); -enum ACTION_RESULT +enum E_RESULT try_move(const int8_t location, const enum MOVE_DIRECTION direction, const uint8_t steps, const uint8_t drops[5]); -enum WIN_RESULT -check_win(const enum COLOUR colour); +enum E_RESULT +check_win(void); diff --git a/include/tak.c b/include/tak.c new file mode 100644 index 0000000..85d04d4 --- /dev/null +++ b/include/tak.c @@ -0,0 +1,29 @@ +#include "tak.h" + +enum E_RESULT +try_ptn(char *ptn) { + + enum E_RESULT res; + uint8_t location; + + if (likely_move(ptn)) { + uint8_t steps, drops[5]; + enum MOVE_DIRECTION direction; + res = parse_move(board_size, ptn, &location, + &direction, &steps, drops); + if (res == PTN_VALID) + res = try_move(location, direction, steps, drops); + } else { + enum STONE_VARIANT stone; + res = parse_place(board_size, ptn, &location, &stone); + if (res == PTN_VALID) + res = try_place(location, current_colour, stone); + } + + if (res == A_OK) { + next_turn(); + if (turn > 1) return check_win(); + } + + return res; +} diff --git a/include/tak.h b/include/tak.h new file mode 100644 index 0000000..1c0ef50 --- /dev/null +++ b/include/tak.h @@ -0,0 +1,7 @@ +#include "state.h" +#include "ptn.h" + +void reset_game(const uint8_t new_board_size); + +enum E_RESULT +try_ptn(char *ptn); |
