]> granicus.if.org Git - nethack/commitdiff
Fix flipping while punished
authorPasi Kallinen <paxed@alt.org>
Fri, 27 Mar 2020 15:19:27 +0000 (17:19 +0200)
committerPasi Kallinen <paxed@alt.org>
Fri, 27 Mar 2020 15:30:23 +0000 (17:30 +0200)
... if either you, the ball, or the chain are outside the flip area.
Just unplace the b&c and then put it down under the hero.
This can only happen via #wizlevelflip, as normal level flipping
is done when creating the level and b&c are not on the map.

src/sp_lev.c

index d74f641ed92b8cc62cefcbd973c7985f762bb0f1..a60a17c3d07212d86153863205054cde3dbfed9a 100755 (executable)
@@ -432,6 +432,7 @@ flip_encoded_direction_bits(int flp, int val)
 
 #define FlipX(val) ((maxx - (val)) + minx)
 #define FlipY(val) ((maxy - (val)) + miny)
+#define inFlipArea(x,y) ((x) >= minx && (x) <= maxx && (y) >= miny && (y) <= maxy)
 
 /* transpose top with bottom or left with right or both; sometimes called
    for new special levels, or for any level via the #wizlevelflip command */
@@ -449,6 +450,8 @@ boolean extras;
     struct engr *etmp;
     struct mkroom *sroom;
     timer_element *timer;
+    boolean ball_active = (Punished && uball->where != OBJ_FREE);
+    boolean ball_fliparea;
 
     get_level_extends(&minx, &miny, &maxx, &maxy);
     /* get_level_extends() returns -1,-1 to COLNO,ROWNO at max */
@@ -461,6 +464,13 @@ boolean extras;
     if (maxy >= ROWNO)
         maxy = (ROWNO - 1);
 
+    ball_fliparea = Punished
+     && inFlipArea(uball->ox, uball->oy) == inFlipArea(uchain->ox, uchain->oy)
+     && inFlipArea(uball->ox, uball->oy) == inFlipArea(u.ux, u.uy);
+
+    if (ball_active && extras && !ball_fliparea)
+        unplacebc();
+
     /* stairs and ladders */
     if (flp & 1) {
         if (xupstair)
@@ -489,8 +499,7 @@ boolean extras;
 
     /* traps */
     for (ttmp = g.ftrap; ttmp; ttmp = ttmp->ntrap) {
-        if (ttmp->tx < minx || ttmp->tx > maxx
-            || ttmp->ty < miny || ttmp->ty > maxy)
+        if (!inFlipArea(ttmp->tx, ttmp->ty))
             continue;
        if (flp & 1) {
            ttmp->ty = FlipY(ttmp->ty);
@@ -516,8 +525,7 @@ boolean extras;
 
     /* objects */
     for (otmp = fobj; otmp; otmp = otmp->nobj) {
-        if (otmp->ox < minx || otmp->ox > maxx
-            || otmp->oy < miny || otmp->oy > maxy)
+        if (!inFlipArea(otmp->ox, otmp->oy))
             continue;
        if (flp & 1)
            otmp->oy = FlipY(otmp->oy);
@@ -527,8 +535,7 @@ boolean extras;
 
     /* buried objects */
     for (otmp = g.level.buriedobjlist; otmp; otmp = otmp->nobj) {
-        if (otmp->ox < minx || otmp->ox > maxx
-            || otmp->oy < miny || otmp->oy > maxy)
+        if (!inFlipArea(otmp->ox, otmp->oy))
             continue;
        if (flp & 1)
            otmp->oy = FlipY(otmp->oy);
@@ -541,8 +548,7 @@ boolean extras;
         if (mtmp->isgd && mtmp->mx == 0)
             continue;
         /* skip the occasional earth elemental outside the flip area */
-        if (mtmp->mx < minx || mtmp->mx > maxx
-            || mtmp->my < miny || mtmp->my > maxy)
+        if (!inFlipArea(mtmp->mx, mtmp->my))
             continue;
        if (flp & 1) {
            mtmp->my = FlipY(mtmp->my);
@@ -735,6 +741,8 @@ boolean extras;
             if (flp & 2)
                 u.ux = FlipX(u.ux), u.ux0 = FlipX(u.ux0);
         }
+        if (ball_active && !ball_fliparea)
+            placebc();
     }
 
     fix_wall_spines(1, 0, COLNO - 1, ROWNO - 1);
@@ -747,6 +755,7 @@ boolean extras;
 
 #undef FlipX
 #undef FlipY
+#undef inFlipArea
 
 /* randomly transpose top with bottom or left with right or both;
    caller controls which transpositions are allowed */