home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume7
/
nethack3
/
part27
< prev
next >
Wrap
Text File
|
1989-07-31
|
56KB
|
2,428 lines
Path: uunet!zephyr.ens.tek.com!tektronix!tekgen!tekred!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v07i082: NetHack3 - display oriented dungeons & dragons (Ver. 3.0), Part27/38
Message-ID: <4339@tekred.CNA.TEK.COM>
Date: 24 Jul 89 19:05:57 GMT
Sender: nobody@tekred.CNA.TEK.COM
Lines: 2417
Approved: billr@saab.CNA.TEK.COM
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 82
Archive-name: NetHack3/Part27
#! /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 27 (of 38)."
# Contents: others/pcmain.c src/mkmaze.c src/sp_lev.c src/unixmain.c
# Wrapped by billr@saab on Sun Jul 23 21:33:10 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'others/pcmain.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'others/pcmain.c'\"
else
echo shar: Extracting \"'others/pcmain.c'\" \(12406 characters\)
sed "s/^X//" >'others/pcmain.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)pcmain.c 3.0 88/11/23
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X/* main.c - (PC, TOS and AMIGA) version */
X
X#ifndef TOS
X#include <signal.h>
X#else
X#define msmsg cprintf
X#endif
X#include "hack.h"
X
Xchar orgdir[PATHLEN];
X
Xextern struct permonst mons[NUMMONS];
Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ];
X
Xint (*afternmv)(), (*occupation)();
Xstatic void moveloop(); /* a helper function for MSC optimizer */
X
X#if defined(DGK) && !defined(TOS)
Xstruct finfo zfinfo = ZFINFO;
Xint i;
X#endif /* DGK && !TOS */
X
Xchar SAVEF[FILENAME];
Xchar *hname = "NetHack"; /* used for syntax messages */
Xchar obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
Xint hackpid; /* not used anymore, but kept in for save files */
X
Xextern char *nomovemsg;
Xextern long wailmsg;
X#ifdef __TURBOC__ /* tell Turbo C to make a bigger stack */
Xextern unsigned _stklen = 0x2000; /* 8K */
Xextern unsigned char _osmajor;
X#endif
X
X#ifdef TOS
X#define OMASK 0x8000
X#else
X#define OMASK 0
X#endif
X
Xint
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X extern int x_maze_max, y_maze_max;
X register int fd;
X register char *dir;
X
X#ifdef AMIGA
X /*
X * Make sure screen IO is initialized before anything happens.
X */
X gettty();
X startup();
X#else /* AMIGA */
X /* Save current directory and make sure it gets restored when
X * the game is exited.
X */
X int (*funcp)();
X
X# ifdef __TURBOC__
X if (_osmajor >= 3) hname = argv[0]; /* DOS 3.0+ */
X# endif
X if (getcwd(orgdir, sizeof orgdir) == NULL) {
X xputs("NetHack: current directory path too long\n");
X _exit(1);
X }
X funcp = exit; /* Kludge to get around LINT_ARGS of signal.
X * This will produce a compiler warning, but that's OK.
X */
X# ifndef TOS
X signal(SIGINT, (SIG_RET_TYPE) funcp); /* restore original directory */
X# endif
X#endif /* AMIGA */
X
X /* Set the default values of the presentation characters */
X memcpy((genericptr_t) &showsyms, (genericptr_t) &defsyms, sizeof(struct symbols));
X if ((dir = getenv("HACKDIR")) != NULL) {
X Strcpy(hackdir, dir);
X#ifdef CHDIR
X chdirx (dir, 1);
X#endif
X }
X#if defined(DGK) && !defined(TOS)
X /* zero "fileinfo" array to prevent crashes on level change */
X for (i = 0 ; i <= MAXLEVEL + 1; i++)
X fileinfo[i] = zfinfo;
X#endif /* DGK && !TOS */
X initoptions();
X if (!hackdir[0])
X Strcpy(hackdir, orgdir);
X#ifdef TOS
X if(argc > 1 && !strncmp(argv[1], "-D", 2)) {
X#else
X if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
X#endif
X argc--;
X argv++;
X dir = argv[0]+2;
X if(*dir == '=' || *dir == ':') dir++;
X if(!*dir && argc > 1) {
X argc--;
X argv++;
X dir = argv[0];
X }
X if(!*dir)
X error("Flag -d must be followed by a directory name.");
X Strcpy(hackdir, dir);
X }
X
X /*
X * Now we know the directory containing 'record' and
X * may do a prscore().
X */
X#ifdef TOS
X if(argc > 1 && !strncmp(argv[1], "-S", 2)) {
X#else
X if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
X#endif
X#ifdef CHDIR
X chdirx(hackdir,0);
X#endif
X prscore(argc, argv);
X exit(0);
X }
X
X#ifndef AMIGA
X /*
X * It seems he really wants to play.
X * Remember tty modes, to be restored on exit.
X */
X gettty();
X setbuf(stdout,obuf);
X startup();
X#endif
X setrandom();
X cls();
X u.uhp = 1; /* prevent RIP on early quits */
X u.ux = FAR; /* prevent nscr() */
X#ifndef TOS
X /*
X * We cannot do chdir earlier, otherwise gethdate will fail.
X */
X#ifdef CHDIR
X chdirx(hackdir,1);
X#endif
X#endif
X /*
X * Process options.
X */
X while(argc > 1 && argv[1][0] == '-'){
X argv++;
X argc--;
X switch(argv[0][1]){
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X#ifndef TOS
X case 'D':
X#endif /* TOS */
X case 'X':
X# ifdef WIZARD
X /* Must have "name" set correctly by NETHACK.CNF,
X * NETHACKOPTIONS, or -U
X * before this flag to enter wizard mode. */
X if(!strcmp(plname, WIZARD))
X wizard = TRUE;
X# endif
X# if defined(WIZARD) && defined(EXPLORE_MODE)
X else
X# endif
X# ifdef EXPLORE_MODE
X discover = TRUE;
X# endif
X break;
X#endif
X#ifdef NEWS
X case 'N':
X flags.nonews = TRUE;
X break;
X#endif
X case 'U':
X if(argv[0][2])
X (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
X else if(argc > 1) {
X argc--;
X argv++;
X (void) strncpy(plname, argv[0], sizeof(plname)-1);
X } else
X Printf("Player name expected after -U\n");
X break;
X#ifdef DGK
X /* Person does not want to use a ram disk
X */
X case 'R':
X ramdisk = FALSE;
X break;
X#endif
X case 'C': /* character role is next character */
X /* allow -T for Tourist, etc. */
X (void) strncpy(pl_character, argv[0]+2,
X sizeof(pl_character)-1);
X default:
X Printf("Unknown option: %s\n", *argv);
X }
X }
X
X#ifdef DGK
X set_lock_and_bones();
X copybones(FROMPERM);
X#endif
X#ifdef WIZARD
X if (wizard)
X Strcpy(plname, "wizard");
X else
X#endif
X if (!*plname)
X askname();
X plnamesuffix(); /* strip suffix from name; calls askname() */
X /* again if suffix was whole name */
X /* accepts any suffix */
X#ifndef DGK
X Strcpy(lock,plname);
X Strcat(lock,".99");
X#endif
X start_screen();
X
X /*
X * Initialisation of the boundaries of the mazes
X * Both boundaries have to be even.
X */
X
X x_maze_max = COLNO-1;
X if (x_maze_max % 2)
X x_maze_max--;
X y_maze_max = ROWNO-1;
X if (y_maze_max % 2)
X y_maze_max--;
X
X /* initialize static monster strength array */
X init_monstr();
X
X#ifdef AMIGA
X (void) strncat(SAVEF, plname, 31-4);
X#else
X (void) strncat(SAVEF, plname, 8);
X#endif
X Strcat(SAVEF, ".sav");
X cls();
X if (
X#ifdef DGK
X saveDiskPrompt(1) &&
X#endif /* DGK */
X ((fd = open(SAVEF, OMASK)) >= 0) &&
X (uptodate(fd) || !unlink(SAVEF))) {
X#ifndef TOS
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X pline("Restoring old save file...");
X (void) fflush(stdout);
X if(!dorecover(fd))
X goto not_recovered;
X pline("Hello %s, welcome to NetHack!", plname);
X /* get shopkeeper set properly if restore is in shop */
X (void) inshop();
X#ifdef EXPLORE_MODE
X if (discover) {
X You("are in non-scoring discovery mode.");
X pline("Do you want to keep the save file? ");
X if(yn() == 'n')
X (void) unlink(SAVEF);
X }
X#endif
X flags.move = 0;
X } else {
Xnot_recovered:
X#ifdef DGK
X gameDiskPrompt();
X#endif
X fobj = fcobj = invent = 0;
X fmon = fallen_down = 0;
X ftrap = 0;
X fgold = 0;
X flags.ident = 1;
X init_objects();
X u_init();
X#ifndef TOS
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X mklev();
X u.ux = xupstair;
X u.uy = yupstair;
X (void) inshop();
X setsee();
X flags.botlx = 1;
X /* Fix bug with dog not being made because a monster
X * was on the level 1 staircase
X */
X if(levl[u.ux][u.uy].mmask) mnexto(m_at(u.ux, u.uy));
X (void) makedog();
X seemons();
X#ifdef NEWS
X if(flags.nonews || !readnews())
X /* after reading news we did docrt() already */
X#endif
X docrt();
X
X /* give welcome message before pickup messages */
X pline("Hello %s, welcome to NetHack!", plname);
X set_wear();
X pickup(1);
X read_engr_at(u.ux,u.uy);
X flags.move = 0;
X }
X flags.moonphase = phase_of_the_moon();
X if(flags.moonphase == FULL_MOON) {
X You("are lucky! Full moon tonight.");
X if(!u.uluck) change_luck(1);
X } else if(flags.moonphase == NEW_MOON) {
X pline("Be careful! New moon tonight.");
X }
X
X initrack();
X#ifndef TOS
X (void) signal(SIGINT, SIG_IGN);
X#endif
X /* Help for Microsoft optimizer. Otherwise main is too large -dgk*/
X moveloop();
X return 0;
X}
X
Xstatic void
Xmoveloop()
X{
X char ch;
X int abort;
X
X for(;;) {
X if(flags.move) { /* actual time passed */
X
X#ifdef SOUNDS
X dosounds();
X#endif
X settrack();
X
X if(moves%2 == 0 ||
X (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
X movemon();
X#ifdef HARD
X if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
X#else
X if(!rn2(70))
X#endif
X (void) makemon((struct permonst *)0, 0, 0);
X }
X if(Glib) glibr();
X timeout();
X ++moves;
X#ifdef THEOLOGY
X if (u.ublesscnt) u.ublesscnt--;
X#endif
X#ifdef POLYSELF
X if(u.mtimedone)
X if(u.mh < 1) rehumanize();
X else
X#endif
X if(u.uhp < 1) {
X You("die...");
X done("died");
X }
X#ifdef POLYSELF
X if (u.mtimedone) {
X if (u.mh < u.mhmax) {
X if (Regeneration || !(moves%20)) {
X flags.botl = 1;
X u.mh++;
X }
X }
X }
X#endif
X if(u.uhp < u.uhpmax) {
X if(u.ulevel > 9) {
X int heal;
X
X if(HRegeneration || !(moves%3)) {
X flags.botl = 1;
X if (ACURR(A_CON) <= 12) heal = 1;
X else heal = rnd((int) ACURR(A_CON)-12);
X if (heal > u.ulevel-9) heal = u.ulevel-9;
X u.uhp += heal;
X if(u.uhp > u.uhpmax)
X u.uhp = u.uhpmax;
X }
X } else if(HRegeneration ||
X (!(moves%((MAXULEV+12)/(u.ulevel+2)+1)))) {
X flags.botl = 1;
X u.uhp++;
X }
X }
X#ifdef SPELLS
X if ((u.uen<u.uenmax) && (!(moves%(19-ACURR(A_INT)/2)))) {
X u.uen += rn2((int)ACURR(A_WIS)/5 + 1) + 1;
X if (u.uen > u.uenmax) u.uen = u.uenmax;
X flags.botl = 1;
X }
X#endif
X if(Teleportation && !rn2(85)) tele();
X#ifdef POLYSELF
X if(Polymorph && !rn2(100))
X polyself();
X if(u.ulycn >= 0 && !rn2(80 - (20 * night())))
X you_were();
X#endif
X if(Searching && multi >= 0) (void) dosearch0(1);
X gethungry();
X hatch_eggs();
X invault();
X amulet();
X#ifdef HARD
X if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3));
X if (u.udemigod) {
X
X u.udg_cnt--;
X if(u.udg_cnt <= 0) {
X
X intervene();
X u.udg_cnt = rn1(200, 50);
X }
X }
X#endif
X restore_attrib();
X }
X if(multi < 0) {
X if(!++multi){
X pline(nomovemsg ? nomovemsg :
X "You can move again.");
X nomovemsg = 0;
X if(afternmv) (*afternmv)();
X afternmv = 0;
X }
X }
X
X find_ac();
X if(!flags.mv || Blind)
X {
X seeobjs();
X seemons();
X seeglds();
X nscr();
X }
X if(flags.time) flags.botl = 1;
X
X if(flags.botl || flags.botlx) bot();
X
X flags.move = 1;
X
X if(multi >= 0 && occupation) {
X abort = 0;
X if (kbhit()) {
X if ((ch = Getchar()) == ABORT)
X abort++;
X#ifdef REDO
X else
X pushch(ch);
X#endif /* REDO */
X }
X if(abort || monster_nearby())
X stop_occupation();
X else if ((*occupation)() == 0)
X occupation = 0;
X if (!(++occtime % 7))
X (void) fflush(stdout);
X continue;
X }
X
X if((u.uhave_amulet || Clairvoyant) &&
X#ifdef ENDGAME
X dlevel != ENDLEVEL &&
X#endif
X !(moves%15) && !rn2(2)) do_vicinity_map();
X
X u.umoved = FALSE;
X if(multi > 0) {
X lookaround();
X if(!multi) { /* lookaround may clear multi */
X flags.move = 0;
X continue;
X }
X if(flags.mv) {
X if(multi < COLNO && !--multi)
X flags.mv = flags.run = 0;
X domove();
X } else {
X --multi;
X rhack(save_cm);
X }
X } else if(multi == 0) {
X#ifdef MAIL
X ckmailstatus();
X#endif
X rhack(NULL);
X }
X if(multi && multi%7 == 0)
X (void) fflush(stdout);
X }
X}
X
X/*
X * plname is filled either by an option (-U Player or -UPlayer) or
X * explicitly (by being the wizard) or by askname.
X * It may still contain a suffix denoting pl_character.
X */
Xvoid
Xaskname() {
X register int c, ct;
X
X Printf("\nWho are you? ");
X (void) fflush(stdout);
X ct = 0;
X while((c = Getchar()) != '\n') {
X if(c == EOF) error("End of input\n");
X /* some people get confused when their erase char is not ^H */
X if(c == '\b') {
X if(ct) {
X ct--;
X#ifdef MSDOS
X msmsg("\b \b");
X#endif
X }
X continue;
X }
X if(c != '-')
X if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
X if(ct < sizeof(plname)-1) {
X#ifdef MSDOS
X msmsg("%c", c);
X#endif
X plname[ct++] = c;
X }
X }
X plname[ct] = 0;
X if(ct == 0) askname();
X}
X
X/*VARARGS1*/
Xvoid
Ximpossible(s,x1,x2)
X register char *s, *x1, *x2;
X{
X pline(s,x1,x2);
X pline("Program in disorder - perhaps you'd better Quit.");
X}
X
X#ifdef CHDIR
Xvoid
Xchdirx(dir, wr)
Xchar *dir;
Xboolean wr;
X{
X
X if(dir && chdir(dir) < 0) {
X error("Cannot chdir to %s.", dir);
X }
X
X /* Change the default drive as well.
X */
X#ifndef AMIGA
X chdrive(dir);
X#endif
X
X /* warn the player if he cannot write the record file */
X /* perhaps we should also test whether . is writable */
X /* unfortunately the access systemcall is worthless */
X if(wr) {
X register int fd;
X
X if(dir == NULL)
X#ifdef AMIGA
X dir = "";
X#else
X dir = ".";
X#endif
X if((fd = open(RECORD, 2)) < 0) {
X#ifdef DGK
X char tmp[PATHLEN];
X
X Strcpy(tmp, dir);
X append_slash(tmp);
X msmsg("Warning: cannot write %s%s\n", tmp, RECORD);
X getreturn("to continue");
X#else
X Printf("Warning: cannot write %s/%s", dir, RECORD);
X getret();
X#endif
X } else
X (void) close(fd);
X }
X}
X#endif /* CHDIR /**/
X
Xvoid
Xstop_occupation()
X{
X if(occupation) {
X You("stop %s.", occtxt);
X occupation = 0;
X#ifdef REDO
X multi = 0;
X pushch(0);
X#endif
X }
X}
END_OF_FILE
if test 12406 -ne `wc -c <'others/pcmain.c'`; then
echo shar: \"'others/pcmain.c'\" unpacked with wrong size!
fi
# end of 'others/pcmain.c'
fi
if test -f 'src/mkmaze.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/mkmaze.c'\"
else
echo shar: Extracting \"'src/mkmaze.c'\" \(12398 characters\)
sed "s/^X//" >'src/mkmaze.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)mkmaze.c 3.0 88/10/25
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
Xextern int x_maze_max, y_maze_max;
X
X#if defined(WALLIFIED_MAZE) || defined(STRONGHOLD)
Xstatic int
Xiswall(x,y)
Xint x,y;
X{
X# ifndef WALLIFIED_MAZE
X if (x<0 || y<0 || x>COLNO-1 || y>ROWNO-1)
X# else
X if (x<0 || y<0 || x>COLNO || y>ROWNO)
X# endif
X return 0;
X return (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)
X || levl[x][y].typ == SDOOR);
X}
X
Xvoid
Xwallification(x1, y1, x2, y2, see)
Xint x1, y1, x2, y2;
Xboolean see;
X{
X char type;
X short x,y;
X register struct rm *room;
X
X if (x1 < 0) x1 = 0;
X if (x2 < x1) x2 = x1;
X if (x2 > COLNO-1) x2 = COLNO-1;
X if (x1 > x2) x1 = x2;
X if (y1 < 0) y1 = 0;
X if (y2 < y1) y2 = y1;
X if (y2 > COLNO-1) y2 = ROWNO-1;
X if (y1 > y2) y1 = y2;
X for(x = x1; x <= x2; x++)
X for(y = y1; y <= y2; y++) {
X room = &levl[x][y];
X type = room->typ;
X if (iswall(x,y)) {
X if (IS_DOOR(type)) {
X room->scrsym = DOOR_SYM;
X continue;
X } else
X if (iswall(x,y-1))
X if (iswall(x,y+1))
X if (iswall(x-1,y))
X if (iswall(x+1,y)) {
X room->scrsym = CRWALL_SYM; /* -+- */
X room->typ = CROSSWALL;
X } else {
X room->scrsym = TLWALL_SYM; /* -| */
X room->typ = TLWALL;
X }
X else
X if (iswall(x+1,y)) {
X room->scrsym = TRWALL_SYM; /* |- */
X room->typ = TRWALL;
X } else {
X room->typ = VWALL;
X#ifdef STRONGHOLD
X if (is_drawbridge_wall(x,y) >= 0)
X room->scrsym = DB_VWALL_SYM;
X else
X#endif
X room->scrsym = VWALL_SYM; /* | */
X }
X else
X if (iswall(x-1,y))
X if (iswall(x+1,y)) {
X room->scrsym = TUWALL_SYM; /* | */
X room->typ = TUWALL; /* -+- */
X } else {
X room->scrsym = BRCORN_SYM; /* | */
X room->typ = BRCORNER; /* -+ */
X }
X else
X if (iswall(x+1,y)) {
X room->scrsym = BLCORN_SYM; /* | */
X room->typ = BLCORNER; /* +- */
X } else {
X room->typ = VWALL;
X#ifdef STRONGHOLD
X if (is_drawbridge_wall(x,y) >= 0)
X room->scrsym = DB_VWALL_SYM;
X else
X#endif
X room->scrsym = VWALL_SYM; /* | */
X }
X else
X if (iswall(x,y+1))
X if (iswall(x-1,y))
X if (iswall(x+1,y)) {
X room->scrsym = TDWALL_SYM; /* -+- */
X room->typ = TDWALL; /* | */
X } else {
X room->scrsym = TRCORN_SYM; /* -+ */
X room->typ = TRCORNER; /* | */
X }
X else
X if (iswall(x+1,y)) {
X room->scrsym = TLCORN_SYM; /* +- */
X room->typ = TLCORNER; /* | */
X } else {
X room->typ = VWALL;
X#ifdef STRONGHOLD
X if (is_drawbridge_wall(x,y) >= 0)
X room->scrsym = DB_VWALL_SYM;
X else
X#endif
X room->scrsym = VWALL_SYM; /* | */
X }
X else {
X room->typ = HWALL;
X#ifdef STRONGHOLD
X if (is_drawbridge_wall(x,y) >= 0)
X room->scrsym = DB_HWALL_SYM;
X else
X#endif
X room->scrsym = HWALL_SYM;
X }
X if (type == SDOOR) room->typ = type;
X if (see) room->seen = 0;
X } else {
X switch(room->typ) {
X case STONE:
X room->scrsym = STONE_SYM;
X break;
X case CORR:
X room->scrsym = CORR_SYM;
X break;
X case ROOM:
X room->scrsym = ROOM_SYM;
X }
X if (see) room->seen = 0;
X }
X }
X}
X#endif /* WALLIFIED_MAZE /**/
X
Xstatic boolean
Xokay(x,y,dir)
Xint x,y;
Xregister int dir;
X{
X move(&x,&y,dir);
X move(&x,&y,dir);
X if(x<3 || y<3 || x>x_maze_max || y>y_maze_max || levl[x][y].typ != 0)
X return(FALSE);
X return(TRUE);
X}
X
Xstatic void
Xmaze0xy(cc) /* find random starting point for maze generation */
X coord *cc;
X{
X cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
X cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
X return;
X}
X
Xstatic const uchar tower[] = {
X MOAT, MOAT, MOAT, MOAT, MOAT, MOAT, MOAT,
X MOAT, MOAT, TLCORNER, HWALL, TRCORNER, MOAT, MOAT,
X MOAT, TLCORNER, BRCORNER, ROOM, BLCORNER, TRCORNER, MOAT,
X MOAT, VWALL, ROOM, ROOM, ROOM, VWALL, MOAT,
X MOAT, BLCORNER, TRCORNER, ROOM, TLCORNER, BRCORNER, MOAT,
X MOAT, MOAT, BLCORNER, HWALL, BRCORNER, MOAT, MOAT,
X MOAT, MOAT, MOAT, MOAT, MOAT, MOAT, MOAT,
X};
X
Xvoid
Xmakemaz()
X{
X int x,y;
X register int zx,zy;
X coord mm;
X int i;
X
X is_maze_lev = TRUE;
X#ifdef STRONGHOLD
X xdnladder = ydnladder = xupladder = yupladder = 0;
X if (dlevel == stronghold_level) {
X if (load_special("castle")) {
X xupstair = yupstair = 3;
X levl[xupstair][yupstair].scrsym = UP_SYM;
X levl[xupstair][yupstair].typ = STAIRS;
X return;
X }
X impossible("Cannot build the STRONGHOLD!");
X }
X if (dlevel == tower_level) {
X if (load_special("tower1")) {
X xupstair = yupstair = 3;
X levl[xupstair][yupstair].scrsym = UP_SYM;
X levl[xupstair][yupstair].typ = STAIRS;
X return;
X }
X impossible("Cannot build the TOWER!");
X }
X if (dlevel == tower_level+1) {
X if (load_special("tower2")) {
X xupstair = yupstair = 3;
X levl[xupstair][yupstair].scrsym = UP_SYM;
X levl[xupstair][yupstair].typ = STAIRS;
X return;
X }
X impossible("Cannot build the TOWER!");
X }
X if (dlevel == tower_level+2) {
X if (load_special("tower3")) {
X xupstair = yupstair = 3;
X levl[xupstair][yupstair].scrsym = UP_SYM;
X levl[xupstair][yupstair].typ = STAIRS;
X return;
X }
X impossible("Cannot build the TOWER!");
X }
X# ifdef ENDGAME
X if (dlevel == ENDLEVEL) { /* EndGame level */
X if (load_special("endgame")) {
X pline("Well done, mortal!");
X pline("But now thou must face the final Test...");
X pline("Prove thyself worthy or perish!");
X u.ux = x_maze_max - 1;
X u.uy = y_maze_max - 1;
X xupstair = yupstair = 0;
X return;
X }
X impossible("Cannot build the EndGame Level!");
X done("escaped");
X }
X# endif
X#endif
X#ifndef WALLIFIED_MAZE
X for(x = 2; x < x_maze_max; x++)
X for(y = 2; y < y_maze_max; y++)
X levl[x][y].typ = STONE;
X#else
X for(x = 2; x <= x_maze_max; x++)
X for(y = 2; y <= y_maze_max; y++)
X levl[x][y].typ = ((x % 2) && (y % 2)) ? STONE : HWALL;
X#endif
X
X /* make decoy wizard levels */
X if((dlevel == wiz_level) ||
X#ifdef STRONGHOLD
X (!rn2(3) && (dlevel > stronghold_level+1))) {
X#else
X (!rn2(3) && (dlevel > medusa_level+1))) {
X#endif
X
X register struct monst *mtmp;
X
X zx = x_maze_max / 2;
X zy = y_maze_max / 2;
X if (!(zx % 2)) zx++;
X if (!(zy % 2)) zy++;
X for(y = zy-3, i=0; y <= zy+3; y++)
X for(x = zx-3; x <= zx+3; x++)
X levl[x][y].typ = tower[i++];
X walkfrom(zx+4, zy);
X if(mtmp = makemon(&mons[PM_HELL_HOUND], zx+1, zy))
X mtmp->msleep = 1;
X (void) makemon(&mons[PM_KRAKEN], zx+2, zy+2);
X if (dlevel == wiz_level) {
X
X (void) mksobj_at(AMULET_OF_YENDOR, zx, zy);
X flags.made_amulet = 1;
X#ifndef STRONGHOLD
X if(mtmp = makemon(&mons[PM_VLAD_THE_IMPALER], zx-1, zy))
X mtmp->msleep = 1;
X#endif
X if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], zx, zy))
X mtmp->msleep = 1;
X } else {
X struct obj *ot;
X /* make a cheap plastic imitation */
X if (ot = mksobj_at(AMULET_OF_YENDOR, zx, zy))
X ot-> spe = -1;
X#ifndef STRONGHOLD
X if (mtmp = makemon(&mons[PM_VAMPIRE_LORD], zx-1, zy))
X mtmp->msleep = 1;
X#endif
X (void) makemon(&mons[dprince()], zx, zy);
X }
X /* they should wake up when we intrude */
X (void) maketrap(zx-1, zy, SQBRD);
X (void) maketrap(zx+1, zy, SQBRD);
X (void) maketrap(zx, zy-1, SQBRD);
X (void) maketrap(zx, zy+1, SQBRD);
X } else {
X maze0xy(&mm);
X zx = mm.x;
X zy = mm.y;
X walkfrom(zx,zy);
X#ifndef STRONGHOLD /* it's in the castle */
X# ifdef HARD /* only one wand of wishing created */
X if(!rn2(10) || (dlevel == medusa_level + 1))
X# endif
X (void) mksobj_at(WAN_WISHING, zx, zy);
X#endif
X (void) mksobj_at(BOULDER, zx, zy); /* put a boulder on top of it */
X }
X
X#ifdef WALLIFIED_MAZE
X wallification(2, 2, x_maze_max, y_maze_max, TRUE);
X#else
X for(x = 2; x < x_maze_max; x++)
X for(y = 2; y < y_maze_max; y++) {
X switch(levl[x][y].typ) {
X case STONE:
X levl[x][y].scrsym = STONE_SYM;
X break;
X case CORR:
X levl[x][y].scrsym = CORR_SYM;
X break;
X case ROOM:
X levl[x][y].scrsym = ROOM_SYM;
X break;
X case HWALL:
X levl[x][y].scrsym = HWALL_SYM;
X break;
X case VWALL:
X levl[x][y].scrsym = VWALL_SYM;
X break;
X case TLCORNER:
X levl[x][y].scrsym = TLCORN_SYM;
X break;
X case TRCORNER:
X levl[x][y].scrsym = TRCORN_SYM;
X break;
X case BLCORNER:
X levl[x][y].scrsym = BLCORN_SYM;
X break;
X case BRCORNER:
X levl[x][y].scrsym = BRCORN_SYM;
X break;
X }
X }
X#endif
X mazexy(&mm);
X levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = UP_SYM;
X levl[xupstair][yupstair].typ = STAIRS;
X xdnstair = ydnstair = 0;
X#ifdef STRONGHOLD
X if (dlevel < stronghold_level) {
X mazexy(&mm);
X levl[(xdnstair = mm.x)][(ydnstair = mm.y)].scrsym = DN_SYM;
X levl[xdnstair][ydnstair].typ = STAIRS;
X }
X#endif
X for(x = rn1(8,11); x; x--) {
X mazexy(&mm);
X (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y);
X }
X for(x = rn1(10,2); x; x--) {
X mazexy(&mm);
X (void) mksobj_at(BOULDER, mm.x, mm.y);
X }
X mazexy(&mm);
X (void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y);
X for(x = rn1(5,7); x; x--) {
X mazexy(&mm);
X (void) makemon((struct permonst *) 0, mm.x, mm.y);
X }
X for(x = rn1(6,7); x; x--) {
X mazexy(&mm);
X mkgold(0L,mm.x,mm.y);
X }
X for(x = rn1(6,7); x; x--)
X mktrap(0,1,(struct mkroom *) 0);
X}
X
X#ifdef MSDOS
X/* Make the mazewalk iterative by faking a stack. This is needed to
X * ensure the mazewalk is successful in the limited stack space of
X * the program. This iterative version uses the mimumum amount of stack
X * that is totally safe.
X */
Xvoid
Xwalkfrom(x,y)
Xint x,y;
X{
X#define CELLS (ROWNO * COLNO) / 4 /* a maze cell is 4 squares */
X char mazex[CELLS + 1], mazey[CELLS + 1]; /* char's are OK */
X int q, a, dir, pos;
X int dirs[4];
X
X pos = 1;
X mazex[pos] = (char) x;
X mazey[pos] = (char) y;
X while (pos) {
X x = (int) mazex[pos];
X y = (int) mazey[pos];
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = CORR;
X#else
X levl[x][y].typ = ROOM;
X#endif
X q = 0;
X for (a = 0; a < 4; a++)
X if(okay(x, y, a)) dirs[q++]= a;
X if (!q)
X pos--;
X else {
X dir = dirs[rn2(q)];
X move(&x, &y, dir);
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = CORR;
X#else
X levl[x][y].typ = ROOM;
X#endif
X move(&x, &y, dir);
X pos++;
X if (pos > CELLS)
X panic("Overflow in walkfrom");
X mazex[pos] = (char) x;
X mazey[pos] = (char) y;
X }
X }
X}
X#else
X
Xvoid
Xwalkfrom(x,y) int x,y; {
Xregister int q,a,dir;
Xint dirs[4];
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = CORR;
X#else
X levl[x][y].typ = ROOM;
X#endif
X while(1) {
X q = 0;
X for(a = 0; a < 4; a++)
X if(okay(x,y,a)) dirs[q++]= a;
X if(!q) return;
X dir = dirs[rn2(q)];
X move(&x,&y,dir);
X#ifndef WALLIFIED_MAZE
X levl[x][y].typ = CORR;
X#else
X levl[x][y].typ = ROOM;
X#endif
X move(&x,&y,dir);
X walkfrom(x,y);
X }
X}
X#endif /* MSDOS */
X
Xvoid
Xmove(x,y,dir)
Xregister int *x, *y;
Xregister int dir;
X{
X switch(dir){
X case 0: --(*y); break;
X case 1: (*x)++; break;
X case 2: (*y)++; break;
X case 3: --(*x); break;
X }
X}
X
Xvoid
Xmazexy(cc) /* find random point in generated corridors
X i.e., don't create items in moats, bunkers, or walls */
X coord *cc;
X{
X int cpt=0;
X
X do {
X cc->x = 3 + 2*rn2((x_maze_max>>1) - 1);
X cc->y = 3 + 2*rn2((y_maze_max>>1) - 1);
X cpt++;
X#ifndef WALLIFIED_MAZE
X } while (cpt < 100 && levl[cc->x][cc->y].typ != CORR);
X#else
X } while (cpt < 100 && levl[cc->x][cc->y].typ != ROOM);
X#endif
X if (cpt >= 100) panic("mazexy: can't find a place!");
X return;
X}
X
Xvoid
Xbound_digging()
X/* put a non-diggable boundary around the initial portion of a level map.
X * assumes that no level will initially put things beyond the isok() range.
X */
X{
X register int x,y;
X register boolean found;
X int xmin,xmax,ymin,ymax;
X
X found = FALSE;
X for(xmin=1; !found; xmin++)
X for(y=0; y<=ROWNO-1; y++)
X if(levl[xmin][y].typ != STONE) found = TRUE;
X xmin -= 2;
X
X found = FALSE;
X for(xmax=COLNO-2; !found; xmax--)
X for(y=0; y<=ROWNO-1; y++)
X if(levl[xmax][y].typ != STONE) found = TRUE;
X xmax += 2;
X
X found = FALSE;
X for(ymin=1; !found; ymin++)
X for(x=xmin; x<=xmax; x++)
X if(levl[x][ymin].typ != STONE) found = TRUE;
X ymin -= 2;
X
X found = FALSE;
X for(ymax=ROWNO-2; !found; ymax--)
X for(x=xmin; x<=xmax; x++)
X if(levl[x][ymax].typ != STONE) found = TRUE;
X ymax += 2;
X
X for(x=xmin; x<=xmax; x++) {
X levl[x][ymin].diggable = W_NONDIGGABLE;
X levl[x][ymax].diggable = W_NONDIGGABLE;
X }
X
X for(y=ymin; y<=ymax; y++) {
X levl[xmin][y].diggable = W_NONDIGGABLE;
X levl[xmax][y].diggable = W_NONDIGGABLE;
X }
X}
END_OF_FILE
if test 12398 -ne `wc -c <'src/mkmaze.c'`; then
echo shar: \"'src/mkmaze.c'\" unpacked with wrong size!
fi
# end of 'src/mkmaze.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'\" \(12800 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(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 walklist[50];
Xextern int x_maze_max, y_maze_max;
X
Xstatic char Map[COLNO][ROWNO];
Xstatic char robjects[10], rloc_x[10], rloc_y[10], rmonst[10],
X ralign[3] = { A_CHAOS, A_NEUTRAL, A_LAW };
Xstatic xchar xstart, ystart, xsize, ysize;
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 dig 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
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);
X else if (tmpobj.id != -1)
X (void) mksobj_at(tmpobj.id, x, y);
X else
X (void) mkobj_at(c, x, y);
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);
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)
Xchar *name;
X{
X FILE *fd;
X boolean result;
X schar c;
X
X fd = fopen(name, RDMODE);
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 12800 -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
if test -f 'src/unixmain.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/unixmain.c'\"
else
echo shar: Extracting \"'src/unixmain.c'\" \(12696 characters\)
sed "s/^X//" >'src/unixmain.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)unixmain.c 3.0 89/01/13
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X/* main.c - (Unix) version */
X
X#include <signal.h>
X#include <pwd.h>
X
X#include "hack.h"
X
Xint hackpid = 0; /* current pid */
Xint locknum = 0; /* max num of players */
X#ifdef DEF_PAGER
Xchar *catmore = 0; /* default pager */
X#endif
Xchar SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */
Xchar *hname = 0; /* name of the game (argv[0] of call) */
Xchar obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
X
Xint (*occupation)() = DUMMY;
Xint (*afternmv)() = DUMMY;
X#ifdef CHDIR
Xstatic void chdirx();
X#endif /* CHDIR */
Xstatic void whoami(), newgame();
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X struct passwd *pw;
X extern struct passwd *getpwuid();
X extern int x_maze_max, y_maze_max;
X register int fd;
X#ifdef CHDIR
X register char *dir;
X#endif
X#ifdef COMPRESS
X char cmd[80], old[80];
X#endif
X hname = argv[0];
X hackpid = getpid();
X (void) umask(0);
X
X#ifdef CHDIR /* otherwise no chdir() */
X /*
X * See if we must change directory to the playground.
X * (Perhaps hack runs suid and playground is inaccessible
X * for the player.)
X * The environment variable HACKDIR is overridden by a
X * -d command line option (must be the first option given)
X */
X
X dir = getenv("HACKDIR");
X if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
X argc--;
X argv++;
X dir = argv[0]+2;
X if(*dir == '=' || *dir == ':') dir++;
X if(!*dir && argc > 1) {
X argc--;
X argv++;
X dir = argv[0];
X }
X if(!*dir)
X error("Flag -d must be followed by a directory name.");
X }
X#endif /* CHDIR /**/
X /* Set the default values of the presentation characters */
X (void) memcpy((char *) &showsyms,
X (char *) &defsyms, sizeof(struct symbols));
X initoptions();
X whoami();
X /*
X * Now we know the directory containing 'record' and
X * may do a prscore().
X */
X if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
X#ifdef CHDIR
X chdirx(dir,0);
X#endif
X prscore(argc, argv);
X exit(0);
X }
X
X /*
X * It seems he really wants to play.
X * Remember tty modes, to be restored on exit.
X */
X gettty();
X setbuf(stdout,obuf);
X setrandom();
X startup();
X cls();
X u.uhp = 1; /* prevent RIP on early quits */
X u.ux = FAR; /* prevent nscr() */
X (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
X
X /*
X * Find the creation date of this game,
X * so as to avoid restoring outdated savefiles.
X */
X gethdate(hname);
X
X /*
X * We cannot do chdir earlier, otherwise gethdate will fail.
X */
X#ifdef CHDIR
X chdirx(dir,1);
X#endif
X
X /*
X * Process options.
X */
X while(argc > 1 && argv[1][0] == '-'){
X argv++;
X argc--;
X switch(argv[0][1]){
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X case 'D':
X case 'X':
X pw = getpwuid(getuid());
X# ifdef WIZARD
X if(!strcmp(pw->pw_name, WIZARD))
X wizard = TRUE;
X# endif
X# if defined(WIZARD) && defined(EXPLORE_MODE)
X else
X# endif
X# ifdef EXPLORE_MODE
X discover = TRUE;
X# endif
X break;
X#endif
X#ifdef NEWS
X case 'n':
X flags.nonews = TRUE;
X break;
X#endif
X case 'u':
X if(argv[0][2])
X (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
X else if(argc > 1) {
X argc--;
X argv++;
X (void) strncpy(plname, argv[0], sizeof(plname)-1);
X } else
X Printf("Player name expected after -u\n");
X break;
X default:
X /* allow -T for Tourist, etc. */
X (void) strncpy(pl_character, argv[0]+1,
X sizeof(pl_character)-1);
X
X /* Printf("Unknown option: %s\n", *argv); */
X }
X }
X
X if(argc > 1)
X locknum = atoi(argv[1]);
X#ifdef MAX_NR_OF_PLAYERS
X if(!locknum || locknum > MAX_NR_OF_PLAYERS)
X locknum = MAX_NR_OF_PLAYERS;
X#endif
X#ifdef DEF_PAGER
X if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
X catmore = DEF_PAGER;
X#endif
X#ifdef MAIL
X getmailstatus();
X#endif
X#ifdef WIZARD
X if(wizard) Strcpy(plname, "wizard"); else
X#endif
X if(!*plname || !strncmp(plname, "player", 4)
X || !strncmp(plname, "games", 4))
X askname();
X plnamesuffix(); /* strip suffix from name; calls askname() */
X /* again if suffix was whole name */
X /* accepts any suffix */
X#ifdef WIZARD
X if(!wizard) {
X#endif
X /*
X * check for multiple games under the same name
X * (if !locknum) or check max nr of players (otherwise)
X */
X (void) signal(SIGQUIT,SIG_IGN);
X (void) signal(SIGINT,SIG_IGN);
X if(!locknum)
X Strcpy(lock,plname);
X getlock(); /* sets lock if locknum != 0 */
X#ifdef WIZARD
X } else
X Strcpy(lock,plname);
X#endif /* WIZARD /**/
X setftty();
X
X /*
X * Initialisation of the boundaries of the mazes
X * Both boundaries have to be even.
X */
X
X x_maze_max = COLNO-1;
X if (x_maze_max % 2)
X x_maze_max--;
X y_maze_max = ROWNO-1;
X if (y_maze_max % 2)
X y_maze_max--;
X
X /* initialize static monster strength array */
X init_monstr();
X
X Sprintf(SAVEF, "save/%d%s", getuid(), plname);
X regularize(SAVEF+5); /* avoid . or / in name */
X#ifdef COMPRESS
X Strcpy(old,SAVEF);
X Strcat(SAVEF,".Z");
X if((fd = open(SAVEF,0)) >= 0) {
X (void) close(fd);
X Strcpy(cmd, COMPRESS);
X Strcat(cmd, " -d "); /* uncompress */
X# ifdef COMPRESS_OPTIONS
X Strcat(cmd, COMPRESS_OPTIONS);
X Strcat(cmd, " ");
X# endif
X Strcat(cmd,SAVEF);
X (void) system(cmd);
X }
X Strcpy(SAVEF,old);
X#endif
X if((fd = open(SAVEF,0)) >= 0 &&
X (uptodate(fd) || unlink(SAVEF) == 666)) {
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X pline("Restoring old save file...");
X (void) fflush(stdout);
X if(!dorecover(fd))
X goto not_recovered;
X pline("Hello %s, welcome to NetHack!", plname);
X /* get shopkeeper set properly if restore is in shop */
X (void) inshop();
X#ifdef EXPLORE_MODE
X if (discover) {
X You("are in non-scoring discovery mode.");
X pline("Do you want to keep the save file? ");
X if(yn() == 'n')
X (void) unlink(SAVEF);
X }
X#endif
X flags.move = 0;
X } else {
Xnot_recovered:
X newgame();
X /* give welcome message before pickup messages */
X pline("Hello %s, welcome to NetHack!", plname);
X#ifdef EXPLORE_MODE
X if (discover)
X You("are in non-scoring discovery mode.");
X#endif
X flags.move = 0;
X set_wear();
X pickup(1);
X read_engr_at(u.ux,u.uy);
X }
X
X flags.moonphase = phase_of_the_moon();
X if(flags.moonphase == FULL_MOON) {
X You("are lucky! Full moon tonight.");
X if(!u.uluck) change_luck(1);
X } else if(flags.moonphase == NEW_MOON) {
X pline("Be careful! New moon tonight.");
X }
X
X initrack();
X
X for(;;) {
X if(flags.move) { /* actual time passed */
X
X#ifdef SOUNDS
X dosounds();
X#endif
X settrack();
X
X if(moves%2 == 0 ||
X (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
X movemon();
X#ifdef HARD
X if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
X#else
X if(!rn2(70))
X#endif
X (void) makemon((struct permonst *)0, 0, 0);
X }
X if(Glib) glibr();
X timeout();
X ++moves;
X#ifdef THEOLOGY
X if (u.ublesscnt) u.ublesscnt--;
X#endif
X if(flags.time) flags.botl = 1;
X#ifdef POLYSELF
X if(u.mtimedone)
X if(u.mh < 1) rehumanize();
X else
X#endif
X if(u.uhp < 1) {
X You("die...");
X done("died");
X }
X#ifdef POLYSELF
X if (u.mtimedone) {
X if (u.mh < u.mhmax) {
X if (Regeneration || !(moves%20)) {
X flags.botl = 1;
X u.mh++;
X }
X }
X }
X#endif
X if(u.uhp < u.uhpmax) {
X if(u.ulevel > 9) {
X int heal;
X
X if(HRegeneration || !(moves%3)) {
X flags.botl = 1;
X if (ACURR(A_CON) <= 12) heal = 1;
X else heal = rnd((int) ACURR(A_CON)-12);
X if (heal > u.ulevel-9) heal = u.ulevel-9;
X u.uhp += heal;
X if(u.uhp > u.uhpmax)
X u.uhp = u.uhpmax;
X }
X } else if(HRegeneration ||
X (!(moves%((MAXULEV+12)/(u.ulevel+2)+1)))) {
X flags.botl = 1;
X u.uhp++;
X }
X }
X#ifdef SPELLS
X if ((u.uen<u.uenmax) && (!(moves%(19-ACURR(A_INT)/2)))) {
X u.uen += rn2((int)ACURR(A_WIS)/5 + 1) + 1;
X if (u.uen > u.uenmax) u.uen = u.uenmax;
X flags.botl = 1;
X }
X#endif
X if(Teleportation && !rn2(85)) tele();
X#ifdef POLYSELF
X if(Polymorph && !rn2(100)) polyself();
X if(u.ulycn >= 0 && !rn2(80 - (20 * night())))
X you_were();
X#endif
X if(Searching && multi >= 0) (void) dosearch0(1);
X hatch_eggs();
X gethungry();
X invault();
X amulet();
X#ifdef HARD
X if (!rn2(40+(int)(ACURR(A_DEX)*3))) u_wipe_engr(rnd(3));
X if (u.udemigod) {
X
X if(u.udg_cnt) u.udg_cnt--;
X if(!u.udg_cnt) {
X
X intervene();
X u.udg_cnt = rn1(200, 50);
X }
X }
X#endif
X restore_attrib();
X }
X if(multi < 0) {
X if(!++multi){
X pline(nomovemsg ? nomovemsg :
X "You can move again.");
X nomovemsg = 0;
X if(afternmv) (*afternmv)();
X afternmv = 0;
X }
X }
X
X find_ac();
X if(!flags.mv || Blind)
X {
X seeobjs();
X seemons();
X seeglds();
X nscr();
X }
X if(flags.botl || flags.botlx) bot();
X
X flags.move = 1;
X
X if(multi >= 0 && occupation) {
X
X if(monster_nearby())
X stop_occupation();
X else if ((*occupation)() == 0)
X occupation = 0;
X continue;
X }
X
X if((u.uhave_amulet || Clairvoyant) &&
X#ifdef ENDGAME
X dlevel != ENDLEVEL &&
X#endif
X !(moves%15) && !rn2(2)) do_vicinity_map();
X
X u.umoved = FALSE;
X if(multi > 0) {
X lookaround();
X if(!multi) { /* lookaround may clear multi */
X flags.move = 0;
X continue;
X }
X if(flags.mv) {
X if(multi < COLNO && !--multi)
X flags.mv = flags.run = 0;
X domove();
X } else {
X --multi;
X rhack(save_cm);
X }
X } else if(multi == 0) {
X#ifdef MAIL
X ckmailstatus();
X#endif
X rhack(NULL);
X }
X if(multi && multi%7 == 0)
X (void) fflush(stdout);
X }
X}
X
Xvoid
Xglo(foo)
Xregister int foo;
X{
X /* construct the string xlock.n */
X register char *tf;
X
X tf = lock;
X while(*tf && *tf != '.') tf++;
X Sprintf(tf, ".%d", foo);
X}
X
X/*
X * plname is filled either by an option (-u Player or -uPlayer) or
X * explicitly (by being the wizard) or by askname.
X * It may still contain a suffix denoting pl_character.
X */
Xvoid
Xaskname(){
Xregister int c,ct;
X Printf("\nWho are you? ");
X (void) fflush(stdout);
X ct = 0;
X while((c = Getchar()) != '\n'){
X if(c == EOF) error("End of input\n");
X /* some people get confused when their erase char is not ^H */
X if(c == '\010') {
X if(ct) ct--;
X continue;
X }
X if(c != '-')
X if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
X if(ct < sizeof(plname)-1) plname[ct++] = c;
X }
X plname[ct] = 0;
X if(ct == 0) askname();
X}
X
X/*VARARGS1*/
Xvoid
Ximpossible(s,x1,x2)
Xregister char *s, *x1, *x2;
X{
X pline(s,x1,x2);
X pline("Program in disorder - perhaps you'd better Quit.");
X}
X
X#ifdef CHDIR
Xstatic void
Xchdirx(dir, wr)
Xchar *dir;
Xboolean wr;
X{
X
X# ifdef SECURE
X if(dir /* User specified directory? */
X# ifdef HACKDIR
X && strcmp(dir, HACKDIR) /* and not the default? */
X# endif
X ) {
X (void) setgid(getgid());
X (void) setuid(getuid()); /* Ron Wessels */
X }
X# endif
X
X# ifdef HACKDIR
X if(dir == NULL)
X dir = HACKDIR;
X# endif
X
X if(dir && chdir(dir) < 0) {
X perror(dir);
X error("Cannot chdir to %s.", dir);
X }
X
X /* warn the player if he cannot write the record file */
X /* perhaps we should also test whether . is writable */
X /* unfortunately the access systemcall is worthless */
X if(wr) {
X register int fd;
X
X if(dir == NULL)
X dir = ".";
X if((fd = open(RECORD, 2)) < 0) {
X Printf("Warning: cannot write %s/%s", dir, RECORD);
X getret();
X } else
X (void) close(fd);
X }
X}
X#endif /* CHDIR /**/
X
Xvoid
Xstop_occupation()
X{
X if(occupation) {
X You("stop %s.", occtxt);
X occupation = 0;
X#ifdef REDO
X multi = 0;
X pushch(0);
X#endif
X }
X}
X
Xstatic void
Xwhoami() {
X /*
X * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
X * 2. Use $USER or $LOGNAME (if 1. fails)
X * 3. Use getlogin() (if 2. fails)
X * The resulting name is overridden by command line options.
X * If everything fails, or if the resulting name is some generic
X * account like "games", "play", "player", "hack" then eventually
X * we'll ask him.
X * Note that we trust him here; it is possible to play under
X * somebody else's name.
X */
X register char *s;
X
X if(!*plname && (s = getenv("USER")))
X (void) strncpy(plname, s, sizeof(plname)-1);
X if(!*plname && (s = getenv("LOGNAME")))
X (void) strncpy(plname, s, sizeof(plname)-1);
X if(!*plname && (s = getlogin()))
X (void) strncpy(plname, s, sizeof(plname)-1);
X}
X
Xstatic void
Xnewgame() {
X fobj = fcobj = invent = 0;
X fmon = fallen_down = 0;
X ftrap = 0;
X fgold = 0;
X flags.ident = 1;
X
X init_objects();
X u_init();
X
X (void) signal(SIGINT, (SIG_RET_TYPE) done1);
X
X mklev();
X u.ux = xupstair;
X u.uy = yupstair;
X (void) inshop();
X
X setsee();
X flags.botlx = 1;
X
X /* Move the monster from under you or else
X * makedog() will fail when it calls makemon().
X * - ucsfcgl!kneller
X */
X if(levl[u.ux][u.uy].mmask) mnexto(m_at(u.ux, u.uy));
X
X (void) makedog();
X seemons();
X#ifdef NEWS
X if(flags.nonews || !readnews())
X /* after reading news we did docrt() already */
X#endif
X docrt();
X
X return;
X}
END_OF_FILE
if test 12696 -ne `wc -c <'src/unixmain.c'`; then
echo shar: \"'src/unixmain.c'\" unpacked with wrong size!
fi
# end of 'src/unixmain.c'
fi
echo shar: End of archive 27 \(of 38\).
cp /dev/null ark27isdone
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 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 38 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0