Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2019-01-23 00:42:41 -05:00
8 changed files with 369 additions and 107 deletions

View File

@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.232 $ $NHDT-Date: 1547849604 2019/01/18 22:13:24 $
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.235 $ $NHDT-Date: 1548209734 2019/01/23 02:15:34 $
This fixes36.2 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.1 in April 2018. Please note, however,
@@ -343,6 +343,13 @@ the simulation of dual weapon combat when polymorphed into a form with more
even when current shape couldn't handle silver, or if it was cursed;
cursed is allowed but weapon will be dropped, just like in two-weapon
demons gated in other demons without any message
if vampire revives from from dead bat/cloud/wolf shape held by hero poly'd
into grabber, release it from hero's grasp
various non-weapon attacks while polymorphed didn't inflict blessed or silver
weapon damage when worn items contacted vulnerable target monsters
hero poly'd into rope golem form could choke headless or non-breathing monsts
hero poly'd into creature with hug attack could hug a long worm's tail which
rendered the whole worm immobile
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1547486885 2019/01/14 17:28:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.682 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1548209735 2019/01/23 02:15:35 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.684 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1907,6 +1907,7 @@ E int NDECL(dogaze);
E int NDECL(dohide);
E int NDECL(dopoly);
E int NDECL(domindblast);
E void NDECL(uunstick);
E void FDECL(skinback, (BOOLEAN_P));
E const char *FDECL(mbodypart, (struct monst *, int));
E const char *FDECL(body_part, (int));
@@ -2516,7 +2517,7 @@ E int FDECL(find_roll_to_hit, (struct monst *, UCHAR_P, struct obj *,
int *, int *));
E boolean FDECL(attack, (struct monst *));
E boolean FDECL(hmon, (struct monst *, struct obj *, int, int));
E int FDECL(damageum, (struct monst *, struct attack *));
E int FDECL(damageum, (struct monst *, struct attack *, int));
E void FDECL(missum, (struct monst *, struct attack *, BOOLEAN_P));
E int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int,
UCHAR_P, BOOLEAN_P));
@@ -2733,6 +2734,8 @@ E int FDECL(vms_get_saved_games, (const char *, char ***));
E const char *FDECL(weapon_descr, (struct obj *));
E int FDECL(hitval, (struct obj *, struct monst *));
E int FDECL(dmgval, (struct obj *, struct monst *));
E int FDECL(special_dmgval, (struct monst *, struct monst *, long, long *));
E void FDECL(silver_sears, (struct monst *, struct monst *, long));
E struct obj *FDECL(select_rwep, (struct monst *));
E boolean FDECL(monmightthrowwep, (struct obj *));
E struct obj *FDECL(select_hwep, (struct monst *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mondata.h $NHDT-Date: 1547086248 2019/01/10 02:10:48 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.35 $ */
/* NetHack 3.6 mondata.h $NHDT-Date: 1548209737 2019/01/23 02:15:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.36 $ */
/* Copyright (c) 1989 Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */
@@ -59,6 +59,7 @@
#define slithy(ptr) (((ptr)->mflags1 & M1_SLITHY) != 0L)
#define is_wooden(ptr) ((ptr) == &mons[PM_WOOD_GOLEM])
#define thick_skinned(ptr) (((ptr)->mflags1 & M1_THICK_HIDE) != 0L)
#define hug_throttles(ptr) ((ptr) == &mons[PM_ROPE_GOLEM])
#define slimeproof(ptr) \
((ptr) == &mons[PM_GREEN_SLIME] || flaming(ptr) || noncorporeal(ptr))
#define lays_eggs(ptr) (((ptr)->mflags1 & M1_OVIPAROUS) != 0L)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 dokick.c $NHDT-Date: 1547086527 2019/01/10 02:15:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.129 $ */
/* NetHack 3.6 dokick.c $NHDT-Date: 1548209738 2019/01/23 02:15:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.130 $ */
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
@@ -23,15 +23,15 @@ STATIC_DCL void FDECL(drop_to, (coord *, SCHAR_P));
static const char kick_passes_thru[] = "kick passes harmlessly through";
/* kicking damage when not poly'd into a form with a kick attack */
STATIC_OVL void
kickdmg(mon, clumsy)
register struct monst *mon;
register boolean clumsy;
struct monst *mon;
boolean clumsy;
{
register int mdx, mdy;
register int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
int kick_skill = P_NONE;
int blessed_foot_damage = 0;
int mdx, mdy;
int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
int specialdmg, kick_skill = P_NONE;
boolean trapkilled = FALSE;
if (uarmf && uarmf->otyp == KICKING_BOOTS)
@@ -45,15 +45,13 @@ register boolean clumsy;
if (thick_skinned(mon->data))
dmg = 0;
/* attacking a shade is useless */
/* attacking a shade is normally useless */
if (mon->data == &mons[PM_SHADE])
dmg = 0;
if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon))
&& uarmf && uarmf->blessed)
blessed_foot_damage = 1;
specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
if (mon->data == &mons[PM_SHADE] && !specialdmg) {
pline_The("%s.", kick_passes_thru);
/* doesn't exercise skill or abuse alignment or frighten pet,
and shades have no passive counterattack */
@@ -85,8 +83,7 @@ register boolean clumsy;
/* a good kick exercises your dex */
exercise(A_DEX, TRUE);
}
if (blessed_foot_damage)
dmg += rnd(4);
dmg += specialdmg; /* for blessed (or hypothetically, silver) boots */
if (uarmf)
dmg += uarmf->spe;
dmg += u.udaminc; /* add ring(s) of increase damage */
@@ -184,7 +181,7 @@ xchar x, y;
*/
if (Upolyd && attacktype(g.youmonst.data, AT_KICK)) {
struct attack *uattk;
int sum, kickdieroll, armorpenalty,
int sum, kickdieroll, armorpenalty, specialdmg,
attknum = 0,
tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum,
&armorpenalty);
@@ -200,14 +197,16 @@ xchar x, y;
if (uattk->aatyp != AT_KICK)
continue;
if (mon->data == &mons[PM_SHADE] && (!uarmf || !uarmf->blessed)) {
kickdieroll = rnd(20);
specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
if (mon->data == &mons[PM_SHADE] && !specialdmg) {
/* doesn't matter whether it would have hit or missed,
and shades have no passive counterattack */
Your("%s %s.", kick_passes_thru, mon_nam(mon));
break; /* skip any additional kicks */
} else if (tmp > (kickdieroll = rnd(20))) {
} else if (tmp > kickdieroll) {
You("kick %s.", mon_nam(mon));
sum = damageum(mon, uattk);
sum = damageum(mon, uattk, specialdmg);
(void) passive(mon, uarmf, (boolean) (sum > 0),
(sum != 2), AT_KICK, FALSE);
if (sum == 2)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1545430257 2018/12/21 22:10:57 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.276 $ */
/* NetHack 3.6 mon.c $NHDT-Date: 1548208236 2019/01/23 01:50:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.277 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1941,9 +1941,14 @@ register struct monst *mtmp;
if (mtmp->mhpmax <= 0)
mtmp->mhpmax = 10;
mtmp->mhp = mtmp->mhpmax;
/* this can happen if previously a fog cloud */
if (u.uswallow && (mtmp == u.ustuck))
expels(mtmp, mtmp->data, FALSE);
/* mtmp==u.ustuck can happen if previously a fog cloud
or poly'd hero is hugging a vampire bat */
if (mtmp == u.ustuck) {
if (u.uswallow)
expels(mtmp, mtmp->data, FALSE);
else
uunstick();
}
if (in_door) {
coord new_xy;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 polyself.c $NHDT-Date: 1547086249 2019/01/10 02:10:49 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.125 $ */
/* NetHack 3.6 polyself.c $NHDT-Date: 1548208238 2019/01/23 01:50:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.126 $ */
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -25,7 +25,6 @@ STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P));
STATIC_DCL void FDECL(polyman, (const char *, const char *));
STATIC_DCL void NDECL(break_armor);
STATIC_DCL void FDECL(drop_weapon, (int));
STATIC_DCL void NDECL(uunstick);
STATIC_DCL int FDECL(armor_to_dragon, (int));
STATIC_DCL void NDECL(newman);
STATIC_DCL void NDECL(polysense);
@@ -743,10 +742,14 @@ int mntmp;
}
newsym(u.ux, u.uy); /* Change symbol */
/* [note: this 'sticky' handling is only sufficient for changing from
grabber to engulfer or vice versa because engulfing by poly'd hero
always ends immediately so won't be in effect during a polymorph] */
if (!sticky && !u.uswallow && u.ustuck && sticks(g.youmonst.data))
u.ustuck = 0;
else if (sticky && !sticks(g.youmonst.data))
uunstick();
if (u.usteed) {
if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) {
pline("%s touch %s.", no_longer_petrify_resistant,
@@ -1537,9 +1540,13 @@ domindblast()
return 1;
}
STATIC_OVL void
void
uunstick()
{
if (!u.ustuck) {
impossible("uunstick: no ustuck?");
return;
}
pline("%s is no longer in your clutches.", Monnam(u.ustuck));
u.ustuck = 0;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1548125661 2019/01/22 02:54:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.202 $ */
/* NetHack 3.6 uhitm.c $NHDT-Date: 1548209742 2019/01/23 02:15:42 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.203 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -387,6 +387,7 @@ register struct monst *mtmp;
it uses g.bhitpos instead; it might map an invisible monster there */
g.bhitpos.x = u.ux + u.dx;
g.bhitpos.y = u.uy + u.dy;
notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
if (attack_checks(mtmp, uwep))
return TRUE;
@@ -681,6 +682,7 @@ int dieroll;
/* not grapnels; applied implies uwep */
|| (thrown == HMON_APPLIED && is_pole(uwep)));
int jousting = 0;
long silverhit = 0L;
int wtype;
struct obj *monwep;
char unconventional[BUFSZ]; /* substituted for word "attack" in msg */
@@ -698,23 +700,15 @@ int dieroll;
else
tmp = rnd(2);
valid_weapon_attack = (tmp > 1);
/* blessed gloves give bonuses when fighting 'bare-handed' */
if (uarmg && uarmg->blessed
&& (is_undead(mdat) || is_demon(mdat) || is_vampshifter(mon)))
tmp += rnd(4);
/* So do silver rings. Note: rings are worn under gloves, so you
* don't get both bonuses.
*/
if (!uarmg) {
if (uleft && objects[uleft->otyp].oc_material == SILVER)
barehand_silver_rings++;
if (uright && objects[uright->otyp].oc_material == SILVER)
barehand_silver_rings++;
if (barehand_silver_rings && mon_hates_silver(mon)) {
tmp += rnd(20);
silvermsg = TRUE;
}
}
/* Blessed gloves give bonuses when fighting 'bare-handed'. So do
silver rings. Note: rings are worn under gloves, so you don't
get both bonuses, and two silver rings don't give double bonus. */
tmp += special_dmgval(&youmonst, mon, (W_ARMG | W_RINGL | W_RINGR),
&silverhit);
barehand_silver_rings += (((silverhit & W_RINGL) ? 1 : 0)
+ ((silverhit & W_RINGR) ? 1 : 0));
if (barehand_silver_rings > 0)
silvermsg = TRUE;
} else {
if (!(artifact_light(obj) && obj->lamplit))
Strcpy(saved_oname, cxname(obj));
@@ -1566,9 +1560,10 @@ struct attack *mattk;
}
int
damageum(mdef, mattk)
damageum(mdef, mattk, specialdmg)
register struct monst *mdef;
register struct attack *mattk;
int specialdmg; /* blessed and/or silver bonus against various things */
{
register struct permonst *pd = mdef->data;
int armpro, tmp = d((int) mattk->damn, (int) mattk->damd);
@@ -1604,19 +1599,24 @@ register struct attack *mattk;
case AD_HEAL: /* likewise */
case AD_PHYS:
physical:
if (pd == &mons[PM_SHADE]) {
tmp = 0;
if (!specialdmg)
impossible("bad shade attack function flow?");
}
tmp += specialdmg;
if (mattk->aatyp == AT_WEAP) {
if (uwep)
tmp = 0;
} else if (mattk->aatyp == AT_KICK) {
/* hmonas() uses known_hitum() to deal physical damage,
then also damageum() for non-AD_PHYS; don't inflict
extra physical damage for unusual damage types */
tmp = 0;
} else if (mattk->aatyp == AT_KICK
|| mattk->aatyp == AT_CLAW
|| mattk->aatyp == AT_TUCH
|| mattk->aatyp == AT_HUGS) {
if (thick_skinned(pd))
tmp = 0;
if (pd == &mons[PM_SHADE]) {
if (!(uarmf && uarmf->blessed)) {
impossible("bad shade attack function flow?");
tmp = 0;
} else
tmp = rnd(4); /* bless damage */
}
tmp = (mattk->aatyp == AT_KICK) ? 0 : (tmp + 1) / 2;
/* add ring(s) of increase damage */
if (u.udaminc > 0) {
/* applies even if damage was 0 */
@@ -2117,7 +2117,7 @@ register struct attack *mattk;
}
/* Use up amulet of life saving */
if (!!(otmp = mlifesaver(mdef)))
if ((otmp = mlifesaver(mdef)) != 0)
m_useup(mdef, otmp);
newuhs(FALSE);
@@ -2279,9 +2279,20 @@ register struct monst *mon;
{
struct attack *mattk, alt_attk;
struct obj *weapon, **originalweapon;
boolean altwep = FALSE, weapon_used = FALSE;
boolean altwep = FALSE, weapon_used = FALSE, odd_claw = TRUE;
int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0;
int dieroll;
int dieroll, multi_claw = 0;
/* with just one touch/claw/weapon attack, both rings matter;
with more than one, alternate right and left when checking
whether silver ring causes successful hit */
for (i = 0; i < NATTK; i++) {
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
if (mattk->aatyp == AT_WEAP
|| mattk->aatyp == AT_CLAW || mattk->aatyp == AT_TUCH)
++multi_claw;
}
multi_claw = (multi_claw > 1); /* switch from count to yes/no */
for (i = 0; i < NATTK; i++) {
sum[i] = 0;
@@ -2289,7 +2300,9 @@ register struct monst *mon;
weapon = 0;
switch (mattk->aatyp) {
case AT_WEAP:
/* if (!uwep) goto weaponless; */
use_weapon:
odd_claw = !odd_claw; /* see case AT_CLAW,AT_TUCH below */
/* if we've already hit with a two-handed weapon, we don't
get to make another weapon attack (note: monsters who
use weapons do not have this restriction, but they also
@@ -2358,7 +2371,7 @@ register struct monst *mon;
}
/* Do not print "You hit" message; known_hitum already did it. */
if (dhit && mattk->adtyp != AD_SPEL && mattk->adtyp != AD_PHYS)
sum[i] = damageum(mon, mattk);
sum[i] = damageum(mon, mattk, 0);
break;
case AT_CLAW:
if (uwep && !cantwield(g.youmonst.data) && !weapon_used)
@@ -2373,73 +2386,189 @@ register struct monst *mon;
case AT_STNG:
case AT_BUTT:
case AT_TENT:
/*weaponless:*/
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
&attknum, &armorpenalty);
dieroll = rnd(20);
dhit = (tmp > dieroll || u.uswallow);
if (dhit) {
int compat;
int compat, specialdmg;
long silverhit = 0L;
const char *verb = 0; /* verb or body part */
if (!u.uswallow
&& (compat = could_seduce(&g.youmonst, mon, mattk))) {
&& (compat = could_seduce(&g.youmonst, mon, mattk)) != 0) {
You("%s %s %s.",
mon->mcansee && haseyes(mon->data) ? "smile at"
: "talk to",
(mon->mcansee && haseyes(mon->data)) ? "smile at"
: "talk to",
mon_nam(mon),
compat == 2 ? "engagingly" : "seductively");
(compat == 2) ? "engagingly" : "seductively");
/* doesn't anger it; no wakeup() */
sum[i] = damageum(mon, mattk);
sum[i] = damageum(mon, mattk, 0);
break;
}
wakeup(mon, TRUE);
/* maybe this check should be in damageum()? */
if (mon->data == &mons[PM_SHADE]
&& !(mattk->aatyp == AT_KICK && uarmf
&& uarmf->blessed)) {
Your("attack passes harmlessly through %s.",
mon_nam(mon));
specialdmg = 0; /* blessed and/or silver bonus */
switch (mattk->aatyp) {
case AT_CLAW:
case AT_TUCH:
/* verb=="claws" may be overridden below */
verb = (mattk->aatyp == AT_TUCH) ? "touch" : "claws";
/* decide if silver-hater will be hit by silver ring(s);
for 'multi_claw' where attacks alternate right/left,
assume 'even' claw or touch attacks use right hand
or paw, 'odd' ones use left for ring interaction;
even vs odd is based on actual attacks rather
than on index into mon->dat->mattk[] so that {bite,
claw,claw} instead of {claw,claw,bite} doesn't
make poly'd hero mysteriously become left-handed */
odd_claw = !odd_claw;
specialdmg = special_dmgval(&youmonst, mon,
W_ARMG
| ((odd_claw || !multi_claw)
? W_RINGL : 0L)
| ((!odd_claw || !multi_claw)
? W_RINGR : 0L),
&silverhit);
break;
case AT_TENT:
/* assumes mind flayer's tentacles-on-head rather
than sea monster's tentacle-as-arm */
verb = "tentacles";
break;
case AT_KICK:
verb = "kick";
specialdmg = special_dmgval(&youmonst, mon, W_ARMF,
&silverhit);
break;
case AT_BUTT:
verb = "head butt"; /* mbodypart(mon,HEAD)=="head" */
/* hypothetical; if any form with a head-butt attack
could wear a helmet, it would hit shades when
wearing a blessed (or silver) one */
specialdmg = special_dmgval(&youmonst, mon, W_ARMH,
&silverhit);
break;
case AT_BITE:
verb = "bite";
break;
case AT_STNG:
verb = "sting";
break;
default:
verb = "hit";
break;
}
if (mattk->aatyp == AT_KICK)
You("kick %s.", mon_nam(mon));
else if (mattk->aatyp == AT_BITE)
You("bite %s.", mon_nam(mon));
else if (mattk->aatyp == AT_STNG)
You("sting %s.", mon_nam(mon));
else if (mattk->aatyp == AT_BUTT)
You("butt %s.", mon_nam(mon));
else if (mattk->aatyp == AT_TUCH)
You("touch %s.", mon_nam(mon));
else if (mattk->aatyp == AT_TENT)
Your("tentacles suck %s.", mon_nam(mon));
else
You("hit %s.", mon_nam(mon));
sum[i] = damageum(mon, mattk);
} else {
if (mon->data == &mons[PM_SHADE] && !specialdmg) {
if (!strcmp(verb, "hit")
|| (mattk->aatyp == AT_CLAW && humanoid(mon->data)))
verb = "attack";
Your("%s %s harmlessly through %s.",
verb, vtense(verb, "pass"), mon_nam(mon));
} else {
if (mattk->aatyp == AT_TENT) {
Your("tentacles suck %s.", mon_nam(mon));
} else {
if (mattk->aatyp == AT_CLAW)
verb = "hit"; /* not "claws" */
You("%s %s.", verb, mon_nam(mon));
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
}
sum[i] = damageum(mon, mattk, specialdmg);
}
} else { /* !dhit */
missum(mon, mattk, (tmp + armorpenalty > dieroll));
}
break;
case AT_HUGS:
case AT_HUGS: {
int specialdmg;
long silverhit = 0L;
boolean byhand = hug_throttles(&mons[u.umonnum]), /* rope golem */
unconcerned = (byhand && !can_be_strangled(mon));
if (sticks(mon->data) || u.uswallow || notonhead
|| (byhand && (uwep || !has_head(mon->data)))) {
/* can't hold a holder due to subsequent ambiguity over
who is holding whom; can't hug engulfer from inside;
can't hug a worm tail (would immobilize entire worm!);
byhand: can't choke something that lacks a head;
not allowed to make a choking hug if wielding a weapon
(but might have grabbed w/o weapon, then wielded one,
and may even be attacking a different monster now) */
if (byhand && uwep && u.ustuck
&& !(sticks(u.ustuck->data) || u.uswallow))
uunstick();
continue; /* not 'break'; bypass passive counter-attack */
}
/* automatic if prev two attacks succeed, or if
* already grabbed in a previous attack
*/
already grabbed in a previous attack */
dhit = 1;
wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE])
Your("hug passes harmlessly through %s.", mon_nam(mon));
else if (!sticks(mon->data) && !u.uswallow) {
if (mon == u.ustuck) {
pline("%s is being %s.", Monnam(mon),
u.umonnum == PM_ROPE_GOLEM ? "choked" : "crushed");
sum[i] = damageum(mon, mattk);
} else if (i >= 2 && sum[i - 1] && sum[i - 2]) {
You("grab %s!", mon_nam(mon));
u.ustuck = mon;
sum[i] = damageum(mon, mattk);
/* choking hug/throttling grab uses hands (gloves or rings);
normal hug uses outermost of cloak/suit/shirt */
specialdmg = special_dmgval(&youmonst, mon,
byhand ? (W_ARMG | W_RINGL | W_RINGR)
: (W_ARMC | W_ARM | W_ARMU),
&silverhit);
if (unconcerned) {
/* strangling something which can't be strangled */
if (mattk != &alt_attk) {
alt_attk = *mattk;
mattk = &alt_attk;
}
/* change damage to 1d1; not strangling but still
doing [minimal] physical damage to victim's body */
mattk->damn = mattk->damd = 1;
/* don't give 'unconcerned' feedback if there is extra damage
or if it is nearly destroyed or if creature doesn't have
the mental ability to be concerned in the first place */
if (specialdmg || mindless(mon->data)
|| mon->mhp <= 1 + max(u.udaminc, 1))
unconcerned = FALSE;
}
break;
if (mon->data == &mons[PM_SHADE]) {
const char *verb = byhand ? "grasp" : "hug";
/* hugging a shade; successful if blessed outermost armor
for normal hug, or blessed gloves or silver ring(s) for
choking hug; deals damage but never grabs hold */
if (specialdmg) {
You("%s %s%s", verb, mon_nam(mon), exclam(specialdmg));
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
sum[i] = damageum(mon, mattk, specialdmg);
} else {
Your("%s passes harmlessly through %s.",
verb, mon_nam(mon));
}
break;
}
/* hug attack against ordinary foe */
if (mon == u.ustuck) {
pline("%s is being %s%s.", Monnam(mon),
byhand ? "throttled" : "crushed",
/* extra feedback for non-breather being choked */
unconcerned ? " but doesn't seem concerned" : "");
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
sum[i] = damageum(mon, mattk, specialdmg);
} else if (i >= 2 && sum[i - 1] && sum[i - 2]) {
/* in case we're hugging a new target while already
holding something else; yields feedback
"<u.ustuck> is no longer in your clutches" */
if (u.ustuck && u.ustuck != mon)
uunstick();
You("grab %s!", mon_nam(mon));
u.ustuck = mon;
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
sum[i] = damageum(mon, mattk, specialdmg);
}
break; /* AT_HUGS */
}
case AT_EXPL: /* automatic hit if next to */
dhit = -1;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 weapon.c $NHDT-Date: 1547025169 2019/01/09 09:12:49 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.68 $ */
/* NetHack 3.6 weapon.c $NHDT-Date: 1548209744 2019/01/23 02:15:44 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.69 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -350,6 +350,117 @@ struct monst *mon;
return tmp;
}
/* check whether blessed and/or silver damage applies for *non-weapon* hit;
return value is the amount of the extra damage */
int
special_dmgval(magr, mdef, armask, silverhit_p)
struct monst *magr, *mdef;
long armask; /* armor mask, multiple bits accepted for W_ARMC|W_ARM|W_ARMU
* or W_ARMG|W_RINGL|W_RINGR only */
long *silverhit_p; /* output flag mask for silver bonus */
{
struct obj *obj;
struct permonst *ptr = mdef->data;
boolean left_ring = (armask & W_RINGL) ? TRUE : FALSE,
right_ring = (armask & W_RINGR) ? TRUE : FALSE;
long silverhit = 0L;
int bonus = 0;
obj = 0;
if (armask & (W_ARMC | W_ARM | W_ARMU)) {
if ((armask & W_ARMC) != 0L
&& (obj = which_armor(magr, W_ARMC)) != 0)
armask = W_ARMC;
else if ((armask & W_ARM) != 0L
&& (obj = which_armor(magr, W_ARM)) != 0)
armask = W_ARM;
else if ((armask & W_ARMU) != 0L
&& (obj = which_armor(magr, W_ARMU)) != 0)
armask = W_ARMU;
else
armask = 0L;
} else if (armask & (W_ARMG | W_RINGL | W_RINGR)) {
armask = ((obj = which_armor(magr, W_ARMG)) != 0) ? W_ARMG : 0L;
} else {
obj = which_armor(magr, armask);
}
if (obj) {
if (obj->blessed
&& (is_undead(ptr) || is_demon(ptr) || is_vampshifter(mdef)))
bonus += rnd(4);
/* the only silver armor is shield of reflection (silver dragon
scales refer to color, not material) and the only way to hit
with one--aside from throwing--is to wield it and perform a
weapon hit, but we include a general check here */
if (objects[obj->otyp].oc_material == SILVER
&& mon_hates_silver(mdef)) {
bonus += rnd(20);
silverhit |= armask;
}
/* when no gloves we check for silver rings (blessed rings ignored) */
} else if ((left_ring || right_ring) && magr == &youmonst) {
if (left_ring && uleft) {
if (objects[uleft->otyp].oc_material == SILVER
&& mon_hates_silver(mdef)) {
bonus += rnd(20);
silverhit |= W_RINGL;
}
}
if (right_ring && uright) {
if (objects[uright->otyp].oc_material == SILVER
&& mon_hates_silver(mdef)) {
/* two silver rings don't give double silver damage
but 'silverhit' messages might be adjusted for them */
if (!(silverhit & W_RINGL))
bonus += rnd(20);
silverhit |= W_RINGR;
}
}
}
if (silverhit_p)
*silverhit_p = silverhit;
return bonus;
}
/* give a "silver <item> sears <target>" message;
not used for weapon hit, so we only handle rings */
void
silver_sears(magr, mdef, silverhit)
struct monst *magr UNUSED;
struct monst *mdef;
long silverhit;
{
char rings[20]; /* plenty of room for "rings" */
int ltyp = ((uleft && (silverhit & W_RINGL) != 0L)
? uleft->otyp : STRANGE_OBJECT),
rtyp = ((uright && (silverhit & W_RINGR) != 0L)
? uright->otyp : STRANGE_OBJECT);
boolean both,
l_ag = (objects[ltyp].oc_material == SILVER && uleft->dknown),
r_ag = (objects[rtyp].oc_material == SILVER && uright->dknown);
if ((silverhit & (W_RINGL | W_RINGR)) != 0L) {
/* plural if both the same type (so not multi_claw and both rings
are non-Null) and either both known or neither known, or both
silver (in case there is ever more than one type of silver ring)
and both known; singular if multi_claw (where one of ltyp or
rtyp will always be STRANGE_OBJECT) even if both rings are known
silver [see hmonas(uhitm.c) for explanation of 'multi_claw'] */
both = ((ltyp == rtyp && uleft->dknown == uright->dknown)
|| (l_ag && r_ag));
Sprintf(rings, "ring%s", both ? "s" : "");
Your("%s%s %s %s!",
(l_ag || r_ag) ? "silver "
: both ? ""
: ((silverhit & W_RINGL) != 0L) ? "left "
: "right ",
rings, vtense(rings, "sear"), mon_nam(mdef));
}
}
STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int));
#define Oselect(x) \
if ((otmp = oselect(mtmp, x)) != 0) \