Make all stackable weapons capable of multi-shot volleys when thrown.
Affects knives, spears & javelins, and boomerangs; requires advanced skill
assignment (skilled: 1-2 missiles per throw, expert: 1-3 missiles) or
role-specific bonus (ranger class's general +1 bonus is the only one that
applies to any of these weapon types). For monsters, prince-caste get 1-3
missiles and lord-caste get 1-2, as before, with fake player monsters now
also getting 1-2; those counts apply to all stackable weapons regardless
of whether the species or role ordinarily uses whatever is being thrown.
Related changes: monks now get a role-based +1 count for shuriken,
throwing 1-2 instead of just one (they're only allowed to achieve basic
skill so won't reach any higher volley count). Monster monks and ninjas
get that too; ninjas now get the same for darts and they're guaranteed
weapons in starting inventory. Also, fake player rogues now sometimes
get orcish daggers instead of short sword, providing a decent chance to
occasionally have Grimtooth be randomly generated on the Astral level.
Potentially controversial: wizards can still become expert in dagger
skill and receive the to-hit and damage bonuses for that when throwing as
well as when wielding, but the number of missiles for them has now been
reduced to 1-2 (in other words, going from skilled to expert no longer
improves the max count for the volley amount for wizard role). They're
supposed to be spellcasters; being able to throw up to three +7 daggers
at a pop was a big temptation for resorting to brute force, particularly
since they'll already want highest dagger skill for wielding Magicbane.
To do: throwing multiple boomerangs either needs to behave as if
they're all in flight before the first returns, or else the volley needs
to be cut short if one comes back and isn't successfully caught. The
latter is a lot easier to do but the former fits better with what multi-
shot volley is supposed to represent. Another alternative is to change
them to no longer be stackable, then this sequencing issue goes away.
To do too: make worm teeth and crysknives become stackable like the
other knife-skill weapons.
Using #tip (post-3.4.3 code) on a container that's on a shop floor
didn't handle ownership correctly. Bag of tricks could be emptied for
free, and contents of other containers were being sold to the shop even
when the shop already owned them. This fixes bag of tricks and makes a
first cut at doing so for regular containers.
Message handling when #tipping any bag of tricks was also suboptimal
since the decision about message delivery was made again as each charge
released something instead of waiting until the whole bag was emptied.
So you could get inappropriate "nothing seems to happen" before or after
a monster visibily popped up if something unseen was also produced.
Fido grows up into a large dog.
The soldier becomes a sargeant.
Similar feedback was previously given only when the monster was going to be
killed off due to its new form having been genocided.
This is an overhaul to the NetHack drawing mechanism.
- eliminates the need to have separate lists in drawing.c
for the things and their associated explanations by grouping
those thing together on the same inializer in a struct.
- replaces all of these options: IBMgraphics, DECgraphics, MACgraphics,
graphics, monsters, objects, boulder, traps, effects
- drawing.c contains only the set of NetHack standard symbols for
the main game and a set of NetHack standard symbols for the
roguelevel.
- introduces a symbols file that contains named sets of
symbols that can be loaded at run time making it extensible
for situations like multinational code pages like those reported
by <Someone>, without hardcoding additional sets into the game code.
- symbols file uses names for the symbols, so offsets will not break
when new things are introduced into the game, the way the older
config file uchar load routines did.
- symbols file only contains exceptions to the standard NetHack
set, not entire sets so they are much less verbose than all of
the g_FILLER() entries that were previously in drawing.c
- 'symset' and 'roguesymset' config file options for
preselecting a symbol set from the file called 'symbols'
at startup time. The name of the symbols file is not under the
users control, only the symbol set name desired from within the
symbols file is.
- 'symset' config file option loads a desired symbol set for
everything but the rogue level.
- 'roguesymset' config file option loads a desired symbol set
for the rogue level.
- 'SYMBOLS' config file option allows the user to specify replacement
symbols on a per symbol basis. You can specify as many or as few symbols
as you wish. The symbols are identified by a name:value pair, and line
continuation is supported. Multiple symbol assignments can be made on
the same line if each name:value pair is separated by a comma.
For example:
SYMBOLS = S_bars:\xf0, S_tree: \xf1, S_room:\xfa \
S_fountain:\xf4 \
S_boulder:0
- 'symbols' file has the following structure:
start: DECgraphics
Handling: DEC
S_vwall: \xf8 # meta-x, vertical rule
S_hwall: \xf1 # meta-q, horizontal rule
finish
start: IBMgraphics
Handling: IBM
S_vwall: \xb3 # meta-3, vertical rule
S_hwall: \xc4 # meta-D, horizontal rule
finish
- 'symbols' file added to the source tree in the dat directory
- Port Makefiles/scripts will need to be adjusted to move them into
HACKDIR destination
Give demon lords and other monsters who teleport to your location a
oneshot arrival message. Brought about by the report of the late "<demon>
appears" message delivered during its bribery demand, after the character
had already been able to see it for long enough to extract gold from a bag.
Now, if you can't see or sense a monster before it teleports to you, and
you can see or sense it after, you'll get "<monster> suddenly appears!".
The message will be given at most once for any given monster, and it won't
be shown at all if you already see/sense the monster before it teleports or
still don't see/sense it afterwards. The fixes entry is deliberately a bit
vague (and I put it in the new feature section rather than the fix section).
The change from long to unsigned long for monst.mstrategy may bring
some lint complaints along with it. The various constants (STRAT_xxx) used
to populate it are still signed. I didn't increment EDITLEVEL for this;
existing data should still work ok.
[the problem in the earlier rev was tracked to cleanup_burn(),
where arg was holding a (genericptr_t) timer id, and
passed directly to del_light_source() as is.]
P64 (Win64) has a 64 bit pointer size, but a 32 bit long size.
Remove some code that forced pointers into a long int, and
vice versa where information could be lost.
This part deals with light source functions and their
arguments mostly, and switches some arguments
from type genericptr_t to 'anything'.
P64 (Win64) has a 64 bit pointer size, but a 32 bit long size.
Remove some code that forced pointers into a long int, and
vice versa where information could be lost.
This part deals with light source functions and their
arguments mostly, and switches some arguments
from type genericptr_t to 'anything'.
<Someone> reported that he applied an unID'd bag and it became
discovered as a bag of tricks even though a spellbook appeared on the floor
next to him rather than having a monster show up (the monster was a mimic).
Suppress the bag discovery unless you can see or sense a monster appear.
(This doesn't really achieve much for most players, who'll recognize the
bag because they know that only one type of container doesn't prompt to
take things out and/or put things in, but I think it does make sense.)
While mucking with bag of tricks I decided that to be consistent with
the behavior of other containers, the #tip command should release all the
monsters in the bag instead of just one.
And after doing that, I realized that horn of plenty ought to behave
much the same, so #tip will operate on it now. However, it won't be listed
as a likely candidate in the "which item?" prompt unless/until it has been
discovered. (Attempting to empty any other type of horn yields "nothing
happens", same as for a horn of plenty with no charges left.) Emptying a
horn of plenty in a shop can be extremely verbose, but I don't think that
qualifies as a bug and don't currently have any plans to alter it.
move oattached and oname and other things that vary
the size of the obj structure into a separate
non-adjacent oextra structure, similar to what has
already been done for mextra. The obj structure
itself becomes a fixed size.
New macros:
#define ONAME(o) ((o)->oextra->oname)
#define OMID(o) ((o)->oextra->omid)
#define OMONST(o) ((o)->oextra->omonst)
#define OLONG(o) ((o)->oextra->olong)
#define OMAILCMD(o) ((o)->oextra->omailcmd)
#define has_oname(o) ((o)->oextra && ONAME(o))
#define has_omid(o) ((o)->oextra && OMID(o))
#define has_omonst(o) ((o)->oextra && OMONST(o))
#define has_olong(o) ((o)->oextra && OLONG(o))
#define has_omailcmd(o) ((o)->oextra && OMAILCMD(o))
changed macros:
has_name(mon) becomes has_mname(mon) to correspond.
The CVS repository was tagged with
NETHACK_PRE_OEXTRA
before commiting these, and
tagged with
NETHACK_POST_OEXTRA
immediately after. The diff
between those two tags is this oextra patch.
The associated mail daemon changes to use an oextra
structure instead of a hidden command located in the
name after the terminating NUL, have not been tried
or tested.
- restore intended behaviour of kill_genocided_monsters().
It has been incorrect since the chameleon overhaul in June 2004.
- eliminate CHAM_ORDINARY and use NON_PM instead.
Implement the following suggestion by <email deleted>
- Reading a scroll of light while confused should
create a hostile yellow light (black light if cursed).
It only creates the light monster effect 1 out of 5 times.
Cleanup up a couple of priest and minion allocation/conversion bits.
Also, restrict minion naming so that "guardian <foo>" is only applied when
<foo> is an Angel. (That restores old behavior from before a change I made
last October; it prevents the guardian Angel from being recognized while
hallucinating. It probably affects slash'em too, where they have tame
minions besides the astral level's guardian Angel.)
<Someone> noticed the leftover zeromextra, this removes it.
Using memset() on a possibly failed mextra allocation was inapprorpriate,
so replace the newmextra() macro with a function.
Prevent a crash in christen_monst() if mextra was not initialized.
Note: The CVS repository was tagged with NETHACK_PRE_MEXTRA
prior to application of this patch to allow easy withdrawal if necessary.
Adds a new mextra structure type that has a set
of pointers to various types of monster structures
including:
mname, egd, epri, eshk, emin, edog
Replaces the mextra bits in the monst structure
with a single pointer called mtmp->mextra of type
(struct mextra *).
The pointer can be null if there are no additional
structures attached. The mextra structure is not
adjacent to the monst structure.
Reduces the in-memory footprint of the monst that
has no other structures attached, at the cost
of adding 6 extra long ints per monster to
the save file
The new mextra structure has the mextra fields
independent of each other, not overlapping as was
the case with previous NetHack versions.
This patch doesn't do anything to capitalize on
that difference however.
Consolidates vault.h, epri.h, eshk.h, emin.h and edog.h
into mextra.h
Adds a macro for checking for whether a monster has
a name:
has_name(monst)
This fixes the magic trap panic
expels() -> spoteffects() -> dotrap() ->
domagictrap() -> tamedog()
because the monst no longer varies in size so no
replacement is required.
Angels used the epri extension even though they're never priests,
presumeably because they're sometimes flagged as "renegade". Since the
only priests ever flagged as renegade are roaming minions rather than
temple priests, move the renegade flag to the emin extension and switch
Angels over to that. Summoned Angels will now always have the isminion
flag set.
Makefiles need updating: monst.{c,o} now depends upon emin.h.
Noticed when incorporating the "vampire dancing" patch: losing a level
while polymorphed would subtract from your normal hit points but didn't
affect your monster hit points. Now they'll lose d8 from max and current,
similar to the amount they increase when gaining a level.
This also addresses an issue from the newsgroup a few weeks back:
someone mentioned an assumption that Stormbringer drained an amount other
than d8 for monsters who use some other formula for their hit points. It
wasn't true, but now it will be (approximately). Most monsters with unusual
hit points aren't subject to level drain, so it shouldn't have much impact.
I've gotten tired of seeing newsgroup claims along the lines of
"since devteam is aware of this and has chosen not to eliminate it, they
must endorse it", so weaken the tactic of "pudding farming". It is still
possible to gain unlimited experience (past level 15 or so there's not
much point), but will be less effective for gaining items and for providing
sacrifice fodder. Keep track of which monsters have been created via
cloning (mostly puddings; gremlins and blue jellies are affected too but
nobody's likely to care much about them) so that they can receive special
handling. Make cloned monsters progressively less likely to leave corpses
as the number killed for a particular type goes up, and also much less
likely to drop random items at death. This is sure to need some tuning
once hard core farmers point out how they can still abuse it. For the
absurdly extreme case, see
http://scavenger.homeip.net/farmbot/HomePage
FYI, farmbot/PuddingFarmingHOWTO includes an impressive screen shot of a
dungeon level where rampant farming is taking place.
<Someone> recently reported that after lieutenants had been genocided,
he saw a sergeant drink a potion of gain level and then vanish, leaving
behind its gear but no corpse. The message about growing into a lieutenant
and subsequently dropping dead would only be given if the monster could
be sensed via telepathy, not when it occurred in plain sight. I'm not
absolutely sure that this was unintentional, since sensing the dying
monster's mind might be giving additional information about what was
happening. But there was no comment stating that and I think such behavior
violates the principal of least surprise, so seeing it happen will now give
the message too.
- can shift into fog clouds, vampire bats, and vampire lords into wolves
- after being "killed" in shifted form, they transform back rather than get
destroyed, and you must take them on in vampire form to defeat them
- can deliberately shift into fog clouds to pass under closed doors
<Someone> wrote:
>It seems silly to have two flags being used for counting djinn and
>ghosts, now that there's mvitals.born...
This does not break save and bones compatibility in the 3.4.x branch,
it changes the code, but leaves the obsolete fields in flags.
On mazelike levels, mimics will mimic either boulders or statues (of giant
ants, as it turns out). However, it does not make sense to mimic a boulder
on a hole or even a pit, since boulders would typically fall in. Also,
statues are not typical objects in Sokoban. So, skip statue special case
in Sokoban and always avoid the forced emulation of a boulder when on a
trap location outside a room. This is a bit drastic, but I couldn't think of
an argument for adding the code to do this only for pits, holes, et al,
which are the most likely traps outside rooms anyway.
Try to fix the report of a doppelganger (created from using stone-
to-flesh on a fake statue of Demogorgon) having 1700 hit points after
reverting to its native form. The problem was due to the special monster
level of Demogorgon rather than anything to do with shape changers; the
actual bug was use of `mdat->mlevel' where it should have been using
`mtmp->data->mlevel'. But the whole section of code was rather suspect
since it didn't attempt to handle other types of monsters (dragons, golems,
elementals) which have non-standard hit points, so I knocked some out.
Monsters who have gained or lost levels prior to changing form will no
longer carry that adjustment along; the new form will always be a brand
new one of its type. However, if the old form is injured at the time of
change, the new form will be too (same as before).
Since the rogue level does not have closed doors, mimicking one there makes
no sense. Similar to what wand of locking does there, make mimics that end
up there mimic a wall instead of a door.
Try to address the problem From a bug report: turning the Wizard
of Yendor to stone preserves monster information with his statue and
presence of that information overrides the statue animation check
intended to prevent players from creating the Wizard (or other unique
monsters). That's ok for the current game--the monster had to have been
in play in order to be turned to stone--but is a problem if the statue
is found in a bones file. The report was for placing such a statue at
the location of an untriggered statue trap by a player who leaves bones,
but stone-to-flesh by the player who loads bones is a simpler way to
trigger this. (Aside from getting unique monsters earlier than usual
under some degree of player control they won't have their starting
inventory so special items like the Candelabrum might not get created.)
Using undead turning to revive corpses found in bones was another way to
get into the same trouble (I thought corpses of special monsters were
already excluded from bones?).
It looks like it's also possible to get strange quest behavior if
a corpse or statue of the leader or nemesis is brought into the dungeon,
left in bones, then revived by the second player, but I didn't attempt
to reproduce it. More work is probably needed; this tightens up leader
handling a bit but doesn't do anything about the nemesis. This patch
has already been spreading tentacles and I've got to cut it off....
The patch discards saved monster traits for corpses and statues of
unique monsters while saving bones; reviving or reanimating them will
produce doppelgangers instead of the original monsters, same as stone-to-
flesh on wished-for statues behaves. It also discards saved traits for
shopkeepers (also temple priests and vault guards--their traits weren't
saved in 3.4.2 though). That info might be useable when the corpse or
statue is on the same level as the monster started (ie, where its special
room is located), but that's a complication I'm going to bypass. This
patch also adds chameleon handling for statue activation--it wouldn't
have mattered in 3.4.2 since shapechangers didn't get their traits saved;
it does matter now but was omitted when trait-saving was extended to all
statues a while back. (It adds chameleon handling to corpse revival too,
but they still don't get their traits saved with corpses so that's just
protection in case of future modifications.)
Other bits: `cant_create()' is renamed to `cant_revive()' since
the latter is a more signicant use than wizard mode <ctrl/G> handling.
Now save traits with nymph corses so that cancellation can be propagated
if they're revived; that doesn't matter much but matches statue handling
(where it was more important since it dealt with succubi as well as with
nymphs). Explicitly initialize the shape-changer field of all monsters
instead of relying on implicit initialization to 0 (CHAM_ORDINARY).
There'll be a *much* shorter patch for 3.4.3 which will have to get
by with most of these obscure problems--fortunately they're unlikely to
impact many (any?) players.
Cutting a shopkeeper poly'd as a long worm would generate strange messages
and could result in a crash. cutworm didn't deal with all the intricacies
of duplicating a monster. Fixed by changing cutworm() to use clone_mon()
to do most of its dirty work. It seems to me that without this change,
cutting a tame long worm could also have similar bad effects.
Other side effects of this change:
- clone_mon now takes x,y coordinates, 0,0 results in previous behavior
- clone_mon no longer always makes cloned monsters tame/peaceful if player
caused the clone, using the same formula previously in cutworm. Someone
else may wish to tweak this for gremlins.
- clone_mon will christen the new mon with the old shopkeeper's name, even
though clones are never shopkeepers (game can't handle 2 for a shop)
- cutworm can now be called during conflict or pet combat, although I
added no such calls (yet)
When changing levels, the state of rndmonst() is reset, causing the monster
choices to be recalculated. However, the frequency counts for initial
uncommon() monsters were never cleared. Thus, if the first non-extinct
monster were a hell monster, and you returned to the main dungeon, the hell
monster will remain in the list and could be selected.
Reported a while back, a (stonable) hiding monster will hide at a location
containing only a cockatrice corpse. While it would be interesting to
allow monsters to try, and stone themselves as a result, I chose the
simpler fix which is to not have monsters hide in such situations. I found
the hiding code was duplicated in several places, so I moved it into a new
hideunder() function that works for both the hero and monsters.
Pat Rankin wrote:
> collect them all into some new struct and
> save that separately rather than jamming more non-option stuff
> into struct flags.
This patch:
- collects all context/tracking related fields from flags
into a new structure called "context."
It also adds the following to the new structure:
- stethoscope turn support
- victual support
- tin support
Bones loading was only checking to see if a
monster was marked extinct, it wasn't adding
up the born count of a species in the current
game with the number of that species on the
bones level being loaded. That made it possible
to exceed the correct number of nazgul and
erinys via bones.
This adds a common routine called propagate()
that makemon() and restmonchn(ghostly) share,
for incrementing the born count and checking for
extinction, etc.
When a bones level is loaded, restmonchn()
will flag an illegal monster (duplicated unique,
or too many of a species) by setting the
individual monster's mhpmax to the cookie
value DEFUNCT_MONSTER. Before getbones() finishes
loading the bones level, it will purge those
monsters from the chain.
Move a couple of instances of container contents manipulation into
their own routines. Behavior for items disappearing from cursed bags of
holding isn't quite identical but is effectively the same. I think its
use of stolen_value (or simply the behavior of the latter) is buggy, but
I haven't tried to fix that. (Cursed bag of holding destroying a player
owned bag containing shopped owned items definitely doesn't work well.)
<Someone> reported that couatl and ki-rin could wear boots and gloves.
Two problems: 1. all minions were created with a sword and armor, even those
that couldn't use them. 2. couatl and ki-rin were missing some important
bits in their M1 flags.
Now neither couatl or ki-rin are created with armor, and they won't try
to wear any armor they cross in the dungeon.
>More worrying is the fact that applying a figurine over water lets
>the monster wait until its next move before it drowns (giving
>you time to teleport it to safety, or whatever) [...]
>Should there be a minliquid() check as part of make_familiar()?
Applying at the water location next to you was easy. But
applying it at your own location (triggering BY_YOU) could
end up placing the figurine at the far side of the level if
there was lots of water.
Correcting that required the ability to pass a flag from
make_familiar to makemon() telling it to not rule out
water locations as good positions. The flag had to
be passed on down to goodpos() and enexto().
The bulk of this patch is just adding an additional
argument to goodpos() in all of the callers.
m_initweap() was trying to give him wands of fire and cold; since
he had no weapon attacks, he wasn't is_armed(), so this code never
got called.
This moves the code to m_initinv().
When Angels were introduced, they were always lawful. Somewhere along the
line, non-lawful angels were added, but is_lminion and uses of it was never
updated to address this change. Among other things, this resulted in
non-lawful angels delivering messages via #chat that are only appropriate
for lawful angels. That is addressed simply by changing the definition of
is_lminion, which must take a struct monst, not a permonst, to return valid
results. Also, non-lawful angels should summon appropriate monsters, not
lawful minions.
Add a param to newcham() to let it print "The oldmon turns into a newmon!"
rather than always printing this externally. Should ensure a good ordering
of the messages. Also put some special name handling in one place and
catch a couple cases where "saddled" was printed, resulting in funny messages.