Commit Graph

408 Commits

Author SHA1 Message Date
PatR
4a965bbd83 boulder pushing feedback
Redo the details about giving or suppressing "with great effort you
push the boulder".  It works the same except that if push a different
boulder than previously, you'll get a new message.  If you do it
while riding, you have the same lack-of-message for successive pushes
instead of getting a message every turn.

Don't exercise strength when pushing a boulder if poly'd into a giant.
2022-12-07 16:45:35 -08:00
PatR
20392a68fd yet more shop sanity checking
Reconcile boulder pushing with no_charge sanity checking.  The hack.c
part comes from entrez.

Pushing a for-sale boulder from inside the shop to the shop's boundary
("free spot", doorway, or gap in wall) adds it to the shop bill even
though it's still on the floor.  Leaving the shop without paying for
it is a robbery.  Also, pushing an unpaid boulder that's on the shop
boundary to any spot that's all the way outside the shop is robbery.
2022-12-05 23:05:20 -08:00
PatR
54aa047ec9 \#wizkill fix
When running #wizkill, if hero was swallowed and you killed the
engulfer and that dropped hero onto a level teleporter, the targetting
loop for selecting the next monster to kill kept going after changing
to another level.  Terminate #wizkill if killing something sends you
to a different level.

Not fixed, and an old bug, or variation of one:  the cursor got
positioned at the coordinates of your spot on the prior level even
though the part of the new level where you actually arrived was
displayed.

The hack.c and trap.c bits are just reformatting.
2022-12-01 15:36:40 -08:00
nhmall
02a48aa8cf split g into multiple structures
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
     ^ ^
2022-11-29 21:53:21 -05:00
SHIRAKATA Kentaro
0d441b0c2f remove the code to silence lint
Warning facilities on recent compilers are incredibly improved,
so the code to silence "good-old" lint is much less sense.
2022-11-19 00:49:11 -08:00
PatR
546930e05e tweak PR #925 - don't expose shop bill details
Avoid use of 'struct bill_x' outside of shk.c.
2022-11-19 00:38:20 -08:00
Michael Meyer
b8472af927 Charge hero for making off with shop-owned boulder
Pushing a shop-owned boulder out of the shop wouldn't charge the hero
anything.  Remedy this (and remove the boulder from the bill if the hero
then pushes it back in).  Also tried to handle a couple other uncharged
boulder "theft" scenarios: pushing a boulder into lava or water, into a
trapdoor or hole, or into a level teleporter (various other traps
already charged for the boulder -- it was pretty inconsistent).

I externified onbill() for this, since relying on otmp->unpaid by itself
impossibles if you push a boulder through a gap in a wall between two
adjoining shops.
2022-11-19 00:13:13 -08:00
PatR
333735863f tweak for #914 - attacking nothing
In the code that checks for attacking the edge of the map, the m_at()
that was just introduced isn't at risk of using <0,0> because of the
way 'glyph' is initialized.  But guard against future changes.

And I omitted this when checking the PR #914 commit in:
Closes #914
2022-10-29 23:48:46 -07:00
Michael Meyer
671f68fe98 Some displacer beast swapping tweaks
When fighting an unseen displacer beast mapped as an 'I' glyph on the
map, its typical ability to swap places with you was disabled and
replaced by it being treated like "thin air".  This was because
execution reaches domove_fight_empty when the target swaps places with
you.  Other than the displacement passive, this function is typically
only reached if there's no monster on the target square, so it prints
the "thin air" message and wastes a turn if you'd "expect" to attack
something (either because the player used an 'F' prefix, or because
there is an 'I' mapped on the destination square being moved into).

Hitting "thin air" seems like OK behavior for force-fighting a displacer
beast, since you are explicitly not trying to move into its spot (though
you could probably make an argument that the displacement should happen
even then, since it's the displacer beast initiating it), but the mon
being mapped as an 'I' doesn't seem like a good reason to disallow the
actual displacement from happening.

Don't treat an 'I' as "thin air" in domove_fight_empty if there's
actually a monster there, since it means there's a displacer beast
trying to swap places with you.

A couple other related changes: put an 'I' down on the map when an
unseen displacer beast swaps places with you, and use 'something' in the
'it swaps places with you' message when you didn't even realize there
was a monster there to begin with, so there's no context for the 'it' (I
used Some_Monnam at first, but the 'something' felt a little weird when
you were intentionally attacking an 'I' or warning glyph; this limits
the usage of 'something' further than Some_Monnam does).
2022-10-29 15:15:07 -07:00
nhmall
99a93fe50b some C99 changes
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.

If you want to try building on a platform that doesn't offer those
two functions, these are available:
    define NOT_C99       /* to make some non-C99 code available */
    define NEED_INDEX    /* to define a macro for index()  */
    define NEED_RINDX    /* to define a macro for rindex() */
2022-10-29 10:54:25 -04:00
Michael Meyer
c0dfa40cd3 Don't use boolean for losehp killer format type
Killer format isn't a boolean, since it has 3 possible values
(KILLED_BY_AN, KILLED_BY, NO_KILLER_PREFIX).  It shouldn't make any
difference behind the scenes, but it's confusing to use 'boolean' for
it.
2022-10-08 16:29:55 -07:00
Pasi Kallinen
60252cd28b Remove leftover debug pline 2022-10-07 11:44:03 +03:00
PatR
1c90965555 Passes_walls
While testing the secret door message handling, I wanted to phaze
through solid rock to get near some secret corridors.  Instead of
polymorphing into a xorn, I used #wizintrinsic to get temporary pass
through walls.  That let me move orthogonally through rock but not
diagonally.  Polymorph to xorn did allow diagonal movement.  I think
the difference was gaining 18/100 strength in that form.

Have wall phazing override narrow diagonal checks.
2022-09-08 09:18:43 -07:00
nhmall
c548fff9e4 some spelling corrections
The pull request included some changes that were neither accidental nor
unintentional, so only a subset of the changes from pull request #869
submitted by klorpa were manually applied.

behaviour  -> behavior
speach     -> speech
knowlege   -> knowledge
incrments  -> increments
stethscope -> stethoscope
staiway    -> stairway
arifact    -> artifact
extracing  -> extracting

The uses of "iff" were left alone.

Close #869
2022-09-08 10:54:11 -04:00
PatR
b07fe59b3c attack/damage by trapper and lurker above
Change trappers and lurkers above to remove digestion damage.  They
fold themselves around rather than swallow the victim.  There were
are lot of places that assumed that an engulfer which is an animal
would swallow and digest the victim.  In hindsight, it might have
been simpler to take the M1_ANIMAL flag off of trappers and lurkers
above.

This adds a new digests() predicate for creatures with AT_ENGL+AD_DGST
(purple worm) and also enfolds() for AT_ENGL+AD_WRAP (both 't'-class
critters).

There are several minor fixes mixed in with this.  I didn't record
them as I went along but the two I remember are
1) if poly'd into a holder and holding on to a monster, the '<' and
   '>' commands refursed to work; release the held creature first
   and then treat those commands as normal;
2) throwing a non-weapon while engulfed by an ochre jelly reported
   "the <item> vanishes into the ochre jelly's /currents/".

This needs a lot more testing.  I found and fixed multiple minor
details before my own testing burned out.
2022-08-15 04:14:36 -07:00
copperwater
549dfb92ea Remove obsolete find_skates function
find_skates was still in use for its one intended case, but objdescr_is
has been around for a few years now and can do just as good a job
without having to hardcode the first and last boots in objects[].
2022-08-14 10:12:54 +03:00
Pasi Kallinen
9be2e581b7 Macros for checking is object artifact 2022-08-12 19:37:34 +03:00
Michael Meyer
94e8141c01 Fix: lookaround trap detection
Whether a trap exists is independent on the underlying terrain type, so
putting a check for traps in a block structured like

| if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM)
|     ; /* do nothing */
| else if (levl[x][y].typ == CORR)
|     do_corridor();
| else if ((trap = t_at(x, y)))
|     avoid_trap(trap);

would mean that the check for traps only happens on terrain other than
normal room and corridor spots.  As a result, it wasn't being evaluated
in most places where traps might actually occur.

Move the test for traps outside of the terrain type evaluation if/else
series, so that it happens independent of terrain (and remove the
'continue' so it doesn't preclue evaluation of the terrain).

Once the rule actually started coming into play, it became clear the
avoid_moving_on_trap message was being printed in cases where the hero
didn't actually stop (i.e. shift-dir runmode, the "if you must" case),
so I also modified the value for that parameter so it will match the
situations where the hero stops running.
2022-08-10 20:01:22 +03:00
Michael Meyer
ce0107aff9 Restore old behavior for running onto trap
The refactor of domove made it impossible to run onto a trap (or water,
if blind), even in the shift-dir mode where the hero is meant to stop
only upon "hitting a wall or running into something".  I use this
runmode to sprint large distances across the map, and the change to this
behavior meant that it was no longer possible to press shift-dir again
to continue past the trap.  This restores the old behavior of allowing
shift-dir running to carry you onto a trap (though the hero will still
stop before hitting a trap in less breakneck runmodes).
2022-08-10 20:01:22 +03:00
Pasi Kallinen
fd9745f9c6 Command repeating by using cmd queues
This replaces the old pushq/saveq arrays (which were used to save
the keys pressed by the user for repeating a previous command)
with a new command queue.  This means there's no hard-coded limit
to the saved keys, and it can repeat extended commands which are
not bound to any key.
2022-08-09 11:54:45 +03:00
Pasi Kallinen
f07f065f7d Allow cutting a known spider web by force-fighting it
Original code from xNetHack by copperwater <aosdict@gmail.com>.
2022-07-25 18:06:10 +03:00
Pasi Kallinen
6fe0f7c132 Unify impaired movement direction checks 2022-07-17 12:23:49 +03:00
PatR
bb53addd14 more #802 - lava travel rather than running
Too many negations for my brain to cope with.  I've tested travel
properly this time, but not re-tested running (which shouldn't be
affected by this code).
2022-07-04 12:28:12 -07:00
PatR
d1d4614b26 more #802 - lava running
From entrez, then modified possibly beyond recognition:  don't run
or travel onto lava even with known safe lava-walking because that
isn't 100% safe.  But if already on/over lava, allow moving onto
adjacent lava in that situation.
2022-07-03 16:27:19 -07:00
Michael Meyer
6d222e88b0 Allow travel on water with IDed water walking
If you have a known source of water walking (i.e. are wearing formally
IDed water walking boots), allow travel to path you over water and allow
running over water.  A transition from land to water will still cause
the hero to stop in modes other than the shift+dir "move until you hit
something" running mode, so that you don't careen across the entire
level unless you really want to.

Also, fix running over water when levitation or flying is equipped.
This stopped working after f88dce6970, only allowing the hero to move
one square at a time.  And prevent travel from pathing the hero into a
wall of water even if flying or levitation is equipped, since they don't
allow you to bypass that terrain.
2022-07-02 15:10:54 -07:00
nhmall
3004cf2d34 be more consistent with coordinates 2022-07-02 09:10:03 -04:00
nhmall
30b557f7d5 change xchar to other typedefs
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
2022-06-30 23:48:18 -04:00
PatR
20c43287eb hack.c reformatting
Mostly adjusting some wide lines.  Should be no change in generated
code.
2022-06-13 03:35:46 -07:00
nhmall
be76727265 granular verbose message suppression mechanics
Switch to using a macro invocation Verbos(n, s) in place of the
flags.verbose checks.

Provide the mechanics for individual suppression of any of the
existing messages that were considered verbose.

Mechanics only - this code update does not provide any means of
setting the suppression bits.

iflags.verbose = 0
is still a master suppression of all the verbose messages.

iflags.verbose = 1
turns on the verbose messages only for those whose suppression
bit is 0 (not set).
2022-06-09 13:53:20 -04:00
PatR
5e1fba6e29 forcefight against edge of map
Noticed when testing the forcefight against obscured furniture fix:
if you attempted forcefight against the edge of the map, you got
feedback about having already moved as far in <direction> as possible
rather than about forcefight failing to attack anything.  Have the
can't move out bounds test check for forcefight before deciding to
give to its normal feedback.
2022-04-28 02:21:46 -07:00
Michael Meyer
d3d5f7f88b Fix: force-fight 'unknown obstacle' descriptions
This is intended to address a couple quirks with force-fighting an
unoccupied spot that I noticed:

 * Now that furniture is considered 'solid', an object is much more
   likely to be sitting on the square, obscuring the terrain glyph.  As
   a result, the current glyph is no longer sufficient to accurately
   describe the contents of the spot -- e.g., an altar with a corpse on
   top of it was being described as "an unknown obstacle", even when the
   hero knew exactly what furniture was there.

 * When blind and attacking an unexplored 'solid' square, the attacked
   position would always be described as 'the stone', even something
   like a fountain or sink which didn't seem likely to be confused with
   a stone wall.

 * The feedback for attacking stone was previously changed from 'solid
   rock' to 'stone' in order to be consistent with the feedback for
   attacking an unseen wall, but they still weren't quite the same
   ("stone" vs "the stone").

 * The 'stone' feedback for all STONE/SCORR spots was incorrect on
   levels flagged as arboreal, where stone is rendered and described as
   trees.

This relies on back_to_glyph for positions where the hero is aware of
the terrain and certain other spots (like stone, walls, etc) for which
back_to_glyph produces good results even if they're unseen, and falls
back to the generic "unknown terrain" in other cases.

Pretty long commit message for such a small commit, but oh well...
2022-04-28 01:10:46 -07:00
PatR
d194459c7d u.utraptype, TT_BEARTRAP
Add 'FIXME' fix by entrez to change TT_BEARTRAP to non-zero.

Increments EDITLEVEL, invalidating existing save and bones files.
2022-04-27 11:04:12 -07:00
Pasi Kallinen
6977aef436 Fix stuck travel for good
My fixes to the travel stuck oscillation did not fix all of them,
and I've even seen a 3-step loop - which my fixes cannot detect.
I guess there could be arbitrary-sized loops too.

To definitely fix this, keep track of all the map locations travel
has moved the hero through, and if it tries to go on a location already
used, stop travel and give the unsure -message.
2022-04-02 18:27:53 +03:00
Pasi Kallinen
476e47b2cd Use correct findtravelpath param value 2022-03-31 17:50:00 +03:00
Pasi Kallinen
c763e26aa7 Second fix to stuck travel
There were at least two cases of travel oscillation that occurred,
even after my previous fix. To fix those, the guessing routine
would also have to consider distance to original target location.
I opted not to make that part more complex - as there was
no guarantee those changes would catch all of the oscillation cases.

Instead, when we're guessing where to move, and we would actually move
back to where we came from, stop travel, and give a message.

This should fix (and fuzzing seems to confirm) all of the travel
oscillation bugs for good, and it shouldn't affect actual good travel.
(Other than the player getting a YAFM in the occasional case of trying
to travel to a location with no travel path)
2022-03-27 10:58:12 +03:00
Pasi Kallinen
1d78d3c3f2 Fix travel getting stuck oscillating between two locations
There's been occasional reports (perhaps once or twice a year)
of travel getting stuck moving repeatedly between two locations
next to each other, but it has never been reproduced before.

This special level lua code fragment is a minimal test case
which triggers it:

--- special level lua fragment, indented
  des.map([[
  --##---
  ###----
  #-+----
  ####--L
  ]]);
  des.door("open", 2,2)
--- end of special level lua fragment

The open door is required.

Magic map the level. Start from somewhere NW of the door, and try
to travel to the lava pool. Hero will get stuck oscillating between NW
of the door and two steps west of the door.

Here are the maps of the travel[][] array values from findtravelpath()
in those two steps in the above map:

-------------  -------------
|  . . 2 3  |  |  . . 1 2  |
|  1 1 2 .  |  |  1 @ 1 .  |
|  @ . . .  |  |  1 . 2 .  |
|  1 1 2 .  |  |  2 . 3 4  |
-------------  -------------

There are two possible closest locations to the lava pool,
the one marked with "3" on the left map, and "4" on the right map.
Based on that alone, both would be valid places to path to.

But, in the left case, hero could not see the bottom location, so
the code won't even consider pathing to it, so it will start moving
towards the "3".

When hero moves to the second position, in the right map, now the "4"
could be seen. Now there are two possible closest locations we could
choose from. The code that scans the possible locations goes from top-left
to bottom-right, first going down (y-axis). So, the code sees the
"2" on the right. distmin() to there is 2. Good, we pick that location
to path to. Next, going down, the code considers the "4" ... which is
also equally close to the lava pool. and distmin does not consider terrain,
so ignores the door, so it has the same distmin value of "2", so the
code picks this location.

But: this was just a guess, because there's no known valid path to the
lava pool. The code loops back up to rebuild the travel[][] array
with a new starting location as the "4" from the right map, pathing
back to hero.

This is that travel array map:
-------------
|  . . . .  |
|  4 @ 3 .  |
|  3 . 2 .  |
|  3 2 1 x  |
-------------

The way travelstepx and travelstepy arrays are built means that the first
location that considers the hero's location is the "3" SW of hero, so
hero will move there next. Repeat from beginning. If there was no door,
the travelsteps would reach hero's location first from SE.

(I left the travel[][] array rebuild and travelstepx/travelstrepy build
off from the other movement position, as it's not relevant)

The fix: When considering which of the two possible closest places to the
lava pool to path to, use the one with the lowest value in the travel array.
That value is the real number of moves it takes for the hero to walk there,
so the code will consistently path to the upper location, as it is "2",
instead of considering the "4" below it.

Also some minor code reorg, so it considers couldsee first instead of
later in two separate places.
2022-03-26 23:58:30 +02:00
Pasi Kallinen
60bf399f91 Don't stop travel when going past a closed door 2022-03-24 19:33:37 +02:00
Pasi Kallinen
39acd095b2 Add helpless monster macro 2022-03-18 10:19:04 +02:00
nhkeni
e51026aee1 LIMIT_TO_RANGE_INT macro and various casts. 2022-03-16 17:59:23 -04:00
Pasi Kallinen
71fe55eba8 Reset next_boulder when boulder was pushed 2022-03-05 16:36:26 +02:00
Pasi Kallinen
3834bb2ca0 Get out of moverock correctly, so we clear next_boulder 2022-03-05 15:46:16 +02: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
4b6b976e3b Split escaping from sticking monster check out of domove 2022-02-25 22:26:12 +02:00
Pasi Kallinen
f88dce6970 Unify domove and lookaround trap/liquid avoidance code
Nearly same code was in two places - the only difference was
how g.context.run == 1 was handled.  Previously, if you were
blind, and knew about the water or lava, you still ran into it.
Now, we always avoid the dunking if running/rushing.
2022-02-25 21:52:52 +02:00
Pasi Kallinen
e57c631ef9 Minor code clarification 2022-02-25 19:48:17 +02:00
Pasi Kallinen
86bc0a2633 Split movement out of bounds check out of domove 2022-02-25 18:33:50 +02:00
Pasi Kallinen
4e11a85fb7 Split carrying too much check out of domove 2022-02-25 18:12:55 +02:00
Pasi Kallinen
2012254c39 Split impaired movement code out of domove 2022-02-25 17:06:25 +02:00
Pasi Kallinen
7733cbe399 Split water turbulence code out of domove 2022-02-25 16:59:52 +02:00
Pasi Kallinen
7a29110514 Split ice fumbling code out of domove 2022-02-25 16:43:09 +02:00