From f145cc02f4eab11dacac08feb60a5d1fa062f868 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 26 Jul 2025 11:03:20 -0400 Subject: [PATCH] photograph experience gains often counted only prior to first move More details in https://github.com/NetHack/NetHack/issues/1430 track photographed monsters using a distinct bit also adds a pair of new context fields to track the total number of monsters seen up close, and the total number of monsters photographed. So, if somebody wants to add unique end-of-game disclosure statements for tourists that relate to those, the groundwork should be there. NOTE: This increments EDITLEVEL, so existing save and bones files will become outdated. Fixes #1430 --- include/context.h | 6 ++++++ include/extern.h | 2 +- include/hack.h | 1 + include/patchlevel.h | 2 +- src/apply.c | 2 +- src/mon.c | 16 ++++++++++++---- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/context.h b/include/context.h index 73fee29bc..f2105f147 100644 --- a/include/context.h +++ b/include/context.h @@ -135,6 +135,11 @@ struct achievement_tracking { boolean minetn_reached; /* avoid redundant checking for town entry */ }; +struct lifelists { + long total_seen_upclose; /* count of critters seen up close */ + long total_photographed; /* count of critters photographed (tourists) */ +}; + struct context_info { unsigned ident; /* social security number for each monster */ unsigned no_of_wizards; /* 0, 1 or 2 (wizard and his shadow) */ @@ -175,6 +180,7 @@ struct context_info { struct tribute_info tribute; struct novel_tracking novel; struct achievement_tracking achieveo; + struct lifelists lifelist; char jingle[5 + 1]; }; diff --git a/include/extern.h b/include/extern.h index 1d3e5ade1..c8180ec44 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1812,7 +1812,7 @@ extern void dealloc_mextra(struct monst *); extern boolean usmellmon(struct permonst *); extern void mimic_hit_msg(struct monst *, short); extern void adj_erinys(unsigned); -extern void see_monster_closeup(struct monst *) NONNULLARG1; +extern void see_monster_closeup(struct monst *, boolean) NONNULLARG1; extern void see_nearby_monsters(void); extern void shieldeff_mon(struct monst *) NONNULLARG1; extern void flash_mon(struct monst *) NONNULLARG1; diff --git a/include/hack.h b/include/hack.h index fcb669d10..99eaca753 100644 --- a/include/hack.h +++ b/include/hack.h @@ -670,6 +670,7 @@ struct mvitals { uchar died; uchar mvflags; Bitfield(seen_close, 1); + Bitfield(photographed, 1); }; diff --git a/include/patchlevel.h b/include/patchlevel.h index 1de0380b0..27a7ac520 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 128 +#define EDITLEVEL 129 /* * Development status possibilities. diff --git a/src/apply.c b/src/apply.c index 3e7370c4a..a4d64bd23 100644 --- a/src/apply.c +++ b/src/apply.c @@ -68,7 +68,7 @@ do_blinding_ray(struct obj *obj) if (mtmp) { (void) flash_hits_mon(mtmp, obj); if (obj->otyp == EXPENSIVE_CAMERA) - see_monster_closeup(mtmp); + see_monster_closeup(mtmp, TRUE); /* TRUE for photo */ } /* normally bhit() would do this but for FLASHED_LIGHT we want it to be deferred until after flash_hits_mon() */ diff --git a/src/mon.c b/src/mon.c index ade679695..891c744f6 100644 --- a/src/mon.c +++ b/src/mon.c @@ -5896,13 +5896,18 @@ adj_erinys(unsigned abuse) pm->difficulty = min(10 + (u.ualign.abuse / 3), 25); } -/* mark monster type as seen from close-up, +/* mark individual monster type as seen from close-up, if we haven't seen it nearby before */ void -see_monster_closeup(struct monst *mtmp) +see_monster_closeup(struct monst *mtmp, boolean photo) { if (!svm.mvitals[monsndx(mtmp->data)].seen_close) { svm.mvitals[monsndx(mtmp->data)].seen_close = TRUE; + 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(); @@ -5921,8 +5926,11 @@ see_nearby_monsters(void) if (isok(x, y) && MON_AT(x, y)) { struct monst *mtmp = m_at(x, y); - if (canspotmon(mtmp) && !mtmp->mundetected && !M_AP_TYPE(mtmp)) - svm.mvitals[monsndx(mtmp->data)].seen_close = TRUE; + 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++; + } } }