aboutsummaryrefslogtreecommitdiff
path: root/src/core/sok.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/sok.h')
-rw-r--r--src/core/sok.h257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/core/sok.h b/src/core/sok.h
new file mode 100644
index 0000000..1503b5f
--- /dev/null
+++ b/src/core/sok.h
@@ -0,0 +1,257 @@
+#ifndef SOK_H
+#define SOK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdint.h> // uint16_t
+#include <stddef.h> // size_t
+
+/*********/
+/* types */
+/*********/
+
+typedef struct {
+ uint16_t x, y;
+} sok_pos_t;
+
+typedef enum {
+ SOK_DIR_RIGHT,
+ SOK_DIR_UP,
+ SOK_DIR_LEFT,
+ SOK_DIR_DOWN,
+ SOK_DIR_LAST,
+} sok_dir_t;
+
+#define SOK_DIR_TO_CHAR(dir) ( \
+ ((dir) == SOK_DIR_RIGHT) ? 'r' : \
+ (((dir) == SOK_DIR_UP) ? 'u' : \
+ ((((dir) == SOK_DIR_LEFT) ? 'l' : \
+ (((((dir) == SOK_DIR_DOWN) ? 'd' : \
+ 'X' \
+)))))))
+
+
+#define SOK_DIR_TO_STR(dir) ( \
+ ((dir) == SOK_DIR_RIGHT) ? "r" : \
+ (((dir) == SOK_DIR_UP) ? "u" : \
+ ((((dir) == SOK_DIR_LEFT) ? "l" : \
+ (((((dir) == SOK_DIR_DOWN) ? "d" : \
+ "X" \
+)))))))
+
+typedef struct {
+ sok_pos_t pos;
+ sok_dir_t dir;
+ _Bool is_push;
+} sok_move_t;
+
+/****************/
+/* level parser */
+/****************/
+
+typedef struct sok_level_parser_t_ sok_level_parser_t;
+
+typedef _Bool (*sok_level_parser_pos_cb_t)(
+ const sok_level_parser_t * const,
+ const sok_pos_t
+);
+
+typedef _Bool (*sok_level_parser_junk_cb_t)(
+ const sok_level_parser_t * const,
+ const size_t,
+ const char
+);
+
+typedef struct {
+ sok_level_parser_pos_cb_t on_size,
+ on_home,
+ on_wall,
+ on_goal,
+ on_box;
+ sok_level_parser_junk_cb_t on_junk;
+} sok_level_parser_cbs_t;
+
+struct sok_level_parser_t_ {
+ const sok_level_parser_cbs_t *cbs;
+ void *user_data;
+};
+
+void sok_level_parser_init(
+ sok_level_parser_t * const parser,
+ const sok_level_parser_cbs_t * const cbs,
+ void * const user_data
+);
+
+_Bool sok_level_parser_parse(
+ sok_level_parser_t * const parser,
+ const char * const buf,
+ const size_t buf_len
+);
+
+/*********/
+/* level */
+/*********/
+
+#define SOK_LEVEL_MAX_WIDTH (1 << 8)
+#define SOK_LEVEL_MAX_HEIGHT (1 << 8)
+#define SOK_LEVEL_MAX_BOXES 64
+#define SOK_LEVEL_MAX_GOALS 64
+
+typedef struct {
+ sok_pos_t size;
+ _Bool walls[SOK_LEVEL_MAX_WIDTH * SOK_LEVEL_MAX_HEIGHT];
+
+ // player home position
+ sok_pos_t home;
+
+ // boxes
+ sok_pos_t boxes[SOK_LEVEL_MAX_BOXES];
+ size_t num_boxes;
+
+ // goals
+ sok_pos_t goals[SOK_LEVEL_MAX_GOALS];
+ size_t num_goals;
+} sok_level_t;
+
+/***********/
+/* context */
+/***********/
+
+#define SOK_CTX_MAX_MOVES 1024
+
+typedef struct {
+ sok_level_t level;
+
+ // moves
+ sok_move_t moves[SOK_CTX_MAX_MOVES];
+ size_t num_moves;
+
+ // number of open goals
+ size_t num_goals_left;
+
+ // are there boxes in corners?
+ // _Bool is_lost;
+
+ // player position
+ sok_pos_t home;
+
+ // box positions
+ sok_pos_t boxes[SOK_LEVEL_MAX_BOXES];
+
+ // user data
+ void *user_data;
+} sok_ctx_t;
+
+void sok_ctx_init(sok_ctx_t * const ctx, void *user_data);
+
+_Bool sok_ctx_set_level(sok_ctx_t * const ctx, const char * const level);
+
+_Bool sok_ctx_is_done(const sok_ctx_t * const);
+// _Bool sok_ctx_is_lost(const sok_ctx_t * const);
+
+_Bool sok_ctx_move(sok_ctx_t * const, const sok_dir_t);
+_Bool sok_ctx_undo(sok_ctx_t * const);
+
+/******************/
+/* context walker */
+/******************/
+
+typedef _Bool (*sok_ctx_walk_step_cb_t)(
+ const sok_ctx_t * const,
+ void * const
+);
+
+typedef _Bool (*sok_ctx_walk_pos_cb_t)(
+ const sok_ctx_t * const,
+ const sok_pos_t,
+ void * const
+);
+
+typedef _Bool (*sok_ctx_walk_tile_cb_t)(
+ const sok_ctx_t * const,
+ const sok_pos_t,
+ const _Bool,
+ void * const
+);
+
+typedef _Bool (*sok_ctx_walk_goal_cb_t)(
+ const sok_ctx_t * const,
+ const sok_pos_t,
+ const _Bool has_player,
+ const _Bool has_box,
+ void * const
+);
+
+typedef _Bool (*sok_ctx_walk_move_cb_t)(
+ const sok_ctx_t * const,
+ const sok_move_t,
+ void * const
+);
+
+typedef struct {
+ sok_ctx_walk_pos_cb_t on_size;
+
+ sok_ctx_walk_step_cb_t on_walls_start,
+ on_walls_end;
+ sok_ctx_walk_pos_cb_t on_wall;
+
+ sok_ctx_walk_tile_cb_t on_home;
+
+ sok_ctx_walk_step_cb_t on_boxes_start,
+ on_boxes_end;
+ sok_ctx_walk_tile_cb_t on_box;
+
+ sok_ctx_walk_step_cb_t on_goals_start,
+ on_goals_end;
+ sok_ctx_walk_goal_cb_t on_goal;
+
+ sok_ctx_walk_step_cb_t on_moves_start,
+ on_moves_end;
+ sok_ctx_walk_move_cb_t on_move;
+} sok_ctx_walk_cbs_t;
+
+_Bool sok_ctx_walk(
+ const sok_ctx_t * const,
+ const sok_ctx_walk_cbs_t * const,
+ void * const
+);
+
+/****************/
+/* context hash */
+/****************/
+
+uint64_t sok_ctx_hash(const sok_ctx_t * const);
+
+/*********/
+/* cache */
+/*********/
+
+#define SOK_CACHE_DEFAULT_CAPACITY 1024
+
+typedef struct {
+ uint64_t *vals;
+ size_t num_vals, capacity;
+} sok_cache_t;
+
+_Bool sok_cache_init(sok_cache_t * const, const size_t);
+void sok_cache_fini(sok_cache_t * const);
+
+_Bool sok_cache_has(const sok_cache_t * const, const sok_ctx_t * const);
+_Bool sok_cache_add(sok_cache_t * const, const sok_ctx_t * const);
+
+/*********/
+/* solve */
+/*********/
+
+_Bool sok_solve(
+ sok_ctx_t * const,
+ void (*on_error)(const char * const)
+);
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif /* SOK_H */