#include #include "sok.h" #define UNUSED(a) ((void) (a)) static bool sok_solve_step( sok_ctx_t * const ctx, sok_cache_t * const cache, const sok_solve_cbs_t * const cbs, void * const user_data ) { // check for success if (sok_ctx_is_done(ctx)) { // return success return true; } if (sok_cache_has(cache, ctx)) { // return failure return false; } // add to cache if (!sok_cache_add(cache, ctx)) { if (cbs && cbs->on_error) { // log error cbs->on_error("sok_cache_add() failed", user_data); } // return failure return false; } if (cbs && cbs->on_step && !cbs->on_step(ctx, user_data)) { // return failure return false; } // make sure level is solvable if (sok_ctx_is_lost(ctx)) { // return failure return false; } for (size_t dir = 0; dir < SOK_DIR_LAST; dir++) { if (!sok_ctx_move(ctx, dir)) { continue; } // recurse, check for success if (sok_solve_step(ctx, cache, cbs, user_data)) { // return success return true; } // undo move if (!sok_ctx_undo(ctx)) { if (cbs && cbs->on_error) { // log error cbs->on_error("sok_ctx_undo() failed", user_data); } // return failure return false; } } // return failure return false; } bool sok_solve( sok_ctx_t * const ctx, const sok_solve_cbs_t * const cbs, void *user_data ) { // init cache sok_cache_t cache; if (!sok_cache_init(&cache, SOK_CACHE_DEFAULT_CAPACITY)) { if (cbs && cbs->on_error) { cbs->on_error("sok_cache_init() failed", user_data); } // return failure return false; } // solve const bool r = sok_solve_step(ctx, &cache, cbs, user_data); // finalize cache sok_cache_fini(&cache); // return result return r; }