diff options
author | Paul Duncan <pabs@pablotron.org> | 2019-01-07 19:46:00 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2019-01-07 19:46:00 -0500 |
commit | 6c5f348397d092fb2630496d22f4328404d762d5 (patch) | |
tree | b31f8181e8540c01cff1127865643b6b59101d31 /src/sok-level-parser.c | |
download | sok-6c5f348397d092fb2630496d22f4328404d762d5.tar.bz2 sok-6c5f348397d092fb2630496d22f4328404d762d5.zip |
initial commit
Diffstat (limited to 'src/sok-level-parser.c')
-rw-r--r-- | src/sok-level-parser.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/sok-level-parser.c b/src/sok-level-parser.c new file mode 100644 index 0000000..eec08c3 --- /dev/null +++ b/src/sok-level-parser.c @@ -0,0 +1,159 @@ +#include <stdbool.h> +#include <stddef.h> // size_t +#include "sok.h" + +#define UNUSED(a) ((void) (a)) + +void +sok_level_parser_init( + sok_level_parser_t * const parser, + const sok_level_parser_cbs_t * const cbs, + void * const user_data +) { + parser->cbs = cbs; + parser->user_data = user_data; +} + +bool +sok_level_parser_parse( + sok_level_parser_t * const parser, + const char * const buf, + const size_t buf_len +) { + sok_pos_t size = { .x = 0, .y = 0 }; + + for (size_t i = 0, w = 0; i < buf_len; i++) { + if (buf[i] == '|') { + if (w > size.x) { + size.x = w; + } + + // reset column position, increment row count + w = 0; + size.y++; + } else { + w++; + } + } + + // increment row count + size.y++; + + // emit level size + if ( + parser->cbs->on_size && + !parser->cbs->on_size(parser, size) + ) { + // return failure + return false; + } + + sok_pos_t pos = { 0, 0 }; + for (size_t i = 0; i < buf_len; i++) { + switch (buf[i]) { + case '|': + // new line + pos.x = 0; + pos.y++; + + break; + case '-': + case '_': + case ' ': + // advance + pos.x++; + + break; + case '+': + // emit goal + if (parser->cbs->on_goal && !parser->cbs->on_goal(parser, pos)) { + // return failure + return false; + } + + // emit home + if (parser->cbs->on_home && !parser->cbs->on_home(parser, pos)) { + // return failure + return false; + } + + // advance + pos.x++; + + break; + case '@': + // emit home + if (parser->cbs->on_home && !parser->cbs->on_home(parser, pos)) { + // return failure + return false; + } + + // advance + pos.x++; + + break; + case '#': + // emit wall + if (parser->cbs->on_wall && !parser->cbs->on_wall(parser, pos)) { + // return failure + return false; + } + + // advance + pos.x++; + + break; + case '*': + // emit goal + if (parser->cbs->on_goal && !parser->cbs->on_goal(parser, pos)) { + // return failure + return false; + } + + // emit box + if (parser->cbs->on_box && !parser->cbs->on_box(parser, pos)) { + // return failure + return false; + } + + // advance + pos.x++; + + break; + case '.': + // emit goal + if (parser->cbs->on_goal && !parser->cbs->on_goal(parser, pos)) { + // return failure + return false; + } + + // advance + pos.x++; + + break; + case '$': + // emit box + if (parser->cbs->on_box && !parser->cbs->on_box(parser, pos)) { + // return failure + return false; + } + + // advance + pos.x++; + + break; + default: + // emit junk + if (parser->cbs->on_junk && !parser->cbs->on_junk(parser, i, buf[i])) { + // return failure + return false; + } + + // return failure + return false; + } + } + + // return success + return true; +} |