#ifndef SOK_H #define SOK_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include // uint16_t #include // 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 */ /*********/ typedef struct { _Bool (*on_step)(const sok_ctx_t *, void *); void (*on_error)(const char * const, void *); } sok_solve_cbs_t; _Bool sok_solve( sok_ctx_t * const, const sok_solve_cbs_t * const, void * const ); #ifdef __cplusplus }; #endif /* __cplusplus */ #endif /* SOK_H */