Commit Graph

1160 Commits

Author SHA1 Message Date
nhkeni
1151d54500 Add and use Strlen(), like strlen() but panics on unreasonably long strings. 2022-03-16 21:42:00 -04:00
nhkeni
ff1289e828 Add Strlen(), a strlen(3) that panics if string is stupid long and returns unsigned.
First batch of changes to use it to suppress warnings.
2022-03-16 21:34:21 -04:00
nhkeni
1e31fee0df Don't infringe on POSIX typedef namespace. 2022-03-16 21:31:26 -04:00
nhkeni
7f484815e5 Add streq() and start finding places it fixes warnings.
Some type fixes from Michael Allison.
2022-03-16 18:50:17 -04:00
nhkeni
16ea5e7fa6 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.
2022-03-16 17:33:44 -04:00
Pasi Kallinen
074476758c Change map terrain changing from macro to function
The function handles setting lava lit, and removing ice melt timers.
2022-03-16 20:59:58 +02:00
Pasi Kallinen
38924002e0 Lua: ice theme room and melting ice
Allow the ice theme room to occasionally have melting ice.
Add nh.abscoord() to convert room-relative to map-absolute coords.
2022-03-15 22:05:36 +02:00
copperwater
cc04bf9d8f Fix selection "random" grow direction, and other code cleanup
Noticed that when I set a selection to grow in a random direction, it
instead grew in all directions, which is not what I wanted. Turns out
the -1 random dir ended up being passed straight to the code which
checks bitmasks, without any form of randomizing among directions.

So this adds code to do that, and defines W_RANDOM as -1 rather than
using a magic number. In the process I also noticed that specifying
"random" as the wall for a door in a room made it rerandomize the
direction every iteration of its loop, essentially rolling two rn2(4)s
and only proceeding if they matched. That was pointless so I cleaned it
up a bit.

Also added safety checks in the form of an impossible for des.corridor()
being called with "random" as either walldir, because this is not
implemented currently.

And lastly, I noticed that create_secret_door was entirely unused
(secret door creation is handled in create_door), so I deleted it.

The only behavior change caused by this is that the Valkyrie quest lava
pools will be a little smaller, which is the only place grow is
currently used. If it's desired to keep them the same, that should be
changed to "all".
2022-03-15 07:44:56 +02:00
copperwater
a61a97856b Externify trycall() and replace many docall() calls with it
trycall() is a short docall() wrapper that is a no-op if the item is
already identified or the player has called the object type already. For
some reason, many calls to docall() did those same exact checks
beforehand.

This commit eliminates that redundancy by converting those calls into
trycall(), which is now made extern rather than local to do.c. No
behavior should be changed by this commit; I've checked that none of the
affected places could take a different code path now that the
oc_name_known and oc_uname checks are removed.
2022-03-14 09:48:19 -04:00
Pasi Kallinen
20f214592a Lua: object timers
Expose object timers to lua scripts. For example:

   local o = obj.new("cockatrice egg");
   o:placeobj(5, 5);
   o:start_timer("hatch-egg", 3);

Available methods are:

- obj.has_timer("rot-corpse")
    returns true if object has attached timer, false otherwise.

- obj.peek_timer("hatch-egg")
    returns an integer value, which is the turn when the timer
    attached to the object would trigger. returns 0 if no such timer.

- obj.stop_timer("shrink-glob")
    stops attached timer, or if no timer type is given, stops all
    timers attached to the object.

- obj.start_timer("zombify-mon", 15)
    starts a timer with a trigger time in that many turns in the future.
    replaces any previous timer of the same type.

Valid timers are "rot-organic", "rot-corpse", "revive-mon",
"zombify-mon", "burn-obj", "hatch-egg", "fig-transform",
and "shrink-glob". Also "melt-ice" is recognized, but does nothing
to objects.
2022-03-13 14:50:07 +02:00
PatR
77dc522a62 artifact tracking again
Redo the recent artifact creation stuff by replacing several nearly
identical routines with one more general one.  Also adds a tracking
bit for one or two more creation methods.  That changed artiexist[]
from an array of structs holding 8 or less bits to one holding 9, so
bump EDITLEVEL in case the total size changed.
2022-03-12 17:25:54 -08:00
PatR
7a335eb030 more artifact tracking
This should have been broken up into multiple pieces but they're
all lumped together.  I did ultimately throw away a fourth change.

Implement artiexist[].bones and artiexist[].rndm artifact creation
tracking bits that were added recently.  Doesn't need to increment
EDITLEVEL this time.

Add a new wizard mode feature:  if you use `a to show discovered
artifacts, it will prompt about whether to show the tracking bits
for all artifacts instead.  If not using menustyle traditional,
you need at least one artifact to have been discovered in order to
have 'a' choice available when selecting what class of discovered
objects to show for the '`' command.

artifact_gift(), aritfact_wish(), and so forth return a value that
none of the existing callers use, so cast their calls to (void).
2022-03-11 11:00:44 -08:00
PatR
2d977a5d48 keep track of how artifacts got created
Since the struct used for elements of artiexist[] has a lot of unused
bits, add some new ones to extend it to indicate how artifacts have
been created.  It had
| .exists (has been created) and
| .found (hero is aware that it has been created)
introduce
| .gift (divine gift),
| .wish (player wish),
| .named (naming elven weapon Sting or Orcrist)
| .viadip (made Excalibur by dipping long sword into fountain)
| .rndm (randomly created), and
| .bones (from bones file--how it got created in earlier game isn't
tracked).  The first four are implemented, fifth and sixth aren't.

Some of the feedback when receiving an artifact or spellbook has been
revised.

When artiexist[] was changed from an array of booleans to an array of
structs a couple of days ago, EDITLEVEL should have been incremented
but I overlooked that at the time.  This commit does so now.
2022-03-09 16:11:14 -08:00
PatR
e3490743e0 divine gift of spell knowledge
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.
2022-03-09 07:06:37 -08:00
PatR
d37fa4138a found_artifact() groundwork
Lay groundwork for generating a log event when finding an artifact
on the floor or carried by a monster.  This part should not produce
any change in behavior.

Move g.artidisco[] and g.artiexist[] out of the instance_globals
struct back to local within artifact.c.  They are both initialized
at the start of a game (and only used in that file) so don't need
to be part of any bulk reinitialization if restart-instead-of-exit
ever gets implemented.

Convert artiexist[] from an array of booleans to an array of structs
containing a pair of bitfields.  artiexist[].exists is a direct
replacement for the boolean; artiexist[].found is new but not put to
any significant use yet.  If will be used to suppress the future
found-an-artifact event for cases where a more specific event (like
crowning or divine gift as #offer reward) is already produced.

Remove g.via_naming altogether and add an extra argument to oname()
calls to replace it.

Add an extra argument to artifact_exists() calls.
2022-03-07 02:06:55 -08:00
PatR
90fc7402b8 livelog event for crowning gift
There is an event for being crowned "Hand of Elebereth" and so forth
and an event for being given an artifact (any, not just the first) as
reward for #offer, but there wasn't one for the item usually given
along with being crowned.

Now there is.  It's not something that an observer (of the events
being logged) can deduce since sometimes an alternative is given
(wizard and monk) and other times nothing is given (artifact already
exists or lawful character isn't wielding non-artifact long sword).

I flagged the spellbook given to a wizard or a monk as
'divinegift | artifact | spoiler'.  'artifact' since even though it
isn't actually an artifact, it is standing in the place for one.  And
'spoiler', to hide from #chronicle, in case the hero doesn't know the
spellbook yet.
2022-03-05 15:14:18 -08:00
Pasi Kallinen
62906e732e Trap sanity checking 2022-03-04 16:54:43 +02:00
PatR
43e2f7d0ae 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.
2022-03-02 13:09:42 -08:00
PatR
2bef05bb77 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.
2022-03-01 13:53:57 -08:00
PatR
77bd50fd77 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.

Closes #687
2022-03-01 04:15:55 -08:00
nhkeni
3cf1b87914 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.
2022-02-27 20:01:49 -05:00
PatR
ca97f4f3dd 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.
2022-02-25 07:10:30 -08:00
PatR
ab2bcf4dac trap followup
Make the flags argument to dotrap() and mintrap() and the constants
passed to them all have consistent type: unsigned int.
2022-02-24 12:17:21 -08:00
Pasi Kallinen
2777f45bd5 Get rid of force_mintrap, allow passing flags to mintrap
It uses the same flags as dotrap, so simulate force_mintrap
by passing FORCETRAP flag.
2022-02-24 17:13:23 +02:00
Pasi Kallinen
5786ddadbb Use IS_WATERWALL and is_waterwall 2022-02-23 12:53:09 +02:00
Kestrel Gregorich-Trevor
355ed43a29 pull request #660 from NullCGT - sleeping monsters
Indicate to players that monsters are sleeping.

Closes #660
2022-02-22 11:36:40 -08:00
Pasi Kallinen
33556788c3 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.
2022-02-22 12:26:06 +02:00
Pasi Kallinen
4a61602436 Illiterate hero will learn spells directly from deity
... instead of receiving a spellbook.
2022-02-20 22:05:33 +02:00
Pasi Kallinen
038ae7f984 Clean up some spell-related code
Add two helper functions and use those outside of spell.c,
instead of iterating through all the spells.
2022-02-20 21:12:26 +02:00
Pasi Kallinen
26ea5824c1 Reading a magic marker shows the specific red ink color 2022-02-19 13:11:24 +02:00
Pasi Kallinen
122634ec9e Hallucinatory rays
When hallucinating, use nonsensical names for the rays
(wands, spells, and breath weapons), and random ray glyphs.

Original code from xNetHack by copperwater <aosdict@gmail.com>,
inspired by a YANI by Kahran042.
2022-02-16 21:09:23 +02:00
Pasi Kallinen
d958d032a0 Looting will fall through to force
If you have autounlock on, and don't have unlocking tool, but
are wielding a weapon usable for forcing the lock.
2022-02-16 08:49:16 +02:00
nhmall
a68cf63a05 another obsolete function reference 2022-02-15 08:16:21 -05:00
nhmall
c0a4b38bf6 remove obsolete function and references 2022-02-15 08:13:27 -05:00
Pasi Kallinen
73dbd39d98 Use proper locomotion when avoiding water or lava 2022-02-13 10:56:40 +02:00
PatR
3ea4b00879 memory management
MONITOR_HEAP+heaputil pointed out some unreleased memory.  The livelog
stuff wasn't being freed.  Not surpringly the data used for collecting
and formatting build-options that just got changed from strdup() to
dupstr() wasn't being freed.  And a couple of date/version bits.
2022-02-10 12:14:27 -08:00
PatR
96ba3c04d1 logging experience level changes again
The livelog message for losing a level had an off-by-1 error, showing
the level the hero ended up at rather than the level that was lost.

There was a message for regaining a previously lost level when rank
title stayed the same but no such message if the title changed (the
achievement of gaining a particular title only occurs once).

Say "regained" rather than "gained" when gaining a previously lost
level.  (Blessed potions of full healing regain levels but can also
reduce u.ulevelmax so a different way to remember peak experience
level has been added.)

Report level change due to polymorphing into new man/woman/elf/&c.
I hadn't realized that that hasn't been recording achievement for new
rank when applicable and decided to leave things that way.

Report gender change when putting on an amulet of change or becoming
a new man/&c unless hero is polymorphed at the time or experience
level is also changing.
2022-02-10 05:45:07 -08:00
Pasi Kallinen
1e90f89203 Chronicle of major events, and livelog
Log game events, such as entering a new dungeon level, breaking
a conduct, or killing a unique monster, in a new "Major events"
chronicle. The entries record the turn when the event happened.
The log can be viewed with #chronicle -command, and the entries
also show up in the end-of-game dump, if that is available.

This feature is on by default, but can be disabled by
defining NO_CHRONICLE compile-time option.

This also contains "live logging", writing the events as they
happen into a single livelog-file. This is mostly useful for
public servers. The livelog is off by default, and must be
compiled in with LIVELOG, and then turned on in sysconf.

Mostly this a version of livelogging from the Hardfought server,
with some changes.
2022-02-09 22:49:25 +02:00
PatR
b3c5d68399 fix movement prefixes
My earlier change resulted in rejecting all commands entered after
a movement prefix key, rather than just ones that aren't supposed to
take any prefix.

This fixes that and also restores the ability to use 'm>' or 'm<' on
stairs to change levels without auto-pickup at the destination.
2022-02-06 17:46:31 -08:00
PatR
f233f1d18c water description
The wall of water goaded me into updating waterbody_name().  It's
mostly the same, aside from being moved from mkmaze.c to pager.c and
adding "{wall of|limitless} water" instead of plain "water" for WATER
terrain.  I'm not very happy with "limitless" for the Plane of Water
because limits imposed by air bubbles are all over the place.  "Wall
of water" might work ok for that level.

Water on Medusa's level is now described as "shallow sea" rather than
lame "water".  The two unusual pools on the Samurai home level are
described as "pond" rather than previous "water" which replaced 3.6's
ridiculous "moat".  When lava is hallucinated, it is described as
"molten <substance>" (yielding silly things like "molten yoghurt"),
rather than just "<substance>" to distinguish it from hallucinated
water.  'autodescribe' doesn't use waterbody_name() though.
2022-02-06 13:20:15 -08:00
PatR
e8341dc9d7 fix github issue #666 - cursed light vs worn light
Another gold dragon scales/mail issue, reported bu vultur-cadens:
reading a cursed scroll of light extinguishes carried light sources
except for wielded Sunsword and worn gold dragon scales/mail; there
was a special message for Sunsword (preventing the hero from being in
darkness) but no such message for gold dragon scales/mail.  Replace
the special message with a more generic one applicable to both cases.

Also, implement the suggestion that cursed light degrade the amount
of light being emitted (which varies by bless/curse state) for those
two cases.  Sunsword has a 75% chance to resist, gold dragon scales
25% chance.  And add the inverse:  blessed scroll of light might
increase the amount of light by improving their bless/curse state.
The resistance check applies here too and isn't inverted; Sunsword
is still fairly likely to resist.

Uncursed scroll of light, spell of light regardless of skill, zapped
or broken wand of light have so such effect.

Closes #666
2022-02-04 16:20:03 -08:00
Pasi Kallinen
218c0d4a3b Stinking clouds block line of sight
... you will also get a message when a seen stinking cloud
or the one surrounding the hero dissipates.

Original feature comes from Fourk, but this version (with some
minor changes) comes from xnethack by copperwater <aosdict@gmail.com>
2022-01-31 19:00:19 +02:00
Pasi Kallinen
a6816824c7 Lua: Pass more data to room contents function 2022-01-23 13:27:00 +02:00
Pasi Kallinen
9d64d135b8 Curses: fix extended command input
The extended command input prompt was behaving in an unintended way:
Typing #a<enter> executed #adjust. Spaces in the entry prevented matching
any command. No error message was given when no command was matched.

Fix all of those, so it behaves more like the tty.

Clean up the tty, curses, and X11 windowport code, so they don't use
the extcmdlist array directly, but query with extcmds_match
and extcmds_getentry.
2022-01-22 14:32:53 +02:00
PatR
6a72e48a40 fix rest_on_space
When rest_on_space is On, assign same function as for #wait to the
<space> key.  When Off, set that key to Null instead.  Binding some
other command to <space> when rest_on_space is Off doesn't work but
I would classify that as something to be discouraged anyway.
2022-01-21 15:51:05 -08:00
PatR
aab21eba95 blessed objects vs vulnerable creatures
Collect creatures that don't like being hit by blessed objects in one
place.  No change in behavior.
2022-01-21 13:19:57 -08:00
PatR
f420b9672f Qt: more '#' support
Add an entry for running an extended command to Qt's 'game' menu.
2022-01-17 14:38:16 -08:00
Pasi Kallinen
2e144e814d Change repeat into extended command 2022-01-17 17:13:59 +02:00
Pasi Kallinen
e7fa065203 Change special keys into extended commands
Changes most of the special keys used in the main input loop
into extended commands:

- movement keys are now bound to extended commands, eg.
  #movewest and so on.

- m-prefix is now #reqmenu extended command, still bound to
  the 'm' key.

- run, rush, and fight are now extended commands, still bound
  to the same keys as previously.

- nopickup and runnopickup keys are removed.
  Nopickup was using 'm' key, the same as the m-prefix, so
  allow #reqmenu to modify movement commands to disable pickup.

- multiple prefix commands are allowed. This lets user to
  use #reqmenu, followed by #run, followed by movement to simulate
  runnopickup behaviour. (If necessary, adding runnopickup back
  as an extended command would be easy)
2022-01-16 14:48:24 +02:00
Pasi Kallinen
1f2d16082e Fix shopkeeper Kop summons causing segfault
... if it happened on a level with no downstairs, such as the tourist quest.
2022-01-11 22:55:43 +02:00