Merge branch 'NetHack-3.6'

This commit is contained in:
nhmall
2019-06-08 09:38:27 -04:00
10 changed files with 179 additions and 47 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 light.c $NHDT-Date: 1446191876 2015/10/30 07:57:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
/* NetHack 3.6 light.c $NHDT-Date: 1559994625 2019/06/08 11:50:25 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.30 $ */
/* Copyright (c) Dean Luick, 1994 */
/* NetHack may be freely redistributed. See license for details. */
@@ -63,7 +63,7 @@ anything *id;
return;
}
ls = (light_source *) alloc(sizeof(light_source));
ls = (light_source *) alloc(sizeof *ls);
ls->next = g.light_base;
ls->x = x;
@@ -152,8 +152,8 @@ char **cs_rows;
ls->flags |= LSF_SHOW;
}
/* minor optimization: don't bother with duplicate light sources */
/* at hero */
/* minor optimization: don't bother with duplicate light sources
at hero */
if (ls->x == u.ux && ls->y == u.uy) {
if (at_hero_range >= ls->range)
ls->flags &= ~LSF_SHOW;
@@ -190,7 +190,7 @@ char **cs_rows;
* this optimization, is that it allows the vision
* system to correct problems with clear_path().
* The function clear_path() is a simple LOS
* path checker that doesn't go out of its way
* path checker that doesn't go out of its way to
* make things look "correct". The vision system
* does this.
*/
@@ -208,6 +208,80 @@ char **cs_rows;
}
}
/* lit 'obj' has been thrown or kicked and is passing through x,y on the
way to its destination; show its light so that hero has a chance to
remember terrain, objects, and monsters being revealed */
void
show_transient_light(obj, x, y)
struct obj *obj;
int x, y;
{
light_source *ls;
struct monst *mon;
int radius_squared;
/* caller has verified obj->lamplit and that hero is not Blind;
validate light source and obtain its radius (for monster sightings) */
for (ls = g.light_base; ls; ls = ls->next) {
if (ls->type != LS_OBJECT)
continue;
if (ls->id.a_obj == obj)
break;
}
if (!ls || obj->where != OBJ_FREE) {
impossible("transient light %s %s is not %s?",
obj->lamplit ? "lit" : "unlit", xname(obj),
!ls ? "a light source" : "free");
} else {
/* "expensive" but rare */
place_object(obj, g.bhitpos.x, g.bhitpos.y); /* temporarily put on map */
vision_recalc(0);
flush_screen(0);
delay_output();
remove_object(obj); /* take back off of map */
radius_squared = ls->range * ls->range;
for (mon = fmon; mon; mon = mon->nmon) {
if (DEADMONSTER(mon))
continue;
/* light range is the radius of a circle and we're limiting
canseemon() to a square exclosing that circle, but setting
mtemplit 'erroneously' for a seen monster is not a problem;
it just flags monsters for another canseemon() check when
'obj' has reached its destination after missile traversal */
if (dist2(mon->mx, mon->my, x, y) <= radius_squared
&& canseemon(mon))
mon->mtemplit = 1;
/* [what about worm tails?] */
}
}
}
/* draw "remembered, unseen monster" glyph at locations where a monster
was flagged for being visible during transient light movement but can't
be seen now */
void
transient_light_cleanup()
{
struct monst *mon;
int mtempcount = 0;
for (mon = fmon; mon; mon = mon->nmon) {
if (DEADMONSTER(mon))
continue;
if (mon->mtemplit) {
mon->mtemplit = 0;
++mtempcount;
if (!canseemon(mon))
map_invisible(mon->mx, mon->my);
}
}
if (mtempcount) {
vision_recalc(0);
flush_screen(0);
}
}
/* (mon->mx == 0) implies migrating */
#define mon_is_local(mon) ((mon)->mx > 0)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 save.c $NHDT-Date: 1558880688 2019/05/26 14:24:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.120 $ */
/* NetHack 3.6 save.c $NHDT-Date: 1559994625 2019/06/08 11:50:25 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.121 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2009. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1076,6 +1076,8 @@ struct monst *mtmp;
{
int buflen;
mtmp->mtemplit = 0; /* normally clear; if set here then a panic save
* is being written while bhit() was executing */
buflen = (int) sizeof (struct monst);
bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
bwrite(fd, (genericptr_t) mtmp, buflen);

View File

@@ -1,4 +1,4 @@
/* 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 $ */
/* NetHack 3.6 weapon.c $NHDT-Date: 1559998716 2019/06/08 12:58:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.70 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -829,8 +829,18 @@ register struct monst *mon;
setmnotwielded(mon, mw_tmp);
mon->weapon_check = NEED_WEAPON;
if (canseemon(mon)) {
boolean newly_welded;
pline("%s wields %s!", Monnam(mon), doname(obj));
if (mwelded(mw_tmp)) {
/* 3.6.3: mwelded() predicate expects the object to have its
W_WEP bit set in owormmask, but the pline here and for
artifact_light don't want that because they'd have '(weapon
in hand/claw)' appended; so we set it for the mwelded test
and then clear it, until finally setting it for good below */
obj->owornmask |= W_WEP;
newly_welded = mwelded(obj);
obj->owornmask &= ~W_WEP;
if (newly_welded) {
pline("%s %s to %s %s!", Tobjnam(obj, "weld"),
is_plural(obj) ? "themselves" : "itself",
s_suffix(mon_nam(mon)), mbodypart(mon, HAND));
@@ -843,6 +853,12 @@ register struct monst *mon;
pline("%s %s in %s %s!", Tobjnam(obj, "shine"),
arti_light_description(obj), s_suffix(mon_nam(mon)),
mbodypart(mon, HAND));
/* 3.6.3: artifact might be getting wielded by invisible monst */
else if (cansee(mon->mx, mon->my))
pline("Light begins shining %s.",
(distu(mon->mx, mon->my) <= 5 * 5)
? "nearby"
: "in the distance");
}
obj->owornmask = W_WEP;
return 1;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1559685281 2019/06/04 21:54:41 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.310 $ */
/* NetHack 3.6 zap.c $NHDT-Date: 1559994626 2019/06/08 11:50:26 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.311 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
@@ -3215,7 +3215,7 @@ int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
struct obj **pobj; /* object tossed/used, set to NULL
* if object is destroyed */
{
struct monst *mtmp;
struct monst *mtmp, *result = (struct monst *) 0;
struct obj *obj = *pobj;
uchar typ;
boolean shopdoor = FALSE, point_blank = TRUE;
@@ -3241,9 +3241,9 @@ struct obj **pobj; /* object tossed/used, set to NULL
if (weapon == FLASHED_LIGHT) {
tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
} else if (weapon == THROWN_TETHERED_WEAPON && obj) {
tethered_weapon = TRUE;
weapon = THROWN_WEAPON; /* simplify if's that follow below */
tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng));
tethered_weapon = TRUE;
weapon = THROWN_WEAPON; /* simplify 'if's that follow below */
tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng));
} else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng));
@@ -3264,21 +3264,25 @@ struct obj **pobj; /* object tossed/used, set to NULL
if (is_pick(obj) && inside_shop(x, y)
&& (mtmp = shkcatch(obj, x, y)) != 0) {
tmp_at(DISP_END, 0);
return mtmp;
result = mtmp;
goto bhit_done;
}
typ = levl[g.bhitpos.x][g.bhitpos.y].typ;
/* iron bars will block anything big enough */
if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
&& typ == IRONBARS
&& hits_bars(pobj, x - ddx, y - ddy, g.bhitpos.x, g.bhitpos.y,
point_blank ? 0 : !rn2(5), 1)) {
/* caveat: obj might now be null... */
obj = *pobj;
g.bhitpos.x -= ddx;
g.bhitpos.y -= ddy;
break;
/* iron bars will block anything big enough and break some things */
if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) {
if (typ == IRONBARS
&& hits_bars(pobj, x - ddx, y - ddy, g.bhitpos.x, g.bhitpos.y,
point_blank ? 0 : !rn2(5), 1)) {
/* caveat: obj might now be null... */
obj = *pobj;
g.bhitpos.x -= ddx;
g.bhitpos.y -= ddy;
break;
} else if (obj->lamplit && !Blind) {
show_transient_light(obj, g.bhitpos.x, g.bhitpos.y);
}
}
if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
@@ -3358,7 +3362,8 @@ struct obj **pobj; /* object tossed/used, set to NULL
(void) flash_hits_mon(mtmp, obj);
} else {
tmp_at(DISP_END, 0);
return mtmp; /* caller will call flash_hits_mon */
result = mtmp; /* caller will call flash_hits_mon */
goto bhit_done;
}
} else if (weapon == INVIS_BEAM) {
/* Like FLASHED_LIGHT, INVIS_BEAM should continue
@@ -3366,8 +3371,10 @@ struct obj **pobj; /* object tossed/used, set to NULL
prepared for multiple hits so just get first one
that's either visible or could see its invisible
self. [No tmp_at() cleanup is needed here.] */
if (!mtmp->minvis || perceives(mtmp->data))
return mtmp;
if (!mtmp->minvis || perceives(mtmp->data)) {
result = mtmp;
goto bhit_done;
}
} else if (weapon != ZAPPED_WAND) {
/* THROWN_WEAPON, KICKED_WEAPON */
@@ -3376,7 +3383,8 @@ struct obj **pobj; /* object tossed/used, set to NULL
if (cansee(g.bhitpos.x, g.bhitpos.y) && !canspotmon(mtmp))
map_invisible(g.bhitpos.x, g.bhitpos.y);
return mtmp;
result = mtmp;
goto bhit_done;
} else {
/* ZAPPED_WAND */
(*fhitm)(mtmp, obj);
@@ -3399,7 +3407,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
|| ship_object(obj, g.bhitpos.x, g.bhitpos.y,
costly_spot(g.bhitpos.x, g.bhitpos.y)))) {
tmp_at(DISP_END, 0);
return (struct monst *) 0;
goto bhit_done; /* result == (struct monst *) 0 */
}
}
if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
@@ -3482,7 +3490,11 @@ struct obj **pobj; /* object tossed/used, set to NULL
if (shopdoor)
pay_for_damage("destroy", FALSE);
return (struct monst *) 0;
bhit_done:
if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
transient_light_cleanup();
return result;
}
/* process thrown boomerang, which travels a curving path...