Commit Graph

376 Commits

Author SHA1 Message Date
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
Pasi Kallinen
cb5ca657ed Split air turbulence code out of domove 2022-02-25 16:13:27 +02:00
Pasi Kallinen
d617875a82 Split force-fighting empty square out of domove 2022-02-25 15:19:51 +02:00
Pasi Kallinen
48cd81dbfd Split swapping places with pet code out of domove 2022-02-25 15:09:56 +02:00
Pasi Kallinen
f44a4b0485 Change unknown mintrap result into impossible 2022-02-25 14:57:03 +02:00
Pasi Kallinen
3b521aa955 Split force-fight iron bars code out of domove 2022-02-25 14:54:33 +02:00
Pasi Kallinen
57f55f5ca6 Split some code out of domove
Should have no change in behaviour.
2022-02-25 14:46:45 +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
9716f22851 Make trap return values more consistent
Instead of returning monster's mtrapped-state, return specific
trap return values.
Add one extra trap return value, for when a monster was
moved by the trap.
2022-02-24 16:24:02 +02:00
Pasi Kallinen
8e91320d2f Use u_at macro 2022-02-23 20:28:55 +02:00
Pasi Kallinen
5786ddadbb Use IS_WATERWALL and is_waterwall 2022-02-23 12:53:09 +02:00
Kestrel Gregorich-Trevor
355ed43a29 pull request #660 from NullCGT - sleeping monsters
Indicate to players that monsters are sleeping.

Closes #660
2022-02-22 11:36:40 -08:00
Pasi Kallinen
e65c921ccb Use grounded macro 2022-02-15 18:44:56 +02:00
Pasi Kallinen
3b2e4d682d Water walking doesn't help in wall of water 2022-02-13 14:38:54 +02:00
Pasi Kallinen
7302b87dd5 Improve avoiding walls of water 2022-02-13 14:19:40 +02:00
Pasi Kallinen
d26c7dde44 Fix the "wall of water" and paranoid:swim 2022-02-13 11:00:09 +02:00
Pasi Kallinen
73dbd39d98 Use proper locomotion when avoiding water or lava 2022-02-13 10:56:40 +02:00
Pasi Kallinen
03c715f179 Add paranoid:swim to prevent typoing into water or lava
In the name of accessibility: Prevent moving into dangerous liquids.

Now with themed rooms, water and lava are more common, and it's
unreasonable to expect blind players to check every step for those.
With paranoid:swim, just prevent normal walking into those liquids,
unless you prefix the movement with 'm', or if the liquid would not
harm you.

Doesn't completely prevent an accidental dunking - for example
if the hero is impaired or couldn't see the liquid.

This comes from xNetHack by copperwater <aosdict@gmail.com>
with some changes to the code.
2022-02-12 17:29:32 +02:00
Pasi Kallinen
91e2d3633e Use macro for a location next to hero 2022-02-12 11:05:10 +02:00
Pasi Kallinen
1e90f89203 Chronicle of major events, and livelog
Log game events, such as entering a new dungeon level, breaking
a conduct, or killing a unique monster, in a new "Major events"
chronicle. The entries record the turn when the event happened.
The log can be viewed with #chronicle -command, and the entries
also show up in the end-of-game dump, if that is available.

This feature is on by default, but can be disabled by
defining NO_CHRONICLE compile-time option.

This also contains "live logging", writing the events as they
happen into a single livelog-file. This is mostly useful for
public servers. The livelog is off by default, and must be
compiled in with LIVELOG, and then turned on in sysconf.

Mostly this a version of livelogging from the Hardfought server,
with some changes.
2022-02-09 22:49:25 +02:00
Pasi Kallinen
4ee1c66f8f Make solid water behave more consistently
The "water" terrain (as used on the Plane of Water) behaved
strangely outside the plane. Make it behave a bit more consistently,
although it's still not really usable elsewhere.

The rationale here being it's a solid wall of water.

Firstly, disable levitation and flying (which was already done
when moving into the water on the Plane of Water), and moving into
it refers to it as a "wall of water" to make it clear it's a solid
block of water.
2022-02-06 20:38:22 +02:00
PatR
2c456704c4 comment typo 2022-02-06 02:18:17 -08:00
Pasi Kallinen
20054551f9 Don't push unknown boulders when moving
If you're blind and there's a boulder you don't know about,
don't automatically push it. Instead, give a message and show
the boulder on the map.
2022-02-05 11:30:35 +02:00
Pasi Kallinen
8f7f598050 Fix mention_walls distinguishing unseen walls from solid stone
Bumping into an unseen wall reported "a wall" instead of "solid stone",
even though you could not know it was a wall when looking at it.

Use the same method when looking at glyphs on the map instead of
the map location type.

Fixes #318
2022-02-04 14:02:18 +02:00
Pasi Kallinen
6ed315ecf8 Don't stop running next to a peaceful monster
... unless the monster blocks the way.
2022-01-24 18:45:57 +02:00
PatR
6fda779979 move_update()
Some changes I made while investigating the unpaid_code impossible.
Shouldn't produce any noticeable changes in behavior.
2022-01-11 23:42:13 -08: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
b1ed92abad Apply runmode to multiturn actions 2021-12-21 17:37:48 +02:00
PatR
2278434228 simplify issuing urgent messages
Change
 custompline(URGENT_MESSAGE, mesg, ...);
calls to new
 urgent_pline(mesg, ...);
2021-12-20 08:30:48 -08:00
PatR
420d121f93 'urgent' messages
Follow up on some old groundwork.  For tty, if the core has designated
a message as 'urgent', override any message suppression taking place
because of ESC typed at the --More-- prompt.  Right now, "You die"
messages, feedback about having something stolen, feedback for
"amorous demon" interaction (mainly in case of armor removal), and
exploding a bag of holding are treated as urgent.

The "You die" case is already handled by a hack in top-line handling;
I left that in place so the conversion of 3 or 4 pline("You die.*")
to custompline(URGENT_MESSAGE, "You die.*") was redundant.  There
are probably various non-You_die messages which precede done() which
should be marked urgent too.

Other interfaces might want to do something similar.  And we ought to
implement MSGTYPE=force or MSGTYPE=urgent to allow players to indicate
other messages that they want have to override suppression.  But I'm
not intending to work on either of those.  I mainly wanted to force
the magic bag explosion message to be shown since a sequence of "You
put <foo> into <bag>." messages is a likely candidate for --More--ESC.
2021-12-17 17:46:49 -08: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
b4908f6928 fix pull request #621 - potential divide by 0
The pull request by argrath changes weight_cap() to never return a
value less than 1 because try_lift() divides by that return value
and a 0 would trigger a crash.  The code involved is used when
attempting to pull a monster out of a pit via #untrap.

I'm fairly sure that weight_cap() can never produce a value that's
less than 1 already, but have put in a variation of the PR's fix.
I've also implemented a different fix that removes the division
from try_lift().  The original code seems to have gone out of its
way to avoid calculating inv_weight() twice, but doing the latter
(for the once in a hundred games where it might happen) greatly
simplifies things by removing details of carrying capacity.

Fixes #621
2021-10-25 14:51:26 -07:00
PatR
6edadc4884 fix github issue #614 - applying polearm at doors
Reported by G7Nation; attacking walls and such with a polearm just
gave lackluster "you miss; nobody's there" feedback.

Make applying a polearm at some non-monster locations give feedback
similar to using 'F'orcefight with melee weapons.  Was
|You miss; there is no one there to hit.
now
|You uselessly attack the closed door.

Also, extend the supported locations to include dungeon furniture.
Was
|You attack thin air. ('F')
now
|You harmlessly attack the throne. ('F')
|You uselessly attack the throne. ('a')

This doesn't address #613:  attempting to hit non-visible locations
with an applied polearm.

Closes #614
2021-10-24 10:06:30 -07:00