From 1245800023eb9473aab413547c78bbb8d6b9f85e Mon Sep 17 00:00:00 2001 From: "William F. Jolitz" Date: Sun, 5 Mar 1989 19:02:39 -0800 Subject: [PATCH] 386BSD 0.1 development Work on file usr/othersrc/games/larn/Fixed.Bugs Work on file usr/othersrc/games/larn/README Work on file usr/othersrc/games/larn/bill.c Work on file usr/othersrc/games/larn/diag.c Work on file usr/othersrc/games/larn/global.c Work on file usr/othersrc/games/larn/help.c Work on file usr/othersrc/games/larn/io.c Work on file usr/othersrc/games/larn/datfiles/larnopts Work on file usr/othersrc/games/larn/datfiles/larn.help Work on file usr/othersrc/games/larn/datfiles/larnmaze Work on file usr/othersrc/games/larn/datfiles/lfortune Work on file usr/othersrc/games/larn/movem.c Work on file usr/othersrc/games/larn/nap.c Work on file usr/othersrc/games/larn/object.c Work on file usr/othersrc/games/larn/scores.c Work on file usr/othersrc/games/larn/regen.c Work on file usr/othersrc/games/larn/savelev.c Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.1 --- usr/othersrc/games/larn/Fixed.Bugs | 216 +++++ usr/othersrc/games/larn/README | 148 ++++ usr/othersrc/games/larn/bill.c | 132 +++ usr/othersrc/games/larn/datfiles/larn.help | 140 ++++ usr/othersrc/games/larn/datfiles/larnmaze | 288 +++++++ usr/othersrc/games/larn/datfiles/larnopts | 12 + usr/othersrc/games/larn/datfiles/lfortune | 34 + usr/othersrc/games/larn/diag.c | 314 +++++++ usr/othersrc/games/larn/global.c | 621 ++++++++++++++ usr/othersrc/games/larn/help.c | 87 ++ usr/othersrc/games/larn/io.c | 915 +++++++++++++++++++++ usr/othersrc/games/larn/movem.c | 312 +++++++ usr/othersrc/games/larn/nap.c | 116 +++ usr/othersrc/games/larn/object.c | 807 ++++++++++++++++++ usr/othersrc/games/larn/regen.c | 92 +++ usr/othersrc/games/larn/savelev.c | 47 ++ usr/othersrc/games/larn/scores.c | 652 +++++++++++++++ 17 files changed, 4933 insertions(+) create mode 100644 usr/othersrc/games/larn/Fixed.Bugs create mode 100644 usr/othersrc/games/larn/README create mode 100644 usr/othersrc/games/larn/bill.c create mode 100644 usr/othersrc/games/larn/datfiles/larn.help create mode 100644 usr/othersrc/games/larn/datfiles/larnmaze create mode 100644 usr/othersrc/games/larn/datfiles/larnopts create mode 100644 usr/othersrc/games/larn/datfiles/lfortune create mode 100644 usr/othersrc/games/larn/diag.c create mode 100644 usr/othersrc/games/larn/global.c create mode 100644 usr/othersrc/games/larn/help.c create mode 100644 usr/othersrc/games/larn/io.c create mode 100644 usr/othersrc/games/larn/movem.c create mode 100644 usr/othersrc/games/larn/nap.c create mode 100644 usr/othersrc/games/larn/object.c create mode 100644 usr/othersrc/games/larn/regen.c create mode 100644 usr/othersrc/games/larn/savelev.c create mode 100644 usr/othersrc/games/larn/scores.c diff --git a/usr/othersrc/games/larn/Fixed.Bugs b/usr/othersrc/games/larn/Fixed.Bugs new file mode 100644 index 0000000000..d2acae0a93 --- /dev/null +++ b/usr/othersrc/games/larn/Fixed.Bugs @@ -0,0 +1,216 @@ +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 .larnopts 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 .larnopts 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 .larnopts 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 + .larnopts 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 .larnopts 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. + diff --git a/usr/othersrc/games/larn/README b/usr/othersrc/games/larn/README new file mode 100644 index 0000000000..71e477b30f --- /dev/null +++ b/usr/othersrc/games/larn/README @@ -0,0 +1,148 @@ +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: + +Fixed.Bugs this is a list of the things that were changed + since ver 11.0 +Makefile makefile script to compile the program +Make.lint makefile script to run larn sources through lint +README this is what you are now reading +bill.c code for the letters of praise if player wins +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 +.holidays data file which lists upcoming holidays +io.c code to handle file and terminal i/o +.larn.help.uue larn help file (UUENCODED) +.larnmaze data file for pre-made mazes +.larnopts a sample .larnopts option data file +.lfortune data file which contains the hints +main.c code for the main command control and parsing +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 UNIX 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 +=============================================================================== + diff --git a/usr/othersrc/games/larn/bill.c b/usr/othersrc/games/larn/bill.c new file mode 100644 index 0000000000..3926a2e570 --- /dev/null +++ b/usr/othersrc/games/larn/bill.c @@ -0,0 +1,132 @@ +#include "header.h" +/* bill.c "Larn is copyrighted 1986 by Noah Morgan. */ +static char mail600[32]; +/* + * function to create the tax bill for the user + */ +static int pid; +static letter1() + { + sprintf(mail600,"/tmp/#%dmail600",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,"/tmp/#%dmail600",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,"/tmp/#%dmail600",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,"/tmp/#%dmail600",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,"/tmp/#%dmail600",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,"/tmp/#%dmail600",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]; + wait(0); pid=getpid(); + if (fork() == 0) + { + resetscroll(); + for (i=0; i specify difficulty of the game (may be used with -n) +larn -o specify the .larnopts file to be used +larn -c create new scoreboards -- prompts for a password + Special Notes + +When dropping gold, 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 VT100 to operate. A check is made of the environment variable +"TERM" and it must be equal to "vt100". This only applies if +the game has been compiled with "VT100" defined in the Makefile. If compiled +to use termcap, there are no terminal restrictions, save needing cm, ce, & cl +termcap entries. + +When in the store, trading post, school, or home, an  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 'D' 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. + Background Information for Larn + + 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! + + + + How to use the .larnopts option file + +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. + + Explanation of the Larn scoreboard facility + + 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. + + + + + + + + + + + diff --git a/usr/othersrc/games/larn/datfiles/larnmaze b/usr/othersrc/games/larn/datfiles/larnmaze new file mode 100644 index 0000000000..37a89c347d --- /dev/null +++ b/usr/othersrc/games/larn/datfiles/larnmaze @@ -0,0 +1,288 @@ +@################################################################### +# # . # # # # # . # +# 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# # # # #. .# # # # # # # # .. .# # # # +#.###### # # # # #.....# # # # # # ! # # # # +# # ####### ####### ### ### ####### ### ### ####### ### ### # +# # ... .. # +################################################################### + diff --git a/usr/othersrc/games/larn/datfiles/larnopts b/usr/othersrc/games/larn/datfiles/larnopts new file mode 100644 index 0000000000..17216edfe1 --- /dev/null +++ b/usr/othersrc/games/larn/datfiles/larnopts @@ -0,0 +1,12 @@ +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" + diff --git a/usr/othersrc/games/larn/datfiles/lfortune b/usr/othersrc/games/larn/datfiles/lfortune new file mode 100644 index 0000000000..748f7f6118 --- /dev/null +++ b/usr/othersrc/games/larn/datfiles/lfortune @@ -0,0 +1,34 @@ +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 diff --git a/usr/othersrc/games/larn/diag.c b/usr/othersrc/games/larn/diag.c new file mode 100644 index 0000000000..4ed557d1b7 --- /dev/null +++ b/usr/othersrc/games/larn/diag.c @@ -0,0 +1,314 @@ +/* diag.c Larn is copyrighted 1986 by Noah Morgan. */ +#include +#include +#include +#include "header.h" +extern long int initialtime; +extern int rmst,maxitm,lasttime; +extern char nosignal; +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 to save game\n",fname); + nosignal=0; return(-1); + } + + set_score_output(); + lwrite((char*)beenhere,MAXLEVEL+MAXVLEVEL); + for (k=0; kp) + 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); /* 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; kp=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!=i)) fsorry(); + lrclose(); + if (strcmp(fname,ckpfile) == 0) + { + if (lappend(fname) < 0) fcheat(); else { lprc(' '); lwclose(); } + lcreat((char*)0); + } + else if (unlink(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; + } diff --git a/usr/othersrc/games/larn/global.c b/usr/othersrc/games/larn/global.c new file mode 100644 index 0000000000..80a3dd4630 --- /dev/null +++ b/usr/othersrc/games/larn/global.c @@ -0,0 +1,621 @@ +/* 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[],srcount,dropflag; +extern int random;/* the random number seed */ +extern short playerx,playery,lastnum; +extern char cheat,level,monstnamelist[]; +extern char lastmonst[],*what[],*who[]; +extern char winner[]; +extern char logname[],monstlevel[]; +extern char sciv[SCORESIZE+1][26][2],*potionname[],*scrollname[]; +/* + *********** + 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= 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; + cursors(); strcpy(lastmonst,""); + lprcat("\n\nDo you really want to quit?"); + while (1) + { + i=getchar(); + 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? "); + } + } + +/* + function to ask --more-- then the user must enter a space + */ +more() + { + lprcat("\n --- press "); standout("space"); lprcat(" to continue --- "); + while (getchar() != ' '); + } + +/* + 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; +/* cursors(); */ + if ((limit = 15+(c[LEVEL]>>1)) > 26) limit=26; + for (i=0; i25)) 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 0)); + i=36; + while (--i > 0) + { + if ((j=getchar()) != '"') *str++ = j; else i=0; + } + *str = 0; + i=50; + if (j != '"') while ((getchar() != '"') && (--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; + extern char *password; + scbr(); /* system("stty -echo cbreak"); */ + gpwp = gpwbuf; lprcat("\nEnter Password: "); lflush(); + i = strlen(password); + for (j=0; j0)) --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((((randx=randx*1103515245+12345)>>7)%(x))+1); + } + +rund(x) + int x; + { + return((((randx=randx*1103515245+12345)>>7)%(x)) ); + } +#endif MACRORND diff --git a/usr/othersrc/games/larn/help.c b/usr/othersrc/games/larn/help.c new file mode 100644 index 0000000000..0f21367dc7 --- /dev/null +++ b/usr/othersrc/games/larn/help.c @@ -0,0 +1,87 @@ +/* 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) + */ +extern char helpfile[]; +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=getchar(); + 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 (getchar() != '\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'); + } + diff --git a/usr/othersrc/games/larn/io.c b/usr/othersrc/games/larn/io.c new file mode 100644 index 0000000000..dc0d5e7c42 --- /dev/null +++ b/usr/othersrc/games/larn/io.c @@ -0,0 +1,915 @@ +/* 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 + * getchar() 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. + ** putchar(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" + +#ifdef SYSV /* system III or system V */ +#include +#define sgttyb termio +#define stty(_a,_b) ioctl(_a,TCSETA,_b) +#define gtty(_a,_b) ioctl(_a,TCGETA,_b) +static int rawflg = 0; +static char saveeof,saveeol; +#define doraw(_a) if(!rawflg){++rawflg;saveeof=_a.c_cc[VMIN];saveeol=_a.c_cc[VTIME];}\ + _a.c_cc[VMIN]=1;_a.c_cc[VTIME]=1;_a.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL) +#define unraw(_a) _a.c_cc[VMIN]=saveeof;_a.c_cc[VTIME]=saveeol;_a.c_lflag |= ICANON|ECHO|ECHOE|ECHOK|ECHONL + +#else not SYSV + +#ifndef BSD +#define CBREAK RAW /* V7 has no CBREAK */ +#endif + +#define doraw(_a) (_a.sg_flags |= CBREAK,_a.sg_flags &= ~ECHO) +#define unraw(_a) (_a.sg_flags &= ~CBREAK,_a.sg_flags |= ECHO) +#include +#endif not SYSV + +#ifndef NOVARARGS /* if we have varargs */ +#include +#else NOVARARGS /* if we don't have varargs */ +typedef char *va_list; +#define va_dcl int va_alist; +#define va_start(plist) plist = (char *) &va_alist +#define va_end(plist) +#define va_arg(plist,mode) ((mode *)(plist += sizeof(mode)))[-1] +#endif NOVARARGS + +#define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */ +int lfd; /* output file numbers */ +int fd; /* input file numbers */ +static struct sgttyb ttx; /* storage for the tty modes */ +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"); */ + } + +/* + * getchar() Routine to read in one character from the terminal + */ +getchar() + { + char byt; +#ifdef EXTRA + c[BYTESIN]++; +#endif + lflush(); /* be sure output buffer is flushed */ + read(0,&byt,1); /* get byte from terminal */ + return(byt); + } + +/* + * scbr() Function to set cbreak -echo for the terminal + * + * like: system("stty cbreak -echo") + */ +scbr() + { + gtty(0,&ttx); doraw(ttx); stty(0,&ttx); + } + +/* + * sncbr() Function to set -cbreak echo for the terminal + * + * like: system("stty -cbreak echo") + */ +sncbr() + { + gtty(0,&ttx); unraw(ttx); stty(0,&ttx); + } + +/* + * newgame() Subroutine to save the initial time and seed rnd() + */ +newgame() + { + register long *p,*pe; + for (p=c,pe=c+100; p= 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); + } +#endif lint + +/* + * 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++]); + if (iepoint!=MAXIBUF) return(0); + 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,2)) < 0) + { + lfd=1; return(-1); + } + lseek(lfd,0,2); /* seek to 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 staring 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 putchar (); + +/* + * 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(); + } + if ((outbuf=malloc(BUFBIG+16))==0) /* get memory for decoded output buffer*/ + { + 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) { putchar (*str); curx++; } + else switch (*str) + { + case CLEAR: tputs (CL, 0, putchar); curx = cury = 0; + break; + + case CL_LINE: tputs (CE, 0, putchar); + break; + + case CL_DOWN: tputs (CD, 0, putchar); + break; + + case ST_START: tputs (SO, 0, putchar); + break; + + case ST_END: tputs (SE, 0, putchar); + break; + + case CURSOR: curx = *++str - 1; cury = *++str - 1; + tputs (tgoto (CM, curx, cury), 0, putchar); + 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, putchar); + tputs (CE, 0, putchar); + + if (--scrline < 19) scrline=23; + tputs (tgoto (CM, 0, scrline), 0, putchar); + tputs (CE, 0, putchar); + } + else + { + tputs (tgoto (CM, 0, 19), 0, putchar); + tputs (DL, 0, putchar); + tputs (tgoto (CM, 0, 23), 0, putchar); + /* tputs (AL, 0, putchar); */ + } + } + else + { + putchar ('\n'); cury++; + } + curx = 0; + break; + + default: putchar (*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; +/* + * putchar(ch) Print one character in decoded output buffer. + */ +int putchar(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 tmdigit=0; /* the # in \33[#m */ + while (*ss) + { + switch(tmstate) + { + case 0: if (*ss=='\33') { tmstate++; break; } + ign: *sd++ = *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') { *sd++ = ST_END; goto ign2; } + goto ign; + case 3: if (*ss == 'm') + { + if (tmdigit) *sd++ = ST_START; + else *sd++ = ST_END; + goto ign2; + } + default: goto ign; + }; + ss++; + } + *sd=0; /* NULL terminator */ + return(sd); + } +#endif VT100 + +/* + * beep() Routine to emit a beep if enabled (see no-beep in .larnopts) + */ +beep() + { + if (!nobeep) *lpnt++ = '\7'; + } diff --git a/usr/othersrc/games/larn/movem.c b/usr/othersrc/games/larn/movem.c new file mode 100644 index 0000000000..7239a068f3 --- /dev/null +++ b/usr/othersrc/games/larn/movem.c @@ -0,0 +1,312 @@ +/* + * 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= 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; kplayerx) --xh; + if (jplayery) --yh; + for (k=0; k<9; k++) w1[k] = 10000; + + for (k=xl; k 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); + }; + } + } diff --git a/usr/othersrc/games/larn/nap.c b/usr/othersrc/games/larn/nap.c new file mode 100644 index 0000000000..b7a877d147 --- /dev/null +++ b/usr/othersrc/games/larn/nap.c @@ -0,0 +1,116 @@ +/* nap.c Larn is copyrighted 1986 by Noah Morgan. */ +#include +#include +#ifdef SYSV +#include +#else +#ifdef BSD +#include +#endif BSD +#endif SYSV + +/* + * 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 +#ifdef SYSV +/* napms - sleep for time milliseconds - uses times() */ +/* this assumes that times returns a relative time in 60ths 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 */ + if ((matchclock = times(&stats)) == -1 || matchclock == 0) + return; /* error, or BSD style times() */ + matchclock += (time / 17); /*17 ms/tic is 1000 ms/sec / 60 tics/sec */ + + while(matchclock < times(&stats)) + ; + } + +#else not SYSV +#ifdef BSD +#ifdef SIGVTALRM +/* This must be BSD 4.2! */ +#include +#define bit(_a) (1<<((_a)-1)) + +static nullf() + { + } + +/* napms - sleep for time milliseconds - uses setitimer() */ +napms(time) + int time; + { + struct itimerval timeout; + int (*oldhandler) (); + int oldsig; + + if (time <= 0) return; + + timerclear(&timeout.it_interval); + timeout.it_value.tv_sec = time / 1000; + timeout.it_value.tv_usec = (time % 1000) * 1000; + + oldsig = sigblock(bit(SIGALRM)); + setitimer(ITIMER_REAL, &timeout, (struct itimerval *)0); + oldhandler = signal(SIGALRM, nullf); + sigpause(oldsig); + signal(SIGALRM, oldhandler); + sigsetmask(oldsig); + } + +#else +/* napms - sleep for time milliseconds - uses ftime() */ + +static napms(time) + int time; + { + /* assumed to be BSD UNIX */ + struct timeb _gtime; + time_t matchtime; + unsigned short matchmilli; + register struct timeb *tp = & _gtime; + + if (time <= 0) return; + ftime(tp); + matchmilli = tp->millitm + time; + matchtime = tp->time; + while (matchmilli >= 1000) + { + ++matchtime; + matchmilli -= 1000; + } + + while(1) + { + ftime(tp); + if ((tp->time > matchtime) || + ((tp->time == matchtime) && (tp->millitm >= matchmilli))) + break; + } + } +#endif +#else not BSD +static napms(time) int time; {} /* do nothing, forget it */ +#endif BSD +#endif SYSV +#endif NONAP diff --git a/usr/othersrc/games/larn/object.c b/usr/othersrc/games/larn/object.c new file mode 100644 index 0000000000..9bf7c3c504 --- /dev/null +++ b/usr/othersrc/games/larn/object.c @@ -0,0 +1,807 @@ +/* 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=getchar(); + 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=getchar(); + 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=getchar(); + 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=getchar(); + 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=getchar(); + 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=getchar(); + 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=getchar(); + 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 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; i0) 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=getchar(); + 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(getchar()) + { + 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=MAXPOTION) return; /* check for within bounds */ + potionname[pot][0] = ' '; + switch(pot) + { + case 9: lprcat("\nYou feel greedy . . ."); nap(2000); + for (i=0; i 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>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=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=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 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(getchar()) + { + 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(getchar()) + { + 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=getchar(); while (i!='\33' && i!='\n') i=getchar(); + if (i=='\33') { drawscreen(); nosignal = 0; /* enable signals */ return; } + } + } + +/* routine to save program space */ +iopts() + { lprcat(", or (i) ignore it? "); } +ignore() + { lprcat("ignore\n"); } + diff --git a/usr/othersrc/games/larn/regen.c b/usr/othersrc/games/larn/regen.c new file mode 100644 index 0000000000..b9f7a0f2cd --- /dev/null +++ b/usr/othersrc/games/larn/regen.c @@ -0,0 +1,92 @@ +/* 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(); + } + diff --git a/usr/othersrc/games/larn/savelev.c b/usr/othersrc/games/larn/savelev.c new file mode 100644 index 0000000000..4419acb950 --- /dev/null +++ b/usr/othersrc/games/larn/savelev.c @@ -0,0 +1,47 @@ +/* savelev.c Larn is copyrighted 1986 by Noah Morgan. */ +#include "header.h" +extern struct cel *cell; + +/* + * routine to save the present level into storage + */ +savelevel() + { + register struct cel *pcel; + register char *pitem,*pknow,*pmitem; + register short *phitp,*piarg; + register struct cel *pecel; + pcel = &cell[level*MAXX*MAXY]; /* pointer to this level's cells */ + pecel = pcel + MAXX*MAXY; /* pointer to past end of this level's cells */ + pitem=item[0]; piarg=iarg[0]; pknow=know[0]; pmitem=mitem[0]; phitp=hitp[0]; + while (pcel < pecel) + { + pcel->mitem = *pmitem++; + pcel->hitp = *phitp++; + pcel->item = *pitem++; + pcel->know = *pknow++; + pcel++->iarg = *piarg++; + } + } + +/* + * routine to restore a level from storage + */ +getlevel() + { + register struct cel *pcel; + register char *pitem,*pknow,*pmitem; + register short *phitp,*piarg; + register struct cel *pecel; + pcel = &cell[level*MAXX*MAXY]; /* pointer to this level's cells */ + pecel = pcel + MAXX*MAXY; /* pointer to past end of this level's cells */ + pitem=item[0]; piarg=iarg[0]; pknow=know[0]; pmitem=mitem[0]; phitp=hitp[0]; + while (pcel < pecel) + { + *pmitem++ = pcel->mitem; + *phitp++ = pcel->hitp; + *pitem++ = pcel->item; + *pknow++ = pcel->know; + *piarg++ = pcel++->iarg; + } + } diff --git a/usr/othersrc/games/larn/scores.c b/usr/othersrc/games/larn/scores.c new file mode 100644 index 0000000000..f6cf15c13e --- /dev/null +++ b/usr/othersrc/games/larn/scores.c @@ -0,0 +1,652 @@ +/* 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 +#include +#include +#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(); + 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 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; i0) /* 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; iorder == 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= jdat)) + { j=i; jdat=sco[i].score; } + sco[j].order = pos++; + } + pos=0; while (pos < SCORESIZE) + { + jdat=0; + for (i=0; i= 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; itaxes += 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) unlink(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 */ + { +#ifndef NOLOG + 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,0660); + } + 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 cpu 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)/60 + 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(); +#endif NOLOG + +/* 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 ((fd7=creat(playerids,0666)) < 0) return(-1); /* can't make it */ + close(fd7); 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 + -- 2.20.1