PatR [Thu, 3 Mar 2022 15:47:56 +0000 (07:47 -0800)]
github issue #688 - end of game livelog event
Requested by k21971 (hardfought admin): classify the gameover event
as something other than achievement so that live-logging can exclude
it in order to use the xlogfile end-of-game entry instead.
It had been classified as an achievement because that was the only
category being treated as 'major' so written to final dumplog. Give
is a new classification 'dump' which is distinct from achievement
and intended to explicitly request that an event go into dumplog.
The gameover event is the only one in that category, at least for now.
Add a bunch of other classifications besides achievement and dump to
be treated as 'major' for dumplog. The new list is
wish, achieve, umonst (death of unique monster), divinegift,
lifesave (via amulet, not explore-/wizard-mode decline to die),
artifact, genocide, dump
and may still need further tuning. Currently excluded are
conduct (first violation of any conduct), killedpet, alignment
(changed, either via helmet or conversion), minorac (minor
achievement such as level gain or entering the mines), and spoiler
(currently only applies to finding Mines' End luckstone which is
also 'achieve' so will be in dumplog).
This doesn't remove the reference to unimplemented LLC_TURNS that is
mentioned in the template sysconf.
PatR [Thu, 3 Mar 2022 13:38:34 +0000 (05:38 -0800)]
raw_print() usage
Get rid of a couple of mis-formatted casts in lock_file(). raw_print()
is declared as void so casting its result to (void) was pointless.
Presumeably at one point it has used printf() or fprintf(stderr,...)
where the cast would have been useful to pacify 'lint'.
PatR [Thu, 3 Mar 2022 13:27:05 +0000 (05:27 -0800)]
fix issue #689 - ?: warning
From copperwater: a recently added use of <test> ? <if> : <else>
had a ptrdiff_t (signed) expression for <if> and a size_t (unsigned)
expression for <else> which triggered a sign-compare warning when
the two expressions are implicitly converted into the same type.
Use casts to convert both expressions to long rather that convert
the size_t half to ptrdiff_t or vice versa. The final result gets
cast to int already.
PatR [Wed, 2 Mar 2022 22:43:12 +0000 (14:43 -0800)]
clear_bypasses() should operate on buried objects
Fix an object sanity check failure: a buried object with its bypass
bit set.
clear_bypasses() was supposed to be clearing the bypass bit on every
object but was neglecting the buried objects list and the billed
objects list (and inventory of the mydogs list, but that is expected
to always be empty at the time when clear_bypasses() gets called).
We already had an issue with billed objects, revealed by the fuzzer
soon after sanity checking was extended to test bypass/in_use/nomerge
bits. That one was fixed by clearing the bypass bit of specific
objects as they are being added to a shop bill. This fix should make
that earlier one become obsolete, but isn't removing it.
PatR [Wed, 2 Mar 2022 21:09:42 +0000 (13:09 -0800)]
some livelog cleanup
The gamelog structure's type/flags field is 'long' but the
corresponding livelog event type field and the argument passed to
gamelog's logging were 'unsigned'. They take the same values and
those values mean the same things so change them all to long.
The actual livelog logging assumed that time_t is a long number of
seconds, and was also using a boolean as an array index. Perform
proper type conversions.
sysconf parsing used 'int' to hold strtol() value; change to long.
Also it was using raw_printf() instead of config_error_add() to
complain about any problems. Clearly the livelog patch was not
updated to the current code base before being incorporated.
PatR [Wed, 2 Mar 2022 01:23:41 +0000 (17:23 -0800)]
livelog: killing unique monsters revisited
Treat all kills of the Wizard and of any of the Riders as major events
for inclusion in dumplog. For other unique monsters, that only happens
when they're killed for the first time.
PatR [Wed, 2 Mar 2022 00:51:41 +0000 (16:51 -0800)]
livelog: killing unique monsters
Treat the first kill of any unique monster as a major event (for
inclusion in dumplog). Revival and repeat kill is not major but
can still be seen during the game via the #chronicle command.
Show the minor event more often: in addition to death #1 it was
being shown on death 5, 10, 50, 100, 150, 200, and 250. Add 2, 3,
and 25 to that list.
PatR [Tue, 1 Mar 2022 22:11:58 +0000 (14:11 -0800)]
eat.c formatting
This is just reformatting some relatively recently added code.
There's a lot of redundancy in eating conduct tracking and livelog
reporting of that, but this doesn't attempt to streamline it. I may
try again some other time....
PatR [Tue, 1 Mar 2022 21:53:57 +0000 (13:53 -0800)]
livelog level entry events
Fix up the level descriptions used when logging an "entered new level"
event. Most of the change is for adding an extra argument to calls
to describe_level(). The curses portion is in a big chunk of old code
suppressed by #if 0.
I didn't notice that the level entry events are classified as LL_DEBUG
until all the work was done. This promotes the entry events for the
four Plane of <Element> levels from debug events to major ones instead.
It doesn't do that for the Astral Plane because the entered-the-Astral-
Plane achievement already produces a major event for that. Most other
key level entry events are in a similar situation--or will become that
way once another set of achievements eventually gets added--so there
aren't any other event classification promotions.
Alex Smith [Tue, 1 Mar 2022 13:23:10 +0000 (13:23 +0000)]
Avoid panic on zero-byte writes to save files
This is a well-defined operation, so bwrite() should be able to
handle it. However, when running under glibc, fwrite() produces an
unexpected return value for 0-byte writes, which makes bwrite()
think that the write failed (causing a panic).
This change implements 0-byte writes by not calling into libc at
all, so that we don't have to worry about how to decode the return
value of fwrite().
PatR [Tue, 1 Mar 2022 12:15:55 +0000 (04:15 -0800)]
fix github issue #687 - logging of major events
Reported by k21971, the dumplog section labeled "major events" showed
all logged events rather than just the ones classified as major.
Filter out the non-major ones when writing dumplog.
At the moment only a couple of ones other than achievements are major.
Probably various other types should be too.
The #chronicle command still lists all logged events unless they're
flagged as 'spoiler'. So far the mines' end luckstone is the only
one flagged that way. Unfortunately a player with access to live
logging could still learn whether or not the gray stone that has just
been picked up on the last mines level is the target luckstone by
viewing the log from outside of the game.
The #chronicle command would be more useful if it gathered all the
categories of events present and put up a menu allowing the player to
choose which ones to view. I haven't attempted to implement that.
PatR [Mon, 28 Feb 2022 21:46:59 +0000 (13:46 -0800)]
livelog revisions
Some changes to fix things I noticed in the dumplog referenced by
github issue #687 about showing all logged events under the header
"major events". (This doesn't address that. I figured it was
intentional while #chronicle is having any bugs worked out.)
Sequencing: show the event corresponding to an achievement for
entering a dungeon branch before the livelog-specific event of
entering a level for the first time. You enter the branch before
arriving at the new level.
Missing feedback: the you-won achievement didn't produce any
"ascended" event. That turned out to be a side-effect to suppressing
achievements that take place after the gameover flag has been set
(so blind-from-birth and/or nudist when applicable plus duplicate
obtained-amulet and ascended due to manipulation to reposition the
amulet achievement to be right before ascended so that the alternate
wording it has in the achievements listing looks better). Instead of
just forcing the ascended achievement to produce an ascended event,
this adds a more general game-over event.
While in there, change the classification of attaining level 14 from
minor livelog event to major since questing keys off of it.
nhkeni [Mon, 28 Feb 2022 00:57:16 +0000 (19:57 -0500)]
cmdcount_t
Add a type to force g.{command_count,last_command_count,multi} to have the
same type (because cmd.c: g.multi = g.command_count;) and some resulting
cleanup.
PatR [Sun, 27 Feb 2022 20:20:20 +0000 (12:20 -0800)]
document new 'tune' achievement
Add /tune/ to the achievement section of the Guidebook.
The 'note' part is a bit of a spoiler and risks making the prayer
boon of "Hark! To enter the castle you must play the right tune."
redundant for players who actually read the Guidebook (so hardly
anybody). Since that's the first stage of a two-stage reward I've
left it alone.
PatR [Sun, 27 Feb 2022 09:55:25 +0000 (01:55 -0800)]
new achievement: drawbridge tune
Use up the last available bit for achievements:
"You learned the tune to open and close the castle's drawbridge."
(More can still be added but xlogfile will need another field to
track a second set of 31 in order to keep its achievement bitmask(s)
within portable size.)
As achievements go, it's not very exciting, but players who normally
destroy the drawbridge have to choose whether to earn an achievement
first since once it's gone, there's no way to find out the tune
(either via prayer reward or successful Mastermind). I'm guessing
that most will probably decide to ignore this achievement since it
has no effect on the outcome of the game. However, that might not
be true for future tournament play.
There's no need to bump EDITLEVEL for this; room for recording one
additional achievement is already allocated.
PatR [Sat, 26 Feb 2022 18:15:58 +0000 (10:15 -0800)]
choose_stairs() revisited
Rewrite choose_stairs(). Use of '&& !builds_up()' was a no-op in
normal branches and forced picking the down stairs/ladder in Vlad's
Tower (or Sokoban) rather than reversing the usual up/down choice.
Also, the logic used was backwards: Kops always surrounded the up
stairs instead of the down stairs as intended. Non-Kops picked the
opposite direction of what the arguments asked for but since they based
their choice of up versus down on hidden mon->m_id, the reversal wasn't
noticeable.
Extend the choosing so that if nothing in the requested direction can
be found, it tries the opposite direction. Otherwise when Vlad's m_id
happens to force the direction to be 'up', he has nowhere to teleport
to now that being in his Tower doesn't force 'down' anymore. He goes
to down ladder when on the top level but if you level teleport to the
next level down and he accompanies you, he might go to either the down
ladder or the up ladder when he tries to get away from you to heal.
PatR [Sat, 26 Feb 2022 06:35:04 +0000 (22:35 -0800)]
fix github issue #686 - dead code
Reported by argrath: the code in choose_stairs() intended as last
resort wouldn't do anything because the loop's test condition always
started out false. Fix suggested by entrez.
Pasi Kallinen [Fri, 25 Feb 2022 19:49:38 +0000 (21:49 +0200)]
Unify domove and lookaround trap/liquid avoidance code
Nearly same code was in two places - the only difference was
how g.context.run == 1 was handled. Previously, if you were
blind, and knew about the water or lava, you still ran into it.
Now, we always avoid the dunking if running/rushing.
PatR [Fri, 25 Feb 2022 18:39:45 +0000 (10:39 -0800)]
remove references to old Qt 'moc' timestamp files
src/moc.qt[56] existed briefly but got replaced by src/Qt[56].h-t
(controlled by hints/include/compiler.370). The old names were
deliberately left in src/.gitignore and sys/unix/Makefile.src's
'clean' target to give some time for anyone who had generated them
to run 'make clean' to get rid of them. That time is now up. It's
only been about three weeks but if I wait any longer I'll probably
forget.
PatR [Fri, 25 Feb 2022 15:10:30 +0000 (07:10 -0800)]
more thrown object cleanup
Handle thrown or kicked object that's in transit for hangup save and
panic save in addition to normal end of game. Affects ball and chain
placement too, if they've been temporarily taken off the map.
PatR [Fri, 25 Feb 2022 02:10:52 +0000 (18:10 -0800)]
lost objects thrown by monsters
Reported by entrez: if a monster or explosion kills the hero with an
object that has timers or is a light source, it could trigger a panic
when end of game cleanup can't find it because it has been removed
from the map or monster's inventory and not placed back on the map
yet. This isn't much different from something thrown by hero which
had a similar situation dealt with a long time ago. Fix by setting
'thrownobj' for monster-launched and explosion-launched missiles.
That way done_object_cleanup() called from really_done() will place the
missile on the map where saving bones or general cleanup can find it.
It doesn't bother dealing with exploding a lit potion of oil that
kills the hero by missile damage before the potion explodes. If that
ends up in bones, it should still be lit and might blow up before the
new character reaches it. (Not verified.)
The code for a hero polymorphed into a unicorn and catching a thrown
gem has been moved into its own routine. No change in behavior, just
less clutter in the thrown-object-hits-hero section of the monster
throwing routine.
Pasi Kallinen [Thu, 24 Feb 2022 16:55:11 +0000 (18:55 +0200)]
Most traps now require touching the floor to trigger
It was silly how some clearly mechanical traps didn't consider
flight or levitation when to trigger. Do those checks in dotrap/mintrap
making hero and monster trap triggering match more closely.
Pasi Kallinen [Thu, 24 Feb 2022 14:23:56 +0000 (16:23 +0200)]
Make trap return values more consistent
Instead of returning monster's mtrapped-state, return specific
trap return values.
Add one extra trap return value, for when a monster was
moved by the trap.
Michael Meyer [Wed, 23 Feb 2022 17:58:43 +0000 (12:58 -0500)]
Fix: monster hurtling and liquid
A monster hurtling over liquid would drown immediately the instant it
touched the first square of water, even if normally it would have kept
moving (e.g. hurtling over a short moat). Additionally, its placement
on liquid would not take into consideration other monsters, so it could
overwrite an existing monster on that spot and lead to an impossible,
and/or two monsters occupying a single position.
Fix these issues, so that liquid effects like drowning only happen if
the monster ends up in liquid at the end of the hurtle, and so that
other monsters in the way will stop it early even if they're floating
over or swimming on a pool/water/lava square.
Also use canspotmon instead of canseemon for the wiztelekinesis debug
command.
PatR [Wed, 23 Feb 2022 17:50:25 +0000 (09:50 -0800)]
fix #K3529 - perm_invent not IDing blank scroll
Report was for curses but issue is in the core so any interface
that supports persistent inventory is affected. Reading a not-yet-
discovered scroll of blank paper wasn't always updating perm_invent
to show change in formatted description when it became discovered.
Would only happen on turn #1 (so the scroll needed to be acquired
via autopickup at starting location or via wizard mode wish so that
it could be read before any game time elapsed) when the object
discovery routine deliberately avoided updating perm_invent. Fix
by using a different way than moves==1 to decide whether an object
is being discovered because it is part of hero's initial inventory.
PatR [Tue, 22 Feb 2022 20:12:13 +0000 (12:12 -0800)]
more sleeping monster
Extend the PR#660 change that shows whether a monster is asleep when
examined by farlook/quicklook/autodescribe to monsters that aren't
moving due to timed sleep as well as those that are asleep for an
unspecified amount of time. Unfortunately 'mfrozen' isn't specific
about why a monster can't move so the phrasing is less than ideal.
Pasi Kallinen [Tue, 22 Feb 2022 10:26:03 +0000 (12:26 +0200)]
Start with a level 1 spell and enough power
Ensure the first spell - if any - given to the hero in initial
inventory is level 1 - otherwise you can end up with a situation
where the hero knows level 3 spells, but won't have enough power
to cast them.
If the hero starts out with a spell, ensure enough power (5)
to cast that level 1 spell.
Pasi Kallinen [Tue, 22 Feb 2022 07:13:28 +0000 (09:13 +0200)]
Adjust sleep spell, and monk starting spell
Tone down sleep level to 3 (hitting a monster does tend to wake
it up), and replace the random monk starting sleep spell with
confuse monster, which fits nicely with monk's bare-handed
fighting style.
PatR [Mon, 21 Feb 2022 18:59:42 +0000 (10:59 -0800)]
Unix command line bit
For the !SYSCF configuration, the command line processing still checks
for a value for maximum number of simultaneous players. The recent
revisions would have accepted a negative value. I don't know whether
anything interesting would have happened if someone did that.
Pasi Kallinen [Mon, 21 Feb 2022 17:30:52 +0000 (19:30 +0200)]
Adjust enchantment spell levels
The enchantment spells were skewed towards lower spell levels,
and didn't seem to correspond with the spell effectiveness or
power. Adjust the spell levels:
- Confuse monster is probably the least powerful enchantment, and
also requires touch to work, so make it the new level 1 spell.
- Sleep is quite powerful, and ray, bump it to level 4.
- Charm monster is even more powerful so make it level 5.
(Considering that create familiar is level 6)
old new
sleep 1 4
confuse monster 2 1
slow monster 2 2
cause fear 3 3
charm monster 3 5
Also swap sleep and confuse monster generation probability.
PatR [Sun, 20 Feb 2022 22:46:59 +0000 (14:46 -0800)]
fixes entry for pull request #683 - just picked
Pull request from argrath: the code that decides whether to add 'B'
for blessed items, 'X' for unknown bless/curse state and so forth
when setting up prompting for the 'I' command was counting up the
recently introduced "just picked up" category using an uninitialized
variable. So it might erroneously include 'P' as a choice when no
such items were present.
PatR [Sun, 20 Feb 2022 21:52:18 +0000 (13:52 -0800)]
makedefs exit control
Have makedefs do through a common point when exiting, in case it ever
needs extra memory or scratch file cleanup.
While testing, I discovered that the reference use of 'makedefs -o' to
build obsolete onames.h didn't work anymore because of the change to
not require object probabilities to add up to 1000 within classes.
I think fixing that is the only change besides new 'makedefs_exit()'.
PatR [Sun, 20 Feb 2022 21:47:31 +0000 (13:47 -0800)]
memory management for 'nomakedefs'
The nomakedefs struct starts out with static values, then if/when
populate_nomakedefs() is called, the fields are given dynamic values.
free_nomakedefs() needs to know what state it's in.
A big chunk of this if just formatting for indentation.