home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume14
/
umoria4
/
part28
< prev
next >
Wrap
Internet Message Format
|
1992-08-31
|
58KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v14i060: umoria4 - single player dungeon simulation (ver. 5.5), Part28/39
Message-ID: <3424@master.CNA.TEK.COM>
Date: 22 Aug 92 22:13:51 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1959
Approved: billr@saab.CNA.TEK.COM
Submitted-by: grabiner@math.harvard.edu (David Grabiner)
Posting-number: Volume 14, Issue 60
Archive-name: umoria4/Part28
Supersedes: umoria3: Volume 9, Issue 55-97; Volume 10, Issue 15-17
Environment: Curses, Unix, Mac, MS-DOS, Atari-ST, Amiga, VMS
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 28 (of 39)."
# Contents: doc/FEATURES.NEW misc/rick.msg util/mc/creature.y
# Wrapped by billr@saab on Thu Aug 20 09:11:33 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/FEATURES.NEW' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/FEATURES.NEW'\"
else
echo shar: Extracting \"'doc/FEATURES.NEW'\" \(11714 characters\)
sed "s/^X//" >'doc/FEATURES.NEW' <<'END_OF_FILE'
X
XYou get a warning for spells or prayers beyond your strength.
X
XInventory commands (wear, wield, exchange, take off, drop) now always
Xtake one move each. If anything significant happens during that move,
Xsuch as a monster moving somewhere, the screen will be redisplayed.
XInventories are displayed in the top-right corner of the screen, to minimize
Xthe number of characters that must be redrawn afterwards, this makes the game
Xmuch more playable on slow speed modems.
X
XWhen selecting items or spells, you can select with a capital letter to
Xprint a description and confirm you really want that one.
X
XYou can now associate counts with commands. The '?' command shows you
Xthe possibilities. In rogue command mode, simply type in the number.
XIn this mode, numbers are no longer simple commands.
XIn original moria command mode, enter a '#' to start a count.
X
XThere are options (set with the = command) to display weights in
Xan inventory, to highlight mineral seams, to ignore open doors
Xwhile running, etc.
X
XMonster memory: use the / command to access info about a monster after you
Xhave seen/killed at least one of them. This can also be accessed from
Xthe look 'l' command.
X
XCan enter control characters with two keystrokes using ^ key, useful for
Xnoisy phone lines? or stupid terminals?
X
X'M'ap command shows reduced size map. 'L' allows you to scroll around entire
Xmap. The 'L' command also will now center the character on the screen.
X
XLook 'l' views all objects in an arc in the specified direction, or specify
X'5' and it will look in every direction.
X
XCan change your speed in wizard mode.
X
XNew field in status line, used for rest/paralysed/searching/repeat counts.
X
XNew field in status line shows speed.
X
XCan die of starvation.
X
XIf carrying too much weight, you will be slowed immediately, the amount slowed
Xdepends on how much over the weight limit you are.
X
XCan not circle monsters (moving at the same speed as yourself)
Xby moving around them in a diamond pattern.
X
XHigh level monsters have a chance of ignoring your bash, and they also have
Xa chance of recovering immediately even if stunned. You can not bash the
XBalrog.
X
XCan abort rest/repeated command by hitting any character.
X
XEvery duration affect prints a command when it wears off previously
Xresist heat and resist cold, and perhaps others did not.
X
XNew find/run algorithm which is much better than the old one. Also,
Xbetter handling of dangerous conditions that occur during repeat commands/runs.
XAn attack will always stop a repeated command and find/run mode.
X
XCan inscribe names onto objects. Some inscriptions are automatic:
Xan empty wand/staff is inscribed 'empty'. An object which is used, but its
Xuse does not identify it is inscribed 'tried'. Cursed objects are inscribed
X'damned' when identified as cursed. If you detect an object is enchanted,
Xit is inscribed 'magik'.
X
XScrolls have their titles removed after being identified. Scrolls/potions
Xfrom the store/dungeon can stack after the dungeon item is identified.
X
XIf you curse/damage a special object, such as a Holy Avenger sword, it
Xwill lose its special property.
X
XWill automatically save the game correctly if a HANGUP signal is received,
Xi.e. dropped dialup connection, the network crashes, etc. The save file
Xis not a panic save, instead the program plays the game for you (i.e.
Xpretends that you are hitting ESCAPE) until it is safe to save the game.
X
XBetter handling of inventory/equipment lists, i.e. you can drop items
Xin the equipment list, can identify items in the equipment list, etc.
X
XMore consistent monster definitions, i.e. creatures with frost attacks
Xalways take extra damage from fire (except those that also have fire
Xattacks), and many other fixes.
X
XOne source for the UNIX/IBM/Atari ST/Amiga/Mac/VMS versions, should make
Xkeeping the micro versions up-to-date much easier. The game is smaller and
Xhopefully faster. Savefiles are now relatively machine independent, they
Xshould transport from one mini/micro to another without any problems.
X
XIf you are hallucinating, ^R won't help.
X
XBows can have a pluses to damage. These pluses only apply if you are
Xusing the bow to fire the appropriate type of missile (arrow/bolt/etc).
X
XCan haggle incrementally in the stores, i.e. can increase bid by 10
Xby typing +10, similarly -10 will decrease bid by 10.
X
XBeeps if invalid character entered at most prompts.
X
XCan type ^R at any time to refresh the screen.
X
XArmor/weapons show their base AC/hit/dam values in their name.
X
XAny of RETURN (^M), LF (^J), SPACE, or ESCAPE can be typed at -more- prompts.
X
XWhen droping a group of items, you have the choice of dropping only one,
Xor all of them.
X
XThere is a small chance that a player will notice that there are unidentified
Xmagic items in the inventory. The chance is larger if the item is in the
Xequipment list.
X
XObject distribution has been changed so that when you are deep in the dungeon,
Xthere are many more high level objects created than low level objects.
X
XMonster distribution changed so that when you are deep in the dungeon,
Xyou will meet many more high level monsters than low level monsters.
X
XAdditional spikes make a door harder to open, in a progressively decreasing
Xsequence, that is, the more spikes you add, the less effect each additional
Xspike has.
X
XWhen a stat changes, all abilities/etc that depend on the stat will immediately
Xchange. For example, if you CON increases, then your hit points will increase,
Xif your INT/WIS increases then your mana will immediately increase and you
Xwill immediately learn new spells/prayers. This makes the Grape Jelly trick
Xcompletely unnecessary, and, in fact, it will has no effect.
X
XSpell/prayer letters never change, i.e. if you know the second spell of a book,
Xit will not be referred to as spell 'a' if you do not know the first spell.
X
XWhen haggling, if you have reach the final offer much more often than you
Xhaven't, then the store will give you the benefit of the doubt and go
Xdirectly to the final price. The exact formula is (good > 3*bad + 20).
XTwo sets of numbers are kept for every store, one for buying and one for
Xselling.
X
XWhen wielding a weapon that is too heavy, the to hit penalty will be shown
Xby the 'C' command.
X
XIt is harder to hit monsters when you can't see them.
X
XPerfect stealth is impossible now.
X
XSave files are now encrypted.
X
XSlay monster items are now slay animal. The previous slay monster item
Xdid not work as stated by the documentation, fixing it to work reasonably
Xwould have made it too powerful.
X
XIf picking up an item will slow you down, you are asked if you really want
Xto pick it up.
X
XSpells work differently now. You no longer learn them automatically when
Xyou gain a level. Instead, 'Study' appears in the status line when are
Xcapable of learning new spells. Use the 'G' command to actually learn
Xthe spells. The 'G' command can be used anytime that you are eligible to
Xlearn new spells, as for example, after quaffing a restore intelligence/wisdom
Xpotion.
X
XThe object naming routines are completely rewritten. This makes the program
Xmuch smaller. Also, too long names will no longer cause a crash or error,
Xthey will be silently truncated as necessary.
X
XYou can not attack an invisible/unlit monster in a wall by merely moving
Xinto the wall, instead you must tunnel into the wall. Since moving into
Xa wall is a free turn, people could take advantage of this while fighting
Xinvis monsters by checking all of the walls first.
X
XTo change the default moria save file name, define the environment variable
X"MORIA_SAV" to be the full pathname for where you want your save files.
X
X"moria -n" will start a new game, and will ignore "moria.save" if it exists
X
XJellies and molds never carry treasure.
X
XRecharging a high level wand, or a wand which already has many charges, is
Xmuch more likely to fail.
X
XElves and half-elves have infravision now.
X
XThere is no longer a distinction between wizard and god mode; only wizard mode
Xexists now. Also, wizard mode no longer requires a password, and anyone
X(not just the installer) can enter wizard mode. Hence, wizard now works the
Xsame no matter whether you are playing on a micro or a mini. Enter wizard
Xmode by using the ^W command, help is ^H. (Or for the rogue-like option,
X^W and \).
X
XMissile weapons are much more powerful when used with the proper weapon.
XFor example, firing a bolt from a heavy crossbow multiplies its damage by 4.
Xrounded pebble, iron shot: sling = 2x
Xarrow: short bow = 2x, long bow = 3x, composite bow = 4x
Xbolt: light crossbow = 3x, heavy crossbow = 4x
XArrows and bolts appear more often deep in the dungeon.
XMagical missile weapon prices are more reasonable.
X
XThe miscellaneous abilities 'fighting', 'bows/throw', 'saving throw', 'disarm',
Xand 'magical device' are all level dependent, i.e. they improve as you gain
Xlevels. Formerly, the rate of improvement was independent of class, now,
Xhowever, the learning rate is clas dependent. For example, warriors gain
Xproficiency at fighting twice as fast as mages/priests now. As a result,
Xhigh level warriors are better fighters than before, and high level
Xmages/priests do not fight as well as they used to. The complete table is:
X Magic Saving
X Fighting Bows Devices Disarm Throw
XWarrior 4 4 2 2 3
XMage 2 2 4 3 3
XPriest 2 2 4 3 3
XRogue 3 4 3 4 3
XRanger 3 4 3 3 3
XPaladin 3 3 3 2 3
XIn all cases, three is equivalent to the old rate.
X
Xumoria now understands tilde (~) characters at the start of a file name.
X
XTo resurrect a dead character, use "moria -w filename".
X
XNew status line shows "Is wizard" if in wizard mode, "Was wizard" if
Xpreviously was in wizard mode, "Resurrected" if character was resurrected,
Xand "Duplicate" if character is already on the scoreboard.
X
XMoved see invisible from slay animal to slay undead, since this makes a lot
Xmore sense.
X
XDragon lightning breath attacks can now damage items in your inventory,
Xjust like all other dragon breath attacks.
X
XNew scoreboard code added. It will hold 1000 scores by default, scores for
Xsaved characters are listed, can see all scores or just your scores.
XOn multiuser OS's, each user can only have one entry in the scoreboard for
Xeach legal race/sex/class combination. The score file format is portable,
Xand should be able to move from one machine to another with no problems.
X
XThe '-s' option will show all scores in the scoreboard. The '-S' option
Xwill show only your scores. The 'V' command will show all scores in the
Xscoreboard. A second 'V' command typed immediately afterwards will show
Xonly your scores.
X
XTyping '*' for the rest count will make you rest until you reach max mana
Xand max hp.
X
XSpikes can now be wielded as a weapon for completeness. Note however that
Xthey make terrible weapons.
X
XThe damage multiplier for bows is now displayed as part of their name.
X
XTwo new '=' command options: can turn off sound, and can turn off the rest/
Xrepeat counts displayed on the bottom line. The last is useful for those
Xplaying at 2400 baud or less, or on very slow machines.
X
XMany items are now added to the inventory in a sorted position, e.g.
Xthe spell books will always end up in the inventory sorted by their level.
XThis automatic sorting does not work for objects which have a 'color',
Xe.g. potions, wands, staffs, scrolls.
X
XTyping RETURN while haggling will default to the last increment/decrement
Xamount used.
X
XUmoria 5.4:
X
XPrints multiple sentences on the message line if they are short enough.
X
XUmoria 5.5:
X
XThe maximum damage enchantment for a weapon is now equal to its maximum
Xdamage, instead of being fixed at 10 (there is a slight chance of
Xenchantment beyond this level); thus daggers are no longer the best
Xweapons for mid-level characters.
X
Xlast modified 8/12/92
END_OF_FILE
if test 11714 -ne `wc -c <'doc/FEATURES.NEW'`; then
echo shar: \"'doc/FEATURES.NEW'\" unpacked with wrong size!
fi
# end of 'doc/FEATURES.NEW'
fi
if test -f 'misc/rick.msg' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'misc/rick.msg'\"
else
echo shar: Extracting \"'misc/rick.msg'\" \(14612 characters\)
sed "s/^X//" >'misc/rick.msg' <<'END_OF_FILE'
XFrom 18862246%VUVAXCOM.BITNET@lilac.berkeley.edu Thu Aug 24 13:11:19 1989
XReceived: from lilac.Berkeley.EDU by ernie.Berkeley.EDU (5.61/1.36)
X id AA06320; Thu, 24 Aug 89 13:11:14 -0700
XReceived: by lilac.berkeley.edu (5.61.1/1.16.22)
X id AA05399; Thu, 24 Aug 89 12:47:05 PDT
XMessage-Id: <8908241947.AA05399@lilac.berkeley.edu>
XDate: Thu, 24 Aug 89 15:41 EST
XFrom: "Computers and you, living life a bit at a time"
X <188622462%VUVAXCOM.bitnet@lilac.berkeley.edu>
XSubject: Here is the UPDATE.TXT file
XTo: wilson@ernie.Berkeley.EDU
XOriginal_To: BITNET%"wilson@ucbernie"
XStatus: RO
X
X
XHere are the changes incorporated to date in the upgrade from V5.0 to V6.0:
X
X o The source code has been converted from a %INCLUDE format to modular
X programs. Due to low system memory quotas set on student accounts at my
X university, compiling the %INCLUDE form was not possible. By converting
X to modular form, anyone with enough disk space can compile the program,
X by compiling each module separately, and then linking all the files
X together. Along with this, I also changed all the indentation in the
X code so that it is uniform throughout, something that was not there from
X having four or more different people work on it before.
X
X o Creation of a new high score list. Early in Moria's time at my node,
X many people had found out the Wizard mode password (this was for version
X 4.3 and then 4.8), so I have created a Wizard Mode Top Twenty list. Part
X of this has been creating 2 new fields in the player character record to
X enable Moria to remember if your character ever entered Wizard or God
X modes. If you used Wizard mode at any point, you are eligible for the
X Wizard mode list, if you used God mode, you can't get on any list. If
X you die and aren't allowed to go to either of the lists, the game does
X tell you what score you earned.
X
X o A second effect of everyone here knowing the Wizard password was the
X continual resurrection of characters by copying the save file and re-
X storing the character. This lead to multiple copies of the same
X character appearing on the high score lists. I have solved this problem
X by adding two more new fields to the character record, to keep track of
X the birthdate and birthtime of the character, taken from the system time
X at the same point that the stats are rolled. When a character dies, his
X birthdate/time is recorded in the highscore file, and whenever that same
X userid kills another character, it checks to see if the birthdate/times
X match, if so, then it assumes a clone, and doesn't post the score to the
X list. The game does tell you what you had earned in this case.
X
X o The game now saves the userid of the character's creator in the
X save file. This prevents one person making a strong character, then
X giving it to someone else to use to finish off the Balrog.
X
X o The increase of stats via special items (ie: HA increasing strength) and
X via Gain potions has been re-worked. Increase stat items (weapons,
X rings, crowns, amulets, armor) now affects only the current value of the
X stat, not the max value. Gain potions affect the max and the current,
X based on the max value. If you are close to 18/100 and the item would
X increase you past that, you will see a drop in the current value of the
X stat when you take it off, but a Restore potion will return you to what
X it was before you wielded/wore the item.
X
X o The changing of the cost of an item has been repaired where an increase
X to the tohit and todam values are concerned. Also, changes have been
X implemented wherever items are damaged, so that the shops will know of
X their decreased value.
X
X o The Vampire Bites attack has been modified. Originally, you lost the
X same amount (or close to it) of hit points as you did experience points
X (which could be from 18d8 to 32d8, depending on the type of Vampire).
X The Vampire Bite now takes off 1d6 hit points (logic: you bleed a bit).
X
X o The stats area (left side of screen) has been fixed in regards to field
X widths. All fields, when re-printed, wipe out any extra digits from the
X previous value. If you have more than 9,999,999 in gold, the string
X "$$$$$$$" is printed. If more than 9,999,999 experience points are
X earned, the string "*******" is printed. If you have more than 999 mana
X then the string "###/###" will be printed.
X
X o The God mode function ^C (Make Nice Character) now checks to see if the
X character is a Magic-using type (ie: not Warrior or Rogue) before upping
X the mana score. The God function ^E (Change Character) does the same.
X
X o A new wizard function: Describe Object. This will give you information
X about the item specified, including Damage, Tohit and ToDam adjustments,
X weight, and others. This will not identify an unidentified item, only
X help you in figuring out if one item is better than another (ie: which
X sword does more damage?). The hex flags for the item in question will
X be translated to show what special magic is inherit in the item.
X
X o A new God Mode function, ^X, Examine Character. This prints out all the
X values of the Flags section of the player character record. Useful in
X debugging purposes.
X
X o A bug with Search mode and going up/down stairs has been fixed. When
X using stairs, Search mode is turned off (if it was on) and the relevant
X reduction in speed is removed.
X
X o All code referring to the "Consultant" classes and the "Extra" spells
X group have been removed, since a) they were written, but no character
X race was allowed to be one and b) they were simply slight modifications
X on the mage class.
X
X o In the source, there were two people who used their initials as parts of
X variable names. These have all been changed to more descriptive names.
X
X o The Town generation code has been fixed so that any store could appear
X at any of the locations, instead of the Black Market always appearing in
X the upper right-hand corner. The code there has also been fixed so that
X adding in additional stores should not be difficult.
X
X o The various spell books have been fixed so that multiple copies will be
X listed as "a) 2 Books of <whatever>" in the inventory list.
X
X o The running of the Black Market has been fixed up so that it works more
X like the other stores, except store inventory turn-around is still as
X as fast as it was before. The inventory will now flucuate in size, just
X as the other stores do.
X
X o A bug involving the Wizard Mode Light Dungeon function and using a torch
X has been repaired so that the tunnel floors remain lit after passing
X over them.
X
X o Caps/Helms of Intelligence/Wisdom bought in the Black Market now
X correctly increase the relevant stat.
X
X o A bug involving certain area-affect spells (Light Area, any Ball-type
X spell, etc) and the right-hand and bottom edges of the town level has
X been fixed.
X
X o The magic translation case statements in SCROLLS.PAS and POTIONS.PAS
X has been fixed to allow a full set of both to be used. Previously,
X each one was coming up short of the 64 actual possible slots that are
X available by using two Tval values.
X
X o The problem with the special Magic and Prayer books from the Black
X Market has been fixed so that they appear as separate items in your
X inventory and are not added with the normal books.
X
X o The bug concerning enchanting items bought from the Black Market and the
X new values never being seen was been repaired, so that the name string
X of the item will be displayed properly.
X
X o The Control-Y exit command has been changed so the user has to hit Q to
X exit instead of Y. This is to make it more fool-proof and more accident
X proof (but not totally).
X
X o Three new monster attacks: Lose Mana (different from the monster spell),
X Slip, Trip, and Fall (you'll find out), and Eclipse attack. A number of
X new attack descriptions have been added with this. A new function was
X added, function DEX_ADJ, to determine the character's plus or minus to
X his dexterity saving throw.
X
X o New monsters have found their way into the Dungeons of Moria. A list of
X their names can be found in the file MONSTERS.NEW, included in the
X distribution package (or from your local Moria Wizard).
X
X o The creatures "Mother & Baby" and "Small Girl" have been fixed to
X correctly utilize the CDEFENSE flag of Lose Experience for killing that
X creature.
X
X o The global constant store$turn_around has been changed to the global
X array variable store_turnaround, allowing each store to have a different
X inventory turn over rate. This was done partially to work the Black
X Market in more properly.
X
X o A bug involving the running function ('.' and a direction) has been
X fixed so that if you are attacked in any form, either via a physical
X hit or a spell, you will stop running at that point.
X
X o New monster defense: cloning on death. A new value has been added to
X the CDEFENSE flag so that certain monsters can try to clone themselves
X when they have been dealt a mortal blow. There are four types of
X cloning, each giving a different base chance to clone. The chance is
X reduced based on how badly killed the creature is (if you "neutronize"
X the critter, he isn't as likely to clone himself).
X
X o The \ function has been fixed up a bit, mainly in formatting control,
X with an added piece to watch for the end of the screen and page it out
X as needed. Also, it has been renamed to ^U, and is now a Wizard mode
X function, just as creating the Monster Dictionary is.
X
X o The Create Food spell/scroll has been fixed. If an item is under you
X when you cast/read this spell, it will not be deleted as it was doing
X before. Make sure you have a open space of floor under or around you,
X or you may go hungry...
X
X o The Medusa has been fixed so that it's gaze causes Turn to Stone, not
X Vampire Bite.
X
X o Added a new flag to the monster's spell flags. A creature can now be
X set up so that only a percentage of that type of creature will be spell
X casters, assuming the type has any spell ability at all. For example,
X the Young Blue Dragon could be set up so that only 1 in 10 Young Blue
X Dragons can cast spells at all. This does not effect Dragon Breath
X attacks, only spell ability. If a zero or one is in this position,
X all members of that creature type can cast spells, if any are indicated.
X
X
XFrom 18862246%VUVAXCOM.BITNET@lilac.berkeley.edu Thu Aug 31 06:10:59 1989
XReceived: from lilac.Berkeley.EDU by ernie.Berkeley.EDU (5.61/1.36)
X id AA14710; Thu, 31 Aug 89 06:10:54 -0700
XReceived: by lilac.berkeley.edu (5.61.1/1.16.22)
X id AA04291; Thu, 31 Aug 89 05:54:29 PDT
XMessage-Id: <8908311254.AA04291@lilac.berkeley.edu>
XDate: Thu, 31 Aug 89 08:51 EST
XFrom: "Charon, the Ferryman on the River Styx"
X <188622462%VUVAXCOM.bitnet@lilac.berkeley.edu>
XSubject: what to put for a subject? I don't know...
XTo: wilson@ernie.Berkeley.EDU
XOriginal_To: BITNET%"wilson@ucbernie"
XStatus: RO
X
X
XJim-
X
XI see what you mean about the up/down and the search flag thing. What did
Xyou add to the main dungeon procedure to fix this?
X
XAt the end of this letter, I've appended the dictionary descriptions of the
X"Mother & Baby" and "Small Girl". I've also include the piece from the
Xmon_take_hit function that checks the appropriate bit in the monster cdefense
Xflag. I believe this was something written in for the 5.0 UB version, but
XI'm not certain, so if you need more to be able to put it into yours, I can
Xsend whatever you need.
X
XThat bug you mention could well be the result of someone diddling with the
Xsources. Off hand, I can think of one or two reasons they'd do something to
Xthe monster-array parts, to save on memory usage, but the file-access goes
Xway up the minute you do anything other than the orginial form, so you lose
Xout in the end. I'll keep my eye out, but I doubt if I'll ever see it happen
Xhere.
X
XSounds like you and I, and the rest of the Usenet community, are in agreement
Xthen. We'll keep our two separate "schools" of Moria, and just share thoughts
Xback and forth.
X
XNow if only the VM/CMS Moria porter would respond to my letter...
X
XCatch you later,
X
XRick
X
X
X---excerpt from function mon_take_hit. Insert within the section of if
X statement that has determined the monster has died.
X EXP is the player's current experience points. LEV is the player's level.
X I1 is the amount of experience the creature is worth (I think it's a
X calculated value)
X
X {Penalize player - subtract experience}
X if (uand (cdefense, %X'00000400') <> 0) then
X begin
X exp := exp - 10*lev;
X if (exp < 0) then exp := 0;
X end
X else
X exp := exp + i1;
X
X
X--------------------------------------------
X 1 Mother and Baby (p)
X Speed = 1 Level = 0 Exp = 0
X AC = 1 Eye-sight = 4 HD = 1d1
X Creature harmed by cold.
X Creature harmed by fire.
X Creature harmed by poison.
X Creature harmed by acid.
X Creature harmed by stone-to-mud.
X Causes experience loss when killed
X Creature seen with Infra-Vision.
X Creature picks up objects.
X--Spells/Dragon Breath =
X--Movement =
X Moves and attacks normally.
X 20% random movement.
X Can open doors.
X--Creature attacks =
X Touches you for normal damage. (0d0)
X--------------------------------------------
X 2 Small Girl (p)
X Speed = 1 Level = 0 Exp = 0
X AC = 1 Eye-sight = 4 HD = 1d1
X Creature harmed by cold.
X Creature harmed by fire.
X Creature harmed by poison.
X Creature harmed by acid.
X Creature harmed by stone-to-mud.
X Causes experience loss when killed
X Creature seen with Infra-Vision.
X Creature picks up objects.
X--Spells/Dragon Breath =
X--Movement =
X Moves and attacks normally.
X 20% random movement.
X Can open doors.
X--Creature attacks =
X Touches you for normal damage. (0d0)
X--------------------------------------------
X
X
END_OF_FILE
if test 14612 -ne `wc -c <'misc/rick.msg'`; then
echo shar: \"'misc/rick.msg'\" unpacked with wrong size!
fi
# end of 'misc/rick.msg'
fi
if test -f 'util/mc/creature.y' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'util/mc/creature.y'\"
else
echo shar: Extracting \"'util/mc/creature.y'\" \(26665 characters\)
sed "s/^X//" >'util/mc/creature.y' <<'END_OF_FILE'
X/* util/mc/creature.y: a Moria creature definition compiler
X *
X * Copyright 1989 by Joseph Hall.
X * All rights reserved except as stated below.
X * This program may contain portions excerpted from Moria which are
X * copyrighted by others.
X *
X * Jim Wilson and any other holders of copyright on substantial portions
X * of Moria are granted rights to use, modify, and distribute this program
X * as they see fit, so long as the terms of its use, modification and/or
X * distribution are no less restrictive than those applying to Moria,
X * version 5.0 or later, itself, and so long as this use is related to
X * the further development of Moria.
X *
X * Anyone having any other use in mind for this code should contact the
X * author at 4116 Brewster Dr., Raleigh NC 27606 (jnh@ecemwl.ncsu.edu).
X */
X
X%{
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <math.h>
X
X#ifdef ANSI_LIBS
X#include <stdlib.h>
X#else
Xextern double atof();
Xextern char *malloc();
Xextern char *calloc();
Xextern void free();
X#endif
X
X#include "st.h"
X
X#ifndef TRUE
X#define TRUE 1
X#endif
X
X#ifndef FALSE
X#define FALSE 0
X#endif
X
X#define VERBOSE /* to turn on debugging output */
X
Xtypedef unsigned long int32u;
Xtypedef long int32;
Xtypedef unsigned short int16u;
Xtypedef short int16;
Xtypedef unsigned char int8u;
X
Xtypedef struct creature_type
X{
X char *name; /* Descrip of creature */
X int32u cmove; /* Bit field */
X int32u spells; /* Creature spells */
X int16u cdefense; /* Bit field */
X int16u mexp; /* Exp value for kill */
X int8u sleep; /* Inactive counter/10 */
X int8u aaf; /* Area affect radius */
X int8u ac; /* AC */
X int8u speed; /* Movement speed+10 */
X int8u cchar; /* Character rep. */
X int8u hd[2]; /* Creatures hit die */
X int8u damage[4]; /* Type attack and damage*/
X int8u level; /* Level of creature */
X
X int32u general; /* general characteristics; not present in usual */
X /* moria creature_type */
X} creature_type;
X
X
X
X/*
X * defined_t is used to indicate whether all fields have been defined
X */
X
Xtypedef struct {
X unsigned move: 1,
X special: 1,
X treasure: 1,
X spell: 1,
X breath: 1,
X defense: 1,
X mexp: 1,
X sleep: 1,
X aaf: 1,
X ac: 1,
X speed: 1,
X cchar: 1,
X hd: 1,
X damage: 1,
X level: 1;
X} defined_t;
X
X
X
X/*
X * template_t contains creature definition & flags
X */
X
Xtypedef struct {
X creature_type val;
X defined_t def;
X} template_t;
X
X
X
X/*
X * attack_t describes a monster attack
X */
X
Xtypedef struct {
X int8u type,
X desc,
X dice,
X sides;
X} attack_t;
X
X
X
X/*
X * symInit_t is used to initialize symbol tables with integer values
X */
X
Xtypedef struct {
X char *name;
X int32u val;
X} symInit_t;
X
X
X
Xstatic symInit_t defenseInit[] = {
X { "dragon", 0 },
X { "animal", 1 },
X { "evil", 2 },
X { "undead", 3 },
X { "frost", 4 },
X { "fire", 5 },
X { "poison", 6 },
X { "acid", 7 },
X { "light", 8 },
X { "stone", 9 },
X { "bit_9", 10 },
X { "bit_10", 11 },
X { "no_sleep", 12 },
X { "infra", 13 },
X { "max_hp", 14 },
X { "bit_15", 15 },
X { NULL, 0 }
X};
X
Xstatic symInit_t moveInit[] = {
X { "attack_only", 0 },
X { "move_normal", 1 },
X { "bit_2", 2 },
X { "random_20", 3 },
X { "random_40", 4 },
X { "random_75", 5 },
X { NULL, 0 }
X};
X
Xstatic symInit_t specialInit[] = {
X { "invisible", 16 },
X { "open_door", 17 },
X { "phase", 18 },
X { "eats_other", 19 },
X { "picks_up", 20 },
X { "multiply", 21 },
X { "win_creature", 31 },
X { NULL, 0 }
X};
X
Xstatic symInit_t treasureInit[] = {
X { "carry_obj", 24 },
X { "carry_gold", 25 },
X { "has_random_60", 26 },
X { "has_random_90", 27 },
X { "has_1d2_obj", 28 },
X { "has_2d2_obj", 29 },
X { "has_4d2_obj", 30 },
X { NULL, 0 }
X};
X
Xstatic symInit_t spellInit[] = {
X { "tel_short", 4 },
X { "tel_long", 5 },
X { "tel_to", 6 },
X { "lght_wnd", 7 },
X { "ser_wnd", 8 },
X { "hold_per", 9 },
X { "blind", 10 },
X { "confuse", 11 },
X { "fear", 12 },
X { "summon_mon", 13 },
X { "summon_und", 14 },
X { "slow_per", 15 },
X { "drain_mana", 16 },
X { "bit_17", 17 },
X { "bit_18", 18 },
X { NULL, 0 }
X};
X
Xstatic symInit_t breathInit[] = {
X { "light", 19 },
X { "gas", 20 },
X { "acid", 21 },
X { "frost", 22 },
X { "fire", 23 },
X { NULL, 0 }
X};
X
Xstatic symInit_t attackTypeInit[] = {
X { "normal_damage", 1 },
X { "lose_str", 2 },
X { "confusion", 3 },
X { "cause_fear", 4 },
X { "fire_damage", 5 },
X { "acid_damage", 6 },
X { "cold_damage", 7 },
X { "lightning_damage", 8 },
X { "corrosion", 9 },
X { "cause_blindness", 10 },
X { "cause_paralysis", 11 },
X { "steal_money", 12 },
X { "steal_obj", 13 },
X { "poison", 14 },
X { "lose_dex", 15 },
X { "lose_con", 16 },
X { "lose_int", 17 },
X { "lose_wis", 18 },
X { "lose_exp", 19 },
X { "aggravation", 20 },
X { "disenchant", 21 },
X { "eat_food", 22 },
X { "eat_light", 23 },
X { "eat_charges", 24 },
X { "blank", 99 },
X { NULL, 0 }
X};
X
Xstatic symInit_t attackDescInit[] = {
X { "hits", 1 },
X { "bites", 2 },
X { "claws", 3 },
X { "stings", 4 },
X { "touches", 5 },
X { "kicks", 6 },
X { "gazes", 7 },
X { "breathes", 8 },
X { "spits", 9 },
X { "wails", 10 },
X { "embraces", 11 },
X { "crawls_on", 12 },
X { "releases_spores", 13 },
X { "begs_for_money", 14 },
X { "slimes", 15 },
X { "crushes", 16 },
X { "tramples", 17 },
X { "drools_on", 18 },
X { "insults", 19 },
X { "is_repelled", 99 },
X { NULL, 0 }
X};
X
X
X
X
X/*
X * Maximum token length = maximum string constant length
X * Also, trim the stack to an "acceptable" size.
X */
X
X#define MAX_TOK_LEN 64 /* maximum acceptable token length */
X#define YYSTACKSIZE 128
X
X#define GEN_TYPE_TMPL 256 /* type of a template for st */
X
X/*
X * Globals used by the tokenizer (lexical analyzer)
X */
X
X#define INPUT_BUF_SIZE 256
Xstatic char inputBuf[INPUT_BUF_SIZE] = { 0 };
X /* input line buffer */
Xstatic char *inputBufp = inputBuf; /* position in input line buffer */
Xstatic int lineNo = 0; /* number of current line */
Xstatic FILE *input_F;
Xstatic char tokStr[MAX_TOK_LEN]; /* text of current token */
Xstatic int tokType; /* type of current token */
Xstatic double tokVal; /* numeric value of current token, */
X /* if applicable */
X
Xstatic template_t blankTemplate = { 0 }; /* blank template for init-ing */
Xstatic template_t tmpTemplate; /* working template for current */
X /* class or creature */
X
X#define MAX_ATTACK 250
Xstatic attack_t attackList[MAX_ATTACK] = { 0 };
Xstatic int attackCt = 1, creatureAttacks = 0;
Xstatic int maxCreatureLevel = 0;
X
X/*
X * Global symbol tables
X */
X
Xstatic st_Table_Pt keywordT_P, /* parser's keywords */
X defenseT_P, /* defense flags */
X moveT_P, /* movement flags */
X specialT_P, /* special flags */
X treasureT_P, /* treasure flags */
X spellT_P, /* spell flags */
X breathT_P, /* breath flags */
X attackTypeT_P, /* attack type flags */
X attackDescT_P, /* attack desc flags */
X classT_P, /* class templates */
X creatureT_P; /* creature definitions */
X
X/*
X * Function declarations
X */
X
Xextern void AddDefense();
Xextern void NegDefense();
Xextern void AddMove();
Xextern void NegMove();
Xextern void AddTreasure();
Xextern void NegTreasure();
Xextern void AddSpecial();
Xextern void NegSpecial();
Xextern void AddSpell();
Xextern void NegSpell();
Xextern void AddBreath();
Xextern void NegBreath();
Xextern void AddAttack();
Xextern void WriteCreature();
Xextern void PutClassTemplate();
Xextern template_t GetClassTemplate();
Xextern void PutCreature();
X
X%}
X
X
X/*
X * YACC DEFINITIONS
X */
X
X/*
X * The parser's stack can hold ints, doubles, and strings.
X */
X
X%union {
X int ival;
X double dval;
X char sval[MAX_TOK_LEN];
X }
X
X/*
X * Reserved words
X */
X
X%token CLASS CREATURE NAMED HD D MOVE SPELL BREATH DEFENSE XP CCHAR SLEEP
X%token RADIUS SPEED ATTACK FOR AC LEVEL TREASURE SPECIAL OF IN
X
X/*
X * Entities
X */
X
X%token <sval> IDENTIFIER /* identifier, not a keyword */
X%token <dval> FLOAT_LIT /* floating-pt literal */
X%token <ival> INT_LIT /* integer literal */
X%token <sval> STRING_LIT /* string literal */
X%token <ival> BOOL_LIT /* boolean literal */
X
X/*
X * ASCII chars are their own tokens
X */
X
X%start creatures
X
X
X/*
X * THE PARSER
X */
X
X%%
X
Xcreatures : class_def ';' creatures
X | creature_def ';' creatures
X | /* empty */
X ;
X
Xclass_def : CLASS IDENTIFIER parent_class '{' features '}'
X { PutClassTemplate($<sval>2, &tmpTemplate); }
X ;
X
Xparent_class : ':' IDENTIFIER
X { tmpTemplate = GetClassTemplate($<sval>2);
X creatureAttacks = 0; }
X | /* empty */
X { tmpTemplate = blankTemplate;
X creatureAttacks = 0; }
X ;
X
Xcreature_def : CREATURE STRING_LIT parent_class
X '{' features '}'
X { tmpTemplate.val.name =
X (char *) malloc(strlen($<sval>2) + 1);
X strcpy(tmpTemplate.val.name, $<sval>2);
X PutCreature($<sval>2, &tmpTemplate);
X }
X ;
X
Xfeatures : feature ';' features
X | /* empty */
X ;
X
Xfeature : LEVEL ':' INT_LIT
X { tmpTemplate.val.level = $<ival>3;
X tmpTemplate.def.level = TRUE; }
X | HD ':' INT_LIT D INT_LIT
X { tmpTemplate.val.hd[0] = $<ival>3;
X tmpTemplate.val.hd[1] = $<ival>5;
X tmpTemplate.def.hd = TRUE; }
X | XP ':' INT_LIT
X { tmpTemplate.val.mexp = $<ival>3;
X tmpTemplate.def.mexp = TRUE; }
X | CCHAR ':' STRING_LIT
X { tmpTemplate.val.cchar = $<sval>3[0];
X tmpTemplate.def.cchar = TRUE; }
X | AC ':' INT_LIT
X { tmpTemplate.val.ac = $<ival>3;
X tmpTemplate.def.ac = TRUE; }
X | SLEEP ':' INT_LIT
X { tmpTemplate.val.sleep = $<ival>3;
X tmpTemplate.def.sleep = TRUE; }
X | RADIUS ':' INT_LIT
X { tmpTemplate.val.aaf = $<ival>3;
X tmpTemplate.def.aaf = TRUE; }
X | SPEED ':' INT_LIT
X { tmpTemplate.val.speed = $<ival>3 + 10;
X tmpTemplate.def.speed = TRUE; }
X | ATTACK ':' attacks
X | MOVE ':' moves
X | SPELL ':' spells
X | SPELL INT_LIT '%' ':' spells
X { float chance = 100.0 / $<ival>2;
X if (chance > 15.0)
X chance = 0.0;
X if (chance < 0.0)
X chance = 0.0;
X tmpTemplate.val.spells &= ~0xf;
X tmpTemplate.val.spells |=
X (int) ceil(chance);
X tmpTemplate.def.spell = TRUE; }
X | BREATH ':' breaths
X | BREATH INT_LIT '%' ':' breaths
X { float chance = 100.0 / $<ival>2;
X if (chance > 15.0)
X chance = 0.0;
X if (chance < 0.0)
X chance = 0.0;
X tmpTemplate.val.spells &= ~0xf;
X tmpTemplate.val.spells |=
X (int) ceil(chance);
X tmpTemplate.def.spell = TRUE; }
X | DEFENSE ':' defenses
X | TREASURE ':' carries
X | SPECIAL ':' specials
X ;
X
Xattacks : attack more_attacks
X ;
X
Xattack : IDENTIFIER FOR INT_LIT D INT_LIT OF IDENTIFIER
X { AddAttack($<sval>1, $<ival>3,
X $<ival>5, $<sval>7); }
X ;
X
Xmore_attacks : ',' attack more_attacks
X | /* empty */
X ;
X
Xmoves : move more_moves
X ;
X
Xmove : IDENTIFIER { AddMove($<sval>1); }
X | '~' IDENTIFIER { NegMove($<sval>2); }
X ;
X
Xmore_moves : ',' move more_moves
X | /* empty */
X ;
X
Xspells : spell more_spells
X | /* empty */
X ;
X
Xspell : IDENTIFIER { AddSpell($<sval>1); }
X | '~' IDENTIFIER { NegSpell($<sval>2); }
X ;
X
Xmore_spells : ',' spell more_spells
X | /* empty */
X ;
X
Xbreaths : breath more_breaths
X ;
X
Xbreath : IDENTIFIER { AddBreath($<sval>1); }
X | '~' IDENTIFIER { NegBreath($<sval>2); }
X ;
X
Xmore_breaths : ',' breath more_breaths
X | /* empty */
X ;
X
Xdefenses : defense more_defenses
X ;
X
Xdefense : IDENTIFIER { AddDefense($<sval>1); }
X | '~' IDENTIFIER { NegDefense($<sval>2); }
X ;
X
Xmore_defenses : ',' defense more_defenses
X | /* empty */
X ;
X
Xcarries : carry more_carries
X ;
X
Xcarry : IDENTIFIER { AddTreasure($<sval>1); }
X | '~' IDENTIFIER { NegTreasure($<sval>2); }
X ;
X
Xmore_carries : ',' carry more_carries
X | /* empty */
X ;
X
Xspecials : special more_specials
X ;
X
Xspecial : IDENTIFIER { AddSpecial($<sval>1); }
X | '~' IDENTIFIER { NegSpecial($<sval>2); }
X ;
X
Xmore_specials : ',' special more_specials
X | /* empty */
X ;
X
X
X%%
X
Xstatic symInit_t keywordInit[] = {
X { "class", CLASS },
X { "creature", CREATURE },
X { "named", NAMED },
X { "hd", HD },
X { "d", D },
X { "move", MOVE },
X { "spell", SPELL },
X { "breath", BREATH },
X { "defense", DEFENSE },
X { "xp", XP },
X { "cchar", CCHAR },
X { "sleep", SLEEP },
X { "radius", RADIUS },
X { "speed", SPEED },
X { "attack", ATTACK },
X { "for", FOR },
X { "ac", AC },
X { "level", LEVEL },
X { "treasure", TREASURE },
X { "special", SPECIAL },
X { "of", OF },
X { "in", IN },
X { NULL, 0 }
X};
X
X
X
X/*
X * MyFGetC--
X * fgetc with support for comments
X *
X * # is the comment character. comment lasts till end of line.
X * Spews out an extra char of whitespace at EOF since something seems to
X * need it. I'll figure this out eventually...
X */
Xstatic int MyFGetC(input_F)
XFILE *input_F;
X{
X static int atEof = FALSE;
X while (!*inputBufp || (*inputBufp == '#')) {
X fgets(inputBuf, INPUT_BUF_SIZE, input_F);
X if (feof(input_F))
X return EOF;
X lineNo++;
X inputBufp = inputBuf;
X }
X return *inputBufp++;
X}
X
X
X
X/*
X * Advance--
X * Advance to the next token in the input stream and set tokStr,
X * tokType, tokVal as appropriate.
X *
X * On error, tokType is set to a negative value.
X */
Xstatic void Advance(input_F)
XFILE *input_F;
X{
X
X register char
X *tok = tokStr; /* accumulating token string */
X register int
X len = 0; /* length of current token */
X static int c = 32; /* current character; ' ' is harmless init */
X
X
X /*
X * Skip whitespace in the stream
X */
X while ((c != EOF) && isspace(c))
X c = MyFGetC(input_F);
X
X /*
X * At end of file?
X */
X if (c == EOF) {
X tokType = EOF;
X strcpy(tokStr, "[EOF]");
X return;
X }
X
X /*
X * Recognize a number [+|-][dddd][.][dddd][{e|E}[+|-]dddd]
X */
X if (isdigit(c) || (c == '.') || (c == '+') || (c == '-')) {
X
X register int
X decPt = FALSE, /* seen a decimal point yet? */
X hasExp = FALSE; /* has an exponent? */
X
X if ((c == '-') || (c == '+')) {
X *tok++ = c;
X c = MyFGetC(input_F);
X }
X
X while ((len < MAX_TOK_LEN - 1) && (isdigit(c) || (c == '.'))) {
X if (c == '.') {
X if (decPt)
X break;
X else
X decPt = TRUE;
X }
X
X *tok++ = c;
X c = MyFGetC(input_F);
X len++;
X }
X
X if ((c == 'e') || (c == 'E')) {
X hasExp = TRUE;
X *tok++ = c;
X c = MyFGetC(input_F);
X len++;
X
X if ((c == '-') || (c == '+')) {
X *tok++ = c;
X c = MyFGetC(input_F);
X len++;
X }
X
X while ((len < MAX_TOK_LEN - 1) && isdigit(c)) {
X *tok++ = c;
X c = MyFGetC(input_F);
X len++;
X }
X }
X
X *tok = 0;
X
X if (decPt || hasExp) {
X tokType = FLOAT_LIT;
X yylval.dval = atof(tokStr);
X } else {
X tokType = INT_LIT;
X yylval.ival = atoi(tokStr);
X }
X
X return;
X
X }
X
X /*
X * Recognize a quoted string
X */
X if (c == '\"') {
X
X c = MyFGetC(input_F);
X
X while ((len < MAX_TOK_LEN - 1) &&
X (c != EOF) && (c != '\n') && (c != '\"')) {
X *tok++ = c;
X c = MyFGetC(input_F);
X }
X
X *tok = 0;
X
X c = MyFGetC(input_F);
X
X tokType = STRING_LIT;
X strncpy(yylval.sval, tokStr, MAX_TOK_LEN - 1);
X yylval.sval[MAX_TOK_LEN - 1] = 0;
X
X return;
X
X }
X
X /*
X * Recognize an identifier and try to match it with a keyword.
X * Identifiers begin with a letter and continue in letters and/or
X * digits. Convert it to lowercase.
X */
X if (isalpha(c) || (c == '_') || (c == '$')) {
X
X if (isupper(c))
X c = tolower(c);
X *tok++ = c;
X c = MyFGetC(input_F);
X len++;
X
X while ((len < MAX_TOK_LEN - 1) && (isalpha(c) || isdigit(c) ||
X (c == '_') || (c == '$'))) {
X if (isupper(c))
X c = tolower(c);
X *tok++ = c;
X c = MyFGetC(input_F);
X len++;
X }
X
X *tok = 0;
X
X /*
X * We've got the identifier; see if it matches any keywords.
X */
X
X {
X generic_t gval;
X int type;
X if (St_GetSym(keywordT_P, tokStr, &type, &gval) ==
X ST_SYM_FOUND) {
X tokType = gval.i;
X strncpy(yylval.sval, tokStr, MAX_TOK_LEN - 1);
X yylval.sval[MAX_TOK_LEN - 1] = 0;
X } else if (!strcmp(tokStr, "true")) {
X tokType = BOOL_LIT;
X yylval.ival = 1;
X } else if (!strcmp(tokStr, "false")) {
X tokType = BOOL_LIT;
X yylval.ival = 0;
X } else {
X tokType = IDENTIFIER;
X strncpy(yylval.sval, tokStr, MAX_TOK_LEN - 1);
X yylval.sval[MAX_TOK_LEN - 1] = 0;
X }
X }
X
X return;
X
X }
X
X /*
X * Recognize punctuation
X */
X
X tokType = c;
X *tok++ = c;
X *tok = 0;
X c = MyFGetC(input_F);
X return;
X
X}
X
Xvoid ErrMsg(s)
Xchar *s;
X{
X int i;
X
X fprintf(stderr, "Error: %s at line %d\n", s, lineNo);
X fprintf(stderr, "%s", inputBuf);
X for (i = 0; i < inputBufp - inputBuf; i++) {
X fputc((inputBuf[i] == '\t' ? '\t' : ' '), stderr);
X }
X fprintf(stderr, "^ before here\n\n");
X}
X
Xint yyerror(s)
Xchar *s;
X{
X ErrMsg(s);
X}
X
X
Xint yylex()
X{
X Advance(input_F);
X return(tokType);
X}
X
Xvoid AddSpell(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(spellT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown spell '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.spells |= (1 << gval.i);
X tmpTemplate.def.spell = TRUE;
X }
X}
X
X
Xvoid NegSpell(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(spellT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown spell '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.spells &= ~(1 << gval.i);
X tmpTemplate.def.spell = TRUE;
X }
X}
X
X
Xvoid AddBreath(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(breathT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown breath '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.spells |= (1 << gval.i);
X tmpTemplate.def.breath = TRUE;
X }
X}
X
X
Xvoid NegBreath(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(breathT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown breath '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.spells &= ~(1 << gval.i);
X tmpTemplate.def.breath = TRUE;
X }
X}
X
X
Xvoid AddSpecial(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(specialT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown special '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cmove |= (1 << gval.i);
X tmpTemplate.def.special = TRUE;
X }
X}
X
X
Xvoid NegSpecial(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(specialT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown special '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cmove &= ~(1 << gval.i);
X tmpTemplate.def.special = TRUE;
X }
X}
X
X
Xvoid AddMove(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(moveT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown move '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cmove |= (1 << gval.i);
X tmpTemplate.def.move = TRUE;
X }
X}
X
X
Xvoid NegMove(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(moveT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown move '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cmove &= ~(1 << gval.i);
X tmpTemplate.def.move = TRUE;
X }
X}
X
X
Xvoid AddTreasure(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(treasureT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown treasure '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cmove |= (1 << gval.i);
X tmpTemplate.def.treasure = TRUE;
X }
X}
X
X
Xvoid NegTreasure(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(treasureT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown treasure '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cmove &= ~(1 << gval.i);
X tmpTemplate.def.treasure = TRUE;
X }
X}
X
X
Xvoid AddDefense(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(defenseT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown defense '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cdefense |= (1 << gval.i);
X tmpTemplate.def.defense = TRUE;
X }
X}
X
X
Xvoid NegDefense(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(defenseT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "unknown defense '%s'", s);
X ErrMsg(s1);
X } else {
X tmpTemplate.val.cdefense &= ~(1 << gval.i);
X tmpTemplate.def.defense = TRUE;
X }
X}
X
X
Xint PutAttack(attack)
Xattack_t attack;
X{
X register int i;
X
X for (i = 0; i < attackCt; i++) {
X if ((attack.type == attackList[i].type) &&
X (attack.desc == attackList[i].desc) &&
X (attack.dice == attackList[i].dice) &&
X (attack.sides == attackList[i].sides)) {
X return(i);
X }
X }
X
X if (attackCt == MAX_ATTACK) {
X fprintf(stderr, "fatal error: too many different attacks.\n");
X fprintf(stderr, "increase MAX_ATTACK.\n");
X exit(1);
X }
X
X attackList[attackCt].type = attack.type;
X attackList[attackCt].desc = attack.desc;
X attackList[attackCt].dice = attack.dice;
X attackList[attackCt].sides = attack.sides;
X
X return attackCt++;
X}
X
Xvoid AddAttack(s1, dice, sides, s2)
Xchar *s1, *s2;
Xint dice, sides;
X{
X generic_t gval;
X int type, aDesc;
X attack_t attack;
X char s[256];
X
X if (St_GetSym(attackDescT_P, s1, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s, "unknown attack description '%s'", s1);
X ErrMsg(s);
X return;
X } else {
X aDesc = gval.i;
X }
X
X if (St_GetSym(attackTypeT_P, s2, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s, "unknown attack type '%s'", s2);
X ErrMsg(s);
X } else {
X if (creatureAttacks > 3) {
X sprintf(s, "creature limited to 4 attacks");
X ErrMsg(s);
X return;
X }
X attack.type = gval.i;
X attack.dice = dice;
X attack.desc = aDesc;
X attack.sides = sides;
X tmpTemplate.val.damage[creatureAttacks++] =
X PutAttack(attack);
X tmpTemplate.def.damage = TRUE;
X }
X}
X
Xst_Table_Pt InitTable(name, init)
Xchar *name;
XsymInit_t *init;
X{
X int i;
X st_Table_Pt table_P;
X generic_t gval;
X
X table_P = St_NewTable(name, 20);
X for (i = 0; init[i].name; i++) {
X gval.i = init[i].val;
X St_DefSym(table_P, init[i].name, GEN_TYPE_INT, gval);
X }
X
X return table_P;
X}
X
X
Xvoid InitTables()
X{
X int i;
X generic_t gval;
X
X keywordT_P = InitTable("keyword", keywordInit);
X defenseT_P = InitTable("defense", defenseInit);
X spellT_P = InitTable("spell", spellInit);
X moveT_P = InitTable("move", moveInit);
X specialT_P = InitTable("special", specialInit);
X breathT_P = InitTable("breath", breathInit);
X treasureT_P = InitTable("treasure", treasureInit);
X attackTypeT_P = InitTable("attackType", attackTypeInit);
X attackDescT_P = InitTable("attackDesc", attackDescInit);
X
X classT_P = St_NewTable("class", 40);
X creatureT_P = St_NewTable("creature", 200);
X}
X
Xvoid WriteCreature(tmpl_P)
Xtemplate_t *tmpl_P;
X{
X char s[256];
X strcpy(s, "\"");
X strcat(s, tmpl_P->val.name);
X strcat(s, "\"");
X printf("{%-28s, 0x%08x,0x%06x,0x%04x,%5d,%3d,\n",
X s, tmpl_P->val.cmove, tmpl_P->val.spells,
X tmpl_P->val.cdefense, tmpl_P->val.mexp, tmpl_P->val.sleep);
X printf(" %2d, %3d, %2d, '%c', {%3d,%2d}, {%3d,%3d,%3d,%3d}, %3d},\n",
X tmpl_P->val.aaf, tmpl_P->val.ac, tmpl_P->val.speed,
X tmpl_P->val.cchar,
X tmpl_P->val.hd[0], tmpl_P->val.hd[1],
X tmpl_P->val.damage[0], tmpl_P->val.damage[1],
X tmpl_P->val.damage[2], tmpl_P->val.damage[3],
X tmpl_P->val.level);
X}
X
Xvoid WriteCreatures()
X{
X char **s_A, **sp;
X int level, type;
X generic_t gval;
X
X s_A = St_SListTable(creatureT_P);
X
X printf("creature_type c_list[MAX_CREATURES] = {\n");
X
X for (level = 0; level <= maxCreatureLevel; level++) {
X for (sp = s_A; *sp; sp++) {
X if (St_GetSym(creatureT_P, *sp, &type, &gval) !=
X ST_SYM_FOUND) {
X fprintf(stderr, "internal err. in WriteCreatures\n");
X exit(1);
X }
X if ((*(template_t *) gval.v).val.level == level) {
X WriteCreature((template_t *) gval.v);
X }
X }
X }
X
X printf("};\n\n");
X
X St_SListTable(NULL);
X}
X
Xvoid PutClassTemplate(s, tmpl_P)
Xchar *s;
Xtemplate_t *tmpl_P;
X{
X generic_t gval;
X char s1[256];
X
X gval.v = malloc(sizeof(template_t));
X *(template_t *) gval.v = *tmpl_P;
X
X if (St_DefSym(classT_P, s, GEN_TYPE_TMPL, gval) == ST_SYM_FOUND) {
X sprintf(s1, "attempt to redefine class '%s'", s);
X ErrMsg(s1);
X free(gval.v);
X return;
X }
X}
X
X
Xtemplate_t GetClassTemplate(s)
Xchar *s;
X{
X generic_t gval;
X int type;
X char s1[256];
X
X if (St_GetSym(classT_P, s, &type, &gval) != ST_SYM_FOUND) {
X sprintf(s1, "class '%s' undefined\n", s);
X ErrMsg(s1);
X return blankTemplate;
X } else {
X return *(template_t *) gval.v;
X }
X}
X
X
X
X
Xvoid NotDefined(name, s)
Xchar *name, *s;
X{
X printf("Warning: %s not defined for \"%s\", line %d\n",
X s, name, lineNo);
X}
X
X
Xvoid PutCreature(s, tmpl_P)
Xchar *s;
Xtemplate_t *tmpl_P;
X{
X generic_t gval;
X char s1[256];
X
X gval.v = malloc(sizeof(template_t));
X *(template_t *) gval.v = *tmpl_P;
X
X if (!tmpl_P->def.move)
X NotDefined(tmpl_P->val.name, "MOVE");
X if (!tmpl_P->def.treasure)
X NotDefined(tmpl_P->val.name, "TREASURE");
X if (!tmpl_P->def.defense)
X NotDefined(tmpl_P->val.name, "DEFENSE");
X if (!tmpl_P->def.mexp)
X NotDefined(tmpl_P->val.name, "XP");
X if (!tmpl_P->def.sleep)
X NotDefined(tmpl_P->val.name, "SLEEP");
X if (!tmpl_P->def.aaf)
X NotDefined(tmpl_P->val.name, "RADIUS");
X if (!tmpl_P->def.ac)
X NotDefined(tmpl_P->val.name, "AC");
X if (!tmpl_P->def.speed)
X NotDefined(tmpl_P->val.name, "SPEED");
X if (!tmpl_P->def.cchar)
X NotDefined(tmpl_P->val.name, "CCHAR");
X if (!tmpl_P->def.hd)
X NotDefined(tmpl_P->val.name, "HD");
X if (!tmpl_P->def.damage)
X NotDefined(tmpl_P->val.name, "ATTACK");
X if (!tmpl_P->def.level)
X NotDefined(tmpl_P->val.name, "LEVEL");
X
X if (St_DefSym(creatureT_P, s, GEN_TYPE_TMPL, gval) == ST_SYM_FOUND) {
X sprintf(s1, "attempt to redefine creature '%s'\n", s);
X ErrMsg(s1);
X free(gval.v);
X return;
X }
X
X if (tmpl_P->val.level > maxCreatureLevel)
X maxCreatureLevel = tmpl_P->val.level;
X
X}
X
Xvoid WriteAttacks()
X{
X int i;
X
X printf("struct m_attack_type monster_attacks[N_MONS_ATTS] = {\n");
X for (i = 0; i < attackCt; i++) {
X printf("/* %3d */ { %2d, %2d, %2d, %2d },\n",
X i, attackList[i].type, attackList[i].desc,
X attackList[i].dice, attackList[i].sides);
X };
X printf("};\n");
X}
X
Xvoid WriteConstants()
X{
X printf("/* These values should match the values defined in constant.h. */");
X printf("\n#define MAX_CREATURES\t%d\n", St_TableSize(creatureT_P));
X printf("#define N_MON_ATTS\t%d\n\n", attackCt);
X}
X
Xvoid WriteMonsterHdr()
X{
X printf("/* The following code belongs in the file monster.c. */\n\n");
X printf("/* The following data was generated by the program in util/mc.");
X printf("*/\n\n");
X}
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char inputFilename[256];
X
X InitTables();
X
X if (argc > 1) {
X strncpy(inputFilename, argv[1], 255);
X inputFilename[255] = 0;
X } else {
X fprintf(stderr, "input file: ");
X scanf("%255s", inputFilename);
X }
X
X input_F = fopen(inputFilename, "r");
X if (!input_F) {
X printf("Error: couldn't open file.\n");
X exit(1);
X }
X
X if (yyparse()) {
X printf("Errors prevent continuation.\n");
X exit(1);
X }
X
X WriteConstants();
X WriteMonsterHdr();
X WriteCreatures();
X WriteAttacks();
X}
END_OF_FILE
if test 26665 -ne `wc -c <'util/mc/creature.y'`; then
echo shar: \"'util/mc/creature.y'\" unpacked with wrong size!
fi
# end of 'util/mc/creature.y'
fi
echo shar: End of archive 28 \(of 39\).
cp /dev/null ark28isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 39 archives.
echo "Now run "bldfiles.sh" to build split files"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0