|
@ -181,6 +181,9 @@ Usz UCLAMP(Usz val, Usz min, Usz max) { |
|
|
#define STUN(_delta_y, _delta_x) \ |
|
|
#define STUN(_delta_y, _delta_x) \ |
|
|
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ |
|
|
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ |
|
|
_delta_x, Mark_flag_sleep) |
|
|
_delta_x, Mark_flag_sleep) |
|
|
|
|
|
#define LOCK(_delta_y, _delta_x) \ |
|
|
|
|
|
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \ |
|
|
|
|
|
_delta_x, Mark_flag_lock) |
|
|
|
|
|
|
|
|
#define STORE(_glyph_array) \ |
|
|
#define STORE(_glyph_array) \ |
|
|
oper_bank_store(bank_params, width, y, x, _glyph_array, sizeof(_glyph_array)) |
|
|
oper_bank_store(bank_params, width, y, x, _glyph_array, sizeof(_glyph_array)) |
|
@ -197,12 +200,16 @@ Usz UCLAMP(Usz val, Usz min, Usz max) { |
|
|
Dual_is_uppercase | \ |
|
|
Dual_is_uppercase | \ |
|
|
oper_has_neighboring_bang(gbuffer, height, width, y, x); |
|
|
oper_has_neighboring_bang(gbuffer, height, width, y, x); |
|
|
|
|
|
|
|
|
|
|
|
#define PSEUDO_DUAL bool const Dual_is_active = true |
|
|
|
|
|
|
|
|
#define BEGIN_DUAL_PORTS \ |
|
|
#define BEGIN_DUAL_PORTS \ |
|
|
{ \ |
|
|
{ \ |
|
|
bool const Oper_ports_enabled = Dual_is_active; |
|
|
bool const Oper_ports_enabled = Dual_is_active; |
|
|
|
|
|
|
|
|
#define DUAL_IS_ACTIVE Dual_is_active |
|
|
#define DUAL_IS_ACTIVE Dual_is_active |
|
|
|
|
|
|
|
|
|
|
|
#define IS_AWAKE (!(cell_flags & (Mark_flag_lock | Mark_flag_sleep))) |
|
|
|
|
|
|
|
|
#define STOP_IF_DUAL_INACTIVE \ |
|
|
#define STOP_IF_DUAL_INACTIVE \ |
|
|
if (!Dual_is_active) \ |
|
|
if (!Dual_is_active) \ |
|
|
return |
|
|
return |
|
@ -211,8 +218,6 @@ Usz UCLAMP(Usz val, Usz min, Usz max) { |
|
|
if (!oper_has_neighboring_bang(gbuffer, height, width, y, x)) \ |
|
|
if (!oper_has_neighboring_bang(gbuffer, height, width, y, x)) \ |
|
|
return |
|
|
return |
|
|
|
|
|
|
|
|
#define BEGIN_IF_DUAL_ACTIVE if (Dual_is_active) { |
|
|
|
|
|
|
|
|
|
|
|
#define END_IF } |
|
|
#define END_IF } |
|
|
|
|
|
|
|
|
#define OPER_PORT_IO_MASK \ |
|
|
#define OPER_PORT_IO_MASK \ |
|
@ -267,6 +272,7 @@ Usz UCLAMP(Usz val, Usz min, Usz max) { |
|
|
_('K', 'k', kill) \ |
|
|
_('K', 'k', kill) \ |
|
|
_('M', 'm', modulo) \ |
|
|
_('M', 'm', modulo) \ |
|
|
_('O', 'o', offset) \ |
|
|
_('O', 'o', offset) \ |
|
|
|
|
|
_('T', 't', track) \ |
|
|
_('U', 'u', uturn) \ |
|
|
_('U', 'u', uturn) \ |
|
|
_('X', 'x', teleport) |
|
|
_('X', 'x', teleport) |
|
|
|
|
|
|
|
@ -461,6 +467,40 @@ BEGIN_DUAL_PHASE_1(offset) |
|
|
STUN(0, 1); |
|
|
STUN(0, 1); |
|
|
END_PHASE |
|
|
END_PHASE |
|
|
|
|
|
|
|
|
|
|
|
BEGIN_DUAL_PHASE_0(track) |
|
|
|
|
|
PSEUDO_DUAL; |
|
|
|
|
|
Usz read_val_x = 1; |
|
|
|
|
|
if (IS_AWAKE) { |
|
|
|
|
|
Glyph params[2]; |
|
|
|
|
|
params[0] = PEEK(0, -1); // len
|
|
|
|
|
|
params[1] = PEEK(0, -2); // key
|
|
|
|
|
|
STORE(params); |
|
|
|
|
|
for (Usz i = 0; i < read_val_x; ++i) { |
|
|
|
|
|
LOCK(0, (Isz)(i + 1)); |
|
|
|
|
|
} |
|
|
|
|
|
Usz len = UCLAMP(INDEX(params[0]), 1, 16); |
|
|
|
|
|
Usz key = INDEX(params[1]); |
|
|
|
|
|
read_val_x = key % len + 1; |
|
|
|
|
|
} |
|
|
|
|
|
BEGIN_DUAL_PORTS |
|
|
|
|
|
PORT(0, -1, IN | HASTE); |
|
|
|
|
|
PORT(0, -2, IN | HASTE); |
|
|
|
|
|
PORT(0, (Isz)read_val_x, IN); |
|
|
|
|
|
PORT(1, 0, OUT); |
|
|
|
|
|
END_PORTS |
|
|
|
|
|
END_PHASE |
|
|
|
|
|
BEGIN_DUAL_PHASE_1(track) |
|
|
|
|
|
Usz read_val_x = 1; |
|
|
|
|
|
Glyph params[2]; |
|
|
|
|
|
if (LOAD(params)) { |
|
|
|
|
|
Usz len = UCLAMP(INDEX(params[0]), 1, 16); |
|
|
|
|
|
Usz key = INDEX(params[1]); |
|
|
|
|
|
read_val_x = key % len + 1; |
|
|
|
|
|
} |
|
|
|
|
|
POKE(1, 0, PEEK(0, (Isz)read_val_x)); |
|
|
|
|
|
STUN(1, 0); |
|
|
|
|
|
END_PHASE |
|
|
|
|
|
|
|
|
#define UTURN_DIRS(_) \ |
|
|
#define UTURN_DIRS(_) \ |
|
|
_(-1, 0, 'N') \ |
|
|
_(-1, 0, 'N') \ |
|
|
_(0, -1, 'W') \ |
|
|
_(0, -1, 'W') \ |
|
|