u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # bill.c # changes.txt # create.c # data.c # This archive created: Sat Aug 30 14:43:16 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'bill.c'" '(6254 characters)' if test -f 'bill.c' then echo shar: will not over-write existing file "'bill.c'" else cat << \SHAR_EOF > 'bill.c' #include "header.h" /* bill.c "Larn is copyrighted 1986 by Noah Morgan. */ static char mail600[40]; /* * function to create the tax bill for the user */ static int pid; static letter1() { sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid); /* prepare path */ if (lcreat(mail600) < 0) { write(1, "can't write 600 letter\n", 23); return(0); } lprcat("\n\n\n\n\n\n\n\n\n\n\n\n"); standout("From:"); lprcat(" the LRS(Larn Revenue Service)\n"); standout("\nSubject:"); lprcat(" undeclared income\n"); lprcat("\n We heard you survived the caverns of Larn. Let me be the"); lprcat("\nfirst to congratulate you on your success. It is quite a feat."); lprcat("\nIt must also have been very profitable for you."); lprcat("\n\n The Dungeon Master has informed us that you brought"); lprintf("\n%d gold pieces back with you from your journey. As the",(long) c[GOLD]); lprcat("\ncounty of Larn is in dire need of funds, we have spared no time"); lprintf("\nin preparing your tax bill. You owe %d gold pieces as", (long) c[GOLD] * TAXRATE); lprcat("\nof this notice, and is due within 5 days. Failure to pay will"); lprcat("\nmean penalties. Once again, congratulations, We look forward"); lprcat("\nto your future successful expeditions.\n"); lwclose(); return(1); } static letter2() { sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */ if (lcreat(mail600) < 0) { write(1, "can't write 601 letter\n", 23); return(0); } lprcat("\n\n\n\n\n\n\n\n\n\n\n\n"); standout("From:"); lprcat(" His Majesty King Wilfred of Larndom\n"); standout("\nSubject:"); lprcat(" a noble deed\n"); lprcat("\n I have heard of your magnificent feat, and I, King Wilfred,"); lprcat("\nforthwith declare today to be a national holiday. Furthermore,"); lprcat("\nhence three days, Ye be invited to the castle to receive the"); lprcat("\nhonour of Knight of the realm. Upon thy name shall it be written. . ."); lprcat("\nBravery and courage be yours."); lprcat("\nMay you live in happiness forevermore . . .\n"); lwclose(); return(1); } static letter3() { sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */ if (lcreat(mail600) < 0) { write(1, "can't write 602 letter\n", 23); return(0); } lprcat("\n\n\n\n\n\n\n\n\n\n\n\n"); standout("From:"); lprcat(" Count Endelford\n"); standout("\nSubject:"); lprcat(" You Bastard!\n"); lprcat("\n I heard(from sources) of your journey. Congratulations!"); lprcat("\nYou Bastard! With several attempts I have yet to endure the"); lprcat(" caves,\nand you, a nobody, makes the journey! From this time"); lprcat(" onward, bewarned\nupon our meeting you shall pay the price!\n"); lwclose(); return(1); } static letter4() { sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */ if (lcreat(mail600) < 0) { write(1, "can't write 603 letter\n", 23); return(0); } lprcat("\n\n\n\n\n\n\n\n\n\n\n\n"); standout("From:"); lprcat(" Mainair, Duke of Larnty\n"); standout("\nSubject:"); lprcat(" High Praise\n"); lprcat("\n With a certainty a hero I declare to be amongst us! A nod of"); lprcat("\nfavour I send to thee. Me thinks Count Endelford this day of"); lprcat("\nright breath'eth fire as of dragon of whom ye are slayer. I"); lprcat("\nyearn to behold his anger and jealously. Should ye choose to"); lprcat("\nunleash some of thy wealth upon those who be unfortunate, I,"); lprcat("\nDuke Mainair, Shall equal thy gift also.\n"); lwclose(); return(1); } static letter5() { sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */ if (lcreat(mail600) < 0) { write(1, "can't write 604 letter\n", 23); return(0); } lprcat("\n\n\n\n\n\n\n\n\n\n\n\n"); standout("From:"); lprcat(" St. Mary's Children's Home\n"); standout("\nSubject:"); lprcat(" these poor children\n"); lprcat("\n News of your great conquests has spread to all of Larndom."); lprcat("\nMight I have a moment of a great man's time. We here at St."); lprcat("\nMary's Children's Home are very poor, and many children are"); lprcat("\nstarving. Disease is widespread and very often fatal without"); lprcat("\ngood food. Could you possibly find it in your heart to help us"); lprcat("\nin our plight? Whatever you could give will help much."); lprcat("\n(your gift is tax deductible)\n"); lwclose(); return(1); } static letter6() { sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */ if (lcreat(mail600) < 0) { write(1, "can't write 605 letter\n", 23); return(0); } lprcat("\n\n\n\n\n\n\n\n\n\n\n\n"); standout("From:"); lprcat(" The National Cancer Society of Larn\n"); standout("\nSubject:"); lprcat(" hope\n"); lprcat("\nCongratulations on your successful expedition. We are sure much"); lprcat("\ncourage and determination were needed on your quest. There are"); lprcat("\nmany though, that could never hope to undertake such a journey"); lprcat("\ndue to an enfeebling disease -- cancer. We at the National"); lprcat("\nCancer Society of Larn wish to appeal to your philanthropy in"); lprcat("\norder to save many good people -- possibly even yourself a few"); lprcat("\nyears from now. Much work needs to be done in researching this"); lprcat("\ndreaded disease, and you can help today. Could you please see it"); lprcat("\nin your heart to give generously? Your continued good health"); lprcat("\ncan be your everlasting reward.\n"); lwclose(); return(1); } /* * function to mail the letters to the player if a winner */ static int (*pfn[])() = { letter1, letter2, letter3, letter4, letter5, letter6 }; mailbill() { register int i; char buf[128]; pid = getpid(); resetscroll(); for (i = 0; i < sizeof(pfn) / sizeof(int (*)()); i++) if ((*pfn[i])()) { sleep(10); sprintf(buf, "MAIL /SUBJECT=LARN %s %s",mail600,loginname); system(buf); delete(mail600); } exit(); } SHAR_EOF if test 6254 -ne "`wc -c < 'bill.c'`" then echo shar: error transmitting "'bill.c'" '(should have been 6254 characters)' fi fi # end of overwriting check echo shar: extracting "'changes.txt'" '(11826 characters)' if test -f 'changes.txt' then echo shar: will not over-write existing file "'changes.txt'" else cat << \SHAR_EOF > 'changes.txt' This is a list of the fixes/enhancements made to larn V11.0 in Version 12.0. (Version numbers consist of 2 parts: ver.subver. When the save file format changes, ver must be bumped. This is why the next release of Larn is 12.0 and not 11.1. This is used in the savefile routines to check for out-of-date save files). This list was mainly meant to be a record of what changed, for my own sanity. It's included for your benefit (Warning: SPOILER!): 0. lprintf() in fileio.c (now called io.c) has been changed to use varargs so that its variable number of arguments usage is now portable. Pyramids primarily had this problem. 1. Panic handler was added to signal.c. This routine catches fatal errors like segmentation faults, bus errors, illegal instructions, etc., and trys to performs a savegame() before dumping core. This helps prevent the loss of a good game due to a game malfunction. Also, the name of the signal received is printed, instead of just its number. 2. The version number of the program is now selectable from the Makefile. see the symbols VER and SUBVER. 3. When at an altar, pray and donate 3000000000 gp. and ye used to receive a whopping amount of gold due to a wraparound problem with the signed ints. This has been fixed by using unsigned longs when asking for money amounts. 4. It was possible that when compiled with work hours checking, checkpointing enabled, and having "play-day-play" in the LARN12.OPT file a segmentation fault would occur at its first attempt to do a checkpoint. This was due to an improperly declared savefilename array in tok.c. This has been fixed. 5. on level H, casting a missile weapon (mle cld ssp bal lit) off the edge of the level would mess up the display, as it didn't know when to stop. This is needless to say, fixed. Absolute bounds are now in effect for missile type spells, see godirect() in monster.c. 6. The create monster routine will now create monsters in random positions around the player. Before, the 1st one would always be created to the upper left. 7. If you vpr or lit at a throne, it would summon a gnome king that you would have to deal with. However, as each throne has only one king with it, successive vpr's should not create more gnome kings. Presently, successive vpr's will create more kings. This has been fixed. 8. The mechanism to manage spheres of annihilation has been reworked to provide a cleaner design and to eliminate some possible problems. 9. The spell gen (genocide monsters) has been implemented. 10. When dropping a ring of strength and having been weakened to STR=3 the player might end up with a negative strength. Strength is now stored in 2 variables, real strength, and strength bonuses. Only real strength can now be weakened down to a minimum of 3, so unless you have a ring of strength -3 or less, strengths below 3 should not occur. 11. larn -h will now print out a list of all available command line options. 12. larn -o<optsfile> now lets you specify a LARN12.OPT file on the command line. This was necessary as part of the solution to number 14 below. 13. The "savefile:" statement has been aded to the LARN12.OPT format to allow specifying the savefilename (full path) for the savegame operation. This too was needed as part of # 14 below. 14. A player id facility has been added to larn. The complaint was that the game used the userid to order the scoreboard, thus only one scoreboard entry was allowed for each userid. If the compile time symbol UIDSCORE is defined at compilation time (see Makefile), this will still be true. However, if this define is omitted, the game will create and manage a file called ".playerids" where names are taken from the specified LARN12.OPT file (now a command line option) and assigned a unique playerid. playerid's will now be used to govern scoreboard entry posting. This feature makes it easy for one person to have many characters, each appearing on the scoreboard. Be kind to your fellow players! The philosophy of one score per player gives more players the opportunity to bask in glory for all to see! 15. It is no longer required that the player be WIZID to create the scoreboard or to examine the logfile. Anyone with the correct wizard's password can now use these command line options (password is only needed to create/clear the scoreboard). If you want to prevent players from zeroing the scoreboard, change the wizard's password. (in config.c) By the way, wizards may be alot of fun, but they are prevented from being placed on any scoreboard. (for clarification) 16. Monsters now have intelligence, that is some of them. This determines if the monster moves using the previously stupid movement method, or by using the new IMM (intelligent monster movement) algorithm. With IMM, monsters will move around corners, avoid pits, traps, etc. With increasing levels of difficulty, more monsters will be using IMM. Beware of IMM when aggravated! Those little beasties can really find you! 17. Added the scroll of life protection. 18. Larn now consults the file ".holiday" to check for holidays if the TIMECHECK option (no playing during working hours) is enabled. Before, larn knew nothing about holidays. It should now let people play if it is a holiday. The format for a .holiday entry is: "mmm dd yyyy comments . . .". 19. In nap() and napms() it is possible that with nap(0) or napms(0) there would be an infinite loop and the game would hang. The case of nap(0) is now looked for. 20. The granularity of gold piles has been increased. iarg[] has been changed from char's to short's, so instead of 255 x 10^n granularity we now have 32767 x 10^n granularity. This also means more than 255000 gp can be dropped in one place. Not realistic, but it prevents a worthless annoyance. Who said games were supposed to be realistic? 21. Termcap capability has been added to larn. If the symbol VT100 is defined in the makefile, the game will be compiled to use only VT100 compatible terminals (Much more efficient). If the symbol VT100 is omitted, the game will be compiled to use the termcap entry for whatever terminal you are using. This involves an extra layer of output interpretation, as every byte sent to the terminal must be inspected for control tokens. Only 3 termcap entries need be found for the game to be functional: CM (cursor movement), CE (clear to end of line), and CL (clear screen). For a better display, the following are optional: AL (insert line), DL (delete line), SO (Standout begin), SE (Standout end), and CD (clear to end of screen). The .larn.help file was left as is, with VT100 escape sequences in it. If the termcap version of larn reads it, it is translated for the desired terminal type. The .mail60* files have been removed, and their text is now included in bill.c so it can be used with any terminal. Note: If compiled for termcap, and using a VT100, the display will act a little different. This is because the VT100 does not have insert line/ delete line codes, and the scrolling region must be simulated with vertical wraparound instead of scrolling. Thanks goes to Michiel Huisjes for the original termcap patch. 22. When playing as wizard, if you go down stairs on 10 or V3, or up stairs on H, 1, or V1, etc. you would be placed in a phantom zone where the display was really weird ([-1] subscripting), and would eventually lead to a segmentation fault. Stairs and volcano shafts now check for the level they are being used on. 23. In response to some sites having only unsigned chars (flame the manufacturer), the chars that were used to store positive and negative numbers have been changed to shorts. This includes diroffx[], diroffy[], iarg[][][], ivenarg[], and some others. I believe the changes are correct, but I have none of these machines to try it out on. (Volunteers?) 24. The function fullhit(n) in monster.c was supposed to return the damage done by n full hits on a monster. It only returned the damage for ONE hit, thus severely limiting the usefulness of the web and sle spells. 25. Someone said that they were getting segmentation faults when they were reading scrolls as the wizard. I couldn't find the problem, which may have had something to do with the signed char problem mentioned above. However, I've added a check in read_scroll() and quaff_potion() to trap any scroll or potion types that are not in the game. 26. "vt125" has been added to the acceptable terminal list (checked only if compiled with -DVT100). 27. In savegame() and restoregame(), there was a 6 hardwired into the i/o statements which assumed the size of struct cel was 6. On some machines this caused the rightmost part of each level to not be saved in a savefile. These 6's have been replaced with sizeof(struct cel), and should now be portable. 28. The option "no-beep" has been added to the LARN12.OPT file. When specified, beeping is inhibited at the terminal. 29. When becoming wizard, no longer to you wear the ring of protection, and null scrolls and potions are no longer created. 30. Many spelling errors have been fixed, both in player messages, and in the code itself. A thanks goes to Mars Gralia who sent me a detailed list of the mistakes. 31. When a player wins a game, if getlogin() fails, a segmentation fault will result, because the NULL returned from getlogin() is used as a pointer. This call has been replaced (now using loginname already determined). Also, the mail creation upon winning has been rewritten, mainly to allow termcapping of the text. 32. The Larn Revenue Service will now always appear on level H. Before, it was only created if the player had outstanding taxes. In that multiple save files per player are now more possible, this was seen as incorrect. 33. Input buffer flushing is now in effect. If the input char queue exceeds 5 bytes, the excess is discarded. Also, if the player hits or gets hit all input bytes are flushed (within 1). This relieves the situation where many moves have been typed ahead of the display and the player keeps getting hit while the queue of moves is processed. 34. When a savefile has been altered, a warning message is displayed to the effect that you've cheated, and you will not be placed on the normal scoreboard. If you then save the game, and start 'er up again, memory of the cheating was lost. This has been fixed, by letting the scoreboard routines consult the cheating flag. Also, the I node number of the savefile is written into the savefile, so cp'ing, etc., will avail the cheater not. If high security is needed, the game should be run suid. This suid mode has not been made the default because most installations do not want to install it that way. 35. The sources have been run through lint, and most of lint's complaints have been taken care of. An attempt was made to adjust the code for 16 bit int machines. Many casts to long have been put in. I don't know if it will run on a 16 bitter, but it should be closer to that end. 36. When larn starts up, if it can't find the scoreboard, it will now make a blank one instead of complaining that there is no scoreboard. It is not necessary to do "larn -c" to initially create the scoreboard. 37. When listing out the logfile (larn -l), the error message "error reading from input file" has been fixed. Also, the date & time of a player's demise is now included in the logfile. 38. When casting web or sle into a mirror, the game will no longer bash the player. Instead, the player will either fall asleep or get stuck in his web. 39. Items like cookies, books, chests, swords of slashing, and Bessmann's flailing hammer can now be sold at the trading post. SHAR_EOF if test 11826 -ne "`wc -c < 'changes.txt'`" then echo shar: error transmitting "'changes.txt'" '(should have been 11826 characters)' fi fi # end of overwriting check echo shar: extracting "'create.c'" '(14156 characters)' if test -f 'create.c' then echo shar: will not over-write existing file "'create.c'" else cat << \SHAR_EOF > 'create.c' /* create.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* makeplayer() subroutine to create the player and the players attributes this is called at the beginning of a game and at no other time */ makeplayer() { register int i; scbr(); clear(); c[HPMAX] = c[HP] = 10; /* start player off with 10 hit points */ c[LEVEL] = 1; /* player starts at level one */ c[SPELLMAX] = c[SPELLS] = 1; /* total # spells starts off as 1 */ c[REGENCOUNTER] = 16; c[ECOUNTER] = 96; /* start regeneration correctly */ c[SHIELD] = c[WEAR] = c[WIELD] = -1; for (i = 0; i < 26; i++) iven[i] = 0; spelknow[0] = spelknow[1] = 1; /* he knows protection, magic missile */ if (c[HARDGAME] <= 0) { iven[0] = OLEATHER; iven[1] = ODAGGER; ivenarg[1] = ivenarg[0] = c[WEAR] = 0; c[WIELD] = 1; } playerx = rnd(MAXX - 2); playery = rnd(MAXY - 2); oldx = 0; oldy = 25; gtime = 0; /* time clock starts at zero */ cbak[SPELLS] = -50; for (i = 0; i < 6; i++) c[i] = 12; /* make the attributes, ie str, int, etc. */ recalc(); } /* newcavelevel(level) int level; function to enter a new level. This routine must be called anytime the player changes levels. If that level is unknown it will be created. A new set of monsters will be created for a new level, and existing levels will get a few more monsters. Note that it is here we remove genocided monsters from the present level. */ newcavelevel(x) register int x; { register int i,j; if (beenhere[level]) savelevel(); /* put the level back into storage */ level = x; /* get the new level and put in working storage */ if (beenhere[x] == 0) for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) know[j][i] = mitem[j][i] = 0; else { getlevel(); sethp(0); goto chgn; } makemaze(x); makeobject(x); beenhere[x] = 1; sethp(1); #if WIZID if (wizard || x == 0) #else if (x == 0) #endif for (j = 0; j < MAXY; j++) for (i = 0; i < MAXX; i++) know[i][j] = 1; chgn: checkgen(); /* wipe out any genocided monsters */ } /* makemaze(level) int level; subroutine to make the caverns for a given level. only walls are made. */ static int mx,mxl,mxh,my,myl,myh,tmp2; makemaze(k) int k; { register int i,j,tmp; int z; if (k > 1 &&(rnd(17) <= 4 || k == MAXLEVEL - 1 || k == MAXLEVEL + MAXVLEVEL - 1)) { if (cannedlevel(k)); return; /* read maze from data file */ } if (k == 0) tmp = 0; else tmp = OWALL; for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) item[j][i] = tmp; if (k == 0) return; eat(1, 1); if (k == 1) item[33][MAXY - 1] = 0; /* exit from dungeon */ /* now for open spaces -- not on level 10 */ if (k != MAXLEVEL - 1) { tmp2 = rnd(3) + 3; for (tmp = 0; tmp < tmp2; tmp++) { my = rnd(11) + 2; myl = my - rnd(2); myh = my + rnd(2); if (k < MAXLEVEL) { mx = rnd(44) + 5; mxl = mx - rnd(4); mxh = mx + rnd(12) + 3; z = 0; } else { mx = rnd(60) + 3; mxl = mx - rnd(2); mxh = mx + rnd(2); z = makemonst(k); } for (i = mxl; i < mxh; i++) for (j = myl; j < myh; j++) { item[i][j] = 0; if ((mitem[i][j] = z)) hitp[i][j] = monster[z].hitpoints; } } } if (k != MAXLEVEL - 1) { my = rnd(MAXY - 2); for (i = 1; i < MAXX - 1; i++) item[i][my] = 0; } if (k > 1) treasureroom(k); } /* function to eat away a filled in maze */ eat(xx, yy) register int xx,yy; { register int dir,try; dir = rnd(4); try = 2; while (try) { switch(dir) { case 1: if (xx <= 2) break; /* west */ if ((item[xx - 1][yy] != OWALL) ||(item[xx - 2][yy] != OWALL)) break; item[xx - 1][yy] = item[xx - 2][yy] = 0; eat(xx - 2, yy); break; case 2: if (xx >= MAXX - 3) break; /* east */ if ((item[xx + 1][yy] != OWALL) ||(item[xx + 2][yy] != OWALL)) break; item[xx + 1][yy] = item[xx + 2][yy] = 0; eat(xx + 2, yy); break; case 3: if (yy <= 2) break; /* south */ if ((item[xx][yy - 1] != OWALL) ||(item[xx][yy - 2] != OWALL)) break; item[xx][yy - 1] = item[xx][yy - 2] = 0; eat(xx, yy - 2); break; case 4: if (yy >= MAXY - 3) break; /* north */ if ((item[xx][yy + 1] != OWALL) ||(item[xx][yy + 2] != OWALL)) break; item[xx][yy + 1] = item[xx][yy + 2] = 0; eat(xx, yy + 2); break; }; if (++dir > 4) { dir = 1; --try; } } } /* * function to read in a maze from a data file * * Format of maze data file: 1st character = # of mazes in file(ascii digit) * For each maze: 18 lines(1st 17 used) 67 characters per line * * Special characters in maze data file: * * # wall D door . random monster * ~ eye of larn ! cure dianthroritis * - random object */ cannedlevel(k) int k; { char *row,*lgetl(); register int i,j; int it,arg,mit,marg; if (lopen(larnlevels) < 0) { write(1, "Can't open the maze data file\n", 30); died(-282); return(0); } i = lgetc(); if (i <= '0') { died(-282); return(0); } for (i = 18 * rund(i - '0'); i > 0; i--) lgetl(); /* advance to desired maze */ for (i = 0; i < MAXY; i++) { row = lgetl(); for (j = 0; j < MAXX; j++) { it = mit = arg = marg = 0; switch(*row++) { case '#': it = OWALL; break; case 'D': it = OCLOSEDDOOR; arg = rnd(30); break; case '~': if (k != MAXLEVEL - 1) break; it = OLARNEYE; mit = rund(8) + DEMONLORD; marg = monster[mit].hitpoints; break; case '!': if (k != MAXLEVEL + MAXVLEVEL - 1) break; it = OPOTION; arg = 21; mit = DEMONLORD + 7; marg = monster[mit].hitpoints; break; case '.': if (k < MAXLEVEL) break; mit = makemonst(k + 1); marg = monster[mit].hitpoints; break; case '-': it = newobject(k + 1, &arg); break; }; item[j][i] = it; iarg[j][i] = arg; mitem[j][i] = mit; hitp[j][i] = marg; #if WIZID know[j][i] = (wizard) ? 1 : 0; #else know[j][i] = 0; #endif } } lrclose(); return(1); } /* function to make a treasure room on a level level 10's treasure room has the eye in it and demon lords level V3 has potion of cure dianthroritis and demon prince */ treasureroom(lv) register int lv; { register int tx,ty,xsize,ysize; for (tx = 1 + rnd(10); tx < MAXX - 10; tx += 10) if ((lv == MAXLEVEL - 1) ||(lv == MAXLEVEL + MAXVLEVEL - 1) || rnd(13) == 2) { xsize = rnd(6) + 3; ysize = rnd(3) + 3; ty = rnd(MAXY - 9) + 1;/* upper left corner of room */ if (lv == MAXLEVEL - 1 || lv == MAXLEVEL + MAXVLEVEL - 1) troom(lv, xsize, ysize, tx = tx + rnd(MAXX - 24), ty, rnd(3) + 6); else troom(lv, xsize, ysize, tx, ty, rnd(9)); } } /* * subroutine to create a treasure room of any size at a given location * room is filled with objects and monsters * the coordinate given is that of the upper left corner of the room */ troom(lv, xsize, ysize, tx, ty, glyph) int lv,xsize,ysize,tx,ty,glyph; { register int i,j; int tp1,tp2; for (j = ty - 1; j <= ty + ysize; j++) for (i = tx - 1; i <= tx + xsize; i++)/* clear out space for room */ item[i][j] = 0; for (j = ty; j < ty + ysize; j++) for (i = tx; i < tx + xsize; i++) {/* now put in the walls */ item[i][j] = OWALL; mitem[i][j] = 0; } for (j = ty + 1; j < ty + ysize - 1; j++) for (i = tx + 1; i < tx + xsize - 1; i++)/* now clear out interior */ item[i][j] = 0; switch(rnd(2)) { /* locate the door on the treasure room */ case 1: item[i = tx + rund(xsize)][j = ty +(ysize - 1) * rund(2)] = OCLOSEDDOOR; iarg[i][j] = glyph; /* on horizontal walls */ break; case 2: item[i = tx +(xsize - 1) * rund(2)][j = ty + rund(ysize)] = OCLOSEDDOOR; iarg[i][j] = glyph; /* on vertical walls */ break; }; tp1 = playerx; tp2 = playery; playery = ty +(ysize >> 1); if (c[HARDGAME] < 2) for (playerx = tx + 1; playerx <= tx + xsize - 2; playerx += 2) for (i = 0, j = rnd(6); i <= j; i++) { something(lv + 2); createmonster(makemonst(lv + 1)); } else for (playerx = tx + 1; playerx <= tx + xsize - 2; playerx += 2) for (i = 0, j = rnd(4); i <= j; i++) { something(lv + 2); createmonster(makemonst(lv + 3)); } playerx = tp1; playery = tp2; } /* *********** MAKE_OBJECT *********** subroutine to create the objects in the maze for the given level */ makeobject(j) register int j; { register int i; if (j == 0) { fillroom(OENTRANCE, 0); /* entrance to dungeon */ fillroom(ODNDSTORE, 0); /* the DND STORE */ fillroom(OSCHOOL, 0); /* college of Larn */ fillroom(OBANK, 0); /* 1st national bank of larn */ fillroom(OVOLDOWN, 0); /* volcano shaft to temple */ fillroom(OHOME, 0); /* the players home & family */ fillroom(OTRADEPOST, 0);/* the trading post */ fillroom(OLRS, 0); /* the larn revenue service */ return; } if (j == MAXLEVEL) fillroom(OVOLUP, 0); /* volcano shaft up from the temple */ /* make the fixed objects in the maze STAIRS */ if ((j > 0) &&(j != MAXLEVEL - 1) &&(j != MAXLEVEL + MAXVLEVEL - 1)) fillroom(OSTAIRSDOWN, 0); if ((j > 1) &&(j != MAXLEVEL)) fillroom(OSTAIRSUP, 0); /* make the random objects in the maze */ fillmroom(rund(3), OBOOK, j); fillmroom(rund(3), OALTAR, 0); fillmroom(rund(3), OSTATUE, 0); fillmroom(rund(3), OPIT, 0); fillmroom(rund(3), OFOUNTAIN, 0); fillmroom(rnd(3) - 2, OIVTELETRAP, 0); fillmroom(rund(2), OTHRONE, 0); fillmroom(rund(2), OMIRROR, 0); fillmroom(rund(2), OTRAPARROWIV, 0); fillmroom(rnd(3) - 2, OIVDARTRAP, 0); fillmroom(rund(3), OCOOKIE, 0); if (j == 1) fillmroom(1, OCHEST, j); else fillmroom(rund(2), OCHEST, j); if ((j != MAXLEVEL - 1) &&(j != MAXLEVEL + MAXVLEVEL - 1)) fillmroom(rund(2), OIVTRAPDOOR, 0); if (j <= 10) { fillmroom((rund(2)), ODIAMOND, rnd(10 * j + 1) + 10); fillmroom(rund(2), ORUBY, rnd(6 * j + 1) + 6); fillmroom(rund(2), OEMERALD, rnd(4 * j + 1) + 4); fillmroom(rund(2), OSAPPHIRE, rnd(3 * j + 1) + 2); } for (i = 0; i < rnd(4) + 3; i++) fillroom(OPOTION, newpotion()); /* make a POTION */ for (i = 0; i < rnd(5) + 3; i++) fillroom(OSCROLL, newscroll()); /* make a SCROLL */ for (i = 0; i < rnd(12) + 11; i++) fillroom(OGOLDPILE, 12 * rnd(j + 1) +(j << 3) + 10); /* make GOLD */ if (j == 5) fillroom(OBANK2, 0); /* branch office of the bank */ froom(2, ORING, 0); /* a ring mail */ froom(1, OSTUDLEATHER, 0); /* a studded leather */ froom(3, OSPLINT, 0); /* a splint mail */ froom(5, OSHIELD, rund(3));/* a shield */ froom(2, OBATTLEAXE, rund(3));/* a battle axe */ froom(5, OLONGSWORD, rund(3));/* a long sword */ froom(5, OFLAIL, rund(3));/* a flail */ froom(4, OREGENRING, rund(3));/* ring of regeneration */ froom(1, OPROTRING, rund(3));/* ring of protection */ froom(2, OSTRRING, 4); /* ring of strength + 4 */ froom(7, OSPEAR, rnd(5)); /* a spear */ froom(3, OORBOFDRAGON, 0); /* orb of dragon slaying */ froom(4, OSPIRITSCARAB, 0);/* scarab of negate spirit */ froom(4, OCUBEofUNDEAD, 0);/* cube of undead control */ froom(2, ORINGOFEXTRA, 0); /* ring of extra regen */ froom(3, ONOTHEFT, 0); /* device of antitheft */ froom(2, OSWORDofSLASHING, 0);/* sword of slashing */ if (c[BESSMANN] == 0) { froom(4, OHAMMER, 0); /* Bessman's flailing hammer */ c[BESSMANN] = 1; } if (c[HARDGAME] < 3 ||(rnd(4) == 3)) { if (j > 3) { froom(3, OSWORD, 3);/* sunsword + 3 */ froom(5, O2SWORD, rnd(4));/* a two handed sword */ froom(3, OBELT, 4);/* belt of striking */ froom(3, OENERGYRING, 3);/* energy ring */ froom(4, OPLATE, 5);/* platemail + 5 */ } } } /* subroutine to fill in a number of objects of the same kind */ fillmroom(n, what, arg) int n,arg; char what; { register int i; for (i = 0; i < n; i++) fillroom(what, arg); } froom(n, itm, arg) int n,arg; char itm; { if (rnd(151) < n) fillroom(itm, arg); } /* * subroutine to put an object into an empty room * uses a random walk */ static fillroom(what, arg) int arg; char what; { register int x,y; #ifdef EXTRA c[FILLROOM]++; #endif x = rnd(MAXX - 2); y = rnd(MAXY - 2); while (item[x][y]) { #ifdef EXTRA c[RANDOMWALK]++; /* count up these random walks */ #endif x += rnd(3) - 2; y += rnd(3) - 2; if (x > MAXX - 2) x = 1; if (x < 1) x = MAXX - 2; if (y > MAXY - 2) y = 1; if (y < 1) y = MAXY - 2; } item[x][y] = what; iarg[x][y] = arg; } /* subroutine to put monsters into an empty room without walls or other monsters */ fillmonst(what) char what; { register int x,y,trys; for (trys = 5; trys > 0; --trys) { /* max # of creation attempts */ x = rnd(MAXX - 2); y = rnd(MAXY - 2); if ((item[x][y] == 0) &&(mitem[x][y] == 0) &&((playerx != x) ||(playery != y))) { mitem[x][y] = what; know[x][y] = 0; hitp[x][y] = monster[what].hitpoints; return(0); } } return(-1); /* creation failure */ } /* creates an entire set of monsters for a level must be done when entering a new level if sethp(1) then wipe out old monsters else leave them there */ sethp(flg) int flg; { register int i,j; if (flg) for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) stealth[j][i] = 0; if (level == 0) { c[TELEFLAG] = 0; return; } /* if teleported and found level 1 then know level we are on */ if (flg) j = rnd(12) + 2 +(level >> 1); else j =(level >> 1) + 1; for (i = 0; i < j; i++) fillmonst(makemonst(level)); positionplayer(); } /* * Function to destroy all genocided monsters on the present level */ checkgen() { register int x,y; for (y = 0; y < MAXY; y++) for (x = 0; x < MAXX; x++) if (monster[mitem[x][y]].genocided) mitem[x][y] = 0; /* no more monster */ } SHAR_EOF if test 14156 -ne "`wc -c < 'create.c'`" then echo shar: error transmitting "'create.c'" '(should have been 14156 characters)' fi fi # end of overwriting check echo shar: extracting "'data.c'" '(31933 characters)' if test -f 'data.c' then echo shar: will not over-write existing file "'data.c'" else cat << \SHAR_EOF > 'data.c' /* data.c Larn is copyrighted 1986 by Noah Morgan. */ #define NODEFS #include "header.h" /* class[c[LEVEL]-1] gives the correct name of the players experience level */ static char aa1[] = " mighty evil master"; static char aa2[] = "apprentice demi-god"; static char aa3[] = " minor demi-god "; static char aa4[] = " major demi-god "; static char aa5[] = " minor deity "; static char aa6[] = " major deity "; static char aa7[] = " novice guardian "; static char aa8[] = "apprentice guardian"; static char aa9[] = " The Creator "; globaldef char *class[]= { " novice explorer ", "apprentice explorer", " practiced explorer",/* -3*/ " expert explorer ", " novice adventurer", " adventurer ",/* -6*/ "apprentice conjurer", " conjurer ", " master conjurer ",/* -9*/ " apprentice mage ", " mage ", " experienced mage ",/* -12*/ " master mage ", " apprentice warlord", " novice warlord ",/* -15*/ " expert warlord ", " master warlord ", " apprentice gorgon ",/* -18*/ " gorgon ", " practiced gorgon ", " master gorgon ",/* -21*/ " demi-gorgon ", " evil master ", " great evil master ",/* -24*/ aa1 , aa1 , aa1 ,/* -27*/ aa1 , aa1 , aa1 ,/* -30*/ aa1 , aa1 , aa1 ,/* -33*/ aa1 , aa1 , aa1 ,/* -36*/ aa1 , aa1 , aa1 ,/* -39*/ aa2 , aa2 , aa2 ,/* -42*/ aa2 , aa2 , aa2 ,/* -45*/ aa2 , aa2 , aa2 ,/* -48*/ aa3 , aa3 , aa3 ,/* -51*/ aa3 , aa3 , aa3 ,/* -54*/ aa3 , aa3 , aa3 ,/* -57*/ aa4 , aa4 , aa4 ,/* -60*/ aa4 , aa4 , aa4 ,/* -63*/ aa4 , aa4 , aa4 ,/* -66*/ aa5 , aa5 , aa5 ,/* -69*/ aa5 , aa5 , aa5 ,/* -72*/ aa5 , aa5 , aa5 ,/* -75*/ aa6 , aa6 , aa6 ,/* -78*/ aa6 , aa6 , aa6 ,/* -81*/ aa6 , aa6 , aa6 ,/* -84*/ aa7 , aa7 , aa7 ,/* -87*/ aa8 , aa8 , aa8 ,/* -90*/ aa8 , aa8 , aa8 ,/* -93*/ " earth guardian ", " air guardian ", " fire guardian ",/* -96*/ " water guardian ", " time guardian ", " ethereal guardian ",/* -99*/ aa9 , aa9 , aa9 ,/* -102*/ }; /* table of experience needed to be a certain level of player skill[c[LEVEL]] is the experience required to attain the next level */ #define MEG 1000000 globaldef long skill[] = { 0, 10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120, /* 1-11 */ 10240, 20480, 40960, 100000, 200000, 400000, 700000, 1*MEG, /* 12-19 */ 2*MEG,3*MEG,4*MEG,5*MEG,6*MEG,8*MEG,10*MEG, /* 20-26 */ 12*MEG,14*MEG,16*MEG,18*MEG,20*MEG,22*MEG,24*MEG,26*MEG,28*MEG, /* 27-35 */ 30*MEG,32*MEG,34*MEG,36*MEG,38*MEG,40*MEG,42*MEG,44*MEG,46*MEG, /* 36-44 */ 48*MEG,50*MEG,52*MEG,54*MEG,56*MEG,58*MEG,60*MEG,62*MEG,64*MEG, /* 45-53 */ 66*MEG,68*MEG,70*MEG,72*MEG,74*MEG,76*MEG,78*MEG,80*MEG,82*MEG, /* 54-62 */ 84*MEG,86*MEG,88*MEG,90*MEG,92*MEG,94*MEG,96*MEG,98*MEG,100*MEG, /* 63-71 */ 105*MEG,110*MEG,115*MEG,120*MEG, 125*MEG, 130*MEG, 135*MEG, 140*MEG, /* 72-79 */ 145*MEG,150*MEG,155*MEG,160*MEG, 165*MEG, 170*MEG, 175*MEG, 180*MEG, /* 80-87 */ 185*MEG,190*MEG,195*MEG,200*MEG, 210*MEG, 220*MEG, 230*MEG, 240*MEG, /* 88-95 */ 250*MEG,260*MEG,270*MEG,280*MEG, 290*MEG, 300*MEG /* 96-101*/ }; #undef MEG globaldef char *lpbuf,*lpnt,*inbuffer,*lpend; /* input/output pointers to the buffers */ globaldef struct cel cell[(MAXLEVEL+MAXVLEVEL) * MAXX * MAXY]; /* dungeon storage */ globaldef short hitp[MAXX][MAXY]; /* monster hp on level */ globaldef short iarg[MAXX][MAXY]; /* arg for the item array */ globaldef char item[MAXX][MAXY]; /* objects in maze if any */ globaldef char know[MAXX][MAXY]; /* 1 or 0 if here before */ globaldef char mitem[MAXX][MAXY]; /* monster item array */ globaldef char moved[MAXX][MAXY]; /* monster movement flags */ globaldef char stealth[MAXX][MAXY]; /* 0=sleeping 1=awake monst */ globaldef char iven[26]; /* inventory for player */ globaldef short ivenarg[26]; /* inventory for player */ globaldef char lastmonst[40]; /* this has the name of the current monster */ globaldef char beenhere[MAXLEVEL+MAXVLEVEL]; /* 1 if have been on this level */ globaldef char VERSION=VER; /* this is the present version # of the program */ globaldef char SUBVERSION=SUBVER; globaldef char nosignal=0; /* set to 1 to disable the signals from doing anything */ globaldef char predostuff=0; /* 2 means that the trap handling routines must do a showplayer() after a trap. 0 means don't showplayer() 0 - we are in create player screen 1 - we are in welcome screen 2 - we are in the normal game */ globaldef char loginname[20]; /* players login name */ globaldef char logname[LOGNAMESIZE]; /* players name storage for scoring */ globaldef char sex=1; /* default is a man 0=woman */ globaldef char boldon=1; /* 1=bold objects 0=inverse objects */ globaldef char ckpflag=0; /* 1 if want checkpointing of game, 0 otherwise */ globaldef char cheat=0; /* 1 if the player has fudged save file */ globaldef char level=0; /* cavelevel player is on = c[CAVELEVEL] */ globaldef char wizard=0; /* the wizard mode flag */ globaldef short lastnum=0; /* the number of the monster last hitting player */ globaldef short hitflag=0; /* flag for if player has been hit when running */ globaldef short hit2flag=0; /* flag for if player has been hit when running */ globaldef short hit3flag=0; /* flag for if player has been hit flush input */ globaldef short playerx,playery; /* the room on the present level of the player */ globaldef short lastpx,lastpy; /* 0 --- MAXX-1 or 0 --- MAXY-1 */ globaldef short oldx,oldy; globaldef short lasthx=0,lasthy=0; /* location of monster last hit by player */ globaldef short nobeep=0; /* true if program is not to beep */ globaldef unsigned long rand_x=33601; /* the random number seed */ globaldef long initialtime=0; /* time playing began */ globaldef long gtime=0; /* the clock for the game */ globaldef long outstanding_taxes=0; /* present tax bill from score file */ globaldef long c[100],cbak[100]; /* the character description arrays */ globaldef int enable_scroll=0; /* constant for enabled/disabled scrolling regn */ globaldef char *aborted = " aborted"; globaldef struct sphere *spheres=0; /*pointer to linked list for spheres of annihilation*/ globaldef char *levelname[]= { " H"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10","V1","V2","V3" }; globaldef char objnamelist[]=" ATOP%^F&^+M=%^$$f*OD#~][[)))(((||||||||{?!BC}o:@.<<<<EVV))([[]]](^ [H*** ^^ S tsTLc............................................"; globaldef char monstnamelist[]=" BGHJKOScjtAELNQRZabhiCTYdegmvzFWflorXV pqsyUkMwDDPxnDDuD ..............................................................."; globaldef char *objectname[]= { 0,"a holy altar","a handsome jewel encrusted throne","the orb","a pit", "a staircase leading upwards","an elevator going up","a bubbling fountain", "a great marble statue","a teleport trap","the college of Larn", "a mirror","the DND store","a staircase going down","an elevator going down", "the bank of Larn","the 5th branch of the Bank of Larn", "a dead fountain","gold","an open door","a closed door", "a wall","The Eye of Larn","plate mail","chain mail","leather armor", "a sword of slashing","Bessman's flailing hammer","a sunsword", "a two handed sword","a spear","a dagger", "ring of extra regeneration","a ring of regeneration","a ring of protection", "an energy ring","a ring of dexterity","a ring of strength", "a ring of cleverness","a ring of increase damage","a belt of striking", "a magic scroll","a magic potion","a book","a chest", "an amulet of invisibility","an orb of dragon slaying", "a scarab of negate spirit","a cube of undead control", "device of theft prevention","a brilliant diamond","a ruby", "an enchanting emerald","a sparkling sapphire","the dungeon entrance", "a volcanic shaft leaning downward","the base of a volcanic shaft", "a battle axe","a longsword","a flail","ring mail","studded leather armor", "splint mail","plate armor","stainless plate armor","a lance of death", "an arrow trap","an arrow trap","a shield","your home", "gold","gold","gold","a dart trap", "a dart trap","a trapdoor","a trapdoor","the local trading post", "a teleport trap", "a massive throne", "a sphere of annihilation","a handsome jewel encrusted throne", "the Larn Revenue Service","a fortune cookie","","","","","","", "","","","","","","","","","","","","","","","","","","","" }; /* * for the monster data * * array to do rnd() to create monsters <= a given level */ globaldef char monstlevel[] = { 5, 11, 17, 22, 27, 33, 39, 42, 46, 50, 53, 56, 59 }; globaldef struct monst monster[] = { /* NAME LV AC DAM ATT DEF GEN INT GOLD HP EXP ------------------------------------------------------------------------------------------------- */ { "", 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }, { "bat", 1, 0, 1, 0, 0, 0, 3, 0, 1, 1 }, { "gnome", 1, 10, 1, 0, 0, 0, 8, 30, 2, 2 }, { "hobgoblin", 1, 14, 2, 0, 0, 0, 5, 25, 3, 2 }, { "jackal", 1, 17, 1, 0, 0, 0, 4, 0, 1, 1 }, { "kobold", 1, 20, 1, 0, 0, 0, 7, 10, 1, 1 }, { "orc", 2, 12, 1, 0, 0, 0, 9, 40, 4, 2 }, { "snake", 2, 15, 1, 0, 0, 0, 3, 0, 3, 1 }, { "giant centipede", 2, 14, 0, 4, 0, 0, 3, 0, 1, 2 }, { "jaculi", 2, 20, 1, 0, 0, 0, 3, 0, 2, 1 }, { "troglodyte", 2, 10, 2, 0, 0, 0, 5, 80, 4, 3 }, { "giant ant", 2, 8, 1, 4, 0, 0, 4, 0, 5, 5 }, /* NAME LV AC DAM ATT DEF GEN INT GOLD HP EXP ------------------------------------------------------------------------------------------------- */ { "floating eye", 3, 8, 1, 0, 0, 0, 3, 0, 5, 2 }, { "leprechaun", 3, 3, 0, 8, 0, 0, 3,1500, 13, 45 }, { "nymph", 3, 3, 0, 14, 0, 0, 9, 0, 18, 45 }, { "quasit", 3, 5, 3, 0, 0, 0, 3, 0, 10, 15 }, { "rust monster", 3, 4, 0, 1, 0, 0, 3, 0, 18, 25 }, { "zombie", 3, 12, 2, 0, 0, 0, 3, 0, 6, 7 }, { "assassin bug", 4, 9, 3, 0, 0, 0, 3, 0, 20, 15 }, { "bugbear", 4, 5, 4, 15, 0, 0, 5, 40, 20, 35 }, { "hell hound", 4, 5, 2, 2, 0, 0, 6, 0, 16, 35 }, { "ice lizard", 4, 11, 2, 10, 0, 0, 6, 50, 16, 25 }, { "centaur", 4, 6, 4, 0, 0, 0, 10, 40, 24, 45 }, /* NAME LV AC DAM ATT DEF GEN INT GOLD HP EXP ------------------------------------------------------------------------------------------------- */ { "troll", 5, 4, 5, 0, 0, 0, 9, 80, 50, 300 }, { "yeti", 5, 6, 4, 0, 0, 0, 5, 50, 35, 100 }, { "white dragon", 5, 2, 4, 5, 0, 0, 16, 500, 55, 1000}, { "elf", 5, 8, 1, 0, 0, 0, 15, 50, 22, 35 }, { "gelatinous cube", 5, 9, 1, 0, 0, 0, 3, 0, 22, 45 }, { "metamorph", 6, 7, 3, 0, 0, 0, 3, 0, 30, 40 }, { "vortex", 6, 4, 3, 0, 0, 0, 3, 0, 30, 55 }, { "ziller", 6, 15, 3, 0, 0, 0, 3, 0, 30, 35 }, { "violet fungi", 6, 12, 3, 0, 0, 0, 3, 0, 38, 100 }, { "wraith", 6, 3, 1, 6, 0, 0, 3, 0, 30, 325 }, { "forvalaka", 6, 2, 5, 0, 0, 0, 7, 0, 50, 280 }, /* NAME LV AC DAM ATT DEF GEN INT GOLD HP EXP ------------------------------------------------------------------------------------------------- */ { "lama nobe", 7, 7, 3, 0, 0, 0, 6, 0, 35, 80 }, { "osequip", 7, 4, 3, 16, 0, 0, 4, 0, 35, 100 }, { "rothe", 7, 15, 5, 0, 0, 0, 3, 100, 50, 250 }, { "xorn", 7, 0, 6, 0, 0, 0, 13, 0, 60, 300 }, { "vampire", 7, 3, 4, 6, 0, 0, 17, 0, 50, 1000}, { "invisible stalker", 7, 3, 6, 0, 0, 0, 5, 0, 50, 350 }, { "poltergeist", 8, 1, 4, 0, 0, 0, 3, 0, 50, 450 }, { "disenchantress", 8, 3, 0, 9, 0, 0, 3, 0, 50, 500 }, { "shambling mound", 8, 2, 5, 0, 0, 0, 6, 0, 45, 400 }, { "yellow mold", 8, 12, 4, 0, 0, 0, 3, 0, 35, 250 }, { "umber hulk", 8, 3, 7, 11, 0, 0, 14, 0, 65, 600 }, /* NAME LV AC DAM ATT DEF GEN INT GOLD HP EXP ------------------------------------------------------------------------------------------------- */ { "gnome king", 9, -1, 10, 0, 0, 0, 18, 2000, 100, 3000 }, { "mimic", 9, 5, 6, 0, 0, 0, 8, 0, 55, 99 }, { "water lord", 9, -10, 15, 7, 0, 0, 20, 0, 150, 15000 }, { "bronze dragon", 9, 2, 9, 3, 0, 0, 16, 300, 80, 4000 }, { "green dragon", 9, 3, 8, 10, 0, 0, 15, 200, 70, 2500 }, { "purple worm", 9, -1, 11, 0, 0, 0, 3, 100, 120, 15000 }, { "xvart", 9, -2, 12, 0, 0, 0, 13, 0, 90, 1000 }, { "spirit naga", 10, -20, 12, 12, 0, 0, 23, 0, 95, 20000 }, { "silver dragon", 10, -1, 12, 3, 0, 0, 20, 700, 100, 10000 }, { "platinum dragon", 10, -5, 15, 13, 0, 0, 22, 1000, 130, 24000 }, { "green urchin", 10, -3, 12, 0, 0, 0, 3, 0, 85, 5000 }, { "red dragon", 10, -2, 13, 3, 0, 0, 19, 800, 110, 14000 }, { "type I demon lord", 12, -30, 18, 0, 0, 0, 20, 0, 140, 50000 }, { "type II demon lord", 13, -30, 18, 0, 0, 0, 21, 0, 160, 75000 }, { "type III demon lord",14, -30, 18, 0, 0, 0, 22, 0, 180, 100000 }, { "type IV demon lord", 15, -35, 20, 0, 0, 0, 23, 0, 200, 125000 }, { "type V demon lord", 16, -40, 22, 0, 0, 0, 24, 0, 220, 150000 }, { "type VI demon lord", 17, -45, 24, 0, 0, 0, 25, 0, 240, 175000 }, { "type VII demon lord",18, -70, 27, 6, 0, 0, 26, 0, 260, 200000 }, { "demon prince", 25, -127, 30, 6, 0, 0, 28, 0, 345, 300000 } /* NAME LV AC DAM ATT DEF GEN INT GOLD HP EXP ------------------------------------------------------------------------------------------------- */ }; /* name array for scrolls */ globaldef char *scrollname[] = { "\0enchant armor", "\0enchant weapon", "\0enlightenment", "\0blank paper", "\0create monster", "\0create artifact", "\0aggravate monsters", "\0time warp", "\0teleportation", "\0expanded awareness", "\0haste monsters", "\0monster healing", "\0spirit protection", "\0undead protection", "\0stealth", "\0magic mapping", "\0hold monsters", "\0gem perfection", "\0spell extension", "\0identify", "\0remove curse", "\0annihilation", "\0pulverization", "\0life protection", "\0 ", "\0 ", "\0 ", "\0 " }; /* name array for magic potions */ globaldef char *potionname[] = { "\0sleep", "\0healing", "\0raise level", "\0increase ability", "\0wisdom", "\0strength", "\0raise charisma", "\0dizziness", "\0learning", "\0gold detection", "\0monster detection", "\0forgetfulness", "\0water", "\0blindness", "\0confusion", "\0heroism", "\0sturdiness", "\0giant strength", "\0fire resistance", "\0treasure finding", "\0instant healing", " cure dianthroritis", "\0poison", "\0see invisible", "\0 ", "\0 ", "\0 ", "\0 ", "\0 ", "\0 ", "\0 ", "\0 ", "\0 ", "\0 ", "\0 " }; /* spell data */ globaldef char spelknow[SPNUM] = 0; globaldef char splev[] = { 1, 4, 9, 14, 18, 22, 26, 29, 32, 35, 37, 37, 37, 37, 37 }; globaldef char *spelcode[]={ "pro", "mle", "dex", "sle", "chm", "ssp", "web", "str", "enl", "hel", "cbl", "cre", "pha", "inv", "bal", "cld", "ply", "can", "has", "ckl", "vpr", "dry", "lit", "drl", "glo", "flo", "fgr", "sca", "hld", "stp", "tel", "mfi", /* 31 */ "sph", "gen", "sum", "wtw", "alt", "per" }; globaldef char *spelname[]={ "protection", "magic missile", "dexterity", "sleep", "charm monster", "sonic spear", "web", "strength", "enlightenment", "healing", "cure blindness", "create monster", "phantasmal forces", "invisibility", "fireball", "cold", "polymorph", "cancellation", "haste self", "cloud kill", "vaporize rock", "dehydration", "lightning", "drain life", "invulnerability", "flood", "finger of death", "scare monster", "hold monster", "time stop", "teleport away", "magic fire", "sphere of annihilation", "genocide", "summon demon", "walk through walls", "alter reality", "permanence", "" }; globaldef char *speldescript[]={ /* 1 */ "generates a +2 protection field", "creates and hurls a magic missile equivalent to a + 1 magic arrow", "adds +2 to the casters dexterity", "causes some monsters to go to sleep", "some monsters may be awed at your magnificence", "causes your hands to emit a screeching sound toward what they point", /* 7 */ "causes strands of sticky thread to entangle an enemy", "adds +2 to the casters strength for a short term", "the caster becomes aware of things around him", "restores some hp to the caster", "restores sight to one so unfortunate as to be blinded", "creates a monster near the caster appropriate for the location", "creates illusions, and if believed, monsters die", "the caster becomes invisible", /* 15 */ "makes a ball of fire that burns on what it hits", "sends forth a cone of cold which freezes what it touches", "you can find out what this does for yourself", "negates the ability of a monster to use his special abilities", "speeds up the casters movements", "creates a fog of poisonous gas which kills all that is within it", "this changes rock to air", /* 22 */ "dries up water in the immediate vicinity", "you finger will emit a lightning bolt when this spell is cast", "subtracts hit points from both you and a monster", "this globe helps to protect the player from physical attack", "this creates an avalanche of H2O to flood the immediate chamber", "this is a holy spell and calls upon your god to back you up", /* 28 */ "terrifies the monster so that hopefully he wont hit the magic user", "the monster is frozen in his tracks if this is successful", "all movement in the caverns ceases for a limited duration", "moves a particular monster around in the dungeon (hopefully away from you)", "this causes a curtain of fire to appear all around you", /* 33 */ "anything caught in this sphere is instantly killed. Warning -- dangerous", "eliminates a species of monster from the game -- use sparingly", "summons a demon who hopefully helps you out", "allows the player to walk through walls for a short period of time", "god only knows what this will do", "makes a character spell permanent, i. e. protection, strength, etc.", "" }; globaldef char spelweird[MAXMONST+8][SPNUM] = { /* p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t m s g s w a p */ /* r l e l h s e t n e b r h n a l l a a k p r i r l l g c l t e f p e u t l e */ /* o e x e m p b r l l l e a v l d y n s l r y t l o o r a d p l i h n m w t r */ /* bat */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* gnome */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* hobgoblin */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* jackal */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* kobold */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* orc */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 4,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* snake */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /*giant centipede */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* jaculi */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* troglodyte */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* giant ant */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* floating eye */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* leprechaun */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* nymph */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* quasit */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* rust monster */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 4,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* zombie */ { 0,0,0,8,0,4, 0,0,0,0,0,0,0,0, 0,0,0,0,0,4,0, 4,0,0,0,0,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* assassin bug */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* bugbear */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* hell hound */ { 0,6,0,0,0,0, 12,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* ice lizard */ { 0,0,0,0,0,0, 11,0,0,0,0,0,0,0, 0,15,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* centaur */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* troll */ { 0,7,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 4,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* yeti */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,15,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* white dragon */ { 0,0,0,0,0,0, 0,0,0,0,0,0,14,0, 0,15,0,0,0,0,0, 4,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* elf */ { 0,0,0,0,0,0, 0,0,0,0,0,0,14,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /*gelatinous cube */ { 0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 0,0,0,0,0,4,0, 0,0,0,0,0,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* metamorph */ { 0,13,0,0,0,0, 2,0,0,0,0,0,0,0, 0,0,0,0,0,4,0, 4,0,0,0,0,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* vortex */ { 0,13,0,0,0,10, 1,0,0,0,0,0,0,0, 0,0,0,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* ziller */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* violet fungi */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* wraith */ { 0,0,0,8,0,4, 0,0,0,0,0,0,0,0, 0,0,0,0,0,4,0, 4,0,0,0,0,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* forvalaka */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* lama nobe */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* osequip */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* rothe */ { 0,7,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* xorn */ { 0,7,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 4,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* vampire */ { 0,0,0,8,0,4, 0,0,0,0,0,0,0,0, 0,0,0,0,0,4,0, 0,0,0,0,0,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /*invisible staker*/ { 0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* poltergeist */ { 0,13,0,8,0,4, 1,0,0,0,0,0,0,0, 0,4,0,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* disenchantress */ { 0,0,0,8,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /*shambling mound */ { 0,0,0,0,0,10, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* yellow mold */ { 0,0,0,8,0,0, 1,0,0,0,0,0,4,0, 0,0,0,0,0,4,0, 0,0,0,0,0,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* umber hulk */ { 0,7,0,0,0,0, 0,0,0,0,0,0,0,5, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* gnome king */ { 0,7,0,0,3,0, 0,0,0,0,0,0,0,5, 0,0,9,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* mimic */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* water lord */ { 0,13,0,8,3,4, 1,0,0,0,0,0,0,0, 0,0,9,0,0,4,0, 0,0,0,0,16,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* bronze dragon */ { 0,7,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* green dragon */ { 0,7,0,0,0,0, 11,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* purple worm */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* xvart */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* spirit naga */ { 0,13,0,8,3,4, 1,0,0,0,0,0,0,5, 0,4,9,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 0,0,0,0,0,0 }, /* silver dragon */ { 0,6,0,9,0,0, 12,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /*platinum dragon */ { 0,7,0,9,0,0, 11,0,0,0,0,0,14,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* green urchin */ { 0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* red dragon */ { 0,6,0,0,0,0, 12,0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,0 }, /* p m d s c s w s e h c c p i b c p c h c v d l d g f f s h s t m s g s w a p */ /* r l e l h s e t n e b r h n a l l a a k p r i r l l g c l t e f p e u t l e */ /* o e x e m p b r l l l e a v l d y n s l r y t l o o r a d p l i h n m w t r */ /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon lord */ { 0,7,0,4,3,0, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 0,0,0,0,0, 9,0,0,0,0,0 }, /* demon prince */ { 0,7,0,4,3,9, 1,0,0,0,0,0,14,5, 0,0,4,0,0,4,0, 4,0,0,0,4,4, 4,0,0,0,4, 9,0,0,0,0,0 } }; globaldef char *spelmes[] = { "", /* 1 */ "the web had no effect on the %s", /* 2 */ "the %s changed shape to avoid the web", /* 3 */ "the %s isn't afraid of you", /* 4 */ "the %s isn't affected", /* 5 */ "the %s can see you with his infravision", /* 6 */ "the %s vaporizes your missile", /* 7 */ "your missile bounces off the %s", /* 8 */ "the %s doesn't sleep", /* 9 */ "the %s resists", /* 10 */ "the %s can't hear the noise", /* 11 */ "the %s's tail cuts it free of the web", /* 12 */ "the %s burns through the web", /* 13 */ "your missiles pass right through the %s", /* 14 */ "the %s sees through your illusions", /* 15 */ "the %s loves the cold!", /* 16 */ "the %s loves the water!" }; globaldef char to_lower[]= /* tolower[character] = lower case converted character */ { 0000,0001,0002,0003,0004,0005,0006,0007,0010,0011,0012,0013,0014,0015,0016,0017, /* NUL-SI*/ 0020,0021,0022,0023,0024,0025,0026,0027,0030,0031,0032,0033,0034,0035,0036,0037, /* DLE-US*/ 0040,0041,0042,0043,0044,0045,0046,0047,0050,0051,0052,0053,0054,0055,0056,0057, /* SP-/ */ 0060,0061,0062,0063,0064,0065,0066,0067,0070,0071,0072,0073,0074,0075,0076,0077, /* 0-? */ 0100,0141,0142,0143,0144,0145,0146,0147,0150,0151,0152,0153,0154,0155,0156,0157, /* @-O */ 0160,0161,0162,0163,0164,0165,0166,0167,0170,0171,0172,0133,0134,0135,0136,0137, /* P-_ */ 0140,0141,0142,0143,0144,0145,0146,0147,0150,0151,0152,0153,0154,0155,0156,0157, /* `-o */ 0160,0161,0162,0163,0164,0165,0166,0167,0170,0171,0172,0173,0174,0175,0176,0177, /* p-DEL */ }; globaldef char to_upper[]= /* toupper[character] = upper case converted character */ { 0000,0001,0002,0003,0004,0005,0006,0007,0010,0011,0012,0013,0014,0015,0016,0017, /* NUL-SI*/ 0020,0021,0022,0023,0024,0025,0026,0027,0030,0031,0032,0033,0034,0035,0036,0037, /* DLE-US*/ 0040,0041,0042,0043,0044,0045,0046,0047,0050,0051,0052,0053,0054,0055,0056,0057, /* SP-/ */ 0060,0061,0062,0063,0064,0065,0066,0067,0070,0071,0072,0073,0074,0075,0076,0077, /* 0-? */ 0100,0101,0102,0103,0104,0105,0106,0107,0110,0111,0112,0113,0114,0115,0116,0117, /* @-O */ 0120,0121,0122,0123,0124,0125,0126,0127,0130,0131,0132,0133,0134,0135,0136,0137, /* P-_ */ 0140,0101,0102,0103,0104,0105,0106,0107,0110,0111,0112,0113,0114,0115,0116,0117, /* `-o */ 0120,0121,0122,0123,0124,0125,0126,0127,0130,0131,0132,0173,0174,0175,0176,0177, /* p-DEL */ }; globaldef char is_digit[]= /* isdigit[character] = TRUE || FALSE */ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* NUL-SI*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DLE-US*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SP-/ */ 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 0-? */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* @-O */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* P-_ */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* `-o */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* p-DEL */ }; globaldef char is_alpha[]= /* isalpha[character] = TRUE || FALSE */ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* NUL-SI*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DLE-US*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SP-/ */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0-? */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* @-O */ 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, /* P-_ */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* `-o */ 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, /* p-DEL */ }; /* * function to create scroll numbers with appropriate probability of * occurrence * * 0 - armor 1 - weapon 2 - enlightenment 3 - paper * 4 - create monster 5 - create item 6 - aggravate 7 - time warp * 8 - teleportation 9 - expanded awareness 10 - haste monst * 11 - heal monster 12 - spirit protection 13 - undead protection * 14 - stealth 15 - magic mapping 16 - hold monster * 17 - gem perfection 18 - spell extension 19 - identify * 20 - remove curse 21 - annihilation 22 - pulverization * 23 - life protection */ globaldef char scprob[]= { 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 20, 20, 21, 22, 22, 22, 23 }; /* * function to return a potion number created with appropriate probability * of occurrence * * 0 - sleep 1 - healing 2 - raise level * 3 - increase ability 4 - gain wisdom 5 - gain strength * 6 - charismatic character 7 - dizziness 8 - learning * 9 - gold detection 10 - monster detection 11 - forgetfulness * 12 - water 13 - blindness 14 - confusion * 15 - heroism 16 - sturdiness 17 - giant strength * 18 - fire resistance 19 - treasure finding 20 - instant healing * 21 - cure dianthroritis 22 - poison 23 - see invisible */ globaldef char potprob[] = { 0, 0, 1, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 20, 22, 22, 23, 23 }; globaldef char nlpts[] = { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7 }; globaldef char nch[] = { 0, 0, 0, 1, 1, 1, 2, 2, 3, 4 }; globaldef char nplt[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 4 }; globaldef char ndgg[] = { 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5 }; globaldef char nsw[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3 }; SHAR_EOF if test 31933 -ne "`wc -c < 'data.c'`" then echo shar: error transmitting "'data.c'" '(should have been 31933 characters)' fi fi # end of overwriting check # End of shell archive exit 0
u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # diag.c # display.c # fortune.c # global.c # header.h # help.c # This archive created: Sat Aug 30 14:46:47 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'diag.c'" '(11426 characters)' if test -f 'diag.c' then echo shar: will not over-write existing file "'diag.c'" else cat << \SHAR_EOF > 'diag.c' /* diag.c Larn is copyrighted 1986 by Noah Morgan. */ #include <times.h> #include <stat.h> #include "header.h" extern int rmst,maxitm,lasttime; static struct tms cputime; /* *************************** DIAG -- dungeon diagnostics *************************** subroutine to print out data for debugging */ #ifdef EXTRA static int rndcount[16]; diag() { register int i,j; int hit,dam; cursors(); lwclose(); if (lcreat(diagfile) < 0) { /* open the diagnostic file */ lcreat((char *) 0); lprcat("\ndiagnostic failure\n"); return(-1); } write(1, "\nDiagnosing . . .\n", 18); lprcat("\n\nBeginning of DIAG diagnostics ----------\n"); /* for the character attributes */ lprintf("\n\nPlayer attributes:\n\nHit points: %2d(%2d)",(long) c[HP],(long) c[HPMAX]); lprintf("\ngold: %d Experience: %d Character level: %d Level in caverns: %d", (long) c[GOLD],(long) c[EXPERIENCE],(long) c[LEVEL],(long) level); lprintf("\nTotal types of monsters: %d",(long) MAXMONST + 8); lprcat("\f\nHere's the dungeon:\n\n"); i = level; for (j = 0; j < MAXLEVEL + MAXVLEVEL; j++) { newcavelevel(j); lprintf("\nMaze for level %s:\n", levelname[level]); diagdrawscreen(); } newcavelevel(i); lprcat("\f\nNow for the monster data:\n\n"); lprcat(" Monster Name LEV AC DAM ATT DEF GOLD HP EXP \n"); lprcat("--------------------------------------------------------------------------\n"); for (i = 0; i <= MAXMONST + 8; i++) { lprintf("%19s %2d %3d ", monster[i].name,(long) monster[i].level,(long) monster[i].armorclass); lprintf(" %3d %3d %3d ",(long) monster[i].damage,(long) monster[i].attack,(long) monster[i].defense); lprintf("%6d %3d %6d\n",(long) monster[i].gold,(long) monster[i].hitpoints,(long) monster[i].experience); } lprcat("\n\nHere's a Table for the to hit percentages\n"); lprcat("\n We will be assuming that players level = 2 * monster level"); lprcat("\n and that the players dexterity and strength are 16."); lprcat("\n to hit: if (rnd(22) <(2[monst AC] + your level + dex + WC/8 -1)/2) then hit"); lprcat("\n damage = rund(8) + WC/2 + STR - c[HARDGAME] - 4"); lprcat("\n to hit: if rnd(22) < to hit then player hits\n"); lprcat("\n Each entry is as follows: to hit / damage / number hits to kill\n"); lprcat("\n monster WC = 4 WC = 20 WC = 40"); lprcat("\n---------------------------------------------------------------"); for (i = 0; i <= MAXMONST + 8; i++) { hit = 2 * monster[i].armorclass + 2 * monster[i].level + 16; dam = 16 - c[HARDGAME]; lprintf("\n%20s %2d/%2d/%2d %2d/%2d/%2d %2d/%2d/%2d", monster[i].name, (long)(hit / 2),(long) max(0, dam + 2),(long)(monster[i].hitpoints /(dam + 2) + 1), (long)((hit + 2) / 2),(long) max(0, dam + 10),(long)(monster[i].hitpoints /(dam + 10) + 1), (long)((hit + 5) / 2),(long) max(0, dam + 20),(long)(monster[i].hitpoints /(dam + 20) + 1)); } lprcat("\n\nHere's the list of available potions:\n\n"); for (i = 0; i < MAXPOTION; i++) lprintf("%20s\n", &potionname[i][1]); lprcat("\n\nHere's the list of available scrolls:\n\n"); for (i = 0; i < MAXSCROLL; i++) lprintf("%20s\n", &scrollname[i][1]); lprcat("\n\nHere's the spell list:\n\n"); lprcat("spell name description\n"); lprcat("-------------------------------------------------------------------------------------------\n\n"); for (j = 0; j < SPNUM; j++) { lprc(' '); lprcat(spelcode[j]); lprintf(" %21s %s\n", spelname[j], speldescript[j]); } lprcat("\n\nFor the c[] array:\n"); for (j = 0; j < 100; j += 10) { lprintf("\nc[%2d] = ",(long) j); for (i = 0; i < 9; i++) lprintf("%5d ",(long) c[i + j]); } lprcat("\n\nTest of random number generator ----------------"); lprcat("\n for 25,000 calls divided into 16 slots\n\n"); for (i = 0; i < 16; i++) rndcount[i] = 0; for (i = 0; i < 25000; i++) rndcount[rund(16)]++; for (i = 0; i < 16; i++) { lprintf(" %5d",(long) rndcount[i]); if (i == 7) lprc('\n'); } lprcat("\n\n"); lwclose(); lcreat((char *) 0); lprcat("Done Diagnosing . . ."); return(0); } /* subroutine to count the number of occurrences of an object */ dcount(l) int l; { register int i,j,p; int k = 0; for (i = 0; i < MAXX; i++) for (j = 0; j < MAXY; j++) for (p = 0; p < MAXLEVEL; p++) if (cell[p * MAXX * MAXY + i * MAXY + j].item == l) k++; return(k); } /* subroutine to draw the whole screen as the player knows it */ diagdrawscreen() { register int i,j,k; for (i = 0; i < MAXY; i++) { /* for the east west walls of this line */ for (j = 0; j < MAXX; j++) if (k = mitem[j][i]) lprc(monstnamelist[k]); else lprc(objnamelist[item[j][i]]); lprc('\n'); } } #endif /* to save the game in a file */ static long int zzz = 0; savegame(fname) char *fname; { register int i,k; register struct sphere *sp; struct stat statbuf; nosignal = 1; lflush(); savelevel(); ointerest(); if (lcreat(fname) < 0) { lcreat((char *) 0); lprintf("\nCan't open file \"%s\" to save game\n", fname); nosignal = 0; return(-1); } set_score_output(); lwrite((char *) beenhere, MAXLEVEL + MAXVLEVEL); for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++) if (beenhere[k]) lwrite((char *) & cell[k * MAXX * MAXY], sizeof(struct cel) * MAXY * MAXX); times(&cputime); /* get cpu time */ c[CPUTIME] += (cputime.tms_utime + cputime.tms_stime - start_cpu) / 100; lwrite((char *) &c[0], 100 * sizeof(long)); lprint((long) gtime); lprc(level); lprc(playerx); lprc(playery); lwrite((char *) iven, 26); lwrite((char *) ivenarg, 26 * sizeof(short)); for (k = 0; k < MAXSCROLL; k++) lprc(scrollname[k][0]); for (k = 0; k < MAXPOTION; k++) lprc(potionname[k][0]); lwrite((char *) spelknow, SPNUM); lprc(wizard); lprc(rmst); /* random monster generation counter */ for (i = 0; i < 90; i++) lprc(itm[i].qty); lwrite((char *) course, 25); lprc(cheat); lprc(VERSION); for (i = 0; i < MAXMONST; i++) lprc(monster[i].genocided);/* genocide info */ for (sp = spheres; sp; sp = sp -> p) lwrite((char *) sp, sizeof(struct sphere));/* save spheres of annihilation */ time(&zzz); lprint((long)(zzz - initialtime)); lwrite((char *) & zzz, sizeof(long)); if (fstat(lfd, &statbuf) < 0) lprint(0L); else { lprint((long) statbuf.st_ino[0]); /* inode # */ lprint((long) statbuf.st_ino[1]); /* inode # */ lprint((long) statbuf.st_ino[2]); /* inode # */ } lwclose(); lastmonst[0] = 0; #ifndef VT100 setscroll(); #endif VT100 lcreat((char *) 0); nosignal = 0; return(0); } restoregame(fname) char *fname; { register int i,k; register struct sphere *sp,*sp2; struct stat filetimes; cursors(); lprcat("\nRestoring . . ."); lflush(); if (lopen(fname) <= 0) { lcreat((char *) 0); lprintf("\nCan't open file \"%s\" to restore game\n", fname); nap(2000); c[GOLD] = c[BANKACCOUNT] = 0; died(-265); return; } lrfill((char *) beenhere, MAXLEVEL + MAXVLEVEL); for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++) if (beenhere[k]) lrfill((char *) & cell[k * MAXX * MAXY], sizeof(struct cel) * MAXY * MAXX); lrfill((char *) & c[0], 100 * sizeof(long)); gtime = lrint(); level = c[CAVELEVEL] = lgetc(); playerx = lgetc(); playery = lgetc(); lrfill((char *) iven, 26); lrfill((char *) ivenarg, 26 * sizeof(short)); for (k = 0; k < MAXSCROLL; k++) scrollname[k][0] = lgetc(); for (k = 0; k < MAXPOTION; k++) potionname[k][0] = lgetc(); lrfill((char *) spelknow, SPNUM); wizard = lgetc(); rmst = lgetc(); /* random monster creation flag */ for (i = 0; i < 90; i++) itm[i].qty = lgetc(); lrfill((char *) course, 25); cheat = lgetc(); if (VERSION != lgetc()) { /* version number */ cheat = 1; lprcat("Sorry, But your save file is for an older version of larn\n"); nap(2000); c[GOLD] = c[BANKACCOUNT] = 0; died(-266); return; } for (i = 0; i < MAXMONST; i++) monster[i].genocided = lgetc();/* genocide info */ for (sp = 0, i = 0; i < c[SPHCAST]; i++) { sp2 = sp; sp =(struct sphere *) malloc(sizeof(struct sphere)); if (sp == 0) { write(2, "Can't malloc() for sphere space\n", 32); break; } lrfill((char *) sp, sizeof(struct sphere));/* get spheres of annihilation */ sp->p = 0; /* null out pointer */ if (i == 0) spheres = sp; /* beginning of list */ else sp2->p = sp; } time(&zzz); initialtime = zzz - lrint(); fstat(fd, &filetimes); /* get the creation and modification time of file */ lrfill((char *) & zzz, sizeof(long)); zzz += 6; if (filetimes.st_ctime > zzz) fsorry(); /* file create time */ else if (filetimes.st_mtime > zzz) fsorry(); /* file modify time */ if (c[HP] < 0) { died(284); return; } /* died a post mortem death */ oldx = oldy = 0; i = lrint(); /* inode # */ if (i &&(filetimes.st_ino[0] != i)) fsorry(); i = lrint(); /* inode # */ if (i &&(filetimes.st_ino[1] != i)) fsorry(); i = lrint(); /* inode # */ if (i &&(filetimes.st_ino[2] != i)) fsorry(); lrclose(); if (strcmp(fname, ckpfile) == 0) { if (lappend(fname) < 0) fcheat(); else { lprc(' '); lwclose(); } lcreat((char *) 0); } else if (delete(fname) < 0) fcheat(); /* can't unlink save file */ /* for the greedy cheater checker */ for (k = 0; k < 6; k++) if (c[k] > 99) greedy(); if (c[HPMAX] > 999 || c[SPELLMAX] > 125) greedy(); if (c[LEVEL] == 25 && c[EXPERIENCE] > skill[24]) {/* if patch up lev 25 player */ long tmp; tmp = c[EXPERIENCE] - skill[24];/* amount to go up */ c[EXPERIENCE] = skill[24]; raiseexperience((long) tmp); } getlevel(); lasttime = gtime; } /* subroutine to not allow greedy cheaters */ greedy() { #if WIZID if (wizard) return; #endif lprcat("\n\nI am so sorry, but your character is a little TOO good! Since this\n"); lprcat("cannot normally happen from an honest game, I must assume that you cheated.\n"); lprcat("In that you are GREEDY as well as a CHEATER, I cannot allow this game\n"); lprcat("to continue.\n"); nap(5000); c[GOLD] = c[BANKACCOUNT] = 0; died(-267); return; } /* subroutine to not allow altered save files and terminate the attempted restart */ fsorry() { lprcat("\nSorry, but your savefile has been altered.\n"); lprcat("However, seeing as I am a good sport, I will let you play.\n"); lprcat("Be advised though, you won't be placed on the normal scoreboard."); cheat = 1; nap(4000); } /* subroutine to not allow game if save file can't be deleted */ fcheat() { #if WIZID if (wizard) return; #endif lprcat("\nSorry, but your savefile can't be deleted. This can only mean\n"); lprcat("that you tried to CHEAT by protecting the directory the savefile\n"); lprcat("is in. Since this is unfair to the rest of the larn community, I\n"); lprcat("cannot let you play this game.\n"); nap(5000); c[GOLD] = c[BANKACCOUNT] = 0; died(-268); return; } SHAR_EOF if test 11426 -ne "`wc -c < 'diag.c'`" then echo shar: error transmitting "'diag.c'" '(should have been 11426 characters)' fi fi # end of overwriting check echo shar: extracting "'display.c'" '(13152 characters)' if test -f 'display.c' then echo shar: will not over-write existing file "'display.c'" else cat << \SHAR_EOF > 'display.c' /* display.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" #define makecode(_a,_b,_c)(((_a)<<16) +((_b)<<8) +(_c)) static int minx,maxx,miny,maxy,k,m; static char bot1f = 0,bot2f = 0,bot3f = 0; char always = 0; /* bottomline() now for the bottom line of the display */ bottomline() { recalc(); bot1f = 1; } bottomhp() { bot2f = 1; } bottomspell() { bot3f = 1; } bottomdo() { if (bot1f) { bot3f = bot1f = bot2f = 0; bot_linex(); return; } if (bot2f) { bot2f = 0; bot_hpx(); } if (bot3f) { bot3f = 0; bot_spellx(); } } bot_linex() { register int i; if (cbak[SPELLS] <= -50 ||(always)) { cursor(1, 18); if (c[SPELLMAX] > 99) lprintf("Spells:%3d(%3d)",(long) c[SPELLS],(long) c[SPELLMAX]); else lprintf("Spells:%3d(%2d) ",(long) c[SPELLS],(long) c[SPELLMAX]); lprintf(" AC: %-3d WC: %-3d Level",(long) c[AC],(long) c[WCLASS]); if (c[LEVEL] > 99) lprintf("%3d",(long) c[LEVEL]); else lprintf(" %-2d",(long) c[LEVEL]); lprintf(" Exp: %-9d %s\n",(long) c[EXPERIENCE], class[c[LEVEL] - 1]); lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ", (long) c[HP],(long) c[HPMAX],(long)(c[STRENGTH] + c[STREXTRA]),(long) c[INTELLIGENCE]); lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:", (long) c[WISDOM],(long) c[CONSTITUTION],(long) c[DEXTERITY],(long) c[CHARISMA]); if ((level == 0) ||(wizard)) c[TELEFLAG] = 0; if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]); lprintf(" Gold: %-6d",(long) c[GOLD]); always = 1; botside(); c[TMP] = c[STRENGTH] + c[STREXTRA]; for (i = 0; i < 100; i++) cbak[i] = c[i]; return; } botsub(makecode(SPELLS, 8, 18), "%3d"); if (c[SPELLMAX] > 99) botsub(makecode(SPELLMAX, 12, 18), "%3d)"); else botsub(makecode(SPELLMAX, 12, 18), "%2d) "); botsub(makecode(HP, 5, 19), "%3d"); botsub(makecode(HPMAX, 9, 19), "%3d"); botsub(makecode(AC, 21, 18), "%-3d"); botsub(makecode(WCLASS, 30, 18), "%-3d"); botsub(makecode(EXPERIENCE, 49, 18), "%-9d"); if (c[LEVEL] != cbak[LEVEL]) { cursor(59, 18); lprcat(class[c[LEVEL] - 1]); } if (c[LEVEL] > 99) botsub(makecode(LEVEL, 40, 18), "%3d"); else botsub(makecode(LEVEL, 40, 18), " %-2d"); c[TMP] = c[STRENGTH] + c[STREXTRA]; botsub(makecode(TMP, 18, 19), "%-2d"); botsub(makecode(INTELLIGENCE, 25, 19), "%-2d"); botsub(makecode(WISDOM, 32, 19), "%-2d"); botsub(makecode(CONSTITUTION, 39, 19), "%-2d"); botsub(makecode(DEXTERITY, 46, 19), "%-2d"); botsub(makecode(CHARISMA, 53, 19), "%-2d"); if ((level != cbak[CAVELEVEL]) ||(c[TELEFLAG] != cbak[TELEFLAG])) { if ((level == 0) ||(wizard)) c[TELEFLAG] = 0; cbak[TELEFLAG] = c[TELEFLAG]; cbak[CAVELEVEL] = level; cursor(59, 19); if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]); } botsub(makecode(GOLD, 69, 19), "%-6d"); botside(); } /* special subroutine to update only the gold number on the bottomlines called from ogold() */ bottomgold() { botsub(makecode(GOLD, 69, 19), "%-6d"); /* botsub(GOLD,"%-6d",69,19); */ } /* special routine to update hp and level fields on bottom lines called in monster.c hitplayer() and spattack() */ bot_hpx() { if (c[EXPERIENCE] != cbak[EXPERIENCE]) { recalc(); bot_linex(); } else botsub(makecode(HP, 5, 19), "%3d"); } /* special routine to update number of spells called from regen() */ bot_spellx() { botsub(makecode(SPELLS, 9, 18), "%2d"); } /* common subroutine for a more economical bottomline() */ static struct bot_side_def { int typ; char *string; } bot_data[] = { STEALTH, "stealth", UNDEADPRO, "undead pro", SPIRITPRO, "spirit pro", CHARMCOUNT, "Charm", TIMESTOP, "Time Stop", HOLDMONST, "Hold Monst", GIANTSTR, "Giant Str", FIRERESISTANCE, "Fire Resit", DEXCOUNT, "Dexterity", STRCOUNT, "Strength", SCAREMONST, "Scare", HASTESELF, "Haste Self", CANCELLATION, "Cancel", INVISIBILITY, "Invisible", ALTPRO, "Protect 3", PROTECTIONTIME, "Protect 2", WTW, "Wall-Walk" }; botside() { register int i,idx; for (i = 0; i < 17; i++) { idx = bot_data[i].typ; if ((always) ||(c[idx] != cbak[idx])) { if ((always) ||(cbak[idx] == 0)) { if (c[idx]) { cursor(70, i + 1); lprcat(bot_data[i].string); } } else if (c[idx] == 0) { cursor(70, i + 1); lprcat(" "); } cbak[idx] = c[idx]; } } always = 0; } static botsub(idx, str) register int idx; char *str; { register int x,y; y = idx & 0xff; x =(idx >> 8) & 0xff; idx >>= 16; if (c[idx] != cbak[idx]) { cbak[idx] = c[idx]; cursor(x, y); lprintf(str,(long) c[idx]); } } /* * subroutine to draw only a section of the screen * only the top section of the screen is updated. If entire lines * are being drawn, then they will be cleared first. */ int d_xmin = 0,d_xmax = MAXX,d_ymin = 0,d_ymax = MAXY; /* for limited screen drawing */ draws(xmin, xmax, ymin, ymax) int xmin,xmax,ymin,ymax; { register int i,idx; if (xmin == 0 && xmax == MAXX) { /* clear section of screen as needed */ if (ymin == 0) cl_up(79, ymax); else for (i = ymin; i < ymin; i++) cl_line(1, i + 1); xmin = -1; } d_xmin = xmin; d_xmax = xmax; d_ymin = ymin; d_ymax = ymax; /* for limited screen drawing */ drawscreen(); if (xmin <= 0 && xmax == MAXX) {/* draw stuff on right side of screen as needed */ for (i = ymin; i < ymax; i++) { idx = bot_data[i].typ; if (c[idx]) { cursor(70, i + 1); lprcat(bot_data[i].string); } cbak[idx] = c[idx]; } } } /* drawscreen() subroutine to redraw the whole screen as the player knows it */ globaldef char screen[MAXX][MAXY]; /* template for the screen */ char d_flag; drawscreen() { register int i,j,k; int lastx,lasty; /* variables used to optimize the object printing */ if (d_xmin == 0 && d_xmax == MAXX && d_ymin == 0 && d_ymax == MAXY) { d_flag = 1; clear(); /* clear the screen */ } else { d_flag = 0; cursor(1, 1); } if (d_xmin < 0) d_xmin = 0; /* d_xmin=-1 means display all without bottomline */ for (i = d_ymin; i < d_ymax; i++) for (j = d_xmin; j < d_xmax; j++) if (know[j][i] == 0) screen[j][i] = ' '; else if (k = mitem[j][i]) screen[j][i] = monstnamelist[k]; else if ((k = item[j][i]) == OWALL) screen[j][i] = '#'; else screen[j][i] = ' '; for (i = d_ymin; i < d_ymax; i++) { j = d_xmin; while ((screen[j][i] == ' ') &&(j < d_xmax)) j++; /* was m=0 */ if (j >= d_xmax) m = d_xmin; /* don't search backwards if blank line */ else { /* search backwards for end of line */ m = d_xmax - 1; while ((screen[m][i] == ' ') &&(m > d_xmin)) --m; if (j <= m) cursor(j + 1, i + 1); else continue; } while (j <= m) { if (j <= m - 3) { for (k = j; k <= j + 3; k++) if (screen[k][i] != ' ') k = 1000; if (k < 1000) { while (screen[j][i] == ' ' && j <= m) j++; cursor(j + 1, i + 1); } } lprc(screen[j++][i]); } } setbold(); /* print out only bold objects now */ for (lastx = lasty = 127, i = d_ymin; i < d_ymax; i++) for (j = d_xmin; j < d_xmax; j++) { if (k = item[j][i]) if (k != OWALL) if ((know[j][i]) &&(mitem[j][i] == 0)) if (objnamelist[k] != ' ') { if (lasty != i + 1 || lastx != j) cursor(lastx = j + 1, lasty = i + 1); else lastx++; lprc(objnamelist[k]); } } resetbold(); if (d_flag) { always = 1; botside(); always = 1; bot_linex(); } oldx = 99; d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;/* for limited screen drawing */ } /* showcell(x,y) subroutine to display a cell location on the screen */ showcell(x, y) int x,y; { register int i,j,k,m; if (c[BLINDCOUNT]) return; /* see nothing if blind */ if (c[AWARENESS]) { minx = x - 3; maxx = x + 3; miny = y - 3; maxy = y + 3; } else { minx = x - 1; maxx = x + 1; miny = y - 1; maxy = y + 1; } if (minx < 0) minx = 0; if (maxx > MAXX - 1) maxx = MAXX - 1; if (miny < 0) miny = 0; if (maxy > MAXY - 1) maxy = MAXY - 1; for (j = miny; j <= maxy; j++) for (m = minx; m <= maxx; m++) if (know[m][j] == 0) { cursor(m + 1, j + 1); x = maxx; while (know[x][j]) --x; for (i = m; i <= x; i++) { if ((k = mitem[i][j]) != 0) lprc(monstnamelist[k]); else switch(k = item[i][j]) { case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV: case OIVDARTRAP: case OIVTRAPDOOR: lprc(objnamelist[k]); break; default: setbold(); lprc(objnamelist[k]); resetbold(); }; know[i][j] = 1; } m = maxx; } } /* this routine shows only the spot that is given it. the spaces around these coordinated are not shown used in godirect() in monster.c for missile weapons display */ show1cell(x, y) int x,y; { if (c[BLINDCOUNT]) return; /* see nothing if blind */ cursor(x + 1, y + 1); if ((k = mitem[x][y]) != 0) lprc(monstnamelist[k]); else switch(k = item[x][y]) { case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV: case OIVDARTRAP: case OIVTRAPDOOR: lprc(objnamelist[k]); break; default: setbold(); lprc(objnamelist[k]); resetbold(); }; know[x][y] |= 1; /* we end up knowing about it */ } /* showplayer() subroutine to show where the player is on the screen cursor values start from 1 up */ showplayer() { cursor(playerx + 1, playery + 1); oldx = playerx; oldy = playery; } /* moveplayer(dir) subroutine to move the player from one room to another returns 0 if can't move in that direction or hit a monster or on an object else returns 1 nomove is set to 1 to stop the next move(inadvertent monsters hitting players when walking into walls) if player walks off screen or into wall */ globaldef short diroffx[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 }; globaldef short diroffy[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 }; moveplayer(dir) int dir; /* from = present room # direction = [1-north] [2-east] [3-south] [4-west] [5-northeast] [6-northwest] [7-southeast] [8-southwest] if direction=0, don't move--just show where he is */ { register int k,m,i,j; if (c[CONFUSE]) if (c[LEVEL] < rnd(30)) dir = rund(9); /* if confused any dir */ k = playerx + diroffx[dir]; m = playery + diroffy[dir]; if (k < 0 || k >= MAXX || m < 0 || m >= MAXY) { nomove = 1; return(yrepcount = 0); } i = item[k][m]; j = mitem[k][m]; if (i == OWALL && c[WTW] == 0) { nomove = 1; return(yrepcount = 0); } /* hit a wall */ if (k == 33 && m == MAXY - 1 && level == 1) { newcavelevel(0); for (k = 0; k < MAXX; k++) for (m = 0; m < MAXY; m++) if (item[k][m] == OENTRANCE) { playerx = k; playery = m; positionplayer(); drawscreen(); return(0); } } if (j > 0) { hitmonster(k, m); return(yrepcount = 0); } /* hit a monster */ lastpx = playerx; lastpy = playery; playerx = k; playery = m; if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR) return(yrepcount = 0); else return(1); } /* * function to show what magic items have been discovered thus far * enter with -1 for just spells, anything else will give scrolls & potions */ static int lincount,count; seemagic(arg) int arg; { register int i,number; count = lincount = 0; nosignal = 1; if (arg == -1) { /* if display spells while casting one */ for (number = i = 0; i < SPNUM; i++) if (spelknow[i]) number++; number =(number + 2) / 3 + 4;/* # lines needed to display */ cl_up(79, number); cursor(1, 1); } else { resetscroll(); clear(); } lprcat("The magic spells you have discovered thus far:\n\n"); for (i = 0; i < SPNUM; i++) if (spelknow[i]) { lprintf("%s %-20s ", spelcode[i], spelname[i]); seepage(); } if (arg == -1) { seepage(); more(); nosignal = 0; draws(0, MAXX, 0, number); return; } lincount += 3; if (count != 0) { count = 2; seepage(); } lprcat("\nThe magic scrolls you have found to date are:\n\n"); count = 0; for (i = 0; i < MAXSCROLL; i++) if (scrollname[i][0]) if (scrollname[i][1] != ' ') { lprintf("%-26s", &scrollname[i][1]); seepage(); } lincount += 3; if (count != 0) { count = 2; seepage(); } lprcat("\nThe magic potions you have found to date are:\n\n"); count = 0; for (i = 0; i < MAXPOTION; i++) if (potionname[i][0]) if (potionname[i][1] != ' ') { lprintf("%-26s", &potionname[i][1]); seepage(); } if (lincount != 0) more(); nosignal = 0; setscroll(); drawscreen(); } /* * subroutine to paginate the seemagic function */ seepage() { if (++count == 3) { lincount++; count = 0; lprc('\n'); if (lincount > 17) { lincount = 0; more(); clear(); } } } SHAR_EOF if test 13152 -ne "`wc -c < 'display.c'`" then echo shar: error transmitting "'display.c'" '(should have been 13152 characters)' fi fi # end of overwriting check echo shar: extracting "'fortune.c'" '(1991 characters)' if test -f 'fortune.c' then echo shar: will not over-write existing file "'fortune.c'" else cat << \SHAR_EOF > 'fortune.c' /* fortune.c Larn is copyrighted 1986 by Noah Morgan. */ #include <stat.h> #include <file.h> #include "header.h" /* * function to return a random fortune from the fortune file */ static char *base = 0; /* pointer to the fortune text */ static char **flines = 0; /* array of pointers to each fortune */ static int fd = 0; /* true if we have load the fortune info */ static int nlines = 0; /* # lines in fortune database */ char *fortune (file) char *file; { register char *p, *bptr; register int lines,tmp,i; struct stat stat; char *malloc (); if (fd == 0) { if ((fd = open (file, O_RDONLY)) < 0)/* open the file */ return (0); /* can't find file */ /* find out how big fortune file is and get memory for it */ stat.st_size = 16384; if ((fstat (fd, &stat) < 0) || ((base = malloc (1 + stat.st_size)) == 0)) { close (fd); fd = -1; free ((char *) base); return (0); /* can't stat file */ } /* read in the entire fortune file */ bptr = base; while ((i = read(fd,bptr,stat.st_size)) > 0) bptr += i; if (bptr == base) { close (fd); fd = -1; free ((char *) base); return (0); /* can't read file */ } close (fd); base[stat.st_size] = 0; /* final NULL termination */ /* count up all the lines (and NULL terminate) to know memory needs */ for (p = base, lines = 0; p < base + stat.st_size; p++)/* count lines */ if (*p == '\n') *p = 0, lines++; nlines = lines; /* get memory for array of pointers to each fortune */ if ((flines = (char **) malloc (nlines * sizeof (char *))) == 0) { free ((char *) base); fd = -1; return (0); /* malloc() failure */ } /* now assign each pointer to a line */ for (p = base, tmp = 0; tmp < nlines; tmp++) { flines[tmp] = p; while (*p++); /* advance to next line */ } } if (fd > 2) /* if we have a database to look at */ return (flines[rund ((nlines <= 0) ? 1 : nlines)]); else return (0); } SHAR_EOF if test 1991 -ne "`wc -c < 'fortune.c'`" then echo shar: error transmitting "'fortune.c'" '(should have been 1991 characters)' fi fi # end of overwriting check echo shar: extracting "'global.c'" '(16893 characters)' if test -f 'global.c' then echo shar: will not over-write existing file "'global.c'" else cat << \SHAR_EOF > 'global.c' /* global.c Larn is copyrighted 1986 by Noah Morgan. * * raiselevel() subroutine to raise the player one level * loselevel() subroutine to lower the player by one level * raiseexperience(x) subroutine to increase experience points * loseexperience(x) subroutine to lose experience points * losehp(x) subroutine to remove hit points from the player * losemhp(x) subroutine to remove max # hit points from the player * raisehp(x) subroutine to gain hit points * raisemhp(x) subroutine to gain maximum hit points * losespells(x) subroutine to lose spells * losemspells(x) subroutine to lose maximum spells * raisespells(x) subroutine to gain spells * raisemspells(x) subroutine to gain maximum spells * recalc() function to recalculate the armor class of the player * makemonst(lev) function to return monster number for a randomly selected monster * positionplayer() function to be sure player is not in a wall * quit() subroutine to ask if the player really wants to quit */ #include "header.h" extern int score[],dropflag; extern int random; /* the random number seed */ extern char *what[],*who[]; extern char winner[]; extern char sciv[SCORESIZE + 1][26][2]; /* *********** RAISE LEVEL *********** raiselevel() subroutine to raise the player one level uses the skill[] array to find level boundarys uses c[EXPERIENCE] c[LEVEL] */ raiselevel() { if (c[LEVEL] < MAXPLEVEL) raiseexperience((long)(skill[c[LEVEL]] - c[EXPERIENCE])); } /* *********** LOOSE LEVEL *********** loselevel() subroutine to lower the players character level by one */ loselevel() { if (c[LEVEL] > 1) loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL] - 1] + 1)); } /* **************** RAISE EXPERIENCE **************** raiseexperience(x) subroutine to increase experience points */ raiseexperience(x) register long x; { register int i,tmp; i = c[LEVEL]; c[EXPERIENCE] += x; while (c[EXPERIENCE] >= skill[c[LEVEL]] &&(c[LEVEL] < MAXPLEVEL)) { tmp =(c[CONSTITUTION] - c[HARDGAME]) >> 1; c[LEVEL]++; raisemhp((int)(rnd(3) + rnd((tmp > 0) ? tmp : 1))); raisemspells((int) rund(3)); if (c[LEVEL] < 7 - c[HARDGAME]) raisemhp((int)(c[CONSTITUTION] >> 2)); } if (c[LEVEL] != i) { cursors(); beep(); lprintf("\nWelcome to level %d",(long) c[LEVEL]);/* if we changed levels */ } bottomline(); } /* **************** LOOSE EXPERIENCE **************** loseexperience(x) subroutine to lose experience points */ loseexperience(x) register long x; { register int i,tmp; i = c[LEVEL]; c[EXPERIENCE] -= x; if (c[EXPERIENCE] < 0) c[EXPERIENCE] = 0; while (c[EXPERIENCE] < skill[c[LEVEL] - 1]) { if (--c[LEVEL] <= 1) c[LEVEL] = 1; /* down one level */ tmp =(c[CONSTITUTION] - c[HARDGAME]) >> 1;/* lose hpoints */ losemhp((int) rnd((tmp > 0) ? tmp : 1));/* lose hpoints */ if (c[LEVEL] < 7 - c[HARDGAME]) losemhp((int)(c[CONSTITUTION] >> 2)); losemspells((int) rund(3));/* lose spells */ } if (i != c[LEVEL]) { cursors(); beep(); lprintf("\nYou went down to level %d!",(long) c[LEVEL]); } bottomline(); } /* ******** LOOSE HP ******** losehp(x) losemhp(x) subroutine to remove hit points from the player warning -- will kill player if hp goes to zero */ losehp(x) register int x; { if ((c[HP] -= x) <= 0) { beep(); lprcat("\n"); nap(3000); died(lastnum); } } losemhp(x) register int x; { c[HP] -= x; if (c[HP] < 1) c[HP] = 1; c[HPMAX] -= x; if (c[HPMAX] < 1) c[HPMAX] = 1; } /* ******** RAISE HP ******** raisehp(x) raisemhp(x) subroutine to gain maximum hit points */ raisehp(x) register int x; { if ((c[HP] += x) > c[HPMAX]) c[HP] = c[HPMAX]; } raisemhp(x) register int x; { c[HPMAX] += x; c[HP] += x; } /* ************ RAISE SPELLS ************ raisespells(x) raisemspells(x) subroutine to gain maximum spells */ raisespells(x) register int x; { if ((c[SPELLS] += x) > c[SPELLMAX]) c[SPELLS] = c[SPELLMAX]; } raisemspells(x) register int x; { c[SPELLMAX] += x; c[SPELLS] += x; } /* ************ LOOSE SPELLS ************ losespells(x) losemspells(x) subroutine to lose maximum spells */ losespells(x) register int x; { if ((c[SPELLS] -= x) < 0) c[SPELLS] = 0; } losemspells(x) register int x; { if ((c[SPELLMAX] -= x) < 0) c[SPELLMAX] = 0; if ((c[SPELLS] -= x) < 0) c[SPELLS] = 0; } /* makemonst(lev) int lev; function to return monster number for a randomly selected monster for the given cave level */ makemonst(lev) register int lev; { register int tmp,x; if (lev < 1) lev = 1; if (lev > 12) lev = 12; tmp = WATERLORD; if (lev < 5) while (tmp == WATERLORD) tmp = rnd((x = monstlevel[lev - 1]) ? x : 1); else while (tmp == WATERLORD) tmp = rnd((x = monstlevel[lev - 1] - monstlevel[lev - 4]) ? x : 1) + monstlevel[lev - 4]; while (monster[tmp].genocided && tmp < MAXMONST) tmp++; /* genocided? */ return(tmp); } /* positionplayer() function to be sure player is not in a wall */ positionplayer() { int try = 2; while ((item[playerx][playery] || mitem[playerx][playery]) &&(try)) if (++playerx >= MAXX - 1) { playerx = 1; if (++playery >= MAXY - 1) { playery = 1; --try; } } if (try == 0) lprcat("Failure in positionplayer\n"); } /* recalc() function to recalculate the armor class of the player */ recalc() { register int i,j,k; c[AC] = c[MOREDEFENSES]; if (c[WEAR] >= 0) switch(iven[c[WEAR]]) { case OSHIELD: c[AC] += 2 + ivenarg[c[WEAR]]; break; case OLEATHER: c[AC] += 2 + ivenarg[c[WEAR]]; break; case OSTUDLEATHER: c[AC] += 3 + ivenarg[c[WEAR]]; break; case ORING: c[AC] += 5 + ivenarg[c[WEAR]]; break; case OCHAIN: c[AC] += 6 + ivenarg[c[WEAR]]; break; case OSPLINT: c[AC] += 7 + ivenarg[c[WEAR]]; break; case OPLATE: c[AC] += 9 + ivenarg[c[WEAR]]; break; case OPLATEARMOR: c[AC] += 10 + ivenarg[c[WEAR]]; break; case OSSPLATE: c[AC] += 12 + ivenarg[c[WEAR]]; break; } if (c[SHIELD] >= 0) if (iven[c[SHIELD]] == OSHIELD) c[AC] += 2 + ivenarg[c[SHIELD]]; if (c[WIELD] < 0) c[WCLASS] = 0; else { i = ivenarg[c[WIELD]]; switch(iven[c[WIELD]]) { case ODAGGER: c[WCLASS] = 3 + i; break; case OBELT: c[WCLASS] = 7 + i; break; case OSHIELD: c[WCLASS] = 8 + i; break; case OSPEAR: c[WCLASS] = 10 + i; break; case OFLAIL: c[WCLASS] = 14 + i; break; case OBATTLEAXE: c[WCLASS] = 17 + i; break; case OLANCE: c[WCLASS] = 19 + i; break; case OLONGSWORD: c[WCLASS] = 22 + i; break; case O2SWORD: c[WCLASS] = 26 + i; break; case OSWORD: c[WCLASS] = 32 + i; break; case OSWORDofSLASHING: c[WCLASS] = 30 + i; break; case OHAMMER: c[WCLASS] = 35 + i; break; default: c[WCLASS] = 0; } } c[WCLASS] += c[MOREDAM]; /* now for regeneration abilities based on rings */ c[REGEN] = 1; c[ENERGY] = 0; j = 0; for (k = 25; k > 0; k--) if (iven[k]) { j = k; k = 0; } for (i = 0; i <= j; i++) { switch(iven[i]) { case OPROTRING: c[AC] += ivenarg[i] + 1; break; case ODAMRING: c[WCLASS] += ivenarg[i] + 1; break; case OBELT: c[WCLASS] +=((ivenarg[i] << 1)) + 2; break; case OREGENRING: c[REGEN] += ivenarg[i] + 1; break; case ORINGOFEXTRA: c[REGEN] += 5 *(ivenarg[i] + 1); break; case OENERGYRING: c[ENERGY] += ivenarg[i] + 1; break; } } } /* quit() subroutine to ask if the player really wants to quit */ quit() { register int i, was_on = 1; cursors(); if (!Check_KeySense()) { scbr(); was_on = 0; } strcpy(lastmonst, ""); lprcat("\n\nDo you really want to quit?"); while (1) { i = readchar(); if (i == 'y') { died(300); return; } if ((i == 'n') ||(i == '\33')) { lprcat(" no"); lflush(); return; } lprcat("\n"); setbold(); lprcat("Yes"); resetbold(); lprcat(" or "); setbold(); lprcat("No"); resetbold(); lprcat(" please? Do you want to quit? "); } if (!was_on) sncbr(); } /* function to ask --more-- then the user must enter a space */ more() { lprcat("\n --- press "); standout("space"); lprcat(" to continue --- "); while (readchar() != ' '); } /* function to put something in the players inventory returns 0 if success, 1 if a failure */ take(itm, arg) int itm,arg; { register int i,limit; if ((limit = 15 +(c[LEVEL] >> 1)) > 26) limit = 26; for (i = 0; i < limit; i++) if (iven[i] == 0) { iven[i] = itm; ivenarg[i] = arg; limit = 0; switch(itm) { case OPROTRING: case ODAMRING: case OBELT: limit = 1; break; case ODEXRING: c[DEXTERITY] += ivenarg[i] + 1; limit = 1; break; case OSTRRING: c[STREXTRA] += ivenarg[i] + 1; limit = 1; break; case OCLEVERRING: c[INTELLIGENCE] += ivenarg[i] + 1; limit = 1; break; case OHAMMER: c[DEXTERITY] += 10; c[STREXTRA] += 10; c[INTELLIGENCE] -= 10; limit = 1; break; case OORBOFDRAGON: c[SLAYING]++; break; case OSPIRITSCARAB: c[NEGATESPIRIT]++; break; case OCUBEofUNDEAD: c[CUBEofUNDEAD]++; break; case ONOTHEFT: c[NOTHEFT]++; break; case OSWORDofSLASHING: c[DEXTERITY] += 5; limit = 1; break; }; lprcat("\nYou pick up:"); srcount = 0; show3(i); if (limit) bottomline(); return(0); } lprcat("\nYou can't carry anything else"); return(1); } /* subroutine to drop an object returns 1 if something there already else 0 */ drop_object(k) int k; { int itm; if ((k < 0) ||(k > 25)) return(0); itm = iven[k]; cursors(); if (itm == 0) { lprintf("\nYou don't have item %c! ", k + 'a'); return(1); } if (item[playerx][playery]) { beep(); lprcat("\nThere's something here already"); return(1); } if (playery == MAXY - 1 && playerx == 33) return(1); /* not in entrance */ item[playerx][playery] = itm; iarg[playerx][playery] = ivenarg[k]; srcount = 0; lprcat("\n You drop:"); show3(k); /* show what item you dropped */ know[playerx][playery] = 0; iven[k] = 0; if (c[WIELD] == k) c[WIELD] = -1; if (c[WEAR] == k) c[WEAR] = -1; if (c[SHIELD] == k) c[SHIELD] = -1; adjustcvalues(itm, ivenarg[k]); dropflag = 1; /* say dropped an item so wont ask to pick it up right away */ return(0); } /* function to enchant armor player is currently wearing */ enchantarmor() { register int tmp; if (c[WEAR] < 0) { if (c[SHIELD] < 0) { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; } else { tmp = iven[c[SHIELD]]; if (tmp != OSCROLL) if (tmp != OPOTION) { ivenarg[c[SHIELD]]++; bottomline(); } } } tmp = iven[c[WEAR]]; if (tmp != OSCROLL) if (tmp != OPOTION) { ivenarg[c[WEAR]]++; bottomline(); } } /* function to enchant a weapon presently being wielded */ enchweapon() { register int tmp; if (c[WIELD] < 0) { cursors(); beep(); lprcat("\nYou feel a sense of loss"); return; } tmp = iven[c[WIELD]]; if (tmp != OSCROLL) if (tmp != OPOTION) { ivenarg[c[WIELD]]++; if (tmp == OCLEVERRING) c[INTELLIGENCE]++; else if (tmp == OSTRRING) c[STREXTRA]++; else if (tmp == ODEXRING) c[DEXTERITY]++; bottomline(); } } /* routine to tell if player can carry one more thing returns 1 if pockets are full, else 0 */ pocketfull() { register int i,limit; if ((limit = 15 +(c[LEVEL] >> 1)) > 26) limit = 26; for (i = 0; i < limit; i++) if (iven[i] == 0) return(0); return(1); } /* function to return 1 if a monster is next to the player else returns 0 */ nearbymonst() { register int tmp,tmp2; for (tmp = playerx - 1; tmp < playerx + 2; tmp++) for (tmp2 = playery - 1; tmp2 < playery + 2; tmp2++) if (mitem[tmp][tmp2]) return(1); /* if monster nearby */ return(0); } /* function to steal an item from the players pockets returns 1 if steals something else returns 0 */ stealsomething() { register int i,j = 100; while (1) { i = rund(26); if (iven[i]) if (c[WEAR] != i) if (c[WIELD] != i) if (c[SHIELD] != i) { srcount = 0; show3(i); adjustcvalues(iven[i], ivenarg[i]); iven[i] = 0; return(1); } if (--j <= 0) return(0); } } /* function to return 1 is player carrys nothing else return 0 */ emptyhanded() { register int i; for (i = 0; i < 26; i++) if (iven[i]) if (i != c[WIELD]) if (i != c[WEAR]) if (i != c[SHIELD]) return(0); return(1); } /* function to create a gem on a square near the player */ creategem() { register int i,j; switch(rnd(4)) { case 1: i = ODIAMOND; j = 50; break; case 2: i = ORUBY; j = 40; break; case 3: i = OEMERALD; j = 30; break; default: i = OSAPPHIRE; j = 20; break; }; createitem(i, rnd(j) + j / 10); } /* function to change character levels as needed when dropping an object that affects these characteristics */ adjustcvalues(itm, arg) int itm,arg; { register int flag = 0; switch(itm) { case ODEXRING: c[DEXTERITY] -= arg + 1; flag = 1; break; case OSTRRING: c[STREXTRA] -= arg + 1; flag = 1; break; case OCLEVERRING: c[INTELLIGENCE] -= arg + 1; flag = 1; break; case OHAMMER: c[DEXTERITY] -= 10; c[STREXTRA] -= 10; c[INTELLIGENCE] += 10; flag = 1; break; case OSWORDofSLASHING: c[DEXTERITY] -= 5; flag = 1; break; case OORBOFDRAGON: --c[SLAYING]; return; case OSPIRITSCARAB: --c[NEGATESPIRIT]; return; case OCUBEofUNDEAD: --c[CUBEofUNDEAD]; return; case ONOTHEFT: --c[NOTHEFT]; return; case OLANCE: c[LANCEDEATH] = 0; return; case OPOTION: case OSCROLL: return; default: flag = 1; }; if (flag) bottomline(); } /* function to read a string from token input "string" returns a pointer to the string */ gettokstr(str) register char *str; { register int i = 50,j; while ((readchar() != '"') &&(--i > 0)); i = 36; while (--i > 0) { if ((j = readchar()) != '"') *str++ = j; else i = 0; } *str = 0; i = 50; if (j != '"') while ((readchar() != '"') &&(--i > 0));/* if end due to too long, then find closing quote */ } /* function to ask user for a password(no echo) returns 1 if entered correctly, 0 if not */ static char gpwbuf[33]; getpassword() { register int i,j; register char *gpwp; globalref char *password; scbr(); /* system("stty -echo cbreak"); */ gpwp = gpwbuf; lprcat("\nEnter Password: "); lflush(); i = strlen(password); for (j = 0; j < i; j++) *(gpwp++) = readchar(); gpwbuf[i] = 0; sncbr(); /* system("stty echo -cbreak"); */ if (strcmp(gpwbuf, password) != 0) { lprcat("\nSorry\n"); lflush(); return(0); } else return(1); } /* subroutine to get a yes or no response from the user returns y or n */ getyn() { register int i = 0; while (i != 'y' && i != 'n' && i != '\33') i = readchar(); return(i); } /* function to calculate the pack weight of the player returns the number of pounds the player is carrying */ packweight() { register int i,j,k; k = c[GOLD] / 1000; j = 25; while ((iven[j] == 0) &&(j > 0)) --j; for (i = 0; i <= j; i++) switch(iven[i]) { case 0: break; case OSSPLATE: case OPLATEARMOR: k += 40; break; case OPLATE: k += 35; break; case OHAMMER: k += 30; break; case OSPLINT: k += 26; break; case OSWORDofSLASHING: case OCHAIN: case OBATTLEAXE: case O2SWORD: k += 23; break; case OLONGSWORD: case OSWORD: case ORING: case OFLAIL: k += 20; break; case OLANCE: case OSTUDLEATHER: k += 15; break; case OLEATHER: case OSPEAR: k += 8; break; case OORBOFDRAGON: case OBELT: k += 4; break; case OSHIELD: k += 7; break; case OCHEST: k += 30 + ivenarg[i]; break; default: k++; }; return(k); } #ifndef MACRORND /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */ rnd(x) int x; { return((((rand_x = rand_x * 1103515245 + 12345) >> 7) %(x)) + 1); } rund(x) int x; { return((((rand_x = rand_x * 1103515245 + 12345) >> 7) %(x))); } #endif MACRORND SHAR_EOF if test 16893 -ne "`wc -c < 'global.c'`" then echo shar: error transmitting "'global.c'" '(should have been 16893 characters)' fi fi # end of overwriting check echo shar: extracting "'header.h'" '(12521 characters)' if test -f 'header.h' then echo shar: will not over-write existing file "'header.h'" else cat << \SHAR_EOF > 'header.h' /* header.h Larn is copyrighted 1986 by Noah Morgan. */ #define SCORENAME "LARN12.SCR" #define LOGFNAME "LARN12.LOG" #define HELPNAME "LARN12.HLP" #define LEVELSNAME "LARN12.MAZ" #define FORTSNAME "LARN12.FTN" #define PLAYERIDS "LARN12.IDS" #define HOLIFILE "LARN12.HDY" #define MAXLEVEL 11 /* max # levels in the dungeon */ #define MAXVLEVEL 3 /* max # of levels in the temple of the luran */ #define MAXX 67 #define MAXY 17 #define SCORESIZE 10 /* this is the number of people on a scoreboard max */ #define MAXPLEVEL 100 /* maximum player level allowed */ #define MAXMONST 56 /* maximum # monsters in the dungeon */ #define SPNUM 38 /* maximum number of spells in existance */ #define MAXSCROLL 28 /* maximum number of scrolls that are possible */ #define MAXPOTION 35 /* maximum number of potions that are possible */ #define TIMELIMIT 30000 /* the maximum number of moves before the game is called */ #define TAXRATE 1/20 /* the tax rate for the LRS */ #define MAXOBJ 93 /* the maximum number of objects n < MAXOBJ */ /* this is the structure definition of the monster data */ struct monst { char *name; char level; short armorclass; char damage; char attack; char defense; char genocided; char intelligence; /* monsters intelligence -- used to choose movement */ short gold; short hitpoints; unsigned long experience; }; /* this is the structure definition for the items in the dnd store */ struct _itm { short price; char **mem; char obj; char arg; char qty; }; /* this is the structure that holds the entire dungeon specifications */ struct cel { short hitp; /* monster's hit points */ char mitem; /* the monster ID */ char item; /* the object's ID */ short iarg; /* the object's argument */ char know; /* have we been here before */ }; /* this is the structure for maintaining & moving the spheres of annihilation */ struct sphere { struct sphere *p; /* pointer to next structure */ char x,y,lev; /* location of the sphere */ char dir; /* direction sphere is going in */ char lifetime; /* duration of the sphere */ }; /* defines for the character attribute array c[] */ #define STRENGTH 0 /* characters physical strength not due to objects */ #define INTELLIGENCE 1 #define WISDOM 2 #define CONSTITUTION 3 #define DEXTERITY 4 #define CHARISMA 5 #define HPMAX 6 #define HP 7 #define GOLD 8 #define EXPERIENCE 9 #define LEVEL 10 #define REGEN 11 #define WCLASS 12 #define AC 13 #define BANKACCOUNT 14 #define SPELLMAX 15 #define SPELLS 16 #define ENERGY 17 #define ECOUNTER 18 #define MOREDEFENSES 19 #define WEAR 20 #define PROTECTIONTIME 21 #define WIELD 22 #define AMULET 23 #define REGENCOUNTER 24 #define MOREDAM 25 #define DEXCOUNT 26 #define STRCOUNT 27 #define BLINDCOUNT 28 #define CAVELEVEL 29 #define CONFUSE 30 #define ALTPRO 31 #define HERO 32 #define CHARMCOUNT 33 #define INVISIBILITY 34 #define CANCELLATION 35 #define HASTESELF 36 #define EYEOFLARN 37 #define AGGRAVATE 38 #define GLOBE 39 #define TELEFLAG 40 #define SLAYING 41 #define NEGATESPIRIT 42 #define SCAREMONST 43 #define AWARENESS 44 #define HOLDMONST 45 #define TIMESTOP 46 #define HASTEMONST 47 #define CUBEofUNDEAD 48 #define GIANTSTR 49 #define FIRERESISTANCE 50 #define BESSMANN 51 #define NOTHEFT 52 #define HARDGAME 53 #define CPUTIME 54 #define BYTESIN 55 #define BYTESOUT 56 #define MOVESMADE 57 #define MONSTKILLED 58 #define SPELLSCAST 59 #define LANCEDEATH 60 #define SPIRITPRO 61 #define UNDEADPRO 62 #define SHIELD 63 #define STEALTH 64 #define ITCHING 65 #define LAUGHING 66 #define DRAINSTRENGTH 67 #define CLUMSINESS 68 #define INFEEBLEMENT 69 #define HALFDAM 70 #define SEEINVISIBLE 71 #define FILLROOM 72 #define RANDOMWALK 73 #define SPHCAST 74 /* nz if an active sphere of annihilation */ #define WTW 75 /* walk through walls */ #define STREXTRA 76 /* character strength due to objects or enchantments */ #define TMP 77 /* misc scratch space */ #define LIFEPROT 78 /* life protection counter */ /* defines for the objects in the game */ #define OALTAR 1 #define OTHRONE 2 #define OORB 3 #define OPIT 4 #define OSTAIRSUP 5 #define OELEVATORUP 6 #define OFOUNTAIN 7 #define OSTATUE 8 #define OTELEPORTER 9 #define OSCHOOL 10 #define OMIRROR 11 #define ODNDSTORE 12 #define OSTAIRSDOWN 13 #define OELEVATORDOWN 14 #define OBANK2 15 #define OBANK 16 #define ODEADFOUNTAIN 17 #define OMAXGOLD 70 #define OGOLDPILE 18 #define OOPENDOOR 19 #define OCLOSEDDOOR 20 #define OWALL 21 #define OTRAPARROW 66 #define OTRAPARROWIV 67 #define OLARNEYE 22 #define OPLATE 23 #define OCHAIN 24 #define OLEATHER 25 #define ORING 60 #define OSTUDLEATHER 61 #define OSPLINT 62 #define OPLATEARMOR 63 #define OSSPLATE 64 #define OSHIELD 68 #define OELVENCHAIN 92 #define OSWORDofSLASHING 26 #define OHAMMER 27 #define OSWORD 28 #define O2SWORD 29 #define OSPEAR 30 #define ODAGGER 31 #define OBATTLEAXE 57 #define OLONGSWORD 58 #define OFLAIL 59 #define OLANCE 65 #define OVORPAL 90 #define OSLAYER 91 #define ORINGOFEXTRA 32 #define OREGENRING 33 #define OPROTRING 34 #define OENERGYRING 35 #define ODEXRING 36 #define OSTRRING 37 #define OCLEVERRING 38 #define ODAMRING 39 #define OBELT 40 #define OSCROLL 41 #define OPOTION 42 #define OBOOK 43 #define OCHEST 44 #define OAMULET 45 #define OORBOFDRAGON 46 #define OSPIRITSCARAB 47 #define OCUBEofUNDEAD 48 #define ONOTHEFT 49 #define ODIAMOND 50 #define ORUBY 51 #define OEMERALD 52 #define OSAPPHIRE 53 #define OENTRANCE 54 #define OVOLDOWN 55 #define OVOLUP 56 #define OHOME 69 #define OKGOLD 71 #define ODGOLD 72 #define OIVDARTRAP 73 #define ODARTRAP 74 #define OTRAPDOOR 75 #define OIVTRAPDOOR 76 #define OTRADEPOST 77 #define OIVTELETRAP 78 #define ODEADTHRONE 79 #define OANNIHILATION 80 /* sphere of annihilation */ #define OTHRONE2 81 #define OLRS 82 /* Larn Revenue Service */ #define OCOOKIE 83 #define OURN 84 #define OBRASSLAMP 85 #define OHANDofFEAR 86 /* hand of fear */ #define OSPHTAILSMAN 87 /* tailsman of the sphere */ #define OWWAND 88 /* wand of wonder */ #define OPSTAFF 89 /* staff of power */ /* used up to 92 */ /* defines for the monsters as objects */ #define BAT 1 #define GNOME 2 #define HOBGOBLIN 3 #define JACKAL 4 #define KOBOLD 5 #define ORC 6 #define SNAKE 7 #define CENTIPEDE 8 #define JACULI 9 #define TROGLODYTE 10 #define ANT 11 #define EYE 12 #define LEPRECHAUN 13 #define NYMPH 14 #define QUASIT 15 #define RUSTMONSTER 16 #define ZOMBIE 17 #define ASSASSINBUG 18 #define BUGBEAR 19 #define HELLHOUND 20 #define ICELIZARD 21 #define CENTAUR 22 #define TROLL 23 #define YETI 24 #define WHITEDRAGON 25 #define ELF 26 #define CUBE 27 #define METAMORPH 28 #define VORTEX 29 #define ZILLER 30 #define VIOLETFUNGI 31 #define WRAITH 32 #define FORVALAKA 33 #define LAMANOBE 34 #define OSEQUIP 35 #define ROTHE 36 #define XORN 37 #define VAMPIRE 38 #define INVISIBLESTALKER 39 #define POLTERGEIST 40 #define DISENCHANTRESS 41 #define SHAMBLINGMOUND 42 #define YELLOWMOLD 43 #define UMBERHULK 44 #define GNOMEKING 45 #define MIMIC 46 #define WATERLORD 47 #define BRONZEDRAGON 48 #define GREENDRAGON 49 #define PURPLEWORM 50 #define XVART 51 #define SPIRITNAGA 52 #define SILVERDRAGON 53 #define PLATINUMDRAGON 54 #define GREENURCHIN 55 #define REDDRAGON 56 #define DEMONLORD 57 #define DEMONPRINCE 64 #define NULL 0 #define BUFBIG 4096 /* size of the output buffer */ #define MAXIBUF 4096 /* size of the input buffer */ #define LOGNAMESIZE 40 /* max size of the players name */ #define SAVEFILENAMESIZE 128 /* max size of the savefile path */ #ifndef NODEFS globalref char VERSION,SUBVERSION; globalref char *aborted,beenhere[MAXLEVEL+MAXVLEVEL],boldon,cheat,ckpfile[]; globalref char ckpflag; globalref char *class[],course[],diagfile[],fortfile[],helpfile[],holifile[]; globalref char *inbuffer,is_alpha[],is_digit[]; globalref char item[MAXX][MAXY],iven[],know[MAXX][MAXY],larnlevels[],lastmonst[]; globalref char level,*levelname[],logfile[],loginname[],logname[],*lpbuf,*lpend; globalref char *lpnt,moved[MAXX][MAXY],mitem[MAXX][MAXY],monstlevel[]; globalref char monstnamelist[],nch[],ndgg[],nlpts[],nomove,nosignal,nowelcome; globalref char nplt[],nsw[],*objectname[]; globalref char objnamelist[],optsfile[],*potionname[],playerids[],potprob[]; globalref char predostuff,restorflag,savefilename[],scorefile[],scprob[]; globalref char screen[MAXX][MAXY],*scrollname[],sex,*spelcode[]; globalref char *speldescript[],spelknow[],*spelname[],*spelmes[]; globalref char spelweird[MAXMONST+8][SPNUM]; globalref char splev[],stealth[MAXX][MAXY],to_lower[],to_upper[],wizard; globalref short diroffx[],diroffy[],hitflag,hit2flag,hit3flag,hitp[MAXX][MAXY]; globalref short iarg[MAXX][MAXY],ivenarg[26],lasthx,lasthy,lastnum; globalref short lastpx,lastpy,nobeep,oldx,oldy,playerx,playery; globalref int dayplay,enable_scroll,srcount,yrepcount,userid,wisid,lfd,fd; globalref long initialtime,outstanding_taxes,skill[],gtime,c[100],cbak[100]; globalref long start_cpu; globalref unsigned long rand_x; globalref struct cel cell[(MAXLEVEL+MAXVLEVEL) * MAXX * MAXY]; globalref struct monst monster[]; globalref struct sphere *spheres; globalref struct _itm itm[90]; extern char *fortune(),*malloc(),*getenv(),*getlogin(),*lgetw(),*lgetl(),*ctime(); #ifndef VT100 extern char *tmcapcnv(),*tgetstr(),*tgoto(); #endif VT100 extern long paytaxes(),lgetc(),lrint(),time(); extern unsigned long readnum(); /* macro to create scroll #'s with probability of occurrence */ #define newscroll() (scprob[rund(81)]) /* macro to return a potion # created with probability of occurrence */ #define newpotion() (potprob[rund(41)]) /* macro to return the + points on created leather armor */ #define newleather() (nlpts[rund(c[HARDGAME]?13:15)]) /* macro to return the + points on chain armor */ #define newchain() (nch[rund(10)]) /* macro to return + points on plate armor */ #define newplate() (nplt[rund(c[HARDGAME]?4:12)]) /* macro to return + points on new daggers */ #define newdagger() (ndgg[rund(13)]) /* macro to return + points on new swords */ #define newsword() (nsw[rund(c[HARDGAME]?6:13)]) /* macro to destroy object at present location */ #define forget() (item[playerx][playery]=know[playerx][playery]=0) /* macro to wipe out a monster at a location */ #define disappear(x,y) (mitem[x][y]=know[x][y]=0) #ifdef VT100 /* macro to turn on bold display for the terminal */ #define setbold() (lprcat(boldon?"\33[1m":"\33[7m")) /* macro to turn off bold display for the terminal */ #define resetbold() (lprcat("\33[m")) /* macro to setup the scrolling region for the terminal */ #define setscroll() (lprcat("\33[20;24r")) /* macro to clear the scrolling region for the terminal */ #define resetscroll() (lprcat("\33[;24r")) /* macro to clear the screen and home the cursor */ #define clear() (lprcat("\33[2J\33[f"), cbak[SPELLS]= -50) #define cltoeoln() lprcat("\33[K") #else VT100 /* defines below are for use in the termcap mode only */ #define ST_START 1 #define ST_END 2 #define BOLD 3 #define END_BOLD 4 #define CLEAR 5 #define CL_LINE 6 #define CL_DOWN 14 #define CURSOR 15 /* macro to turn on bold display for the terminal */ #define setbold() (*lpnt++ = ST_START) /* macro to turn off bold display for the terminal */ #define resetbold() (*lpnt++ = ST_END) /* macro to setup the scrolling region for the terminal */ #define setscroll() enable_scroll=1 /* macro to clear the scrolling region for the terminal */ #define resetscroll() enable_scroll=0 /* macro to clear the screen and home the cursor */ #define clear() (*lpnt++ =CLEAR, cbak[SPELLS]= -50) /* macro to clear to end of line */ #define cltoeoln() (*lpnt++ = CL_LINE) #endif VT100 /* macro to output one byte to the output buffer */ #define lprc(ch) ((lpnt>=lpend)?(*lpnt++ =(ch), lflush()):(*lpnt++ =(ch))) /* macro to seed the random number generator */ #define srand(x) (rand_x=x) #ifdef MACRORND /* macros to generate random numbers 1<=rnd(N)<=N 0<=rund(N)<=N-1 */ #define rnd(x) ((((rand_x=rand_x*1103515245+12345)>>7)%(x))+1) #define rund(x) ((((rand_x=rand_x*1103515245+12345)>>7)%(x)) ) #endif MACRORND /* macros for miscellaneous data conversion */ #define min(x,y) (((x)>(y))?(y):(x)) #define max(x,y) (((x)>(y))?(x):(y)) #define isalpha(x) (is_alpha[x]) #define isdigit(x) (is_digit[x]) #define tolower(x) (to_lower[x]) #define toupper(x) (to_upper[x]) #define lcc(x) (to_lower[x]) #define ucc(x) (to_upper[x]) #endif NODEFS SHAR_EOF if test 12521 -ne "`wc -c < 'header.h'`" then echo shar: error transmitting "'header.h'" '(should have been 12521 characters)' fi fi # end of overwriting check echo shar: extracting "'help.c'" '(2367 characters)' if test -f 'help.c' then echo shar: will not over-write existing file "'help.c'" else cat << \SHAR_EOF > 'help.c' /* help.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* * help function to display the help info * * format of the .larn.help file * * 1st character of file: # of pages of help available(ascii digit) * page(23 lines) for the introductory message(not counted in above) * pages of help text(23 lines per page) */ help() { register int i,j; #ifndef VT100 char tmbuf[128]; /* intermediate translation buffer when not a VT100 */ #endif VT100 if ((j = openhelp()) < 0) return; /* open the help file and get # pages */ for (i = 0; i < 23; i++) lgetl(); /* skip over intro message */ for (; j > 0; j--) { clear(); for (i = 0; i < 23; i++) #ifdef VT100 lprcat(lgetl()); /* print out each line that we read in */ #else VT100 { tmcapcnv(tmbuf, lgetl()); lprcat(tmbuf); } /* intercept \33's */ #endif VT100 if (j > 1) { lprcat(" ---- Press "); standout("return"); lprcat(" to exit, "); standout("space"); lprcat(" for more help ---- "); i = 0; while ((i != ' ') &&(i != '\n') &&(i != '\33')) i = readchar(); if ((i == '\n') ||(i == '\33')) { lrclose(); setscroll(); drawscreen(); return; } } } lrclose(); retcont(); drawscreen(); } /* * function to display the welcome message and background */ welcome() { register int i; #ifndef VT100 char tmbuf[128]; /* intermediate translation buffer when not a VT100 */ #endif VT100 if (openhelp() < 0) return; /* open the help file */ clear(); for (i = 0; i < 23; i++) #ifdef VT100 lprcat(lgetl()); /* print out each line that we read in */ #else VT100 { tmcapcnv(tmbuf, lgetl()); lprcat(tmbuf); } /* intercept \33's */ #endif VT100 lrclose(); retcont(); /* press return to continue */ } /* * function to say press return to continue and reset scroll when done */ retcont() { cursor(1, 24); lprcat("Press "); standout("return"); lprcat(" to continue: "); while (readchar() != '\n'); setscroll(); } /* * routine to open the help file and return the first character - '0' */ openhelp() { if (lopen(helpfile) < 0) { lprintf("Can't open help file \"%s\" ", helpfile); lflush(); sleep(4); drawscreen(); setscroll(); return(-1); } resetscroll(); return(lgetc() - '0'); } SHAR_EOF if test 2367 -ne "`wc -c < 'help.c'`" then echo shar: error transmitting "'help.c'" '(should have been 2367 characters)' fi fi # end of overwriting check # End of shell archive exit 0
u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # io.c # keysense.c # larn.c # larn12.ftn # larn12.hdy # This archive created: Sat Aug 30 14:47:38 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'io.c'" '(22021 characters)' if test -f 'io.c' then echo shar: will not over-write existing file "'io.c'" else cat << \SHAR_EOF > 'io.c' /* io.c Larn is copyrighted 1986 by Noah Morgan. * * Below are the functions in this file: * * setupvt100() Subroutine to set up terminal in correct mode for game * clearvt100() Subroutine to clean up terminal when the game is over * readchar() Routine to read in one character from the terminal * scbr() Function to set cbreak -echo for the terminal * sncbr() Function to set -cbreak echo for the terminal * newgame() Subroutine to save the initial time and seed rnd() * * FILE OUTPUT ROUTINES * * lprintf(format,args . . .) printf to the output buffer * lprint(integer) send binary integer to output buffer * lwrite(buf,len) write a buffer to the output buffer * lprcat(str) sent string to output buffer * * FILE OUTPUT MACROS(in header.h) * * lprc(character) put the character into the output buffer * * FILE INPUT ROUTINES * * long lgetc() read one character from input buffer * long lrint() read one integer from input buffer * lrfill(address,number) put input bytes into a buffer * char *lgetw() get a whitespace ended word from input * char *lgetl() get a \n or EOF ended line from input * * FILE OPEN / CLOSE ROUTINES * * lcreat(filename) create a new file for write * lopen(filename) open a file for read * lappend(filename) open for append to an existing file * lrclose() close the input file * lwclose() close output file * lflush() flush the output buffer * * Other Routines * * cursor(x,y) position cursor at [x,y] * cursors() position cursor at [1,24](saves memory) * cl_line(x,y) Clear line at [1,y] and leave cursor at [x,y] * cl_up(x,y) Clear screen from [x,1] to current line. * cl_dn(x,y) Clear screen from [1,y] to end of display. * standout(str) Print the string in standout mode. * set_score_output() Called when output should be literally printed. ** writechar(ch) Print one character in decoded output buffer. ** flush_buf() Flush buffer with decoded output. ** init_term() Terminal initialization -- setup termcap info * char *tmcapcnv(sd,ss) Routine to convert VT100 \33's to termcap format * beep() Routine to emit a beep if enabled(see no-beep in .larnopts) * * Note: ** entries are available only in termcap mode. */ #include "header.h" #include <stdio.h> #include <file.h> #include <varargs.h> #define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */ globaldef int lfd, /* output file numbers */ fd; /* input file numbers */ static int ipoint = MAXIBUF, iepoint = MAXIBUF; /* input buffering pointers */ static char lgetwbuf[LINBUFSIZE]; /* get line(word) buffer */ /* * setupvt100() Subroutine to set up terminal in correct mode for game * * Attributes off, clear screen, set scrolling region, set tty mode */ setupvt100() { clear(); setscroll(); scbr(); /* system("stty cbreak -echo"); */ } /* * clearvt100() Subroutine to clean up terminal when the game is over * * Attributes off, clear screen, unset scrolling region, restore tty mode */ clearvt100() { resetscroll(); clear(); sncbr(); /* system("stty -cbreak echo"); */ } /* * readchar() Routine to read in one character from the terminal */ readchar() { #ifdef EXTRA c[BYTESIN]++; #endif lflush(); /* be sure output buffer is flushed */ if (Check_KeySense()) return(KeySense(1)); /* get byte from terminal */ else return(getchar()); } /* * scbr() Function to set cbreak -echo for the terminal * * like: system("SET TERM/NOECHO/PASTHRU") */ scbr() { KeySense_On(); } /* * sncbr() Function to set -cbreak echo for the terminal * * like: system("SET TERM/ECHO/NOPASTHRU") */ sncbr() { KeySense_Off(); } /* * newgame() Subroutine to save the initial time and seed rnd() */ newgame() { register long *p, *pe; for(p = c, pe = c + 100; p < pe; *p++ = 0); time(&initialtime); srand(initialtime); lcreat((char *) 0); /* open buffering for output to terminal */ } /* * lprintf(format,args . . .) printf to the output buffer * char *format; * {args . . .} * * Enter with the format string in "format", as per printf() usage * and any needed arguments following it * Note: lprintf() only supports %s, %c and %d, with width modifier and * left or right justification. * No correct checking for output buffer overflow is done, but flushes * are done beforehand if needed. * Returns nothing of value. */ lprintf(va_alist) va_dcl { va_list ap; /* pointer for variable argument list */ register char *fmt; register char *outb,*tmpb; register long wide,left,cont,n; /* data for lprintf */ char db[12]; /* %d buffer in lprintf */ va_start(ap); /* initialize the var args pointer */ fmt = va_arg(ap, char *); /* pointer to format string */ if (lpnt >= lpend) lflush(); outb = lpnt; for(;;) { while(*fmt != '%') if (*fmt) *outb++ = *fmt++; else { lpnt = outb; return; } wide = 0; left = 1; cont = 1; while(cont) switch(*(++fmt)) { case 'd': n = va_arg(ap, long); if (n < 0) { n = -n; *outb++ = '-'; if (wide) --wide; } tmpb = db + 11; *tmpb =(char)(n % 10 + '0'); while(n > 9) *(--tmpb) =(char)((n /= 10) % 10 + '0'); if (wide == 0) while(tmpb < db + 12) *outb++ = *tmpb++; else { wide -= db - tmpb + 12; if (left) while(wide-- > 0) *outb++ = ' '; while(tmpb < db + 12) *outb++ = *tmpb++; if (left == 0) while(wide-- > 0) *outb++ = ' '; } cont = 0; break; case 's': tmpb = va_arg(ap, char *); if (wide == 0) { while(*outb++ = *tmpb++); --outb; } else { n = wide - strlen(tmpb); if (left) while(n-- > 0) *outb++ = ' '; while(*outb++ = *tmpb++); --outb; if (left == 0) while(n-- > 0) *outb++ = ' '; } cont = 0; break; case 'c': *outb++ = va_arg(ap, int); cont = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': wide = 10 * wide + *fmt - '0'; break; case '-': left = 0; break; default: *outb++ = *fmt; cont = 0; break; }; fmt++; } va_end(ap); } /* * lprint(long-integer) send binary integer to output buffer * long integer; * * +---------+---------+---------+---------+ * | high | | | low | * | order | | | order | * | byte | | | byte | * +---------+---------+---------+---------+ * 31 --- 24 23 --- 16 15 --- 8 7 --- 0 * * The save order is low order first, to high order(4 bytes total) * and is written to be system independent. * No checking for output buffer overflow is done, but flushes if needed! * Returns nothing of value. */ lprint(x) register long x; { if (lpnt >= lpend) lflush(); *lpnt++ = 255 & x; *lpnt++ = 255 &(x >> 8); *lpnt++ = 255 &(x >> 16); *lpnt++ = 255 &(x >> 24); } /* * lwrite(buf,len) write a buffer to the output buffer * char *buf; * int len; * * Enter with the address and number of bytes to write out * Returns nothing of value */ lwrite(buf, len) register char *buf; int len; { register char *str; register int num2; if (len > 399) { /* don't copy data if can just write it */ #ifdef EXTRA c[BYTESOUT] += len; #endif #ifndef VT100 for(str = buf; len > 0; --len) lprc(*str++); #else VT100 lflush(); write(lfd, buf, len); #endif VT100 } else while(len) { if (lpnt >= lpend) lflush(); /* if buffer is full flush it */ num2 = lpbuf + BUFBIG - lpnt; /* # bytes left in output buffer */ if (num2 > len) num2 = len; str = lpnt; len -= num2; while(num2--) *str++ = *buf++; /* copy in the bytes */ lpnt = str; } } /* * long lgetc() Read one character from input buffer * * Returns 0 if EOF, otherwise the character */ long lgetc() { register int i; if (ipoint != iepoint) return(inbuffer[ipoint++]); /* NOTE: VAX/VMS reads only one line */ if ((i = read(fd, inbuffer, MAXIBUF)) <= 0) { if (i != 0) write(1, "error reading from input file\n", 30); iepoint = ipoint = 0; return(0); } ipoint = 1; iepoint = i; return(*inbuffer); } /* * long lrint() Read one integer from input buffer * * +---------+---------+---------+---------+ * | high | | | low | * | order | | | order | * | byte | | | byte | * +---------+---------+---------+---------+ * 31 --- 24 23 --- 16 15 --- 8 7 --- 0 * * The save order is low order first, to high order(4 bytes total) * Returns the int read */ long lrint() { register unsigned long i; i = 255 & lgetc(); i |=(255 & lgetc()) << 8; i |=(255 & lgetc()) << 16; i |=(255 & lgetc()) << 24; return(i); } /* * lrfill(address,number) put input bytes into a buffer * char *address; * int number; * * Reads "number" bytes into the buffer pointed to by "address". * Returns nothing of value */ lrfill(adr, num) register char *adr; int num; { register char *pnt; register int num2; while(num) { if (iepoint == ipoint) { if (num > 5) { /* fast way */ if (read(fd, adr, num) != num) write(2, "error reading from input file\n", 30); num = 0; } else { *adr++ = lgetc(); --num; } } else { num2 = iepoint - ipoint;/* # of bytes left in the buffer */ if (num2 > num) num2 = num; pnt = inbuffer + ipoint; num -= num2; ipoint += num2; while(num2--) *adr++ = *pnt++; } } } /* * char *lgetw() Get a whitespace ended word from input * * Returns pointer to a buffer that contains word. If EOF, returns a NULL */ char *lgetw() { register char *lgp,cc; register int n = LINBUFSIZE, quote = 0; lgp = lgetwbuf; do cc = lgetc(); while((cc <= 32) &&(cc > NULL)); /* eat whitespace */ for(;; --n, cc = lgetc()) { if ((cc == NULL) &&(lgp == lgetwbuf)) return(NULL); /* EOF */ if ((n <= 1) ||((cc <= 32) &&(quote == 0))) { *lgp = NULL; return(lgetwbuf); } if (cc != '"') *lgp++ = cc; else quote ^= 1; } } /* * char *lgetl() Function to read in a line ended by newline or EOF * * Returns pointer to a buffer that contains the line. If EOF, * Returns NULL */ char *lgetl() { register int i = LINBUFSIZE,ch; register char *str = lgetwbuf; for(;; --i) { if ((*str++ = ch = lgetc()) == NULL) { if (str == lgetwbuf + 1) return(NULL); /* EOF */ ot: *str = NULL; return(lgetwbuf); /* line ended by EOF */ } if ((ch == '\n') ||(i <= 1)) goto ot; /* line ended by \n */ } } /* * lcreat(filename) Create a new file for write * char *filename; * * lcreat((char*)0); means to the terminal * Returns -1 if error, otherwise the file descriptor opened. */ lcreat(str) char *str; { lpnt = lpbuf; lpend = lpbuf + BUFBIG; if (str == NULL) return(lfd = 1); if ((lfd = creat(str, 0644)) < 0) { lfd = 1; lprintf("error creating file <%s>\n", str); lflush(); return(-1); } return(lfd); } /* * lopen(filename) Open a file for read * char *filename; * * lopen(0) means from the terminal * Returns -1 if error, otherwise the file descriptor opened. */ lopen(str) char *str; { ipoint = iepoint = MAXIBUF; if (str == NULL) return(fd = 0); if ((fd = open(str, 0)) < 0) { lwclose(); lfd = 1; lpnt = lpbuf; return(-1); } return(fd); } /* * lappend(filename) Open for append to an existing file * char *filename; * * lappend(0) means to the terminal * Returns -1 if error, otherwise the file descriptor opened. */ lappend(str) char *str; { lpnt = lpbuf; lpend = lpbuf + BUFBIG; if (str == NULL) return(lfd = 1); if ((lfd = open(str, O_RDWR|O_APPEND)) < 0) { lfd = 1; return(-1); } lseek(lfd,0,2); /* go to the end-of-file */ return(lfd); } /* * lrclose() close the input file * * Returns nothing of value. */ lrclose() { if (fd > 0) close(fd); } /* * lwclose() close output file flushing if needed * * Returns nothing of value. */ lwclose() { lflush(); if (lfd > 2) close(lfd); } /* * lprcat(string) append a string to the output buffer * avoids calls to lprintf(time consuming) */ lprcat(str) register char *str; { register char *str2; if (lpnt >= lpend) lflush(); str2 = lpnt; while(*str2++ = *str++); lpnt = str2 - 1; } #ifdef VT100 /* * cursor(x,y) Subroutine to set the cursor position * * x and y are the cursor coordinates, and lpbuff is the output buffer where * escape sequence will be placed. */ static char *y_num[] = { "\33[", "\33[", "\33[2", "\33[3", "\33[4", "\33[5", "\33[6", "\33[7", "\33[8", "\33[9", "\33[10", "\33[11", "\33[12", "\33[13", "\33[14", "\33[15", "\33[16", "\33[17", "\33[18", "\33[19", "\33[20", "\33[21", "\33[22", "\33[23", "\33[24" }; static char *x_num[] = { "H", "H", ";2H", ";3H", ";4H", ";5H", ";6H", ";7H", ";8H", ";9H", ";10H", ";11H", ";12H", ";13H", ";14H", ";15H", ";16H", ";17H", ";18H", ";19H", ";20H", ";21H", ";22H", ";23H", ";24H", ";25H", ";26H", ";27H", ";28H", ";29H", ";30H", ";31H", ";32H", ";33H", ";34H", ";35H", ";36H", ";37H", ";38H", ";39H", ";40H", ";41H", ";42H", ";43H", ";44H", ";45H", ";46H", ";47H", ";48H", ";49H", ";50H", ";51H", ";52H", ";53H", ";54H", ";55H", ";56H", ";57H", ";58H", ";59H", ";60H", ";61H", ";62H", ";63H", ";64H", ";65H", ";66H", ";67H", ";68H", ";69H", ";70H", ";71H", ";72H", ";73H", ";74H", ";75H", ";76H", ";77H", ";78H", ";79H", ";80H" }; cursor(x, y) int x,y; { register char *p; if (lpnt >= lpend) lflush(); p = y_num[y]; /* get the string to print */ while(*p) *lpnt++ = *p++; /* print the string */ p = x_num[x]; /* get the string to print */ while(*p) *lpnt++ = *p++; /* print the string */ } #else VT100 /* * cursor(x,y) Put cursor at specified coordinates starting at [1,1](termcap) */ cursor(x, y) int x,y; { if (lpnt >= lpend) lflush(); *lpnt++ = CURSOR; *lpnt++ = x; *lpnt++ = y; } #endif VT100 /* * Routine to position cursor at beginning of 24th line */ cursors() { cursor(1, 24); } #ifndef VT100 /* * Warning: ringing the bell is control code 7. Don't use in defines. * Don't change the order of these defines. * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with * obvious meanings. */ static char cap[256]; char *CM, *CE, *CD, *CL, *SO, *SE, *AL, *DL; /* Termcap capabilities */ static char *outbuf = 0; /* translated output buffer */ int writechar(); /* * init_term() Terminal initialization -- setup termcap info */ init_term() { char termbuf[1024]; char *capptr = cap + 10; char *term; switch(tgetent(termbuf, term = getenv("TERM"))) { case -1: write(2, "Cannot open termcap file.\n", 26); exit(); case 0: write(2, "Cannot find entry of ", 21); write(2, term, strlen(term)); write(2, " in termcap\n", 12); exit(); }; CM = tgetstr("cm", &capptr);/* Cursor motion */ CE = tgetstr("ce", &capptr);/* Clear to eoln */ CL = tgetstr("cl", &capptr);/* Clear screen */ /* OPTIONAL */ AL = tgetstr("al", &capptr);/* Insert line */ DL = tgetstr("dl", &capptr);/* Delete line */ SO = tgetstr("so", &capptr);/* Begin standout mode */ SE = tgetstr("se", &capptr);/* End standout mode */ CD = tgetstr("cd", &capptr);/* Clear to end of display */ if (!CM) { /* can't find cursor motion entry */ write(2, "Sorry, for a ", 13); write(2, term, strlen(term)); write(2, ", I can't find the cursor motion entry in termcap\n", 50); exit(); } if (!CE) { /* can't find clear to end of line entry */ write(2, "Sorry, for a ", 13); write(2, term, strlen(term)); write(2, ", I can't find the clear to end of line entry in termcap\n", 57); exit(); } if (!CL) { /* can't find clear entire screen entry */ write(2, "Sorry, for a ", 13); write(2, term, strlen(term)); write(2, ", I can't find the clear entire screen entry in termcap\n", 56); exit(); } /* get memory for decoded output buffer */ if ((outbuf = malloc(BUFBIG + 16)) == 0) { write(2, "Error malloc'ing memory for decoded output buffer\n", 50); died(-285); /* malloc() failure */ } } #endif VT100 /* * cl_line(x,y) Clear the whole line indicated by 'y' and leave cursor at [x,y] */ cl_line(x, y) int x,y; { #ifdef VT100 cursor(x, y); lprcat("\33[2K"); #else VT100 cursor(1, y); *lpnt++ = CL_LINE; cursor(x, y); #endif VT100 } /* * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y] */ cl_up(x, y) register int x,y; { #ifdef VT100 cursor(x, y); lprcat("\33[1J\33[2K"); #else VT100 register int i; cursor(1, 1); for(i = 1; i <= y; i++) { *lpnt++ = CL_LINE; *lpnt++ = '\n'; } cursor(x, y); #endif VT100 } /* * cl_dn(x,y) Clear screen from [1,y] to end of display. Leave cursor at [x,y] */ cl_dn(x, y) register int x,y; { #ifdef VT100 cursor(x, y); lprcat("\33[J\33[2K"); #else VT100 register int i; cursor(1, y); if (!CD) { *lpnt++ = CL_LINE; for(i = y; i <= 24; i++) { *lpnt++ = CL_LINE; if (i != 24) *lpnt++ = '\n'; } cursor(x, y); } else *lpnt++ = CL_DOWN; cursor(x, y); #endif VT100 } /* * standout(str) Print the argument string in inverse video(standout mode). */ standout(str) register char *str; { #ifdef VT100 setbold(); while(*str) *lpnt++ = *str++; resetbold(); #else VT100 *lpnt++ = ST_START; while(*str) *lpnt++ = *str++; *lpnt++ = ST_END; #endif VT100 } /* * set_score_output() Called when output should be literally printed. */ set_score_output() { enable_scroll = -1; } /* * lflush() Flush the output buffer * * Returns nothing of value. * For termcap version: Flush output in output buffer according to output * status as indicated by `enable_scroll' */ #ifndef VT100 static int scrline = 18; /* line # for wraparound instead of scrolling if no DL */ lflush() { register int lpoint; register char *str; static int curx = 0; static int cury = 0; if ((lpoint = lpnt - lpbuf) > 0) { #ifdef EXTRA c[BYTESOUT] += lpoint; #endif if (enable_scroll <= -1) { flush_buf(); if (write(lfd, lpbuf, lpoint) != lpoint) write(2, "error writing to output file\n", 29); lpnt = lpbuf; /* point back to beginning of buffer */ return; } for(str = lpbuf; str < lpnt; str++) { if (*str >= 32) { writechar(*str); curx++; } else switch(*str) { case CLEAR: tputs(CL, 0, writechar); curx = cury = 0; break; case CL_LINE: tputs(CE, 0, writechar); break; case CL_DOWN: tputs(CD, 0, writechar); break; case ST_START: tputs(SO, 0, writechar); break; case ST_END: tputs(SE, 0, writechar); break; case CURSOR: curx = *++str - 1; cury = *++str - 1; tputs(tgoto(CM, curx, cury), 0, writechar); break; case '\n': if ((cury == 23) && enable_scroll) { if (!DL || !AL) {/* wraparound or scroll? */ if (++scrline > 23) scrline = 19; if (++scrline > 23) scrline = 19; tputs(tgoto(CM, 0, scrline), 0, writechar); tputs(CE, 0, writechar); if (--scrline < 19) scrline = 23; tputs(tgoto(CM, 0, scrline), 0, writechar); tputs(CE, 0, writechar); } else { tputs(tgoto(CM, 0, 19), 0, writechar); tputs(DL, 0, writechar); tputs(tgoto(CM, 0, 23), 0, writechar); /* tputs(AL, 0, writechar); */ } } else { writechar('\n'); cury++; } curx = 0; break; default: writechar(*str); curx++; }; } } lpnt = lpbuf; flush_buf(); /* flush real output buffer now */ } #else VT100 /* * lflush() flush the output buffer * * Returns nothing of value. */ lflush() { register int lpoint; if ((lpoint = lpnt - lpbuf) > 0) { #ifdef EXTRA c[BYTESOUT] += lpoint; #endif if (write(lfd, lpbuf, lpoint) != lpoint) write(2, "error writing to output file\n", 29); } lpnt = lpbuf; /* point back to beginning of buffer */ } #endif VT100 #ifndef VT100 static int index = 0; /* * writechar(ch) Print one character in decoded output buffer. */ int writechar(c) int c; { outbuf[index++] = c; if (index >= BUFBIG) flush_buf(); } /* * flush_buf() Flush buffer with decoded output. */ flush_buf() { if (index) write(lfd, outbuf, index); index = 0; } /* * char *tmcapcnv(sd,ss) Routine to convert VT100 escapes to termcap format * * Processes only the \33[#m sequence(converts . files for termcap use) */ char *tmcapcnv(sd, ss) register char *sd,*ss; { register int tmstate = 0; /* 0=normal, 1=\33 2=[ 3=# */ char *sdptr,tmdigit = 0; /* the # in \33[#m */ sdptr = sd; while(*ss) { switch(tmstate) { case 0: if (*ss == '\33') { tmstate++; break; } ign: *sdptr++ = *ss; ign2: tmstate = 0; break; case 1: if (*ss != '[') goto ign; tmstate++; break; case 2: if (isdigit(*ss)) { tmdigit = *ss - '0'; tmstate++; break; } if (*ss == 'm') { *sdptr++ = ST_END; goto ign2; } goto ign; case 3: if (*ss == 'm') { if (tmdigit) *sdptr++ = ST_START; else *sdptr++ = ST_END; goto ign2; } default: goto ign; }; ss++; } *sdptr = 0; /* NULL terminator */ return(sd); } #endif VT100 /* * beep() Routine to emit a beep if enabled(see no-beep in larn.opt) */ beep() { if (!nobeep) *lpnt++ = '\7'; } SHAR_EOF if test 22021 -ne "`wc -c < 'io.c'`" then echo shar: error transmitting "'io.c'" '(should have been 22021 characters)' fi fi # end of overwriting check echo shar: extracting "'keysense.c'" '(7755 characters)' if test -f 'keysense.c' then echo shar: will not over-write existing file "'keysense.c'" else cat << \SHAR_EOF > 'keysense.c' /* * MODULE NAME : KEYSENSE * MODULE TYPE : Implementation * * DESCRIPTION: * This module declares three functions that, together, make it possible to * to sense single keypresses in VAX/VMS. There is an enable routine, a * disable routine, and the actual sensing routine. The sensing routine is * synchronous - that is, it waits until a key is pressed before continuing * with the program. * * IMPLEMENTED BY: * Mark D. Nagel (Original code by Dave Conroy) * Department of Internal Medicine * Section of Infectious and Immunologic Diseases * University of California, Davis * Davis, CA 95616 * * LAST MODIFIED : 27 May 1986 * * REVISION HISTORY - Version 1.00 */ #include <stdio.h> #include <ctype.h> #include <stsdef.h> #include <ssdef.h> #include <descrip.h> #include <iodef.h> #include <ttdef.h> #include <tt2def.h> #define EOS '\0' #define ESC '\33' #define TRUE 1 #define FALSE 0 /* * GLOBAL VARIABLES * * DESCRIPTION: * The variables declared here are used globally throughout this module. * They relate to I/O buffering and channel information. */ #define NIBUF 128 /* Size of input buffer */ #define EFN 0 /* Event flag number */ char ibuf[NIBUF]; /* Input buffer */ int nibuf = 0; /* # of bytes in above */ int ibufi = 0; /* Read index */ int oldmode[3]; /* Old TTY mode bits */ int newmode[3]; /* New TTY mode bits */ short iochan; /* TTY I/O channel */ static short keysense_on = FALSE; /* * FUNCTION NAME: KeySense_On() * * DESCRIPTION: * This function assigns a channel to SYS$COMMAND on VAX/VMS and sets it * to raw mode so that single keypresses may be sensed. * * RETURN VALUE: None. */ void KeySense_On() { struct dsc$descriptor idsc; struct dsc$descriptor odsc; char oname[40]; int iosb[2]; int status; if (!keysense_on) { odsc.dsc$a_pointer = "SYS$COMMAND"; odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); odsc.dsc$b_dtype = DSC$K_DTYPE_T; odsc.dsc$b_class = DSC$K_CLASS_S; idsc.dsc$b_dtype = DSC$K_DTYPE_T; idsc.dsc$b_class = DSC$K_CLASS_S; do { idsc.dsc$a_pointer = odsc.dsc$a_pointer; idsc.dsc$w_length = odsc.dsc$w_length; odsc.dsc$a_pointer = &oname[0]; odsc.dsc$w_length = sizeof(oname); status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); if (status != SS$_NORMAL && status != SS$_NOTRAN) exit(status); if (oname[0] == 0x1B) { odsc.dsc$a_pointer += 4; odsc.dsc$w_length -= 4; } } while (status == SS$_NORMAL); status = SYS$ASSIGN(&odsc, &iochan, 0, 0); if (status != SS$_NORMAL) exit(status); status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL) exit(status); newmode[0] = oldmode[0]; /* Only in version 4. */ newmode[1] = oldmode[1] | TT$M_NOECHO | TT$M_TTSYNC; newmode[2] = oldmode[2] | TT2$M_PASTHRU; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0); if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL) exit(status); keysense_on = TRUE; } } /* * FUNCTION NAME: KeySense(wait) * * DESCRIPTION: * This function will return the next key typed at the terminal if the * function 'KeySense_On' has been executed. The character is returned * synchronously - that is, the program will hang until a key is pressed if * the parameter 'wait' is TRUE. Otherwise, the routine will return the * last key presses or -1 if no key was pressed. * * RETURN VALUE: Single character or -1. */ char KeySense(wait) int wait; { int status; int iosb[2]; int term[2]; if (keysense_on) { term[0] = 0; term[1] = 0; while (ibufi >= nibuf) { ibufi = 0; status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); if (status != SS$_NORMAL) continue; status = iosb[0] & 0xFFFF; if (status != SS$_NORMAL && status != SS$_TIMEOUT) continue; nibuf = (iosb[0]>>16) + (iosb[1]>>16); if (nibuf == 0) { if (wait) { status = SYS$QIOW(EFN, iochan, IO$_READLBLK, iosb, 0, 0, ibuf, 1, 0, term, 0, 0); if (status != SS$_NORMAL) continue; if ((iosb[0] & 0xFFFF) != SS$_NORMAL) continue; nibuf = (iosb[0]>>16) + (iosb[1]>>16); } else { lib$wait(&0.10); return (-1); } } } if (ibuf[ibufi] == 0x0A || ibuf[ibufi] == 0x0D) ibuf[ibufi] = '\n'; return (ibuf[ibufi++] & 0xFF); } } /* * FUNCTION NAME: Check_KeySense() * * DESCRIPTION: * This function will return TRUE if keysense is currently on and FALSE * if it is not. * * RETURN VALUE: Boolean. */ int Check_KeySense() { return(keysense_on); } /* * FUNCTION NAME: KeySense_Off() * * DESCRIPTION: * This function disables the single keypress input mode. * * RETURN VALUE: None. */ void KeySense_Off() { int status; int iosb[1]; if (keysense_on) { status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL) exit(status); status = SYS$DASSGN(iochan); if (status != SS$_NORMAL) exit(status); keysense_on = FALSE; } } /* * FUNCTION NAME: system(cmd) * * DESCRIPTION: * Run a command. The "cmd" is a pointer to a command string, or NULL if * you want to run a copy of DCL in the subjob (this is how the standard * routine LIB$SPAWN works. You have to do weird stuff with the terminal * on the way in and the way out if KeySense is on, because DCL does not * want the channel to be in raw mode. * * RETURN VALUE: None. */ system(cmd) register char *cmd; { struct dsc$descriptor cdsc; struct dsc$descriptor *cdscp; long status; long substatus; long iosb[2]; if (keysense_on) { status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL) return (FALSE); } cdscp = NULL; /* Assume DCL. */ if (cmd != NULL) { /* Build descriptor. */ cdsc.dsc$a_pointer = cmd; cdsc.dsc$w_length = strlen(cmd); cdsc.dsc$b_dtype = DSC$K_DTYPE_T; cdsc.dsc$b_class = DSC$K_CLASS_S; cdscp = &cdsc; } status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0); if (status != SS$_NORMAL) substatus = status; if (keysense_on) { status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0); if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL) return (FALSE); } if ((substatus & STS$M_SUCCESS) == 0) /* Command failed. */ return (FALSE); return (TRUE); } /* * FUNCTION NAME: getpass(prompt) * * DESCRIPTION: * Read a password from the keyboard with echoing turned off. The password * must be terminated by a CR. This CR will become a NUL. The password * is stored statically, so if it is necessary to keep it you must copy * it. * * RETURN VALUE: pointer to string or NULL if this is an invalid device. */ #define MAXBUF 100 char *getpass(prompt) char *prompt; { static char inbuf[MAXBUF+1]; char ch, KeySense(); int i = 0, was_on; was_on = keysense_on; if (isatty(stdin)) { puts(prompt); KeySense_On(); while (1) { ch = KeySense(1); if ((ch == 0x7F || ch == 0x08) && i > 0) --i; else if (ch == 0x0A || ch == 0x0D) break; else if (i >= MAXBUF - 1) continue; else if (isprint(ch)) inbuf[i++] = ch; } inbuf[i] = '\0'; if (!was_on) KeySense_Off(); return(inbuf); } return(NULL); } SHAR_EOF if test 7755 -ne "`wc -c < 'keysense.c'`" then echo shar: error transmitting "'keysense.c'" '(should have been 7755 characters)' fi fi # end of overwriting check echo shar: extracting "'larn.c'" '(28359 characters)' if test -f 'larn.c' then echo shar: will not over-write existing file "'larn.c'" else cat << \SHAR_EOF > 'larn.c' /* main.c */ #include "header.h" #include <times.h> #ifndef LARNHOME #define LARNHOME "SYS$GAMES:" /* normally supplied by a Makefile */ #endif #ifndef WIZID #define WIZID 0 #endif #define MAXFILENAMESIZE 128 /* * All these strings will be appended to in main() to be complete filenames */ /* the game save filename */ globaldef char savefilename[SAVEFILENAMESIZE]; /* the score file */ globaldef char scorefile[255]; /* the logging file */ globaldef char logfile[255]; /* the help text file */ globaldef char helpfile[255]; /* the maze data file */ globaldef char larnlevels[255]; /* the fortune data file */ globaldef char fortfile[255]; /* the larn.opt filename */ globaldef char optsfile[255]; /* the player id datafile name */ globaldef char playerids[255]; /* the holiday datafile */ globaldef char holifile[255]; globaldef char diagfile[] = "LARN12.DBG"; /* the diagnostic filename */ globaldef char ckpfile[] = "LARN12.CKP"; /* the checkpoint filename */ globaldef char *password = "pvnert(x)"; /* the wizards password <=32 */ #if WIZID == -1 globaldef int wisid = 0; /* the user id of the only person who can be wizard */ #else globaldef int wisid = WIZID; /* the user id of the only person who can be wizard */ #endif static char copyright[] = "\nLarn is copyrighted 1986 by Noah Morgan.\n"; globaldef int srcount = 0; /* line counter for showstr() */ globaldef int dropflag = 0; /* if 1 then don't lookforobject() next round */ int rmst = 80; /* random monster creation counter */ globaldef int userid; /* the players login user id number */ globaldef char nowelcome = 0; globaldef char nomove = 0; /* if (nomove) then don't count next iteration as a move */ globaldef long start_cpu; static char viewflag = 0; /* if viewflag then we have done a 99 stay here and don't showcell in the main loop */ globaldef char restorflag = 0; /* 1 means restore has been done */ static char cmdhelp[] = "\ Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\ -s show the scoreboard\n\ -l show the logfile\n\ -i show scoreboard with inventory of checkpoint file\n\ -c clear the scoreboard file (requires password)\n\ -h print this help message\n\ -o<optsfile> specify option filename to be used instead of LARN12.OPT\n\ -## set the difficulty level to ##\n\ ++ restore a checkpointed game\n\ "; #ifdef VT100 static char *termtypes[] = { "vt100-80", "vt100","vt101", "vt102", "vt103", "vt125", "vt131", "vt140" }; #endif VT100 main(argc, argv) int argc; char **argv; { register int i,j; int hard; char *ptr = 0, *ttype; struct tms cputime; /* * first task is to identify the player */ #ifndef VT100 init_term(); /* setup the terminal(find out what type) for termcap */ #endif VT100 if ((ptr = getenv("USER")) == 0) if ((ptr = getenv("LOGNAME")) == 0) { write(2, "Can't find your logname. Who Are You?\n", 39); exit(); } times(&cputime); /* need to know what it was */ start_cpu = cputime.tms_utime + cputime.tms_stime; /* * now malloc the memory for the buffers */ lpbuf = malloc((5 * BUFBIG) >> 2);/* output buffer */ inbuffer = malloc((5 * MAXIBUF) >> 2);/* output buffer */ if ((lpbuf == 0) ||(inbuffer == 0)) died(-285); /* malloc() failure */ lcreat((char *) 0); newgame(); /* set the initial clock */ for (i = 0; i < MAXLEVEL+MAXVLEVEL; beenhere[i++] = 0); hard = -1; /* * second task is to prepare the pathnames the player will need */ strcpy(loginname, ptr);/* save loginname of the user for logging purposes */ strcpy(logname, ptr); /* this will be overwritten with the players name */ if ((ptr = getenv("HOME")) == 0) ptr = "[]"; #ifdef SAVEINHOME sprintf(savefilename,"%sLARN12.SAV",ptr); #else sprintf(savefilename,%s%s.SAV",LARNHOME,logname); /* prepare savefile name */ #endif sprintf(optsfile, "%sLARN12.OPT", ptr); /* the larn.opt filename */ sprintf(scorefile,"%s%s",LARNHOME,SCORENAME); /* the larn scoreboard filename */ sprintf(logfile,"%s%s",LARNHOME,LOGFNAME); /* larn activity logging filename */ sprintf(helpfile,"%s%s",LARNHOME,HELPNAME); /* the larn on-line help file */ sprintf(larnlevels,"%s%s",LARNHOME,LEVELSNAME); /* the pre-made cave level data file */ sprintf(fortfile,"%s%s",LARNHOME,FORTSNAME); /* the fortune data file name */ sprintf(playerids,"%s%s",LARNHOME,PLAYERIDS); /* the playerid data file name */ sprintf(holifile,"%s%s",LARNHOME,HOLIFILE); /* the holiday data file name */ #ifdef VT100 /* * check terminal type to avoid users who have not vt100 type terminals */ ttype = getenv("TERM"); for (j = 1, i = 0; i < sizeof(termtypes) / sizeof(char *); i++) if (strcmp(ttype, termtypes[i]) == 0) { j = 0; break; } if (j) { lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n"); lflush(); exit(); } #endif VT100 /* * now make scoreboard if it is not there (don't clear) */ if (access(scorefile, 0) == -1)/* not there */ makeboard(); /* * now process the command line arguments */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') switch(argv[i][1]) { case 's': /* show scoreboard */ showscores(); exit(); case 'l': /* show log file */ diedlog(); exit(); case 'i': /* show all scoreboard */ showallscores(); exit(); case 'c': /* anyone with password can create scoreboard */ lprcat("Preparing to initialize the scoreboard.\n"); if (getpassword() != 0) { /* make new scoreboard */ makeboard(); lprc('\n'); showscores(); } exit(); case 'n': /* no welcome msg */ nowelcome = 1; argv[i][0] = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* for hardness */ sscanf(&argv[i][1], "%d", &hard); break; case 'h': /* print out command line arguments */ write(1, cmdhelp, sizeof(cmdhelp)); exit(); case 'o': /* specify a larn.opt filename */ strncpy(optsfile, argv[i] + 2, 127); break; default: printf("Unknown option <%s>\n", argv[i]); exit(); }; if (argv[i][0] == '+') { clear(); restorflag = 1; if (argv[i][1] == '+') { hitflag = 1; restoregame(ckpfile);/* restore checkpointed game */ } i = argc; } } readopts(); /* read the options file if there is one */ #ifdef UIDSCORE userid = (getegid()<<16) | geteuid(); /* obtain the user's id number */ #else UIDSCORE userid = getplid(logname); /* obtain the players id number */ if (userid < 0) { write(2, "Can't obtain playerid\n", 22); exit(1); } #endif UIDSCORE #ifdef TIMECHECK /* * this section of code checks to see if larn is allowed during working hours */ if (dayplay == 0) /* check for not-during-daytime-hours */ if (playable()) { write(2, "Sorry, Larn can not be played during working hours.\n", 52); exit(); } #endif TIMECHECK if (access(savefilename, 0) == 0) { /* restore game if need to */ clear(); restorflag = 1; hitflag = 1; restoregame(savefilename);/* restore last game */ } sigsetup(); /* trap all needed signals */ sethard(hard); /* set up the desired difficulty */ setupvt100(); /* setup the terminal special mode */ if (c[HP] == 0) { /* create new game */ makeplayer(); /* make the character that will play */ newcavelevel(0); /* make the dungeon */ predostuff = 1; /* tell signals that we are in the welcome screen */ if (nowelcome == 0) welcome(); /* welcome the player to the game */ } drawscreen(); /* show the initial dungeon */ predostuff = 2; /* tell the trap functions that they must do a showplayer() from here on */ nice(1); /* games should be run niced */ yrepcount = hit2flag = 0; while (1) { if (dropflag == 0) lookforobject(); /* see if there is an object here */ else dropflag = 0; /* don't show it just dropped an item */ if (hitflag == 0) { if (c[HASTEMONST]) movemonst(); movemonst(); } /* move the monsters */ if (viewflag == 0) showcell(playerx, playery); else viewflag = 0; /* show stuff around player */ if (hit3flag) flushall(); hitflag = hit3flag = 0; nomove = 1; bot_linex(); /* update bottom line */ while (nomove) { if (hit3flag) flushall(); nomove = 0; parse(); } /* get commands and make moves */ regen(); /* regenerate hp and spells */ if (c[TIMESTOP] == 0) if (--rmst <= 0) { rmst = 120 - (level << 2); fillmonst(makemonst(level)); } } } /* showstr() show character's inventory */ showstr() { register int i,number; for (number = 3, i = 0; i < 26; i++) if (iven[i]) number++; /* count items in inventory */ t_setup(number); qshowstr(); t_endup(number); } qshowstr() { register int i,j,k,sigsav; srcount = 0; sigsav = nosignal; nosignal = 1; /* don't allow ^C etc */ if (c[GOLD]) { lprintf(".) %d gold pieces",(long) c[GOLD]); srcount++; } for (k = 26; k >= 0; k--) if (iven[k]) { for (i = 22; i < 84; i++) for (j = 0; j <= k; j++) if (i == iven[j]) show3(j); k = 0; } lprintf("\nElapsed time is %d. You have %d mobuls left",(long)((gtime + 99) / 100 + 1),(long)((TIMELIMIT - gtime) / 100)); more(); nosignal = sigsav; } /* * subroutine to clear screen depending on # lines to display */ t_setup(count) register int count; { if (count < 20) { /* how do we clear the screen? */ cl_up(79, count); cursor(1, 1); } else { resetscroll(); clear(); } } /* * subroutine to restore normal display screen depending on t_setup() */ t_endup(count) register int count; { if (count < 18) /* how did we clear the screen? */ draws(0, MAXX, 0,(count > MAXY) ? MAXY : count); else { drawscreen(); setscroll(); } } /* function to show the things player is wearing only */ showwear() { register int i,j,sigsav,count; sigsav = nosignal; nosignal = 1; /* don't allow ^c etc */ srcount = 0; for (count = 2, j = 0; j <= 26; j++)/* count number of items we will display */ if (i = iven[j]) switch(i) { case OLEATHER: case OPLATE: case OCHAIN: case ORING: case OSTUDLEATHER: case OSPLINT: case OPLATEARMOR: case OSSPLATE: case OSHIELD: count++; }; t_setup(count); for (i = 22; i < 84; i++) for (j = 0; j <= 26; j++) if (i == iven[j]) switch(i) { case OLEATHER: case OPLATE: case OCHAIN: case ORING: case OSTUDLEATHER: case OSPLINT: case OPLATEARMOR: case OSSPLATE: case OSHIELD: show3(j); }; more(); nosignal = sigsav; t_endup(count); } /* function to show the things player can wield only */ showwield() { register int i,j,sigsav,count; sigsav = nosignal; nosignal = 1; /* don't allow ^c etc */ srcount = 0; for (count = 2, j = 0; j <= 26; j++)/* count how many items */ if (i = iven[j]) switch(i) { case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT: case OSPIRITSCARAB: case OCUBEofUNDEAD: case OPOTION: case OSCROLL: break; default: count++; }; t_setup(count); for (i = 22; i < 84; i++) for (j = 0; j <= 26; j++) if (i == iven[j]) switch(i) { case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: case OBOOK: case OCHEST: case OLARNEYE: case ONOTHEFT: case OSPIRITSCARAB: case OCUBEofUNDEAD: case OPOTION: case OSCROLL: break; default: show3(j); }; more(); nosignal = sigsav; t_endup(count); } /* * function to show the things player can read only */ showread() { register int i,j,sigsav,count; sigsav = nosignal; nosignal = 1; /* don't allow ^c etc */ srcount = 0; for (count = 2, j = 0; j <= 26; j++) switch(iven[j]) { case OBOOK: case OSCROLL: count++; }; t_setup(count); for (i = 22; i < 84; i++) for (j = 0; j <= 26; j++) if (i == iven[j]) switch(i) { case OBOOK: case OSCROLL: show3(j); }; more(); nosignal = sigsav; t_endup(count); } /* * function to show the things player can eat only */ showeat() { register int i,j,sigsav,count; sigsav = nosignal; nosignal = 1; /* don't allow ^c etc */ srcount = 0; for (count = 2, j = 0; j <= 26; j++) switch(iven[j]) { case OCOOKIE: count++; }; t_setup(count); for (i = 22; i < 84; i++) for (j = 0; j <= 26; j++) if (i == iven[j]) switch(i) { case OCOOKIE: show3(j); }; more(); nosignal = sigsav; t_endup(count); } /* function to show the things player can quaff only */ showquaff() { register int i,j,sigsav,count; sigsav = nosignal; nosignal = 1; /* don't allow ^c etc */ srcount = 0; for (count = 2, j = 0; j <= 26; j++) switch(iven[j]) { case OPOTION: count++; }; t_setup(count); for (i = 22; i < 84; i++) for (j = 0; j <= 26; j++) if (i == iven[j]) switch(i) { case OPOTION: show3(j); }; more(); nosignal = sigsav; t_endup(count); } show1(idx, str2) register int idx; register char *str2[]; { if (str2 == 0) lprintf("\n%c) %s", idx + 'a', objectname[iven[idx]]); else if (*str2[ivenarg[idx]] == 0) lprintf("\n%c) %s", idx + 'a', objectname[iven[idx]]); else lprintf("\n%c) %s of%s", idx + 'a', objectname[iven[idx]], str2[ivenarg[idx]]); } show3(index) register int index; { switch(iven[index]) { case OPOTION: show1(index, potionname); break; case OSCROLL: show1(index, scrollname); break; case OLARNEYE: case OBOOK: case OSPIRITSCARAB: case ODIAMOND: case ORUBY: case OCUBEofUNDEAD: case OEMERALD: case OCHEST: case OCOOKIE: case OSAPPHIRE: case ONOTHEFT: show1(index,(char **) 0); break; default: lprintf("\n%c) %s", index + 'a', objectname[iven[index]]); if (ivenarg[index] > 0) lprintf(" + %d",(long) ivenarg[index]); else if (ivenarg[index] < 0) lprintf(" %d",(long) ivenarg[index]); break; } if (c[WIELD] == index) lprcat("(weapon in hand)"); if ((c[WEAR] == index) ||(c[SHIELD] == index)) lprcat("(being worn)"); if (++srcount >= 22) { srcount = 0; more(); clear(); } } /* subroutine to randomly create monsters if needed */ randmonst() { if (c[TIMESTOP]) return; /* don't make monsters if time is stopped */ if (--rmst <= 0) { rmst = 120 - (level << 2); fillmonst(makemonst(level)); } } /* parse() get and execute a command */ parse() { register int i,j,k,flag; while (1) { k = yylex(); switch(k) { /* get the token from the input and switch on it */ case 'h': moveplayer(4); return; /* west */ case 'H': run(4); return; /* west */ case 'l': moveplayer(2); return; /* east */ case 'L': run(2); return; /* east */ case 'j': moveplayer(1); return; /* south */ case 'J': run(1); return; /* south */ case 'k': moveplayer(3); return; /* north */ case 'K': run(3); return; /* north */ case 'u': moveplayer(5); return; /* northeast */ case 'U': run(5); return; /* northeast */ case 'y': moveplayer(6); return; /* northwest */ case 'Y': run(6); return; /* northwest */ case 'n': moveplayer(7); return; /* southeast */ case 'N': run(7); return; /* southeast */ case 'b': moveplayer(8); return; /* southwest */ case 'B': run(8); return; /* southwest */ case '.': /* stay here */ if (yrepcount) viewflag = 1; return; case 'w': /* wield a weapon */ yrepcount = 0; wield(); return; case 'W': /* wear armor */ yrepcount = 0; wear(); return; case 'r': /* to read a scroll */ yrepcount = 0; if (c[BLINDCOUNT]) { cursors(); lprcat("\nYou can't read anything when you're blind!"); } else if (c[TIMESTOP] == 0) readscr(); return; case 'q': /* quaff a potion */ yrepcount = 0; if (c[TIMESTOP] == 0) quaff(); return; case 'd': /* to drop an object */ yrepcount = 0; if (c[TIMESTOP] == 0) dropobj(); return; case 'c': /* cast a spell */ yrepcount = 0; cast(); return; case 'i': /* status */ yrepcount = 0; nomove = 1; showstr(); return; case 'e': /* to eat a fortune cookie */ yrepcount = 0; if (c[TIMESTOP] == 0) eatcookie(); return; case 'D': /* list spells and scrolls */ yrepcount = 0; seemagic(0); nomove = 1; return; case '?': /* give the help screen */ yrepcount = 0; help(); nomove = 1; return; case 'S': /* save the game - doesn't return */ clear(); lprcat("Saving . . ."); lflush(); savegame(savefilename); wizard = 1; died(-257); case 'Z': yrepcount = 0; if (c[LEVEL] > 9) { oteleport(1); return; } cursors(); lprcat("\nAs yet, you don't have enough experience to use teleportation"); return; /* teleport yourself */ case '^': /* identify traps */ flag = yrepcount = 0; cursors(); lprc('\n'); for (j = playery - 1; j < playery + 2; j++) { if (j < 0) j = 0; if (j >= MAXY) break; for (i = playerx - 1; i < playerx + 2; i++) { if (i < 0) i = 0; if (i >= MAXX) break; switch(item[i][j]) { case OTRAPDOOR: case ODARTRAP: case OTRAPARROW: case OTELEPORTER: lprcat("\nIts "); lprcat(objectname[item[i][j]]); flag++; }; } } if (flag == 0) lprcat("\nNo traps are visible"); return; #if WIZID case '_': /* this is the fudge player password for wizard mode */ yrepcount = 0; cursors(); nomove = 1; if (userid != wisid) { lprcat("Sorry, you are not empowered to be a wizard.\n"); scbr(); /* system("stty -echo cbreak"); */ lflush(); return; } if (getpassword() == 0) { scbr(); /* system("stty -echo cbreak"); */ return; } wizard = 1; scbr(); /* system("stty -echo cbreak"); */ for (i = 0; i < 6; i++) c[i] = 70; iven[0] = iven[1] = 0; take(OPROTRING, 50); take(OLANCE, 25); c[WIELD] = 1; c[LANCEDEATH] = 1; c[WEAR] = c[SHIELD] = -1; raiseexperience(6000000L); c[AWARENESS] += 25000; { register int i,j; for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) know[j][i] = 1; for (i = 0; i < SPNUM; i++) spelknow[i] = 1; for (i = 0; i < MAXSCROLL; i++) scrollname[i][0] = ' '; for (i = 0; i < MAXPOTION; i++) potionname[i][0] = ' '; } for (i = 0; i < MAXSCROLL; i++) if (strlen(scrollname[i]) > 2) { /* no null items */ item[i][0] = OSCROLL; iarg[i][0] = i; } for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--) if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) {/* no null items */ item[i][0] = OPOTION; iarg[i][0] = i - MAXX + MAXPOTION; } for (i = 1; i < MAXY; i++) { item[0][i] = i; iarg[0][i] = 0; } for (i = MAXY; i < MAXY + MAXX; i++) { item[i - MAXY][MAXY - 1] = i; iarg[i - MAXY][MAXY - 1] = 0; } for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) { item[MAXX - 1][i - MAXX - MAXY] = i; iarg[MAXX - 1][i - MAXX - MAXY] = 0; } c[GOLD] += 250000; drawscreen(); return; #endif case 'T': yrepcount = 0; cursors(); if (c[SHIELD] != -1) { c[SHIELD] = -1; lprcat("\nYour shield is off"); bottomline(); } else if (c[WEAR] != -1) { c[WEAR] = -1; lprcat("\nYour armor is off"); bottomline(); } else lprcat("\nYou aren't wearing anything"); return; case 'g': cursors(); lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long) packweight()); case ' ': yrepcount = 0; nomove = 1; return; case 'v': yrepcount = 0; cursors(); lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long) VERSION,(long) SUBVERSION,(long) c[HARDGAME]); if (wizard) lprcat(" Wizard"); nomove = 1; if (cheat) lprcat(" Cheater"); lprcat(copyright); return; case 'Q': /* quit */ case 'Y'-64: case 'C'-64: yrepcount = 0; quit(); nomove = 1; return; case 'L' - 64: /* look */ yrepcount = 0; drawscreen(); nomove = 1; return; #if WIZID #ifdef EXTRA case 'A': /* create diagnostic file */ yrepcount = 0; nomove = 1; if (wizard) { diag(); return; } return; #endif #endif case 'P': cursors(); if (outstanding_taxes > 0) lprintf("\nYou presently owe %d gp in taxes.",(long) outstanding_taxes); else lprcat("\nYou do not owe any taxes."); return; }; } } parse2() { if (c[HASTEMONST]) movemonst(); movemonst(); /* move the monsters */ randmonst(); regen(); } run(dir) int dir; { register int i = 1; while (i) { i = moveplayer(dir); if (i > 0) { if (c[HASTEMONST]) movemonst(); movemonst(); randmonst(); regen(); } if (hitflag) i = 0; if (i != 0) showcell(playerx, playery); } } /* function to wield a weapon */ wield() { register int i; while (1) { if ((i = whatitem("wield")) == '\33') return; if (i != '.') { if (i == '*') showwield(); else if (iven[i - 'a'] == 0) { ydhi(i); return; } else if (iven[i - 'a'] == OPOTION) { ycwi(i); return; } else if (iven[i - 'a'] == OSCROLL) { ycwi(i); return; } else if ((c[SHIELD] != -1) &&(iven[i - 'a'] == O2SWORD)) { lprcat("\nBut one arm is busy with your shield!"); return; } else { c[WIELD] = i - 'a'; if (iven[i - 'a'] == OLANCE) c[LANCEDEATH] = 1; else c[LANCEDEATH] = 0; bottomline(); return; } } } } /* common routine to say you don't have an item */ ydhi(x) int x; { cursors(); lprintf("\nYou don't have item %c!", x); } ycwi(x) int x; { cursors(); lprintf("\nYou can't wield item %c!", x); } /* function to wear armor */ wear() { register int i; while (1) { if ((i = whatitem("wear")) == '\33') return; if (i != '.') { if (i == '*') showwear(); else switch(iven[i - 'a']) { case 0: ydhi(i); return; case OLEATHER: case OCHAIN: case OPLATE: case OSTUDLEATHER: case ORING: case OSPLINT: case OPLATEARMOR: case OSSPLATE: if (c[WEAR] != -1) { lprcat("\nYou're already wearing some armor"); return; } c[WEAR] = i - 'a'; bottomline(); return; case OSHIELD: if (c[SHIELD] != -1) { lprcat("\nYou are already wearing a shield"); return; } if (iven[c[WIELD]] == O2SWORD) { lprcat("\nYour hands are busy with the two handed sword!"); return; } c[SHIELD] = i - 'a'; bottomline(); return; default: lprcat("\nYou can't wear that!"); }; } } } /* function to drop an object */ dropobj() { register int i; register char *p; long amt; p = &item[playerx][playery]; while (1) { if ((i = whatitem("drop")) == '\33') return; if (i == '*') showstr(); else { if (i == '.') { /* drop some gold */ if (*p) { lprcat("\nThere's something here already!"); return; } lprcat("\n\n"); cl_dn(1, 23); lprcat("How much gold do you drop? "); if ((amt = readnum((long) c[GOLD])) == 0) return; if (amt > c[GOLD]) { lprcat("\nYou don't have that much!"); return; } if (amt <= 32767) { *p = OGOLDPILE; i = amt; } else if (amt <= 327670L) { *p = ODGOLD; i = amt / 10; amt = 10 * i; } else if (amt <= 3276700L) { *p = OMAXGOLD; i = amt / 100; amt = 100 * i; } else if (amt <= 32767000L) { *p = OKGOLD; i = amt / 1000; amt = 1000 * i; } else { *p = OKGOLD; i = 32767; amt = 32767000L; } c[GOLD] -= amt; lprintf("You drop %d gold pieces",(long) amt); iarg[playerx][playery] = i; bottomgold(); know[playerx][playery] = 0; dropflag = 1; return; } drop_object(i - 'a'); return; } } } /* * readscr() Subroutine to read a scroll one is carrying */ readscr() { register int i; while (1) { if ((i = whatitem("read")) == '\33') return; if (i != '.') { if (i == '*') showread(); else { if (iven[i - 'a'] == OSCROLL) { read_scroll(ivenarg[i - 'a']); iven[i - 'a'] = 0; return; } if (iven[i - 'a'] == OBOOK) { readbook(ivenarg[i - 'a']); iven[i - 'a'] = 0; return; } if (iven[i - 'a'] == 0) { ydhi(i); return; } lprcat("\nThere's nothing on it to read"); return; } } } } /* * subroutine to eat a cookie one is carrying */ eatcookie() { register int i; char *p; while (1) { if ((i = whatitem("eat")) == '\33') return; if (i != '.') if (i == '*') showeat(); else { if (iven[i - 'a'] == OCOOKIE) { lprcat("\nThe cookie was delicious."); iven[i - 'a'] = 0; if (!c[BLINDCOUNT]) { if (p = fortune(fortfile)) { lprcat(" Inside you find a scrap of paper that says:\n"); lprcat(p); } } return; } if (iven[i - 'a'] == 0) { ydhi(i); return; } lprcat("\nYou can't eat that!"); return; } } } /* * subroutine to quaff a potion one is carrying */ quaff() { register int i; while (1) { if ((i = whatitem("quaff")) == '\33') return; if (i != '.') { if (i == '*') showquaff(); else { if (iven[i - 'a'] == OPOTION) { quaffpotion(ivenarg[i - 'a']); iven[i - 'a'] = 0; return; } if (iven[i - 'a'] == 0) { ydhi(i); return; } lprcat("\nYou wouldn't want to quaff that, would you? "); return; } } } } /* function to ask what player wants to do */ whatitem(str) char *str; { int i; cursors(); lprintf("\nWhat do you want to %s [* for all] ? ", str); i = 0; while (i > 'z' ||(i < 'a' && i != '*' && i != '\33' && i != '.')) i = readchar(); if (i == '\33') lprcat(" aborted"); return(i); } /* subroutine to get a number from the player and allow * to mean return amt, else return the number entered */ unsigned long readnum(mx) long mx; { register int i; register unsigned long amt = 0; sncbr(); if ((i = readchar()) == '*') amt = mx; /* allow him to say * for all gold */ else while (i != '\n') { if (i == '\033') { scbr(); lprcat(" aborted"); return(0); } if ((i <= '9') && (i >= '0') && (amt < 999999999)) amt = amt * 10 + i - '0'; i = readchar(); } scbr(); return(amt); } #ifdef TIMECHECK /* * routine to check the time of day and return 1 if its during work hours * checks the file ".holidays" for forms like "mmm dd comment..." */ int playable() { long g_time,time(); int hour,day,year; char *date,*month,*p; time(&g_time); /* get the time and date */ date = ctime(&g_time); /* format: Fri Jul 4 00:27:56 EDT 1986 */ year = atoi(date + 20); hour = (date[11] - '0') * 10 + date[12] - '0'; day = (date[8] != ' ') ?((date[8] - '0') * 10 + date[9] - '0') :(date[9] - '0'); month = date + 4; date[7] = 0; /* point to and NULL terminate month */ if (((hour >= 8 && hour < 17))/* 8AM - 5PM */ && strncmp("Sat", date, 3) != 0 /* not a Saturday */ && strncmp("Sun", date, 3) != 0) { /* not a Sunday */ /* now check for a .holidays datafile */ lflush(); if (lopen(holifile) >= 0) for (;;) { if ((p = lgetw()) == 0) break; if (strlen(p) < 6) continue; if ((strncmp(p, month, 3) == 0) &&(day == atoi(p + 4)) &&(year == atoi(p + 7))) return(0);/* a holiday */ } lrclose(); lcreat((char *) 0); return(1); } return(0); } #endif TIMECHECK SHAR_EOF if test 28359 -ne "`wc -c < 'larn.c'`" then echo shar: error transmitting "'larn.c'" '(should have been 28359 characters)' fi fi # end of overwriting check echo shar: extracting "'larn12.ftn'" '(1324 characters)' if test -f 'larn12.ftn' then echo shar: will not over-write existing file "'larn12.ftn'" else cat << \SHAR_EOF > 'larn12.ftn' gem value = gem * 2 ^ perfection sitting down can have unexpected results don't pry into the affairs of others drinking can be hazardous to your health beware of the gusher! some monsters are greedy nymphs have light fingers try kissing a disenchantress! hammers and brains don't mix what does a potion of cure dianthroritis taste like? hit point gain/loss when raising a level depends on constitution healing a mighty wizard can be exhilarating be sure to pay your taxes are Vampires afraid of something? some dragons can fly dos thou strive for perfection? patience is a virtue, unless your daughter dies what does the Eye of Larn see in its guardian? a level 25 player casts like crazy! energy rings affect spell regeneration difficulty affects regeneration control of the pesty spirits is most helpful don't fall into a bottomless pit dexterity allows you to carry more you can get 2 points of WC for the price of one never enter the dungeon naked! the monsters will laugh at you! did someone put itching powder in your armor? you klutz! avoid opening doors. you never know whats on the other side. infinite regeneration ---> temptation the greatest weapon in the game has not the highest Weapon Class you can't buy the most powerful scroll identify things before you use them there's more than one way through a wall SHAR_EOF if test 1324 -ne "`wc -c < 'larn12.ftn'`" then echo shar: error transmitting "'larn12.ftn'" '(should have been 1324 characters)' fi fi # end of overwriting check echo shar: extracting "'larn12.hdy'" '(2304 characters)' if test -f 'larn12.hdy' then echo shar: will not over-write existing file "'larn12.hdy'" else cat << \SHAR_EOF > 'larn12.hdy' "Jan 01 1986 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 17 1986 Washingtons Birthday (Presidents Day)" "May 26 1986 Memorial Day" "Jul 04 1986 Independence Day" "Sep 01 1986 Labor Day" "Oct 13 1986 Columbus Day" "Nov 27 1986 Thanksgiving" "Dec 25 1986 Christmas" "Jan 01 1987 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 16 1987 Washingtons Birthday (Presidents Day)" "May 25 1987 Memorial Day" "Jul 04 1987 Independence Day" "Sep 07 1987 Labor Day" "Oct 12 1987 Columbus Day" "Nov 26 1987 Thanksgiving" "Dec 25 1987 Christmas" "Jan 01 1988 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 15 1988 Washingtons Birthday (Presidents Day)" "May 30 1988 Memorial Day" "Jul 04 1988 Independence Day" "Sep 05 1988 Labor Day" "Oct 10 1988 Columbus Day" "Nov 24 1988 Thanksgiving" "Dec 25 1988 Christmas" "Jan 01 1989 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 13 1989 Washingtons Birthday (Presidents Day)" "May 28 1989 Memorial Day" "Jul 04 1989 Independence Day" "Sep 03 1989 Labor Day" "Oct 15 1989 Columbus Day" "Nov 29 1989 Thanksgiving" "Dec 25 1989 Christmas" "Jan 01 1990 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 12 1990 Washingtons Birthday (Presidents Day)" "May 27 1990 Memorial Day" "Jul 04 1990 Independence Day" "Sep 02 1990 Labor Day" "Oct 14 1990 Columbus Day" "Nov 28 1990 Thanksgiving" "Dec 25 1990 Christmas" "Jan 01 1991 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 11 1991 Washingtons Birthday (Presidents Day)" "May 26 1991 Memorial Day" "Jul 04 1991 Independence Day" "Sep 01 1991 Labor Day" "Oct 10 1991 Columbus Day" "Nov 27 1991 Thanksgiving" "Dec 25 1991 Christmas" "Jan 01 1992 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 10 1992 Washingtons Birthday (Presidents Day)" "May 25 1992 Memorial Day" "Jul 04 1992 Independence Day" "Sep 07 1992 Labor Day" "Oct 12 1992 Columbus Day" "Nov 26 1992 Thanksgiving" "Dec 25 1992 Christmas" "Jan 01 1993 New Years Day. Any comment goes here. Dont forget 01 not 1" "Feb 15 1993 Washingtons Birthday (Presidents Day)" "May 30 1993 Memorial Day" "Jul 04 1993 Independence Day" "Sep 05 1993 Labor Day" "Oct 10 1993 Columbus Day" "Nov 24 1993 Thanksgiving" "Dec 25 1993 Christmas" SHAR_EOF if test 2304 -ne "`wc -c < 'larn12.hdy'`" then echo shar: error transmitting "'larn12.hdy'" '(should have been 2304 characters)' fi fi # end of overwriting check # End of shell archive exit 0
u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # larn12.hlp # larn12.maz # larn12.opt # make.com # moreobj.c # movem.c # nap.c # readme.txt # This archive created: Sat Aug 30 14:51:08 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'larn12.hlp'" '(6275 characters)' if test -f 'larn12.hlp' then echo shar: will not over-write existing file "'larn12.hlp'" else cat << \SHAR_EOF > 'larn12.hlp' 5 Welcome to the game of Larn. At this moment, you face a great problem. Your daughter has contracted a strange disease, and none of your home remedies seem to have any effect. You sense that she is in mortal danger, and you must try to save her. Time ago you heard of a land of great danger and opportunity. Perhaps here is the solution you need. It has been said that there once was a great magician who called himself Polinneaus. Many years ago, after having many miraculous successes, Polinneaus retired to the caverns of Larn, where he devoted most of his time to the creation of magic. Rumors have it that one day Polinneaus set out to dispel an attacking army in a forest some distance to the north. It is believed that here he met his demise. The caverns of Larn, it is thought, must be magnificent in design, and contain much magic and treasure. One option you have is to undertake a journey into these caverns. Good Luck! You're going to need it! [4mHelp File for The Caverns of Larn[m h move to the left H run left . stay here j move down J run down Z teleport yourself k move up K run up c cast a spell l move to the right L run right r read a scroll y move northwest Y run northwest q quaff a potion u move northeast U run northeast W wear armor b move southwest B run southwest T take off armor n move southeast N run southeast w wield a weapon ^ identify a trap g give present pack weight P give tax status d drop an item i inventory your pockets Q quit the game v print program version S save the game D list all items found ? this help screen A create diagnostic file e eat something (wizards only) larn ++ restore checkpointed game larn -s list the scoreboard larn -i list scores with inventories larn -n suppress welcome message when beginning a game larn -h print out all the command line options larn -<number> specify difficulty of the game (may be used with -n) larn -o<optsfile> specify the .larnopts file to be used larn -c create new scoreboards -- prompts for a password [7mSpecial Notes[m When [7mdropping gold[m, if you type '*' as your amount, all your gold gets dropped. In general, typing in '*' means all of what your interested in. This is true when visiting the bank, or when contributing at altars. Larn may need a [7mVT100[m to operate. A check is made of the environment variable [7m"TERM"[m and it must be equal to [7m"vt100"[m. This only applies if the game has been compiled with "VT100" defined in the Makefile. If compiled to use [7mtermcap[m, there are no terminal restrictions, save needing cm, ce, & cl termcap entries. When in the store, trading post, school, or home, an [7m<escape>[m will get you out. larn -l print out the larn log file When casting a spell, if you need a list of spells you can cast, type '[7mD[m' as the first letter of your spell. The available list of spells will be shown, after which you may enter the spell code. This only works on the 1st letter of the spell you are casting. The Author of Larn is Noah Morgan (1982-3), Copying for Profit is Prohibited Copyright 1986 by Noah Morgan, All Rights Reserved. [7mBackground Information for Larn[m Welcome to the game of Larn. At this moment, you face a great problem. Your daughter has contracted a strange disease, and none of your home remedies seem to have any effect. You sense that she is in mortal danger, and you must try to save her. Time ago you heard of a land of great danger and opportunity. Perhaps here is the solution you need. It has been said that there once was a great magician who called himself Polinneaus. Many years ago, after having many miraculous successes, Polinneaus retired to the caverns of Larn, where he devoted most of his time to the creation of magic. Rumors have it that one day Polinneaus set out to dispel an attacking army in a forest some distance to the north. It is believed that here he met his demise. The caverns of Larn, it is thought, must be magnificent in design, and contain much magic and treasure. One option you have is to undertake a journey into these caverns. Good Luck! You're going to need it! [7mHow to use the .larnopts option file[m The file ".larnopts", if used, should be in your home directory (see -o). A sequence of words terminated by whitespace is used to specify options. Word Meaning bold-objects select bold display of objects inverse-objects select inverse video display of objects no-introduction do not display intro message enable-checkpointing turn on periodic checkpointing no-beep disable beeping of the terminal male choose your sex to be a man female choose your sex to be a woman name: "your name" choose your playing name monster: "monst name" choose a name for a monster savefile: "save-file-name" define what the savegame filename will be Your name and monster names must be enclosed in double quotation marks and may be up to 34 characters long. Longer names are truncated. Anything enclosed in quotation marks is considered one word, and must be separated from other words by whitespace. [7mExplanation of the Larn scoreboard facility[m Larn supports TWO scoreboards, one for winners, and one for deceased characters. Each player (by userid or playerid, see UIDSCORE in Makefile) is allowed one slot on each scoreboard, if the score is in the top ten for that scoreboard. This design helps insure that frequent players of Larn do not hog the scoreboard, and gives more players a chance for glory. Level of difficulty is also noted on the scoreboards, and this takes precedence over score for determining what entry is on the scoreboard. For example: if "Yar, the Bug Slayer" has a score of 128003 on the scoreboard at diff 0, then his game at diff 1 and a score of 4112 would replace his previous entry on the scoreboard. Note that when a player dies, his inventory is stored in the scoreboard so that everyone can see what items the player had at the time of his death. SHAR_EOF echo shar: 24 control characters may be missing from "'larn12.hlp'" if test 6275 -ne "`wc -c < 'larn12.hlp'`" then echo shar: error transmitting "'larn12.hlp'" '(should have been 6275 characters)' fi fi # end of overwriting check echo shar: extracting "'larn12.maz'" '(18513 characters)' if test -f 'larn12.maz' then echo shar: will not over-write existing file "'larn12.maz'" else cat << \SHAR_EOF > 'larn12.maz' @################################################################### # # . # # # # # . # # D D . . D . # ###D########################################## # # ###D### # -# #. # # ################ . .# # ####### ######## ############ D #### # # # # ... #.# # # # . # # # #### # ############ # ###D### # #.# # # ## # # # ############ #### # #- # # # #. # # . # # # # ## #- # # # - D #### # # . D # #.# # ... # # # #.# # # # # # . . # # # # # # #-# # ~.! # ###D### ### #######D## # ############ ###### ########## ### ####### # # @ .# # ..... ...# ###D###########################################################D### # . #.....# # # # -# # # # # # # ..... . D D D D. # # #.....# # # # # # .# # # # ################################################################### ################################################################### #.. . D # . # #- # ############# ######### # ## ### ##### ## #### ###### ####### ### # #.#!#~# # # .-# # #- # # # # -# # # # # # #.# . # ####### # # # # # # # # # ##### # # ..# ##### # # # #### # ## ## ## # ###### ####### # # # - ..D # D # . D # # # #.##### ## ## # #. #.# #..# # ### # ####### ####### ### # # # # # # D # D D #..D # # #- # # # #### # ###### # ## # #. # #..# ##### ### #######################- # # # ###################### # # # ... # . #..# ### # - .. . #. ### # # # # # ### #################### # # # # ### # ################################################################# # #- D ### # # # # # . # # # D # ################################################################### ################################################################### # .. # # ############## ############################################## # # # # # # # .. # # # # #D## # # ############D################# ########### # # # ######### #- # # # #- D # # ~ # # # # # # # # # # # # # # ### # # # D - # # ####### # # # # # .... # #### # # # #!# # # ###### .. #.# # # # # # # # .... # # # # ### # # # # #########D#### # ### # # # # # # .... ######## # # D # #- # #.. # ...#.# # #.# # # # # # # # # ### # #### #.- D - #.# #.#.# # # # # # #####DD## ######## # # D D. # # # #...# # # # # # # # ..# # # # ############################## # ##### # # # # # # ......# # # # # # # # # # # ####### ###### ################################ ######### # ### # # .D. # # ################################################################### ################################################################### # ## ## ### ## # # ##### ## ..- ## ##.## ## # # # ! ## ## . ## ## .## .. ## # # #....###### ## ## ## . ## ## # # # - # ## ##D# ## . ## ## # # #####D ~ ####### ###........ ## ... ## ## # # # # ## ## .... ## . ## ## # # #. ######## ## ## . - ####D#### - # # #.- #...## ## ... ## ### ...... ## ## # # #. #..## ## ######### ## ... ## ### ## .. # # #.. #.## ## ## - ## . #### ## ## ##### ## # # #####D## ## ## ###### ## ## ####### ## # # D -.## #### ######## ##DD## ######## #D # # ###### ... ## ########## ## # #### . . ### ################################################################### ################################################################### # # # ####.########################################## ## ########## # # #.#.#.# #.. #. # # # ####### # # # # # ##### #! # ########### # ### # # # # # # # # ##...## # # # # # #-# # # ..- D # # # # # ## . ## ####D##### .. ### # # # # # # # # ##. ~ .## # # ### # # ##### # # ############ # # # # ## . . .## #...# .. #.# # # # # # .. .# # # # # ## - ## # # D.D # ######### # # . D # # # # ##.......## ####D#####.# # # # - . # # # # # ## ## # . # ### ########### # ############ #.#.# # ###D### # . #....# # # # # #-# D .. # .# ###....## ##-### # #### ########################################## ###### ### # # . # ################################################################### ################################################################### # # # ###########################D####### ## # # ####################### # ##...... ## ## # # ########D###### # # !##.... ## ## # # ############ ## ## ... # # #...## ~ ## ###### # # # # # # ...... # # # .. ##### ## # # # - .. # # # ########### # # . ######### ## # # ##### ##### # # # # #... ## ## # # # # ########## ######## ########DD#### ####### # # # # .... # # # # # ## ## # # ##### # # ....# # ######### # # ##### ## # # #- ######D##########..# # ######### # - #.. ## ## # # ##### # # # #... #.....## # # # ################### ###############... #### # ###### # # # ################################################################### ################################################################### # # ########### ##### ##### #####D#### ##### ###### # #.. # #-..D ###### ## # ## # ## ..## ### #### # # #### ### ##### # ## # ##### # ## ### ## # # # # # # # # # ##### # ## # # #### # #..##### - ### # # # # ####### ### #...# # ######## # # #~. .... # # # # # # #...# # # ######### ############## # # # ###### ####### # ### ### # .. # # # # # - # #-#####!# # # #### ## #### # # # ###### # ########## #.. ....# # ######## # # # ## ## # # -.# ##### ####...## # . .# #..# # ## # # # #### ###### #.### #####.#### #### ### ## # # # #- #######....#### ...... #.# . # ## # # # ####### ##### ###########.############### ### # # . # ################################################################### ################################################################### # # #- . # # # # # # # # # # # # #####.##### # # # # # # # # # # ###########D########### # # # ##### # # ### # # # # # # # # # ### #.... # # # # # # # # # # # # # # # # # # #.!. -.. #.##.# # # # # . - # # ####### # # # # # # # # # ########## ## # # #.####### # # D # . # # # #. -# ################################################### # # ##### D. . # # # ### ###D### ### ### ###D### ### ### ###D### ###.### # # # ###### ### .# .# #. # # # # # # # # . # # # ### # -# ### .#. - .# # # #...- # # .. # # -..# # . # # # # # ### #. ~ .# # # # # # # # .. .# # # # #.###### # ### # # #.....# # # # # # # # # # # # ####### ####### ####### ####### ####### ####### ####### # # # ... .. # ################################################################### ################################################################### # # . # ### # # # # . # # D D . # . D . # ############################################### # # ###D### # -# #. # # ################ . .# # #######D######## ############ # #### # # # # ... #. # #!~ . # # # #--# # ############ #####D### # #.# # # ## # # # ############ #--# # #- # # # #. # # . # #-# # ## #- # # # - D ## # # # . D #### #.# # ... # # # #-# # # # # # . . # # # # # # #-# # -.- # ###D### ### ####### ## # ############ ###### ########## ### ###D### # # @ . ..... ...# ##################################### ###############D### # . #.....# # # # -# # # # # # ..... . D D D D. # # #.....# # # # # .# # # # ################################################################### ################################################################### #.. . # D . #- # ### ######### ######### # ## ### ##### ## ########### ####### ### # #.# # # # .-# # #- # # # # -# # # # # # #.# . # ####### # # # # # # # # # ##### # # ..####### # # # #### # ## ## ##!# ###### ####### # # # - ..D # D # . D # # # #.##### ## ## # #. #.# #..# # ### # ####### ####### ### # # # # # # D # D D #..D # # #- # # # #### # ###### # ## # #. # #..# ##### ### #######################- # # # ###################### # # # ... # . #..# ### # - .. . #. ### # # # # # #-# #################### # # # # # -# # ################################-################################ # #-..... # ####D ### # # # # #~..... # # # # D # ################################################################### ################################################################### # .. # # ############## ############################################## # # # # # # # .. # # # # #D## # # ############D################# ########### # # # ######### #- # # # #- D # #.!..# # # # # # # # # # # # # # # ### ## # #....D - # # ####### # # # # # .... # #### # # # #~# # # ###### .. #.# # # # # # # ###....## # # # ###.# # # #########D## # # ### # # # # # # .... ######## # # D .# #- # .. # ...#.# # #.# # # # # # # # ## # ### .# #### .- D - #.# #.#.# # # # # # #####DD## ######## #... .# . # # # #.#. # # # # # # # ..# # # ############################## # # ##### # # # # # ......# # # # # # # # # # # # ####### ###### ################################D# ######### ### # # .D. #-.-# ################################################################### ################################################################### # ## ## ## ## ## # # ############## ## ..- ## ## . ## ## # # # # ## ## . ## ## . ##.. ## # # #....###### ## ## ######## ####### . ## ## # # # - # ## ## ##D# ## . ## ## # # # D###### ###........ ## ... ## ###### # # # # ## ## .... ## . ## ## - # # # #. ######## ## ## . - ####D####.. D # # #.- #...## ## ... ## ### ...... ## ##### # # #. #..## ## ######### ## ... ## ### ## .. # # #.. #.## ## ## - ## . #### ## ## ##### ## # # #####D####### # ## ## ##..## ## ## ## ## ## # # D -.## # # #### ##.-.-## ##DD## ### #### ## # # ######. ...# #### ## #### ##### ## ##D# ####~!.... D . . # ################################################################### ################################################################### # # # ####.########################################## ## ########## # # #.#.#.# #.. . # # # ####### # # # # # ############# # ########### # ### # # # # # # # # --##...##-- # # # # #-# # # ..- D # # # # # #-## . ##-# ####D##### .. ### # # # # # # # # ###. .### # ~ # ### ### ##### # # ############ # # # # ## . . .## #...# .. #.# # # # .. .# # # # # ## - ## # # D. # ######### # # . D # # # # ###.......### ####D#####.# # # # - . # # # # # -## ##- # . ### ########### # ############ #.#.# # ######D###### # . ....# # # # #!#-# # .. # . ###....## ##-### # #### ############################## ########## ###### ### # # D . # ################################################################### ################################################################### # # # ###############D####################D# # # ####################### # ##...... # # # ########D###### # # ##.... # # # ############### ## ## ... # # #...## ##### # # # ~ # # #!...... # # # .. ##### # # # # - .. # # # ########### # # . ######### # # # ##### ######## # # # # # #... ## # # # # # # ########## ######## ########D #### ###### # # # # ....# # # # # # ## # # # ##### # ###### # ....# # ######### # # #####D# # # #- ## # #######..# # ######### # - #.. # # ##### # # # #... #..... # # # ################### ###############... #### ###### # # # ################################################################### ################################################################### # # # ########### ##### # #####D#### ##### ###### # #.. # #~..D ###### ## # ## # ## ..## ### #### # # #### ### ##### # ## # ##### # ## ### ## # # # # # # # # # ##### # ## # # #### # #..##### - ### # # # # ####### ### #...# # ######## # # #!. .... # # # # # # #...# # # ######### ############## # # # ###### ####### # ### ### # .. # # # # # - # #- # # # ######## #### # # # # # ########## #.. ....# # ######## # ## ## # # # -. ##### ####...## # . .# .. # # # # # ###### ##### #####.#### ####### # # # # - #######....#### ...... #.# . # ## # # # ######### ##### ###########.############### ### # # . # ################################################################### ################################################################### # D D #-..........# # # # # # #D#D# #####.#####.# # # # # # #############D########### # # # ##### #.#~###.# # # # # # ### .... # # # # #D# # #.......# # # # # # # . . -.. #. #.# # # # # . - # #.####### # # # # # ################## # # #D####### #. # D # . # # # #. D D -# ################################################### # # ###### . . # # # D ### ###D### ####### ###D### ####### ###D### ####### # # # ###### # # .# .# #. # # # # # # # # . # # # ### -# # # .#. - .# # # #...- # # .. # # -..# # . # # #DD# # # # #. .# # # # # # # # .. .# # # # #.###### # # # # #.....# # # # # # ! # # # # # # ####### ####### ### ### ####### ### ### ####### ### ### # # # ... .. # ################################################################### SHAR_EOF if test 18513 -ne "`wc -c < 'larn12.maz'`" then echo shar: error transmitting "'larn12.maz'" '(should have been 18513 characters)' fi fi # end of overwriting check echo shar: extracting "'larn12.opt'" '(253 characters)' if test -f 'larn12.opt' then echo shar: will not over-write existing file "'larn12.opt'" else cat << \SHAR_EOF > 'larn12.opt' process-name: "Winnie-the-Pooh" enable-checkpointing bold-objects male play-day-play no-introduction name: "King of the Realm" monster: "abominable snowman" monster: "tooth fairy" monster: "Yaccerous Lexicous" savefile: "/save/noah/games/Larn12.0.sav" SHAR_EOF if test 253 -ne "`wc -c < 'larn12.opt'`" then echo shar: error transmitting "'larn12.opt'" '(should have been 253 characters)' fi fi # end of overwriting check echo shar: extracting "'make.com'" '(5478 characters)' if test -f 'make.com' then echo shar: will not over-write existing file "'make.com'" else cat << \SHAR_EOF > 'make.com' $ $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $! Available compile time options: $! WIZID=xxx - this is the userid (or playerid) of the wizard. Default is $! zero (superuser), which disables all wizard functions. $! Players must have this userid (or playerid) in order to $! become the non-scoring wizard player. Definition of WIZID $! to non-zero will enable the special wizard debugging $! commands. For root to become wizard, use WIZID= -1. $! EXTRA - incorporates code to gather additional performance statistics $! TIMECHECK - incorporates code to disable play during working hours (8-5) $! SAVEINHOME - put save files in users HOME instead of LARNHOME the as default $! VER - This is the version of the software, example: 12 $! SUBVER - This is the revision of the software, example: 1 $! MACRORND $! - Define to use macro version of rnd() and rund() (fast & big) $! UIDSCORE $! - Define to use user id's to manage scoreboard. Leaving this $! out will cause player id's from the file "LARN12.IDS" to be $! used instead. (LARN12.IDS is created upon demand). Only one $! entry per id # is allowed in each scoreboard (winning & $! non-winning). $! VT100 - Compile for using vt100 family of terminals. Omission of this $! define will cause larn to use termcap, but it will be MUCH $! slower due to an extra layer of output interpretation. $! Also, only VT100 mode allows 2 different standout modes, $! inverse video, and bold video. And only in VT100 mode is $! the scrolling region of the terminal used (much nicer than $! insert/delete line sequences to simulate it, if VT100 is $! omitted). $! NONAP - This causes napms() to return immediately instead of delaying $! n milliseconds. This define may be needed on some systems $! if the nap stuff does not work correctly (possible hang). $! nap() is primarilly used to delay for effect when casting $! missile type spells. $! $! End of configurable make options $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $! $! $! WIZID = (0101<<16) | 02 ([101,2]) $! $ $! You must define LARNHOME in LARN.C before executing this command file. $ $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $ DEF = " /DEF=(SAVEINHOME,WIZZARD,WIZID=4259842,EXTRA,VT100,VER=12,SUBVER=0,MACRORND)" $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! $ $ SET DEFAULT [MARK.SRC.GAMES.LARN.TMP] ! change to suit your needs $ $!-------------------------------------------- $! Make command file for VMS Larn version 12.0 $!-------------------------------------------- $ $ ON ERROR THEN GOTO ERROR_HANDLER $! $! If we are making a debug version, define options appropriately. $! $ C_OPTS = "/NOLIST /NOOPT" $ L_OPTS = "/NOMAP" $ IF P1 .NES. "DEBUG" THEN GOTO NO_DEBUG $ C_OPTS = C_OPTS + " /DEBUG" $ L_OPTS = L_OPTS + " /DEBUG" $ NO_DEBUG: $ C_OPTS = C_OPTS + "'DEF'" $! $! Define the module library $! $ LIB = "LARNLIB.OLB" $ $ IF F$SEARCH("''LIB'") .EQS. "" THEN - LIBRARY/CREATE 'LIB'/OBJ ! CREATE THE LIBRARY IF IT DOESN'T EXIST $! $! Main module doesn't go in the library $! $ CC 'C_OPTS' LARN $ $! $! Everything else does $! $ CC 'C_OPTS' BILL $ LIBRARY 'LIB'/OBJ BILL $ DELETE BILL.OBJ; $ CC 'C_OPTS' CREATE $ LIBRARY 'LIB'/OBJ CREATE $ DELETE CREATE.OBJ; $ CC 'C_OPTS' DATA $ LIBRARY 'LIB'/OBJ DATA $ DELETE DATA.OBJ; $ CC 'C_OPTS' DIAG $ LIBRARY 'LIB'/OBJ DIAG $ DELETE DIAG.OBJ; $ CC 'C_OPTS' DISPLAY $ LIBRARY 'LIB'/OBJ DISPLAY $ DELETE DISPLAY.OBJ; $ CC 'C_OPTS' FORTUNE $ LIBRARY 'LIB'/OBJ FORTUNE $ DELETE FORTUNE.OBJ; $ CC 'C_OPTS' GLOBAL $ LIBRARY 'LIB'/OBJ GLOBAL $ DELETE GLOBAL.OBJ; $ CC 'C_OPTS' HELP $ LIBRARY 'LIB'/OBJ HELP $ DELETE HELP.OBJ; $ CC 'C_OPTS' IO $ LIBRARY 'LIB'/OBJ IO $ DELETE IO.OBJ; $ CC 'C_OPTS' KEYSENSE $ LIBRARY 'LIB'/OBJ KEYSENSE $ DELETE KEYSENSE.OBJ; $ CC 'C_OPTS' MONSTER $ LIBRARY 'LIB'/OBJ MONSTER $ DELETE MONSTER.OBJ; $ CC 'C_OPTS' MOREOBJ $ LIBRARY 'LIB'/OBJ MOREOBJ $ DELETE MOREOBJ.OBJ; $ CC 'C_OPTS' MOVEM $ LIBRARY 'LIB'/OBJ MOVEM $ DELETE MOVEM.OBJ; $ CC 'C_OPTS' NAP $ LIBRARY 'LIB'/OBJ NAP $ DELETE NAP.OBJ; $ CC 'C_OPTS' OBJECT $ LIBRARY 'LIB'/OBJ OBJECT $ DELETE OBJECT.OBJ; $ CC 'C_OPTS' REGEN $ LIBRARY 'LIB'/OBJ REGEN $ DELETE REGEN.OBJ; $ CC 'C_OPTS' SAVELEV $ LIBRARY 'LIB'/OBJ SAVELEV $ DELETE SAVELEV.OBJ; $ CC 'C_OPTS' SCORES $ LIBRARY 'LIB'/OBJ SCORES $ DELETE SCORES.OBJ; $ CC 'C_OPTS' SIGNAL $ LIBRARY 'LIB'/OBJ SIGNAL $ DELETE SIGNAL.OBJ; $ CC 'C_OPTS' STORE $ LIBRARY 'LIB'/OBJ STORE $ DELETE STORE.OBJ; $ CC 'C_OPTS' TOK $ LIBRARY 'LIB'/OBJ TOK $ DELETE TOK.OBJ; $! $! now link 'em up $! $ LINK 'L_OPTS' LARN,'LIB'/LIB,SYS$LIBRARY:VAXCRTL/LIB $ $ EXIT $ $ ERROR_HANDLER: $ WRITE SYS$OUTPUT "Fatal error has occurred. See ya!" SHAR_EOF echo shar: a missing newline was added to "'make.com'" echo shar: 485 control characters may be missing from "'make.com'" if test 5478 -ne "`wc -c < 'make.com'`" then echo shar: error transmitting "'make.com'" '(should have been 5478 characters)' fi fi # end of overwriting check echo shar: extracting "'moreobj.c'" '(9411 characters)' if test -f 'moreobj.c' then echo shar: will not over-write existing file "'moreobj.c'" else cat << \SHAR_EOF > 'moreobj.c' /* moreobj.c Larn is copyrighted 1986 by Noah Morgan. * * Routines in this file: * * oaltar() * othrone() * ochest() * ofountain() */ #include "header.h" /* * ****** * OALTAR * ****** * * subroutine to process an altar object */ oaltar() { unsigned long k; lprcat("\nDo you (p) pray or (d) desecrate"); iopts(); while (1) { while (1) switch(readchar()) { case 'p': lprcat(" pray\nDo you (m) give money or (j) just pray? "); while (1) switch(readchar()) { case 'j': if (rnd(100) < 75) lprcat("\nnothing happens"); else if (rnd(13) < 4) ohear(); else if (rnd(43) == 10) { if (c[WEAR]) lprcat("\nYou feel your armor vibrate for a moment"); enchantarmor(); return; } else if (rnd(43) == 10) { if (c[WIELD]) lprcat("\nYou feel your weapon vibrate for a moment"); enchweapon(); return; } else createmonster(makemonst(level + 1)); return; case 'm': lprcat("\n\n"); cursor(1, 24); cltoeoln(); cursor(1, 23); cltoeoln(); lprcat("How much do you donate? "); k = readnum((long) c[GOLD]); if (c[GOLD] < k) { lprcat("\nYou don't have that much!"); return; } c[GOLD] -= k; if (k < c[GOLD] / 10 || k < rnd(50)) { createmonster(makemonst(level + 1)); c[AGGRAVATE] += 200; } else if (rnd(101) > 50) { ohear(); return; } else if (rnd(43) == 5) { if (c[WEAR]) lprcat("\nYou feel your armor vibrate for a moment"); enchantarmor(); return; } else if (rnd(43) == 8) { if (c[WIELD]) lprcat("\nYou feel your weapon vibrate for a moment"); enchweapon(); return; } else lprcat("\nThank You."); bottomline(); return; case '\33': return; }; case 'd': lprcat(" desecrate"); if (rnd(100) < 60) { createmonster(makemonst(level + 2) + 8); c[AGGRAVATE] += 2500; } else if (rnd(101) < 30) { lprcat("\nThe altar crumbles into a pile of dust before your eyes"); forget(); /* remember to destroy the altar */ } else lprcat("\nnothing happens"); return; case 'i': case '\33': ignore(); if (rnd(100) < 30) { createmonster(makemonst(level + 1)); c[AGGRAVATE] += rnd(450); } else lprcat("\nnothing happens"); return; }; } } /* function to cast a +3 protection on the player */ static ohear() { lprcat("\nYou have been heard!"); if (c[ALTPRO] == 0) c[MOREDEFENSES] += 3; c[ALTPRO] += 500; /* protection field */ bottomline(); } /* ******* OTHRONE ******* subroutine to process a throne object */ othrone(arg) int arg; { register int i,k; lprcat("\nDo you (p) pry off jewels or (s) sit down"); iopts(); while (1) { while (1) switch(readchar()) { case 'p': lprcat(" pry off"); k = rnd(101); if (k < 25) { for (i = 0; i < rnd(4); i++) creategem();/* gems pop off the throne */ item[playerx][playery] = ODEADTHRONE; know[playerx][playery] = 0; } else if (k < 40 && arg == 0) { createmonster(GNOMEKING); item[playerx][playery] = OTHRONE2; know[playerx][playery] = 0; } else lprcat("\nnothing happens"); return; case 's': lprcat(" sit down"); k = rnd(101); if (k < 30 && arg == 0) { createmonster(GNOMEKING); item[playerx][playery] = OTHRONE2; know[playerx][playery] = 0; } else if (k < 35) { lprcat("\nZaaaappp! You've been teleported!\n"); beep(); oteleport(0); } else lprcat("\nnothing happens"); return; case 'i': case '\33': ignore(); return; }; } } odeadthrone() { register int k; lprcat("\nDo you (s) sit down"); iopts(); while (1) { while (1) switch(readchar()) { case 's': lprcat(" sit down"); k = rnd(101); if (k < 35) { lprcat("\nZaaaappp! You've been teleported!\n"); beep(); oteleport(0); } else lprcat("\nnothing happens"); return; case 'i': case '\33': ignore(); return; }; } } /* ****** OCHEST ****** subroutine to process a throne object */ ochest() { register int i,k; lprcat("\nDo you (t) take it or (o) try to open it"); iopts(); while (1) { while (1) switch(readchar()) { case 'o': lprcat(" open it"); k = rnd(101); if (k < 40) { lprcat("\nThe chest explodes as you open it"); beep(); i = rnd(10); lastnum = 281;/* in case he dies */ lprintf("\nYou suffer %d hit points damage!",(long) i); checkloss(i); switch(rnd(10)) {/* see if he gets a curse */ case 1: c[ITCHING] += rnd(1000) + 100; lprcat("\nYou feel an irritation spread over your skin!"); beep(); break; case 2: c[CLUMSINESS] += rnd(1600) + 200; lprcat("\nYou begin to lose hand to eye coordination!"); beep(); break; case 3: c[HALFDAM] += rnd(1600) + 200; beep(); lprcat("\nA sickness engulfs you!"); break; }; item[playerx][playery] = know[playerx][playery] = 0; if (rnd(100) < 69) creategem();/* gems from the chest */ dropgold(rnd(110 * iarg[playerx][playery] + 200)); for (i = 0; i < rnd(4); i++) something(iarg[playerx][playery] + 2); } else lprcat("\nnothing happens"); return; case 't': lprcat(" take"); if (take(OCHEST, iarg[playerx][playery]) == 0) item[playerx][playery] = know[playerx][playery] = 0; return; case 'i': case '\33': ignore(); return; }; } } /* ********* OFOUNTAIN ********* */ ofountain() { register int x; cursors(); lprcat("\nDo you (d) drink or (w) wash yourself"); iopts(); while (1) switch(readchar()) { case 'd': lprcat("drink"); if (rnd(1501) < 2) { lprcat("\nOops! You seem to have caught the dreadful sleep!"); beep(); lflush(); sleep(3); died(280); return; } x = rnd(100); if (x < 7) { c[HALFDAM] += 200 + rnd(200); lprcat("\nYou feel a sickness coming on"); } else if (x < 13) quaffpotion(23);/* see invisible */ else if (x < 45) lprcat("\nnothing seems to have happened"); else if (rnd(3) != 2) fntchange(1); /* change char levels upward */ else fntchange(-1); /* change char levels downward */ if (rnd(12) < 3) { lprcat("\nThe fountains bubbling slowly quiets"); item[playerx][playery] = ODEADFOUNTAIN;/* dead fountain */ know[playerx][playery] = 0; } return; case '\33': case 'i': ignore(); return; case 'w': lprcat("wash yourself"); if (rnd(100) < 11) { x = rnd((level << 2) + 2); lprintf("\nOh no! The water was foul! You suffer %d hit points!",(long) x); lastnum = 273; losehp(x); bottomline(); cursors(); } else if (rnd(100) < 29) lprcat("\nYou got the dirt off!"); else if (rnd(100) < 31) lprcat("\nThis water seems to be hard water! The dirt didn't come off!"); else if (rnd(100) < 34) createmonster(WATERLORD); /* make water lord */ else lprcat("\nnothing seems to have happened"); return; } } /* a subroutine to raise or lower character levels if x > 0 they are raised if x < 0 they are lowered */ fntchange(how) int how; { register long j; lprc('\n'); switch(rnd(9)) { case 1: lprcat("Your strength"); fch(how, &c[0]); break; case 2: lprcat("Your intelligence"); fch(how, &c[1]); break; case 3: lprcat("Your wisdom"); fch(how, &c[2]); break; case 4: lprcat("Your constitution"); fch(how, &c[3]); break; case 5: lprcat("Your dexterity"); fch(how, &c[4]); break; case 6: lprcat("Your charm"); fch(how, &c[5]); break; case 7: j = rnd(level + 1); if (how < 0) { lprintf("You lose %d hit point",(long) j); if (j > 1) lprcat("s!"); else lprc('!'); losemhp((int) j); } else { lprintf("You gain %d hit point",(long) j); if (j > 1) lprcat("s!"); else lprc('!'); raisemhp((int) j); } bottomline(); break; case 8: j = rnd(level + 1); if (how > 0) { lprintf("You just gained %d spell",(long) j); raisemspells((int) j); if (j > 1) lprcat("s!"); else lprc('!'); } else { lprintf("You just lost %d spell",(long) j); losemspells((int) j); if (j > 1) lprcat("s!"); else lprc('!'); } bottomline(); break; case 9: j = 5 * rnd((level + 1) *(level + 1)); if (how < 0) { lprintf("You just lost %d experience point",(long) j); if (j > 1) lprcat("s!"); else lprc('!'); loseexperience((long) j); } else { lprintf("You just gained %d experience point",(long) j); if (j > 1) lprcat("s!"); else lprc('!'); raiseexperience((long) j); } break; } cursors(); } /* *** FCH *** subroutine to process an up/down of a character attribute for ofountain */ static fch(how, x) int how; long *x; { if (how < 0) { lprcat(" went down by one!"); --(*x); } else { lprcat(" went up by one!"); (*x)++; } bottomline(); } SHAR_EOF if test 9411 -ne "`wc -c < 'moreobj.c'`" then echo shar: error transmitting "'moreobj.c'" '(should have been 9411 characters)' fi fi # end of overwriting check echo shar: extracting "'movem.c'" '(11581 characters)' if test -f 'movem.c' then echo shar: will not over-write existing file "'movem.c'" else cat << \SHAR_EOF > 'movem.c' /* * movem.c (move monster) Larn is copyrighted 1986 by Noah Morgan. * * Here are the functions in this file: * * movemonst() Routine to move the monsters toward the player * movemt(x,y) Function to move a monster at (x,y) -- must determine where * mmove(x,y,xd,yd) Function to actually perform the monster movement * movsphere() Function to look for and move spheres of annihilation */ #include "header.h" /* * movemonst() Routine to move the monsters toward the player * * This routine has the responsibility to determine which monsters are to * move, and call movemt() to do the move. * Returns no value. */ static short w1[9], w1x[9], w1y[9]; static int tmp1, tmp2, tmp3, tmp4, distance; movemonst () { register int i, j; if (c[TIMESTOP]) return; /* no action if time is stopped */ if (c[HASTESELF]) if ((c[HASTESELF] & 1) == 0) return; if (spheres) movsphere (); /* move the spheres of annihilation if any */ if (c[HOLDMONST]) return; /* no action if monsters are held */ if (c[AGGRAVATE]) { /* determine window of monsters to move */ tmp1 = playery - 5; tmp2 = playery + 6; tmp3 = playerx - 10; tmp4 = playerx + 11; distance = 40; /* depth of intelligent monster movement */ } else { tmp1 = playery - 3; tmp2 = playery + 4; tmp3 = playerx - 5; tmp4 = playerx + 6; distance = 17; /* depth of intelligent monster movement */ } if (level == 0) { /* if on outside level monsters can move in perimeter */ if (tmp1 < 0) tmp1 = 0; if (tmp2 > MAXY) tmp2 = MAXY; if (tmp3 < 0) tmp3 = 0; if (tmp4 > MAXX) tmp4 = MAXX; } else { /* if in a dungeon monsters can't be on the perimeter (wall there) */ if (tmp1 < 1) tmp1 = 1; if (tmp2 > MAXY - 1) tmp2 = MAXY - 1; if (tmp3 < 1) tmp3 = 1; if (tmp4 > MAXX - 1) tmp4 = MAXX - 1; } for (j = tmp1; j < tmp2; j++)/* now reset monster moved flags */ for (i = tmp3; i < tmp4; i++) moved[i][j] = 0; moved[lasthx][lasthy] = 0; if (c[AGGRAVATE] || !c[STEALTH]) {/* who gets moved? split for efficiency */ for (j = tmp1; j < tmp2; j++)/* look thru all locations in window */ for (i = tmp3; i < tmp4; i++) if (mitem[i][j])/* if there is a monster to move */ if (moved[i][j] == 0)/* if it has not already been moved */ movemt (i, j);/* go and move the monster */ } else { /* not aggravated and not stealth */ for (j = tmp1; j < tmp2; j++)/* look thru all locations in window */ for (i = tmp3; i < tmp4; i++) if (mitem[i][j])/* if there is a monster to move */ if (moved[i][j] == 0)/* if it has not already been moved */ if (stealth[i][j])/* if it is asleep due to stealth */ movemt (i, j);/* go and move the monster */ } if (mitem[lasthx][lasthy]) {/* now move monster last hit by player if not already moved */ if (moved[lasthx][lasthy] == 0) {/* if it has not already been moved */ movemt (lasthx, lasthy); lasthx = w1x[0]; lasthy = w1y[0]; } } } /* * movemt(x,y) Function to move a monster at (x,y) -- must determine where * int x,y; * * This routine is responsible for determining where one monster at (x,y) will * move to. Enter with the monsters coordinates in (x,y). * Returns no value. */ static int tmpitem, xl, xh, yl, yh; movemt (i, j) int i, j; { register int k, m, z, tmp, xtmp, ytmp, monst; switch (monst = mitem[i][j]) {/* for half speed monsters */ case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART: case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return; }; if (c[SCAREMONST]) { /* choose destination randomly if scared */ if ((xl = i + rnd (3) - 2) < 0) xl = 0; if (xl >= MAXX) xl = MAXX - 1; if ((yl = j + rnd (3) - 2) < 0) yl = 0; if (yl >= MAXY) yl = MAXY - 1; if ((tmp = item[xl][yl]) != OWALL) if (mitem[xl][yl] == 0) if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR)) if (tmp != OCLOSEDDOOR) mmove (i, j, xl, yl); return; } if (monster[monst].intelligence > 10 - c[HARDGAME]) {/* if smart monster */ /* intelligent movement here -- first setup screen array */ xl = tmp3 - 2; yl = tmp1 - 2; xh = tmp4 + 2; yh = tmp2 + 2; vxy (&xl, &yl); vxy (&xh, &yh); for (k = yl; k < yh; k++) for (m = xl; m < xh; m++) { switch (item[m][k]) { case OWALL: case OPIT: case OTRAPARROW: case ODARTRAP: case OCLOSEDDOOR: case OTRAPDOOR: case OTELEPORTER: smm: screen[m][k] = 127; break; case OMIRROR: if (mitem[m][k] == VAMPIRE) goto smm; default: screen[m][k] = 0; break; }; } screen[playerx][playery] = 1; /* now perform proximity ripple from playerx,playery to monster */ xl = tmp3 - 1; yl = tmp1 - 1; xh = tmp4 + 1; yh = tmp2 + 1; vxy (&xl, &yl); vxy (&xh, &yh); for (tmp = 1; tmp < distance; tmp++)/* only up to 20 squares away */ for (k = yl; k < yh; k++) for (m = xl; m < xh; m++) if (screen[m][k] == tmp)/* if find proximity n advance it */ for (z = 1; z < 9; z++) {/* go around in a circle */ if (screen[xtmp = m + diroffx[z]][ytmp = k + diroffy[z]] == 0) screen[xtmp][ytmp] = tmp + 1; if (xtmp == i && ytmp == j) goto out; } out: if (tmp < distance) /* did find connectivity */ /* now select lowest value around playerx,playery */ for (z = 1; z < 9; z++)/* go around in a circle */ if (screen[xl = i + diroffx[z]][yl = j + diroffy[z]] == tmp) if (!mitem[xl][yl]) { mmove (i, j, w1x[0] = xl, w1y[0] = yl); return; } } /* dumb monsters move here */ xl = i - 1; yl = j - 1; xh = i + 2; yh = j + 2; if (i < playerx) xl++; else if (i > playerx) --xh; if (j < playery) yl++; else if (j > playery) --yh; for (k = 0; k < 9; k++) w1[k] = 10000; for (k = xl; k < xh; k++) for (m = yl; m < yh; m++) {/* for each square compute distance to player */ tmp = k - i + 4 + 3 * (m - j); tmpitem = item[k][m]; if (tmpitem != OWALL || (k == playerx && m == playery)) if (mitem[k][m] == 0) if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR)) if (tmpitem != OCLOSEDDOOR) { w1[tmp] = (playerx - k) * (playerx - k) + (playery - m) * (playery - m); w1x[tmp] = k; w1y[tmp] = m; } } tmp = 0; for (k = 1; k < 9; k++) if (w1[tmp] > w1[k]) tmp = k; if (w1[tmp] < 10000) if ((i != w1x[tmp]) || (j != w1y[tmp])) mmove (i, j, w1x[tmp], w1y[tmp]); } /* * mmove(x,y,xd,yd) Function to actually perform the monster movement * int x,y,xd,yd; * * Enter with the from coordinates in (x,y) and the destination coordinates * in (xd,yd). */ mmove (aa, bb, cc, dd) int aa, bb, cc, dd; { register int tmp, i, flag; char *who, *p; flag = 0; /* set to 1 if monster hit by arrow trap */ if ((cc == playerx) && (dd == playery)) { hitplayer (aa, bb); moved[aa][bb] = 1; return; } i = item[cc][dd]; if ((i == OPIT) || (i == OTRAPDOOR)) switch (mitem[aa][bb]) { case SPIRITNAGA: case PLATINUMDRAGON: case WRAITH: case VAMPIRE: case SILVERDRAGON: case POLTERGEIST: case DEMONLORD: case DEMONLORD + 1: case DEMONLORD + 2: case DEMONLORD + 3: case DEMONLORD + 4: case DEMONLORD + 5: case DEMONLORD + 6: case DEMONPRINCE: break; default: mitem[aa][bb] = 0;/* fell in a pit or trapdoor */ }; tmp = mitem[cc][dd] = mitem[aa][bb]; if (i == OANNIHILATION) { if (tmp >= DEMONLORD + 3) {/* demons dispel spheres */ cursors (); lprintf ("\nThe %s dispels the sphere!", monster[tmp].name); rmsphere (cc, dd); /* delete the sphere */ } else i = tmp = mitem[cc][dd] = 0; } stealth[cc][dd] = 1; if ((hitp[cc][dd] = hitp[aa][bb]) < 0) hitp[cc][dd] = 1; mitem[aa][bb] = 0; moved[cc][dd] = 1; if (tmp == LEPRECHAUN) switch (i) { case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD: case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: item[cc][dd] = 0;/* leprechaun takes gold */ }; if (tmp == TROLL) /* if a troll regenerate him */ if ((gtime & 1) == 0) if (monster[tmp].hitpoints > hitp[cc][dd]) hitp[cc][dd]++; if (i == OTRAPARROW) { /* arrow hits monster */ who = "An arrow"; if ((hitp[cc][dd] -= rnd (10) + level) <= 0) { mitem[cc][dd] = 0; flag = 2; } else flag = 1; } if (i == ODARTRAP) { /* dart hits monster */ who = "A dart"; if ((hitp[cc][dd] -= rnd (6)) <= 0) { mitem[cc][dd] = 0; flag = 2; } else flag = 1; } if (i == OTELEPORTER) { /* monster hits teleport trap */ flag = 3; fillmonst (mitem[cc][dd]); mitem[cc][dd] = 0; } if (c[BLINDCOUNT]) return; /* if blind don't show where monsters are */ if (know[cc][dd] & 1) { p = 0; if (flag) cursors (); switch (flag) { case 1: p = "\n%s hits the %s"; break; case 2: p = "\n%s hits and kills the %s"; break; case 3: p = "\nThe %s%s gets teleported"; who = ""; break; }; if (p) { lprintf (p, who, monster[tmp].name); beep (); } } /* if (yrepcount>1) { know[aa][bb] &= 2; know[cc][dd] &= 2; return; } */ if (know[aa][bb] & 1) show1cell (aa, bb); if (know[cc][dd] & 1) show1cell (cc, dd); } /* * movsphere() Function to look for and move spheres of annihilation * * This function works on the sphere linked list, first duplicating the list * (the act of moving changes the list), then processing each sphere in order * to move it. They eat anything in their way, including stairs, volcanic * shafts, potions, etc, except for upper level demons, who can dispel * spheres. * No value is returned. */ #define SPHMAX 20 /* maximum number of spheres movsphere can handle */ movsphere () { register int x, y, dir, len; register struct sphere *sp, *sp2; struct sphere sph[SPHMAX]; /* first duplicate sphere list */ for (sp = 0, x = 0, sp2 = spheres; sp2; sp2 = sp2 -> p)/* look through sphere list */ if (sp2 -> lev == level) {/* only if this level */ sph[x] = *sp2; sph[x++].p = 0; /* copy the struct */ if (x > 1) sph[x - 2].p = &sph[x - 1];/* link pointers */ } if (x) sp = sph; /* if any spheres, point to them */ else return; /* no spheres */ for (sp = sph; sp; sp = sp -> p) {/* look through sphere list */ x = sp -> x; y = sp -> y; if (item[x][y] != OANNIHILATION) continue; /* not really there */ if (--(sp -> lifetime) < 0) {/* has sphere run out of gas? */ rmsphere (x, y); /* delete sphere */ continue; } switch (rnd ((int) max (7, c[INTELLIGENCE] >> 1))) {/* time to move the sphere */ case 1: case 2: /* change direction to a random one */ sp -> dir = rnd (8); default: /* move in normal direction */ dir = sp -> dir; len = sp -> lifetime; rmsphere (x, y); newsphere (x + diroffx[dir], y + diroffy[dir], dir, len); }; } } SHAR_EOF if test 11581 -ne "`wc -c < 'movem.c'`" then echo shar: error transmitting "'movem.c'" '(should have been 11581 characters)' fi fi # end of overwriting check echo shar: extracting "'nap.c'" '(938 characters)' if test -f 'nap.c' then echo shar: will not over-write existing file "'nap.c'" else cat << \SHAR_EOF > 'nap.c' /* nap.c Larn is copyrighted 1986 by Noah Morgan. */ #include <times.h> /* * routine to take a nap for n milliseconds */ nap (x) register int x; { if (x <= 0) return; /* eliminate chance for infinite loop */ lflush (); if (x > 999) sleep (x / 1000); else napms (x); } #ifdef NONAP napms (x) /* do nothing */ int x; { } #else NONAP /* napms - sleep for time milliseconds - uses times() * This assumes that times returns a relative time in 100ths of a * second. This will do horrible things if your times() returns * seconds! */ napms (time) int time; { long matchclock,times (); struct tms stats; if (time <= 0) time = 1; /* eliminate chance for infinite loop */ times(&stats); /* 10ms/tic is 1000 ms/sec / 100 tics/sec */ matchclock = stats.tms_utime + (time/10); while (1) { times(&stats); if (matchclock < stats.tms_utime) break; } } #endif NONAP SHAR_EOF if test 938 -ne "`wc -c < 'nap.c'`" then echo shar: error transmitting "'nap.c'" '(should have been 938 characters)' fi fi # end of overwriting check echo shar: extracting "'readme.txt'" '(8418 characters)' if test -f 'readme.txt' then echo shar: will not over-write existing file "'readme.txt'" else cat << \SHAR_EOF > 'readme.txt' ****************************************************************************** PREFACE FOR VMS PORT OF LARN 12.0 After hacking away at this thing, I have finally gotten it to work on VMS 4.2 using the VAX-11 C 2.1 compiler. I have not tested it completely, but it seems to function correctly. I left the termcap stuff in because it works fine on VMS if you have a termcap database, but the VT100 *is* incredibly faster. You can adjust the compile time options in the DEF line of MAKE.COM (except for LARNHOME; you will have to change that inside of LARN.C). I removed a few obviously anti-VMS options, but everything else seems OK. Anyway, to compile this baby just MAKE.COM after you have edited the options and LARN.C. NOTE: Since does not have a *real* fork(), you should *not* enable checkpoints in option file unless your system is pretty unreliable. It slows the game a lot. Have fun! To compile: 1) Edit MAKE.COM to reflect your needs. a) If you choose to use the playerid option, make sure you have whoever is to be wizard play first. Otherwise you must set WISID to be 65536*GID+UID. Note that the GID and UID come from [GID,UID] account numbers (the displayed values are in OCTAL). So the WISID for [101,3] is 101(octal) * 65536 + 3(octal). b) You will have to modify the symbol LARNHOME in the LARN.C file since I couldn't figure out how to /DEFINE=(LARNHOME="whatever") in the MAKE.COM file. All LARN12.* files should also go in this directory (LARNHOME) before sexecuting. c) Execute MAKE.COM (you will have to edit the default directory in this command file). d) Move the executable (LARN.EXE) and all LARN12.* files to LARNHOME and set LARN as a foreign command (LARN :== $LARNHOME:LARN). - Mark Nagel ..!{ucbvax,dual,lll-crg}!ucdavis!{u557676751ea,u572112244ea,donovan} ******************************************************************************* ******************************************************************************* Larn is a dungeon type game program. Larn is a adventure/action game similar in concept to rogue or hack, but with a much different feel. Try it, you'll like it! You will have to edit the Makefile to reflect your configuration. Define LARNHOME as the place where the larn auxiliary files will reside, and BINDIR as the place where the larn executable should be placed. Type "make" to compile, or "make all" to compile and install ("make install" does just the install). Here's a list of what is in each of the various source files: CHANGES.TXT this is a list of the things that were changed since ver 11.0 1MAKEFILE. makefile script to compile the program README.TXT this is what you are now reading BILL.C code for the letters of praise if player wins /* moved to LARN.C MDN */ CONFIG.C data definitions for the installation dependent data -- savefilenames, where the scorefiles are, etc. CREATE.C code to create the dungeon and all objects DATA.C data definitions for the game -- no code here DIAG.C code to produce diagnostic data for wizards, & savegame stuff DISPLAY.C code to update the display on the screen FORTUNE.C code for the fortune cookies GLOBAL.C code for globally used functions that are specific to larn HEADER.H constant and structure definitions HELP.C code for the help screens in the game of larn LARN12.HDY data file which lists upcoming holidays IO.C code to handle file and terminal i/o /* added this module -- MDN */ KEYSENSE.C code to handle single key reading, dcl spawning LARN.C code for the main command control and parsing LARN12.MAZ data file for pre-made mazes LARN12.OPT a sample .larnopts option data file LARN12.FTN data file which contains the hints MONSTER.C code to handle attack and defense modes with monsters MOREOBJ.C code for the fountains, altars, thrones MOVEM.C code to move the monsters around the dungeon NAP.C code to sleep for less than a second OBJECT.C code to handle objects in the dungeon REGEN.C code to regenerate the player and advance game time SAVELEV.C code to get/put a level from level storage into working level memory SCORES.C code to process and manage the scoreboard SIGNAL.C code to handle signals that are trapped STORE.C code for the larn thrift shoppe, bank, trading post, lrs TOK.C code for the input front end and options file processing To find out how to play the game, run it and type in a '?' to get the help screens. By the way, the wizards password is "pvnert(x)" and to become wizard type in an underscore, you are then prompted for the password. Wizards are non-scoring characters that get enlightenment, everlasting expanded awareness, and one of every object in the game. They help the author to debug the game. Note regarding the wizard id: If you are using userid's, then WIZID must be set to the userid of the person who can become wizard. If you are using player id's, WIZID must be set to the playerid (edit file .playerids if needed) of the player who can become wizard. You may want to clear out the scoreboard. The command "larn -c" will make a new scoreboard. It will prompt you for the wizards password. BUGS & FIXES: James McNamara has volunteered to maintain the latest sources, and provide latest bug fixes to anyone who asks. Both James and I will field requests for sources, for those who ask. ___ Prince of Gems (alias Noah Morgan) /. \ USENET: panda!condor!noah \ / at GenRad Inc. Bolton MA \ / v Below is some additional info about the installation of larn: Install: Notes on the game LARN installation. Larn is copyrighted 1986 by Noah Morgan. This file (below) originally by James D. McNamara, last update 7/27/86 by nm THIS DISTRIBUTION: You should receive six (6) shar files, which are: larn.part-1 larn.part-2 larn.part-3 larn.part-4 larn.part-5 larn.part-6 I. Use /bin/sh (or your system equivalent) to "unravel" shar files larn.part-1, ..., larn.part-6. I suggest you do this directly into $LARNHOME (See Section III.). Notable files: README - The author's how-to. MANIFEST - Files you should have. III. Edit a copy of "Makefile" and leave the edited version in $LARNHOME. All the "configuration" options are tidily near the top of the "Makefile." Here are the ones you probably will want to edit: LARNHOME I specified (literally) the directory, with path from root, where "larn" will reside. This included where I put the *.c files, it is where the *.o files ended up, as well as all data and *.h files. i suspect the *.c and intallation-documentation files can be moved off, but the data and bits must all remain here for execution. BINDIR I specified (literally) the directory, with path from root, where the executable "larn" will reside. The "Makefile" will dump the "a.out", named "larn", in this directory. My BINDIR was not my LARNHOME, so $BINDIR/larn was the ONLY file dumed here. You'll probably have to chmod it for public execute, etc. OPTIONS This is how *I* specified them... they are documented in-line: OPTIONS = -DWIZZARD -DWIZID=157 -DEXTRA -DBSD -DSAVEINHOME IV. Compile the bugger. Read "README" before you do. You have a couple of options here: make - will not install, suspect good for updates. make all - compile (and) intall make install - just install I did "make" and then "make install" -- seems to work "ok", but "make all" probably safer, if I had known. Note that "Makefile" is the default file for "make." V. Execute and have fun. If wizard code "ok", larn -c will refresh the scoreboard. Play and win (or get killed) to put somebody on the scoreboard. VI. BUGS and FIXES. Please forward any bug-fixes in these regards to me (or Noah), so I may compile a fix-list for other installers. Thanks. Regards, =============================================================================== James D. McNamara CSNET: jim@bu-cs ARPANET: jim%bu-cs@csnet-relay UUCP: ...harvard!bu-cs!jim BITNET: jim%bu-cs%csnet-relay.arpa@wiscvm =============================================================================== SHAR_EOF if test 8418 -ne "`wc -c < 'readme.txt'`" then echo shar: error transmitting "'readme.txt'" '(should have been 8418 characters)' fi fi # end of overwriting check # End of shell archive exit 0
u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # monster.c # regen.c # savelev.c # signal.c # tok.c # This archive created: Sat Aug 30 14:52:16 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'monster.c'" '(45763 characters)' if test -f 'monster.c' then echo shar: will not over-write existing file "'monster.c'" else cat << \SHAR_EOF > 'monster.c' /* * monster.c Larn is copyrighted 1986 by Noah Morgan. * *This file contains the following functions: *---------------------------------------------------------------------------- * *createmonster(monstno) Function to create a monster next to the player *int monstno; * *int cgood(x,y,itm,monst) Function to check location for emptiness *int x,y,itm,monst; * *createitem(it,arg) Routine to place an item next to the player *int it,arg; * *cast() Subroutine called by parse to cast a spell for the user * *speldamage(x) Function to perform spell functions cast by the player *int x; * *loseint() Routine to decrement your int(intelligence) if > 3 * *isconfuse() Routine to check to see if player is confused * *nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster *int x,monst; * *fullhit(xx) Function to return full damage against a monst(aka web) *int xx; * *direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir *int spnum,dam,arg; *char *str; * *godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks *int spnum,dam,delay; *char *str,cshow; * *ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt *int x,y; * *tdirect(spnum) Routine to teleport away a monster *int spnum; * *omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player *int sp,dam; *char *str; * *dirsub(x,y) Routine to ask for direction, then modify x,y for it *int *x,*y; * *vxy(x,y) Routine to verify/fix(*x,*y) for being within bounds *int *x,*y; * *dirpoly(spnum) Routine to ask for a direction and polymorph a monst *int spnum; * *hitmonster(x,y) Function to hit a monster at the designated coordinates *int x,y; * *hitm(x,y,amt) Function to just hit a monster at a given coordinates *int x,y,amt; * *hitplayer(x,y) Function for the monster to hit the player from(x,y) *int x,y; * *dropsomething(monst) Function to create an object when a monster dies *int monst; * *dropgold(amount) Function to drop some gold around player *int amount; * *something(level) Function to create a random item around player *int level; * *newobject(lev,i) Routine to return a randomly selected new object *int lev,*i; * *spattack(atckno,xx,yy) Function to process special attacks from monsters *int atckno,xx,yy; * *checkloss(x) Routine to subtract hp from user and flag bottomline display *int x; * *annihilate() Routine to annihilate monsters around player, playerx,playery * *newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation *int x,y,dir,lifetime; * *rmsphere(x,y) Function to delete a sphere of annihilation from list *int x,y; * *sphboom(x,y) Function to perform the effects of a sphere detonation *int x,y; * *genmonst() Function to ask for monster and genocide from game * */ #include "header.h" struct isave { /* used for alter reality */ char type; /* 0=item, 1=monster */ char id; /* item number or monster number */ short arg; /* the type of item or hitpoints of monster */ }; /* *createmonster(monstno) Function to create a monster next to the player *int monstno; * * Enter with the monster number(1 to MAXMONST+8) * Returns no value. */ createmonster(mon) int mon; { register int x, y, k, i; if (mon < 1 || mon > MAXMONST + 8) {/* check for monster number out of bounds */ beep(); lprintf("\ncan't createmonst(%d)\n",(long) mon); nap(3000); return; } while (monster[mon].genocided && mon < MAXMONST) mon++; /* genocided? */ for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */ if (k > 8) k = 1; /* wraparound the diroff arrays */ x = playerx + diroffx[k]; y = playery + diroffy[k]; if (cgood(x, y, 0, 1)) {/* if we can create here */ mitem[x][y] = mon; hitp[x][y] = monster[mon].hitpoints; stealth[x][y] = know[x][y] = 0; switch(mon) { case ROTHE: case POLTERGEIST: case VAMPIRE: stealth[x][y] = 1; }; return; } } } /* * int cgood(x,y,itm,monst) Function to check location for emptiness * int x,y,itm,monst; * * Routine to return TRUE if a location does not have itm or monst there * returns FALSE(0) otherwise * Enter with itm or monst TRUE or FALSE if checking it * Example: if itm==TRUE check for no item at this location * if monst==TRUE check for no monster at this location * This routine will return FALSE if at a wall or the dungeon exit on level 1 */ int cgood(x, y, itm, monst) register int x, y; int itm, monst; { if ((y >= 0) && (y <= MAXY - 1) && (x >= 0) && (x <= MAXX - 1))/* within bounds? */ if (item[x][y] != OWALL)/* can't make anything on walls */ if (itm == 0 || (item[x][y] == 0))/* is it free of items? */ if (monst == 0 || (mitem[x][y] == 0))/* is it free of monsters? */ if ((level != 1) || (x != 33) || (y != MAXY - 1))/* not exit to level 1 */ return(1); return(0); } /* * createitem(it,arg) Routine to place an item next to the player * int it,arg; * * Enter with the item number and its argument(iven[], ivenarg[]) * Returns no value, thus we don't know about createitem() failures. */ createitem(it, arg) int it, arg; { register int x, y, k, i; if (it >= MAXOBJ) return; /* no such object */ for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */ if (k > 8) k = 1; /* wraparound the diroff arrays */ x = playerx + diroffx[k]; y = playery + diroffy[k]; if (cgood(x, y, 1, 0)) {/* if we can create here */ item[x][y] = it; know[x][y] = 0; iarg[x][y] = arg; return; } } } /* * cast() Subroutine called by parse to cast a spell for the user * * No arguments and no return value. */ static char eys[] = "\nEnter your spell: "; cast() { register int i,j,a,b,d; cursors(); if (c[SPELLS] <= 0) { lprcat("\nYou don't have any spells!"); return; } lprcat(eys); --c[SPELLS]; while ((a = readchar()) == 'D') { seemagic(-1); cursors(); lprcat(eys); } if (a == '\33') goto over; /* to escape casting a spell */ if ((b = readchar()) == '\33') goto over; /* to escape casting a spell */ if ((d = readchar()) == '\33') { over: lprcat(aborted); c[SPELLS]++; return; } /* to escape casting a spell */ #ifdef EXTRA c[SPELLSCAST]++; #endif for (lprc('\n'), j = -1, i = 0; i < SPNUM; i++)/* seq search for his spell, hash? */ if ((spelcode[i][0] == a) && (spelcode[i][1] == b) && (spelcode[i][2] == d)) if (spelknow[i]) { speldamage(i); j = 1; i = SPNUM; } if (j == -1) lprcat(" Nothing Happened "); bottomline(); } /* * speldamage(x) Function to perform spell functions cast by the player * int x; * * Enter with the spell number, returns no value. * Please insure that there are 2 spaces before all messages here */ speldamage(x) int x; { register int i, j, clev; int xl, xh, yl, yh; register char *p, *kn, *pm; if (x >= SPNUM) return; /* no such spell */ if (c[TIMESTOP]) { lprcat(" It didn't seem to work"); return; } /* not if time stopped */ clev = c[LEVEL]; if ((rnd(23) == 7) || (rnd(18) > c[INTELLIGENCE])) { lprcat(" It didn't work!"); return; } if (clev * 3 + 2 < x) { lprcat(" Nothing happens. You seem inexperienced at this"); return; } switch(x) { /* ----- LEVEL 1 SPELLS ----- */ case 0: if (c[PROTECTIONTIME] == 0) c[MOREDEFENSES] += 2;/* protection field +2 */ c[PROTECTIONTIME] += 250; return; case 1: i = rnd(((clev + 1) << 1)) + clev + 3; godirect(x, i,(clev >= 2) ? " Your missiles hit the %s" : " Your missile hit the %s", 100, '+'); /* magic missile */ return; case 2: if (c[DEXCOUNT] == 0) c[DEXTERITY] += 3;/* dexterity */ c[DEXCOUNT] += 400; return; case 3: i = rnd(3) + 1; p = " While the %s slept, you smashed it %d times"; ws: direct(x, fullhit(i), p, i);/* sleep */ return; case 4: /* charm monster */ c[CHARMCOUNT] += c[CHARISMA] << 1; return; case 5: godirect(x, rnd(10) + 15 + clev, " The sound damages the %s", 70, '@');/* sonic spear */ return; /* ----- LEVEL 2 SPELLS ----- */ case 6: i = rnd(3) + 2; p = " While the %s is entangled, you hit %d times"; goto ws; /* web */ case 7: if (c[STRCOUNT] == 0) c[STREXTRA] += 3;/* strength */ c[STRCOUNT] += 150 + rnd(100); return; case 8: yl = playery - 5; /* enlightenment */ yh = playery + 6; xl = playerx - 15; xh = playerx + 16; vxy(&xl, &yl); vxy(&xh, &yh); /* check bounds */ for (i = yl; i <= yh; i++)/* enlightenment */ for (j = xl; j <= xh; j++) know[j][i] = 1; draws(xl, xh + 1, yl, yh + 1); return; case 9: raisehp(20 +(clev << 1)); return; /* healing */ case 10: c[BLINDCOUNT] = 0; return; /* cure blindness */ case 11: createmonster(makemonst(level + 1) + 8); return; case 12: if (rnd(11) + 7 <= c[WISDOM]) direct(x, rnd(20) + 20 + clev, " The %s believed!", 0); else lprcat(" It didn't believe the illusions!"); return; case 13: /* if he has the amulet of invisibility then add more time */ for (j = i = 0; i < 26; i++) if (iven[i] == OAMULET) j += 1 + ivenarg[i]; c[INVISIBILITY] +=(j << 7) + 12; return; /* ----- LEVEL 3 SPELLS ----- */ case 14: godirect(x, rnd(25 + clev) + 25 + clev, " The fireball hits the %s", 40, '*'); return; /* fireball */ case 15: godirect(x, rnd(25) + 20 + clev, " Your cone of cold strikes the %s", 60, 'O');/* cold */ return; case 16: dirpoly(x); return; /* polymorph */ case 17: c[CANCELLATION] += 5 + clev; return; /* cancellation */ case 18: c[HASTESELF] += 7 + clev; return; /* haste self */ case 19: omnidirect(x, 30 + rnd(10), " The %s gasps for air");/* cloud kill */ return; case 20: xh = min(playerx + 1, MAXX - 2); yh = min(playery + 1, MAXY - 2); for (i = max(playerx - 1, 1); i <= xh; i++)/* vaporize rock */ for (j = max(playery - 1, 1); j <= yh; j++) { kn = &know[i][j]; pm = &mitem[i][j]; switch(*(p = &item[i][j])) { case OWALL: if (level < MAXLEVEL + MAXVLEVEL - 1) *p = *kn = 0; break; case OSTATUE: if (c[HARDGAME] < 3) { *p = OBOOK; iarg[i][j] = level; *kn = 0; } break; case OTHRONE: *pm = GNOMEKING; *kn = 0; *p = OTHRONE2; hitp[i][j] = monster[GNOMEKING].hitpoints; break; case OALTAR: *pm = DEMONPRINCE; *kn = 0; hitp[i][j] = monster[DEMONPRINCE].hitpoints; break; }; switch(*pm) { case XORN: ifblind(i, j); hitm(i, j, 200); break;/* Xorn takes damage from vpr */ } } return; /* ----- LEVEL 4 SPELLS ----- */ case 21: direct(x, 100 + clev, " The %s shrivels up", 0);/* dehydration */ return; case 22: godirect(x, rnd(25) + 20 +(clev << 1), " A lightning bolt hits the %s", 1, '~');/* lightning */ return; case 23: i = min(c[HP] - 1, c[HPMAX] / 2);/* drain life */ direct(x, i + i, "", 0); c[HP] -= i; return; case 24: if (c[GLOBE] == 0) c[MOREDEFENSES] += 10; c[GLOBE] += 200; loseint(); /* globe of invulnerability */ return; case 25: omnidirect(x, 32 + clev, " The %s struggles for air in your flood!");/* flood */ return; case 26: if (rnd(151) == 63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000); died(270); return; } if (c[WISDOM] > rnd(10) + 10) direct(x, 2000, " The %s's heart stopped", 0);/* finger of death */ else lprcat(" It didn't work"); return; /* ----- LEVEL 5 SPELLS ----- */ case 27: c[SCAREMONST] += rnd(10) + clev; return; /* scare monster */ case 28: c[HOLDMONST] += rnd(10) + clev; return; /* hold monster */ case 29: c[TIMESTOP] += rnd(20) +(clev << 1); return; /* time stop */ case 30: tdirect(x); return; /* teleport away */ case 31: omnidirect(x, 35 + rnd(10) + clev, " The %s cringes from the flame");/* magic fire */ return; /* ----- LEVEL 6 SPELLS ----- */ case 32: if ((rnd(23) == 5) && (wizard == 0)) {/* sphere of annihilation */ beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n"); nap(4000); died(258); return; } xl = playerx; yl = playery; loseint(); i = dirsub(&xl, &yl);/* get direction of sphere */ newsphere(xl, yl, i, rnd(20) + 11);/* make a sphere */ return; case 33: genmonst(); spelknow[33] = 0; /* genocide */ loseint(); return; case 34: /* summon demon */ if (rnd(100) > 30) { direct(x, 150, " The demon strikes at the %s", 0); return; } if (rnd(100) > 15) { lprcat(" Nothing seems to have happened"); return; } lprcat(" The demon turned on you and vanished!"); beep(); i = rnd(40) + 30; lastnum = 277; losehp(i); /* must say killed by a demon */ return; case 35: /* walk through walls */ c[WTW] += rnd(10) + 5; return; case 36: /* alter reality */ { struct isave *save;/* pointer to item save structure */ int sc; sc = 0; /* # items saved */ save =(struct isave *) malloc(sizeof(struct isave) * MAXX * MAXY * 2); for (j = 0; j < MAXY; j++) for (i = 0; i < MAXX; i++) {/* save all items and monsters */ xl = item[i][j]; if (xl && xl != OWALL && xl != OANNIHILATION) { save[sc].type = 0; save[sc].id = item[i][j]; save[sc++].arg = iarg[i][j]; } if (mitem[i][j]) { save[sc].type = 1; save[sc].id = mitem[i][j]; save[sc++].arg = hitp[i][j]; } item[i][j] = OWALL; mitem[i][j] = 0; if (wizard) know[i][j] = 1; else know[i][j] = 0; } eat(1, 1); if (level == 1) item[33][MAXY - 1] = 0; for (j = rnd(MAXY - 2), i = 1; i < MAXX - 1; i++) item[i][j] = 0; while (sc > 0) {/* put objects back in level */ --sc; if (save[sc].type == 0) { int trys; for (trys = 100, i = j = 1; --trys > 0 && item[i][j]; i = rnd(MAXX - 1), j = rnd(MAXY - 1)); if (trys) { item[i][j] = save[sc].id; iarg[i][j] = save[sc].arg; } } else { /* put monsters back in */ int trys; for (trys = 100, i = j = 1; --trys > 0 && (item[i][j] == OWALL || mitem[i][j]); i = rnd(MAXX - 1), j = rnd(MAXY - 1)); if (trys) { mitem[i][j] = save[sc].id; hitp[i][j] = save[sc].arg; } } } loseint(); draws(0, MAXX, 0, MAXY); if (wizard == 0) spelknow[36] = 0; free((char *) save); positionplayer(); return; } case 37: /* permanence */ adjtime(-99999L); spelknow[37] = 0; /* forget */ loseint(); return; default: lprintf(" spell %d not available!",(long) x); beep(); return; }; } /* * loseint() Routine to subtract 1 from your int(intelligence) if > 3 * * No arguments and no return value */ loseint() { if (--c[INTELLIGENCE] < 3) c[INTELLIGENCE] = 3; } /* * isconfuse() Routine to check to see if player is confused * * This routine prints out a message saying "You can't aim your magic!" * returns 0 if not confused, non-zero(time remaining confused) if confused */ isconfuse() { if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); } return(c[CONFUSE]); } /* * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster * int x,monst; * * Subroutine to return 1 if the spell can't affect the monster * otherwise returns 0 * Enter with the spell number in x, and the monster number in monst. */ nospell(x, monst) int x, monst; { register int tmp; if (x >= SPNUM || monst >= MAXMONST + 8 || monst < 0 || x < 0) return(0); /* bad spell or monst */ if ((tmp = spelweird[monst - 1][x]) == 0) return(0); cursors(); lprc('\n'); lprintf(spelmes[tmp], monster[monst].name); return(1); } /* * fullhit(xx) Function to return full damage against a monster(aka web) * int xx; * * Function to return hp damage to monster due to a number of full hits * Enter with the number of full hits being done */ fullhit(xx) int xx; { register int i; if (xx < 0 || xx > 20) return(0); /* fullhits are out of range */ if (c[LANCEDEATH]) return(10000); /* lance of death */ i = xx *((c[WCLASS] >> 1) + c[STRENGTH] + c[STREXTRA] - c[HARDGAME] - 12 + c[MOREDAM]); return((i >= 1) ? i : xx); } /* * direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir * int spnum,dam,arg; * char *str; * * Routine to ask for a direction to a spell and then hit the monster * Enter with the spell number in spnum, the damage to be done in dam, * lprintf format string in str, and lprintf's argument in arg. * Returns no value. */ direct(spnum, dam, str, arg) int spnum, dam, arg; char *str; { int x, y; register int m; if (spnum < 0 || spnum >= SPNUM || str == 0) return; /* bad arguments */ if (isconfuse()) return; dirsub(&x, &y); m = mitem[x][y]; if (item[x][y] == OMIRROR) { if (spnum == 3) { /* sleep */ lprcat("You fall asleep! "); beep(); fool: arg += 2; while (arg-- > 0) { parse2(); nap(1000); } return; } else if (spnum == 6) { /* web */ lprcat("You get stuck in your own web! "); beep(); goto fool; } else { lastnum = 278; lprintf(str, "spell caster(thats you)",(long) arg); beep(); losehp(dam); return; } } if (m == 0) { lprcat(" There wasn't anything there!"); return; } ifblind(x, y); if (nospell(spnum, m)) { lasthx = x; lasthy = y; return; } lprintf(str, lastmonst,(long) arg); hitm(x, y, dam); } /* * godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks * int spnum,dam,delay; * char *str,cshow; * * Function to hit in a direction from a missile weapon and have it keep * on going in that direction until its power is exhausted * Enter with the spell number in spnum, the power of the weapon in hp, * lprintf format string in str, the # of milliseconds to delay between * locations in delay, and the character to represent the weapon in cshow. * Returns no value. */ godirect(spnum, dam, str, delay, cshow) int spnum, dam, delay; char *str, cshow; { register char *p; register int x, y, m; int dx, dy; if (spnum < 0 || spnum >= SPNUM || str == 0 || delay < 0) return; /* bad args */ if (isconfuse()) return; dirsub(&dx, &dy); x = dx; y = dy; dx = x - playerx; dy = y - playery; x = playerx; y = playery; while (dam > 0) { x += dx; y += dy; if ((x > MAXX - 1) || (y > MAXY - 1) || (x < 0) || (y < 0)) { dam = 0; break; /* out of bounds */ } if ((x == playerx) && (y == playery)) {/* if energy hits player */ cursors(); lprcat("\nYou are hit my your own magic!"); beep(); lastnum = 278; losehp(dam); return; } if (c[BLINDCOUNT] == 0) {/* if not blind show effect */ cursor(x + 1, y + 1); lprc(cshow); nap(delay); show1cell(x, y); } if ((m = mitem[x][y])) {/* is there a monster there? */ ifblind(x, y); if (nospell(spnum, m)) { lasthx = x; lasthy = y; return; } cursors(); lprc('\n'); lprintf(str, lastmonst); dam -= hitm(x, y, dam); show1cell(x, y); nap(1000); x -= dx; y -= dy; } else switch(*(p = &item[x][y])) { case OWALL: cursors(); lprc('\n'); lprintf(str, "wall"); if (dam >= 50 + c[HARDGAME])/* enough damage? */ if (level < MAXLEVEL + MAXVLEVEL - 1)/* not on V3 */ if ((x < MAXX - 1) && (y < MAXY - 1) && (x) && (y)) { lprcat(" The wall crumbles"); god3: *p = 0; god: know[x][y] = 0; show1cell(x, y); } god2: dam = 0; break; case OCLOSEDDOOR: cursors(); lprc('\n'); lprintf(str, "door"); if (dam >= 40) { lprcat(" The door is blasted apart"); goto god3; } goto god2; case OSTATUE: cursors(); lprc('\n'); lprintf(str, "statue"); if (c[HARDGAME] < 3) if (dam > 44) { lprcat(" The statue crumbles"); *p = OBOOK; iarg[x][y] = level; goto god; } goto god2; case OTHRONE: cursors(); lprc('\n'); lprintf(str, "throne"); if (dam > 39) { mitem[x][y] = GNOMEKING; hitp[x][y] = monster[GNOMEKING].hitpoints; *p = OTHRONE2; goto god; } goto god2; case OMIRROR: dx *= -1; dy *= -1; break; }; dam -= 3 +(c[HARDGAME] >> 1); } } /* * ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt * int x,y; * * Subroutine to copy the word "monster" into lastmonst if the player is blind * Enter with the coordinates(x,y) of the monster * Returns no value. */ ifblind(x, y) int x, y; { char *p; vxy(&x, &y); /* verify correct x,y coordinates */ if (c[BLINDCOUNT]) { lastnum = 279; p = "monster"; } else { lastnum = mitem[x][y]; p = monster[lastnum].name; } strcpy(lastmonst, p); } /* * tdirect(spnum) Routine to teleport away a monster * int spnum; * * Routine to ask for a direction to a spell and then teleport away monster * Enter with the spell number that wants to teleport away * Returns no value. */ tdirect(spnum) int spnum; { int x, y; register int m; if (spnum < 0 || spnum >= SPNUM) return; /* bad args */ if (isconfuse()) return; dirsub(&x, &y); if ((m = mitem[x][y]) == 0) { lprcat(" There wasn't anything there!"); return; } ifblind(x, y); if (nospell(spnum, m)) { lasthx = x; lasthy = y; return; } fillmonst(m); mitem[x][y] = know[x][y] = 0; } /* * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player * int sp,dam; * char *str; * * Routine to cast a spell and then hit the monster in all directions * Enter with the spell number in sp, the damage done to wach square in dam, * and the lprintf string to identify the spell in str. * Returns no value. */ omnidirect(spnum, dam, str) int spnum, dam; char *str; { register int x, y, m; if (spnum < 0 || spnum >= SPNUM || str == 0) return; /* bad args */ for (x = playerx - 1; x < playerx + 2; x++) for (y = playery - 1; y < playery + 2; y++) { if (m = mitem[x][y]) if (nospell(spnum, m) == 0) { ifblind(x, y); cursors(); lprc('\n'); lprintf(str, lastmonst); hitm(x, y, dam); nap(800); } else { lasthx = x; lasthy = y; } } } /* * static dirsub(x,y) Routine to ask for direction, then modify x,y for it * int *x,*y; * * Function to ask for a direction and modify an x,y for that direction * Enter with the origination coordinates in(x,y). * Returns index into diroffx[](0-8). */ static dirsub(x, y) int *x, *y; { register int i; lprcat("\nIn What Direction? "); for (i = 0;;) switch(readchar()) { case 'b': i++; case 'n': i++; case 'y': i++; case 'u': i++; case 'h': i++; case 'k': i++; case 'l': i++; case 'j': i++; goto out; }; out: *x = playerx + diroffx[i]; *y = playery + diroffy[i]; vxy(x, y); return(i); } /* * vxy(x,y) Routine to verify/fix coordinates for being within bounds * int *x,*y; * * Function to verify x & y are within the bounds for a level * If *x or *y is not within the absolute bounds for a level, fix them so that * they are on the level. * Returns TRUE if it was out of bounds, and the *x & *y in the calling * routine are affected. */ vxy(x, y) int *x, *y; { int flag = 0; if (*x < 0) { *x = 0; flag++; } if (*y < 0) { *y = 0; flag++; } if (*x >= MAXX) { *x = MAXX - 1; flag++; } if (*y >= MAXY) { *y = MAXY - 1; flag++; } return(flag); } /* * dirpoly(spnum) Routine to ask for a direction and polymorph a monst * int spnum; * * Subroutine to polymorph a monster and ask for the direction its in * Enter with the spell number in spmun. * Returns no value. */ dirpoly(spnum) int spnum; { int x, y, m; if (spnum < 0 || spnum >= SPNUM) return; /* bad args */ if (isconfuse()) return; /* if he is confused, he can't aim his magic */ dirsub(&x, &y); if (mitem[x][y] == 0) { lprcat(" There wasn't anything there!"); return; } ifblind(x, y); if (nospell(spnum, mitem[x][y])) { lasthx = x; lasthy = y; return; } while (monster[m = mitem[x][y] = rnd(MAXMONST + 7)].genocided); hitp[x][y] = monster[m].hitpoints; show1cell(x, y); /* show the new monster */ } /* * hitmonster(x,y) Function to hit a monster at the designated coordinates * int x,y; * * This routine is used for a bash & slash type attack on a monster * Enter with the coordinates of the monster in(x,y). * Returns no value. */ hitmonster(x, y) int x, y; { register int tmp, monst, damag, flag; if (c[TIMESTOP]) return; /* not if time stopped */ vxy(&x, &y); /* verify coordinates are within range */ if ((monst = mitem[x][y]) == 0) return; hit3flag = 1; ifblind(x, y); tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS] / 4 - 12; cursors(); if ((rnd(20) < tmp - c[HARDGAME]) || (rnd(71) < 5)) {/* need at least random chance to hit */ lprcat("\nYou hit"); flag = 1; damag = fullhit(1); if (damag < 9999) damag = rnd(damag) + 1; } else { lprcat("\nYou missed"); flag = 0; } lprcat(" the "); lprcat(lastmonst); if (flag) /* if the monster was hit */ if ((monst == RUSTMONSTER) || (monst == DISENCHANTRESS) || (monst == CUBE)) if (c[WIELD] > 0) if (ivenarg[c[WIELD]] > -10) { lprintf("\nYour weapon is dulled by the %s", lastmonst); beep(); --ivenarg[c[WIELD]]; } if (flag) hitm(x, y, damag); if (monst == VAMPIRE) if (hitp[x][y] < 25) { mitem[x][y] = BAT; know[x][y] = 0; } } /* * hitm(x,y,amt) Function to just hit a monster at a given coordinates * int x,y,amt; * * Returns the number of hitpoints the monster absorbed * This routine is used to specifically damage a monster at a location(x,y) * Called by hitmonster(x,y) */ hitm(x, y, amt) int x, y; register amt; { register int monst; int hpoints, amt2; vxy(&x, &y); /* verify coordinates are within range */ amt2 = amt; /* save initial damage so we can return it */ monst = mitem[x][y]; if (c[HALFDAM]) amt >>= 1; /* if half damage curse adjust damage points */ if (amt <= 0) amt2 = amt = 1; lasthx = x; lasthy = y; stealth[x][y] = 1; /* make sure hitting monst breaks stealth condition */ c[HOLDMONST] = 0; /* hit a monster breaks hold monster spell */ switch(monst) { /* if a dragon and orb(s) of dragon slaying */ case WHITEDRAGON: case REDDRAGON: case GREENDRAGON: case BRONZEDRAGON: case PLATINUMDRAGON: case SILVERDRAGON: amt *= 1 +(c[SLAYING] << 1); break; } /* invincible monster fix is here */ if (hitp[x][y] > monster[monst].hitpoints) hitp[x][y] = monster[monst].hitpoints; if ((hpoints = hitp[x][y]) <= amt) { #ifdef EXTRA c[MONSTKILLED]++; #endif lprintf("\nThe %s died!", lastmonst); raiseexperience((long) monster[monst].experience); amt = monster[monst].gold; if (amt > 0) dropgold(rnd(amt) + amt); dropsomething(monst); disappear(x, y); bottomline(); return(hpoints); } hitp[x][y] = hpoints - amt; return(amt2); } /* * hitplayer(x,y) Function for the monster to hit the player from(x,y) * int x,y; * * Function for the monster to hit the player with monster at location x,y * Returns nothing of value. */ hitplayer(x, y) int x, y; { register int dam, tmp, mster, bias; vxy(&x, &y); /* verify coordinates are within range */ lastnum = mster = mitem[x][y]; /* spirit naga's and poltergeist's do nothing if scarab of negate spirit */ if (c[NEGATESPIRIT] || c[SPIRITPRO]) if ((mster == POLTERGEIST) || (mster == SPIRITNAGA)) return; /* if undead and cube of undead control */ if (c[CUBEofUNDEAD] || c[UNDEADPRO]) if ((mster == VAMPIRE) || (mster == WRAITH) || (mster == ZOMBIE)) return; if ((know[x][y] & 1) == 0) { know[x][y] = 1; show1cell(x, y); } bias =(c[HARDGAME]) + 1; hitflag = hit2flag = hit3flag = 1; yrepcount = 0; cursors(); ifblind(x, y); if (c[INVISIBILITY]) if (rnd(33) < 20) { lprintf("\nThe %s misses wildly", lastmonst); return; } if (c[CHARMCOUNT]) if (rnd(30) + 5 * monster[mster].level - c[CHARISMA] < 30) { lprintf("\nThe %s is awestruck at your magnificence!", lastmonst); return; } if (mster == BAT) dam = 1; else { dam = monster[mster].damage; dam += rnd((int)((dam < 1) ? 1 : dam)) + monster[mster].level; } tmp = 0; if (monster[mster].attack > 0) if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) { if (spattack(monster[mster].attack, x, y)) { flushall(); return; } tmp = 1; bias -= 2; cursors(); } if (((dam + bias) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) { lprintf("\n The %s hit you ", lastmonst); tmp = 1; if ((dam -= c[AC]) < 0) dam = 0; if (dam > 0) { losehp(dam); bottomhp(); flushall(); } } if (tmp == 0) lprintf("\n The %s missed ", lastmonst); } /* * dropsomething(monst) Function to create an object when a monster dies * int monst; * * Function to create an object near the player when certain monsters are killed * Enter with the monster number * Returns nothing of value. */ dropsomething(monst) int monst; { switch(monst) { case ORC: case NYMPH: case ELF: case TROGLODYTE: case TROLL: case ROTHE: case VIOLETFUNGI: case PLATINUMDRAGON: case GNOMEKING: case REDDRAGON: something(level); return; case LEPRECHAUN: if (rnd(101) >= 75) creategem(); if (rnd(5) == 1) dropsomething(LEPRECHAUN); return; } } /* * dropgold(amount) Function to drop some gold around player * int amount; * * Enter with the number of gold pieces to drop * Returns nothing of value. */ dropgold(amount) register int amount; { if (amount > 250) createitem(OMAXGOLD, amount / 100); else createitem(OGOLDPILE, amount); } /* * something(level) Function to create a random item around player * int level; * * Function to create an item from a designed probability around player * Enter with the cave level on which something is to be dropped * Returns nothing of value. */ something(level) int level; { register int j; int i; if (level < 0 || level > MAXLEVEL + MAXVLEVEL) return; /* correct level? */ if (rnd(101) < 8) something(level); /* possibly more than one item */ j = newobject(level, &i); createitem(j, i); } /* * newobject(lev,i) Routine to return a randomly selected new object * int lev,*i; * * Routine to return a randomly selected object to be created * Returns the object number created, and sets *i for its argument * Enter with the cave level and a pointer to the items arg */ static char nobjtab[] = { 0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION, OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE, OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER, OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR, OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE, OLONGSWORD }; newobject(lev, i) register int lev, *i; { register int tmp = 32, j; if (level < 0 || level > MAXLEVEL + MAXVLEVEL) return(0); /* correct level? */ if (lev > 6) tmp = 37; else if (lev > 4) tmp = 35; j = nobjtab[tmp = rnd(tmp)];/* the object type */ switch(tmp) { case 1: case 2: case 3: case 4: *i = newscroll(); break; case 5: case 6: case 7: case 8: *i = newpotion(); break; case 9: case 10: case 11: case 12: *i = rnd((lev + 1) * 10) + lev * 10 + 10; break; case 13: case 14: case 15: case 16: *i = lev; break; case 17: case 18: case 19: if (!(*i = newdagger())) return(0); break; case 20: case 21: case 22: if (!(*i = newleather())) return(0); break; case 23: case 32: case 35: *i = rund(lev / 3 + 1); break; case 24: case 26: *i = rnd(lev / 4 + 1); break; case 25: *i = rund(lev / 4 + 1); break; case 27: *i = rnd(lev / 2 + 1); break; case 30: case 33: *i = rund(lev / 2 + 1); break; case 28: *i = rund(lev / 3 + 1); if (*i == 0) return(0); break; case 29: case 31: *i = rund(lev / 2 + 1); if (*i == 0) return(0); break; case 34: *i = newchain(); break; case 36: *i = newplate(); break; case 37: *i = newsword(); break; } return(j); } /* * spattack(atckno,xx,yy) Function to process special attacks from monsters * int atckno,xx,yy; * * Enter with the special attack number, and the coordinates(xx,yy) * of the monster that is special attacking * Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise * * atckno monster effect * --------------------------------------------------- * 0 none * 1 rust monster eat armor * 2 hell hound breathe light fire * 3 dragon breathe fire * 4 giant centipede weakening sing * 5 white dragon cold breath * 6 wraith drain level * 7 waterlord water gusher * 8 leprechaun steal gold * 9 disenchantress disenchant weapon or armor * 10 ice lizard hits with barbed tail * 11 umber hulk confusion * 12 spirit naga cast spells taken from special attacks * 13 platinum dragon psionics * 14 nymph steal objects * 15 bugbear bite * 16 osequip bite * * char rustarm[ARMORTYPES][2]; * special array for maximum rust damage to armor from rustmonster * format is: { armor type , minimum attribute */ #define ARMORTYPES 6 static char rustarm[ARMORTYPES][2] = { OSTUDLEATHER, -2, ORING, -4, OCHAIN, -5, OSPLINT, -6, OPLATE, -8, OPLATEARMOR, -9 }; static char spsel[] = { 1, 2, 3, 5, 6, 8, 9, 11, 13, 14 }; spattack(x, xx, yy) int x, xx, yy; { register int i, j = 0, k, m; register char *p = 0; if (c[CANCELLATION]) return(0); vxy(&xx, &yy); /* verify x & y coordinates */ switch(x) { case 1: /* rust your armor, j=1 when rusting has occurred */ m = k = c[WEAR]; if ((i = c[SHIELD]) != -1) if (--ivenarg[i] < -1) ivenarg[i] = -1; else j = 1; if ((j == 0) && (k != -1)) { m = iven[k]; for (i = 0; i < ARMORTYPES; i++) if (m == rustarm[i][0]) {/* find his armor in table */ if (--ivenarg[k] < rustarm[i][1]) ivenarg[k] = rustarm[i][1]; else j = 1; break; } } if (j == 0) /* if rusting did not occur */ switch(m) { case OLEATHER: p = "\nThe %s hit you -- Your lucky you have leather on"; break; case OSSPLATE: p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!"; break; } else { beep(); p = "\nThe %s hit you -- your armor feels weaker"; } break; case 2: i = rnd(15) + 8 - c[AC]; spout: p = "\nThe %s breathes fire at you!"; if (c[FIRERESISTANCE]) p = "\nThe %s's flame doesn't phase you!"; else spout2: if (p) { lprintf(p, lastmonst); beep(); } checkloss(i); return(0); case 3: i = rnd(20) + 25 - c[AC]; goto spout; case 4: if (c[STRENGTH] > 3) { p = "\nThe %s stung you! You feel weaker"; beep(); --c[STRENGTH]; } else p = "\nThe %s stung you!"; break; case 5: p = "\nThe %s blasts you with his cold breath"; i = rnd(15) + 18 - c[AC]; goto spout2; case 6: lprintf("\nThe %s drains you of your life energy!", lastmonst); loselevel(); beep(); return(0); case 7: p = "\nThe %s got you with a gusher!"; i = rnd(15) + 25 - c[AC]; goto spout2; case 8: if (c[NOTHEFT]) return(0); /* he has a device of no theft */ if (c[GOLD]) { p = "\nThe %s hit you -- Your purse feels lighter"; if (c[GOLD] > 32767) c[GOLD] >>= 1; else c[GOLD] -= rnd((int)(1 +(c[GOLD] >> 1))); if (c[GOLD] < 0) c[GOLD] = 0; } else p = "\nThe %s couldn't find any gold to steal"; lprintf(p, lastmonst); disappear(xx, yy); beep(); bottomgold(); return(1); case 9: for (j = 50;;) { /* disenchant */ i = rund(26); m = iven[i]; /* randomly select item */ if (m > 0 && ivenarg[i] > 0 && m != OSCROLL && m != OPOTION) { if ((ivenarg[i] -= 3) < 0) ivenarg[i] = 0; lprintf("\nThe %s hits you -- you feel a sense of loss", lastmonst); srcount = 0; beep(); show3(i); bottomline(); return(0); } if (--j <= 0) { p = "\nThe %s nearly misses"; break; } break; } break; case 10: p = "\nThe %s hit you with his barbed tail"; i = rnd(25) - c[AC]; goto spout2; case 11: p = "\nThe %s has confused you"; beep(); c[CONFUSE] += 10 + rnd(10); break; case 12: /* performs any number of other special attacks */ return(spattack(spsel[rund(10)], xx, yy)); case 13: p = "\nThe %s flattens you with his psionics!"; i = rnd(15) + 30 - c[AC]; goto spout2; case 14: if (c[NOTHEFT]) return(0); /* he has device of no theft */ if (emptyhanded() == 1) { p = "\nThe %s couldn't find anything to steal"; break; } lprintf("\nThe %s picks your pocket and takes:", lastmonst); beep(); if (stealsomething() == 0) lprcat(" nothing"); disappear(xx, yy); bottomline(); return(1); case 15: i = rnd(10) + 5 - c[AC]; spout3: p = "\nThe %s bit you!"; goto spout2; case 16: i = rnd(15) + 10 - c[AC]; goto spout3; }; if (p) { lprintf(p, lastmonst); bottomline(); } return(0); } /* * checkloss(x) Routine to subtract hp from user and flag bottomline display * int x; * * Routine to subtract hitpoints from the user and flag the bottomline display * Enter with the number of hit points to lose * Note: if x > c[HP] this routine could kill the player! */ checkloss(x) int x; { if (x > 0) { losehp(x); bottomhp(); } } /* * annihilate() Routine to annihilate all monsters around player(playerx,playery) * * Gives player experience, but no dropped objects * Returns the experience gained from all monsters killed */ annihilate() { int i,j; register long k; register char *p; for (k = 0, i = playerx - 1; i <= playerx + 1; i++) for (j = playery - 1; j <= playery + 1; j++) if (!vxy(&i, &j)) /* if not out of bounds */ if (*(p = &mitem[i][j]))/* if a monster there */ if (*p < DEMONLORD + 2) { k += monster[*p].experience; *p = know[i][j] = 0; } else { lprintf("\nThe %s barely escapes being annihilated!", monster[*p].name); hitp[i][j] =(hitp[i][j] >> 1) + 1;/* lose half hit points */ } if (k > 0) { lprcat("\nYou hear loud screams of agony!"); raiseexperience((long) k); } return(k); } /* * newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation * int x,y,dir,lifetime; * * Enter with the coordinates of the sphere in x,y * the direction(0-8 diroffx format) in dir, and the lifespan of the * sphere in lifetime(in turns) * Returns the number of spheres currently in existence */ newsphere(x, y, dir, life) int x, y, dir, life; { int m; struct sphere *sp; if (((sp =(struct sphere *) malloc(sizeof(struct sphere)))) == 0) return(c[SPHCAST]);/* can't malloc, therefore failure */ if (dir >= 9) dir = 0; /* no movement if direction not found */ if (level == 0) vxy(&x, &y); /* don't go out of bounds */ else { if (x < 1) x = 1; if (x >= MAXX - 1) x = MAXX - 2; if (y < 1) y = 1; if (y >= MAXY - 1) y = MAXY - 2; } if ((m = mitem[x][y]) >= DEMONLORD + 4) {/* demons dispel spheres */ know[x][y] = 1; show1cell(x, y); /* show the demon(ha ha) */ cursors(); lprintf("\nThe %s dispels the sphere!", monster[m].name); beep(); rmsphere(x, y); /* remove any spheres that are here */ return(c[SPHCAST]); } if (m == DISENCHANTRESS) { /* disenchantress cancels spheres */ cursors(); lprintf("\nThe %s causes cancellation of the sphere!", monster[m].name); beep(); boom: sphboom(x, y); /* blow up stuff around sphere */ rmsphere(x, y); /* remove any spheres that are here */ return(c[SPHCAST]); } if (c[CANCELLATION]) { /* cancellation cancels spheres */ cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); beep(); goto boom; } if (item[x][y] == OANNIHILATION) {/* collision of spheres detonates spheres */ cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); beep(); rmsphere(x, y); goto boom; } if (playerx == x && playery == y) {/* collision of sphere and player! */ cursors(); lprcat("\nYou have been enveloped by the zone of nothingness!\n"); beep(); rmsphere(x, y); /* remove any spheres that are here */ nap(4000); died(258); } item[x][y] = OANNIHILATION; mitem[x][y] = 0; know[x][y] = 1; show1cell(x, y); /* show the new sphere */ sp -> x = x; sp -> y = y; sp -> lev = level; sp -> dir = dir; sp -> lifetime = life; sp -> p = 0; if (spheres == 0) spheres = sp; /* if first node in the sphere list */ else { /* add sphere to beginning of linked list */ sp -> p = spheres; spheres = sp; } return(++c[SPHCAST]); /* one more sphere in the world */ } /* * rmsphere(x,y) Function to delete a sphere of annihilation from list * int x,y; * * Enter with the coordinates of the sphere(on current level) * Returns the number of spheres currently in existence */ rmsphere(x, y) int x,y; { register struct sphere *sp,*sp2 = 0; for (sp = spheres; sp; sp2 = sp, sp = sp -> p) if (level == sp -> lev) /* is sphere on this level? */ if ((x == sp -> x) && (y == sp -> y)) {/* locate sphere at this location */ item[x][y] = mitem[x][y] = 0; know[x][y] = 1; show1cell(x, y);/* show the now missing sphere */ --c[SPHCAST]; if (sp == spheres) { sp2 = sp; spheres = sp -> p; free((char *) sp2); } else { sp2 -> p = sp -> p; free((char *) sp); } break; } return(c[SPHCAST]); /* return number of spheres in the world */ } /* * sphboom(x,y) Function to perform the effects of a sphere detonation * int x,y; * * Enter with the coordinates of the blast, Returns no value */ sphboom(x, y) int x, y; { register int i, j; if (c[HOLDMONST]) c[HOLDMONST] = 1; if (c[CANCELLATION]) c[CANCELLATION] = 1; for (j = max(1, x - 2); j < min(x + 3, MAXX - 1); j++) for (i = max(1, y - 2); i < min(y + 3, MAXY - 1); i++) { item[j][i] = mitem[j][i] = 0; show1cell(j, i); if (playerx == j && playery == i) { cursors(); beep(); lprcat("\nYou were too close to the sphere!"); nap(3000); died(283); /* player killed in explosion */ } } } /* * genmonst() Function to ask for monster and genocide from game * * This is done by setting a flag in the monster[] structure */ genmonst() { register int i,j; cursors(); lprcat("\nGenocide what monster? "); for (i = 0;(!isalpha(i)) && (i != ' '); i = readchar()); lprc(i); for (j = 0; j < MAXMONST; j++)/* search for the monster type */ if (monstnamelist[j] == i) {/* have we found it? */ monster[j].genocided = 1;/* genocided from game */ lprintf(" There will be no more %s's", monster[j].name); /* now wipe out monsters on this level */ newcavelevel(level); draws(0, MAXX, 0, MAXY); bot_linex(); return; } lprcat(" You sense failure!"); } SHAR_EOF if test 45763 -ne "`wc -c < 'monster.c'`" then echo shar: error transmitting "'monster.c'" '(should have been 45763 characters)' fi fi # end of overwriting check echo shar: extracting "'regen.c'" '(3839 characters)' if test -f 'regen.c' then echo shar: will not over-write existing file "'regen.c'" else cat << \SHAR_EOF > 'regen.c' /* regen.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* ******* REGEN() ******* regen() subroutine to regenerate player hp and spells */ regen () { register int i, flag; register long *d; d = c; #ifdef EXTRA d[MOVESMADE]++; #endif if (d[TIMESTOP]) { if (--d[TIMESTOP] <= 0) bottomline (); return; } /* for stop time spell */ flag = 0; if (d[STRENGTH] < 3) { d[STRENGTH] = 3; flag = 1; } if ((d[HASTESELF] == 0) || ((d[HASTESELF] & 1) == 0)) gtime++; if (d[HP] != d[HPMAX]) if (d[REGENCOUNTER]-- <= 0) {/* regenerate hit points */ d[REGENCOUNTER] = 22 + (d[HARDGAME] << 1) - d[LEVEL]; if ((d[HP] += d[REGEN]) > d[HPMAX]) d[HP] = d[HPMAX]; bottomhp (); } if (d[SPELLS] < d[SPELLMAX])/* regenerate spells */ if (d[ECOUNTER]-- <= 0) { d[ECOUNTER] = 100 + 4 * (d[HARDGAME] - d[LEVEL] - d[ENERGY]); d[SPELLS]++; bottomspell (); } if (d[HERO]) if (--d[HERO] <= 0) { for (i = 0; i < 6; i++) d[i] -= 10; flag = 1; } if (d[ALTPRO]) if (--d[ALTPRO] <= 0) { d[MOREDEFENSES] -= 3; flag = 1; } if (d[PROTECTIONTIME]) if (--d[PROTECTIONTIME] <= 0) { d[MOREDEFENSES] -= 2; flag = 1; } if (d[DEXCOUNT]) if (--d[DEXCOUNT] <= 0) { d[DEXTERITY] -= 3; flag = 1; } if (d[STRCOUNT]) if (--d[STRCOUNT] <= 0) { d[STREXTRA] -= 3; flag = 1; } if (d[BLINDCOUNT]) if (--d[BLINDCOUNT] <= 0) { cursors (); lprcat ("\nThe blindness lifts "); beep (); } if (d[CONFUSE]) if (--d[CONFUSE] <= 0) { cursors (); lprcat ("\nYou regain your senses"); beep (); } if (d[GIANTSTR]) if (--d[GIANTSTR] <= 0) { d[STREXTRA] -= 20; flag = 1; } if (d[CHARMCOUNT]) if ((--d[CHARMCOUNT]) <= 0) flag = 1; if (d[INVISIBILITY]) if ((--d[INVISIBILITY]) <= 0) flag = 1; if (d[CANCELLATION]) if ((--d[CANCELLATION]) <= 0) flag = 1; if (d[WTW]) if ((--d[WTW]) <= 0) flag = 1; if (d[HASTESELF]) if ((--d[HASTESELF]) <= 0) flag = 1; if (d[AGGRAVATE]) --d[AGGRAVATE]; if (d[SCAREMONST]) if ((--d[SCAREMONST]) <= 0) flag = 1; if (d[STEALTH]) if ((--d[STEALTH]) <= 0) flag = 1; if (d[AWARENESS]) --d[AWARENESS]; if (d[HOLDMONST]) if ((--d[HOLDMONST]) <= 0) flag = 1; if (d[HASTEMONST]) --d[HASTEMONST]; if (d[FIRERESISTANCE]) if ((--d[FIRERESISTANCE]) <= 0) flag = 1; if (d[GLOBE]) if (--d[GLOBE] <= 0) { d[MOREDEFENSES] -= 10; flag = 1; } if (d[SPIRITPRO]) if (--d[SPIRITPRO] <= 0) flag = 1; if (d[UNDEADPRO]) if (--d[UNDEADPRO] <= 0) flag = 1; if (d[HALFDAM]) if (--d[HALFDAM] <= 0) { cursors (); lprcat ("\nYou now feel better "); beep (); } if (d[SEEINVISIBLE]) if (--d[SEEINVISIBLE] <= 0) { monstnamelist[INVISIBLESTALKER] = ' '; cursors (); lprcat ("\nYou feel your vision return to normal"); beep (); } if (d[ITCHING]) { if (d[ITCHING] > 1) if ((d[WEAR] != -1) || (d[SHIELD] != -1)) if (rnd (100) < 50) { d[WEAR] = d[SHIELD] = -1; cursors (); lprcat ("\nThe hysteria of itching forces you to remove your armor!"); beep (); recalc (); bottomline (); } if (--d[ITCHING] <= 0) { cursors (); lprcat ("\nYou now feel the irritation subside!"); beep (); } } if (d[CLUMSINESS]) { if (d[WIELD] != -1) if (d[CLUMSINESS] > 1) if (item[playerx][playery] == 0)/* only if nothing there */ if (rnd (100) < 33)/* drop your weapon due to clumsiness */ drop_object ((int) d[WIELD]); if (--d[CLUMSINESS] <= 0) { cursors (); lprcat ("\nYou now feel less awkward!"); beep (); } } if (flag) bottomline (); } SHAR_EOF if test 3839 -ne "`wc -c < 'regen.c'`" then echo shar: error transmitting "'regen.c'" '(should have been 3839 characters)' fi fi # end of overwriting check echo shar: extracting "'savelev.c'" '(852 characters)' if test -f 'savelev.c' then echo shar: will not over-write existing file "'savelev.c'" else cat << \SHAR_EOF > 'savelev.c' /* savelev.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* * routine to save the present level into storage */ savelevel () { register int x,y,t; t = level * (MAXX*MAXY); for (x = 0; x < MAXX; x++) { t += MAXY; for (y = 0; y < MAXY; y++) { cell[t+y].item = item[x][y]; cell[t+y].iarg = iarg[x][y]; cell[t+y].know = know[x][y]; cell[t+y].mitem = mitem[x][y]; cell[t+y].hitp = hitp[x][y]; } } } /* * routine to restore a level from storage */ getlevel () { register int x,y,t; t = level * (MAXX*MAXY); for (x = 0; x < MAXX; x++) { t += MAXY; for (y = 0; y < MAXY; y++) { item[x][y] = cell[t+y].item; iarg[x][y] = cell[t+y].iarg; know[x][y] = cell[t+y].know; mitem[x][y] = cell[t+y].mitem; hitp[x][y] = cell[t+y].hitp; } } } SHAR_EOF if test 852 -ne "`wc -c < 'savelev.c'`" then echo shar: error transmitting "'savelev.c'" '(should have been 852 characters)' fi fi # end of overwriting check echo shar: extracting "'signal.c'" '(2848 characters)' if test -f 'signal.c' then echo shar: will not over-write existing file "'signal.c'" else cat << \SHAR_EOF > 'signal.c' #include <signal.h> #include "header.h" /* "Larn is copyrighted 1986 by Noah Morgan.\n" */ #define BIT(a)(1<<((a)-1)) /* text to be displayed if ^C during intro screen */ static s2choose() { cursor(1, 24); lprcat("Press "); setbold(); lprcat("return"); resetbold(); lprcat(" to continue: "); lflush(); } /* what to do for a ^C */ static cntlc() { if (nosignal) return; /* don't do anything if inhibited */ signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); quit(); if (predostuff == 1) s2choose(); else showplayer(); lflush(); signal(SIGQUIT, cntlc); signal(SIGINT, cntlc); } /* * subroutine to save the game if a hangup signal */ static sgam() { savegame(savefilename); wizard = 1; died(-257); /* hangup signal */ } /* * subroutine to issue the needed signal traps - called from main() */ static sigill() { sigpanic(SIGILL); } static sigtrap() { sigpanic(SIGTRAP); } static sigiot() { sigpanic(SIGIOT); } static sigemt() { sigpanic(SIGEMT); } static sigfpe() { sigpanic(SIGFPE); } static sigbus() { sigpanic(SIGBUS); } static sigsegv() { sigpanic(SIGSEGV); } static sigsys() { sigpanic(SIGSYS); } static sigpipe() { sigpanic(SIGPIPE); } static sigterm() { sigpanic(SIGTERM); } sigsetup() { signal(SIGQUIT, cntlc); signal(SIGINT, cntlc); signal(SIGKILL, SIG_IGN); signal(SIGHUP, sgam); signal(SIGILL, sigill); signal(SIGTRAP, sigtrap); signal(SIGIOT, sigiot); signal(SIGEMT, sigemt); signal(SIGFPE, sigfpe); signal(SIGBUS, sigbus); signal(SIGSEGV, sigsegv); signal(SIGSYS, sigsys); signal(SIGPIPE, sigpipe); signal(SIGTERM, sigterm); } static char *signame[NSIG] = { "", "SIGHUP", /* 1 hangup */ "SIGINT", /* 2 interrupt */ "SIGQUIT", /* 3 quit */ "SIGILL", /* 4 illegal instruction(not reset when caught) */ "SIGTRAP", /* 5 trace trap(not reset when caught) */ "SIGIOT", /* 6 IOT instruction */ "SIGEMT", /* 7 EMT instruction */ "SIGFPE", /* 8 floating point exception */ "SIGKILL", /* 9 kill(cannot be caught or ignored) */ "SIGBUS", /* 10 bus error */ "SIGSEGV", /* 11 segmentation violation */ "SIGSYS", /* 12 bad argument to system call */ "SIGPIPE", /* 13 write on a pipe with no one to read it */ "SIGALRM", /* 14 alarm clock */ "SIGTERM" /* 15 software termination signal from kill */ }; /* * routine to process a fatal error signal */ static sigpanic(sig) int sig; { char buf[128]; signal(sig, SIG_DFL); sprintf(buf, "\nLarn - Panic! Signal %d received [%s]", sig, signame[sig]); write(2, buf, strlen(buf)); sleep(2); sncbr(); savegame(savefilename); kill(getpid(), sig); /* this will terminate us */ } SHAR_EOF if test 2848 -ne "`wc -c < 'signal.c'`" then echo shar: error transmitting "'signal.c'" '(should have been 2848 characters)' fi fi # end of overwriting check echo shar: extracting "'tok.c'" '(5032 characters)' if test -f 'tok.c' then echo shar: will not over-write existing file "'tok.c'" else cat << \SHAR_EOF > 'tok.c' /* tok.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" static char lastok = 0; globaldef int yrepcount = 0,dayplay = 0; #define MAXUM 52 /* maximum number of user re-named monsters */ #define MAXMNAME 40 /* max length of a monster re-name */ static char usermonster[MAXUM][MAXMNAME];/* the user named monster name goes here */ static char usermpoint = 0; /* the user monster pointer */ /* lexical analyzer for larn */ yylex () { char cc; int ic; if (hit2flag) { hit2flag = 0; yrepcount = 0; return (' '); } if (yrepcount > 0) { --yrepcount; return (lastok); } else yrepcount = 0; if (yrepcount == 0) { bottomdo (); showplayer (); } /* show where the player is */ lflush (); while (1) { c[BYTESIN]++; if (ckpflag) /* check for periodic checkpointing */ if ((c[BYTESIN] % 400) == 0) { savegame (ckpfile); #ifdef TIMECHECK if (dayplay == 0) if (playable ()) { cursor (1, 19); lprcat ("\nSorry, but it is now time for work. Your game has been saved.\n"); beep (); lflush (); savegame (savefilename); wizard = nomove = 1; sleep (4); died (-257); } #endif TIMECHECK } if ((cc = KeySense(0)) == -1) return (lastok = -1); if (cc == 'Y' - 64) { /* control Y -- shell escape */ resetscroll (); clear(); /* scrolling region, home, clear, no attributes */ system(0); setscroll (); return (lastok = 'L' - 64); /* redisplay screen */ } if ((cc <= '9') && (cc >= '0')) { yrepcount = yrepcount * 10 + cc - '0'; } else { if (yrepcount > 0) --yrepcount; return (lastok = cc); } } } /* * flushall() Function to flush all type-ahead in the input buffer */ flushall () { /* if keyboard input buffer is too big, flush some of it */ while (KeySense(0) >= 0); } /* function to set the desired hardness enter with hard= -1 for default hardness, else any desired hardness */ sethard (hard) int hard; { register int j,k,i; j = c[HARDGAME]; hashewon (); if (restorflag == 0) { /* don't set c[HARDGAME] if restoring game */ if (hard >= 0) c[HARDGAME] = hard; } else c[HARDGAME] = j; /* set c[HARDGAME] to proper value if restoring game */ if (k = c[HARDGAME]) for (j = 0; j <= MAXMONST + 8; j++) { i = ((6 + k) * monster[j].hitpoints + 1) / 6; monster[j].hitpoints = (i < 0) ? 32767 : i; i = ((6 + k) * monster[j].damage + 1) / 5; monster[j].damage = (i > 127) ? 127 : i; i = (10 * monster[j].gold) / (10 + k); monster[j].gold = (i > 32767) ? 32767 : i; i = monster[j].armorclass - k; monster[j].armorclass = (i < -127) ? -127 : i; i = (7 * monster[j].experience) / (7 + k) + 1; monster[j].experience = (i <= 0) ? 1 : i; } } /* function to read and process the larn options file */ readopts () { register char *i; register int j,k; int flag = 1; /* set to 0 if he specifies a name for his character */ if (lopen (optsfile) < 0) { strcpy (logname, loginname); return; /* user name if no character name */ } i = " "; while (*i) { if ((i = (char *) lgetw ()) == 0) break; /* check for EOF */ while ((*i == ' ') || (*i == '\t')) i++; /* eat leading whitespace */ switch (*i) { case 'b': if (strcmp (i, "bold-objects") == 0) boldon = 1; break; case 'e': if (strcmp (i, "enable-checkpointing") == 0) ckpflag = 1; break; case 'i': if (strcmp (i, "inverse-objects") == 0) boldon = 0; break; case 'f': if (strcmp (i, "female") == 0) sex = 0; /* male or female */ break; case 'm': if (strcmp (i, "monster:") == 0) {/* name favorite monster */ if ((i = lgetw ()) == 0) break; if (strlen (i) >= MAXMNAME) i[MAXMNAME - 1] = 0; strcpy (usermonster[usermpoint], i); if (usermpoint >= MAXUM) break; /* defined all of em */ if (isalpha (j = usermonster[usermpoint][0])) { for (k = 1; k < MAXMONST + 8; k++)/* find monster */ if (monstnamelist[k] == j) { monster[k].name = &usermonster[usermpoint++][0]; break; } } } else if (strcmp (i, "male") == 0) sex = 1; break; case 'n': if (strcmp (i, "name:") == 0) {/* defining players name */ if ((i = lgetw ()) == 0) break; if (strlen (i) >= LOGNAMESIZE) i[LOGNAMESIZE - 1] = 0; strcpy (logname, i); flag = 0; } else if (strcmp (i, "no-introduction") == 0) nowelcome = 1; else if (strcmp (i, "no-beep") == 0) nobeep = 1; break; case 'p': if (strcmp (i, "play-day-play") == 0) dayplay = 1; break; case 's': if (strcmp (i, "savefile:") == 0) {/* defining savefilename */ if ((i = lgetw ()) == 0) break; if (strlen (i) >= SAVEFILENAMESIZE)/* avoid overflow */ i[SAVEFILENAMESIZE - 1] = 0; strcpy (savefilename, i); flag = 0; } break; }; } if (flag) strcpy (logname, loginname); } SHAR_EOF if test 5032 -ne "`wc -c < 'tok.c'`" then echo shar: error transmitting "'tok.c'" '(should have been 5032 characters)' fi fi # end of overwriting check # End of shell archive exit 0
u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)
Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # object.c # scores.c # store.c # This archive created: Sat Aug 30 14:53:02 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'object.c'" '(28817 characters)' if test -f 'object.c' then echo shar: will not over-write existing file "'object.c'" else cat << \SHAR_EOF > 'object.c' /* object.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* *************** LOOK_FOR_OBJECT *************** subroutine to look for an object and give the player his options if an object was found. */ lookforobject () { register int i,j; if (c[TIMESTOP]) return; /* can't find objects is time is stopped */ i = item[playerx][playery]; if (i == 0) return; showcell (playerx, playery); cursors (); yrepcount = 0; switch (i) { case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD: lprcat ("\n\nYou have found some gold!"); ogold (i); break; case OPOTION: lprcat ("\n\nYou have found a magic potion"); i = iarg[playerx][playery]; if (potionname[i][0]) lprintf (" of %s", &potionname[i][1]); opotion (i); break; case OSCROLL: lprcat ("\n\nYou have found a magic scroll"); i = iarg[playerx][playery]; if (scrollname[i][0]) lprintf (" of %s", &scrollname[i][1]); oscroll (i); break; case OALTAR: if (nearbymonst ()) return; lprcat ("\n\nThere is a Holy Altar here!"); oaltar (); break; case OBOOK: lprcat ("\n\nYou have found a book."); obook (); break; case OCOOKIE: lprcat ("\n\nYou have found a fortune cookie."); ocookie (); break; case OTHRONE: if (nearbymonst ()) return; lprintf ("\n\nThere is %s here!", objectname[i]); othrone (0); break; case OTHRONE2: if (nearbymonst ()) return; lprintf ("\n\nThere is %s here!", objectname[i]); othrone (1); break; case ODEADTHRONE: lprintf ("\n\nThere is %s here!", objectname[i]); odeadthrone (); break; case OORB: lprcat ("\n\nYou have found the Orb!!!!!"); oorb (); break; case OPIT: lprcat ("\n\nYou're standing at the top of a pit."); opit (); break; case OSTAIRSUP: lprcat ("\n\nThere is a circular staircase here"); ostairs (1); /* up */ break; case OELEVATORUP: lprcat ("\n\nYou feel heavy for a moment, but the feeling disappears"); oelevator (1); /* up */ break; case OFOUNTAIN: if (nearbymonst ()) return; lprcat ("\n\nThere is a fountain here"); ofountain (); break; case OSTATUE: if (nearbymonst ()) return; lprcat ("\n\nYou are standing in front of a statue"); ostatue (); break; case OCHEST: lprcat ("\n\nThere is a chest here"); ochest (); break; case OIVTELETRAP: if (rnd (11) < 6) return; item[playerx][playery] = OTELEPORTER; know[playerx][playery] = 1; case OTELEPORTER: lprcat ("\nZaaaappp! You've been teleported!\n"); beep (); nap (3000); oteleport (0); break; case OSCHOOL: if (nearbymonst ()) return; lprcat ("\n\nYou have found the College of Larn."); lprcat ("\nDo you (g) go inside, or (i) stay here? "); i = 0; while ((i != 'g') && (i != 'i') && (i != '\33')) i = readchar (); if (i == 'g') { oschool (); /* the college of larn */ } else lprcat (" stay here"); break; case OMIRROR: if (nearbymonst ()) return; lprcat ("\n\nThere is a mirror here"); omirror (); break; case OBANK2: case OBANK: if (nearbymonst ()) return; if (i == OBANK) lprcat ("\n\nYou have found the bank of Larn."); else lprcat ("\n\nYou have found a branch office of the bank of Larn."); lprcat ("\nDo you (g) go inside, or (i) stay here? "); j = 0; while ((j != 'g') && (j != 'i') && (j != '\33')) j = readchar (); if (j == 'g') { if (i == OBANK) obank (); else obank2 (); /* the bank of larn */ } else lprcat (" stay here"); break; case ODEADFOUNTAIN: if (nearbymonst ()) return; lprcat ("\n\nThere is a dead fountain here"); break; case ODNDSTORE: if (nearbymonst ()) return; lprcat ("\n\nThere is a DND store here."); lprcat ("\nDo you (g) go inside, or (i) stay here? "); i = 0; while ((i != 'g') && (i != 'i') && (i != '\33')) i = readchar (); if (i == 'g') dndstore (); /* the dnd adventurers store */ else lprcat (" stay here"); break; case OSTAIRSDOWN: lprcat ("\n\nThere is a circular staircase here"); ostairs (-1); /* down */ break; case OELEVATORDOWN: lprcat ("\n\nYou feel light for a moment, but the feeling disappears"); oelevator (-1); /* down */ break; case OOPENDOOR: lprintf ("\n\nYou have found %s", objectname[i]); lprcat ("\nDo you (c) close it"); iopts (); i = 0; while ((i != 'c') && (i != 'i') && (i != '\33')) i = readchar (); if ((i == '\33') || (i == 'i')) { ignore (); break; } lprcat ("close"); forget (); item[playerx][playery] = OCLOSEDDOOR; iarg[playerx][playery] = 0; playerx = lastpx; playery = lastpy; break; case OCLOSEDDOOR: lprintf ("\n\nYou have found %s", objectname[i]); lprcat ("\nDo you (o) try to open it"); iopts (); i = 0; while ((i != 'o') && (i != 'i') && (i != '\33')) i = readchar (); if ((i == '\33') || (i == 'i')) { ignore (); playerx = lastpx; playery = lastpy; break; } else { lprcat ("open"); if (rnd (11) < 7) { switch (iarg[playerx][playery]) { case 6: c[AGGRAVATE] += rnd (400); break; case 7: lprcat ("\nYou are jolted by an electric shock "); lastnum = 274; losehp (rnd (20)); bottomline (); break; case 8: loselevel (); break; case 9: lprcat ("\nYou suddenly feel weaker "); if (c[STRENGTH] > 3) c[STRENGTH]--; bottomline (); break; default: break; } playerx = lastpx; playery = lastpy; } else { forget (); item[playerx][playery] = OOPENDOOR; } } break; case OENTRANCE: lprcat ("\nYou have found "); lprcat (objectname[OENTRANCE]); lprcat ("\nDo you (g) go inside"); iopts (); i = 0; while ((i != 'g') && (i != 'i') && (i != '\33')) i = readchar (); if (i == 'g') { newcavelevel (1); playerx = 33; playery = MAXY - 2; item[33][MAXY - 1] = know[33][MAXY - 1] = mitem[33][MAXY - 1] = 0; draws (0, MAXX, 0, MAXY); bot_linex (); return; } else ignore (); break; case OVOLDOWN: lprcat ("\nYou have found "); lprcat (objectname[OVOLDOWN]); lprcat ("\nDo you (c) climb down"); iopts (); i = 0; while ((i != 'c') && (i != 'i') && (i != '\33')) i = readchar (); if ((i == '\33') || (i == 'i')) { ignore (); break; } if (level != 0) { lprcat ("\nThe shaft only extends 5 feet downward!"); return; } if (packweight () > 45 + 3 * (c[STRENGTH] + c[STREXTRA])) { lprcat ("\nYou slip and fall down the shaft"); beep (); lastnum = 275; losehp (30 + rnd (20)); bottomhp (); } else lprcat ("climb down"); nap (3000); newcavelevel (MAXLEVEL); for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++)/* put player near volcano shaft */ if (item[j][i] == OVOLUP) { playerx = j; playery = i; j = MAXX; i = MAXY; positionplayer (); } draws (0, MAXX, 0, MAXY); bot_linex (); return; case OVOLUP: lprcat ("\nYou have found "); lprcat (objectname[OVOLUP]); lprcat ("\nDo you (c) climb up"); iopts (); i = 0; while ((i != 'c') && (i != 'i') && (i != '\33')) i = readchar (); if ((i == '\33') || (i == 'i')) { ignore (); break; } if (level != 11) { lprcat ("\nThe shaft only extends 8 feet upwards before you find a blockage!"); return; } if (packweight () > 45 + 5 * (c[STRENGTH] + c[STREXTRA])) { lprcat ("\nYou slip and fall down the shaft"); beep (); lastnum = 275; losehp (15 + rnd (20)); bottomhp (); return; } lprcat ("climb up"); lflush (); nap (3000); newcavelevel (0); for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++)/* put player near volcano shaft */ if (item[j][i] == OVOLDOWN) { playerx = j; playery = i; j = MAXX; i = MAXY; positionplayer (); } draws (0, MAXX, 0, MAXY); bot_linex (); return; case OTRAPARROWIV: if (rnd (17) < 13) return; /* for an arrow trap */ item[playerx][playery] = OTRAPARROW; know[playerx][playery] = 0; case OTRAPARROW: lprcat ("\nYou are hit by an arrow"); beep (); /* for an arrow trap */ lastnum = 259; losehp (rnd (10) + level); bottomhp (); return; case OIVDARTRAP: if (rnd (17) < 13) return; /* for a dart trap */ item[playerx][playery] = ODARTRAP; know[playerx][playery] = 0; case ODARTRAP: lprcat ("\nYou are hit by a dart"); beep (); /* for a dart trap */ lastnum = 260; losehp (rnd (5)); if ((--c[STRENGTH]) < 3) c[STRENGTH] = 3; bottomline (); return; case OIVTRAPDOOR: if (rnd (17) < 13) return; /* for a trap door */ item[playerx][playery] = OTRAPDOOR; know[playerx][playery] = 1; case OTRAPDOOR: lastnum = 272; /* a trap door */ if ((level == MAXLEVEL - 1) || (level == MAXLEVEL + MAXVLEVEL - 1)) { lprcat ("\nYou fell through a bottomless trap door!"); beep (); nap (3000); died (271); } lprcat ("\nYou fall through a trap door!"); beep (); /* for a trap door */ losehp (rnd (5 + level)); nap (2000); newcavelevel (level + 1); draws (0, MAXX, 0, MAXY); bot_linex (); return; case OTRADEPOST: if (nearbymonst ()) return; lprcat ("\nYou have found the Larn trading Post."); lprcat ("\nDo you (g) go inside, or (i) stay here? "); i = 0; while ((i != 'g') && (i != 'i') && (i != '\33')) i = readchar (); if (i == 'g') otradepost (); else lprcat ("stay here"); return; case OHOME: if (nearbymonst ()) return; lprcat ("\nYou have found your way home."); lprcat ("\nDo you (g) go inside, or (i) stay here? "); i = 0; while ((i != 'g') && (i != 'i') && (i != '\33')) i = readchar (); if (i == 'g') ohome (); else lprcat ("stay here"); return; case OWALL: break; case OANNIHILATION: died (283); return; /* annihilated by sphere of annihilation */ case OLRS: if (nearbymonst ()) return; lprcat ("\n\nThere is an LRS office here."); lprcat ("\nDo you (g) go inside, or (i) stay here? "); i = 0; while ((i != 'g') && (i != 'i') && (i != '\33')) i = readchar (); if (i == 'g') olrs (); /* the larn revenue service */ else lprcat (" stay here"); break; default: finditem (i); break; }; } /* function to say what object we found and ask if player wants to take it */ finditem (itm) int itm; { int tmp, i; lprintf ("\n\nYou have found %s ", objectname[itm]); tmp = iarg[playerx][playery]; switch (itm) { case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: case OSPIRITSCARAB: case OORBOFDRAGON: case OCUBEofUNDEAD: case ONOTHEFT: break; default: if (tmp > 0) lprintf ("+ %d", (long) tmp); else if (tmp < 0) lprintf (" %d", (long) tmp); } lprcat ("\nDo you want to (t) take it"); iopts (); i = 0; while (i != 't' && i != 'i' && i != '\33') i = readchar (); if (i == 't') { lprcat ("take"); if (take (itm, tmp) == 0) forget (); return; } ignore (); } /* ******* OSTAIRS ******* subroutine to process the stair cases if dir > 0 the up else down */ ostairs (dir) int dir; { register int k; lprcat ("\nDo you (s) stay here "); if (dir > 0) lprcat ("(u) go up "); else lprcat ("(d) go down "); lprcat ("or (f) kick stairs? "); while (1) switch (readchar ()) { case '\33': case 's': case 'i': lprcat ("stay here"); return; case 'f': lprcat ("kick stairs"); if (rnd (2) == 1) lprcat ("\nI hope you feel better. Showing anger rids you of frustration."); else { k = rnd ((level + 1) << 1); lprintf ("\nYou hurt your foot dumb dumb! You suffer %d hit points", (long) k); lastnum = 276; losehp (k); bottomline (); } return; case 'u': lprcat ("go up"); if (dir < 0) lprcat ("\nThe stairs don't go up!"); else if (level >= 2 && level != 11) { k = level; newcavelevel (level - 1); draws (0, MAXX, 0, MAXY); bot_linex (); } else lprcat ("\nThe stairs lead to a dead end!"); return; case 'd': lprcat ("go down"); if (dir > 0) lprcat ("\nThe stairs don't go down!"); else if (level != 0 && level != 10 && level != 13) { k = level; newcavelevel (level + 1); draws (0, MAXX, 0, MAXY); bot_linex (); } else lprcat ("\nThe stairs lead to a dead end!"); return; }; } /* ********* OTELEPORTER ********* subroutine to handle a teleport trap +/- 1 level maximum */ oteleport (err) int err; { register int tmp; if (err) if (rnd (151) < 3) died (264); /* stuck in a rock */ c[TELEFLAG] = 1; /* show ?? on bottomline if been teleported */ if (level == 0) tmp = 0; else if (level < MAXLEVEL) { tmp = rnd (5) + level - 3; if (tmp >= MAXLEVEL) tmp = MAXLEVEL - 1; if (tmp < 1) tmp = 1; } else { tmp = rnd (3) + level - 2; if (tmp >= MAXLEVEL + MAXVLEVEL) tmp = MAXLEVEL + MAXVLEVEL - 1; if (tmp < MAXLEVEL) tmp = MAXLEVEL; } playerx = rnd (MAXX - 2); playery = rnd (MAXY - 2); if (level != tmp) newcavelevel (tmp); positionplayer (); draws (0, MAXX, 0, MAXY); bot_linex (); } /* ******* OPOTION ******* function to process a potion */ opotion (pot) int pot; { lprcat ("\nDo you (d) drink it, (t) take it"); iopts (); while (1) switch (readchar ()) { case '\33': case 'i': ignore (); return; case 'd': lprcat ("drink\n"); forget (); /* destroy potion */ quaffpotion (pot); return; case 't': lprcat ("take\n"); if (take (OPOTION, pot) == 0) forget (); return; }; } /* function to drink a potion */ quaffpotion (pot) int pot; { register int i, j, k; if (pot < 0 || pot >= MAXPOTION) return; /* check for within bounds */ potionname[pot][0] = ' '; switch (pot) { case 9: lprcat ("\nYou feel greedy . . ."); nap (2000); for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) if ((item[j][i] == OGOLDPILE) || (item[j][i] == OMAXGOLD)) { know[j][i] = 1; show1cell (j, i); } showplayer (); return; case 19: lprcat ("\nYou feel greedy . . ."); nap (2000); for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) { k = item[j][i]; if ((k == ODIAMOND) || (k == ORUBY) || (k == OEMERALD) || (k == OMAXGOLD) || (k == OSAPPHIRE) || (k == OLARNEYE) || (k == OGOLDPILE)) { know[j][i] = 1; show1cell (j, i); } } showplayer (); return; case 20: c[HP] = c[HPMAX]; break; /* instant healing */ case 1: lprcat ("\nYou feel better"); if (c[HP] == c[HPMAX]) raisemhp (1); else if ((c[HP] += rnd (20) + 20 + c[LEVEL]) > c[HPMAX]) c[HP] = c[HPMAX]; break; case 2: lprcat ("\nSuddenly, you feel much more skillful!"); raiselevel (); raisemhp (1); return; case 3: lprcat ("\nYou feel strange for a moment"); c[rund (6)]++; break; case 4: lprcat ("\nYou feel more self confident!"); c[WISDOM] += rnd (2); break; case 5: lprcat ("\nWow! You feel great!"); if (c[STRENGTH] < 12) c[STRENGTH] = 12; else c[STRENGTH]++; break; case 6: lprcat ("\nYour charm went up by one!"); c[CHARISMA]++; break; case 8: lprcat ("\nYour intelligence went up by one!"); c[INTELLIGENCE]++; break; case 10: for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) if (mitem[j][i]) { know[j][i] = 1; show1cell (j, i); } /* monster detection */ return; case 12: lprcat ("\nThis potion has no taste to it"); return; case 15: lprcat ("\nWOW!!! You feel Super-fantastic!!!"); if (c[HERO] == 0) for (i = 0; i < 6; i++) c[i] += 11; c[HERO] += 250; break; case 16: lprcat ("\nYou have a greater intestinal constitude!"); c[CONSTITUTION]++; break; case 17: lprcat ("\nYou now have incredibly bulging muscles!!!"); if (c[GIANTSTR] == 0) c[STREXTRA] += 21; c[GIANTSTR] += 700; break; case 18: lprcat ("\nYou feel a chill run up your spine!"); c[FIRERESISTANCE] += 1000; break; case 0: lprcat ("\nYou fall asleep. . ."); i = rnd (11) - (c[CONSTITUTION] >> 2) + 2; while (--i > 0) { parse2 (); nap (1000); } cursors (); lprcat ("\nYou woke up!"); return; case 7: lprcat ("\nYou become dizzy!"); if (--c[STRENGTH] < 3) c[STRENGTH] = 3; break; case 11: lprcat ("\nYou stagger for a moment . ."); for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) know[j][i] = 0; nap (2000); draws (0, MAXX, 0, MAXY);/* potion of forgetfulness */ return; case 13: lprcat ("\nYou can't see anything!");/* blindness */ c[BLINDCOUNT] += 500; return; case 14: lprcat ("\nYou feel confused"); c[CONFUSE] += 20 + rnd (9); return; case 21: lprcat ("\nYou don't seem to be affected"); return; /* cure dianthroritis */ case 22: lprcat ("\nYou feel a sickness engulf you");/* poison */ c[HALFDAM] += 200 + rnd (200); return; case 23: lprcat ("\nYou feel your vision sharpen");/* see invisible */ c[SEEINVISIBLE] += rnd (1000) + 400; monstnamelist[INVISIBLESTALKER] = 'I'; return; }; bottomline (); /* show new stats */ return; } /* ******* OSCROLL ******* function to process a magic scroll */ oscroll (typ) int typ; { lprcat ("\nDo you "); if (c[BLINDCOUNT] == 0) lprcat ("(r) read it, "); lprcat ("(t) take it"); iopts (); while (1) switch (readchar ()) { case '\33': case 'i': ignore (); return; case 'r': if (c[BLINDCOUNT]) break; lprcat ("read"); forget (); if (typ == 2 || typ == 15) { show1cell (playerx, playery); cursors (); } /* destroy it */ read_scroll (typ); return; case 't': lprcat ("take"); if (take (OSCROLL, typ) == 0) forget (); /* destroy it */ return; }; } /* data for the function to read a scroll */ static int xh, yh, yl, xl; static char curse[] = { BLINDCOUNT, CONFUSE, AGGRAVATE, HASTEMONST, ITCHING, LAUGHING, DRAINSTRENGTH, CLUMSINESS, INFEEBLEMENT, HALFDAM }; static char exten[] = { PROTECTIONTIME, DEXCOUNT, STRCOUNT, CHARMCOUNT, INVISIBILITY, CANCELLATION, HASTESELF, GLOBE, SCAREMONST, HOLDMONST, TIMESTOP }; char time_change[] = { HASTESELF, HERO, ALTPRO, PROTECTIONTIME, DEXCOUNT, STRCOUNT, GIANTSTR, CHARMCOUNT, INVISIBILITY, CANCELLATION, HASTESELF, AGGRAVATE, SCAREMONST, STEALTH, AWARENESS, HOLDMONST, HASTEMONST, FIRERESISTANCE, GLOBE, SPIRITPRO, UNDEADPRO, HALFDAM, SEEINVISIBLE, ITCHING, CLUMSINESS, WTW }; /* * function to adjust time when time warping and taking courses in school */ adjtime (tim) register long tim; { register int j; for (j = 0; j < 26; j++) /* adjust time related parameters */ if (c[time_change[j]]) if ((c[time_change[j]] -= tim) < 1) c[time_change[j]] = 1; regen (); } /* function to read a scroll */ read_scroll (typ) int typ; { register int i, j; if (typ < 0 || typ >= MAXSCROLL) return; /* be sure we are within bounds */ scrollname[typ][0] = ' '; switch (typ) { case 0: lprcat ("\nYour armor glows for a moment"); enchantarmor (); return; case 1: lprcat ("\nYour weapon glows for a moment"); enchweapon (); return; /* enchant weapon */ case 2: lprcat ("\nYou have been granted enlightenment!"); yh = min (playery + 7, MAXY); xh = min (playerx + 25, MAXX); yl = max (playery - 7, 0); xl = max (playerx - 25, 0); for (i = yl; i < yh; i++) for (j = xl; j < xh; j++) know[j][i] = 1; nap (2000); draws (xl, xh, yl, yh); return; case 3: lprcat ("\nThis scroll seems to be blank"); return; case 4: createmonster (makemonst (level + 1)); return; /* this one creates a monster */ case 5: something (level); /* create artifact */ return; case 6: c[AGGRAVATE] += 800; return; /* aggravate monsters */ case 7: gtime += (i = rnd (1000) - 850);/* time warp */ if (i >= 0) lprintf ("\nYou went forward in time by %d mobuls", (long) ((i + 99) / 100)); else lprintf ("\nYou went backward in time by %d mobuls", (long) (-(i + 99) / 100)); adjtime ((long) i); /* adjust time for time warping */ return; case 8: oteleport (0); return; /* teleportation */ case 9: c[AWARENESS] += 1800; return; /* expanded awareness */ case 10: c[HASTEMONST] += rnd (55) + 12; return; /* haste monster */ case 11: for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) if (mitem[j][i]) hitp[j][i] = monster[mitem[j][i]].hitpoints; return; /* monster healing */ case 12: c[SPIRITPRO] += 300 + rnd (200); bottomline (); return; /* spirit protection */ case 13: c[UNDEADPRO] += 300 + rnd (200); bottomline (); return; /* undead protection */ case 14: c[STEALTH] += 250 + rnd (250); bottomline (); return; /* stealth */ case 15: lprcat ("\nYou have been granted enlightenment!");/* magic mapping */ for (i = 0; i < MAXY; i++) for (j = 0; j < MAXX; j++) know[j][i] = 1; nap (2000); draws (0, MAXX, 0, MAXY); return; case 16: c[HOLDMONST] += 30; bottomline (); return; /* hold monster */ case 17: for (i = 0; i < 26; i++)/* gem perfection */ switch (iven[i]) { case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE: j = ivenarg[i]; j &= 255; j <<= 1; if (j > 255) j = 255;/* double value */ ivenarg[i] = j; break; } break; case 18: for (i = 0; i < 11; i++) c[exten[i]] <<= 1;/* spell extension */ break; case 19: for (i = 0; i < 26; i++) {/* identify */ if (iven[i] == OPOTION) potionname[ivenarg[i]][0] = ' '; if (iven[i] == OSCROLL) scrollname[ivenarg[i]][0] = ' '; } break; case 20: for (i = 0; i < 10; i++)/* remove curse */ if (c[curse[i]]) c[curse[i]] = 1; break; case 21: annihilate (); break; /* scroll of annihilation */ case 22: godirect (22, 150, "The ray hits the %s", 0, ' ');/* pulverization */ break; case 23: c[LIFEPROT]++; break; /* life protection */ }; } oorb () { } opit () { register int i; if (rnd (101) < 81) if (rnd (70) > 9 * c[DEXTERITY] - packweight () || rnd (101) < 5) if (level == MAXLEVEL - 1) obottomless (); else if (level == MAXLEVEL + MAXVLEVEL - 1) obottomless (); else { if (rnd (101) < 20) { i = 0; lprcat ("\nYou fell into a pit! Your fall is cushioned by an unknown force\n"); } else { i = rnd (level * 3 + 3); lprintf ("\nYou fell into a pit! You suffer %d hit points damage", (long) i); lastnum = 261;/* if he dies scoreboard will say so */ } losehp (i); nap (2000); newcavelevel (level + 1); draws (0, MAXX, 0, MAXY); } } obottomless () { lprcat ("\nYou fell into a bottomless pit!"); beep (); nap (3000); died (262); } oelevator (dir) int dir; { #ifdef lint int x; x = dir; dir = x; #endif lint } ostatue () { } omirror () { } obook () { lprcat ("\nDo you "); if (c[BLINDCOUNT] == 0) lprcat ("(r) read it, "); lprcat ("(t) take it"); iopts (); while (1) switch (readchar ()) { case '\33': case 'i': ignore (); return; case 'r': if (c[BLINDCOUNT]) break; lprcat ("read"); /* no more book */ readbook (iarg[playerx][playery]); forget (); return; case 't': lprcat ("take"); if (take (OBOOK, iarg[playerx][playery]) == 0) forget (); /* no more book */ return; }; } /* function to read a book */ readbook (lev) register int lev; { register int i, tmp; if (lev <= 3) i = rund ((tmp = splev[lev]) ? tmp : 1); else i = rnd ((tmp = splev[lev] - 9) ? tmp : 1) + 9; spelknow[i] = 1; lprintf ("\nSpell \"%s\": %s\n%s", spelcode[i], spelname[i], speldescript[i]); if (rnd (10) == 4) { lprcat ("\nYour int went up by one!"); c[INTELLIGENCE]++; bottomline (); } } ocookie () { char *p; lprcat ("\nDo you (e) eat it, (t) take it"); iopts (); while (1) switch (readchar ()) { case '\33': case 'i': ignore (); return; case 'e': lprcat ("eat\nThe cookie tasted good."); forget (); /* no more cookie */ if (c[BLINDCOUNT]) return; if (!(p = fortune (fortfile))) return; lprcat (" A message inside the cookie reads:\n"); lprcat (p); return; case 't': lprcat ("take"); if (take (OCOOKIE, 0) == 0) forget (); /* no more book */ return; }; } /* routine to pick up some gold -- if arg==OMAXGOLD then the pile is worth 100* the argument */ ogold (arg) int arg; { register long i; i = iarg[playerx][playery]; if (arg == OMAXGOLD) i *= 100; else if (arg == OKGOLD) i *= 1000; else if (arg == ODGOLD) i *= 10; lprintf ("\nIt is worth %d!", (long) i); c[GOLD] += i; bottomgold (); item[playerx][playery] = know[playerx][playery] = 0;/* destroy gold */ } ohome () { register int i; nosignal = 1; /* disable signals */ for (i = 0; i < 26; i++) if (iven[i] == OPOTION) if (ivenarg[i] == 21) { iven[i] = 0; /* remove the potion of cure dianthroritis from inventory */ clear (); lprcat ("Congratulations. You found a potion of cure dianthroritis.\n"); lprcat ("\nFrankly, No one thought you could do it. Boy! Did you surprise them!\n"); if (gtime > TIMELIMIT) { lprcat ("\nThe doctor has the sad duty to inform you that your daughter died!\n"); lprcat ("You didn't make it in time. In your agony, you kill the doctor,\nyour wife, and yourself! Too bad!\n"); nap (5000); died (269); } else { lprcat ("\nThe doctor is now administering the potion, and in a few moments\n"); lprcat ("Your daughter should be well on her way to recovery.\n"); nap (6000); lprcat ("\nThe potion is"); nap (3000); lprcat (" working! The doctor thinks that\n"); lprcat ("your daughter will recover in a few days. Congratulations!\n"); beep (); nap (5000); died (263); } } while (1) { clear (); lprintf ("Welcome home %s. Latest word from the doctor is not good.\n", logname); if (gtime > TIMELIMIT) { lprcat ("\nThe doctor has the sad duty to inform you that your daughter died!\n"); lprcat ("You didn't make it in time. In your agony, you kill the doctor,\nyour wife, and yourself! Too bad!\n"); nap (5000); died (269); } lprcat ("\nThe diagnosis is confirmed as dianthroritis. He guesses that\n"); lprintf ("your daughter has only %d mobuls left in this world. It's up to you,\n", (long) ((TIMELIMIT - gtime + 99) / 100)); lprintf ("%s, to find the only hope for your daughter, the very rare\n", logname); lprcat ("potion of cure dianthroritis. It is rumored that only deep in the\n"); lprcat ("depths of the caves can this potion be found.\n\n\n"); lprcat ("\n ----- press "); standout ("return"); lprcat (" to continue, "); standout ("escape"); lprcat (" to leave ----- "); i = readchar (); while (i != '\33' && i != '\n') i = readchar (); if (i == '\33') { drawscreen (); nosignal = 0; /* enable signals */ return; } } } /* routine to save program space */ iopts () { lprcat (", or (i) ignore it? "); } ignore () { lprcat ("ignore\n"); } SHAR_EOF if test 28817 -ne "`wc -c < 'object.c'`" then echo shar: error transmitting "'object.c'" '(should have been 28817 characters)' fi fi # end of overwriting check echo shar: extracting "'scores.c'" '(22296 characters)' if test -f 'scores.c' then echo shar: will not over-write existing file "'scores.c'" else cat << \SHAR_EOF > 'scores.c' /* scores.c Larn is copyrighted 1986 by Noah Morgan. * * Functions in this file are: * * readboard() Function to read in the scoreboard into a static buffer * writeboard() Function to write the scoreboard from readboard()'s buffer * makeboard() Function to create a new scoreboard(wipe out old one) * hashewon() Function to return 1 if player has won a game before, else 0 * long paytaxes(x) Function to pay taxes if any are due * winshou() Subroutine to print out the winning scoreboard * shou(x) Subroutine to print out the non-winners scoreboard * showscores() Function to show the scoreboard on the terminal * showallscores() Function to show scores and the iven lists that go with them * sortboard() Function to sort the scoreboard * newscore(score, whoo, whyded, winner) Function to add entry to scoreboard * new1sub(score,i,whoo,taxes) Subroutine to put player into a * new2sub(score,i,whoo,whyded) Subroutine to put player into a * died(x) Subroutine to record who played larn, and what the score was * diedsub(x) Subroutine to print out a line showing player when he is killed * diedlog() Subroutine to read a log file and print it out in ascii format * getplid(name) Function to get players id # from id file * */ #include <times.h> #include <stat.h> #include "header.h" struct scofmt { /* This is the structure for the scoreboard */ long score; /* the score of the player */ long suid; /* the user id number of the player */ short what; /* the number of the monster that killed player */ short level; /* the level player was on when he died */ short hardlev; /* the level of difficulty player played at */ short order; /* the relative ordering place of this entry */ char who[40]; /* the name of the character */ char sciv[26][2];/* this is the inventory list of the character */ }; struct wscofmt { /* This is the structure for the winning scoreboard */ long score; /* the score of the player */ long timeused; /* the time used in mobuls to win the game */ long taxes; /* taxes he owes to LRS */ long suid; /* the user id number of the player */ short hardlev; /* the level of difficulty player played at */ short order; /* the relative ordering place of this entry */ char who[40]; /* the name of the character */ }; struct log_fmt { /* 102 bytes struct for the log file */ long score; /* the players score */ long diedtime; /* time when game was over */ short cavelev; /* level in caves */ short diff; /* difficulty player played at */ #ifdef EXTRA long elapsedtime;/* real time of game in seconds */ long bytout; /* bytes input and output */ long bytin; long moves; /* number of moves made by player */ short ac; /* armor class of player */ short hp,hpmax; /* players hitpoints */ short cputime; /* cpu time needed in seconds */ short killed, spused; /* monsters killed and spells cast */ short usage; /* usage of the cpu in % */ short lev; /* player level */ #endif char who[12]; /* player name */ char what[46]; /* what happened to player */ }; static struct scofmt sco[SCORESIZE];/* the structure for the scoreboard */ static struct wscofmt winr[SCORESIZE];/* struct for the winning scoreboard */ static struct log_fmt logg; /* structure for the log file */ static char *whydead[] = { "quit", "suspended", "self - annihilated", "shot by an arrow", "hit by a dart", "fell into a pit", "fell into a bottomless pit", "a winner", "trapped in solid rock", "killed by a missing save file", "killed by an old save file", "caught by the greedy cheater checker trap", "killed by a protected save file", "killed his family and committed suicide", "erased by a wayward finger", "fell through a bottomless trap door", "fell through a trap door", "drank some poisonous water", "fried by an electric shock", "slipped on a volcano shaft", "killed by a stupid act of frustration", "attacked by a revolting demon", "hit by his own magic", "demolished by an unseen attacker", "fell into the dreadful sleep", "killed by an exploding chest", /* 26 */ "killed by a missing maze data file", "annihilated in a sphere", "died a post mortem death", "wasted by a malloc() failure" }; /* * readboard() Function to read in the scoreboard into a static buffer * * returns -1 if unable to read in the scoreboard, returns 0 if all is OK */ readboard() { if (lopen(scorefile) < 0) { lprcat("Can't read scoreboard\n"); lflush(); return(-1); } lrfill((char *) sco, sizeof(sco)); lrfill((char *) winr, sizeof(winr)); lrclose(); lcreat((char *) 0); return(0); } /* * writeboard() Function to write the scoreboard from readboard()'s buffer * * returns -1 if unable to write the scoreboard, returns 0 if all is OK */ writeboard() { set_score_output(); delete(scorefile); /* otherwise we get many many copies */ if (lcreat(scorefile) < 0) { lprcat("Can't write scoreboard\n"); lflush(); return(-1); } lwrite((char *) sco, sizeof(sco)); lwrite((char *) winr, sizeof(winr)); lwclose(); lcreat((char *) 0); return(0); } /* * makeboard() Function to create a new scoreboard(wipe out old one) * * returns -1 if unable to write the scoreboard, returns 0 if all is OK */ makeboard() { register int i; for (i = 0; i < SCORESIZE; i++) { winr[i].taxes = winr[i].score = sco[i].score = 0; winr[i].order = sco[i].order = i; } if (writeboard()) return(-1); chmod(scorefile, 0664); return(0); } /* * hashewon() Function to return 1 if player has won a game before, else 0 * * This function also sets c[HARDGAME] to appropriate value -- 0 if not a * winner, otherwise the next level of difficulty listed in the winners * scoreboard. This function also sets outstanding_taxes to the value in * the winners scoreboard. */ hashewon() { register int i; c[HARDGAME] = 0; if (readboard() < 0) return(0); /* can't find scoreboard */ for (i = 0; i < SCORESIZE; i++)/* search through winners scoreboard */ if (winr[i].suid == userid) if (winr[i].score > 0) { c[HARDGAME] = winr[i].hardlev + 1; outstanding_taxes = winr[i].taxes; return(1); } return(0); } /* * long paytaxes(x) Function to pay taxes if any are due * * Enter with the amount(in gp) to pay on the taxes. * Returns amount actually paid. */ long paytaxes(x) long x; { register int i; register long amt; if (x < 0) return(0L); if (readboard() < 0) return(0L); for (i = 0; i < SCORESIZE; i++) if (winr[i].suid == userid)/* look for players winning entry */ if (winr[i].score > 0) {/* search for a winning entry for the player */ amt = winr[i].taxes; if (x < amt) amt = x; /* don't overpay taxes(Ughhhhh) */ winr[i].taxes -= amt; outstanding_taxes -= amt; if (writeboard() < 0) return(0); return(amt); } return(0L); /* couldn't find user on winning scoreboard */ } /* * winshou() Subroutine to print out the winning scoreboard * * Returns the number of players on scoreboard that were shown */ winshou() { register struct wscofmt *p; register int i,j,count; for (count = j = i = 0; i < SCORESIZE; i++)/* is there anyone on the scoreboard? */ if (winr[i].score != 0) { j++; break; } if (j) { lprcat("\n Score Difficulty Time Needed Larn Winners List\n"); for (i = 0; i < SCORESIZE; i++)/* this loop is needed to print out the */ for (j = 0; j < SCORESIZE; j++) {/* winners in order */ p = &winr[j]; /* pointer to the scoreboard entry */ if (p -> order == i) { if (p -> score) { count++; lprintf("%10d %2d %5d Mobuls %s \n", (long) p -> score,(long) p -> hardlev,(long) p -> timeused, p -> who); } break; } } } return(count); /* return number of people on scoreboard */ } /* * shou(x) Subroutine to print out the non-winners scoreboard * int x; * * Enter with 0 to list the scores, enter with 1 to list inventories too * Returns the number of players on scoreboard that were shown */ shou(x) int x; { register int i,j,n,k; int count; for (count = j = i = 0; i < SCORESIZE; i++)/* is the scoreboard empty? */ if (sco[i].score != 0) { j++; break; } if (j) { lprcat("\n Score Difficulty Larn Visitor Log\n"); for (i = 0; i < SCORESIZE; i++)/* be sure to print them out in order */ for (j = 0; j < SCORESIZE; j++) if (sco[j].order == i) { if (sco[j].score) { count++; lprintf("%10d %2d %s ", (long) sco[j].score,(long) sco[j].hardlev, sco[j].who); if (sco[j].what < 256) lprintf("killed by a %s", monster[sco[j].what].name); else lprintf("%s", whydead[sco[j].what - 256]); if (x != 263) lprintf(" on %s", levelname[sco[j].level]); if (x) { for (n = 0; n < 26; n++) { iven[n] = sco[j].sciv[n][0]; ivenarg[n] = sco[j].sciv[n][1]; } for (k = 1; k < 99; k++) for (n = 0; n < 26; n++) if (k == iven[n]) { srcount = 0; show3(n); } lprcat("\n\n"); } else lprc('\n'); } j = SCORESIZE; } } return(count); /* return the number of players just shown */ } /* * showscores() Function to show the scoreboard on the terminal * * Returns nothing of value */ static char esb[] = "The scoreboard is empty.\n"; showscores() { register int i,j; lflush(); lcreat((char *) 0); if (readboard() < 0) return; i = winshou(); j = shou(0); if (i + j == 0) lprcat(esb); else lprc('\n'); lflush(); } /* * showallscores() Function to show scores and the iven lists that go with them * * Returns nothing of value */ showallscores() { register int i,j; lflush(); lcreat((char *) 0); if (readboard() < 0) return; c[WEAR] = c[WIELD] = c[SHIELD] = -1;/* not wielding or wearing anything */ for (i = 0; i < MAXPOTION; i++) potionname[i][0] = ' '; for (i = 0; i < MAXSCROLL; i++) scrollname[i][0] = ' '; i = winshou(); j = shou(1); if (i + j == 0) lprcat(esb); else lprc('\n'); lflush(); } /* * sortboard() Function to sort the scoreboard * * Returns 0 if no sorting done, else returns 1 */ sortboard() { register int i,j,pos; long jdat; for (i = 0; i < SCORESIZE; i++) sco[i].order = winr[i].order = -1; pos = 0; while (pos < SCORESIZE) { jdat = 0; for (i = 0; i < SCORESIZE; i++) if ((sco[i].order < 0) &&(sco[i].score >= jdat)) { j = i; jdat = sco[i].score; } sco[j].order = pos++; } pos = 0; while (pos < SCORESIZE) { jdat = 0; for (i = 0; i < SCORESIZE; i++) if ((winr[i].order < 0) &&(winr[i].score >= jdat)) { j = i; jdat = winr[i].score; } winr[j].order = pos++; } return(1); } /* * newscore(score, whoo, whyded, winner) Function to add entry to scoreboard * int score, winner, whyded; * char *whoo; * * Enter with the total score in gp in score, players name in whoo, * died() reason # in whyded, and TRUE/FALSE in winner if a winner * ex. newscore(1000, "player 1", 32, 0); */ newscore(score, whoo, whyded, winner) long score; int winner,whyded; char *whoo; { register int i; long taxes; if (readboard() < 0) return; /* do the scoreboard */ /* if a winner then delete all non-winning scores */ if (cheat) winner = 0; /* if he cheated, don't let him win */ if (winner) { for (i = 0; i < SCORESIZE; i++) if (sco[i].suid == userid) sco[i].score = 0; taxes = score * TAXRATE; score += 100000 * c[HARDGAME];/* bonus for winning */ /* if he has a slot on the winning scoreboard update it if greater score */ for (i = 0; i < SCORESIZE; i++) if (winr[i].suid == userid) { new1sub(score, i, whoo, taxes); return; } /* he had no entry. look for last entry and see if he has a greater score */ for (i = 0; i < SCORESIZE; i++) if (winr[i].order == SCORESIZE - 1) { new1sub(score, i, whoo, taxes); return; } } else if (!cheat) { /* for not winning scoreboard */ /* if he has a slot on the scoreboard update it if greater score */ for (i = 0; i < SCORESIZE; i++) if (sco[i].suid == userid) { new2sub(score, i, whoo, whyded); return; } /* he had no entry. look for last entry and see if he has a greater score */ for (i = 0; i < SCORESIZE; i++) if (sco[i].order == SCORESIZE - 1) { new2sub(score, i, whoo, whyded); return; } } } /* * new1sub(score,i,whoo,taxes) Subroutine to put player into a * int score,i,whyded,taxes; winning scoreboard entry if his score * char *whoo; is high enough * * Enter with the total score in gp in score, players name in whoo, * died() reason # in whyded, and TRUE/FALSE in winner if a winner * slot in scoreboard in i, and the tax bill in taxes. * Returns nothing of value */ new1sub(score, i, whoo, taxes) long score,taxes; int i; char *whoo; { register struct wscofmt *p; p = &winr[i]; p -> taxes += taxes; if ((score >= p -> score) ||(c[HARDGAME] > p -> hardlev)) { strcpy(p -> who, whoo); p -> score = score; p -> hardlev = c[HARDGAME]; p -> suid = userid; p -> timeused = gtime / 100; } } /* * new2sub(score,i,whoo,whyded) Subroutine to put player into a * int score,i,whyded,taxes; non-winning scoreboard entry if his * char *whoo; score is high enough * * Enter with the total score in gp in score, players name in whoo, * died() reason # in whyded, and slot in scoreboard in i. * Returns nothing of value */ new2sub(score, i, whoo, whyded) long score; int i,whyded; char *whoo; { register int j; register struct scofmt *p; p = &sco[i]; if ((score >= p -> score) ||(c[HARDGAME] > p -> hardlev)) { strcpy(p -> who, whoo); p -> score = score; p -> what = whyded; p -> hardlev = c[HARDGAME]; p -> suid = userid; p -> level = level; for (j = 0; j < 26; j++) { p -> sciv[j][0] = iven[j]; p -> sciv[j][1] = ivenarg[j]; } } } /* * died(x) Subroutine to record who played larn, and what the score was * int x; * * if x < 0 then don't show scores * died() never returns!(unless c[LIFEPROT] and a reincarnatable death!) * * < 256 killed by the monster number * 256 quit * 257 suspended * 258 self - annihilated * 259 shot by an arrow * 260 hit by a dart * 261 fell into a pit * 262 fell into a bottomless pit * 263 a winner * 264 trapped in solid rock * 265 killed by a missing save file * 266 killed by an old save file * 267 caught by the greedy cheater checker trap * 268 killed by a protected save file * 269 killed his family and killed himself * 270 erased by a wayward finger * 271 fell through a bottomless trap door * 272 fell through a trap door * 273 drank some poisonous water * 274 fried by an electric shock * 275 slipped on a volcano shaft * 276 killed by a stupid act of frustration * 277 attacked by a revolting demon * 278 hit by his own magic * 279 demolished by an unseen attacker * 280 fell into the dreadful sleep * 281 killed by an exploding chest * 282 killed by a missing maze data file * 283 killed by a sphere of annihilation * 284 died a post mortem death * 285 malloc() failure * 300 quick quit -- don't put on scoreboard */ static int scorerror; died(x) int x; { register int f,win; char ch,*mod; long zzz,i; struct tms cputime; if (c[LIFEPROT] > 0) { /* if life protection */ switch((x > 0) ? x : -x) { case 256: case 257: case 262: case 263: case 265: case 266: case 267: case 268: case 269: case 271: case 282: case 284: case 285: case 300: goto invalid; /* can't be saved */ }; --c[LIFEPROT]; c[HP] = 1; --c[CONSTITUTION]; cursors(); lprcat("\nYou feel wiiieeeeerrrrrd all over! "); beep(); lflush(); sleep(4); return; /* only case where died() returns */ } invalid: clearvt100(); lflush(); f = 0; if (ckpflag) delete(ckpfile); /* remove checkpoint file if used */ if (x < 0) { f++; x = -x; } /* if we are not to display the scores */ if ((x == 300) ||(x == 257)) exit(); /* for quick exit or saved game */ if (x == 263) win = 1; else win = 0; c[GOLD] += c[BANKACCOUNT]; c[BANKACCOUNT] = 0; /* now enter the player at the end of the scoreboard */ newscore(c[GOLD], logname, x, win); diedsub(x); /* print out the score line */ lflush(); set_score_output(); if ((wizard == 0) &&(c[GOLD] > 0)) {/* wizards can't score */ if (lappend(logfile) < 0) {/* append to file */ if (lcreat(logfile) < 0) {/* and can't create new log file */ lcreat((char *) 0); lprcat("\nCan't open record file: I can't post your score.\n"); sncbr(); resetscroll(); lflush(); exit(); } chmod(logfile, 0666); } strcpy(logg.who, loginname); logg.score = c[GOLD]; logg.diff = c[HARDGAME]; if (x < 256) { ch = *monster[x].name; if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') mod = "an"; else mod = "a"; sprintf(logg.what, "killed by %s %s", mod, monster[x].name); } else sprintf(logg.what, "%s", whydead[x - 256]); logg.cavelev = level; time(&zzz); /* get current time -- write out score info */ logg.diedtime = zzz; #ifdef EXTRA times(&cputime); /* get cpu time -- write out score info */ logg.cputime = i = (cputime.tms_utime + cputime.tms_stime - start_cpu) / 100 + c[CPUTIME]; logg.lev = c[LEVEL]; logg.ac = c[AC]; logg.hpmax = c[HPMAX]; logg.hp = c[HP]; logg.elapsedtime = (zzz - initialtime + 59) / 60; logg.usage = (10000 * i) / (zzz - initialtime); logg.bytin = c[BYTESIN]; logg.bytout = c[BYTESOUT]; logg.moves = c[MOVESMADE]; logg.spused = c[SPELLSCAST]; logg.killed = c[MONSTKILLED]; #endif lwrite((char *) & logg, sizeof(struct log_fmt)); lwclose(); /* now for the scoreboard maintenance -- not for a suspended game */ if (x != 257) { if (sortboard()) scorerror = writeboard(); } } if ((x == 256) ||(x == 257) ||(f != 0)) exit(); if (scorerror == 0) showscores(); /* if we updated the scoreboard */ if (x == 263) mailbill(); exit(); } /* * diedsub(x) Subroutine to print out the line showing the player when he is killed * int x; */ diedsub(x) int x; { register char ch,*mod; lprintf("Score: %d, Diff: %d, %s ",(long) c[GOLD],(long) c[HARDGAME], logname); if (x < 256) { ch = *monster[x].name; if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') mod = "an"; else mod = "a"; lprintf("killed by %s %s", mod, monster[x].name); } else lprintf("%s", whydead[x - 256]); if (x != 263) lprintf(" on %s\n", levelname[level]); else lprc('\n'); } /* * diedlog() Subroutine to read a log file and print it out in ascii format */ diedlog() { register int n; register char *p; struct stat stbuf; lcreat((char *) 0); if (lopen(logfile) < 0) { lprintf("Can't locate log file \"%s\"\n", logfile); return; } if (fstat(fd, &stbuf) < 0) { lprintf("Can't stat log file \"%s\"\n", logfile); return; } for (n = stbuf.st_size / sizeof(struct log_fmt); n > 0; --n) { lrfill((char *) & logg, sizeof(struct log_fmt)); p = ctime(&logg.diedtime); p[16] = '\n'; p[17] = 0; lprintf("Score: %d, Diff: %d, %s %s on %d at %s",(long)(logg.score),(long)(logg.diff), logg.who, logg.what,(long)(logg.cavelev), p + 4); #ifdef EXTRA if (logg.moves <= 0) logg.moves = 1; lprintf(" Experience Level: %d, AC: %d, HP: %d/%d, Elapsed Time: %d minutes\n", (long)(logg.lev),(long)(logg.ac),(long)(logg.hp),(long)(logg.hpmax),(long)(logg.elapsedtime)); lprintf(" CPU time used: %d seconds, Machine usage: %d.%02d%%\n", (long)(logg.cputime),(long)(logg.usage / 100),(long)(logg.usage % 100)); lprintf(" BYTES in: %d, out: %d, moves: %d, deaths: %d, spells cast: %d\n", (long)(logg.bytin),(long)(logg.bytout),(long)(logg.moves),(long)(logg.killed),(long)(logg.spused)); lprintf(" out bytes per move: %d, time per move: %d ms\n", (long)(logg.bytout / logg.moves),(long)((logg.cputime * 1000) / logg.moves)); #endif } lflush(); lrclose(); return; } #ifndef UIDSCORE /* * getplid(name) Function to get players id # from id file * * Enter with the name of the players character in name. * Returns the id # of the players character, or -1 if failure. * This routine will try to find the name in the id file, if its not there, * it will try to make a new entry in the file. Only returns -1 if can't * find him in the file, and can't make a new entry in the file. * Format of playerids file: * Id # in ascii \n character name \n */ static int havepid = -1; /* playerid # if previously done */ getplid(nam) char *nam; { int fd7,high = 999,no; register char *p,*p2; char name[80]; if (havepid != -1) return(havepid); /* already did it */ lflush(); /* flush any pending I/O */ sprintf(name, "%s\n", nam); /* append a \n to name */ if (lopen(playerids) < 0) { /* no file, make it */ if (lcreat(playerids) < 0) return(-1); /* can't make it */ lwclose(); goto addone; /* now append new playerid record to file */ } for (;;) { /* now search for the name in the player id file */ p = lgetl(); if (p == NULL) break; /* EOF? */ no = atoi(p); /* the id # */ p2 = lgetl(); if (p2 == NULL) break; /* EOF? */ if (no > high) high = no; /* accumulate highest id # */ if (strcmp(p2, name) == 0) {/* we found him */ return(no); /* his id number */ } } lrclose(); /* if we get here, we didn't find him in the file -- put him there */ addone: if (lappend(playerids) < 0) return(-1); /* can't open file for append */ lprintf("%d\n%s",(long) ++high, name);/* new id # and name */ lwclose(); lcreat((char *) 0); /* re-open terminal channel */ return(high); } #endif UIDSCORE SHAR_EOF if test 22296 -ne "`wc -c < 'scores.c'`" then echo shar: error transmitting "'scores.c'" '(should have been 22296 characters)' fi fi # end of overwriting check echo shar: extracting "'store.c'" '(22511 characters)' if test -f 'store.c' then echo shar: will not over-write existing file "'store.c'" else cat << \SHAR_EOF > 'store.c' /* store.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" static int dndcount = 0,dnditm = 0; /* this is the data for the stuff in the dnd store */ int maxitm = 83; /* number of items in the dnd inventory table */ globaldef struct _itm itm[90] = { /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 2, 0, OLEATHER, 0, 3 }, { 10, 0, OSTUDLEATHER, 0, 2 }, { 40, 0, ORING, 0, 2 }, { 85, 0, OCHAIN, 0, 2 }, { 220, 0, OSPLINT, 0, 1 }, { 400, 0, OPLATE, 0, 1 }, { 900, 0, OPLATEARMOR, 0, 1 }, { 2600, 0, OSSPLATE, 0, 1 }, { 150, 0, OSHIELD, 0, 1 }, /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 2, 0, ODAGGER, 0, 3 }, { 20, 0, OSPEAR, 0, 3 }, { 80, 0, OFLAIL, 0, 2}, { 150, 0, OBATTLEAXE, 0, 2}, { 450, 0, OLONGSWORD, 0, 2}, { 1000, 0, O2SWORD, 0, 2}, { 5000, 0, OSWORD, 0, 1}, { 16500, 0, OLANCE, 0, 1}, { 6000, 0, OSWORDofSLASHING, 0, 0}, { 10000, 0, OHAMMER, 0, 0 }, /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 150, 0, OPROTRING, 1, 1 } , { 85, 0, OSTRRING, 1, 1 } , { 120, 0, ODEXRING, 1, 1 } , { 120, 0, OCLEVERRING, 1, 1 } , { 180, 0, OENERGYRING, 0, 1 } , { 125, 0, ODAMRING, 0, 1 } , { 220, 0, OREGENRING, 0, 1 } , { 1000, 0, ORINGOFEXTRA, 0, 1 } , { 280, 0, OBELT, 0, 1 } , { 400, 0, OAMULET, 0, 1 } , { 6500, 0, OORBOFDRAGON, 0, 0 } , { 5500, 0, OSPIRITSCARAB, 0, 0 } , { 5000, 0, OCUBEofUNDEAD, 0, 0 } , { 6000, 0, ONOTHEFT, 0, 0 } , { 590, 0, OCHEST, 6, 1 } , { 200, 0, OBOOK, 8, 1 } , { 10, 0, OCOOKIE, 0, 3 } , /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 20, potionname, OPOTION, 0, 6 } , { 90, potionname, OPOTION, 1, 5 } , { 520, potionname, OPOTION, 2, 1 } , { 100, potionname, OPOTION, 3, 2 } , { 50, potionname, OPOTION, 4, 2 } , { 150, potionname, OPOTION, 5, 2 } , { 70, potionname, OPOTION, 6, 1 } , { 30, potionname, OPOTION, 7, 7 } , { 200, potionname, OPOTION, 8, 1 } , { 50, potionname, OPOTION, 9, 1 } , { 80, potionname, OPOTION, 10, 1 } , /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 30, potionname, OPOTION, 11, 3 } , { 20, potionname, OPOTION, 12, 5 } , { 40, potionname, OPOTION, 13, 3 } , { 35, potionname, OPOTION, 14, 2 } , { 520, potionname, OPOTION, 15, 1 } , { 90, potionname, OPOTION, 16, 2 } , { 200, potionname, OPOTION, 17, 2 } , { 220, potionname, OPOTION, 18, 4 } , { 80, potionname, OPOTION, 19, 6 } , { 370, potionname, OPOTION, 20, 3 } , { 50, potionname, OPOTION, 22, 1 } , { 150, potionname, OPOTION, 23, 3 } , /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 100, scrollname, OSCROLL, 0, 2 } , { 125, scrollname, OSCROLL, 1, 2 } , { 60, scrollname, OSCROLL, 2, 4 } , { 10, scrollname, OSCROLL, 3, 4 } , { 100, scrollname, OSCROLL, 4, 3 } , { 200, scrollname, OSCROLL, 5, 2 } , { 110, scrollname, OSCROLL, 6, 1 } , { 500, scrollname, OSCROLL, 7, 2 } , { 200, scrollname, OSCROLL, 8, 2 } , { 250, scrollname, OSCROLL, 9, 4 } , { 20, scrollname, OSCROLL, 10, 5 } , { 30, scrollname, OSCROLL, 11, 3 } , /* cost memory iven name iven arg how gp pointer iven[] ivenarg[] many */ { 340, scrollname, OSCROLL, 12, 1 } , { 340, scrollname, OSCROLL, 13, 1 } , { 300, scrollname, OSCROLL, 14, 2 } , { 400, scrollname, OSCROLL, 15, 2 } , { 500, scrollname, OSCROLL, 16, 2 } , { 1000, scrollname, OSCROLL, 17, 1 } , { 500, scrollname, OSCROLL, 18, 1 } , { 340, scrollname, OSCROLL, 19, 2 } , { 220, scrollname, OSCROLL, 20, 3 } , { 3900, scrollname, OSCROLL, 21, 0 } , { 610, scrollname, OSCROLL, 22, 1 } , { 3000, scrollname, OSCROLL, 23, 0 } }; /* function for the dnd store */ dnd_2hed() { lprcat("Welcome to the Larn Thrift Shoppe. We stock many items explorers find useful\n"); lprcat(" in their adventures. Feel free to browse to your hearts content.\n"); lprcat("Also be advised, if you break 'em, you pay for 'em."); } dnd_hed() { register int i; for (i = dnditm; i < 26 + dnditm; i++) dnditem(i); cursor(50, 18); lprcat("You have "); } dndstore() { register int i; dnditm = 0; nosignal = 1; /* disable signals */ clear(); dnd_2hed(); if (outstanding_taxes > 0) { lprcat("\n\nThe Larn Revenue Service has ordered us to not do business with tax evaders.\n"); beep(); lprintf("They have also told us that you owe %d gp in back taxes, and as we must\n",(long) outstanding_taxes); lprcat("comply with the law, we cannot serve you at this time. Soo Sorry.\n"); cursors(); lprcat("\nPress "); standout("escape"); lprcat(" to leave: "); lflush(); i = 0; while (i != '\33') i = readchar(); drawscreen(); nosignal = 0; /* enable signals */ return; } dnd_hed(); while (1) { cursor(59, 18); lprintf("%d gold pieces",(long) c[GOLD]); cltoeoln(); cl_dn(1, 20); /* erase to eod */ lprcat("\nEnter your transaction ["); standout("space"); lprcat(" for more, "); standout("escape"); lprcat(" to leave]? "); i = 0; while ((i < 'a' || i > 'z') &&(i != ' ') &&(i != '\33') &&(i != 12)) i = readchar(); if (i == 12) { clear(); dnd_2hed(); dnd_hed(); } else if (i == '\33') { drawscreen(); nosignal = 0; /* enable signals */ return; } else if (i == ' ') { cl_dn(1, 4); if ((dnditm += 26) >= maxitm) dnditm = 0; dnd_hed(); } else { /* buy something */ lprc(i); /* echo the byte */ i += dnditm - 'a'; if (i >= maxitm) outofstock(); else if (itm[i].qty <= 0) outofstock(); else if (pocketfull()) handsfull(); else if (c[GOLD] < itm[i].price * 10) nogold(); else { if (itm[i].mem != 0) *itm[i].mem[itm[i].arg] = ' '; c[GOLD] -= itm[i].price * 10; itm[i].qty--; take(itm[i].obj, itm[i].arg); if (itm[i].qty == 0) dnditem(i); nap(1001); } } } } /* function for the players hands are full */ static handsfull() { lprcat("\nYou can't carry anything more!"); lflush(); nap(2200); } static outofstock() { lprcat("\nSorry, but we are out of that item."); lflush(); nap(2200); } static nogold() { lprcat("\nYou don't have enough gold to pay for that!"); lflush(); nap(2200); } /* dnditem(index) to print the item list; used in dndstore() enter with the index into itm */ static dnditem(i) register int i; { register int j,k; if (i >= maxitm) return; cursor((j = (i & 1) * 40 + 1),(k = ((i % 26) >> 1) + 5)); if (itm[i].qty == 0) { lprintf("%39s", ""); return; } lprintf("%c) ",(i % 26) + 'a'); if (itm[i].obj == OPOTION) { lprcat("potion of "); lprintf("%s", &potionname[itm[i].arg][1]); } else if (itm[i].obj == OSCROLL) { lprcat("scroll of "); lprintf("%s", &scrollname[itm[i].arg][1]); } else lprintf("%s", objectname[itm[i].obj]); cursor(j + 31, k); lprintf("%6d",(long)(itm[i].price * 10)); } /* for the college of larn */ globaldef char course[26] = 0; /* the list of courses taken */ char coursetime[] = { 10, 15, 10, 20, 10, 10, 10, 5 }; /* function to display the header info for the school */ sch_hed() { clear(); lprcat("The College of Larn offers the exciting opportunity of higher education to\n"); lprcat("all inhabitants of the caves. Here is a list of the class schedule:\n\n\n"); lprcat("\t\t Course Name \t Time Needed\n\n"); if (course[0] == 0) lprcat("\t\ta) Fighters Training I 10 mobuls");/* line 7 of crt */ lprc('\n'); if (course[1] == 0) lprcat("\t\tb) Fighters Training II 15 mobuls"); lprc('\n'); if (course[2] == 0) lprcat("\t\tc) Introduction to Wizardry 10 mobuls"); lprc('\n'); if (course[3] == 0) lprcat("\t\td) Applied Wizardry 20 mobuls"); lprc('\n'); if (course[4] == 0) lprcat("\t\te) Behavioral Psychology 10 mobuls"); lprc('\n'); if (course[5] == 0) lprcat("\t\tf) Faith for Today 10 mobuls"); lprc('\n'); if (course[6] == 0) lprcat("\t\tg) Contemporary Dance 10 mobuls"); lprc('\n'); if (course[7] == 0) lprcat("\t\th) History of Larn 5 mobuls"); lprcat("\n\n\t\tAll courses cost 250 gold pieces."); cursor(30, 18); lprcat("You are presently carrying "); } oschool() { register int i; long time_used; nosignal = 1; /* disable signals */ sch_hed(); while (1) { cursor(57, 18); lprintf("%d gold pieces. ",(long) c[GOLD]); cursors(); lprcat("\nWhat is your choice ["); standout("escape"); lprcat(" to leave] ? "); yrepcount = 0; i = 0; while ((i < 'a' || i > 'h') &&(i != '\33') &&(i != 12)) i = readchar(); if (i == 12) { sch_hed(); continue; } else if (i == '\33') { nosignal = 0; drawscreen(); /* enable signals */ return; } lprc(i); if (c[GOLD] < 250) nogold(); else if (course[i - 'a']) { lprcat("\nSorry, but that class is filled."); nap(1000); } else if (i <= 'h') { c[GOLD] -= 250; time_used = 0; switch(i) { case 'a': c[STRENGTH] += 2; c[CONSTITUTION]++; lprcat("\nYou feel stronger!"); cl_line(16, 7); break; case 'b': if (course[0] == 0) { lprcat("\nSorry, but this class has a prerequisite of Fighters Training I"); c[GOLD] += 250; time_used = -10000; break; } lprcat("\nYou feel much stronger!"); cl_line(16, 8); c[STRENGTH] += 2; c[CONSTITUTION] += 2; break; case 'c': c[INTELLIGENCE] += 2; lprcat("\nThe task before you now seems more attainable!"); cl_line(16, 9); break; case 'd': if (course[2] == 0) { lprcat("\nSorry, but this class has a prerequisite of Introduction to Wizardry"); c[GOLD] += 250; time_used = -10000; break; } lprcat("\nThe task before you now seems very attainable!"); cl_line(16, 10); c[INTELLIGENCE] += 2; break; case 'e': c[CHARISMA] += 3; lprcat("\nYou now feel like a born leader!"); cl_line(16, 11); break; case 'f': c[WISDOM] += 2; lprcat("\nYou now feel more confident that you can find the potion in time!"); cl_line(16, 12); break; case 'g': c[DEXTERITY] += 3; lprcat("\nYou feel like dancing!"); cl_line(16, 13); break; case 'h': c[INTELLIGENCE]++; lprcat("\nYour instructor told you that the Eye of Larn is rumored to be guarded\n"); lprcat("by a platinum dragon who possesses psionic abilities. "); cl_line(16, 14); break; } time_used += coursetime[i - 'a'] * 100; if (time_used > 0) { gtime += time_used; course[i - 'a']++;/* remember that he has taken that course */ c[HP] = c[HPMAX]; c[SPELLS] = c[SPELLMAX];/* he regenerated */ if (c[BLINDCOUNT]) c[BLINDCOUNT] = 1;/* cure blindness too! */ if (c[CONFUSE]) c[CONFUSE] = 1;/* end confusion */ adjtime((long) time_used);/* adjust parameters for time change */ } nap(1000); } } } /* * for the first national bank of Larn */ int lasttime = 0; /* last time he was in bank */ obank() { banktitle(" Welcome to the First National Bank of Larn."); } obank2() { banktitle("Welcome to the 5th level branch office of the First National Bank of Larn."); } static banktitle(str) char *str; { nosignal = 1; /* disable signals */ clear(); lprcat(str); if (outstanding_taxes > 0) { register int i; lprcat("\n\nThe Larn Revenue Service has ordered that your account be frozen until all\n"); beep(); lprintf("levied taxes have been paid. They have also told us that you owe %d gp in\n",(long) outstanding_taxes); lprcat("taxes, and we must comply with them. We cannot serve you at this time. Sorry.\n"); lprcat("We suggest you go to the LRS office and pay your taxes.\n"); cursors(); lprcat("\nPress "); standout("escape"); lprcat(" to leave: "); lflush(); i = 0; while (i != '\33') i = readchar(); drawscreen(); nosignal = 0; /* enable signals */ return; } lprcat("\n\n\tGemstone\t Appraisal\t\tGemstone\t Appraisal"); obanksub(); nosignal = 0; /* enable signals */ drawscreen(); } /* * function to put interest on your bank account */ ointerest() { register int i; if (c[BANKACCOUNT] < 0) c[BANKACCOUNT] = 0; else if ((c[BANKACCOUNT] > 0) &&(c[BANKACCOUNT] < 500000)) { i = (gtime - lasttime) / 100;/* # mobuls elapsed */ while ((i-- > 0) &&(c[BANKACCOUNT] < 500000)) c[BANKACCOUNT] += c[BANKACCOUNT] / 250; if (c[BANKACCOUNT] > 500000) c[BANKACCOUNT] = 500000;/* interest limit */ } lasttime = (gtime / 100) * 100; } static short gemorder[26] = 0;/* the reference to screen location for each */ static long gemvalue[26] = 0; /* the appraisal of the gems */ obanksub() { unsigned long amt; register int i, k; ointerest(); /* credit any needed interest */ for (k = i = 0; i < 26; i++) switch(iven[i]) { case OLARNEYE: case ODIAMOND: case OEMERALD: case ORUBY: case OSAPPHIRE: if (iven[i] == OLARNEYE) { gemvalue[i] = 250000 - ((gtime * 7) / 100) * 100; if (gemvalue[i] < 50000) gemvalue[i] = 50000; } else gemvalue[i] = (255 & ivenarg[i]) * 100; gemorder[i] = k; cursor((k % 2) * 40 + 1,(k >> 1) + 4); lprintf("%c) %s", i + 'a', objectname[iven[i]]); cursor((k % 2) * 40 + 33,(k >> 1) + 4); lprintf("%5d",(long) gemvalue[i]); k++; }; cursor(31, 17); lprintf("You have %8d gold pieces in the bank.",(long) c[BANKACCOUNT]); cursor(40, 18); lprintf("You have %8d gold pieces",(long) c[GOLD]); if (c[BANKACCOUNT] + c[GOLD] >= 500000) lprcat("\nNote: Larndom law states that only deposits under 500,000gp can earn interest."); while (1) { cl_dn(1, 20); lprcat("\nYour wish? [("); standout("d"); lprcat(") deposit,("); standout("w"); lprcat(") withdraw,("); standout("s"); lprcat(") sell a stone, or "); standout("escape"); lprcat("] "); yrepcount = 0; i = 0; while (i != 'd' && i != 'w' && i != 's' && i != '\33') i = readchar(); switch(i) { case 'd': lprcat("deposit\nHow much? "); amt = readnum((long) c[GOLD]); if (amt < 0) { lprcat("\nSorry, but we can't take negative gold!"); nap(2000); amt = 0; } else if (amt > c[GOLD]) { lprcat(" You don't have that much."); nap(2000); } else { c[GOLD] -= amt; c[BANKACCOUNT] += amt; } break; case 'w': lprcat("withdraw\nHow much? "); amt = readnum((long) c[BANKACCOUNT]); if (amt < 0) { lprcat("\nSorry, but we don't have any negative gold!"); nap(2000); amt = 0; } else if (amt > c[BANKACCOUNT]) { lprcat("\nYou don't have that much in the bank!"); nap(2000); } else { c[GOLD] += amt; c[BANKACCOUNT] -= amt; } break; case 's': lprcat("\nWhich stone would you like to sell? "); i = 0; while ((i < 'a' || i > 'z') && i != '*') i = readchar(); if (i == '*') for (i = 0; i < 26; i++) { if (gemvalue[i]) { c[GOLD] += gemvalue[i]; iven[i] = 0; gemvalue[i] = 0; k = gemorder[i]; cursor((k % 2) * 40 + 1,(k >> 1) + 4); lprintf("%39s", ""); } } else { if (gemvalue[i = i - 'a'] == 0) { lprintf("\nItem %c is not a gemstone!", i + 'a'); nap(2000); break; } c[GOLD] += gemvalue[i]; iven[i] = 0; gemvalue[i] = 0; k = gemorder[i]; cursor((k % 2) * 40 + 1,(k >> 1) + 4); lprintf("%39s", ""); } break; case '\33': return; }; cursor(40, 17); lprintf("%8d",(long) c[BANKACCOUNT]); cursor(49, 18); lprintf("%8d",(long) c[GOLD]); } } /* subroutine to appraise any stone for the bank */ appraise(gemstone) register int gemstone; { register int j, amt; for (j = 0; j < 26; j++) if (iven[j] == gemstone) { lprintf("\nI see you have %s", objectname[gemstone]); if (gemstone == OLARNEYE) lprcat(" I must commend you. I didn't think\nyou could get it."); lprcat(" Shall I appraise it for you? "); yrepcount = 0; if (getyn() == 'y') { lprcat("yes.\n Just one moment please \n"); nap(1000); if (gemstone == OLARNEYE) { amt = 250000 - ((gtime * 7) / 100) * 100; if (amt < 50000) amt = 50000; } else amt = (255 & ivenarg[j]) * 100; lprintf("\nI can see this is an excellent stone, It is worth %d",(long) amt); lprcat("\nWould you like to sell it to us? "); yrepcount = 0; if (getyn() == 'y') { lprcat("yes\n"); c[GOLD] += amt; iven[j] = 0; } else lprcat("no thank you.\n"); if (gemstone == OLARNEYE) lprcat("It is, of course, your privilege to keep the stone\n"); } else lprcat("no\nO. K.\n"); } } /* function for the trading post */ static otradhead() { clear(); lprcat("Welcome to the Larn Trading Post. We buy items that explorers no longer find\n"); lprcat("useful. Since the condition of the items you bring in is not certain,\n"); lprcat("and we incur great expense in reconditioning the items, we usually pay\n"); lprcat("only 20% of their value were they to be new. If the items are badly\n"); lprcat("damaged, we will pay only 10% of their new value.\n\n"); } otradepost() { register int i, j, value, isub, izarg; dnditm = dndcount = 0; nosignal = 1; /* disable signals */ resetscroll(); otradhead(); while (1) { lprcat("\nWhat item do you want to sell to us ["); standout("*"); lprcat(" for list, or "); standout("escape"); lprcat("] ? "); i = 0; while (i > 'z' ||(i < 'a' && i != '*' && i != '\33' && i != '.')) i = readchar(); if (i == '\33') { setscroll(); recalc(); drawscreen(); nosignal = 0; /* enable signals */ return; } isub = i - 'a'; j = 0; if (iven[isub] == OSCROLL) if (scrollname[ivenarg[isub]][0] == 0) { j = 1; cnsitm(); } /* can't sell unidentified item */ if (iven[isub] == OPOTION) if (potionname[ivenarg[isub]][0] == 0) { j = 1; cnsitm(); } /* can't sell unidentified item */ if (!j) if (i == '*') { clear(); qshowstr(); otradhead(); } else if (iven[isub] == 0) lprintf("\nYou don't have item %c!", isub + 'a'); else { for (j = 0; j < maxitm; j++) if ((itm[j].obj == iven[isub]) ||(iven[isub] == ODIAMOND) ||(iven[isub] == ORUBY) ||(iven[isub] == OEMERALD) ||(iven[isub] == OSAPPHIRE)) { srcount = 0; show3(isub);/* show what the item was */ if ((iven[isub] == ODIAMOND) ||(iven[isub] == ORUBY) ||(iven[isub] == OEMERALD) ||(iven[isub] == OSAPPHIRE)) value = 20 * ivenarg[isub]; else if ((itm[j].obj == OSCROLL) ||(itm[j].obj == OPOTION)) value = 2 * itm[j + ivenarg[isub]].price; else { izarg = ivenarg[isub]; value = itm[j].price;/* appreciate if a +n object */ if (izarg >= 0) value *= 2; while ((izarg-- > 0) &&((value = 14 *(67 + value) / 10) < 500000)); } lprintf("\nItem(%c) is worth %d gold pieces to us. Do you want to sell it? ", i,(long) value); yrepcount = 0; if (getyn() == 'y') { lprcat("yes\n"); c[GOLD] += value; if (c[WEAR] == isub) c[WEAR] = -1; if (c[WIELD] == isub) c[WIELD] = -1; if (c[SHIELD] == isub) c[SHIELD] = -1; adjustcvalues(iven[isub], ivenarg[isub]); iven[isub] = 0; } else lprcat("no thanks.\n"); j = maxitm + 100;/* get out of the inner loop */ } if (j <= maxitm + 2) lprcat("\nSo sorry, but we are not authorized to accept that item."); } } } cnsitm() { lprcat("\nSorry, we can't accept unidentified objects."); } /* * for the Larn Revenue Service */ olrs() { register int i, first; unsigned long amt; first = nosignal = 1; /* disable signals */ clear(); resetscroll(); cursor(1, 4); lprcat("Welcome to the Larn Revenue Service district office. How can we help you?"); while (1) { if (first) { first = 0; goto nxt; } cursors(); lprcat("\n\nYour wish? [("); standout("p"); lprcat(") pay taxes, or "); standout("escape"); lprcat("] "); yrepcount = 0; i = 0; while (i != 'p' && i != '\33') i = readchar(); switch(i) { case 'p': lprcat("pay taxes\nHow much? "); amt = readnum((long) c[GOLD]); if (amt < 0) { lprcat("\nSorry, but we can't take negative gold\n"); amt = 0; } else if (amt > c[GOLD]) lprcat(" You don't have that much.\n"); else c[GOLD] -= paytaxes((long) amt); break; case '\33': nosignal = 0; /* enable signals */ setscroll(); drawscreen(); return; }; nxt: cursor(1, 6); if (outstanding_taxes > 0) lprintf("You presently owe %d gp in taxes. ",(long) outstanding_taxes); else lprcat("You do not owe us any taxes. "); cursor(1, 8); if (c[GOLD] > 0) lprintf("You have %6d gp. ",(long) c[GOLD]); else lprcat("You have no gold pieces. "); } } SHAR_EOF if test 22511 -ne "`wc -c < 'store.c'`" then echo shar: error transmitting "'store.c'" '(should have been 22511 characters)' fi fi # end of overwriting check # End of shell archive exit 0