Merge remote-tracking branch 'origin/NetHack-3.6.0'

This commit is contained in:
keni
2017-12-04 17:34:59 -05:00
38 changed files with 329 additions and 10840 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 explode.c $NHDT-Date: 1503355817 2017/08/21 22:50:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.50 $ */
/* NetHack 3.6 explode.c $NHDT-Date: 1511658058 2017/11/26 01:00:58 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -42,7 +42,8 @@ int expltype;
uchar adtyp;
int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
boolean shopdamage = FALSE, generic = FALSE, physical_dmg = FALSE,
do_hallu = FALSE, inside_engulfer;
do_hallu = FALSE, inside_engulfer, grabbed, grabbing;
coord grabxy;
char hallu_buf[BUFSZ];
short exploding_wand_typ = 0;
@@ -87,6 +88,30 @@ int expltype;
/* if hero is engulfed and caused the explosion, only hero and
engulfer will be affected */
inside_engulfer = (u.uswallow && type >= 0);
/* held but not engulfed implies holder is reaching into second spot
so might get hit by double damage */
grabbed = grabbing = FALSE;
if (u.ustuck && !u.uswallow) {
if (Upolyd && sticks(youmonst.data))
grabbing = TRUE;
else
grabbed = TRUE;
grabxy.x = u.ustuck->mx;
grabxy.y = u.ustuck->my;
} else
grabxy.x = grabxy.y = 0; /* lint suppression */
/* FIXME:
* It is possible for a grabber to be outside the explosion
* radius and reaching inside to hold the hero. If so, it ought
* to take damage (the extra half of double damage). It is also
* possible for poly'd hero to be outside the radius and reaching
* in to hold a monster. Hero should take damage in that situation.
*
* Probably the simplest way to handle this would be to expand
* the radius used when collecting targets but exclude everything
* beyond the regular radius which isn't reaching inside. Then
* skip harm to gear of any extended targets when inflicting damage.
*/
if (olet == MON_EXPLODE) {
str = killer.name;
@@ -401,8 +426,15 @@ int expltype;
pline("%s resists the %s!", Monnam(mtmp), str);
mdam = (dam + 1) / 2;
}
if (mtmp == u.ustuck)
/* if grabber is reaching into hero's spot and
hero's spot is within explosion radius, grabber
gets hit by double damage */
if (grabbed && mtmp == u.ustuck && distu(x, y) <= 2)
mdam *= 2;
/* being resistant to opposite type of damage makes
target more vulnerable to current type of damage
(when target is also resistant to current type,
we won't get here) */
if (resists_cold(mtmp) && adtyp == AD_FIRE)
mdam *= 2;
else if (resists_fire(mtmp) && adtyp == AD_COLD)
@@ -468,6 +500,13 @@ int expltype;
ugolemeffects((int) adtyp, damu);
if (uhurt == 2) {
/* if poly'd hero is grabbing another victim, hero takes
double damage (note: don't rely on u.ustuck here because
that victim might have been killed when hit by the blast) */
if (grabbing && dist2((int) grabxy.x, (int) grabxy.y, x, y) <= 2)
damu *= 2;
/* hero does not get same fire-resistant vs cold and
cold-resistant vs fire double damage as monsters [why not?] */
if (Upolyd)
u.mh -= damu;
else

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 invent.c $NHDT-Date: 1508827592 2017/10/24 06:46:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.220 $ */
/* NetHack 3.6 invent.c $NHDT-Date: 1512096431 2017/12/01 02:47:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.222 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -617,8 +617,7 @@ void
carry_obj_effects(obj)
struct obj *obj;
{
/* Cursed figurines can spontaneously transform
when carried. */
/* Cursed figurines can spontaneously transform when carried. */
if (obj->otyp == FIGURINE) {
if (obj->cursed && obj->corpsenm != NON_PM
&& !dead_species(obj->corpsenm, TRUE)) {
@@ -1473,6 +1472,9 @@ redo_menu:
else if (otmp->otyp == LOADSTONE && otmp->cursed)
/* kludge for canletgo()'s can't-drop-this message */
otmp->corpsenm = (int) cnt;
} else if (!strcmp(word, "adjust")) {
/* specifying stack's full count means something to #adjust */
otmp->nomerge = 1;
}
}
return otmp;
@@ -3568,7 +3570,7 @@ doorganize() /* inventory organizer by Del Lamb */
char qbuf[QBUFSZ];
char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
const char *adj_type;
boolean ever_mind = FALSE;
boolean ever_mind = FALSE, dont_collect = FALSE;
if (!invent) {
You("aren't carrying anything to adjust.");
@@ -3600,12 +3602,19 @@ doorganize() /* inventory organizer by Del Lamb */
/* figure out whether user gave a split count to getobj() */
splitting = bumped = 0;
for (otmp = invent; otmp; otmp = otmp->nobj)
if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
if (otmp->invlet == obj->invlet)
splitting = otmp;
break;
}
if (obj->nomerge) {
/* player specified full count; no split occurred and we'll
avoid collecting compatible stacks when moving this one */
obj->nomerge = 0;
dont_collect = TRUE;
} else {
for (otmp = invent; otmp; otmp = otmp->nobj)
if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
if (otmp->invlet == obj->invlet)
splitting = otmp;
break;
}
}
/* initialize the list with all lower and upper case letters */
lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
@@ -3659,7 +3668,7 @@ doorganize() /* inventory organizer by Del Lamb */
/* adjusting to same slot is meaningful since all
compatible stacks get collected along the way,
but splitting to same slot is not */
|| (splitting && let == obj->invlet)) {
|| ((splitting || dont_collect) && let == obj->invlet)) {
noadjust:
if (splitting)
(void) merged(&splitting, &obj);
@@ -3692,7 +3701,7 @@ doorganize() /* inventory organizer by Del Lamb */
extract_nobj(obj, &invent);
for (otmp = invent; otmp;) {
if (!splitting) {
if (!splitting && !dont_collect) {
if (merged(&otmp, &obj)) {
adj_type = "Merging:";
obj = otmp;
@@ -3730,7 +3739,7 @@ doorganize() /* inventory organizer by Del Lamb */
if (merged(&otmp, &obj)) {
obj = otmp;
extract_nobj(obj, &invent);
} else if (inv_cnt(FALSE) >= 52) {
} else if (inv_cnt(FALSE) >= 52 && !dont_collect) {
(void) merged(&splitting, &obj); /* undo split */
/* "knapsack cannot accommodate any more items" */
Your("pack is too full.");

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mklev.c $NHDT-Date: 1446191876 2015/10/30 07:57:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
/* NetHack 3.6 mklev.c $NHDT-Date: 1511681724 2017/11/26 07:35:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1256,6 +1256,7 @@ struct mkroom *croom;
coord *tm;
{
register int kind;
unsigned lvl = level_difficulty();
coord m;
/* no traps in pools */
@@ -1292,8 +1293,6 @@ coord *tm;
/* bias the frequency of fire traps in Gehennom */
kind = FIRE_TRAP;
} else {
unsigned lvl = level_difficulty();
do {
kind = rnd(TRAPNUM - 1);
/* reject "too hard" traps */
@@ -1348,9 +1347,9 @@ coord *tm;
if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz))
kind = ROCKTRAP;
if (tm)
if (tm) {
m = *tm;
else {
} else {
register int tryct = 0;
boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT
|| kind == TRAPDOOR || kind == HOLE);
@@ -1369,6 +1368,133 @@ coord *tm;
(void) maketrap(m.x, m.y, kind);
if (kind == WEB)
(void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
/* The hero isn't the only person who's entered the dungeon in
search of treasure. On the very shallowest levels, there's a
chance that a created trap will have killed something already
(and this is guaranteed on the first level).
This isn't meant to give any meaningful treasure (in fact, any
items we drop here are typically cursed, other than ammo fired
by the trap). Rather, it's mostly just for flavour and to give
players on very early levels a sufficient chance to avoid traps
that may end up killing them before they have a fair chance to
build max HP. Including cursed items gives the same fair chance
to the starting pet, and fits the rule that possessions of the
dead are normally cursed.
Some types of traps are excluded because they're entirely
nonlethal, even indirectly. We also exclude all of the
later/fancier traps because they tend to have special
considerations (e.g. webs, portals), often are indirectly
lethal, and tend not to generate on shallower levels anyway.
Finally, pits are excluded because it's weird to see an item
in a pit and yet not be able to identify that the pit is there. */
if (lvl <= (unsigned) rnd(4)
&& kind != SQKY_BOARD && kind != RUST_TRAP
&& kind != PIT && kind != SPIKED_PIT && kind < HOLE) {
/* Object generated by the trap; initially NULL, stays NULL if
we fail to generate an object or if the trap doesn't
generate objects. */
struct obj *otmp = NULL;
int victim_mnum; /* race of the victim */
/* Not all trap types have special handling here; only the ones
that kill in a specific way that's obvious after the fact. */
switch (kind) {
case ARROW_TRAP:
otmp = mksobj(ARROW, TRUE, FALSE);
otmp->opoisoned = 0;
/* don't adjust the quantity; maybe the trap shot multiple
times, there was an untrapping attempt, etc... */
break;
case DART_TRAP:
otmp = mksobj(DART, TRUE, FALSE);
break;
case ROCKTRAP:
otmp = mksobj(ROCK, TRUE, FALSE);
break;
default:
/* no item dropped by the trap */
break;
}
if (otmp) {
place_object(otmp, m.x, m.y);
}
/* now otmp is reused for other items we're placing */
/* Place a random possession. This could be a weapon, tool,
food, or gem, i.e. the item classes that are typically
nonmagical and not worthless. */
do {
int poss_class = RANDOM_CLASS; /* init => lint suppression */
switch (rn2(4)) {
case 0:
poss_class = WEAPON_CLASS;
break;
case 1:
poss_class = TOOL_CLASS;
break;
case 2:
poss_class = FOOD_CLASS;
break;
case 3:
poss_class = GEM_CLASS;
break;
}
otmp = mkobj(poss_class, FALSE);
/* these items are always cursed, both for flavour (owned
by a dead adventurer, bones-pile-style) and for balance
(less useful to use, and encourage pets to avoid the trap) */
if (otmp) {
otmp->blessed = 0;
otmp->cursed = 1;
otmp->owt = weight(otmp);
place_object(otmp, m.x, m.y);
}
/* 20% chance of placing an additional item, recursively */
} while (!rn2(5));
/* Place a corpse. */
switch (rn2(15)) {
case 0:
/* elf corpses are the rarest as they're the most useful */
victim_mnum = PM_ELF;
break;
case 1: case 2:
victim_mnum = PM_DWARF;
break;
case 3: case 4: case 5:
victim_mnum = PM_ORC;
break;
case 6: case 7: case 8: case 9:
/* more common as they could have come from the Mines */
victim_mnum = PM_GNOME;
/* 10% chance of a candle too */
if (!rn2(10)) {
otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
TRUE, FALSE);
otmp->quan = 1;
otmp->blessed = 0;
otmp->cursed = 1;
otmp->owt = weight(otmp);
place_object(otmp, m.x, m.y);
}
break;
default:
/* the most common race */
victim_mnum = PM_HUMAN;
break;
}
otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
CORPSTAT_INIT);
if (otmp)
otmp->age -= 51; /* died too long ago to eat */
}
}
void