home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume14
/
umoria4
/
part15
< prev
next >
Wrap
Internet Message Format
|
1992-08-31
|
58KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v14i047: umoria4 - single player dungeon simulation (ver. 5.5), Part15/39
Message-ID: <3405@master.CNA.TEK.COM>
Date: 20 Aug 92 18:04:57 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1703
Approved: billr@saab.CNA.TEK.COM
Submitted-by: grabiner@math.harvard.edu (David Grabiner)
Posting-number: Volume 14, Issue 47
Archive-name: umoria4/Part15
Supersedes: umoria3: Volume 9, Issue 55-97; Volume 10, Issue 15-17
Environment: Curses, Unix, Mac, MS-DOS, Atari-ST, Amiga, VMS
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 15 (of 39)."
# Contents: misc/README misc/mail.msg source/moria4.c
# Wrapped by billr@saab on Thu Aug 20 09:11:29 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'misc/README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'misc/README'\"
else
echo shar: Extracting \"'misc/README'\" \(489 characters\)
sed "s/^X//" >'misc/README' <<'END_OF_FILE'
Xstuff that isn't part of Umoria, but would be nice if it was
X
Xfunckeys.h, funckeys.c, mabbrev are (mama) Liz's code for handling SUN keypads
X
Xshading is joseph n hall's ideas on how to efficiently calculate multiple
Xlines of sight
X
Xhaggle.sug, moria.msg, and mail.msg are some interesting mail messages
Xabout moria which suggest changes or additions
X
Xrick.msg is a mail message from the author of VMS Moria 6.0, which lists
Xthe changes he was working on, VMS Moria 6.0 seems to be defunct
END_OF_FILE
if test 489 -ne `wc -c <'misc/README'`; then
echo shar: \"'misc/README'\" unpacked with wrong size!
fi
# end of 'misc/README'
fi
if test -f 'misc/mail.msg' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'misc/mail.msg'\"
else
echo shar: Extracting \"'misc/mail.msg'\" \(21386 characters\)
sed "s/^X//" >'misc/mail.msg' <<'END_OF_FILE'
XFrom afc@klaatu.cc.purdue.edu Tue Jan 16 13:33:16 1990
XReceived: from klaatu.cc.purdue.edu by ernie.Berkeley.EDU (5.61/1.36)
X id AA09793; Tue, 16 Jan 90 13:33:09 -0800
XReceived: by klaatu.cc.purdue.edu (5.61/1.14)
X id AA01432; Tue, 16 Jan 90 16:32:51 -0500
XDate: Tue, 16 Jan 90 16:32:51 -0500
XFrom: afc@klaatu.cc.purdue.edu (Greg Flint)
XMessage-Id: <9001162132.AA01432@klaatu.cc.purdue.edu>
XTo: wilson@ernie.Berkeley.EDU
XSubject: Some comments about PC Moria 4.873 aimed toward your Moria 5.0
XStatus: RO
X
XYou comment that Umoria 5.0 will have good balance because it will be
Xplayer tested before its release. I'd be willing to volunteer to do
Xsome of this beta testing. I don't have lots of time to play but I find
Xmoria to be a good way to unwind after a long day fighting more mundane
Xmosters such as Vaxes, Cybers and Suns.
X
XA few opinions about PC Moria 4.873 that might influence Umoria 5.0:
X
X STATS
X -----
X * Once stats get to the 18/xx stage, I find that I can deal with almost
X anything non-hastened (except for MHD's and Green d/D's) because by then
X my HP's are usually quite high. I can just hack away and usually come
X out on top. If I have sufficient haste self, I tackle V's and L's. If
X I don't, I phase door, teleport away or run for the stairs. (The method
X depends on my character type, distance from the monster and equipment at
X hand.)
X
X * After I reach the 18/xx stage, the game degenerates in to a sequence of
X 1) attack until I loose life levels,
X 2) WOR to store level,
X 3) buy more WOR and RLL, if available,
X 4) kill time on level 1 if no RLL, then back to #3
X 5) WOR back to deepest level,
X 6) go to #1".
X until I'm finally ready to go to level 50 of the dungeon.
X
X
X MONSTERS
X --------
X
X * It seems to take "forever" to go up the levels of 32+ because there is a
X big disparity between the value of monsters and the amount of points needed
X to rise to the next level. I find myself looking for D's (and L's if I've
X the proper abilities and/or tools) and being bored by almost anything else
X -- and yet I'm not yet ready for Iggy or the big "B".
X
X
X MAGIC
X -----
X * Maybe I've been lucky, but I've always been able to find some "see
X invisible" item early (about Banshee dungeon level). This makes G's, L's,
X etc a lot easier (see the earlier comment on my playing sequence.)
X
X * When playing as a mage and reaching about level 29 where I gain fire ball,
X I find that I've reached the peak in spells. Of the two spells after that,
X I've never used WOD and find Genocide so powerful that it seems like
X cheating.
X
X
X STORES and MONEY
X ----------------
X
X * Money is an issue early, but once I get to about 10,000, I never need to
X worry about money again -- for two reasons. The scrolls, potions, staves
X and the like are cheap (relative to 10K gold). The weapons that are HA,
X DF, etc almost never appear so even though they are expensive, I never
X seem to need the money.
X
X * It would be nice to know how may of a given item are in a store. This
X would help with questions such as "should I buy now or wait and chance
X that it (they?) are gone next time?" or "can I buy him out in the hopes
X of getting better stock next time?".
X
X
X MAGE SPELLS
X -----------
X
X * The two recharge and the three sleep spells seem redundant (especially
X the latter). I usually ignore the Level I recharge and Levels I and II
X sleep spells because I need more offensive weaponry (spells). By the time
X I get around to learning these low level spells (because I've moved up
X a mage level and you've got to pick something), I really don't need them.
X
X * I don't know what I'd suggest, but I'd like to see some other spells in
X place of the ones listed above -- especially some after level 29.
X
X * How about spells being fixed in terms of there letter? Nothing is more
X painful than forgetting that I've added spell "b" thereby making spell "e"
X spell "f" and wasting a bunch of mana and maybe allowing a monster a free
X hit.
X
X
X MAP
X ---
X
X * I find the reduced map a help in speeding up the game. I favor anything
X that speeds up the game at no penalty me. (For example, using "H" to
X "run" in place of lots of h's is a no cost plus. I would not want to be
X penalized for "running" since all I'm doing is speeding up the game, not
X trying to "tire out" the character.)
X
X------------------------------------------------------------------------------
XGreg Flint Math G-169 (317) 494-1787 UUCP: purdue!klaatu.cc!afc
X Purdue Univ. Purdue University INTERNET: afc@klaatu.cc.purdue.edu
X Computing Ctr. West Lafayette, IN 47907 BITNET: flint@purccvm.bitnet
X
XFrom qqc@h.cc.purdue.edu Thu Jan 18 13:54:52 1990
XReceived: from h.cc.purdue.edu by ernie.Berkeley.EDU (5.61/1.36)
X id AA09437; Thu, 18 Jan 90 13:54:47 -0800
XReceived: by h.cc.purdue.edu (5.61/1.14)
X id AA15380; Thu, 18 Jan 90 16:54:08 -0500
XDate: Thu, 18 Jan 90 16:54:08 -0500
XFrom: qqc@h.cc.purdue.edu (Dale Forsyth)
XMessage-Id: <9001182154.AA15380@h.cc.purdue.edu>
XTo: wilson@ernie.Berkeley.EDU
XSubject: program comments
XStatus: RO
X
X
XJim Wilson: As I perceive you as the author/programmer now associated
Xwith moria, I have several comments to make, in light of messages you have
Xposted in the past about the program. I use the ibm-pc version 4.873, but
Xexpect my comments apply universally. All the following is, of course, only
Xone person's opinion.
X I'm almost ashamed to admit how much I've used the program -- suffice to
Xsay I consider myself VERY experienced. I think I could win with ANY
Xcharacter, but I would not have the patience to do so.
X I consider the ONLY reason to use the program is for my own enjoyment.
XAny cheating I do is only to myself, for myself, and affects no one else; of
Xcourse mine isn't a multi-user machine, for which you are concerned.
X In my opinion, a mage is a reasonable and fun character. I don't think it
Xshould be necessary to change it's balance. A priest (current character) is
Xok EXCEPT that it needs an identify spell. Either that or the shops MUST keep
Xidentify spells stocked. Since they do not in my version, I would quit this
Xcharacter as NOT FUN anymore, except that I use wizard mode and cheat on this
Xpoint.
X I do NOT consider the 'triangle dance' around monsters a bad thing. I think
Xthere SHOULD be a way to outdo monsters that are bigger and badder than you,
Xif you have patience.
X The shops is an area that needs improvement; they should contain better and
Xbetter things as one's level increases. After a while there becomes NO REASON
Xto return topside and accumulation of gold becomes moot. It would stay more
XFUN if you could BUY that HA weapon, even at 300,000 gp, when you have only
X175,000 gp. But really good stuff never appears in MY shops.
X Endless repetition of mundane tactics that you know, waiting for something
Xyou NEED, is NOT FUN. A little is ok, month's of my life that way is NOT FUN.
X Characters beyond the BALROG would be possible, as for example Mordred from
XMordor (Lord of the Rings), the Ring Wraiths, etc. I think reincarnation,
Xperhaps with some penalty, would be I think reasonable. (Me, I cheat with
Xbackups, to learn, try things that if I knew I couldn't get back I just
Xwouldn't do, and therefore wouldn't have that particular fun, etc).
X If one thing is over-powerful, it's perhaps bashing for good characters.
XWhen I am REALLY ready to take on the balrog, (not try it for FUN with a worse
Xcharacter), I accomplish his demise, fully loaded with mana, equipment, etc,
Xnone of which I need or use, and he dies without ever touching me. Of course
Xthis takes searching for months for enough speed, but bashing is the secret
X(as I know you know) and reduces the game to trivial at that point. (3 AMHD's
Xat one time, all always stunned, none ever hurting you; that's an example).
X
X My main points in this letter are Priests and others need Identify or stores
Xmust keep scrolls, to be fun, and stores should stock better, more expensive
Xthings as one progresses.
X Thanks for maintaining such a good program, one of the most
X addictive I know.
XDale Forsyth (45 yr-old game addict) qqc@h.cc.purdue.edu
X
XFrom ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!yale!cs.yale.edu
XStatus: RO
X
XArticle 4187 of rec.games.moria:
XPath: ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!yale!cs.yale.edu!
X>From: berman-andrew@CS.Yale.EDU (Andrew Berman)
XNewsgroups: rec.games.moria
XSubject: Possible Enhancements
XMessage-ID: <12615@cs.yale.edu>
XDate: 24 Jan 90 03:52:46 GMT
XSender: news@cs.yale.edu
XReply-To: berman-andrew@CS.Yale.EDU (Andrew Berman)
XOrganization: Yale University Computer Science Dept, New Haven CT 06520-2158
XLines: 47
X
X
XI've been playing moria off and on for several years, only recently with
Xversion 4.87. I have some suggestions which I'd like input on. Most of
Xthem would make the game *harder*, but would also increase the power
Xand attractiveness of some classes, like the fighter, which don't get
Xused as often.
X
XThe first suggestion is to give fighters limited poison
Ximmunity. Let them take a % damage which diminishes with their level,
Xup to, say 1/2 damage for a level 39 character. So they won't get
Xblown away like other characters by AMHD. They have enough problems
Xas it is. And it's somewhat consistent- a fighters training may
Xinclude ducking blasts, holding their breath, keeping their skin from
Xbeing exposed, etc...
X
XThe second suggestion is to limit the power of the "cure poison" *spell*
Xof the mages and priests. Right now, you can fight a black mamba and
Xkill it without looking at your stats, because a simple relatively low
Xlevel spell will eliminate any future problems. Keep the potion as
Xcurrently powered, though.
X
X
X
XThe third suggestion is to limit weapons and Armor based on character class,
Xlike in D & D. I see no reason to allow a Priest full use of an Executioner's
Xsword, no matter what his/her strength/dex. If a Priest uses an edged
Xweapon, have some sort of minus. If a Mage tries to cast a spell through
XPlate Armor, decrease chance of success. If a Rogue uses a dagger, give
Xa +3 to hit bonus. Fighters and Paladins can use anything. Rangers get
Xdouble damage with bows. Something like that.
X
XMy fourth suggestion is to limit max stats based on character race and
Xmaybe on character class.
X
XThe point of the previous two suggestions is to eliminate the
Xdemigodlike character, a 250 hitpoint, 4-hits-per-round-with-a-Beaked-Axe,
Xarmor class of 58 character elven mage.
X
XMy fifth suggestion is to allow "disenchanting" creatures to occasionally
Xzap an ego weapon, low probability, but maybe "you hear your longsword scream
Xin agony" as it goes from an HA to zip.
X
XMy sixth suggestion is to give critical hits to monsters. Let a Bezerker
Xoccasionally get a good one in for triple damage. Let a touch have
Xa 5% chance of being a grasp for double drain..
X
XAny comments?
X
X
XFrom ucbvax!decwrl!lll-winken!uwm.edu!cs.utexas.edu!tut.cis.ohio-state.edu
XStatus: RO
X
XArticle 4188 of rec.games.moria:
XPath: ucbvax!decwrl!lll-winken!uwm.edu!cs.utexas.edu!tut.cis.ohio-state.edu
X>From: mf2t+@andrew.cmu.edu (Matthew David Fletcher)
XNewsgroups: rec.games.moria
XSubject: Re: Possible Enhancements
XMessage-ID: <YZjHVGi00XM101NVNs@andrew.cmu.edu>
XDate: 24 Jan 90 05:08:34 GMT
XReferences: <12615@cs.yale.edu>
XOrganization: Carnegie Mellon, Pittsburgh, PA
XLines: 35
XIn-Reply-To: <12615@cs.yale.edu>
X
Xberman-andrew@CS.Yale.EDU (Andrew Berman) writes:
X
X>The first suggestion is to give fighters limited poison
X>immunity. Let them take a % damage which diminishes with their level,
X>up to, say 1/2 damage for a level 39 character. So they won't get
X>blown away like other characters by AMHD. They have enough problems
X>as it is. And it's somewhat consistent- a fighters training may
X>include ducking blasts, holding their breath, keeping their skin from
X>being exposed, etc...
X>
X>The second suggestion is to limit the power of the "cure poison" *spell*
X>of the mages and priests. Right now, you can fight a black mamba and
X>kill it without looking at your stats, because a simple relatively low
X>level spell will eliminate any future problems. Keep the potion as
X>currently powered, though.
X
XMy current character is a twenty third level half-troll warrior. The
Xonly time I've come close to dying while being poisoned was when the
XStone Giant came up and started pounding me half way through. Certain
Xraces are naturally suited to certain classes by virtue of their
Xbeginning stats.
X
XAre mages capable of casting spells while afraid. If so, a natural
Xresistance to fear would make it more even. A ghost almost killed me a
Xwhile ago, because I couldn't attack it.
X
X>My fifth suggestion is to allow "disenchanting" creatures to occasionally
X>zap an ego weapon, low probability, but maybe "you hear your longsword scream
X>in agony" as it goes from an HA to zip.
X
XThis could be rather expensive, considering the cost of all the computer
Xequipment that would be destroyed when a person's dagger (HA) (+8,+8)
Xgets zapped.
X
X Fletch
X
X
XFrom ucbvax!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!unix.cis.p
XStatus: RO
X
XArticle 4193 of rec.games.moria:
XPath: ucbvax!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!unix.cis.
X>From: dtate@unix.cis.pitt.edu (David M Tate)
XNewsgroups: rec.games.moria
XSubject: Re: Possible Enhancements
XMessage-ID: <21833@unix.cis.pitt.edu>
XDate: 24 Jan 90 17:00:57 GMT
XReferences: <12615@cs.yale.edu>
XReply-To: dtate@unix.cis.pitt.edu (David M Tate)
XOrganization: Univ. of Pittsburgh, Comp & Info Services
XLines: 35
X
XAndrew Berman lists a number of possible enhancements for later versions of
XMoria. Some of them, I think, bear serious consideration.
X
XIn particular, I think that the idea of distinguishing various character
Xclasses even more sharply is a good one. I agree wholeheartedly that the only
Xweapons usable by a priest should be mace/morningstar/hammer/club/flail types.
XNo one but a fighter, paladin, or ranger should be able to wield a 2-handed
Xsword or Executioner's Sword. No matter how strong a mage gets, he should not
Xbe able to fight effectively with anything heavy, nor able to cast spells
Xeffectively while wearing heavy armor.
X
XOne way to reduce the mage/ranger advantage would be to implement a "setup
Xcost" for the switch between magic mode and fighting mode: you can't cast a
Xspell in the round immediately following a slash/fire move. This makes some
Xsense, as one would in general have to "prepare" a spell before casting it.
XSimilarly, one would expect the act of praying to take some finite time.
X(For that matter,eating should take some time--a character interrupted while
Xeating would have the option of finishing the meal (while getting stomped) or
Xabandoning it (in which case the remainder is lost--trampled in battle, or
Xsome such).
X
XOne touch of realism that I would like to see is more more NPC's to pick up
Xthings. I know this can be done, because ghosts do it already. Can you
Xreally imagine a hobgoblin coming into a room and *not* picking up the gold
Xand gems? This would add the challenge of preserving items to the character.
X
XSimilarly, why can't you get your stolen gold back from a dead rogue? What
Xdid he do with it? Hide it? If you're a rogue yourself, you should be able
Xto (a) keep him from picking your pocket, and (b) find where he hid it.
X
XJust a few ramblings...
X
X--
X==============================================================================
X David M. Tate | "I do not know which to prefer: the beauty
X dtate@unix.cis.pitt.edu | of inflections, or the beauty of innuendoes;
X | the blackbird whistling, or just after..."
X
X
XFrom 73230.224@compuserve.com Tue Jan 30 11:46:30 1990
XReceived: from saqqara.cis.ohio-state.edu by ernie.Berkeley.EDU (5.61/1.36)
X id AA23367; Tue, 30 Jan 90 11:46:14 -0800
XReceived: by saqqara.cis.ohio-state.edu (5.61/4.891221)
X id AA09041; Tue, 30 Jan 90 14:45:48 -0500
XDate: 30 Jan 90 12:41:49 EST
XFrom: Curtis McCauley <73230.224@CompuServe.COM>
XTo: <wilson@ernie.Berkeley.EDU>
XSubject: Umoria 5.0.13 disks mailed
XMessage-Id: <"900130174148 73230.224 EHA20-1"@CompuServe.COM>
XStatus: RO
X
XTo: >INTERNET:wilson@ernie.Berkeley.EDU
XI mailed you the sources either Monday or Tuesday of last week. I can't
Xremember which day for sure. I used regular mail, so it may take some time.
XThe mailing required two diskettes, one for the source, the other for a
Xcompiled version of the game. Do you have access to MPW 3.0? You will need
Xit to compile. I don't think that THINK C could be used very easily in place
Xof MPW. I rely pretty heavily on the MPW environment to make the program.
X
XWhile I'm thinking about it, there are a couple of principles which, if
Xobserved in all parts of the code, would make the mac port easier and less
Xof a hack:
X
X1) Don't modify a variable which is initialized in its declaration (e.g.,
X"int foo_flag = TRUE"). I had to try to find all of these in order to make
Xthe game restartable.
X
X2) Don't rely on the value of a variable which is not initialized in its
Xdeclaration being zero. For example, get_panel() forces the panel to be
Xredrawn the first time it is called in the course of a game because
Xpanel_[row/col]_[min/max] are all zero. In the mac version, when the game is
Xrestarted, these variables have the values left over from the previous game.
XI do with them what I do with the variables which fall under 1 above: I keep
Xtheir "initialized" value in a resource and restore them each time a game is
Xrestarted.
X
X3) (This follows a fortiori from 1 above.) Don't modify a private variable
Xwhich is initialized in its declaration. These I had to move from the source
Xfiles in which they were declared to variables.c and externs.h in order to
Xmake them accessible for the routines which build the restart resource and
Xcopy the saved data when a new game is started.
X
XAdmittedly, there is some inconvience involved in following these rules. It's
Xa judgement call.
X
XThe version I have given you "hilights" the veins instead of using '%'. I
Xdidn't discover that you had given up on hilighting until after I had ported
Xio.c to allow it. So I figured I'd leave it in. I discovered after I had
Xsent you the game that this causes the map command to screw up because it
Xdoesn't know how to handle -'#'. What do you think? Remove the hilighting
Xcapability or fix the map command to handle it?
X
XYou might want to consider the possibility of having two mac file types for
Xsave files: one for living characters, another for dead characters' memories.
XThis way the two files will be distinguishable by their icons. (Perhaps a
Xtombstone as the latter type of icon.)
X
XDo we want to get a new application signature from Apple? I'd prefer not to,
Xbut there likely will be problems for people who try to keep the old version
Xaround on their disks. For example, I am not certain which program will come
Xup if the user double clicks on a save file from the finder when he has both
Xcopies of the game on his disk. Maybe this can be handled by simply telling
Xthe player to throw away his old version in the mac help text.
X
XI do not like the way the game "flows" at the end, particularly the standard
Xfile dialog which prompts for saving the player's memories. It seems kind of
Xintrusive. I do not know how things will change when the top ten is added.
XAlso, there is a problem with the prompt in this dialog box. In save_char() I
Xtry to say "Save your memories as:" instead of "Save the game as:" when I
Xthink the player has died or quit. This doesn't always work right. Sometimes
Xit says "memories" when it should say "game". This always happens when ^X is
Xused to save the game. I have fixed that problem since I sent you the source.
XAnother problem remains: I rely upon the variable death to decide which
Xprompt to choose. This will not work when the player quits the character.
XDeath is not set, yet only the memories will get saved, right? In the version
Xyou have, I have the two prompts switched in save_char(). So, you get the
X"memories" prompt when you quit and the "game" prompt when you are killed.
X
XFinally, do female dwarves really have beards? Ugh.
X
X-Curtis (73230.224@compuserve.com)
X
X
XFrom chinet!saj@gargoyle.uchicago.edu Mon Feb 5 23:29:25 1990
XReceived: from gargoyle.uchicago.edu by ernie.Berkeley.EDU (5.61/1.36)
X id AA00727; Mon, 5 Feb 90 23:29:21 -0800
XReceived: by gargoyle.uchicago.edu (5.59/1.14)
X id AA06383; Tue, 6 Feb 90 01:28:53 199
XReceived: by chinet.chi.il.us (/\=-/\ Smail3.1.18.1 #18.65)
X id <m0gvOff-0002kbC@chinet.chi.il.us>; Tue, 6 Feb 90 00:27 CST
XMessage-Id: <m0gvOff-0002kbC@chinet.chi.il.us>
XFrom: saj@chinet.chi.il.us (Stephen Jacobs)
XSubject: Source arrived today
XTo: ernie.Berkeley.EDU!wilson@gargoyle.uchicago.edu (James E. Wilson)
XDate: Tue, 6 Feb 90 0:27:26 CST
XIn-Reply-To: <9002020111.AA22413@ernie.Berkeley.EDU>; from "James E. Wilson"
XX-Mailer: ELM [version 2.2 PL16]
XStatus: RO
X
XThe source arrived today. Thanks. I've barely begun to scan it, but I'd
Xguess that there shouldn't be any special problems bringing it up on the
XST. One immediate suggestion: the Mark Williams C compiler defines the
Xmacro GEMDOS, and defines the macro __STDC__ to be 0. Using those as
Xconditions could make recognition of the situation automatic.
X
X Steve J.
X
X
END_OF_FILE
if test 21386 -ne `wc -c <'misc/mail.msg'`; then
echo shar: \"'misc/mail.msg'\" unpacked with wrong size!
fi
# end of 'misc/mail.msg'
fi
if test -f 'source/moria4.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source/moria4.c'\"
else
echo shar: Extracting \"'source/moria4.c'\" \(31210 characters\)
sed "s/^X//" >'source/moria4.c' <<'END_OF_FILE'
X/* source/moria4.c: misc code, mainly to handle player commands
X
X Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X#ifdef __TURBOC__
X#include <stdio.h>
X#include <stdlib.h>
X#endif
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X#include "externs.h"
X
X#ifdef USG
X#ifndef ATARIST_MWC
X#include <string.h>
X#endif
X#else
X#include <strings.h>
X#endif
X
X#include <ctype.h>
X
X
X#if defined(LINT_ARGS)
Xstatic int look_ray(int, int, int);
Xstatic int look_see(int, int, int *);
Xstatic void inven_throw(int, struct inven_type *);
Xstatic void facts(struct inven_type *, int *, int *, int *, int *);
Xstatic void drop_throw(int, int, struct inven_type *);
Xstatic void py_bash(int, int);
X#else
Xstatic int look_ray();
Xstatic int look_see();
X#endif
X
X
X/* Tunnels through rubble and walls -RAK- */
X/* Must take into account: secret doors, special tools */
Xvoid tunnel(dir)
Xint dir;
X{
X register int i, tabil;
X register cave_type *c_ptr;
X register inven_type *i_ptr;
X int y, x;
X monster_type *m_ptr;
X vtype out_val, m_name;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X if ((py.flags.confused > 0) && /* Confused? */
X (randint(4) > 1)) /* 75% random movement */
X dir = randint(9);
X y = char_row;
X x = char_col;
X (void) mmove(dir, &y, &x);
X
X c_ptr = &cave[y][x];
X /* Compute the digging ability of player; based on */
X /* strength, and type of tool used */
X tabil = py.stats.use_stat[A_STR];
X i_ptr = &inventory[INVEN_WIELD];
X
X /* Don't let the player tunnel somewhere illegal, this is necessary to
X prevent the player from getting a free attack by trying to tunnel
X somewhere where it has no effect. */
X if (c_ptr->fval < MIN_CAVE_WALL
X && (c_ptr->tptr == 0 || (t_list[c_ptr->tptr].tval != TV_RUBBLE
X && t_list[c_ptr->tptr].tval != TV_SECRET_DOOR)))
X {
X if (c_ptr->tptr == 0)
X {
X msg_print ("Tunnel through what? Empty air?!?");
X free_turn_flag = TRUE;
X }
X else
X {
X msg_print("You can't tunnel through that.");
X free_turn_flag = TRUE;
X }
X return;
X }
X
X if (c_ptr->cptr > 1)
X {
X m_ptr = &m_list[c_ptr->cptr];
X if (m_ptr->ml)
X (void) sprintf (m_name, "The %s", c_list[m_ptr->mptr].name);
X else
X (void) strcpy (m_name, "Something");
X (void) sprintf(out_val, "%s is in your way!", m_name);
X msg_print(out_val);
X
X /* let the player attack the creature */
X if (py.flags.afraid < 1)
X py_attack(y, x);
X else
X msg_print("You are too afraid!");
X }
X else if (i_ptr->tval != TV_NOTHING)
X {
X#ifdef ATARIST_MWC
X if ((holder = TR_TUNNEL) & i_ptr->flags)
X#else
X if (TR_TUNNEL & i_ptr->flags)
X#endif
X tabil += 25 + i_ptr->p1*50;
X else
X {
X tabil += (i_ptr->damage[0]*i_ptr->damage[1]) + i_ptr->tohit
X + i_ptr->todam;
X /* divide by two so that digging without shovel isn't too easy */
X tabil >>= 1;
X }
X
X /* If this weapon is too heavy for the player to wield properly, then
X also make it harder to dig with it. */
X
X if (weapon_heavy)
X {
X tabil += (py.stats.use_stat[A_STR] * 15) - i_ptr->weight;
X if (tabil < 0)
X tabil = 0;
X }
X
X /* Regular walls; Granite, magma intrusion, quartz vein */
X /* Don't forget the boundary walls, made of titanium (255)*/
X switch(c_ptr->fval)
X {
X case GRANITE_WALL:
X i = randint(1200) + 80;
X if (twall(y, x, tabil, i))
X msg_print("You have finished the tunnel.");
X else
X count_msg_print("You tunnel into the granite wall.");
X break;
X case MAGMA_WALL:
X i = randint(600) + 10;
X if (twall(y, x, tabil, i))
X msg_print("You have finished the tunnel.");
X else
X count_msg_print("You tunnel into the magma intrusion.");
X break;
X case QUARTZ_WALL:
X i = randint(400) + 10;
X if (twall(y, x, tabil, i))
X msg_print("You have finished the tunnel.");
X else
X count_msg_print("You tunnel into the quartz vein.");
X break;
X case BOUNDARY_WALL:
X msg_print("This seems to be permanent rock.");
X break;
X default:
X /* Is there an object in the way? (Rubble and secret doors)*/
X if (c_ptr->tptr != 0)
X {
X /* Rubble. */
X if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
X {
X if (tabil > randint(180))
X {
X (void) delete_object(y, x);
X msg_print("You have removed the rubble.");
X if (randint(10) == 1)
X {
X place_object(y, x);
X if (test_light(y, x))
X msg_print("You have found something!");
X }
X lite_spot(y, x);
X }
X else
X count_msg_print("You dig in the rubble.");
X }
X /* Secret doors.*/
X else if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
X {
X count_msg_print("You tunnel into the granite wall.");
X search(char_row, char_col, py.misc.srh);
X }
X else
X abort ();
X }
X else
X abort ();
X break;
X }
X }
X else
X msg_print("You dig with your hands, making no progress.");
X}
X
X
X/* Disarms a trap -RAK- */
Xvoid disarm_trap()
X{
X int y, x, level, tmp, dir, no_disarm;
X register int tot, i;
X register cave_type *c_ptr;
X register inven_type *i_ptr;
X monster_type *m_ptr;
X vtype m_name, out_val;
X
X y = char_row;
X x = char_col;
X if (get_dir(CNIL, &dir))
X {
X (void) mmove(dir, &y, &x);
X c_ptr = &cave[y][x];
X no_disarm = FALSE;
X if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
X (t_list[c_ptr->tptr].tval == TV_VIS_TRAP
X || t_list[c_ptr->tptr].tval == TV_CHEST))
X {
X m_ptr = &m_list[c_ptr->cptr];
X if (m_ptr->ml)
X (void) sprintf (m_name, "The %s", c_list[m_ptr->mptr].name);
X else
X (void) strcpy (m_name, "Something");
X (void) sprintf(out_val, "%s is in your way!", m_name);
X msg_print(out_val);
X }
X else if (c_ptr->tptr != 0)
X {
X tot = py.misc.disarm + 2*todis_adj() + stat_adj(A_INT)
X + (class_level_adj[py.misc.pclass][CLA_DISARM] * py.misc.lev / 3);
X if ((py.flags.blind > 0) || (no_light()))
X tot = tot / 10;
X if (py.flags.confused > 0)
X tot = tot / 10;
X if (py.flags.image > 0)
X tot = tot / 10;
X i_ptr = &t_list[c_ptr->tptr];
X i = i_ptr->tval;
X level = i_ptr->level;
X if (i == TV_VIS_TRAP) /* Floor trap */
X {
X if ((tot + 100 - level) > randint(100))
X {
X msg_print("You have disarmed the trap.");
X py.misc.exp += i_ptr->p1;
X (void) delete_object(y, x);
X /* make sure we move onto the trap even if confused */
X tmp = py.flags.confused;
X py.flags.confused = 0;
X move_char(dir, FALSE);
X py.flags.confused = tmp;
X prt_experience();
X }
X /* avoid randint(0) call */
X else if ((tot > 5) && (randint(tot) > 5))
X count_msg_print("You failed to disarm the trap.");
X else
X {
X msg_print("You set the trap off!");
X /* make sure we move onto the trap even if confused */
X tmp = py.flags.confused;
X py.flags.confused = 0;
X move_char(dir, FALSE);
X py.flags.confused += tmp;
X }
X }
X else if (i == TV_CHEST)
X {
X if (!known2_p(i_ptr))
X {
X msg_print("I don't see a trap.");
X free_turn_flag = TRUE;
X }
X else if (CH_TRAPPED & i_ptr->flags)
X {
X if ((tot - level) > randint(100))
X {
X i_ptr->flags &= ~CH_TRAPPED;
X if (CH_LOCKED & i_ptr->flags)
X i_ptr->name2 = SN_LOCKED;
X else
X i_ptr->name2 = SN_DISARMED;
X msg_print("You have disarmed the chest.");
X known2(i_ptr);
X py.misc.exp += level;
X prt_experience();
X }
X else if ((tot > 5) && (randint(tot) > 5))
X count_msg_print("You failed to disarm the chest.");
X else
X {
X msg_print("You set a trap off!");
X known2(i_ptr);
X chest_trap(y, x);
X }
X }
X else
X {
X msg_print("The chest was not trapped.");
X free_turn_flag = TRUE;
X }
X }
X else
X no_disarm = TRUE;
X }
X else
X no_disarm = TRUE;
X
X if (no_disarm)
X {
X msg_print("I do not see anything to disarm there.");
X free_turn_flag = TRUE;
X }
X }
X}
X
X
X/* An enhanced look, with peripheral vision. Looking all 8 -CJS-
X directions will see everything which ought to be visible. Can
X specify direction 5, which looks in all directions.
X
X For the purpose of hindering vision, each place is regarded as
X a diamond just touching its four immediate neighbours. A
X diamond is opaque if it is a wall, or shut door, or something
X like that. A place is visible if any part of its diamond is
X visible: i.e. there is a line from the view point to part of
X the diamond which does not pass through any opaque diamonds.
X
X Consider the following situation:
X
X @.... X X X X X
X .##.. / \ / \ / \ / \ / \
X ..... X @ X . X . X 1 X . X
X \ / \ / \ / \ / \ /
X X X X X X
X Expanded view, with / \ / \ / \ / \ / \
X diamonds inscribed X . X # X # X 2 X . X
X about each point, \ / \ / \ / \ / \ /
X and some locations X X X X X
X numbered. / \ / \ / \ / \ / \
X X . X . X . X 3 X 4 X
X \ / \ / \ / \ / \ /
X X X X X X
X - Location 1 is fully visible.
X - Location 2 is visible, even though partially obscured.
X - Location 3 is invisible, but if either # were
X transparent, it would be visible.
X - Location 4 is completely obscured by a single #.
X
X The function which does the work is look_ray. It sets up its
X own co-ordinate frame (global variables map back to the
X dungeon frame) and looks for everything between two angles
X specified from a central line. It is recursive, and each call
X looks at stuff visible along a line parallel to the center
X line, and a set distance away from it. A diagonal look uses
X more extreme peripheral vision from the closest horizontal and
X vertical directions; horizontal or vertical looks take a call
X for each side of the central line. */
X
X/* Globally accessed variables: gl_nseen counts the number of places where
X something is seen. gl_rock indicates a look for rock or objects.
X
X The others map co-ords in the ray frame to dungeon co-ords.
X
X dungeon y = char_row + gl_fyx * (ray x) + gl_fyy * (ray y)
X dungeon x = char_col + gl_fxx * (ray x) + gl_fxy * (ray y) */
Xstatic int gl_fxx, gl_fxy, gl_fyx, gl_fyy;
Xstatic int gl_nseen, gl_noquery;
Xstatic int gl_rock;
X/* Intended to be indexed by dir/2, since is only relevant to horizontal or
X vertical directions. */
Xstatic int set_fxy[] = { 0, 1, 0, 0, -1 };
Xstatic int set_fxx[] = { 0, 0, -1, 1, 0 };
Xstatic int set_fyy[] = { 0, 0, 1, -1, 0 };
Xstatic int set_fyx[] = { 0, 1, 0, 0, -1 };
X/* Map diagonal-dir/2 to a normal-dir/2. */
Xstatic int map_diag1[] = { 1, 3, 0, 2, 4 };
Xstatic int map_diag2[] = { 2, 1, 0, 4, 3 };
X
X#define GRADF 10000 /* Any sufficiently big number will do */
X
X/* Look at what we can see. This is a free move.
X
X Prompts for a direction, and then looks at every object in
X turn within a cone of vision in that direction. For each
X object, the cursor is moved over the object, a description is
X given, and we wait for the user to type something. Typing
X ESCAPE will abort the entire look.
X
X Looks first at real objects and monsters, and looks at rock
X types only after all other things have been seen. Only looks at rock
X types if the highlight_seams option is set. */
X
Xvoid look()
X{
X register int i, abort;
X int dir, dummy;
X
X if (py.flags.blind > 0)
X msg_print("You can't see a damn thing!");
X else if (py.flags.image > 0)
X msg_print("You can't believe what you are seeing! It's like a dream!");
X else if (get_alldir("Look which direction?", &dir))
X {
X abort = FALSE;
X gl_nseen = 0;
X gl_rock = 0;
X gl_noquery = FALSE; /* Have to set this up for the look_see */
X if (look_see(0, 0, &dummy))
X abort = TRUE;
X else
X {
X do
X {
X abort = FALSE;
X if (dir == 5)
X {
X for (i = 1; i <= 4; i++)
X {
X gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
X gl_fxy = set_fxy[i]; gl_fyy = set_fyy[i];
X if (look_ray(0, 2*GRADF-1, 1))
X {
X abort = TRUE;
X break;
X }
X gl_fxy = -gl_fxy;
X gl_fyy = -gl_fyy;
X if (look_ray(0, 2*GRADF, 2))
X {
X abort = TRUE;
X break;
X }
X }
X }
X else if ((dir & 1) == 0) /* Straight directions */
X {
X i = dir >> 1;
X gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
X gl_fxy = set_fxy[i]; gl_fyy = set_fyy[i];
X if (look_ray(0, GRADF, 1))
X abort = TRUE;
X else
X {
X gl_fxy = -gl_fxy;
X gl_fyy = -gl_fyy;
X abort = look_ray(0, GRADF, 2);
X }
X }
X else
X {
X i = map_diag1[dir >> 1];
X gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
X gl_fxy = -set_fxy[i]; gl_fyy = -set_fyy[i];
X if (look_ray(1, 2*GRADF, GRADF))
X abort = TRUE;
X else
X {
X i = map_diag2[dir >> 1];
X gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
X gl_fxy = set_fxy[i]; gl_fyy = set_fyy[i];
X abort = look_ray(1, 2*GRADF-1, GRADF);
X }
X }
X }
X while (abort == FALSE && highlight_seams && (++gl_rock < 2));
X if (abort)
X msg_print("--Aborting look--");
X else
X {
X if (gl_nseen)
X {
X if (dir == 5)
X msg_print("That's all you see.");
X else
X msg_print("That's all you see in that direction.");
X }
X else if (dir == 5)
X msg_print("You see nothing of interest.");
X else
X msg_print("You see nothing of interest in that direction.");
X }
X }
X }
X}
X
X/* Look at everything within a cone of vision between two ray
X lines emanating from the player, and y or more places away
X from the direct line of view. This is recursive.
X
X Rays are specified by gradients, y over x, multiplied by
X 2*GRADF. This is ONLY called with gradients between 2*GRADF
X (45 degrees) and 1 (almost horizontal).
X
X (y axis)/ angle from
X ^ / ___ angle to
X | / ___
X ...|../.....___.................... parameter y (look at things in the
X | / ___ cone, and on or above this line)
X |/ ___
X @--------------------> direction in which you are looking. (x axis)
X |
X | */
Xstatic int look_ray(y, from, to)
Xint y, from, to;
X{
X register int max_x, x;
X int transparent;
X
X /* from is the larger angle of the ray, since we scan towards the
X center line. If from is smaller, then the ray does not exist. */
X if (from <= to || y > MAX_SIGHT)
X return FALSE;
X /* Find first visible location along this line. Minimum x such
X that (2x-1)/x < from/GRADF <=> x > GRADF(2x-1)/from. This may
X be called with y=0 whence x will be set to 0. Thus we need a
X special fix. */
X x = (int)((long)GRADF * (2 * y - 1) / from + 1);
X if (x <= 0)
X x = 1;
X
X /* Find last visible location along this line.
X Maximum x such that (2x+1)/x > to/GRADF <=> x < GRADF(2x+1)/to */
X max_x = (int)(((long)GRADF * (2 * y + 1) - 1) / to);
X if (max_x > MAX_SIGHT)
X max_x = MAX_SIGHT;
X if (max_x < x)
X return FALSE;
X
X /* gl_noquery is a HACK to prevent doubling up on direct lines of
X sight. If 'to' is greater than 1, we do not really look at
X stuff along the direct line of sight, but we do have to see
X what is opaque for the purposes of obscuring other objects. */
X if (y == 0 && to > 1 || y == x && from < GRADF*2)
X gl_noquery = TRUE;
X else
X gl_noquery = FALSE;
X if (look_see(x, y, &transparent))
X return TRUE;
X if (y == x)
X gl_noquery = FALSE;
X if (transparent)
X goto init_transparent;
X
X for (;;)
X {
X /* Look down the window we've found. */
X if (look_ray(y+1, from, (int)((2 * y + 1) * (long)GRADF / x)))
X return TRUE;
X /* Find the start of next window. */
X do
X {
X if (x == max_x)
X return FALSE;
X /* See if this seals off the scan. (If y is zero, then it will.) */
X from = (int)((2 * y - 1) * (long)GRADF / x);
X if (from <= to)
X return FALSE;
X x++;
X if (look_see(x, y, &transparent))
X return TRUE;
X }
X while(!transparent);
X init_transparent:
X /* Find the end of this window of visibility. */
X do
X {
X if (x == max_x)
X /* The window is trimmed by an earlier limit. */
X return look_ray(y+1, from, to);
X x++;
X if (look_see(x, y, &transparent))
X return TRUE;
X }
X while(transparent);
X }
X}
X
Xstatic int look_see(x, y, transparent)
Xregister int x, y;
Xint *transparent;
X{
X char *dstring, *string, query;
X register cave_type *c_ptr;
X register int j;
X bigvtype out_val, tmp_str;
X
X if (x < 0 || y < 0 || y > x)
X {
X (void) sprintf(tmp_str, "Illegal call to look_see(%d, %d)", x, y);
X msg_print(tmp_str);
X }
X if (x == 0 && y == 0)
X dstring = "You are on";
X else
X dstring = "You see";
X j = char_col + gl_fxx * x + gl_fxy * y;
X y = char_row + gl_fyx * x + gl_fyy * y;
X x = j;
X if (!panel_contains(y, x))
X {
X *transparent = FALSE;
X return FALSE;
X }
X c_ptr = &cave[y][x];
X *transparent = c_ptr->fval <= MAX_OPEN_SPACE;
X if (gl_noquery)
X return FALSE; /* Don't look at a direct line of sight. A hack. */
X out_val[0] = 0;
X if (gl_rock == 0 && c_ptr->cptr > 1 && m_list[c_ptr->cptr].ml)
X {
X j = m_list[c_ptr->cptr].mptr;
X (void) sprintf(out_val, "%s %s %s. [(r)ecall]",
X dstring,
X is_a_vowel( c_list[j].name[0] ) ? "an" : "a",
X c_list[j].name);
X dstring = "It is on";
X prt(out_val, 0, 0);
X move_cursor_relative(y, x);
X query = inkey();
X if (query == 'r' || query == 'R')
X {
X save_screen();
X query = roff_recall(j);
X restore_screen();
X }
X }
X if (c_ptr->tl || c_ptr->pl || c_ptr->fm)
X {
X if (c_ptr->tptr != 0)
X {
X if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
X goto granite;
X if (gl_rock ==0 && t_list[c_ptr->tptr].tval != TV_INVIS_TRAP)
X {
X objdes(tmp_str, &t_list[c_ptr->tptr], TRUE);
X (void) sprintf(out_val, "%s %s ---pause---", dstring, tmp_str);
X dstring = "It is in";
X prt(out_val, 0, 0);
X move_cursor_relative(y, x);
X query = inkey();
X }
X }
X if ((gl_rock || out_val[0]) && c_ptr->fval >= MIN_CLOSED_SPACE)
X {
X switch(c_ptr->fval)
X {
X case BOUNDARY_WALL:
X case GRANITE_WALL:
X granite:
X /* Granite is only interesting if it contains something. */
X if(out_val[0])
X string = "a granite wall";
X else
X string = CNIL; /* In case we jump here */
X break;
X case MAGMA_WALL: string = "some dark rock";
X break;
X case QUARTZ_WALL: string = "a quartz vein";
X break;
X default: string = CNIL;
X break;
X }
X if (string)
X {
X (void) sprintf(out_val, "%s %s ---pause---", dstring, string);
X prt(out_val, 0, 0);
X move_cursor_relative(y, x);
X query = inkey();
X }
X }
X }
X if (out_val[0])
X {
X gl_nseen++;
X if (query == ESCAPE)
X return TRUE;
X }
X
X return FALSE;
X}
X
X
Xstatic void inven_throw(item_val, t_ptr)
Xint item_val;
Xinven_type *t_ptr;
X{
X register inven_type *i_ptr;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X i_ptr = &inventory[item_val];
X *t_ptr = *i_ptr;
X if (i_ptr->number > 1)
X {
X t_ptr->number = 1;
X i_ptr->number--;
X inven_weight -= i_ptr->weight;
X#ifdef ATARIST_MWC
X py.flags.status |= (holder = PY_STR_WGT);
X#else
X py.flags.status |= PY_STR_WGT;
X#endif
X }
X else
X inven_destroy(item_val);
X}
X
X
X/* Obtain the hit and damage bonuses and the maximum distance for a
X thrown missile. */
Xstatic void facts(i_ptr, tbth, tpth, tdam, tdis)
Xregister inven_type *i_ptr;
Xint *tbth, *tpth, *tdam, *tdis;
X{
X register int tmp_weight;
X
X if (i_ptr->weight < 1)
X tmp_weight = 1;
X else
X tmp_weight = i_ptr->weight;
X
X /* Throwing objects */
X *tdam = pdamroll(i_ptr->damage) + i_ptr->todam;
X *tbth = py.misc.bthb * 75 / 100;
X *tpth = py.misc.ptohit + i_ptr->tohit;
X
X /* Add this back later if the correct throwing device. -CJS- */
X if (inventory[INVEN_WIELD].tval != TV_NOTHING)
X *tpth -= inventory[INVEN_WIELD].tohit;
X
X *tdis = (((py.stats.use_stat[A_STR]+20)*10)/tmp_weight);
X if (*tdis > 10) *tdis = 10;
X
X /* multiply damage bonuses instead of adding, when have proper
X missile/weapon combo, this makes them much more useful */
X
X /* Using Bows, slings, or crossbows */
X if (inventory[INVEN_WIELD].tval == TV_BOW)
X switch(inventory[INVEN_WIELD].p1)
X {
X case 1:
X if (i_ptr->tval == TV_SLING_AMMO) /* Sling and ammo */
X {
X *tbth = py.misc.bthb;
X *tpth += 2 * inventory[INVEN_WIELD].tohit;
X *tdam += inventory[INVEN_WIELD].todam;
X *tdam = *tdam * 2;
X *tdis = 20;
X }
X break;
X case 2:
X if (i_ptr->tval == TV_ARROW) /* Short Bow and Arrow */
X {
X *tbth = py.misc.bthb;
X *tpth += 2 * inventory[INVEN_WIELD].tohit;
X *tdam += inventory[INVEN_WIELD].todam;
X *tdam = *tdam * 2;
X *tdis = 25;
X }
X break;
X case 3:
X if (i_ptr->tval == TV_ARROW) /* Long Bow and Arrow */
X {
X *tbth = py.misc.bthb;
X *tpth += 2 * inventory[INVEN_WIELD].tohit;
X *tdam += inventory[INVEN_WIELD].todam;
X *tdam = *tdam * 3;
X *tdis = 30;
X }
X break;
X case 4:
X if (i_ptr->tval == TV_ARROW) /* Composite Bow and Arrow*/
X {
X *tbth = py.misc.bthb;
X *tpth += 2 * inventory[INVEN_WIELD].tohit;
X *tdam += inventory[INVEN_WIELD].todam;
X *tdam = *tdam * 4;
X *tdis = 35;
X }
X break;
X case 5:
X if (i_ptr->tval == TV_BOLT) /* Light Crossbow and Bolt*/
X {
X *tbth = py.misc.bthb;
X *tpth += 2 * inventory[INVEN_WIELD].tohit;
X *tdam += inventory[INVEN_WIELD].todam;
X *tdam = *tdam * 3;
X *tdis = 25;
X }
X break;
X case 6:
X if (i_ptr->tval == TV_BOLT) /* Heavy Crossbow and Bolt*/
X {
X *tbth = py.misc.bthb;
X *tpth += 2 * inventory[INVEN_WIELD].tohit;
X *tdam += inventory[INVEN_WIELD].todam;
X *tdam = *tdam * 4;
X *tdis = 35;
X }
X break;
X }
X}
X
X
Xstatic void drop_throw(y, x, t_ptr)
Xint y, x;
Xinven_type *t_ptr;
X{
X register int i, j, k;
X int flag, cur_pos;
X bigvtype out_val, tmp_str;
X register cave_type *c_ptr;
X
X flag = FALSE;
X i = y;
X j = x;
X k = 0;
X if (randint(10) > 1)
X {
X do
X {
X if (in_bounds(i, j))
X {
X c_ptr = &cave[i][j];
X if (c_ptr->fval <= MAX_OPEN_SPACE && c_ptr->tptr == 0)
X flag = TRUE;
X }
X if (!flag)
X {
X i = y + randint(3) - 2;
X j = x + randint(3) - 2;
X k++;
X }
X }
X while ((!flag) && (k <= 9));
X }
X if (flag)
X {
X cur_pos = popt();
X cave[i][j].tptr = cur_pos;
X t_list[cur_pos] = *t_ptr;
X lite_spot(i, j);
X }
X else
X {
X objdes(tmp_str, t_ptr, FALSE);
X (void) sprintf(out_val, "The %s disappears.", tmp_str);
X msg_print(out_val);
X }
X}
X
X/* Throw an object across the dungeon. -RAK- */
X/* Note: Flasks of oil do fire damage */
X/* Note: Extra damage and chance of hitting when missiles are used*/
X/* with correct weapon. I.E. wield bow and throw arrow. */
Xvoid throw_object()
X{
X int item_val, tbth, tpth, tdam, tdis;
X int y, x, oldy, oldx, cur_dis, dir;
X int flag, visible;
X bigvtype out_val, tmp_str;
X inven_type throw_obj;
X register cave_type *c_ptr;
X register monster_type *m_ptr;
X register int i;
X char tchar;
X
X if (inven_ctr == 0)
X {
X msg_print("But you are not carrying anything.");
X free_turn_flag = TRUE;
X }
X else if (get_item(&item_val, "Fire/Throw which one?", 0, inven_ctr-1, CNIL,
X CNIL))
X {
X if (get_dir(CNIL, &dir))
X {
X desc_remain(item_val);
X if (py.flags.confused > 0)
X {
X msg_print("You are confused.");
X do
X {
X dir = randint(9);
X }
X while (dir == 5);
X }
X inven_throw(item_val, &throw_obj);
X facts(&throw_obj, &tbth, &tpth, &tdam, &tdis);
X tchar = throw_obj.tchar;
X flag = FALSE;
X y = char_row;
X x = char_col;
X oldy = char_row;
X oldx = char_col;
X cur_dis = 0;
X do
X {
X (void) mmove(dir, &y, &x);
X cur_dis++;
X lite_spot(oldy, oldx);
X if (cur_dis > tdis) flag = TRUE;
X c_ptr = &cave[y][x];
X if ((c_ptr->fval <= MAX_OPEN_SPACE) && (!flag))
X {
X if (c_ptr->cptr > 1)
X {
X flag = TRUE;
X m_ptr = &m_list[c_ptr->cptr];
X tbth = tbth - cur_dis;
X /* if monster not lit, make it much more difficult to
X hit, subtract off most bonuses, and reduce bthb
X depending on distance */
X if (!m_ptr->ml)
X tbth = (tbth / (cur_dis+2))
X - (py.misc.lev *
X class_level_adj[py.misc.pclass][CLA_BTHB] / 2)
X - (tpth * (BTH_PLUS_ADJ-1));
X if (test_hit(tbth, (int)py.misc.lev, tpth,
X (int)c_list[m_ptr->mptr].ac, CLA_BTHB))
X {
X i = m_ptr->mptr;
X objdes(tmp_str, &throw_obj, FALSE);
X /* Does the player know what he's fighting? */
X if (!m_ptr->ml)
X {
X (void) sprintf(out_val,
X "You hear a cry as the %s finds a mark.", tmp_str);
X visible = FALSE;
X }
X else
X {
X (void) sprintf(out_val, "The %s hits the %s.",
X tmp_str, c_list[i].name);
X visible = TRUE;
X }
X msg_print(out_val);
X tdam = tot_dam(&throw_obj, tdam, i);
X tdam = critical_blow((int)throw_obj.weight,
X tpth, tdam, CLA_BTHB);
X if (tdam < 0) tdam = 0;
X i = mon_take_hit((int)c_ptr->cptr, tdam);
X if (i >= 0)
X {
X if (!visible)
X msg_print("You have killed something!");
X else
X {
X (void) sprintf(out_val,"You have killed the %s.",
X c_list[i].name);
X msg_print(out_val);
X }
X prt_experience();
X }
X }
X else
X drop_throw(oldy, oldx, &throw_obj);
X }
X else
X { /* do not test c_ptr->fm here */
X if (panel_contains(y, x) && (py.flags.blind < 1)
X && (c_ptr->tl || c_ptr->pl))
X {
X print(tchar, y, x);
X put_qio(); /* show object moving */
X }
X }
X }
X else
X {
X flag = TRUE;
X drop_throw(oldy, oldx, &throw_obj);
X }
X oldy = y;
X oldx = x;
X }
X while (!flag);
X }
X }
X}
X
X
X/* Make a bash attack on someone. -CJS-
X Used to be part of bash above. */
Xstatic void py_bash(y, x)
Xint y, x;
X{
X int monster, k, avg_max_hp, base_tohit;
X register creature_type *c_ptr;
X register monster_type *m_ptr;
X vtype m_name, out_val;
X
X monster = cave[y][x].cptr;
X m_ptr = &m_list[monster];
X c_ptr = &c_list[m_ptr->mptr];
X m_ptr->csleep = 0;
X /* Does the player know what he's fighting? */
X if (!m_ptr->ml)
X (void) strcpy(m_name, "it");
X else
X (void) sprintf(m_name, "the %s", c_ptr->name);
X base_tohit = py.stats.use_stat[A_STR] + inventory[INVEN_ARM].weight/2
X + py.misc.wt/10;
X if (!m_ptr->ml)
X base_tohit = (base_tohit / 2)
X - (py.stats.use_stat[A_DEX]*(BTH_PLUS_ADJ-1))
X - (py.misc.lev * class_level_adj[py.misc.pclass][CLA_BTH] / 2);
X
X if (test_hit(base_tohit, (int)py.misc.lev,
X (int)py.stats.use_stat[A_DEX], (int)c_ptr->ac, CLA_BTH))
X {
X (void) sprintf(out_val, "You hit %s.", m_name);
X msg_print(out_val);
X k = pdamroll(inventory[INVEN_ARM].damage);
X k = critical_blow((int)(inventory[INVEN_ARM].weight / 4
X + py.stats.use_stat[A_STR]), 0, k, CLA_BTH);
X k += py.misc.wt/60 + 3;
X if (k < 0) k = 0;
X
X /* See if we done it in. */
X if (mon_take_hit(monster, k) >= 0)
X {
X (void) sprintf(out_val, "You have slain %s.", m_name);
X msg_print(out_val);
X prt_experience();
X }
X else
X {
X m_name[0] = toupper((int)m_name[0]); /* Capitalize */
X /* Can not stun Balrog */
X avg_max_hp = (c_ptr->cdefense & CD_MAX_HP ?
X c_ptr->hd[0] * c_ptr->hd[1] :
X (c_ptr->hd[0] * (c_ptr->hd[1] + 1)) >> 1);
X if ((100 + randint(400) + randint(400))
X > (m_ptr->hp + avg_max_hp))
X {
X m_ptr->stunned += randint(3) + 1;
X if (m_ptr->stunned > 24) m_ptr->stunned = 24;
X (void) sprintf(out_val, "%s appears stunned!", m_name);
X }
X else
X (void) sprintf(out_val, "%s ignores your bash!", m_name);
X msg_print(out_val);
X }
X }
X else
X {
X (void) sprintf(out_val, "You miss %s.", m_name);
X msg_print(out_val);
X }
X if (randint(150) > py.stats.use_stat[A_DEX])
X {
X msg_print("You are off balance.");
X py.flags.paralysis = 1 + randint(2);
X }
X}
X
X
X/* Bash open a door or chest -RAK- */
X/* Note: Affected by strength and weight of character
X
X For a closed door, p1 is positive if locked; negative if
X stuck. A disarm spell unlocks and unjams doors!
X
X For an open door, p1 is positive for a broken door.
X
X A closed door can be opened - harder if locked. Any door might
X be bashed open (and thereby broken). Bashing a door is
X (potentially) faster! You move into the door way. To open a
X stuck door, it must be bashed. A closed door can be jammed
X (which makes it stuck if previously locked).
X
X Creatures can also open doors. A creature with open door
X ability will (if not in the line of sight) move though a
X closed or secret door with no changes. If in the line of
X sight, closed door are openned, & secret door revealed.
X Whether in the line of sight or not, such a creature may
X unlock or unstick a door.
X
X A creature with no such ability will attempt to bash a
X non-secret door. */
Xvoid bash()
X{
X int y, x, dir, tmp;
X register cave_type *c_ptr;
X register inven_type *t_ptr;
X
X y = char_row;
X x = char_col;
X if (get_dir(CNIL, &dir))
X {
X if (py.flags.confused > 0)
X {
X msg_print("You are confused.");
X do
X {
X dir = randint(9);
X }
X while (dir == 5);
X }
X (void) mmove(dir, &y, &x);
X c_ptr = &cave[y][x];
X if (c_ptr->cptr > 1)
X {
X if (py.flags.afraid > 0)
X msg_print("You are afraid!");
X else
X py_bash(y, x);
X }
X else if (c_ptr->tptr != 0)
X {
X t_ptr = &t_list[c_ptr->tptr];
X if (t_ptr->tval == TV_CLOSED_DOOR)
X {
X count_msg_print("You smash into the door!");
X tmp = py.stats.use_stat[A_STR] + py.misc.wt / 2;
X /* Use (roughly) similar method as for monsters. */
X if (randint(tmp*(20+abs(t_ptr->p1))) < 10*(tmp-abs(t_ptr->p1)))
X {
X msg_print("The door crashes open!");
X invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
X t_ptr->p1 = 1 - randint(2); /* 50% chance of breaking door */
X c_ptr->fval = CORR_FLOOR;
X if (py.flags.confused == 0)
X move_char(dir, FALSE);
X else
X lite_spot(y, x);
X }
X else if (randint(150) > py.stats.use_stat[A_DEX])
X {
X msg_print("You are off-balance.");
X py.flags.paralysis = 1 + randint(2);
X }
X else if (command_count == 0)
X msg_print("The door holds firm.");
X }
X else if (t_ptr->tval == TV_CHEST)
X {
X if (randint(10) == 1)
X {
X msg_print("You have destroyed the chest.");
X msg_print("and its contents!");
X t_ptr->index = OBJ_RUINED_CHEST;
X t_ptr->flags = 0;
X }
X else if ((CH_LOCKED & t_ptr->flags) && (randint(10) == 1))
X {
X msg_print("The lock breaks open!");
X t_ptr->flags &= ~CH_LOCKED;
X }
X else
X count_msg_print("The chest holds firm.");
X }
X else
X /* Can't give free turn, or else player could try directions
X until he found invisible creature */
X msg_print("You bash it, but nothing interesting happens.");
X }
X else
X {
X if (c_ptr->fval < MIN_CAVE_WALL)
X msg_print("You bash at empty space.");
X else
X /* same message for wall as for secret door */
X msg_print("You bash it, but nothing interesting happens.");
X }
X }
X}
END_OF_FILE
if test 31210 -ne `wc -c <'source/moria4.c'`; then
echo shar: \"'source/moria4.c'\" unpacked with wrong size!
fi
# end of 'source/moria4.c'
fi
echo shar: End of archive 15 \(of 39\).
cp /dev/null ark15isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 39 archives.
echo "Now run "bldfiles.sh" to build split files"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0