summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/enums.h7
-rw-r--r--include/ptn.c18
-rw-r--r--include/ptn.h7
-rw-r--r--include/state.c106
-rw-r--r--include/state.h10
-rw-r--r--include/tak.c29
-rw-r--r--include/tak.h7
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);