Merge branch 'NetHack-3.7' into keni-fetchlua

This commit is contained in:
nhkeni
2024-07-29 17:07:17 -04:00
6 changed files with 103 additions and 102 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 extern.h $NHDT-Date: 1720128155 2024/07/04 21:22:35 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1430 $ */
/* NetHack 3.7 extern.h $NHDT-Date: 1722116044 2024/07/27 21:34:04 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1433 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1757,7 +1757,7 @@ extern void kill_genocided_monsters(void);
extern void golemeffects(struct monst *, int, int);
extern boolean angry_guards(boolean);
extern void pacify_guards(void);
extern void decide_to_shapeshift(struct monst *, int) NONNULLARG1;
extern void decide_to_shapeshift(struct monst *) NONNULLARG1;
extern boolean vamp_stone(struct monst *) NONNULLARG1;
extern void check_gear_next_turn(struct monst *) NONNULLARG1;
extern void copy_mextra(struct monst *, struct monst *);

105
src/mon.c
View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 mon.c $NHDT-Date: 1718303201 2024/06/13 18:26:41 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.576 $ */
/* NetHack 3.7 mon.c $NHDT-Date: 1722116051 2024/07/27 21:34:11 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.583 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -712,7 +712,7 @@ make_corpse(struct monst *mtmp, unsigned int corpseflags)
case PM_FIRE_ANT: case PM_GIANT_BEETLE: case PM_QUEEN_BEE:
case PM_QUIVERING_BLOB: case PM_ACID_BLOB: case PM_GELATINOUS_CUBE:
case PM_CHICKATRICE: case PM_COCKATRICE: case PM_PYROLISK:
case PM_CHICKATRICE: case PM_COCKATRICE: case PM_PYROLISK:
case PM_JACKAL: case PM_FOX: case PM_COYOTE: case PM_WEREJACKAL:
case PM_LITTLE_DOG: case PM_DINGO: case PM_DOG: case PM_LARGE_DOG:
@@ -780,7 +780,7 @@ make_corpse(struct monst *mtmp, unsigned int corpseflags)
case PM_GNOME: case PM_GNOME_LEADER: case PM_GNOMISH_WIZARD:
case PM_GNOME_RULER:
case PM_GIANT: case PM_STONE_GIANT: case PM_HILL_GIANT:
case PM_GIANT: case PM_STONE_GIANT: case PM_HILL_GIANT:
case PM_FIRE_GIANT: case PM_FROST_GIANT: case PM_ETTIN:
case PM_STORM_GIANT: case PM_TITAN:
@@ -1151,9 +1151,7 @@ m_calcdistress(struct monst *mtmp)
/* possibly polymorph shapechangers and lycanthropes */
if (ismnum(mtmp->cham))
decide_to_shapeshift(mtmp, (canspotmon(mtmp)
|| engulfing_u(mtmp))
? SHIFT_MSG : 0);
decide_to_shapeshift(mtmp);
were_change(mtmp);
/* gradually time out temporary problems */
@@ -2808,8 +2806,6 @@ lifesaved_monster(struct monst *mtmp)
}
}
DISABLE_WARNING_FORMAT_NONLITERAL
/* when a shape-shifted vampire is killed, it reverts to base form instead
of dying; moved into separate routine to unclutter mondead() */
staticfn boolean
@@ -2820,7 +2816,7 @@ vamprises(struct monst *mtmp)
if (ismnum(mndx) && mndx != monsndx(mtmp->data)
&& !(svm.mvitals[mndx].mvflags & G_GENOD)) {
coord new_xy;
char buf[BUFSZ];
char action[BUFSZ];
/* alternate message phrasing for some monster types */
boolean spec_mon = (nonliving(mtmp->data)
|| noncorporeal(mtmp->data)
@@ -2830,13 +2826,12 @@ vamprises(struct monst *mtmp)
|| amorphous(mtmp->data));
coordxy x = mtmp->mx, y = mtmp->my;
/* construct a format string before transformation;
will be capitalized when used, expects one %s arg */
Snprintf(buf, sizeof buf,
"%s suddenly %s and rises as %%s!",
/* construct a 'before' argument to pass to pline(); this used
to construct a dynamic format string but that's overkill */
Snprintf(action, sizeof action, "%s suddenly %s and rises as",
x_monnam(mtmp, ARTICLE_THE,
spec_mon ? (char *) 0 : "seemingly dead",
(SUPPRESS_INVISIBLE | SUPPRESS_IT), FALSE),
(SUPPRESS_INVISIBLE | AUGMENT_IT), FALSE),
spec_death ? "reconstitutes" : "transforms");
mtmp->mcanmove = 1;
mtmp->mfrozen = 0;
@@ -2857,19 +2852,16 @@ vamprises(struct monst *mtmp)
rloc_to(mtmp, new_xy.x, new_xy.y);
}
(void) newcham(mtmp, &mons[mndx], NO_NC_FLAGS);
if (mtmp->data == &mons[mndx])
mtmp->cham = NON_PM;
else
mtmp->cham = mndx;
mtmp->cham = (mtmp->data == &mons[mndx]) ? NON_PM : mndx;
if (canspotmon(mtmp)) {
/* 3.6.0 used a_monnam(mtmp); that was weird if mtmp was
named: "Dracula suddenly transforms and rises as Dracula";
3.6.1 used mtmp->data->mname; that ignored hallucination */
pline_mon(mtmp, upstart(buf),
x_monnam(mtmp, ARTICLE_A, (char *) 0,
pline_mon(mtmp, "%s %s!", upstart(action),
x_monnam(mtmp, ARTICLE_A, (char *) 0,
(SUPPRESS_NAME | SUPPRESS_IT | SUPPRESS_INVISIBLE),
FALSE));
FALSE));
gv.vamp_rise_msg = TRUE;
}
newsym(x, y);
@@ -2878,8 +2870,6 @@ vamprises(struct monst *mtmp)
return FALSE;
}
RESTORE_WARNING_FORMAT_NONLITERAL
/* specific combination of x_monnam flags for livelogging; show what was
actually killed even when unseen or hallucinated to be something else */
#define livelog_mon_nam(mtmp) \
@@ -4671,16 +4661,12 @@ pick_animal(void)
}
void
decide_to_shapeshift(struct monst *mon, int shiftflags)
decide_to_shapeshift(struct monst *mon)
{
struct permonst *ptr = 0;
int mndx;
unsigned was_female = mon->female;
boolean msg = FALSE, dochng = FALSE;
if ((shiftflags & SHIFT_MSG)
|| ((shiftflags & SHIFT_SEENMSG) && sensemon(mon)))
msg = TRUE;
boolean dochng = FALSE;
if (!is_vampshifter(mon)) {
/* regular shapeshifter */
@@ -4729,11 +4715,27 @@ decide_to_shapeshift(struct monst *mon, int shiftflags)
}
}
if (dochng) {
if (newcham(mon, ptr, msg ? NC_SHOW_MSG : 0) && is_vampshifter(mon)) {
/* for vampshift, override the 10% chance for sex change */
ptr = mon->data;
if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
mon->female = was_female;
unsigned ncflags = (is_vampshifter(mon) || canspotmon(mon))
? NC_SHOW_MSG : 0U;
if (!ncflags) {
/* cheat */
struct permonst *oldptr = mon->data;
mon->data = ptr;
if (canspotmon(mon))
ncflags = NC_SHOW_MSG;
mon->data = oldptr;
}
if (newcham(mon, ptr, ncflags)) {
/* for vampshift, override the 10% chance for sex change
(by forcing original gender in case that occurred) */
if (is_vampshifter(mon)) {
ptr = mon->data;
if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
mon->female = was_female;
}
}
}
}
@@ -5077,10 +5079,11 @@ newcham(
{
boolean polyspot = ((ncflags & NC_VIA_WAND_OR_SPELL) !=0),
/* "The oldmon turns into a newmon!" */
msg = ((ncflags & NC_SHOW_MSG) != 0);
msg = ((ncflags & NC_SHOW_MSG) != 0),
seenorsensed = canspotmon(mtmp);
int hpn, hpd, mndx, tryct;
struct permonst *olddata = mtmp->data;
char *p, oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
char *p, oldname[BUFSZ], l_oldname[BUFSZ];
/* Riders are immune to polymorph and green slime
(but apparent Rider might actually be a doppelganger) */
@@ -5101,9 +5104,10 @@ newcham(
}
if (msg) {
/* like Monnam() but never mention saddle */
Strcpy(oldname, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
SUPPRESS_SADDLE, FALSE));
Strcpy(oldname,
/* like YMonnam() but never mention saddle */
x_monnam(mtmp, mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE,
(char *) 0, SUPPRESS_SADDLE, FALSE));
oldname[0] = highc(oldname[0]);
}
/* we need this one whether msg is true or not */
@@ -5251,17 +5255,20 @@ newcham(
newsym(mtmp->mx, mtmp->my);
if (msg) {
Strcpy(newname, noname_monnam(mtmp, ARTICLE_A));
/* oldname was capitalized above; newname will be lower case */
if (!strcmpi(newname, "it")) { /* can't see or sense it now */
if (!!strcmpi(oldname, "it")) /* could see or sense it before */
pline("%s disappears!", oldname);
/* oldname is capitalized and might be an assigned name */
if (!canspotmon(mtmp)) { /* can't see or sense it now */
if (seenorsensed) /* could see or sense it before */
pline_mon(mtmp, "%s disappears!", oldname);
(void) usmellmon(mdat);
} else { /* can see or sense it now */
if (!strcmpi(oldname, "it")) /* couldn't see or sense it before */
pline("%s appears!", upstart(newname));
else
pline("%s turns into %s!", oldname, newname);
} else if (!seenorsensed) { /* couldn't see/sense before, can now */
char *mnm = x_monnam(mtmp, mtmp->mtame ? ARTICLE_YOUR : ARTICLE_A,
(char *) 0, 0, FALSE);
pline_mon(mtmp, "%s appears!", upstart(mnm));
} else { /* saw/sensed it before, still see/sense it now */
pline_mon(mtmp, "%s turns into %s!", oldname,
/* "a <monster type>" even if it has a name assigned */
noname_monnam(mtmp, ARTICLE_A));
}
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 monmove.c $NHDT-Date: 1701435190 2023/12/01 12:53:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.229 $ */
/* NetHack 3.7 monmove.c $NHDT-Date: 1722116054 2024/07/27 21:34:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.255 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -18,9 +18,9 @@ staticfn boolean holds_up_web(coordxy, coordxy);
staticfn int count_webbing_walls(coordxy, coordxy);
staticfn boolean soko_allow_web(struct monst *);
staticfn boolean m_search_items(struct monst *, coordxy *, coordxy *, int *,
int *);
int *) NONNULLPTRS;
staticfn int postmov(struct monst *, struct permonst *, coordxy, coordxy, int,
boolean, boolean, boolean, boolean);
unsigned, boolean, boolean, boolean) NONNULLPTRS;
staticfn boolean leppie_avoidance(struct monst *);
staticfn void leppie_stash(struct monst *);
staticfn boolean m_balks_at_approaching(struct monst *);
@@ -598,19 +598,20 @@ mind_blast(struct monst *mtmp)
}
}
/* called every turn for each living monster on the map,
and the hero */
/* called every turn for each living monster on the map, and the hero;
caller makes sure that we're not called for DEADMONSTER() */
void
m_everyturn_effect(struct monst *mtmp)
{
boolean is_u = (mtmp == &gy.youmonst) ? TRUE : FALSE;
coordxy x = is_u ? u.ux : mtmp->mx,
y = is_u ? u.uy : mtmp->my;
y = is_u ? u.uy : mtmp->my;
if (mtmp->data == &mons[PM_FOG_CLOUD]) {
NhRegion *reg = visible_region_at(x, y);
if (!reg)
/* don't leave a vapor cloud if some other gas cloud is already
present, or when flowing under closed doors so that visibility
changes aren't mixed with messages about doing such */
if (!closed_door(x, y) && !visible_region_at(x, y))
create_gas_cloud(x, y, 1, 0); /* harmless vapor */
}
}
@@ -626,7 +627,7 @@ m_postmove_effect(struct monst *mtmp)
{
boolean is_u = (mtmp == &gy.youmonst) ? TRUE : FALSE;
coordxy x = is_u ? u.ux0 : mtmp->mx,
y = is_u ? u.uy0 : mtmp->my;
y = is_u ? u.uy0 : mtmp->my;
/* Hezrous create clouds of stench. This does not cost a move. */
if (mtmp->data == &mons[PM_HEZROU]) /* stench */
@@ -1371,7 +1372,7 @@ m_search_items(
}
}
finish_search:
finish_search:
if (minr < SQSRCHRADIUS && *appr == -1) {
if (distmin(omx, omy, mtmp->mux, mtmp->muy) <= 3) {
*ggx = mtmp->mux;
@@ -1390,7 +1391,7 @@ postmov(
struct permonst *ptr,
coordxy omx, coordxy omy,
int mmoved,
boolean sawmon,
unsigned seenflgs,
boolean can_tunnel,
boolean can_unlock,
boolean can_open)
@@ -1419,15 +1420,18 @@ postmov(
&& IS_DOOR(levl[nix][niy].typ)
&& ((levl[nix][niy].doormask & (D_LOCKED | D_CLOSED)) != 0)
&& can_fog(mtmp)) {
if (sawmon) {
/* note: remove_monster()+place_monster is not right for
long worms but they won't reach here */
if (seenflgs) {
remove_monster(nix, niy);
place_monster(mtmp, omx, omy);
newsym(nix, niy), newsym(omx, omy);
}
if (vamp_shift(mtmp, &mons[PM_FOG_CLOUD], sawmon)) {
if (vamp_shift(mtmp, &mons[PM_FOG_CLOUD],
((seenflgs & 1) != 0) ? TRUE : FALSE)) {
ptr = mtmp->data; /* update cached value */
}
if (sawmon) {
if (seenflgs) {
remove_monster(omx, omy);
place_monster(mtmp, nix, niy);
newsym(omx, omy), newsym(nix, niy);
@@ -1475,7 +1479,7 @@ postmov(
if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
&& amorphous(ptr)) {
if (flags.verbose && canseemon(mtmp))
pline_mon(mtmp, "%s %s under the door.", Monnam(mtmp),
pline_mon(mtmp, "%s %s under the door.", YMonnam(mtmp),
(ptr == &mons[PM_FOG_CLOUD]
|| ptr->mlet == S_LIGHT) ? "flows" : "oozes");
} else if (here->doormask & D_LOCKED && can_unlock) {
@@ -1647,7 +1651,7 @@ m_move(struct monst *mtmp, int after)
boolean getitems = FALSE;
boolean avoid = FALSE;
boolean better_with_displacing = FALSE;
boolean sawmon = canspotmon(mtmp); /* before it moved */
unsigned seenflgs;
struct permonst *ptr;
int chi, mmoved = MMOVE_NOTHING; /* not strictly nec.: chi >= 0 will do */
long info[9];
@@ -1673,9 +1677,13 @@ m_move(struct monst *mtmp, int after)
return MMOVE_DONE; /* still eating */
}
if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my)
&& can_hide_under_obj(svl.level.objects[mtmp->mx][mtmp->my]) && rn2(10))
&& can_hide_under_obj(svl.level.objects[mtmp->mx][mtmp->my])
&& rn2(10))
return MMOVE_NOTHING; /* do not leave hiding place */
/* set up pre-move visibility flags */
seenflgs = (canseemon(mtmp) ? 1 : 0) | (canspotmon(mtmp) ? 2 : 0);
/* Where does 'mtmp' think you are? Not necessary if m_move() called
from this file, but needed for other calls of m_move(). */
set_apparxy(mtmp); /* set mtmp->mux, mtmp->muy */
@@ -1691,7 +1699,7 @@ m_move(struct monst *mtmp, int after)
/* my dog gets special treatment */
if (mtmp->mtame) {
return postmov(mtmp, ptr, omx, omy, dog_move(mtmp, after),
sawmon, can_tunnel, can_unlock, can_open);
seenflgs, can_tunnel, can_unlock, can_open);
}
/* and the acquisitive monsters get special treatment */
@@ -1720,7 +1728,7 @@ m_move(struct monst *mtmp, int after)
mmoved = MMOVE_NOTHING;
}
return postmov(mtmp, ptr, omx, omy, mmoved,
sawmon, can_tunnel, can_unlock, can_open);
seenflgs, can_tunnel, can_unlock, can_open);
}
/* likewise for shopkeeper, guard, or priest */
@@ -1742,7 +1750,7 @@ m_move(struct monst *mtmp, int after)
case 1:
return postmov(mtmp, ptr, omx, omy,
(xm != 1) ? MMOVE_NOTHING : MMOVE_MOVED,
sawmon, can_tunnel, can_unlock, can_open);
seenflgs, can_tunnel, can_unlock, can_open);
}
}
@@ -1765,7 +1773,7 @@ m_move(struct monst *mtmp, int after)
else
mnexto(mtmp, RLOC_MSG);
return postmov(mtmp, ptr, omx, omy, MMOVE_MOVED,
sawmon, can_tunnel, can_unlock, can_open);
seenflgs, can_tunnel, can_unlock, can_open);
}
not_special:
if (u.uswallow && !mtmp->mflee && u.ustuck != mtmp)
@@ -1825,7 +1833,7 @@ m_move(struct monst *mtmp, int after)
if (getitems && m_search_items(mtmp, &ggx, &ggy, &mmoved, &appr))
return postmov(mtmp, ptr, omx, omy, mmoved,
sawmon, can_tunnel, can_unlock, can_open);
seenflgs, can_tunnel, can_unlock, can_open);
/* don't tunnel if hostile and close enough to prefer a weapon */
if (can_tunnel && needspick(ptr)
@@ -1988,7 +1996,7 @@ m_move(struct monst *mtmp, int after)
worm_nomove(mtmp);
}
return postmov(mtmp, ptr, omx, omy, mmoved,
sawmon, can_tunnel, can_unlock, can_open);
seenflgs, can_tunnel, can_unlock, can_open);
}
/* The part of m_move that deals with a monster attacking another monster (and
@@ -2287,6 +2295,9 @@ can_fog(struct monst *mtmp)
return FALSE;
}
/* this is called when a vampire turns into a fog cloud in order to move
under a closed door; if it was sensed via telepathy or seen via
infravision, its new fog cloud shape will disappear */
staticfn int
vamp_shift(
struct monst *mon,
@@ -2294,34 +2305,16 @@ vamp_shift(
boolean domsg)
{
int reslt = 0;
char oldmtype[BUFSZ];
boolean sawmon = canseemon(mon); /* before shape change */
/* remember current monster type before shapechange */
Strcpy(oldmtype, domsg ? noname_monnam(mon, ARTICLE_THE) : "");
if (mon->data == ptr) {
/* already right shape */
reslt = 1;
domsg = FALSE;
} else if (is_vampshifter(mon)) {
reslt = newcham(mon, ptr, NO_NC_FLAGS);
}
if (reslt && domsg) {
/* might have seen vampire/bat/wolf with infravision then be
unable to see the same creature when it turns into a fog cloud */
if (canspotmon(mon))
You("%s %s where %s was.",
!canseemon(mon) ? "now detect" : "observe",
noname_monnam(mon, ARTICLE_A), oldmtype);
else
You("can no longer %s %s.", sawmon ? "see" : "sense", oldmtype);
/* this message is given when it turns into a fog cloud
in order to move under a closed door */
reslt = newcham(mon, ptr, domsg ? NC_SHOW_MSG : NO_NC_FLAGS);
/* shape-change message is given when vampshifter turns into a
fog cloud in order to move under a closed door */
display_nhwindow(WIN_MESSAGE, FALSE);
}
return reslt;
}

View File

@@ -227,7 +227,7 @@ nhmain(int argc, char *argv[])
/* wizard mode access is deferred until here */
set_playmode(); /* sets plname to "wizard" for wizard mode */
/* hide any hyphens from plnamesuffix() */
svp.plnamelen = exact_username ? (int) strlen(svp.plname) : 0;
gp.plnamelen = exact_username ? (int) strlen(svp.plname) : 0;
/* strip role,race,&c suffix; calls askname() if plname[] is empty
or holds a generic user name like "player" or "games" */
plnamesuffix();
@@ -382,12 +382,12 @@ process_options(int argc, char *argv[])
case 'u':
if (argv[0][2]) {
(void) strncpy(svp.plname, argv[0] + 2, sizeof svp.plname - 1);
svp.plnamelen = 0; /* plname[] might have -role-race attached */
gp.plnamelen = 0; /* plname[] might have -role-race attached */
} else if (argc > 1) {
argc--;
argv++;
(void) strncpy(svp.plname, argv[0], sizeof svp.plname - 1);
svp.plnamelen = 0;
gp.plnamelen = 0;
} else {
raw_print("Player name expected after -u");
}

View File

@@ -82,10 +82,10 @@ dodata:
endif # CROSS_TO_MSDOS
ifdef CROSS_TO_WASM
$(WASM_TARGET): pregame $(TARGETPFX)date.o $(HOSTOBJ) $(HOBJ) $(LUACROSSLIB) $(WASM_DATA_DIR)
$(WASM_TARGET): pregame $(TARGET_HACKLIB) $(TARGETPFX)date.o $(HOSTOBJ) $(HOBJ) $(LUACROSSLIB) $(WASM_DATA_DIR)
-rm $@
$(TARGET_CC) $(TARGET_LFLAGS) $(TARGET_CFLAGS) -o $@ \
$(HOBJ) $(TARGETPFX)date.o $(TARGET_LIBS)
$(HOBJ) $(TARGETPFX)date.o $(TARGET_HACKLIB) $(TARGET_LIBS)
$(WASM_DATA_DIR): $(WASM_DATA_DIR)/nhdat
touch $(WASM_DATA_DIR)/perm

View File

@@ -275,7 +275,8 @@ WASM_CFLAGS += -Wshadow
# Nethack C flags
WASM_CFLAGS += $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
WASM_CFLAGS += -DSYSCF -DSYSCF_FILE=\"/sysconf\" -DSECURE
WASM_CFLAGS += -g -I../include -DNOTPARMDECL
#WASM_CFLAGS += -g -I../include -DNOTPARMDECL
WASM_CFLAGS += -I../include -DNOTPARMDECL
# NetHack sources control
WASM_CFLAGS += -DDLB
WASM_CFLAGS += -DHACKDIR=\"$(HACKDIR)\"