billr@saab.CNA.TEK.COM (Bill Randle) (07/25/89)
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