Add a bc sanity check. It seems to work ok--in other words, not
trigger--under normal punishment. I don't have any test cases to
exercise its warnings.
This dragged in a couple of minor bc changes that were pending. I
should have cleared those out before tackling the sanity checking.
During shop repair, give a message about the shopkeeper using a spell
(if hero is close enough) before "Suddenly, <various repairs occur>."
And when shop repair is for a single untrap of landmine or bear trap
adjacent to shk (and the hero can see it happen), say "<Shk> untraps
<trap>" rather than just "Suddenly, a trap is removed from the floor!"
Change in meaning of mnearto()'s return value wasn't progagated to
shkcatch(). Make it an int instead of boolean so that it can
communicate both 'moved successfully' and 'moved but had to move
another monster out of the way to do so'.
Take care of a minor 'TODO' and make another stab at getting truncated
encumbrance and/or level-description to reset to full size when enough
space becomes available.
Put the prototypes for routines in botl.c into the same order as the
corresponding functions are in the file. Also a few were missing and
another few used STATIC_OVL when STATIC_DCL was appropriate.
When the 'time' option is on and context.botl isn't already set,
call a simpler status update routine that ignores all other fields.
When that flag is already set, full status update takes care of time
along with the other fields.
Expected to reduce bottom lines processing time but not screen I/O.
Only lightly tested.
Noticed while testing statuslines on a small terminal window. Using
the cursor to pick locations that panned the map to view a new subset
would end up showing a new view of the regular map rather than a
different section of what was currently displayed. For farlook that
caused monsters to take on new hallucinatory forms which was fairly
inconsequential, but for #terrain and various forms of detection it
reverted to the ordinary map instead of showing the map features that
the player requested or the temporarily revealed monsters and such.
Most interfaces keep track of the whole map and just show their view
of the new subset when panning, similar to redisplay after being
covered up and then re-exposed, but tty isn't doing that. I made
same change to Amiga as to tty since the code it was using was very
similar. I haven't touched any of the other interfaces and assume
that they don't need this. I've verified that curses and X11 don't.
decode_mixed() writes its output into a 'char *' buffer that's passed
in to it and then returns that buffer. Some excessively paranoid
error checking forced to return 'const char *'. Relax that and use
'char *' so callers can work with the result without extra casts.
Fixes#177
The monst struct has 'mintrinsics' field which attempts to handle
both mon->data->mresists and extrinsics supplied by worn armor, but
polymorph/shape-change was clobbering the extrinsics side of things.
Potentially fixing that by changing newcham() to use set_mon_data(...,1)
instead of (...,0) solved that but exposed two other bugs. Intrinsics
from the old form carried over to the new form along with extrinsics
from worn armor, and update_mon_intrinsics() for armor being destroyed
or dropped only worked as intended if the armor->owornmask was cleared
beforehand--some places were clearing it after, so extrinsics from worn
gear could persist even after that gear was gone.
So, fixing the set_mon_data() call in newcham() was a no go. This
fixes update_mon_intrinsics() and adopts the suggested code from
github pull request #177 to have mon->mintrinsics only handle worn
gear instead of trying to overload innate intrinsics with that. This
is a superset of that; the flag argument to set_mon_data() is gone
and mon->mintrinsics has been renamed mon->mextrinsics. (The routine
update_mon_intrinsics() ought to be renamed too, but I didn't do that.)
Do late message suppression in a different fashion. Also, there are
more messages than shk taking hero's possessions and guard taking
hero's gold that need to be suppressed if regular message delivery
is no longer possible: "do not pass Go", "you arise from the grave
as a foo", "the corridor disappears", "you are encased in the rock".
Those last two are from vault handling but take place in a convoluted
manner: paygd -> mongone -> grddead -> clear_fcorr.
Fixes#101
If you tell the vault guard your name, drop carried gold, wait one
turn, then pick up the gold again, the guard will move a step away
during the wait. If you teleport away, the guard will seal vault
walls and then park himself on the one-square (so far) temporary
corridor adjacent to the vault wall. Periodically he'll say "Move
along!" and the hero will hear it, regardless of location on the
level. Unless you dig a corridor to rescue him, or one or more of
the vault's walls get breached again, he will never move.
The report emphasized that you could use this to steal the vault's
gold, but it relies on being able to teleport beyond the gaurd's
reach and if you can do that, you might as well do so before the
guard comes. The stranded guard, and him saying "Move along!" when
no longer leading hero out of the vault, are more significant bugs.
Bonus fix: if the game ends and the guard seals up the vault while
the hero is in a spot that gets fixed up (vault wall or temporary
corridor) don't give the "You are encased in the rock" message if
game end was due to death rather than quit.
The new code provoked several warnings; this fixes one of them.
Moving the declaration of 'rolecount' would have been sufficient,
but I've gone another way.
This is branched from Alex's hallu-rng-stability branch,
with two build corrections (detect.c, zap.c), and merged
with the isaac64 branch that we have ready to go.
Alex's dual rng is supported by setting up the array
of multiple isaac64 contexts.
I stuck with Alex's approach of passing the rng function
name around as the parameter (rng or rn2_on_display_rng)
for the new additional parameter needed for
set_random(), init_random(), reseed_random(),
and init_isaac64().
move some system-specific seed-related stuff from hacklib.c to
a system-specific source file and #define SYS_RANDOM_SEED to
utilize it during build.
Windows changes for random seed generation using
crypto next gen (CNG) api routines.
Corresponding vms changes due to disentangling of VMS and
unix when the unix seed bits got moved (untested).
Linux and BSD system have random number source devices that can be used
as source for a unguessable seed source.
Other platforms fall back to generate the seed with gettime().
This is based on the multiple-RNGs code fron NetHack4, but using
only the parts relevant to the display RNG (and with substantial
changes, both because of post-3.4.3 changes, and because Nethack4's
display code is based on Slash'EM's rather than NetHack's).
I did much of this quite some time ago, as prequisite for a different
bug report about monsters vs shades, then set it aside. It ended up
being more complicated than I anticipated.
When deciding whether various non-weapon attacks might hit a shade,
hmonas() was not checking for blessed or silver armor that should have
been applicable. It did check boots when kicking, but not gloves or
rings (when no gloves) when touching, or outermost of cloak/suit/shirt
when hugging, or helmet when head-butting. (The last one is actually
moot because nothing with a head-butt attack is able to wear a helm.)
The problem was more general than just whether attacks might hit and
hurt shades. Various undead and/or demons are also affected by blessed
and/or silver attack but weren't for non-weapon attacks by poly'd hero.
At least two unrelated bugs are fixed: a rope golem's AT_HUGS attack
gives feedback about choking but was fully effective against monsters
which fail the can_be_strangled() test. And it was possible to hug a
long worm's tail, rendering the entire worm immobile.
The report also suggested that all artifacts be able to hit shades for
full effect, but by the time shades are encountered everyone has an
artifact so that would nullify a shade's most interesting ability.
TODO: monster against hero and monster against other monster need to
have similar changes.
Both u_on_rndspot() and losedogs() might result in having a monster
and the hero be at the same location. Have wiz_makemap() use the
same fixup for that as goto_level().
The recent attempt to have looking inside a container show shop
prices had multiple problems. Worst one was showing shop prices as
if the hero would be buying for items already owned by the hero.
Item handling inside containers on shop floor was inconsistent: if
shop was selling those items, they would include a price, but if not
selling--either already owned by hero or shopkeeper didn't care about
them--they were only marked "no charge" if hero owned the container.
This is definitely better but I won't be surprised if other obscure
issues crop up. Gold inside containers on shop floor is always owned
by the shop (credit is issued if it was owned by the hero) but is not
described as such.
Fixes#172
Casting teleport-away via ^T used different requirements for energy,
strength, and hunger than casting it via 'Z'. The strength and hunger
requirements were more stringent, the energy one more lenient. When
it rejected a cast attempt due to any of those, it used up the move,
but 'Z' didn't.
When testing my fix, I wanted an easier way than a debugger to control
how ^T interacts with wizard mode, so finally got around to a first
cut at being able to invoke it via wizard mode but not override those
energy/strength/hunger requirements. It uses the 'm' prefix to ask
for a menu. 'm^T' gives four options about how to teleport. (There
are other permutations which aren't handled.)
Also noticed while testing: ^T wouldn't attempt to cast teleport-away
if you didn't know the corresponding spellbook. 'Z' will attempt that
because it is possible to forget a book and still know its spell.
Fixes#170
Monsters never throw athames or scalpels but some fake player monsters
on the Astral Plane are given those. Since they're stackable the
quantity usually gets boosted but there's no point in having more than
one if they won't be thrown.
This could have been fixed by letting monsters throw those two items,
but I prevented the quantity from being boosted instead.
Player came across a stack of 2 gray stones in a shop and kicked one.
That one ended up with a different (in his case, lower) price once it
was separate. This behavior only applies to non-glass gems which add
a price variation derived from internal ID (obj->o_id) number. Make
splitting stacks always yield the same price per item in the new stack
as was being charged in the old stack by choosing a similar o_id. Do
it for all splits (that can vary price by ID, so just non-glass gems),
not just ones performed inside shops.
He picked up the lower priced one and dropped it back on the original
higher priced one; the combined stack took on the lower price. That
will no longer happen if they come from splitting a stack, but this
fix doesn't address merging with different prices when they start out
as separate stacks. (Unpaid items won't merge in inventory if prices
are different, but shop-owned items will merge on floor.)