Commit Graph

305 Commits

Author SHA1 Message Date
PatR
c08f79b26e more photographing monsters
Don't record hallucinated monsters as having been seen up close or as
photographed.

Treat a tourist's starting pet has having been photographed prior to
bringing the camera and dog or cat into the dungeon.

No extra points to tourist when first long worm tail is photographed.

EDITLEVEL is incremented again, for extra context to track starting
pet.
2025-07-29 15:45:11 -07:00
nhmall
f145cc02f4 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
2025-07-26 11:03:20 -04:00
Pasi Kallinen
e240efa10b Restoring a game can return to the wishing prompt
In TTY or curses, if the terminal goes away while you're in the wishing
prompt, return to the prompt when the game is restored.

Breaks saves.
2025-07-12 18:21:12 +03:00
Alex Smith
308c5ab237 The Amulet of Yendor gives a wish when initially picked up
Part 4 of implementing wish spreading. (This is now a complete
implementation, although the details are likely to change - but it
makes sense to commit something with the right balance properties,
and then tweak it based on feedback from playtesting.)

This helps to make the Amulet of Yendor feel special, and restores
approximately the same average number of wishes per game as existed
prior to the nerf to wands of wishing.

Placing the wish in allmain helps to avoid the wish happening at an
awkward place in the game's control flow, and is simpler than
testing every possible mechanism for gaining items for bugs (message
order is a common issue when trying to place it in addinv-related
functions, and this also avoids issues with the wished-for item
immediately invalidating an assumption that was made by the calling
code).

It is possible that this would be better as an invoke effect,
although I like the impact of picking up the Amulet and immediately
being given a wish.
2025-05-30 02:10:58 +01:00
Alex Smith
0e50adcc1e Restore monsters.h to its previous order
This causes the difficulties to get out of sequence, but we agreed
that this is a less important rule than keeping monster IDs stable.

Breaks save and bones files, because it changes monster IDs.
2025-05-29 19:14:10 +01:00
Alex Smith
47724f0137 Increase generation depth of soldier ants and killer bees
These two types of monster were extreme outliers in terms of where
they appeared versus how lethal they were (3-4 times as deadly as
other monsters that appeared at similar depth, based on statistics
from actual play), so their generation depth has been manually
modified.

Breaks save and bones files (because monster type IDs have to be
sorted numerically by difficulty, and changing difficulties thus
changes the IDs, but the IDs are used to identify the monsters in
save files).
2025-05-29 17:53:38 +01:00
Pasi Kallinen
035cd4377f Snickersnee can hit at a distance once per turn for free
Once per turn, Snickersnee can be used to hit at a distance,
similar to a polearm, without taking any time.

Breaks saves.
2025-05-12 20:26:53 +03:00
nhmall
502b60d210 follow-up bit
oextra should have been included in the critical bytes
2025-04-15 15:49:36 -04:00
nhmall
a3e12550ea savefile changes - part 1
This is the first of several savefile-related changes to
follow later. This one is groundwork for those later changes.

Remove internal compression schemes (RLECOMP and ZEROCOMP)
and discard the savefile_info struct that was primarily used to
convey which internal compression schemes had been in use.

Relocate some struct definitions into appropriate header files
for use by code to come in later changes.

Remove the two struct size-related fields from version_info and
from the nmakedefs_s. Instead, include a series of bytes near the
beginning of the savefile, representing the size of each
struct or base data type that impacts the historical savefile
content. Those are referred to as the "critical bytes".
(Related note: the "you" struct required two bytes, low and high,
due to its size).

Compare those critical bytes in a savefile against the NetHack
build that is reading the savefile. This allows mismatch detection
early in the savefile-reading process, and a clean exit, rather than
proceeding to read nonsensical values from the file. Include some
feedback on what the first mismatch was when encountering
one.

For arrays stored in the savefile, use loop-logic in the core
to write/read the array elements one at a time, rather than in
a single blob. This will be required for changes to follow later.
(impacts artiexist[], artidisco[], svd.dungeons[], svl.level_info[],
svl.level.locations[][], msrooms[] field of mapseen, svb.bases[],
svb.disco[] objects[], svm.mvitals[], svs.spl_book[], svd.doors[],
go.oracle_loc[], utrack[], wgrowtime[])

This also adds data model to the long version information.

This invalidates existing save and bones files due to the changes in
the information at the start of the file.
2025-04-15 15:35:17 -04:00
Pasi Kallinen
197e6af78c Increment EDITLEVEL for silver maces 2025-04-09 21:26:22 +03:00
Pasi Kallinen
3cb7819c81 Split monster goal coordinate out of mstrategy field
Instead of packing a coordinate into unsigned long, store the goal in
a coord struct, making the code a bit cleaner.  Monster struct is
of course slightly bigger, but that should not really matter.
No change in monster behaviour.

Breaks saves and bones.
2025-02-16 10:46:21 +02:00
nhmall
c24786430f 'struct former' -> 'struct ebones'
Some variants were already using a similar approach
using a struct called 'ebones', so adopt the same naming
so NetHack-3.7, hardfought, and some variants are using
the same name.

As before there are fields in the struct that are not
currently used by NetHack-3.7, but the intent is that
hardfought save and bones files can be loaded by
NetHack-3.7 without code modification, for debugging
bug reports.

This invalidates existing save and bones files.
2025-02-04 15:16:42 -05:00
nhmall
d65d0062a9 follow-up: evolve placeholder content to match variant
suggestion by paxed

Increments EDITLEVEL again.
2025-02-02 12:53:58 -05:00
nhmall
d331029b03 more clobber-detection 2025-02-02 09:08:48 -05:00
nhmall
bda3437eab bump EDITLEVEL 2025-02-02 09:00:21 -05:00
nhmall
e08a9671dc another follow-up: another bit is needed
breaks savefiles and bones.
2025-01-12 14:08:15 -05:00
nhmall
35f2ca44e2 update year in COPYRIGHT_BANNER_A to 2025 2025-01-01 08:46:41 -05:00
nhmall
21d35e768c bump EDITLEVEL for previous two commits DEC19-2024 2024-12-19 17:54:55 -05:00
Pasi Kallinen
87694e1a95 Hero remembers trapped boxes
After finding a trap on a chest or a large box, remember it
as trapped: "You see here a trapped large box."
Randomly generated chests and boxes can be obviously trapped.
Allow defining obviously trapped containers via lua.

Invalidates saves and bones.
2024-12-19 13:11:25 +02:00
nhmall
1f8b75b8c6 different ls content values, so bump EDITLEVEL 2024-12-09 16:21:31 -05:00
Pasi Kallinen
89c4c3a722 Tourists gain experience by seeing new types of creatures up close
Experience equivalent to killing a monster is gained when starting a turn
adjacent to and being able to see the monster.

Breaks saves.

Idea and parts of code via dNetHack
2024-12-06 21:30:23 +02:00
PatR
d32ab55b84 new property: BLND_RES
Add enlightenment feedback for Sunsword's blocking of becoming blind
from light flashes.  It uses an extra property so that wizard mode
can report the reason.

EDITLEVEL is being incremented, so existing save and bones files are
invalidated.
2024-11-26 20:57:11 -08:00
PatR
11a4fe42de 'selectsaved' again - update EDITLEVEL again
The role, race, gender, and alignment string values are 3 letters
preceded by a dash.  I was looking at "name-race-role-gend-algn"
and mistakenly treated them as 4 letters preceded by a dash.

Fixing that changes PL_NSIZ_PLUS and there is one item of that size
written into save files, so the fix invalidates existing save files.
2024-10-11 22:35:38 -07:00
PatR
1f36b98b8f 'selectsaved' extension
Instead of a menu listing
 a - hero1
 b - hero2
 n - New game
 q - Quit
show
 a - hero1-role1-race1-gend1-algn1
 b - hero2-role2-race2-gend2-algn2
 n - New game
 q - Quit
or
 a - - hero1-role1-race1-gend1-algn1
 b - X hero2-role2-race2-gend2-algn2
 c - D wizard-role3-race3-gend3-algn3
 n - New game
 q - Quit
when any game in the list wasn't saved during normal play.  (Those
are sorted by character name; the playmode is just coincidence.)

The dash for 'normal' doesn't look great but -/X/D are codes used in
entries written to paniclog.  The whole playmode prefix doesn't look
particularly good but I suspect that most players relying on restore
via menu won't see it.

It should work when the character name has dashes in it but that
hasn't been properly tested.

The gender and alignment suffices reflect their value at the time of
save rather than at the start of the game.  That might be considered
a bug but it was easiest.

Increments EDITLEVEL; existing save and bones files are invalidated.
2024-10-10 23:14:25 -07:00
PatR
cf6509dde9 some reformatting (5 of 4)
Take care of most of include/*.h.  I punted on extern.h.

For both src/*.c and include/*.h, I used mismatched checks of
width > 79 to decide which files to look at and then width > 78
to decide which lines to maybe revise, so I didn't look at a bunch
of the files.

I don't plan to go back and do it right.  Shortening lines that are
80 or wider to less than 80 is the significant part.  Otherwise
emacs puts a backslash in column 80 and the rest of the line of text
on the next line of the screen, making things harder to read.
2024-09-06 13:08:07 -07:00
Pasi Kallinen
e645c0b4bb Allow starting game as pauper, without any inventory
And also without spells, skills, or preidentified items.
This also implies nudist.

Breaks saves and bones.
2024-08-29 20:51:13 +03:00
nhmall
6c0ae092c6 distinguish global variables that get written to savefile
The g? structs had a mix of variables that were written to
the savefile, and those that were not.

For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.

This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.

Details:

    gb.bases            -> svb.bases
    gb.bbubbles         -> svb.bbubbles
    gb.branches         -> svb.branches
    gc.context          -> svc.context
    gd.disco            -> svd.disco
    gd.dndest           -> svd.dndest
    gd.doors            -> svd.doors
    gd.doors_alloc      -> svd.doors_alloc
    gd.dungeon_topology -> svd.dungeon_topology
    gd.dungeons         -> svd.dungeons
    ge.exclusion_zones  -> sve.exclusion_zones
    gh.hackpid          -> svh.hackpid
    gi.inv_pos          -> svi.inv_pos
    gk.killer           -> svk.killer
    gl.lastseentyp      -> svl.lastseentyp
    gl.level            -> svl.level
    gl.level_info       -> svl.level_info
    gm.mapseenchn       -> svm.mapseenchn
    gm.moves            -> svm.moves
    gm.mvitals          -> svm.mvitals
    gn.n_dgns           -> svn.n_dgns
    gn.n_regions        -> svn.n_regions
    gn.nroom            -> svn.nroom
    go.oracle_cnt       -> svo.oracle_cnt
    gp.pl_character     -> svp.pl_character
    gp.pl_fruit         -> svp.pl_fruit
    gp.plname           -> svp.plname
    gp.program_state    -> svp.program_state
    gq.quest_status     -> svq.quest_status
    gr.rooms            -> svr.rooms
    gs.sp_levchn        -> svs.sp_levchn
    gs.spl_book         -> svs.spl_book
    gt.timer_id         -> svt.timer_id
    gt.tune             -> svt.tune
    gu.updest           -> svu.updest
    gx.xmax             -> svx.xmax
    gx.xmin             -> svx.xmin
    gy.ymax             -> svy.ymax
    gy.ymin             -> svy.ymin

Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
          gf.ftrap, gl.light_base, gt.timer_base
2024-07-13 14:57:50 -04:00
PatR
0e4083153c another EDITLEVEL increment
Since save and bones files just got clobbered, make another clobbering
change.  The 'queuedpay' field added to shop's ESHK(shkp)->bill[] was
replaced last week by a similar field in the transient itemizing bill.
At the time, the old field was left in place to avoid incrementing
EDITLEVEL.

shkp->mextra->bill[] is saved and restored, so its queuedpay field was
too.  Eliminate that no longer used field.

Unrelated:  bill[]->useup is declared as boolean but being assigned 1
or 0.  Change the assignments to use TRUE or FALSE.
2024-07-11 10:22:40 -07:00
Patric Mueller
b844632dfd bump EDITLEVEL for 0447a1f10
Commit 0447a1f10 accidentally broke save compatibility.
2024-07-11 16:35:24 +02:00
Pasi Kallinen
7139ee7446 Move light source and timer types so zero means none
Breaks saves and bones.
2024-05-06 19:58:21 +03:00
Pasi Kallinen
28ed8e7962 Unblind telepathy range
Unblind telepathy range depends on the number of telepathy granting
items worn.

Breaks saves.
2024-04-04 23:22:28 +03:00
RainRat
a3658f85ac fix typos 2024-02-28 20:15:56 -08:00
nhmall
b53a43027f generic obj addition broke obj entity count use
yet another EDITLEVEL bump
2024-02-28 16:24:40 -05:00
nhmall
3edd3e5869 catch invalid id on restore
Another EDITLEVEL bump.
2024-02-28 16:15:30 -05:00
nhmall
1a02a2df16 purge a couple of placeholders from context struct
Take advantage of today's EDITLEVEL bump, and add yet another to
remove some field placeholders left behind in when two fields were moved
elsewhere in 22e52ee9.
2024-02-28 15:54:34 -05:00
PatR
41a5565403 new 'showvers' option
Add options 'showvers' (boolean) and 'versinfo' (numeric mask) to
show nethack's version on the status lines during play.  It won't be
particularly interesting to ordinary players but should be useful
when making screenshots or video to be streamed, or for someone who
switches between git branches or between nethack and variants.

I worked on this several months back but it was combined with
unfinished changes to 'hitpointbar'.  I've separated it out so that
it can be put into use.  When enabled, one or more components of
"<name> <branch> <version>" will be shown right justified after
status conditions.  At present the default is "<branch>" if that is
available and overall status isn't 'released', or "<version>" if
'released' or if branch isn't available.  That might need some
refinement.

It works as intended for tty and curses, although some abbreviation
mechanism would be useful if/when the program resorts to abbreviating
status conditions to make things narrow enough to fit.

For X11, it works ok for fancy_status:True (the default, controlled
via NetHack.ad settings) but is messed up for tty-style status.  The
text is positioned correctly but there are gaps in it, making it
appear garbled, similar to what I saw when I tried and failed to
implement statuslines:3 for X11.  [It might be due to having empty
condition widgets be 1 pixel wide instead of being totally removed
but I don't think the situation is that simple.]

For Qt, if the text needs to be truncated in order to fit, the center
portion of the string will be shown, discarding parts from the left
and right.  That ought to discard from left and retain rightmost
portion instead.

For win32|mswin|Win GUI, no attempt to support it has been included.
Things should be ok when 'showvers' is left as False (the default)
but I don't know what will happen if that gets toggled to True.  At a
minimum, the version info won't be right justified.  The information,
or at least some of it, is displayed in the game window's title bar
so there isn't any pressing need to add it to status, but toggling
the option will need to behave sensibly if it doesn't already.
2024-02-28 11:47:16 -08:00
Pasi Kallinen
3160112ece Accessibility: Show a message when monster is spotted
Adds a new boolean option, spot_monsters.  If on, every time
the hero notices a monster which was out of sight before,
a message is given.  Combine with accessiblemsg to get the
monster location:

(3north): You see a newt.

Breaks saves and bones.
2024-01-14 13:33:02 +02:00
PatR
02c675078b PR #1150 - rework erinyes into avenging Furies
Pull request from entrez:  change erinyes from lame devils named
after the Furies of Greek myth into those Furies.

Bumps EDITLEVEL because of changes to saved data.  I augmented the
new data.base entry.

Closes #1150
2024-01-10 23:22:56 -08:00
nhmall
aeab3f69a6 update year in copyright to 2024 2024-01-01 11:04:26 -05:00
PatR
7a533a911c enhance timer sanity checks a bit
Four kinds of timers are defined but only two have ever been used.
Have sanity checking complain if the other two occur or if 'kind'
doesn't match any of the four.

Also, replacing a perfectly normal use of isok() with an inline test
just to pacify static analysis feels like a slippery slope, so handle
that a little differently.

I reordered the shrink_glob timer to put all object timers together.
Unfortunately that warrants incrementing EDITLEVEL which invalidates
existing save files.
2023-12-22 17:48:51 -08:00
Pasi Kallinen
1ceb9d2d91 Show menu when paying items
... and have more than 1 billed item, and using non-traditional
menustyle.

I opted to add an extra field to the bill struct, because
that made the code cleaner.

Breaks saves and bones.
2023-12-09 12:43:41 +02:00
PatR
c459630bf3 bump EDITLEVEL for nopick_dropped+pickup_stolen
Despite the tag on the pull request (#1140), I forgot to increment
EDITLEVEL to reflect the new options' affect on old save files.
2023-12-08 15:49:16 -08:00
Alex Smith
0d508cc936 Implement the spellbook of chain lightning
Prior to this commit, there was no good way to deal with swarms of
weak, good-AC enemies using magic; trying to play a wizard as a
pure spellcaster would make bees and ants very difficult to deal
with (because they would usually dodge force bolts).

This commit adds a new spell designed to be very good against
swarms of weak enemies: "chain lightning", which does 2d6 lightning
damage to every monster around you. It has an initially short range,
but can chain from monster to monster to cover potentially large
distances (as long as none of the monsters en route are shock
resistant or tame/peaceful; the spell can't chain past shock
resistant monsters and avoids peacefuls). Monsters within one
space of the visible lightning bolts are affected. Unlike other
lightning effects, this one does only 2d6 damage, not enough to
blind affected monsters.

This commit breaks existing save and bones files (thus the
EDITLEVEL increase).
2023-12-06 20:02:35 +00:00
Pasi Kallinen
d8421aa219 Save and restore hero tracks
The tracks left by hero were cleared when player saved and
restored the game, or changed levels.  Now the tracks are
saved in the dungeon level, so changing levels keeps the tracks
left by hero in that level.

Also increased the length of tracks from 50 to 100, and
simplify the tracking function.

Thing not done: fade out old tracks when returning to a level.

Breaks saves and bones.
2023-12-04 17:50:48 +02:00
nhmall
3c82780c1c bump patchlevel for u field addition 2023-12-02 11:31:58 -05:00
Pasi Kallinen
e407af4477 Allow defining random-teleport exclusion zones in lua
Adds a new lua command

  des.exclusion({ type = "teleport", region = { x1,y1, x2,y2 } });

which allows defining "exclusion zones" in the level, areas where
random teleports (or falling into the level) will never place the hero.
Does not prevent targeted teleportation into the area.

Breaks saves and bones.
2023-08-24 18:38:39 +03:00
PatR
60a3263a85 fix github issue #1070 - Minetown achievement
Issue reported by vultur-cadens:  arriving on the Mine Town level
via falling or level teleport won't register the "entered Minetown"
achievement if hero doesn't arrive inside a room.

Reorder some code in check_special_room() so that town entry will be
tested before the early return if no room entry has occurred.  This
adds 'level.flags.has_town' to make the town test be cheaper when
the hero hasn't attained the achievement yet and is wandering around
the mines.

Fixes #1070
2023-07-06 13:18:19 -07:00
PatR
fb0509a6b3 fix #3841 - steed and engulfer on same map spot
Reported five months ago, a save was performed while a mounted hero
was engulfed.  Restore issued a warning about the engulfer being
placed on top of the steed (who shouldn't have been on the map).

The report arrived at about the same time as engulfing a riding
hero was changed to force a dismount instead of engulfing both hero
and steed so nothing further was done about it.  This changes
restore to not put a steed on the map and then take it off again.
It also attempts to simplify usteed and ustuck handling during save
and restore.

Testing so far indicates that things are still working correctly.
Keep makeplural(body_part(FINGER)) crossed.

Existing save and bones files are invalidated.
2023-06-14 00:04:21 -07:00
PatR
aa63aa8d98 issue #1027 - sticky 'nofollowers' flag
Reported by copperwater:  entering the tutorial sets 'u.nofollowers',
changing to the tutorial level saves a copy of 'u', post-level change
from entering the tutorial level resets u.followers, but subsequently
changing levels to return to the original level 1 restores 'u' from
the saved copy with has 'u.nofollowers==True', overriding the reset.

Move the nofollowers flag from 'u' to 'iflags'.  Invalides save and
bones files.

Fixes #1027
2023-05-25 17:08:53 -07:00
PatR
42356daec0 pull request #1024 - keep hero movement points
Pull request from saltwaterterrapin:  record current move's pending
movement points in save file.  They were being thrown away during
save and hero given 12 at time of restore.  Hero had to have had at
least 12 in order for player to issue the S command, but might have
had more than that if able to move faster than normal speed.

This implements it differently from the suggested commit.  Add new
field umovement to 'struct u' instead of using youmonst.movement and
needing to save and restore that separately.

Invalidates existing save and bones files.

Closes #1024
2023-05-24 11:16:23 -07:00