autounlock overhaul

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
This commit is contained in:
PatR
2022-05-04 19:13:28 -07:00
parent d1b14e08c4
commit 44d5be6eb4
9 changed files with 282 additions and 31 deletions

View File

@@ -1872,8 +1872,6 @@ do_loot_cont(struct obj **cobjp,
if (!cobj)
return ECMD_OK;
if (cobj->olocked) {
struct obj *unlocktool;
if (ccount < 2 && (g.level.objects[cobj->ox][cobj->oy] == cobj))
pline("%s locked.",
cobj->lknown ? "It is" : "Hmmm, it turns out to be");
@@ -1884,10 +1882,18 @@ do_loot_cont(struct obj **cobjp,
cobj->lknown = 1;
if (flags.autounlock) {
if ((unlocktool = autokey(TRUE)) != 0) {
struct obj *unlocktool;
/* TODO: handle AUTOUNLOCK_UNTRAP and maybe add kicking at
self when chest present to handle AUTOUNLOCK_KICK */
u.dz = 0; /* might be non-zero from previous command since
* #loot isn't a move command; pick_lock() cares */
if ((flags.autounlock & AUTOUNLOCK_APPLY_KEY) != 0
&& (unlocktool = autokey(TRUE)) != 0) {
/* pass ox and oy to avoid direction prompt */
return (pick_lock(unlocktool, cobj->ox, cobj->oy, cobj) != 0);
} else if (ccount == 1 && u_have_forceable_weapon()) {
} else if ((flags.autounlock & AUTOUNLOCK_FORCE) != 0
&& ccount == 1 && u_have_forceable_weapon()) {
/* single container, and we could #force it open... */
cmdq_add_ec(doforce); /* doforce asks for confirmation */
g.abort_looting = TRUE;