home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume14 / umoria4 / part28 < 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: v14i060:  umoria4 - single player dungeon simulation (ver. 5.5), Part28/39
  5. Message-ID: <3424@master.CNA.TEK.COM>
  6. Date: 22 Aug 92 22:13:51 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1959
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: grabiner@math.harvard.edu (David Grabiner)
  12. Posting-number: Volume 14, Issue 60
  13. Archive-name: umoria4/Part28
  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 28 (of 39)."
  26. # Contents:  doc/FEATURES.NEW misc/rick.msg util/mc/creature.y
  27. # Wrapped by billr@saab on Thu Aug 20 09:11:33 1992
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'doc/FEATURES.NEW' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'doc/FEATURES.NEW'\"
  31. else
  32. echo shar: Extracting \"'doc/FEATURES.NEW'\" \(11714 characters\)
  33. sed "s/^X//" >'doc/FEATURES.NEW' <<'END_OF_FILE'
  34. X
  35. XYou get a warning for spells or prayers beyond your strength.
  36. X
  37. XInventory commands (wear, wield, exchange, take off, drop) now always
  38. Xtake one move each. If anything significant happens during that move,
  39. Xsuch as a monster moving somewhere, the screen will be redisplayed.
  40. XInventories are displayed in the top-right corner of the screen, to minimize
  41. Xthe number of characters that must be redrawn afterwards, this makes the game
  42. Xmuch more playable on slow speed modems.
  43. X
  44. XWhen selecting items or spells, you can select with a capital letter to
  45. Xprint a description and confirm you really want that one.
  46. X
  47. XYou can now associate counts with commands. The '?' command shows you
  48. Xthe possibilities. In rogue command mode, simply type in the number.
  49. XIn this mode, numbers are no longer simple commands.
  50. XIn original moria command mode, enter a '#' to start a count.
  51. X
  52. XThere are options (set with the = command) to display weights in
  53. Xan inventory, to highlight mineral seams, to ignore open doors
  54. Xwhile running, etc.
  55. X
  56. XMonster memory: use the / command to access info about a monster after you
  57. Xhave seen/killed at least one of them.    This can also be accessed from
  58. Xthe look 'l' command.
  59. X
  60. XCan enter control characters with two keystrokes using ^ key, useful for
  61. Xnoisy phone lines? or stupid terminals?
  62. X
  63. X'M'ap command shows reduced size map.  'L' allows you to scroll around entire
  64. Xmap.  The 'L' command also will now center the character on the screen.
  65. X
  66. XLook 'l' views all objects in an arc in the specified direction, or specify
  67. X'5' and it will look in every direction.
  68. X
  69. XCan change your speed in wizard mode.
  70. X
  71. XNew field in status line, used for rest/paralysed/searching/repeat counts.
  72. X
  73. XNew field in status line shows speed.
  74. X
  75. XCan die of starvation.
  76. X
  77. XIf carrying too much weight, you will be slowed immediately, the amount slowed
  78. Xdepends on how much over the weight limit you are.
  79. X
  80. XCan not circle monsters (moving at the same speed as yourself)
  81. Xby moving around them in a diamond pattern.
  82. X
  83. XHigh level monsters have a chance of ignoring your bash, and they also have
  84. Xa chance of recovering immediately even if stunned.  You can not bash the
  85. XBalrog.
  86. X
  87. XCan abort rest/repeated command by hitting any character.
  88. X
  89. XEvery duration affect prints a command when it wears off previously
  90. Xresist heat and resist cold, and perhaps others did not.
  91. X
  92. XNew find/run algorithm which is much better than the old one.  Also,
  93. Xbetter handling of dangerous conditions that occur during repeat commands/runs.
  94. XAn attack will always stop a repeated command and find/run mode.
  95. X
  96. XCan inscribe names onto objects.  Some inscriptions are automatic:
  97. Xan empty wand/staff is inscribed 'empty'.  An object which is used, but its
  98. Xuse does not identify it is inscribed 'tried'.    Cursed objects are inscribed
  99. X'damned' when identified as cursed.  If you detect an object is enchanted,
  100. Xit is inscribed 'magik'.
  101. X
  102. XScrolls have their titles removed after being identified.  Scrolls/potions
  103. Xfrom the store/dungeon can stack after the dungeon item is identified.
  104. X
  105. XIf you curse/damage a special object, such as a Holy Avenger sword, it
  106. Xwill lose its special property.
  107. X
  108. XWill automatically save the game correctly if a HANGUP signal is received,
  109. Xi.e. dropped dialup connection, the network crashes, etc.  The save file
  110. Xis not a panic save, instead the program plays the game for you (i.e.
  111. Xpretends that you are hitting ESCAPE) until it is safe to save the game.
  112. X
  113. XBetter handling of inventory/equipment lists, i.e. you can drop items
  114. Xin the equipment list, can identify items in the equipment list, etc.
  115. X
  116. XMore consistent monster definitions, i.e. creatures with frost attacks
  117. Xalways take extra damage from fire (except those that also have fire
  118. Xattacks), and many other fixes.
  119. X
  120. XOne source for the UNIX/IBM/Atari ST/Amiga/Mac/VMS versions, should make
  121. Xkeeping the micro versions up-to-date much easier.  The game is smaller and
  122. Xhopefully faster.  Savefiles are now relatively machine independent, they
  123. Xshould transport from one mini/micro to another without any problems.
  124. X
  125. XIf you are hallucinating, ^R won't help.
  126. X
  127. XBows can have a pluses to damage.  These pluses only apply if you are
  128. Xusing the bow to fire the appropriate type of missile (arrow/bolt/etc).
  129. X
  130. XCan haggle incrementally in the stores, i.e. can increase bid by 10
  131. Xby typing +10, similarly -10 will decrease bid by 10.
  132. X
  133. XBeeps if invalid character entered at most prompts.
  134. X
  135. XCan type ^R at any time to refresh the screen.
  136. X
  137. XArmor/weapons show their base AC/hit/dam values in their name.
  138. X
  139. XAny of RETURN (^M), LF (^J), SPACE, or ESCAPE can be typed at -more- prompts.
  140. X
  141. XWhen droping a group of items, you have the choice of dropping only one,
  142. Xor all of them.
  143. X
  144. XThere is a small chance that a player will notice that there are unidentified
  145. Xmagic items in the inventory.  The chance is larger if the item is in the
  146. Xequipment list.
  147. X
  148. XObject distribution has been changed so that when you are deep in the dungeon,
  149. Xthere are many more high level objects created than low level objects.
  150. X
  151. XMonster distribution changed so that when you are deep in the dungeon,
  152. Xyou will meet many more high level monsters than low level monsters.
  153. X
  154. XAdditional spikes make a door harder to open, in a progressively decreasing
  155. Xsequence, that is, the more spikes you add, the less effect each additional
  156. Xspike has.
  157. X
  158. XWhen a stat changes, all abilities/etc that depend on the stat will immediately
  159. Xchange.     For example, if you CON increases, then your hit points will increase,
  160. Xif your INT/WIS increases then your mana will immediately increase and you
  161. Xwill immediately learn new spells/prayers.  This makes the Grape Jelly trick
  162. Xcompletely unnecessary, and, in fact, it will has no effect.
  163. X
  164. XSpell/prayer letters never change, i.e. if you know the second spell of a book,
  165. Xit will not be referred to as spell 'a' if you do not know the first spell.
  166. X
  167. XWhen haggling, if you have reach the final offer much more often than you
  168. Xhaven't, then the store will give you the benefit of the doubt and go
  169. Xdirectly to the final price.  The exact formula is (good > 3*bad + 20).
  170. XTwo sets of numbers are kept for every store, one for buying and one for
  171. Xselling.
  172. X
  173. XWhen wielding a weapon that is too heavy, the to hit penalty will be shown
  174. Xby the 'C' command.
  175. X
  176. XIt is harder to hit monsters when you can't see them.
  177. X
  178. XPerfect stealth is impossible now.
  179. X
  180. XSave files are now encrypted.
  181. X
  182. XSlay monster items are now slay animal.  The previous slay monster item
  183. Xdid not work as stated by the documentation, fixing it to work reasonably
  184. Xwould have made it too powerful.
  185. X
  186. XIf picking up an item will slow you down, you are asked if you really want
  187. Xto pick it up.
  188. X
  189. XSpells work differently now.  You no longer learn them automatically when
  190. Xyou gain a level.  Instead, 'Study' appears in the status line when are
  191. Xcapable of learning new spells.  Use the 'G' command to actually learn
  192. Xthe spells.  The 'G' command can be used anytime that you are eligible to
  193. Xlearn new spells, as for example, after quaffing a restore intelligence/wisdom
  194. Xpotion.
  195. X
  196. XThe object naming routines are completely rewritten.  This makes the program
  197. Xmuch smaller.  Also, too long names will no longer cause a crash or error,
  198. Xthey will be silently truncated as necessary.
  199. X
  200. XYou can not attack an invisible/unlit monster in a wall by merely moving
  201. Xinto the wall, instead you must tunnel into the wall.  Since moving into
  202. Xa wall is a free turn, people could take advantage of this while fighting
  203. Xinvis monsters by checking all of the walls first.
  204. X
  205. XTo change the default moria save file name, define the environment variable
  206. X"MORIA_SAV" to be the full pathname for where you want your save files.
  207. X
  208. X"moria -n" will start a new game, and will ignore "moria.save" if it exists
  209. X
  210. XJellies and molds never carry treasure.
  211. X
  212. XRecharging a high level wand, or a wand which already has many charges, is
  213. Xmuch more likely to fail.
  214. X
  215. XElves and half-elves have infravision now.
  216. X
  217. XThere is no longer a distinction between wizard and god mode; only wizard mode
  218. Xexists now.  Also, wizard mode no longer requires a password, and anyone
  219. X(not just the installer) can enter wizard mode.  Hence, wizard now works the
  220. Xsame no matter whether you are playing on a micro or a mini.  Enter wizard
  221. Xmode by using the ^W command, help is ^H. (Or for the rogue-like option,
  222. X^W and \).
  223. X
  224. XMissile weapons are much more powerful when used with the proper weapon.
  225. XFor example, firing a bolt from a heavy crossbow multiplies its damage by 4.
  226. Xrounded pebble, iron shot: sling = 2x
  227. Xarrow: short bow = 2x, long bow = 3x, composite bow = 4x
  228. Xbolt: light crossbow = 3x, heavy crossbow = 4x
  229. XArrows and bolts appear more often deep in the dungeon.
  230. XMagical missile weapon prices are more reasonable.
  231. X
  232. XThe miscellaneous abilities 'fighting', 'bows/throw', 'saving throw', 'disarm',
  233. Xand 'magical device' are all level dependent, i.e. they improve as you gain
  234. Xlevels.  Formerly, the rate of improvement was independent of class, now,
  235. Xhowever, the learning rate is clas dependent.  For example, warriors gain
  236. Xproficiency at fighting twice as fast as mages/priests now.  As a result,
  237. Xhigh level warriors are better fighters than before, and high level
  238. Xmages/priests do not fight as well as they used to.  The complete table is:
  239. X                  Magic         Saving
  240. X         Fighting  Bows  Devices  Disarm  Throw
  241. XWarrior        4    4    2    2    3
  242. XMage        2    2    4    3    3
  243. XPriest        2    2    4    3    3
  244. XRogue        3    4    3    4    3
  245. XRanger        3    4    3    3    3
  246. XPaladin        3    3    3    2    3
  247. XIn all cases, three is equivalent to the old rate.
  248. X
  249. Xumoria now understands tilde (~) characters at the start of a file name.
  250. X
  251. XTo resurrect a dead character, use "moria -w filename".
  252. X
  253. XNew status line shows "Is wizard" if in wizard mode, "Was wizard" if
  254. Xpreviously was in wizard mode, "Resurrected" if character was resurrected,
  255. Xand "Duplicate" if character is already on the scoreboard.
  256. X
  257. XMoved see invisible from slay animal to slay undead, since this makes a lot
  258. Xmore sense.
  259. X
  260. XDragon lightning breath attacks can now damage items in your inventory,
  261. Xjust like all other dragon breath attacks.
  262. X
  263. XNew scoreboard code added.  It will hold 1000 scores by default, scores for
  264. Xsaved characters are listed, can see all scores or just your scores.
  265. XOn multiuser OS's, each user can only have one entry in the scoreboard for
  266. Xeach legal race/sex/class combination.  The score file format is portable,
  267. Xand should be able to move from one machine to another with no problems.
  268. X
  269. XThe '-s' option will show all scores in the scoreboard.  The '-S' option
  270. Xwill show only your scores.  The 'V' command will show all scores in the
  271. Xscoreboard.  A second 'V' command typed immediately afterwards will show
  272. Xonly your scores.
  273. X
  274. XTyping '*' for the rest count will make you rest until you reach max mana
  275. Xand max hp.
  276. X
  277. XSpikes can now be wielded as a weapon for completeness.  Note however that
  278. Xthey make terrible weapons.
  279. X
  280. XThe damage multiplier for bows is now displayed as part of their name.
  281. X
  282. XTwo new '=' command options: can turn off sound, and can turn off the rest/
  283. Xrepeat counts displayed on the bottom line.  The last is useful for those
  284. Xplaying at 2400 baud or less, or on very slow machines.
  285. X
  286. XMany items are now added to the inventory in a sorted position, e.g.
  287. Xthe spell books will always end up in the inventory sorted by their level.
  288. XThis automatic sorting does not work for objects which have a 'color',
  289. Xe.g. potions, wands, staffs, scrolls.
  290. X
  291. XTyping RETURN while haggling will default to the last increment/decrement
  292. Xamount used.
  293. X
  294. XUmoria 5.4:
  295. X
  296. XPrints multiple sentences on the message line if they are short enough.
  297. X
  298. XUmoria 5.5:
  299. X
  300. XThe maximum damage enchantment for a weapon is now equal to its maximum
  301. Xdamage, instead of being fixed at 10 (there is a slight chance of
  302. Xenchantment beyond this level); thus daggers are no longer the best
  303. Xweapons for mid-level characters.
  304. X
  305. Xlast modified 8/12/92
  306. END_OF_FILE
  307. if test 11714 -ne `wc -c <'doc/FEATURES.NEW'`; then
  308.     echo shar: \"'doc/FEATURES.NEW'\" unpacked with wrong size!
  309. fi
  310. # end of 'doc/FEATURES.NEW'
  311. fi
  312. if test -f 'misc/rick.msg' -a "${1}" != "-c" ; then 
  313.   echo shar: Will not clobber existing file \"'misc/rick.msg'\"
  314. else
  315. echo shar: Extracting \"'misc/rick.msg'\" \(14612 characters\)
  316. sed "s/^X//" >'misc/rick.msg' <<'END_OF_FILE'
  317. XFrom 18862246%VUVAXCOM.BITNET@lilac.berkeley.edu Thu Aug 24 13:11:19 1989
  318. XReceived: from lilac.Berkeley.EDU by ernie.Berkeley.EDU (5.61/1.36)
  319. X    id AA06320; Thu, 24 Aug 89 13:11:14 -0700
  320. XReceived: by lilac.berkeley.edu (5.61.1/1.16.22)
  321. X    id AA05399; Thu, 24 Aug 89 12:47:05 PDT
  322. XMessage-Id: <8908241947.AA05399@lilac.berkeley.edu>
  323. XDate:     Thu, 24 Aug 89 15:41 EST
  324. XFrom: "Computers and you, living life a bit at a time"
  325. X          <188622462%VUVAXCOM.bitnet@lilac.berkeley.edu>
  326. XSubject:  Here is the UPDATE.TXT file
  327. XTo: wilson@ernie.Berkeley.EDU
  328. XOriginal_To:  BITNET%"wilson@ucbernie"
  329. XStatus: RO
  330. X
  331. X
  332. XHere are the changes incorporated to date in the upgrade from V5.0 to V6.0:
  333. X
  334. X    o The source code has been converted from a %INCLUDE format to modular
  335. X      programs.  Due to low system memory quotas set on student accounts at my
  336. X      university, compiling the %INCLUDE form was not possible.  By converting
  337. X      to modular form, anyone with enough disk space can compile the program,
  338. X      by compiling each module separately, and then linking all the files
  339. X      together.  Along with this, I also changed all the indentation in the
  340. X      code so that it is uniform throughout, something that was not there from
  341. X      having four or more different people work on it before.
  342. X
  343. X    o Creation of a new high score list.  Early in Moria's time at my node,
  344. X      many people had found out the Wizard mode password (this was for version
  345. X      4.3 and then 4.8), so I have created a Wizard Mode Top Twenty list. Part
  346. X      of this has been creating 2 new fields in the player character record to
  347. X      enable Moria to remember if your character ever entered Wizard or God
  348. X      modes.  If you used Wizard mode at any point, you are eligible for the
  349. X      Wizard mode list, if you used God mode, you can't get on any list.  If
  350. X      you die and aren't allowed to go to either of the lists, the game does
  351. X      tell you what score you earned.
  352. X
  353. X    o A second effect of everyone here knowing the Wizard password was the
  354. X      continual resurrection of characters by copying the save file and re-
  355. X      storing the character.  This lead to multiple copies of the same
  356. X      character appearing on the high score lists.  I have solved this problem
  357. X      by adding two more new fields to the character record, to keep track of
  358. X      the birthdate and birthtime of the character, taken from the system time
  359. X      at the same point that the stats are rolled.  When a character dies, his
  360. X      birthdate/time is recorded in the highscore file, and whenever that same
  361. X      userid kills another character, it checks to see if the birthdate/times
  362. X      match, if so, then it assumes a clone, and doesn't post the score to the
  363. X      list.  The game does tell you what you had earned in this case.
  364. X
  365. X    o The game now saves the userid of the character's creator in the
  366. X      save file.  This prevents one person making a strong character, then
  367. X      giving it to someone else to use to finish off the Balrog.
  368. X
  369. X    o The increase of stats via special items (ie: HA increasing strength) and
  370. X      via Gain potions has been re-worked.  Increase stat items (weapons,
  371. X      rings, crowns, amulets, armor) now affects only the current value of the
  372. X      stat, not the max value.  Gain potions affect the max and the current,
  373. X      based on the max value.  If you are close to 18/100 and the item would
  374. X      increase you past that, you will see a drop in the current value of the
  375. X      stat when you take it off, but a Restore potion will return you to what
  376. X      it was before you wielded/wore the item.
  377. X
  378. X    o The changing of the cost of an item has been repaired where an increase
  379. X      to the tohit and todam values are concerned.  Also, changes have been
  380. X      implemented wherever items are damaged, so that the shops will know of
  381. X      their decreased value.
  382. X
  383. X    o The Vampire Bites attack has been modified.  Originally, you lost the
  384. X      same amount (or close to it) of hit points as you did experience points
  385. X      (which could be from 18d8 to 32d8, depending on the type of Vampire).
  386. X      The Vampire Bite now takes off 1d6 hit points (logic: you bleed a bit).
  387. X
  388. X    o The stats area (left side of screen) has been fixed in regards to field
  389. X      widths.  All fields, when re-printed, wipe out any extra digits from the
  390. X      previous value.  If you have more than 9,999,999 in gold, the string
  391. X      "$$$$$$$" is printed.  If more than 9,999,999 experience points are
  392. X      earned, the string "*******" is printed.  If you have more than 999 mana
  393. X      then the string "###/###" will be printed.
  394. X
  395. X    o The God mode function ^C (Make Nice Character) now checks to see if the
  396. X      character is a Magic-using type (ie: not Warrior or Rogue) before upping
  397. X      the mana score.  The God function ^E (Change Character) does the same.
  398. X
  399. X    o A new wizard function: Describe Object.  This will give you information
  400. X      about the item specified, including Damage, Tohit and ToDam adjustments,
  401. X      weight, and others.  This will not identify an unidentified item, only
  402. X      help you in figuring out if one item is better than another (ie: which
  403. X      sword does more damage?).  The hex flags for the item in question will
  404. X      be translated to show what special magic is inherit in the item.
  405. X
  406. X    o A new God Mode function, ^X, Examine Character.  This prints out all the
  407. X      values of the Flags section of the player character record.  Useful in
  408. X      debugging purposes.
  409. X
  410. X    o A bug with Search mode and going up/down stairs has been fixed.  When
  411. X      using stairs, Search mode is turned off (if it was on) and the relevant
  412. X      reduction in speed is removed.
  413. X
  414. X    o All code referring to the "Consultant" classes and the "Extra" spells
  415. X      group have been removed, since a) they were written, but no character
  416. X      race was allowed to be one and b) they were simply slight modifications
  417. X      on the mage class.
  418. X
  419. X    o In the source, there were two people who used their initials as parts of
  420. X      variable names.  These have all been changed to more descriptive names.
  421. X
  422. X    o The Town generation code has been fixed so that any store could appear
  423. X      at any of the locations, instead of the Black Market always appearing in
  424. X      the upper right-hand corner.  The code there has also been fixed so that
  425. X      adding in additional stores should not be difficult.
  426. X
  427. X    o The various spell books have been fixed so that multiple copies will be
  428. X      listed as "a) 2 Books of <whatever>" in the inventory list.
  429. X
  430. X    o The running of the Black Market has been fixed up so that it works more
  431. X      like the other stores, except store inventory turn-around is still as
  432. X      as fast as it was before.  The inventory will now flucuate in size, just
  433. X      as the other stores do.
  434. X
  435. X    o A bug involving the Wizard Mode Light Dungeon function and using a torch
  436. X      has been repaired so that the tunnel floors remain lit after passing
  437. X      over them.
  438. X
  439. X    o Caps/Helms of Intelligence/Wisdom bought in the Black Market now
  440. X      correctly increase the relevant stat.
  441. X
  442. X    o A bug involving certain area-affect spells (Light Area, any Ball-type
  443. X      spell, etc) and the right-hand and bottom edges of the town level has
  444. X      been fixed.
  445. X
  446. X    o The magic translation case statements in SCROLLS.PAS and POTIONS.PAS
  447. X      has been fixed to allow a full set of both to be used.  Previously,
  448. X      each one was coming up short of the 64 actual possible slots that are
  449. X      available by using two Tval values.
  450. X
  451. X    o The problem with the special Magic and Prayer books from the Black
  452. X      Market has been fixed so that they appear as separate items in your
  453. X      inventory and are not added with the normal books.
  454. X
  455. X    o The bug concerning enchanting items bought from the Black Market and the
  456. X      new values never being seen was been repaired, so that the name string
  457. X      of the item will be displayed properly.
  458. X
  459. X    o The Control-Y exit command has been changed so the user has to hit Q to
  460. X      exit instead of Y.  This is to make it more fool-proof and more accident
  461. X      proof (but not totally).
  462. X
  463. X    o Three new monster attacks: Lose Mana (different from the monster spell),
  464. X      Slip, Trip, and Fall (you'll find out), and Eclipse attack.  A number of
  465. X      new attack descriptions have been added with this.  A new function was
  466. X      added, function DEX_ADJ, to determine the character's plus or minus to
  467. X      his dexterity saving throw.
  468. X
  469. X    o New monsters have found their way into the Dungeons of Moria.  A list of
  470. X      their names can be found in the file MONSTERS.NEW, included in the
  471. X      distribution package (or from your local Moria Wizard).
  472. X
  473. X    o The creatures "Mother & Baby" and "Small Girl" have been fixed to
  474. X      correctly utilize the CDEFENSE flag of Lose Experience for killing that
  475. X      creature.
  476. X
  477. X    o The global constant store$turn_around has been changed to the global
  478. X      array variable store_turnaround, allowing each store to have a different
  479. X      inventory turn over rate.  This was done partially to work the Black
  480. X      Market in more properly.
  481. X
  482. X    o A bug involving the running function ('.' and a direction) has been
  483. X      fixed so that if you are attacked in any form, either via a physical
  484. X      hit or a spell, you will stop running at that point.
  485. X
  486. X    o New monster defense: cloning on death.  A new value has been added to
  487. X      the CDEFENSE flag so that certain monsters can try to clone themselves
  488. X      when they have been dealt a mortal blow.  There are four types of
  489. X      cloning, each giving a different base chance to clone.  The chance is
  490. X      reduced based on how badly killed the creature is (if you "neutronize"
  491. X      the critter, he isn't as likely to clone himself).
  492. X
  493. X    o The \ function has been fixed up a bit, mainly in formatting control,
  494. X      with an added piece to watch for the end of the screen and page it out
  495. X      as needed.  Also, it has been renamed to ^U, and is now a Wizard mode
  496. X      function, just as creating the Monster Dictionary is.
  497. X
  498. X    o The Create Food spell/scroll has been fixed.  If an item is under you
  499. X      when you cast/read this spell, it will not be deleted as it was doing
  500. X      before.  Make sure you have a open space of floor under or around you,
  501. X      or you may go hungry...
  502. X
  503. X    o The Medusa has been fixed so that it's gaze causes Turn to Stone, not
  504. X      Vampire Bite.
  505. X
  506. X    o Added a new flag to the monster's spell flags.  A creature can now be
  507. X      set up so that only a percentage of that type of creature will be spell
  508. X      casters, assuming the type has any spell ability at all.  For example,
  509. X      the Young Blue Dragon could be set up so that only 1 in 10 Young Blue
  510. X      Dragons can cast spells at all.  This does not effect Dragon Breath
  511. X      attacks, only spell ability.  If a zero or one is in this position,
  512. X      all members of that creature type can cast spells, if any are indicated.
  513. X
  514. X
  515. XFrom 18862246%VUVAXCOM.BITNET@lilac.berkeley.edu Thu Aug 31 06:10:59 1989
  516. XReceived: from lilac.Berkeley.EDU by ernie.Berkeley.EDU (5.61/1.36)
  517. X    id AA14710; Thu, 31 Aug 89 06:10:54 -0700
  518. XReceived: by lilac.berkeley.edu (5.61.1/1.16.22)
  519. X    id AA04291; Thu, 31 Aug 89 05:54:29 PDT
  520. XMessage-Id: <8908311254.AA04291@lilac.berkeley.edu>
  521. XDate:     Thu, 31 Aug 89 08:51 EST
  522. XFrom: "Charon, the Ferryman on the River Styx"
  523. X          <188622462%VUVAXCOM.bitnet@lilac.berkeley.edu>
  524. XSubject:  what to put for a subject?  I don't know...
  525. XTo: wilson@ernie.Berkeley.EDU
  526. XOriginal_To:  BITNET%"wilson@ucbernie"
  527. XStatus: RO
  528. X
  529. X
  530. XJim-
  531. X
  532. XI see what you mean about the up/down and the search flag thing.  What did
  533. Xyou add to the main dungeon procedure to fix this?
  534. X
  535. XAt the end of this letter, I've appended the dictionary descriptions of the
  536. X"Mother & Baby" and "Small Girl".  I've also include the piece from the
  537. Xmon_take_hit function that checks the appropriate bit in the monster cdefense
  538. Xflag.  I believe this was something written in for the 5.0 UB version, but
  539. XI'm not certain, so if you need more to be able to put it into yours, I can
  540. Xsend whatever you need.
  541. X
  542. XThat bug you mention could well be the result of someone diddling with the
  543. Xsources.  Off hand, I can think of one or two reasons they'd do something to
  544. Xthe monster-array parts, to save on memory usage, but the file-access goes
  545. Xway up the minute you do anything other than the orginial form, so you lose
  546. Xout in the end.  I'll keep my eye out, but I doubt if I'll ever see it happen
  547. Xhere.
  548. X
  549. XSounds like you and I, and the rest of the Usenet community, are in agreement
  550. Xthen.  We'll keep our two separate "schools" of Moria, and just share thoughts
  551. Xback and forth.
  552. X
  553. XNow if only the VM/CMS Moria porter would respond to my letter...
  554. X
  555. XCatch you later,
  556. X
  557. XRick
  558. X
  559. X
  560. X---excerpt from function mon_take_hit.  Insert within the section of if
  561. X   statement that has determined the monster has died.
  562. X   EXP is the player's current experience points.  LEV is the player's level.
  563. X   I1 is the amount of experience the creature is worth (I think it's a
  564. X   calculated value)
  565. X
  566. X                {Penalize player - subtract experience}
  567. X                if (uand (cdefense, %X'00000400') <> 0) then
  568. X                  begin
  569. X                    exp := exp - 10*lev;
  570. X                    if (exp < 0) then exp := 0;
  571. X                  end
  572. X                else
  573. X                  exp := exp + i1;
  574. X
  575. X
  576. X--------------------------------------------
  577. X  1  Mother and Baby                (p)
  578. X     Speed =  1  Level     =  0  Exp =     0
  579. X     AC    =  1  Eye-sight =  4  HD  =   1d1
  580. X     Creature harmed by cold.
  581. X     Creature harmed by fire.
  582. X     Creature harmed by poison.
  583. X     Creature harmed by acid.
  584. X     Creature harmed by stone-to-mud.
  585. X     Causes experience loss when killed
  586. X     Creature seen with Infra-Vision.
  587. X     Creature picks up objects.
  588. X--Spells/Dragon Breath =
  589. X--Movement =
  590. X     Moves and attacks normally.
  591. X     20% random movement.
  592. X     Can open doors.
  593. X--Creature attacks =
  594. X     Touches you for normal damage. (0d0)
  595. X--------------------------------------------
  596. X  2  Small Girl                     (p)
  597. X     Speed =  1  Level     =  0  Exp =     0
  598. X     AC    =  1  Eye-sight =  4  HD  =   1d1
  599. X     Creature harmed by cold.
  600. X     Creature harmed by fire.
  601. X     Creature harmed by poison.
  602. X     Creature harmed by acid.
  603. X     Creature harmed by stone-to-mud.
  604. X     Causes experience loss when killed
  605. X     Creature seen with Infra-Vision.
  606. X     Creature picks up objects.
  607. X--Spells/Dragon Breath =
  608. X--Movement =
  609. X     Moves and attacks normally.
  610. X     20% random movement.
  611. X     Can open doors.
  612. X--Creature attacks =
  613. X     Touches you for normal damage. (0d0)
  614. X--------------------------------------------
  615. X
  616. X
  617. END_OF_FILE
  618. if test 14612 -ne `wc -c <'misc/rick.msg'`; then
  619.     echo shar: \"'misc/rick.msg'\" unpacked with wrong size!
  620. fi
  621. # end of 'misc/rick.msg'
  622. fi
  623. if test -f 'util/mc/creature.y' -a "${1}" != "-c" ; then 
  624.   echo shar: Will not clobber existing file \"'util/mc/creature.y'\"
  625. else
  626. echo shar: Extracting \"'util/mc/creature.y'\" \(26665 characters\)
  627. sed "s/^X//" >'util/mc/creature.y' <<'END_OF_FILE'
  628. X/* util/mc/creature.y: a Moria creature definition compiler
  629. X *
  630. X * Copyright 1989 by Joseph Hall.
  631. X * All rights reserved except as stated below.
  632. X * This program may contain portions excerpted from Moria which are
  633. X * copyrighted by others.
  634. X *
  635. X * Jim Wilson and any other holders of copyright on substantial portions
  636. X * of Moria are granted rights to use, modify, and distribute this program
  637. X * as they see fit, so long as the terms of its use, modification and/or
  638. X * distribution are no less restrictive than those applying to Moria,
  639. X * version 5.0 or later, itself, and so long as this use is related to
  640. X * the further development of Moria.
  641. X *
  642. X * Anyone having any other use in mind for this code should contact the
  643. X * author at 4116 Brewster Dr., Raleigh NC 27606 (jnh@ecemwl.ncsu.edu).
  644. X */
  645. X
  646. X%{
  647. X#include <stdio.h>
  648. X#include <string.h>
  649. X#include <ctype.h>
  650. X#include <math.h>
  651. X
  652. X#ifdef ANSI_LIBS
  653. X#include <stdlib.h>
  654. X#else
  655. Xextern double atof();
  656. Xextern char *malloc();
  657. Xextern char *calloc();
  658. Xextern void free();
  659. X#endif
  660. X
  661. X#include "st.h"
  662. X
  663. X#ifndef TRUE
  664. X#define TRUE 1
  665. X#endif
  666. X
  667. X#ifndef FALSE
  668. X#define FALSE 0
  669. X#endif
  670. X
  671. X#define VERBOSE /* to turn on debugging output */
  672. X
  673. Xtypedef unsigned long  int32u;
  674. Xtypedef long           int32;
  675. Xtypedef unsigned short int16u;
  676. Xtypedef short          int16;
  677. Xtypedef unsigned char  int8u;
  678. X
  679. Xtypedef struct creature_type
  680. X{
  681. X  char *name;           /* Descrip of creature  */
  682. X  int32u cmove;         /* Bit field            */
  683. X  int32u spells;        /* Creature spells      */
  684. X  int16u cdefense;      /* Bit field            */
  685. X  int16u mexp;          /* Exp value for kill   */
  686. X  int8u sleep;          /* Inactive counter/10  */
  687. X  int8u aaf;            /* Area affect radius   */
  688. X  int8u ac;             /* AC                   */
  689. X  int8u speed;          /* Movement speed+10    */
  690. X  int8u cchar;          /* Character rep.       */
  691. X  int8u hd[2];          /* Creatures hit die    */
  692. X  int8u damage[4];      /* Type attack and damage*/
  693. X  int8u level;          /* Level of creature    */
  694. X
  695. X    int32u general;    /* general characteristics; not present in usual */
  696. X            /* moria creature_type */
  697. X} creature_type;
  698. X
  699. X
  700. X
  701. X/*
  702. X * defined_t is used to indicate whether all fields have been defined
  703. X */
  704. X
  705. Xtypedef struct {
  706. X    unsigned    move: 1,
  707. X        special: 1,
  708. X        treasure: 1,
  709. X        spell: 1,
  710. X        breath: 1,
  711. X        defense: 1,
  712. X        mexp: 1,
  713. X        sleep: 1,
  714. X        aaf: 1,
  715. X        ac: 1,
  716. X        speed: 1,
  717. X        cchar: 1,
  718. X        hd: 1,
  719. X        damage: 1,
  720. X        level: 1;
  721. X} defined_t;
  722. X
  723. X
  724. X
  725. X/*
  726. X * template_t contains creature definition & flags
  727. X */
  728. X
  729. Xtypedef struct {
  730. X    creature_type    val;
  731. X    defined_t    def;
  732. X} template_t;
  733. X
  734. X
  735. X
  736. X/*
  737. X * attack_t describes a monster attack
  738. X */
  739. X
  740. Xtypedef struct {
  741. X    int8u        type,
  742. X            desc,
  743. X            dice,
  744. X            sides;
  745. X} attack_t;
  746. X
  747. X
  748. X
  749. X/*
  750. X * symInit_t is used to initialize symbol tables with integer values
  751. X */
  752. X
  753. Xtypedef struct {
  754. X    char        *name;
  755. X    int32u        val;
  756. X} symInit_t;
  757. X
  758. X
  759. X
  760. Xstatic symInit_t defenseInit[] = {
  761. X    { "dragon", 0 },
  762. X    { "animal", 1 },
  763. X    { "evil", 2 },
  764. X    { "undead", 3 },
  765. X    { "frost", 4 },
  766. X    { "fire", 5 },
  767. X    { "poison", 6 },
  768. X    { "acid", 7 },
  769. X    { "light", 8 },
  770. X    { "stone", 9 },
  771. X    { "bit_9", 10 },
  772. X    { "bit_10", 11 },
  773. X    { "no_sleep", 12 },
  774. X    { "infra", 13 },
  775. X    { "max_hp", 14 },
  776. X    { "bit_15", 15 },
  777. X    { NULL, 0 }
  778. X};
  779. X
  780. Xstatic symInit_t moveInit[] = {
  781. X    { "attack_only", 0 },
  782. X    { "move_normal", 1 },
  783. X    { "bit_2", 2 },
  784. X    { "random_20", 3 },
  785. X    { "random_40", 4 },
  786. X    { "random_75", 5 },
  787. X    { NULL, 0 }
  788. X};
  789. X
  790. Xstatic symInit_t specialInit[] = {
  791. X    { "invisible", 16 },
  792. X    { "open_door", 17 },
  793. X    { "phase", 18 },
  794. X    { "eats_other", 19 },
  795. X    { "picks_up", 20 },
  796. X    { "multiply", 21 },
  797. X    { "win_creature", 31 },
  798. X    { NULL, 0 }
  799. X};
  800. X
  801. Xstatic symInit_t treasureInit[] = {
  802. X    { "carry_obj", 24 },
  803. X    { "carry_gold", 25 },
  804. X    { "has_random_60", 26 },
  805. X    { "has_random_90", 27 },
  806. X    { "has_1d2_obj", 28 },
  807. X    { "has_2d2_obj", 29 },
  808. X    { "has_4d2_obj", 30 },
  809. X    { NULL, 0 }
  810. X};
  811. X
  812. Xstatic symInit_t spellInit[] = {
  813. X    { "tel_short", 4 },
  814. X    { "tel_long", 5 },
  815. X    { "tel_to", 6 },
  816. X    { "lght_wnd", 7 },
  817. X    { "ser_wnd", 8 },
  818. X    { "hold_per", 9 },
  819. X    { "blind", 10 },
  820. X    { "confuse", 11 },
  821. X    { "fear", 12 },
  822. X    { "summon_mon", 13 },
  823. X    { "summon_und", 14 },
  824. X    { "slow_per", 15 },
  825. X    { "drain_mana", 16 },
  826. X    { "bit_17", 17 },
  827. X    { "bit_18", 18 },
  828. X    { NULL, 0 }
  829. X};
  830. X
  831. Xstatic symInit_t breathInit[] = {
  832. X    { "light", 19 },
  833. X    { "gas", 20 },
  834. X    { "acid", 21 },
  835. X    { "frost", 22 },
  836. X    { "fire", 23 },
  837. X    { NULL, 0 }
  838. X};
  839. X
  840. Xstatic symInit_t attackTypeInit[] = {
  841. X    { "normal_damage", 1 },
  842. X    { "lose_str", 2 },
  843. X    { "confusion", 3 },
  844. X    { "cause_fear", 4 },
  845. X    { "fire_damage", 5 },
  846. X    { "acid_damage", 6 },
  847. X    { "cold_damage", 7 },
  848. X    { "lightning_damage", 8 },
  849. X    { "corrosion", 9 },
  850. X    { "cause_blindness", 10 },
  851. X    { "cause_paralysis", 11 },
  852. X    { "steal_money", 12 },
  853. X    { "steal_obj", 13 },
  854. X    { "poison", 14 },
  855. X    { "lose_dex", 15 },
  856. X    { "lose_con", 16 },
  857. X    { "lose_int", 17 },
  858. X    { "lose_wis", 18 },
  859. X    { "lose_exp", 19 },
  860. X    { "aggravation", 20 },
  861. X    { "disenchant", 21 },
  862. X    { "eat_food", 22 },
  863. X    { "eat_light", 23 },
  864. X    { "eat_charges", 24 },
  865. X    { "blank", 99 },
  866. X    { NULL, 0 }
  867. X};
  868. X
  869. Xstatic symInit_t attackDescInit[] = {
  870. X    { "hits", 1 },
  871. X    { "bites", 2 },
  872. X    { "claws", 3 },
  873. X    { "stings", 4 },
  874. X    { "touches", 5 },
  875. X    { "kicks", 6 },
  876. X    { "gazes", 7 },
  877. X    { "breathes", 8 },
  878. X    { "spits", 9 },
  879. X    { "wails", 10 },
  880. X    { "embraces", 11 },
  881. X    { "crawls_on", 12 },
  882. X    { "releases_spores", 13 },
  883. X    { "begs_for_money", 14 },
  884. X    { "slimes", 15 },
  885. X    { "crushes", 16 },
  886. X    { "tramples", 17 },
  887. X    { "drools_on", 18 },
  888. X    { "insults", 19 },
  889. X    { "is_repelled", 99 },
  890. X    { NULL, 0 }
  891. X};
  892. X
  893. X
  894. X
  895. X
  896. X/*
  897. X * Maximum token length = maximum string constant length
  898. X * Also, trim the stack to an "acceptable" size.
  899. X */
  900. X
  901. X#define    MAX_TOK_LEN    64        /* maximum acceptable token length  */
  902. X#define    YYSTACKSIZE    128
  903. X
  904. X#define GEN_TYPE_TMPL    256        /* type of a template for st        */
  905. X
  906. X/*
  907. X * Globals used by the tokenizer (lexical analyzer)
  908. X */
  909. X
  910. X#define INPUT_BUF_SIZE 256
  911. Xstatic char    inputBuf[INPUT_BUF_SIZE] = { 0 };
  912. X                    /* input line buffer            */
  913. Xstatic char    *inputBufp = inputBuf;    /* position in input line buffer    */
  914. Xstatic int    lineNo = 0;        /* number of current line        */
  915. Xstatic FILE    *input_F;
  916. Xstatic char    tokStr[MAX_TOK_LEN];    /* text of current token        */
  917. Xstatic    int    tokType;        /* type of current token        */
  918. Xstatic    double    tokVal;            /* numeric value of current token,  */
  919. X                    /* if applicable            */
  920. X
  921. Xstatic template_t blankTemplate = { 0 }; /* blank template for init-ing     */
  922. Xstatic template_t tmpTemplate;        /* working template for current     */
  923. X                    /* class or creature            */
  924. X
  925. X#define MAX_ATTACK 250
  926. Xstatic attack_t attackList[MAX_ATTACK] = { 0 };
  927. Xstatic int attackCt = 1, creatureAttacks = 0;
  928. Xstatic int maxCreatureLevel = 0;
  929. X
  930. X/*
  931. X * Global symbol tables
  932. X */
  933. X
  934. Xstatic st_Table_Pt keywordT_P,        /* parser's keywords            */
  935. X        defenseT_P,        /* defense flags            */
  936. X        moveT_P,        /* movement flags            */
  937. X        specialT_P,        /* special flags            */
  938. X        treasureT_P,        /* treasure flags            */
  939. X        spellT_P,        /* spell flags                */
  940. X        breathT_P,        /* breath flags                */
  941. X        attackTypeT_P,        /* attack type flags            */
  942. X        attackDescT_P,        /* attack desc flags            */
  943. X        classT_P,        /* class templates            */
  944. X        creatureT_P;        /* creature definitions            */
  945. X
  946. X/*
  947. X * Function declarations
  948. X */
  949. X
  950. Xextern void AddDefense();
  951. Xextern void NegDefense();
  952. Xextern void AddMove();
  953. Xextern void NegMove();
  954. Xextern void AddTreasure();
  955. Xextern void NegTreasure();
  956. Xextern void AddSpecial();
  957. Xextern void NegSpecial();
  958. Xextern void AddSpell();
  959. Xextern void NegSpell();
  960. Xextern void AddBreath();
  961. Xextern void NegBreath();
  962. Xextern void AddAttack();
  963. Xextern void WriteCreature();
  964. Xextern void PutClassTemplate();
  965. Xextern template_t GetClassTemplate();
  966. Xextern void PutCreature();
  967. X
  968. X%}
  969. X
  970. X
  971. X/*
  972. X * YACC DEFINITIONS
  973. X */
  974. X
  975. X/*
  976. X * The parser's stack can hold ints, doubles, and strings.
  977. X */
  978. X
  979. X%union {
  980. X    int ival;
  981. X    double dval;
  982. X    char sval[MAX_TOK_LEN];
  983. X    }
  984. X
  985. X/*
  986. X * Reserved words
  987. X */
  988. X
  989. X%token CLASS CREATURE NAMED HD D MOVE SPELL BREATH DEFENSE XP CCHAR SLEEP
  990. X%token RADIUS SPEED ATTACK FOR AC LEVEL TREASURE SPECIAL OF IN
  991. X
  992. X/*
  993. X * Entities
  994. X */
  995. X
  996. X%token <sval> IDENTIFIER    /* identifier, not a keyword            */
  997. X%token <dval> FLOAT_LIT        /* floating-pt literal                */
  998. X%token <ival> INT_LIT        /* integer literal                */
  999. X%token <sval> STRING_LIT    /* string literal                */
  1000. X%token <ival> BOOL_LIT        /* boolean literal                */
  1001. X
  1002. X/*
  1003. X * ASCII chars are their own tokens
  1004. X */
  1005. X
  1006. X%start    creatures
  1007. X
  1008. X
  1009. X/*
  1010. X * THE PARSER
  1011. X */
  1012. X
  1013. X%%
  1014. X
  1015. Xcreatures    :    class_def ';' creatures
  1016. X        |    creature_def ';' creatures
  1017. X        |    /* empty */
  1018. X        ;
  1019. X
  1020. Xclass_def    :    CLASS IDENTIFIER parent_class '{' features '}'
  1021. X                { PutClassTemplate($<sval>2, &tmpTemplate); }
  1022. X        ;
  1023. X
  1024. Xparent_class    :    ':' IDENTIFIER
  1025. X                { tmpTemplate = GetClassTemplate($<sval>2);
  1026. X                  creatureAttacks = 0; }
  1027. X        |    /* empty */
  1028. X                { tmpTemplate = blankTemplate;
  1029. X                  creatureAttacks = 0; }
  1030. X        ;
  1031. X
  1032. Xcreature_def    :    CREATURE STRING_LIT parent_class
  1033. X            '{' features '}'
  1034. X                { tmpTemplate.val.name =
  1035. X                    (char *) malloc(strlen($<sval>2) + 1);
  1036. X                  strcpy(tmpTemplate.val.name, $<sval>2);
  1037. X                  PutCreature($<sval>2, &tmpTemplate);
  1038. X                }
  1039. X        ;
  1040. X
  1041. Xfeatures    :    feature ';' features
  1042. X        |    /* empty */
  1043. X        ;
  1044. X
  1045. Xfeature        :    LEVEL ':' INT_LIT
  1046. X                { tmpTemplate.val.level = $<ival>3;
  1047. X                  tmpTemplate.def.level = TRUE; }
  1048. X        |    HD ':' INT_LIT D INT_LIT
  1049. X                { tmpTemplate.val.hd[0] = $<ival>3;
  1050. X                  tmpTemplate.val.hd[1] = $<ival>5;
  1051. X                  tmpTemplate.def.hd = TRUE; }
  1052. X        |    XP ':' INT_LIT
  1053. X                { tmpTemplate.val.mexp = $<ival>3;
  1054. X                  tmpTemplate.def.mexp = TRUE; }
  1055. X        |    CCHAR ':' STRING_LIT
  1056. X                { tmpTemplate.val.cchar = $<sval>3[0];
  1057. X                  tmpTemplate.def.cchar = TRUE; }
  1058. X        |    AC ':' INT_LIT
  1059. X                { tmpTemplate.val.ac = $<ival>3;
  1060. X                  tmpTemplate.def.ac = TRUE; }
  1061. X        |    SLEEP ':' INT_LIT
  1062. X                { tmpTemplate.val.sleep = $<ival>3;
  1063. X                  tmpTemplate.def.sleep = TRUE; }
  1064. X        |    RADIUS ':' INT_LIT
  1065. X                { tmpTemplate.val.aaf = $<ival>3;
  1066. X                  tmpTemplate.def.aaf = TRUE; }
  1067. X        |    SPEED ':' INT_LIT
  1068. X                { tmpTemplate.val.speed = $<ival>3 + 10;
  1069. X                  tmpTemplate.def.speed = TRUE; }
  1070. X        |    ATTACK ':' attacks
  1071. X        |    MOVE ':' moves
  1072. X        |    SPELL ':' spells
  1073. X        |    SPELL INT_LIT '%' ':' spells
  1074. X                { float chance = 100.0 / $<ival>2;
  1075. X                  if (chance > 15.0)
  1076. X                      chance = 0.0;
  1077. X                  if (chance < 0.0)
  1078. X                      chance = 0.0;
  1079. X                  tmpTemplate.val.spells &= ~0xf;
  1080. X                  tmpTemplate.val.spells |=
  1081. X                      (int) ceil(chance);
  1082. X                  tmpTemplate.def.spell = TRUE; }
  1083. X        |    BREATH ':' breaths
  1084. X        |    BREATH INT_LIT '%' ':' breaths
  1085. X                { float chance = 100.0 / $<ival>2;
  1086. X                  if (chance > 15.0)
  1087. X                      chance = 0.0;
  1088. X                  if (chance < 0.0)
  1089. X                      chance = 0.0;
  1090. X                  tmpTemplate.val.spells &= ~0xf;
  1091. X                  tmpTemplate.val.spells |=
  1092. X                      (int) ceil(chance);
  1093. X                  tmpTemplate.def.spell = TRUE; }
  1094. X        |    DEFENSE ':' defenses
  1095. X        |    TREASURE ':' carries
  1096. X        |    SPECIAL ':' specials
  1097. X        ;
  1098. X
  1099. Xattacks        :    attack more_attacks
  1100. X        ;
  1101. X
  1102. Xattack        :    IDENTIFIER FOR INT_LIT D INT_LIT OF IDENTIFIER
  1103. X                { AddAttack($<sval>1, $<ival>3,
  1104. X                        $<ival>5, $<sval>7); }
  1105. X        ;
  1106. X
  1107. Xmore_attacks    :    ',' attack more_attacks
  1108. X        |    /* empty */
  1109. X        ;
  1110. X
  1111. Xmoves        :    move more_moves
  1112. X        ;
  1113. X
  1114. Xmove        :    IDENTIFIER { AddMove($<sval>1); }
  1115. X        |    '~' IDENTIFIER { NegMove($<sval>2); }
  1116. X        ;
  1117. X
  1118. Xmore_moves    :    ',' move more_moves
  1119. X        |    /* empty */
  1120. X        ;
  1121. X
  1122. Xspells        :    spell more_spells
  1123. X        |    /* empty */
  1124. X        ;
  1125. X
  1126. Xspell        :    IDENTIFIER { AddSpell($<sval>1); }
  1127. X        |    '~' IDENTIFIER { NegSpell($<sval>2); }
  1128. X        ;
  1129. X
  1130. Xmore_spells    :    ',' spell more_spells
  1131. X        |    /* empty */
  1132. X        ;
  1133. X
  1134. Xbreaths        :    breath more_breaths
  1135. X        ;
  1136. X
  1137. Xbreath        :    IDENTIFIER { AddBreath($<sval>1); }
  1138. X        |    '~' IDENTIFIER { NegBreath($<sval>2); }
  1139. X        ;
  1140. X
  1141. Xmore_breaths    :    ',' breath more_breaths
  1142. X        |    /* empty */
  1143. X        ;
  1144. X
  1145. Xdefenses    :    defense more_defenses
  1146. X        ;
  1147. X
  1148. Xdefense        :    IDENTIFIER { AddDefense($<sval>1); }
  1149. X        |    '~' IDENTIFIER { NegDefense($<sval>2); }
  1150. X        ;
  1151. X
  1152. Xmore_defenses    :    ',' defense more_defenses
  1153. X        |    /* empty */
  1154. X        ;
  1155. X
  1156. Xcarries        :    carry more_carries
  1157. X        ;
  1158. X
  1159. Xcarry        :    IDENTIFIER { AddTreasure($<sval>1); }
  1160. X        |    '~' IDENTIFIER { NegTreasure($<sval>2); }
  1161. X        ;
  1162. X
  1163. Xmore_carries    :    ',' carry more_carries
  1164. X        |    /* empty */
  1165. X        ;
  1166. X
  1167. Xspecials    :    special more_specials
  1168. X        ;
  1169. X
  1170. Xspecial        :    IDENTIFIER { AddSpecial($<sval>1); }
  1171. X        |    '~' IDENTIFIER { NegSpecial($<sval>2); }
  1172. X        ;
  1173. X
  1174. Xmore_specials    :    ',' special more_specials
  1175. X        |    /* empty */
  1176. X        ;
  1177. X
  1178. X
  1179. X%%
  1180. X
  1181. Xstatic symInit_t keywordInit[] = {
  1182. X    { "class", CLASS },
  1183. X    { "creature", CREATURE },
  1184. X    { "named", NAMED },
  1185. X    { "hd", HD },
  1186. X    { "d", D },
  1187. X    { "move", MOVE },
  1188. X    { "spell", SPELL },
  1189. X    { "breath", BREATH },
  1190. X    { "defense", DEFENSE },
  1191. X    { "xp", XP },
  1192. X    { "cchar", CCHAR },
  1193. X    { "sleep", SLEEP },
  1194. X    { "radius", RADIUS },
  1195. X    { "speed", SPEED },
  1196. X    { "attack", ATTACK },
  1197. X    { "for", FOR },
  1198. X    { "ac", AC },
  1199. X    { "level", LEVEL },
  1200. X    { "treasure", TREASURE },
  1201. X    { "special", SPECIAL },
  1202. X    { "of", OF },
  1203. X    { "in", IN },
  1204. X    { NULL, 0 }
  1205. X};
  1206. X
  1207. X
  1208. X
  1209. X/*
  1210. X * MyFGetC--
  1211. X *    fgetc with support for comments
  1212. X *
  1213. X *    # is the comment character.  comment lasts till end of line.
  1214. X * Spews out an extra char of whitespace at EOF since something seems to
  1215. X * need it.  I'll figure this out eventually...
  1216. X */
  1217. Xstatic int MyFGetC(input_F)
  1218. XFILE *input_F;
  1219. X{
  1220. X    static int atEof = FALSE;
  1221. X    while (!*inputBufp || (*inputBufp == '#')) {
  1222. X    fgets(inputBuf, INPUT_BUF_SIZE, input_F);
  1223. X        if (feof(input_F))
  1224. X        return EOF;
  1225. X    lineNo++;
  1226. X    inputBufp = inputBuf;
  1227. X    }
  1228. X    return *inputBufp++;
  1229. X}
  1230. X
  1231. X
  1232. X
  1233. X/*
  1234. X * Advance--
  1235. X *    Advance to the next token in the input stream and set tokStr,
  1236. X * tokType, tokVal as appropriate.
  1237. X *
  1238. X *    On error, tokType is set to a negative value.
  1239. X */
  1240. Xstatic void Advance(input_F)
  1241. XFILE *input_F;
  1242. X{
  1243. X
  1244. X    register char
  1245. X        *tok = tokStr;    /* accumulating token string            */
  1246. X    register int
  1247. X        len = 0;        /* length of current token            */
  1248. X    static int c = 32;        /* current character; ' ' is harmless init  */
  1249. X
  1250. X
  1251. X    /*
  1252. X     * Skip whitespace in the stream
  1253. X     */
  1254. X    while ((c != EOF) && isspace(c))
  1255. X    c = MyFGetC(input_F);
  1256. X
  1257. X    /*
  1258. X     * At end of file?
  1259. X     */
  1260. X    if (c == EOF) {
  1261. X    tokType = EOF;
  1262. X    strcpy(tokStr, "[EOF]");
  1263. X    return;
  1264. X    }
  1265. X
  1266. X    /*
  1267. X     * Recognize a number [+|-][dddd][.][dddd][{e|E}[+|-]dddd]
  1268. X     */
  1269. X    if (isdigit(c) || (c == '.') || (c == '+') || (c == '-')) {
  1270. X
  1271. X    register int
  1272. X        decPt = FALSE,        /* seen a decimal point yet?    */
  1273. X        hasExp = FALSE;        /* has an exponent?            */
  1274. X
  1275. X    if ((c == '-') || (c == '+')) {
  1276. X        *tok++ = c;
  1277. X        c = MyFGetC(input_F);
  1278. X    }
  1279. X
  1280. X    while ((len < MAX_TOK_LEN - 1) && (isdigit(c) || (c == '.'))) {
  1281. X        if (c == '.') {
  1282. X        if (decPt)
  1283. X            break;
  1284. X        else
  1285. X            decPt = TRUE;
  1286. X        }
  1287. X
  1288. X        *tok++ = c;
  1289. X        c = MyFGetC(input_F);
  1290. X        len++;
  1291. X    }
  1292. X
  1293. X    if ((c == 'e') || (c == 'E')) {
  1294. X        hasExp = TRUE;
  1295. X        *tok++ = c;
  1296. X        c = MyFGetC(input_F);
  1297. X        len++;
  1298. X
  1299. X        if ((c == '-') || (c == '+')) {
  1300. X        *tok++ = c;
  1301. X        c = MyFGetC(input_F);
  1302. X        len++;
  1303. X        }
  1304. X
  1305. X        while ((len < MAX_TOK_LEN - 1) && isdigit(c)) {
  1306. X        *tok++ = c;
  1307. X        c = MyFGetC(input_F);
  1308. X        len++;
  1309. X        }
  1310. X    }
  1311. X
  1312. X    *tok = 0;
  1313. X
  1314. X    if (decPt || hasExp) {
  1315. X        tokType = FLOAT_LIT;
  1316. X        yylval.dval = atof(tokStr);
  1317. X    } else {
  1318. X        tokType = INT_LIT;
  1319. X        yylval.ival = atoi(tokStr);
  1320. X    }
  1321. X
  1322. X    return;
  1323. X
  1324. X    }
  1325. X
  1326. X    /*
  1327. X     * Recognize a quoted string
  1328. X     */
  1329. X    if (c == '\"') {
  1330. X
  1331. X    c = MyFGetC(input_F);
  1332. X
  1333. X    while ((len < MAX_TOK_LEN - 1) &&
  1334. X                (c != EOF) && (c != '\n') && (c != '\"')) {
  1335. X        *tok++ = c;
  1336. X        c = MyFGetC(input_F);
  1337. X    }
  1338. X
  1339. X    *tok = 0;
  1340. X
  1341. X    c = MyFGetC(input_F);
  1342. X
  1343. X    tokType = STRING_LIT;
  1344. X    strncpy(yylval.sval, tokStr, MAX_TOK_LEN - 1);
  1345. X    yylval.sval[MAX_TOK_LEN - 1] = 0;
  1346. X
  1347. X    return;
  1348. X
  1349. X    }
  1350. X
  1351. X    /*
  1352. X     * Recognize an identifier and try to match it with a keyword.
  1353. X     * Identifiers begin with a letter and continue in letters and/or
  1354. X     * digits.  Convert it to lowercase.
  1355. X     */
  1356. X    if (isalpha(c) || (c == '_') || (c == '$')) {
  1357. X
  1358. X        if (isupper(c))
  1359. X      c = tolower(c);
  1360. X        *tok++ = c;
  1361. X    c = MyFGetC(input_F);
  1362. X    len++;
  1363. X
  1364. X    while ((len < MAX_TOK_LEN - 1) && (isalpha(c) || isdigit(c) ||
  1365. X                        (c == '_') || (c == '$'))) {
  1366. X        if (isupper(c))
  1367. X          c = tolower(c);
  1368. X        *tok++ = c;
  1369. X        c = MyFGetC(input_F);
  1370. X        len++;
  1371. X    }
  1372. X
  1373. X    *tok = 0;
  1374. X
  1375. X    /*
  1376. X     * We've got the identifier; see if it matches any keywords.
  1377. X     */
  1378. X
  1379. X    {
  1380. X        generic_t gval;
  1381. X        int type;
  1382. X        if (St_GetSym(keywordT_P, tokStr, &type, &gval) ==
  1383. X                                ST_SYM_FOUND) {
  1384. X            tokType = gval.i;
  1385. X                strncpy(yylval.sval, tokStr, MAX_TOK_LEN - 1);
  1386. X            yylval.sval[MAX_TOK_LEN - 1] = 0;
  1387. X        } else if (!strcmp(tokStr, "true")) {
  1388. X            tokType = BOOL_LIT;
  1389. X            yylval.ival = 1;
  1390. X        } else if (!strcmp(tokStr, "false")) {
  1391. X            tokType = BOOL_LIT;
  1392. X            yylval.ival = 0;
  1393. X        } else {
  1394. X            tokType = IDENTIFIER;
  1395. X            strncpy(yylval.sval, tokStr, MAX_TOK_LEN - 1);
  1396. X            yylval.sval[MAX_TOK_LEN - 1] = 0;
  1397. X        }
  1398. X    }
  1399. X
  1400. X    return;
  1401. X
  1402. X    }
  1403. X
  1404. X    /*
  1405. X     * Recognize punctuation
  1406. X     */
  1407. X
  1408. X    tokType = c;
  1409. X    *tok++ = c;
  1410. X    *tok = 0;
  1411. X    c = MyFGetC(input_F);
  1412. X    return;
  1413. X
  1414. X}
  1415. X
  1416. Xvoid ErrMsg(s)
  1417. Xchar *s;
  1418. X{
  1419. X    int i;
  1420. X
  1421. X    fprintf(stderr, "Error: %s at line %d\n", s, lineNo);
  1422. X    fprintf(stderr, "%s", inputBuf);
  1423. X    for (i = 0; i < inputBufp - inputBuf; i++) {
  1424. X        fputc((inputBuf[i] == '\t' ? '\t' : ' '), stderr);
  1425. X    }
  1426. X    fprintf(stderr, "^ before here\n\n");
  1427. X}
  1428. X
  1429. Xint yyerror(s)
  1430. Xchar *s;
  1431. X{
  1432. X    ErrMsg(s);
  1433. X}
  1434. X
  1435. X
  1436. Xint yylex()
  1437. X{
  1438. X    Advance(input_F);
  1439. X    return(tokType);
  1440. X}
  1441. X
  1442. Xvoid AddSpell(s)
  1443. Xchar *s;
  1444. X{
  1445. X    generic_t gval;
  1446. X    int type;
  1447. X    char s1[256];
  1448. X
  1449. X    if (St_GetSym(spellT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1450. X        sprintf(s1, "unknown spell '%s'", s);
  1451. X        ErrMsg(s1);
  1452. X    } else {
  1453. X        tmpTemplate.val.spells |= (1 << gval.i);
  1454. X        tmpTemplate.def.spell = TRUE;
  1455. X    }
  1456. X}
  1457. X
  1458. X
  1459. Xvoid NegSpell(s)
  1460. Xchar *s;
  1461. X{
  1462. X    generic_t gval;
  1463. X    int type;
  1464. X    char s1[256];
  1465. X
  1466. X    if (St_GetSym(spellT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1467. X        sprintf(s1, "unknown spell '%s'", s);
  1468. X        ErrMsg(s1);
  1469. X    } else {
  1470. X        tmpTemplate.val.spells &= ~(1 << gval.i);
  1471. X        tmpTemplate.def.spell = TRUE;
  1472. X    }
  1473. X}
  1474. X
  1475. X
  1476. Xvoid AddBreath(s)
  1477. Xchar *s;
  1478. X{
  1479. X    generic_t gval;
  1480. X    int type;
  1481. X    char s1[256];
  1482. X
  1483. X    if (St_GetSym(breathT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1484. X        sprintf(s1, "unknown breath '%s'", s);
  1485. X        ErrMsg(s1);
  1486. X    } else {
  1487. X        tmpTemplate.val.spells |= (1 << gval.i);
  1488. X        tmpTemplate.def.breath = TRUE;
  1489. X    }
  1490. X}
  1491. X
  1492. X
  1493. Xvoid NegBreath(s)
  1494. Xchar *s;
  1495. X{
  1496. X    generic_t gval;
  1497. X    int type;
  1498. X    char s1[256];
  1499. X
  1500. X    if (St_GetSym(breathT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1501. X        sprintf(s1, "unknown breath '%s'", s);
  1502. X        ErrMsg(s1);
  1503. X    } else {
  1504. X        tmpTemplate.val.spells &= ~(1 << gval.i);
  1505. X        tmpTemplate.def.breath = TRUE;
  1506. X    }
  1507. X}
  1508. X
  1509. X
  1510. Xvoid AddSpecial(s)
  1511. Xchar *s;
  1512. X{
  1513. X    generic_t gval;
  1514. X    int type;
  1515. X    char s1[256];
  1516. X
  1517. X    if (St_GetSym(specialT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1518. X        sprintf(s1, "unknown special '%s'", s);
  1519. X        ErrMsg(s1);
  1520. X    } else {
  1521. X        tmpTemplate.val.cmove |= (1 << gval.i);
  1522. X        tmpTemplate.def.special = TRUE;
  1523. X    }
  1524. X}
  1525. X
  1526. X
  1527. Xvoid NegSpecial(s)
  1528. Xchar *s;
  1529. X{
  1530. X    generic_t gval;
  1531. X    int type;
  1532. X    char s1[256];
  1533. X
  1534. X    if (St_GetSym(specialT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1535. X        sprintf(s1, "unknown special '%s'", s);
  1536. X        ErrMsg(s1);
  1537. X    } else {
  1538. X        tmpTemplate.val.cmove &= ~(1 << gval.i);
  1539. X        tmpTemplate.def.special = TRUE;
  1540. X    }
  1541. X}
  1542. X
  1543. X
  1544. Xvoid AddMove(s)
  1545. Xchar *s;
  1546. X{
  1547. X    generic_t gval;
  1548. X    int type;
  1549. X    char s1[256];
  1550. X
  1551. X    if (St_GetSym(moveT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1552. X        sprintf(s1, "unknown move '%s'", s);
  1553. X        ErrMsg(s1);
  1554. X    } else {
  1555. X        tmpTemplate.val.cmove |= (1 << gval.i);
  1556. X        tmpTemplate.def.move = TRUE;
  1557. X    }
  1558. X}
  1559. X
  1560. X
  1561. Xvoid NegMove(s)
  1562. Xchar *s;
  1563. X{
  1564. X    generic_t gval;
  1565. X    int type;
  1566. X    char s1[256];
  1567. X
  1568. X    if (St_GetSym(moveT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1569. X        sprintf(s1, "unknown move '%s'", s);
  1570. X        ErrMsg(s1);
  1571. X    } else {
  1572. X        tmpTemplate.val.cmove &= ~(1 << gval.i);
  1573. X        tmpTemplate.def.move = TRUE;
  1574. X    }
  1575. X}
  1576. X
  1577. X
  1578. Xvoid AddTreasure(s)
  1579. Xchar *s;
  1580. X{
  1581. X    generic_t gval;
  1582. X    int type;
  1583. X    char s1[256];
  1584. X
  1585. X    if (St_GetSym(treasureT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1586. X        sprintf(s1, "unknown treasure '%s'", s);
  1587. X        ErrMsg(s1);
  1588. X    } else {
  1589. X        tmpTemplate.val.cmove |= (1 << gval.i);
  1590. X        tmpTemplate.def.treasure = TRUE;
  1591. X    }
  1592. X}
  1593. X
  1594. X
  1595. Xvoid NegTreasure(s)
  1596. Xchar *s;
  1597. X{
  1598. X    generic_t gval;
  1599. X    int type;
  1600. X    char s1[256];
  1601. X
  1602. X    if (St_GetSym(treasureT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1603. X        sprintf(s1, "unknown treasure '%s'", s);
  1604. X        ErrMsg(s1);
  1605. X    } else {
  1606. X        tmpTemplate.val.cmove &= ~(1 << gval.i);
  1607. X        tmpTemplate.def.treasure = TRUE;
  1608. X    }
  1609. X}
  1610. X
  1611. X
  1612. Xvoid AddDefense(s)
  1613. Xchar *s;
  1614. X{
  1615. X    generic_t gval;
  1616. X    int type;
  1617. X    char s1[256];
  1618. X
  1619. X    if (St_GetSym(defenseT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1620. X        sprintf(s1, "unknown defense '%s'", s);
  1621. X        ErrMsg(s1);
  1622. X    } else {
  1623. X        tmpTemplate.val.cdefense |= (1 << gval.i);
  1624. X        tmpTemplate.def.defense = TRUE;
  1625. X    }
  1626. X}
  1627. X
  1628. X
  1629. Xvoid NegDefense(s)
  1630. Xchar *s;
  1631. X{
  1632. X    generic_t gval;
  1633. X    int type;
  1634. X    char s1[256];
  1635. X
  1636. X    if (St_GetSym(defenseT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1637. X        sprintf(s1, "unknown defense '%s'", s);
  1638. X        ErrMsg(s1);
  1639. X    } else {
  1640. X        tmpTemplate.val.cdefense &= ~(1 << gval.i);
  1641. X        tmpTemplate.def.defense = TRUE;
  1642. X    }
  1643. X}
  1644. X
  1645. X
  1646. Xint PutAttack(attack)
  1647. Xattack_t attack;
  1648. X{
  1649. X    register int i;
  1650. X
  1651. X    for (i = 0; i < attackCt; i++) {
  1652. X        if ((attack.type == attackList[i].type) &&
  1653. X            (attack.desc == attackList[i].desc) &&
  1654. X            (attack.dice == attackList[i].dice) &&
  1655. X            (attack.sides == attackList[i].sides)) {
  1656. X                return(i);
  1657. X        }
  1658. X    }
  1659. X
  1660. X    if (attackCt == MAX_ATTACK) {
  1661. X        fprintf(stderr, "fatal error: too many different attacks.\n");
  1662. X        fprintf(stderr, "increase MAX_ATTACK.\n");
  1663. X        exit(1);
  1664. X    }
  1665. X
  1666. X    attackList[attackCt].type = attack.type;
  1667. X    attackList[attackCt].desc = attack.desc;
  1668. X    attackList[attackCt].dice = attack.dice;
  1669. X    attackList[attackCt].sides = attack.sides;
  1670. X
  1671. X    return attackCt++;
  1672. X}
  1673. X
  1674. Xvoid AddAttack(s1, dice, sides, s2)
  1675. Xchar *s1, *s2;
  1676. Xint dice, sides;
  1677. X{
  1678. X    generic_t gval;
  1679. X    int type, aDesc;
  1680. X    attack_t attack;
  1681. X    char s[256];
  1682. X
  1683. X    if (St_GetSym(attackDescT_P, s1, &type, &gval) != ST_SYM_FOUND) {
  1684. X        sprintf(s, "unknown attack description '%s'", s1);
  1685. X        ErrMsg(s);
  1686. X        return;
  1687. X    } else {
  1688. X        aDesc = gval.i;
  1689. X    }
  1690. X
  1691. X    if (St_GetSym(attackTypeT_P, s2, &type, &gval) != ST_SYM_FOUND) {
  1692. X        sprintf(s, "unknown attack type '%s'", s2);
  1693. X        ErrMsg(s);
  1694. X    } else {
  1695. X        if (creatureAttacks > 3) {
  1696. X            sprintf(s, "creature limited to 4 attacks");
  1697. X            ErrMsg(s);
  1698. X            return;
  1699. X        }
  1700. X        attack.type = gval.i;
  1701. X        attack.dice = dice;
  1702. X        attack.desc = aDesc;
  1703. X        attack.sides = sides;
  1704. X        tmpTemplate.val.damage[creatureAttacks++] =
  1705. X                        PutAttack(attack);
  1706. X        tmpTemplate.def.damage = TRUE;
  1707. X    }
  1708. X}
  1709. X
  1710. Xst_Table_Pt InitTable(name, init)
  1711. Xchar *name;
  1712. XsymInit_t *init;
  1713. X{
  1714. X    int i;
  1715. X    st_Table_Pt table_P;
  1716. X    generic_t gval;
  1717. X
  1718. X    table_P = St_NewTable(name, 20);
  1719. X    for (i = 0; init[i].name; i++) {
  1720. X        gval.i = init[i].val;
  1721. X        St_DefSym(table_P, init[i].name, GEN_TYPE_INT, gval);
  1722. X    }
  1723. X
  1724. X    return table_P;
  1725. X}
  1726. X
  1727. X
  1728. Xvoid InitTables()
  1729. X{
  1730. X    int i;
  1731. X    generic_t gval;
  1732. X
  1733. X    keywordT_P = InitTable("keyword", keywordInit);
  1734. X    defenseT_P = InitTable("defense", defenseInit);
  1735. X    spellT_P = InitTable("spell", spellInit);
  1736. X    moveT_P = InitTable("move", moveInit);
  1737. X    specialT_P = InitTable("special", specialInit);
  1738. X    breathT_P = InitTable("breath", breathInit);
  1739. X    treasureT_P = InitTable("treasure", treasureInit);
  1740. X    attackTypeT_P = InitTable("attackType", attackTypeInit);
  1741. X    attackDescT_P = InitTable("attackDesc", attackDescInit);
  1742. X
  1743. X    classT_P = St_NewTable("class", 40);
  1744. X    creatureT_P = St_NewTable("creature", 200);
  1745. X}
  1746. X
  1747. Xvoid WriteCreature(tmpl_P)
  1748. Xtemplate_t *tmpl_P;
  1749. X{
  1750. X    char s[256];
  1751. X    strcpy(s, "\"");
  1752. X    strcat(s, tmpl_P->val.name);
  1753. X    strcat(s, "\"");
  1754. X    printf("{%-28s, 0x%08x,0x%06x,0x%04x,%5d,%3d,\n",
  1755. X        s, tmpl_P->val.cmove, tmpl_P->val.spells,
  1756. X        tmpl_P->val.cdefense, tmpl_P->val.mexp, tmpl_P->val.sleep);
  1757. X    printf(" %2d, %3d, %2d, '%c', {%3d,%2d}, {%3d,%3d,%3d,%3d}, %3d},\n",
  1758. X        tmpl_P->val.aaf, tmpl_P->val.ac, tmpl_P->val.speed,
  1759. X        tmpl_P->val.cchar,
  1760. X        tmpl_P->val.hd[0], tmpl_P->val.hd[1],
  1761. X        tmpl_P->val.damage[0], tmpl_P->val.damage[1],
  1762. X        tmpl_P->val.damage[2], tmpl_P->val.damage[3],
  1763. X        tmpl_P->val.level);
  1764. X}
  1765. X
  1766. Xvoid WriteCreatures()
  1767. X{
  1768. X    char **s_A, **sp;
  1769. X    int level, type;
  1770. X    generic_t gval;
  1771. X
  1772. X    s_A = St_SListTable(creatureT_P);
  1773. X
  1774. X    printf("creature_type c_list[MAX_CREATURES] = {\n");
  1775. X
  1776. X    for (level = 0; level <= maxCreatureLevel; level++) {
  1777. X        for (sp = s_A; *sp; sp++) {
  1778. X        if (St_GetSym(creatureT_P, *sp, &type, &gval) !=
  1779. X                            ST_SYM_FOUND) {
  1780. X            fprintf(stderr, "internal err. in WriteCreatures\n");
  1781. X            exit(1);
  1782. X        }
  1783. X        if ((*(template_t *) gval.v).val.level == level) {
  1784. X            WriteCreature((template_t *) gval.v);
  1785. X        }
  1786. X       }
  1787. X    }
  1788. X
  1789. X    printf("};\n\n");
  1790. X
  1791. X    St_SListTable(NULL);
  1792. X}
  1793. X
  1794. Xvoid PutClassTemplate(s, tmpl_P)
  1795. Xchar *s;
  1796. Xtemplate_t *tmpl_P;
  1797. X{
  1798. X    generic_t gval;
  1799. X    char s1[256];
  1800. X
  1801. X    gval.v = malloc(sizeof(template_t));
  1802. X    *(template_t *) gval.v = *tmpl_P;
  1803. X
  1804. X    if (St_DefSym(classT_P, s, GEN_TYPE_TMPL, gval) == ST_SYM_FOUND) {
  1805. X        sprintf(s1, "attempt to redefine class '%s'", s);
  1806. X        ErrMsg(s1);
  1807. X        free(gval.v);
  1808. X        return;
  1809. X    }
  1810. X}
  1811. X
  1812. X
  1813. Xtemplate_t GetClassTemplate(s)
  1814. Xchar *s;
  1815. X{
  1816. X    generic_t gval;
  1817. X    int type;
  1818. X    char s1[256];
  1819. X
  1820. X    if (St_GetSym(classT_P, s, &type, &gval) != ST_SYM_FOUND) {
  1821. X        sprintf(s1, "class '%s' undefined\n", s);
  1822. X        ErrMsg(s1);
  1823. X        return blankTemplate;
  1824. X    } else {
  1825. X        return *(template_t *) gval.v;
  1826. X    }
  1827. X}
  1828. X
  1829. X
  1830. X
  1831. X
  1832. Xvoid NotDefined(name, s)
  1833. Xchar *name, *s;
  1834. X{
  1835. X    printf("Warning: %s not defined for \"%s\", line %d\n",
  1836. X        s, name, lineNo);
  1837. X}
  1838. X
  1839. X
  1840. Xvoid PutCreature(s, tmpl_P)
  1841. Xchar *s;
  1842. Xtemplate_t *tmpl_P;
  1843. X{
  1844. X    generic_t gval;
  1845. X    char s1[256];
  1846. X
  1847. X    gval.v = malloc(sizeof(template_t));
  1848. X    *(template_t *) gval.v = *tmpl_P;
  1849. X
  1850. X    if (!tmpl_P->def.move)
  1851. X        NotDefined(tmpl_P->val.name, "MOVE");
  1852. X    if (!tmpl_P->def.treasure)
  1853. X        NotDefined(tmpl_P->val.name, "TREASURE");
  1854. X    if (!tmpl_P->def.defense)
  1855. X        NotDefined(tmpl_P->val.name, "DEFENSE");
  1856. X    if (!tmpl_P->def.mexp)
  1857. X        NotDefined(tmpl_P->val.name, "XP");
  1858. X    if (!tmpl_P->def.sleep)
  1859. X        NotDefined(tmpl_P->val.name, "SLEEP");
  1860. X    if (!tmpl_P->def.aaf)
  1861. X        NotDefined(tmpl_P->val.name, "RADIUS");
  1862. X    if (!tmpl_P->def.ac)
  1863. X        NotDefined(tmpl_P->val.name, "AC");
  1864. X    if (!tmpl_P->def.speed)
  1865. X        NotDefined(tmpl_P->val.name, "SPEED");
  1866. X    if (!tmpl_P->def.cchar)
  1867. X        NotDefined(tmpl_P->val.name, "CCHAR");
  1868. X    if (!tmpl_P->def.hd)
  1869. X        NotDefined(tmpl_P->val.name, "HD");
  1870. X    if (!tmpl_P->def.damage)
  1871. X        NotDefined(tmpl_P->val.name, "ATTACK");
  1872. X    if (!tmpl_P->def.level)
  1873. X        NotDefined(tmpl_P->val.name, "LEVEL");
  1874. X
  1875. X    if (St_DefSym(creatureT_P, s, GEN_TYPE_TMPL, gval) == ST_SYM_FOUND) {
  1876. X        sprintf(s1, "attempt to redefine creature '%s'\n", s);
  1877. X        ErrMsg(s1);
  1878. X        free(gval.v);
  1879. X        return;
  1880. X    }
  1881. X
  1882. X    if (tmpl_P->val.level > maxCreatureLevel)
  1883. X        maxCreatureLevel = tmpl_P->val.level;
  1884. X
  1885. X}
  1886. X
  1887. Xvoid WriteAttacks()
  1888. X{
  1889. X    int i;
  1890. X
  1891. X    printf("struct m_attack_type monster_attacks[N_MONS_ATTS] = {\n");
  1892. X    for (i = 0; i < attackCt; i++) {
  1893. X        printf("/* %3d */ { %2d, %2d, %2d, %2d },\n",
  1894. X            i, attackList[i].type, attackList[i].desc,
  1895. X            attackList[i].dice, attackList[i].sides);
  1896. X    };
  1897. X    printf("};\n");
  1898. X}
  1899. X
  1900. Xvoid WriteConstants()
  1901. X{
  1902. X  printf("/* These values should match the values defined in constant.h. */");
  1903. X  printf("\n#define MAX_CREATURES\t%d\n", St_TableSize(creatureT_P));
  1904. X  printf("#define N_MON_ATTS\t%d\n\n", attackCt);
  1905. X}
  1906. X
  1907. Xvoid WriteMonsterHdr()
  1908. X{
  1909. X  printf("/* The following code belongs in the file monster.c. */\n\n");
  1910. X  printf("/* The following data was generated by the program in util/mc.");
  1911. X  printf("*/\n\n");
  1912. X}
  1913. X
  1914. Xmain(argc, argv)
  1915. Xint argc;
  1916. Xchar *argv[];
  1917. X{
  1918. X    char inputFilename[256];
  1919. X
  1920. X    InitTables();
  1921. X
  1922. X    if (argc > 1) {
  1923. X        strncpy(inputFilename, argv[1], 255);
  1924. X        inputFilename[255] = 0;
  1925. X    } else {
  1926. X        fprintf(stderr, "input file: ");
  1927. X        scanf("%255s", inputFilename);
  1928. X    }
  1929. X
  1930. X    input_F = fopen(inputFilename, "r");
  1931. X    if (!input_F) {
  1932. X        printf("Error: couldn't open file.\n");
  1933. X        exit(1);
  1934. X    }
  1935. X
  1936. X    if (yyparse()) {
  1937. X        printf("Errors prevent continuation.\n");
  1938. X        exit(1);
  1939. X    }
  1940. X
  1941. X    WriteConstants();
  1942. X    WriteMonsterHdr();
  1943. X    WriteCreatures();
  1944. X    WriteAttacks();
  1945. X}
  1946. END_OF_FILE
  1947. if test 26665 -ne `wc -c <'util/mc/creature.y'`; then
  1948.     echo shar: \"'util/mc/creature.y'\" unpacked with wrong size!
  1949. fi
  1950. # end of 'util/mc/creature.y'
  1951. fi
  1952. echo shar: End of archive 28 \(of 39\).
  1953. cp /dev/null ark28isdone
  1954. MISSING=""
  1955. 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
  1956.     if test ! -f ark${I}isdone ; then
  1957.     MISSING="${MISSING} ${I}"
  1958.     fi
  1959. done
  1960. if test "${MISSING}" = "" ; then
  1961.     echo You have unpacked all 39 archives.
  1962.     echo "Now run "bldfiles.sh" to build split files"
  1963.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1964. else
  1965.     echo You still need to unpack the following archives:
  1966.     echo "        " ${MISSING}
  1967. fi
  1968. ##  End of shell archive.
  1969. exit 0
  1970.