Commit Graph

247 Commits

Author SHA1 Message Date
Alex Smith
3491535548 More bugfixes for the recent artifact gifting changes 2024-12-12 07:35:50 +00:00
Alex Smith
3d8081c748 Bugfixes for the recent artifact gifting changes 2024-12-12 06:58:43 +00:00
Alex Smith
c2c797fa35 Artifact and #offer rebalance, part 2: luck from sacrificing
Luck from sacrificing is now limited by the value of the sacrifice.

This fixes two exploits, both of which rely on getting luck up to
maximum as soon as you have an altar, a luckstone, and a few
rations, via altar-camping until you accumulate enough luck. One of
them is to use the resulting luck to throw off the balance of combat
via using it to make hit chance calculations irrelevant. The other
is to use it to get crowned early in the game; in particular,
getting crowned pre-Sokoban is often viable and, especially for
chaotic characters, solves most of the game's difficulty at that
point (because the intrinisics and weapon are enough to carry a
character to the Castle given even mediocre luck with finding armor).

After this commit, becoming crowned very early in the game is more
difficult (likely requiring unicorns and identified gems), and the
hit chance gain from luck becomes a more gradual gain over the
course of the game rather than all happening immediately upon
finding the altar and luckstone.

In addition to making the game more balanced, this also discourages
grinding by reducing the incentive for altar-camping, so it will
hopefully make it more fun as well.
2024-12-12 03:37:02 +00:00
Alex Smith
d87cadaf73 Artifact and #offer rebalance, part 1: sacrifice gifts
In 3.6, artifact gifts are often either a) entirely useless or
b) gamebreaking, neither of which is really ideal from a balance
perspective.

This commit aims to make artifact gifts more useful in the early
game by greatly increasing the chance for situational artifacts to
generate positively enchanted.  However, the most powerful
artifacts will now only be gifted if you offer a high-value corpse,
meaning that they are only likely to be accessible later in the
game.  The selection of which artifact to gift has become more
complicated in order to a) increase the chance that it fits the
character and b) reduce cheese strategies (e.g. it is no longer
possible for elves to force the gifting of Stormbringer as the
first sacrifice gift).
2024-12-12 03:14:47 +00:00
Pasi Kallinen
b96c59e9b1 Angry god may remove an intrinsic 2024-12-04 20:54:47 +02:00
nhmall
c2c2e84485 remove some tabs that snuck in unintentionally 2024-11-30 19:35:25 -05:00
nhmall
0792e5fe9e expand implicit fallthrough detection to non-gcc compilers
gcc has recognized various "magic comments" for white-listing
occurrences of implicit fallthrough in switch statements for
a long time:

    The range and shape of "falls through" comments accepted are
    contingent upon the level of the warning. (The default level is =3.)

    -Wimplicit-fallthrough=0 disables the warning altogether.
    -Wimplicit-fallthrough=1 treats any kind of comment as a "falls through" comment.
    -Wimplicit-fallthrough=2 essentially accepts any comment that contains something
     that matches (case insensitively) "falls?[ \t-]*thr(ough|u)" regular expression.
    -Wimplicit-fallthrough=3 case sensitively matches a wide range of regular
     expressions, listed in the GCC manual. E.g., all of these are accepted:
        /* Falls through. */
        /* fall-thru */
        /* Else falls through. */
        /* FALLTHRU */
        /* ... falls through ... */
       etc.
    -Wimplicit-fallthrough=4 also, case sensitively matches a range of regular
     expressions but is much more strict than level =3.
    -Wimplicit-fallthrough=5 doesn't recognize any comments.

Plenty of other compilers did not recognize the gcc comment convention,
and up until now the compiler warning for detecting unintended
fallthrough had to be suppressed on other compilers. That's because the code
in NetHack has been relying on the gcc approach, and only the gcc approach.

The C23 standard introduces an attribute [[fallthrough]] for the
functionality, when implicit fallthrough warnings have been enabled.

Several popular compilers already support that, or a very similar attribute
style approach, today, even ahead of their C23 support:

       C compiler                       whitelist approach
       ---------------------------   -------------------------------------
       C23 conforming compilers         [[fallthrough]]

       clang versions supporting
       standards prior to
       C23                              __attribute__((__fallthrough__))

       Microsoft Visual Studio
       since VS 2022 17.4.
       The warning C5262 controls
       whether the implict
       fallthrough is detected and
       warned about with
       /std:clatest.                    [[fallthrough]]

This adds support to NetHack for the attribute approach by inserting a
macro FALLTHROUGH to the existing cases that require white-listing, so
other compilers can analyze things too.

The definition of the FALLTHROUGH macro is controlled in include/tradstdc.h.

The gcc comment approach has also been left in place at this time.
2024-11-30 14:16:27 -05:00
PatR
689f6c4c82 prayer lint 2024-11-28 14:24:27 -08:00
SHIRAKATA Kentaro
aba2bda159 split eval_offering() into a separate function 2024-11-16 04:10:11 +09:00
SHIRAKATA Kentaro
2ee31972a5 unify to early return on offer_corpse()
* remove redundant `else`
 * reduce indent
2024-11-12 22:50:17 +09:00
SHIRAKATA Kentaro
93072b8784 shrink scopes of some vars on offer_corpse() 2024-11-11 17:34:32 +09:00
SHIRAKATA Kentaro
e23095a829 omit return value of offer_corpse(), as it is always ECMD_TIME 2024-11-10 22:46:31 +09:00
nhmall
a40d85a430 Merge branch 'offer_corpse' of https://github.com/argrath/NetHack into NetHack-3.7 2024-11-09 14:47:33 -05:00
nhmall
1dbba0f63b rename IS_ROCK() macro to IS_OBSTRUCTED()
It has included trees since they were added, so give it a
more fitting name.
2024-11-09 11:12:42 -05:00
SHIRAKATA Kentaro
db460a4fcf split offering a corpse into a separate function 2024-11-09 02:35:19 +09:00
nhmall
9e75dec8f3 Merge branch 'negative_valued' of https://github.com/argrath/NetHack into NetHack-3.7 2024-11-07 10:37:38 -05:00
nhmall
e863583c56 iterating gi.invent (github issue #1315)
GitHub issue #1315 points out that it is possible for
a downstream function to change an object's nobj field
to point to a completely different chain.

The cited example by @vultur-cadens was:

     for (obj = gi.invent; obj; obj = obj->nobj)
         if (obj->oclass != COIN_CLASS && !obj->cursed && !rn2(5)) {
             curse(obj);
             ++buc_changed;
         }

    curse() drops the weapon with drop_uswapwep(),
        which calls dropx(),
            which calls dropy(),
                which calls dropz(),
                    which calls place_object().

place_object alters the nobj pointer, to point to the floor chain:
    otmp->nobj = fobj;
    fobj = otmp;

The result was that the next loop iteration was then using floor
objects from the floor chain.

This alters several for-loops to use a more consistent approach,
particularly when the obj is being handed off to a function,
where a downstream function might, or might not, alter the nobj
field.

References:

https://github.com/NetHack/NetHack/issues/1315
https://www.reddit.com/r/nethack/comments/1gkc9ub/even_if_you_drop_an_item_before_drinking_from_the/
2024-11-06 16:59:51 -05:00
SHIRAKATA Kentaro
ffe2dfc17c split offering negative valued items into a separate function 2024-11-07 03:30:13 +09:00
SHIRAKATA Kentaro
b953625e5b early return when value == 0 on dosacrifice()
`calc_value()` returns a non-negative value, and there is no code that sets `value` to 0 after this point.
2024-11-05 15:30:07 +09:00
SHIRAKATA Kentaro
955c2c5faf early return on dosacrifice()
... to reduce indents and prepare further refactorings.
2024-11-05 00:50:19 +09:00
SHIRAKATA Kentaro
3f3e1cc49a split calculating sacrifice value into a separate function 2024-10-30 13:36:42 +09:00
PatR
e9a25a0a1c sanity_check: current hero health better than max
Changes to setuhpmax() a couple of days ago to deal with sanity_check
for "current hero health as monster better than maximum" ended up
triggering sanity_check about "current hero health better than maximum"
when gaining experience level(s) while polymorphed.
2024-09-26 23:00:42 -07:00
PatR
da8ba281a4 more setuhpmax()
Prayer result of fix very low HP.  Tricky because when poly'd,
prayer operates on both u.mhmax and regular u.uhpmax but setuhpmax()
only operates on one of the two depending on Upolyd.
2024-09-25 00:58:43 -07:00
PatR
993c3b303f some reformatting (4 of 4) 2024-09-05 16:49:42 -07: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
8558981d9d "can't #offer" phrasing
When you attempt #offer at a non-altar location, the feedback
"you are not standing on an altar" made it sound as if you wouldn't
be able to #offer if you were levitating.  Since that is possible,
change the feedback.
2024-04-04 05:28:22 -07:00
Pasi Kallinen
defb5d5f80 Pets considered any noise made by hero as whistling
In 3.6.2 parts of the wakeup code were merged together, and this
caused pets consider any noise made by the hero - such as hitting
iron bars or digging - as whistling for them to come to the hero.

Change it to only consider actual whistling and ringing a bell.
2024-04-03 12:46:15 +03:00
nhkeni
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
RainRat
a3658f85ac fix typos 2024-02-28 20:15:56 -08:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
Pasi Kallinen
32adc3a092 Split #turn undead monster iteration function 2024-01-12 14:43:50 +02:00
nhmall
25a8c258e6 replace x >= LOW_PM with ismnum(x) shorthand macro 2024-01-11 14:01:10 -05:00
Michael Meyer
f42250eb9d Eliminate magic numbers from uchangealign() 2024-01-10 22:59:18 -08:00
Michael Meyer
6d29efcf04 Require a clear head to #offer
This will increase the potential challenge involved in donning a helm of
opposite alignment on Astral, now that it confuses the hero -- it means
that you must spend at least a turn after putting on the helm clearing
the confusion.  Since putting on the helm of opposite alignment may also
summon erinyes, this hopefully turns it from a situation where it's a
no-brainer to immediately ditch them by #offering the Amulet of Yendor
into one where the player must actually stop and think a little bit.
2024-01-10 22:57:11 -08:00
nhmall
4e19221e55 variable 'display' causes shadow variable warnings in X11 build
display.botl      -> disp.botl
display.botlx     -> disp.botlx
display.time_botl -> disp.time_botl
2024-01-05 05:58:51 -05:00
nhmall
49a5d043c0 consistent use of TRUE vs 1 with botl and botlx 2024-01-04 23:48:38 -05:00
nhmall
22e52ee905 bundle the display-related hints, that tell bot() and others
that an update is required, into a struct. Remove it from
context since there is no reason to save those.
2024-01-04 23:16:27 -05:00
PatR
e9e444d109 castle drawbridge tune tweak
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.
2023-12-11 18:44:29 -08:00
Pasi Kallinen
5dc94f3d83 Macro for picking random entry from array 2023-12-05 10:06:27 +02:00
Michael Meyer
0473fff5b5 Make destruction of altar incite its god's wrath
This is for completely destroying an altar with extra-powerful magical
digging -- the normal altar_wrath() punishment didn't seem sufficient
for such an outrage to me, so skip straight to slinging the lightning
bolts.  Destroying an altar is unlikely to happen by accident (though
it's possible with poorly timed usage of a drum of earthquake).
2023-11-29 11:36:56 -08:00
PatR
d0ade3b085 streamline PR #1124
Get rid of an extra 'if'.
2023-11-09 21:58:58 -08:00
SHIRAKATA Kentaro
637db78cea streamline dosacrifice(): early return when offering other than corpse 2023-11-09 21:32:32 -08:00
Michael Meyer
a1b1f3b250 Try to unify "back on solid ground" messaging
Put everything through a single function that can handle all the
complicated parts of using the correct proposition for different terrain
types, and will not just call things "solid ground" indiscriminately.
This got complicated but I'm not sure if it's possible to do it much
simpler while still using the distinct names for each type of terrain
(unless you are OK with the sentences sounding sort of wonky).
2023-11-07 16:13:55 -08:00
SHIRAKATA Kentaro
d5fa2f8ba0 Split sacrificing same race into separete function 2023-11-04 13:52:31 +09:00
Michael Meyer
8fa53d6ac5 Adjust seenres when observed attack succeeds
If a monster sees an elemental attack succeed from some other creature
or environmental danger, it will be willing to try those attacks again.
2023-08-29 12:05:48 +03:00
PatR
70791271dd update PR #1071 - highlighting critical HP
If status field 'hitpoints' has rules for both 'criticalhp' and 'up'
or 'down' or 'changed', make critical-hp take precedence.  Otherwise
critical-hp might never be seen because of the value changing every
move (if hero has regeneration attribute).  Normally up/down/changed
take precedence over other types of highlighting.

Something is messed up with up/down/changed HP though.  I'm seeing
the 'up' highlight when it goes either up or down and not seeing the
'down' highlight at all.  'up' and 'down' for gold work as expected.
2023-08-04 22:33:29 -07:00
SHIRAKATA Kentaro
97edd4b845 split offering fake amulet into separate function 2023-07-04 22:19:04 -07:00
PatR
b1d30fbce9 address github issue #303 - paranoid_confirm:pray
An issue from nearly three years ago, reported by Anerag:  asking
player whether to really pray isn't paranoid enough because it
accepts 'y' rather than requring "yes".

This changes it to require "yes" followed by <return> or <enter> if
paranoid_confirm:Confirm is also set.  (A side-effect of that is
explicit "no<return|enter>" is required instead of just 'n' to
decline--for all the paranoid confirmations, not just for prayer.)
This extension of paranoid:Confirm applies to paranoid:AutoAll too.

A comment asks why paranoid_confirm:pray is different from the other
paranoid questions in the first place.  The answer is that when it
isn't set, no confirmation prompt is issued at all.  The others all
have y/n confirmation prompts when the corresponding paranoid option
isn't set.

Once upon a time there was a boolean option called 'prayconfirm' that
issued "really pray?" prompt when True.  It was added after players
whinged about typing Alt+p when they meant to type Alt+o.  When the
more advanced 'paranoid_confirmation' was introduced, paranoid:pray
superseded prayconfirm, but it still only issues a confirmation
prompt where there normally wouldn't be one rather than change an
existing one to require "yes<return|enter>" instead of 'y'.

Closes #303
2023-06-24 16:12:54 -07:00
PatR
2646688e2d back_on_ground()
Replace a couple of hardcoded "back on solid ground" messages with
something more versatile.

Also, make life-saving handling for failed rescue from drowning
similar to that of failed rescue immolation by lava.  If there are
any cases where more than two tries is needed, they elude me.  The
new code doesn't confer temporary water walking if emergency teleport
fails; perhaps it should.
2023-05-15 01:08:04 -07:00
PatR
7737fcc97c fix out of date safe_teleds() calls
When safe_teleds() was changed to take an int flags argument instead
of a boolean, some calls weren't updated.
2023-05-11 12:12:12 -07:00