aboutsummaryrefslogtreecommitdiff
path: root/src/core/sok-solve.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/sok-solve.c')
-rw-r--r--src/core/sok-solve.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/core/sok-solve.c b/src/core/sok-solve.c
new file mode 100644
index 0000000..34a8320
--- /dev/null
+++ b/src/core/sok-solve.c
@@ -0,0 +1,89 @@
+#include <stdbool.h>
+#include "sok.h"
+
+#define UNUSED(a) ((void) (a))
+
+static bool
+sok_solve_step(
+ sok_ctx_t * const ctx,
+ sok_cache_t * const cache,
+ void (*on_error)(const char * const)
+) {
+ // 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 (on_error) {
+ // log error
+ on_error("sok_cache_add() failed");
+ }
+
+ // 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, on_error)) {
+ // return success
+ return true;
+ }
+
+ // undo move
+ if (!sok_ctx_undo(ctx)) {
+ if (on_error) {
+ // log error
+ on_error("sok_ctx_undo() failed");
+ }
+
+ // return failure
+ return false;
+ }
+ }
+
+ // return failure
+ return false;
+}
+
+bool
+sok_solve(
+ sok_ctx_t * const ctx,
+ void (*on_error)(const char * const)
+) {
+ // init cache
+ sok_cache_t cache;
+ if (!sok_cache_init(&cache, SOK_CACHE_DEFAULT_CAPACITY)) {
+ on_error("sok_cache_init() failed");
+ return false;
+ }
+
+ // solve
+ const bool r = sok_solve_step(ctx, &cache, on_error);
+
+ // finalize cache
+ sok_cache_fini(&cache);
+
+ // return result
+ return r;
+}