Commit Graph

917 Commits

Author SHA1 Message Date
PatR
a51e44e532 move lua context out of dungeons[]
and out of save files so restore doesn't need to clear stale data.
Behavior should be the same as before, except that when entering
the endgame branch and discarding the main dungeon and its other
branches, lua theme context is now discarded for those too.
2020-05-05 18:06:00 -07:00
PatR
19529ffb2f extern.h bits
Clean up a few things I recently noticed:
  obsolete monstr.c was still present;
  mdlib.c was out of alphabetical order;
  monst_global_init() was listed under the wrong file.
2020-05-05 12:39:24 -07:00
PatR
116642ce1e track eight more achievements
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.
2020-05-04 16:35:40 -07:00
PatR
16562b2892 displacer beast as food
Make eating a displacer beast corpse or a tin of displacer beast
meat confer temporary Displacement lasting 6d6 turns.
2020-05-04 09:50:11 -07:00
PatR
88461e1923 makemon and goodpos flags
I added another goodpos flag to simplify handling displacer beast
and that pushed the total number of makemon and goodpos flags past
16.  'int' and 'unsigned' might be too small, so change the flags
and several function arguments to 'long'.
2020-05-04 09:19:37 -07:00
PatR
7817e69c41 two new monsters from slash'em
Adds two monsters originally from slash'em.  I used the slash'em
tiles this time, also its code as a starting point but made various
revisions.  Both the tiles could benefit from some touch-ups.

displacer beast:  blue 'f'.  Attempting a melee hit (ie, trying to
  move to its spot) has a 50:50 chance for it to swap places with you.
  Fairly tough monster to begin with, then half your ordinary attacks
  effectively miss and if you try to face a mob by retreating to a
  corridor or backing into a corner you can end up being drawn back
  into the open.  I added bargethrough capability, and also it won't
  be fooled about hero's location by Displacement.  [It only swaps
  places during combat when contact is initiated by the hero, not
  when attacked by another monster or when attacking.]

genetic engineer:  green 'Q'.  Its attack causes the target to be
  polymorphed unless that target resists.  Hero will almost always
  have magic resistance by the time this monster is encountered, but
  it can make conflict become risky by hitting and polymorphing other
  monsters.  Slash'em flagged it hell-only but I took that flag off;
  I also took away its ability to teleport.  Slash'em polymorphs the
  hero if a genetic engineer corpse is eaten; that's included and I
  introduced that for monsters too.

I added both of these to the list of candidates for monster spell
'summon nasties' and for post-Wizard harassment.

I also gave all the 'f's infravision.  Probably only matters if the
hero polymorphs into a feline.

Displacer beast is originally from AD&D which depicts it as a six-
legged cougar with a pair of tentacles; it has Displacement rather
be able to affect an attacker's location.  I think genetic engineer
is original to slash'em where it expands Q class but seems mainly to
be the base monster for Dr.Frankenstein (a unique monster with a
one-level side-branch lair in slash'em's incarnation of Gehennom).
2020-05-03 14:13:08 -07:00
PatR
c17301a75c Sting vs level teleport revisted
This reverses all of c67f1dd710
except for the fixes37.0 entry and does a better job in a cleaner
fashion.  If Sting is going to start glowing and "you materialize
on a different level" is pending, give the materialize message
before the glowing message.  Otherwise handle both stop-glowing
and/or you-materialize in the normal fashion.
2020-04-27 10:49:34 -07:00
PatR
09f9b3598f fix issue #339 - duplicate feature messages
while 'mention_decor' is enabled.  When stepping onto different
terrain and one or more objects remained on the new spot after
autopickup, describe_decor() was issuing its new-terrain message
right before look_here()'s similar under-the-objects message.  If
autopickup grabbed everything or there weren't any objects to begin
with, look_here() doesn't issue any dfeature (terrain) message.
describe_decor() isn't smart enought to know whether that is going
to happen.  Give look_here() a new flag argument so that its caller
can ask for the dfeature message to be skipped for the case where a
similar message has already been given.
2020-04-27 04:25:26 -07:00
PatR
0ae84411a0 option fixes and missing prototypes
I added -Wmissing-prototypes to my CFLAGS and got a bunch of warnings.
This fixes the core ones (there are more for X11 that I haven't looked
at yet).  While fixing these, I discovered a few option processing
issues:  the non-Amiga 'altmeta' should be settable while the game is
in progress (not sure about the Amiga variation so left that as-is),
'altmeta' and 'menucolor' are booleans so shouldn't have had optfn_XXX
functions; 'MACgraphics' and 'subkeyvalue' were conditionally defined
differently in options.c than in optlist.h.
2020-04-22 13:39:38 -07:00
PatR
28fb6fc67b crystal ball enhancements
Allow crystal ball to search for furniture (stairs and ladders,
altar, throne, sink, fountain) as well as for a class or objects
or of monsters or all traps.  Giving any of '<','>','_','\','#',
or '{' will find all of those rather than just the individual type
specified.  Because of the default character conflict, '_' can no
longer be used to find chains; looking for altars is more useful.

The chance of getting the cursed effect due to failing a saving
throw against intelligence when the ball isn't actually cursed has
been reduced.  If it is the hero's own quest artifact, it will
happen if rnd(8) is greater than Int, so Int of 8 or more will
never yield that effect.  Otherwise if it is blessed, rnd(16) is
used so 16 or better Int means it can't act like it is cursed.
When uncursed and not hero's quest artifact, the old rnd(20) > Int
test is still used.

Crystal balls now start with 3..7 charges rather than 1..5, and
blessed charging sets the amount to 7 charges rather than 6 and
also blesses the ball.  Recharing with uncursed scroll of charging
is slightly better (adds 1..2 charges instead of always just 1,
caps the amount at 7 rather than 5) and uncurses the ball.  Cursed
scroll strips off all charges even if the ball is blessed and also
curses the ball so is harsher than before.

Crystal balls now cancel to -1 instead of 0, like wands, and using
one effect will destroy it, like zapping cancelled wands.

Also a minor tweak to the initial charges for can of grease (5..25
instead of 1..25) and horn of plenty and bag of tricks (both now
3..20 instead of 1..20).
2020-04-22 01:14:09 -07:00
PatR
05403182eb wishing fix
name_to_mon() has a bunch of alternate monster names, such as
"gray-elf" to match "grey-elf" and "ki rin" to match "ki-rin".  Those
worked as intended when they occurred at the end of a wish, but only
worked in the middle if their length was the same or one character
less than the canonical name in mons[].mname.

djinni figurine     -> h - a figurine of a djinni
genie figurine      -> i - a figurine of a djinni
figurine of mumak   -> j - a figurine of a mumak
mumak figurine      -> k - a figurine of a mumak
figurine of mumakil -> l - a figurine of a mumak
mumakil figurine    -> nothing fitting that description exists

(The one-less case worked because its following space ended up being
implicitly removed when skipping ahead by the length of mons[].mname;
subsequent explicit removal didn't find a space so was a no-op.)
2020-04-19 04:58:18 -07:00
Pasi Kallinen
9b74ea0b22 Shaped and themed rooms
Allows creating shaped or themed rooms for the Dungeons of Doom
via lua script.

Invalidates bones and saves.

Makefiles updated for unix/linux by adding themerms.lua, but other
OSes need to have that added.
2020-04-18 19:55:09 +03:00
Pasi Kallinen
43d331c4eb Nerf unicorn horn
Unicorn horns are just too good. Nerf it in similar way several
other variants have done: don't let it restore attribute loss.

This makes potion of restore ability more valuable, and the
int loss from the (nerfed) mind flayers matter more.
2020-04-15 22:45:47 +03:00
Pasi Kallinen
bddb80f13c Make hostile monsters with launcher and ammo keep away
If a hostile monster is wielding a ranged weapon, and is carrying
appropriate ammo for it, make the monster try to stay away,
outside the melee range.
2020-04-14 15:19:30 +03:00
PatR
dc6b2f5de1 let monsters use wand of undead turning
when hero is wielding a cockatrice corpse.  Wands of undead turning
aren't generated as starting equipment but they will now be picked
up if come across while the hero is carrying any corpse, and used
in preference to any other item when carried and non-empty and hero
is wielding a petrifier's corpse.
2020-04-10 18:39:46 -07:00
PatR
2e177a7fc4 fix gibhub issue #320 and more - 'mention_decor'
Fixes #320

Avoid giving "you are back on the bottom" nearly every step when
moving around underwater.

Avoid "you are back on floor" followed by "you trip over <object>"
when fumbling in case that fumbling was due to being on ice when
taking the step to floor.  Done for all fumbling rather than just
one-turn fumbling instigated by ice.

When moving from ice or water to ground, show "you are back on floor"
before listing objects at that spot instead of after.

I think there was at least one more thing but have lost track.  At
any rate, 'mention_rate' potentially has a new set of bugs.
2020-04-08 18:33:55 -07:00
Pasi Kallinen
665eacf40c Expose scaled mazes to special level lua
Adds a new level init type which directly creates a maze,
optionally setting corridor width and wall thickness,
and removing dead ends.

des.level_init({ style = "maze", corrwid = 3, wallthick = 1, deadends = false });
2020-04-07 19:20:39 +03:00
copperwater
0befdbfd02 Re-implement gradient selections
Uncomments and makes available selection.gradient in Lua. (The backend C
code for this still existed, it just wasn't used.)

The only valid way to specify a gradient is with a table. I considered
adding non-table versions, but decided that there are too many
independent variables that can be optional. A non-table version, without
named parameters, would be confusing to read, especially since most of
the arguments are ints.

Also adds an impossible in the (possibly unreachable) case that
selection_do_gradient gets called with a bad gradient type.
2020-04-06 18:54:39 +03:00
Pasi Kallinen
e215f09ddb Fix even more warnings 2020-04-06 13:34:07 +03:00
Pasi Kallinen
99519c4e5b Fix more warnings 2020-04-06 10:25:17 +03:00
copperwater
4b7f34f5f8 Refactor mongets to return the object it creates
The impetus for this was to avoid ugly constructions such as the one
below (none of which currently appear in vanilla NetHack):

mongets(mtmp, LONG_SWORD);
struct obj* sword = m_carrying(mtmp, LONG_SWORD);
if (sword)
  /* do thing to sword */

Most cases where mongets is used discard the returned value (which used
to be the created object's spe); the only places that do use it are the
series of statements that give various human monsters armor and prevent
them from getting too much armor. These statements included hardcoded
constants representing the base AC of the armor, which would have caused
discrepancies if armor's base AC were ever changed.

With mongets now returning a pointer to the created object, it can just
be passed into ARM_BONUS instead, which covers both the base AC and the
enchantment. (It will also cover erosion, if anyone ever decides that
armor should rarely generate as pre-eroded).

The overall algorithm is not changed by this; human monsters should
receive armor with the same probabilities as before.
2020-04-05 21:08:34 +03:00
Pasi Kallinen
cf1c725148 Purple worm changes
Shriekers only spawn purple worms when they're appropriate difficulty.
Non-tame Purple worms eat corpses off the ground.
Baby purple worms attack shriekers.
Hero polyed into baby purple worm is warned against shriekers.

Original changes by copperwater <aosdict@gmail.com>, added with some
formatting adjustments and consolidation.
2020-04-05 12:44:25 +03:00
PatR
8f73f926b1 groundwork: u.twoweap manipulation
Toggle u.twoweap on or off in just one place.
2020-04-03 11:42:17 -07:00
PatR
a2338e92aa groundwork: u.uinwater manipulation
Toggle u.uinwater on or off in just one place.
2020-04-03 01:04:27 -07:00
Pasi Kallinen
2f64f419ad Unify checking if monster is ok in poison gas 2020-04-02 20:53:08 +03:00
PatR
3eed500886 fix #K669 - 'nasty' monster summoning
Report complained about multiple Archons causing his character to
be swarmed by monsters on the Plane of Fire.  I don't think that
the behavior has changed significantly from how it worked in 3.4.3.
Nobody can summon an Archon directly because they're excluded from
the nasties[] list.  But whenever summoning picks a genocided
'nasty', the result gets replaced by random monster of appropriate
difficulty for the level (which could be an Archon for a high level
character in the endgame).  [Note that that won't pick an Archon
in Gehennom or at arch-lich outside of there because the random
monster creation honors the only-in-hell and never-in-hell flags;
picking from the nasties[] list doesn't.]

This prevents that for any creature (except arch-lich or the Wizard)
casting the summon nasties spell.  If a replacement creature is a
spellcaster it now has to have lower difficulty than the summoner.
If not, it will be discarded even though its difficulty is classified
as appropriate.  So to summon an Archon, the summoner has to have
higher difficulty than an Archon; arch-lich and the Wizard are the
only ones meeting that criterium.  When summoner is an arch-lich,
it can't summon another arch-lich (since that wouldn't have lower
difficulty than the summoner) and can summon (via replacement for
genocided type, and only if outside of Gehennom) at most one Archon.
When summoner is the Wizard, he could summon an arch-lich (when in
Gehennom; demoted to master lich elsewhere--see below) or an Archon
(outside Gehennom only), but at most one per summoning.

For post-Wizard harassment, which effectively has infinite
difficulty level, it could still happen.  However, each instance of
harassment is only allowed to create at most one Archon or arch-lich
now, so chain summoning should be lessoned.  Also if it tries to
pick an arch-lich when outside of Gehennom it will switch to master
lich instead (which won't be allowed to summon an Archon or an arch-
lich or even another master lich).

(The monmove.c bit is unrelated, just some comment formatting that
I had laying around that got mixed in.)
2020-03-27 19:05:52 -07:00
PatR
40d19525c3 updating 'time' status
Handling botl updates for 'time' was inconsistent.  Set the flag to
do that when moves is incremented (where the update is suppressed if
running) or when running stops short.

losehp() would cancel running/traveling if called when in normal form
but not if called when polymorphed, so theoretically you could take
damage and keep on running.  I don't have a test case to verify that.
2020-03-16 17:32:12 -07:00
Pasi Kallinen
04c59fff0a Major amnesia revamp
Instead of forgetting maps and objects, make amnesia forget skills.
Forgetting maps and objects could be circumvented with taking notes,
or by using an external tool to remember the forgotten levels.

Forgetting skills allows the player to optionally go down another
skill path, if they trained the wrong weapon in the early game.

Amnesia still forgets spells.

As a replacement for the deja vu messages when entering a forgotten
level, those messages will now indicate a ghost with your own name
existing on the level, given only when the level is entered for
the first time.

These changes based on fiqhack, with some adjustments.
2020-03-15 11:57:34 +02:00
Pasi Kallinen
2ff8523481 Fix priest generated inside temple wall
In a rare case, a random room's width can be 2 tiles, and if
that room was converted into a temple, the priest ended up
inside the wall. Try to put the priest on a random valid position
around the altar, or on it.
2020-03-12 19:17:06 +02:00
Pasi Kallinen
f5d9324f28 Fix wizmakemap to consider monster birth counts and uniques
Also add a new wizmode command #wizborn to show those.
2020-03-07 21:35:26 +02:00
Pasi Kallinen
c9b21e36a7 Add lua selection match method
Also improve the replace_terrain command parameters.
2020-03-02 16:17:53 +02:00
PatR
99035e72ee throw-and-return vs !fixinv
Implement the request that a wielded+thrown aklys be given the same
inventory letter when it returns and is caught and rewielded, even for
the !fixinv setting where inventory letters don't stick.  Works for
Valkyrie-thrown Mjollnir and returning (ie, didn't hit) boomerangs as
well as for aklys.

I'm not sure how useful this really is, because on the rare occasions
that it either doesn't return or fails to be caught, it won't be given
the same letter when subsequently picked up.  So the player who relies
on it will still be vulnerable to using the wrong letter next time a
throw is attempted.  But at least picking it up explicitly displays
the new inventory letter, unlike catching it upon return.
2020-03-01 06:46:37 -08:00
nhmall
2f1be94bfa since sole argument to set_duplicate_opt_detection was unused, eliminate it altogether 2020-02-29 18:47:34 -05:00
nhmall
cca2bcaa84 minor flavor bit of the day 2020-02-29 13:57:31 -05:00
nhmall
1115402c14 Merge branch 'options-overhaul' into NetHack-3.7 2020-02-26 14:36:20 -05:00
Pasi Kallinen
d86b7e8e7c Demon lords and princes suppress teleporting in Gehennom
Instead of having the demon lair levels unconditionally no-teleport,
grant demon lords and princes the ability to suppress teleportation
in Gehennom on the level they are on.
2020-02-26 20:03:00 +02:00
nhmall
68fdc3bbcb February 2020 options.c overhaul
combine boolean and compound options into a single allopt[] array for
processing in options.c.

move the definitions of the options into new include/optlist.h file which
uses a set of macros to define them appropriately.

during compile of options.c each option described in include/optlist.h:
   1. automatically results in a function prototype for an optfn called
      optfn_xxxx (xxxx is the option name).
   2. automatically results in an opt_xxxx enum value for referencing
      its index throughout options.c (xxxx is the option name).
   3. is used to initialize an element of the allopt[] array at index
      opt_xxxx (xxxx is the option name) based on the settings in the
      NHOPTB, NHOPTC, NHOPTP macros. Those macros only live during the
      compilation of include/optlist.h.

each optfn_xxxx() function can be called with a req id of: do_init, do_set,
get_val or do_handler.

req do_init is called from options_init, and if initialization or memory
allocation or other initialization for that particular option is needed,
it can be done in response to the init req.

req do_set is called from parseoptions() for each option it encounters
and the optfn_xxxx() function is expected to react and set the option
based on the string values that parseoptions() passes to it.

req get_val expects each optfn_xxxx() function to write the current
option value into the buffer it is passed.

req do_handler is called during doset() operations in response to player
selections most likely from the 'O' option-setting menu, but only if the
option is identified as having do_handler support in the allopts[]
'has_handler' boolean flag. Not every optfn_xxxx() does.

function special_handling() is eliminated. It's code has been redistributed
to individual handler functions for the option or purpose that they serve.

moved reglyph_darkroom() function from options.c to display.c
2020-02-26 00:24:37 -05:00
PatR
194b174bbc flipping current level with #wizlevelflip
Give wizard mode player control over how a level gets transposed by
prompting for the desired outcome.

Refreshing the screen showed that remembered, no longer in view wall
corners and T walls were shown with their old orientation instead of
being transposed along with the level.  This fixes that, but does so
by adding a chunk of code that will be irrelevant for normal play.
2020-02-24 17:07:01 -08:00
Pasi Kallinen
509576a8b7 Minor tweaks to level flipping 2020-02-23 15:06:44 +02:00
PatR
cbdda9dc9d adopt github pull request #286 - rndmonst()
Eliminate the cache that was supporting rndmonst() and pick a random
monster in a single pass through mons[] via "weighted reservoir
sampling", a term I'm not familiar with.

It had a couple of bugs:  if the first monster examined happened to
be given a weighting of 0, rn2() would divide by 0.  I didn't try
to figure out how to trigger that.  But the second one was easy to
trigger:  if all eligible monsters were extinct or genocided, it
would issue a warning even though the situation isn't impossible.

Aside from fixing those, the rest is mostly as-is.  I included a bit
of formatting in decl.c, moved some declarations to not require C99,
and changed a couple of macros to not hide and duplicate a call to
level_difficulty().

Fixes #286
2020-02-22 17:40:55 -08:00
PatR
9366307210 extra ^X info (mon's location) for u.ustuck 2020-02-21 13:46:03 -08:00
Pasi Kallinen
88aa0793dc Allow flipping levels horizontally or vertically
When a special level is created, there's a chance it gets flipped
horizontally and/or vertically.

Add new level flags "noflip", "noflipx", and "noflipy" to prevent
flipping the level. Add a wiz-mode command #wizlevelflip to test
the flipping on current level - although this doesn't flip everything,
as level flipping is meant to happen during level creation.
2020-02-21 18:16:14 +02:00
PatR
cfd425d5db Wounded_legs condition
Mounting a steed while legs are wounded would offer to cure them
but wasn't going through the heal_legs() routine so didn't update
the status line when Wounded_legs condition is enabled.

Move some common code for describing left/right/both legs into a
new routine used for feedback by jumping, kicking, and ridiing.

For ^X, distinguish between one wounded leg and both but don't
bother with left vs right when it is just one.
2020-02-19 15:47:55 -08:00
PatR
814adb41b8 fix #K376 - tipping cap
Allow #tip to do something if you pick your worn helmet instead of
a container.  It's mostly just a variation of #chat but probably adds
several new bugs....
2020-02-18 03:14:22 -08:00
PatR
3981e3e6e5 controlling u.ustuck
Setting or clearing u.ustuck now requires that context.botl be set,
so make a new routine to take care of both instead of manipulating
that pointer directly.
2020-02-16 13:04:12 -08:00
PatR
75e9055b89 plug a couple of memory leaks in sp_lev.c, take II
[...]
| Change selection_free(foo) to also free(foo) after freeing foo's
| fields.  Every use was already
|   selection_free(foo);
|   free(foo);
| except for the two instances of memory leak.

And except for the three which aren't in sp_lev.c, one of which was
dealing with memory managed by Lua.  This time it seems to be working
as intended.
2020-02-12 18:56:41 -08:00
PatR
d462bdffca redo achievement tracking
Instead of an assortment of bits, assign numeric indices to the
potential achievements and keep an array of those in the order they
were attained.  So disclosure might show the same subset occurring
differently in different games depending on the player's actions.
The encoded field in xlogfile doesn't care about that and remains
the same.

Modifies 'struct u', so EDITLEVEL has been incremented and existing
save files are invalidated.
2020-02-10 00:17:54 -08:00
nhmall
c7c0c87859 move status condition field selection to its own menu 2020-02-09 14:56:37 -05:00
Pasi Kallinen
7eb20c9e7a Unify multishot class bonus code 2020-02-08 18:04:54 +02:00
Pasi Kallinen
0323eecbfe Unify finding a queen bee 2020-02-08 17:35:52 +02:00