This feature was no longer fulfilling its intended purpose: the
issue is that when players are aware of it, instead of creating
interesting stories, it becomes a resource the player can rely on.
Alternative mitigation for some "unfair" early-game deaths has been
added (such as the warning shot for early-game attack wands and the
ability of iron shoes to protect against certain early traps), and
the warning shot in particular can create interesting gameplay
moments and stories of its own, especially when saving grace is
*not* present (discovering that a monster has a wand of fire and
can oneshot you is an interesting emergency situation, but less
scary if you know that its first attempt to oneshot you will fail).
The feature was also proving quite hard to code correctly, because
there are numerous cases that it "obviously" shouldn't affect
(most notably beheading due to Vorpal Blade, but also things like
purple worm digestion) which would need to be special-cased, and
because there are grey areas like wand zap bounces (which might or
might not be an intentional attempt by the player to hit themself
with the bounce) and damage from traps. Removing it saves the need
to work out, for every new damage source, whether and when saving
grace should interact with it.
Breaks save compatibility.
Add a pointer to struct you, and put umonst there. Eliminate
the youmonst struct in gy.
The naming convention better matches the other u related fields,
and u.umonst has the same level of indirection as other monst pointers.
The u.umonst pointer is cleared prior to saving the parent u (struct you),
and u.umonst is reestablished upon restore.
Invalidates existing saves and bones due to the presence of the added
pointer field in struct you.
This adds a "reroll" option that lets players reroll their
character's attributes and starting inventory. Although I generally
think doing this makes the game worse, a) some players are going to
do it regardless and b) if a player is going for a challenge game,
rather than to win, it may be required. So in the absence of an
option like this, players repeatedly start and quit games instead,
creating a large number of junk logfile entries and generally
causing problems for other players on the same shared machine
(because repeatedly reloading the game is very CPU-intensive).
This should in theory be windowport-agnostic (although in practice
it may not be). Tested on tty, X11 and curses; on tty and X11 it
works fine (although X11 treats the change in attributes as
something that needs a status highlight), on curses it is slightly
jankier in terms of what other windows are drawn in the background
(but still plays correctly and I suspect this is a pre-existing
bug).
To form a complete implementation, we will need to consider the
following:
- Should there be a delay on a) starting the game and/or b)
rerolling? If so, what should it be (maybe configurable via
sysconf?)
- Should we take more steps to discourage players from rerolling?
It would be bad if players see the option exists and turn it on
just because it exists, or (worse) treat it as condoning the
particular style of play.
- Should we take steps to detect that players are rerolling
manually and a) tell them to use the option instead, b) tell them
that this is not an intended way to play (and may make the game
less enjoyable and/or prevent them getting the practice they need
to eventually win)?
Breaks save and bones files.
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.
There are two hardfought code additions that render save and bones files incompatible
with the upstream NetHack-3.7, and that makes testing with hardfought
save and bones files more challenging than it needs to be, when
investigating and troubleshooting bug reports.
Add some unused fields to advance towards achieving save file parity with
hardfought, which is a significant source of play-testing for NetHack-3.7.
1) the elbereth field addition to u_conduct
This adds an unused placeholder field named 'hf_reserved1', at the appropriate
place in u_conduct to achieve struct field parity with the one in use on
hardfought.
2) hardfought adds a field to struct monst:
char former_rank[25]; /* for bones' ghost rank in their former life */
Instead of adding that to every monst, this adds a new mextra struct
named 'former', which currently contains the equivalent 25-character
field called 'rank' which can hold the content that was in the
former_rank[25] field. That way, the field will only be added when it
is needed.
A pull request https://github.com/k21971/NetHack37/pull/2 has been
done on hardfought to do it the same way (untested there as of yet).
Even though NetHack-3.7 does not utilize that information presently,
this will be a further step toward allowing hardfought-generated save
and bones files to be used for troubleshooting, without modification,
on a similar architecture running stock NetHack-3.7 code.
That savefile parity won't be achieved until the after the
hardfought pull-request mentioned above (or equivalent) is merged.
As this change will not be compatible with existing save and bones
files, it will be accompanied with an EDITLEVEL increment.
After the drawbridge was destroyed, playing an instrument on the castle
level while knowing the tune continued to offer a chance to play it.
Then nothing interesting happened even if you were close enough to the
former bridge for it to have been useful prior to the destruction.
I think the hero could also be given the tune as a divine prayer boon
after bridge destruction but I didn't verify that. The player might
not know that the tune is no good anymore, but the hero's patron deity
should.
This is a re-creation of a project that was lost years ago while not
quite finished. The old version included some instrumentation to
measure how many hits it takes to kill things during actual play; that
wasn't ready for prime time and this hasn't attempted to redo it.
Changes:
1) improves martial arts and bare-handed combat: they now have a
chance to hit twice when skill is better than 'basic'; 20% chance
for second hit at skilled, 40% at expert, 60% at master, and 80% at
grandmaster; when attacking more than once, strength bonus is
handled as in #2;
2) nerfs two-weapon combat a bit: hitting twice uses only 3/4 strength
bonus on each hit, but when both attacks hit that's 3/2 bonus from
strength which is still more than you get for one hit at a time;
3) beefs up two-handed weapons: hitting via melee with a two-handed
weapon uses 3/2 of stength bonus to reflect the increased influence
of strength; isn't done for applied polearms though.
The reduction in strength bonus for two-weapon has far less impact
than it might sound, due to rounding up with the low values involved.
| full 3/4
| +1 -> +1
| +2 -> +2
| +3 -> +2
| +4 -> +3
| +5 -> +4
| +6 -> +5
The small reduction also doesn't matter if/when current hit happens to
deal a killing blow anyway.
Rings of increase damage apply at full value to every hit, same as
before.
When hitting bare-handed (#1 without gloves), a silver ring on either
hand continues to give a damage bonus against silver haters when you
make an ordinary single attack. However if you attack twice, a silver
ring only applies on the first hit when it is worn on the right hand
and only applies on the second hit when worn on the left hand. (Two
hits with a silver ring on each hand will give silver bonus for both.)
We might conceivably need to add support for a count prefix of 1 to
let player explicitly avoid a second bare-handed/martial-arts hit
attempt (similar to how throw and fire accept a count to limit missile
volley amount).
Kicking has been ignored.
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.
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
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
hmon_hitmon was the biggest function by far; this makes it far more
manageable.
There should be no change in functionality, and although I didn't
test every case, this was just moving chunks of code and changing
variable names until compiler did not complain anymore.
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
Change u.{dx,dy,dz} from schar to int and get rid of unused u.di.
Remove just added getdir_ok2click; it was declared as int but being
assigned booleans. Rename getloc_click to getdir_click and have
getdir() use it for both input and output.
A simulated mouse is becoming quite a nuisance for something which
will probably never be used by anyone in actual play.
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.
This splits the uses of xchar into 3 different situations, and adjusts
their type and size:
xchar
|
-----------------------
| | |
coordxy xint16 xint8
coordxy: Actual x or y coordinates for various things (moved to 16-bits).
xint16: Same data size as coordxy, but for non-coordinate use (16-bits).
xint8: There are only a few use cases initially, where it was very
plain to see that the variable could remain as 8-bits, rather
than be bumped to 16-bits. There are probably more such cases
that could be changed after additional review.
Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.
This increments EDITLEVEL in patchlevel.h
Use up the last available bit for achievements:
"You learned the tune to open and close the castle's drawbridge."
(More can still be added but xlogfile will need another field to
track a second set of 31 in order to keep its achievement bitmask(s)
within portable size.)
As achievements go, it's not very exciting, but players who normally
destroy the drawbridge have to choose whether to earn an achievement
first since once it's gone, there's no way to find out the tune
(either via prayer reward or successful Mastermind). I'm guessing
that most will probably decide to ignore this achievement since it
has no effect on the outcome of the game. However, that might not
be true for future tournament play.
There's no need to bump EDITLEVEL for this; room for recording one
additional achievement is already allocated.
The livelog message for losing a level had an off-by-1 error, showing
the level the hero ended up at rather than the level that was lost.
There was a message for regaining a previously lost level when rank
title stayed the same but no such message if the title changed (the
achievement of gaining a particular title only occurs once).
Say "regained" rather than "gained" when gaining a previously lost
level. (Blessed potions of full healing regain levels but can also
reduce u.ulevelmax so a different way to remember peak experience
level has been added.)
Report level change due to polymorphing into new man/woman/elf/&c.
I hadn't realized that that hasn't been recording achievement for new
rank when applicable and decided to leave things that way.
Report gender change when putting on an amulet of change or becoming
a new man/&c unless hero is polymorphed at the time or experience
level is also changing.
There are no longer distinct gendered versions of monsters, so femalenum
is unused (i.e. set to NON_PM) for all roles and races. Take a pass at
removing all uses of/references to femalenum, and rename 'malenum' to
'mnum' since it no longer has any particular association with
gender or sex.
Keep track of the highest value that u.uhpmax and u.uenmax have
attained, in new u.uhppeak and u.uenpeak. They aren't used for
anything yet. u.mhmax (max HP while polymorphed) isn't interesting
enough to track.
Not save and bones compatible so increments EDITLEVEL.
add MALE, FEMALE, and gender-neutral names for individual monster species
to the mons array. The gender-neutral name (NEUTRAL) is mandatory, the
MALE and FEMALE versions are not.
replace code uses of the mname field of permonst with one of the three
potentially-available gender-specific names.
consolidate some separate mons entries that differed only by species into a
single mons entry (caveman, cavewoman and priest,priestess etc.)
consolidate several "* lord" and "* queen/* king" monst entries into
their single species, and allow both genders on some where it makes some
sense (there is probably more work and cleanup to come out of this at some
point, and the chosen gender-neutral name variations are not cast in stone
if someone has better suggestions).
related function or macro additions:
pmname(pm, gender) to get the gender variation of the permonst name. It
guards against monsters that haven't got anything except NEUTRAL naming
and falls back to the NEUTRAL version if FEMALE and MALE versions are
missing.
Ugender to obtain the current hero gender.
Mgender(mtmp) to obtain the gender of a monster
While the code can safely refer directly to pmnames[NEUTRAL] safely in the
code because it always exists, the other two (pmnames[MALE] and
pmnames[FEMALE] may not exist so use:
pmname(ptr, gidx)
where -ptr is a permonst *
-gidx is an index into the pmnames array field of the
permonst struct
pmname() checks for a valid index and checks for null-pointers for
pmnames[MALE] and pmnames[FEMALE], and will fall back to pmnames[NEUTRAL] if
the pointer requested if the requested variation is unavailable, or if the
gidx is out-of-range.
Allow code to specify makemon flags to request female or male (via MM_MALE
and MM_FEMALE flags respectively)to makedefs, since the species alone doesn't
distinguish male/female anymore. Specifying MM_MALE or MM_FEMALE won't
override the pm M2_MALE and M2_FEMALE flags on a mons[] entry.
male and female tiles have been added to win/share/monsters.txt.
The majority are duplicated placeholders except for those that were
separate mons entries before. Perhaps someone will contribute artwork in the
future to make the male and female variations visually distinguishable.
tilemapping via has the MALE tile indexes in the glyph2tile[]
array produced at build time. If a window port has information that the
FEMALE tile is required, it just has to increment the index returned
from the glyph2tile[] array by 1.
statues already preserved gender of the monster through STATUE_FEMALE
and STATUE_MALE, so ensure that pmnames takes that into consideration.
I expect some refinement will be required after broad play-testing puts it to
the test.
consolidate caveman,cavewoman and priest,priestess monst.c entries etc
This commit will require a bump of editlevel in patchlevel.h because it alters
the index numbers of the monsters due to the consolidation of some. Those
index numbers are saved in some other structures, even though the mons[] array
itself is not part of the savefile.
Window Port Interface Change
Also add a parameter to print_glyph to convey additional information beyond
the glyph to the window ports. Every single window port was calling back to
mapglyph for the information anyway, so just included it in the interface and
produce the information right in the display core.
The mapglyph() function uses will be eliminated, although there are still some
in the code yet to be dealt with.
win32, tty, x11, Qt, msdos window ports have all had adjustments done to
utilize the new parameter instead of calling mapglyph, but some of those
window ports have not been thoroughly tested since the changes.
Interface change additional info:
print_glyph(window, x, y, glyph, bkglyph, *glyphmod)
-- Print the glyph at (x,y) on the given window. Glyphs are
integers at the interface, mapped to whatever the window-
port wants (symbol, font, color, attributes, ...there's
a 1-1 map between glyphs and distinct things on the map).
-- bkglyph is a background glyph for potential use by some
graphical or tiled environments to allow the depiction
to fall against a background consistent with the grid
around x,y. If bkglyph is NO_GLYPH, then the parameter
should be ignored (do nothing with it).
-- glyphmod provides extended information about the glyph
that window ports can use to enhance the display in
various ways.
unsigned int glyphmod[NUM_GLYPHMOD]
where:
glyphmod[GM_TTYCHAR] is the text characters associated
with the original NetHack display.
glyphmod[GM_FLAGS] are the special flags that denote
additional information that window
ports can use.
glyphmod[GM_COLOR] is the text character
color associated with the original
NetHack display.
Support for including the glyphmod info in the display glyph buffer
alongside the glyph itself was added and is the default operation.
That can be turned off by defining UNBUFFERED_GLYPHMOD at compile time.
With UNBUFFERED_GLYPHMOD operation, a call will be placed to map_glyphmod()
immediately prior to every print_glyph() call.
Cap overall AC at -99 instead of -128. Put the same limit of 99
on enchantment and charge count of individual objects.
^X now reports if/when AC has reached its limit since players
could see that reaching that limit and then enchanting worn items
will change the worn items but not the total. (Same thing would
have happened with -128, just without any explanation and less
likely to accomplish.)
Won't affect normal play for any reasonable definition of normal.
When hunger state is "not hungry" (so omitted from the status line),
say so in the status section of ^X output. Mainly so that wizard
mode can append the internal nutrition value without inserting an
entire line that [previously] wouldn't be present in regular play.
Show an internal value for encumbrance too, although that would be
better if it also included some indication of the amount where the
encumbrance state changes. Encumbrance is confusing and I didn't
pursue that.
Track sokoban cheating (taking actions that incur a luck penalty).
The pull request only reported the number of times (possibly zero)
that the player broke nethack's sokoban rules when reporting the
"you obtained the Sokoban prize" achievement, which is when the
count is most meaningful, but this implements it as a full-fledged
conduct instead. This way the #conduct command can be used after
"creative nethacking" to check immediately whether an action has
violated the Sokoban rules so a player willing to put in a bit of
effort can eventually learn which actions have a negative impact.
The new conduct is only shown during games where the character has
entered the Sokoban branch, but once that has happened it gets shown
no matter the location at the time of #conduct or end of game.
Most of this wasn't in the pull request: expanding the Guidebook to
give more information about sokoban and its conduct.
Bump EDITLEVEL to invalidate to-be-3.7 save files because u.uconduct
has been extended.
Fixes#355
Record reaching experience level 3, 6, 10, 14, 18, 22, 26, and 30,
the levels where the character gets a new rank title, and report
those as achievements at end of game. These achievements persist
even if enough levels to lose a rank are lost, and if lost ranks
are regained the original achievement is the one that gets tracked
and disclosed.
Introduce eight achievements that can be attained by more players.
Entered Gnomish Mines - self explanatory
Entered Mine Town - the town portion, not just the level
Entered a shop - any tended shop on any level
Entered a temple - likewise for temple
Consulted the Oracle - bought at least one major or minor oracle
Read a Discworld Novel - read at least one passage
Entered Sokoban - like mines
Entered the Big Room - not always possible since not always present
The novel and bigroom ones aren't always achieveable since novels are
only guaranteed if a book or scroll shop gets created and bigroom is
only guaranteed in wizard mode. No one ever claimed that every
possible achievement can be attained in a single game. (If one for
entering the Fort Ludios level--or perhaps entering the Fort itself--
eventually gets add, that won't be possible in every game either.)
The mine town one probably needs some tweaking. Two of the town's
seven variants have no town boundary (despite a rectangular area of
pre-defined map) and at present simply arriving on either of those
levels is enough to be credited with the entered-town achievement.
Bump EDITLEVEL because u.uachieved[] has increased in size. This
time it has been expanded to the maximum that xlogfile's bitmask of
achievements can handle, enough for up to 9 more achievements without
another EDITLEVEL increment.