Commit Graph

105 Commits

Author SHA1 Message Date
PatR
9682f84aed more knockback induced dismount
When looking at the previous commit, I realized that my comment about
radius 1 was wrong.  The original code prefers dismounting to spots
that are orthogonal to the steed's position over diagonal ones.  It
doesn't say why.
2022-10-27 15:55:57 -07:00
PatR
da32b572a6 knockback knocking riding hero out of saddle
I've implemented targetted dismount such that being knocked out of
the saddle will place the hero opposite the attacker in preference
to a random spot adjacent to the steed.  If that opposite spot
isn't appropriate, the two spots next to it get tried.

In these map fragments, H is knocking mounted hero off of u.  The
digits indicate priority of potential destinations.

|.....   |..21.
|...2.   |..u2.
|.Hu1.   |.H...
|...2.   |.....

If spot 1 isn't acceptable, both of spots 2 (in random order) will
be tried next.  If those aren't acceptable either, it will try the
other 5 spots adjacent to the steed (the one of those with the
attacker will always be unacceptable).  And as before, it none of
those work, it uses enexto() to pick a random spot as close to the
steed as feasible.

Not knockback:  when dismounting due to polymorph, avoid diagonal
adjacent spots if hero's new form can't move diagonally.  (The hero
can't already be in no-diagonal form because riding requires that
the rider be humanoid.  I keep thinking the restriction is "can't
be polymorphed" but that isn't correct.)
2022-10-27 15:33:49 -07:00
Michael Meyer
05f004403e Rename update_mon_intrinsics to ...extrinsics
There was a TODO about this; not exactly a great challenge but it feels
like a worthwhile change since the name was misleading.  I also updated
the name of the do_intrinsics parameter of extract_from_minvent(worn.c),
since it was in a similar situation (and directly related, since it
controls whether to call update_mon_{in/ex}trinsics).
2022-10-23 00:21:44 -07:00
PatR
546fea7db8 getting knocked off flying steed
I was trying to reproduce the reported "no monster to remove" warning
from remove_monster() when a mounted hero was knocked off jabberwocky
steed but so far haven't been able to.

While trying, I came across a more minor bug.  The hero got knocked
off a flying steed and got feedback of "you fly off" rather than
"you fall off".  Flying capability came from the steed and dismount
feedback is aware of that but calls u_locomotion() which isn't.  This
commit fixes that.

This adds some groundwork (DISMOUNT_KNOCKED) for better dismount
control.  With a map fragment of
|....
|.Du.
|....
I got knocked off my steed by the attacking dragon and ended up with
|..@.
|.Du.
|....
It would be better to prefer spot 1, then the 2s, then 3s, then 4s
(not sure about farther spots if none of those are available)
|.432
|.D@1
|.432
when forced to dismount by knockback.  This does _not_ implement that.
2022-10-03 15:53:35 -07:00
PatR
e9ec89a903 fix issue #836 - engulfing mounter hero
Reported by copperwater:  if an engulfer swallowed a mounted hero,
odd things could happen if the hero dismounted.  The steed would be
silently expelled and float-down flooreffects were attempted.

It turns out that if the engulfer is classified as an animal (so
purple worm, lurker above, trapper), the hero got "plucked from
<steed>'s saddle" and was forcibly dismounted prior to completing
the engulf operation, but non-animals (vortices, air elemental,
ocher jelly, Juiblex) swallowed the hero+steed intact.  The most
straightforward fix to dismounting-while-engulfed issues is to change
engulfing to always pluck the hero from the saddle even when the
engulfer isn't an animal.

If there's no room on the level to place the former steed, it gets
killed off.  I looked at changing that to put the steed into limbo,
waiting to migrate back to the current level if hero leaves and
subsequently returns, but that breaks movemon()'s assumption that
when monsters are in the process of moving, only the currently moving
one can be taken off the fmon list to be placed on migrating_mons.

[The recently added monster knockback code violates that assumption
too when knocking the victim into a level changer trap.  It needs to
be fixed in one fashion or another.]
2022-08-09 16:22:50 -07:00
Pasi Kallinen
ac5b92d348 Greased saddle is slippery 2022-07-29 12:27:08 +03:00
nhmall
3004cf2d34 be more consistent with coordinates 2022-07-02 09:10:03 -04:00
Pasi Kallinen
39acd095b2 Add helpless monster macro 2022-03-18 10:19:04 +02:00
PatR
2bef05bb77 livelog level entry events
Fix up the level descriptions used when logging an "entered new level"
event.  Most of the change is for adding an extra argument to calls
to describe_level().  The curses portion is in a big chunk of old code
suppressed by #if 0.

I didn't notice that the level entry events are classified as LL_DEBUG
until all the work was done.  This promotes the entry events for the
four Plane of <Element> levels from debug events to major ones instead.
It doesn't do that for the Astral Plane because the entered-the-Astral-
Plane achievement already produces a major event for that.  Most other
key level entry events are in a similar situation--or will become that
way once another set of achievements eventually gets added--so there
aren't any other event classification promotions.
2022-03-01 13:53:57 -08:00
Pasi Kallinen
1d4d0f4b0e Use more u_locomotion
... and make it autocapitalize the first letter, just like locomotion
2022-02-27 11:07:31 +02:00
Pasi Kallinen
2777f45bd5 Get rid of force_mintrap, allow passing flags to mintrap
It uses the same flags as dotrap, so simulate force_mintrap
by passing FORCETRAP flag.
2022-02-24 17:13:23 +02:00
Pasi Kallinen
8e91320d2f Use u_at macro 2022-02-23 20:28:55 +02:00
Pasi Kallinen
e65c921ccb Use grounded macro 2022-02-15 18:44:56 +02:00
Pasi Kallinen
68b822e4dc Add "user canceled" as extended command return value
Instead of returning ECMD_OK, the commands now return ECMD_CANCEL
when user declined to pick a direction or an object to act on.

Note that this can be ORed with ECMD_TIME, if the command still
took a turn.

For now this has no gameplay meaning.
2022-01-08 20:04:57 +02:00
Pasi Kallinen
d53cd28d46 Make extended commands return defined flags
Instead of returning 0 or 1, we'll now use ECMD_OK or ECMD_TURN.
These have the same meaning as the hardcoded numbers; ECMD_TURN
means the command uses a turn.

In future, could add eg. a flag denoting "user cancelled command"
or "command failed", and should clear eg. the cmdq.

Mostly this was simply replacing return values with the defines
in the extended commands, so hopefully I didn't break anything.
2021-12-30 19:16:33 +02:00
Pasi Kallinen
f6b7be49f4 Accessibility: give a message when teleporting a monster
Teleporting a monster only updated the map. Give a message
so blind players can get the same information.
Making a monster invisible gives the same message, if you
cannot detect invisible.
Several other places where monsters teleported themselves
now also give the same message.
2021-12-12 16:50:49 +02:00
PatR
cf62687630 remove curse vs saddle
Prayer reward can already uncurse a cursed saddle because hero is
stuck on it.  Allow scroll/spell of remove curse to do so too.

The original riding implementation in slash'em operated with the
saddle in hero's inventory rather than in the steed's, so it would
have handled this without any extra effort.  Presumeably that was
overlooked when incorporating riding into nethack changed it to
have saddle be part of the steed's inventory instead of hero's.
2021-04-14 12:51:20 -07:00
PatR
0cca010ff1 fix pull request #470 - two riding fixes
Post-3.6 change to monster inventory handling could result in hero
remaining mounted on an unsaddled steed (if saddle was removed via
opening magic).

Hero falling out of saddle would fall to the ground and take damage
even if levitating or flying without steed's help after dismount.

Fixes #470
2021-03-16 11:01:43 -07:00
nhmall
f963c5aca7 switch source tree from k&r to c99 2021-01-26 21:06:16 -05:00
Michael Meyer
a29b76e1bf Add Sokoban penalty for dismounting onto a boulder
Because landing_spot will select a square containing a boulder as a
last-resort option, provided no other squares are accessible, it is
possible for the player to maneuver into a place where this could be
exploited when completing Sokoban (e.g. to get into a corner that would
normally be inaccessible, from which position an otherwise-blocked
boulder can be pushed away). This behavior should incur the same penalty
as exploitation of other Sokoban 'loopholes'.
2021-01-07 18:55:46 +02:00
Michael Meyer
e7e418c1ec Prevent inappropriate diagonal dismounts
Dismounting a steed checked whether the target spot was accessible and
whether there was a monster on it, but not whether it could actually be
accessed by the hero through normal movement. As a result, dismounting
allowed the hero to pass between diagonal gaps that would normally cause
a "you are carrying too much to get through" pline; this could leave
them in a position where they are effectively stuck, unable to remount
their steed or move away without dropping their inventory.

This also could be abused by dismounting in Sokoban to squeeze between
boulders in a way that would normally be impossible.

Using a successful result test_move as one of the requirements for a
spot to be valid prevents this and limits valid dismount targets to
squares that would normally be accessible through standard movement.
2021-01-07 18:55:46 +02:00
nhmall
0c3b9642e4 pmnames mons gender naming plus a window port interface change
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.
2020-12-26 11:23:23 -05:00
nhmall
d1c7f26d4b clear a couple of new warnings
mondata.c:198:17: warning: unused variable 's' [-Wunused-variable]
    const char *s;
                ^
1 warning generated.

steed.c:43:17: warning: unused variable 's' [-Wunused-variable]
    const char *s;
                ^
1 warning generated.
2020-10-20 19:37:51 -04:00
Pasi Kallinen
566dde8683 Match object description via single function
making the code more readable.

Instead of doing strcmp(OBJ_DESCR(objects[otyp]), "foo"),
just call objdescr_is(obj, "foo")

(via xNetHack)
2020-10-20 19:19:57 +03: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
Patric Mueller
38fa93df73 Restrict the teleportation notification to actual teleportations
teleds() is used for more than just teleportations, the teleportation message
was also given when mounting a steed.

Trying out a new bit flags method parameter design pattern.
2020-01-11 19:51:54 +01:00
copperwater
277dcc05b5 Port the autounlock feature, hallucinatory trap names from UnNetHack
This adds a boolean option, autounlock, defaulting to true. When this is
set to TRUE, messages stating that some door or container is locked are
automatically followed by a prompt asking if you would like to unlock
it, if you are carrying an unlocking tool (key, lock pick, or credit
card).

Architecturally, this extends the pick_lock function to take three
additional arguments (door coordinates or a box on the ground you are
autounlocking).

The code that selects an unlocking tool will always look first for a
skeleton key, then a lock pick, then a credit card. Since curses, rust,
and other attributes don't really have an effect on the viability of the
unlocking device, it didn't seem to warrant making a more complex
function for that.

Add hallucinatory trap names

This adds many funny, realistic, and nonsensical traps to the game, to
be shown when the player is hallucinating.

Architecturally, the biggest change is merging the what_trap macro and
the "defsyms[trap_to_defsym(ttyp)].explanation" pattern into a single
function "trapname", which returns the name of the trap, handling the
hallucination case. There is also a second parameter used for overriding
hallucination in the occasional cases where the actual trap name should
always be returned.

In addition, the what_trap and random_trap macros are now obsolete and
not used anywhere, so they are removed.

reinstate anti-rng abuse bit on hallucination

updates to hallucinatory trap names and fixes37.0 entry
2019-12-19 18:52:23 -05:00
nhmall
a9c946a05f Merge branch 'NetHack-3.6' 2019-12-01 19:30:09 -05:00
nhmall
d2d40289e6 update and/or clarify some version references 2019-12-01 19:07:28 -05:00
PatR
9adeff5e27 3.7: fix #9397 - pronouns when hallucinating
Developed for 3.6 but deferred to 3.7.  Most of the testing was with
the earlier incarnation.

Report was that pronouns were accurate for the underlying monsters
when hallucination was describing something random, and also that the
gender prefix flag from bogusmon.txt wasn't being used.  The latter
is still the case, but pronouns are now chosen at random while under
the influence of hallucination.  One of the choices is plural and an
attempt is made to make the monster name and verb fit that usage.

|The homunculus picks up a wand of speed monster.
|The large cats zap themselves with a wand of speed monster!
|The blue dragon is suddenly moving faster.

There is no attempt to match gender for the singular cases; you might
get
|The succubus zaps himself [...]
or
|The incubus zaps herself [...]
2019-11-24 18:29:14 -08:00
nhmall
6aef1f13a1 Merge branch 'NetHack-3.6' 2019-11-16 17:09:44 -05:00
PatR
2a50fb1845 place_monster() debugging
Show more information if place_monster() detects something wrong.
I don't know whether it will actually be useful.
2019-11-16 13:42:25 -08:00
nhmall
0d34f43830 remove STATIC_DCL, STATIC_OVL, STATIC_VAR, STATIC_PTR from core 2019-07-14 17:24:58 -04:00
nhmall
bfc4445537 Merge branch 'NetHack-3.6' 2019-06-05 08:08:32 -04:00
PatR
43afa91ff8 fix #H8850 - bless/curse state in perm_invent
Changing an inventory item's bknown flag wasn't followed by a call to
update_inventory() in many circumstances, so information which should
have appeared wasn't showing up until some other event triggered an
update.
2019-06-04 10:50:24 -07:00
nhmall
e84fb24ede Merge branch 'NetHack-3.6' 2019-06-01 18:05:42 -04:00
nhmall
4eeebe5e20 fix gcc warning on linux 2019-06-01 17:26:15 -04:00
nhmall
5ee78c5204 improve full level handling in the endgame
Even though a goodpos failure in mnearto() would return 0 to
the caller and trigger proper overcrowding handling for mtmp,
the 'othermon' would be left with its mx,my set to 0,0 under
that circumstance and then trigger a mon_sanity_check()
failure and accompanying impossible() message a short while
afterwards.

This also includes the addition of some flags that proved useful
for troubleshooting the mystery sanity_check failure and helping
to understand some of the code paths the struct monst data had
been through. They are only used for inspection when issues are
reported or when debugging, they don't presently control the
code flow.  Their setting and use is done in an overloaded way
that should not intrude on the existing use of mspare1 for
MIGR_LEFTOVERS. mon->mstate is just a pseudonym for mon->mspare1
and does not alter save file content.
2019-06-01 16:51:10 -04:00
nhmall
d15496ba31 Merge branch 'NetHack-3.6.2' 2019-04-22 14:36:58 -04:00
nhmall
dcf4da2150 preserve dknown field between fakeobj instances
Preserve temporary fake object's previous dknown value by storing it
as a flag value within the m_ap_type field of the posing monster, and
recalling it when it is needed.

This is intended to help eliminate observable differences in price display
between real objects and mimics posing as objects.

98% of this is just switching the code to utilize macro M_AP_TYPE(mon)
everywhere to ensure that the flag bits are stripped off when needed.
2019-04-22 14:17:18 -04:00
Bart House
1c65e6afe0 context to g.context 2018-12-25 07:29:38 -08:00
Bart House
8c1a4d9a97 invent, youmonst, hackdir moved to g. 2018-12-24 21:04:15 -08:00
Bart House
be5cdcf77a killer, level and rooms move to instance globals. 2018-12-24 19:50:08 -08:00
Bart House
572ee347b9 Another round of instance globals changes. 2018-12-24 16:43:50 -08:00
Bart House
74edf42f1c Moved decl.c globals into instance globals. 2018-12-22 18:44:22 -08:00
PatR
8dfc10d8c6 fix #H2709 - exercise_steed() for riding skill
Code appears to intend that riding for 100 turns be treated like a
successful weapon hit as far as skill training goes, but it was
actually requiring 101 turns each time.  It's conceivable that that
was intentional, but unlikely.
2018-12-21 17:11:22 -08:00
PatR
30ddfb01db place_monster() warning bit 2018-12-12 17:54:53 -08:00
PatR
9952049a75 fix #H7677 - guard placed twice at <0,0>
"Placing monster over another?" warning was triggered for vault guard
by an earlier change which made m_detach() stop removing monsters at
<0,*> from level.monsters[][].  So one guard would replace another at
<0,0> for however many guards were created, and memory for all but
the last one would be lost.

This involved a lot of flailing about and the patch includes various
things would could have been discarded.  One or two extended monster
sanity checks are included, plus a couple of debugpline()'s for
tracking guard movement.
2018-12-12 01:54:33 -08:00
PatR
b113aa7439 more steed dismount
By creating a spot of lava, filling up the whole level, and creating
a lurker above, I managed to trigger the impossible "Dismount: can't
place former steed on map" that was added earlier today.  I also was
told that my god was displeased even though the engulfer's attack was
responsible.  This addresses both situations.  I can't trigger that
impossible any more, and only voluntary dismount blames the hero if
it's killed because there's nowhere to place it.  Hero is still blamed
for any dismount that kills the steed while flying or levitating over
dangerous terrain--hero took steed into jeopardy.
2018-11-29 18:02:52 -08:00
PatR
be327d9822 steed vs "no monster to remove"
Noticed whlie testing the steed-in-pit fix.  The EXTRA_SANITY_CHECKS
for remove_monster() are being tripped if riding hero has steed killed
out from under him because the steed is not on the map.  This started
out simple but got a bit complicated.  It seems to be sufficient but
I'm not very confident about it.

Being engulfed while mounted gave "placing monster over another?" due
to a change made along with EXTRA_SANITY_CHECKS but not conditional on
it.  (The change was to issue a warning about an actual problem which
was previously undiagnosed.)  I think bumping the engulfer off the map
in favor of the former steed only worked because some u.uswallow code
eventually used the hero's location to put the engulfer back.  I didn't
pursue that to try to figure what really happened, just prevent it.

The DISMOUNT_BONES handling was being executed even if the steed was
dead.  DISMOUNT_BONES only happens if the hero is dead.  Since I don't
know whether it's possible for dead hero and dead steed to happen at
the same time, move it inside the steed-not-dead block just in case.
2018-11-29 12:15:14 -08:00