diff --git a/sim.c b/sim.c index effa922..a1bdcb9 100644 --- a/sim.c +++ b/sim.c @@ -109,6 +109,18 @@ static inline void oper_move_relative_or_explode(Gbuffer gbuf, Mbuffer mbuf, mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ _delta_x, Mark_flag_lock) +#define PORT_LOCKED Mark_flag_lock +#define PORT_UNLOCKED Mark_flag_none +#define PORT_HASTE Mark_flag_haste_input + +#define OPER_PORT_INPUT(_delta_y, _delta_x, _flags) \ + mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ + _delta_x, Mark_flag_input | _flags) + +#define OPER_PORT_OUTPUT(_delta_y, _delta_x, _flags) \ + mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ + _delta_x, Mark_flag_output | _flags) + #define OPER_MOVE_OR_EXPLODE(_delta_y, _delta_x) \ oper_move_relative_or_explode(gbuffer, mbuffer, height, width, \ This_oper_char, y, x, _delta_y, _delta_x) @@ -162,6 +174,9 @@ OPER_DEFINE_LOWERCASE_DIRECTIONAL(south, 1, 0) OPER_DEFINE_LOWERCASE_DIRECTIONAL(west, 0, -1) OPER_PHASE_0(add) + OPER_PORT_INPUT(0, 1, PORT_LOCKED); + OPER_PORT_INPUT(0, 2, PORT_LOCKED); + OPER_PORT_OUTPUT(1, 0, PORT_LOCKED); OPER_END OPER_PHASE_1(add) OPER_END @@ -204,52 +219,52 @@ OPER_END //////// Run simulation -static void sim_phase_0(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width) { - for (Usz iy = 0; iy < height; ++iy) { - Glyph* glyph_row = gbuf + iy * width; - for (Usz ix = 0; ix < width; ++ix) { - Glyph c = glyph_row[ix]; - if (c == '.') - continue; - if (mbuffer_peek(mbuf, height, width, iy, ix) & - (Mark_flag_lock | Mark_flag_sleep)) - continue; - switch (c) { -#define X(_oper_name, _oper_char) \ +#define SIM_EXPAND_PHASE_0(_oper_name, _oper_char) \ case _oper_char: \ oper_phase0_##_oper_name(gbuf, mbuf, height, width, iy, ix); \ break; - ORCA_OPERATORS(X) -#undef X - } - } - } -} +#define SIM_EXPAND_PHASE_1(_oper_name, _oper_char) \ + case _oper_char: \ + oper_phase1_##_oper_name(gbuf, mbuf, height, width, iy, ix); \ + break; +#define SIM_EXPAND_PHASE_2(_oper_name, _oper_char) \ + case _oper_char: \ + oper_phase2_##_oper_name(gbuf, mbuf, height, width, iy, ix); \ + break; -static void sim_phase_1(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width) { +static void sim_phase_0(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width) { for (Usz iy = 0; iy < height; ++iy) { Glyph* glyph_row = gbuf + iy * width; for (Usz ix = 0; ix < width; ++ix) { Glyph c = glyph_row[ix]; - if (c == '.') - continue; - if (mbuffer_peek(mbuf, height, width, iy, ix) & - (Mark_flag_lock | Mark_flag_sleep)) - continue; - switch (c) { -#define X(_oper_name, _oper_char) \ - case _oper_char: \ - oper_phase1_##_oper_name(gbuf, mbuf, height, width, iy, ix); \ - break; - ORCA_OPERATORS(X) -#undef X - } + switch (c) { ORCA_OPERATORS(SIM_EXPAND_PHASE_0) } } } } +#define SIM_MUTATING_PHASE(_n) \ + static void sim_phase_##_n(Gbuffer gbuf, Mbuffer mbuf, Usz height, \ + Usz width) { \ + for (Usz iy = 0; iy < height; ++iy) { \ + Glyph* glyph_row = gbuf + iy * width; \ + for (Usz ix = 0; ix < width; ++ix) { \ + Glyph c = glyph_row[ix]; \ + if (c == '.') \ + continue; \ + if (mbuffer_peek(mbuf, height, width, iy, ix) & \ + (Mark_flag_lock | Mark_flag_sleep)) \ + continue; \ + switch (c) { ORCA_OPERATORS(SIM_EXPAND_PHASE_##_n) } \ + } \ + } \ + } + +SIM_MUTATING_PHASE(1) +SIM_MUTATING_PHASE(2) + void orca_run(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width) { mbuffer_clear(mbuf, height, width); sim_phase_0(gbuf, mbuf, height, width); sim_phase_1(gbuf, mbuf, height, width); + sim_phase_2(gbuf, mbuf, height, width); }