Commit Graph

2938 Commits

Author SHA1 Message Date
Ray Chason
5eaa162c82 Define and use PRINTF_F_PTR
GCCs older than 3.1 understand __attribute__(printf(...)), but only
with functions; it doesn't work with function pointers. This change
uses PRINTF_F_PTR to remove the attribute from two function pointers.

This change establishes GCC 3.0 as the minimum version to build
NetHack. Older versions have trouble with the variadic macros and
variable declarations in mid-block.
2022-11-03 19:33:30 -04:00
PatR
52511cd329 comment thinko 2022-11-01 09:29:19 -07:00
PatR
1572877429 build fix for NODUMPENUMS and more issue #916
I made more things in dump_enums() static and/or const.  In the
process I discovered both compile problems for NODUMPENUMS and when
fixed, link problems for NODUMPENUMS+ENHANCED_SYMBOLS.

The uft8map.c portion has no changes, just reformatting.
2022-10-31 15:43:14 -07:00
PatR
220726f7ba status condition options
Option parsing rejected
|OPTIONS=!cond_X
for all valid X.

Using the menu to unselect all condition options treated that as not
having made any choice and didn't make any changes.  That would be
reasonable if nothing was preselected, but things are so unselecting
all of them is a choice.  (A bizarre one, but still should be viable.)

Mostly this deals with including cond_X options when #saveoptions is
used to write a new RC file.  It now produces something like
|OPTIONS=!cond_barehanded,cond_blind,!cond_busy,cond_conf,!cond_deaf,\
|        cond_iron,cond_fly,cond_foodPois,!cond_glowhands,cond_grab,\
|        cond_hallucinat,!cond_held,!cond_ice,cond_lava,cond_levitate,\
|        !cond_paralyzed,cond_ride,!cond_sleep,cond_slime,!cond_slip,\
|        cond_stone,cond_strngl,cond_stun,!cond_submerged,cond_termIll,\
|        !cond_tethered,!cond_trap,!cond_unconscious,!cond_woundedlegs,\
|        !cond_holding
after the last alphabetical option and before the bound keys, menu
colors, and others which aren't simple OPTIONS=X settings.  This only
happens if there is already one or more OPTIONS=cond_X entries in the
old file when it was read or if 'mO' gets used to make any changes.

Not fixed:  after my RC had something similar to the above and before
I changed status conditions to accept negation, I was getting several
"the cond_ option may not both have a value and be negated" messages
written to stdout instead of the config file error handler.  So they
vanished when the screen was initialized without providing a --More--
prompt to acknowledge that they have been seen.
2022-10-31 00:53:10 -07:00
nhmall
ad23b4e8e1 grammar: "foo based" to "foo-based"
There seems to be a need to locate these in the distribution every decade or so.
2022-10-30 16:08:14 -04:00
nhmall
99a93fe50b some C99 changes
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.

If you want to try building on a platform that doesn't offer those
two functions, these are available:
    define NOT_C99       /* to make some non-C99 code available */
    define NEED_INDEX    /* to define a macro for index()  */
    define NEED_RINDX    /* to define a macro for rindex() */
2022-10-29 10:54:25 -04:00
PatR
cec7da0505 another comment typo fix 2022-10-28 00:30:38 -07:00
PatR
69f62e5872 fix comment typo 2022-10-27 14:52:50 -07:00
nhmall
8c9d4de9ed Merge branch 'no-urace-in-is_foo' of https://github.com/entrez/NetHack into NetHack-3.7 2022-10-27 10:04:11 -04:00
Michael Meyer
580c5a6e99 Remove urace test from is_elf, etc, macros
Reverts 690e072, which changed the various is_foo macros from this:

| #define is_elf(ptr) ((((ptr)->mflags2 & M2_ELF) != 0L)

to this:

| #define is_elf(ptr) ((((ptr)->mflags2 & M2_ELF) != 0L)     \
|                      || ((ptr) == g.youmonst.data &&       \
|                          !Upolyd && Race_if(PM_ELF)))

This is a problem because g.youmonst.data is not unique to the hero:
the '(ptr) == g.youmonst.data' test will also be true of all player
monsters of the same role.  For this reason, any of those player
monsters will be treated as sharing the hero's race, producing strange
results.  For example, if the player is an elven ranger, any ranger
player monster generated will be considered 'elven' too (so will get a
to-hit bonus when attacking orcs, etc) -- but only while the hero is
unpolymorphed.

There are already other ways of checking the hero's race in addition to
her current polyform, most notably the maybe_polyd() macro.  maybe_polyd
or something similar is already used in nearly all the cases where the
hero's race is being evaluated, meaning Race_if gets used instead when
the hero is in her natural form.  So I think the check of the hero's
race in is_foo had very little effect except for the unintended
side-effects on player monsters.

In reviewing all the uses of is_{elf,dwarf,gnome,orc,human}, I noticed
only one case that relied on the hero-race-checking behavior.  That has
been changed in this commit to use maybe_polyd (there's another 'raw'
is_human(g.youmonst.data) a few lines down, but it doesn't need
maybe_polyd since it already distinguishes between 'hero in nonhuman
polyform' vs 'nonpolyd or human polyform').  same_race(mondata.c) is
another case where &g.youmonst.data can be passed to is_foo, but
everywhere that calls it for the hero also calls your_race() or
same_race(&mons[Race_switch]) to handle the racial case.
2022-10-27 09:53:33 -04:00
nhmall
116f80e8f5 config.h band should have been left off prev 2022-10-26 14:28:29 -04:00
nhmall
88f6df2d8b some tabs to spaces
cd src
    grep -P -n '\t' *.c | grep -v "1:"
    cd ../include
    grep -P -n '\t' *.h | grep -v "1:"
    cd ..

side note: win/Qt/*.cpp are full of tabs
2022-10-26 14:21:23 -04:00
Michael Meyer
05f004403e Rename update_mon_intrinsics to ...extrinsics
There was a TODO about this; not exactly a great challenge but it feels
like a worthwhile change since the name was misleading.  I also updated
the name of the do_intrinsics parameter of extract_from_minvent(worn.c),
since it was in a similar situation (and directly related, since it
controls whether to call update_mon_{in/ex}trinsics).
2022-10-23 00:21:44 -07:00
PatR
84fabf764a allow big humanoids to wear mummy wrappings
A giant mummy starts out with a mummy wrapping but couldn't wear it.
Allow humanoids who are bigger than human size (including poly'd hero
when applicable) to wear such cloaks.  They won't do so if they are
invisible and the cloak would let hero start seeing them.
2022-10-22 17:14:22 -07:00
PatR
f1e2c393f2 cansee() and couldsee()
cansee(), couldsee(), and templit() are macros which are described
as boolean and used as if boolean, but they've been using bit
masking to return integer values greater than 1.  That works since
C treats any non-zero as True but doesn't match boolean intent.
2022-10-22 15:47:48 -07:00
PatR
5226c9633d fix github issue #905 - ^A vs getpos()
Reported by entrez:  using ^A instead of #retravel after interrupted
travel can pick wrong location if cursor was previously positioned
with movement commands rather than feature targeting because it
won't be starting from the original spot.  Also, ^A after ';' will
just redescribe whatever was examined previously instead of having
the player pick a new spot.

This suppresses cursor positioning from the do-again queue so that
repeating travel or quick-look or other command that needs player
to choose a position will repeat the command but then need to have
a position chosen.  For interrupted #travel, the cursor will already
be placed on the previous destination so that's relatively painless,
but also allows a different destination to be chosen.

It adds iflags.remember_getpos that callers of getpos() could set to
be able to restore the old behavior but none do so far.

Fixes #905
2022-10-20 10:27:21 -07:00
PatR
46f2903d43 missing EDITLEVEL update
The Elbereth fix changed 'struct engr' and should have included an
increment to EDITLEVEL to invalidate old save and bones files.
2022-10-15 06:22:18 -07:00
PatR
064c9fb52e fix github issue #900 - "Elbereth" engravings
Issue reported by vultur-cadens:  Elbereth used to be effective in
inhibiting monster movement when an object was present on the same
spot, but since 3.6.0 it isn't.  It only functions that way when the
hero--or hero's displaced image--is present these days.  So special
levels that have been using engraved Elbereth to try to protect
objects from monsters haven't been providing any useful protection.

This makes Elbereth that's engraved during level creation work like
it used to in 3.4.3 and earlier:  when there's at least one object
on the engraving's spot, monsters who are affected by Elbereth will
be affected.  [I'm fairly sure that that behavior started out
unintentionally, as a side-effect of an optimization to only check
for scroll of scare monster when there was at least one item present
which is a necessary condition for such a scroll.]

Old-style Elbereth includes Elbereth chosen as a random engraving
during level creation in addition to engravings specified in special
level definitions.  Engravings by the player don't have the required
attribute and player-engraved Elbereth behaves in the 3.6 way.

This ought to be replaced by something more general.  Perhaps a new
engraving type not usable by the player?

Fixes #900
2022-10-15 02:13:39 -07:00
PatR
2e981966d0 fix several monster difficulty ratings
Fix most of the things pointed out by #wizmondiff.

Weakening of placeholder 'elf' is due to recent removal of M2_STRONG
for it as part of the "orc strongmonst" changes.

I assume that the discrepancies for multiple quest leaders came about
as part of the change that allows killing the leader as an alternate
way to gain access to the lower levels of the quest, but didn't check.

I don't know what's up with 'piranha' but just changed it to match
generated value.

'{freezing,flaming,shocking} sphere' still show up as discrepancies
with hardcoded (mons[].difficulty) value higher than generated value.
They got harder when their explosion was beefed up, so the formula to
calculate difficulty ought to be updated to account for that.
2022-10-14 14:42:54 -07:00
PatR
45c39e108f more #saveoptions
Force windowtype to be the first option written to new RC file since
its value can affect how other options are processed.  (Only saved if
comes from existing RC file, not command line.)  doset() lists a few
compound options before the rest too.  Combine the two sets of want-
to-be-first and move the handling for that to optlist.h where the only
cost is that the options are no longer in alphabetical order.
2022-10-13 14:03:52 -07:00
PatR
02cfdfee30 more github issue #679 - orc strength
Handle alternate values for hero poly'd into a 'strongmonst' form
more thoroughly by propagating max values other than 18/100 to the
attribute manipulation routines.

ATTRMAX(A_STR), which used to be a relatively simple expression, now
contains a function call.

Along the way, change the races[] terminator's value for 'mnum' from
0 (giant ant) to NON_PM.
2022-10-12 02:05:32 -07:00
Michael Meyer
02367077bd Use function for combined str/hp loss from poison
Since losestr and losehp calls go together most of the time, this feels
like it probably makes more sense than repeating the killer name/format
twice in a row all over the place.
2022-10-08 16:29:56 -07:00
Michael Meyer
70fe2ce5cd Don't make callers responsible for losestr death
Remove callers' responsibility to deal with possible hero death when
calling losestr.  This is less fragile and error-prone than leaving it
in the caller's hands, but it means that death from the monster spell
'weaken target' no longer goes through done_in_by, and the death reason
is no longer "killed by <monster name>".
2022-10-08 16:29:55 -07:00
Michael Meyer
c0dfa40cd3 Don't use boolean for losehp killer format type
Killer format isn't a boolean, since it has 3 possible values
(KILLED_BY_AN, KILLED_BY, NO_KILLER_PREFIX).  It shouldn't make any
difference behind the scenes, but it's confusing to use 'boolean' for
it.
2022-10-08 16:29:55 -07:00
Michael Meyer
c78e7af013 Digestion attack can grant hero intrinsics
Monster purple worms can now gain intrinsics from swallowing foes whole,
so maybe the hero should be able to do so too.  Intrinsics aren't
granted immediately upon swallowing (that would probably have been
easier), but only once a corpse is created and then entirely digested.

I'm not sure if this is too powerful and was being avoided deliberately
for that reason, since it includes potential level gain from wraith
corpses in addition to other intrinsics.  That's consistent with monster
purple worms but may be a bit too much in the hands of the hero, though
it is limited by needing the corpse creation roll to succeed.
2022-10-08 16:06:50 -07:00
nhmall
334fd76ab4 mstrength prototype and preprocessor 2022-10-07 11:15:10 -04:00
nhmall
26d13f6656 just the one mstrength() for makedefs and game 2022-10-07 11:00:15 -04:00
nhmall
b0029472de during devel make it easy to review mon difficulty 2022-10-07 10:26:40 -04:00
PatR
01dea35a22 fix github issue #894 - guardian nagas can't grab
Issue reported by eakaye:  for a 'hugs' attack to succeed, the
monster must have at least three attacks and the two preceding the
hug attack need to both hit.  Guardian nagas had three attacks but
the first was melee 'bite' and the second was ranged 'spit'.  Those
are mutually exclusive, so they would never both hit and nagas never
grabbed their prey.

Make the spit attack be first, the bite attack be second, insert a
touch attack for 0 damage third, and make the hug be fourth.  Also,
change their hug damage type from 'phys' to 'wrap'.  The first and
2nd+3rd+4th are still mutually exclusive.

The resulting message feedback left something to be desired and has
been tweaked.

The difficulty-level formula used by deprecated 'makedefs -m' now
generates 17 rather than 16 for guardian naga so I changed revised
monster to match.  They are definitely more difficult now that their
constriction attack has a chance to hit.

Fixes #894
2022-10-07 01:07:43 -07:00
nhmall
08163e94bb Merge branch 'unicode' of https://github.com/chasonr/NetHack into pr889 2022-10-06 12:31:21 -04:00
nhmall
13028143af latest Xcode build issue
An Xcode update has started causing the same problem that was experienced on
Linux with newer compiler or glibc a while back.

˜
In file included from monst.c:6:
In file included from ../include/config.h:670:
In file included from ../include/integer.h:54:
In file included from /Applications/Xcode_14.0.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include/stdint.h:52:
In file included from /Applications/Xcode_14.0.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h:52:
In file included from /Applications/Xcode_14.0.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h:32:
/Applications/Xcode_14.0.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:302:39: error: too few arguments provided to function-like macro invocation
^
1 error generated.
make[1]: *** [monst.o] Error 1

 Please enter the commit message for your changes. Lines starting
2022-10-04 19:09:54 -04:00
PatR
546fea7db8 getting knocked off flying steed
I was trying to reproduce the reported "no monster to remove" warning
from remove_monster() when a mounted hero was knocked off jabberwocky
steed but so far haven't been able to.

While trying, I came across a more minor bug.  The hero got knocked
off a flying steed and got feedback of "you fly off" rather than
"you fall off".  Flying capability came from the steed and dismount
feedback is aware of that but calls u_locomotion() which isn't.  This
commit fixes that.

This adds some groundwork (DISMOUNT_KNOCKED) for better dismount
control.  With a map fragment of
|....
|.Du.
|....
I got knocked off my steed by the attacking dragon and ended up with
|..@.
|.Du.
|....
It would be better to prefer spot 1, then the 2s, then 3s, then 4s
(not sure about farther spots if none of those are available)
|.432
|.D@1
|.432
when forced to dismount by knockback.  This does _not_ implement that.
2022-10-03 15:53:35 -07:00
Ray Chason
8b6fe9d205 Support wide Curses on MS-DOS
Also, fix IBMGraphics on Curses
2022-10-02 20:41:02 -04:00
PatR
b6a3d4b984 fix github issue #679 - orc strength
Reported by eakaye:  orcish hero has maximum strength of 18/50 but
hero poly'd into an orc was given 18/100 strength.  Also, a comment
from vultur-cadens pointed out that orcish heroes start with poison
resistance while monster orcs lack it.

Even though the boost to 18/100 is only temporary until the poly
times out, make orcs a special case where strongmonst from poly'ing
into them only gives 18/50 strength instead of 18/100.  Adopt the
suggestion that Uruk-hai be an exception and continue to give hero
poly'd into them 18/100.

If any gnome becomes strongmonst (currently none are), treat them
as 18/50 too.  Elvenking and elf-lord are strongmonst; treat their
forms as plain 18 though, matching the limit of elf heroes.  Lesser
monster elves aren't strongmost.

While in there, add another special case so that hero poly'd into a
giant gets 19 strength.  Monster giants are still plain strongmonst
so might warrant some sort of adjustment.

Give orcs poison resistance, but eating their corpses doesn't provide
an opportunity to confer it.  Note goblins and hobgoblins still don't
have the resistance (to distinguish them from orcs a bit).

Take away strongmonst from orc shamans and give it to orc mummies.
Human mummies should have it too (at least according to movies) but
I didn't alter them becuase they're already pretty dangerous at the
point they start occurring.  Take away strongmonst from plain 'elf'
placeholder.

New:  when hero polymorphs into a form that lacks the strongmonst
attribute, take away any exceptional strength (drop 18/01 through
18/100 down to 18; as mentioned above, the drop is only temporary).
There's no attempt to set the maximum even lower for wimpy forms.

Fixes #679
2022-10-01 18:14:59 -07:00
Michael Meyer
d1f4e7df85 Fix: IS_SUBROOM_INDEX range
The macro (currently unused, I think) for checking whether a particular
index designates a subroom was off by one on the maximum allowable
value.

Because of the dedicated extra space for the g.rooms array terminator
flag (hx == -1), subroom indices in g.rooms are set out in the range
[MAXNROFROOMS+1, MAXNROFROOMS*2], inclusive.

Also some minor formatting tweaks.
2022-09-28 14:11:05 -07:00
PatR
8509951291 rename "huge chunk of meat" to "enormous meatball"
Pull request #607 by Vivit-R proposed renaming "huge chunk of meat"
to "giant meatball" to better reflect the similarity to meatball.
But an object name that contains a monster name prefix requires extra
work in the wishing code.  I considered "huge meatball" which retains
more of the original name but decided to go with "enormous meatball"
becaues it seems more evocative.

Supersedes #607
Closes #607
2022-09-27 13:32:51 -07:00
PatR
a9436f1311 __attribute__(returns_nonnull)
Refine commit 4885653014.

> I'm not sure whether gcc 3 is really the right test for whether the
> returns_nonnull attribute setting is available.

The gcc.gnu.org website only goes back to 5.1, and searching the
documentation of that version for returns_nonnull finds it.  I used
ftp to get gcc-core-3.0.0 and gcc-core-4.0.0 and their doc files don't
mention this attribute.  It might have been added for some later 4.x
but that really doesn't matter for nethack's purposes.

Use __GNUC__ >= 5 instead of __GNUC__ >= 3 when testing whether
__attribute__(returns_nonnull) is available.
2022-09-26 15:49:42 -07:00
PatR
0735b790f9 object name assignment vs persistent inventory
This is an alternate way to deal with pull request #876, where
splitting a stack that has a name assigned updated perm_invent when
cloning the name and ran into trouble with shop billing when trying
to format for persistent inventory display.

The PR#876 fix has been left in place but wouldn't have been needed
if this had gone in first.
2022-09-26 14:25:06 -07:00
PatR
4885653014 alloc() never returns Null
Mark alloc()--also dupstr() and re_alloc()--for gcc and clang as
always returning non-Null.  This should silence some of the static
analysis complaints.

Almost all the monster and object naming functions (anything that
returns an mbuf or an obuf) should be marked this way too but I'll
leave that for somebody else to deal with.

I didn't attempt to mark alloc() with the 'malloc' attribute because
macro definitions could end up causing trouble.  Specifying its
deallocator would probably be useful but is at even bigger risk of
macro interference.

I'm not sure whether gcc 3 is really the right test for whether the
returns_nonnull attribute setting is available.
2022-09-24 04:39:12 -07:00
Pasi Kallinen
ef093d0b30 Fix curses cursor keys
My change to allow fuzzer run in curses caused the cursor keys
to not work (eg. paging through menus with left and right cursor),
so fix that.
2022-09-24 10:40:38 +03:00
Michael Meyer
81285b661e Apply dest. limit to monster trap door usage
To prevent monsters from falling past the bottom level or into the
sanctum early, and to maintain consistency between monster and hero hole
usage.
2022-09-22 11:36:48 +03:00
Michael Meyer
f8ec9dc32e Fix: antigravity trap doors
Trap doors saved their destinations as an absolute level, rather than a
relative one, so if you loaded bones from a special level their
destinations would reflect the dungeon layout from the bones player's
game.  For example, die on the Oracle level, on dlvl5, with a trap door
that goes to dlvl6.  Another player gets those bones on their Oracle
level, which is dlvl8... the trap door would still go to dlvl6.  Pretty
amazing trap door -- something you might see in a funhouse!

Include relative rather than absolute destinations in save and bones
files, much like stairs do, to avoid this problem.

I bumped EDITLEVEL because although this won't break save files in an
obvious way, it will interpret the (absolute) destinations in existing
save and bones files as relative, leading to some crazy long falls. :)
2022-09-22 11:36:47 +03:00
Michael Meyer
34aabca74b Describe engulf attacks a bit more consistently
Use verbiage for mon vs mon and hero (mostly hero) engulf attacks that
matches recent changes to monster vs hero engulf attacks more closely
(e.g. "swallows whole" instead of "engulfs" for purple worm, other
changes in b07fe59...).  Also ensure non-AD_DGST engulf attacks
(e.g. from revamped trapper or lurker above polyforms) aren't treated as
"eating" (or as involving "debris").

Also change the enfolds and digests macros so they produce booleans
rather than attack pointers (I got a compiler warning about casting
struct attack * to boolean when I did 'boolean b = digests(ptr);').
2022-09-20 16:54:23 -07:00
PatR
a4f7bf2101 tradstdc.h, USE_STDARG
Make USE_STDARG explicitly the default (it was implicitly the default
when NHSTDC is defined) and update some comments related to VA_DECL.
2022-09-16 15:02:23 -07:00
PatR
2b04cc9f5b fix issue #843 - vampire revival sequencing
Reported by Umbire:
|You kill SpaceMannSpiff!  SpaceMannSpiff puts on a dwarvish cloak.
|SpaceMannSpiff puts on a dwarvish iron helm.
|The seemingly dead SpaceMannSpiff suddenly transforms and rises as
| a Vampire.

This was tough to reproduce but I finally managed it.  The issue
text mentions that it was fixed by copperwater in xNetHack with
commit 8c4af50f0aa3e72522f3eb98df039ff25c2a1ea0 to the repository
for that variant.  My attempt to cherry-pick that failed--I'm not
even sure whether it should have been expected to work--and some of
the code has been impinged upon by changes, so I ended up applying
the contents of that commit manually.

The commit changes how/when monsters put on new armor rather than
anything directly related to vampires.  Circumstances similar to
the example above now yield:
|You kill SpaceMannSpiff!
|The seemingly dead SpaceMannSpiff suddenly transforms and rises as
| a Vampire.
on one turn, then on the next turn the revived vampire produces:
|SpaceMannSpiff puts on a dwarvish cloak.

My test case only had one item of interest; I assume that the second
item of armor gets worn on a subsequent turn rather than at the same
time as the first one.

Fixes #843
2022-09-15 18:02:07 -07:00
PatR
6353bddaf6 obj.h mixup
\#if 0 should have been #if 1.  Swap #then and #else instead.
2022-09-15 14:17:43 -07:00
PatR
aa8f73c890 empty horn of plenty
Format a horn of plenty whose charge count is unknown but is known to
be empty as "empty horn of plenty" like is done for real containers.

This was too easy; I must have missed something....
2022-09-15 14:14:12 -07:00
Pasi Kallinen
3605f18a8e Split themeroom shape from themeroom contents
Previously, the tetris-shaped rooms were always either
normal rooms, or turned into shops or other special rooms
in NetHack core. Now, the themed room lua code first picks
the themed room (which can be a themed or shaped), and some
of those will then pick a random filling (eg. ice floor,
traps, corpses, 3 altars).

Adds a new lua binding to create a selection picking locations
in current room.

The content-function in special level regions now get passed
the room data as a parameter.
2022-09-15 18:09:40 +03:00
PatR
c2a9343367 horn_of_plenty-to-container #tip
For tipping purposes, a horn of plenty is treated like a container.
But using one as the source container in a container-to-container tip
wasn't supported.  Implement that.

Also, #tip was offering carried bags of tricks as candidate containers
to tip some other carried container into.  Only do that for ones which
aren't known to be bags of tricks (so when type not discovered yet, or
specific bag not seen yet due to blindness).
2022-09-14 15:54:24 -07:00
PatR
a1e83d1d3a forward declarations for struct monst, struct obj
This should eliminate the 'onefile' complaint for objects.c without
breaking anything with any standard conforming compiler.  (Fingers
crossed.)
2022-09-13 10:27:53 -07:00