]> granicus.if.org Git - nethack/commitdiff
Invert the behavior of selection.gradient
authorcopperwater <aosdict@gmail.com>
Fri, 10 Feb 2023 12:38:22 +0000 (07:38 -0500)
committerPasi Kallinen <paxed@alt.org>
Tue, 14 Feb 2023 07:13:59 +0000 (09:13 +0200)
selection.gradient has some pretty unintuitive behavior, in that it
selects points that are NOT close to the defined center. I've used
gradient selections several times and so far all of them have had to be
negated, because I wanted to select points close to the center with a
decreasing probability further out.

This implements that behavior, and also fixes a bug in which the x,y
coordinates of the gradient center(s) were not converted properly when
used within a des.room or des.map. Also updated the lua documentation
for gradient.

I removed the "limited" argument, as it was previously used to control
whether the rest of the map outside the max given distance would be
included in the selection; now that the area beyond maxdist is naturally
never in the selection, it doesn't have much use. (And I can't think of
a reasonable use case for the inverse: wanting to select points close to
the center, with decreasing chance towards maxdist, but then select the
entire map beyond maxdist.)

Currently this does not affect any special levels or themed rooms
because none of them use selection.gradient.

doc/lua.adoc
include/extern.h
src/nhlsel.c
src/sp_lev.c

index cd08d5ebdb12de0c1081f3b934c14c132692b782..90ec18d2f8158e2d1efdfb06a826742ad52c2e84 100644 (file)
@@ -1090,11 +1090,23 @@ Example:
 
 === gradient
 
-Create a "gradient" of selected positions.
-
-Example:
-
- local s = selection.gradient({ type = "radial", x = 3, y = 5, x2 = 10, y2 = 12, mindist = 4, maxdist = 10, limited = false });
+Create a "gradient" of selected positions, radiating outward from a center point
+or line.
+x and y are required; x2 and y2 are not required. If they are provided and are
+different from x and y, the center of the gradient will be a line; otherwise it
+will be a point source at (x,y).
+type is either "radial" or "square"; defaults to "radial" if not provided.
+mindist is not required and is 0 by default. Points within (mindist) tiles of
+the center will always be added to the selection.
+maxdist is required. Points more than (maxdist) tiles from the center will never
+be added to the selection.
+For any given point between mindist and maxdist, there is a random chance it
+will be added to the selection; this chance starts at 100% at mindist and
+decreases linearly to 0% at maxdist.
+
+Example:
+
+ local s = selection.gradient({ type = "radial", x = 3, y = 5, x2 = 10, y2 = 12, mindist = 4, maxdist = 10 });
 
 
 === grow
index 586b0e844b4717c3bcd04b8ff6865c66454bba6f..5e89e43ef4fa0f81b9ccf67fc3df07aa513e4638 100644 (file)
@@ -2674,7 +2674,7 @@ extern void set_floodfillchk_match_under(coordxy);
 extern void selection_do_ellipse(struct selectionvar *, int, int, int, int,
                                  int);
 extern void selection_do_gradient(struct selectionvar *, long, long, long,
-                                  long, long, long, long, long);
+                                  long, long, long, long);
 extern int lspo_reset_level(lua_State *);
 extern int lspo_finalize_level(lua_State *);
 extern boolean get_coord(lua_State *, int, lua_Integer *, lua_Integer *);
index e3c86e39e83b8ecea6eec63b4788a7eecb3fbe31..52850d8f6baed869cfe9df1b047d6665232790a8 100644 (file)
@@ -840,13 +840,10 @@ l_selection_gradient(lua_State *L)
     /* if x2 and y2 aren't set, the gradient has a single center point of x,y;
      * if they are set, the gradient is centered on a (x,y) to (x2,y2) line */
     coordxy x = 0, y = 0, x2 = -1, y2 = -1;
-    /* points will not be added within mindist of the center; the chance for a
+    /* points are always added within mindist of the center; the chance for a
      * point between mindist and maxdist to be added to the selection starts at
-     * 0% at mindist and increases linearly to 100% at maxdist */
+     * 100% at mindist and decreases linearly to 0% at maxdist */
     coordxy mindist = 0, maxdist = 0;
-    /* if limited is true, no points farther than maxdist will be added; if
-     * false, all points farther than maxdist will be added */
-    boolean limited = FALSE;
     long type = 0;
     static const char *const gradtypes[] = {
         "radial", "square", NULL
@@ -862,17 +859,18 @@ l_selection_gradient(lua_State *L)
         y = (coordxy) get_table_int(L, "y");
         x2 = (coordxy) get_table_int_opt(L, "x2", -1);
         y2 = (coordxy) get_table_int_opt(L, "y2", -1);
+        cvt_to_abscoord(&x, &y);
+        cvt_to_abscoord(&x2, &y2);
         /* maxdist is required because there's no obvious default value for it,
          * whereas mindist has an obvious defalt of 0 */
         maxdist = get_table_int(L, "maxdist");
         mindist = get_table_int_opt(L, "mindist", 0);
-        limited = get_table_boolean_opt(L, "limited", FALSE);
 
         lua_pop(L, 1);
         (void) l_selection_new(L);
         sel = l_selection_check(L, 1);
     } else {
-        nhl_error(L, "wrong parameters");
+        nhl_error(L, "selection.gradient requires table argument");
         /* NOTREACHED */
     }
 
@@ -885,7 +883,7 @@ l_selection_gradient(lua_State *L)
         y2 = y;
     }
 
-    selection_do_gradient(sel, x, y, x2, y2, type, mindist, maxdist, limited);
+    selection_do_gradient(sel, x, y, x2, y2, type, mindist, maxdist);
     lua_settop(L, 1);
     return 1;
 }
index 916e713a444c24672bc37d8638f23a55f8aa1354..7870d0b0a2d0ebf3890a4f98aedea42a8f10edaf 100644 (file)
@@ -4989,13 +4989,14 @@ line_dist_coord(long x1, long y1, long x2, long y2, long x3, long y3)
     return dist;
 }
 
+/* guts of l_selection_gradient */
 void
 selection_do_gradient(
     struct selectionvar *ov,
     long x, long y,
     long x2,long y2,
     long gtyp,
-    long mind, long maxd, long limit)
+    long mind, long maxd)
 {
     long dx, dy, dofs;
 
@@ -5017,10 +5018,8 @@ selection_do_gradient(
         for (dx = 0; dx < COLNO; dx++)
             for (dy = 0; dy < ROWNO; dy++) {
                 long d0 = line_dist_coord(x, y, x2, y2, dx, dy);
-                if (d0 >= mind && (!limit || d0 <= maxd)) {
-                    if (d0 - mind > rn2(dofs))
-                        selection_setpoint(dx, dy, ov, 1);
-                }
+                if (d0 <= mind || (d0 <= maxd && d0 - mind < rn2(dofs)))
+                    selection_setpoint(dx, dy, ov, 1);
             }
         break;
     }
@@ -5034,10 +5033,8 @@ selection_do_gradient(
                 long d5 = line_dist_coord(x, y, x2, y2, dx, dy);
                 long d0 = min(d5, min(max(d1, d2), max(d3, d4)));
 
-                if (d0 >= mind && (!limit || d0 <= maxd)) {
-                    if (d0 - mind > rn2(dofs))
-                        selection_setpoint(dx, dy, ov, 1);
-                }
+                if (d0 <= mind || (d0 <= maxd && d0 - mind < rn2(dofs)))
+                    selection_setpoint(dx, dy, ov, 1);
             }
         break;
     } /*case*/