From 1aff085f4b3759ca1eb4e5b7968cb1aa36f534db Mon Sep 17 00:00:00 2001 From: Alice R Date: Sat, 11 May 2024 19:11:11 -0600 Subject: [PATCH] Add Robotic *_prefix constants, fix REL COUNTERS/COPY behavior for 1.x (#442) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The combination of `REL COUNTERS` and `COPY` behaved sensibly in MegaZeux 1.x—it applied `XPOS` and `YPOS` to both sets of coordinates, which is the same as what the 2.00 help file *claimed* to do. However, this is not how MegaZeux 2.x actually behaves, so the old behavior needed a compatibility hack. --- docs/changelog.txt | 1 + src/counter.c | 4 +- src/robot.c | 62 +++++++++++----------- src/robot.h | 11 ++++ src/run_robot.c | 48 +++++++++++------ testworlds/1.00/010 rel counters copy.mzx | Bin 0 -> 4913 bytes testworlds/1.00/010 rel counters copy.txt | 3 ++ testworlds/2.51/015 rel counters copy.mzx | Bin 0 -> 7493 bytes testworlds/2.51/015 rel counters copy.txt | 3 ++ 9 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 testworlds/1.00/010 rel counters copy.mzx create mode 100644 testworlds/1.00/010 rel counters copy.txt create mode 100644 testworlds/2.51/015 rel counters copy.mzx create mode 100644 testworlds/2.51/015 rel counters copy.txt diff --git a/docs/changelog.txt b/docs/changelog.txt index 975951ba1..2ee97bac9 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -61,6 +61,7 @@ USERS code from the previous row (as if there had been no clipping) instead of whatever the last color code displayed was. The old behavior is version locked to <2.93. ++ Fixed COPY when used with REL COUNTERS for 1.x worlds. DEVELOPERS diff --git a/src/counter.c b/src/counter.c index 434f993b8..f2a37c838 100644 --- a/src/counter.c +++ b/src/counter.c @@ -304,7 +304,7 @@ static int thisx_read(struct world *mzx_world, int thisx, thisy; get_robot_position(cur_robot, &thisx, &thisy); - if(mzx_world->mid_prefix == 2) + if(mzx_world->mid_prefix == REL_TO_PLAYER) return thisx - mzx_world->player_x; return thisx; @@ -317,7 +317,7 @@ static int thisy_read(struct world *mzx_world, int thisx, thisy; get_robot_position(cur_robot, &thisx, &thisy); - if(mzx_world->mid_prefix == 2) + if(mzx_world->mid_prefix == REL_TO_PLAYER) return thisy - mzx_world->player_y; return thisy; diff --git a/src/robot.c b/src/robot.c index 96395a51f..688d7c588 100644 --- a/src/robot.c +++ b/src/robot.c @@ -2007,16 +2007,16 @@ void prefix_first_last_xy(struct world *mzx_world, int *fx, int *fy, switch(mzx_world->first_prefix) { - case 1: - case 5: + case REL_TO_SELF: + case REL_TO_SELF_FIRST_OR_LAST: { tfx += robotx; tfy += roboty; break; } - case 2: - case 6: + case REL_TO_PLAYER: + case REL_TO_PLAYER_FIRST_OR_LAST: { find_player(mzx_world); tfx += mzx_world->player_x; @@ -2024,14 +2024,14 @@ void prefix_first_last_xy(struct world *mzx_world, int *fx, int *fy, break; } - case 3: + case REL_TO_XPOS_YPOS_FIRST_OR_LAST: { tfx += get_counter(mzx_world, "FIRSTXPOS", 0); tfy += get_counter(mzx_world, "FIRSTYPOS", 0); break; } - case 7: + case REL_TO_XPOS_YPOS: { tfx += get_counter(mzx_world, "XPOS", 0); tfy += get_counter(mzx_world, "YPOS", 0); @@ -2041,16 +2041,16 @@ void prefix_first_last_xy(struct world *mzx_world, int *fx, int *fy, switch(mzx_world->last_prefix) { - case 1: - case 5: + case REL_TO_SELF: + case REL_TO_SELF_FIRST_OR_LAST: { tlx += robotx; tly += roboty; break; } - case 2: - case 6: + case REL_TO_PLAYER: + case REL_TO_PLAYER_FIRST_OR_LAST: { find_player(mzx_world); tlx += mzx_world->player_x; @@ -2058,14 +2058,14 @@ void prefix_first_last_xy(struct world *mzx_world, int *fx, int *fy, break; } - case 3: + case REL_TO_XPOS_YPOS_FIRST_OR_LAST: { tlx += get_counter(mzx_world, "LASTXPOS", 0); tly += get_counter(mzx_world, "LASTYPOS", 0); break; } - case 7: + case REL_TO_XPOS_YPOS: { tlx += get_counter(mzx_world, "XPOS", 0); tly += get_counter(mzx_world, "YPOS", 0); @@ -2116,16 +2116,16 @@ void prefix_first_xy_var(struct world *mzx_world, int *fx, int *fy, switch(mzx_world->first_prefix) { - case 1: - case 5: + case REL_TO_SELF: + case REL_TO_SELF_FIRST_OR_LAST: { tfx += robotx; tfy += roboty; break; } - case 2: - case 6: + case REL_TO_PLAYER: + case REL_TO_PLAYER_FIRST_OR_LAST: { find_player(mzx_world); tfx += mzx_world->player_x; @@ -2133,14 +2133,14 @@ void prefix_first_xy_var(struct world *mzx_world, int *fx, int *fy, break; } - case 3: + case REL_TO_XPOS_YPOS_FIRST_OR_LAST: { tfx += get_counter(mzx_world, "FIRSTXPOS", 0); tfy += get_counter(mzx_world, "FIRSTYPOS", 0); break; } - case 7: + case REL_TO_XPOS_YPOS: { tfx += get_counter(mzx_world, "XPOS", 0); tfy += get_counter(mzx_world, "YPOS", 0); @@ -2172,16 +2172,16 @@ void prefix_last_xy_var(struct world *mzx_world, int *lx, int *ly, switch(mzx_world->last_prefix) { - case 1: - case 5: + case REL_TO_SELF: + case REL_TO_SELF_FIRST_OR_LAST: { tlx += robotx; tly += roboty; break; } - case 2: - case 6: + case REL_TO_PLAYER: + case REL_TO_PLAYER_FIRST_OR_LAST: { find_player(mzx_world); tlx += mzx_world->player_x; @@ -2189,14 +2189,14 @@ void prefix_last_xy_var(struct world *mzx_world, int *lx, int *ly, break; } - case 3: + case REL_TO_XPOS_YPOS_FIRST_OR_LAST: { tlx += get_counter(mzx_world, "LASTXPOS", 0); tly += get_counter(mzx_world, "LASTYPOS", 0); break; } - case 7: + case REL_TO_XPOS_YPOS: { tlx += get_counter(mzx_world, "XPOS", 0); tly += get_counter(mzx_world, "YPOS", 0); @@ -2226,16 +2226,16 @@ void prefix_mid_xy_var(struct world *mzx_world, int *mx, int *my, int tmx = *mx; int tmy = *my; - switch(mzx_world->first_prefix) + switch(mzx_world->mid_prefix) { - case 1: + case REL_TO_SELF: { tmx += robotx; tmy += roboty; break; } - case 2: + case REL_TO_PLAYER: { find_player(mzx_world); tmx += mzx_world->player_x; @@ -2243,7 +2243,7 @@ void prefix_mid_xy_var(struct world *mzx_world, int *mx, int *my, break; } - case 3: + case REL_TO_XPOS_YPOS: { tmx += get_counter(mzx_world, "XPOS", 0); tmy += get_counter(mzx_world, "YPOS", 0); @@ -2275,14 +2275,14 @@ void prefix_mid_xy_unbound(struct world *mzx_world, int *mx, int *my, int x, int switch(mzx_world->mid_prefix) { - case 1: + case REL_TO_SELF: { tmx += x; tmy += y; break; } - case 2: + case REL_TO_PLAYER: { find_player(mzx_world); tmx += mzx_world->player_x; @@ -2290,7 +2290,7 @@ void prefix_mid_xy_unbound(struct world *mzx_world, int *mx, int *my, int x, int break; } - case 3: + case REL_TO_XPOS_YPOS: { tmx += get_counter(mzx_world, "XPOS", 0); tmy += get_counter(mzx_world, "YPOS", 0); diff --git a/src/robot.h b/src/robot.h index 756e09b35..177938884 100644 --- a/src/robot.h +++ b/src/robot.h @@ -60,6 +60,17 @@ enum builtin_label LABEL_PLAYERDIED }; +enum rel_prefix +{ + REL_NONE = 0, + REL_TO_SELF = 1, + REL_TO_PLAYER = 2, + REL_TO_XPOS_YPOS = 3, + REL_TO_SELF_FIRST_OR_LAST = 5, + REL_TO_PLAYER_FIRST_OR_LAST = 6, + REL_TO_XPOS_YPOS_FIRST_OR_LAST = 7, +}; + #ifdef CONFIG_DEBYTECODE CORE_LIBSPEC void change_robot_name(struct board *src_board, diff --git a/src/run_robot.c b/src/run_robot.c index 74182b52b..18e776877 100644 --- a/src/run_robot.c +++ b/src/run_robot.c @@ -1999,7 +1999,7 @@ void run_robot(context *ctx, int id, int x, int y) // If REL PLAYER or REL COUNTERS, use special code switch(mzx_world->mid_prefix) { - case 2: + case REL_TO_PLAYER: { // Give an ID of -1 to throw it off from not // allowing global robot. @@ -2009,7 +2009,7 @@ void run_robot(context *ctx, int id, int x, int y) break; } - case 3: + case REL_TO_XPOS_YPOS: { // Give an ID of -1 to throw it off from not // allowing global robot. @@ -3211,6 +3211,8 @@ void run_robot(context *ctx, int id, int x, int y) dest_height = src_board->board_height; } + // Note: due to a bug between 2.80 and 2.93, using a REL FIRST + // command after a REL command prevented this from working. prefix_mid_xy_var(mzx_world, &put_x, &put_y, x, y, dest_width, dest_height); @@ -4505,9 +4507,9 @@ void run_robot(context *ctx, int id, int x, int y) { if(id) { - mzx_world->first_prefix = 1; - mzx_world->mid_prefix = 1; - mzx_world->last_prefix = 1; + mzx_world->first_prefix = REL_TO_SELF; + mzx_world->mid_prefix = REL_TO_SELF; + mzx_world->last_prefix = REL_TO_SELF; lines_run--; goto next_cmd_prefix; } @@ -4516,18 +4518,28 @@ void run_robot(context *ctx, int id, int x, int y) case ROBOTIC_CMD_REL_PLAYER: // rel player { - mzx_world->first_prefix = 2; - mzx_world->mid_prefix = 2; - mzx_world->last_prefix = 2; + mzx_world->first_prefix = REL_TO_PLAYER; + mzx_world->mid_prefix = REL_TO_PLAYER; + mzx_world->last_prefix = REL_TO_PLAYER; lines_run--; goto next_cmd_prefix; } case ROBOTIC_CMD_REL_COUNTERS: // rel counters { - mzx_world->first_prefix = 3; - mzx_world->mid_prefix = 3; - mzx_world->last_prefix = 3; + mzx_world->first_prefix = REL_TO_XPOS_YPOS; + mzx_world->mid_prefix = REL_TO_XPOS_YPOS; + mzx_world->last_prefix = REL_TO_XPOS_YPOS; + + // The REL COUNTERS commands are broken in 2.00+ - the usage of + // XPOS/YPOS and FIRSTXPOS/FIRSTYPOS/LASTXPOS/LASTYPOS are reversed. + // This seems to be intentional but is completely backwards from what + // the 2.00 help file claimed (and what would be sensible). + if(mzx_world->version >= V200) + { + mzx_world->first_prefix = REL_TO_XPOS_YPOS_FIRST_OR_LAST; + mzx_world->last_prefix = REL_TO_XPOS_YPOS_FIRST_OR_LAST; + } lines_run--; goto next_cmd_prefix; } @@ -4952,7 +4964,7 @@ void run_robot(context *ctx, int id, int x, int y) { if(id) { - mzx_world->first_prefix = 5; + mzx_world->first_prefix = REL_TO_SELF_FIRST_OR_LAST; lines_run--; goto next_cmd_prefix; } @@ -4963,7 +4975,7 @@ void run_robot(context *ctx, int id, int x, int y) { if(id) { - mzx_world->last_prefix = 5; + mzx_world->last_prefix = REL_TO_SELF_FIRST_OR_LAST; lines_run--; goto next_cmd_prefix; } @@ -4972,28 +4984,30 @@ void run_robot(context *ctx, int id, int x, int y) case ROBOTIC_CMD_REL_PLAYER_FIRST: // Rel player first { - mzx_world->first_prefix = 6; + mzx_world->first_prefix = REL_TO_PLAYER_FIRST_OR_LAST; lines_run--; goto next_cmd_prefix; } case ROBOTIC_CMD_REL_PLAYER_LAST: // Rel player last { - mzx_world->last_prefix = 6; + mzx_world->last_prefix = REL_TO_PLAYER_FIRST_OR_LAST; lines_run--; goto next_cmd_prefix; } case ROBOTIC_CMD_REL_COUNTERS_FIRST: // Rel counters first { - mzx_world->first_prefix = 7; + // BUG: should be REL_TO_XPOS_YPOS_FIRST_OR_LAST (see REL COUNTERS). + mzx_world->first_prefix = REL_TO_XPOS_YPOS; lines_run--; goto next_cmd_prefix; } case ROBOTIC_CMD_REL_COUNTERS_LAST: // Rel counters last { - mzx_world->last_prefix = 7; + // BUG: should be REL_TO_XPOS_YPOS_FIRST_OR_LAST (see REL COUNTERS). + mzx_world->last_prefix = REL_TO_XPOS_YPOS; lines_run--; goto next_cmd_prefix; } diff --git a/testworlds/1.00/010 rel counters copy.mzx b/testworlds/1.00/010 rel counters copy.mzx new file mode 100644 index 0000000000000000000000000000000000000000..da078b853b418a2be77093c99d6aa6b684a789e7 GIT binary patch literal 4913 zcmcH-TWk~A^-fI2PBMwTD?r2I;#svHAp&B;*0}7*hAp9D#R7tWc4;xOhhyC$Dex{i>wRg*ptM5+`_YmIyExp(Xd zEg${paqN4~J@0ewJ$EJ-2G1zpJ$LEs(BOrOFggE@GL*{ZNP&>IuDng219SG1PiAND zemrYZg4w848jX7!4aA7PW!tt94KSHN?{Eu|Rdr)yLzY#f$*S3Cm<~plfG*RqL1E(_ zsH8ww2#M;t9)*!po@_kbc#5>(K)CREy$+rNsG6p!@;*5zQ~U8F@o+diwOOSkQcM<; z$>e(*>m@+ISVi4XD`=09nNqc8*Q%u%BncjGs2K8k1jN8kS(Z)a8UX_UFd(g1sZ@Tr z7l2~MSLp$8#fS#)7)Yf*jS35(sRgsdFi?wpFakIhz%|L1xMM(8A{{KA?n8`fgU5I?jG z?&+c>$zjbxeyB(^zg8~iDF%5?;41q8E()@QD2x>3Fz3)zQ)T(13lKTi&dG!TuQPAO z%2yoTHW3sij@hfZM{j0 zCIGV>oi=KLn7B?@Z_?<@6h*1PoIwvAH(8ct9y@vh=@1zw93K2bEJ4?4Oo)L_33NDW zOxS3Z$}|%TM0Lxu!6>42sGtGgI%2A}2vIC*?2OfPAZVIiLz=B!ohVFP)mSDNmPl;2 z>ehGK+Ry)AfR`YwIYtnV{fUupZm?3RT5)u5Z~7mmQ3T z0Dxzj5R3sNnJ+Y-*2+Ue>Y;*2gE*K4pe3S`Qx(&^;_{4&QDD0Or?5u@%sQYeE4HC? zOoy`qE+9rzL}O&}+14#6!Xn=>|4<{0> zH99Lu20uBZnn)CAnV8o=GptgH#}EYNdfDMbn(fe{`gnroo8=5>d0;dotPAMW^PrRE z3^q}eriu9}ilj#bfS5rDI5j9B=R~$9Cy*c6D=RC_pw>Vo?|kS>GuMDon$h%z`NGc? zS<7op3XN|n$m0uy!*xh-BnS!+AOu&m)Ee)*K*a*G`cVuj*h)7owkb+%pA)+bU5f4U z9*AZNzH}?$dBQUV3xMM~rNf+_DHvS9P8nOkQw4`g5}``oU^q!VONN79NFeM+nodiK zR-q3T%I?~dk`BqRIP5-YW2EpHyXuaJRS=9ywY(rKkoW(8$J&i#CTRXpj zX76bS7+Dg%dgid2C=Jf zcktVzRxa0;$`8wBEMw1JFhTEac@?Tl18ki*=&`Q6P+BV@iqS2|ZZ(o$!+ni=9_AKr zVbr*)>oMBCIjCCYZd$urVT~8A3AhlQPDEMg-NIQZ1{(&kQpqZ>h7)TaN^*=4hH1+` zjUgF=hQL+RG*x7d=&O39sRZWwDq=64bbl`W-2Hj{nfpT%@;ubs3pJUe5ri!^aHF;x z+s?TqI;@pZlI0L5F_bk{hr7Xf*bw3vqdJ^i z&dnK;IVF(9F0hWaiSC3X%WXyM~*ql zO}Gq1B93Fo0WmNh{B1_W*5cdbxbX6o_*xUyGZNOPvj*-{T z8mjp^Uoot@Wz|ciRV(vDGgDWxgVk#$4mCcEfJW&)v2mu-o#USKzJZ$&MYKj$e4= zq>Ic+orG*YA!PR`@zM?OXY%ql2)#Ap^CWWoJ3mnfq?{(`?~jDOw!iJFj`-XEM99ZK zjzi}DJAm-le<9Bn78aIDU)@{!<8OYs^xMVXJ-c(~&V&2EFF*MFvtK{>!2t>H>qBnKTL&%q4xwBnp z7YrW}id{r#-vM6_A3?eu*4x`CkJRB6{9Rt5)8`eWm%Xr36@;BcsDi{Ekf7r$Ah8!D zWGXR0zrZ&@$mP+Y(?e$l550BnB>841h_W|ja1Y=Pu$2&WTuZPC-li=O1Y4^IhH27V%JZmvdQPf zGHLcdm#e9Xv3x44WXIAe{R3q(tsFj7IHpYIl(DHPeKM6Lu{W+O2ydT1cTpKjk1Oxc zNiL&Y&EzJOY$}&kGMbXiWTwX_(_^_*_KZ1M}!-LncEoIZVb@ffzi=qCY_s1-$>C@G&-8SIW|Rh dLpgodIN}q(PNxbvB4UlP+O91y@0!!;zX4Wms}KMH literal 0 HcmV?d00001 diff --git a/testworlds/1.00/010 rel counters copy.txt b/testworlds/1.00/010 rel counters copy.txt new file mode 100644 index 000000000..893f801b7 --- /dev/null +++ b/testworlds/1.00/010 rel counters copy.txt @@ -0,0 +1,3 @@ +Title: REL COUNTERS COPY Test +Author: Alice Rowan +Desc: REL COUNTERS on COPY behaves sanely in 1.x: it applies XPOS and YPOS to both sets of coordinates. If only someone had checked what 1.x did when adding the 2.00 behavior! diff --git a/testworlds/2.51/015 rel counters copy.mzx b/testworlds/2.51/015 rel counters copy.mzx new file mode 100644 index 0000000000000000000000000000000000000000..0412f1c6762f7a34465f98e8ddb1e89d9de008b7 GIT binary patch literal 7493 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