estes@ttrda.UUCP (Edward Estes ) (09/05/85)
# -------CUT HERE------- # This is a shar archieve. Extract with sh, not csh. # The rest of this file will extract: # README phant.nr func0.c echo extracting - README sed 's/^X//' > README << '!EOR!' XThis is the latest version of Phantasia. It incorporates all the reported Xbug fixes to date. The only problem that may arise is the test for XRAND in 'setup.c'. If you have problems with it complaining, even Xthough the correct RAND is specified, simply delete it. X XPlease send me any bugs you may find, but PLEASE be specific. I cannot Xcorrect a bug which is described as: X X "When I choose a character type, it blows up." X (What blows up? What exactly was printed at the terminal? X Which character type was chosen? Etc. . . ?) X XAlso, please tell me which version of UN*X you are running, and upon Xwhich type of hardware. X XI will also do my best to help anyone with problems just trying to Xget the game running. Again, I need to know which flavor of UN*X Xand what type of CPU. Also, a copy of the output from 'make' Xwould be extremely useful. X XAny and all ideas/suggestions/additions are more than welcome. If Xyou feel strongly enough about it, write the change and send it to me, Xand I will do my best to incorporate it in the next version of Phantasia. XOtherwise, I will give serious thought to adding it myself. X XFollow the directions in the Makefile carefully to set up the game. XRead the comments at the beginning of 'main.c', if you haven't already. X XEnjoy. X XTed Estes XAT&T Computer Systems Division XSkokie, IL 60077 X X...!ihnp4!ttrdc!ttrda!estes !EOR! echo extracting - phant.nr sed 's/^X//' > phant.nr << '!EOR!' X.de sh X.br X.ne 5 X.PP X\fB\\$1\fR X.PP X.. X.TH PHANTASIA 6 GAMES X.UC 4 X.SH NAME Xphantasia \- an interterminal fantasy game X.SH SYNOPSIS X.B phantasia X[ X.B \-s X] [ X.B \-m X] [ X.B \-a X] [ X.B \-x X] [ X.B \-h X] [ X.B \-H X] [ X.B \-p X] [ X.B \-b X] X.SH DESCRIPTION X.I Phantasia Xis a role playing game Xwhich allows players to roll up characters of various types to fight Xmonsters and other players. XProgression of characters is based upon gaining experience from fighting Xmonsters (and other players). X.PP XMost of the game is menu driven and self-explanatory (more or less). XThe screen is cursor updated, so be sure to set up the X.B TERM Xvariable in your environment. X.PP XThe options provide for a variety of functions to support the game. XThey are: X.PP X.TP .5i X.B \-s XInvokes X.I phantasia Xwithout header information. X.TP .5i X.B \-m XGet a monster listing. X.TP .5i X.B \-a XGet a listing of all character names on file. X.TP .5i X.B \-x XExamine/change a particular character on file. X.TP .5i X.B \-h XGet a help listing (this message). X.TP .5i X.B \-H XGet header listing only. X.TP .5i X.B \-p XPurge old characters. X.TP .5i X.B \-b XShow scoreboard of top characters per login. X.PP XThe characters are saved on a common file, in order to make the game Xinteractive between players. The characters are given a password Xin order to retrieve them later. Only characters above X.B level Xzero are saved. Characters unused for more than nine days will be Xpurged. XCharacters are only placed on the scoreboard when they die. X.SH AUTHOR XEdward Estes, AT&T Teletype Corporation X.SH PARTICULARS X.sh "Playing in General" XCertain of the player's more important statistics are almost always Xdisplyed on the screen, with maximums (where applicable) in Xparentheses. X.PP XThe character is placed randomly near the center of a cartesian Xsystem. XMost commands are selected with a single letter or digit. XFor example, one may move by hitting X.B E, W, N, Xor X.B S X(lower case may also be used, at no time is the game case dependent). XTo move to a particular (x,y) coordinate, use the X.B move X('1') command. The distance a character can move is calculated by X1 plus 1.5 per X.B level. XMoving in a particular compass direction will move the player the maximum Xallowed distance in that direction. X.PP XA player may at any time see who else is playing with a X.B players X('2') option. One may see only those who are the same distance or closer Xto the origin as he/she. X.B Kings, Xand X.B council of the wise Xcan see and can be seen by everyone. A X.B palantir Xremoves these retrictions. X.PP XOne can talk to other players with the X.B talk X('3') option. In general, this is a line or so of text. To remove a current Xmessage, just type <return> when prompted for a message. X.PP XThe X.B stats X('4') option shows additional characteristics of a player. X.PP XOne may leave the game either with the X.B quit X('5') option, or by hitting interrupt. Quitting during battle results Xin death for obvious reasons. X.PP XOne may rest by default. Resting lets one regain maximum X.B energy level, Xand also lets one find X.B mana X(more is found for larger levels and further distances from the origin). X.PP XOne may call a monster by hitting '9'. X.PP XSeveral other options become available as the player progresses in X.B level Xand X.B magic, Xor to other stations in the game ( X.B valar, council of the wise, king X). XThese are described elsewhere. XIn general, a control-L will force the redrawing of the screen. X.PP XOther things which may happen are more or less self-explanatory. X.sh "Fighting Monsters" XA player has several options while fighting monsters. They are as follows: X.TP 1.5i X.B melee XInflicts damage on the monster, based upon X.B strength. XAlso decreases the monster's X.B strength Xsome. X.TP 1.5i X.B skirmish XInflicts a little less damage than X.B melee, Xbut decreases the monster's X.B quickness Xinstead. X.TP 1.5i X.B evade XAttempt to run away. Success is based upon both the player's and Xthe monster's X.B brains Xand X.B quickness. X.TP 1.5i X.B spell XSeveral options for throwing spells (described elsewhere). X.TP 1.5i X.B nick XHits the monster one plus the player's X.B sword, Xand gives the player 10% of the monster's X.B experience. XDecreases the monster's X.B experience Xan amount proportional to the amount granted. XThis also increases the monster's quickness. XParalyzed monsters wake up very fast when nicked. X.TP 1.5i X.B luckout XThis is essentially a battle of wits with the monster. Success is based Xupon the player's and the monster's X.B brains. XThe player gets credit for slaying the monster if he/she succeeds. XOtherwise, nothing happens, and the chance to X.B luckout Xis lost. X.sh "Character Statistics" X.TP 1.5i X.B strength Xdetermines how much damage a character can inflict. X.TP 1.5i X.B quickness Xdetermines how many chances a character gets to make decisions while Xfighting. X.TP 1.5i X.B energy level Xspecifies how much damage a character may endure before dying. X.TP 1.5i X.B magic level Xdetermines which spells a character may throw, and how effective those Xspells will be. X.TP 1.5i X.B brains Xbasically, the character's intelligence; used for various fighting options Xand spells. X.TP 1.5i X.B mana Xused as a power source for throwing spells. X.TP 1.5i X.B experience Xgained by fighting monsters and other characters. X.TP 1.5i X.B level Xindicative of how much experience a character has accumulated; progresses Xgeometrically as X.B experience Xincreases. X.TP 1.5i X.B poison Xsickness which degrades a character's performance (affects X.B energy level Xand X.B strength X). X.TP 1.5i X.B sin Xaccumulated as a character does certain nasty things; used only rarely Xin normal play of the game. X.TP 1.5i X.B age Xnumber of seconds of playing time for the character. XAs X.B age Xincreases, many personal statistics degenerate. X.sh "Character Types" XCharacter statistics are rolled randomly from the above list, according Xto character type. The types are as follows: X.TP 1.5i X.B magic user Xstrong in X.B magic level Xand X.B brains X, weak in other areas. Must rely on wits and magic to survive. X.TP 1.5i X.B fighter Xgood in X.B strength Xand X.B energy level X, fairly good in other areas. This adds up to a well-equipped fighter. X.TP 1.5i X.B elf Xvery high X.B quickness Xand above average X.B magic level Xare X.B elves Xselling points. X.TP 1.5i X.B dwarf Xvery high X.B strength Xand X.B energy level X, but with a tendency to be rather slow and not too bright. X.TP 1.5i X.B halfling Xrather quick and smart, with high X.B energy level X, but poor in X.B magic Xand X.B strength. XBorn with some X.B experience. X.TP 1.5i X.B experimento Xvery mediocre in all areas. However, the X.B experimento Xmay be placed almost anywhere within the playing grid. X.PP XThe possible ranges for starting statistics are summarized in Xthe following table. X.PP X.TS Xl c c c c c c Xl c c c c c c. XType Strength Quick Mana Energy Brains Magic X_ XMag. User 20-25 30-35 50-100 30-45 60-85 5-9 XFighter 40-55 30-35 30-50 45-70 25-45 3-6 XElf 35-45 28-38 45-90 30-50 40-65 4-7 XDwarf 50-70 25-30 25-45 60-100 20-40 2-5 XHalfling 20-25 34 25-45 55-90 40-75 1-4 XExperimento 25 27 100 35 25 2 X.TE X.PP XNot only are the starting characteristics different for the different Xcharacter types, the characteristics progress at different rates for the Xdifferent types as the character goes up in X.B level. Experimentoes' Xcharacteristics progress randomly as one of the other types. XThe progression as characters increase in X.B level Xis summarized in the following table. X.PP X.TS Xl c c c c c Xl n n n n n. XType Strength Mana Energy Brains Magic X_ XMag. User 2.0 75 20 6 2.75 XFighter 3.0 40 30 3.0 1.5 XElf 2.5 65 25 4.0 2.0 XDwarf 5 30 35 2.5 1 XHalfling 2.0 30 30 4.5 1 X.TE X.PP XCharacter types are identified by certain numeric values as follows: X.br X1: X.B Magic User X2: X.B Fighter X3: X.B Elf X4: X.B Dwarf X5: X.B Halfling X6: X.B Experimento X.PP XCharacters with one or more X.B crowns Xare designated as a negative type. X.B Kings Xhave ten added to their type; members of the X.B council of the wise Xhave twenty added to their type. X.B Valar Xare type 99, and X.B ex-valar Xare type 90. X.sh "Spells" XDuring the course of the game, the player may exercise his/her particular Xmagic powers. These cases are described below. X.TP 1.5i X.B cloak X.I magic level necessary: X20 (plus level 7) X.br X.I mana used: X35 plus 3 per rest period X.br XUsed during normal play. Prevents monsters from finding the character, Xas well as hiding the player from other players. His/her coordinates Xshow up as '?' in the X.B players Xoption. Players cannot collect X.B mana, Xfind trading posts, or discover the X.B grail Xwhile cloaked. Calling a monster uncloaks, as well as choosing Xthis option while cloaked. X.br X.TP 1.5i X.B teleport X.I magic level necessary: X40 (plus level 12) X.br X.I mana used: X30 per 75 moved X.br XUsed during normal play. Allows the player too move with much more freedom Xthan with the X.B move Xoption, at the price of expending mana. The maximum distance possible Xto move is based upon X.B level Xand X.B magic level. X.TP 1.5i X.B power blast X.I magic level necessary: Xnone X.br X.I mana used: X5 times X.B level X.br XUsed during inter-terminal battle. Damage is based upon X.B magic level Xand X.B strength. XHits much harder than a normal hit. X.TP 1.5i X.B all or nothing X.I magic level necessary: Xnone X.br X.I mana used: X1 X.br XUsed while combatting monsters. XHas a 25% chance of working. If it works it hits the monster just enough Xto kill it. If it fails, it doesn't hit the monster, and doubles the Xmonster's X.B quickness Xand X.B strength. XParalyzed monsters wake up much quicker as a result of this spell. X.TP 1.5i X.B magic bolt X.I magic level necessary: X5 X.br X.I mana used: Xvariable X.br XUsed while combatting monsters. Hits the monster based upon the amount Xof X.B mana Xexpended and X.B magic level. XGuaranteed to hit at least 10 per X.B mana. X.TP 1.5i X.B force field X.I magic level necessary: X15 X.br X.I mana used: X30 X.br XUsed during monster combat. Throws up a shield to protect from damage. XThe shield is added to actual energy level, and is a fixed number, based Xupon maximum energy. Normally, damage occurs first to the shield, and Xthen to the players actual X.B energy level. X.TP 1.5i X.B transform X.I magic level necessary: X25 X.br X.I mana used: X50 X.br XUsed during monster combat. Transforms the monster randomly into one Xof the other 100 monsters from the monster file. X.TP 1.5i X.B increase might X.I magic level necessary: X35 X.br X.I mana used: X75 X.br XUsed during combat with monsters. Increases strength up to a certain maximum. X.TP 1.5i X.B invisibility X.I magic level necessary: X45 X.br X.I mana used: X90 X.br XUsed while fighting monsters. Makes it harder for the monster to hit, Xby temporarily increasing the player's X.B quickness. XThis spell may be thrown several times, but a maximum level will be reached. X.TP 1.5i X.B transport X.I magic level necessary: X60 X.br X.I mana used: X125 X.br XUsed during monster combat. Transports the monster away from the Xplayer. Success is base upon player's X.B magic Xand X.B brains, Xand the monster's X.B experience. XIf it fails the player is transported instead. 60% of the time, the monster Xwill drop any treasure it was carrying. X.TP 1.5i X.B paralyze X.I magic level necessary: X75 X.br X.I mana used: X150 X.br XUsed during monster combat. "Freezes" the monster by putting its X.B quickness Xslightly negative. The monster will slowly wake up. Success is based Xupon player's X.B magic Xand the monster's X.B experience. XIf it fails, nothing happens. X.TP 1.5i X.B specify X.I magic level necessary: Xnone X.br X.I mana used: X1000 X.br XUsed during monster combat only by X.B valar Xor X.B council of the wise. XAllows the player to pick which monster to fight. X.sh "Monsters" XMonsters get bigger as one moves farther from the origin (0,0). Rings of Xdistance 125 from the origin determine the size. A monster's X.B experience, energy level, Xand X.B brains Xare multiplied by the size. X.B Strength Xis increase 50% per size over one, and X.B quickness Xremains the same, regardless of size. X.PP XAlso, meaner monsters are to be found as one progress farther out Xfrom the origin. Monsters also may flock. The percent chance of that Xhappening is designated as X.B flock% Xin the monster listing. Monsters outside the first ring Xmay carry treasure, as determined by their treasure type. XFlocking monsters, and bigger monsters increase the chances of treasure. X.PP XCertain monsters have special abilities; they are as follows: X.TP 1.5i X.B Unicorn Xcan only be subdued if the player is in possession of a X.B virgin. X.TP 1.5i X.B Modnar Xhas random characteristics, including treasure type. X.TP 1.5i X.B Mimic Xwill pick another name from the list of monsters in order to Xconfuse. X.TP 1.5i X.B Dark Lord Xvery nasty person. Does not like to be hit (especially nicked), Xand many spells do not work well against him. XOne can always X.B evade Xfrom the X.B Dark Lord. X.TP 1.5i X.B Leanan-Sidhe Xalso a very nasty person. She will permanently sap X.B strength Xfrom someone. X.TP 1.5i X.B Saruman Xwanders around with X.B Wormtongue X, who can steal a X.B palantir. XAlso, X.B Saruman Xmay turn a player's gems into gold pieces, Xor scramble her/his stats. X.TP 1.5i X.B Thaumaturgist Xcan transport a player. X.TP 1.5i X.B Balrog Xinflicts damage by taking away X.B experience X, not X.B energy. X.TP 1.5i X.B Vortex Xmay take some X.B mana. X.TP 1.5i X.B Nazgul Xmay try to steal a X.B ring Xor neutralize part of one's X.B brains. X.TP 1.5i X.B Tiamat Xmay take half a players X.B gold Xand X.B gems Xand escape. X.TP 1.5i X.B Kobold Xmay get nasty and steal one gold piece and run away. X.TP 1.5i X.B Shelob Xmay bite, inflicting the equivalent of one X.B poison. X.TP 1.5i X.B Assorted Faeries XThese are killed if attacking someone carrying X.B holy water. XThese are X.B Cluricaun, Fir Darrig, Fachan, X.B Ghille Dhu, Bogle, Killmoulis, Xand X.B Bwca. X.TP 1.5i X.B Lamprey Xmay bite, inflicting 1/2 of a X.B poison. X.TP 1.5i X.B Shrieker Xwill call one of its (much bigger) buddies if picked upon. X.TP 1.5i X.B Bonnacon Xwill become bored with battle, fart, and run off. X.TP 1.5i X.B Smeagol Xwill try to steal a X.B ring Xfrom a player, if given the chance. X.TP 1.5i X.B Succubus Xmay inflict damage through a X.B force field. XThis subtracts from X.B energy level Xinstead of any shield the player may have thrown up. XThis is a very easy way to die. X.TP 1.5i X.B Cerberus Xloves metal and will steal all the metal treasures from Xa player if able. X.TP 1.5i X.B Ungoliant Xcan bite and poison. This inflicts five X.B poisons X, and also takes one from the player's X.B quickness. X.TP 1.5i X.B Jabberwock Xmay tire of battle, and leave after calling one of his friends X( X.B Jubjub Bird Xor X.B Bandersnatch X). X.TP 1.5i X.B Morgoth Xactually X.B Modnar X, but reserved for X.B council of the wise, valar, Xand X.B ex-valar. XFights with X.B Morgoth Xend when either he or the player dies. His characteristics Xare calculated based upon the player's. The player is given Xthe chance to ally with him. No magic, except X.B force field Xworks when battling X.B Morgoth. X.TP 1.5i X.B Troll Xmay regenerate its X.B energy Xand X.B strength Xwhile in battle. X.TP 1.5i X.B Wraith Xmay make a player blind. X.sh "Treasures" XVarious treasure types are as follows: X.TP 1.5i X.B Type zero X.I none X.TP 1.5i X.B Type one X.I power booster X\- adds mana. X.br X.I druid X\- adds experience. X.br X.I holy orb X\- subtracts 0.25 sin. X.TP 1.5i X.B Type two X.I amulet X\- protects from cursed treasure. X.br X.I holy water X\- kills X.B assorted faeries. X.br X.I hermit X\- reduces sin by 25% and adds some mana. X.TP 1.5i X.B Type three X.I shield X\- adds to maximum X.B energy level X.br X.I virgin X\- used to subdue a X.B unicorn X, or to give much X.B experience X(and some X.B sin X). X.br X.I athelas X\- subtracts one X.B poison. X.TP 1.5i X.B Type four (scrolls) X.I shield X* \- throws a bigger than normal X.B force field. X.br X.I invisible X* \- puts the finder's X.B quickness Xto one million. X.br X.I ten fold strength X* \- multiplies finder's strength by ten. X.br X.I pick monster X\- allows finder to pick next monster to battle. X.br X.I general knowledge X\- adds to finder's X.B brains Xand X.B magic level. X.PP XAll the scrolls except X.B general knowledge Xautomatically call a monster. Those that are marked with a * preserve any Xspells that were already in effect. Those that call monsters are only in Xeffect while in battle. X.TP 1.5i X.B Type five X.I dagger X\- adds to X.B strength. X.br X.I armour X\- same as a X.B shield, Xbut bigger. X.br X.I tablet X\- adds brains. X.TP 1.5i X.B Type six X.I priest X\- rests to maximum; adds X.B mana, brains; Xand halves X.B sin. X.br X.I Robin Hood X\- increases X.B shield Xand adds permanently to X.B strength. X.br X.I axe X\- like X.B dagger, Xbut bigger. X.TP 1.5i X.B Type seven X.I charm X\- protects from cursed treasure (used before X.B amulet X); used in conjunction with X.B blessing Xto battle X.B Dark Lord. X.br X.I Merlyn X\- adds X.B brains, magic, Xand X.B mana. X.br X.I war hammer X\- like an X.B axe, Xbut bigger. X.TP 1.5i X.B Type eight X.I healing potion X\- sets X.B poison Xto -2, or subtracts two from X.B poison, Xwhichever is better. X.br X.I transporter X\- allows finder to move anywhere. X.br X.I sword X\- like a X.B war hammer X, but bigger. X.TP 1.5i X.B Type nine X.I golden crown X\- allows the player to become X.B king, Xby going to (0,0). X.br X.I blessing X\- cuts X.B sin Xto 1/3, adds X.B mana, Xrests to max., kills X.B Dark Lord Xwith a X.B charm, Xand gives bearer first hit on all monsters. X.br X.I quicksilver X\- adds to X.B quickness. X.TP 1.5i X.B Type ten X.I elven boots X\- adds permanently to X.B quickness. X.TP 1.5i X.B Type eleven X.I palantir X\- allows one to see all the other players; used by X.B council of the wise Xto seek the X.B grail. X.TP 1.5i X.B Type twelve/thirteen X.I ring X\- allows one to hit much harder in battle, etc. X.PP XAny treasure type 10-13 monsters may instead carry a type nine treasure. X.PP XA monster may also be carrying X.B gold Xor X.B gems. XThese are used at X.B trading posts Xto buy things. A X.B gem Xis worth 1000 gold pieces. Too much X.B gold Xwill slow a player down. One may carry 1000 plus 200 per X.B level Xof X.B gold. XA X.B gem Xweighs one half a gold piece. XMonsters of treasure type 7 or higher may carry X.B gems. X.PP XThe chance of a cursed treasure is based upon treasure type. XThe more valuable treasures have a greater chance of being cursed. XA cursed treasure knocks X.B energy level Xvery low, and adds 0.25 X.B poison. X.sh "Rings" X.B Rings Xare only carried by X.B nazguls Xand X.B Dark Lord. XThey come in four different flavors. XAll X.B rings Xrest the player to maximum and cause him/her to hit much harder Xin battle with monsters (assuming one has chosen to use the X.B ring Xfor battle.) X.PP XTwo types of X.B rings Xare cursed and come either from X.B nazguls Xor X.B Dark Lord. XAfter a few times of using these types, the player falls Xunder the control of the X.B ring, Xand strange, random things will occur. XEventually, the player dies, and gives his/her name to a monster Xon the file. XDying before the X.B ring Xis used up also renames the monster. X.PP XThe two remaining types of X.B rings Xare much more benign. XThe one from a X.B nazgul Xis good for a limited number of battle rounds, and will save Xthe player from death if it was being used when he/she died. XThe one from X.B Dark Lord Xis the same, except that it never is used up. X.B rings Xdisappear after saving someone from death. XIn general, cursed X.B rings Xoccur much more often than normal ones. XIt is usually not a good idea to pick one up. XThe only way to get rid of a X.B ring Xis to have a monster steal it. X.sh "King" XA player may become X.B king by finding a X.I crown Xand going to (0,0). Players must have a X.B level Xin the range of 10 to 1000 to be able to find a X.I crown. X.PP XOnce a player is king, he/she may do certain things while in Xthe Lord's Chamber (0,0). These fall under the X.B decree X('0') option. X.TP 1.5i X.I census XLists all players on file, whether playing or not. X.TP 1.5i X.I transport XThis is done to another player. It randomly moves the affected Xplayer about. A X.B charm Xprotects from transports. X.TP 1.5i X.I curse XThis is done to another player. It is analogous to cursed treasure, Xbut worse. It inflicts two X.B poison, Xknocks X.B energy level Xvery low, and degrades the maximum energy. It also Xremoves a X.B cloak. XA X.B blessing Xprotects from king's curses. X.TP 1.5i X.I energy void XThe king may put as many of these (within reason) scattered about Xhis/her kingdom as he/she pleases. XIf a player hits one, he/she loses X.B mana, energy, Xand X.B gold. XThe energy void disappears after being hit. X.TP 1.5i X.I bestow XThis is also done to another player. The king may Xwish to reward one or more loyal subjects by sharing his/her Xriches ( X.B gold X). Or it is a convenient way to dispose of some unwanted Xdeadweight. X.TP 1.5i X.I collect taxes XEveryone pays 10% tax on all X.B gold Xcollected, regardless of the existence of a X.B king. XThe king may collect this amount with this option. X.PP XThe X.B king Xmay also X.B teleport Xanywhere for free by using the origin as a starting place. X.sh "Special Places" XCertain regions of the playing grid have different names. XIn general, this is only to give the player some idea of Xhis/her present location. Some special places do exist. X.TP 1.5i X.I Trading Posts XThese are located at |x| == |y| == n*n*100 for n = 1, 2...1000. XTrading posts farther out have more things for sale. XBe careful about cheating merchants there, as they have short Xtempers. XMerchants are dishonest about 5% of the time. X.TP 1.5i X.I Lord's Chamber XThis is located at (0,0). Only players with X.B crowns Xmay enter. X.TP 1.5i X.I Point of No Return XThis is located beyond 1.2e+6 in any direction. XThe only way to return from here is a X.B transporter Xor to have a X.B valar Xrelocate the player. X.TP 1.5i X.I Dead Marshes XThis is a band located fairly distant from the origin. The first Xfourteen monsters (water monsters) can normally only be found here. X.TP 1.5i X.I Valhala XThis place is where the X.B valar Xresides. It is associated with no particular coordinate on the Xplaying grid. X.TP 1.5i X.I Wormholes XAt fixed locations on the grid are several holes to underground Xdefects in the playing area. XSixty-four chambers exist; sixteen of which open to the outside Xworld. XWhile in the wormholes, one move by going forward, backward, Xleft, or right. XOne can always undo a move by going in the opposite direction. XThe wormholes are mappable. XFor example, to move from the first wormhole {at (-400,0)} to Xthe second wormhole, type 'LL'. X.sh "Miscellaneous" XThere are several bits of trivial knowledge which fall under this category. X.PP XOnce a player reaches X.B level X5, the game will start to time out waiting for input. XThis is to try to keep the game a bit faster paced. X.PP XA X.I guru Xwill never be disgusted with your X.B sins Xif they are less than one. X.PP XA X.I medic Xwants half of a player's X.B gold Xto be happy. Offering more than one has, or a negative amount Xwill anger the X.I medic, Xwho will make the player worse (add one X.B poison X). X.PP XThe X.B Holy Grail Xdoes little for those who are not ready to behold it. XWhenever anyone finds it, it moves. XIt is always located within 1e+6 in any compass direction of the origin. X.PP XThere is a maximum amount of X.B mana Xand X.B charms Xa player may posses, based upon X.B level. X.I Quicksilver Xis always limited to to a maximum of 99. X.PP X.I Books Xbought at a X.B trading post Xincrease X.B brains, Xbased upon the number bought. XIt is unwise, however to buy more than 1/10 of one's X.B level Xin books at a time. X.PP XPlayers over level 10000 are automatically retired. X.PP XA X.I blindness Xgoes away in random time. X.sh "Inter-terminal Battle" XWhen two player's coordinates correspond, they may engage in battle. XIn general, the player with the highest X.B quickness Xgets the first hit. XIf the two players are severely mis-matched, the stronger player Xis drastically handicapped for the battle. XIn order to protect from being stuck in an infinite loop, Xthe player waiting for response may time out. Options for battle are: X.TP 1.5i X.I fight XInflicts damage upon other person. X.TP 1.5i X.I run away XEscape from battle. Has a 75% chance of working. X.TP 1.5i X.I power blast XBattle spell. X.TP 1.5i X.I luckout XOne-time chance to try to win against the foe. Has a 10% chance of working. X.PP XSometimes waits for the other player may be excessive, because Xhe/she may be battling a monster. Upon slaying a player in battle Xthe winner gets the other's X.B experience Xand treasures. X.B Rings Xdo not work for inter-terminal battle. X.sh "Council of the Wise, Valar" XA player automatically becomes a member of the X.B council of the wise Xupon reaching level 3000. Members of the council cannot have X.B rings. XMembers of the council have a few extra options which they can exercise. XThese fall under the X.B intervention X('8') option. XOne is to X.I heal Xanother player. This is just a quick way for that player to be rested Xto maximum and lose a little X.B poison. XThe main purpose in life for members of the council is to seek the X.B Holy Grail. XThis is done with a X.B palantir Xunder the X.I seek grail Xoption. The distance cited by the seek is accurate within 10%, in order Xnot to make it too easy to find the grail. Seeking costs 1000 X.B mana. XA player must have infintesimally small X.B sin, Xor else it's all over upon finding the grail. XIn order to help members of the council on their quest, they Xmay X.I teleport Xwith greater ease. X.PP XUpon finding the grail, the player advance to position of X.B valar. XHe/she may then exercise more and niftier options under X.I intervention. XThese include all of the council members' option plus the Xability to move other players about, bless them, and throw monsters at Xthem. X.B Valar Xare essentially immortal, but are actually given five lives. XIf these are used up, the player is left to die, and becomes an X.B ex-valar. X.B Valar Xcannot X.I move, teleport, Xor call monsters. XAny monsters which a X.B valar Xencounters are based upon his/her size. XOnly one valar may exists at a time. XA player replaces the exiting valar upon finding the grail. XThe valar is then bumped back to the council of the wise. X.SH BUGS XThe handling of incorrectly Xexitted characters is a kludge. The screen is set up assuming a 24 by 80 Xcharacter screen; no attempt was made to provide otherwise. XIf any of the data items get too big for the allotted space on the screen, Xno guarantees are made about what will happen. !EOR! echo extracting - func0.c sed 's/^X//' > func0.c << '!EOR!' X/* X * func0.c Phantasia support routines X */ X X#include "phant.h" X Xvoid treasure(stat,treastyp,size) /* select a treasure */ Xreg struct stats *stat; Xshort treastyp; Xreg int size; X{ Xreg int which; Xint ch; Xdouble temp, temp2; Xchar aline[35]; XFILE *fp; X X which = roll(1,3); X move(4,0); X clrtobot(); X move(6,0); X if (rnd() > 0.65) /* gold and gems */ X if (treastyp > 7) /* gems */ X { X temp = roll(1,(treastyp - 7)*(treastyp - 7)*(size - 1)/4); X printw("You have discovered %.0f gems! Will you pick them up ? ",temp); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch == 'Y') X if (rnd() < treastyp/40 + 0.05) /* cursed */ X { X addstr("They were cursed!\n"); X goto CURSE; X } X else X { X stat->gem += temp; X goto EXIT; X } X else X return; X } X else /* gold */ X { X temp = roll(treastyp*10,treastyp*treastyp*10*(size - 1)); X printw("You have found %.0f gold pieces. Do you want to pick them up ? ",temp); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch == 'Y') X if (rnd() < treastyp/35 + 0.04) /* cursed */ X { X addstr("They were cursed!\n"); X goto CURSE; X } X else X { X stat->gld += floor(0.9 * temp); X if ((fp = fopen(goldfile,"r")) == NULL) X { X error(goldfile); X /*NOTREACHED*/ X } X fread((char *) &temp2,sizeof(double),1,fp); X fclose(fp); X fp = fopen(goldfile,"w"); X temp2 += floor(temp/10); X fwrite((char *) &temp2,sizeof(double),1,fp); X fclose(fp); X goto EXIT; X } X else X return; X } X else /* other treasures */ X { X addstr("You have found some treasure. Do you want to inspect it ? "); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch != 'Y') X return; X else X if (rnd() < 0.08 && treastyp != 4) X { X addstr("It was cursed!\n"); X goto CURSE; X } X else X switch(treastyp) X { X case 1: X switch(which) X { X case 1: X addstr("You've discovered a power booster!\n"); X stat->man += roll(size*4,size*30); X break; X case 2: X addstr("You have encountered a druid.\n"); X stat->exp += roll(0,2000 + size*400); X break; X case 3: X addstr("You have found a holy orb.\n"); X stat->sin = max(0,stat->sin - 0.25); X break; X } X break; X case 2: X switch (which) X { X case 1: X addstr("You have found an amulet.\n"); X ++stat->amu; X break; X case 2: X addstr("You've found some holy water!\n"); X ++stat->hw; X break; X case 3: X addstr("You've met a hermit!\n"); X stat->sin *= 0.75; X stat->man += 12*size; X break; X } X break; X case 3: X switch (which) X { X case 1: X temp = roll(7,30 + size/10); X printw("You've found a +%.0f shield!\n",temp); X if (temp >= stat->shd) X stat->shd = temp; X else X somebetter(); X break; X case 2: X addstr("You have rescued a virgin. Will you be honorable ? "); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch == 'Y') X stat->vrg = TRUE; X else X { X stat->exp += 2000*size; X ++stat->sin; X } X break; X case 3: X addstr("You've discovered some athelas!\n"); X --stat->psn; X break; X } X break; X case 4: X addstr("You've found a scroll. Will you read it ? "); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch == 'Y') X switch ((int) roll(1,6)) X { X case 1: X addstr("It throws up a shield for you next monster.\n"); X getyx(stdscr, which, ch); X paws(which); X longjmp(fightenv,2); X /*NOTREACHED*/ X case 2: X addstr("It makes you invisible for you next monster.\n"); X getyx(stdscr, which, ch); X paws(which); X speed = 1e6; X longjmp(fightenv,0); X /*NOTREACHED*/ X case 3: X addstr("It increases your strength ten fold to fight your next monster.\n"); X getyx(stdscr, which, ch); X paws(which); X strength *= 10; X longjmp(fightenv,0); X /*NOTREACHED*/ X case 4: X addstr("It is a general knowledge scroll.\n"); X stat->brn += roll(2,size); X stat->mag += roll(1,size/2); X break; X case 5: X addstr("It tells you how to pick your next monster.\n"); X addstr("Which monster do you want [0-99] ? "); X which = inflt(); X which = min(99,max(0,which)); X fight(stat,which); X return; X case 6: X addstr("It was cursed!\n"); X goto CURSE; X } X break; X case 5: X switch (which) X { X case 1: X temp = roll(size/4+5,size/2 + 9); X printw("You've discovered a +%.0f dagger.\n",temp); X if (temp >= stat->swd) X stat->swd = temp; X else X somebetter(); X break; X case 2: X temp = roll(7.5 + size*3,size * 2 + 160); X printw("You have found some +%.0f armour!\n",temp); X if (temp >= stat->shd) X stat->shd = temp; X else X somebetter(); X break; X case 3: X addstr("You've found a tablet.\n"); X stat->brn += 4.5*size; X break; X } X break; X case 6: X switch (which) X { X case 1: X addstr("You've found a priest.\n"); X stat->nrg = stat->mxn + stat->shd; X stat->sin /= 2; X stat->man += 24*size; X stat->brn += size; X break; X case 2: X addstr("You have come upon Robin Hood!\n"); X stat->shd += size*2; X stat->str += size/2.5 + 1; X break; X case 3: X temp = roll(2 + size/4,size/1.2 + 10); X printw("You have found a +%.0f axe!\n",temp); X if (temp >= stat->swd) X stat->swd = temp; X else X somebetter(); X break; X } X break; X case 7: X switch (which) X { X case 1: X addstr("You've discovered a charm!\n"); X ++stat->chm; X break; X case 2: X addstr("You have encountered Merlyn!\n"); X stat->brn += size + 5; X stat->mag += size/3 + 5; X stat->man += size*10; X break; X case 3: X temp = roll(5+size/3,size/1.5 + 20); X printw("You have found a +%.0f war hammer!\n",temp); X if (temp >= stat->swd) X stat->swd = temp; X else X somebetter(); X break; X } X break; X case 8: X switch (which) X { X case 1: X addstr("You have found a healing potion.\n"); X stat->psn = min(-2,stat->psn-2); X break; X case 2: X addstr("You have discovered a transporter. Do you wish to go anywhere ? "); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch == 'Y') X { X addstr("X Y Coordinates ? "); X getstring(aline,80); X sscanf(aline,"%F %F",&stat->x,&stat->y); X stat->x = floor(stat->x); X stat->y = floor(stat->y); X } X break; X case 3: X temp = roll(10 + size/1.2,size*3 + 30); X printw("You've found a +%.0f sword!\n",temp); X if (temp >= stat->swd) X stat->swd = temp; X else X somebetter(); X break; X } X break; X case 10: X case 11: X case 12: X case 13: X if (rnd() < 0.33) X { X if (treastyp == 10) X { X addstr("You've found a pair of elven boots!\n"); X stat->quk += 2; X break; X } X else if (treastyp == 11 && !stat->pal) X { X addstr("You've acquired Saruman's palantir.\n"); X stat->pal = TRUE; X break; X } X else if (!stat->rng.type && stat->typ < 20 && (treastyp == 12 || treastyp == 13)) X { X if (treastyp == 12) X if (rnd() < 0.8) X { X which = NAZREG; X temp = 15; X } X else X { X which = NAZBAD; X temp = 10 + rngcalc(stat->typ) + roll(0,5); X } X else X if (rnd() > 0.9) X { X which = DLREG; X temp = 0; X } X else X { X which = DLBAD; X temp = 15 + rngcalc(stat->typ) + roll(0,5); X } X addstr("You've discovered a ring. Will you pick it up ? "); X ch = getans("NY", FALSE); X addstr("\n\n"); X if (ch == 'Y') X { X stat->rng.type = which; X stat->rng.duration = temp; X } X break; X } X } X case 9: X switch (which) X { X case 1: X if (!(stat->lvl > 1000 || stat->crn > floor((double) stat->lvl/100) X || stat->lvl < 10)) X { X addstr("You have found a golden crown!\n"); X ++stat->crn; X break; X } X case 2: X addstr("You've been blessed!\n"); X stat->bls = TRUE; X stat->sin /=3; X stat->nrg = stat->mxn + stat->shd; X stat->man += 100*size; X break; X case 3: X temp = roll(1,size/5+5); X temp = min(temp,99); X printw("You have discovered some +%.0f quicksilver!\n",temp); X if (temp >= stat->quks) X stat->quks = temp; X else X somebetter(); X break; X } X break; X } X } X goto EXIT; XCURSE: if (stat->chm) X { X addstr("But your charm saved you!\n"); X --stat->chm; X } X else if (stat->amu) X { X addstr("But your amulet saved you!\n"); X --stat->amu; X } X else X { X stat->nrg = (stat->mxn + stat->shd)/10; X stat->psn += 0.25; X } XEXIT: X getyx(stdscr, which, ch); X paws(which); X} X Xvoid callmonster(which,size,mons) /* fill a structure with monster 'which' of size 'size' */ Xreg int which, size; Xreg struct mstats *mons; X{ XFILE *fp; Xchar instr[100]; X X which = min(which,99); X if ((fp = fopen(monsterfile,"r")) == NULL) X { X error(monsterfile); X /*NOTREACHED*/ X } X for (++which; which; --which) X fgets(instr,100,fp); X strncpy(mons->name,instr,24); X mons->name[24] = '\0'; X sscanf(instr + 24,"%F%F%F%F%F%d%d%d",&mons->str,&mons->brn,&mons->spd,&mons->hit, X &mons->exp,&mons->trs,&mons->typ,&mons->flk); X if (mons->typ == 2) /* Modnar */ X { X mons->str *= rnd() + 0.5; X mons->brn *= rnd() + 0.5; X mons->spd *= rnd() + 0.5; X mons->hit *= rnd() + 0.5; X mons->exp *= rnd() + 0.5; X mons->trs *= rnd(); X } X else if (mons->typ == 3) /* mimic */ X { X fseek(fp,0L,0); X for (which = roll(0,100); which; --which) X fgets(instr,100,fp); X strncpy(mons->name,instr,24); X } X trunc(mons->name); X mons->str += (size-1)*mons->str/2; X mons->brn *= size; X mons->spd += size * 1.e-9; X mons->hit *= size; X mons->exp *= size; X fclose(fp); X} X Xstruct /* lookup table for rolling stats and making increases upon gaining levels */ X { X struct X { X int base; X int interval; X float increase; X } quick, strength, mana, energy, brains, magic; X } table[7] = X { X/* mag. usr: */ 30, 6, 0.0, 20, 6, 2.0, 50,51,75.0, 30,16,20.0, 60,26, 6.0, 5, 5,2.75, X/* fighter: */ 30, 6, 0.0, 40,16, 3.0, 30,21,40.0, 45,26,30.0, 25,21, 3.0, 3, 4, 1.5, X/* elf: */ 32, 7, 0.0, 35,11, 2.5, 45,46,65.0, 30,21,25.0, 40,26, 4.0, 4, 4, 2.0, X/* dwarf: */ 25, 6, 0.0, 45,21, 5.0, 25,21,30.0, 60,41,35.0, 20,21, 2.5, 2, 4, 1.0, X/* halfling: */ 34, 0, 0.0, 20, 6, 2.0, 25,21,30.0, 55,36,30.0, 40,36, 4.5, 1, 4, 1.0, X/* exprmnto: */ 27, 0, 0.0, 25, 0, 0.0, 100,0, 0.0, 35, 0, 0.0, 25, 0, 0.0, 2, 0, 0.0, X/* super: */ 38, 0, 0.0, 65, 0, 0.0, 100,0, 0.0, 80, 0, 0.0, 85, 0, 0.0, 9, 0, 0.0 X }; X Xvoid genchar(res,type) /* init a charac struct */ Xint type; Xreg struct stats *res; X{ Xregister int subscript; X X if (type < '1' || type > '6') X if (type != '7' || !su) X type = '2'; /* fighter is default */ X subscript = type - '1'; X res->quk = roll(table[subscript].quick.base,table[subscript].quick.interval); X res->str = roll(table[subscript].strength.base,table[subscript].strength.interval); X res->man = roll(table[subscript].mana.base,table[subscript].mana.interval); X res->mxn = res->nrg = roll(table[subscript].energy.base,table[subscript].energy.interval); X res->brn = roll(table[subscript].brains.base,table[subscript].brains.interval); X res->mag = roll(table[subscript].magic.base,table[subscript].magic.interval); X res->typ = subscript; X if (subscript < 6) X ++res->typ; X if (type == '5') X res->exp = roll(600,200); /* give halfling some exp. */ X} X Xvoid movelvl(stat) /* update stats for new level */ Xreg struct stats *stat; X{ Xreg int type; Xreg unsigned new; Xdouble inc; X X changed = TRUE; X type = abs(stat->typ); X if (type < 6) X ; /* normal */ X else if (type < 10) X type = roll(1,5); /* experimento */ X else if (type < 20) X { X type -= 10; /* king */ X if (type > 5) X type = roll(1,5); /* experimento */ X } X else if (type < 26) X type -= 20; /* council of wise */ X else X type = roll(1,5); /* everything else */ X new = level(stat->exp); X inc = new - stat->lvl; X --type; /* set up for subscripting into table */ X stat->str += table[type].strength.increase * inc; X stat->man += table[type].mana.increase * inc; X stat->brn += table[type].brains.increase * inc; X stat->mag += table[type].magic.increase * inc; X stat->mxn += table[type].energy.increase * inc; X stat->nrg = stat->mxn + stat->shd; X if ((stat->lvl = min(10000,new)) >= 1000) X { /* no longer able to be king */ X stat->gld += stat->crn * 5000; X stat->crn = 0; X stat->typ = abs(stat->typ); X } X if (stat->lvl >= 3000 && stat->typ < 20) X { /* make a member of the council */ X mvaddstr(6,0,"You have made it to the Council of the Wise.\nGood Luck on your search for the Holy Grail.\n"); X stat->rng.type = 0; X stat->rng.duration = 3; X stat->typ = abs(stat->typ) + (stat->typ > 10 ? 10 :20); X } X} X Xchar *printloc(x,y) /* return a pointer to a string specifying location */ Xdouble x,y; /* also, set some global flags */ X{ Xreg int size, loc; Xreg char *label; Xstatic char res[80], X *nametable[4][4] = /* names of places */ X { X "Anorien", "Ithilien", "Rohan", "Lorien", X "Gondor", "Mordor", "Dunland", "Rovanion", X "South Gondor", "Khand", "Eriador", "The Iron Hills", X "Far Harad", "Near Harad", "The Northern Waste", "Rhun" X }; X X throne = beyond = marsh = FALSE; X if (wmhl) X return (strcpy(res," is in the Wormholes")); X else if (valhala) X return (strcpy(res," is in Valhala")); X else if ((size = circ(x,y)) >= 1000) X { X if (max(abs(x),abs(y)) > 1100000) X { X label = "The Point of No Return"; X beyond = TRUE; X } X else X label = "The Ashen Mountains"; X } X else if (size >= 55) X label = "Morannon"; X else if (size >= 35) X label = "Kennaquahair"; X else if (size >= 20) X { X label = "The Dead Marshes"; X marsh = TRUE; X } X else if (size >= 9) X label = "The Outer Waste"; X else if (size >= 5) X label = "The Moors Adventurous"; X else X { X if (x == 0.0 && y == 0.0) X { X label = "The Lord's Chamber"; X throne = TRUE; X } X else X { X /* this expression is split to prevent compiler loop with some compilers */ X loc = ((x > 0.0) ? 1 : 0); X loc += ((y >= 0.0) ? 2 : 0); X label = nametable[size-1][loc]; X } X } X sprintf(res," is in %s (%.0f,%.0f)",label,x,y); X return (res); X} X Xvoid initchar(stat) /* put in some default values */ Xreg struct stats *stat; X{ X stat->x = roll(-125,251); X stat->y = roll(-125,251); X stat->exp = stat->lvl = stat->sin = 0; X stat->crn = stat->psn = 0; X stat->rng.type = NONE; X stat->rng.duration = 0; X stat->blind = stat->vrg = stat->pal = FALSE; X stat->hw = stat->amu = stat->bls = 0; X stat->chm = 0; X stat->gem = 0.1; X stat->gld = roll(25,50) + roll(0,25) + 0.1; X stat->quks = stat->swd = stat->shd = 0; X stat->typ = 0; X stat->status = stat->tampered = OFF; X stat->scratch1 = stat->scratch2 = 0.0; X stat->wormhole = 0; X stat->age = 0; X stat->degen = 1; X stat->istat = 0; X} X Xvoid trade(stat) /* trading post */ Xreg struct stats *stat; X{ Xstatic struct X { X char *item; X int cost; X } menu[] = X { X "Mana",1, X "Shield",5, X "Book",200, X "Sword",500, X "Charm",1000, X "Quiksilver",2500, X "Blessing",1000, X "Gem",1000 /* this is only to ease changing the value of gems */ X }; Xdouble temp; Xint ch; Xreg int size, loop; Xbool cheat = FALSE; X X changed = TRUE; X clear(); X addstr("You are at a trading post. All purchases must be made with gold."); X size = sqrt(abs(stat->x/100)) + 1; X size = min(7,size); X /* set up cost of blessing */ X menu[6].cost = 1000 * (stat->lvl + 5); X mvprintw(4,0,"L:Leave P:Purchase S:Sell Gems ? "); X move(6,0); X for (loop = 0; loop < size; ++loop) X printw("(%d) %-10s: %6d\n",loop+1,menu[loop].item,menu[loop].cost); XPROMPT: mvprintw(1,0,"Gold: %9.0f Gems: %9.0f Level: %6u Charms: %6d\n",stat->gld,stat->gem,stat->lvl,stat->chm); X printw("Shield:%9.0f Sword: %9.0f Quicksilver:%3d Blessed: %s", X stat->shd,stat->swd,stat->quks,(stat->bls ? " True" : "False")); X move(4,36); X ch = getans("LPS", FALSE); X move(15,0); X clrtobot(); X switch(ch) X { X case 'L': X case '\n': X stat->x -= roll(-25, 50); X stat->y -= roll(-25, 50); X return; X case 'P': X mvaddstr(15,0,"What what would you like to buy ? "); X ch = getans(" 1234567", FALSE); X move(15,0); X clrtoeol(); X if (ch - '0' > size) X addstr("Sorry, this merchant doesn't have that."); X else X switch (ch) X { X case '1': X printw("Mana is one per %d gold piece. How many do you want (%.0f max) ? ",menu[0].cost,floor(stat->gld/menu[0].cost)); X temp = inflt(); X if (temp * menu[0].cost > stat->gld || temp < 0) X goto CHEAT; X else X { X stat->gld -= floor(temp) * menu[0].cost; X if (rnd() < 0.02) X goto DISHON; X else X stat->man += floor(temp); X } X break; X case '2': X printw("Shields are %d per +1. How many do you want (%.0f max) ? ",menu[1].cost,floor(stat->gld/menu[1].cost)); X temp = inflt(); X if (!temp) X break; X if (temp * menu[1].cost > stat->gld || temp < 0) X goto CHEAT; X else X { X stat->gld -= floor(temp) * menu[1].cost; X if (rnd() < 0.02) X goto DISHON; X else X stat->shd = floor(temp); X } X break; X case '3': X printw("A book costs %d gp. How many do you want (%.0f max) ? ",menu[2].cost,floor(stat->gld/menu[2].cost)); X temp = inflt(); X if (temp * menu[2].cost > stat->gld || temp < 0) X goto CHEAT; X else X { X stat->gld -= floor(temp) * menu[2].cost; X if (rnd() < 0.02) X goto DISHON; X else X if (rnd()*temp > stat->lvl/10 && temp != 1) X { X printw("\nYou blew your mind!\n"); X stat->brn /= 5; X } X else X stat->brn += floor(temp)*roll(20,8); X } X break; X case '4': X printw("Swords are %d gp per +1. How many + do you want (%.0f max) ? ",menu[3].cost,floor(stat->gld/menu[3].cost)); X temp = inflt(); X if (!temp) X break; X if (temp * menu[3].cost > stat->gld || temp < 0) X goto CHEAT; X else X { X stat->gld -= floor(temp) * menu[3].cost; X if (rnd() < 0.02) X goto DISHON; X else X stat->swd = floor(temp); X } X break; X case '5': X printw("A charm costs %d gp. How many do you want (%.0f max) ? ",menu[4].cost,floor(stat->gld/menu[4].cost)); X temp = inflt(); X if (temp * menu[4].cost > stat->gld || temp < 0) X goto CHEAT; X else X { X stat->gld -= floor(temp) * menu[4].cost; X if (rnd() < 0.02) X goto DISHON; X else X stat->chm += floor(temp); X } X break; X case '6': X printw("Quicksilver is %d gp per +1. How many + do you want (%.0f max) ? ",menu[5].cost,floor(stat->gld/menu[5].cost)); X temp = inflt(); X if (!temp) X break; X if (temp * menu[5].cost > stat->gld || temp < 0) X goto CHEAT; X else X { X stat->gld -= floor(temp) * menu[5].cost; X if (rnd() < 0.02) X goto DISHON; X else X stat->quks = min(99,floor(temp)); X } X break; X case '7': X printw("A blessing requires a %d gp donation. Still want one ? ",menu[6].cost); X ch = getans("NY", FALSE); X if (ch == 'Y') X if (stat->gld < menu[6].cost) X goto CHEAT; X else X { X stat->gld -= menu[6].cost; X if (rnd() < 0.02) X goto DISHON; X else X stat->bls = TRUE; X } X break; X } X break; X case 'S': X mvprintw(15,0,"A gem is worth %d gp. How many do you want to sell (%.0f max) ? ",menu[7].cost,stat->gem); X temp = inflt(); X if (temp > stat->gem || temp < 0) X goto CHEAT; X else X { X stat->gem -= floor(temp); X stat->gld += floor(temp) * menu[7].cost; X } X } X goto PROMPT; X XCHEAT: move(17,0); X if (!cheat) X { X addstr("Come on, merchants aren't stupid. Stop cheating.\n"); X cheat = TRUE; X goto PROMPT; X } X else X { X addstr("You had your chance. This merchant happens to be\n"); X printw("a %.0f level magic user, and you made %s mad!\n",roll(size*10,size*20),(rnd() < 0.5) ? "him" : "her"); X stat->x += roll(-250,500)*size; X stat->y += roll(-250,500)*size; X stat->nrg = min(size*20,stat->mxn); X ++stat->sin; X paws(23); X } X return; X XDISHON: mvaddstr(17,0,"The merchant stole your money!"); X refresh(); X stat->x -= floor(stat->x/10); X stat->y -= floor(stat->y/10); X sleep(2); X} X Xvoid printstats(stat) /* show characteristics */ Xreg struct stats *stat; X{ X mvprintw(0,0,"%s%s\n",stat->name,printloc(stat->x,stat->y)); X mvprintw(1,0,"Level :%7u Energy :%9.0f(%9.0f) Mana :%9.0f Users:%3d\n", X stat->lvl,stat->nrg,stat->mxn + stat->shd,stat->man,users); X mvprintw(2,0,"Quick :%3.0f(%3d) strength:%9.0f(%9.0f) Gold :%9.0f ", X speed,stat->quk + stat->quks,strength,stat->str + stat->swd,stat->gld); X switch (stat->status) X { X case PLAYING: X if (stat->nrg < 0.2 * (stat->mxn + stat->shd)) X addstr("Low Energy\n"); X else if (stat->blind) X addstr("Blind\n"); X else X clrtoeol(); X break; X case CLOAKED: X addstr("Cloaked\n"); X break; X case INBATTLE: X addstr("In Battle\n"); X break; X case OFF: X addstr("Off\n"); X } X} X Xvoid showall(stat) /* show special items */ Xreg struct stats *stat; X{ Xstatic char *flags[] = X { X "False", X " True" X }; X X mvprintw(6,0,"Type: %3d -- ",stat->typ); X switch (abs(stat->typ)) X { X case 1: X case 11: X case 21: X addstr("Magic User"); X break; X case 2: X case 12: X case 22: X addstr("Fighter"); X break; X case 3: X case 13: X case 23: X addstr("Elf"); X break; X case 4: X case 14: X case 24: X addstr("Dwarf"); X break; X case 5: X case 15: X case 25: X addstr("Halfling"); X break; X case 6: X case 16: X case 26: X addstr("Experimento"); X break; X case 90: X addstr("Ex-Valar"); X break; X case 99: X addstr("Valar"); X } X if (stat->typ > 10 && stat->typ < 90) X if (stat->typ > 20) X addstr(" (Council of Wise)"); X else X addstr(" (King)"); X addch('\n'); X mvprintw(8,0,"Experience: %9.0f",stat->exp); X mvprintw(9,0,"Brains : %9.0f",stat->brn); X mvprintw(10,0,"Magic Lvl : %9.0f",stat->mag); X mvprintw(11,0,"Sin : %9.5f",stat->sin); X mvprintw(12,0,"Poison : %9.5f",stat->psn); X mvprintw(13,0,"Gems : %9.0f",stat->gem); X mvprintw(14,0,"Age : %9d",stat->age); X mvprintw(8,40,"Holy Water: %9d",stat->hw); X mvprintw(9,40,"Amulets : %9d",stat->amu); X mvprintw(10,40,"Charms : %9d",stat->chm); X mvprintw(11,40,"Crowns : %9d",stat->crn); X mvprintw(12,40,"Shield : %9.0f",stat->shd); X mvprintw(13,40,"Sword : %9.0f",stat->swd); X mvprintw(14,40,"Quickslver: %9d",stat->quks); X X mvprintw(15,0,"Blessing: %s Ring: %s Virgin: %s Palantir: %s", X flags[stat->bls],flags[stat->rng.type != 0],flags[stat->vrg],flags[stat->pal]); X} X Xvoid neatstuff(stat) /* random things */ Xreg struct stats *stat; X{ Xdouble temp; Xint ch; X X switch ((int) roll(0,100)) X { X case 1: X case 2: X if (stat->psn > 0) X { X mvaddstr(4,0,"You've found a medic! How much will you offer to be cured ? "); X temp = inflt(); X if (temp < 0 || temp > stat->gld) X { X mvaddstr(6,0,"He was not amused, and made you worse.\n"); X ++stat->psn; X } X else if (rnd()/2.0 > (temp + 1)/max(stat->gld,1)) X mvaddstr(5,0,"Sorry, he wasn't interested.\n"); X else X { X mvaddstr(5,0,"He accepted."); X stat->psn = max(0,stat->psn-1); X stat->gld -= floor(temp); X } X } X break; X case 3: X mvaddstr(4,0,"You've been caught raping and pillaging!\n"); X stat->exp += 4000; X stat->sin += 0.5; X break; X case 4: X temp = roll(6,50); X mvprintw(4,0,"You've found %.0f gold pieces, want them ? ",temp); X clrtoeol(); X ch = getans("NY", FALSE); X if (ch == 'Y') X stat->gld += temp; X break; X case 5: X if (stat->sin > 1) X { X mvaddstr(4,0,"You've found a Holy Orb!\n"); X stat->sin -= 0.25; X } X break; X case 6: X if (stat->psn < 1) X { X mvaddstr(4,0,"You've been hit with a plague!\n"); X ++stat->psn; X } X break; X case 7: X mvaddstr(4,0,"You've found some holy water.\n"); X ++stat->hw; X break; X case 8: X mvaddstr(4,0,"You've met a Guru. . ."); X if (rnd()*stat->sin > 1) X addstr("You disgusted him with your sins!\n"); X else if (stat->psn > 0) X { X addstr("He looked kindly upon you, and cured you.\n"); X stat->psn = 0; X } X else X { X addstr("He rewarded you for your virtue.\n"); X stat->man += 50; X stat->shd += 2; X } X break; X case 9: X mvaddstr(4,0,"You've found an amulet.\n"); X ++stat->amu; X break; X case 10: X if (stat->blind) X { X mvaddstr(4,0,"You've regained your sight!\n"); X stat->blind = FALSE; X } X break; X default: X if (stat->psn > 0) X stat->nrg -= min(stat->psn*stat->mxn/45,0.9*stat->mxn); X stat->nrg = max(stat->nrg,floor(stat->mxn/11)); X } X} !EOR!
estes@ttrda.UUCP (Edward Estes ) (09/05/85)
# -------CUT HERE------- # This is a shar archieve. Extract with sh, not csh. # The rest of this file will extract: # Makefile.noxst Makefile.xstr fight.c func1.c phant.h echo extracting - Makefile.noxst sed 's/^X//' > Makefile.noxst << '!EOR!' X# Makefile for Phantasia 3.3.1 X# X# Use this makefile if you don't have 'xstr'. Use the other makefile if you do. X# To create game: X# X# 1) Set up a directory where the game and its support files will live. X# (It is suggested that the source be kept somewhere else.) X# X# 2) Set up the variables in Makefile to reflect your particular situation. X# X# 3) Check out ok_to_play() at the end of main.c if you want to include X# code to restrict access at certain times. X# X# 4) 'make install' and watch it fly. X# X# NOTE: It is important to run 'setup' before trying to run 'phantasia'. X# The install procedure does this for you. X XRM = -rm XSHAR = /a2/estes/bin/shar X X# Add '-ljobs' to LIBS if 4.1bsd; add -ltermlib if not SVR2 XLIBS = -lm -lcurses X# May need '-I/usr/include/sys' for 4.2bsd X# May need '-f' on machines without floating point hardware XCFLAGS = -O X X# DEST is where the program and its support files reside XDEST = /a2/estes/phant X X# The following are program constants which are implementation dependent. X# X# PATH is the same as $DEST. Note that there is no closing quote here. X# WIZARD is the login of the one who will clean up things. X# UID is the uid of game wizard. X# RAND is one more than the largest number generated by rand(). X# Possible values for this are: X# 32768.0 (for 15 bit rand()) X# 65536.0 (for 16 bit rand()) X# 2147483648.0 (for 31 bit rand()) X# ACCESS is fopen() access to open a file for writing, without X# clearing the file, e.g. "a", or "r+". (Use "r+" if you have it.) X# define OK_TO_PLAY to restrict playing access. Also see function ok_to_play() X# in main.c, and tailor to your own needs. X# define ENEMY to include code for checking of a 'hit list' of resricted X# accounts. The list of logins goes in the file 'enemy'. X# define BSD41 for 4.1bsd X# define BSD42 for 4.2bsd X# define SYS3 for System III, or similar X# define SYS5 for System V X# define SMALL to save a little space (omits wormholes) X# If you don't have 'strchr()', put '-Dstrchr=index' below. XFLAGS = -DPATH=\"${DEST} \ X -DWIZARD=\"estes\" \ X -DUID=419 \ X -DRAND=32768.0 \ X -DACCESS=\"r+\" \ X -DOK_TO_PLAY \ X -DENEMY \ X -DSYS5 X XOFILES = main.o fight.o func0.o func1.o func2.o func3.o X Xall: phantasia setup phant.help X X# Need separate i/d space on small machines Xphantasia: ${OFILES} pathdefs.o X ${CC} ${OFILES} pathdefs.o ${LIBS} -o phantasia X X${OFILES}: phant.h X ${CC} -c ${CFLAGS} ${FLAGS} $*.c X Xpathdefs.o: phant.h X ${CC} -c ${CFLAGS} ${FLAGS} pathdefs.c X Xsetup: phant.h pathdefs.o X ${CC} ${CFLAGS} ${FLAGS} setup.c -o setup pathdefs.o -lm X Xlint: X lint ${CFLAGS} ${FLAGS} func?.c main.c fight.c pathdefs.c ${LIBS} X X# the flags below on tbl and nroff are to make a line printable version Xphant.help: phant.nr X tbl -TX phant.nr | nroff -Ttn300 -man > phant.help X Xinstall: all X cp phantasia monsters phant.help ${DEST} X chmod 755 ${DEST} X chmod 4711 ${DEST}/phantasia X chmod 644 ${DEST}/phant.help X setup X Xclean: X ${RM} -f *.o phantasia phant.help phant.pt? X Xshar: X ${SHAR} README phant.nr func0.c > phant.pt1 X ${SHAR} Makefile.* fight.c func1.c phant.h > phant.pt2 X ${SHAR} func2.c func3.c main.c monsters pathdefs.c setup.c > phant.pt3 !EOR! echo extracting - Makefile.xstr sed 's/^X//' > Makefile.xstr << '!EOR!' X# Makefile for Phantasia 3.3.1 X# X# Use this makefile if you have 'xstr'. Use the other makefile if you don't. X# X# To create game: X# X# 1) Set up a directory where the game and its support files will live. X# (It is suggested that the source be kept somewhere else.) X# X# 2) Set up the variables in Makefile to reflect your particular situation. X# X# 3) Check out ok_to_play() at the end of main.c if you want to include X# code to restrict access at certain times. X# X# 4) 'make install' and watch it fly. X# X# NOTE: It is important to run 'setup' before trying to run 'phantasia'. X# The install procedure does this for you. X XXSTR = /a2/estes/bin/xstr XRM = -rm XSHAR = /a2/estes/bin/shar X X# Add '-ljobs' to LIBS if 4.1bsd; add -ltermlib if not SVR2 XLIBS = -lm -lcurses X# May need '-I/usr/include/sys' for 4.2bsd X# May need '-f' on machines without floating point hardware XCFLAGS = -O X X# DEST is where the program and its support files reside XDEST = /a2/estes/phant X X# The following are program constants which are implementation dependent. X# X# PATH is the same as $DEST. Note that there is no closing quote here. X# WIZARD is the login of the one who will clean up things. X# UID is the uid of game wizard. X# RAND is one more than the largest number generated by rand(). X# Possible values for this are: X# 32768.0 (for 15 bit rand()) X# 65536.0 (for 16 bit rand()) X# 2147483648.0 (for 31 bit rand()) X# ACCESS is fopen() access to open a file for writing, without X# clearing the file, e.g. "a", or "r+". (Use "r+" if you have it.) X# define OK_TO_PLAY to restrict playing access. Also see function ok_to_play() X# in main.c, and tailor to your own needs. X# define ENEMY to include code for checking of a 'hit list' of resricted X# accounts. The list of logins goes in the file 'enemy'. X# define BSD41 for 4.1bsd X# define BSD42 for 4.2bsd X# define SYS3 for System III, or similar X# define SYS5 for System V X# define SMALL to save a little space (omits wormholes) X# If you don't have 'strchr()', put '-Dstrchr=index' below. XFLAGS = -DPATH=\"${DEST} \ X -DWIZARD=\"estes\" \ X -DUID=419 \ X -DRAND=32768.0 \ X -DACCESS=\"r+\" \ X -DOK_TO_PLAY \ X -DENEMY \ X -DSYS5 X XOFILES = main.o fight.o func0.o func1.o func2.o func3.o X Xall: phantasia setup phant.help X X# Need separate i/d space on small machines Xphantasia: ${OFILES} strings.o pathdefs.o X ${CC} ${OFILES} strings.o pathdefs.o ${LIBS} -o phantasia X X${OFILES}: phant.h X ${CC} -E ${CFLAGS} ${FLAGS} $*.c | ${XSTR} -c - X ${CC} -c ${CFLAGS} x.c X mv x.o $*.o X Xpathdefs.o: phant.h X ${CC} -c ${CFLAGS} ${FLAGS} pathdefs.c X Xstrings.o: strings X ${XSTR} X ${CC} -c xs.c X mv xs.o strings.o X Xsetup: phant.h pathdefs.o X ${CC} ${CFLAGS} ${FLAGS} setup.c -o setup pathdefs.o -lm X Xlint: X lint ${CFLAGS} ${FLAGS} func?.c main.c fight.c pathdefs.c ${LIBS} X X# the flags below on tbl and nroff are to make a line printable version Xphant.help: phant.nr X tbl -TX phant.nr | nroff -Ttn300 -man > phant.help X Xinstall: all X cp phantasia monsters phant.help ${DEST} X chmod 755 ${DEST} X chmod 4711 ${DEST}/phantasia X chmod 644 ${DEST}/phant.help X setup X Xclean: X ${RM} -f *.o phantasia phant.help strings x.c xs.c phant.pt? X Xshar: X ${SHAR} README phant.nr func0.c > phant.pt1 X ${SHAR} Makefile.* fight.c func1.c phant.h > phant.pt2 X ${SHAR} func2.c func3.c main.c monsters pathdefs.c setup.c > phant.pt3 !EOR! echo extracting - fight.c sed 's/^X//' > fight.c << '!EOR!' X/* X * fight.c Phantasia monster fighting routine X */ X X/* X * The code exists here for fight to the finish. Simply add code to X * set 'fgttofin = TRUE' as an option. Everything else is here. X */ X#include "phant.h" X Xvoid fight(stat,particular) /* monster fighting routine */ Xstruct stats *stat; Xint particular; X{ Xbool fghttofin = FALSE, luckout = FALSE, firsthit = stat->bls; Xchar aline[80]; Xdouble monhit, mdamage, sdamage, monspd, maxspd, inflict, monstr, temp, shield; Xint ch; Xint whichm, size, howmany, lines; Xstruct mstats monster; X X fghting = changed = TRUE; X shield = 0.0; X if (setjmp(fightenv) == 2) X shield = roll(100 + (stat->mxn + stat->shd)*6.2,3000); X howmany = 1; X size = (valhala) ? stat->lvl/5 : circ(stat->x,stat->y); X if (particular >= 0) X whichm = particular; X else if (marsh) X whichm = roll(0,15); X else if (size > 24) X whichm = roll(14,86); X else if (size > 15) X whichm = roll(0,50) + roll(14,37); X else if (size > 8) X whichm = roll(0,50) + roll(14,26); X else if (size > 3) X whichm = roll(14,50); X else X whichm = roll(14,25); X move(6,0); X clrtobot(); X XCALL: move(6,0); X lines = 9; X callmonster(whichm,size,&monster); X if (stat->blind) X strcpy(monster.name,"a monster"); X if (monster.typ == 1) /* unicorn */ X if (stat->vrg) X { X printw("You just subdued %s, thanx to the virgin.\n",monster.name); X stat->vrg = FALSE; X goto FINISH; X } X else X { X printw("You just saw %s running away!\n",monster.name); X goto LEAVE; X } X if (monster.typ == 2 && stat->typ > 20) X { X strcpy(monster.name,"Morgoth"); X monster.str = rnd()*(stat->mxn + stat->shd)/1.4 + rnd()*(stat->mxn + stat->shd)/1.5; X monster.brn = stat->brn; X monster.hit = stat->str*30; X monster.typ = 23; X monster.spd = speed*1.1 + speed*(stat->typ == 90); X monster.flk = monster.trs = monster.exp = 0; X mvprintw(4,0,"You've encountered %s, Bane of the Council and Valar.\n",monster.name); X } X fghttofin = luckout = FALSE; X monstr = monster.str; X monhit = monster.hit; X mdamage = sdamage = 0; X monspd = maxspd = monster.spd; X if (speed <= 0) X { X monster.spd += - speed; X speed = 1; X } X *monster.name = toupper(*monster.name); X move(8,0); X clrtobot(); X XTOP: mvprintw(6,0,"You are being attacked by %s, EXP: %.0f (Size: %d)\n",monster.name,monster.exp,size); X printstats(stat); X mesg(); X mvprintw(1,26,"%20.0f",stat->nrg + shield); X if (monster.typ == 4 && stat->bls && stat->chm) X { X mvprintw(7,0,"You just overpowered %s!",monster.name); X lines = 8; X stat->bls = FALSE; X --stat->chm; X goto FINISH; X } X monster.spd = min(monster.spd + 1,maxspd); X if (rnd()*monster.spd > rnd()*speed && monster.typ != 4 && monster.typ != 16 X && !firsthit) X { X if (monster.typ) X switch (monster.typ) /* do special things */ X { X case 5: /* Leanan-Sidhe */ X if (rnd() > 0.25) X goto NORMALHIT; X inflict = roll(1,(size - 1)/2); X inflict = min(stat->str,inflict); X mvprintw(lines++,0,"%s sapped %0.f of your strength!",monster.name,inflict); X stat->str -= inflict; X strength -= inflict; X break; X case 6: /* Saruman */ X if (stat->pal) X { X mvprintw(lines++,0,"Wormtongue stole your palantir!"); X stat->pal = FALSE; X } X else if (rnd() > 0.2) X goto NORMALHIT; X else if (rnd() > 0.5) X { X mvprintw(lines++,0,"%s transformed your gems into gold!",monster.name); X stat->gld += stat->gem; X stat->gem = 0.0; X } X else X { X mvprintw(lines++,0,"%s scrambled your stats!",monster.name); X scramble(stat); X } X break; X case 7: /* Thaumaturgist */ X if (rnd() > 0.15) X goto NORMALHIT; X mvprintw(lines++,0,"%s transported you!",monster.name); X stat->x += sgn(stat->x)*roll(50*size,250*size); X stat->y += sgn(stat->y)*roll(50*size,250*size); X goto LEAVE; X case 8: /* Balrog */ X inflict = roll(10,monster.str); X inflict = min(stat->exp,inflict); X mvprintw(lines++,0,"%s took away %.0f experience points.",monster.name,inflict); X stat->exp -= inflict; X break; X case 9: /* Vortex */ X if (rnd() > 0.2) X goto NORMALHIT; X inflict = roll(0,7.5*size); X inflict = min(stat->man,floor(inflict)); X mvprintw(lines++,0,"%s sucked up %.0f of your mana!",monster.name,inflict); X stat->man -= inflict; X break; X case 10: /* Nazgul */ X if (rnd() > 0.3) X goto NORMALHIT; X if (stat->rng.type && stat->rng.type < 10) X { X mvaddstr(lines++,0,"Will you relinguish your ring ? "); X ch = getans("YN", FALSE); X if (ch == 'Y') X { X stat->rng.type = NONE; X goto LEAVE; X } X } X mvprintw(lines++,0,"%s neutralized 1/5 of your brain!",monster.name); X stat->brn *= 0.8; X break; X case 11: /* Tiamat */ X if (rnd() > 0.6) X goto NORMALHIT; X mvprintw(lines++,0,"%s took half your gold and gems and flew off.",monster.name); X stat->gld = floor(stat->gld/2); X stat->gem = floor(stat->gem/2); X goto LEAVE; X case 12: /* Kobold */ X if (rnd() >.7) X goto NORMALHIT; X mvprintw(lines++,0,"%s stole one gold piece and ran away.",monster.name); X stat->gld = max(0,stat->gld-1); X goto LEAVE; X case 13: /* Shelob */ X if (rnd() > 0.5) X goto NORMALHIT; X mvprintw(lines++,0,"%s has bitten and poisoned you!",monster.name); X ++stat->psn; X break; X case 14: /* Faeries */ X if (!stat->hw) X goto NORMALHIT; X mvprintw(lines++,0,"Your holy water killed it!"); X --stat->hw; X goto FINISH; X case 15: /* Lamprey */ X if (rnd() > 0.7) X goto NORMALHIT; X mvprintw(lines++,0,"%s bit and poisoned you!",monster.name); X stat->psn += 0.25; X break; X case 17: /* Bonnacon */ X if (rnd() > 0.1) X goto NORMALHIT; X mvprintw(lines++,0,"%s farted and scampered off.",monster.name); X stat->nrg /= 2; X goto LEAVE; X case 18: /* Smeagol */ X if (rnd() > 0.5 || !stat->rng.type) X goto NORMALHIT; X mvprintw(lines++,0,"%s tried to steal your ring, ",monster.name); X if (rnd() > 0.1) X addstr("but was unsuccessful."); X else X { X addstr("and ran away with it!"); X stat->rng.type = NONE; X goto LEAVE; X } X break; X case 19: /* Succubus */ X if (rnd() > 0.3) X goto NORMALHIT; X inflict = roll(15,size*10); X inflict = min(inflict,stat->nrg); X mvprintw(lines++,0,"%s sapped %.0f of your energy.",monster.name,inflict); X stat->nrg -= inflict; X break; X case 20: /* Cerberus */ X if (rnd() > 0.25) X goto NORMALHIT; X mvprintw(lines++,0,"%s took all your metal treasures!",monster.name); X stat->swd = stat->shd =stat->gld = stat->crn = 0; X goto LEAVE; X case 21: /* Ungoliant */ X if (rnd() > 0.1) X goto NORMALHIT; X mvprintw(lines++,0,"%s poisoned you, and took one quik.",monster.name); X stat->psn += 5; X --stat->quk; X break; X case 22: /* Jabberwock */ X if (rnd() > 0.1) X goto NORMALHIT; X mvprintw(lines++,0,"%s flew away, and left you to contend with one of its friends.",monster.name); X whichm = 55 + 22*(rnd() > 0.5); X goto CALL; X case 24: /* Troll */ X if (rnd() > 0.5) X goto NORMALHIT; X mvprintw(lines++,0,"%s partially regenerated his energy.!",monster.name); X monster.hit += floor((monhit*size - monster.hit)/2); X monster.str = monstr; X mdamage = sdamage = 0; X maxspd = monspd; X break; X case 25: /* wraith */ X if (rnd() > 0.3 || stat->blind) X goto NORMALHIT; X mvprintw(lines++,0,"%s blinded you!",monster.name); X stat->blind = TRUE; X break; X default: X goto NORMALHIT; X } X else XNORMALHIT: { X inflict = rnd()*monster.str + 0.5; X mvprintw(lines++,0,"%s hit you %.0f times!",monster.name,inflict); XSPECIALHIT: if ((shield -= inflict) < 0) X { X stat->nrg += shield; X shield = 0; X } X } X } X else X { X if (fghttofin) X goto MELEE; X mvaddstr(7,0,"1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick "); X if (!luckout) X if (monster.typ == 23) X addstr("6:Ally "); X else X addstr("6:Luckout "); X if (stat->rng.type > 0) X addstr("7:Use Ring "); X else X clrtoeol(); X ch = gch(stat->rng.type); X firsthit = FALSE; X move(8,0); X clrtobot(); X lines = 9; X mvaddstr(4,0,"\n\n"); X switch (ch) X { X case 'T': /* timeout; lose turn */ X break; X default: X case '1': /* melee */ XMELEE: inflict = roll(strength/2 + 5,1.3*strength) + (stat->rng.type < 0 ? strength : 0); X mdamage += inflict; X monster.str = monstr - mdamage/monhit*monstr/4; X goto HITMONSTER; X case '2': /* skirmish */ X inflict = roll(strength/3 + 3,1.1*strength) + (stat->rng.type < 0 ? strength : 0); X sdamage += inflict; X maxspd = monspd - sdamage/monhit*monspd/4; X goto HITMONSTER; X case '3': /* evade */ X if ((monster.typ == 4 || monster.typ == 16 X || rnd()*speed*stat->brn > rnd()*monster.spd*monster.brn) X && (monster.typ != 23)) X { X mvaddstr(lines++,0,"You got away!"); X stat->x += roll(-2,5); X stat->y += roll(-2,5); X goto LEAVE; X } X else X mvprintw(lines++,0,"%s is still after you!",monster.name); X break; X case '4': /* spell */ X mvaddstr(7,0,"\n\n"); X mvaddstr(7,0,"1:All or Nothing "); X if (stat->mag >= 5) X addstr("2:Magic Bolt "); X if (stat->mag >= 15) X addstr("3:Force Field "); X if (stat->mag >= 25) X addstr("4:Transform "); X if(stat->mag >= 35) X addstr("5:Increase Might\n"); X if (stat->mag >= 45) X mvaddstr(8,0,"6:Invisibility "); X if (stat->mag >= 60) X addstr("7:Transport "); X if (stat->mag >= 75) X addstr("8:Paralyze "); X if (stat->typ > 20) X addstr("9:Specify"); X mvaddstr(4,0,"Spell ? "); X ch = getans(" ", TRUE); X mvaddstr(7,0,"\n\n"); X if (monster.typ == 23 && ch != '3') X illspell(); X else X switch (ch) X { X case '1': /* all or nothing */ X { X inflict = (rnd() < 0.25) ? (monster.hit*1.0001 + 1) : 0; X if (monster.typ == 4) X inflict *= .9; X if (stat->man) X --stat->man; X maxspd *= 2; X monspd *= 2; X monster.spd = max(1,monster.spd * 2); X monstr = monster.str *= 2; X goto HITMONSTER; X } X case '2': /* magic bolt */ X if (stat->mag < 5) X illspell(); X else X { X do X { X mvaddstr(4,0,"How much mana for bolt? "); X getstring(aline,80); X sscanf(aline,"%F",&temp); X } X while (temp < 0 || temp > stat->man); X stat->man -= floor(temp); X inflict = temp*roll(10,sqrt(stat->mag/3.0 + 1.0)); X mvaddstr(5,0,"Magic Bolt fired!\n"); X if (monster.typ == 4) X inflict = 0.0; X goto HITMONSTER; X } X case '5': /* increase might */ X { X if (stat->mag < 45) X illspell(); X else if (stat->man < 75) X nomana(); X else X { X stat->man -= 75; X strength += (1.2*(stat->str+stat->swd)+5-strength)/2; X mvprintw(5,0,"New strength: %.0f\n",strength); X } X break; X } X case '3': /* force field */ X { X if (stat->mag < 15) X illspell(); X else if (stat->man < 30) X nomana(); X else X { X shield = (stat->mxn + stat->shd)*4.2 + 45; X stat->man -= 30; X mvaddstr(5,0,"Force Field up.\n"); X } X break; X } X case '4': /* transform */ X { X if (stat->mag < 25) X illspell(); X else if (stat->man < 50) X nomana(); X else X { X stat->man -= 50; X whichm = roll(0,100); X goto CALL; X } X break; X } X case '6': /* invisible */ X { X if (stat->mag < 45) X illspell(); X else if (stat->man < 90) X nomana(); X else X { X stat->man -= 90; X speed += (1.2*(stat->quk+stat->quks)+5-speed)/2; X mvprintw(5,0,"New quik : %.0f\n",speed); X } X break; X } X case '7': /* transport */ X { X if (stat->mag < 60) X illspell(); X else if (stat->man < 125) X nomana(); X else X { X stat->man -= 125; X if (stat->brn + stat->mag < monster.exp/200*rnd()) X { X mvaddstr(5,0,"Transport backfired!\n"); X stat->x += (250*size*rnd() + 50*size)*sgn(stat->x); X stat->y += (250*size*rnd() + 50*size)*sgn(stat->y); X goto LEAVE; X } X else X { X mvprintw(5,0,"%s is transported.\n",monster.name); X if (rnd() < 0.3) X monster.trs = 0; X goto FINISH; X } X } X break; X } X case '8': /* paralyze */ X { X if (stat->mag < 75) X illspell(); X else if (stat->man < 150) X nomana(); X else X { X stat->man -= 150; X if (stat->mag > monster.exp/1000*rnd()) X { X mvprintw(5,0,"%s is held.\n",monster.name); X monster.spd = -2; X } X else X mvaddstr(5,0,"Monster unaffected.\n"); X } X break; X } X case '9': /* specify */ X { X if (stat->typ < 20) X illspell(); X else if (stat->man < 1000) X nomana(); X else X { X mvaddstr(5,0,"Which monster do you want [0-99] ? "); X whichm = inflt(); X whichm = max(0,min(99,whichm)); X stat->man -= 1000; X goto CALL; X } X break; X } X } X break; X case '5': X inflict = 1 + stat->swd; X stat->exp += floor(monster.exp/10); X monster.exp *= 0.92; X maxspd += 2; X monster.spd = (monster.spd < 0) ? 0 : monster.spd + 2; X if (monster.typ == 4) X { X mvprintw(lines++,0,"You hit %s %.0f times, and made him mad!",monster.name,inflict); X stat->quk /= 2; X stat->x += sgn(stat->x)*roll(50*size,250*size); X stat->y += sgn(stat->y)*roll(50*size,250*size); X stat->y += (250*size*rnd() + 50*size)*sgn(stat->y); X goto LEAVE; X } X else X goto HITMONSTER; X case '6': /* luckout */ X if (luckout) X mvaddstr(lines++,0,"You already tried that."); X else X if (monster.typ == 23) X if (rnd() < stat->sin/100) { X mvprintw(lines++,0,"%s accepted!",monster.name); X goto LEAVE; X } X else X { X luckout = TRUE; X mvaddstr(lines++,0,"Nope, he's not interested."); X } X else X if ((rnd() + .333)*stat->brn < (rnd() + .333)*monster.brn) X { X luckout = TRUE; X mvprintw(lines++,0,"You blew it, %s.",stat->name); X } X else X { X mvaddstr(lines++,0,"You made it!"); X goto FINISH; X } X break; X case '\014': /* clear screen */ X clear(); X break; X case '7': /* use ring */ X if (stat->rng.type > 0) X { X mvaddstr(lines++,0,"Now using ring."); X stat->rng.type = -stat->rng.type; X if (abs(stat->rng.type) != DLREG) X --stat->rng.duration; X goto HITMONSTER; X } X break; X } X goto BOT; XHITMONSTER: { X inflict = floor(inflict); X mvprintw(lines++,0,"You hit %s %.0f times!",monster.name,inflict); X if ((monster.hit -= inflict) >0) X switch (monster.typ) X { X case 4: /* dark lord */ X inflict = stat->nrg + shield +1; X goto SPECIALHIT; X case 16: /* shrieker */ X mvaddstr(lines++,0,"Shreeeek!! You scared it, and it called one of its friends."); X paws(lines); X whichm = roll(70,30); X goto CALL; X } X else X { X if (monster.typ == 23) /* morgoth */ X mvaddstr(lines++,0,"You have defeated Morgoth, but he may return. . ."); X else X mvprintw(lines++,0,"You killed it. Good work, %s.",stat->name); X goto FINISH; X } X } X } XBOT: refresh(); X if (lines > LINES - 2) X { X paws(lines); X move(lines = 8,0); X clrtobot(); X } X if (stat->nrg <= 0) X { X paws(lines); X death(stat, monster.name); X goto LEAVE; X } X goto TOP; XFINISH: stat->exp += monster.exp; X if (rnd() < monster.flk/100.0) /* flock monster */ X { X paws(lines); X fghttofin = FALSE; X ++howmany; X goto CALL; X } X else if (size > 1 && monster.trs && rnd() > 0.2 + pow(0.4,(double) (howmany/3.0 + size/3.0))) /* this takes # of flocks and size into account */ X { X paws(lines); X treasure(stat,monster.trs,size); X } X else XLEAVE: paws(lines); X stat->rng.type = abs(stat->rng.type); X move(4,0); X clrtobot(); X fghting = FALSE; X} !EOR! echo extracting - func1.c sed 's/^X//' > func1.c << '!EOR!' X/* X * func1.c Phantasia support routines X */ X X#include "phant.h" X Xint findname(name,stat) /* return location of character 'name' */ Xreg char *name; /* return -1 if not found, fill structure */ Xreg struct stats *stat; /* if pointer is non-null */ X{ XFILE *fp; Xstruct stats sbuf; Xint loc = 0; X X if (stat == NULL) X stat = &sbuf; X fp = fopen(peoplefile,"r"); X while (fread((char *) stat,sizeof(sbuf),1,fp)) X if (!strcmp(stat->name,name)) X { X fclose(fp); X return (loc); X } X else X ++loc; X fclose(fp); X return (-1); X} X Xint findspace() /* allocate space for a character in peoplefile */ X{ XFILE *fp; Xstruct stats buf; Xreg int loc; X X loc = 0; X fp = fopen(peoplefile,"r"); X while (fread((char *) &buf,sizeof(buf),1,fp)) X { X if (!strcmp(buf.name,"<null>")) X { X fclose(fp); X return (loc); X } X else X ++loc; X } X fclose(fp); X fp = fopen(peoplefile,ACCESS); X fseek(fp,(long) (loc * sizeof(buf)),0); X initchar(&buf); X strcpy(buf.name,"inuse"); X fwrite((char *) &buf,sizeof(buf),1,fp); X fclose(fp); X return (loc); X} X Xint findchar(stat) /* retrieve a character from file */ Xreg struct stats *stat; X{ Xreg int loc = 0, loop; Xchar name[21]; X X clear(); X mvprintw(10,0,"What was your character's name ? "); X getstring(name,21); X trunc(name); X if ((loc = findname(name, stat)) >= 0) X { X move(11,0); X refresh(); X nocrmode(); X for (loop = 0; loop < 2; ++loop) X if (!strcmp(getpass("Password ? "),stat->pswd)) X { X crmode(); X return (loc); X } X else X printf("No good.\n"); X exit1(); X /*NOTREACHED*/ X } X else X addstr("\n\nNot found.\n"); X exit1(); X/*NOTREACHED*/ X} X Xvoid leave(stat) /* save character in file */ Xreg struct stats *stat; X{ Xlong ltemp; X X if (!stat->lvl) X strcpy(stat->name,"<null>"); X stat->status = OFF; X time(<emp); X stat->age += ltemp - secs; X update(stat,fileloc); X exit1(); X /*NOTREACHED*/ X} X Xvoid death(stat, how) /* remove a player after dying */ Xreg struct stats *stat; Xchar *how; X{ XFILE *fp; Xchar aline[100]; Xint ch; Xreg int loop; Xlong ltemp; X X clear(); X if (stat->typ == 99) X if (stat->rng.duration) X { X addstr("Valar should be more cautious. You've been killed.\n"); X printw("You only have %d more chance(s).\n",--stat->rng.duration); X paws(3); X stat->nrg = stat->mxn; X return; X } X else X { X addstr("You had your chances, but Valar aren't totally\n"); X addstr("immortal. You are now left to wither and die . . .\n"); X paws(3); X stat->brn = stat->lvl /25; X stat->nrg = stat->mxn; X stat->quks = stat->swd = 0; X stat->typ = 90; X return; X } X X if (stat->lvl > 9999) X { X addstr("Characters greater than level 10K must be retired. Sorry."); X how = "Old age"; X } X X switch(stat->rng.type) X { X case -DLREG: X case -NAZREG: X mvaddstr(4,0,"Your ring saved you from death!\n"); X refresh(); X stat->rng.type = NONE; X stat->nrg = stat->mxn/12+1; X stat->crn -= (stat->crn > 0); X return; X case DLBAD: X case -DLBAD: X case NAZBAD: X case -NAZBAD: X case -SPOILED: X case SPOILED: X mvaddstr(4,0,"Your ring has taken control of you and turned you into a monster!\n"); X fp = fopen(monsterfile,"r"); X for (loop = 0; loop <= 13; ++loop) X fgets(aline,100,fp); X ltemp = ftell(fp); X fclose(fp); X fp = fopen(monsterfile,ACCESS); X fseek(fp,ltemp,0); X fprintf(fp,"%-20s",stat->name); X fclose(fp); X } X scoreboard(stat); X fp = fopen(lastdead,"w"); X fprintf(fp,"%s (log: %s lvl: %d typ: %d, by %c%s)", X stat->name,stat->login,stat->lvl,stat->typ,tolower(*how),how + 1); X fclose(fp); X fp = fopen(messfile,"w"); X fprintf(fp,"%s was killed by %c%s.", stat->name,tolower(*how),how + 1); X fclose(fp); X initchar(stat); X strcpy(stat->name,"<null>"); X update(stat,fileloc); X clear(); X move(10,0); X switch ((int) roll(1,5)) X { X case 1: X addstr("You've crapped out! "); X break; X case 2: X addstr("You have been disemboweled. "); X break; X case 3: X addstr("You've been mashed, mauled, and spit upon. (You're dead.)\n"); X break; X case 4: X addstr("You died! "); X break; X case 5: X addstr("You're a complete failure -- you've died!!\n"); X } X addstr("Care to give it another try ? "); X ch = getans("NY", FALSE); X if (ch == 'Y') X { X endwin(); X execl(gameprog, "phantasia", "-s", (su ? "-S": (char *) NULL), 0); X } X exit1(); X /*NOTREACHED*/ X} X Xvoid update(stat,place) /* update charac file */ Xreg struct stats *stat; Xreg int place; X{ XFILE *fp; X X fp = fopen(peoplefile,ACCESS); X fseek(fp,(long) (place*sizeof(*stat)),0); X fwrite((char *) stat,sizeof(*stat),1,fp); X fclose(fp); X} X Xvoid printplayers(stat) /* show users */ Xreg struct stats *stat; X{ XFILE *fp; Xstruct stats buf; Xreg int loop = 0; Xdouble mloc; Xlong ltmp; Xint ch; X X if (stat->blind) X { X mvaddstr(8,0,"You can't see anyone.\n"); X return; X } X mloc = circ(stat->x,stat->y); X mvaddstr(8,0,"Name X Y Lvl Type Login\n"); X fp = fopen(peoplefile,"r"); X while (fread((char *) &buf,sizeof(buf),1,fp)) X { X if (buf.status) X { X ch = (buf.status == CLOAKED) ? '?' : 'W'; X if (stat->typ > 10 || buf.typ > 10 || X mloc >= circ(buf.x,buf.y) || stat->pal) X if (buf.status != CLOAKED || (stat->typ == 99 && stat->pal)) X if (buf.typ == 99) X addstr("The Valar is watching you. . .\n"); X else if (buf.wormhole) X printw("%-20s %c %c %6u %3d %-9s\n", X buf.name,ch,ch,buf.lvl,buf.typ,buf.login); X else X printw("%-20s %8.0f %8.0f %6u %3d %-9s\n", X buf.name,buf.x,buf.y,buf.lvl,buf.typ,buf.login); X else X if (buf.typ == 99) X --loop; X else X printw("%-20s ? ? %6u %3d %-9s\n", X buf.name,buf.lvl,buf.typ,buf.login); X ++loop; X } X } X fclose(fp); X time(<mp); X printw("Total users = %d %s\n",loop,ctime(<mp)); X refresh(); X} X X Xvoid titlestuff() /* print out a header */ X{ XFILE *fp; Xbool cowfound = FALSE, kingfound = FALSE; Xstruct stats buf; Xdouble hiexp, nxtexp; Xint hilvl, nxtlvl; Xreg int loop; Xchar instr[120], hiname[21], nxtname[21]; X X mvaddstr(0,14,"W e l c o m e t o P h a n t a s i a (vers. 3.3.1)!"); X if ((fp = fopen(motd,"r")) != NULL && fgets(instr,80,fp)) X { X mvaddstr(2,40 - strlen(instr)/2,instr); X fclose(fp); X } X if ((fp = fopen(peoplefile,"r")) == NULL) X { X error(peoplefile); X /*NOTREACHED*/ X } X while (fread((char *) &buf,sizeof(buf),1,fp)) X if (buf.typ > 10 && buf.typ < 20) X { X sprintf(instr,"The present ruler is %s Level:%d",buf.name,buf.lvl); X mvaddstr(4,40 - strlen(instr)/2,instr); X kingfound = TRUE; X break; X } X if (!kingfound) X mvaddstr(4,24,"There is no ruler at this time."); X fseek(fp,0L,0); X while (fread((char *) &buf,sizeof(buf),1,fp)) X if (buf.typ == 99) X { X sprintf(instr,"The Valar is %s Login: %s",buf.name,buf.login); X mvaddstr(6,40 - strlen(instr)/2,instr); X break; X } X fseek(fp,0L,0); X while (fread((char *) &buf,sizeof(buf),1,fp)) X if (buf.typ > 20 && buf.typ < 90) X { X if (!cowfound) X { X mvaddstr(8,30,"Council of the Wise:"); X loop = 10; X cowfound = TRUE; X } X /* This assumes a finite (<=5) number of C.O.W.: */ X sprintf(instr,"%s Login: %s",buf.name,buf.login); X mvaddstr(loop++,40 - strlen(instr)/2,instr); X } X fseek(fp,0L,0); X nxtname[0] = hiname[0] = '\0'; X hiexp = 0.0; X nxtlvl = hilvl = 0; X while (fread((char *) &buf,sizeof(buf),1,fp)) X if (buf.exp > hiexp && buf.typ < 20) X { X nxtexp = hiexp; X hiexp = buf.exp; X nxtlvl = hilvl; X hilvl = buf.lvl; X strcpy(nxtname,hiname); X strcpy(hiname,buf.name); X } X else if (buf.exp > nxtexp && buf.typ < 20) X { X nxtexp = buf.exp; X nxtlvl = buf.lvl; X strcpy(nxtname,buf.name); X } X fclose(fp); X mvaddstr(15,28,"Highest characters are:"); X sprintf(instr,"%s Level:%d and %s Level:%d",hiname,hilvl,nxtname,nxtlvl); X mvaddstr(17,40 - strlen(instr)/2,instr); X if ((fp = fopen(lastdead,"r")) != NULL) X { X mvaddstr(19,25,"The last character to die was:"); X fgets(instr,80,fp); X mvaddstr(20,40 - strlen(instr)/2,instr); X fclose(fp); X } X refresh(); X} X X X Xvoid printmonster() /* do a monster list on the terminal */ X{ XFILE *fp; Xreg int count = 0; Xchar instr[100]; X X puts(" # Name Str Brains Quick Hits Exp Treas Type Flock%\n"); X fp = fopen(monsterfile,"r"); X while (fgets(instr,100,fp)) X printf("%2d %s",count++,instr); X fclose(fp); X} X Xvoid exit1() /* exit, but cleanup */ X{ X move(23,0); X refresh(); X nocrmode(); X endwin(); X exit(0); X /*NOTREACHED*/ X} X Xvoid init1() /* set up for screen updating */ X{ X /* catch/ingnore signals */ X#ifdef BSD41 X sigignore(SIGQUIT); X sigignore(SIGALRM); X sigignore(SIGTERM); X sigignore(SIGTSTP); X sigignore(SIGTTIN); X sigignore(SIGTTOU); X sighold(SIGINT); X sigset(SIGHUP,ill_sig); X sigset(SIGTRAP,ill_sig); X sigset(SIGIOT,ill_sig); X sigset(SIGEMT,ill_sig); X sigset(SIGFPE,ill_sig); X sigset(SIGBUS,ill_sig); X sigset(SIGSEGV,ill_sig); X sigset(SIGSYS,ill_sig); X sigset(SIGPIPE,ill_sig); X#endif X#ifdef BSD42 X signal(SIGQUIT,SIG_IGN); X signal(SIGALRM,SIG_IGN); X signal(SIGTERM,SIG_IGN); X signal(SIGTSTP,SIG_IGN); X signal(SIGTTIN,SIG_IGN); X signal(SIGTTOU,SIG_IGN); X signal(SIGINT,SIG_IGN); X signal(SIGHUP,ill_sig); X signal(SIGTRAP,ill_sig); X signal(SIGIOT,ill_sig); X signal(SIGEMT,ill_sig); X signal(SIGFPE,ill_sig); X signal(SIGBUS,ill_sig); X signal(SIGSEGV,ill_sig); X signal(SIGSYS,ill_sig); X signal(SIGPIPE,ill_sig); X#endif X#ifdef SYS3 X signal(SIGINT,SIG_IGN); X signal(SIGQUIT,SIG_IGN); X signal(SIGTERM,SIG_IGN); X signal(SIGALRM,SIG_IGN); X signal(SIGHUP,ill_sig); X signal(SIGTRAP,ill_sig); X signal(SIGIOT,ill_sig); X signal(SIGEMT,ill_sig); X signal(SIGFPE,ill_sig); X signal(SIGBUS,ill_sig); X signal(SIGSEGV,ill_sig); X signal(SIGSYS,ill_sig); X signal(SIGPIPE,ill_sig); X#endif X#ifdef SYS5 X signal(SIGINT,SIG_IGN); X signal(SIGQUIT,SIG_IGN); X signal(SIGTERM,SIG_IGN); X signal(SIGALRM,SIG_IGN); X signal(SIGHUP,ill_sig); X signal(SIGTRAP,ill_sig); X signal(SIGIOT,ill_sig); X signal(SIGEMT,ill_sig); X signal(SIGFPE,ill_sig); X signal(SIGBUS,ill_sig); X signal(SIGSEGV,ill_sig); X signal(SIGSYS,ill_sig); X signal(SIGPIPE,ill_sig); X#endif X srand((unsigned) time((long *) NULL)); /* prime random numbers */ X initscr(); X noecho(); X crmode(); X clear(); X refresh(); X} X Xvoid getstring(cp,mx) /* get a string from the stdscr at current y,x */ Xreg char *cp; Xreg int mx; X{ Xreg int loop = 0, x, y, xorig; Xint ch; X X getyx(stdscr,y,xorig); X clrtoeol(); X refresh(); X while((ch = getch()) != '\n' && loop < mx - 1) X switch (ch) X { X case '\033': /* escape */ X case '\010': /* backspace */ X if (loop) X { X --loop; X getyx(stdscr,y,x); X mvaddch(y,x-1,' '); X move(y,x-1); X refresh(); X } X break; X case '\030': /* ctrl-x */ X loop = 0; X move(y,xorig); X clrtoeol(); X refresh(); X break; X default: X if (ch >= ' ') /* printing char */ X { X addch(ch); X cp[loop++] = ch; X refresh(); X } X } X cp[loop] = '\0'; X} X X Xvoid showusers(screen) /* print a list of all characters */ Xbool screen; X{ Xstruct stats buf; XFILE *fp; X X if (screen) X { X clear(); X refresh(); X } X if (fp = fopen(peoplefile,"r")) X { X puts("Current characters on file are:\n"); X while (fread((char *) &buf,sizeof(buf),1,fp)) X if (strcmp("<null>",buf.name)) X printf("%-20s Login: %-9s Level: %6d Type: %3d\n",buf.name,buf.login,buf.lvl,buf.typ); X fclose(fp); X } X if (screen) X { X putchar('\n'); X putchar('\n'); X paws(22); X clear(); X } X} X Xvoid kingstuff(stat) /* stuff upon entering throne */ Xreg struct stats *stat; X{ XFILE *fp; Xstruct stats buf; Xstruct nrgvoid vbuf; Xreg int loc = 0; X X if (stat->typ < 10) /* check to see if king -- assumes crown */ X { X fp = fopen(peoplefile,"r"); X while (fread((char *) &buf,sizeof(buf),1,fp)) X if (buf.typ > 10 && buf.typ < 20) /* found old king */ X if (buf.status != OFF) X { X mvaddstr(4,0,"The king is playing, so you cannot steal his throne\n"); X stat->x = stat->y = 9; X move(6,0); X fclose(fp); X return; X } X else X { X buf.typ -= 10; X if (buf.crn) X --buf.crn; X fclose(fp); X update(&buf,loc); XKING: stat->typ = abs(stat->typ) + 10; X mvaddstr(4,0,"You have become king!\n"); X fp = fopen(messfile,"w"); X fprintf(fp,"All hail the new king!"); X fclose(fp); X /* clear all energy voids */ X fp = fopen(voidfile,"r"); X fread((char *) &vbuf,sizeof(vbuf),1,fp); X fclose(fp); X fp = fopen(voidfile,"w"); X fwrite((char *) &vbuf,sizeof(vbuf),1,fp); X fclose(fp); X goto EXIT; X } X else X ++loc; X fclose(fp); /* old king not found -- install new one */ X goto KING; X } XEXIT: mvaddstr(6,0,"0:Decree "); X} X Xvoid paws(where) /* wait for input to continue */ Xint where; X{ X mvaddstr(where,0,"-- more --"); X getans(" ", FALSE); X} X Xvoid cstat() /* examine/change stats of a character */ X{ Xstruct stats charac; Xchar s[60], flag[2]; Xreg int loc = 0; Xint c, temp, today; Xlong ltemp; Xdouble dtemp; X X flag[0] = 'F', flag[1] = 'T'; X mvaddstr(10,0,"Which character do you want to look at ? "); X getstring(s,60); X trunc(s); X if ((loc = findname(s, &charac)) < 0) X { X mvaddstr(11,0,"Not found."); X exit1(); X /*NOTREACHED*/ X } X X time(<emp); X today = localtime(<emp)->tm_yday; X if (!su) X strcpy(charac.pswd,"XXXXXXXX"); X clear(); XTOP: mvprintw(0,0,"a:Name %s\n",charac.name); X printw("b:Password %s\n",charac.pswd); X printw(" :Login %s\n",charac.login); X temp = today - charac.lastused; X if (temp < 0) X temp += 365; X printw("c:Used %d\n",temp); X mvprintw(5,0,"d:Experience %.0f\n",charac.exp); X printw("e:Level %d\n",charac.lvl); X printw("f:strength %.0f\n",charac.str); X printw("g:Sword %.0f\n",charac.swd); X printw("h:Quickness %d",charac.quk); X if (charac.quk < 0) X printw("(%d)\n",charac.tampered); X else X addch('\n'); X printw("i:Quikslvr %d\n",charac.quks); X printw("j:Energy %.0f\n",charac.nrg); X printw("k:Max-Nrg %.0f\n",charac.mxn); X printw("l:Shield %.0f\n",charac.shd); X printw("m:Magic %.0f\n",charac.mag); X printw("n:Mana %.0f\n",charac.man); X printw("o:Brains %.0f\n",charac.brn); X mvprintw(0,40,"p:X-coord %.0f\n",charac.x); X mvprintw(1,40,"q:Y-coord %.0f\n",charac.y); X if (su) X mvprintw(2,40,"r:Wormhole %d\n",charac.wormhole); X else X mvprintw(2,40,"r:Wormhole %c\n",flag[charac.wormhole != 0]); X mvprintw(3,40,"s:Type %d\n",charac.typ); X mvprintw(5,40,"t:Sin %0.3f\n",charac.sin); X mvprintw(6,40,"u:Poison %0.3f\n",charac.psn); X mvprintw(7,40,"v:Gold %.0f\n",charac.gld); X mvprintw(8,40,"w:Gem %.0f\n",charac.gem); X mvprintw(9,40,"x:Holy Water %d\n",charac.hw); X mvprintw(10,40,"y:Charms %d\n",charac.chm); X mvprintw(11,40,"z:Crowns %d\n",charac.crn); X mvprintw(12,40,"1:Amulets %d\n",charac.amu); X mvprintw(13,40,"2:Age %d\n",charac.age); X mvprintw(18,5,"3:Virgin %c 4:Blessed %c 5:Ring %c 6:Blind %c 7:Palantir %c", X flag[charac.vrg],flag[charac.bls],flag[charac.rng.type != 0],flag[charac.blind],flag[charac.pal]); X if (!su) X exit1(); X mvaddstr(15,40,"!:Quit"); X mvaddstr(16,40,"?:Delete"); X mvaddstr(19,30,"8:Duration"); X mvaddstr(21,0,"What would you like to change? "); X refresh(); X c = getch(); X switch(c) X { X case 'p': /* change x coord */ X mvprintw(23,0,"x = %f; x = ",charac.x); X dtemp = inflt(); X if (dtemp != 0.0) X charac.x = dtemp; X break; X case 'q': /* change y coord */ X mvprintw(23,0,"y = %f; y = ",charac.y); X dtemp = inflt(); X if (dtemp != 0.0) X charac.y = dtemp; X break; X case 'd': /* change Experience */ X mvprintw(23,0,"exp = %f; exp = ",charac.exp); X dtemp = inflt(); X if (dtemp != 0.0) X charac.exp = dtemp; X break; X case 'e': /* change level */ X mvprintw(23,0,"lvl = %d; lvl;= ",charac.lvl); X dtemp = inflt(); X if (dtemp != 0.0) X charac.lvl = dtemp; X break; X case 'h': /* change quickness */ X mvprintw(23,0,"quk = %d; quk;= ",charac.quk); X dtemp = inflt(); X if (dtemp != 0.0) X charac.quk = dtemp; X break; X case 'f': /* change strength */ X mvprintw(23,0,"str = %f; str;= ",charac.str); X dtemp = inflt(); X if (dtemp != 0.0) X charac.str = dtemp; X break; X case 't': /* change Sin */ X mvprintw(23,0,"sin = %f; sin;= ",charac.sin); X dtemp = inflt(); X if (dtemp != 0.0) X charac.sin = dtemp; X break; X case 'n': /* change mana */ X mvprintw(23,0,"man = %f; man;= ",charac.man); X dtemp = inflt(); X if (dtemp != 0.0) X charac.man = dtemp; X break; X case 'v': /* change gold */ X mvprintw(23,0,"gld = %f; gld;= ",charac.gld); X dtemp = inflt(); X if (dtemp != 0.0) X charac.gld = dtemp; X break; X case 'j': /* change energy */ X mvprintw(23,0,"nrg = %f; nrg;= ",charac.nrg); X dtemp = inflt(); X if (dtemp != 0.0) X charac.nrg = dtemp; X break; X case 'k': /* change Maximum energy */ X mvprintw(23,0,"mxn = %f; mxn;= ",charac.mxn); X dtemp = inflt(); X if (dtemp != 0.0) X charac.mxn = dtemp; X break; X case 'm': /* change magic */ X mvprintw(23,0,"mag = %f; mag;= ",charac.mag); X dtemp = inflt(); X if (dtemp != 0.0) X charac.mag = dtemp; X break; X case 'o': /* change brains */ X mvprintw(23,0,"brn = %f; brn;= ",charac.brn); X dtemp = inflt(); X if (dtemp != 0.0) X charac.brn = dtemp; X break; X case 'z': /* change crowns */ X mvprintw(23,0,"crn = %d; crn;= ",charac.crn); X dtemp = inflt(); X if (dtemp != 0.0) X charac.crn = dtemp; X break; X case '5': /* change ring type */ X mvprintw(23,0,"rng-type = %d; rng-type;= ",charac.rng.type); X dtemp = inflt(); X if (dtemp != 0.0) X charac.rng.type = dtemp; X break; X case '8': /* change ring duration */ X mvprintw(23,0,"rng-duration = %d; rng-duration;= ",charac.rng.duration); X dtemp = inflt(); X if (dtemp != 0.0) X charac.rng.duration = dtemp; X break; X case '7': /* change palantir */ X mvprintw(23,0,"pal = %d; pal;= ",charac.pal); X dtemp = inflt(); X if (dtemp != 0.0) X { X charac.pal = dtemp; X charac.pal = (charac.pal != 0); X } X break; X case 'u': /* change poison */ X mvprintw(23,0,"psn = %f; psn;= ",charac.psn); X dtemp = inflt(); X if (dtemp != 0.0) X charac.psn = dtemp; X break; X case 'x': /* change holy water */ X mvprintw(23,0,"hw = %d; hw;= ",charac.hw); X dtemp = inflt(); X if (dtemp != 0.0) X charac.hw = dtemp; X break; X case '1': /* change amulet */ X mvprintw(23,0,"amu = %d; amu;= ",charac.amu); X dtemp = inflt(); X if (dtemp != 0.0) X charac.amu = dtemp; X break; X case '4': /* change Blessing */ X mvprintw(23,0,"bls = %d; bls;= ",charac.bls); X dtemp = inflt(); X if (dtemp != 0.0) X { X charac.bls = dtemp; X charac.bls = (charac.bls != 0); X } X break; X case 'y': /* change Charm */ X mvprintw(23,0,"chm = %d; chm;= ",charac.chm); X dtemp = inflt(); X if (dtemp != 0.0) X charac.chm = dtemp; X break; X case 'w': /* change Gems */ X mvprintw(23,0,"gem = %f; gem;= ",charac.gem); X dtemp = inflt(); X if (dtemp != 0.0) X charac.gem = dtemp; X break; X case 'i': /* change Quicksilver */ X mvprintw(23,0,"quks = %d; quks;= ",charac.quks); X dtemp = inflt(); X if (dtemp != 0.0) X charac.quks = dtemp; X break; X case 'g': /* change swords */ X mvprintw(23,0,"swd = %f; swd;= ",charac.swd); X dtemp = inflt(); X if (dtemp != 0.0) X charac.swd = dtemp; X break; X case 'l': /* change shields */ X mvprintw(23,0,"shd = %f; shd;= ",charac.shd); X dtemp = inflt(); X if (dtemp != 0.0) X charac.shd = dtemp; X break; X case 's': /* change type */ X mvprintw(23,0,"typ = %d; typ;= ",charac.typ); X dtemp = inflt(); X if (dtemp != 0.0) X charac.typ = dtemp; X break; X case '3': /* change virgin */ X mvprintw(23,0,"vrg = %d; vrg;= ",charac.vrg); X dtemp = inflt(); X if (dtemp != 0.0) X { X charac.vrg = dtemp; X charac.vrg = (charac.vrg != 0); X } X break; X case 'c': /* change last-used */ X mvprintw(23,0,"last-used = %d; last-used;= ",charac.lastused); X dtemp = inflt(); X if (dtemp != 0.0) X charac.lastused = dtemp; X break; X case 'b': /* change password */ X mvaddstr(23,0,"New password: "); X getstring(s,60); X if (*s) X strcpy(charac.pswd,s); X break; X case 'a': /* change name */ X mvaddstr(23,0,"New name: "); X getstring(s,60); X if (*s) X strcpy(charac.name,s); X break; X case 'r': /* change wormhole */ X mvprintw(23,0,"wormhole = %d; wormhole;= ",charac.wormhole); X dtemp = inflt(); X if (dtemp != 0.0) X charac.wormhole = dtemp; X break; X case '2': /* change age */ X mvprintw(23,0,"age = %d; age;= ",charac.age); X dtemp = inflt(); X if (dtemp != 0.0) X charac.age = dtemp; X break; X case '6': /* change blindness */ X mvprintw(23,0,"blind = %d; blind;= ",charac.blind); X dtemp = inflt(); X if (dtemp != 0.0) X { X charac.blind = dtemp; X charac.blind = (charac.blind != 0); X } X break; X case '!': /* quit, update */ X goto LEAVE; X case '?': /* delete char */ X strcpy(charac.name,"<null>"); X initchar(&charac); X goto LEAVE; X } X goto TOP; XLEAVE: charac.status = OFF; X update(&charac,loc); X} X Xint level(expr) /* calculate level */ Xdouble expr; X{ X if (expr < 1.1e+7) X return (pow((expr/1000.0), 0.4875)); X else X return (pow((expr/1250.0), 0.4865)); X} X Xvoid trunc(str) /* remove blank spaces at the end of str[] */ Xreg char *str; X{ Xreg int loop; X loop = strlen(str); X while (str[--loop] == ' ') X str[loop] = '\0'; X} X Xdouble inflt() /* get a floating point # from the terminal */ X{ Xchar aline[80]; Xdouble res; X getstring(aline,80); X if (sscanf(aline,"%F",&res) < 1) X res = 0.0; X return (res); X} X Xvoid checkmov(stat) /* see if beyond PONR */ Xreg struct stats *stat; X{ X if (beyond) X { X stat->x = sgn(stat->x) * max(abs(stat->x),1.1e+6); X stat->y = sgn(stat->y) * max(abs(stat->y),1.1e+6); X } X} Xvoid scramble(stat) /* mix up some stats */ Xreg struct stats *stat; X{ Xdouble buf[6], temp1, temp2; Xreg int first, second; Xreg double *bp; X X bp = buf; X *bp++ = stat->str; X *bp++ = stat->man; X *bp++ = stat->brn; X *bp++ = stat->mag; X *bp++ = stat->nrg; X *bp = stat->sin; X X bp = buf; X first = roll(0,5); X second = roll(0,5); X temp1 = bp[first]; X /* this expression is split to prevent a complire loop on some compilers */ X temp2 = bp[second]; X bp[first] = temp2; X bp[second] = temp1; X X stat->str = *bp++; X stat->man = *bp++; X stat->brn = *bp++; X stat->mag = *bp++; X stat->nrg = *bp++; X stat->sin = *bp; X} !EOR! echo extracting - phant.h sed 's/^X//' > phant.h << '!EOR!' X/* X * phant.h Include file for Phantasia X */ X X#include <setjmp.h> X#include <curses.h> X#include <time.h> X#include <pwd.h> X#include <signal.h> X#include <math.h> X X/* ring constants */ X#define NONE 0 X#define NAZBAD 1 X#define NAZREG 2 X#define DLREG 3 X#define DLBAD 4 X#define SPOILED 5 X X/* some functions and pseudo-functions */ X#define toupper(CH) ((CH) > 96 ? (CH) ^ 32 : (CH)) /* may be upper or lower */ X#define tolower(CH) ((CH) | 32) /* must be upper */ X#define rnd() (((double) rand()) / ((double) (RAND))) X#define roll(BASE,INTERVAL) floor((BASE) + (INTERVAL) * rnd()) X#define sgn(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 :0)) X#define abs(x) ((x) < 0 ? -(x) : (x)) X#define circ(x,y) floor(dist(x, 0.0, y, 0.0) /125 + 1) X#define max(A,B) ((A) > (B) ? (A) : (B)) X#define min(A,B) ((A) < (B) ? (A) : (B)) X#define valarstuff(ARG) decree(ARG) X#define illcmd() mvaddstr(5,0,"Illegal command.\n") X#define maxmove (charac.lvl * 1.5 + 1) X#define illmove() mvaddstr(5,0,"Too far.\n") X#define rndattack() if (rnd() < 0.2 && charac.status == PLAYING && !throne) \ X fight(&charac,-1) X#define strcalc(STR,SICK) max(0,min(0.9 * STR, SICK * STR/20)) X#define spdcalc(LVL,GLD,GEM) max(0,((GLD + GEM/2) - 1000)/200.0 - LVL) X#define illspell() mvaddstr(5,0,"Illegal spell.\n") X#define nomana() mvaddstr(5,0,"Not enough mana for that spell.\n") X#define somebetter() addstr("But you already have something better.\n") X X/* status constants */ X#define OFF 0 X#define PLAYING 1 X#define CLOAKED 2 X#define INBATTLE 3 X#define DIE 4 X#define QUIT 5 X X/* tampered constants */ X#define NRGVOID 1 X#define GRAIL 2 X#define TRANSPORT 3 X#define GOLD 4 X#define CURSED 5 X#define MONSTER 6 X#define BLESS 7 X#define MOVED 8 X#define HEAL 9 X#define VAPORIZED 10 X#define STOLEN 11 X X/* structure definitions */ Xstruct stats /* player stats */ X { X char name[21]; /* name */ X char pswd[9]; /* password */ X char login[10]; /* login */ X double x; /* x coord */ X double y; /* y coord */ X double exp; /* experience */ X int lvl; /* level */ X short quk; /* quick */ X double str; /* strength */ X double sin; /* sin */ X double man; /* mana */ X double gld; /* gold */ X double nrg; /* energy */ X double mxn; /* max. energy */ X double mag; /* magic level */ X double brn; /* brains */ X short crn; /* crowns */ X struct X { X short type; X short duration; X } rng; /* ring stuff */ X bool pal; /* palantir */ X double psn; /* poison */ X short hw; /* holy water */ X short amu; /* amulets */ X bool bls; /* blessing */ X short chm; /* charms */ X double gem; /* gems */ X short quks; /* quicksilver */ X double swd; /* sword */ X double shd; /* shield */ X short typ; /* character type */ X bool vrg; /* virgin */ X short lastused; /* day of year last used */ X short status; /* playing, cloaked, etc. */ X short tampered; /* decree'd, etc. flag */ X double scratch1, scratch2; /* var's for above */ X bool blind; /* blindness */ X int wormhole; /* # of wormhole, 0 = none */ X long age; /* age in seconds */ X short degen; /* age/2500 last degenerated */ X short istat; /* used for inter-terminal battle */ X }; X Xstruct mstats /* monster stats */ X { X char name[26]; /* name */ X double str; /* strength */ X double brn; /* brains */ X double spd; /* speed */ X double hit; /* hits (energy) */ X double exp; /* experience */ X int trs; /* treasure type */ X int typ; /* special type */ X int flk; /* % flock */ X }; X Xstruct nrgvoid /* energy void */ X { X bool active; /* active or not */ X double x,y; /* coordinates */ X }; X X#ifndef SMALL Xstruct worm_hole /* worm hole */ X { X char f, b, l, r; /* forward, back, left, right */ X }; X#endif X Xstruct sb_ent /* scoreboard entry */ X { X char name[21]; X char login[10]; X int level; X short type; X }; X X/* files */ Xextern char monsterfile[], X peoplefile[], X gameprog[], X messfile[], X lastdead[], X helpfile[], X motd[], X goldfile[], X voidfile[], X enemyfile[], X sbfile[]; X X/* library functions and system calls */ Xunsigned sleep(); Xlong time(), ftell(); Xchar *getlogin(), *getpass(), *ctime(), *strchr(); Xstruct passwd *getpwuid(); Xchar *strcpy(), *strncpy(); X X/* function and global variable declarations */ Xvoid adjuststats(), callmonster(), checkinterm(), checkmov(), checktampered(), X cstat(), death(), decree(), error(), exit1(), fight(), genchar(), getstring(), X init1(), initchar(), interm(), kingstuff(), leave(), mesg(), movelvl(), X neatstuff(), paws(), printmonster(), printplayers(), printstats(), purge(), X scoreboard(), scramble(), showall(), show_sb(), showusers(), statread(), X tampered(), titlestuff(), trade(), treasure(), trunc(), update(), voidupdate(); Xint allocvoid(), findchar(), findname(), findspace(), getans(), gch(), interrupt(), X ill_sig(), rngcalc(), level(); Xdouble dist(), inflt(); Xchar *printloc(); X#ifdef OK_TO_PLAY Xbool ok_to_play(); X#endif X Xextern jmp_buf fightenv, mainenv; Xextern double strength, speed; Xextern bool beyond, marsh, throne, valhala, changed, fghting, su, wmhl, timeout; X#ifndef SMALL Xextern struct worm_hole w_h[]; X#endif Xextern long secs; Xextern int fileloc, users; !EOR!
estes@ttrda.UUCP (Edward Estes ) (09/05/85)
# -------CUT HERE------- # This is a shar archieve. Extract with sh, not csh. # The rest of this file will extract: # func2.c func3.c main.c monsters pathdefs.c setup.c echo extracting - func2.c sed 's/^X//' > func2.c << '!EOR!' X/* X * func2.c Phantasia support routines X */ X X#include "phant.h" X Xvoid decree(stat) /* king and valar stuff */ Xreg struct stats *stat; X{ XFILE *fp; Xshort arg; Xchar aline[80], *cp; Xstruct stats sbuf; Xstruct nrgvoid vbuf; Xdouble temp1 = 0.0, temp2 = 0.0; Xint ch; Xreg int loc; X X move(6,0); X clrtoeol(); X if (stat->typ < 20 && !su) /* king */ X { X addstr("0:Census 1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes "); X ch = getans(" ", TRUE); X move(6,0); X clrtoeol(); X move(4,0); X switch (ch) X { X case '0': X showusers(TRUE); X return; X case '1': X arg = TRANSPORT; X cp = "transport"; X break; X case '2': X arg = CURSED; X cp = "curse"; X break; X case '3': X addstr("Enter the X Y coordinates of void ? "); X getstring(aline,30); X sscanf(aline,"%F %F",&temp1,&temp2); X vbuf.x = floor(temp1); X vbuf.y = floor(temp2); X vbuf.active = TRUE; X if ((loc = allocvoid()) > 20) X mvaddstr(5,0,"Sorry, void creation limit reached.\n"); X else X voidupdate(&vbuf,loc); X goto EXIT; X case '4': X arg = GOLD; X addstr("How much gold to bestow ? "); X temp1 = inflt(); X if (temp1 > stat->gld || temp1 < 0) X { X mvaddstr(5,0,"You don't have that !\n"); X return; X } X stat->gld -= floor(temp1); X cp = "give gold to"; X break; X case '5': X fp = fopen(goldfile,"r"); X fread((char *) &temp1,sizeof(double),1,fp); X fclose(fp); X mvprintw(4,0,"You have collected %.0f in gold.\n",temp1); X stat->gld += floor(temp1); X fp = fopen(goldfile,"w"); X temp1 = 0.0; X fwrite((char *) &temp1,sizeof(double),1,fp); X fclose(fp); X return; X default: X return; X } X } X else /* council of wise, valar, etc. */ X { X addstr("1:Heal "); X if (stat->pal || su) X addstr("2:Seek Grail "); X if (stat->typ == 99 || su) X addstr("3:Throw Monster 4:Relocate 5:Bless "); X if (su) X addstr("6:Vaporize "); X ch = getans(" ", TRUE); X if (!su && ch > '2' && stat->typ != 99) X { X illcmd(); X return; X } X switch (ch) X { X case '1': X arg = HEAL; X cp = "heal"; X break; X case '2': X if (stat->pal) X { X fp = fopen(voidfile,"r"); X fread((char *) &vbuf,sizeof(vbuf),1,fp); X fclose(fp); X temp1 = dist(stat->x, vbuf.x, stat->y, vbuf.y); X temp1 = floor(temp1 + roll(-temp1/10.0,temp1/5.0)); X mvprintw(5,0,"The palantir says the Grail is about %.0f away.\n",temp1); X return; X } X else X { X mvaddstr(5,0,"You need a palantir to seek the Grail.\n"); X return; X } X case '3': X mvaddstr(4,0,"Which monster [0-99] ? "); X temp1 = inflt(); X temp1 = max(0,min(99,temp1)); X cp = "throw a monster at"; X arg = MONSTER; X break; X case '4': X mvaddstr(4,0,"New X Y coordinates ? "); X getstring(aline,30); X sscanf(aline,"%F %F",&temp1,&temp2); X cp = "relocate"; X arg = MOVED; X break; X case '5': X arg = BLESS; X cp = "bless"; X break; X case '6': X if (su) X { X cp = "vaporize"; X arg = VAPORIZED; X break; X } X default: X return; X } X } X mvprintw(4,0,"Who do you want to %s ? ",cp); X getstring(aline,21); X trunc(aline); X if (strcmp(stat->name,aline)) X { X if ((loc = findname(aline,&sbuf)) >= 0) X { X if (sbuf.tampered) X { X mvaddstr(5,0,"That person has something pending already.\n"); X return; X } X else X { X sbuf.tampered = arg; X sbuf.scratch1 = floor(temp1); X sbuf.scratch2 = floor(temp2); X update(&sbuf,loc); XEXIT: mvaddstr(5,0,"It is done.\n"); X return; X } X } X else X mvaddstr(5,0,"There is no one by that name.\n"); X } X else X mvaddstr(5,0,"You may not do it to yourself!\n"); X} X Xvoid checktampered(stat) /* see if decree'd etc. */ Xreg struct stats *stat; X{ Xstruct nrgvoid vbuf; Xstruct stats sbuf; XFILE *fp; Xreg int loc = 0; X X /* first check for energy voids */ X if ((fp = fopen(voidfile,"r")) == NULL) X { X error(voidfile); X /*NOTREACHED*/ X } X while (fread((char *) &vbuf,sizeof(vbuf),1,fp)) X if (vbuf.active && vbuf.x == stat->x && vbuf.y == stat->y) X { X fclose(fp); X if (loc) X { X vbuf.active = FALSE; X voidupdate(&vbuf,loc); X tampered(stat,NRGVOID,&sbuf); X } X else if (stat->status != CLOAKED) X tampered(stat,GRAIL,&sbuf); X break; X } X else X ++loc; X fclose(fp); X /* now check for other things */ X statread(&sbuf,fileloc); X if (sbuf.tampered) X tampered(stat,sbuf.tampered,&sbuf); X} X Xvoid voidupdate(vp,loc) /* update an energy void */ Xreg struct nrgvoid *vp; Xreg int loc; X{ XFILE *fp; X X fp = fopen(voidfile,ACCESS); X fseek(fp,(long) (loc*sizeof(*vp)),0); X fwrite((char *) vp,sizeof(*vp),1,fp); X fclose(fp); X} X Xint allocvoid() /* find a space to put an energy void */ X{ XFILE *fp; Xreg int loc = 0; Xstruct nrgvoid vbuf; X X fp = fopen(voidfile,"r"); X while (fread((char *) &vbuf,sizeof(vbuf),1,fp)) X if (vbuf.active) X ++loc; X else X { X fclose(fp); X return (loc); X } X fclose(fp); X return (loc); X} X Xvoid statread(stat,loc) /* read a charac. structure */ Xreg struct stats *stat; Xreg int loc; X{ XFILE *fp; X X fp = fopen(peoplefile,"r"); X fseek(fp,(long) (loc * sizeof(*stat)),0); X fread((char *) stat,sizeof(*stat),1,fp); X fclose(fp); X} X Xvoid tampered(stat,what,bufp) /* decree'd, intervened, etc. */ Xreg struct stats *stat, *bufp; Xshort what; X{ Xstruct nrgvoid vbuf; Xreg int loc; Xstruct stats sbuf; XFILE *fp; X X changed = TRUE; X move(4,0); X stat->tampered = OFF; X switch ((int) what) X { X case NRGVOID: X addstr("You've hit an energy void !\n"); X stat->man /= 3; X stat->nrg /= 2; X stat->gld = floor(stat->gld/1.25) + 0.1; X stat->x += roll(-12,25); X stat->y += roll(-12,25); X break; X case TRANSPORT: X addstr("The king transported you ! "); X if (stat->chm) X { X addstr("But your charm save you. . .\n"); X --stat->chm; X } X else X { X stat->x += roll(-50,100) * circ(stat->x,stat->y); X stat->y += roll(-50,100) * circ(stat->x,stat->y); X addch('\n'); X } X break; X case GOLD: X printw("The king has bestowed %.0f gold pieces on you !\n",bufp->scratch1); X stat->gld += bufp->scratch1; X break; X case CURSED: X addstr("You've been cursed ! "); X if (stat->bls) X { X addstr("But your blessing saved you. . .\n"); X stat->bls = FALSE; X } X else X { X addch('\n'); X stat->psn += 2; X stat->nrg = 10; X stat->mxn *= 0.95; X stat->status = PLAYING; X } X break; X case VAPORIZED: X addstr("Woops! You've been vaporized!\n"); X death(stat, "Vaporization"); X break; X case MONSTER: X addstr("The Valar zapped you with a monster!\n"); X paws(7); X fight(stat,(int) bufp->scratch1); X return; X case BLESS: X addstr("The Valar has blessed you!\n"); X stat->nrg = (stat->mxn *= 1.05) + stat->shd; X stat->man += 500; X stat->str += 0.5; X stat->brn += 0.5; X stat->mag += 0.5; X stat->psn = min(0.5,stat->psn); X break; X case MOVED: X addstr("You've been relocated. . .\n"); X stat->x = bufp->scratch1; X stat->y = bufp->scratch2; X break; X case HEAL: X addstr("You've been healed!\n"); X stat->psn -= 0.25; X stat->nrg = stat->mxn + stat->shd; X break; X case STOLEN: X addstr("You'Ve been bumped off as Valar!\n"); X stat->typ = 20 + roll(1,6); X break; X case GRAIL: X addstr("You have found The Holy Grail!!\n"); X if (stat->typ < 20) X { X addstr("However, you are not experienced enough to behold it.\n"); X stat->sin *= stat->sin; X stat->man += 1000; X } X else if (stat->typ == 99 || stat->typ == 90) X { X addstr("You have made it to the position of Valar once already.\n"); X addstr("The Grail is of no more use to you now.\n"); X } X else X { X addstr("It is now time to see if you are worthy to behold it. . .\n"); X refresh(); X sleep(4); X if (rnd() / 2.0 < stat->sin) X { X addstr("You blew this one!\n"); X stat->str = stat->man = stat->quk = stat->nrg = stat->mxn = stat->x = stat->y = X stat->mag = stat->brn = stat->exp =1; X stat->lvl = 0; X } X else X { X addstr("You made to position of Valar!\n"); X stat->typ = 99; X fp = fopen(peoplefile,"r"); X loc = 0; X while (fread((char *) &sbuf,sizeof(sbuf),1,fp)) X if (sbuf.typ == 99) X { X sbuf.tampered = STOLEN; X update(&sbuf,loc); X break; X } X else X ++loc; X fclose(fp); X } X } X vbuf.active = TRUE; X vbuf.x = roll(-1e6,2e6); X vbuf.y = roll(-1e6,2e6); X voidupdate(&vbuf,0); X break; X } X} X Xvoid adjuststats(stat) /* make sure things are within limits, etc. */ Xreg struct stats *stat; X{ Xlong ltemp; Xreg int temp; X X stat->x = floor(stat->x); X stat->y = floor(stat->y); X valhala = (stat->typ == 99); X throne = (stat->x == 0.0 && stat->y == 0.0); X#ifndef SMALL X temp = abs(stat->x)/400; X if (temp > 16) X temp = 0; X if (stat->y == 0.0 && !throne && !valhala && temp == abs(stat->x)/400 && sgn(stat->x) == (int) pow(-1.0, (double) temp)) X { X if (!wmhl) X stat->wormhole = temp; X wmhl = TRUE; X } X else X wmhl = FALSE; X#endif X speed = stat->quk + stat->quks - spdcalc(stat->lvl,stat->gld,stat->gem); X strength = stat->str + stat->swd - strcalc(stat->str,stat->psn); X time(<emp); X stat->age += (ltemp - secs); X secs = ltemp; X stat->quks = min(99,stat->quks); X stat->man = min(stat->man,stat->lvl*15 + 5000); X stat->chm = min(stat->chm,stat->lvl + 10); X stat->typ = (stat->crn && stat->typ < 10) ? -abs(stat->typ) : abs(stat->typ); X if (level(stat->exp) > stat->lvl) X { X movelvl(stat); X if (stat->lvl > 5) X timeout = TRUE; X } X stat->gld = floor(stat->gld) + 0.1; X stat->gem = floor(stat->gem) + 0.1; X if (stat->rng.type) X stat->nrg = stat->mxn + stat->shd; X if (stat->rng.type && stat->rng.duration <= 0) /* clean up rings */ X switch (stat->rng.type) X { X case DLBAD: X case NAZBAD: X stat->rng.type = SPOILED; X stat->rng.duration = roll(10,25); X break; X case NAZREG: X stat->rng.type = NONE; X break; X case SPOILED: X death(stat, "A cursed ring"); X break; X } /* DLREG is ok, so do nothing with it */ X if (stat->age > stat->degen * 5000) X { X ++stat->degen; X if (stat->quk > 23) X --stat->quk; X stat->str *= 0.97; X stat->brn *= 0.95; X stat->mag *= 0.97; X stat->mxn *= 0.95; X if (stat->quks) X --stat->quks; X stat->swd *= 0.93; X stat->shd *= 0.95; X } X} X Xvoid checkinterm(stat) /* see if other person on same x,y */ Xreg struct stats *stat; X{ XFILE *fp; Xstruct stats sbuf; Xreg int foeloc = 0; X X users = 0; X fp = fopen(peoplefile,"r"); X while (fread((char *) &sbuf,sizeof(sbuf),1,fp)) X { X if (sbuf.status && (sbuf.status != CLOAKED || sbuf.typ != 99)) X { X ++users; X if (stat->x == sbuf.x && stat->y == sbuf.y X && foeloc != fileloc && sbuf.typ != 99 X && stat->typ !=99 && !stat->wormhole && !sbuf.wormhole) X { X fclose(fp); X interm(stat,foeloc); X return; X } X } X ++foeloc; X } X fclose(fp); X} X Xint gch(rngtyp) /* get a character from terminal, but check ring if crazy */ Xshort rngtyp; X{ X refresh(); X if (abs(rngtyp) != SPOILED) X return (getans("T ", TRUE)); X else X { X getans(" ", TRUE); X return (roll(0,5) + '0'); X } X} X Xint rngcalc(chartyp) /* pick a duration of a ring */ Xshort chartyp; X{ Xstatic int rngtab[] = { 0, 10, 20, 13, 25, 40, 20}; X X if (chartyp > 10) X chartyp -= 10; X return (rngtab[chartyp - 1]); X} X Xvoid interm(stat,who) /* interterminal battle routine */ Xreg struct stats *stat; Xint who; X{ X#define MAXWAIT 20 X#define BLOCK sizeof(struct stats) X#define RAN 1 X#define STUCK 2 X#define BLEWIT 3 X#define KILLED 4 X#define readfoe() fseek(fin,foeplace,0); \ X fread((char *) foe,BLOCK,1,fin) X#define updateme() fseek(fout,myplace,0); \ X fwrite((char *) stat,BLOCK,1,fout); \ X fflush(fout) X XFILE *fin, *fout; /* pointers for input, output */ Xdouble temp, foespeed, oldhits = 0.0, myhits; Xstruct stats sbuf; Xreg struct stats *foe; Xreg int loop, lines = 8; Xint ch; Xlong myplace, foeplace; Xshort oldtags; Xbool luckout = FALSE; Xchar foename[21]; X X fghting = TRUE; X mvaddstr(4,0,"Preparing for battle!\n"); X refresh(); X /* set up variables, file, etc. */ X myplace = fileloc * BLOCK; X foeplace = who * BLOCK; X fin = fopen(peoplefile,"r"); X setbuf(fin, (char *) NULL); X fout = fopen(peoplefile,ACCESS); X stat->status = INBATTLE; X myhits = stat->nrg; X stat->tampered = oldtags = 1; /* this must be non-zero to prevent a king or valar from trashing it */ X stat->scratch1 = 0.0; X stat->istat = 0; X updateme(); X foe = &sbuf; X readfoe(); X foespeed = foe->quk + foe->quks - spdcalc(foe->lvl,foe->gld,foe->gem); X if (abs(stat->lvl - foe->lvl) > 20) /* see if greatly mismatched */ X { X temp = ((double) (stat->lvl - foe->lvl))/((double) max(stat->lvl,foe->lvl)); X if (temp > 0.5) /* this one outweighs his/her foe */ X foespeed *= 2.0; X else if (temp < -0.5) /* foe outweighs this one */ X speed *= 2.0; X } X if (stat->blind) X strcpy(foename,"someone"); X else X strcpy(foename,foe->name); X mvprintw(6,0,"You have encountered %s Level: %d\n",foename,foe->lvl); X refresh(); X /* now wait for foe to respond */ X for (loop = 1.5*MAXWAIT; foe->status != INBATTLE && loop; --loop) X { X readfoe(); X sleep(1); X } X if (foe->status != INBATTLE) X { X mvprintw(5,0,"%s is not responding.\n",foename); X goto LEAVE; X } X X /* otherwise, everything is set to go */ X move(4,0); X clrtoeol(); X /* check to see who goes first */ X if (speed > foespeed) X goto HITFOE; X else if (foespeed > speed) X goto WAIT; X else if (stat->lvl > foe->lvl) X goto HITFOE; X else if (foe->lvl > stat->lvl) X goto WAIT; X else /* no one is faster */ X { X printw("You can't fight %s yet.",foename); X goto LEAVE; X } X X/* routine to hit, etc */ XHITFOE: printstats(stat); X mesg(); X mvprintw(1,26,"%20.0f",myhits); X mvaddstr(7,0,"1:Fight 2:Run Away! 3:Power Blast "); X if (luckout) X clrtoeol(); X else X addstr("4:Luckout "); X ch = gch(stat->rng.type); X move(lines = 8,0); X clrtobot(); X switch (ch) X { X default: /* fight */ X temp = roll(2,strength); XHIT: mvprintw(lines++,0,"You hit %s %.0f times!",foename,temp); X stat->sin += 0.5; X stat->scratch1 += temp; X stat->istat = FALSE; X break; X case '2': /* run away */ X --stat->scratch1; /* this value changes to indicate action */ X if (rnd() > 0.25) X { X mvaddstr(lines++,0,"You got away!"); X stat->istat = RAN; X goto LEAVE; X } X mvprintw(lines++,0,"%s is still after you!",foename); X stat->istat = STUCK; X break; X case '3': /* power blast */ X temp = min(stat->man,stat->lvl*5); X stat->man -= temp; X temp = (rnd() + 0.5) * temp * stat->mag * 0.2 + 2; X mvprintw(lines++,0,"You blasted %s !",foename); X goto HIT; X case '4': /* luckout */ X if (luckout || rnd() > 0.1) X { X luckout = TRUE; X mvaddstr(lines++,0,"Not this time..."); X --stat->scratch1; X stat->istat = BLEWIT; X } X else X { X mvaddstr(lines++,0,"You just lucked out!"); X stat->scratch1 = foe->nrg + 5; X } X break; X } X refresh(); X stat->scratch1 = floor(stat->scratch1); /* clean up any mess */ X if (stat->scratch1 > foe->nrg) X stat->istat = KILLED; X else if (rnd() * speed < rnd() * foespeed) X { /* foe's turn */ X ++stat->tampered; X updateme(); X goto WAIT; X } X updateme(); X X if (stat->istat == KILLED) X { X mvprintw(lines++,0,"You killed %s!",foename); X stat->exp += foe->exp; X stat->crn += (stat->lvl < 1000) ? foe->crn : 0; X stat->amu += foe->amu; X stat->chm += foe->chm; X stat->gld += foe->gld; X stat->gem += foe->gem; X stat->swd = max(stat->swd,foe->swd); X stat->shd = max(stat->shd,foe->shd); X stat->quks = max(stat->quks,foe->quks); X sleep(3); /* give other person time to die */ X goto LEAVE; X } X goto HITFOE; /* otherwise, my turn again */ X X/* routine to wait for foe to do something */ XWAIT: printstats(stat); X mesg(); X mvprintw(1,26,"%20.0f",myhits); X mvaddstr(4,0,"Waiting...\n"); X refresh(); X for (loop = MAXWAIT; loop; --loop) X { X readfoe(); X if (foe->scratch1 != oldhits) X switch (foe->istat) X { X case RAN: X mvprintw(lines++,0,"%s ran away!",foename); X goto LEAVE; X case STUCK: X mvprintw(lines++,0,"%s tried to run away.",foename); X goto BOT; X case BLEWIT: X mvprintw(lines++,0,"%s tried to luckout!",foename); X goto BOT; X default: X temp = foe->scratch1 - oldhits; X mvprintw(lines++,0,"%s hit you %.0f times!",foename,temp); X myhits -= temp; X goto BOT; X } X sleep(1); X } X /* timeout */ X mvaddstr(22,0,"Timeout: waiting for response. Do you want to wait ? "); X refresh(); X ch = getans("NY", FALSE); X move(22,0); X clrtobot(); X if (ch == 'Y') X goto WAIT; X goto LEAVE; X X/* routine to decide what happens next */ XBOT: refresh(); X if (lines > 21) X { X paws(lines); X move(lines = 8,0); X clrtobot(); X } X if (foe->istat == KILLED || myhits < 0.0) X { X myhits = -2; X goto LEAVE; /* main will pick up death */ X } X oldhits = foe->scratch1; X if (foe->tampered != oldtags) X { X oldtags = foe->tampered; X goto HITFOE; X } X goto WAIT; X X/* routine to clean up things and leave */ XLEAVE: updateme(); X fclose(fin); X fclose(fout); X stat->x += roll(5,-10); X stat->y += roll(5,-10); X stat->nrg = myhits; X stat->tampered = OFF; X stat->status = PLAYING; X changed = TRUE; X paws(lines); X move(4,0); X clrtobot(); X} X Xint interrupt() /* call when break key is hit */ X{ Xchar line[81]; Xreg int loop; Xint x, y, ch; X X#ifdef SYS3 X signal(SIGINT,SIG_IGN); X#endif X#ifdef SYS5 X signal(SIGINT,SIG_IGN); X#endif X getyx(stdscr,y,x); X for (loop = 79; loop >= 0; --loop) /* snarf line */ X { X move(4,loop); X line[loop] = inch(); X } X line[80] = '\0'; X clrtoeol(); X if (fghting) X { X move(4,0); X clrtoeol(); X addstr("Quitting now will automatically kill your character. Still want to ? "); X ch = getans("NY", FALSE); X if (ch == 'Y') X longjmp(mainenv,DIE); X } X else X { X move(4,0); X clrtoeol(); X addstr("Do you really want to quit ? "); X ch = getans("NY", FALSE); X if (ch == 'Y') X longjmp(mainenv,QUIT); X } X mvaddstr(4,0,line); /* return screen to previous state */ X move(y,x); X refresh(); X#ifdef SYS3 X signal(SIGINT,interrupt); X#endif X#ifdef SYS5 X signal(SIGINT,interrupt); X#endif X} X Xvoid purge() /* remove old players */ X{ XFILE *fin, *fout; Xstruct stats sbuf; Xreg int loc, today, temp; Xlong ltime; X X loc = 0; X time(<ime); X today = localtime(<ime)->tm_yday; X fin = fopen(peoplefile,"r"); X fout = fopen(peoplefile,ACCESS); X while(fread((char *) &sbuf,sizeof(sbuf),1,fin)) X { X temp = today - sbuf.lastused; X if (temp < 0) X temp += 365; X if (temp > 9) /* ten days old --> delete */ X { X initchar(&sbuf); X strcpy(sbuf.name,"<null>"); X fseek(fout,(long) (loc * sizeof(sbuf)),0); X fwrite((char *) &sbuf,sizeof(sbuf),1,fout); X } X ++loc; X } X fclose(fin); X fclose(fout); X} !EOR! echo extracting - func3.c sed 's/^X//' > func3.c << '!EOR!' X/* X * func3.c Phantasia support routines X */ X#include "phant.h" X Xjmp_buf btimeout; Xint catchalarm(); X Xint getans(choices, def) /* get a one character option from keyboard */ Xchar *choices; Xbool def; X{ Xint ch, loop, oldx, oldy; Xchar *cptr; X X getyx(stdscr, oldy, oldx); X alarm(0); X X for (loop = 3; loop; --loop) X if (setjmp(btimeout)) X if (def) X return(*choices); X else if (loop > 1) X goto YELL; X else X break; X else X { X clrtoeol(); X refresh(); X#ifdef BSD41 X sigset(SIGALRM, catchalarm); X#else X signal(SIGALRM, catchalarm); X#endif X if (timeout) X alarm(7); X else X alarm(600); X ch = getch(); X alarm(0); X if ((cptr = strchr(choices, toupper(ch))) != NULL) X return(*cptr); X else if (def) X return(toupper(ch)); X else if (!def && loop > 1) X { XYELL: mvprintw(oldy+1,0,"Please choose one of : [%s]\n", choices); X move(oldy, oldx); X clrtoeol(); X continue; X } X else X break; X } X return(*choices); X} X Xint catchalarm() X{ X longjmp(btimeout, 1); X} X Xvoid error(whichfile) Xchar *whichfile; X{ Xextern int errno; X X clear(); X printw("An unrecoverable error has occurred reading %s. (errno = %d)\n", whichfile, errno); X addstr("Please run 'setup' to determine the problem.\n"); X exit1(); X /*NOTREACHED*/ X} X X Xvoid mesg() X{ XFILE *fp; Xchar s[100]; X X move(3,0); X clrtoeol(); X if ((fp = fopen(messfile, "r")) != NULL) X { X if (fgets(s,100,fp)) X addstr(s); X fclose(fp); X } X} X Xdouble dist(x1, x2, y1, y2) Xdouble x1, x2, y1, y2; X{ Xdouble deltax, deltay; X X deltax = x1 - x2; X deltay = y1 - y2; X return(sqrt(deltax * deltax + deltay * deltay)); X} X Xvoid scoreboard(stat) /* enter login into scoreboard */ Xreg struct stats *stat; X{ Xstatic struct sb_ent sbuf; XFILE *fp; Xreg int loc = 0; Xbool found = FALSE; X X if ((fp = fopen(sbfile, "r")) != NULL) X { X while (fread((char *) &sbuf, sizeof(sbuf), 1, fp)) X if (!strcmp(stat->login, sbuf.login)) X { X found = TRUE; X break; X } X else X ++loc; X fclose(fp); X } X X /* X * At this point, 'loc' will either indicate a point beyond X * the end of file, or the place where the previous entry X * was found. X */ X X if ((!found) || stat->lvl > sbuf.level) X { X strcpy(sbuf.login, stat->login); X strcpy(sbuf.name, stat->name); X sbuf.level = stat->lvl; X sbuf.type = stat->typ; X } X if ((fp = fopen(sbfile, ACCESS)) == NULL) X { X error(sbfile); X /*NOTREACHED*/ X } X fseek(fp, (long) (loc * sizeof(sbuf)), 0); X fwrite((char *) &sbuf, sizeof(sbuf), 1, fp); X fclose(fp); X} X X Xvoid show_sb() /* printout the scoreboard */ X{ Xstatic struct sb_ent sbuf; XFILE *fp; X X if ((fp = fopen(sbfile, "r")) != NULL) X while (fread((char *) &sbuf, sizeof(sbuf), 1, fp)) X printf("%-20s Login: %-9s Level: %6d Type: %3d\n", X sbuf.name, sbuf.login, sbuf.level, sbuf.type); X} X Xint ill_sig(whichsig) /* come here on bad signals */ Xint whichsig; X{ X clear(); X printw("Error: caught signal # %d.\n", whichsig); X exit1(); X /*NOTREACHED*/ X} !EOR! echo extracting - main.c sed 's/^X//' > main.c << '!EOR!' X/* X * Phantasia 3.3.1 -- Interterminal fantasy game X * X * Edward A. Estes X * AT&T, August 28, 1985 X */ X X/* DISCLAIMER: X * X * This game is distributed for free as is. It is not guaranteed to work X * in every conceivable environment. It is not even guaranteed to work X * in ANY environment. X * X * This game is distributed without notice of copyright, therefore it X * may be used in any manner the recipient sees fit. However, the X * author assumes no responsibility for maintaining or revising this X * game, in its original form, or any derivitives thereof. X * X * The author shall not be responsible for any loss, cost, or damage, X * including consequential damage, caused by reliance on this material. X * X * The author makes no warranties, express or implied, including warranties X * of merchantability or fitness for a particular purpose or use. X * X * AT&T is in no way connected with this game. X */ X X/* X * This is the program which drives the whole mess. Hopefully, you will be X * able to wade through the garbage if you have to fix something. X * several undocumented items exist. The program checks uid and sets the X * boolean flag 'su' (super user) if the person is allowed special powers. X * This only happens if the game is invoked with '-S' as an option. X * The 'su' may execute any of the valar/council options. Also, X * a 'vaporize' option exists to kill anybody at will. The 'su' can select X * character type 7, which starts out with the maximum possible in each X * category. (The resulting character is an experimento.) The 'su' may X * also change the stats of other characters with the -x option. X */ X X/* X * The program allocates as much file space as it needs to store characters, X * so the possibility exists for the character file to grow without bound. X * The file is purged upon normal entry to try to avoid that problem. X * A similar problem exists for energy voids. To alleviate the problem here, X * the void file is cleared with every new king. X */ X X/* X * The support functions are split between various files with no apparent X * order. Use of 'ctags' is recommended to find a particular function. X */ X X/* X * Put one line of text into the file 'motd' for announcements, etc. X */ X X/* X * If ENEMY is defined, a list of restricted login names is checked X * in the file 'enemy'. These names are listed, one per line, with X * no trailing blanks. X */ X X/* X * The scoreboard file is updated when someone dies, and keeps track X * of the highest character to date for that login. X * Being purged from the character file does not cause the scoreboard X * to be updated. X */ X X#include "phant.h" X Xdouble strength, speed; Xbool beyond, marsh, throne, valhala, changed, fghting, su, wmhl, timeout; Xint fileloc, users; Xjmp_buf fightenv, mainenv; Xlong secs; X X#ifndef SMALL X/* X * worm hole map -- This table is carefully set up so that one can always X * return the way he/she came by inverting the initial path. X */ Xstruct worm_hole w_h[] = X { X 0,0,0,0, 35,22,2,0, 2,2,0,1, 59,34,64,0, X 54,47,0,60, 50,62,0,56, 19,31,25,0, 0,35,41,41, X 0,46,40,23, 24,0,29,30, 44,57,56,0, 0,44,39,40, X 61,41,0,42, 32,0,17,18, 57,0,63,64, 0,33,26,34, X 48,0,54,55, 28,23,22,13, 63,25,13,19, 34,6,18,20, X 27,26,19,21, 15,27,20,27, 1,28,34,17, 17,29,8,24, X 29,9,23,25, 18,30,24,6, 20,32,27,15, 21,20,21,26, X 22,17,46,29, 23,24,28,9, 25,38,9,31, 6,39,30,32, X 26,13,31,33, 15,40,32,35, 3,19,15,22, 7,1,33,36, X 37,37,35,37, 36,36,36,38, 30,42,37,39, 31,43,38,11, X 33,45,11,8, 12,48,7,7, 38,49,12,43, 39,51,42,44, X 11,10,43,45, 40,52,44,46, 8,53,45,28, 4,54,51,48, X 41,16,47,49, 42,55,48,50, 62,5,49,51, 43,56,50,47, X 45,58,53,53, 46,59,52,52, 47,4,55,16, 49,61,16,54, X 51,63,5,10, 10,14,59,58, 52,64,57,59, 53,3,58,57, X 60,60,4,61, 55,12,60,62, 5,50,61,63, 56,18,62,14, X 58,33,14,3 X }; X#endif X Xmain(argc,argv) /* Phantasia main routine */ Xint argc; Xchar *argv[]; X{ Xstatic struct stats charac; Xchar aline[200], *login = NULL; Xdouble x = 0.0, y = 0.0; Xint ch, ch2, loop, temp; XFILE *fp; Xbool shrt = FALSE, examine = FALSE, header = FALSE; X X if ((login = getlogin()) == NULL) X login = getpwuid(getuid())->pw_name; X#ifdef ENEMY X /* check hit list of restricted accounts */ X if ((fp = fopen(enemyfile, "r")) != NULL) X { X char enemy[25]; X X while (fscanf(fp, "%s", enemy) != EOF) X if (!strcmp(login,enemy)) X { X printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", login); X printf ("Mail comments to %s.\n", WIZARD); X exit (0); X } X fclose (fp); X } X#endif X setbuf(stdin, (char *) NULL); /* this may or may not be necessary */ X su = FALSE; X fghting = FALSE; X timeout = FALSE; X users = 0; X while (--argc && (*++argv)[0] == '-') X switch ((*argv)[1]) X { X case 'h': /* help */ X if ((fp = fopen(helpfile, "r")) != NULL) X { X while (fgets(aline, 200, fp)) X fputs(aline, stdout); X fclose(fp); X } X exit(0); X /*NOTREACHED*/ X case 's': /* short */ X shrt = TRUE; X break; X case 'x': /* examine */ X examine = TRUE; X break; X case 'H': /* Header */ X header = TRUE; X break; X case 'm': /* monsters */ X printmonster(); X exit(0); X /*NOTREACHED*/ X case 'a': /* all users */ X showusers(FALSE); X exit(0); X /*NOTREACHED*/ X case 'p': /* purge old players */ X purge(); X exit(0); X /*NOTREACHED*/ X case 'S': X su = (getuid() == UID); X break; X case 'b': X show_sb(); X exit(0); X /*NOTREACHED*/ X } X if (!isatty(0)) /* don't let non-tty's play */ X exit(0); X init1(); /* set up for screen stuff */ X if (examine) X { X cstat(); X exit1(); X /*NOTREACHED*/ X } X if (!shrt) X { X titlestuff(); X purge(); /* clean up old characters */ X } X if (header) X { X exit1(); X /*NOTREACHED*/ X } X#ifdef OK_TO_PLAY X if (!ok_to_play()) X { X mvaddstr(23,27,"Sorry, you can't play now.\n"); X exit1(); X /*NOTREACHED*/ X } X#endif X mvaddstr(22,24,"Do you have a character to run? "); X ch = getans("NY", FALSE); X if (ch == 'Y') X fileloc = findchar(&charac); X else X { X initchar(&charac); X clear(); X mvaddstr(4,21,"Which type of character do you want:"); X mvaddstr(8,4,"1:Magic User 2:Fighter 3:Elf 4:Dwarf 5:Halfling 6:Experimento ? "); X ch = getans("2134567", FALSE); X do X { X genchar(&charac,ch); X mvprintw(12,14,"Strength: %2.0f Mana : %3.0f Quickness : %2d", X charac.str,charac.man,charac.quk); X mvprintw(13,14,"Brains : %2.0f Magic Level: %2.0f Energy Level: %2.0f", X charac.brn,charac.mag,charac.nrg); X if (charac.typ != 6) X { X mvaddstr(14,14,"Type '1' to keep >"); X ch2 = getans(" ", TRUE); X } X else X break; X } X while (ch2 != '1'); X if (charac.typ == 6) X for (;;) X { X mvaddstr(16,0,"Enter the X Y coordinates of your experimento ? "); X getstring(aline,80); X sscanf(aline,"%F %F",&charac.x,&charac.y); X if (abs(charac.x) > 1.2e6 || abs(charac.y) > 1.2e6) X mvaddstr(17,0,"Invalid coordinates. Try again.\n"); X else X break; X } X for (;;) X { X mvaddstr(18,0,"Give your character a name [up to 20 characters] ? "); X getstring(aline,80); X strncpy(charac.name,aline,20); X charac.name[20] = '\0'; X trunc(charac.name); X if (charac.name[0] == '\0') X mvaddstr(19,0,"Invalid name."); X else if (findname(charac.name, (struct stats *) NULL) >= 0) X mvaddstr(19,0,"Name already in use."); X else X break; X addstr(" Pick another.\n"); X } X putchar('\n'); X fflush(stdout); X nocrmode(); X do X { X strcpy(charac.pswd,getpass("Give your character a password [up to 8 characters] ? ")); X putchar('\n'); X strcpy(aline,getpass("One more time to verify ? ")); X } X while (strcmp(charac.pswd,aline)); X fileloc = findspace(); X } X crmode(); X if (charac.status) X { X clear(); X addstr("Your character did not exit normally last time.\n"); X addstr("If you think you have good cause to have your character saved,\n"); X printw("you may quit and mail your reason to '%s'.\n",WIZARD); X addstr("Otherwise, continuing spells certain death.\n"); X addstr("Do you want to quit ? "); X ch = getans("YN", FALSE); X if (ch== 'Y') X { X charac.tampered = charac.quk; /* store this away */ X charac.quk = -100; X leave(&charac); X /*NOTREACHED*/ X } X death(&charac, "Stupidity"); X } X charac.status = PLAYING; X if (charac.lvl > 5) X timeout = TRUE; X strcpy(charac.login,login); X time(&secs); X charac.lastused = localtime(&secs)->tm_yday; X update(&charac,fileloc); X clear(); X#ifdef BSD41 X sigset(SIGINT,interrupt); X#endif X#ifdef BSD42 X signal(SIGINT,interrupt); X#endif X#ifdef SYS3 X signal(SIGINT,interrupt); X#endif X#ifdef SYS5 X signal(SIGINT,interrupt); X#endif X X /* all set for now */ X XTOP: X switch (setjmp(mainenv)) X { X case QUIT: X#ifdef BSD41 X sigrelse(SIGINT); X#endif X#ifdef BSD42 X signal(SIGINT,interrupt); X#endif X#ifdef SYS3 X signal(SIGINT,interrupt); X#endif X#ifdef SYS5 X signal(SIGINT,interrupt); X#endif X leave(&charac); X /*NOTREACHED*/ X case DIE: X#ifdef BSD41 X sigrelse(SIGINT); X#endif X#ifdef BSD42 X signal(SIGINT,interrupt); X#endif X#ifdef SYS3 X signal(SIGINT,interrupt); X#endif X#ifdef SYS5 X signal(SIGINT,interrupt); X#endif X death(&charac, "Bailing out"); X break; X } X#ifdef OK_TO_PLAY X if (!ok_to_play()) X { X mvaddstr(6,0,"Whoops! Can't play now.\n"); X leave(&charac); X /*NOTREACHED*/ X } X#endif X fghting = FALSE; X adjuststats(&charac); X if (throne && !charac.crn && (charac.typ < 10 || charac.typ > 20)) X { X mvaddstr(5,0,"You're not allowed in the Lord's Chamber without a crown.\n"); X changed = TRUE; X charac.x = charac.y = 10 + roll(8, 5); X } X if (charac.status != CLOAKED && abs(charac.x) == abs(charac.y) X && floor(sqrt(fabs(charac.x/100.0))) == sqrt(fabs(charac.x/100.0)) && !throne) X { X trade(&charac); X clear(); X } X checktampered(&charac); X checkinterm(&charac); X if (charac.nrg < 0 || (charac.lvl >= 10000 && charac.typ != 99)) X death(&charac, "Interterminal battle"); X neatstuff(&charac); X if (changed) X { X update(&charac,fileloc); X changed = FALSE; X goto TOP; X } X mesg(); X printstats(&charac); X move(6,0); X#ifndef SMALL X if (!wmhl) X#endif X { X if (throne) X kingstuff(&charac); X addstr("NSEW1:Move 2:Players 3:Talk 4:Stats 5:Quit "); X if (charac.lvl >= 7 && charac.mag >= 20) X addstr("6:Cloak "); X if (charac.lvl >= 12 && charac.mag >= 40) X addstr("7:Teleport "); X if (charac.typ > 20) X addstr("8:Intervene"); X ch = gch(charac.rng.type); X mvaddstr(4,0,"\n\n"); X if (charac.status == CLOAKED) X if (charac.man > 3.0) X charac.man -= 3; X else X { X charac.status = PLAYING; X changed = TRUE; X } X move(7,0); X clrtobot(); X if (charac.typ == 99 && (ch == '1' || ch == '7')) X ch = ' '; X switch (ch2 = ch) X { X case 'N': X charac.y += maxmove; X break; X case 'S': X charac.y -= maxmove; X break; X case 'E': X charac.x += maxmove; X break; X case 'W': X charac.x -= maxmove; X break; X default: /* rest */ X charac.nrg += (charac.mxn+charac.shd)/15+charac.lvl/3+2; X charac.nrg = min(charac.nrg,charac.mxn + charac.shd); X if (charac.status != CLOAKED) X { X charac.man += circ(charac.x,charac.y)/4; X charac.man += charac.lvl/6; X rndattack(); X } X break; X case '1': /* move */ X for (loop = 3; loop; --loop) X { X mvaddstr(4,0,"X Y Coordinates ? "); X getstring(aline,80); X if (sscanf(aline,"%F %F",&x,&y) != 2) X mvaddstr(5,0,"Try again\n"); X else if (dist(charac.x, x, charac.y, y) > maxmove) X illmove(); X else X { X charac.x = x; X charac.y = y; X break; X } X } X break; X case '2': /* players */ X printplayers(&charac); X break; X case '3': /* message */ X mvaddstr(4,0,"Message ? "); X getstring(aline, 80); X fp = fopen(messfile, "w"); X if (*aline) X fprintf(fp, "%s: %s", charac.name, aline); X fclose(fp); X break; X case '4': /* stats */ X showall(&charac); X break; X case '5': /* good-bye */ X leave(&charac); X /*NOTREACHED*/ X case '6': /* cloak */ X if (charac.lvl < 7 || charac.mag < 20) X illcmd(); X else if (charac.status == CLOAKED) X charac.status = PLAYING; X else if (charac.man < 35) X { X mvaddstr(5,0,"No power left.\n"); X refresh(); X } X else X { X changed = TRUE; X charac.man -= 35; X charac.status = CLOAKED; X } X break; X case '7': /* teleport */ X if (charac.lvl < 12 || charac.mag < 40) X illcmd(); X else X for (loop = 3; loop; --loop) X { X mvaddstr(4,0,"X Y Coordinates ? "); X getstring(aline,80); X if (sscanf(aline,"%F %F",&x,&y) == 2) X if ((temp = dist(charac.x,x,charac.y,y)) X > (charac.lvl+charac.mag)*20+((charac.typ > 30) ? 1e+6 : 0) X && !throne) X illmove(); X else if ((temp = (temp/75+1)*20) > charac.man && !throne) X mvaddstr(5,0,"Not enough power for that distance.\n"); X else X { X charac.x = x; X charac.y = y; X if (!throne) X charac.man -= temp; X break; X } X } X break; X case '9': /* monster */ X if (throne) X mvaddstr(5,0,"No monsters in the chamber!\n"); X else if (charac.typ != 99) X { X charac.status = PLAYING; X changed = TRUE; X charac.sin += 1e-6; X fight(&charac,-1); X } X break; X case '0': /* decree */ X if (su || charac.typ > 10 && charac.typ < 20 && throne) X decree(&charac); X else X illcmd(); X break; X case '8': /* intervention */ X if (su || charac.typ > 20) X valarstuff(&charac); X else X illcmd(); X break; X case '\014': /* redo screen */ X clear(); X } X if (ch2 == 'E' || ch2 == 'W' || ch2 == 'N' || ch2 == 'S' X || ch2 == '1' || ch2 == '7') X { X checkmov(&charac); X rndattack(); X changed = TRUE; X } X } X#ifndef SMALL X else X { X addstr("F:Forward B:Back R:Right L:Left Q:Quit T:Talk P:Players S:Stats "); X ch = getans(" ", TRUE); X move(6,0); X clrtobot(); X if (charac.status == CLOAKED) X if (charac.man > 3.0) X charac.man -= 3; X else X { X charac.status = PLAYING; X changed = TRUE; X } X switch (ch) X { X default: /* rest */ X charac.nrg += (charac.mxn+charac.shd)/15+charac.lvl/3+2; X charac.nrg = min(charac.nrg,charac.mxn + charac.shd); X if (charac.status != CLOAKED) X charac.man += charac.lvl/5; X break; X case 'F': X temp = w_h[charac.wormhole].f; X goto CHKMOVE; X case 'B': X temp = w_h[charac.wormhole].b; X goto CHKMOVE; X case 'R': X temp = w_h[charac.wormhole].r; X goto CHKMOVE; X case 'L': X temp = w_h[charac.wormhole].l; X goto CHKMOVE; X case 'Q': X leave(&charac); X /*NOTREACHED*/ X case 'T': X mvaddstr(4,0,"Message ? "); X getstring(aline, 80); X fp = fopen(messfile, "w"); X if (*aline) X fprintf(fp, "%s: %s", charac.name, aline); X fclose(fp); X break; X case 'P': X printplayers(&charac); X break; X case 'S': X showall(&charac); X break; X case '\014': /* redo screen */ X clear(); X } X goto TOP; XCHKMOVE: X if (!temp) X { X charac.y = 0.0; X charac.x = pow(-1.0,(double) charac.wormhole) * charac.wormhole * 400 - 1.0; X charac.wormhole = 0; X changed = TRUE; X } X else X charac.wormhole = temp; X } X#endif X goto TOP; X} X X/* X * This function is provided to allow one to restrict access to the game. X * Tailor this routine as appropriate. X */ X X#ifdef OK_TO_PLAY X#include <sys/types.h> X#include <utmp.h> /* used for counting users on system */ X Xbool ok_to_play() /* return FALSE if playing is not allowed at this time */ X{ X#define MAXUSERS 30 /* max. number of people on system */ Xreg struct tm *tp; Xreg int numusers = 0; XFILE *fp; Xlong now; Xstruct utmp ubuf; X X if (su) X return (TRUE); X /* check time of day */ X time(&now); X if (((tp = localtime(&now))->tm_hour > 8 && tp->tm_hour < 12) /* 8-noon */ X || (tp->tm_hour > 12 && tp->tm_hour < 16)) /* 1-4 pm */ X return (FALSE); X /* check # of users */ X if ((fp = fopen("/etc/utmp","r")) != NULL) X { X while (fread((char *) &ubuf,sizeof(ubuf),1,fp)) X#ifdef SYS5 X if (ubuf.ut_type == USER_PROCESS) X#else X if (*ubuf.ut_name) X#endif X ++numusers; X fclose(fp); X if (numusers > MAXUSERS) X return (FALSE); X } X return (TRUE); X} X#endif !EOR! echo extracting - monsters sed 's/^X//' > monsters << '!EOR!' Xa Water Leaper 12 14 16 24 59 0 0 62 Xa Leech 4 19 29 30 66 0 0 73 Xan Urisk 13 30 15 46 127 1 0 3 XShellycoat 28 21 18 63 226 2 0 0 Xa Naiad 21 62 27 58 378 2 0 11 Xa Nixie 22 58 28 108 604 3 0 6 Xa Glaistig 21 106 25 127 1002 3 0 0 Xa Mermaid 18 116 22 108 809 3 0 0 Xa Merman 24 115 23 109 808 4 0 0 Xa Siren 22 128 31 89 915 4 0 24 Xa Lamprey 14 67 33 156 1562 4 15 37 Xa Kopoacinth 26 36 26 206 2006 5 0 20 Xa Kelpie 61 25 24 223 4025 5 0 0 Xan Aspidchelone 114 104 19 898 10041 7 0 2 Xan Idiot 13 14 16 28 49 0 0 0 Xsome Green Slime 1 5 45 100 57 0 0 26 Xa Pixie 11 29 23 26 64 0 0 32 Xa Serpent 10 18 25 25 79 0 0 10 Xa Cluricaun 12 27 20 30 81 0 14 5 Xan Imp 22 30 14 40 92 0 0 1 Xa Centipede 3 8 18 15 33 0 0 61 Xa Beetle 2 11 21 26 44 0 0 48 Xa Fir Darrig 18 22 17 35 107 0 14 1 XModnar 15 23 20 40 101 7 2 12 Xa Gnome 7 45 26 23 111 0 0 21 Xa Sprite 9 37 25 31 132 1 0 43 Xa Mimic 11 55 29 47 213 1 3 2 Xa Kobold 13 10 14 21 121 1 12 68 Xa Spider 6 11 28 28 124 1 0 57 Xan Uldra 14 37 21 32 93 1 0 6 Xa Gnoll 20 25 15 40 166 1 0 61 Xa Bogie 23 28 19 57 189 1 0 57 Xa Fachan 9 40 15 45 139 1 14 10 Xa Moron 3 1 10 10 28 0 0 100 Xan Orc 25 13 16 26 141 1 0 92 Xa Ghillie Dhu 12 16 13 28 104 2 14 2 Xa Bogle 19 15 16 35 157 2 14 15 Xa Shrieker 2 62 27 9 213 2 16 0 Xa Carrion Crawler 12 20 20 65 142 2 0 42 Xa Trow 15 17 23 51 136 2 0 36 Xa Warg 20 10 17 45 152 2 0 88 Xa Stirge 2 6 35 25 153 2 0 95 Xa Crebain 5 11 31 31 82 2 0 81 Xa Killmoulis 30 19 8 75 175 3 14 22 Xa Hob-goblin 35 20 15 72 246 3 0 18 Xa Unicorn 27 57 27 57 627 3 1 0 Xa Fenoderee 16 6 21 65 222 3 0 42 Xan Ogre 42 14 16 115 409 3 0 19 Xa Dodo 62 12 11 76 563 3 0 3 Xa Hydra 14 27 33 99 599 3 0 27 Xa Hamadryad 23 47 26 62 426 3 0 12 Xa Bwca 21 17 19 55 387 3 14 1 Xan Owlbear 35 16 18 100 623 4 0 22 XBlack Annis 37 52 15 65 786 4 0 2 Xa Jello Blob 100 25 7 264 1257 4 0 13 Xa Jubjub Bird 45 23 12 114 1191 4 0 0 Xa Wichtlein 13 40 25 61 800 4 0 8 Xa Cocodrill 39 28 24 206 1438 4 0 38 Xa Troll 75 12 20 185 1013 4 24 29 Xa Bonnacon 89 26 9 255 1661 4 17 14 Xa Gargoyle 22 21 29 200 1753 5 0 7 Xa Chaladrius 8 49 37 172 1929 5 0 20 Xa Gwyllion 27 73 20 65 1888 5 0 4 Xa Cinomulgus 23 2 10 199 263 5 0 18 Xa Peridexion 26 32 24 98 1300 5 0 2 XSmeagol 41 33 27 373 2487 5 18 0 Xa Wraith 52 102 22 200 3112 5 25 13 Xa Snotgurgle 143 19 26 525 4752 6 0 3 Xa Phooka 42 63 21 300 4125 5 0 12 Xa Vortex 101 30 31 500 6992 6 9 4 XShelob 147 64 28 628 5003 7 13 0 Xa Thaumaturgist 35 200 23 400 7628 6 7 0 XSmaug 251 76 26 1022 9877 7 0 0 Xa Cold-drake 301 102 24 1222 10888 7 0 0 Xa Red Dragon 342 141 23 1299 11649 8 0 0 XScatha the Worm 406 208 20 1790 11999 8 0 0 XTiamat 506 381 29 2000 13001 9 11 0 Xa Bandersnatch 105 98 22 450 7981 6 0 3 Xa Harpy 103 49 24 263 7582 6 0 2 Xa Tigris 182 38 17 809 7777 6 0 3 Xa Gryphon 201 45 19 813 8888 7 0 1 Xa Coblynau 205 46 18 585 8333 6 0 2 Xa Chimaera 173 109 28 947 12006 7 0 0 Xa Jack-in-Irons 222 36 12 1000 9119 7 0 0 XSaruman 55 373 17 1500 17101 11 6 0 Xa Balrog 500 100 25 705 8103 7 8 0 XArgus 201 87 14 1500 10010 8 0 0 Xa Titan 302 1483 12 1625 11011 8 0 0 XCacus 256 43 19 1750 12012 8 0 0 XBegion 403 154 10 1875 13013 8 0 0 XGrendel 197 262 23 2000 14014 8 0 0 Xa Nazgul 250 251 26 1011 9988 12 10 9 Xa Succubus 186 1049 27 2007 19984 9 19 0 XRed Cap 143 50 35 1965 23456 9 0 0 Xa Nuckelavee 300 75 20 2185 11111 8 0 0 XCerberus 236 96 29 2600 25862 9 20 0 Xa Jabberwock 185 136 25 2265 23256 9 22 0 XUngoliant 399 2398 37 2784 27849 10 21 0 XLeanan-Sidhe 486 5432 46 3000 30004 9 5 0 Xthe Dark Lord 9999 9999 31 19999 30005 13 4 0 !EOR! echo extracting - pathdefs.c sed 's/^X//' > pathdefs.c << '!EOR!' X/* X * pathdefs.c X * X * Edit these values to put things in different places. X */ X X#include "phant.h" X Xchar monsterfile[] = PATH/monsters", X peoplefile[] = PATH/characs", X gameprog[] = PATH/phantasia", X messfile[] = PATH/mess", X lastdead[] = PATH/lastdead", X helpfile[] = PATH/phant.help", X motd[] = PATH/motd", X goldfile[] = PATH/gold", X voidfile[] = PATH/void", X#ifdef ENEMY X enemyfile[] = PATH/enemy", X#endif X sbfile[] = PATH/scoreboard"; !EOR! echo extracting - setup.c sed 's/^X//' > setup.c << '!EOR!' X/* X * setup.c Program to set up all files for Phantasia X * X * This program tries to verify the parameters specified in X * the Makefile. Since Phantasia assumes its files exist, X * simple errors can result in core dumps. X * X * This program tries to check against this. X * X * Note that this is not fool-proof, and that this could X * be much more clever in checking everything. X * Hopefully, someone will enhance this someday. X */ X X#include "phant.h" X#include <sys/types.h> X#include <sys/stat.h> X Xmain(argc,argv) /* program to init. files for Phantasia */ Xint argc; Xchar **argv; X{ XFILE *fp; Xstruct stats sbuf; Xstruct nrgvoid grail; Xstruct stat fbuf; Xregister int loop; Xchar stbuf[128]; Xlong ltmp; X X srand((int) time(NULL)); /* prime random numbers */ X /* try to check RAND definition */ X for (loop = 1000; loop; loop--) X { X ltmp = rand(); X if (ltmp > ((long) RAND)) X { X sprintf(stbuf,"%.1f",(double) RAND); X Error("%s is a bad value for RAND.\n",stbuf); X } X } X umask(077); X /* check where Phantasia lives */ X if (stat(PATH",&fbuf) < 0) X { X perror(PATH"); X exit(1); X /*NOTREACHED*/ X } X if (fbuf.st_mode & S_IFDIR == 0) X Error("%s is not a directory.\n",PATH"); X /* try to create data files */ X if ((fp = fopen(goldfile,"w")) == NULL) X Error("cannot create %s.\n",goldfile); X else X fclose(fp); X if ((fp = fopen(motd,"w")) == NULL) X Error("cannot create %s.\n",motd); X else X fclose(fp); X if ((fp = fopen(messfile,"w")) == NULL) X Error("cannot create %s.\n",messfile); X else X fclose(fp); X /* do not reset character file if it already exists */ X if (stat(peoplefile,&fbuf) < 0) X { X buildchar(&sbuf); X strcpy(sbuf.name,"<null>"); X if ((fp = fopen(peoplefile,"w")) == NULL) X Error("cannot create %s.\n",peoplefile); X else X { X fwrite(&sbuf,sizeof(sbuf),1,fp); X fclose(fp); X } X } X grail.active = TRUE; X grail.x = roll(-1.0e6,2.0e6); X grail.y = roll(-1.0e6,2.0e6); X if ((fp = fopen(voidfile,"w")) == NULL) X Error("cannot create %s.\n",voidfile); X else X { X fwrite(&grail,sizeof(grail),1,fp); X fclose(fp); X } X if ((fp = fopen(lastdead,"w")) == NULL) X Error("cannot create %s.\n",lastdead); X else X { X fputs(" ",fp); X fclose(fp); X } X#ifdef ENEMY X if ((fp = fopen(enemyfile,"w")) == NULL) X Error("cannot create %s.\n",enemyfile); X else X fclose(fp); X#endif X if ((fp = fopen(sbfile,"w")) == NULL) X Error("cannot create %s.\n",sbfile); X else X fclose(fp); X if (getuid() != UID) X fprintf(stderr,"Warning: UID (%d) is not equal to current uid.\n",UID); X exit(0); X} X Xbuildchar(stat) /* put in some default values */ X/* Note that this function is almost the same as initchar(). X It is used to insure that unexpected values will not be found in a X new character file. */ Xstruct stats *stat; X{ X stat->x = roll(-125,251); X stat->y = roll(-125,251); X stat->exp = stat->lvl = stat->sin = 0; X stat->crn = stat->psn = 0; X stat->rng.type = NONE; X stat->rng.duration = 0; X stat->pal = FALSE; X stat->hw = stat->amu = stat->bls = 0; X stat->chm = 0; X stat->gem = 0.1; X stat->gld = roll(25,50) + roll(0,25) + 0.1; X stat->quks = stat->swd = stat->shd = 0; X stat->vrg = FALSE; X stat->typ = 0; X} X XError(str,file) /* print an error message, and exit */ Xchar *str, *file; X{ X fprintf(stderr,"Error: "); X fprintf(stderr,str,file); X exit(1); X /*NOTREACHED*/ X} !EOR!