diff --git a/include/context.h b/include/context.h index f2105f147..589a80691 100644 --- a/include/context.h +++ b/include/context.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 context.h $NHDT-Date: 1646428003 2022/03/04 21:06:43 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.45 $ */ +/* NetHack 3.7 context.h $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.58 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -150,6 +150,7 @@ struct context_info { int current_fruit; /* fruit->fid corresponding to svp.pl_fruit[] */ int mysteryforce; /* adjusts how often "mysterious force" kicks in */ int rndencode; /* randomized escape sequence introducer */ + int startingpet_typ; /* monster type for initial pet */ int warnlevel; /* threshold (digit) to warn about unseen mons */ long next_attrib_check; /* next attribute check */ long seer_turn; /* when random clairvoyance will next kick in */ diff --git a/include/patchlevel.h b/include/patchlevel.h index 27a7ac520..ff02f26bc 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 patchlevel.h $NHDT-Date: 1725653013 2024/09/06 20:03:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.264 $ */ +/* NetHack 3.7 patchlevel.h $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.288 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 129 +#define EDITLEVEL 130 /* * Development status possibilities. diff --git a/src/apply.c b/src/apply.c index a4d64bd23..4e3788dd4 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 apply.c $NHDT-Date: 1737275719 2025/01/19 00:35:19 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.464 $ */ +/* NetHack 3.7 apply.c $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.472 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -61,8 +61,8 @@ void do_blinding_ray(struct obj *obj) { struct monst *mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT, - (int (*) (MONST_P, OBJ_P)) 0, - (int (*) (OBJ_P, OBJ_P)) 0, &obj); + (int (*) (MONST_P, OBJ_P)) 0, + (int (*) (OBJ_P, OBJ_P)) 0, &obj); obj->ox = u.ux, obj->oy = u.uy; /* flash_hits_mon() wants this */ if (mtmp) { @@ -100,6 +100,7 @@ use_camera(struct obj *obj) You("take a picture of the %s.", (u.dz > 0) ? surface(u.ux, u.uy) : ceiling(u.ux, u.uy)); } else if (!u.dx && !u.dy) { + /* TODO: we ought to have a "selfie" joke here... */ (void) zapyourself(obj, TRUE); } else { do_blinding_ray(obj); diff --git a/src/dog.c b/src/dog.c index 0682cf610..a583de705 100644 --- a/src/dog.c +++ b/src/dog.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 dog.c $NHDT-Date: 1737287993 2025/01/19 03:59:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.178 $ */ +/* NetHack 3.7 dog.c $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.190 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -214,7 +214,7 @@ make_familiar(struct obj *otmp, coordxy x, coordxy y, boolean quietly) return mtmp; } -/* used exclusively for hero's starting pet */ +/* despite rather general name, used exclusively for hero's starting pet */ struct monst * makedog(void) { @@ -222,10 +222,13 @@ makedog(void) const char *petname; int pettype; - if (gp.preferred_pet == 'n') + if (gp.preferred_pet == 'n') { + /* static init yields 0 (PM_GIANT_ANT); fix that up now */ + svc.context.startingpet_typ = NON_PM; return ((struct monst *) 0); + } - pettype = pet_type(); + pettype = svc.context.startingpet_typ = pet_type(); petname = (pettype == PM_LITTLE_DOG) ? gd.dogname : (pettype == PM_KITTEN) ? gc.catname : (pettype == PM_PONY) ? gh.horsename @@ -264,6 +267,11 @@ makedog(void) put_saddle_on_mon((struct obj *) 0, mtmp); } } + /* starting pet's type has been seen up close (unless PermaBlind) + and for tourist treat it as having already been photographed */ + gb.bhitpos.x = mtmp->mx, gb.bhitpos.y = mtmp->my; + gn.notonhead = FALSE; + see_monster_closeup(mtmp, carrying(EXPENSIVE_CAMERA) ? TRUE : FALSE); } else { impossible("makedog() when startingpet_mid is already non-zero?"); } diff --git a/src/mon.c b/src/mon.c index 891c744f6..a84bb364b 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 mon.c $NHDT-Date: 1722365546 2024/07/30 18:52:26 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.584 $ */ +/* NetHack 3.7 mon.c $NHDT-Date: 1753856387 2025/07/29 22:19:47 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.611 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -5901,16 +5901,52 @@ adj_erinys(unsigned abuse) void see_monster_closeup(struct monst *mtmp, boolean photo) { - if (!svm.mvitals[monsndx(mtmp->data)].seen_close) { - svm.mvitals[monsndx(mtmp->data)].seen_close = TRUE; + int mndx; + + if (Hallucination || (Blind && !Blind_telepat)) + return; + + mndx = monsndx(mtmp->data); + if (M_AP_TYPE(mtmp) == M_AP_MONSTER && !sensemon(mtmp)) + mndx = mtmp->mappearance; + if (mndx == PM_LONG_WORM && gn.notonhead) + mndx = PM_LONG_WORM_TAIL; + + if (!svm.mvitals[mndx].seen_close) { + svm.mvitals[mndx].seen_close = 1; svc.context.lifelist.total_seen_upclose++; } - if (photo && !svm.mvitals[monsndx(mtmp->data)].photographed) { - svm.mvitals[monsndx(mtmp->data)].photographed = 1; - svc.context.lifelist.total_photographed++; - if (Role_if(PM_TOURIST)) { - more_experienced(experience(mtmp, 0), 0); - newexplevel(); + + /* hallucinatory monsters don't reach here--they're not recorded; + being able to see invisible doesn't make invisible monsters show up + on photos; likewise, telepathy allows hero to see hidden monsters + but doesn't cause them to appear on photos */ + if (photo && !mtmp->minvis && !mtmp->mundetected + && (M_AP_TYPE(mtmp) == M_AP_NOTHING + || M_AP_TYPE(mtmp) == M_AP_MONSTER)) { + if (M_AP_TYPE(mtmp) == M_AP_MONSTER) /* cloned Wizard of Yendor */ + mndx = mtmp->mappearance; + + if (!svm.mvitals[mndx].photographed) { + svm.mvitals[mndx].photographed = 1; + svc.context.lifelist.total_photographed++; + + /* tourist earns points (toward EXP but not final score) for + the first instance of each type of monster photographed; + worm tail can be photographed but yields no EXP bonus */ + if (Role_if(PM_TOURIST) + /* suppress extra points for photographing the pet that hero + started with (unless it has changed shape due to growing + up or being polymorphed) */ + && (mtmp->m_id != svc.context.startingpet_mid + || mndx != svc.context.startingpet_typ) + /* monsndx() check covers worm tail and also disguised + Wizard of Yendor; experienced() won't yield a reasonable + value for those */ + && mndx == monsndx(mtmp->data)) { + more_experienced(experience(mtmp, 0), 0); + newexplevel(); + } } } } @@ -5919,19 +5955,32 @@ see_monster_closeup(struct monst *mtmp, boolean photo) void see_nearby_monsters(void) { + struct monst *mtmp; + int mndx; coordxy x, y; - for (x = u.ux - 1; x <= u.ux + 1; x++) - for (y = u.uy - 1; y <= u.uy + 1; y++) - if (isok(x, y) && MON_AT(x, y)) { - struct monst *mtmp = m_at(x, y); + if (Hallucination || (Blind && !Blind_telepat)) + return; - if (canspotmon(mtmp) && !mtmp->mundetected && !M_AP_TYPE(mtmp) - && !svm.mvitals[monsndx(mtmp->data)].seen_close) { - svm.mvitals[monsndx(mtmp->data)].seen_close = 1; - svc.context.lifelist.total_seen_upclose++; - } + for (x = u.ux - 1; x <= u.ux + 1; x++) + for (y = u.uy - 1; y <= u.uy + 1; y++) { + if (!isok(x, y)) + continue; + if (!(mtmp = m_at(x, y))) + continue; + mndx = monsndx(mtmp->data); + if (M_AP_TYPE(mtmp) == M_AP_MONSTER) + mndx = mtmp->mappearance; + /* skip closeup handling if this mon type has already been done */ + if (svm.mvitals[mndx].seen_close) + continue; + /* disguised mimics pass canseemon(); undetected hiders don't */ + if (canseemon(mtmp) || (mtmp->mundetected && sensemon(mtmp))) { + gb.bhitpos.x = x, gb.bhitpos.y = y; + gn.notonhead = (x != mtmp->mx || y != mtmp->my); + see_monster_closeup(mtmp, FALSE); } + } } /* monster resists something.