Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!columbia!caip!clyde!cbatt!cbosgd!ucbvax!ucdavis!deneb!u566393908ea From: u566393908ea@ucdavis.UUCP (u566393908ea) Newsgroups: net.sources.games Subject: VMS Larn 12.0 is here! (part 1 of 6) Message-ID: <494@ucdavis.UUCP> Date: Sat, 30-Aug-86 18:00:38 EDT Article-I.D.: ucdavis.494 Posted: Sat Aug 30 18:00:38 1986 Date-Received: Sun, 31-Aug-86 09:09:02 EDT Distribution: net Organization: University of California, Davis Lines: 1677 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 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:@.<<<