#include // bool #include // atoi() #include // EXIT_{FAILURE,SUCCESS} #include #include "../core/sok.h" #include "util.h" #include "levels.h" #include "action.h" #include "draw.h" static void solve_on_error( const char * const err ) { die("Error solving level: %s", err); } static void draw_moves( const sok_ctx_t * const ctx, const size_t skip_moves ) { printf("Solution (%d moves): ", (int) (ctx->num_moves - skip_moves)); for (size_t i = skip_moves; i < ctx->num_moves; i++) { if (ctx->moves[i].dir >= SOK_DIR_LAST) { die("invalid move: %u", ctx->moves[i].dir); } fputs(SOK_DIR_TO_STR(ctx->moves[i].dir), stdout); } printf("\n"); } int main(int argc, char *argv[]) { size_t level_num = (argc > 1) ? atoi(argv[1]) : 0; const level_t *level = levels_get_level(level_num); // init context sok_ctx_t ctx; sok_ctx_init(&ctx, NULL); if (!sok_ctx_set_level(&ctx, level->data)) { die("Couldn't load level %d", (int) level_num); } bool done = false; while (!done) { // draw screen draw(&ctx, level_num, level); // read input, check for error const action_t action = get_action(); switch (action.type) { case ACTION_QUIT: done = true; break; case ACTION_MOVE: if (!sok_ctx_move(&ctx, (sok_dir_t) action.data)) { warn("move %s failed", SOK_DIR_TO_STR((sok_dir_t) action.data)); } break; case ACTION_UNDO: if (!sok_ctx_undo(&ctx)) { warn("undo failed"); } break; case ACTION_NEXT: if (sok_ctx_is_done(&ctx)) { // advance level level_num++; level = levels_get_level(level_num); // load next level if (!sok_ctx_set_level(&ctx, level->data)) { die("Couldn't load level %d", (int) level_num); } } else { warn("cannot advance to next level"); } break; case ACTION_RESET: // reset level if (!sok_ctx_set_level(&ctx, level->data)) { die("Couldn't load level %d", (int) level_num); } break; case ACTION_WARP: level_num = action.data; level = levels_get_level(level_num); // load level if (!sok_ctx_set_level(&ctx, level->data)) { die("Couldn't load level %d", (int) level_num); } break; case ACTION_SOLVE: { // get current number of moves const size_t old_num_moves = ctx.num_moves; if (sok_solve(&ctx, solve_on_error)) { // found solution, print it draw_moves(&ctx, old_num_moves); } else { warn("Couldn't solve level"); } } break; default: // ignore break; } } // return success return EXIT_SUCCESS; }