Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2018-09-20 18:45:37 -04:00
68 changed files with 765 additions and 294 deletions
+3 -4
View File
@@ -599,8 +599,7 @@ drag:
|| !is_pool(uball->ox, uball->oy)
|| levl[uball->ox][uball->oy].typ == POOL))
|| ((t = t_at(uchain->ox, uchain->oy))
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT || t->ttyp == HOLE
|| t->ttyp == TRAPDOOR))) {
&& (is_pit(t->ttyp) || is_hole(t->ttyp)))) {
if (Levitation) {
You_feel("a tug from the iron ball.");
if (t)
@@ -745,8 +744,8 @@ xchar x, y;
if (!Levitation && !MON_AT(x, y) && !u.utrap
&& (is_pool(x, y)
|| ((t = t_at(x, y))
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT
|| t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) {
&& (is_pit(t->ttyp)
|| is_hole(t->ttyp))))) {
u.ux = x;
u.uy = y;
} else {
+1
View File
@@ -57,6 +57,7 @@ NEARDATA char pl_fruit[PL_FSIZ] = DUMMY;
NEARDATA struct fruit *ffruit = (struct fruit *) 0;
NEARDATA char tune[6] = DUMMY;
NEARDATA boolean ransacked = 0;
const char *occtxt = DUMMY;
const char quitchars[] = " \r\n\033";
+7 -9
View File
@@ -312,8 +312,7 @@ dig(VOID_ARGS)
}
if (context.digging.effort <= 50
|| (ttmp && (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == PIT
|| ttmp->ttyp == SPIKED_PIT))) {
|| (ttmp && (ttmp->ttyp == TRAPDOOR || is_pit(ttmp->ttyp)))) {
return 1;
} else if (ttmp && (ttmp->ttyp == LANDMINE
|| (ttmp->ttyp == BEAR_TRAP && !u.utrap))) {
@@ -803,7 +802,7 @@ coord *cc;
}
} else if ((boulder_here = sobj_at(BOULDER, dig_x, dig_y)) != 0) {
if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)
if (ttmp && is_pit(ttmp->ttyp)
&& rn2(2)) {
pline_The("boulder settles into the %spit.",
(dig_x != u.ux || dig_y != u.uy) ? "adjacent " : "");
@@ -1087,7 +1086,7 @@ struct obj *obj;
KILLED_BY);
} else if (u.utrap && u.utraptype == TT_PIT && trap
&& (trap_with_u = t_at(u.ux, u.uy))
&& (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
&& is_pit(trap->ttyp)
&& !conjoined_pits(trap, trap_with_u, FALSE)) {
int idx;
@@ -1462,8 +1461,7 @@ zap_dig()
struct trap *adjpit = t_at(zx, zy);
if ((diridx < 8) && !conjoined_pits(adjpit, trap_with_u, FALSE)) {
digdepth = 0; /* limited to the adjacent location only */
if (!(adjpit && (adjpit->ttyp == PIT
|| adjpit->ttyp == SPIKED_PIT))) {
if (!(adjpit && is_pit(adjpit->ttyp))) {
char buf[BUFSZ];
cc.x = zx;
cc.y = zy;
@@ -1477,7 +1475,7 @@ zap_dig()
}
}
if (adjpit
&& (adjpit->ttyp == PIT || adjpit->ttyp == SPIKED_PIT)) {
&& is_pit(adjpit->ttyp)) {
int adjidx = (diridx + 4) % 8;
trap_with_u->conjoined |= (1 << diridx);
adjpit->conjoined |= (1 << adjidx);
@@ -1566,7 +1564,7 @@ zap_dig()
if (pitflow && isok(flow_x, flow_y)) {
struct trap *ttmp = t_at(flow_x, flow_y);
if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)) {
if (ttmp && is_pit(ttmp->ttyp)) {
schar filltyp = fillholetyp(ttmp->tx, ttmp->ty, TRUE);
if (filltyp != ROOM)
pit_flow(ttmp, filltyp);
@@ -1681,7 +1679,7 @@ struct trap *trap;
schar filltyp;
{
if (trap && (filltyp != ROOM)
&& (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
&& is_pit(trap->ttyp)) {
struct trap t;
int idx;
+1 -1
View File
@@ -783,7 +783,7 @@ register int x, y;
/* if monster is in a physical trap, you see the trap too
*/
if (tt == BEAR_TRAP || tt == PIT || tt == SPIKED_PIT
if (tt == BEAR_TRAP || is_pit(tt)
|| tt == WEB) {
trap->tseen = TRUE;
}
+2 -3
View File
@@ -149,8 +149,7 @@ const char *verb;
if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE)) {
return TRUE;
} else if (obj->otyp == BOULDER && (t = t_at(x, y)) != 0
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT
|| t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
&& (is_pit(t->ttyp) || is_hole(t->ttyp))) {
if (((mtmp = m_at(x, y)) && mtmp->mtrapped)
|| (u.utrap && u.ux == x && u.uy == y)) {
if (*verb)
@@ -956,7 +955,7 @@ dodown()
if (trap && uteetering_at_seen_pit(trap)) {
dotrap(trap, TOOKPLUNGE);
return 1;
} else if (!trap || (trap->ttyp != TRAPDOOR && trap->ttyp != HOLE)
} else if (!trap || !is_hole(trap->ttyp)
|| !Can_fall_thru(&u.uz) || !trap->tseen) {
if (flags.autodig && !context.nopick && uwep && is_pick(uwep)) {
return use_pick_axe2(uwep);
+45 -7
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 do_name.c $NHDT-Date: 1519420054 2018/02/23 21:07:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.128 $ */
/* NetHack 3.6 do_name.c $NHDT-Date: 1537477563 2018/09/20 21:06:03 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.132 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -543,7 +543,7 @@ int cx, cy;
cc.x = cx;
cc.y = cy;
if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch, (struct permonst **)0)) {
(void) coord_desc(cx, cy, tmpbuf, iflags.getpos_coords);
custompline(SUPPRESS_HISTORY,
"%s%s%s%s%s", firstmatch, *tmpbuf ? " " : "", tmpbuf,
@@ -593,7 +593,8 @@ int gloc;
any.a_int = i + 1;
tmpcc.x = garr[i].x;
tmpcc.y = garr[i].y;
if (do_screen_description(tmpcc, TRUE, sym, tmpbuf, &firstmatch)) {
if (do_screen_description(tmpcc, TRUE, sym, tmpbuf,
&firstmatch, (struct permonst **)0)) {
(void) coord_desc(garr[i].x, garr[i].y, tmpbuf,
iflags.getpos_coords);
Sprintf(fullbuf, "%s%s%s", firstmatch,
@@ -1699,10 +1700,7 @@ boolean called;
if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind
&& !Hallucination)
Strcat(buf, "saddled ");
if (buf[0] != 0)
has_adjectives = TRUE;
else
has_adjectives = FALSE;
has_adjectives = (buf[0] != '\0');
/* Put the actual monster name or type into the buffer now */
/* Be sure to remember whether the buffer starts with a name */
@@ -2067,6 +2065,46 @@ char *buf;
return buf;
}
char *
rndorcname(s)
char *s;
{
int i;
const char *v[] = {"a", "ai", "og", "u"};
const char *snd[] = {"gor", "gris", "un", "bane", "ruk",
"oth","ul", "z", "thos","akh","hai"};
int vstart = rn2(2);
if (s) {
*s = '\0';
for (i = 0; i < rn2(2) + 3; ++i) {
vstart = 1 - vstart; /* 0 -> 1, 1 -> 0 */
if (!rn2(30) && i > 0)
(void) strcat(s, "-");
(void) sprintf(eos(s), "%s", vstart ? v[rn2(SIZE(v))] :
snd[rn2(SIZE(snd))]);
}
}
return s;
}
struct monst *
christen_orc(mtmp, gang)
struct monst *mtmp;
char *gang;
{
int sz = 0;
char buf[BUFSZ], buf2[BUFSZ], *orcname;
orcname = rndorcname(buf2);
sz = (int) (strlen(gang) + strlen(orcname) + sizeof " of " - sizeof "");
if (gang && orcname && sz < BUFSZ) {
Sprintf(buf, "%s of %s", upstart(orcname), upstart(gang));
mtmp = christen_monst(mtmp, buf);
}
return mtmp;
}
/* make sure "The Colour of Magic" remains the first entry in here */
static const char *const sir_Terry_novels[] = {
"The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
+6
View File
@@ -407,6 +407,12 @@ boolean with_you;
break;
}
if ((mtmp->mspare1 & MIGR_LEFTOVERS) != 0L) {
/* Pick up the rest of the MIGR_TO_SPECIES objects */
if (migrating_objs)
deliver_obj_to_mon(mtmp, DF_ALL);
}
if (xlocale && wander) {
/* monster moved a bit; pick a nearby location */
/* mnearto() deals w/stone, et al */
+48 -3
View File
@@ -495,7 +495,7 @@ xchar x, y;
return 0;
if ((trap = t_at(x, y)) != 0) {
if (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && !Passes_walls)
if ((is_pit(trap->ttyp) && !Passes_walls)
|| trap->ttyp == WEB) {
if (!trap->tseen)
find_trap(trap);
@@ -1515,7 +1515,7 @@ boolean shop_floor_obj;
/* boulders never fall through trap doors, but they might knock
other things down before plugging the hole */
if (otmp->otyp == BOULDER && ((t = t_at(x, y)) != 0)
&& (t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
&& is_hole(t->ttyp)) {
if (impact)
impact_drop(otmp, x, y, 0);
return FALSE; /* let caller finish the drop */
@@ -1612,6 +1612,9 @@ boolean near_hero;
continue;
where = (int) (otmp->owornmask & 0x7fffL); /* destination code */
if ((where & MIGR_TO_SPECIES) != 0)
continue;
nobreak = (where & MIGR_NOBREAK) != 0;
noscatter = (where & MIGR_WITH_HERO) != 0;
where &= ~(MIGR_NOBREAK | MIGR_NOSCATTER);
@@ -1667,6 +1670,48 @@ boolean near_hero;
}
}
void
deliver_obj_to_mon(mtmp, deliverflags)
struct monst *mtmp;
unsigned long deliverflags;
{
struct obj *otmp, *otmp2;
int where, cnt = 0, maxobj = 0;
if (deliverflags & DF_RANDOM3)
maxobj = rn2(3) + 1;
else if (deliverflags & DF_RANDOM2)
maxobj = rn2(2) + 1;
else if (deliverflags == DF_NONE)
maxobj = 1;
for (otmp = migrating_objs; otmp; otmp = otmp2) {
otmp2 = otmp->nobj;
where = (int) (otmp->owornmask & 0x7fffL); /* destination code */
if ((where & MIGR_TO_SPECIES) == 0)
continue;
if ((mtmp->data->mflags2 & otmp->corpsenm) != 0) {
obj_extract_self(otmp);
otmp->owornmask = 0L;
otmp->ox = otmp->oy = 0;
/* special treatment for orcs and their kind */
if ((otmp->corpsenm & M2_ORC) != 0 && has_oname(otmp)) {
if (!has_mname(mtmp))
mtmp = christen_orc(mtmp, ONAME(otmp));
free_oname(otmp);
}
otmp->corpsenm = 0;
(void) add_to_minv(mtmp, otmp);
cnt++;
if (maxobj && cnt >= maxobj)
break;
/* getting here implies DF_ALL */
}
}
}
STATIC_OVL void
otransit_msg(otmp, nodrop, num)
register struct obj *otmp;
@@ -1717,7 +1762,7 @@ xchar x, y;
}
if (((ttmp = t_at(x, y)) != 0 && ttmp->tseen)
&& (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE)) {
&& is_hole(ttmp->ttyp)) {
gate_str = (ttmp->ttyp == TRAPDOOR) ? "through the trap door"
: "through the hole";
return MIGR_RANDOM;
+1 -2
View File
@@ -744,8 +744,7 @@ int x, y;
dotrap(ttmp, 0); /* doesn't print messages */
} else if (ttmp->ttyp == FIRE_TRAP) {
dotrap(ttmp, 0);
} else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT
|| ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR)
} else if ((is_pit(ttmp->ttyp) || is_hole(ttmp->ttyp))
&& Sokoban) {
/* air currents overcome the recoil in Sokoban;
when jumping, caller performs last step and enters trap */
+1 -1
View File
@@ -1280,7 +1280,7 @@ int how;
if (WIN_INVEN != WIN_ERR) {
destroy_nhwindow(WIN_INVEN), WIN_INVEN = WIN_ERR;
/* precaution in case any late update_inventory() calls occur */
flags.perm_invent = 0;
iflags.perm_invent = 0;
}
display_nhwindow(WIN_MESSAGE, TRUE);
destroy_nhwindow(WIN_MAP), WIN_MAP = WIN_ERR;
+4 -5
View File
@@ -151,8 +151,7 @@ moverock()
if (mtmp && !noncorporeal(mtmp->data)
&& (!mtmp->mtrapped
|| !(ttmp && ((ttmp->ttyp == PIT)
|| (ttmp->ttyp == SPIKED_PIT))))) {
|| !(ttmp && is_pit(ttmp->ttyp)))) {
if (Blind)
feel_location(sx, sy);
if (canspotmon(mtmp)) {
@@ -1205,7 +1204,7 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
break;
case TT_PIT:
if (desttrap && desttrap->tseen
&& (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
&& is_pit(desttrap->ttyp))
return TRUE; /* move into adjacent pit */
/* try to escape; position stays same regardless of success */
climb_pit();
@@ -1736,7 +1735,7 @@ domove()
u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
&& (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
&& is_pit(trap->ttyp)
&& sobj_at(BOULDER, trap->tx, trap->ty)) {
/* can't swap places with pet pinned in a pit by a boulder */
u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
@@ -2100,7 +2099,7 @@ boolean pick;
* If not a pit, pickup before triggering trap.
* If pit, trigger trap before pickup.
*/
pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
pit = (trap && is_pit(trap->ttyp));
if (pick && !pit)
(void) pickup(1);
+3 -3
View File
@@ -2511,7 +2511,7 @@ long *out_cnt;
if (lets && !*lets)
lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
if (flags.perm_invent && (lets || xtra_choice)) {
if (iflags.perm_invent && (lets || xtra_choice)) {
/* partial inventory in perm_invent setting; don't operate on
full inventory window, use an alternate one instead; create
the first time needed and keep it for re-use as needed later */
@@ -2536,7 +2536,7 @@ long *out_cnt;
* more than 1; for the last one, we don't need a precise number.
* For perm_invent update we force 'more than 1'.
*/
n = (flags.perm_invent && !lets && !want_reply) ? 2
n = (iflags.perm_invent && !lets && !want_reply) ? 2
: lets ? (int) strlen(lets)
: !invent ? 0 : !invent->nobj ? 1 : 2;
/* for xtra_choice, there's another 'item' not included in initial 'n';
@@ -2670,7 +2670,7 @@ nextclass:
nothing has been listed (because there isn't anyhing to list;
recognized via any.a_char still being zero; the n==0 case above
gets skipped for perm_invent), put something into the menu */
if (flags.perm_invent && !lets && !any.a_char) {
if (iflags.perm_invent && !lets && !any.a_char) {
any = zeroany;
add_menu(win, NO_GLYPH, &any, 0, 0, 0,
not_carrying_anything, MENU_UNSELECTED);
+5 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 makemon.c $NHDT-Date: 1495237801 2017/05/19 23:50:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */
/* NetHack 3.6 makemon.c $NHDT-Date: 1537477761 2018/09/20 21:09:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.124 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1390,6 +1390,9 @@ int mmflags;
mtmp->mstrategy |= STRAT_APPEARMSG;
}
if (allow_minvent && migrating_objs)
deliver_obj_to_mon(mtmp, DF_RANDOM2); /* in case there's waiting items */
if (!in_mklev)
newsym(mtmp->mx, mtmp->my); /* make sure the mon shows up */
@@ -1835,7 +1838,7 @@ struct monst *mtmp, *victim;
slightly less sexist if prepared for it...) */
: (fem && !mtmp->female) ? "female " : "",
ptr->mname);
pline("%s %s %s.", Monnam(mtmp),
pline("%s %s %s.", upstart(y_monnam(mtmp)),
(fem != mtmp->female) ? "changes into"
: humanoid(ptr) ? "becomes"
: "grows up into",
+3
View File
@@ -1266,6 +1266,9 @@ register struct attack *mattk;
mwepgone(mdef);
otmp->owornmask = 0L;
update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
/* give monster a chance to wear other equipment on its next
move instead of waiting until it picks something up */
mdef->misc_worn_check |= I_SPECIAL;
}
/* add_to_minv() might free otmp [if it merges] */
if (vis)
+1 -1
View File
@@ -1744,7 +1744,7 @@ struct attack *mattk;
if (!engulf_target(mtmp, &youmonst))
return 0;
if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)))
if ((t && is_pit(t->ttyp))
&& sobj_at(BOULDER, u.ux, u.uy))
return 0;
+4 -6
View File
@@ -503,8 +503,7 @@ int trap_type;
if (trap_type || !rn2(4)) {
rm->typ = SCORR;
if (trap_type) {
if ((trap_type == HOLE || trap_type == TRAPDOOR)
&& !Can_fall_thru(&u.uz))
if (is_hole(trap_type) && !Can_fall_thru(&u.uz))
trap_type = ROCKTRAP;
ttmp = maketrap(xx, yy + dy, trap_type);
if (ttmp) {
@@ -1345,15 +1344,14 @@ coord *tm;
} while (kind == NO_TRAP);
}
if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz))
if (is_hole(kind) && !Can_fall_thru(&u.uz))
kind = ROCKTRAP;
if (tm) {
m = *tm;
} else {
register int tryct = 0;
boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT
|| kind == TRAPDOOR || kind == HOLE);
boolean avoid_boulder = (is_pit(kind) || is_hole(kind));
do {
if (++tryct > 200)
@@ -1393,7 +1391,7 @@ coord *tm;
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) {
&& !is_pit(kind) && 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. */
+151 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1518718417 2018/02/15 18:13:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.55 $ */
/* NetHack 3.6 mkmaze.c $NHDT-Date: 1537477570 2018/09/20 21:06:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.61 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -30,6 +30,10 @@ STATIC_DCL boolean FDECL(put_lregion_here, (XCHAR_P, XCHAR_P, XCHAR_P,
STATIC_DCL void NDECL(baalz_fixup);
STATIC_DCL void NDECL(setup_waterlevel);
STATIC_DCL void NDECL(unsetup_waterlevel);
STATIC_DCL void FDECL(check_ransacked, (char *));
STATIC_DCL void FDECL(migr_booty_item, (int, const char *));
STATIC_DCL void FDECL(migrate_orc, (struct monst *, unsigned long));
STATIC_DCL void NDECL(stolen_booty);
#ifdef CONWAY
STATIC_DCL void NDECL(conway_setup);
@@ -619,6 +623,8 @@ fixup_special()
} else if (on_level(&u.uz, &baalzebub_level)) {
/* custom wallify the "beetle" potion of the level */
baalz_fixup();
} else if (u.uz.dnum == mines_dnum && ransacked) {
stolen_booty();
}
#ifdef CONWAY
if (level.flags.conway) {
@@ -631,6 +637,149 @@ fixup_special()
num_lregions = 0;
}
void
check_ransacked(s)
char *s;
{
/* this kludge only works as long as orctown is minetn-1 */
ransacked = (u.uz.dnum == mines_dnum && !strcmp(s, "minetn-1"));
}
#define ORC_LEADER 1
void
migrate_orc(mtmp, mflags)
struct monst *mtmp;
unsigned long mflags;
{
int nlev, max_depth, cur_depth;
d_level dest;
cur_depth = (int) depth(&u.uz);
max_depth = dunlevs_in_dungeon(&u.uz) +
(dungeons[u.uz.dnum].depth_start - 1);
if (mflags == ORC_LEADER) {
/* Note that the orc leader will take possession of any
* remaining stuff not already delivered to other
* orcs between here and the bottom of the mines.
*/
nlev = max_depth;
mtmp->mspare1 = MIGR_LEFTOVERS;
} else {
nlev = rn2(max_depth - cur_depth) + cur_depth + 1;
if (nlev == cur_depth)
nlev++;
if (nlev > max_depth)
nlev = max_depth;
mtmp->mspare1 = 0L;
}
get_level(&dest, nlev);
migrate_to_level(mtmp, ledger_no(&dest), MIGR_RANDOM, (coord *) 0);
}
void
migr_booty_item(otyp, gang)
int otyp;
const char *gang;
{
struct obj *otmp;
otmp = mksobj_migr_to_species(otyp, (unsigned long) M2_ORC, FALSE, FALSE);
if (otmp && gang) {
new_oname(otmp, strlen(gang) + 1); /* removes old name if one is present */
Strcpy(ONAME(otmp), gang);
if (otyp >= TRIPE_RATION && otyp <= TIN)
otmp->quan += (long) rn2(3);
}
}
void
stolen_booty(VOID_ARGS)
{
char *gang, gang_name[BUFSZ];
struct monst *mtmp;
int cnt, i, otyp;
/*
* --------------------------------------------------------
* Mythos:
*
* A tragic accident has occurred in Frontier Town...
* It has been overrun by orcs.
*
* The booty that the orcs took from the town is now
* in the possession of the orcs that did this and
* have long since fled the level.
* --------------------------------------------------------
*/
gang = rndorcname(gang_name);
/* create the leader of the orc gang */
mtmp = makemon(&mons[PM_ORC_CAPTAIN], 0, 0, MM_NONAME);
if (mtmp) {
mtmp = christen_monst(mtmp, upstart(gang));
mtmp->mpeaceful = 0;
migrate_orc(mtmp, ORC_LEADER);
}
/* create the stuff that the rest of the gang took */
migr_booty_item(rn2(2) ? LONG_SWORD : SILVER_SABER, gang);
cnt = rn2(3) + 1;
for (i = 0; i < cnt; ++i)
migr_booty_item(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE, gang);
cnt = rn2(2) + 1;
for (i = 0; i < cnt; ++i)
migr_booty_item(SKELETON_KEY, gang);
otyp = rn2((GAUNTLETS_OF_DEXTERITY - LEATHER_GLOVES) + 1) + LEATHER_GLOVES;
migr_booty_item(otyp, gang);
cnt = rn2(9) + 1;
for (i = 0; i < cnt; ++i) {
/* Food items - but no lembas! (or some other weird things) */
otyp = rn2((TIN - TRIPE_RATION) + 1) + TRIPE_RATION;
if (otyp != LEMBAS_WAFER && otyp != GLOB_OF_GRAY_OOZE &&
otyp != GLOB_OF_BROWN_PUDDING && otyp != GLOB_OF_GREEN_SLIME &&
otyp != GLOB_OF_BLACK_PUDDING && otyp != MEAT_STICK &&
otyp != MEATBALL && otyp != MEAT_STICK && otyp != MEAT_RING &&
otyp != HUGE_CHUNK_OF_MEAT && otyp != CORPSE)
migr_booty_item(otyp, gang);
}
/* Make most of the orcs on the level be part of the invading gang */
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
if (is_orc(mtmp->data) && !has_mname(mtmp) && rn2(10)) {
/*
* We'll consider the orc captain from the level
* .des file to be the captain of a rival orc horde
* who is there to see what has transpired, and to
* contemplate future action.
*
* Don't christen the orc captain as a subordinate
* member of the main orc horde.
*/
if (mtmp->data != &mons[PM_ORC_CAPTAIN])
mtmp = christen_orc(mtmp, upstart(gang));
}
}
/* Lastly, ensure there's several more orcs from the gang along the way.
* The mechanics are such that they aren't actually identified as
* members of the invading gang until they get their spoils assigned
* to the inventory; handled during that assignment.
*/
cnt = rn2(7) + 5;
for (i = 0; i < cnt; ++i) {
int mtyp;
mtyp = rn2((PM_ORC_SHAMAN - PM_ORC) + 1) + PM_ORC;
mtmp = makemon(&mons[mtyp], 0, 0, MM_NONAME);
if (mtmp)
migrate_orc(mtmp, 0UL);
}
ransacked = 0;
}
#undef ORC_LEADER
boolean
maze_inbounds(x, y)
int x, y;
@@ -833,6 +982,7 @@ const char *s;
}
if (*protofile) {
check_ransacked(protofile);
Strcat(protofile, LEV_EXT);
if (load_special(protofile)) {
/* some levels can end up with monsters
+17
View File
@@ -224,6 +224,23 @@ boolean init, artif;
return otmp;
}
struct obj *
mksobj_migr_to_species(otyp, mflags2, init, artif)
int otyp;
unsigned mflags2;
boolean init, artif;
{
struct obj *otmp;
otmp = mksobj(otyp, init, artif);
if (otmp) {
add_to_migration(otmp);
otmp->owornmask = (long) MIGR_TO_SPECIES;
otmp->corpsenm = mflags2;
}
return otmp;
}
/* mkobj(): select a type of item from a class, use mksobj() to create it */
struct obj *
mkobj(oclass, artif)
+33 -12
View File
@@ -731,6 +731,17 @@ movemon()
if (minliquid(mtmp))
continue;
/* after losing equipment, try to put on replacement */
if (mtmp->misc_worn_check & I_SPECIAL) {
long oldworn;
mtmp->misc_worn_check &= ~I_SPECIAL;
oldworn = mtmp->misc_worn_check;
m_dowear(mtmp, FALSE);
if (mtmp->misc_worn_check != oldworn || !mtmp->mcanmove)
continue;
}
if (is_hider(mtmp->data)) {
/* unwatched mimics and piercers may hide again [MRS] */
if (restrap(mtmp))
@@ -1435,8 +1446,7 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
if ((ttmp->ttyp != RUST_TRAP
|| mdat == &mons[PM_IRON_GOLEM])
&& ttmp->ttyp != STATUE_TRAP
&& ((ttmp->ttyp != PIT && ttmp->ttyp != SPIKED_PIT
&& ttmp->ttyp != TRAPDOOR && ttmp->ttyp != HOLE)
&& ((!is_pit(ttmp->ttyp) && !is_hole(ttmp->ttyp))
|| (!is_flyer(mdat) && !is_floater(mdat)
&& !is_clinger(mdat)) || Sokoban)
&& (ttmp->ttyp != SLP_GAS_TRAP || !resists_sleep(mon))
@@ -1796,6 +1806,8 @@ struct monst *mtmp;
pline_The("medallion crumbles to dust!");
}
m_useup(mtmp, lifesave);
/* equip replacement amulet, if any, on next move */
mtmp->misc_worn_check |= I_SPECIAL;
surviver = !(mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
mtmp->mcanmove = 1;
@@ -1806,13 +1818,14 @@ struct monst *mtmp;
if (mtmp->mhpmax <= 0)
mtmp->mhpmax = 10;
mtmp->mhp = mtmp->mhpmax;
if (surviver)
return;
/* genocided monster can't be life-saved */
if (cansee(mtmp->mx, mtmp->my))
pline("Unfortunately, %s is still genocided...", mon_nam(mtmp));
mtmp->mhp = 0;
if (!surviver) {
/* genocided monster can't be life-saved */
if (cansee(mtmp->mx, mtmp->my))
pline("Unfortunately, %s is still genocided...",
mon_nam(mtmp));
mtmp->mhp = 0;
}
}
}
@@ -2242,7 +2255,7 @@ int xkill_flags; /* 1: suppress message, 2: suppress corpse, 4: pacifist */
}
if (mtmp->mtrapped && (t = t_at(x, y)) != 0
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
&& is_pit(t->ttyp)) {
if (sobj_at(BOULDER, x, y))
nocorpse = TRUE; /* Prevent corpses/treasure being created
"on top" of boulder that is about to fall in.
@@ -2887,7 +2900,8 @@ restartcham()
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
mtmp->cham = pm_to_cham(monsndx(mtmp->data));
if (!mtmp->mcan)
mtmp->cham = pm_to_cham(monsndx(mtmp->data));
if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping
&& cansee(mtmp->mx, mtmp->my)) {
set_mimic_sym(mtmp);
@@ -2929,7 +2943,7 @@ register struct monst *mtmp;
|| rn2(3) || mtmp == u.ustuck
/* can't hide while trapped except in pits */
|| (mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0
&& !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))
&& !is_pit(t->ttyp))
|| (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
return FALSE;
@@ -2957,7 +2971,7 @@ struct monst *mtmp;
; /* can't hide if holding you or held by you */
} else if (is_u ? (u.utrap && u.utraptype != TT_PIT)
: (mtmp->mtrapped && (t = t_at(x, y)) != 0
&& !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
&& !is_pit(t->ttyp))) {
; /* can't hide while stuck in a non-pit trap */
} else if (mtmp->data->mlet == S_EEL) {
undetected = (is_pool(x, y) && !Is_waterlevel(&u.uz));
@@ -3404,6 +3418,13 @@ boolean msg; /* "The oldmon turns into a newmon!" */
anomalous extinction feedback during final disclsoure */
if (mbirth_limit(monsndx(olddata)) < MAXMONNO)
return 0;
/* cancelled shapechangers become uncancelled prior
to being given a new shape */
if (mtmp->mcan && !Protection_from_shape_changers) {
mtmp->cham = pm_to_cham(monsndx(mtmp->data));
if (mtmp->cham != NON_PM)
mtmp->mcan = 0;
}
}
if (msg) {
+1 -1
View File
@@ -126,7 +126,7 @@ int x, y;
if (create && !((mtmp = m_at(x, y)) != 0 && mtmp->mtrapped
&& (t = t_at(x, y)) != 0
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
&& is_pit(t->ttyp))) {
int objgone = 0;
if (down_gate(x, y) != -1)
+2 -2
View File
@@ -439,7 +439,7 @@ struct monst *mtmp;
|| onscary(xx, yy, mtmp))
continue;
/* use trap if it's the correct type */
if ((t->ttyp == TRAPDOOR || t->ttyp == HOLE)
if (is_hole(t->ttyp)
&& !is_floater(mtmp->data)
&& !mtmp->isshk && !mtmp->isgd && !mtmp->ispriest
&& Can_fall_thru(&u.uz)) {
@@ -489,7 +489,7 @@ struct monst *mtmp;
/* kludge to cut down on trap destruction (particularly portals) */
t = t_at(x, y);
if (t && (t->ttyp == PIT || t->ttyp == SPIKED_PIT || t->ttyp == WEB
if (t && (is_pit(t->ttyp) || t->ttyp == WEB
|| t->ttyp == BEAR_TRAP))
t = 0; /* ok for monster to dig here */
+1 -1
View File
@@ -249,7 +249,7 @@ int force;
unsigned tu_pit = 0;
if (trap_at_u)
tu_pit = (trap_at_u->ttyp == PIT || trap_at_u->ttyp == SPIKED_PIT);
tu_pit = is_pit(trap_at_u->ttyp);
start_x = u.ux - (force * 2);
start_y = u.uy - (force * 2);
end_x = u.ux + (force * 2);
+1 -1
View File
@@ -368,7 +368,7 @@ HELM("helm of telepathy", "visored helmet",
* There is code in obj.h, objnam.c, mon.c, read.c that assumes (2).
* (1) The dragon scale mails and the dragon scales are together.
* (2) That the order of the dragon scale mail and dragon scales
* is the the same as order of dragons defined in monst.c.
* is the same as order of dragons defined in monst.c.
*/
#define DRGN_ARMR(name,mgc,power,cost,ac,color) \
ARMOR(name, None, 1, mgc, 1, power, 0, 5, 40, \
+7 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 objnam.c $NHDT-Date: 1533352036 2018/08/04 03:07:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.206 $ */
/* NetHack 3.6 objnam.c $NHDT-Date: 1537313446 2018/09/18 23:30:46 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.208 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -3204,6 +3204,11 @@ struct obj *no_wish;
typ = SPE_BLANK_PAPER;
goto typfnd;
}
/* specific food rather than color of gem/potion/spellbook[/scales] */
if (!BSTRCMPI(bp, p - 6, "orange") && mntmp == NON_PM) {
typ = ORANGE;
goto typfnd;
}
/*
* NOTE: Gold pieces are handled as objects nowadays, and therefore
* this section should probably be reconsidered as well as the entire
@@ -3508,7 +3513,7 @@ wiztrap:
if (strncmpi(tname, bp, strlen(tname)))
continue;
/* found it; avoid stupid mistakes */
if ((trap == TRAPDOOR || trap == HOLE) && !Can_fall_thru(&u.uz))
if (is_hole(trap) && !Can_fall_thru(&u.uz))
trap = ROCKTRAP;
if ((t = maketrap(x, y, trap)) != 0) {
trap = t->ttyp;
+2 -1
View File
@@ -173,7 +173,8 @@ static struct Bool_Opt {
#else
{ "page_wait", (boolean *) 0, FALSE, SET_IN_FILE },
#endif
{ "perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME },
/* 3.6.2: move perm_invent from flags to inflags and out of save file */
{ "perm_invent", &iflags.perm_invent, FALSE, SET_IN_GAME },
{ "pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME },
{ "popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME }, /*WC*/
{ "preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME }, /*WC*/
+90 -16
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 pager.c $NHDT-Date: 1523142395 2018/04/07 23:06:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.123 $ */
/* NetHack 3.6 pager.c $NHDT-Date: 1537477571 2018/09/20 21:06:11 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.129 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -16,8 +16,9 @@ STATIC_DCL void FDECL(look_at_monster, (char *, char *,
struct monst *, int, int));
STATIC_DCL struct permonst *FDECL(lookat, (int, int, char *, char *));
STATIC_DCL void FDECL(checkfile, (char *, struct permonst *,
BOOLEAN_P, BOOLEAN_P));
BOOLEAN_P, BOOLEAN_P, char *));
STATIC_DCL void FDECL(look_all, (BOOLEAN_P,BOOLEAN_P));
STATIC_DCL void FDECL(do_supplemental_info, (char *, struct permonst *,BOOLEAN_P));
STATIC_DCL void NDECL(whatdoes_help);
STATIC_DCL void NDECL(docontact);
STATIC_DCL void NDECL(dispfile_help);
@@ -279,7 +280,7 @@ int x, y;
int tt = t ? t->ttyp : NO_TRAP;
/* newsym lets you know of the trap, so mention it here */
if (tt == BEAR_TRAP || tt == PIT || tt == SPIKED_PIT || tt == WEB)
if (tt == BEAR_TRAP || is_pit(tt) || tt == WEB)
Sprintf(eos(buf), ", trapped in %s",
an(defsyms[trap_to_defsym(tt)].explanation));
}
@@ -509,10 +510,11 @@ char *buf, *monbuf;
* Therefore, we create a copy of inp _just_ for data.base lookup.
*/
STATIC_OVL void
checkfile(inp, pm, user_typed_name, without_asking)
checkfile(inp, pm, user_typed_name, without_asking, supplemental_name)
char *inp;
struct permonst *pm;
boolean user_typed_name, without_asking;
char *supplemental_name;
{
dlb *fp;
char buf[BUFSZ], newstr[BUFSZ], givenname[BUFSZ];
@@ -619,7 +621,7 @@ boolean user_typed_name, without_asking;
int chk_skip, pass = 1;
boolean yes_to_moreinfo, found_in_file, pass1found_in_file,
skipping_entry;
char *ap, *alt = 0; /* alternate description */
char *sp, *ap, *alt = 0; /* alternate description */
/* adjust the input to remove "named " and "called " */
if ((ep = strstri(dbase_str, " named ")) != 0) {
@@ -629,6 +631,8 @@ boolean user_typed_name, without_asking;
} else if ((ep = strstri(dbase_str, " called ")) != 0) {
copynchars(givenname, ep + 8, BUFSZ - 1);
alt = givenname;
if (supplemental_name && (sp = strstri(inp, " called ")) != 0)
copynchars(supplemental_name, sp + 8, BUFSZ - 1);
} else
ep = strstri(dbase_str, ", ");
if (ep && ep > dbase_str)
@@ -760,12 +764,13 @@ boolean user_typed_name, without_asking;
}
int
do_screen_description(cc, looked, sym, out_str, firstmatch)
do_screen_description(cc, looked, sym, out_str, firstmatch, for_supplement)
coord cc;
boolean looked;
int sym;
char *out_str;
const char **firstmatch;
struct permonst **for_supplement;
{
static const char mon_interior[] = "the interior of a monster",
unreconnoitered[] = "unreconnoitered";
@@ -1008,11 +1013,15 @@ const char **firstmatch;
didlook:
if (looked) {
struct permonst *pm = (struct permonst *)0;
if (found > 1 || need_to_look) {
char monbuf[BUFSZ];
char temp_buf[BUFSZ];
(void) lookat(cc.x, cc.y, look_buf, monbuf);
pm = lookat(cc.x, cc.y, look_buf, monbuf);
if (pm && for_supplement)
*for_supplement = pm;
*firstmatch = look_buf;
if (*(*firstmatch)) {
Sprintf(temp_buf, " (%s)", *firstmatch);
@@ -1043,7 +1052,7 @@ coord *click_cc;
boolean clicklook = (mode == 2); /* right mouse-click method */
char out_str[BUFSZ] = DUMMY;
const char *firstmatch = 0;
struct permonst *pm = 0;
struct permonst *pm = 0, *supplemental_pm = 0;
int i = '\0', ans = 0;
int sym; /* typed symbol or converted glyph */
int found; /* count of matching syms found */
@@ -1137,7 +1146,7 @@ coord *click_cc;
break;
}
if (*out_str)
checkfile(out_str, pm, TRUE, TRUE);
checkfile(out_str, pm, TRUE, TRUE, (char *) 0);
return 0;
}
case '?':
@@ -1151,7 +1160,7 @@ coord *click_cc;
return 0;
if (out_str[1]) { /* user typed in a complete string */
checkfile(out_str, pm, TRUE, TRUE);
checkfile(out_str, pm, TRUE, TRUE, (char *) 0);
return 0;
}
sym = out_str[0];
@@ -1204,7 +1213,7 @@ coord *click_cc;
}
found = do_screen_description(cc, (from_screen || clicklook), sym,
out_str, &firstmatch);
out_str, &firstmatch, &supplemental_pm);
/* Finally, print out our explanation. */
if (found) {
@@ -1215,16 +1224,19 @@ coord *click_cc;
if (found == 1 && ans != LOOK_QUICK && ans != LOOK_ONCE
&& (ans == LOOK_VERBOSE || (flags.help && !quick))
&& !clicklook) {
char temp_buf[BUFSZ];
char temp_buf[BUFSZ], supplemental_name[BUFSZ];
supplemental_name[0] = '\0';
Strcpy(temp_buf, firstmatch);
checkfile(temp_buf, pm, FALSE,
(boolean) (ans == LOOK_VERBOSE));
(boolean) (ans == LOOK_VERBOSE), supplemental_name);
if (supplemental_pm)
do_supplemental_info(supplemental_name, supplemental_pm,
(boolean) (ans == LOOK_VERBOSE));
}
} else {
pline("I've never heard of such things.");
}
} while (from_screen && !quick && ans != LOOK_ONCE && !clicklook);
flags.verbose = save_verbose;
@@ -1319,6 +1331,69 @@ boolean do_mons; /* True => monsters, False => objects */
destroy_nhwindow(win);
}
void
do_supplemental_info(name, pm, without_asking)
char *name;
struct permonst *pm;
boolean without_asking;
{
winid datawin = WIN_ERR;
char *entrytext = name, *bp;
char question[QBUFSZ];
boolean yes_to_moreinfo = FALSE;
/*
* Provide some info on some specific things
* meant to support in-game mythology, and not
* available from data.base or other sources.
*/
if (name && pm && is_orc(pm) &&
(strlen(name) < (BUFSZ - 1)) &&
(bp = strstri(name, " of ")) != 0) {
char fullname[BUFSZ];
Strcpy(fullname, name);
if (!without_asking) {
Strcpy(question, "More info about \"");
/* +2 => length of "\"?" */
copynchars(eos(question), entrytext,
(int) (sizeof question - 1 - (strlen(question) + 2)));
Strcat(question, "\"?");
if (yn(question) == 'y')
yes_to_moreinfo = TRUE;
}
if (yes_to_moreinfo) {
int i, subs = 0;
char *gang = bp + 4;
static const char *text[] = {
"%s is a member of a marauding horde of orcs",
"rumored to have brutally attacked and plundered the ordinarily",
"sheltered town that is located deep within The Gnomish Mines.",
"",
"The members of that vicious horde proudly and defiantly acclaim",
"their allegiance to their leader %s in their names.",
};
*bp = '\0';
datawin = create_nhwindow(NHW_MENU);
for (i = 0; i < SIZE(text); i++) {
char buf[BUFSZ];
const char *txt;
if (strstri(text[i], "%s") != 0) {
Sprintf(buf, text[i],
subs++ ? gang : fullname);
txt = buf;
} else
txt = text[i];
putstr(datawin, 0, txt);
}
display_nhwindow(datawin, FALSE);
destroy_nhwindow(datawin), datawin = WIN_ERR;
}
}
}
/* the '/' command */
int
dowhatis()
@@ -1362,8 +1437,7 @@ doidtrap()
break;
tt = trap->ttyp;
if (u.dz) {
if (u.dz < 0 ? (tt == TRAPDOOR || tt == HOLE)
: tt == ROCKTRAP)
if (u.dz < 0 ? is_hole(tt) : tt == ROCKTRAP)
break;
}
tt = what_trap(tt);
+1 -1
View File
@@ -921,7 +921,7 @@ aligntyp g_align;
* - fix all of your problems;
* - do you a gratuitous favor.
*
* If you make it to the the last category, you roll randomly again
* If you make it to the last category, you roll randomly again
* to see what they do for you.
*
* If your luck is at least 0, then you are guaranteed rescued from
+8 -4
View File
@@ -543,9 +543,12 @@ unsigned int *stuckid, *steedid;
/* avoid keeping permanent inventory window up to date during restore
(setworn() calls update_inventory); attempting to include the cost
of unpaid items before shopkeeper's bill is available is a no-no;
named fruit names aren't accessible yet either */
defer_perm_invent = flags.perm_invent;
flags.perm_invent = FALSE;
named fruit names aren't accessible yet either
[3.6.2: moved perm_invent from flags to iflags to keep it out of
save files; retaining the override here is simpler than trying to
to figure out where it really belongs now] */
defer_perm_invent = iflags.perm_invent;
iflags.perm_invent = FALSE;
/* wizard and discover are actually flags.debug and flags.explore;
player might be overriding the save file values for them;
in the discover case, we don't want to set that for a normal
@@ -595,6 +598,7 @@ unsigned int *stuckid, *steedid;
u.uz.dlevel = 1;
/* revert to pre-restore option settings */
iflags.deferred_X = FALSE;
iflags.perm_invent = defer_perm_invent;
flags = newgameflags;
#ifdef SYSFLAGS
sysflags = newgamesysflags;
@@ -672,7 +676,7 @@ unsigned int *stuckid, *steedid;
relink_timers(FALSE);
relink_light_sources(FALSE);
/* inventory display is now viable */
flags.perm_invent = defer_perm_invent;
iflags.perm_invent = defer_perm_invent;
return TRUE;
}
+23 -33
View File
@@ -2662,8 +2662,7 @@ fill_empty_maze()
maze1xy(&mm, DRY);
trytrap = rndtrap();
if (sobj_at(BOULDER, mm.x, mm.y))
while (trytrap == PIT || trytrap == SPIKED_PIT
|| trytrap == TRAPDOOR || trytrap == HOLE)
while (is_pit(trytrap) || is_hole(trytrap))
trytrap = rndtrap();
(void) maketrap(mm.x, mm.y, trytrap);
}
@@ -3834,7 +3833,7 @@ selection_do_grow(ov, dir)
struct opvar *ov;
int dir;
{
int x, y, c;
int x, y;
char tmp[COLNO][ROWNO];
if (ov->spovartyp != SPOVAR_SEL)
@@ -3842,40 +3841,31 @@ int dir;
if (!ov)
return;
(void) memset(tmp, 0, sizeof(tmp));
(void) memset(tmp, 0, sizeof tmp);
for (x = 0; x < COLNO; x++)
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++) {
c = 0;
if ((dir & W_WEST) && (x > 0)
&& (selection_getpoint(x - 1, y, ov)))
c++;
if ((dir & (W_WEST | W_NORTH)) && (x > 0) && (y > 0)
&& (selection_getpoint(x - 1, y - 1, ov)))
c++;
if ((dir & W_NORTH) && (y > 0)
&& (selection_getpoint(x, y - 1, ov)))
c++;
if ((dir & (W_NORTH | W_EAST)) && (y > 0) && (x < COLNO - 1)
&& (selection_getpoint(x + 1, y - 1, ov)))
c++;
if ((dir & W_EAST) && (x < COLNO - 1)
&& (selection_getpoint(x + 1, y, ov)))
c++;
if ((dir & (W_EAST | W_SOUTH)) && (x < COLNO - 1)
&& (y < ROWNO - 1) && (selection_getpoint(x + 1, y + 1, ov)))
c++;
if ((dir & W_SOUTH) && (y < ROWNO - 1)
&& (selection_getpoint(x, y + 1, ov)))
c++;
if ((dir & (W_SOUTH | W_WEST)) && (y < ROWNO - 1) && (x > 0)
&& (selection_getpoint(x - 1, y + 1, ov)))
c++;
if (c)
/* note: dir is a mask of multiple directions, but the only
way to specify diagonals is by including the two adjacent
orthogonal directions, which effectively specifies three-
way growth [WEST|NORTH => WEST plus WEST|NORTH plus NORTH] */
if (((dir & W_WEST) && selection_getpoint(x + 1, y, ov))
|| (((dir & (W_WEST | W_NORTH)) == (W_WEST | W_NORTH))
&& selection_getpoint(x + 1, y + 1, ov))
|| ((dir & W_NORTH) && selection_getpoint(x, y + 1, ov))
|| (((dir & (W_NORTH | W_EAST)) == (W_NORTH | W_EAST))
&& selection_getpoint(x - 1, y + 1, ov))
|| ((dir & W_EAST) && selection_getpoint(x - 1, y, ov))
|| (((dir & (W_EAST | W_SOUTH)) == (W_EAST | W_SOUTH))
&& selection_getpoint(x - 1, y - 1, ov))
|| ((dir & W_SOUTH) && selection_getpoint(x, y - 1, ov))
|| (((dir & (W_SOUTH | W_WEST)) == (W_SOUTH | W_WEST))
&& selection_getpoint(x + 1, y - 1, ov))) {
tmp[x][y] = 1;
}
}
for (x = 0; x < COLNO; x++)
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++)
if (tmp[x][y])
selection_setpoint(x, y, ov, 1);
@@ -4501,7 +4491,7 @@ ensure_way_out()
while (ttmp) {
if ((ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE
|| ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR)
|| is_hole(ttmp->ttyp))
&& !selection_getpoint(ttmp->tx, ttmp->ty, ov))
selection_floodfill(ov, ttmp->tx, ttmp->ty, TRUE);
ttmp = ttmp->ntrap;
+1 -1
View File
@@ -1159,7 +1159,7 @@ int in_sight;
d_level tolevel;
int migrate_typ = MIGR_RANDOM;
if ((tt == HOLE || tt == TRAPDOOR)) {
if (is_hole(tt)) {
if (Is_stronghold(&u.uz)) {
assign_level(&tolevel, &valley_level);
} else if (Is_botlevel(&u.uz)) {
+64 -70
View File
@@ -7,6 +7,15 @@
extern const char *const destroy_strings[][3]; /* from zap.c */
STATIC_DCL boolean FDECL(keep_saddle_with_steedcorpse, (unsigned, struct obj *,
struct obj *));
STATIC_DCL struct obj *FDECL(t_missile, (int, struct trap *));
STATIC_DCL char *FDECL(trapnote, (struct trap *, BOOLEAN_P));
STATIC_DCL int FDECL(steedintrap, (struct trap *, struct obj *));
STATIC_DCL void FDECL(launch_drop_spot, (struct obj *, XCHAR_P, XCHAR_P));
STATIC_DCL int FDECL(mkroll_launch, (struct trap *, XCHAR_P, XCHAR_P,
SHORT_P, long));
STATIC_DCL boolean FDECL(isclearpath, (coord *, int, SCHAR_P, SCHAR_P));
STATIC_DCL void FDECL(dofiretrap, (struct obj *));
STATIC_DCL void NDECL(domagictrap);
STATIC_DCL boolean FDECL(emergency_disrobe, (boolean *));
@@ -18,26 +27,16 @@ STATIC_DCL int FDECL(disarm_holdingtrap, (struct trap *));
STATIC_DCL int FDECL(disarm_landmine, (struct trap *));
STATIC_DCL int FDECL(disarm_squeaky_board, (struct trap *));
STATIC_DCL int FDECL(disarm_shooting_trap, (struct trap *, int));
STATIC_DCL void FDECL(clear_conjoined_pits, (struct trap *));
STATIC_DCL boolean FDECL(adj_nonconjoined_pit, (struct trap *));
STATIC_DCL int FDECL(try_lift, (struct monst *, struct trap *, int,
BOOLEAN_P));
STATIC_DCL int FDECL(help_monster_out, (struct monst *, struct trap *));
STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int,
BOOLEAN_P));
STATIC_DCL void FDECL(launch_drop_spot, (struct obj *, XCHAR_P, XCHAR_P));
STATIC_DCL int FDECL(mkroll_launch, (struct trap *, XCHAR_P, XCHAR_P,
SHORT_P, long));
STATIC_DCL boolean FDECL(isclearpath, (coord *, int, SCHAR_P, SCHAR_P));
STATIC_DCL char *FDECL(trapnote, (struct trap *, BOOLEAN_P));
#if 0
STATIC_DCL void FDECL(join_adjacent_pits, (struct trap *));
#endif
STATIC_DCL void FDECL(clear_conjoined_pits, (struct trap *));
STATIC_DCL boolean FDECL(adj_nonconjoined_pit, (struct trap *));
STATIC_DCL int FDECL(steedintrap, (struct trap *, struct obj *));
STATIC_DCL boolean FDECL(keep_saddle_with_steedcorpse, (unsigned,
struct obj *,
struct obj *));
STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int,
BOOLEAN_P));
STATIC_DCL void NDECL(maybe_finish_sokoban);
/* mintrap() should take a flags argument, but for time being we use this */
@@ -328,8 +327,7 @@ int x, y, typ;
if (u.utrap && x == u.ux && y == u.uy
&& ((u.utraptype == TT_BEARTRAP && typ != BEAR_TRAP)
|| (u.utraptype == TT_WEB && typ != WEB)
|| (u.utraptype == TT_PIT && typ != PIT
&& typ != SPIKED_PIT)))
|| (u.utraptype == TT_PIT && !is_pit(typ))))
u.utrap = 0;
/* old <tx,ty> remain valid */
} else if (IS_FURNITURE(lev->typ)
@@ -407,8 +405,7 @@ int x, y, typ;
case HOLE:
case TRAPDOOR:
if (*in_rooms(x, y, SHOPBASE)
&& (typ == HOLE || typ == TRAPDOOR
|| IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
&& (is_hole(typ) || IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
add_damage(x, y, /* schedule repair */
((IS_DOOR(lev->typ) || IS_WALL(lev->typ))
&& !context.mon_moving)
@@ -841,6 +838,21 @@ struct trap *trap;
return FALSE;
}
/* make a single arrow/dart/rock for a trap to shoot or drop */
STATIC_OVL struct obj *
t_missile(otyp, trap)
int otyp;
struct trap *trap;
{
struct obj *otmp = mksobj(otyp, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp->opoisoned = 0;
otmp->ox = trap->tx, otmp->oy = trap->ty;
return otmp;
}
void
dotrap(trap, trflags)
register struct trap *trap;
@@ -862,8 +874,7 @@ unsigned trflags;
nomul(0);
/* KMH -- You can't escape the Sokoban level traps */
if (Sokoban && (ttype == PIT || ttype == SPIKED_PIT
|| ttype == HOLE || ttype == TRAPDOOR)) {
if (Sokoban && (is_pit(ttype) || is_hole(ttype))) {
/* The "air currents" message is still appropriate -- even when
* the hero isn't flying or levitating -- because it conveys the
* reason why the player cannot escape the trap with a dexterity
@@ -875,7 +886,7 @@ unsigned trflags;
/* then proceed to normal trap effect */
} else if (already_seen && !forcetrap) {
if ((Levitation || (Flying && !plunged))
&& (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE
&& (is_pit(ttype) || ttype == HOLE
|| ttype == BEAR_TRAP)) {
You("%s over %s %s.", Levitation ? "float" : "fly",
a_your[trap->madeby_u],
@@ -885,7 +896,7 @@ unsigned trflags;
if (!Fumbling && ttype != MAGIC_PORTAL && ttype != VIBRATING_SQUARE
&& ttype != ANTI_MAGIC && !forcebungle && !plunged
&& !conj_pit && !adj_pit
&& (!rn2(5) || ((ttype == PIT || ttype == SPIKED_PIT)
&& (!rn2(5) || (is_pit(ttype)
&& is_clinger(youmonst.data)))) {
You("escape %s %s.", (ttype == ARROW_TRAP && !trap->madeby_u)
? "an"
@@ -914,12 +925,9 @@ unsigned trflags;
trap->once = 1;
seetrap(trap);
pline("An arrow shoots out at you!");
otmp = mksobj(ARROW, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp->opoisoned = 0;
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) { /* nothing */
;
otmp = t_missile(ARROW, trap);
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) {
; /* nothing */
} else if (thitu(8, dmgval(otmp, &youmonst), &otmp, "arrow")) {
if (otmp)
obfree(otmp, (struct obj *) 0);
@@ -942,14 +950,12 @@ unsigned trflags;
trap->once = 1;
seetrap(trap);
pline("A little dart shoots out at you!");
otmp = mksobj(DART, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp = t_missile(DART, trap);
if (!rn2(6))
otmp->opoisoned = 1;
oldumort = u.umortality;
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) { /* nothing */
;
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) {
; /* nothing */
} else if (thitu(7, dmgval(otmp, &youmonst), &otmp, "little dart")) {
if (otmp) {
if (otmp->opoisoned)
@@ -979,13 +985,11 @@ unsigned trflags;
trap->once = 1;
feeltrap(trap);
otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp = t_missile(ROCK, trap);
place_object(otmp, u.ux, u.uy);
pline("A trap door in %s opens and %s falls on your %s!",
the(ceiling(u.ux, u.uy)), an(xname(otmp)), body_part(HEAD));
if (uarmh) {
if (is_metallic(uarmh)) {
pline("Fortunately, you are wearing a hard helmet.");
@@ -994,7 +998,6 @@ unsigned trflags;
pline("%s does not protect you.", Yname2(uarmh));
}
}
if (!Blind)
otmp->dknown = 1;
stackobj(otmp);
@@ -1642,7 +1645,7 @@ static struct {
xchar x, y;
} launchplace;
static void
STATIC_OVL void
launch_drop_spot(obj, x, y)
struct obj *obj;
xchar x, y;
@@ -2075,8 +2078,8 @@ register struct monst *mtmp;
mtmp->mtrapped = 0; /* perhaps teleported? */
} else if (mtmp->mtrapped) { /* is currently in the trap */
if (!trap->tseen && cansee(mtmp->mx, mtmp->my) && canseemon(mtmp)
&& (trap->ttyp == SPIKED_PIT || trap->ttyp == BEAR_TRAP
|| trap->ttyp == HOLE || trap->ttyp == PIT
&& (is_pit(trap->ttyp) || trap->ttyp == BEAR_TRAP
|| trap->ttyp == HOLE
|| trap->ttyp == WEB)) {
/* If you come upon an obviously trapped monster, then
* you must be able to see the trap it's in too.
@@ -2086,7 +2089,7 @@ register struct monst *mtmp;
if (!rn2(40)) {
if (sobj_at(BOULDER, mtmp->mx, mtmp->my)
&& (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
&& is_pit(trap->ttyp)) {
if (!rn2(2)) {
mtmp->mtrapped = 0;
if (canseemon(mtmp))
@@ -2150,10 +2153,7 @@ register struct monst *mtmp;
break;
}
trap->once = 1;
otmp = mksobj(ARROW, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp->opoisoned = 0;
otmp = t_missile(ARROW, trap);
if (in_sight)
seetrap(trap);
if (thitm(8, mtmp, otmp, 0, FALSE))
@@ -2169,9 +2169,7 @@ register struct monst *mtmp;
break;
}
trap->once = 1;
otmp = mksobj(DART, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp = t_missile(DART, trap);
if (!rn2(6))
otmp->opoisoned = 1;
if (in_sight)
@@ -2190,9 +2188,7 @@ register struct monst *mtmp;
break;
}
trap->once = 1;
otmp = mksobj(ROCK, TRUE, FALSE);
otmp->quan = 1L;
otmp->owt = weight(otmp);
otmp = t_missile(ROCK, trap);
if (in_sight)
seetrap(trap);
if (thitm(0, mtmp, otmp, d(2, 6), FALSE))
@@ -2818,7 +2814,7 @@ int x, y;
struct obj *otmp;
struct trap *t;
if ((t = t_at(x, y)) && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))
if ((t = t_at(x, y)) && is_pit(t->ttyp)
&& (otmp = sobj_at(BOULDER, x, y))) {
obj_extract_self(otmp);
(void) flooreffects(otmp, x, y, "settle");
@@ -2865,8 +2861,7 @@ long hmask, emask; /* might cancel timeout */
if (Punished && !carried(uball)
&& (is_pool(uball->ox, uball->oy)
|| ((trap = t_at(uball->ox, uball->oy))
&& ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT)
|| (trap->ttyp == TRAPDOOR) || (trap->ttyp == HOLE))))) {
&& (is_pit(trap->ttyp) || is_hole(trap->ttyp))))) {
u.ux0 = u.ux;
u.uy0 = u.uy;
u.ux = uball->ox;
@@ -4313,7 +4308,7 @@ boolean force;
if (ttmp) {
Strcpy(the_trap, the(trapdescr));
if (boxcnt) {
if (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) {
if (is_pit(ttmp->ttyp)) {
You_cant("do much about %s%s.", the_trap,
u.utrap ? " that you're stuck in"
: " while standing on the edge of it");
@@ -4615,8 +4610,7 @@ boolean *noticed; /* set to true iff hero notices the effect; */
/* if no trap here or it's not a falling trap, we're done
(note: falling rock traps have a trapdoor in the ceiling) */
if (!t || ((t->ttyp != TRAPDOOR && t->ttyp != ROCKTRAP)
&& (trapdoor_only || (t->ttyp != HOLE && t->ttyp != PIT
&& t->ttyp != SPIKED_PIT))))
&& (trapdoor_only || (t->ttyp != HOLE && !is_pit(t->ttyp)))))
return FALSE;
if (ishero) {
@@ -4875,8 +4869,8 @@ boolean u_entering_trap2;
if (!trap1 || !trap2)
return FALSE;
if (!isok(trap2->tx, trap2->ty) || !isok(trap1->tx, trap1->ty)
|| !(trap2->ttyp == PIT || trap2->ttyp == SPIKED_PIT)
|| !(trap1->ttyp == PIT || trap1->ttyp == SPIKED_PIT)
|| !is_pit(trap2->ttyp)
|| !is_pit(trap1->ttyp)
|| (u_entering_trap2 && !(u.utrap && u.utraptype == TT_PIT)))
return FALSE;
dx = sgn(trap2->tx - trap1->tx);
@@ -4894,21 +4888,21 @@ boolean u_entering_trap2;
return FALSE;
}
void
STATIC_OVL void
clear_conjoined_pits(trap)
struct trap *trap;
{
int diridx, adjidx, x, y;
struct trap *t;
if (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
if (trap && is_pit(trap->ttyp)) {
for (diridx = 0; diridx < 8; ++diridx) {
if (trap->conjoined & (1 << diridx)) {
x = trap->tx + xdir[diridx];
y = trap->ty + ydir[diridx];
if (isok(x, y)
&& (t = t_at(x, y)) != 0
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
&& is_pit(t->ttyp)) {
adjidx = (diridx + 4) % 8;
t->conjoined &= ~(1 << adjidx);
}
@@ -4918,15 +4912,15 @@ struct trap *trap;
}
}
boolean
STATIC_OVL boolean
adj_nonconjoined_pit(adjtrap)
struct trap *adjtrap;
{
struct trap *trap_with_u = t_at(u.ux0, u.uy0);
if (trap_with_u && adjtrap && u.utrap && u.utraptype == TT_PIT &&
(trap_with_u->ttyp == PIT || trap_with_u->ttyp == SPIKED_PIT) &&
(adjtrap->ttyp == PIT || adjtrap->ttyp == SPIKED_PIT)) {
is_pit(trap_with_u->ttyp) &&
is_pit(adjtrap->ttyp)) {
int idx;
for (idx = 0; idx < 8; idx++) {
if (xdir[idx] == u.dx && ydir[idx] == u.dy)
@@ -4955,7 +4949,7 @@ struct trap *trap;
y = trap->ty + ydir[diridx];
if (isok(x, y)) {
if ((t = t_at(x, y)) != 0
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
&& is_pit(t->ttyp)) {
trap->conjoined |= (1 << diridx);
join_adjacent_pits(t);
} else
@@ -4973,7 +4967,7 @@ uteetering_at_seen_pit(trap)
struct trap *trap;
{
if (trap && trap->tseen && (!u.utrap || u.utraptype != TT_PIT)
&& (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT))
&& is_pit(trap->ttyp))
return TRUE;
else
return FALSE;
@@ -4987,8 +4981,8 @@ register struct trap *ttmp;
/* some of these are arbitrary -dlc */
if (ttmp && ((ttmp->ttyp == SQKY_BOARD) || (ttmp->ttyp == BEAR_TRAP)
|| (ttmp->ttyp == LANDMINE) || (ttmp->ttyp == FIRE_TRAP)
|| (ttmp->ttyp == PIT) || (ttmp->ttyp == SPIKED_PIT)
|| (ttmp->ttyp == HOLE) || (ttmp->ttyp == TRAPDOOR)
|| is_pit(ttmp->ttyp)
|| is_hole(ttmp->ttyp)
|| (ttmp->ttyp == TELEP_TRAP) || (ttmp->ttyp == LEVEL_TELEP)
|| (ttmp->ttyp == WEB) || (ttmp->ttyp == MAGIC_TRAP)
|| (ttmp->ttyp == ANTI_MAGIC))) {
+3
View File
@@ -1484,6 +1484,9 @@ struct attack *mattk;
setmnotwielded(mdef, otmp);
otmp->owornmask = 0L;
update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
/* give monster a chance to wear other equipment on its next
move instead of waiting until it picks something up */
mdef->misc_worn_check |= I_SPECIAL;
if (otmp == stealoid) /* special message for final item */
pline("%s finishes taking off %s suit.", Monnam(mdef),
+1 -1
View File
@@ -1916,7 +1916,7 @@ char *limits; /* points at range limit for current row, or NULL */
* shadow limit imposed by the far block (right) then use the far
* wall as our new far block when we recurse.
*
* If the limits are the the same, and the far block really exists
* If the limits are the same, and the far block really exists
* (fb_row >= 0) then do the same as above.
*
* Normally, the check would be for the far wall being closer OR EQUAL
+17 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 worn.c $NHDT-Date: 1526728754 2018/05/19 11:19:14 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.51 $ */
/* NetHack 3.6 worn.c $NHDT-Date: 1537234121 2018/09/18 01:28:41 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.55 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -710,6 +710,13 @@ clear_bypasses()
struct obj *otmp, *nobj;
struct monst *mtmp;
/*
* 'Object' bypass is also used for one monster function:
* polymorph control of long worms. Activated via setting
* context.bypasses even if no specific object has been
* bypassed.
*/
for (otmp = fobj; otmp; otmp = nobj) {
nobj = otmp->nobj;
if (otmp->bypass) {
@@ -741,10 +748,19 @@ clear_bypasses()
continue;
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
otmp->bypass = 0;
/* long worm created by polymorph has mon->mextra->mcorpsenm set
to PM_LONG_WORM to flag it as not being subject to further
polymorph (so polymorph zap won't hit monster to transform it
into a long worm, then hit that worm's tail and transform it
again on same zap); clearing mcorpsenm reverts worm to normal */
if (mtmp->data == &mons[PM_LONG_WORM] && has_mcorpsenm(mtmp))
MCORPSENM(mtmp) = NON_PM;
}
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
otmp->bypass = 0;
/* no MCORPSENM(mtmp)==PM_LONG_WORM check here; long worms can't
be just created by polymorph and migrating at the same time */
}
/* billobjs and mydogs chains don't matter here */
context.bypasses = FALSE;
+54 -14
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1525012627 2018/04/29 14:37:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.277 $ */
/* NetHack 3.6 zap.c $NHDT-Date: 1537234123 2018/09/18 01:28:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.287 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -222,7 +222,11 @@ struct obj *otmp;
case WAN_POLYMORPH:
case SPE_POLYMORPH:
case POT_POLYMORPH:
if (resists_magm(mtmp)) {
if (mtmp->data == &mons[PM_LONG_WORM] && has_mcorpsenm(mtmp)) {
/* if a long worm has mcorpsenm set, it was polymophed by
the current zap and shouldn't be affected if hit again */
;
} else if (resists_magm(mtmp)) {
/* magic resistance protects from polymorph traps, so make
it guard against involuntary polymorph attacks too... */
shieldeff(mtmp->mx, mtmp->my);
@@ -238,6 +242,7 @@ struct obj *otmp;
if (polyspot)
for (obj = mtmp->minvent; obj; obj = obj->nobj)
bypass_obj(obj);
/* natural shapechangers aren't affected by system shock
(unless protection from shapechangers is interfering
with their metabolism...) */
@@ -261,6 +266,22 @@ struct obj *otmp;
|| (u.uswallow && mtmp == u.ustuck)))
learn_it = TRUE;
}
/* do this even if polymorphed failed (otherwise using
flags.mon_polycontrol prompting to force mtmp to remain
'long worm' would prompt again if zap hit another segment) */
if (!DEADMONSTER(mtmp) && mtmp->data == &mons[PM_LONG_WORM]) {
if (!has_mcorpsenm(mtmp))
newmcorpsenm(mtmp);
/* flag to indicate that mtmp became a long worm
on current zap, so further hits (on mtmp's new
tail) don't do further transforms */
MCORPSENM(mtmp) = PM_LONG_WORM;
/* flag to indicate that cleanup is needed; object
bypass cleanup also clears mon->mextra->mcorpsenm
for all long worms on the level */
context.bypasses = TRUE;
}
}
break;
case WAN_CANCELLATION:
@@ -2306,7 +2327,7 @@ boolean ordinary;
case WAN_CANCELLATION:
case SPE_CANCELLATION:
(void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE);
(void) cancel_monst(&youmonst, obj, TRUE, TRUE, TRUE);
break;
case SPE_DRAIN_LIFE:
@@ -2675,25 +2696,45 @@ boolean youattack, allow_cancel_kill, self_cancel;
/* now handle special cases */
if (youdefend) {
if (Upolyd) {
if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
pline(writing_vanishes, your);
if (Unchanging)
if (Upolyd) { /* includes lycanthrope in creature form */
/*
* Return to normal form unless Unchanging.
* Hero in clay golem form dies if Unchanging.
* Does not cure lycanthropy or stop timed random polymorph.
*/
if (u.umonnum == PM_CLAY_GOLEM) {
if (!Blind)
pline(writing_vanishes, your);
else /* note: "dark" rather than "heavy" is intentional... */
You_feel("%s headed.", Hallucination ? "dark" : "light");
u.mh = 0; /* fatal; death handled by rehumanize() */
}
if (Unchanging && u.mh > 0)
Your("amulet grows hot for a moment, then cools.");
else
rehumanize();
}
} else {
mdef->mcan = TRUE;
if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
mdef->mcan = 1;
/* force shapeshifter into its base form */
if (mdef->m_ap_type != M_AP_NOTHING)
seemimic(mdef);
/* [not 'else if'; chameleon might have been hiding as a mimic] */
if (mdef->cham >= LOW_PM) {
/* note: newcham() uncancels shapechangers (resets m->mcan
to 0), but only for shapechangers whose m->cham is already
NON_PM and we just verified that it's LOW_PM or higher */
newcham(mdef, &mons[mdef->cham], FALSE, FALSE);
mdef->cham = NON_PM; /* cancelled shapeshifter can't shift */
}
if (is_were(mdef->data) && !is_human(mdef->data))
were_change(mdef);
if (mdef->data == &mons[PM_CLAY_GOLEM]) {
if (canseemon(mdef))
pline(writing_vanishes, s_suffix(mon_nam(mdef)));
/* !allow_cancel_kill is for Magicbane, where clay golem
will be killed somewhere back up the call/return chain... */
if (allow_cancel_kill) {
if (youattack)
killed(mdef);
@@ -3373,8 +3414,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
The(distant_name(obj, xname))); /* lame */
range = 0;
} else if (Sokoban && (t = t_at(x, y)) != 0
&& (t->ttyp == PIT || t->ttyp == SPIKED_PIT
|| t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
&& (is_pit(t->ttyp) || is_hole(t->ttyp))) {
/* hero falls into the trap, so ball stops */
range = 0;
}