aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile18
-rw-r--r--include/tak.c59
-rw-r--r--include/tak.h54
-rw-r--r--src/ctaklm.c8
5 files changed, 141 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..261c153
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.o
+ctaklm
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..afc530a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+IDIR=include
+CFLAGS=-g -Wall -I$(IDIR)
+LIBS=
+
+SRCS=$(wildcard src/*.c) $(wildcard include/*.c)
+OBJS=$(SRCS:.c=.o)
+
+PROG=ctaklm
+
+%.o: %.c
+ cc -c $< -o $@ $(CFLAGS)
+
+$(PROG): $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) -o $(PROG)
+
+clean:
+ rm -f $(PROG)
+ rm -f $(OBJS)
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
diff --git a/src/ctaklm.c b/src/ctaklm.c
new file mode 100644
index 0000000..8330012
--- /dev/null
+++ b/src/ctaklm.c
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <tak.h>
+
+int main(int argc, char **argv) {
+ cell_t x = CELL_EMPTY_VALUE;
+ printf("Test %d\n",x);
+}