From 59d2bcc057454b7c97dd2c62a72b839bcb2abc22 Mon Sep 17 00:00:00 2001 From: cancel Date: Mon, 26 Nov 2018 12:30:06 +0900 Subject: [PATCH] Add more movement and oper macros --- field.h | 9 +++++++++ sim.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/field.h b/field.h index e37eada..9d9f5e7 100644 --- a/field.h +++ b/field.h @@ -27,3 +27,12 @@ typedef enum { } Field_load_error; Field_load_error field_load_file(char const* filepath, Field* field); + +inline Glyph gbuffer_peek_relative(Field_buffer gbuffer, Usz height, Usz width, + Usz y, Usz x, Isz delta_y, Isz delta_x) { + Isz y0 = (Isz)y + delta_y; + Isz x0 = (Isz)x + delta_x; + if (y0 < 0 || x0 < 0 || (Usz)y0 >= height || (Usz)x0 >= width) + return '.'; + return gbuffer[(Usz)y0 * width + (Usz)x0]; +} diff --git a/sim.c b/sim.c index bbb1619..fbda7f9 100644 --- a/sim.c +++ b/sim.c @@ -48,6 +48,14 @@ static inline Glyph glyphs_mod(Glyph a, Glyph b) { return indexed_glyphs[ib == 0 ? 0 : (ia % ib)]; } +static inline bool oper_has_neighboring_bang(Field_buffer gbuf, Usz h, Usz w, + Usz y, Usz x) { + return gbuffer_peek_relative(gbuf, h, w, y, x, 0, 1) == '*' || + gbuffer_peek_relative(gbuf, h, w, y, x, 0, -1) == '*' || + gbuffer_peek_relative(gbuf, h, w, y, x, 1, 0) == '*' || + gbuffer_peek_relative(gbuf, h, w, y, x, -1, 0) == '*'; +} + static inline void oper_move_relative_or_explode(Field_buffer field_buffer, Markmap_buffer markmap, Usz field_height, Usz field_width, Glyph moved, @@ -98,16 +106,31 @@ oper_move_relative_or_explode(Field_buffer field_buffer, Markmap_buffer markmap, field_poke_relative(field, y, x, _delta_x, _delta_y, _glyph) #define OPER_POKE_SELF(_glyph) OPER_POKE_ABSOLUTE(y, x, _glyph) +#define OPER_REQUIRE_BANG() \ + if (!oper_has_neighboring_bang(field->buffer, field->height, field->width, \ + y, x)) \ + return; + #define OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x) \ oper_move_relative_or_explode(field->buffer, markmap, field->height, \ field->width, This_oper_char, y, x, _delta_y, \ - _delta_x); + _delta_x) #define OPER_DEFINE_UPPERCASE_DIRECTIONAL(_oper_name, _delta_y, _delta_x) \ OPER_PHASE_0(_oper_name) \ OPER_END \ OPER_PHASE_1(_oper_name) \ - OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x) \ + OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x); \ + OPER_END \ + OPER_PHASE_2(_oper_name) \ + OPER_END + +#define OPER_DEFINE_LOWERCASE_DIRECTIONAL(_oper_name, _delta_y, _delta_x) \ + OPER_PHASE_0(_oper_name) \ + OPER_END \ + OPER_PHASE_1(_oper_name) \ + OPER_REQUIRE_BANG(); \ + OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x); \ OPER_END \ OPER_PHASE_2(_oper_name) \ OPER_END @@ -121,6 +144,10 @@ oper_move_relative_or_explode(Field_buffer field_buffer, Markmap_buffer markmap, _(East, 'E') \ _(South, 'S') \ _(West, 'W') \ + _(north, 'n') \ + _(east, 'e') \ + _(south, 's') \ + _(west, 'w') \ _(modulo, 'm') ORCA_DECLARE_OPERATORS(ORCA_OPERATORS) @@ -131,6 +158,10 @@ OPER_DEFINE_UPPERCASE_DIRECTIONAL(North, -1, 0) OPER_DEFINE_UPPERCASE_DIRECTIONAL(East, 0, 1) OPER_DEFINE_UPPERCASE_DIRECTIONAL(South, 1, 0) OPER_DEFINE_UPPERCASE_DIRECTIONAL(West, 0, -1) +OPER_DEFINE_LOWERCASE_DIRECTIONAL(north, -1, 0) +OPER_DEFINE_LOWERCASE_DIRECTIONAL(east, 0, 1) +OPER_DEFINE_LOWERCASE_DIRECTIONAL(south, 1, 0) +OPER_DEFINE_LOWERCASE_DIRECTIONAL(west, 0, -1) OPER_PHASE_0(add) OPER_END