billr@saab.CNA.TEK.COM (Bill Randle) (07/14/90)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 87
Archive-name: nethack3p9/Part42
Supersedes: NetHack3: Volume 7, Issue 56-93
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 42 (of 56)."
# Contents: Install.dos Install.ovl src/do_name.c src/sp_lev.c
# Wrapped by billr@saab on Wed Jul 11 17:11:56 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Install.dos' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Install.dos'\"
else
echo shar: Extracting \"'Install.dos'\" \(13860 characters\)
sed "s/^X//" >'Install.dos' <<'END_OF_FILE'
X Instructions for compiling and installing NetHack 3.0
X on an MS-DOS, TOS, or OS/2 system
X =====================================================
X (or, How to make PC, ST, and OS/2 NetHack 3.0)
X Last revision: 22 May 1990
X
X Credit for ST and OS/2 NetHack 3.0 goes to Eric Smith and Timo Hakulinen,
X respectively. Additional credit should be given to Steve Creps and
X Mike Threepoint for PC NetHack.
X
X*** Note: if you intend to compile NetHack on an MS-DOS PC using OVERLAY,
X please turn to the instructions in Install.ovl. The overlay version is
X currently available only for MSC.
X
X1. Make sure all the NetHack files are in the appropriate directory structure.
X You should have a main directory with subdirectories src, include, auxil,
X others, amiga, mac, and vms. If you do not follow this structure, the
X Makefile will not function properly.
X
X All the shared and UNIX-specific .c files and the source Makefile belong
X in src; all the PC .c files and make files belong in others; all the .h
X files belong in include; other assorted files belong in auxil. We will
X not need any of the files from the amiga, mac, and vms directories.
X
X If you downloaded or ftp'd the sources from a UNIX system, the lines
X will probably end in UNIX-style newlines, instead of the carriage
X return and line feed pairs used by DOS and OS/2. Turbo C 2.0 in
X particular dislikes these; you'll have to convert them (with a utility
X like Rahul Dhesi's "flip"). Also, every file should end with an empty
X line, because both Microsoft C has a habit of ignoring the last line of
X each file. (TOS compilers generally don't have either problem).
X
X2. Copy the .c files from the others directory to your src directory
X based on the following decisions. (You will probably want to include
X all of these files.)
X
X You will definitely need pc*.c and msdos.c.
X
X The file termcap.uu is the fixed version of the Fred Fish termcap library.
X You will need to run a uudecode utility on it to generate the file
X termcap.arc. termcap.arc contains several files of termcap routines.
X Using them with NetHack involves very little knowledge of the UNIX concept
X of a termcap database; mostly you need to know enough to set a TERM
X environment variable. You can unarc termcap.arc here in the others
X directory, but if you are going to use it, it is probably best to unarc a
X copy in the src directory. That way you will not miss copying any
X files over. Wherever you unarc it, get rid of the included makefile
X since a better version has been provided as Makefile.lib.
X
X random.c is only needed if you want the high-quality random number
X generation routines.
X
X trampoli.c and ovlmgr.obj files are needed for the MS-DOS overlays.
X You may ignore these.
X
X TOS users should use others/lev_lex.c instead of src/lev_lex.c.
X MS-DOS users should be able to use either, but the one in src
X is smaller. If you have flex or some other lex work-alike, use
X that to produce lev_lex.c from lev_comp.l.
X
X Obviously, TOS users don't need the MS-DOS overlay functions.
X Moreover, the GCC "curses" library has termcap routines built
X in, so if you have this you don't need termcap.arc.
X
X3. Now look at Makefile.* in your others directory. Consult the list below
X and pick out the makefile most appropriate to your system. Rename this
X file to "Makefile" (no extension), and move it into your src directory.
X
X DOS:
X Microsoft C 5.0+ Makefile.msc
X Microsoft C 4.0 Makefile.pc
X Turbo C 2.0 Makefile.tcc
X OS/2:
X Microsoft C 5.1 Makefile.os2
X TOS:
X GCC 1.34 Makefile.st
X
X The PC NetHack makefiles are set up for NDMAKE, a public domain
X "make" utility. Both Microsoft's and Borland's "make" leave much to
X be desired. It is worth the extra effort to get NDMAKE if you don't
X already have it. Among other things, NDMAKE automatically generates
X link response files when the link command involves so many objects
X that the command would become longer than DOS can handle. If you must
X use Microsoft's or Borland's "make", you'll need to edit the makefile
X into a form your make can use, and add instructions to generate a link
X response file.
X
X Makefile.os2 can also be used with Microsoft NMAKE, which is shipped with
X new versions of MS languages. This "make", although slightly incompatible
X with NDMAKE, is powerful enough to make NetHack. Since NDMAKE only works
X in DOS, the only way to compile NetHack in OS/2 currently is to use NMAKE.
X However, when cross-compiling for OS/2 in DOS, NDMAKE is a better choice
X because it requires less RAM for itself. See Makefile.os2 for more
X information.
X
X The ST NetHack makefile should work with either the widely available
X PD make, or (much better) GNU Make.
X
X If you're using a different compiler, you will have to adapt one of
X the makefiles to your needs. In particular, change the CC and CFLAGS
X macros to your C compiler's file name and the parameters to pass it.
X
X For DOS users, if you are going to be constructing the Fred Fish termlib
X you will need the Makefile.lib. Copy this to your source directory too,
X and do not change its name.
X
X Makefile.top in the top directory and Makefile.aux(il) in the
X auxil directory are for UNIX NetHack. You may delete them.
X
X4. Now go to the include subdirectory to edit a couple of the header files
X there.
X
X First edit config.h according to the comments to match your system and
X desired set of features. Mostly you need to check the WIZARD option,
X make sure the HACKDIR is set properly, and check TERMLIB and COMPRESS.
X
X Also edit pcconf.h for PC or OS/2 NetHack, or tosconf.h for ST NetHack.
X pcconf.h should not need much editing. If you are not going to include
X random.c or termcap.uu you will need to comment out RANDOM or TERMLIB
X respectively. You will definitely need to comment out OVERLAY.
X
X Commenting out the #define TERMLIB in pcconf.h/tosconf.h to disable
X use of termcap routines (relying on the ANSI_DEFAULT feature) will make
X your job a bit easier. However, you can compile with both and simply
X not set your TERM variable if you do not wish to use the termcap file
X settings.
X
X ST and OS/2 NetHackers can skip to the next section, since the entire game
X will fit in less than one megabyte.
X
X PC NetHackers:
X
X To compile under MS-DOS, you must either produce an overlaid executable or
X make some very difficult decisions about which features to include.
X
X The base size of a PC NetHack executable, with no extra features or
X overlays, will be around 570 (or better) kilobytes. Anything over 590K
X is likely not to work. Here's an incomplete and outdated list of the
X approximate costs of various additional features in terms of executable
X size, using Microsoft C:
X
X WIZARD 3K
X LOGFILE
X NEWS
X COMPRESS 2K
X ZEROCOMP
X CHDIR
X
X POLYSELF 31K
X THEOLOGY 11K
X SOUNDS 6K
X KICK
X
X THRONES 3K
X FOUNTAINS 2K
X SINKS 5K
X ALTARS 4K
X
X WALLIFIED_MAZE 1K
X REINCARNATION 7K
X STRONGHOLD 13K
X
X ORACLE
X MEDUSA
X KOPS
X ARMY 1K
X WORM
X GOLEMS 2K
X INFERNO
X SEDUCE
X TOLKIEN
X PROBING 1K
X WALKIES 4K
X SHIRT
X MUSIC 6K
X TUTTI_FRUTTI
X SPELLS 10K
X NAMED_ITEMS
X
X ELBERETH 3K
X EXPLORE_MODE 2K
X HARD
X
X REDO 1K
X COM_COMPL 1K
X CLIPPING
X
X DGK 7K
X TERMLIB
X RANDOM 1K
X SHELL
X TEXTCOLOR 1K
X
X Using Turbo C, we eked by with just WIZARD, ZEROCOMP, BITFIELDS, ELBERETH,
X HARD, REDO, DGK and TEXTCOLOR.
X
X5. If you're using a compiler not in the list in step 3, you may want to look
X through system.h, in the include directory. This file matches the return
X and parameter types for system calls and library routines with various
X flavors of compilers and operating systems. Leaving this file alone is
X unlikely to cause problems, but if you get compile errors with any
X functions in the standard library, it's worth checking the declarations
X there.
X
X6. If you want to change the high score list behavior, examine the top of
X topten.c, in the src directory. You may want to change the definitions of
X PERSMAX, POINTSMIN, and ENTRYMAX. I set POINTSMIN to 51 and ENTRYMAX to
X 50 to keep the size of the score list down.
X
X7. Go to the src directory and edit the top of your Makefile. Be sure the
X directory you want the game installed in actually exists.
X
X If you elected not to use the high-quality BSD random number routines by
X commenting out RANDOM in pcconf.h or tosconf.h, comment out (or set equal
X to nothing) the RANDOM macro in your Makefile.
X
X If you elected to use Fred Fish's termcap library (bundled in as
X termcap.arc), you will have to generate termcap.lib from those sources
X by typing make -f makefile.lib termlib.lib. DOS / OS/2 users must set the
X TERMLIB option in Makefile.msc / Makefile.os2 to link in the resulting
X termlib.lib.
X
X If you are recompiling after patching your sources, or if you got your
X files from somewhere other than the official distribution, "touch
X makedefs.c" to ensure that certain files (onames.h and pm.h) are remade,
X lest potentially troublesome timestamps fool "make".
X
X8. Now, enter "make all", and take a long siesta; your computer will be
X occupied for a long time. If all goes well, you will get an executable.
X If you tried to compile in too many features, you will probably get a
X dysfunctional executable, and will have to start over.
X
X Hint: If you're short on memory, you might enter "make -n all
X >script.bat", and then in DOS enter "script", or in TOS use the Gulam
X command "source script.bat". GCC users will be short on memory if
X they only have 2 megabytes. Indeed, some files will not compile in
X 2 megabytes with the GCC 1.36; for these you'll either have to turn
X off the -O option or use an earlier version of the GCC.
X
X9. Make sure the support files-- data, rumors, cmdhelp, opthelp, help, hh,
X history, license, and oracles (if ORACLES was #define'd)-- were copied
X to the game directory. If not, move them there from the auxil directory
X yourself. rumors can be created manually by entering "makedefs -r";
X data by entering "makedefs -d".
X
X If you compiled in the compiled levels (if STRONGHOLD was #define'd), make
X sure castle, tower?, and possibly endgame are there, too. They can be
X created manually by entering "lev_comp filename.des", where filename.des
X is the appropriate description file (found in the auxil directory).
X
X10. Go to the others directory. Copy NetHack.cnf, or Atari.cnf for TOS, to
X your game directory as "NetHack.cnf". Edit it to reflect your particular
X setup and personal preferences, following the comments.
X
X If you compiled in the TERMLIB feature, also move the "termcap" file to
X your game directory. (Note: GCC's termcap routines have built-in
X defaults, so the termcap file is not necessary with that compiler.)
X
X To use funky graphics charaters in TOS, uudecode "atarifnt.uue" and unarc
X the resulting "atarifnt.arc". This contains a program to run that makes
X some line graphics characters available to NetHack. To use them, uncomment
X the appropriate line in your NetHack.cnf file, and run the program before
X running NetHack (you can put the program in an AUTO folder if you want).
X
X If you'll be running NetHack from a different subdirectory, you will
X want to "set HACKDIR=\games\nethack" (or whatever directory you want to
X use) now. Add it to your autoexec.bat (in DOS), if you'll be playing
X often.
X
X11. Play NetHack. If it works, you're done!
X
X
XNotes
X-----
X
X1) Save files and bones files from previous versions will not work with
X NetHack 3.0. Don't bother trying to keep them. Record (score) files
X from before 3.0 patchlevel 7 will almost work, but you need to make one
X change manually to them: At the end of each line is a word or phrase
X specifying what killed the player. Change the string to start with the
X words "killed by", "killed by a", or "killed by an" (whichever is
X appropriate). If the death was petrification, it should read "petrified
X by" instead of "killed by". Don't change "starvation", "quit", "escaped",
X or "ascended".
X
X2) To install an update of NetHack after changing something, enter "make"
X from the src directory. If you add, delete, or reorder monsters or
X objects, or you change the format of saved level files, delete any save
X and bones files. (Trying to use such files sometimes produces amusing
X confusions on the game's part, but usually crashes.)
X
X3) During linking, the Microsoft Overlay Linker will need temporary storage
X space to make the PC and OS/2 versions. Make sure you have
X about a meg of free disk where ever you have defined your temporary
X storage. It is also a good idea to compile with as much free RAM as
X possible. It may otherwise get crowded with the bigger, more complex
X source files. (Compiler bombs with "out of heap space" or similar.)
X If this happens, strip your configuration, zap TSR's etc.
X
X4) On a 286 10MHz PC you will have NetHack in about 2 - 2.5 hours.
X
X5) Both OS/2 NetHack and the overlaid PC NetHack have been developed using
X MSC 5.1. MSC 6.0 is on the market, but since there hasn't been enough
X time to fully test the game compiled with MSC 6.0, the distribution version
X supports officially only MSC 5.1. To compile NetHack with MSC 6.0, it may
X be necessary to make some slight modifications to respective makefiles
X as well as some source files. Also, when compiling OS/2 version with MSC
X 6.0, change library "doscalls" to "os2" in Makefile.os2.
END_OF_FILE
if test 13860 -ne `wc -c <'Install.dos'`; then
echo shar: \"'Install.dos'\" unpacked with wrong size!
fi
# end of 'Install.dos'
fi
if test -f 'Install.ovl' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Install.ovl'\"
else
echo shar: Extracting \"'Install.ovl'\" \(14761 characters\)
sed "s/^X//" >'Install.ovl' <<'END_OF_FILE'
X Instructions for compiling and installing the Overlaid
X NetHack 3.0 on an MS-DOS system
X ======================================================
X (or, How to make PC NetHack 3.0)
X Last revision: June 02, 1990
X
X (Credit for a runnable full PC NetHack 3.0 goes to the overlay team of
X Pierre Martineau, Stephen Spackman, Norm Meluch, and Kevin Smolkowski,
X who built on the work of Steve Creps and Mike Threepoint.)
X
X
XI. Dispelling the Myths:
X
X Compiling NetHack is not as easy as it sounds, nor as hard as it looks,
X however it will behoove you to read this entire file through before
X beginning the task.
X
X The NetHack executable that you are about to get will be generated by an
X overlay linker. The beauty of this overlay linker beastie is that it will
X create an executable that will function in much less memory than it would
X "normally" take to run. Do not be deceived. The RAM requirement for the
X overlay version is about 550k! You can load the program in less RAM, but
X you will begin to experience a serious amount of disk thrashing at 530k
X or less. Absolute minimum will probably be in the neighborhood of 380-400k.
X You do not want to run the program like that! The more free RAM you have
X available for the program, the more smoothly it will run.
X
X The magic piece to the overlay puzzle is a program called ovlmgr.asm. This
X is a replacement for the Microsoft (and we use the term loosely) overlay
X manager. This program has been enhanced since its release in November
X 1989. It will now allow NetHack to use EMS memory if any is available,
X therefore, RAM requirements can be reduced to the minimum with at least
X 256K of EMS.
X
X As of patch level 7, version 3.0 has an added feature in the Makefile.
X This feature enables a structured break-up of the object modules so that
X we can link heavily used functions together without actual source code
X movement. This has provided a great speed improvement for this release.
X See the file others\maintain.ovl for more information on this structuring.
X
X
XII. How long is this going to take?
X
X On an XT class PC it has been rumored that NetHack can be built in 8 - 10
X hours.
X On a 286 10MHz PC you can build NetHack in about 3 - 3.5 hours,
X On the flip side if you have a 386 33MHz PC with a *VERRRRY* fast hard
X disk, math coprocessor, 32 bit bus, and severe I/O caching you will have
X NetHack in about 15 minutes!
X
X Hope you enjoy the game. We have worked very hard to try to bring it back
X to the PC.
X
X
XIII. Tools:
X
X The following programs are necessary to successfully compile the overlaid
X version of NetHack:
X
X A. Microsoft C, version 5.1 or newer.
X
X B. The Microsoft Overlay Linker, version 3.6 or newer or preferably,
X the Microsoft Segmented Linker, version 5.01.20 or newer. The
X overlay linker has been known to cause problems with other
X programs, but not with NetHack, yet.
X One of these linkers should be included in your MSC version.
X
X C. NDmake, version 4.5 or newer, (available from your local ftp site).
X As the overlay makefile is pretty large, you will want to use the
X large model of NDmake: MAKE45L.EXE, as your make program.
X MSC 6.0 has a new make program distributed with it that might be
X able to handle the Makefile.ovl with a few modifications. This has
X not been completely tested. We recommend NDmake 4.5.
X
X
XIV. Optional tools:
X
X The following programs are not necessary, because pre-built copies of the
X files are included in this distribution. However, if you want to build
X NetHack 100% from scratch, you will need them.
X
X A. An 80x86 assembler.
X This is for assembling the ovlmgr.asm file into ovlmgr.obj. If you
X want to assemble your own copy of the overlay manager. The file
X others\ovlmgr.uu is a uuencoded version of the assembled ovlmgr.asm.
X For details, see the file ovlmgr.doc.
X
X B. Yacc/Bison & Lex/Flex workalike programs for the PC.
X The source files for the special levels compiler are built using
X bison and flex. Precompiled copies of the files lev_lex.c, and
X lev_comp.c have been provided if you do not have these utilities.
X Bison & flex should also be available at your local ftp site.
X
X
XV. To compile your copy of NetHack on a MSDOS machine:
X (or "just follow the "simple" steps outlined below.)
X
X1. It almost goes without saying that you should make sure that your tools
X are set up and running correctly.
X
X2. Make sure all the NetHack files are in the appropriate directory
X structure. You should have a main directory with subdirectories
X src, include, auxil, others, amiga, mac, and vms. If you do not
X follow this structure, the Makefile.ovl will not function properly.
X
X All the shared and UNIX-specific .c files and the source Makefile(.src)
X belong in src; all the PC *.c files and PC make files belong in others;
X all the .h files belong in include; other assorted files belong in auxil.
X Check the file "Files" in your top level directory for an exact listing
X of what file is in which directory.
X
X We will not need any of the files from the amiga, mac, and vms
X directories, so you can delete them if you need the space.
X
X If you downloaded or ftp'd the sources from a UNIX system, the lines
X will probably end in UNIX-style newlines, instead of the carriage
X return and line feed pairs used by DOS. Some programs have trouble
X with them, you may need to convert them (with a utility like
X Rahul Dhesi's "flip"). Also, every file should end with an empty
X line, because both Microsoft C and MASM have a habit of ignoring the
X last line of each file.
X
X3. Move/Copy files from the others directory to your src directory
X based on the following criteria. You will probably want to include
X most all of these files.
X
X You will definitely need pc*.c, msdos.c, and trampoli.c.
X
X random.c is only needed if you want the high-quality random number
X generation routines.
X
X You should be able to use either others/lev_lex.c (generated by flex)
X or src/lev_lex.c (generated by lex), but the one in src is smaller.
X If you have flex or some other lex work-alike, you can use that to
X produce lev_lex.c from lev_comp.l.
X
X The file termcap.uu is the fixed version of the Fred Fish termcap library.
X You will need to run a uudecode utility on it to generate the file
X termcap.arc. termcap.arc contains several files of termcap routines.
X Using them with NetHack involves very little knowledge of the UNIX concept
X of a termcap database; mostly you need to know enough to set a TERM
X environment variable. You can unarc termcap.arc here in the others
X directory, but if you are going to use it, it is probably best to unarc a
X copy in the src directory. That way you will not miss copying any
X files over. Wherever you unarc it, get rid of the included makefile
X since a better version has been provided as Makefile.lib.
X
X ovlmgr.uu (MS-DOS overlay manager) is the uuencoded assembled
X object module for the overlay manager in case you do not have an assembler.
X You will need to run a uudecode utility on this file too, to generate
X ovlmgr.obj.
X
X Exesmurf.uu is the uuencoded copy of the exesmurf utility which displays
X and modifies the contents of an executable file header. It is similar
X to Microsoft's exemod utility but it provides infomation on overlays
X which EXEMOD does not. It is used to modify the Nethack executable's
X memory allocation.
X
X4. Rename the file Makefile.ovl to "Makefile." (no extension), and move
X it into your src directory.
X
X The PC NetHack makefiles are set up for NDMAKE, a public domain
X "make" utility. Both Microsoft's "make" leaves much to
X be desired. It is worth the extra effort to get NDMAKE if you don't
X already have it. Among other things, NDMAKE automatically generates
X link response files when the link command involves so many objects
X that the command would become longer than DOS can handle. If you must
X use Microsoft's or Borland's "make", you'll need to edit the makefile
X into a form your make can use, and add instructions to generate a link
X response file.
X
X If you are going to be constructing the Fred Fish termlib you will need
X the Makefile.lib. Copy this to your source directory too, and do not
X change its name.
X
X Makefile.top in the top directory, Makefile.src in the src directory,
X and Makefile.aux(il) in the auxil directory are for UNIX NetHack. You
X will not need these, and you may delete them.
X
X Makefile.pc, Makefile.msc, and Makefile.tos are for compiling non-
X overlaid versions of NetHack, and for the atari. You may delete these
X too.
X
X4. Now go to the include subdirectory to edit a couple of the header files
X there.
X
X First edit config.h according to the comments to match your system and
X desired set of features. Mostly you need to check the WIZARD option,
X make sure the HACKDIR is set properly, and check TERMLIB and COMPRESS.
X
X Using Microsoft C and overlays, we've managed to enable all the special
X features. You may include all the neat features you want.
X
X Also check pcconf.h, which should not need much editing (if you are
X including termcap.uu and random.c). If you are not including these, you
X will need to comment out TERMLIB and/or RANDOM. You should make doubly
X certain that OVERLAY is defined in pcconf.h, since otherwise things will
X compile properly but very ugly things are likely to happen wherever
X function pointers cross overlay boundaries - the linker is a little thick
X about that.
X
X Commenting out the #define TERMLIB in pcconf.h to disable use of termcap
X routines (relying on the ANSI_DEFAULT feature) will make your job a bit
X easier. However, you can compile with both TERMLIB and ANSI_DEFAULT
X and simply not set your TERM variable if you do not wish to use the
X termcap file settings.
X
X6. If you want to change the high score list behavior, examine the top of
X topten.c, in the src directory. You may want to change the definitions of
X PERSMAX, POINTSMIN, and ENTRYMAX. I set POINTSMIN to 51 and ENTRYMAX to
X 50 to keep the size of the score list down.
X
X7. Go to the src directory and edit the top of your Makefile. Be sure the
X directory you want the game installed (GAMEDIR) in actually exists.
X
X If you elected not to use the high-quality BSD random number routines by
X commenting out RANDOM in pcconf.h or tosconf.h, comment out (or set equal
X to nothing) the RANDOM macro in your Makefile.
X
X If you elected to use Fred Fish's termcap library (bundled in as
X termcap.arc), you will have to generate termlib.lib from those sources
X by typing "make -f makefile.lib". You must also set the TERMLIB option
X in Makefile.ovl to link in the resulting termlib.lib.
X
X If you have a MASM compatible Assembler, you may want to enable the option
X in the makefile to rebuild ovlmgr.obj, although a ready-made object file
X is provided for those of you without. Before assembling ovlmgr, be sure
X to read ovlmgr.doc as there are several options that you may or may not
X wish to enable/disable.
X
X If you are recompiling after patching your sources, or if you got your
X files from somewhere other than the official distribution, "touch
X makedefs.c" to ensure that certain files (onames.h and pm.h) are remade,
X lest potentially troublesome timestamps fool "make".
X
X8. Now, enter "make45l install", and take a long siesta; your computer will
X be occupied for a long time. If all goes well, you will get an executable.
X
X9. Make sure the support files -- data, rumors, cmdhelp, opthelp, help, hh,
X history, license, and oracles (if ORACLE was #define'd) -- were copied
X to the game directory. If not, move them there from the auxil directory
X yourself. rumors can be created manually by entering "makedefs -r",
X data by entering "makedefs -d".
X
X If you compiled in the special levels (if STRONGHOLD was #define'd), make
X sure castle, tower?, and possibly endgame are there, too. They can be
X created manually by entering "lev_comp filename.des", where filename.des
X is the appropriate description file (found in the auxil directory).
X
X Make sure the files NetHack.cnf and termcap also made it to your game
X directory. If not go to the others directory and copy NetHack.cnf and
X termcap to your game directory. Edit NetHack.cnf to reflect your
X particular setup and personal preferences, by following the comments.
X
X If you'll be running NetHack from a different subdirectory, you will
X want to "set HACKDIR=c:\games\nethack" (or whatever drive and directory
X you want to use) now. Add it to your autoexec.bat (in DOS), if you'll
X be playing often.
X
X11. Play NetHack. If it works, you're done!
X
X
XNotes
X-----
X1) First and foremost: We have been developing with MSC 5.1 as a compiler
X and NDmake 4.5 as a make. NDmake is readily available on the Usenet;
X obtaining MSC might be more of a problem. MSC 5.0 is broken. You *will
X not* be able to compile the overlay version with that compiler due to
X problems with the /Gt option allowing the CONST segment to become
X > 64k when linking.
X MSC 6.0 and its make utility have been used to generate an overlaid
X NetHack.exe, however sufficient testing has not been completed at this
X time for us to "recommend" its use.
X
X2) Save files and bones files from previous versions will not work with
X NetHack 3.0. Don't bother trying to keep them. Record (score) files
X from before 3.0 patchlevel 7 will almost work, but you need to make one
X change manually to them: At the end of each line is a word or phrase
X specifying what killed the player. Change the string to start with the
X words "killed by", "killed by a", or "killed by an" (whichever is
X appropriate). If the death was petrification, it should read "petrified
X by" instead of "killed by". Don't change "starvation", "quit", "escaped",
X or "ascended".
X
X3) To install an update of NetHack after changing something, enter "make"
X from the src directory. If you add, delete, or reorder monsters or
X objects, or you change the format of saved level files, delete any save
X and bones files. (Trying to use such files sometimes produces amusing
X confusions on the game's part, but usually crashes.)
X
X4) During linking the Microsoft Overlay Linker will need temporary storage
X space. Make sure you have about a meg of free disk wherever you have
X defined your temporary storage.
END_OF_FILE
if test 14761 -ne `wc -c <'Install.ovl'`; then
echo shar: \"'Install.ovl'\" unpacked with wrong size!
fi
# end of 'Install.ovl'
fi
if test -f 'src/do_name.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/do_name.c'\"
else
echo shar: Extracting \"'src/do_name.c'\" \(13564 characters\)
sed "s/^X//" >'src/do_name.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)do_name.c 3.0 89/11/08
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#ifdef NAMED_ITEMS
X# include <ctype.h>
X#endif
X
X#ifdef OVLB
X
Xstatic char *FDECL(visctrl, (CHAR_P));
Xstatic void FDECL(do_oname, (struct obj *));
X
Xstatic
Xchar *
Xvisctrl(c)
Xchar c;
X{
X#ifdef LINT /* static char ccc[3]; */
X char ccc[3];
X#else
X static char ccc[3];
X#endif
X
X if(c < 040) {
X ccc[0] = '^';
X ccc[1] = c + 0100;
X ccc[2] = 0;
X } else {
X ccc[0] = c;
X ccc[1] = 0;
X }
X return(ccc);
X}
X
Xvoid
Xgetpos(cc,force,goal)
Xcoord *cc;
Xint force;
Xconst char *goal;
X{
X register int cx, cy, i, c;
X const char *sdp = flags.num_pad ? ndir : sdir;
X#ifdef MACOS
X extern short macflags;
X Boolean fUpdateFlagOn;
X long ticks;
X#endif
X
X if(flags.verbose) pline("(For instructions type a ?)");
X#ifdef MACOS
X if ((macflags & fDoUpdate) && (macflags & fDoNonKeyEvt)) {
X fUpdateFlagOn = true;
X } else {
X fUpdateFlagOn = false;
X macflags |= (fDoUpdate | fDoNonKeyEvt);
X }
X macflags |= fMoveWRTMouse;
X#endif
X cx = cc->x;
X cy = cc->y;
X#ifdef CLIPPING
X cliparound(cx, cy);
X (void) win_curs(cx, cy);
X#else
X curs(cx,cy+2);
X#endif
X while((c = readchar()) != '.'){
X for(i=0; i<8; i++) if(sdp[i] == c){
X if(1 <= cx + xdir[i] && cx + xdir[i] <= COLNO)
X cx += xdir[i];
X if(0 <= cy + ydir[i] && cy + ydir[i] <= ROWNO-1)
X cy += ydir[i];
X goto nxtc;
X }
X if(c == '?'){
X pline("Use [%s] to move the cursor to %s.",
X flags.num_pad ? "2468" : "hjkl", goal);
X pline("Type a . when you are at the right place.");
X } else {
X if (!index(quitchars, c))
X pline("Unknown direction: '%s' (%s).",
X visctrl(c),
X force ?
X flags.num_pad ? "use 2468 or ." :
X "use hjkl or ." :
X "aborted");
X if(force) goto nxtc;
X#ifdef MACOS
X macflags &= ~fMoveWRTMouse;
X if (!fUpdateFlagOn)
X macflags &= ~(fDoUpdate | fDoNonKeyEvt);
X#endif
X cc->x = -1;
X cc->y = 0;
X return;
X }
X nxtc: ;
X#ifdef CLIPPING
X cliparound(cx, cy);
X (void) win_curs(cx, cy);
X#else
X curs(cx,cy+2);
X#endif
X }
X#ifdef MACOS
X macflags &= ~fMoveWRTMouse;
X if (!fUpdateFlagOn)
X macflags &= ~(fDoUpdate | fDoNonKeyEvt);
X#endif
X cc->x = cx;
X cc->y = cy;
X return;
X}
X
Xstruct monst *
Xchristen_monst(mtmp, name)
Xstruct monst *mtmp;
Xconst char *name;
X{
X register int lth,i;
X register struct monst *mtmp2;
X
X /* dogname and catname are 63-character arrays; the generic naming
X * function do_mname() below also cut names off at 63 characters */
X lth = strlen(name)+1;
X if(lth > 63){
X lth = 63;
X }
X mtmp2 = newmonst(mtmp->mxlth + lth);
X *mtmp2 = *mtmp;
X for(i=0; i<mtmp->mxlth; i++)
X ((char *) mtmp2->mextra)[i] = ((char *) mtmp->mextra)[i];
X mtmp2->mnamelth = lth;
X (void)strncpy(NAME(mtmp2), name, lth);
X NAME(mtmp2)[lth-1] = 0;
X replmon(mtmp,mtmp2);
X return(mtmp2);
X}
X
Xint
Xdo_mname(){
X char buf[BUFSZ];
X coord cc;
X register int cx,cy;
X register struct monst *mtmp;
X register char *curr;
X boolean blank;
X
X cc.x = u.ux;
X cc.y = u.uy;
X getpos(&cc, 0, "the monster you want to name");
X cx = cc.x;
X cy = cc.y;
X if(cx < 0) return(0);
X if (cx == u.ux && cy == u.uy) {
X pline("This %s creature is called %s and cannot be renamed.",
X ACURR(A_CHA) > 14 ?
X (flags.female ? "beautiful" : "handsome") :
X "ugly",
X plname);
X return(0);
X }
X if (!cansee(cx,cy) || !MON_AT(cx,cy) || (mtmp = m_at(cx, cy))->mimic
X || (mtmp->minvis && !See_invisible) || mtmp->mundetected) {
X pline("I see no monster there.");
X return(0);
X }
X pline("What do you want to call %s? ", lmonnam(mtmp));
X getlin(buf);
X clrlin();
X if(!*buf || *buf == '\033') return(0);
X
X /* unnames monster if all spaces */
X for (curr = buf, blank = 1; *curr; blank = (*curr++ == ' '));
X if(blank) *buf = '\0';
X
X if(type_is_pname(mtmp->data)) {
X pline("%s doesn't like being called names!", Monnam(mtmp));
X if(!mtmp->mtame) {
X pline("%s gets %sangry!", Monnam(mtmp),
X mtmp->mpeaceful ? "" : "very ");
X mtmp->mpeaceful = 0;
X mtmp->msleep = 0;
X }
X return(0);
X }
X (void) christen_monst(mtmp, buf);
X return(0);
X}
X
X/*
X * This routine changes the address of obj. Be careful not to call it
X * when there might be pointers around in unknown places. For now: only
X * when obj is in the inventory.
X */
Xstatic
Xvoid
Xdo_oname(obj)
Xregister struct obj *obj;
X{
X char buf[BUFSZ];
X register char *curr;
X boolean blank;
X
X pline("What do you want to name %s? ", doname(obj));
X getlin(buf);
X clrlin();
X if(!*buf || *buf == '\033') return;
X
X /* unnames item if all spaces */
X for (curr = buf, blank = 1; *curr; blank = (*curr++ == ' '));
X if(blank) *buf = '\0';
X
X#ifdef NAMED_ITEMS
X if(is_artifact(obj))
X pline("The artifact seems to resist the attempt.");
X else if (restr_name(obj, buf) || exist_artifact(obj, buf)) {
X int n = rn2(strlen(buf));
X char c1,c2;
X
X c1 = isupper(buf[n]) ? tolower(buf[n]) : buf[n];
X while (c1 == (c2 = 'a' + rn2('z'-'a')));
X if (isupper(buf[n]))
X /* islower(c2) guaranteed by generation */
X buf[n] = toupper(c2);
X else buf[n] = c2;
X pline("While engraving your hand slips.");
X more();
X You("engrave: \"%s\".",buf);
X (void)oname(obj, buf, 1);
X }
X else
X#endif
X (void)oname(obj, buf, 1);
X}
X
Xstruct obj *
Xoname(obj, buf, ininv)
Xregister struct obj *obj;
Xconst char *buf;
Xregister int ininv;
X{
X register struct obj *otmp, *otmp2, *contents;
X register int lth;
X
X lth = *buf ? strlen(buf)+1 : 0;
X if(lth > 63){
X lth = 63;
X }
X /* if already properly named */
X if(lth == obj->onamelth && (!lth || !strcmp(ONAME(obj),buf)))
X return obj;
X#ifdef NAMED_ITEMS
X /* If named artifact exists in the game, do not create another.
X * Also trying to create an artifact shouldn't de-artifact
X * it (e.g. Excalibur from prayer). In this case the object
X * will retain its current name. */
X if (is_artifact(obj) || exist_artifact(obj, buf))
X return obj;
X else
X artifact_exists(obj, buf, TRUE);
X#endif
X otmp2 = newobj(lth);
X *otmp2 = *obj;
X otmp2->onamelth = lth;
X#ifdef __GNUC__
X /* Without the following line, the program gives anything an empty
X * name when I try to #name it. Probably a compiler bug, but at the
X * point where I discovered this, there's no time to check to make
X * sure.
X */
X if (buf) (void)donull();
X#endif
X if(lth) {
X (void)strncpy(ONAME(otmp2), buf, lth);
X ONAME(otmp2)[lth-1] = 0;
X }
X if (obj->owornmask) {
X /* Note: dying by burning in Hell causes problems if you
X * try doing this when owornmask isn't set.
X */
X setworn((struct obj *)0, obj->owornmask);
X setworn(otmp2, otmp2->owornmask);
X }
X
X if (ininv) {
X /* do freeinv(obj); etc. by hand in order to preserve
X the position of this object in the inventory */
X if(obj == invent) invent = otmp2;
X else for(otmp = invent; ; otmp = otmp->nobj){
X if(!otmp)
X panic("oname: cannot find obj.");
X if(otmp->nobj == obj){
X otmp->nobj = otmp2;
X break;
X }
X }
X }
X if (Is_container(obj)) {
X for(contents=fcobj; contents; contents=contents->nobj)
X if(contents->cobj==obj) contents->cobj = otmp2;
X }
X /* obfree(obj, otmp2); /* now unnecessary: no pointers on bill */
X free((genericptr_t) obj); /* let us hope nobody else saved a pointer */
X return otmp2;
X}
X
Xstatic const char NEARDATA callable[] = {
X SCROLL_SYM, POTION_SYM, WAND_SYM, RING_SYM, AMULET_SYM, GEM_SYM,
X#ifdef SPELLS
X SPBOOK_SYM,
X#endif
X ARMOR_SYM, TOOL_SYM, 0 };
X
Xint
Xddocall()
X{
X register struct obj *obj;
X#ifdef REDO
X char ch;
X
X if (!in_doagain)
X#endif
X pline("Name an individual object? ");
X switch(
X#ifdef REDO
X ch =
X#endif
X ynq()) {
X case 'q':
X break;
X case 'y':
X#ifdef REDO
X savech(ch);
X#endif
X obj = getobj("#", "name");
X if(obj) do_oname(obj);
X break;
X default:
X#ifdef REDO
X savech(ch);
X#endif
X obj = getobj(callable, "call");
X if(obj) docall(obj);
X }
X return 0;
X}
X
Xvoid
Xdocall(obj)
Xregister struct obj *obj;
X{
X char buf[BUFSZ];
X struct obj otemp;
X register char **str1;
X register char *str;
X boolean blank;
X
X otemp = *obj;
X otemp.quan = 1;
X otemp.onamelth = 0;
X if (otemp.corpsenm) { /* kludge, meaning it's sink water */
X pline("Call a stream of %s fluid: ",
X objects[otemp.otyp].oc_descr);
X } else
X pline("Call %s: ", an(xname(&otemp)));
X getlin(buf);
X clrlin();
X if(!*buf || *buf == '\033')
X return;
X
X /* clear old name */
X str1 = &(objects[obj->otyp].oc_uname);
X if(*str1) free((genericptr_t)*str1);
X
X /* uncalls item if all spaces */
X for (str = buf, blank = 1; *str; blank = (*str++ == ' '));
X if(blank) *buf = '\0';
X if (!*buf) {
X *str1 = NULL;
X return;
X }
X
X str = (char *) alloc((unsigned)strlen(buf)+1);
X Strcpy(str,buf);
X *str1 = str;
X}
X
X#endif /*OVLB*/
X#ifdef OVL0
X
Xstatic const char *ghostnames[] = {
X /* these names should have length < PL_NSIZ */
X /* Capitalize the names for aesthetics -dgk */
X "Adri", "Andries", "Andreas", "Bert", "David", "Dirk", "Emile",
X "Frans", "Fred", "Greg", "Hether", "Jay", "John", "Jon", "Karnov",
X "Kay", "Kenny", "Kevin", "Maud", "Michiel", "Mike", "Peter", "Robert",
X "Ron", "Tom", "Wilmar", "Nick Danger", "Phoenix", "Havok",
X "Stephan", "Lance Braccus", "Shadowhawk"
X};
X
Xchar *
Xx_monnam(mtmp, vb)
Xregister struct monst *mtmp;
Xint vb;
X{
X#ifdef LINT /* static char buf[BUFSZ]; */
X char buf[BUFSZ];
X#else
X static char buf[BUFSZ];
X#endif
X boolean isinvis = (mtmp->minvis && mtmp->data != &mons[PM_STALKER]
X && mtmp->data != &mons[PM_GHOST]);
X
X buf[0] = '\0';
X#if defined(ALTARS) && defined(THEOLOGY)
X if(mtmp->ispriest) return(priestname(mtmp));
X#endif
X if(mtmp->isshk) {
X Strcpy(buf, shkname(mtmp));
X if (mtmp->data == &mons[PM_SHOPKEEPER] && !mtmp->minvis)
X return(buf);
X /* For normal shopkeepers, just 'Asidonhopo'.
X * For unusual ones, 'Asidonhopo the invisible shopkeeper'
X * or 'Asidonhopo the blue dragon'.
X */
X Strcat(buf, " ");
X } else if(mtmp->mnamelth && !vb) {
X if(isinvis) {
X Strcpy(buf, "the invisible ");
X Strcat(buf, NAME(mtmp));
X } else
X Strcpy(buf, NAME(mtmp));
X return(buf);
X }
X
X switch(mtmp->data->mlet) {
X case S_GHOST:
X { register const char *gn = (const char *) mtmp->mextra;
X if(!*gn) { /* might also look in scorefile */
X gn = ghostnames[rn2(SIZE(ghostnames))];
X Strcpy((char *) mtmp->mextra, !rn2(5) ? (const char *)plname : gn);
X }
X if (Hallucination) {
X Strcat(buf, "the ");
X Strcat(buf, rndmonnam());
X }
X else
X Sprintf(buf, "%s's ghost", (char *) mtmp->mextra);
X }
X break;
X default:
X if (mtmp->minvis)
X Strcat(buf, "the invisible ");
X else if (!type_is_pname(mtmp->data) || Hallucination
X || mtmp->data == &mons[PM_WIZARD_OF_YENDOR])
X Strcat(buf, "the ");
X Strcat(buf, Hallucination ? rndmonnam() : mtmp->data->mname);
X }
X if(vb && mtmp->mnamelth) {
X Strcat(buf, " called ");
X Strcat(buf, NAME(mtmp));
X }
X return(buf);
X}
X
X#endif /* OVL0 */
X#ifdef OVLB
X
Xchar *
Xlmonnam(mtmp)
Xregister struct monst *mtmp;
X{
X return(x_monnam(mtmp, 1));
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
Xchar *
Xmon_nam(mtmp)
Xregister struct monst *mtmp;
X{
X return(x_monnam(mtmp, 0));
X}
X
Xchar *
XMonnam(mtmp)
Xregister struct monst *mtmp;
X{
X register char *bp = mon_nam(mtmp);
X
X if('a' <= *bp && *bp <= 'z') *bp += ('A' - 'a');
X return(bp);
X}
X
X#endif /* OVL0 */
X#ifdef OVLB
X
Xchar *
Xa_monnam(mtmp,adj)
Xregister struct monst *mtmp;
Xregister const char *adj;
X{
X register char *bp = mon_nam(mtmp);
X#ifdef LINT /* static char buf[BUFSZ]; */
X char buf[BUFSZ];
X#else
X static char buf[BUFSZ];
X#endif
X
X if(!strncmp(bp, "the ", 4)) bp += 4;
X Sprintf(buf, "the %s %s", adj, bp);
X return(buf);
X}
X
X/* sometimes we don't want an article in front of definite names */
X
Xchar *
Xa2_monnam(mtmp,adj)
Xregister struct monst *mtmp;
Xregister const char *adj;
X{
X register char *bp = mon_nam(mtmp);
X#ifdef LINT /* static char buf[BUFSZ]; */
X char buf[BUFSZ];
X#else
X static char buf[BUFSZ];
X#endif
X
X if(!strncmp(bp, "the ", 4))
X Sprintf(buf, "the %s %s", adj, bp+4);
X else
X Sprintf(buf, "%s %s", adj, bp);
X return(buf);
X}
X
Xchar *
XAmonnam(mtmp, adj)
Xregister struct monst *mtmp;
Xregister const char *adj;
X{
X register char *bp = a_monnam(mtmp,adj);
X
X *bp = 'T';
X return(bp);
X}
X
Xchar *
XXmonnam(mtmp)
Xregister struct monst *mtmp;
X{
X register char *bp = Monnam(mtmp);
X
X if(!strncmp(bp, "The ", 4) && !type_is_pname(mtmp->data)) {
X if(index(vowels,*(bp+4))) {
X *((++bp)+1) = 'n';
X } else
X bp += 2;
X *bp = 'A';
X }
X return(bp);
X}
X
Xchar *
Xdefmonnam(mtmp)
Xregister struct monst *mtmp;
X{
X register char *bp = Xmonnam(mtmp);
X
X if (!strncmp(bp,"A ",2) || !strncmp(bp,"An ",3)) *bp = 'a';
X return(bp);
X}
X
Xconst char *
Xrndmonnam() { /* Random name of monster type, if hallucinating */
X int name;
X
X do {
X name = rn2(PM_ARCHEOLOGIST);
X /* archeologist: first player class */
X } while(type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN));
X return(mons[name].mname);
X}
X
Xconst char *pronoun_pairs[][2] = {
X {"him", "her"}, {"Him", "Her"}, {"his", "her"}, {"His", "Her"},
X {"he", "she"}, {"He", "She"},
X {0, 0}
X};
X
Xchar *
Xself_pronoun(str, pronoun)
Xconst char *str;
Xconst char *pronoun;
X{
X static char NEARDATA buf[BUFSZ];
X register int i;
X
X for(i=0; pronoun_pairs[i][0]; i++) {
X if(!strncmp(pronoun, pronoun_pairs[i][0], 3)) {
X Sprintf(buf, str, pronoun_pairs[i][flags.female]);
X return buf;
X }
X }
X impossible("never heard of pronoun %s?", pronoun);
X Sprintf(buf, str, pronoun_pairs[i][0]);
X return buf;
X}
X
X#ifdef REINCARNATION
Xconst char *
Xroguename() /* Name of a Rogue player */
X{
X char *i, *opts;
X
X if(opts = getenv("ROGUEOPTS")) {
X for(i=opts; *i; i++)
X if (!strncmp("name=",i,5)) {
X char *j;
X if (j=index(i+5,','))
X *j = (char)0;
X return i+5;
X }
X }
X return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold")
X : "Glenn Wichman";
X}
X#endif
X
X#endif /* OVLB */
END_OF_FILE
if test 13564 -ne `wc -c <'src/do_name.c'`; then
echo shar: \"'src/do_name.c'\" unpacked with wrong size!
fi
# end of 'src/do_name.c'
fi
if test -f 'src/sp_lev.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/sp_lev.c'\"
else
echo shar: Extracting \"'src/sp_lev.c'\" \(13593 characters\)
sed "s/^X//" >'src/sp_lev.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)sp_lev.c 3.0 89/01/11
X/* Copyright (c) 1989 by Jean-Christophe Collet */
X/* NetHack may be freely redistributed. See license for details. */
X
X/*
X * This file contains the various functions that are related to the special
X * levels.
X * It contains also the special level loader.
X *
X */
X
X#include "hack.h"
X
X#ifdef STRONGHOLD
X#include "sp_lev.h"
X
X#if defined(MACOS) || (defined(MSDOS) && !defined(AMIGA))
X# define RDMODE "rb"
X#else
X# define RDMODE "r"
X#endif
X
X#define LEFT 1
X#define CENTER 2
X#define RIGHT 3
X#define TOP 1
X#define BOTTOM 3
X
Xstatic walk NEARDATA walklist[50];
Xextern int x_maze_max, y_maze_max;
X
X#ifdef MACOS
Xchar **Map;
X#else
Xstatic char Map[COLNO][ROWNO];
X#endif
Xstatic char robjects[10], rloc_x[10], rloc_y[10], rmonst[10],
X ralign[3] = { A_CHAOS, A_NEUTRAL, A_LAW };
Xstatic xchar NEARDATA xstart, NEARDATA ystart, NEARDATA xsize, NEARDATA ysize;
X
Xstatic void FDECL(make_walls_nondiggable, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
Xstatic int NDECL(rnddoor);
Xstatic int NDECL(rndtrap);
Xstatic void FDECL(get_location, (schar *,schar *));
Xstatic void FDECL(shuffle, (char *,XCHAR_P));
Xstatic void FDECL(shuffle2, (char *,char *,XCHAR_P));
Xstatic boolean FDECL(load_rooms, (FILE *));
Xstatic void FDECL(maze1xy, (coord *));
Xstatic boolean FDECL(load_maze, (FILE *));
X
X/*
X * Make walls of the area (x1, y1, x2, y2) non diggable
X */
X
Xstatic void
Xmake_walls_nondiggable(x1,y1,x2,y2)
Xxchar x1, y1, x2, y2;
X{
X register xchar x, y;
X
X for(y = y1; y <= y2; y++)
X for(x = x1; x <= x2; x++)
X if(IS_WALL(levl[x][y].typ))
X levl[x][y].diggable |= W_NONDIGGABLE;
X}
X
X/*
X * Choose randomly the state (nodoor, open, closed or locked) for a door
X */
X
Xstatic int
Xrnddoor()
X{
X int i;
X
X i = 1 << rn2(5);
X i >>= 1;
X return i;
X}
X
X/*
X * Select a random trap
X */
X
Xstatic int
Xrndtrap()
X{
X return(rnd(TRAPNUM-1));
X}
X
X/*
X * Coordinates in special level files are handled specially:
X *
X * if x or y is -11, we generate a random coordinate.
X * if x or y is between -1 and -10, we read one from the corresponding
X * register (x0, x1, ... x9).
X * if x or y is nonnegative, we convert it from relative to the local map
X * to global coordinates.
X */
X
Xstatic void
Xget_location(x, y)
Xschar *x, *y;
X{
X int cpt = 0;
X
X if (*x >= 0) { /* normal locations */
X *x += xstart;
X *y += ystart;
X } else if (*x > -11) { /* special locations */
X *y = ystart + rloc_y[ - *y - 1];
X *x = xstart + rloc_x[ - *x - 1];
X } else { /* random location */
X do {
X *x = xstart + rn2((int)xsize);
X *y = ystart + rn2((int)ysize);
X } while (cpt < 100 &&
X levl[*x][*y].typ != ROOM &&
X levl[*x][*y].typ != CORR);
X if(cpt >= 100)
X panic("get_location: can't find a place!");
X }
X
X if (*x < 0 || *x > x_maze_max || *y < 0 || *y > y_maze_max) {
X impossible("get_location: (%d,%d) out of bounds", *x, *y);
X *x = x_maze_max; *y = y_maze_max;
X }
X}
X
X/*
X * Shuffle the registers for locations, objects or monsters
X */
X
Xstatic void
Xshuffle(list, n)
Xchar list[];
Xxchar n;
X{
X int i, j;
X char k;
X
X for(i = n-1; i; i--) {
X j = rn2(i);
X
X k = list[j];
X list[j] = list[i];
X list[i] = k;
X }
X}
X
X/*
X * Shuffle two arrays in the same order (for rloc_x & rloc_y)
X */
X
Xstatic void
Xshuffle2(list1, list2, n)
Xchar list1[], list2[];
Xxchar n;
X{
X int i, j;
X char k1, k2;
X
X for(i = n-1; i; i--) {
X j = rn2(i);
X
X k1 = list1[j];
X k2 = list2[j];
X
X list1[j] = list1[i];
X list2[j] = list2[i];
X
X list1[i] = k1;
X list2[i] = k2;
X }
X}
X
X/*
X * NOT YET IMPLEMENTED!!!
X */
X
Xstatic boolean
Xload_rooms(fd)
XFILE *fd;
X{
X return FALSE;
X}
X
X/*
X * Select a random coordinate in the maze.
X *
X * We want a place not 'touched' by the loader. That is, a place in
X * the maze outside every part of the special level.
X */
X
Xstatic void
Xmaze1xy(m)
Xcoord *m;
X{
X do {
X m->x = rn1(x_maze_max - 3, 3);
X m->y = rn1(y_maze_max - 3, 3);
X } while (!(m->x % 2) || !(m->y % 2) || Map[m->x][m->y]);
X}
X
X/*
X * The Big Thing: special maze loader
X *
X * Could be cleaner, but it works.
X */
X
Xstatic boolean
Xload_maze(fd)
XFILE *fd;
X{
X xchar x, y, n, typ;
X char c;
X
X xchar numpart = 0, nwalk = 0;
X uchar halign, valign;
X
X int xi, yi, dir;
X coord mm;
X int mapcount, mapcountmax, mapfact;
X
X region tmpregion;
X door tmpdoor;
X trap tmptrap;
X monster tmpmons;
X object tmpobj;
X drawbridge tmpdb;
X walk tmpwalk;
X digpos tmpdig;
X lad tmplad;
X#ifdef ALTARS
X altar tmpaltar;
X#endif
X
X /* shuffle alignments */
X shuffle(ralign,3);
X
X /* Initialize map */
X xupstair = yupstair = xdnstair = ydnstair = doorindex = 0;
X for(x = 2; x <= x_maze_max; x++)
X for(y = 2; y <= y_maze_max; y++) {
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = STONE;
X#else
X levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
X#endif
X Map[x][y] = 0;
X }
X
X /* Start reading the file */
X numpart = fgetc(fd); /* Number of parts */
X if (!numpart || numpart > 9)
X panic("load_maze error: numpart = %d", (int) numpart);
X
X while (numpart--) {
X halign = fgetc(fd); /* Horizontal alignment */
X valign = fgetc(fd); /* Vertical alignment */
X xsize = fgetc(fd); /* size in X */
X ysize = fgetc(fd); /* size in Y */
X
X switch((int) halign) {
X case LEFT: xstart = 3; break;
X case CENTER: xstart = 2+((x_maze_max-2-xsize)/2); break;
X case RIGHT: xstart = x_maze_max-xsize-1; break;
X }
X switch((int) valign) {
X case TOP: ystart = 3; break;
X case CENTER: ystart = 2+((y_maze_max-2-ysize)/2); break;
X case BOTTOM: ystart = y_maze_max-ysize-1; break;
X }
X if (!(xstart % 2)) xstart++;
X if (!(ystart % 2)) ystart++;
X
X /* Load the map */
X for(y = ystart; y < ystart+ysize; y++)
X for(x = xstart; x < xstart+xsize; x++) {
X levl[x][y].typ = fgetc(fd);
X initsym(x,y);
X /* secret doors default closed */
X if (levl[x][y].typ == SDOOR)
X levl[x][y].doormask = D_CLOSED;
X Map[x][y] = 1;
X }
X
X n = fgetc(fd); /* Random objects */
X if(n) {
X (void) fread((genericptr_t)robjects, 1, (int) n, fd);
X shuffle(robjects, n);
X }
X
X n = fgetc(fd); /* Random locations */
X if(n) {
X (void) fread((genericptr_t)rloc_x, 1, (int) n, fd);
X (void) fread((genericptr_t)rloc_y, 1, (int) n, fd);
X shuffle2(rloc_x, rloc_y, n);
X }
X
X n = fgetc(fd); /* Random monsters */
X if(n) {
X (void) fread((genericptr_t)rmonst, 1, (int) n, fd);
X shuffle(rmonst, n);
X }
X
X n = fgetc(fd); /* Number of subrooms */
X while(n--) {
X (void) fread((genericptr_t)&tmpregion, sizeof(tmpregion), 1, fd);
X if (nroom >= MAXNROFROOMS) continue;
X
X get_location(&tmpregion.x1, &tmpregion.y1);
X get_location(&tmpregion.x2, &tmpregion.y2);
X
X rooms[nroom].lx = tmpregion.x1;
X rooms[nroom].ly = tmpregion.y1;
X rooms[nroom].hx = tmpregion.x2;
X rooms[nroom].hy = tmpregion.y2;
X rooms[nroom].rtype = tmpregion.rtype;
X rooms[nroom].rlit = tmpregion.rlit;
X if (tmpregion.rlit == 1)
X for(x = rooms[nroom].lx-1; x <= rooms[nroom].hx+1; x++)
X for(y = rooms[nroom].ly-1; y <= rooms[nroom].hy+1; y++)
X levl[x][y].lit = 1;
X
X rooms[nroom].fdoor = rooms[nroom].doorct = 0;
X
X ++nroom;
X rooms[nroom].hx = -1;
X }
X
X n = fgetc(fd); /* Number of doors */
X while(n--) {
X struct mkroom *croom = &rooms[0], *broom;
X int tmp;
X
X (void) fread((genericptr_t)&tmpdoor, sizeof(tmpdoor), 1, fd);
X
X x = tmpdoor.x; y = tmpdoor.y;
X typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
X
X get_location(&x, &y);
X levl[x][y].doormask = typ;
X mnewsym(x,y);
X
X /* Now the complicated part, list it with each subroom */
X /* The dog move and mail daemon routines use this */
X while(croom->hx >= 0 && doorindex < DOORMAX) {
X if(croom->hx >= x-1 && croom->lx <= x+1 &&
X croom->hy >= y-1 && croom->ly <= y+1) {
X /* Found it */
X croom->doorct++;
X
X /* Append or insert into doors[] */
X broom = croom+1;
X if(broom->hx < 0) tmp = doorindex;
X else
X for(tmp = doorindex; tmp > broom->fdoor; tmp--)
X doors[tmp] = doors[tmp-1];
X
X doors[tmp].x = x;
X doors[tmp].y = y;
X doorindex++;
X
X for( ; broom->hx >= 0; broom++) broom->fdoor++;
X }
X croom++;
X }
X }
X
X n = fgetc(fd); /* Number of traps */
X while(n--) {
X (void) fread((genericptr_t)&tmptrap, sizeof(tmptrap), 1, fd);
X
X x = tmptrap.x; y = tmptrap.y;
X typ = (tmptrap.type == -1 ? rndtrap() : tmptrap.type);
X
X get_location(&x, &y);
X (void) maketrap(x, y, typ);
X }
X
X n = fgetc(fd); /* Number of monsters */
X while(n--) {
X (void) fread((genericptr_t)&tmpmons, sizeof(tmpmons), 1, fd);
X
X x = tmpmons.x; y = tmpmons.y;
X get_location(&x, &y);
X
X if (tmpmons.class >= 0)
X c = tmpmons.class;
X else if (tmpmons.class > -11)
X c = rmonst[-tmpmons.class - 1];
X else
X c = 0;
X
X if (!c)
X (void) makemon((struct permonst *) 0, x, y);
X else if (tmpmons.id != -1)
X (void) makemon(&mons[tmpmons.id], x, y);
X else
X (void) makemon(mkclass(c), x, y);
X }
X
X n = fgetc(fd); /* Number of objects */
X while(n--) {
X (void) fread((genericptr_t) &tmpobj, sizeof(object),1, fd);
X
X x = tmpobj.x; y = tmpobj.y;
X get_location(&x, &y);
X
X if (tmpobj.class >= 0)
X c = tmpobj.class;
X else if (tmpobj.class > -11)
X c = robjects[-tmpobj.class - 1];
X else
X c = 0;
X
X if (!c)
X (void) mkobj_at(0, x, y, TRUE);
X else if (tmpobj.id != -1)
X (void) mksobj_at(tmpobj.id, x, y);
X else
X (void) mkobj_at(c, x, y, TRUE);
X }
X
X n = fgetc(fd); /* Number of drawbridges */
X while(n--) {
X (void) fread((genericptr_t)&tmpdb, sizeof(tmpdb), 1, fd);
X
X x = tmpdb.x; y = tmpdb.y;
X get_location(&x, &y);
X
X if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.open))
X impossible("Cannot create drawbridge.");
X }
X
X n = fgetc(fd); /* Number of mazewalks */
X while(n--) {
X (void) fread((genericptr_t)&tmpwalk, sizeof(tmpwalk), 1, fd);
X
X get_location(&tmpwalk.x, &tmpwalk.y);
X
X walklist[nwalk++] = tmpwalk;
X }
X
X n = fgetc(fd); /* Number of non_diggables */
X while(n--) {
X (void) fread((genericptr_t)&tmpdig, sizeof(tmpdig), 1, fd);
X
X get_location(&tmpdig.x1, &tmpdig.y1);
X get_location(&tmpdig.x2, &tmpdig.y2);
X
X make_walls_nondiggable(tmpdig.x1, tmpdig.y1,
X tmpdig.x2, tmpdig.y2);
X }
X
X n = fgetc(fd); /* Number of ladders */
X while(n--) {
X (void) fread((genericptr_t)&tmplad, sizeof(tmplad), 1, fd);
X
X x = tmplad.x; y = tmplad.y;
X get_location(&x, &y);
X
X levl[x][y].typ = LADDER;
X if (tmplad.up == 1) {
X xupladder = x; yupladder = y;
X levl[x][y].ladder = LA_UP;
X } else {
X xdnladder = x; ydnladder = y;
X levl[x][y].ladder = LA_DOWN;
X }
X }
X
X#ifdef ALTARS
X n = fgetc(fd); /* Number of altars */
X while(n--) {
X (void) fread((genericptr_t)&tmpaltar, sizeof(tmpaltar), 1, fd);
X
X x = tmpaltar.x; y = tmpaltar.y;
X get_location(&x, &y);
X
X typ = tmpaltar.align == -11 ? rn2(3) :
X (tmpaltar.align < 0 ? ralign[-tmpaltar.align-1] :
X tmpaltar.align);
X if (tmpaltar.shrine)
X typ |= A_SHRINE;
X
X levl[x][y].typ = ALTAR;
X levl[x][y].altarmask = typ;
X }
X#endif /* ALTARS /**/
X }
X
X while(nwalk--) {
X xi = walklist[nwalk].x;
X yi = walklist[nwalk].y;
X dir = walklist[nwalk].dir;
X
X move(&xi, &yi, dir);
X x = xi;
X y = yi;
X
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = CORR;
X#else
X levl[x][y].typ = ROOM;
X#endif
X
X /*
X * We must be sure that the parity of the coordinates for
X * walkfrom() is odd. But we must also take into account
X * what direction was chosen.
X */
X if(!(x % 2))
X if (dir == W_EAST)
X x++;
X else
X x--;
X
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = CORR;
X#else
X levl[x][y].typ = ROOM;
X#endif
X
X if (!(y % 2))
X if (dir == W_SOUTH)
X y++;
X else
X y--;
X
X walkfrom(x, y);
X }
X wallification(2, 2, x_maze_max, y_maze_max, TRUE);
X
X /*
X * If there's a significant portion of maze unused by the special level,
X * we don't want it empty.
X *
X * Makes the number of traps, monsters, etc. proportional
X * to the size of the maze.
X */
X mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
X
X for(x = 2; x < x_maze_max; x++)
X for(y = 2; y < y_maze_max; y++)
X if(Map[x][y]) mapcount--;
X
X if (mapcount > (int) (mapcountmax / 10)) {
X mapfact = (int) ((mapcount * 100L) / mapcountmax);
X for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
X maze1xy(&mm);
X (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y, TRUE);
X }
X for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
X maze1xy(&mm);
X (void) mksobj_at(BOULDER, mm.x, mm.y);
X }
X maze1xy(&mm);
X (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
X for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
X maze1xy(&mm);
X (void) makemon((struct permonst *) 0, mm.x, mm.y);
X }
X for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
X maze1xy(&mm);
X mkgold(0L,mm.x,mm.y);
X }
X for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
X maze1xy(&mm);
X (void) maketrap(mm.x, mm.y,rndtrap());
X }
X }
X return TRUE;
X}
X
X/*
X * General loader
X */
X
Xboolean
Xload_special(name)
Xconst char *name;
X{
X FILE *fd;
X boolean result;
X schar c;
X
X#ifdef OS2_CODEVIEW
X {
X char tmp[PATHLEN];
X
X Strcpy(tmp,hackdir);
X append_slash(tmp);
X Strcat(tmp,name);
X fd = fopen(tmp, RDMODE);
X#else
X fd = fopen(name, RDMODE);
X# ifdef MACOS
X if (!fd)
X fd = openFile(name, RDMODE);
X# endif
X#endif
X#ifdef OS2_CODEVIEW
X }
X#endif
X if (!fd) return FALSE;
X
X if ((c = fgetc(fd)) == EOF) {
X (void)fclose(fd);
X return FALSE;
X }
X
X switch (c) {
X case 1: /* Alas, this is not yet implemented. */
X result = load_rooms(fd);
X break;
X case 2: /* But this is implemented :-) */
X result = load_maze(fd);
X break;
X default: /* ??? */
X result = FALSE;
X }
X (void)fclose(fd);
X return result;
X}
X#endif /* STRONGHOLD /**/
END_OF_FILE
if test 13593 -ne `wc -c <'src/sp_lev.c'`; then
echo shar: \"'src/sp_lev.c'\" unpacked with wrong size!
fi
# end of 'src/sp_lev.c'
fi
echo shar: End of archive 42 \(of 56\).
cp /dev/null ark42isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 56 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
echo Building monst.c from monst.c1 and monst.c2
cat src/monst.c1 src/monst.c2 > src/monst.c
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0