diff --git a/include/extern.h b/include/extern.h index 0be195583..27c308019 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *); diff --git a/src/mon.c b/src/mon.c index da6efd321..97a7faed5 100644 --- a/src/mon.c +++ b/src/mon.c @@ -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 " even if it has a name assigned */ + noname_monnam(mtmp, ARTICLE_A)); } } diff --git a/src/monmove.c b/src/monmove.c index 0c563c3de..5822d5fc9 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -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; } diff --git a/sys/libnh/libnhmain.c b/sys/libnh/libnhmain.c index 06f8c93d0..d43cdc362 100644 --- a/sys/libnh/libnhmain.c +++ b/sys/libnh/libnhmain.c @@ -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"); } diff --git a/sys/unix/hints/include/cross-post.370 b/sys/unix/hints/include/cross-post.370 index f8106995a..557b3504a 100644 --- a/sys/unix/hints/include/cross-post.370 +++ b/sys/unix/hints/include/cross-post.370 @@ -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 diff --git a/sys/unix/hints/include/cross-pre2.370 b/sys/unix/hints/include/cross-pre2.370 index 55294e286..fa5f0911c 100644 --- a/sys/unix/hints/include/cross-pre2.370 +++ b/sys/unix/hints/include/cross-pre2.370 @@ -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)\"