While polymorphed and underwater, an eel bite killed the hero who
rehumaized and crawled out of the water, then the eel continued with
its second attack and "wrapped itself around you" even though no
longer adjacent. That's a long reach....
| ...@.
| .;}..
| .}}..
Make any additional attacks silently miss if hero changes location
during the attack sequence of a monster who has pinpointed the hero.
Role selection is insanely complex. I had to use a debugger to force
the relevant routine to be executed.
The analysis was correct: it could use rn2(14) to pick a role (valid
values 0 through 12) and randomly getting 13 would lead to a crash.
The terminating element of roles[] passes all the ok_role(), ok_race(),
etc tests. Explicitly exclude that element when collecting the roles
to choose from.
Implement the request that a wielded+thrown aklys be given the same
inventory letter when it returns and is caught and rewielded, even for
the !fixinv setting where inventory letters don't stick. Works for
Valkyrie-thrown Mjollnir and returning (ie, didn't hit) boomerangs as
well as for aklys.
I'm not sure how useful this really is, because on the rare occasions
that it either doesn't return or fails to be caught, it won't be given
the same letter when subsequently picked up. So the player who relies
on it will still be vulnerable to using the wrong letter next time a
throw is attempted. But at least picking it up explicitly displays
the new inventory letter, unlike catching it upon return.
Instead of having the demon lair levels unconditionally no-teleport,
grant demon lords and princes the ability to suppress teleportation
in Gehennom on the level they are on.
Eliminate the cache that was supporting rndmonst() and pick a random
monster in a single pass through mons[] via "weighted reservoir
sampling", a term I'm not familiar with.
It had a couple of bugs: if the first monster examined happened to
be given a weighting of 0, rn2() would divide by 0. I didn't try
to figure out how to trigger that. But the second one was easy to
trigger: if all eligible monsters were extinct or genocided, it
would issue a warning even though the situation isn't impossible.
Aside from fixing those, the rest is mostly as-is. I included a bit
of formatting in decl.c, moved some declarations to not require C99,
and changed a couple of macros to not hide and duplicate a call to
level_difficulty().
Fixes#286
The traceback points directly to the problem: divide by 0 happens
if the 'bogusmon' file only contains the "do not edit" line, which
would happen if 'bogusmon.txt' is empty. makedefs probably ought to
complain about that.
There is now one hardcoded bogus monster to fall back to: 'bogon'.
Random tombstone epitaphs report divide by 0 if their text source is
empty, but it is done by rn2() rather than rn2_for_display_rng() so
is just a warning for pre-release code. It would crash for release
version though.
I tried placing an empty engravings file and expected similar results
but didn't see any response. Not sure what that means.
After the fix, empty epitaph file yields blank result so graves that
want a random epitaph won't have any epitaph.
Fixes#302
When a special level is created, there's a chance it gets flipped
horizontally and/or vertically.
Add new level flags "noflip", "noflipx", and "noflipy" to prevent
flipping the level. Add a wiz-mode command #wizlevelflip to test
the flipping on current level - although this doesn't flip everything,
as level flipping is meant to happen during level creation.
Allow #tip to do something if you pick your worn helmet instead of
a container. It's mostly just a variation of #chat but probably adds
several new bugs....
Several conditions result in stale data on the status line when
starting or stopping because things which didn't used to affect it
haven't been setting context.botl to force an update. This wasn't
systematic; there are bound to be lots more.
The saying /corvus oculum corvi non eruit/ (Latin) means "a crow
doesn't pluck out the eye of another crow" (roughly). Something
along the lines of "like-minded people stick together". Honor the
literal meaning by preventing a raven's blinding attack that gets
directed at another raven from being able to cause blindness.
Fixes#293
Update sys/unix/Makefile.doc to be able to build Guidebook.dat, an
unpaginated copy of the plain text Guidebook. It's generated from
the 'roff source rather than by attempting to post-process the
regular text Guidebook.
No doubt there are easier ways to do this.
Mon rummages in <container> and Mon takes <item> from <container>
was missing an() for the container itself and should have been
using doname() rather than xname() for any items taken out (when
done adjacent to hero).
The "you have a sad feeling for a moment" message was only given when
one monster kills another (and the latter is an unseen pet). Give it
for drowning too. There are probably a bunch of other circumstances
which warrant it as well but I've settled for handling minliquid().
Side note: Here's a correction for the commit
message for 330287da42:
The original incorrectly stated 'CONDITION_SIZE' (which
doesn't exist) instead of CONDITION_COUNT in one of the
paragraphs.
--- snip ---
eliminate the uses of the manually maintained BL_MASK_BITS
Use CONDITION_COUNT which does not require manual updating.
Also attempts to adjust win32 graphics window port for
the new fields.
That port has its own field names and should be adjusted
to using the following which are declared extern in
include/botl.h.
struct conditions[CONDITION_COUNT];
int cond_idx[CONDITION_COUNT];
The former contains the fields that were port-specifically
added to the win32 graphical port and more, plus it is
centrally maintained and currently utilized by tty and curses.
The cond_idx[] array contains the ranked ordering of the
condition fields from highest ranking to lowest. Instead
of indexing like this:
int i;
for (i = 0; i < CONDITION_COUNT; ++i) {
...conditons[i].enabled;
...condtions[i].text[0];
}
you can use the ranked ordering like this:
int i, ci;
for (i = 0; i < CONDITION_COUNT; ++i) {
ci = cond_idx[i];
...conditons[ci].enabled;
...condtions[ci].text[0];
}
Level teleporting to current level doesn't give any feedback but
is usually done intentionally to abort the level teleport. Being
on the bottom level of branch and attempting to teleport even lower
failed silently like choosing the current level. Have it give some
feedback about not being able to go any lower.
It was possible to create a pit on top of iron bars, by first creating
a pit next to the bars, going down into the pit, and then digging sideways
towards the bars. This did not destroy the iron bars.
The #wizgenesis command can also accept a quantity in the input prompt,
previously it only accepted a command repeat prefix.
(via UnNetHack, originally from NetHack4)
After casting a spell, a monster got a chance to make a regular attack
despite the apparent attempt to set up a return value indicating that
it wouldn't move.
When looking over the return value situation, I noticed 'wormhitu()'
for the first time. It gives worms additional attacks when the hero
is adjacent to some of the tail, that only works if the head is within
reach of a melee attack. The hidden tail segment at head's location
always met that criterium so gave an extra attack that didn't make
sense; change wormhitu() to skip that segment.
Do some formatting in mcastu.c; no change in actual code there.
Fixes#285
While testing the changes to dungeon and special level handling, I got
|A mysterious force prevents you from descending!
|You materialize on a different level!
The mystery force is handled by goto_level() so level_tele() doesn't
know that the failure is going to happen when it sets up the message
for deferred delivery. Suppress the message if you don't change levels.
Stairs up from Orcish Town variation of Mine Town were being forced
to be near the bottom of the left side of the level due to a bogus
exclusion region in the level description. If that small area was all
solid rock then a warning was issued and no stairs up were created.
Applying royal jelly listed all of inventory as likely candidates for
what to rub it on, including itself.
Applying it to anything took no time.
After the "you smear royal jelly on <foo>" message,
unsuccessfully applying it to non-eggs gave no other feedback;
successfully applying it to eggs gave no additional feedback.
Allow #rub to use royal jelly too.
Also, require hands to apply or #rub anything.
Not done: fumbling and/or slippery fingers should have a chance to
drop the jelly or to drop whatever gets rubbed with it.
Royal jelly applied on an egg will change a killer bee egg to
a queen bee egg. Cursed jelly will kill the egg, uncursed and blessed
will revive it. Blessed jelly will also make the creature think
you're the parent.
Original patch was by Kenneth Call
Hero shouldn't be able to zap wands when polymorphed into a form which
lacks hands.
The other tweaks to dozap() shouldn't produce any change in behavior.
If level teleport took you somewhere special, things like shop entry
or quest summons or valley atmosphere messages were being given first,
then "you materialize on a different level" after. schedule_goto()
takes before-change-message and after-change-message arguments; it
ought to be extended to have a mid-change-message one too but I didn't
think of that until just now.
Like lava when that looks the same as water with color Off, render ice
in inverse video if it looks the same as the floor of a room. (I tried
bold first but the result didn't look very good.)
Done for tty and curses; others may want to follow suit.
There was a complaint that despite charisma of 13 being above average,
the character was described as "ugly". The cut-off was actually >14
for "beautiful" or "handsome" vs <=14 for "ugly". This adds several
more grades of appearance.
Make long worms grow more slowly (although that didn't seem to make
as much a difference as expected) and limit the amount of HP they
acculate if they shrink and then re-expand. Shrinking doesn't take
away max HP but growing used to always add to max. Now it won't add
to max HP unless the number of segments is at that worm's peak, so
shrinking will inhibit the exhorbitant HP expansion that idle worms
have had.
When disclosing conduct at end of game (but not during except in
wizard mode), display achievements too. They're also included in
dumplog if it's enabled. Previously they were only output as an
extra field in xlogfile.
This turned out to be a lot more work than I anticipated, but it is
definitely simpler (other than having #wizmakemap take achievements
away if you replace the level that contains the 'prize', which wasn't
handled before).
I cheated and made Mine's End into a no-bones level because the new
flagging scheme for luckstone, bag, and amulet can't carry over from
one game to another. It probably should have been no-bones all along.
Sokoban didn't have this issue because it's already no-bones.
Existing save files are invalidated.