diff options
Diffstat (limited to 'src/core/sok.h')
-rw-r--r-- | src/core/sok.h | 257 |
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 */ |