diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/tak.c | 59 | ||||
| -rw-r--r-- | include/tak.h | 54 |
2 files changed, 113 insertions, 0 deletions
diff --git a/include/tak.c b/include/tak.c new file mode 100644 index 0000000..a4c053b --- /dev/null +++ b/include/tak.c @@ -0,0 +1,59 @@ +#include "tak.h" + +// Be sure not to set higher bits in colour than LSB +void set_stone(board_t board, bit_board_t *capstand, + const uint8_t location, + const uint8_t colour, + const enum STONE_VARIANT stone) { + + board[location] = (STONE_IS_CAPSTAND(stone) ? CELL_MASK_CAPSTAND : 0x0000) + | CELL_COUNT_INC | colour; + if (stone == STONE_CAPSTONE) BITBOARD_SET(*capstand, location); +} + +// This can overflow, checks are elsewhere +void push_cells_stack(board_t board, bit_board_t *capstand, + const uint8_t location, const uint8_t count, + const uint8_t colours, + const enum STONE_VARIANT top_stone) { + + if (top_stone == STONE_CAPSTONE) BITBOARD_RST(*capstand, location); + + const cell_t cell = board[location]; + const uint8_t new_count = CELL_GET_COUNT(cell) + count; + const uint8_t new_stack = (CELL_GET_STACK(cell) << count) | colours; + + board[location] = (STONE_IS_CAPSTAND(top_stone) ? CELL_MASK_CAPSTAND : 0x0000) + | ((new_count > 0xA) ? 0xA : new_count) + | (new_stack & CELL_MASK_STACK); +} + +// Calling this with count = 0 is destructive +void drop_cells_stack(board_t board, bit_board_t *capstand, + const uint8_t location, const uint8_t count) { + + // NOTE: We always clear the bitboard and capstand flags as it's not + // possible that those stones are underneath anything. + + BITBOARD_RST(*capstand, location); + const uint8_t cur_count = CELL_GET_COUNT(board[location]); + if (count >= cur_count) { + board[location] = CELL_EMPTY_VALUE; + } else { + board[location] = ((cur_count - count) << CELL_COUNT_SHIFT) + | (CELL_GET_STACK(board[location]) >> count); + } +} + +enum ACTION_RESULT try_place_stone(board_t board, bit_board_t *capstand, + const uint8_t location, const uint8_t colour, + const enum STONE_VARIANT stone) +{ + // Can't place on an occupied square + if (CELL_IS_EMPTY(board[location])) { + set_stone(board, capstand, location, colour, stone); + return A_OK; + } else { + return A_ILLEGAL; + } +} diff --git a/include/tak.h b/include/tak.h new file mode 100644 index 0000000..5a7f2fa --- /dev/null +++ b/include/tak.h @@ -0,0 +1,54 @@ +#include <stdlib.h> +#include <stdint.h> + +/* 16 bits arranged as follows: + + MSB : capstone or standing stone + 14-11: number of stones in the cell, 0x0-0xA valid, 0xF means empty + 0-10 : stack, LSB is top + +*/ +typedef uint16_t cell_t; + +#define CELL_EMPTY_VALUE 0b0111100000000000 +#define CELL_MASK_CAPSTAND 0b1000000000000000 +#define CELL_MASK_COUNT CELL_EMPTY_VALUE +#define CELL_MASK_STACK 0b0000011111111111 +#define CELL_MASK_NOTSTACK 0b1111100000000000 + +#define CELL_COUNT_MAX 0b0101000000000000 +#define CELL_COUNT_INC 0b0000100000000000 +#define CELL_COUNT_SHIFT 11 + +#define CELL_IS_EMPTY(x) ((x) == CELL_EMPTY_VALUE) +#define CELL_IS_CAPSTAND(x) ((x) & CELL_MASK_CAPSTAND) +#define CELL_TOP_IS_BLACK(x) ((x) & 1) +#define CELL_TOP_IS_WHITE(x) (~(CELL_TOP_IS_BLACK(x))) + +#define CELL_SET_TOP_BLACK(x) ((x) |= 0x0001) +#define CELL_SET_TOP_WHITE(x) ((x) &= 0xFFFE) +#define CELL_SET_CAPSTAND(x) ((x) |= CELL_MASK_CAPSTAND) + +#define CELL_GET_COUNT(x) ((uint8_t)(((x) & CELL_MASK_COUNT) >> CELL_COUNT_SHIFT)) +#define CELL_GET_STACK(x) ((x) & CELL_MASK_STACK) +#define CELL_GET_NOTSTACK(x) ((x) & CELL_MASK_NOTSTACK) + +enum ACTION_RESULT { A_OK, A_ILLEGAL, A_OVERFLOW }; + +typedef cell_t* board_t; +typedef uint64_t bit_board_t; // 8x8 board is exactly 8 bytes :) + +#define BITBOARD_SET(bb,location) ((bb) |= 1ULL << (location)) +#define BITBOARD_RST(bb,location) ((bb) &= ~(1ULL << (location))) + +enum STONE_VARIANT { STONE_FLAT, STONE_STANDING, STONE_CAPSTONE }; +#define STONE_IS_CAPSTAND(s) ((s == STONE_CAPSTONE) || (s == STONE_STANDING)) + +// Taking actions +enum ACTION_RESULT try_place_stone(board_t board, bit_board_t *capstand, + const uint8_t location, const uint8_t colour, + const enum STONE_VARIANT stone); + +// enum ACTION_RESULT move_stack(board_t *board, bit_board *capstand, uint8_t source, uint); + +// Querying things |
