Adds two monsters originally from slash'em. I used the slash'em
tiles this time, also its code as a starting point but made various
revisions. Both the tiles could benefit from some touch-ups.
displacer beast: blue 'f'. Attempting a melee hit (ie, trying to
move to its spot) has a 50:50 chance for it to swap places with you.
Fairly tough monster to begin with, then half your ordinary attacks
effectively miss and if you try to face a mob by retreating to a
corridor or backing into a corner you can end up being drawn back
into the open. I added bargethrough capability, and also it won't
be fooled about hero's location by Displacement. [It only swaps
places during combat when contact is initiated by the hero, not
when attacked by another monster or when attacking.]
genetic engineer: green 'Q'. Its attack causes the target to be
polymorphed unless that target resists. Hero will almost always
have magic resistance by the time this monster is encountered, but
it can make conflict become risky by hitting and polymorphing other
monsters. Slash'em flagged it hell-only but I took that flag off;
I also took away its ability to teleport. Slash'em polymorphs the
hero if a genetic engineer corpse is eaten; that's included and I
introduced that for monsters too.
I added both of these to the list of candidates for monster spell
'summon nasties' and for post-Wizard harassment.
I also gave all the 'f's infravision. Probably only matters if the
hero polymorphs into a feline.
Displacer beast is originally from AD&D which depicts it as a six-
legged cougar with a pair of tentacles; it has Displacement rather
be able to affect an attacker's location. I think genetic engineer
is original to slash'em where it expands Q class but seems mainly to
be the base monster for Dr.Frankenstein (a unique monster with a
one-level side-branch lair in slash'em's incarnation of Gehennom).
We haven't added any new objects or monsters in a really long time.
This adds two new useful amulets, putting more pressure on the
decision over which type of amulet to wear.
amulet of flying: idea from slash'em, implemented from scratch.
Should be self-explanatory. Polymorphing into a form capable of
eating amulets and then eating one does not confer intrinsic
flight. (I've no idea how slash'em behaves is in that regard.)
amulet of guarding: adds +2 AC, which is fairly negligible, also
+2 MC, which is not. Initially called amulet of protection but MC
of 2 is referred to as 'guarded' by enlightenment so I changed it.
(By that reasoning, rings of protection ought to be called rings of
warding; oh, well.) Successfully eating one confers +2 AC without
any MC benefit. When wearing one of these, rings of protection
only confer AC, their +1 MC gets superseded rather than combined.
Monsters will wear an amulet of guarding and gain both the AC and
MC benefit, but if not cursed and they acquire one of life-saving or
reflection, they'll swap. They won't wear an amulet of flying.
I cloned two extra copies of the tile for one of the existing amulets
and ran sys/share/objects.txt through renumtiles.pl. The result
appears to be ok but on X11 the tiles map ends up looking psychedelic
so something beyond the tile art itself needs to be fixed here.
This matches the nurses' hitting behavior with their chatting messages.
Chatting to them suggested that the heal attack would happen but the check in
mhitu.c was just for wielding anything.
This opens up the possibility of a YAFM in MS_NURSE when wielding something
that allos the heal attack to proceed. But I couldn't come up with a good
one.
Move demon summoning and were creature summoning out of mattacku()
to a separate routine. Should be no change in behavior.
Also, redo several comments that came after what they applied to
rather than before, and reorder the file-scope prototypes to be in
the same order as the corresponding functions.
Instead of forgetting maps and objects, make amnesia forget skills.
Forgetting maps and objects could be circumvented with taking notes,
or by using an external tool to remember the forgotten levels.
Forgetting skills allows the player to optionally go down another
skill path, if they trained the wrong weapon in the early game.
Amnesia still forgets spells.
As a replacement for the deja vu messages when entering a forgotten
level, those messages will now indicate a ghost with your own name
existing on the level, given only when the level is entered for
the first time.
These changes based on fiqhack, with some adjustments.
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.
Setting or clearing u.ustuck now requires that context.botl be set,
so make a new routine to take care of both instead of manipulating
that pointer directly.
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.
teleds() is used for more than just teleportations, the teleportation message
was also given when mounting a steed.
Trying out a new bit flags method parameter design pattern.
When GOLDOBJ was activated unconditionally, several texts started referencing
"money" instead of "gold".
As we don't have the intention to introduce a complex coin system with
different denominations, change it back and also some other places that
reference "money".
Fixes#240
Monster versus monster (melee and throwing) didn't handle shades
(need silver or blessed weapon to take damage) or silver feedback
(extra info when silver-haters are hit).
I did a lot of test, revise, re-test but didn't always re-test
everything that had previously been tested, so bugs that I thought
were quashed might have crept in.
Now if a missile weapon "passes harmlessly through the shade" it
will continue on and maybe hit something else. (Regular misses
still stop at the missed target.)
A couple of minor ball&chain changes accidentally got included.
Fixes#204
3.6.2's attempts to fix turning off SEDUCE in 'sysconf' introduced
an unintentional change in behavior for hero poly'd into nymph form:
theft attack always angered the target. The actual change was
intentional but its ramifications were unexpected.
Fixes#188
The change to fix setting SEDUCE=0 in sysconf broke chatting with
seductive demons by unintentionally changing the way Null attack
argument was handled. It's still handled differently than it used
to be, but I think this difference is correct.
Preserve temporary fake object's previous dknown value by storing it
as a flag value within the m_ap_type field of the posing monster, and
recalling it when it is needed.
This is intended to help eliminate observable differences in price display
between real objects and mimics posing as objects.
98% of this is just switching the code to utilize macro M_AP_TYPE(mon)
everywhere to ensure that the flag bits are stripped off when needed.
Noticed while trying to find the reason for the wildmiss impossible(),
you could be teleported and then drop dead at the destination. A QM's
AD_TLPT hit also does 1d4 physical damage which gets applied after the
teleport. Getting "You die." seemed pretty strange, particularly after
picking the destination with telport control. This makes sure that the
damage will never be fatal when teleport is attempted.
When SEDUCE is disabled, instead of swapping attacks in mons[] once,
do it on the fly in getmattk() whenever needed. That allows mons[]
to become readonly, although this doesn't declare it 'const' because
doing so will require a zillion 'struct permonst *' updates to match.
This seemed trickier than it should be, but that turned out to be
because the old behavior was broken. Setting SEDUCE=0 in sysconf or
user's own configuration file resulted in all succubus and incubus
attacks being described as monster smiles engagingly or seductively
rather than hitting (while dishing out physical damage). I didn't
try rebuilding 3.4.3 to see whether this was already broken before
being migrated to SYSCF.
Static analysis notices that
if (physical_damage)
tmp = Maybe_Half_Phys(tmp);
will never pass the test because all code paths leading to it set
'physical_damage' to False. Instead of getting rid of it, add a fake
case that leaves that True.
Life-saving was setting u.uswldtim to 0, presumably intending that
to stop the hero from being digested, but it actually resulted in
being totally digested on the swallower's next turn if the death
being short-circuited wasn't digestion. Change life-saving to make
swallower or grabber release the hero instead of tinkering with
u.uswldtim. In addition to rescuing the hero from digestion, it
prevents an eel which has just drowned the hero (who has survived
drowning via life-saving) from pulling him/her back into the water
on its next turn. It will need to make another successful grab to
do that now.
While testing, I noticed that if I was polymorphed and wearing an
amulet of unchanging, life-saving didn't restore my HP-as-a-monster
and due to the recent change to force that to 0 when the hero dies,
I died again immediately after my life was saved. So this bug was
latent in the past and became noticeable in the last couple of days.
Make being trapped in/on/over floor block Levitation and Flying, the
way that being inside solid rock already does, and the way levitating
blocks flight.
Blocked levitation still provides enhanced carrying capacity since
magic is attempting to make the hero's body be bouyant. I think that
that is appropriate but am not completely convinced.
One thing that almost certainly needs fixing is digging a hole when
trapped in the floor or tethered to a buried iron ball, where the
first part of digactualhole() releases the hero from being trapped.
If being released re-enables blocked levitation, the further stages
of digging might not make sense in some circumstances.
I recently realized that being held by a grabbing monster is similar
to being trapped so should also interfere with levitation and flying.
Nothing here attempts to address that.
Save files change, but in a compatible fashion unless trapped at the
time of saving. If someone saves while trapped prior to this patch,
then applies it and restores, the game will behave as if the patch
wasn't in place--until escape from trap is achieved. (Not verified.)
Most shop messages accurately identify the shopkeeper even when he
or she can't be seen, but some also include a pronoun reference that
ended up as "it" or "its" when not seen. Extend pronoun selection
so that visibility can be ignored: noit_mhe(mon), noit_mhim(mon),
and noit_mhis(mon). Note that despite being called noit_foo(),
those will still return "it" if mon is neuter.
"Accurately identify shopkeeper" is misleading if the hero is
hallucinating; a random shopkeeper name is used then. noit_foo()
yields the pronoun applicable to the actual shopkeeper and might
not match the gender of a hallucinatory name. That could be fixed
in a couple of ways (add shk_mhe()/shk_mhim()/shk_mhis() and either
pass them the randomly chosen name so that they can figure out the
appropriate gender, or just have them use a random gender whenever
hallucinating) but I don't think that's worth bothering with.
A bunch of shop messages needed noit_foo(); only a couple of those
have actually been tested. A bunch more were using shkname() at
the beginning of a sentence where Shknam() should be used instead.
(All the existing shk names are already capitalized so there's no
noticeable difference.)
The three places outside shk.c and vault.c which directly use
pronoun_gender() have been successfully tested.
Interrupt seduction if the hero gets moved away from the seducer, or
if both of them move to another level. Loss of levitation can drop
the hero onto a trap which sends him/her somewhere else, but seduction
was continuing as if nothing had happened. In theory it could continue
despite level change because succubus and incubus are level followers,
but there's no way of knowing whether seducer and victim will arrive
next to each other until they get delivered and that doesn't happen
until long after the attack needs to finish.
I don't think theft has the same problem because it is a multi-turn
activity operating on one item at a time, but I didn't check it out.
Various seduction messages with a verbal component were being given
to hero even when deaf. This uses alternate messages if some cases
and bypasses the message in others. In particular, if hero is deaf
then he or she will not be given the choice to decline removing a
piece of armor--or taking off or putting on a ring of adornment--
that can ordinarily occur (based on die roll against Charisma).
The seduction code was also using '!Blind' to test whether the hero
could see his/her seducer, ignoring the possibility that it might be
invisible. I think the only ramification is that "It" would appear
in messages instead of the "She" or "He" that are explicitly used
when not seen due to blindness.
If an mplayer Valkyrie on the Astral Plane is given a war hammer,
give her gauntlets of power instead of random gloves since that will
either be Mjollnir or a very wimpy endgame weapon. (Maybe someday
mplayer Valkyrie's will be able to throw Mjollnir; their chance of
having it on the Astral Plane is moderately high if it hasn't already
been created prior to arriving there.)
I also gave monsters wearing gauntlets of power a 3..6 damage bonus
for hand-to-hand. While making that change, I noticed that monsters
wielding a scalpel or tsurugi wouldn't split puddings, unlike the
hero (a post-3.6.0 change), so fix that.
When a monster killed a paper golem with a fire attack, the player was
told that the golem "burns completely" yet it might still leave some
blank scrolls as 'corpse'. The fix for that was one-line, but several
other death-by-fire situations which didn't report "burns completely"
were also leaving scrolls: fireball spell or scroll of fire or other
fire explosions (if any), also wand of fire. Fire trap and poly'd
hero with fire attack were already suppressing 'corpse'.
Self-genocide (own role or race) while polymorphed sets u.uhp to -1
so that you'll be killed during rehumanization. I found a couple
of places which were testing (u.uhp < 1) without checking polymorph
state, and one of those was where monster movement decides whether or
not to attack. This bug seems to have been present since start of
the second cvs repository, so has been around for quite a long time
without anybody letting on that they'd noticed. So it probably isn't
a very effective exploit, although it would certainly make ascending
without wearing armor become much more feasible.
There are bound to be other places which examine u.uhp directly
instead of '(Upolyd ? u.mh : u.uhp)' but I only checked m*.c.