home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume14 / umoria4 / part15 < prev    next >
Internet Message Format  |  1992-08-31  |  58KB

  1. Path: uunet!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v14i047:  umoria4 - single player dungeon simulation (ver. 5.5), Part15/39
  5. Message-ID: <3405@master.CNA.TEK.COM>
  6. Date: 20 Aug 92 18:04:57 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1703
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: grabiner@math.harvard.edu (David Grabiner)
  12. Posting-number: Volume 14, Issue 47
  13. Archive-name: umoria4/Part15
  14. Supersedes: umoria3: Volume 9, Issue 55-97; Volume 10, Issue 15-17
  15. Environment: Curses, Unix, Mac, MS-DOS, Atari-ST, Amiga, VMS
  16.  
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 15 (of 39)."
  26. # Contents:  misc/README misc/mail.msg source/moria4.c
  27. # Wrapped by billr@saab on Thu Aug 20 09:11:29 1992
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'misc/README' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'misc/README'\"
  31. else
  32. echo shar: Extracting \"'misc/README'\" \(489 characters\)
  33. sed "s/^X//" >'misc/README' <<'END_OF_FILE'
  34. Xstuff that isn't part of Umoria, but would be nice if it was
  35. X
  36. Xfunckeys.h, funckeys.c, mabbrev are (mama) Liz's code for handling SUN keypads
  37. X
  38. Xshading is joseph n hall's ideas on how to efficiently calculate multiple
  39. Xlines of sight
  40. X
  41. Xhaggle.sug, moria.msg, and mail.msg are some interesting mail messages
  42. Xabout moria which suggest changes or additions
  43. X
  44. Xrick.msg is a mail message from the author of VMS Moria 6.0, which lists
  45. Xthe changes he was working on, VMS Moria 6.0 seems to be defunct
  46. END_OF_FILE
  47. if test 489 -ne `wc -c <'misc/README'`; then
  48.     echo shar: \"'misc/README'\" unpacked with wrong size!
  49. fi
  50. # end of 'misc/README'
  51. fi
  52. if test -f 'misc/mail.msg' -a "${1}" != "-c" ; then 
  53.   echo shar: Will not clobber existing file \"'misc/mail.msg'\"
  54. else
  55. echo shar: Extracting \"'misc/mail.msg'\" \(21386 characters\)
  56. sed "s/^X//" >'misc/mail.msg' <<'END_OF_FILE'
  57. XFrom afc@klaatu.cc.purdue.edu Tue Jan 16 13:33:16 1990
  58. XReceived: from klaatu.cc.purdue.edu by ernie.Berkeley.EDU (5.61/1.36)
  59. X    id AA09793; Tue, 16 Jan 90 13:33:09 -0800
  60. XReceived: by klaatu.cc.purdue.edu (5.61/1.14)
  61. X    id AA01432; Tue, 16 Jan 90 16:32:51 -0500
  62. XDate: Tue, 16 Jan 90 16:32:51 -0500
  63. XFrom: afc@klaatu.cc.purdue.edu (Greg Flint)
  64. XMessage-Id: <9001162132.AA01432@klaatu.cc.purdue.edu>
  65. XTo: wilson@ernie.Berkeley.EDU
  66. XSubject: Some comments about PC Moria 4.873 aimed toward your Moria 5.0
  67. XStatus: RO
  68. X
  69. XYou comment that Umoria 5.0 will have good balance because it will be
  70. Xplayer tested before its release.  I'd be willing to volunteer to do
  71. Xsome of this beta testing.  I don't have lots of time to play but I find
  72. Xmoria to be a good way to unwind after a long day fighting more mundane
  73. Xmosters such as Vaxes, Cybers and Suns.
  74. X
  75. XA few opinions about PC Moria 4.873 that might influence Umoria 5.0:
  76. X
  77. X STATS
  78. X -----
  79. X * Once stats get to the 18/xx stage, I find that I can deal with almost
  80. X   anything non-hastened (except for MHD's and Green d/D's) because by then
  81. X   my HP's are usually quite high.  I can just hack away and usually come
  82. X   out on top.  If I have sufficient haste self, I tackle V's and L's.  If
  83. X   I don't, I phase door, teleport away or run for the stairs.  (The method
  84. X   depends on my character type, distance from the monster and equipment at
  85. X   hand.)
  86. X
  87. X * After I reach the 18/xx stage, the game degenerates in to a sequence of
  88. X    1) attack until I loose life levels,
  89. X    2) WOR to store level,
  90. X    3) buy more WOR and RLL, if available,
  91. X    4) kill time on level 1 if no RLL, then back to #3
  92. X           5) WOR back to deepest level,
  93. X    6) go to #1".
  94. X   until I'm finally ready to go to level 50 of the dungeon.
  95. X
  96. X
  97. X MONSTERS
  98. X --------
  99. X
  100. X * It seems to take "forever" to go up the levels of 32+ because there is a
  101. X   big disparity between the value of monsters and the amount of points needed
  102. X   to rise to the next level.  I find myself looking for D's (and L's if I've
  103. X   the proper abilities and/or tools) and being bored by almost anything else
  104. X   -- and yet I'm not yet ready for Iggy or the big "B".
  105. X
  106. X
  107. X MAGIC
  108. X -----
  109. X * Maybe I've been lucky, but I've always been able to find some "see
  110. X   invisible" item early (about Banshee dungeon level).  This makes G's, L's,
  111. X   etc a lot easier (see the earlier comment on my playing sequence.)
  112. X
  113. X * When playing as a mage and reaching about level 29 where I gain fire ball,
  114. X   I find that I've reached the peak in spells.  Of the two spells after that,
  115. X   I've never used WOD and find Genocide so powerful that it seems like
  116. X   cheating.
  117. X
  118. X
  119. X STORES and MONEY
  120. X ----------------
  121. X
  122. X * Money is an issue early, but once I get to about 10,000, I never need to
  123. X   worry about money again -- for two reasons.  The scrolls, potions, staves
  124. X   and the like are cheap (relative to 10K gold).  The weapons that are HA,
  125. X   DF, etc almost never appear so even though they are expensive, I never
  126. X   seem to need the money.
  127. X
  128. X * It would be nice to know how may of a given item are in a store.  This
  129. X   would help with questions such as "should I buy now or wait and chance
  130. X   that it (they?) are gone next time?" or "can I buy him out in the hopes
  131. X   of getting better stock next time?".
  132. X
  133. X
  134. X MAGE SPELLS
  135. X -----------
  136. X
  137. X * The two recharge and the three sleep spells seem redundant (especially
  138. X   the latter).  I usually ignore the Level I recharge and Levels I and II
  139. X   sleep spells because I need more offensive weaponry (spells).  By the time
  140. X   I get around to learning these low level spells (because I've moved up
  141. X   a mage level and you've got to pick something), I really don't need them.
  142. X
  143. X * I don't know what I'd suggest, but I'd like to see some other spells in
  144. X   place of the ones listed above -- especially some after level 29.
  145. X
  146. X * How about spells being fixed in terms of there letter?  Nothing is more
  147. X   painful than forgetting that I've added spell "b" thereby making spell "e"
  148. X   spell "f" and wasting a bunch of mana and maybe allowing a monster a free
  149. X   hit.
  150. X
  151. X
  152. X MAP
  153. X ---
  154. X
  155. X * I find the reduced map a help in speeding up the game.  I favor anything
  156. X   that speeds up the game at no penalty me.  (For example, using "H" to
  157. X   "run" in place of lots of h's is a no cost plus.  I would not want to be
  158. X   penalized for "running" since all I'm doing is speeding up the game, not
  159. X   trying to "tire out" the character.)
  160. X
  161. X------------------------------------------------------------------------------
  162. XGreg Flint       Math G-169   (317) 494-1787   UUCP:  purdue!klaatu.cc!afc
  163. X  Purdue Univ.      Purdue University        INTERNET:  afc@klaatu.cc.purdue.edu
  164. X  Computing Ctr.  West Lafayette, IN 47907    BITNET:  flint@purccvm.bitnet
  165. X
  166. XFrom qqc@h.cc.purdue.edu Thu Jan 18 13:54:52 1990
  167. XReceived: from h.cc.purdue.edu by ernie.Berkeley.EDU (5.61/1.36)
  168. X    id AA09437; Thu, 18 Jan 90 13:54:47 -0800
  169. XReceived: by h.cc.purdue.edu (5.61/1.14)
  170. X    id AA15380; Thu, 18 Jan 90 16:54:08 -0500
  171. XDate: Thu, 18 Jan 90 16:54:08 -0500
  172. XFrom: qqc@h.cc.purdue.edu (Dale Forsyth)
  173. XMessage-Id: <9001182154.AA15380@h.cc.purdue.edu>
  174. XTo: wilson@ernie.Berkeley.EDU
  175. XSubject: program comments
  176. XStatus: RO
  177. X
  178. X
  179. XJim Wilson:  As I perceive you as the author/programmer now associated
  180. Xwith moria, I have several comments to make, in light of messages you have
  181. Xposted in the past about the program.  I use the ibm-pc version 4.873, but
  182. Xexpect my comments apply universally.  All the following is, of course, only
  183. Xone person's opinion.
  184. X   I'm almost ashamed to admit how much I've used the program -- suffice to
  185. Xsay I consider myself VERY experienced.  I think I could win with ANY
  186. Xcharacter, but I would not have the patience to do so.
  187. X   I consider the ONLY reason to use the program is for my own enjoyment.
  188. XAny cheating I do is only to myself, for myself, and affects no one else; of
  189. Xcourse mine isn't a multi-user machine, for which you are concerned.
  190. X   In my opinion, a mage is a reasonable and fun character.  I don't think it
  191. Xshould be necessary to change it's balance.  A priest (current character) is
  192. Xok EXCEPT that it needs an identify spell.  Either that or the shops MUST keep
  193. Xidentify spells stocked.  Since they do not in my version, I would quit this
  194. Xcharacter as NOT FUN anymore, except that I use wizard mode and cheat on this
  195. Xpoint.
  196. X  I do NOT consider the 'triangle dance' around monsters a bad thing.  I think
  197. Xthere SHOULD be a way to outdo monsters that are bigger and badder than you,
  198. Xif you have patience.
  199. X  The shops is an area that needs improvement; they should contain better and
  200. Xbetter things as one's level increases.  After a while there becomes NO REASON
  201. Xto return topside and accumulation of gold becomes moot.  It would stay more
  202. XFUN if you could BUY that HA weapon, even at 300,000 gp, when you have only
  203. X175,000 gp.  But really good stuff never appears in MY shops.
  204. X   Endless repetition of mundane tactics that you know, waiting for something
  205. Xyou NEED, is NOT FUN.  A little is ok, month's of my life that way is NOT FUN.
  206. X   Characters beyond the BALROG would be possible, as for example Mordred from
  207. XMordor (Lord of the Rings), the Ring Wraiths, etc.  I think reincarnation,
  208. Xperhaps with some penalty, would be I think reasonable.  (Me, I cheat with
  209. Xbackups, to learn, try things that if I knew I couldn't get back I just
  210. Xwouldn't do, and therefore wouldn't have that particular fun, etc).
  211. X   If one thing is over-powerful, it's perhaps bashing for good characters.
  212. XWhen I am REALLY ready to take on the balrog, (not try it for FUN with a worse
  213. Xcharacter), I accomplish his demise, fully loaded with mana, equipment, etc,
  214. Xnone of which I need or use, and he dies without ever touching me.  Of course
  215. Xthis takes searching for months for enough speed, but bashing is the secret
  216. X(as I know you know) and reduces the game to trivial at that point.  (3 AMHD's
  217. Xat one time, all always stunned, none ever hurting you; that's an example).
  218. X
  219. X  My main points in this letter are Priests and others need Identify or stores
  220. Xmust keep scrolls, to be fun, and stores should stock better, more expensive
  221. Xthings as one progresses.
  222. X             Thanks for maintaining such a good program, one of the most
  223. X             addictive I know.
  224. XDale Forsyth (45 yr-old game addict)  qqc@h.cc.purdue.edu
  225. X
  226. XFrom ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!yale!cs.yale.edu
  227. XStatus: RO
  228. X
  229. XArticle 4187 of rec.games.moria:
  230. XPath: ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!yale!cs.yale.edu!
  231. X>From: berman-andrew@CS.Yale.EDU (Andrew Berman)
  232. XNewsgroups: rec.games.moria
  233. XSubject: Possible Enhancements
  234. XMessage-ID: <12615@cs.yale.edu>
  235. XDate: 24 Jan 90 03:52:46 GMT
  236. XSender: news@cs.yale.edu
  237. XReply-To: berman-andrew@CS.Yale.EDU (Andrew Berman)
  238. XOrganization: Yale University Computer Science Dept, New Haven CT  06520-2158
  239. XLines: 47
  240. X
  241. X
  242. XI've been playing moria off and on for several years, only recently with
  243. Xversion 4.87.  I have some suggestions which I'd like input on.  Most of
  244. Xthem would make the game *harder*, but would also increase the power
  245. Xand attractiveness of some classes, like the fighter, which don't get
  246. Xused as often.
  247. X
  248. XThe first suggestion is to give fighters limited poison
  249. Ximmunity.  Let them take a % damage which diminishes with their level,
  250. Xup to, say 1/2 damage for a level 39 character.  So they won't get
  251. Xblown away like other characters by AMHD.  They have enough problems
  252. Xas it is.  And it's somewhat consistent- a fighters training may
  253. Xinclude ducking blasts, holding their breath, keeping their skin from
  254. Xbeing exposed, etc...
  255. X
  256. XThe second suggestion is to limit the power of the "cure poison" *spell*
  257. Xof the mages and priests. Right now, you can fight a black mamba and
  258. Xkill it without looking at your stats, because a simple relatively low
  259. Xlevel spell will eliminate any future problems.  Keep the potion as
  260. Xcurrently powered, though.
  261. X
  262. X
  263. X
  264. XThe third suggestion is to limit weapons and Armor based on character class,
  265. Xlike in D & D.  I see no reason to allow a Priest full use of an Executioner's
  266. Xsword, no matter what his/her strength/dex.  If a Priest uses an edged
  267. Xweapon,  have some sort of minus.  If a Mage tries to cast a spell through
  268. XPlate Armor, decrease chance of success. If a Rogue uses a dagger, give
  269. Xa +3 to hit bonus.  Fighters and Paladins can use anything.  Rangers get
  270. Xdouble damage with bows. Something like that.
  271. X
  272. XMy fourth suggestion is to limit max stats based on character race and
  273. Xmaybe on character class.
  274. X
  275. XThe point of the previous two suggestions is to eliminate the
  276. Xdemigodlike character, a 250 hitpoint, 4-hits-per-round-with-a-Beaked-Axe,
  277. Xarmor class of 58 character elven mage.
  278. X
  279. XMy fifth suggestion is to allow "disenchanting" creatures to occasionally
  280. Xzap an ego weapon, low probability, but maybe "you hear your longsword scream
  281. Xin agony" as it goes from an HA to zip.
  282. X
  283. XMy sixth suggestion is to give critical hits to monsters.  Let a Bezerker
  284. Xoccasionally get a good one in for triple damage.  Let a touch have
  285. Xa 5% chance of being a grasp for double drain..
  286. X
  287. XAny comments?
  288. X
  289. X
  290. XFrom ucbvax!decwrl!lll-winken!uwm.edu!cs.utexas.edu!tut.cis.ohio-state.edu
  291. XStatus: RO
  292. X
  293. XArticle 4188 of rec.games.moria:
  294. XPath: ucbvax!decwrl!lll-winken!uwm.edu!cs.utexas.edu!tut.cis.ohio-state.edu
  295. X>From: mf2t+@andrew.cmu.edu (Matthew David Fletcher)
  296. XNewsgroups: rec.games.moria
  297. XSubject: Re: Possible Enhancements
  298. XMessage-ID: <YZjHVGi00XM101NVNs@andrew.cmu.edu>
  299. XDate: 24 Jan 90 05:08:34 GMT
  300. XReferences: <12615@cs.yale.edu>
  301. XOrganization: Carnegie Mellon, Pittsburgh, PA
  302. XLines: 35
  303. XIn-Reply-To: <12615@cs.yale.edu>
  304. X
  305. Xberman-andrew@CS.Yale.EDU (Andrew Berman) writes:
  306. X
  307. X>The first suggestion is to give fighters limited poison
  308. X>immunity.  Let them take a % damage which diminishes with their level,
  309. X>up to, say 1/2 damage for a level 39 character.  So they won't get
  310. X>blown away like other characters by AMHD.  They have enough problems
  311. X>as it is.  And it's somewhat consistent- a fighters training may
  312. X>include ducking blasts, holding their breath, keeping their skin from
  313. X>being exposed, etc...
  314. X>
  315. X>The second suggestion is to limit the power of the "cure poison" *spell*
  316. X>of the mages and priests. Right now, you can fight a black mamba and
  317. X>kill it without looking at your stats, because a simple relatively low
  318. X>level spell will eliminate any future problems.  Keep the potion as
  319. X>currently powered, though.
  320. X
  321. XMy current character is a twenty third level half-troll warrior.  The
  322. Xonly time I've come close to dying while being poisoned was when the
  323. XStone Giant came up and started pounding me half way through.  Certain
  324. Xraces are naturally suited to certain classes by virtue of their
  325. Xbeginning stats.
  326. X
  327. XAre mages capable of casting spells while afraid.  If so, a natural
  328. Xresistance to fear would make it more even.  A ghost almost killed me a
  329. Xwhile ago, because I couldn't attack it.
  330. X
  331. X>My fifth suggestion is to allow "disenchanting" creatures to occasionally
  332. X>zap an ego weapon, low probability, but maybe "you hear your longsword scream
  333. X>in agony" as it goes from an HA to zip.
  334. X
  335. XThis could be rather expensive, considering the cost of all the computer
  336. Xequipment that would be destroyed when a person's dagger (HA) (+8,+8)
  337. Xgets zapped.
  338. X
  339. X                Fletch
  340. X
  341. X
  342. XFrom ucbvax!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!unix.cis.p
  343. XStatus: RO
  344. X
  345. XArticle 4193 of rec.games.moria:
  346. XPath: ucbvax!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!unix.cis.
  347. X>From: dtate@unix.cis.pitt.edu (David M Tate)
  348. XNewsgroups: rec.games.moria
  349. XSubject: Re: Possible Enhancements
  350. XMessage-ID: <21833@unix.cis.pitt.edu>
  351. XDate: 24 Jan 90 17:00:57 GMT
  352. XReferences: <12615@cs.yale.edu>
  353. XReply-To: dtate@unix.cis.pitt.edu (David M Tate)
  354. XOrganization: Univ. of Pittsburgh, Comp & Info Services
  355. XLines: 35
  356. X
  357. XAndrew Berman lists a number of possible enhancements for later versions of
  358. XMoria.  Some of them, I think, bear serious consideration.
  359. X
  360. XIn particular, I think that the idea of distinguishing various character
  361. Xclasses even more sharply is a good one.  I agree wholeheartedly that the only
  362. Xweapons usable by a priest should be mace/morningstar/hammer/club/flail types.
  363. XNo one but a fighter, paladin, or ranger should be able to wield a 2-handed
  364. Xsword or Executioner's Sword.  No matter how strong a mage gets, he should not
  365. Xbe able to fight effectively with anything heavy, nor able to cast spells
  366. Xeffectively while wearing heavy armor.
  367. X
  368. XOne way to reduce the mage/ranger advantage would be to implement a "setup
  369. Xcost" for the switch between magic mode and fighting mode: you can't cast a
  370. Xspell in the round immediately following a slash/fire move.  This makes some
  371. Xsense, as one would in general have to "prepare" a spell before casting it.
  372. XSimilarly, one would expect the act of praying to take some finite time.
  373. X(For that matter,eating should take some time--a character interrupted while
  374. Xeating would have the option of finishing the meal (while getting stomped) or
  375. Xabandoning it (in which case the remainder is lost--trampled in battle, or
  376. Xsome such).
  377. X
  378. XOne touch of realism that I would like to see is more more NPC's to pick up
  379. Xthings.  I know this can be done, because ghosts do it already.  Can you
  380. Xreally imagine a hobgoblin coming into a room and *not* picking up the gold
  381. Xand gems?  This would add the challenge of preserving items to the character.
  382. X
  383. XSimilarly, why can't you get your stolen gold back from a dead rogue?  What
  384. Xdid he do with it?  Hide it?  If you're a rogue yourself, you should be able
  385. Xto (a) keep him from picking your pocket, and (b) find where he hid it.
  386. X
  387. XJust a few ramblings...
  388. X
  389. X--
  390. X==============================================================================
  391. X          David M. Tate        | "I do not know which to prefer: the beauty
  392. X    dtate@unix.cis.pitt.edu    |  of inflections, or the beauty of innuendoes;
  393. X                               |  the blackbird whistling, or just after..."
  394. X
  395. X
  396. XFrom 73230.224@compuserve.com Tue Jan 30 11:46:30 1990
  397. XReceived: from saqqara.cis.ohio-state.edu by ernie.Berkeley.EDU (5.61/1.36)
  398. X    id AA23367; Tue, 30 Jan 90 11:46:14 -0800
  399. XReceived: by saqqara.cis.ohio-state.edu (5.61/4.891221)
  400. X    id AA09041; Tue, 30 Jan 90 14:45:48 -0500
  401. XDate: 30 Jan 90 12:41:49 EST
  402. XFrom: Curtis McCauley <73230.224@CompuServe.COM>
  403. XTo: <wilson@ernie.Berkeley.EDU>
  404. XSubject: Umoria 5.0.13 disks mailed
  405. XMessage-Id: <"900130174148 73230.224 EHA20-1"@CompuServe.COM>
  406. XStatus: RO
  407. X
  408. XTo: >INTERNET:wilson@ernie.Berkeley.EDU
  409. XI mailed you the sources either Monday or Tuesday of last week.  I can't
  410. Xremember which day for sure.  I used regular mail, so it may take some time.
  411. XThe mailing required two diskettes, one for the source, the other for a
  412. Xcompiled version of the game.  Do you have access to MPW 3.0?  You will need
  413. Xit to compile.  I don't think that THINK C could be used very easily in place
  414. Xof MPW.  I rely pretty heavily on the MPW environment to make the program.
  415. X
  416. XWhile I'm thinking about it, there are a couple of principles which, if
  417. Xobserved in all parts of the code, would make the mac port easier and less
  418. Xof a hack:
  419. X
  420. X1)  Don't modify a variable which is initialized in its declaration (e.g.,
  421. X"int foo_flag = TRUE").  I had to try to find all of these in order to make
  422. Xthe game restartable.
  423. X
  424. X2)  Don't rely on the value of a variable which is not initialized in its
  425. Xdeclaration being zero.  For example, get_panel() forces the panel to be
  426. Xredrawn the first time it is called in the course of a game because
  427. Xpanel_[row/col]_[min/max] are all zero.  In the mac version, when the game is
  428. Xrestarted, these variables have the values left over from the previous game.
  429. XI do with them what I do with the variables which fall under 1 above:  I keep
  430. Xtheir "initialized" value in a resource and restore them each time a game is
  431. Xrestarted.
  432. X
  433. X3)  (This follows a fortiori from 1 above.)  Don't modify a private variable
  434. Xwhich is initialized in its declaration.  These I had to move from the source
  435. Xfiles in which they were declared to variables.c and externs.h in order to
  436. Xmake them accessible for the routines which build the restart resource and
  437. Xcopy the saved data when a new game is started.
  438. X
  439. XAdmittedly, there is some inconvience involved in following these rules.  It's
  440. Xa judgement call.
  441. X
  442. XThe version I have given you "hilights" the veins instead of using '%'.  I
  443. Xdidn't discover that you had given up on hilighting until after I had ported
  444. Xio.c to allow it.  So I figured I'd leave it in.  I discovered after I had
  445. Xsent you the game that this causes the map command to screw up because it
  446. Xdoesn't know how to handle -'#'.  What do you think?  Remove the hilighting
  447. Xcapability or fix the map command to handle it?
  448. X
  449. XYou might want to consider the possibility of having two mac file types for
  450. Xsave files:  one for living characters, another for dead characters' memories.
  451. XThis way the two files will be distinguishable by their icons.  (Perhaps a
  452. Xtombstone as the latter type of icon.)
  453. X
  454. XDo we want to get a new application signature from Apple?  I'd prefer not to,
  455. Xbut there likely will be problems for people who try to keep the old version
  456. Xaround on their disks.  For example, I am not certain which program will come
  457. Xup if the user double clicks on a save file from the finder when he has both
  458. Xcopies of the game on his disk.  Maybe this can be handled by simply telling
  459. Xthe player to throw away his old version in the mac help text.
  460. X
  461. XI do not like the way the game "flows" at the end, particularly the standard
  462. Xfile dialog which prompts for saving the player's memories.  It seems kind of
  463. Xintrusive.  I do not know how things will change when the top ten is added.
  464. XAlso, there is a problem with the prompt in this dialog box.  In save_char() I
  465. Xtry to say "Save your memories as:" instead of "Save the game as:" when I
  466. Xthink the player has died or quit.  This doesn't always work right.  Sometimes
  467. Xit says "memories" when it should say "game".  This always happens when ^X is
  468. Xused to save the game.  I have fixed that problem since I sent you the source.
  469. XAnother problem remains:  I rely upon the variable death to decide which
  470. Xprompt to choose.  This will not work when the player quits the character.
  471. XDeath is not set, yet only the memories will get saved, right?  In the version
  472. Xyou have, I have the two prompts switched in save_char().  So, you get the
  473. X"memories" prompt when you quit and the "game" prompt when you are killed.
  474. X
  475. XFinally, do female dwarves really have beards?  Ugh.
  476. X
  477. X-Curtis (73230.224@compuserve.com)
  478. X
  479. X
  480. XFrom chinet!saj@gargoyle.uchicago.edu Mon Feb  5 23:29:25 1990
  481. XReceived: from gargoyle.uchicago.edu by ernie.Berkeley.EDU (5.61/1.36)
  482. X    id AA00727; Mon, 5 Feb 90 23:29:21 -0800
  483. XReceived: by gargoyle.uchicago.edu (5.59/1.14)
  484. X    id AA06383; Tue, 6 Feb 90 01:28:53 199
  485. XReceived: by chinet.chi.il.us (/\=-/\ Smail3.1.18.1 #18.65)
  486. X    id <m0gvOff-0002kbC@chinet.chi.il.us>; Tue, 6 Feb 90 00:27 CST
  487. XMessage-Id: <m0gvOff-0002kbC@chinet.chi.il.us>
  488. XFrom: saj@chinet.chi.il.us (Stephen Jacobs)
  489. XSubject: Source arrived today
  490. XTo: ernie.Berkeley.EDU!wilson@gargoyle.uchicago.edu  (James E. Wilson)
  491. XDate: Tue, 6 Feb 90 0:27:26 CST
  492. XIn-Reply-To: <9002020111.AA22413@ernie.Berkeley.EDU>; from "James E. Wilson"
  493. XX-Mailer: ELM [version 2.2 PL16]
  494. XStatus: RO
  495. X
  496. XThe source arrived today.  Thanks.  I've barely begun to scan it, but I'd
  497. Xguess that there shouldn't be any special problems bringing it up on the
  498. XST.  One immediate suggestion: the Mark Williams C compiler defines the
  499. Xmacro GEMDOS, and defines the macro __STDC__ to be 0.  Using those as
  500. Xconditions could make recognition of the situation automatic.
  501. X
  502. X                                     Steve J.
  503. X
  504. X
  505. END_OF_FILE
  506. if test 21386 -ne `wc -c <'misc/mail.msg'`; then
  507.     echo shar: \"'misc/mail.msg'\" unpacked with wrong size!
  508. fi
  509. # end of 'misc/mail.msg'
  510. fi
  511. if test -f 'source/moria4.c' -a "${1}" != "-c" ; then 
  512.   echo shar: Will not clobber existing file \"'source/moria4.c'\"
  513. else
  514. echo shar: Extracting \"'source/moria4.c'\" \(31210 characters\)
  515. sed "s/^X//" >'source/moria4.c' <<'END_OF_FILE'
  516. X/* source/moria4.c: misc code, mainly to handle player commands
  517. X
  518. X   Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  519. X
  520. X   This software may be copied and distributed for educational, research, and
  521. X   not for profit purposes provided that this copyright and statement are
  522. X   included in all such copies. */
  523. X
  524. X#ifdef __TURBOC__
  525. X#include    <stdio.h>
  526. X#include    <stdlib.h>
  527. X#endif
  528. X
  529. X#include "config.h"
  530. X#include "constant.h"
  531. X#include "types.h"
  532. X#include "externs.h"
  533. X
  534. X#ifdef USG
  535. X#ifndef ATARIST_MWC
  536. X#include <string.h>
  537. X#endif
  538. X#else
  539. X#include <strings.h>
  540. X#endif
  541. X
  542. X#include <ctype.h>
  543. X
  544. X
  545. X#if defined(LINT_ARGS)
  546. Xstatic int look_ray(int, int, int);
  547. Xstatic int look_see(int, int, int *);
  548. Xstatic void inven_throw(int, struct inven_type *);
  549. Xstatic void facts(struct inven_type *, int *, int *, int *, int *);
  550. Xstatic void drop_throw(int, int, struct inven_type *);
  551. Xstatic void py_bash(int, int);
  552. X#else
  553. Xstatic int look_ray();
  554. Xstatic int look_see();
  555. X#endif
  556. X
  557. X
  558. X/* Tunnels through rubble and walls            -RAK-    */
  559. X/* Must take into account: secret doors,  special tools          */
  560. Xvoid tunnel(dir)
  561. Xint dir;
  562. X{
  563. X  register int i, tabil;
  564. X  register cave_type *c_ptr;
  565. X  register inven_type *i_ptr;
  566. X  int y, x;
  567. X  monster_type *m_ptr;
  568. X  vtype out_val, m_name;
  569. X#ifdef ATARIST_MWC
  570. X  int32u holder;
  571. X#endif
  572. X
  573. X  if ((py.flags.confused > 0) &&    /* Confused?         */
  574. X      (randint(4) > 1))            /* 75% random movement   */
  575. X    dir = randint(9);
  576. X  y = char_row;
  577. X  x = char_col;
  578. X  (void) mmove(dir, &y, &x);
  579. X
  580. X  c_ptr = &cave[y][x];
  581. X  /* Compute the digging ability of player; based on       */
  582. X  /* strength, and type of tool used               */
  583. X  tabil = py.stats.use_stat[A_STR];
  584. X  i_ptr = &inventory[INVEN_WIELD];
  585. X
  586. X  /* Don't let the player tunnel somewhere illegal, this is necessary to
  587. X     prevent the player from getting a free attack by trying to tunnel
  588. X     somewhere where it has no effect.  */
  589. X  if (c_ptr->fval < MIN_CAVE_WALL
  590. X      && (c_ptr->tptr == 0 || (t_list[c_ptr->tptr].tval != TV_RUBBLE
  591. X                   && t_list[c_ptr->tptr].tval != TV_SECRET_DOOR)))
  592. X    {
  593. X      if (c_ptr->tptr == 0)
  594. X    {
  595. X      msg_print ("Tunnel through what?  Empty air?!?");
  596. X      free_turn_flag = TRUE;
  597. X    }
  598. X      else
  599. X    {
  600. X      msg_print("You can't tunnel through that.");
  601. X      free_turn_flag = TRUE;
  602. X    }
  603. X      return;
  604. X    }
  605. X
  606. X  if (c_ptr->cptr > 1)
  607. X    {
  608. X      m_ptr = &m_list[c_ptr->cptr];
  609. X      if (m_ptr->ml)
  610. X    (void) sprintf (m_name, "The %s", c_list[m_ptr->mptr].name);
  611. X      else
  612. X    (void) strcpy (m_name, "Something");
  613. X      (void) sprintf(out_val, "%s is in your way!", m_name);
  614. X      msg_print(out_val);
  615. X
  616. X      /* let the player attack the creature */
  617. X      if (py.flags.afraid < 1)
  618. X    py_attack(y, x);
  619. X      else
  620. X    msg_print("You are too afraid!");
  621. X    }
  622. X  else if (i_ptr->tval != TV_NOTHING)
  623. X    {
  624. X#ifdef ATARIST_MWC
  625. X      if ((holder = TR_TUNNEL) & i_ptr->flags)
  626. X#else
  627. X      if (TR_TUNNEL & i_ptr->flags)
  628. X#endif
  629. X    tabil += 25 + i_ptr->p1*50;
  630. X      else
  631. X    {
  632. X      tabil += (i_ptr->damage[0]*i_ptr->damage[1]) + i_ptr->tohit
  633. X        + i_ptr->todam;
  634. X      /* divide by two so that digging without shovel isn't too easy */
  635. X      tabil >>= 1;
  636. X    }
  637. X
  638. X      /* If this weapon is too heavy for the player to wield properly, then
  639. X     also make it harder to dig with it.  */
  640. X
  641. X      if (weapon_heavy)
  642. X    {
  643. X      tabil += (py.stats.use_stat[A_STR] * 15) - i_ptr->weight;
  644. X      if (tabil < 0)
  645. X        tabil = 0;
  646. X    }
  647. X
  648. X      /* Regular walls; Granite, magma intrusion, quartz vein  */
  649. X      /* Don't forget the boundary walls, made of titanium (255)*/
  650. X      switch(c_ptr->fval)
  651. X    {
  652. X    case GRANITE_WALL:
  653. X      i = randint(1200) + 80;
  654. X      if (twall(y, x, tabil, i))
  655. X        msg_print("You have finished the tunnel.");
  656. X      else
  657. X        count_msg_print("You tunnel into the granite wall.");
  658. X      break;
  659. X    case MAGMA_WALL:
  660. X      i = randint(600) + 10;
  661. X      if (twall(y, x, tabil, i))
  662. X        msg_print("You have finished the tunnel.");
  663. X      else
  664. X        count_msg_print("You tunnel into the magma intrusion.");
  665. X      break;
  666. X    case QUARTZ_WALL:
  667. X      i = randint(400) + 10;
  668. X      if (twall(y, x, tabil, i))
  669. X        msg_print("You have finished the tunnel.");
  670. X      else
  671. X        count_msg_print("You tunnel into the quartz vein.");
  672. X      break;
  673. X    case BOUNDARY_WALL:
  674. X      msg_print("This seems to be permanent rock.");
  675. X      break;
  676. X    default:
  677. X      /* Is there an object in the way?  (Rubble and secret doors)*/
  678. X      if (c_ptr->tptr != 0)
  679. X        {
  680. X          /* Rubble.     */
  681. X          if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
  682. X        {
  683. X          if (tabil > randint(180))
  684. X            {
  685. X              (void) delete_object(y, x);
  686. X              msg_print("You have removed the rubble.");
  687. X              if (randint(10) == 1)
  688. X            {
  689. X              place_object(y, x);
  690. X              if (test_light(y, x))
  691. X                msg_print("You have found something!");
  692. X            }
  693. X              lite_spot(y, x);
  694. X            }
  695. X          else
  696. X            count_msg_print("You dig in the rubble.");
  697. X        }
  698. X          /* Secret doors.*/
  699. X          else if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
  700. X        {
  701. X          count_msg_print("You tunnel into the granite wall.");
  702. X          search(char_row, char_col, py.misc.srh);
  703. X        }
  704. X          else
  705. X        abort ();
  706. X        }
  707. X      else
  708. X        abort ();
  709. X      break;
  710. X    }
  711. X    }
  712. X  else
  713. X    msg_print("You dig with your hands, making no progress.");
  714. X}
  715. X
  716. X
  717. X/* Disarms a trap                    -RAK-    */
  718. Xvoid disarm_trap()
  719. X{
  720. X  int y, x, level, tmp, dir, no_disarm;
  721. X  register int tot, i;
  722. X  register cave_type *c_ptr;
  723. X  register inven_type *i_ptr;
  724. X  monster_type *m_ptr;
  725. X  vtype m_name, out_val;
  726. X
  727. X  y = char_row;
  728. X  x = char_col;
  729. X  if (get_dir(CNIL, &dir))
  730. X    {
  731. X      (void) mmove(dir, &y, &x);
  732. X      c_ptr = &cave[y][x];
  733. X      no_disarm = FALSE;
  734. X      if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
  735. X      (t_list[c_ptr->tptr].tval == TV_VIS_TRAP
  736. X       || t_list[c_ptr->tptr].tval == TV_CHEST))
  737. X    {
  738. X      m_ptr = &m_list[c_ptr->cptr];
  739. X      if (m_ptr->ml)
  740. X        (void) sprintf (m_name, "The %s", c_list[m_ptr->mptr].name);
  741. X      else
  742. X        (void) strcpy (m_name, "Something");
  743. X      (void) sprintf(out_val, "%s is in your way!", m_name);
  744. X      msg_print(out_val);
  745. X    }
  746. X      else if (c_ptr->tptr != 0)
  747. X    {
  748. X      tot = py.misc.disarm + 2*todis_adj() + stat_adj(A_INT)
  749. X        + (class_level_adj[py.misc.pclass][CLA_DISARM] * py.misc.lev / 3);
  750. X      if ((py.flags.blind > 0) || (no_light()))
  751. X        tot = tot / 10;
  752. X      if (py.flags.confused > 0)
  753. X        tot = tot / 10;
  754. X      if (py.flags.image > 0)
  755. X        tot = tot / 10;
  756. X      i_ptr = &t_list[c_ptr->tptr];
  757. X      i = i_ptr->tval;
  758. X      level = i_ptr->level;
  759. X      if (i == TV_VIS_TRAP)            /* Floor trap    */
  760. X        {
  761. X          if ((tot + 100 - level) > randint(100))
  762. X        {
  763. X          msg_print("You have disarmed the trap.");
  764. X          py.misc.exp += i_ptr->p1;
  765. X          (void) delete_object(y, x);
  766. X          /* make sure we move onto the trap even if confused */
  767. X          tmp = py.flags.confused;
  768. X          py.flags.confused = 0;
  769. X          move_char(dir, FALSE);
  770. X          py.flags.confused = tmp;
  771. X          prt_experience();
  772. X        }
  773. X          /* avoid randint(0) call */
  774. X          else if ((tot > 5) && (randint(tot) > 5))
  775. X        count_msg_print("You failed to disarm the trap.");
  776. X          else
  777. X        {
  778. X          msg_print("You set the trap off!");
  779. X          /* make sure we move onto the trap even if confused */
  780. X          tmp = py.flags.confused;
  781. X          py.flags.confused = 0;
  782. X          move_char(dir, FALSE);
  783. X          py.flags.confused += tmp;
  784. X        }
  785. X        }
  786. X      else if (i == TV_CHEST)
  787. X        {
  788. X          if (!known2_p(i_ptr))
  789. X        {
  790. X          msg_print("I don't see a trap.");
  791. X          free_turn_flag = TRUE;
  792. X        }
  793. X          else if (CH_TRAPPED & i_ptr->flags)
  794. X        {
  795. X          if ((tot - level) > randint(100))
  796. X            {
  797. X              i_ptr->flags &= ~CH_TRAPPED;
  798. X              if (CH_LOCKED & i_ptr->flags)
  799. X            i_ptr->name2 = SN_LOCKED;
  800. X              else
  801. X            i_ptr->name2 = SN_DISARMED;
  802. X              msg_print("You have disarmed the chest.");
  803. X              known2(i_ptr);
  804. X              py.misc.exp += level;
  805. X              prt_experience();
  806. X            }
  807. X          else if ((tot > 5) && (randint(tot) > 5))
  808. X            count_msg_print("You failed to disarm the chest.");
  809. X          else
  810. X            {
  811. X              msg_print("You set a trap off!");
  812. X              known2(i_ptr);
  813. X              chest_trap(y, x);
  814. X            }
  815. X        }
  816. X          else
  817. X        {
  818. X          msg_print("The chest was not trapped.");
  819. X          free_turn_flag = TRUE;
  820. X        }
  821. X        }
  822. X      else
  823. X        no_disarm = TRUE;
  824. X    }
  825. X      else
  826. X    no_disarm = TRUE;
  827. X
  828. X      if (no_disarm)
  829. X    {
  830. X      msg_print("I do not see anything to disarm there.");
  831. X      free_turn_flag = TRUE;
  832. X    }
  833. X    }
  834. X}
  835. X
  836. X
  837. X/* An enhanced look, with peripheral vision. Looking all 8    -CJS-
  838. X   directions will see everything which ought to be visible. Can
  839. X   specify direction 5, which looks in all directions.
  840. X
  841. X   For the purpose of hindering vision, each place is regarded as
  842. X   a diamond just touching its four immediate neighbours. A
  843. X   diamond is opaque if it is a wall, or shut door, or something
  844. X   like that. A place is visible if any part of its diamond is
  845. X   visible: i.e. there is a line from the view point to part of
  846. X   the diamond which does not pass through any opaque diamonds.
  847. X
  848. X   Consider the following situation:
  849. X
  850. X     @....                X    X   X    X   X
  851. X     .##..               / \ / \ / \ / \ / \
  852. X     .....              X @ X . X . X 1 X . X
  853. X                   \ / \ / \ / \ / \ /
  854. X                    X    X   X    X   X
  855. X       Expanded view, with       / \ / \ / \ / \ / \
  856. X       diamonds inscribed      X . X # X # X 2 X . X
  857. X       about each point,       \ / \ / \ / \ / \ /
  858. X       and some locations        X    X   X    X   X
  859. X       numbered.           / \ / \ / \ / \ / \
  860. X                  X . X . X . X 3 X 4 X
  861. X                   \ / \ / \ / \ / \ /
  862. X                    X    X   X    X   X
  863. X    - Location 1 is fully visible.
  864. X    - Location 2 is visible, even though partially obscured.
  865. X    - Location 3 is invisible, but if either # were
  866. X      transparent, it would be visible.
  867. X    - Location 4 is completely obscured by a single #.
  868. X
  869. X   The function which does the work is look_ray. It sets up its
  870. X   own co-ordinate frame (global variables map back to the
  871. X   dungeon frame) and looks for everything between two angles
  872. X   specified from a central line. It is recursive, and each call
  873. X   looks at stuff visible along a line parallel to the center
  874. X   line, and a set distance away from it. A diagonal look uses
  875. X   more extreme peripheral vision from the closest horizontal and
  876. X   vertical directions; horizontal or vertical looks take a call
  877. X   for each side of the central line. */
  878. X
  879. X/* Globally accessed variables: gl_nseen counts the number of places where
  880. X   something is seen. gl_rock indicates a look for rock or objects.
  881. X
  882. X   The others map co-ords in the ray frame to dungeon co-ords.
  883. X
  884. X   dungeon y = char_row     + gl_fyx * (ray x)  + gl_fyy * (ray y)
  885. X   dungeon x = char_col     + gl_fxx * (ray x)  + gl_fxy * (ray y) */
  886. Xstatic int gl_fxx, gl_fxy, gl_fyx, gl_fyy;
  887. Xstatic int gl_nseen, gl_noquery;
  888. Xstatic int gl_rock;
  889. X/* Intended to be indexed by dir/2, since is only relevant to horizontal or
  890. X   vertical directions. */
  891. Xstatic int set_fxy[] = { 0,  1,     0,  0, -1 };
  892. Xstatic int set_fxx[] = { 0,  0, -1,  1,     0 };
  893. Xstatic int set_fyy[] = { 0,  0,     1, -1,     0 };
  894. Xstatic int set_fyx[] = { 0,  1,     0,  0, -1 };
  895. X/* Map diagonal-dir/2 to a normal-dir/2. */
  896. Xstatic int map_diag1[] = { 1, 3, 0, 2, 4 };
  897. Xstatic int map_diag2[] = { 2, 1, 0, 4, 3 };
  898. X
  899. X#define GRADF    10000    /* Any sufficiently big number will do */
  900. X
  901. X/* Look at what we can see. This is a free move.
  902. X
  903. X   Prompts for a direction, and then looks at every object in
  904. X   turn within a cone of vision in that direction. For each
  905. X   object, the cursor is moved over the object, a description is
  906. X   given, and we wait for the user to type something. Typing
  907. X   ESCAPE will abort the entire look.
  908. X
  909. X   Looks first at real objects and monsters, and looks at rock
  910. X   types only after all other things have been seen.  Only looks at rock
  911. X   types if the highlight_seams option is set. */
  912. X
  913. Xvoid look()
  914. X{
  915. X  register int i, abort;
  916. X  int dir, dummy;
  917. X
  918. X  if (py.flags.blind > 0)
  919. X    msg_print("You can't see a damn thing!");
  920. X  else if (py.flags.image > 0)
  921. X    msg_print("You can't believe what you are seeing! It's like a dream!");
  922. X  else if (get_alldir("Look which direction?", &dir))
  923. X    {
  924. X      abort = FALSE;
  925. X      gl_nseen = 0;
  926. X      gl_rock = 0;
  927. X      gl_noquery = FALSE;    /* Have to set this up for the look_see */
  928. X      if (look_see(0, 0, &dummy))
  929. X    abort = TRUE;
  930. X      else
  931. X    {
  932. X      do
  933. X        {
  934. X          abort = FALSE;
  935. X          if (dir == 5)
  936. X        {
  937. X          for (i = 1; i <= 4; i++)
  938. X            {
  939. X              gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
  940. X              gl_fxy = set_fxy[i]; gl_fyy = set_fyy[i];
  941. X              if (look_ray(0, 2*GRADF-1, 1))
  942. X            {
  943. X              abort = TRUE;
  944. X              break;
  945. X            }
  946. X              gl_fxy = -gl_fxy;
  947. X              gl_fyy = -gl_fyy;
  948. X              if (look_ray(0, 2*GRADF, 2))
  949. X            {
  950. X              abort = TRUE;
  951. X              break;
  952. X            }
  953. X            }
  954. X        }
  955. X          else if ((dir & 1) == 0)    /* Straight directions */
  956. X        {
  957. X          i = dir >> 1;
  958. X          gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
  959. X          gl_fxy = set_fxy[i]; gl_fyy = set_fyy[i];
  960. X          if (look_ray(0, GRADF, 1))
  961. X            abort = TRUE;
  962. X          else
  963. X            {
  964. X              gl_fxy = -gl_fxy;
  965. X              gl_fyy = -gl_fyy;
  966. X              abort = look_ray(0, GRADF, 2);
  967. X            }
  968. X        }
  969. X          else
  970. X        {
  971. X          i = map_diag1[dir >> 1];
  972. X          gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
  973. X          gl_fxy = -set_fxy[i]; gl_fyy = -set_fyy[i];
  974. X          if (look_ray(1, 2*GRADF, GRADF))
  975. X            abort = TRUE;
  976. X          else
  977. X            {
  978. X              i = map_diag2[dir >> 1];
  979. X              gl_fxx = set_fxx[i]; gl_fyx = set_fyx[i];
  980. X              gl_fxy = set_fxy[i]; gl_fyy = set_fyy[i];
  981. X              abort = look_ray(1, 2*GRADF-1, GRADF);
  982. X            }
  983. X        }
  984. X        }
  985. X      while (abort == FALSE && highlight_seams && (++gl_rock < 2));
  986. X      if (abort)
  987. X        msg_print("--Aborting look--");
  988. X      else
  989. X        {
  990. X          if (gl_nseen)
  991. X        {
  992. X          if (dir == 5)
  993. X            msg_print("That's all you see.");
  994. X          else
  995. X            msg_print("That's all you see in that direction.");
  996. X        }
  997. X          else if (dir == 5)
  998. X        msg_print("You see nothing of interest.");
  999. X          else
  1000. X        msg_print("You see nothing of interest in that direction.");
  1001. X        }
  1002. X    }
  1003. X    }
  1004. X}
  1005. X
  1006. X/* Look at everything within a cone of vision between two ray
  1007. X   lines emanating from the player, and y or more places away
  1008. X   from the direct line of view. This is recursive.
  1009. X
  1010. X   Rays are specified by gradients, y over x, multiplied by
  1011. X   2*GRADF. This is ONLY called with gradients between 2*GRADF
  1012. X   (45 degrees) and 1 (almost horizontal).
  1013. X
  1014. X   (y axis)/ angle from
  1015. X     ^      /        ___ angle to
  1016. X     |     /     ___
  1017. X  ...|../.....___.................... parameter y (look at things in the
  1018. X     | /   ___                  cone, and on or above this line)
  1019. X     |/ ___
  1020. X     @-------------------->   direction in which you are looking. (x axis)
  1021. X     |
  1022. X     | */
  1023. Xstatic int look_ray(y, from, to)
  1024. Xint y, from, to;
  1025. X{
  1026. X  register int max_x, x;
  1027. X  int transparent;
  1028. X
  1029. X  /* from is the larger angle of the ray, since we scan towards the
  1030. X     center line. If from is smaller, then the ray does not exist. */
  1031. X  if (from <= to || y > MAX_SIGHT)
  1032. X    return FALSE;
  1033. X  /* Find first visible location along this line. Minimum x such
  1034. X     that (2x-1)/x < from/GRADF <=> x > GRADF(2x-1)/from. This may
  1035. X     be called with y=0 whence x will be set to 0. Thus we need a
  1036. X     special fix. */
  1037. X  x = (int)((long)GRADF * (2 * y - 1) / from + 1);
  1038. X  if (x <= 0)
  1039. X    x = 1;
  1040. X
  1041. X  /* Find last visible location along this line.
  1042. X     Maximum x such that (2x+1)/x > to/GRADF <=> x < GRADF(2x+1)/to */
  1043. X  max_x = (int)(((long)GRADF * (2 * y + 1) - 1) / to);
  1044. X  if (max_x > MAX_SIGHT)
  1045. X    max_x = MAX_SIGHT;
  1046. X  if (max_x < x)
  1047. X    return FALSE;
  1048. X
  1049. X  /* gl_noquery is a HACK to prevent doubling up on direct lines of
  1050. X     sight. If 'to' is    greater than 1, we do not really look at
  1051. X     stuff along the direct line of sight, but we do have to see
  1052. X     what is opaque for the purposes of obscuring other objects. */
  1053. X  if (y == 0 && to > 1 || y == x && from < GRADF*2)
  1054. X    gl_noquery = TRUE;
  1055. X  else
  1056. X    gl_noquery = FALSE;
  1057. X  if (look_see(x, y, &transparent))
  1058. X    return TRUE;
  1059. X  if (y == x)
  1060. X    gl_noquery = FALSE;
  1061. X  if (transparent)
  1062. X    goto init_transparent;
  1063. X
  1064. X  for (;;)
  1065. X    {
  1066. X      /* Look down the window we've found. */
  1067. X      if (look_ray(y+1, from, (int)((2 * y + 1) * (long)GRADF / x)))
  1068. X    return TRUE;
  1069. X      /* Find the start of next window. */
  1070. X      do
  1071. X    {
  1072. X      if (x == max_x)
  1073. X        return FALSE;
  1074. X      /* See if this seals off the scan. (If y is zero, then it will.) */
  1075. X      from = (int)((2 * y - 1) * (long)GRADF / x);
  1076. X      if (from <= to)
  1077. X        return FALSE;
  1078. X      x++;
  1079. X      if (look_see(x, y, &transparent))
  1080. X        return TRUE;
  1081. X    }
  1082. X      while(!transparent);
  1083. X    init_transparent:
  1084. X      /* Find the end of this window of visibility. */
  1085. X      do
  1086. X    {
  1087. X      if (x == max_x)
  1088. X        /* The window is trimmed by an earlier limit. */
  1089. X        return look_ray(y+1, from, to);
  1090. X      x++;
  1091. X      if (look_see(x, y, &transparent))
  1092. X        return TRUE;
  1093. X    }
  1094. X      while(transparent);
  1095. X    }
  1096. X}
  1097. X
  1098. Xstatic int look_see(x, y, transparent)
  1099. Xregister int x, y;
  1100. Xint *transparent;
  1101. X{
  1102. X  char *dstring, *string, query;
  1103. X  register cave_type *c_ptr;
  1104. X  register int j;
  1105. X  bigvtype out_val, tmp_str;
  1106. X
  1107. X  if (x < 0 || y < 0 || y > x)
  1108. X    {
  1109. X      (void) sprintf(tmp_str, "Illegal call to look_see(%d, %d)", x, y);
  1110. X      msg_print(tmp_str);
  1111. X    }
  1112. X  if (x == 0 && y == 0)
  1113. X    dstring = "You are on";
  1114. X  else
  1115. X    dstring = "You see";
  1116. X  j = char_col + gl_fxx * x + gl_fxy * y;
  1117. X  y = char_row + gl_fyx * x + gl_fyy * y;
  1118. X  x = j;
  1119. X  if (!panel_contains(y, x))
  1120. X    {
  1121. X      *transparent = FALSE;
  1122. X      return FALSE;
  1123. X    }
  1124. X  c_ptr = &cave[y][x];
  1125. X  *transparent = c_ptr->fval <= MAX_OPEN_SPACE;
  1126. X  if (gl_noquery)
  1127. X    return FALSE; /* Don't look at a direct line of sight. A hack. */
  1128. X  out_val[0] = 0;
  1129. X  if (gl_rock == 0 && c_ptr->cptr > 1 && m_list[c_ptr->cptr].ml)
  1130. X    {
  1131. X      j = m_list[c_ptr->cptr].mptr;
  1132. X      (void) sprintf(out_val, "%s %s %s. [(r)ecall]",
  1133. X             dstring,
  1134. X             is_a_vowel( c_list[j].name[0] ) ? "an" : "a",
  1135. X             c_list[j].name);
  1136. X      dstring = "It is on";
  1137. X      prt(out_val, 0, 0);
  1138. X      move_cursor_relative(y, x);
  1139. X      query = inkey();
  1140. X      if (query == 'r' || query == 'R')
  1141. X    {
  1142. X      save_screen();
  1143. X      query = roff_recall(j);
  1144. X      restore_screen();
  1145. X    }
  1146. X    }
  1147. X  if (c_ptr->tl || c_ptr->pl || c_ptr->fm)
  1148. X    {
  1149. X      if (c_ptr->tptr != 0)
  1150. X    {
  1151. X      if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
  1152. X        goto granite;
  1153. X      if (gl_rock ==0 && t_list[c_ptr->tptr].tval != TV_INVIS_TRAP)
  1154. X        {
  1155. X          objdes(tmp_str, &t_list[c_ptr->tptr], TRUE);
  1156. X          (void) sprintf(out_val, "%s %s ---pause---", dstring, tmp_str);
  1157. X          dstring = "It is in";
  1158. X          prt(out_val, 0, 0);
  1159. X          move_cursor_relative(y, x);
  1160. X          query = inkey();
  1161. X        }
  1162. X    }
  1163. X      if ((gl_rock || out_val[0]) && c_ptr->fval >= MIN_CLOSED_SPACE)
  1164. X    {
  1165. X      switch(c_ptr->fval)
  1166. X        {
  1167. X        case BOUNDARY_WALL:
  1168. X        case GRANITE_WALL:
  1169. X        granite:
  1170. X          /* Granite is only interesting if it contains something. */
  1171. X          if(out_val[0])
  1172. X        string = "a granite wall";
  1173. X          else
  1174. X        string = CNIL;    /* In case we jump here */
  1175. X          break;
  1176. X        case MAGMA_WALL: string = "some dark rock";
  1177. X          break;
  1178. X        case QUARTZ_WALL: string = "a quartz vein";
  1179. X          break;
  1180. X        default: string = CNIL;
  1181. X          break;
  1182. X        }
  1183. X      if (string)
  1184. X        {
  1185. X          (void) sprintf(out_val, "%s %s ---pause---", dstring, string);
  1186. X          prt(out_val, 0, 0);
  1187. X          move_cursor_relative(y, x);
  1188. X          query = inkey();
  1189. X        }
  1190. X    }
  1191. X    }
  1192. X  if (out_val[0])
  1193. X    {
  1194. X      gl_nseen++;
  1195. X      if (query == ESCAPE)
  1196. X    return TRUE;
  1197. X    }
  1198. X
  1199. X  return FALSE;
  1200. X}
  1201. X
  1202. X
  1203. Xstatic void inven_throw(item_val, t_ptr)
  1204. Xint item_val;
  1205. Xinven_type *t_ptr;
  1206. X{
  1207. X  register inven_type *i_ptr;
  1208. X#ifdef ATARIST_MWC
  1209. X  int32u holder;
  1210. X#endif
  1211. X
  1212. X  i_ptr = &inventory[item_val];
  1213. X  *t_ptr = *i_ptr;
  1214. X  if (i_ptr->number > 1)
  1215. X    {
  1216. X      t_ptr->number = 1;
  1217. X      i_ptr->number--;
  1218. X      inven_weight -= i_ptr->weight;
  1219. X#ifdef ATARIST_MWC
  1220. X      py.flags.status |= (holder = PY_STR_WGT);
  1221. X#else
  1222. X      py.flags.status |= PY_STR_WGT;
  1223. X#endif
  1224. X    }
  1225. X  else
  1226. X    inven_destroy(item_val);
  1227. X}
  1228. X
  1229. X
  1230. X/* Obtain the hit and damage bonuses and the maximum distance for a
  1231. X   thrown missile. */
  1232. Xstatic void facts(i_ptr, tbth, tpth, tdam, tdis)
  1233. Xregister inven_type *i_ptr;
  1234. Xint *tbth, *tpth, *tdam, *tdis;
  1235. X{
  1236. X  register int tmp_weight;
  1237. X
  1238. X  if (i_ptr->weight < 1)
  1239. X    tmp_weight = 1;
  1240. X  else
  1241. X    tmp_weight = i_ptr->weight;
  1242. X
  1243. X  /* Throwing objects            */
  1244. X  *tdam = pdamroll(i_ptr->damage) + i_ptr->todam;
  1245. X  *tbth = py.misc.bthb * 75 / 100;
  1246. X  *tpth = py.misc.ptohit + i_ptr->tohit;
  1247. X
  1248. X  /* Add this back later if the correct throwing device. -CJS- */
  1249. X  if (inventory[INVEN_WIELD].tval != TV_NOTHING)
  1250. X    *tpth -= inventory[INVEN_WIELD].tohit;
  1251. X
  1252. X  *tdis = (((py.stats.use_stat[A_STR]+20)*10)/tmp_weight);
  1253. X  if (*tdis > 10)  *tdis = 10;
  1254. X
  1255. X  /* multiply damage bonuses instead of adding, when have proper
  1256. X     missile/weapon combo, this makes them much more useful */
  1257. X
  1258. X  /* Using Bows,  slings,  or crossbows    */
  1259. X  if (inventory[INVEN_WIELD].tval == TV_BOW)
  1260. X    switch(inventory[INVEN_WIELD].p1)
  1261. X      {
  1262. X      case 1:
  1263. X    if (i_ptr->tval == TV_SLING_AMMO) /* Sling and ammo */
  1264. X      {
  1265. X        *tbth = py.misc.bthb;
  1266. X        *tpth += 2 * inventory[INVEN_WIELD].tohit;
  1267. X        *tdam += inventory[INVEN_WIELD].todam;
  1268. X        *tdam = *tdam * 2;
  1269. X        *tdis = 20;
  1270. X      }
  1271. X    break;
  1272. X      case 2:
  1273. X    if (i_ptr->tval == TV_ARROW)      /* Short Bow and Arrow    */
  1274. X      {
  1275. X        *tbth = py.misc.bthb;
  1276. X        *tpth += 2 * inventory[INVEN_WIELD].tohit;
  1277. X        *tdam += inventory[INVEN_WIELD].todam;
  1278. X        *tdam = *tdam * 2;
  1279. X        *tdis = 25;
  1280. X      }
  1281. X    break;
  1282. X      case 3:
  1283. X    if (i_ptr->tval == TV_ARROW)      /* Long Bow and Arrow    */
  1284. X      {
  1285. X        *tbth = py.misc.bthb;
  1286. X        *tpth += 2 * inventory[INVEN_WIELD].tohit;
  1287. X        *tdam += inventory[INVEN_WIELD].todam;
  1288. X        *tdam = *tdam * 3;
  1289. X        *tdis = 30;
  1290. X      }
  1291. X    break;
  1292. X      case 4:
  1293. X    if (i_ptr->tval == TV_ARROW)      /* Composite Bow and Arrow*/
  1294. X      {
  1295. X        *tbth = py.misc.bthb;
  1296. X        *tpth += 2 * inventory[INVEN_WIELD].tohit;
  1297. X        *tdam += inventory[INVEN_WIELD].todam;
  1298. X        *tdam = *tdam * 4;
  1299. X        *tdis = 35;
  1300. X      }
  1301. X    break;
  1302. X      case 5:
  1303. X    if (i_ptr->tval == TV_BOLT)      /* Light Crossbow and Bolt*/
  1304. X      {
  1305. X        *tbth = py.misc.bthb;
  1306. X        *tpth += 2 * inventory[INVEN_WIELD].tohit;
  1307. X        *tdam += inventory[INVEN_WIELD].todam;
  1308. X        *tdam = *tdam * 3;
  1309. X        *tdis = 25;
  1310. X      }
  1311. X    break;
  1312. X      case 6:
  1313. X    if (i_ptr->tval == TV_BOLT)      /* Heavy Crossbow and Bolt*/
  1314. X      {
  1315. X        *tbth = py.misc.bthb;
  1316. X        *tpth += 2 * inventory[INVEN_WIELD].tohit;
  1317. X        *tdam += inventory[INVEN_WIELD].todam;
  1318. X        *tdam = *tdam * 4;
  1319. X        *tdis = 35;
  1320. X      }
  1321. X    break;
  1322. X      }
  1323. X}
  1324. X
  1325. X
  1326. Xstatic void drop_throw(y, x, t_ptr)
  1327. Xint y, x;
  1328. Xinven_type *t_ptr;
  1329. X{
  1330. X  register int i, j, k;
  1331. X  int flag, cur_pos;
  1332. X  bigvtype out_val, tmp_str;
  1333. X  register cave_type *c_ptr;
  1334. X
  1335. X  flag = FALSE;
  1336. X  i = y;
  1337. X  j = x;
  1338. X  k = 0;
  1339. X  if (randint(10) > 1)
  1340. X    {
  1341. X      do
  1342. X    {
  1343. X      if (in_bounds(i, j))
  1344. X        {
  1345. X          c_ptr = &cave[i][j];
  1346. X          if (c_ptr->fval <= MAX_OPEN_SPACE && c_ptr->tptr == 0)
  1347. X        flag = TRUE;
  1348. X        }
  1349. X      if (!flag)
  1350. X        {
  1351. X          i = y + randint(3) - 2;
  1352. X          j = x + randint(3) - 2;
  1353. X          k++;
  1354. X        }
  1355. X    }
  1356. X      while ((!flag) && (k <= 9));
  1357. X    }
  1358. X  if (flag)
  1359. X    {
  1360. X      cur_pos = popt();
  1361. X      cave[i][j].tptr = cur_pos;
  1362. X      t_list[cur_pos] = *t_ptr;
  1363. X      lite_spot(i, j);
  1364. X    }
  1365. X  else
  1366. X    {
  1367. X      objdes(tmp_str, t_ptr, FALSE);
  1368. X      (void) sprintf(out_val, "The %s disappears.", tmp_str);
  1369. X      msg_print(out_val);
  1370. X    }
  1371. X}
  1372. X
  1373. X/* Throw an object across the dungeon.        -RAK-    */
  1374. X/* Note: Flasks of oil do fire damage                 */
  1375. X/* Note: Extra damage and chance of hitting when missiles are used*/
  1376. X/*     with correct weapon.  I.E.  wield bow and throw arrow.     */
  1377. Xvoid throw_object()
  1378. X{
  1379. X  int item_val, tbth, tpth, tdam, tdis;
  1380. X  int y, x, oldy, oldx, cur_dis, dir;
  1381. X  int flag, visible;
  1382. X  bigvtype out_val, tmp_str;
  1383. X  inven_type throw_obj;
  1384. X  register cave_type *c_ptr;
  1385. X  register monster_type *m_ptr;
  1386. X  register int i;
  1387. X  char tchar;
  1388. X
  1389. X  if (inven_ctr == 0)
  1390. X    {
  1391. X      msg_print("But you are not carrying anything.");
  1392. X      free_turn_flag = TRUE;
  1393. X    }
  1394. X  else if (get_item(&item_val, "Fire/Throw which one?", 0, inven_ctr-1, CNIL,
  1395. X            CNIL))
  1396. X    {
  1397. X      if (get_dir(CNIL, &dir))
  1398. X    {
  1399. X      desc_remain(item_val);
  1400. X      if (py.flags.confused > 0)
  1401. X        {
  1402. X          msg_print("You are confused.");
  1403. X          do
  1404. X        {
  1405. X          dir = randint(9);
  1406. X        }
  1407. X          while (dir == 5);
  1408. X        }
  1409. X      inven_throw(item_val, &throw_obj);
  1410. X      facts(&throw_obj, &tbth, &tpth, &tdam, &tdis);
  1411. X      tchar = throw_obj.tchar;
  1412. X      flag = FALSE;
  1413. X      y = char_row;
  1414. X      x = char_col;
  1415. X      oldy = char_row;
  1416. X      oldx = char_col;
  1417. X      cur_dis = 0;
  1418. X      do
  1419. X        {
  1420. X          (void) mmove(dir, &y, &x);
  1421. X          cur_dis++;
  1422. X          lite_spot(oldy, oldx);
  1423. X          if (cur_dis > tdis)  flag = TRUE;
  1424. X          c_ptr = &cave[y][x];
  1425. X          if ((c_ptr->fval <= MAX_OPEN_SPACE) && (!flag))
  1426. X        {
  1427. X          if (c_ptr->cptr > 1)
  1428. X            {
  1429. X              flag = TRUE;
  1430. X              m_ptr = &m_list[c_ptr->cptr];
  1431. X              tbth = tbth - cur_dis;
  1432. X              /* if monster not lit, make it much more difficult to
  1433. X             hit, subtract off most bonuses, and reduce bthb
  1434. X             depending on distance */
  1435. X              if (!m_ptr->ml)
  1436. X            tbth = (tbth / (cur_dis+2))
  1437. X              - (py.misc.lev *
  1438. X                 class_level_adj[py.misc.pclass][CLA_BTHB] / 2)
  1439. X                - (tpth * (BTH_PLUS_ADJ-1));
  1440. X              if (test_hit(tbth, (int)py.misc.lev, tpth,
  1441. X                   (int)c_list[m_ptr->mptr].ac, CLA_BTHB))
  1442. X            {
  1443. X              i = m_ptr->mptr;
  1444. X              objdes(tmp_str, &throw_obj, FALSE);
  1445. X              /* Does the player know what he's fighting?       */
  1446. X              if (!m_ptr->ml)
  1447. X                {
  1448. X                  (void) sprintf(out_val,
  1449. X               "You hear a cry as the %s finds a mark.", tmp_str);
  1450. X                  visible = FALSE;
  1451. X                }
  1452. X              else
  1453. X                {
  1454. X                  (void) sprintf(out_val, "The %s hits the %s.",
  1455. X                         tmp_str, c_list[i].name);
  1456. X                  visible = TRUE;
  1457. X                }
  1458. X              msg_print(out_val);
  1459. X              tdam = tot_dam(&throw_obj, tdam, i);
  1460. X              tdam = critical_blow((int)throw_obj.weight,
  1461. X                           tpth, tdam, CLA_BTHB);
  1462. X              if (tdam < 0) tdam = 0;
  1463. X              i = mon_take_hit((int)c_ptr->cptr, tdam);
  1464. X              if (i >= 0)
  1465. X                {
  1466. X                  if (!visible)
  1467. X                msg_print("You have killed something!");
  1468. X                  else
  1469. X                {
  1470. X              (void) sprintf(out_val,"You have killed the %s.",
  1471. X                         c_list[i].name);
  1472. X                  msg_print(out_val);
  1473. X                }
  1474. X                  prt_experience();
  1475. X                }
  1476. X            }
  1477. X              else
  1478. X            drop_throw(oldy, oldx, &throw_obj);
  1479. X            }
  1480. X          else
  1481. X            {    /* do not test c_ptr->fm here */
  1482. X              if (panel_contains(y, x) && (py.flags.blind < 1)
  1483. X              && (c_ptr->tl || c_ptr->pl))
  1484. X            {
  1485. X              print(tchar, y, x);
  1486. X              put_qio(); /* show object moving */
  1487. X            }
  1488. X            }
  1489. X        }
  1490. X          else
  1491. X        {
  1492. X          flag = TRUE;
  1493. X          drop_throw(oldy, oldx, &throw_obj);
  1494. X        }
  1495. X          oldy = y;
  1496. X          oldx = x;
  1497. X        }
  1498. X      while (!flag);
  1499. X    }
  1500. X    }
  1501. X}
  1502. X
  1503. X
  1504. X/* Make a bash attack on someone.                -CJS-
  1505. X   Used to be part of bash above. */
  1506. Xstatic void py_bash(y, x)
  1507. Xint y, x;
  1508. X{
  1509. X  int monster, k, avg_max_hp, base_tohit;
  1510. X  register creature_type *c_ptr;
  1511. X  register monster_type *m_ptr;
  1512. X  vtype m_name, out_val;
  1513. X
  1514. X  monster = cave[y][x].cptr;
  1515. X  m_ptr = &m_list[monster];
  1516. X  c_ptr = &c_list[m_ptr->mptr];
  1517. X  m_ptr->csleep = 0;
  1518. X  /* Does the player know what he's fighting?       */
  1519. X  if (!m_ptr->ml)
  1520. X    (void) strcpy(m_name, "it");
  1521. X  else
  1522. X    (void) sprintf(m_name, "the %s", c_ptr->name);
  1523. X  base_tohit = py.stats.use_stat[A_STR] + inventory[INVEN_ARM].weight/2
  1524. X    + py.misc.wt/10;
  1525. X  if (!m_ptr->ml)
  1526. X    base_tohit = (base_tohit / 2)
  1527. X      - (py.stats.use_stat[A_DEX]*(BTH_PLUS_ADJ-1))
  1528. X    - (py.misc.lev * class_level_adj[py.misc.pclass][CLA_BTH] / 2);
  1529. X
  1530. X  if (test_hit(base_tohit, (int)py.misc.lev,
  1531. X           (int)py.stats.use_stat[A_DEX], (int)c_ptr->ac, CLA_BTH))
  1532. X    {
  1533. X      (void) sprintf(out_val, "You hit %s.", m_name);
  1534. X      msg_print(out_val);
  1535. X      k = pdamroll(inventory[INVEN_ARM].damage);
  1536. X      k = critical_blow((int)(inventory[INVEN_ARM].weight / 4
  1537. X                  + py.stats.use_stat[A_STR]), 0, k, CLA_BTH);
  1538. X      k += py.misc.wt/60 + 3;
  1539. X      if (k < 0) k = 0;
  1540. X
  1541. X      /* See if we done it in.                     */
  1542. X      if (mon_take_hit(monster, k) >= 0)
  1543. X    {
  1544. X      (void) sprintf(out_val, "You have slain %s.", m_name);
  1545. X      msg_print(out_val);
  1546. X      prt_experience();
  1547. X    }
  1548. X      else
  1549. X    {
  1550. X      m_name[0] = toupper((int)m_name[0]); /* Capitalize */
  1551. X      /* Can not stun Balrog */
  1552. X      avg_max_hp = (c_ptr->cdefense & CD_MAX_HP ?
  1553. X            c_ptr->hd[0] * c_ptr->hd[1] :
  1554. X            (c_ptr->hd[0] * (c_ptr->hd[1] + 1)) >> 1);
  1555. X      if ((100 + randint(400) + randint(400))
  1556. X          > (m_ptr->hp + avg_max_hp))
  1557. X        {
  1558. X          m_ptr->stunned += randint(3) + 1;
  1559. X          if (m_ptr->stunned > 24)    m_ptr->stunned = 24;
  1560. X          (void) sprintf(out_val, "%s appears stunned!", m_name);
  1561. X        }
  1562. X      else
  1563. X        (void) sprintf(out_val, "%s ignores your bash!", m_name);
  1564. X      msg_print(out_val);
  1565. X    }
  1566. X    }
  1567. X  else
  1568. X    {
  1569. X      (void) sprintf(out_val, "You miss %s.", m_name);
  1570. X      msg_print(out_val);
  1571. X    }
  1572. X  if (randint(150) > py.stats.use_stat[A_DEX])
  1573. X    {
  1574. X      msg_print("You are off balance.");
  1575. X      py.flags.paralysis = 1 + randint(2);
  1576. X    }
  1577. X}
  1578. X
  1579. X
  1580. X/* Bash open a door or chest                -RAK-    */
  1581. X/* Note: Affected by strength and weight of character
  1582. X
  1583. X   For a closed door, p1 is positive if locked; negative if
  1584. X   stuck. A disarm spell unlocks and unjams doors!
  1585. X
  1586. X   For an open door, p1 is positive for a broken door.
  1587. X
  1588. X   A closed door can be opened - harder if locked. Any door might
  1589. X   be bashed open (and thereby broken). Bashing a door is
  1590. X   (potentially) faster! You move into the door way. To open a
  1591. X   stuck door, it must be bashed. A closed door can be jammed
  1592. X   (which makes it stuck if previously locked).
  1593. X
  1594. X   Creatures can also open doors. A creature with open door
  1595. X   ability will (if not in the line of sight) move though a
  1596. X   closed or secret door with no changes. If in the line of
  1597. X   sight, closed door are openned, & secret door revealed.
  1598. X   Whether in the line of sight or not, such a creature may
  1599. X   unlock or unstick a door.
  1600. X
  1601. X   A creature with no such ability will attempt to bash a
  1602. X   non-secret door. */
  1603. Xvoid bash()
  1604. X{
  1605. X  int y, x, dir, tmp;
  1606. X  register cave_type *c_ptr;
  1607. X  register inven_type *t_ptr;
  1608. X
  1609. X  y = char_row;
  1610. X  x = char_col;
  1611. X  if (get_dir(CNIL, &dir))
  1612. X    {
  1613. X      if (py.flags.confused > 0)
  1614. X    {
  1615. X      msg_print("You are confused.");
  1616. X      do
  1617. X        {
  1618. X          dir = randint(9);
  1619. X        }
  1620. X      while (dir == 5);
  1621. X    }
  1622. X      (void) mmove(dir, &y, &x);
  1623. X      c_ptr = &cave[y][x];
  1624. X      if (c_ptr->cptr > 1)
  1625. X    {
  1626. X      if (py.flags.afraid > 0)
  1627. X        msg_print("You are afraid!");
  1628. X      else
  1629. X        py_bash(y, x);
  1630. X    }
  1631. X      else if (c_ptr->tptr != 0)
  1632. X    {
  1633. X      t_ptr = &t_list[c_ptr->tptr];
  1634. X      if (t_ptr->tval == TV_CLOSED_DOOR)
  1635. X        {
  1636. X          count_msg_print("You smash into the door!");
  1637. X          tmp = py.stats.use_stat[A_STR] + py.misc.wt / 2;
  1638. X          /* Use (roughly) similar method as for monsters. */
  1639. X          if (randint(tmp*(20+abs(t_ptr->p1))) < 10*(tmp-abs(t_ptr->p1)))
  1640. X        {
  1641. X          msg_print("The door crashes open!");
  1642. X          invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
  1643. X          t_ptr->p1 = 1 - randint(2); /* 50% chance of breaking door */
  1644. X          c_ptr->fval = CORR_FLOOR;
  1645. X          if (py.flags.confused == 0)
  1646. X            move_char(dir, FALSE);
  1647. X          else
  1648. X            lite_spot(y, x);
  1649. X        }
  1650. X          else if (randint(150) > py.stats.use_stat[A_DEX])
  1651. X        {
  1652. X          msg_print("You are off-balance.");
  1653. X          py.flags.paralysis = 1 + randint(2);
  1654. X        }
  1655. X          else if (command_count == 0)
  1656. X        msg_print("The door holds firm.");
  1657. X        }
  1658. X      else if (t_ptr->tval == TV_CHEST)
  1659. X        {
  1660. X          if (randint(10) == 1)
  1661. X        {
  1662. X          msg_print("You have destroyed the chest.");
  1663. X          msg_print("and its contents!");
  1664. X          t_ptr->index = OBJ_RUINED_CHEST;
  1665. X          t_ptr->flags = 0;
  1666. X        }
  1667. X          else if ((CH_LOCKED & t_ptr->flags) && (randint(10) == 1))
  1668. X        {
  1669. X          msg_print("The lock breaks open!");
  1670. X          t_ptr->flags &= ~CH_LOCKED;
  1671. X        }
  1672. X          else
  1673. X        count_msg_print("The chest holds firm.");
  1674. X        }
  1675. X      else 
  1676. X        /* Can't give free turn, or else player could try directions
  1677. X           until he found invisible creature */
  1678. X        msg_print("You bash it, but nothing interesting happens.");
  1679. X    }
  1680. X      else
  1681. X    {
  1682. X      if (c_ptr->fval < MIN_CAVE_WALL)
  1683. X        msg_print("You bash at empty space.");
  1684. X      else
  1685. X        /* same message for wall as for secret door */
  1686. X        msg_print("You bash it, but nothing interesting happens.");
  1687. X    }
  1688. X    }
  1689. X}
  1690. END_OF_FILE
  1691. if test 31210 -ne `wc -c <'source/moria4.c'`; then
  1692.     echo shar: \"'source/moria4.c'\" unpacked with wrong size!
  1693. fi
  1694. # end of 'source/moria4.c'
  1695. fi
  1696. echo shar: End of archive 15 \(of 39\).
  1697. cp /dev/null ark15isdone
  1698. MISSING=""
  1699. 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
  1700.     if test ! -f ark${I}isdone ; then
  1701.     MISSING="${MISSING} ${I}"
  1702.     fi
  1703. done
  1704. if test "${MISSING}" = "" ; then
  1705.     echo You have unpacked all 39 archives.
  1706.     echo "Now run "bldfiles.sh" to build split files"
  1707.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1708. else
  1709.     echo You still need to unpack the following archives:
  1710.     echo "        " ${MISSING}
  1711. fi
  1712. ##  End of shell archive.
  1713. exit 0
  1714.