new 'mention_decor' option

Somewhat similar to 'mention_walls', 'mention_decor' is a way to
request additional feedback when moving around the map.  It reports
furniture or unusual terrain when you step on that.  Normally stepping
on furniture only mentions it when it is covered by object(s).  And
moving onto (rather than into) water or lava or ice doesn't bother
saying anything at all.  With the new option set there will be a
message.  It uses Norep so won't repeat when moving from one water
spot to another or one lava spot to another or one ice spot to another
unless there has been at least one intervening message.  There is also
a one-shot message when moving from water or lava or ice onto ordinary
terrain (not Norep, just once since there's no land to land message).

Having the verbose flag Off doesn't inhibit these new messages but it
does shorten them: "A fountain." instead of "There is a fountain here."

The Guidebook gets a new subsection "Movement feedback" of the "Rooms
and corridors" section and it covers more than just 'mention_decor'.
As usual, Guidebook.tex is untested.

'mention_decor' persists across save/restore, so 'struct flags' has
changed and EDITLEVEL is being bumped, hence save files are invalided.
This commit is contained in:
PatR
2020-01-29 09:47:36 -08:00
parent 63310076bb
commit ea8248e3c6
7 changed files with 256 additions and 15 deletions

View File

@@ -34,6 +34,8 @@ legacy print introductory message [TRUE]
lit_corridor show a dark corridor as lit if in sight [FALSE]
lootabc use a/b/c rather than o/i/b when looting [FALSE]
mail enable the mail daemon [TRUE]
mention_decor give feedback when walking across stairs, altars, [FALSE]
fountains, and such even when not obscured by objects
mention_walls give feedback when walking against a wall [FALSE]
menu_objsyms show object symbols in menus if it is selectable [FALSE]
menu_overlay overlay menus on the screen and align to right [TRUE]

View File

@@ -1784,6 +1784,81 @@ any other customers.
If a shop is \(lqclosed for inventory,\(rq it will not open of its own accord.
.lp * 2
Shops do not get restocked with new items, regardless of inventory depletion.
.hn 2
Movement feedback
.pg
Moving around the map usually provides no feedback--other than drawing the
hero at the new location--unless you step on an object or pile of objects,
or on a trap, or attempt to move onto a spot where a monster is located.
There are several options which can be used to augment the normal feedback.
.pg
The
.op pile_limit
option controls how many objects can be in a pile--sharing the same map
location--for the game to state \(lqthere are objects here\(rq
instead of listing them.
The default is \f(CR5\fP.
Setting it to \f(CR1\fP would always give that message instead of listing
any objects.
Setting it to \f(CR0\fP is a special case which will always list all
objects no matter how big a pile is.
Note that the number refers to the count of separate stacks of objects
present rather than the sum of the quantities of those stacks (so
\f(CR7 arrows\fP or \f(CR25 gold pieces\fP will each count as 1 rather
than as 7 and 25, respectively, and total to 2 when both are at the
same location).
.pg
The \(lqnopickup\(rq command prefix (default \(oq\f(CRm\fP\(cq) before
a movement direction can be used to step on objects without attempting
auto-pickup and without giving feedback about them.
.pg
The
.op mention_walls
option controls whether you get feedback if you try to walk into a wall
or solid stone or off the edge of the map.
Normally nothing happens (unless the hero is blind and no wall is shown,
then the wall that is being bumped into will be drawn on the map).
This option also gives feedback when the various rush or run variations
of movement stop for some non-obvious reason.
.pg
The
.op mention_decor
option controls whether you get feedback when walking on \(lqfurniture.\(rq
Normally stepping onto stairs or a fountain or an altar or various other
things doesn't elicit anything unless it is covered by one or more objects
so is obscured on the map.
Doorless doorways and open doors aren't considered worthy of mention;
closed doors (if you can move onto their spots) and broken doors are.
Assuming that you're able to do so, moving onto water or lava or ice
will give feedback if not yet on that type of terrain but not repeat it
(unless there has been some intervening message) when moving from water
to another water spot, or lava to lava, or ice to ice.
Moving off of any of those back onto \(lqnormal\(rq terrain will give one
message too, unless there is feedback about one or more objects, in which
case the back on land circumstance is implied.
.pg
The
.op confirm
and
.op safe_pet
options control what happens when you try to move onto a peaceful monster's
spot or a tame one's spot.
.\" getting away from "Movement feedback" here; oh well...
.pg
The \(lqnopickup\(rq command prefix (default \(oq\f(CRm\fP\(cq) is
also the move-without-attacking prefix and can be used to try to step
onto a visible monster's spot without the move being considered an attack
(see the \fIFighting\fP subsection of \fIMonsters\fP below).
The \(lqfight\(rq command prefix (default \(oq\f(CRF\fP\(cq;
also \(oq\f(CR\-\fP\(cq if
.op number_pad
is on) can be used to force an attack, when guessing where an unseen
monster is or when deliberately attacking a peaceful or tame creature.
.pg
The
.op run_mode
option controls how frequently the map gets redrawn when moving more
than one step in a single command (so when rushing, running, or traveling).
.
.hn 1
Monsters
@@ -1809,8 +1884,10 @@ shopkeeper or the Oracle of Delphi can produce useful results.
Fighting
.pg
If you see a monster and you wish to fight it, just attempt to walk
into it. Many monsters you find will mind their own business unless
you attack them. Some of them are very dangerous when angered.
into it.
Many monsters you find will mind their own business unless
you attack them.
Some of them are very dangerous when angered.
Remember: discretion is the better part of valor.
.pg
In most circumstances, if you attempt to attack a peaceful monster by
@@ -3182,6 +3259,11 @@ Enable mail delivery during the game (default on). Persistent.
.lp "male "
An obsolete synonym for \(lqgender:male\(rq.
Cannot be set with the \(oqO\(cq command.
.lp mention_decor
Give feedback when walking on various dungeon features such as stairs,
fountains, or altars which are ordinarily only described when covered
by one or more objects (default off).
Persistent.
.lp mention_walls
Give feedback when walking against a wall (default off).
Persistent.

View File

@@ -1966,6 +1966,90 @@ If a shop is ``closed for inventory,'' it will not open of its own accord.
Shops do not get restocked with new items, regardless of inventory depletion.
\end{itemize}
%.hn 2
\subsubsection*{Movement feedback}
%.pg
Moving around the map usually provides no feedback--other than drawing the
hero at the new location--unless you step on an object or pile of objects,
or on a trap, or attempt to move onto a spot where a monster is located.
There are several options which can be used to augment the normal feedback.
%.pg
The
{\it pile\verb+_+limit\/}
option controls how many objects can be in a pile--sharing the same map
location--for the game to state ``there are objects here''
instead of listing them.
The default is {\tt 5}.
Setting it to {\tt 1} would always give that message instead of listing
any objects.
Setting it to {\tt 0} is a special case which will always list all
objects no matter how big a pile is.
Note that the number refers to the count of separate stacks of objects
present rather than the sum of the quantities of those stacks (so
{\tt 7 arrows} or {\tt 25 gold pieces} will each count as 1 rather
than as 7 and 25, respectively, and total to 2 when both are at the
same location).
%.pg
The \{\tt nopickup} command prefix (default `\{\tt m}') before
a movement direction can be used to step on objects without attempting
auto-pickup and without giving feedback about them.
%.pg
The
{\it mention\verb+_+walls\/}
option controls whether you get feedback if you try to walk into a wall
or solid stone or off the edge of the map.
Normally nothing happens (unless the hero is blind and no wall is shown,
then the wall that is being bumped into will be drawn on the map).
This option also gives feedback when the various rush or run variations
of movement stop for some non-obvious reason.
%.pg
The
{\it mention\verb+_+decor\/}
option controls whether you get feedback when walking on ``furniture.''
Normally stepping onto stairs or a fountain or an altar or various other
things doesn't elicit anything unless it is covered by one or more objects
so is obscured on the map.
Doorless doorways and open doors aren't considered worthy of mention;
closed doors (if you can move onto their spots) and broken doors are.
Assuming that you're able to do so, moving onto water or lava or ice
will give feedback if not yet on that type of terrain but not repeat it
(unless there has been some intervening message) when moving from water
to another water spot, or lava to lava, or ice to ice.
Moving off of any of those back onto ``normal'' terrain will give one
message too, unless there is feedback about one or more objects, in which
case the back on land circumstance is implied.
%.pg
The
{\it confirm\/}
and
{\it safe\verb+_+pet\/}
options control what happens when you try to move onto a peaceful monster's
spot or a tame one's spot.
%.\" getting away from "Movement feedback" here; oh well...
%.pg
The {\tt nopickup} command prefix (default `{\tt m}' is
also the move-without-attacking prefix and can be used to try to step
onto a visible monster's spot without the move being considered an attack
(see the {\it Fighting\/} subsection of {\it Monsters\/} below).
The `{\tt fight}' command prefix (default `{\tt F}';
also `{\tt -}' if
{\it number\verb+_+pad\/}
is on) can be used to force an attack, when guessing where an unseen
monster is or when deliberately attacking a peaceful or tame creature.
%.pg
The
{\it run\verb+_+mode}
option controls how frequently the map gets redrawn when moving more
than one step in a single command (so when rushing, running, or traveling).
%.hn 1
\section{Monsters}
@@ -3489,6 +3573,11 @@ Enable mail delivery during the game (default on). Persistent.
An obsolete synonym for ``{\tt gender:male}''. Cannot be set with the
`{\tt O}' command.
%.lp
\item[\ib{mention\verb+_+decor}]
Give feedback when walking on various dungeon features such as stairs,
fountains, or altars which are ordinarily only described when covered
by one or more objects (default off). Persistent.
%.lp
\item[\ib{mention\verb+_+walls}]
Give feedback when walking against a wall (default off). Persistent.
%.lp

View File

@@ -41,6 +41,7 @@ struct flag {
boolean invlet_constant; /* let objects keep their inventory symbol */
boolean legacy; /* print game entry "story" */
boolean lit_corridor; /* show a dark corr as lit if it is in sight */
boolean mention_decor; /* give feedback for unobscured furniture */
boolean mention_walls; /* give feedback when bumping walls */
boolean nap; /* `timed_delay' option for display effects */
boolean null; /* OK to send nulls to the terminal */
@@ -283,6 +284,7 @@ struct instance_flags {
boolean zerocomp; /* write zero-compressed save files */
boolean rlecomp; /* alternative to zerocomp; run-length encoding
* compression of levels when writing savefile */
schar prev_decor; /* 'mention_decor' just mentioned this */
uchar num_pad_mode;
uchar bouldersym; /* symbol for boulder display */
char prevmsg_window; /* type of old message window to use */

View File

@@ -14,7 +14,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 11
#define EDITLEVEL 12
#define COPYRIGHT_BANNER_A "NetHack, Copyright 1985-2020"
#define COPYRIGHT_BANNER_B \

View File

@@ -158,6 +158,7 @@ static const struct Bool_Opt {
#else
{ "mail", (boolean *) 0, TRUE, SET_IN_FILE },
#endif
{ "mention_decor", &flags.mention_decor, FALSE, SET_IN_GAME },
{ "mention_walls", &flags.mention_walls, FALSE, SET_IN_GAME },
{ "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME },
/* for menu debugging only*/
@@ -4168,6 +4169,8 @@ boolean tinitial, tfrom_file;
|| boolopt[i].addr == &iflags.wc2_guicolor) {
update_inventory();
#endif /* TEXTCOLOR */
} else if (boolopt[i].addr == &flags.mention_decor) {
iflags.prev_decor = STONE;
}
return retval;
}

View File

@@ -16,6 +16,7 @@ static boolean FDECL(query_classes, (char *, boolean *, boolean *,
const char *, struct obj *,
BOOLEAN_P, int *));
static boolean FDECL(fatal_corpse_mistake, (struct obj *, BOOLEAN_P));
static void NDECL(describe_decor);
static void FDECL(check_here, (BOOLEAN_P));
static boolean FDECL(n_or_more, (struct obj *));
static boolean FDECL(all_but_uchain, (struct obj *));
@@ -285,6 +286,60 @@ boolean remotely;
return TRUE;
}
/* handle 'mention_decor' (when walking onto a dungeon feature such as
stairs or altar, describe it even if it isn't covered up by an object) */
static void
describe_decor()
{
char outbuf[BUFSZ], fbuf[QBUFSZ];
boolean doorhere, waterhere, do_norep;
const char *dfeature = dfeature_at(u.ux, u.uy, fbuf);
int ltyp = levl[u.ux][u.uy].typ;
if (ltyp == DRAWBRIDGE_UP) /* surface for spot in front of closed db */
ltyp = db_under_typ(levl[u.ux][u.uy].drawbridgemask);
/* we don't mention "ordinary" doors but do mention broken ones */
doorhere = dfeature && (!strcmp(dfeature, "open door")
|| !strcmp(dfeature, "doorway"));
waterhere = dfeature && !strcmp(dfeature, "pool of water");
if (doorhere || (waterhere && Underwater))
dfeature = 0;
if (dfeature) {
if (waterhere)
dfeature = strcpy(fbuf, waterbody_name(u.ux, u.uy));
if (strcmp(dfeature, "swamp"))
dfeature = an(dfeature);
if (flags.verbose) {
Sprintf(outbuf, "There is %s here.", dfeature);
} else {
if (dfeature != fbuf)
Strcpy(fbuf, dfeature);
Sprintf(outbuf, "%s.", upstart(fbuf));
}
do_norep = (ltyp == iflags.prev_decor
&& (waterhere
|| !strcmp(dfeature, "molten lava")
|| !strcmp(dfeature, "ice")));
if (!do_norep)
pline("%s", outbuf);
else
Norep("%s", outbuf);
} else {
if ((IS_POOL(iflags.prev_decor)
|| iflags.prev_decor == LAVAPOOL
|| iflags.prev_decor == ICE)) {
pline("%s %s %s.",
flags.verbose ? "You are back" : "Back",
(Levitation || Flying) ? "over" : "on",
surface(u.ux, u.uy));
}
}
iflags.prev_decor = ltyp;
}
/* look at the objects at our location, unless there are too many of them */
static void
check_here(picked_some)
@@ -305,7 +360,11 @@ boolean picked_some;
nomul(0);
flush_screen(1);
(void) look_here(ct, picked_some);
iflags.prev_decor = STONE;
} else {
if (flags.mention_decor)
describe_decor();
read_engr_at(u.ux, u.uy);
}
}
@@ -320,7 +379,6 @@ struct obj *obj;
return (boolean) (obj->quan >= g.val_for_n_or_more);
}
/* check valid_menu_classes[] for an entry; also used by askchain() */
boolean
menu_class_present(c)
@@ -487,8 +545,10 @@ int what; /* should be a long */
and read_engr_at in addition to bypassing autopickup itself
[probably ought to check whether hero is using a cockatrice
corpse for a pillow here... (also at initial faint/sleep)] */
if (autopickup && g.multi < 0 && unconscious())
if (autopickup && g.multi < 0 && unconscious()) {
iflags.prev_decor = STONE;
return 0;
}
if (what < 0) /* pick N of something */
count = -what;
@@ -496,20 +556,23 @@ int what; /* should be a long */
count = 0;
if (!u.uswallow) {
struct trap *ttmp;
struct trap *t;
/* no auto-pick if no-pick move, nothing there, or in a pool */
if (autopickup && (g.context.nopick || !OBJ_AT(u.ux, u.uy)
|| (is_pool(u.ux, u.uy) && !Underwater)
|| is_lava(u.ux, u.uy))) {
if (flags.mention_decor)
describe_decor();
read_engr_at(u.ux, u.uy);
return 0;
}
/* no pickup if levitating & not on air or water level */
if (!can_reach_floor(TRUE)) {
describe_decor(); /* even when !flags.mention_decor */
if ((g.multi && !g.context.run) || (autopickup && !flags.pickup)
|| ((ttmp = t_at(u.ux, u.uy)) != 0
&& (uteetering_at_seen_pit(ttmp) || uescaped_shaft(ttmp))))
|| ((t = t_at(u.ux, u.uy)) != 0
&& (uteetering_at_seen_pit(t) || uescaped_shaft(t))))
read_engr_at(u.ux, u.uy);
return 0;
}
@@ -517,15 +580,13 @@ int what; /* should be a long */
* action, or possibly paralyzed, sleeping, etc.... and they just
* teleported onto the object. They shouldn't pick it up.
*/
if ((g.multi && !g.context.run) || (autopickup && !flags.pickup)) {
if ((g.multi && !g.context.run)
|| (autopickup && !flags.pickup)
|| notake(g.youmonst.data)) {
check_here(FALSE);
return 0;
}
if (notake(g.youmonst.data)) {
if (!autopickup)
if (notake(g.youmonst.data) && OBJ_AT(u.ux, u.uy)
&& (autopickup || flags.pickup))
You("are physically incapable of picking anything up.");
else
check_here(FALSE);
return 0;
}
@@ -534,6 +595,8 @@ int what; /* should be a long */
&& !g.context.nopick)
nomul(0);
}
/* for describe_decor()'s Norep handling */
iflags.prev_decor = STONE;
add_valid_menu_class(0); /* reset */
if (!u.uswallow) {