Give more information when magic whistle is already discovered and
applying it affects multiple pets, without much increase in verbosity.
For each of the three categories
1) was already in view and moves to another spot still in view,
2) was out of view and arrives at a spot within view,
3) was in view but gets sent to a spot out of view,
show the pet by name (which might be "your <monst>" if it hasn't been
named) when there is just one, or "two creatures", "three...", "four...",
"several...", or "many..." when there are more than one. The first
category with more than 1 says "creatures". When there are additional
categories with more than 1, their part of the message says "others" if
prior part(s) already mention "creatures", or it says "other creatures"
if the prior part(s) only list pets by name.
For example
|Three creatures appear.
|Fido shifts location and Fang appears.
|Your pony shifts location and two other creatures appear.
|Many creatures shift locations, several others appear, and two others
disappear.
|Two creatures appear and two others disappear.
Restore old behavior of magic whistle causing pets to be moved to
different locations even when already adjacent to the hero.
This lets rloc() give its relatively new, more verbose messages if
a magic whistle isn't discovered yet but suppresses those when
already discovered in order to issue its own message. For a single
pet that starts within view and arrives elsewhere within view it says
"shifts location" rather than "vanishes and reappears". For multiple
pets, it gives one summary message instead of a separate one for each
pet affected by whistling.
Add some basic functions to iterate through the monster list,
ignoring dead monsters. Mainly just to allow splitting up code
into discrete functions.
Not quite happy with the get_iter_mons_xy - should probably have
a pointer to iterator data struct, which gets passed through instead,
but this works for now.
If poly_when_stoned() is true, an uninitialized buffer kbuf[] is passed to instapetrify().
Although instapetrify() doesn't access it in that situation for now,
it should be initialized anyway for readability.
When applying some tools (whips, polearms, grapples), or rubbing
a lamp, or when fireassist is on and you fire something without
wielded launcher, the automatic wielding should take as much time
as wielding the item normally does.
Fixes#696
Remove the conduct-specific aspect of receiving spells as prayer boon.
Anyone now has a 25% chance of having the spell directly implanted
into their head, not just characters who have maintained illiterate
conduct. It can now also restore a forgotten spell or refresh one
that is nearly forgotten. It still tries to choose a spell which
isn't already known (new: or was known but has been forgotten) but if
it picks one that is known and doesn't need refreshing, a redundant
book will be given, same as the behavior in earlier versions.
The chance for receiving a blank spellbook is higher when that item
is undiscovered. When given as a prayer reward, make it become
discovered even if hero doesn't read it so that it will be less likely
to be given again. There's a 1% chance for that auto-discovery to
happen with other bestowed books. Unlike blank boots, having the book
be discovered doesn't lessen their chance of being repeat gifts.
Minor bug fix: for a spell implanted from scratch, the book remains
unknown. That's ok; it's actually more interesting than discovering
a book you haven't seen yet. But after acquiring and reading the book
you could get "you know <spell> quite well already" and the book would
stay undiscovered even though you were just told what spell it's for.
If you want to declare a pointer which the address pointed to is constant,
you should declare it as like `static const char *const var = "...";`.
This commit supplies missing `const` and prevents some programming
error in the future.
moveloop() has been calling restore_attrib() every turn, and
restore_attrib() loops through all six characteristics every time
to check for ones that have temporary adjustments timing out. But
ATIME(characteristic) is never set anywhere and no time outs would
occur. So delete the call to restore_attrib() from moveloop().
This leaves that no-longer-called routine in place and updates it
to handle Wounded_legs properly in case it ever does get used.
Also, add a comment about "restore ability" not fixing temporarily
lost characteristics due to hunger or wounded legs. And update
unfixable_trouble_count() to check for those so that restore ability
won't say "you feel great" when it fails to fix them.
Instead of returning ECMD_OK, the commands now return ECMD_CANCEL
when user declined to pick a direction or an object to act on.
Note that this can be ORed with ECMD_TIME, if the command still
took a turn.
For now this has no gameplay meaning.
Always give a message when creating a detected monster
during gameplay (as opposed to during level creation).
To prevent the message, use the MM_NOMSG flag for makemon.
Most places already handled their own messaging, but there
were some, such as bag of tricks, create monster magic
and random monsters created during gameplay that didn't.
Instead of returning 0 or 1, we'll now use ECMD_OK or ECMD_TURN.
These have the same meaning as the hardcoded numbers; ECMD_TURN
means the command uses a turn.
In future, could add eg. a flag denoting "user cancelled command"
or "command failed", and should clear eg. the cmdq.
Mostly this was simply replacing return values with the defines
in the extended commands, so hopefully I didn't break anything.
Wield a polearm and use 'f'ire to automatically hit with it,
if there's a single valid target.
With fireassist-option, will swapweapon to a polearm.
This only applies if quiver is empty and autoquiver is off.
'moves' is actually turns and there hasn't been any straightforward
way to track actual hero moves. Add hero_seq for that. It isn't a
counter but is distinct each time the hero makes a move. I wanted
it for curses ^P support but so far use it for checking stethoscope
usage and for shopkeeper behavior when items in a shop are broken by
the hero.
Increment EDITLEVEL due to change in save file contents.
Replace some
(foo &&
bar)
that had crept back into the code with
(foo
&& bar)
to match the reformatting which took place before 3.6.0. There are a
couple of lines ending in '||' still present but they look intentional.
isaac64.c has some trailing '|' bit operators that could/should be
moved to the start of the next line but I didn't touch that file.
While in the affected files, I tried to shorten most overly wide lines
(the right margin is supposed to at column 78 and there are quite a
few lines which are 79 characters long, but I left most of those
rather than introduce new line splits). Also replace a handful of
tabs with spaces. I was a little surprised not find any trailing
spaces (in the dozen or so files being updated). I didn't look for
trailing arithmetic or '?'/':' operators which aught to be moved to
the start of the next line.
Teleporting a monster only updated the map. Give a message
so blind players can get the same information.
Making a monster invisible gives the same message, if you
cannot detect invisible.
Several other places where monsters teleported themselves
now also give the same message.
Reported by entrez: applying a bullwhip towards a medium or small
peaceful monster used to be an attack but that stopped working when
'safepet' was extended to peacefuls in order for the hero to be able
to swap places which those. Also, side-effects were different when
hero applied the whip from within a pit compared to when not in one.
This allows the hero trapped in a pit to try to snag furniture or a
boulder even when a small or medium is present, and escaping that
pit if successful. (It still snags big monsters in preference to
furniture/boulder at their location.) When no such non-monster
target is available, it attacks the monster if hostile or peaceful
but not when tame. When revealing a previously unseen monster it
prevents snagging that monster's wielded weapon because hero couldn't
possibly target the weapon in that situation.
This makes other changes, mostly dealing with finding and exposing
concealed monsters, which may introduce some new bugs.
Since I was already in the right place, implement snagging an item
off the floor while flying. It isn't necessary since a flyer can
pick things up off the floor directly, but there isn't any pressing
reason to disallow it. Supersedes the commit in pull request #632
by RojjaCebolla.
Closes#632
Reported by G7Nation; attacking walls and such with a polearm just
gave lackluster "you miss; nobody's there" feedback.
Make applying a polearm at some non-monster locations give feedback
similar to using 'F'orcefight with melee weapons. Was
|You miss; there is no one there to hit.
now
|You uselessly attack the closed door.
Also, extend the supported locations to include dungeon furniture.
Was
|You attack thin air. ('F')
now
|You harmlessly attack the throne. ('F')
|You uselessly attack the throne. ('a')
This doesn't address #613: attempting to hit non-visible locations
with an applied polearm.
Closes#614
It's redundant with g.moves, so there is no more need for it.
Way, way back, it looks like g.moves and g.monstermoves can and did
desync, where g.moves would track the amount of moves the player had
gotten (and would therefore increase faster if the player were hasted)
and g.monstermoves would track the amount of monster move cycles, aka
turns. But this has not been the case for a long time, and they both
increment together in the same location in allmain.c. There are no
longer any cases where they will not be the same value.
This is a save-breaking change because it changes struct
instance_globals, but I have not updated the editlevel in this commit.
While testing some corpse/statue name manipulation changes I managed
to trigger a panic during end-of-game cleanup. Using a bullwhip to
snatch a wielded cockatrice corpse from a monster's inventory into
the hero's inventory and being turned to stone due to lack of gloves
took the corpse out of the monster's inventory but didn't place it
anywhere. If no life-saving took place, it led to an "obj_is_local"
panic during timer cleanup when freeing the level.
This patch includes some of the stuff I've been testing rather than
just the fix for the panic (which is the very last bit of the diff).
Applying a novel to flip through its pages described them as having
"ink" rather than "magical ink" but that wasn't a very suitable way
to distinguish them from spellbooks since their ink never fades.
The Book of the Dead's pages "glowed faintly red" even when the
hero couldn't see them.
Fixes#513
Restore some old behavior for the apply command that was changed
by the "getobj refactor" patch. You couldn't attempt to apply
potions to determine whether they were oil, couldn't apply gray
stones once touchstone was discovered, and attempting to apply
arbitrary items gave "that is a silly thing to apply" rather
than "sorry, I don't know how to use that."
The message given when attempting to light a lantern with no power
left described it as a lamp. Change that to lantern. Also, "has
run out of power" duplicates the message given when it burns out;
change that part to "is out of power".
Your lamp has run out of power. -> Your lantern is out of power.
Fixes#489
Zapping wand of opening or spell of knock at engulfer while swallowed
would make the engulfer expel the hero; this change makes zapping
other holders release their hold. Zapping self now achieves the same
effect, as does breaking a non-empty wand of opening. When poly'd
hero is holding a monster rather than being held, that monster will
be released.
Engulfers can't re-engulf for 1 or 2 turns after releasing the hero
in order to prevent hero from being immediately re-engulfed. Impose
the same limitation on other holders.
without using any time. Targetting an apparently empty spot at
valid polearm range where a monster happens to be hiding reports
"Wait! There's something there you can't see!" and displays the
remembered, unseen monster glyph, then aborts the attack attempt.
It would use a turn if the polearm became wielded in the attempt
but not if it was already wielded. Make latter case take time.
We have a struct called mkroom and a function called mkroom()
so c++ complains about the mkroom() function hiding the
initializer for the struct.
Similarly, we have a struct called attack and a function
called attack().
There may be a more elegant way of eliminating those two
warnings, but renaming mkroom() to do_mkroom() and
attack() to do_attack() was straightforward enough.
If an empty lamp was hit by fire, the feedback was "the lamp
catches fire!" even though it wouldn't light.
ingite_items() imperfectly duplicated catch_lit(). Just call
the latter. The resulting message will be slightly different
but that's insignificant.
This replaces the arcane system previously used by getobj where the
caller would pass in a "string" whose characters were object class
numbers, with the first up to four characters being special constants
that effectively acted as flags and had to be in a certain order.
Because there are many places where getobj must behave more granularly
than just object class filtering, this was supplemented by over a
hundred lines enumerating all these special cases and "ugly checks", as
well as other ugly code spread around in getobj callers that formatted
the "string".
Now, getobj callers pass in a callback which will return one of five
possible values for any given object in the player's inventory. The
logic of determining the eligibility of a given object is handled in the
caller, which greatly simplifies the code and makes it clearer to read.
Particularly since there's no real need to cram everything into one if
statement.
This is related to pull request #77 by FIQ; it's largely a
reimplementation of its callbacks system, without doing a bigger than
necessary refactor of getobj or adding the ability to select a
floor/trap/dungeon feature with getobj. Differences in implementation
are mostly minor:
- using enum constants for returns instead of magic numbers
- 5 possible return values for callbacks instead of 3, due to trying to
make it behave exactly as it did previously. PR #77 would sometimes
outright exclude objects because it lacked semantics for invalid
objects that should be selectable anyway, or give slightly different
messages.
- passing a bitmask of flags to getobj rather than booleans (easier to
add more flags later - such as FIQ's "allow floor features" flag, if
that becomes desirable)
- renaming some of getobj's variables to clearer versions
- naming all callbacks consistently with "_ok"
- generally more comments explaining things
The callbacks use the same logic from getobj_obj_exclude,
getobj_obj_exclude_too and getobj_obj_acceptable_unlisted (and in a few
cases, from special cases still within getobj). In a number of them, I
added comments suggesting possible further refinements to what is and
isn't eligible (e.g. should a bullwhip really be presented as a
candidate for readying a thrown weapon?)
This also removed ALLOW_COUNT and ALLOW_NONE, relics of the old system,
and moved ALLOW_ALL's definition into detect.c which is the only place
it's used now (unrelated to getobj). The ALLOW_ALL functionality still
exists as the GETOBJ_PROMPT flag, because its main use is to force
getobj to prompt for input even if nothing is valid.
I did not refactor ggetobj() as part of this change.
further adjustments to the window port interface to pass a pointer
to a glyph_info struct which describes not just the glyph number
itself, but also the ttychar, the color, the glyphflags, and the
symset index.
This affects two existing window port calls that get passed glyphs
and does the parameter consistently for both of them using the
glyph_info struct pointer:
print_glyph()
add_menu().
The recently added glyphmod parameter is now unnecessary and has been
removed.
add MALE, FEMALE, and gender-neutral names for individual monster species
to the mons array. The gender-neutral name (NEUTRAL) is mandatory, the
MALE and FEMALE versions are not.
replace code uses of the mname field of permonst with one of the three
potentially-available gender-specific names.
consolidate some separate mons entries that differed only by species into a
single mons entry (caveman, cavewoman and priest,priestess etc.)
consolidate several "* lord" and "* queen/* king" monst entries into
their single species, and allow both genders on some where it makes some
sense (there is probably more work and cleanup to come out of this at some
point, and the chosen gender-neutral name variations are not cast in stone
if someone has better suggestions).
related function or macro additions:
pmname(pm, gender) to get the gender variation of the permonst name. It
guards against monsters that haven't got anything except NEUTRAL naming
and falls back to the NEUTRAL version if FEMALE and MALE versions are
missing.
Ugender to obtain the current hero gender.
Mgender(mtmp) to obtain the gender of a monster
While the code can safely refer directly to pmnames[NEUTRAL] safely in the
code because it always exists, the other two (pmnames[MALE] and
pmnames[FEMALE] may not exist so use:
pmname(ptr, gidx)
where -ptr is a permonst *
-gidx is an index into the pmnames array field of the
permonst struct
pmname() checks for a valid index and checks for null-pointers for
pmnames[MALE] and pmnames[FEMALE], and will fall back to pmnames[NEUTRAL] if
the pointer requested if the requested variation is unavailable, or if the
gidx is out-of-range.
Allow code to specify makemon flags to request female or male (via MM_MALE
and MM_FEMALE flags respectively)to makedefs, since the species alone doesn't
distinguish male/female anymore. Specifying MM_MALE or MM_FEMALE won't
override the pm M2_MALE and M2_FEMALE flags on a mons[] entry.
male and female tiles have been added to win/share/monsters.txt.
The majority are duplicated placeholders except for those that were
separate mons entries before. Perhaps someone will contribute artwork in the
future to make the male and female variations visually distinguishable.
tilemapping via has the MALE tile indexes in the glyph2tile[]
array produced at build time. If a window port has information that the
FEMALE tile is required, it just has to increment the index returned
from the glyph2tile[] array by 1.
statues already preserved gender of the monster through STATUE_FEMALE
and STATUE_MALE, so ensure that pmnames takes that into consideration.
I expect some refinement will be required after broad play-testing puts it to
the test.
consolidate caveman,cavewoman and priest,priestess monst.c entries etc
This commit will require a bump of editlevel in patchlevel.h because it alters
the index numbers of the monsters due to the consolidation of some. Those
index numbers are saved in some other structures, even though the mons[] array
itself is not part of the savefile.
Window Port Interface Change
Also add a parameter to print_glyph to convey additional information beyond
the glyph to the window ports. Every single window port was calling back to
mapglyph for the information anyway, so just included it in the interface and
produce the information right in the display core.
The mapglyph() function uses will be eliminated, although there are still some
in the code yet to be dealt with.
win32, tty, x11, Qt, msdos window ports have all had adjustments done to
utilize the new parameter instead of calling mapglyph, but some of those
window ports have not been thoroughly tested since the changes.
Interface change additional info:
print_glyph(window, x, y, glyph, bkglyph, *glyphmod)
-- Print the glyph at (x,y) on the given window. Glyphs are
integers at the interface, mapped to whatever the window-
port wants (symbol, font, color, attributes, ...there's
a 1-1 map between glyphs and distinct things on the map).
-- bkglyph is a background glyph for potential use by some
graphical or tiled environments to allow the depiction
to fall against a background consistent with the grid
around x,y. If bkglyph is NO_GLYPH, then the parameter
should be ignored (do nothing with it).
-- glyphmod provides extended information about the glyph
that window ports can use to enhance the display in
various ways.
unsigned int glyphmod[NUM_GLYPHMOD]
where:
glyphmod[GM_TTYCHAR] is the text characters associated
with the original NetHack display.
glyphmod[GM_FLAGS] are the special flags that denote
additional information that window
ports can use.
glyphmod[GM_COLOR] is the text character
color associated with the original
NetHack display.
Support for including the glyphmod info in the display glyph buffer
alongside the glyph itself was added and is the default operation.
That can be turned off by defining UNBUFFERED_GLYPHMOD at compile time.
With UNBUFFERED_GLYPHMOD operation, a call will be placed to map_glyphmod()
immediately prior to every print_glyph() call.
Multiple functions are involved in the process of targeting and
attacking an enemy with a polearm or lance, and these functions
previously used inconsistent tests to determine which targets were
legal. For instance, find_poleable_mon would give up immediately if the
hero was blind, while neither get_valid_polearm_position nor use_pole
cared as long as the hero could detect a target on the square (e.g. by
ESP). find_poleable_mon considered warning symbols as potential
targets, but use_pole discarded them. get_valid_polearm_position
considered moats and pools to be illegal targets, but use_pole would
let the hero successfully hit a monster on those squares; on the
other hand, get_valid_polearm_position would mark squares that were not
visible and did not contain a known monster as legal targets, while
find_poleable_mon and use_pole would exclude them.
Obviously this was inconsistent and could introduce confusion for
polearm users, who would potentially need to explicitly target squares
marked "(illegal)" at some point over the course of their game, among
other problems. This commit makes polearm targeting tests more
consistent; the following rules are applied to positions within the
appropriate range:
* Monsters which are detected by any means that reveals an actual
monster glyph are legal to target, even if the hero is blind
* Monsters the hero cannot detect, but is aware of -- i.e. those
represented by an 'I' -- are similarly legal to target
* Monsters detected via warning are not legal targets, since the hero
does not have as strong a sense of where exactly they are, their shape
and size, etc
* Statues are legal targets, but will not be suggested by
find_poleable_mon unless the hero is impaired (confused, stunned, or
hallucinating); the same is true of tame/peaceful monsters
* Apparently empty squares, including those containing an undetected
monster, are legal to target unless they cannot be seen (whether due
to blindness or a very dark room/level)
* Positions which are otherwise legal but are blocked by an obstruction like a
tree or pillar are not legal targets
Use a linked list to store stair and ladder information, instead
of having fixed up/down stairs/ladders and a single "special" (branch)
stair.
Breaks saves and bones.
Adds information to migrating objects and monsters for the dungeon
and level where they are migrating from.
Breaking a wand didn't require the hero to have free hands.
That's definitely a bug when they're both welded to the same
two-handed weapon. It's debatable when welded separately to
a one-handed weapon and to a shield but simpler to pretend
there's no such distinction.
This also makes glass wand join balsa wand as "fragile". Hero
doesn't need as much strength to break them as other wands and
the wording for breaking them is slightly different.
My fixes entry initially had a trailing space. When I took
that out, I spotted a couple of others so take those out too.
ignitable() was excluding magic lamp and then every place that
used it did so as 'ignitable(obj) || obj->otyp == MAGIC_LAMP'
so just include magic lamp.
I noticed that while hunting for an explanation for report #K2734
where returning to a previously visited level triggered the
warning "begin_burn: unexpected eggs". I've decided that the
zombie apocalypse is probably the cause. It inserted a new type
of timer in the list of such but it didn't bump EDITLEVEL to
invalidate save and bones files which relied on indices into the
old list. I'm not sure whether we should bump that now.
Noticed while working on Qt's version of persistent inventory
window (paper doll-style display of equipment in use), leashing
or unleashing a pet wasn't updating persistent inventory. Leash
descriptions format differently when in use so immediate update
is warranted.