Some jumping paths are rotationally asymmetrical
Certain jumping patterns take you on a different path depend on the origin and destination. An example of a 2/1 jump:
....
.X..
.T*.
..@.
In this case, if you jump from the @ to the X, you pass to the right of the tree and make it to your destination. However, if you try to jump the other way, you bump into the tree. Jumping 4/1 has a similar issue. I know that NetHack Is Not Real LifeTM, but this seems like an egregious case of pedantic gameplay mechanics, and makes the already esoteric jumping system even more user-unfriendly. I thought of a few possible solutions:
- Make the ambiguous space depend on the parity of the row for north/south jumps, or the column for east/west jumps. This makes jumping deterministic, so you can always jump back to your destination. On the downside, some jumps become completely impossible in either direction, for no good reason.
- Have jumps deliberately choose a clear space if the other one is occupied by a known obstacle. If the obstacle is hidden (an invisible monster, or an eel hidden under water), revert to the existing behavior, but the player at least has a chance to avoid it.
- Add a keypress to flip the ambiguous part. It complicate jumping a bit, but gives the player complete control over their path.
On Thu, Dec 14, 2023 at 07:36:43AM -0800, eakaye wrote:
I thought of a few possible solutions: [...]
- Have jumps deliberately choose a clear space if the other one is occupied by a known obstacle. If the obstacle is hidden (an invisible monster, or an eel hidden under water), revert to the existing behavior, but the player at least has a chance to avoid it.
There's actually already a comment discussing this idea in walk_path(dothrow.c):
/* Use Bresenham's Line Algorithm to walk from src to dest.
*
* This should be replaced with a more versatile algorithm
* since it handles slanted moves in a suboptimal way.
* Going from 'x' to 'y' needs to pass through 'z', and will
* fail if there's an obstacle there, but it could choose to
* pass through 'Z' instead if that way imposes no obstacle.
* ..y .Zy
* xz. vs x..
* Perhaps we should check both paths and accept whichever
* one isn't blocked. But then multiple zigs and zags could
* potentially produce a meandering path rather than the best
* attempt at a straight line. And (*check_proc)() would
* need to work more like 'travel', distinguishing between
* testing a possible move and actually attempting that move.
*/
In a way the jumps in both directions are the same. They both move vertically first, then diagonally. Probably because the vertical distance is the greater of the two.
There's actually already a comment discussing this idea in walk_path(dothrow.c):
That comment discusses a fully general case where every move of the jump is negotiable. I'm suggesting implementing wiggle room only where the path passes exactly between two squares, so both choices are equally valid:
@,
AB
CD
EF
.X
In this case, the player would be able to choose between passing through C or D (or it would be chosen for them in a deterministic way, so that a reverse jump would choose the same square). They wouldn't be able to choose B instead of A, or E instead of F, because the path is biased against those squares. So the "meandering path" issue noted by the comment would never come up.