fix #K125 - autounlock vs touching artifacts

Apply makes a touch_artifact check on the tool being applied, but
autounlock would pick an unlocking tool to use without doing that.
Noticed while fixing that:  autounlock took no time.

Since picking an artifact unlocking tool might now blast the hero,
change the tool selection.  First choice: any key except another
role's quest artifact; second: any lock-pick except another role's
quest artifact; third: any credit card except another role's quest
artifact; fourth, fifth, sixth: other roles' quest artifact key,
lock-pick, or credit card.  The fifth category (artifact lock-picks)
is empty.  Rogues will pick non-cursed Master Key over any other
key (special case for first choice).  Tourists will pick a key or
a lock-pick over their PYEC (first and second choices over third).
This commit is contained in:
PatR
2020-01-05 23:54:11 -08:00
parent 3a8990b8a0
commit bfa0f072f7
4 changed files with 88 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 lock.c $NHDT-Date: 1577759837 2019/12/31 02:37:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.97 $ */
/* NetHack 3.6 lock.c $NHDT-Date: 1578297245 2020/01/06 07:54:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.98 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -103,7 +103,7 @@ picklock(VOID_ARGS)
state is adequate (non-cursed for rogues, blessed for others;
checked when setting up 'xlock') */
if ((!g.xlock.door ? (int) g.xlock.box->otrapped
: (g.xlock.door->doormask & D_TRAPPED) != 0)
: (g.xlock.door->doormask & D_TRAPPED) != 0)
&& g.xlock.magic_key) {
g.xlock.chance += 20; /* less effort needed next time */
/* unfortunately we don't have a 'tknown' flag to record
@@ -284,6 +284,66 @@ struct obj *container; /* passed from obfree() */
reset_pick();
}
/* pick a tool for autounlock */
struct obj *
autokey(opening)
boolean opening; /* True: key, pick, or card; False: key or pick */
{
struct obj *o, *key, *pick, *card, *akey, *apick, *acard;
/* mundane item or regular artifact or own role's quest artifact */
key = pick = card = (struct obj *) 0;
/* other role's quest artifact (Rogue's Key or Tourist's Credit Card) */
akey = apick = acard = (struct obj *) 0;
for (o = g.invent; o; o = o->nobj) {
if (any_quest_artifact(o) && !is_quest_artifact(o)) {
switch (o->otyp) {
case SKELETON_KEY:
if (!akey)
akey = o;
break;
case LOCK_PICK:
if (!apick)
apick = o;
break;
case CREDIT_CARD:
if (!acard)
acard = o;
break;
default:
break;
}
} else {
switch (o->otyp) {
case SKELETON_KEY:
if (!key || is_magic_key(&g.youmonst, o))
key = o;
break;
case LOCK_PICK:
if (!pick)
pick = o;
break;
case CREDIT_CARD:
if (!card)
card = o;
break;
default:
break;
}
}
}
if (!opening)
card = acard = 0;
/* only resort to other role's quest artifact if no other choice */
if (!key && !pick && !card)
key = akey;
if (!pick && !card)
pick = apick;
if (!card)
card = acard;
return key ? key : pick ? pick : card ? card : 0;
}
/* for doapply(); if player gives a direction or resumes an interrupted
previous attempt then it costs hero a move even if nothing ultimately
happens; when told "can't do that" before being asked for direction
@@ -355,8 +415,8 @@ struct obj *container; /* container, for autounlock */
if (rx != 0 && ry != 0) { /* autounlock; caller has provided coordinates */
cc.x = rx;
cc.y = ry;
}
else if (!get_adjacent_loc((char *) 0, "Invalid location!", u.ux, u.uy, &cc)) {
} else if (!get_adjacent_loc((char *) 0, "Invalid location!",
u.ux, u.uy, &cc)) {
return PICKLOCK_DID_NOTHING;
}
@@ -406,9 +466,10 @@ struct obj *container; /* container, for autounlock */
return 0;
} else {
/* "There is <a box> here; <verb> <it|its lock>?" */
Sprintf(qsfx, " here; %s %s?", verb, it ? "it" : "its lock");
Sprintf(qsfx, " here; %s %s?",
verb, it ? "it" : "its lock");
(void) safe_qbuf(qbuf, "There is ", qsfx, otmp, doname,
ansimpleoname, "a box");
ansimpleoname, "a box");
otmp->lknown = 1;
c = ynq(qbuf);
@@ -426,6 +487,9 @@ struct obj *container; /* container, for autounlock */
You_cant("do that with %s.",
an(simple_typename(picktyp)));
return PICKLOCK_LEARNED_SOMETHING;
} else if (autounlock && !touch_artifact(pick, &g.youmonst)) {
/* note: for !autounlock, apply already did touch check */
return PICKLOCK_DID_SOMETHING;
}
switch (picktyp) {
case CREDIT_CARD:
@@ -511,6 +575,10 @@ struct obj *container; /* container, for autounlock */
if (c == 'n')
return 0;
/* note: for !autounlock, 'apply' already did touch check */
if (autounlock && !touch_artifact(pick, &g.youmonst))
return PICKLOCK_DID_SOMETHING;
switch (picktyp) {
case CREDIT_CARD:
ch = 2 * ACURR(A_DEX) + 20 * Role_if(PM_ROGUE);
@@ -724,11 +792,8 @@ int x, y;
break;
}
pline("This door%s.", mesg);
if (locked && flags.autounlock
&& ((unlocktool = carrying(SKELETON_KEY)) != 0
|| (unlocktool = carrying(LOCK_PICK)) != 0
|| (unlocktool = carrying(CREDIT_CARD)) != 0)) {
pick_lock(unlocktool, cc.x, cc.y, (struct obj *) 0);
if (locked && flags.autounlock && (unlocktool = autokey(TRUE)) != 0) {
res = pick_lock(unlocktool, cc.x, cc.y, (struct obj *) 0);
}
return res;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pickup.c $NHDT-Date: 1577759853 2019/12/31 02:37:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.257 $ */
/* NetHack 3.6 pickup.c $NHDT-Date: 1578297247 2020/01/06 07:54:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.258 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1729,12 +1729,9 @@ int cindex, ccount; /* index of this container (1..N), number of them (N) */
pline("Hmmm, %s turns out to be locked.", the(xname(cobj)));
cobj->lknown = 1;
if (flags.autounlock
&& ((unlocktool = carrying(SKELETON_KEY)) != 0
|| (unlocktool = carrying(LOCK_PICK)) != 0
|| (unlocktool = carrying(CREDIT_CARD)) != 0)) {
if (flags.autounlock && (unlocktool = autokey(TRUE)) != 0) {
/* pass ox and oy to avoid direction prompt */
pick_lock(unlocktool, cobj->ox, cobj->oy, cobj);
return (pick_lock(unlocktool, cobj->ox, cobj->oy, cobj) != 0);
}
return 0;
}