diff options
author | Paul Duncan <pabs@pablotron.org> | 2019-01-07 22:05:19 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2019-01-07 22:05:19 -0500 |
commit | c31caa18f969199a3fb91995ae08b29368cf010d (patch) | |
tree | ce48c67b8394db3e9d5c6077ea06f5244785940f /src/text | |
parent | ad4c3bf0154aae2adedd4ecf7239e30e2d5f9e1c (diff) | |
download | sok-c31caa18f969199a3fb91995ae08b29368cf010d.tar.bz2 sok-c31caa18f969199a3fb91995ae08b29368cf010d.zip |
reorganize src/, add support for RLE
Diffstat (limited to 'src/text')
-rw-r--r-- | src/text/main.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/text/main.c b/src/text/main.c new file mode 100644 index 0000000..bcf53a1 --- /dev/null +++ b/src/text/main.c @@ -0,0 +1,190 @@ +#include <stdbool.h> // bool +#include <string.h> // atoi() +#include <stdlib.h> // EXIT_{FAILURE,SUCCESS} +#include <stdio.h> +#include "../libsok/sok.h" + +#define UNUSED(a) ((void) (a)) + +static const char * const +LEVELS[] = { + "5#|#@$.#|5#", + "7#|3#.3#|3#$3#|#.$@$.#|3#$3#|3#.3#|7#", +}; +#define NUM_LEVELS (sizeof(LEVELS) / sizeof(char*)) + +static char print_buf[(SOK_LEVEL_MAX_WIDTH + 1) * SOK_LEVEL_MAX_HEIGHT + 1]; + +static bool +on_size( + const sok_ctx_t * const ctx, + const sok_pos_t size, + void * const data +) { + UNUSED(ctx); + UNUSED(data); + + // fprintf(stderr, "size: x = %u, y = %u\n", size.x, size.y); + + memset(print_buf, ' ', sizeof(print_buf)); + print_buf[(size.x + 1) * size.y + 1] = '\0'; + for (size_t i = 0; i < size.y; i++) { + print_buf[(i + 1) * (size.x + 1) - 1] = '\n'; + } + + return true; +} + +static bool +on_home( + const sok_ctx_t * const ctx, + const sok_pos_t pos, + const bool has_goal, + void * const data +) { + UNUSED(data); + print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = has_goal ? '+' : '@'; + return true; +} + +static bool +on_wall( + const sok_ctx_t * const ctx, + const sok_pos_t pos, + void * const data +) { + // fprintf(stderr, "wall: x = %u, y = %u\n", pos.x, pos.y); + UNUSED(data); + print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = '#'; + return true; +} + +static bool +on_goal( + const sok_ctx_t * const ctx, + const sok_pos_t pos, + const bool has_player, + const bool has_box, + void * const data +) { + UNUSED(data); + const char c = has_player ? '+' : (has_box ? '*' : '.'); + print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = c; + return true; +} + +static bool +on_box( + const sok_ctx_t * const ctx, + const sok_pos_t pos, + const bool has_goal, + void * const data +) { + UNUSED(data); + print_buf[pos.y * (ctx->level.size.x + 1) + pos.x] = has_goal ? '*' : '$'; + return true; +} + +static sok_ctx_walk_cbs_t PRINT_CBS = { + .on_size = on_size, + .on_home = on_home, + .on_wall = on_wall, + .on_goal = on_goal, + .on_box = on_box, +}; + +static void +print_level( + const sok_ctx_t * const ctx +) { + // fill buffer + if (!sok_ctx_walk(ctx, &PRINT_CBS, NULL)) { + fprintf(stderr, "Couldn't print level\n"); + exit(EXIT_FAILURE); + } + + // print level + printf("%s\n", print_buf); +} + +int main(int argc, char *argv[]) { + size_t level = (argc > 1) ? atoi(argv[1]) : 0; + + // init context + sok_ctx_t ctx; + sok_ctx_init(&ctx, NULL); + + if (!sok_ctx_set_level(&ctx, LEVELS[level])) { + fprintf(stderr, "Couldn't load level %zu\n", level); + return EXIT_FAILURE; + } + + char buf[1024]; + bool done = false; + while (!done) { + print_level(&ctx); + printf("%zu%s> ", ctx.num_moves, sok_ctx_is_done(&ctx) ? " (won!)" : ""); + + if (!fgets(buf, sizeof(buf), stdin)) { + done = true; + break; + } + + switch (buf[0]) { + case EOF: + case 'q': + done = true; + break; + case 'k': + if (!sok_ctx_move(&ctx, SOK_DIR_UP)) { + fprintf(stderr, "W: move up failed\n"); + } + + break; + case 'h': + if (!sok_ctx_move(&ctx, SOK_DIR_LEFT)) { + fprintf(stderr, "W: move left failed\n"); + } + + break; + case 'j': + if (!sok_ctx_move(&ctx, SOK_DIR_DOWN)) { + fprintf(stderr, "W: move down failed\n"); + } + + break; + case 'l': + if (!sok_ctx_move(&ctx, SOK_DIR_RIGHT)) { + fprintf(stderr, "W: move right failed\n"); + } + + break; + case 'u': + if (!sok_ctx_undo(&ctx)) { + fprintf(stderr, "W: undo failed\n"); + } + + break; + case 'n': + if (sok_ctx_is_done(&ctx)) { + // advance level + level = (level + 1) % NUM_LEVELS; + + // load next level + if (!sok_ctx_set_level(&ctx, LEVELS[level])) { + fprintf(stderr, "Couldn't load level %zu\n", level); + return EXIT_FAILURE; + } + } else { + fprintf(stderr, "W: cannot advance to next level\n"); + } + + break; + default: + // ignore + break; + } + } + + return 0; +} |