Modifying an() [actually just_an()] to treat "<thickness> ice" and
"frozen <hallucinatory liquid>" as special cases which shouldn't be
prefixed with "a" or "an" affected using something like "shaved ice"
or "frozen yogurt" as named fruit.
|a) shaved ice
|b) frozen yogurt (weapon in hand)
now have article "a" preceding them:
|a) a shaved ice
|b) a frozen yogurt (weapon in hand)
However, the existing cases
|c) iron bars
|d) an iron bars (weapon in hand)
still get item 'c' wrong. 'd' is slightly odd but that's because the
fruit name is ambiguous as to whether it's singular or plural.
Classify nearby ice as "solid" (no melt timer), "sturdy" (more than
1000 turns left), "steady" (101 to 1000 turns left), "unsteady" (51
to 100 turns left), "thin" (15 to 50 turns left), or "slushy" (1 to
14 turns left, matching walking on ice with the Warning attribute).
[I'm not thrilled with "steady" and particularly "unsteady".]
I was originally going to do this just for probing downward, but ended
up also doing it for look-here and getpos's autodescribe. It nearly
got out of hand and touched more files than anticipated.
'mention_decor' ought to treat moving from ice firmer than thin to
thin or slushy, from thin to slushy, from slushy to any other, and
from thin to firmer as if moving onto different terrain but I haven't
attempted to tackle that.
The melt timer could work more like a candle's burn timer, triggering
at intermediate stages and resetting itself, so that ice which changes
to a weaker state under the hero could be reported to the player. But
this doesn't implement that.
From a comment w/ diff in the pull request by entrez, combine the
show-full-map flag (available in wizard mode and explore mode) with
the bitmask for map-only, map-and-traps, map-and-traps-and-objects
flags for #terrain mode (and getpos() help) instead of passing that
as a separate argument. No change in behavior unless I messed up.
Only show the '/' menu choice for context-sensitive inventory item
action if data.base look up for the item will find something. Lack
of '/' is as informative as "you don't know anything about that".
Harder to implement than expected but seems to be working ok.
This also changes the menu for the '/' command, replacing cryptic /^
and /" with /t and /T so that listing near traps or all traps is more
like listing near|all objects|monsters. I put caret and double-quote
in as group accelerators; double-quote works on tty, caret gets
intercepted as "menu first page" so doesn't. I didn't check other
interfaces since supporting that doesn't seem to be worth the bother.
Also a little bit of reformatting.
Rest of 'not PR #1102'. Resizing the terminal while getpos was in
operation recalculated the map from scratch instead of redrawing what
the core considers to already be shown. And it was always operating
while an asynchronous signal was excuting which could potentially
clobber whatever was running at the time the signal arrived.
This uses same redrawing as the prior '^R during getpos()' fix. It
also only performs the resize while tty_nhgetch() is waiting for
input. If that is the situation at the time that the signal arrives
then it will resize immediately (while in the asynchronous signal
handler); if not, it will set a flag and tty_nhgetch() will do the
resize the next time it gets called.
This builds with TTY_PERM_INVENT enabled and doesn't seem to be any
worse than before, but there are bugs with that. The only way I could
get perminv to appear was to save and restore, then perm_invent was
honored for both RC file and mO command. And once I managed to get it
to display, moving an item from a lower case slot to slot 'A', made
that item vanish; nothing appeared in the invent's right hand panel.
Both of those misbehaviors already happen prior to this commit. I
also saw an abort+panictrace if I resized while at the "Dump core?"
prompt when running the pre-commit code and didn't see that with the
post-commit code (although the prompt wasn't shown so I couldn't tell
that it was waiting for an answer). The abort probably sounds scarier
than it warrants; I suspect that the pre-commit code just treated the
resize as answering 'y' for some reason, possibly a stale value in the
variable it uses.
This fixes the part of pull request #1102 by entrez dealing with the
map refresh side of things. It was pulled out of a much larger patch
that also deals with terminal window resize for tty.
Using ^R when getpos() is in operation, whether actually picking a
position for something or browsing the map during #terrain or post
detection magic, it was reconstructing the known map and positioning
the cursor on the hero instead redrawing the selected terrain subset
or detected objects/monsters/whatever. There's already a routine to
redraw the current view of the map without recalculating it, but it
wasn't being used for ^R during getpos operation.
b_trapped was treating 0 as a null value for its bodypart parameter, but
0 is actually the value of ARM, so b_trapped(..., ARM) would be treated
as intending no A_CON abuse. Add NO_PART = -1 to the bodypart_types
enum, and use that instead of 0 as the "no body part" value in
b_trapped, so that ARM can be passed to it without any ambiguity.
aosdict identified this issue in xNetHack and handled it differently; he
added NO_PART with a value of 0, incremented the existing bodypart_types
values, and padded the body part arrays so the actual body parts would
start at index 1. I think using NO_PART = -1 is simpler, but that's an
alternative approach that can be used instead -- it is advantageous in
that it automatically fixes any other places where 0 is assumed to be a
non-body-part value that I may have overlooked.
If there were outdated savefiles encountered during
startup, each individual one was getting a wait_synch
that required a <return> even though a message window
wasn't being used at that point.
Allow suppression of the individual per-file wait_synch()
calls on Windows, so that a single one can be done once
the selectsave processing is overwith.
This was a little messy because an indicator had to flow
down through validate(), uptodate(), etc.
There shouldn't be any change in how things behave on
any non-Windows platforms.
For Autoselect-all confirmation, accept yes|n|q (or yes|no|quit)
rather than just yes|n (or yes|no). An extra query routine is needed
to support it, but the existing paranoid_query() can just call the
new paranoid_ynq() with an extra argument, keeping things painless.
For menustyle:full plus paranoid_confirmation:Autoall, if you include
'A' in the class filtering choices then you're prompted for whether
you really meant it. (Same behavior as in the past few weeks.) Yes
auto-selects items matching all other chosen classes, or from all
classes if 'A' is the only choice. (Again, same behavior.) n|no
moves on to menu:full's second menu. If anything else was chosen
along with 'A', that's what the second menu will offer. (Same as
past few weeks but revised from initial implementation.) If 'A' was
the only choice, it will now use 'a' and offer a choice of everything
in the second menu. (That's a change; it used to cancel if declining
to honor 'A' and nothing else was present.) Now <return> without
answering or q|quit or ESC skips the second menu, whether or not the
rejected 'A' was the only choice made in the first menu. (New.)
Other paranoid confirmations still just accept yes and n|no responses,
treating ESC as n|no.
The hitpoints and power/energy status values (and corresponding
maxima) shown on the screen are capped at 9999 to control status line
width. The actual values can be bigger than that. Highlights based
on percentages were doing their calculations on the potentially
truncated values rather than on the actual ones.
Add another field to the blstat[] structure, populate it for BL_HP,
BL_HPMAX, BL_ENE, and BL_EXEMAX and switch to it for their percentage
calculations.
Doesn't seem to break highlighting of 'normal' range values but hasn't
been tested for extreme ones.
The default engraving-in-corridor character is the same as the default
corridor symbol (and also default lit corridor one), distinguished by
color. Show it differently (in inverse vidoe, like lava vs water and
sink vs fountain) if color is Off.
It might be better to change the engraving-in-room symbol to be the
same as the room one so that they'll be more consistent with corridors;
color is probably sufficient without resorting to back-tick. But this
update hasn't done that.
Fairly old pull request from copperwater: add new paranoid_confirm
setting 'trap'.
The old commit suffered from bit rot and merging needed too much
fixing up despite there not being many bands of change in the commit's
diffs. I ultimately redid it from scratch, although the two biggest
chunks of code started with copy+paste of the pull request's commit.
It operates like paranoid:pray. Setting paranoid:trap adds a new
"Really step into <trap>?" y/n prompt when attempting to move
into/onto a known trap, even if an object covers it on the map.
Setting both 'paranoid:Confirm trap' turns that into a yes/no prompt.
(Adding 'Confirm' affects other paranoid confirmations; in addition
to requiring yes<return> rather than just y to accept, it also forces
no<return> to reject.)
However, moving into a known trap that is considered to be harmless
behaves as if no trap was present. Some of the trap classification
might be out of date; several types of traps have undergone changes
since implementation of the original pull request, notably anti-magic
field. When the hero is hallucinating, all known traps are considered
harmful since the map no longer reliably describes them.
Preceding a movement command with the 'm' prefix also behaves as if
no trap was present, bypassing confirmation for that move, similar to
how paranoid:swim currently behaves. Being stunned or confused also
behaves as if no trap was present, taking priority over hallucination.
This updates the documentation.
Supersedes #259Closes#259
Monsters can become permanently blind (in very narrow circumstances -- I
think limited only to a very short-range camera flash), in which case
they have both mon->mblinded and mon->mcansee set to 0. Such
permanently blinded monsters can counterintuitively regain their sight
by being blinded a second time from a different source: for example, by
being hit with a cream pie. That second blinding will increase
mon->mblinded (which functions as a blindness timeout) by some amount,
and when it runs out the monster will regain its sight. Try to make
sure that doesn't happen by skipping any blinding attacks if the monster
has already been permanently blinded.
When calling panic() or impossible(), create the option
of opening a browser window with most of the fields
already populated. Code for MacOS and linux is included;
other ports are affected by argument change to early_init
which are done but not tested.
To enable, define CRASHREPORT in config.h and set
CRASHREPORTURL in sysconf to (for the moment at least)
http[s]://www.nethack.org/common/contactcr.html
Adds --grep-defined option to makedefs for Makefiles.
Adds "bid" (binary identifier), an MD4 of the main nethack
binary. This is ONLY for helping (in the future) contact.html
to set the "NetHack from" field automatically for our own
binaries. This can be faked, but the user can lie so nothing
lost. There's nothing magic about MD4; other ports can use
anything that prodcues a long apparently random string we can
match against.
- new option --bidshow for us to get the MD4 of a
released binary so I can add it to the website.
Only available in wizard mode and not in nethack.6.
- typo macos -> macosx in hints file
No support for packaging builds as I'm not sure what that
would look like.
Adds a javascript helper for MacOS.
Adds a lua helper for linux (and builds and installs
nhlua).
If you killed a second high priest (either two on Astral or first in
the Sanctum and another on Astral) the livelog/#chronicle message
would report "killed high priest of Foo (2nd time)" even though the
first was the high priest of Bar, or even just "killed high priest
(2nd time)" if second kill happened when not adjacent.
High priests pass the 'unique monster' test (even though they aren't
actually unique--there will be four of them) so get logged for killing
such. Always report "killed high priest of Foo" and only do so if the
specific high priest[ess] monster hasn't been revived and re-killed.
Logging deaths of unique monsters normally reports the 1st, 2nd, 3rd,
5th, 10th, and various later instances. If you were to kill Moloch's
high priest and all three on Astral, the last one wouldn't be logged
because 4th instance gets skipped. This forces each one to be treated
as the 1st (provided that the mrevived flag is clear), so for logging
purposes it will now behave as if there are 4 distinct high priests.
If a monster sees you remove some piece of gear that grants a
resistance, it will remove that resistance from its list of remembered
resistances and be willing to try attacking you with that adtyp again.
This avoids the situation where you put on a ring of cold, get hit with
one cold attack, and then can remove it because all the monsters nearby
will permanently remember you as being cold resistant (but even after
this change a wily hero could still step into a niche and do it without
any monsters seeing, so trick them into thinking she's still cold
resistant...). The hero could still be resistant if there were multiple
sources to begin with, of course, but the monsters will test it and
learn that again if necessary.
It's a little weird that the monsters can recognize the intrinsic
granted by the item being removed, but they display knowledge of
unidentified (by the hero) objects in many other circumstances too, so I
hope it's forgivable in the pursuit of having them act more cleverly
about resuming previously-resisted attacks like this. Another approach
that avoids the gear recognition, blanking seenres on any gear change,
can result in odd situations like orcs treating their own cloaks as
potential sources of many different resistances, which also seems silly.
Adds a new lua command
des.exclusion({ type = "teleport", region = { x1,y1, x2,y2 } });
which allows defining "exclusion zones" in the level, areas where
random teleports (or falling into the level) will never place the hero.
Does not prevent targeted teleportation into the area.
Breaks saves and bones.
The sortloot classification routine had some inappropriate casts to
'coordxy' for things had nothing to do with map coordinates. I was
going to change the relevant fields to 'short' but that seems iffy
for 'indx' so I changed them all to 'int'.
This is a re-creation of a project that was lost years ago while not
quite finished. The old version included some instrumentation to
measure how many hits it takes to kill things during actual play; that
wasn't ready for prime time and this hasn't attempted to redo it.
Changes:
1) improves martial arts and bare-handed combat: they now have a
chance to hit twice when skill is better than 'basic'; 20% chance
for second hit at skilled, 40% at expert, 60% at master, and 80% at
grandmaster; when attacking more than once, strength bonus is
handled as in #2;
2) nerfs two-weapon combat a bit: hitting twice uses only 3/4 strength
bonus on each hit, but when both attacks hit that's 3/2 bonus from
strength which is still more than you get for one hit at a time;
3) beefs up two-handed weapons: hitting via melee with a two-handed
weapon uses 3/2 of stength bonus to reflect the increased influence
of strength; isn't done for applied polearms though.
The reduction in strength bonus for two-weapon has far less impact
than it might sound, due to rounding up with the low values involved.
| full 3/4
| +1 -> +1
| +2 -> +2
| +3 -> +2
| +4 -> +3
| +5 -> +4
| +6 -> +5
The small reduction also doesn't matter if/when current hit happens to
deal a killing blow anyway.
Rings of increase damage apply at full value to every hit, same as
before.
When hitting bare-handed (#1 without gloves), a silver ring on either
hand continues to give a damage bonus against silver haters when you
make an ordinary single attack. However if you attack twice, a silver
ring only applies on the first hit when it is worn on the right hand
and only applies on the second hit when worn on the left hand. (Two
hits with a silver ring on each hand will give silver bonus for both.)
We might conceivably need to add support for a count prefix of 1 to
let player explicitly avoid a second bare-handed/martial-arts hit
attempt (similar to how throw and fire accept a count to limit missile
volley amount).
Kicking has been ignored.
Don't use "slither" for movement action when observing an aquatic
monster go into hiding underwater. Use "dive" instead.
Shark, pirahna, and jellyfish had been flagged M1_SLITHY but aren't
anymore. Giant eel and electric eel are still M1_SLITHY and kraken
wasn't and still isn't.
There may be some odd cases that used to use slither and it went by
unnoticed where now use of the default verb might become noticeable.
When returning to play from within the tutorial, remove the level files
similar to how they're discarded for the rest of the dungeon when going
into the endgame. It turned out to be a bit messier than anticipated.
The dungeon.c bit is sufficient for #overview, which now hides regular
level 1 while in the tutorial and hides all tutorial levels once exited.
Those will still appear in end-of-game disclosure.
This allows players to specify a highlight for critically low HP in
the config file, for example:
OPTIONS=hilite_status:hitpoints/criticalhp/purple&inverse
This will cause the hitpoints field to be highlighted when HP is low
enough to be considered a major trouble. The new "criticalhp" setting
only applies to the hitpoints field.
Since the critical HP threshold changes with level (and most of the
fractions are not integer percents) it was impossible to set
highlights to match the critical HP threshold using percentage
settings.
Issue reported by vultur-cadens: arriving on the Mine Town level
via falling or level teleport won't register the "entered Minetown"
achievement if hero doesn't arrive inside a room.
Reorder some code in check_special_room() so that town entry will be
tested before the early return if no room entry has occurred. This
adds 'level.flags.has_town' to make the town test be cheaper when
the hero hasn't attained the achievement yet and is wandering around
the mines.
Fixes#1070
Pull request from entrez: the legend for wizard mode #terrain wasn't
updated to include terrain type "lava wall", so the entries for it
and everything that followed were inaccurate.
I've expanded the comment about level type codes in rm.h.
Closes#1052
Something that's reasonable to expect to see in Lua files is something
like:
local sel4 = sel1 - sel2 - sel3
or more generally, producing a selection from subtraction that will then
be used in subsequent selection math.
I discovered this wasn't actually working correctly, and that it also
applied to the xor operation. The reason behind this is that
l_selection_sub and l_selection_xor create a new selection from nothing,
which by default has "lower" bounds of COLNO, ROWNO and "upper" bounds
of 0,0. Iterating across the intersecting rectangle of both selections
does not reliably set the bounds of the resulting selection properly,
since the first selection_setpoint with a value of 0 will cause the
selection's bounds_dirty flag to be set, at which point they will cease
to change as more points are added.
Then this selection with its incorrect boundaries is pushed back onto
the Lua stack, and becomes the first operand of the next subtraction
(i.e. selr in the first l_selection_sub becomes sela in the second
l_selection_sub). Depending on how broken the bounding box is, results
may vary, but if the bounding box is still (COLNO,ROWNO,0,0), the
resulting selection will have no points selected at all.
This fixes this problem by forcibly recalculating the bounds of the
result selection, so any subsequent operations on it will be valid.
I saw this in the YANI archive, and I think it's fairly interesting.
Doppelgangers are known for commiting identity theft, but in NetHack
they function as just another shapeshifter. This commit makes them
a bit more interesting, I think.
Original YANI by aosdict and Andrio.