Skip to content

Commit

Permalink
autounlock overhaul
Browse files Browse the repository at this point in the history
This gives the player more control over what autounlock does.  It is
now a compound option rather than a boolean, and takes values of
  autounlock:none
  !autounlock or noautounlock (shortcuts for none)
  autounlock:untrap + apply-key + kick + force (spaces are optional
    or can be used instead of plus-signs, but can't mix "foo bar+quux")
  autounlock (without a value, shortcut for autounlock:apply-key).
Default is autounlock:apply-key.

Untrap isn't implemented (feel free to jump in) so is suppressed from
the 'O' command's new sub-menu for autounlock.  It's parsed and
accepted from .nethackrc but won't accomplish anything.

[Just musing: it should be feasible to kick in direction '.' to break
open a container or #force to an adjacent spot to break open a door.
If that was done, autounlock:kick+force (or more likely autounlock:
apply-key+kick+force when lacking a key) would resort to force if hero
couldn't kick due to wounded legs or riding.

This changes struct flags so increments EDITLEVEL again.

This includes pull requests #750 from entrez and #751 from FIQ but was
entered from scratch rather than using use their commits.

Closes #750
Closes #751
  • Loading branch information
PatR committed May 5, 2022
1 parent d1b14e0 commit 44d5be6
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 31 deletions.
8 changes: 6 additions & 2 deletions dat/opthelp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ autoopen walking into a door attempts to open it [True]
autopickup automatically pick up objects you move over [True]
autoquiver when firing with an empty quiver, select some [False]
suitable inventory weapon to fill the quiver
autounlock when opening a locked door or looting a locked [True]
container while carrying a key, offer to use it
BIOS allow the use of IBM ROM BIOS calls [False]
blind your character is permanently blind [False]
bones allow loading bones files [True]
Expand Down Expand Up @@ -150,6 +148,12 @@ Compound options are written as option_name:option_value.

Compound options which can be set during the game are:

autounlock when attempting to open a door or loot a [Apply-Key]
container that is locked, specifies an action to take:
can be None, or one or more of Apply-Key + Kick + Force;
Kick is only useful for doors and Force is only useful for
containers; either will only be attempted if Apply-Key is
omitted or you aren't carrying any unlocking tool
boulder override the default boulder symbol [`]
disclose the types of information you want [ni na nv ng nc no]
offered at the end of the game
Expand Down
25 changes: 22 additions & 3 deletions doc/Guidebook.mn
Original file line number Diff line number Diff line change
Expand Up @@ -3659,9 +3659,28 @@ If no weapon is found or the option is
false, the \(oqt\(cq (throw) command is executed instead.
Persistent.
.lp autounlock
Walking into a locked door or looting a locked container while carrying
an unlocking tool (such as a key) will ask whether to use that tool to
unlock the door or container (default true).
Controls what action to take when attempting to walk into a locked door
or to loot a locked container.
Takes a plus-sign separated list of values:
\fIapply-key\fP which will attempt to use a key or other unlocking tool
if you have one;
\fIkick\fP which will kick the door (if you lack a key or omit apply-key;
has no effect on containers);
\fIforce\fP which will try to force a container's lid with your currently
wielded weapon (if you lack a key or omit apply-key; has no effect on
doors); or
\fInone\fP which can't be combined with the other choices.
.lp ""
Omitting the value is treated as if \f(CRautounlock:apply-key\fP.
Preceding \f(CRautounlock\fP with \(oq!\(cq or \(lqno\(rq is treated as
\f(CRautounlock:none\fP.
.lp ""
Applying a key might set off a trap if the door or container is trapped.
Successfully kicking a door will break it and wake up nearby monsters.
Successfully forcing a container open will break its lock and might also
destroy some of its contents or damage your weapon or both.
.lp ""
The default is \fIapply-key\fP.
Persistent.
.lp blind
Start the character permanently blind (default false).
Expand Down
28 changes: 25 additions & 3 deletions doc/Guidebook.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3970,9 +3970,31 @@ \subsection*{Customization options}
false, the `t' (throw) command is executed instead. Persistent.
%.lp
\item[\ib{autounlock}]
Walking into a locked door or looting a locked container while carrying
an unlocking tool (such as a key) will ask whether to use that tool to
unlock the door or container (default true).
Controls what action to take when attempting to walk into a locked door
or to loot a locked container.
Takes a plus-sign separated list of values:
{\it apply-key\/} which will attempt to use a key or other unlocking tool
if you have one;
{\it kick\/} which will kick the door (if you lack a key or omit apply-key;
has no effect on containers);
{\it force\/} which will try to force a container's lid with your currently
wielded weapon (if you lack a key or omit apply-key; has no effect on
doors); or
{\it none\/} which can't be combined with the other choices.
\\
%.lp ""
Omitting the value is treated as if {\tt autounlock:apply-key}.
Preceding {\tt autounlock} with `{\tt !}' or ``{\tt no}'' is treated as
{\tt autounlock:none}.
\\
%.lp ""
Applying a key might set off a trap if the door or container is trapped.
Successfully kicking a door will break it and wake up nearby monsters.
Successfully forcing a container open will break its lock and might also
destroy some of its contents or damage your weapon or both.
\\
%.lp ""
The default is {\it apply-key\/}.
Persistent.
%.lp
\item[\ib{blind}]
Expand Down
6 changes: 5 additions & 1 deletion include/flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ struct flag {
boolean autodig; /* MRKR: Automatically dig */
boolean autoquiver; /* Automatically fill quiver */
boolean autoopen; /* open doors by walking into them */
boolean autounlock; /* automatically apply unlocking tools */
boolean beginner; /* True early in each game; affects feedback */
boolean biff; /* enable checking for mail */
boolean bones; /* allow saving/loading bones */
Expand Down Expand Up @@ -63,6 +62,11 @@ struct flag {
boolean tombstone; /* print tombstone */
boolean verbose; /* max battle info */
int end_top, end_around; /* describe desired score list */
unsigned autounlock; /* locked door/chest action */
#define AUTOUNLOCK_UNTRAP 1
#define AUTOUNLOCK_APPLY_KEY 2
#define AUTOUNLOCK_KICK 4
#define AUTOUNLOCK_FORCE 8
unsigned moonphase;
unsigned long suppress_alert;
#define NEW_MOON 0
Expand Down
7 changes: 5 additions & 2 deletions include/optlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ opt_##a,
set_in_game, No, Yes, No, NoAlias, "edit autopickup exceptions")
NHOPTB(autoquiver, 0, opt_in, set_in_game, Off, Yes, No, No, NoAlias,
&flags.autoquiver)
NHOPTB(autounlock, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
&flags.autounlock)
NHOPTC(autounlock,
(sizeof "none" + sizeof "untrap" + sizeof "apply-key"
+ sizeof "kick" + sizeof "force" + 20),
opt_out, set_in_game, Yes, Yes, No, Yes, NoAlias,
"action to take when encountering locked door or chest")
#if defined(MICRO) && !defined(AMIGA)
NHOPTB(BIOS, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
&iflags.BIOS)
Expand Down
2 changes: 1 addition & 1 deletion include/patchlevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 57
#define EDITLEVEL 58

/*
* Development status possibilities.
Expand Down
44 changes: 29 additions & 15 deletions src/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,18 +350,19 @@ DISABLE_WARNING_FORMAT_NONLITERAL

/* player is applying a key, lock pick, or credit card */
int
pick_lock(struct obj *pick,
xchar rx, xchar ry, /* coordinates of doors/container,
for autounlock: does not prompt
for direction if these are set */
struct obj *container) /* container, for autounlock */
pick_lock(
struct obj *pick,
xchar rx, xchar ry, /* coordinates of door/container, for autounlock:
* does not prompt for direction if these are set */
struct obj *container) /* container, for autounlock */
{
int picktyp, c, ch;
coord cc;
struct rm *door;
struct obj *otmp;
char qbuf[QBUFSZ];
boolean autounlock = (rx != 0 && ry != 0) || (container != NULL);
boolean autounlock = (((rx != 0 && ry != 0) || container != NULL)
&& (flags.autounlock & AUTOUNLOCK_APPLY_KEY) != 0);

picktyp = pick->otyp;

Expand Down Expand Up @@ -422,7 +423,7 @@ pick_lock(struct obj *pick,
boolean it;
int count;

if (u.dz < 0) {
if (u.dz < 0 && !autounlock) { /* beware stale u.dz value */
There("isn't any sort of lock up %s.",
Levitation ? "here" : "there");
return PICKLOCK_LEARNED_SOMETHING;
Expand All @@ -436,10 +437,12 @@ pick_lock(struct obj *pick,

count = 0;
c = 'n'; /* in case there are no boxes here */
for (otmp = g.level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere)
/* autounlock on boxes: only the one that just informed you it was
* locked. Don't include any other boxes which might be here. */
if ((!autounlock && Is_box(otmp)) || (otmp == container)) {
for (otmp = g.level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere) {
/* autounlock on boxes: only the one that was just discovered to
be locked; don't include any other boxes which might be here */
if (autounlock && otmp != container)
continue;
if (Is_box(otmp)) {
++count;
if (!can_reach_floor(TRUE)) {
You_cant("reach %s from up here.", the(xname(otmp)));
Expand Down Expand Up @@ -508,6 +511,7 @@ pick_lock(struct obj *pick,
g.xlock.door = 0;
break;
}
}
if (c != 'y') {
if (!count)
There("doesn't seem to be any sort of lock here.");
Expand Down Expand Up @@ -626,6 +630,11 @@ doforce(void)
register int c, picktyp;
char qbuf[QBUFSZ];

/*
* TODO?
* allow force with edged weapon to be performed on doors.
*/

if (u.uswallow) {
You_cant("force anything from inside here.");
return ECMD_OK;
Expand Down Expand Up @@ -780,7 +789,6 @@ doopen_indir(int x, int y)
if (!(door->doormask & D_CLOSED)) {
const char *mesg;
boolean locked = FALSE;
struct obj* unlocktool;

switch (door->doormask) {
case D_BROKEN:
Expand All @@ -798,11 +806,17 @@ doopen_indir(int x, int y)
break;
}
pline("This door%s.", mesg);
if (locked) {
if (flags.autounlock && (unlocktool = autokey(TRUE)) != 0) {
if (locked && flags.autounlock) {
struct obj *unlocktool;

u.dz = 0; /* should already be 0 since hero moved toward door */
if ((flags.autounlock & AUTOUNLOCK_APPLY_KEY) != 0
&& (unlocktool = autokey(TRUE)) != 0) {
res = pick_lock(unlocktool, cc.x, cc.y,
(struct obj *) 0) ? ECMD_TIME : ECMD_OK;
} else if (!u.usteed && ynq("Kick it?") == 'y') {
} else if (!u.usteed
&& (flags.autounlock & AUTOUNLOCK_KICK) != 0
&& ynq("Kick it?") == 'y') {
cmdq_add_ec(dokick);
cmdq_add_dir(sgn(cc.x - u.ux), sgn(cc.y - u.uy), 0);
res = ECMD_TIME;
Expand Down

0 comments on commit 44d5be6

Please sign in to comment.