Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!tektronix!tekgen!tekred!games-request
From: games-request@tekred.TEK.COM
Newsgroups: comp.sources.games
Subject: v03i012: NetHack2.2 - display oriented dungeons and dragons, Part12/20
Message-ID: <1898@tekred.TEK.COM>
Date: Wed, 2-Dec-87 12:03:24 EST
Article-I.D.: tekred.1898
Posted: Wed Dec 2 12:03:24 1987
Date-Received: Sun, 6-Dec-87 06:08:08 EST
Sender: billr@tekred.TEK.COM
Lines: 2420
Approved: billr@tekred.TEK.COM
Submitted by: mike@genat.UUCP (Mike Stephenson)
Comp.sources.games: Volume 3, Issue 12
Archive-name: nethack2.2/Part12
#! /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 pcmain.c <<'END_OF_pcmain.c'
X/* SCCS Id: @(#)pcmain.c 2.1 87/10/18
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* main.c - (PC) version */
X
X#include
X#include
X#include "hack.h"
X
X#ifdef QUEST
X#define gamename "PC NetQuest"
X#else
X#define gamename "PC NetHack"
X#endif
X
Xchar orgdir[PATHLEN], *getcwd();
X
Xextern struct permonst mons[CMNUM+2];
Xextern char genocided[], fut_geno[];
Xextern char *getlogin(), *getenv();
Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ];
X
Xint (*afternmv)(), done1(), (*occupation)();
X
Xchar SAVEF[FILENAME];
Xchar *hname = gamename;
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
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X register int fd;
X register char *dir;
X#ifdef MSDOS
X static void moveloop(); /* a helper function for MSC optimizer */
X
X /* Save current directory and make sure it gets restored when
X * the game is exited.
X */
X int (*funcp)();
X
X if (getcwd(orgdir, sizeof orgdir) == NULL) {
X xputs("hack: 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 signal(SIGINT, funcp); /* restore original directory */
X#endif
X
X#ifdef GRAPHICS
X /* Set the default values of the presentation characters */
X memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols));
X#endif
X#ifdef DGK
X if ((dir = getenv("HACKDIR")) != (char *) NULL) {
X (void) strcpy(hackdir, dir);
X chdirx (dir, 1);
X }
X zero_finfo();
X initoptions();
X if (!hackdir[0])
X (void) strcpy(hackdir, orgdir);
X dir = hackdir;
X#else
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 /* DGK */
X
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 chdirx(dir,0);
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 init_corpses(); /* initialize optional corpse names */
X cls();
X u.uhp = 1; /* prevent RIP on early quits */
X u.ux = FAR; /* prevent nscr() */
X
X /*
X * We cannot do chdir earlier, otherwise gethdate will fail.
X */
X chdirx(dir,1);
X
X /*
X * Process options.
X */
X while(argc > 1 && argv[1][0] == '-'){
X argv++;
X argc--;
X switch(argv[0][1]){
X#ifdef WIZARD
X case 'D':
X# ifdef MSDOS
X wizard = TRUE;
X# else
X if(!strcmp(getlogin(), WIZARD))
X wizard = TRUE;
X else {
X settty("Sorry, you can't operate in debug mode.\n");
X clearlocks();
X exit(0);
X }
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 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#ifdef DGK
X set_lock_and_bones();
X copybones(FROMPERM);
X#endif
X#ifdef WIZARD
X if (wizard)
X (void) 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#ifdef WIZARD
X if(wizard) {
X register char *sfoo;
X# ifndef DGK
X /* lock is set in read_config_file */
X (void) strcpy(lock,plname);
X# endif
X if(sfoo = getenv("MAGIC"))
X while(*sfoo) {
X switch(*sfoo++) {
X case 'n': (void) srand(*sfoo++);
X break;
X }
X }
X if(sfoo = getenv("GENOCIDED")){
X if(*sfoo == '!'){
X register struct permonst *pm = mons;
X register char *gp = genocided;
X
X while(pm < mons+CMNUM+2){
X if(!index(sfoo, pm->mlet))
X *gp++ = pm->mlet;
X pm++;
X }
X *gp = 0;
X } else
X (void) strcpy(genocided, sfoo);
X (void) strcpy(fut_geno, genocided);
X }
X }
X#endif /* WIZARD */
X start_screen();
X#ifdef DGK
X strncat(SAVEF, plname, 8);
X strcat(SAVEF, ".sav");
X cls();
X if (saveDiskPrompt(1) && ((fd = open(SAVEF, 0)) >= 0) &&
X (uptodate(fd) || !unlink(SAVEF))) {
X#else
X (void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
X regularize(SAVEF+5); /* avoid . or / in name */
X if((fd = open(SAVEF,0)) >= 0 &&
X (uptodate(fd) || unlink(SAVEF) == 666)) {
X#endif /* DGK */
X (void) signal(SIGINT,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 %s!", plname, hname);
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
X (void) signal(SIGINT,done1);
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 {
X struct monst *mtmp;
X
X if (mtmp = m_at(u.ux, u.uy))
X mnexto(mtmp);
X }
X makedog();
X { register struct monst *mtmp;
X if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); /* riv05!a3 */
X }
X seemons();
X docrt();
X
X /* give welcome message before pickup messages */
X pline("Hello %s, welcome to %s!", plname, hname);
X
X pickup(1);
X read_engr_at(u.ux,u.uy);
X flags.move = 1;
X }
X flags.moonphase = phase_of_the_moon();
X if(flags.moonphase == FULL_MOON) {
X pline("You are lucky! Full moon tonight.");
X if(!u.uluck) u.uluck++;
X } else if(flags.moonphase == NEW_MOON) {
X pline("Be careful! New moon tonight.");
X }
X
X initrack();
X (void) signal(SIGINT, SIG_IGN);
X#ifdef MSDOS
X /* Help for Microsoft optimizer. Otherwise main is too large -dgk*/
X moveloop();
X}
X
Xstatic void
Xmoveloop()
X{
X char ch;
X int abort;
X#endif /* MSDOS */
X for(;;) {
X if(flags.move) { /* actual time passed */
X
X settrack();
X
X if(moves%2 == 0 ||
X (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
X extern struct monst *makemon();
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 PRAYERS
X if (u.ublesscnt) u.ublesscnt--;
X#endif
X#ifndef DGK
X if(flags.time) flags.botl = 1;
X#endif
X#ifdef KAA
X if(u.mtimedone)
X if(u.mh < 1) rehumanize();
X else
X#endif
X if(u.uhp < 1) {
X pline("You die...");
X done("died");
X }
X if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
X wailmsg = moves;
X#ifdef KAA
X if(index("WEV", pl_character[0])) {
X if (u.uhp == 1)
X pline("%s is about to die.", pl_character);
X else
X pline("%s, your life force is running out.",
X pl_character);
X } else {
X#endif
X if(u.uhp == 1)
X pline("You hear the wailing of the Banshee...");
X else
X pline("You hear the howling of the CwnAnnwn...");
X#ifdef KAA
X }
X#endif
X }
X#ifdef KAA
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 if(HRegeneration || !(moves%3)) {
X flags.botl = 1;
X u.uhp += rnd((int) u.ulevel-9);
X if(u.uhp > u.uhpmax)
X u.uhp = u.uhpmax;
X }
X } else if(HRegeneration ||
X (!(moves%(22-u.ulevel*2)))) {
X flags.botl = 1;
X u.uhp++;
X }
X }
X#ifdef SPELLS
X if ((u.uen u.uenmax) u.uen = u.uenmax;
X flags.botl = 1;
X }
X#endif
X if(Teleportation && !rn2(85)) tele();
X#if defined(KAA) && defined(BVH)
X if(Polymorph && !rn2(100)) polyself();
X#endif
X if(Searching && multi >= 0) (void) dosearch();
X gethungry();
X invault();
X amulet();
X#ifdef HARD
X if (!rn2(50+(u.ulevel*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 }
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#ifndef QUEST
X if(!flags.mv || Blind)
X#endif
X {
X seeobjs();
X seemons();
X nscr();
X }
X#ifdef DGK
X if(flags.time) flags.botl = 1;
X#endif
X if(flags.botl || flags.botlx) bot();
X
X flags.move = 1;
X
X if(multi >= 0 && occupation) {
X#ifdef DGK
X abort = 0;
X if (kbhit()) {
X if ((ch = getchar()) == ABORT)
X abort++;
X# ifdef REDO
X else
X pushch(ch);
X# endif
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#else
X if (monster_nearby())
X stop_occupation();
X else if ((*occupation)() == 0)
X occupation = 0;
X#endif
X continue;
X }
X
X if(multi > 0) {
X#ifdef QUEST
X if(flags.run >= 4) finddir();
X#endif
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 rhack((char *) 0);
X }
X if(multi && multi%7 == 0)
X (void) fflush(stdout);
X }
X}
X
X#ifndef DGK
X/* This function is unnecessary and incompatible with the #define
X * of glo(x) in config.h -dgk
X */
Xglo(foo)
Xregister foo;
X{
X /* construct the string xlock.n */
X register char *tf;
X
X tf = lock;
X while(*tf && *tf != '.') tf++;
X (void) sprintf(tf, ".%d", foo);
X}
X#endif
X
X/*
X * plname is filled either by an option (-u Player or -uPlayer) or
X * explicitly (-w implies wizard) or by askname.
X * It may still contain a suffix denoting pl_character.
X */
Xaskname(){
Xregister int c,ct;
X printf("\nWho are you? ");
X (void) fflush(stdout);
X ct = 0;
X while((c = getchar()) != '\n'){
X#ifdef MSDOS
X msmsg("%c", c);
X#endif
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*/
Ximpossible(s,x1,x2)
Xregister char *s;
X{
X pline(s,x1,x2);
X pline("Program in disorder - perhaps you'd better Quit.");
X}
X
X#ifdef CHDIR
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#ifdef DGK
X /* Change the default drive as well.
X */
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 fd;
X
X if(dir == NULL)
X dir = ".";
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
Xstop_occupation()
X{
X if(occupation) {
X pline("You stop %s.", occtxt);
X occupation = 0;
X#ifdef REDO
X multi = 0;
X pushch(0);
X#endif
X }
X}
X
X#ifdef DGK
Xstruct finfo zfinfo = ZFINFO;
X
Xzero_finfo() { /* zero "fileinfo" array to prevent crashes on level change */
X int i;
X
X for (i = 0 ; i <= MAXLEVEL; i++)
X fileinfo[i] = zfinfo;
X}
X#endif
END_OF_pcmain.c
if test 11972 -ne `wc -c pri.c <<'END_OF_pri.c'
X/* SCCS Id: @(#)pri.c 2.1 87/11/09
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include
X#include "hack.h"
X#ifdef GENIX
X#define void int /* jhn - mod to prevent compiler from bombing */
X#endif
X#ifdef MSDOSCOLOR
Xextern int hilite();
X#endif
X
Xxchar scrlx, scrhx, scrly, scrhy; /* corners of new area on screen */
X
Xextern char *hu_stat[]; /* in eat.c */
Xextern char *CD;
Xextern struct monst *makemon();
X
Xswallowed()
X{
X char *ulook = "|@|";
X ulook[1] = u.usym;
X
X cls();
X curs(u.ux-1, u.uy+1);
X fputs("/-\\", stdout);
X curx = u.ux+2;
X curs(u.ux-1, u.uy+2);
X fputs(ulook, stdout);
X curx = u.ux+2;
X curs(u.ux-1, u.uy+3);
X fputs("\\-/", stdout);
X curx = u.ux+2;
X u.udispl = 1;
X u.udisx = u.ux;
X u.udisy = u.uy;
X}
X
Xsetclipped(){
X error("Hack needs a screen of size at least %d by %d.\n",
X ROWNO+2, COLNO);
X}
X
X#ifdef DGK
Xstatic int multipleAts; /* TRUE if we have many at()'s to do */
Xstatic int DECgraphics; /* The graphics mode toggle */
X
X#define DECgraphicsON() ((void) putchar('\16'), DECgraphics = TRUE)
X#define DECgraphicsOFF() ((void) putchar('\17'), DECgraphics = FALSE)
X#endif
X
Xat(x,y,ch)
Xregister xchar x,y;
Xchar ch;
X{
X#ifndef LINT
X /* if xchar is unsigned, lint will complain about if(x < 0) */
X if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) {
X impossible("At gets 0%o at %d %d.", ch, x, y);
X return;
X }
X#endif
X if(!ch) {
X impossible("At gets null at %d %d.", x, y);
X return;
X }
X y += 2;
X curs(x,y);
X#ifdef DGK
X if (flags.DECRainbow) {
X /* If there are going to be many at()s in a row without
X * intervention, only change the graphics mode when the
X * character changes between graphic and regular.
X */
X if (multipleAts) {
X if (ch & 0x80) {
X if (!DECgraphics)
X DECgraphicsON();
X (void) putchar(ch ^ 0x80); /* Strip 8th bit */
X } else {
X if (DECgraphics)
X DECgraphicsOFF();
X (void) putchar(ch);
X }
X /* Otherwise, we don't know how many at()s will be happening
X * before printing of normal strings, so change to graphics
X * mode when necessary, then change right back.
X */
X } else {
X if (ch & 0x80) {
X DECgraphicsON();
X (void) putchar(ch ^ 0x80); /* Strip 8th bit */
X DECgraphicsOFF();
X } else
X (void) putchar(ch);
X }
X } else
X#endif
X#ifdef MSDOSCOLOR
X hilite(ch);
X#else
X (void) putchar(ch);
X#endif
X curx++;
X}
X
Xprme(){
X if(!Invisible) at(u.ux,u.uy,u.usym);
X}
X
Xdoredraw()
X{
X docrt();
X return(0);
X}
X
Xdocrt()
X{
X register x,y;
X register struct rm *room;
X register struct monst *mtmp;
X
X if(u.uswallow) {
X swallowed();
X return;
X }
X cls();
X
X/* Some ridiculous code to get display of @ and monsters (almost) right */
X if(!Invisible) {
X levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym;
X levl[u.udisx][u.udisy].seen = 1;
X u.udispl = 1;
X } else u.udispl = 0;
X
X seemons(); /* reset old positions */
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X mtmp->mdispl = 0;
X seemons(); /* force new positions to be shown */
X/* This nonsense should disappear soon --------------------------------- */
X
X#if defined(DGK) && !defined(MSDOSCOLOR)
X /* I don't know DEC Rainbows, but if HILITE_COLOR is applicable,
X * the !defined(HILITE_COLOR) will have to be compensated for.
X * -kjs */
X /* For DEC Rainbows, we must translate each character to strip
X * out the 8th bit if necessary.
X */
X if (flags.DECRainbow) {
X multipleAts = TRUE;
X for(y = 0; y < ROWNO; y++)
X for(x = 0; x < COLNO; x++)
X if((room = &levl[x][y])->new) {
X room->new = 0;
X at(x,y,room->scrsym);
X } else if(room->seen)
X at(x,y,room->scrsym);
X multipleAts = FALSE;
X if (DECgraphics)
X DECgraphicsOFF();
X } else {
X /* Otherwise, line buffer the output to do the redraw in
X * about 2/3 of the time.
X */
X for(y = 0; y < ROWNO; y++) {
X char buf[COLNO+1];
X int start, end;
X
X memset(buf, ' ', COLNO);
X for(x = 0, start = -1, end = -1; x < COLNO; x++)
X if((room = &levl[x][y])->new) {
X room->new = 0;
X buf[x] = room->scrsym;
X if (start < 0)
X start = x;
X end = x;
X } else if(room->seen) {
X buf[x] = room->scrsym;
X if (start < 0)
X start = x;
X end = x;
X }
X if (end >= 0) {
X buf[end + 1] = '\0';
X curs(start, y + 2);
X fputs(buf + start, stdout);
X curx = end + 1;
X }
X }
X }
X#else
X for(y = 0; y < ROWNO; y++)
X for(x = 0; x < COLNO; x++)
X if((room = &levl[x][y])->new) {
X room->new = 0;
X at(x,y,room->scrsym);
X } else if(room->seen)
X at(x,y,room->scrsym);
X#endif
X scrlx = COLNO;
X scrly = ROWNO;
X scrhx = scrhy = 0;
X flags.botlx = 1;
X bot();
X}
X
Xdocorner(xmin,ymax) register xmin,ymax; {
X register x,y;
X register struct rm *room;
X register struct monst *mtmp;
X
X if(u.uswallow) { /* Can be done more efficiently */
X swallowed();
X return;
X }
X
X seemons(); /* reset old positions */
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(mtmp->mx >= xmin && mtmp->my < ymax)
X mtmp->mdispl = 0;
X seemons(); /* force new positions to be shown */
X
X#ifdef DGK
X if (flags.DECRainbow)
X multipleAts = TRUE;
X#endif
X for(y = 0; y < ymax; y++) {
X if(y > ROWNO && CD) break;
X curs(xmin,y+2);
X cl_end();
X if(y < ROWNO) {
X for(x = xmin; x < COLNO; x++) {
X if((room = &levl[x][y])->new) {
X room->new = 0;
X at(x,y,room->scrsym);
X } else
X if(room->seen)
X at(x,y,room->scrsym);
X }
X }
X }
X#ifdef DGK
X if (flags.DECRainbow) {
X multipleAts = FALSE;
X if (DECgraphics)
X DECgraphicsOFF();
X }
X#endif
X if(ymax > ROWNO) {
X cornbot(xmin-1);
X if(ymax > ROWNO+1 && CD) {
X curs(1,ROWNO+3);
X cl_eos();
X }
X }
X}
X
X/* Trolls now regenerate thanks to KAA */
X
Xseeobjs(){
Xregister struct obj *obj, *obj2;
X for(obj = fobj; obj; obj = obj2) {
X obj2 = obj->nobj;
X if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE) {
X
X if (obj->otyp == DEAD_TROLL && obj->age + 20 < moves) {
X delobj(obj);
X if (cansee(obj->ox, obj->oy))
X pline("The troll rises from the dead!");
X (void) makemon(PM_TROLL,obj->ox, obj->oy);
X } else if (obj->age + 250 < moves) delobj(obj);
X }
X }
X
X for(obj = invent; obj; obj = obj2) {
X obj2 = obj->nobj;
X if(obj->olet == FOOD_SYM && obj->otyp >= CORPSE) {
X
X if (obj->otyp == DEAD_TROLL && obj->age + 20 < moves) {
X if (obj == uwep)
X pline("The dead troll writhes out of your grasp!");
X else
X pline("You feel squirming in your backpack!");
X (void)makemon(PM_TROLL,u.ux,u.uy);
X useup(obj);
X } else if (obj->age + 250 < moves) useup(obj);
X }
X }
X}
X
Xseemons(){
Xregister struct monst *mtmp;
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
X if(mtmp->data->mlet == ';')
X mtmp->minvis = (u.ustuck != mtmp &&
X levl[mtmp->mx][mtmp->my].typ == POOL);
X pmon(mtmp);
X#ifndef NOWORM
X if(mtmp->wormno) wormsee(mtmp->wormno);
X#endif
X }
X}
X
Xpmon(mon) register struct monst *mon; {
Xregister int show = (Blind && Telepat) || canseemon(mon);
X if(mon->mdispl){
X if(mon->mdx != mon->mx || mon->mdy != mon->my || !show)
X unpmon(mon);
X }
X
X/* If you're hallucinating, the monster must be redrawn even if it has
X already been printed. Problem: the monster must also be redrawn right
X after hallucination is over, so it looks normal again. Therefore
X code similar to pmon is in timeout.c. */
X if(show && (!mon->mdispl || Hallucination)) {
X if (Hallucination)
X atl(mon->mx,mon->my,
X (!mon->mimic || Protection_from_shape_changers) ?
X rndmonsym() :
X (mon->mappearance == DOOR_SYM) ? DOOR_SYM
X : rndobjsym());
X else
X
X atl(mon->mx,mon->my,
X (!mon->mappearance
X || u.uprops[PROP(RIN_PROTECTION_FROM_SHAPE_CHAN)].p_flgs
X ) ? mon->data->mlet : mon->mappearance);
X mon->mdispl = 1;
X mon->mdx = mon->mx;
X mon->mdy = mon->my;
X }
X}
X
Xunpmon(mon) register struct monst *mon; {
X if(mon->mdispl){
X newsym(mon->mdx, mon->mdy);
X mon->mdispl = 0;
X }
X}
X
Xnscr()
X{
X register x,y;
X register struct rm *room;
X
X if(u.uswallow || u.ux == FAR || flags.nscrinh) return;
X pru();
X for(y = scrly; y <= scrhy; y++)
X for(x = scrlx; x <= scrhx; x++)
X if((room = &levl[x][y])->new) {
X room->new = 0;
X at(x,y,room->scrsym);
X }
X scrhx = scrhy = 0;
X scrlx = COLNO;
X scrly = ROWNO;
X}
X
X/* 100 suffices for bot(); no relation with COLNO */
Xchar oldbot[100], newbot[100];
Xcornbot(lth)
Xregister int lth;
X{
X if(lth < sizeof(oldbot)) {
X oldbot[lth] = 0;
X flags.botl = 1;
X }
X}
X
Xbot()
X{
Xregister char *ob = oldbot, *nb = newbot;
Xregister int i;
Xextern char *eos();
X if(flags.botlx) *ob = 0;
X flags.botl = flags.botlx = 0;
X (void) sprintf(newbot,
X#ifdef GOLD_ON_BOTL
X# ifdef SPELLS
X "Lev %-2d Gp %-5lu Hp %3d(%d) Ep %3d(%d) Ac %-2d ",
X dlevel, u.ugold,
X# ifdef KAA
X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax,
X u.uen, u.uenmax, u.uac);
X# else
X u.uhp, u.uhpmax, u.uen, u.uenmax, u.uac);
X# endif
X# else
X "Level %-2d Gold %-5lu Hp %3d(%d) Ac %-2d ",
X dlevel, u.ugold,
X# ifdef KAA
X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax,
X u.uac);
X# else
X u.uhp, u.uhpmax, u.uac);
X# endif
X# endif
X#else
X# ifdef SPELLS
X "Level %-2d Hp %3d(%d) Energy %3d(%d) Ac %-2d ",
X dlevel,
X# ifdef KAA
X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax, u.uhpmax,
X u.uen, u.uenmax, u.uac);
X# else
X u.uhp, u.uhpmax, u.uen, u.uenmax, u.uac);
X# endif
X# else
X "Level %-2d Hp %3d(%d) Ac %-2d ",
X dlevel,
X# ifdef KAA
X u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax, u.uhpmax,
X u.uac);
X# else
X u.uhp, u.uhpmax, u.uac);
X# endif
X# endif
X#endif
X#ifdef KAA
X if (u.mtimedone)
X (void) sprintf(eos(newbot), "HD %d", mons[u.umonnum].mlevel);
X else
X#endif
X if(u.ustr>18) {
X if(u.ustr>117)
X (void) strcat(newbot,"Str 18/**");
X else
X (void) sprintf(eos(newbot), "Str 18/%02d",u.ustr-18);
X } else
X (void) sprintf(eos(newbot), "Str %-2d ",u.ustr);
X#ifdef EXP_ON_BOTL
X (void) sprintf(eos(newbot), " Exp %2d/%-5lu ", u.ulevel,u.uexp);
X#else
X (void) sprintf(eos(newbot), " Exp %2u ", u.ulevel);
X#endif
X (void) strcat(newbot, hu_stat[u.uhs]);
X if(flags.time)
X (void) sprintf(eos(newbot), " %ld", moves);
X if(strlen(newbot) >= COLNO) {
X register char *bp0, *bp1;
X bp0 = bp1 = newbot;
X do {
X if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ')
X *bp1++ = *bp0;
X } while(*bp0++);
X }
X for(i = 1; idata->mlevel, mtmp->mgold, mtmp->mhp, mtmp->mhpmax);
X pline("Ac %-2d Dam %d %s %s",
X mtmp->data->ac, (mtmp->data->damn + 1) * (mtmp->data->damd + 1),
X mtmp->mcan ? ", cancelled" : "" ,mtmp->mtame ? " (tame)" : "");
X}
X
Xextern char plname[];
Xustatusline() {
X pline("Status of %s ", plname);
X pline("Level %d, gold %lu, hit points %d(%d), AC %d.",
X# ifdef KAA
X u.ulevel, u.ugold, u.mtimedone ? u.mh : u.uhp,
X u.mtimedone ? u.mhmax : u.uhpmax, u.uac);
X# else
X u.ulevel, u.ugold, u.uhp, u.uhpmax, u.uac);
X# endif
X}
X#endif
X
Xcls(){
X if(flags.toplin == 1)
X more();
X flags.toplin = 0;
X
X clear_screen();
X
X flags.botlx = 1;
X}
X
Xrndmonsym() {
X register int x;
X if((x=rn2(58)) < 26)
X return('a'+x);
X else if (x<52)
X return('A'+x-26);
X else switch(x) {
X case 52: return(';');
X case 53: return('&');
X case 54: return(':');
X case 55: return('\'');
X case 56: return(',');
X case 57: return('9');
X default: impossible("Bad random monster %d",x); return('{');
X }
X}
X
Xrndobjsym() {
X char *rndsym=")[!?%/=*($`";
X return *(rndsym+rn2(11));
X}
X
Xchar *hcolors[] = { "ultraviolet","infrared","hot pink", "psychedelic",
X"bluish-orange","reddish-green","dark white","light black","loud",
X"salty","sweet","sour","bitter","luminescent","striped","polka-dotted",
X"square","round","triangular","brilliant","navy blue","cerise",
X"chartreuse","copper","sea green","spiral","swirly","blotchy",
X"fluorescent green","burnt orange","indigo","amber","tan",
X"sky blue-pink","lemon yellow" };
X
Xchar *
Xhcolor() {
X return hcolors[rn2(35)];
X}
X
X#ifdef MSDOSCOLOR
X/* what if a level character is the same as an object/monster? */
X
Xextern char obj_symbols[];
X
Xhilite(let)
Xchar let;
X{
X char *isobjct = index(obj_symbols, let);
X int ismnst();
X
X if (!HI || !HE) {
X (void) putchar(let);
X return;
X }
X if (isobjct != NULL || let == GOLD_SYM) {
X /* is an object */
X printf("%s%c%s", HI_OBJ, let, HE);
X } else if (ismnst(let)) {
X /* is a monster */
X printf("%s%c%s", HI_MON, let, HE);
X } else {
X /* default */
X (void) putchar(let);
X }
X}
X
Xint
Xismnst(let)
Xchar let;
X{
X register int ct;
X register struct permonst *ptr;
X
X for (ct = 0 ; ct < CMNUM + 2 ; ct++) {
X ptr = &mons[ct];
X if(ptr->mlet == let) return(1);
X }
X if (let == '1') return(1);
X else if (let == '2') return(1);
X else if (let == ';') return(1);
X else return(0);
X}
X#endif
END_OF_pri.c
if test 12732 -ne `wc -c unixmain.c <<'END_OF_unixmain.c'
X/* SCCS Id: @(#)unixmain.c 2.1 87/10/18
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* main.c - (Unix) version */
X
X#include
X#include
X#include "hack.h"
X
X#ifdef QUEST
X#define gamename "NetQuest"
X#else
X#define gamename "NetHack"
X#endif
X
Xextern char *getlogin(), *getenv();
Xextern char plname[PL_NSIZ], pl_character[PL_CSIZ];
X
Xint (*afternmv)();
Xint (*occupation)();
X
Xint done1();
Xint hangup();
X
Xint hackpid; /* current pid */
Xint locknum; /* max num of players */
X#ifdef DEF_PAGER
Xchar *catmore; /* default pager */
X#endif
Xchar SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */
Xchar *hname; /* name of the game (argv[0] of call) */
Xchar obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
X
Xextern char *nomovemsg;
Xextern long wailmsg;
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X register int fd;
X#ifdef CHDIR
X register char *dir;
X#endif
X
X hname = argv[0];
X hackpid = getpid();
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#ifdef GRAPHICS
X /* Set the default values of the presentation characters */
X memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols));
X#endif
X#ifdef HACKOPTIONS
X initoptions();
X#endif
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 init_corpses(); /* initialize optional corpse names */
X cls();
X u.uhp = 1; /* prevent RIP on early quits */
X u.ux = FAR; /* prevent nscr() */
X (void) signal(SIGHUP, 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#ifdef WIZARD
X case 'D':
X if(!strcmp(getlogin(), WIZARD))
X wizard = TRUE;
X else {
X settty("Sorry, you can't operate in debug mode.\n");
X clearlocks();
X exit(0);
X }
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) (void) 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 (void) strcpy(lock,plname);
X getlock(); /* sets lock if locknum != 0 */
X#ifdef WIZARD
X } else {
X register char *sfoo;
X extern char genocided[], fut_geno[];
X (void) strcpy(lock,plname);
X if(sfoo = getenv("MAGIC"))
X while(*sfoo) {
X switch(*sfoo++) {
X case 'n': (void) srand(*sfoo++);
X break;
X }
X }
X if(sfoo = getenv("GENOCIDED")){
X if(*sfoo == '!'){
X extern struct permonst mons[CMNUM+2];
X register struct permonst *pm = mons;
X register char *gp = genocided;
X
X while(pm < mons+CMNUM+2){
X if(!index(sfoo, pm->mlet))
X *gp++ = pm->mlet;
X pm++;
X }
X *gp = 0;
X } else
X (void) strcpy(genocided, sfoo);
X (void) strcpy(fut_geno, genocided);
X }
X }
X#endif /* WIZARD /**/
X setftty();
X (void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
X regularize(SAVEF+5); /* avoid . or / in name */
X if((fd = open(SAVEF,0)) >= 0 &&
X (uptodate(fd) || unlink(SAVEF) == 666)) {
X (void) signal(SIGINT,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 %s!", plname, gamename);
X flags.move = 0;
X } else {
Xnot_recovered:
X newgame();
X /* give welcome message before pickup messages */
X pline("Hello %s, welcome to %s!", plname, gamename);
X
X pickup(1);
X read_engr_at(u.ux,u.uy);
X flags.move = 1;
X }
X
X flags.moonphase = phase_of_the_moon();
X if(flags.moonphase == FULL_MOON) {
X pline("You are lucky! Full moon tonight.");
X if(!u.uluck) u.uluck++;
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 settrack();
X
X if(moves%2 == 0 ||
X (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
X extern struct monst *makemon();
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 PRAYERS
X if (u.ublesscnt) u.ublesscnt--;
X#endif
X if(flags.time) flags.botl = 1;
X#ifdef KAA
X if(u.mtimedone)
X if(u.mh < 1) rehumanize();
X else
X#endif
X if(u.uhp < 1) {
X pline("You die...");
X done("died");
X }
X if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
X wailmsg = moves;
X#ifdef KAA
X if(index("WEV", pl_character[0])) {
X if (u.uhp == 1)
X pline("%s is about to die.", pl_character);
X else
X pline("%s, your life force is running out.",
X pl_character);
X } else {
X#endif
X if(u.uhp == 1)
X pline("You hear the wailing of the Banshee...");
X else
X pline("You hear the howling of the CwnAnnwn...");
X#ifdef KAA
X }
X#endif
X }
X#ifdef KAA
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 if(HRegeneration || !(moves%3)) {
X flags.botl = 1;
X u.uhp += rnd((int) u.ulevel-9);
X if(u.uhp > u.uhpmax)
X u.uhp = u.uhpmax;
X }
X } else if(HRegeneration ||
X (!(moves%(22-u.ulevel*2)))) {
X flags.botl = 1;
X u.uhp++;
X }
X }
X#ifdef SPELLS
X if ((u.uen u.uenmax) u.uen = u.uenmax;
X flags.botl = 1;
X }
X#endif
X if(Teleportation && !rn2(85)) tele();
X#if defined(KAA) && defined(BVH)
X if(Polymorph && !rn2(100)) polyself();
X#endif
X if(Searching && multi >= 0) (void) dosearch();
X gethungry();
X invault();
X amulet();
X#ifdef HARD
X if (!rn2(50+(u.ulevel*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 }
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#ifndef QUEST
X if(!flags.mv || Blind)
X#endif
X {
X seeobjs();
X seemons();
X nscr();
X }
X#ifdef DGK
X if(flags.time) flags.botl = 1;
X#endif
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(multi > 0) {
X#ifdef QUEST
X if(flags.run >= 4) finddir();
X#endif
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((char *) 0);
X }
X if(multi && multi%7 == 0)
X (void) fflush(stdout);
X }
X}
X
Xglo(foo)
Xregister foo;
X{
X /* construct the string xlock.n */
X register char *tf;
X
X tf = lock;
X while(*tf && *tf != '.') tf++;
X (void) sprintf(tf, ".%d", foo);
X}
X
X/*
X * plname is filled either by an option (-u Player or -uPlayer) or
X * explicitly (-w implies wizard) or by askname.
X * It may still contain a suffix denoting pl_character.
X */
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*/
Ximpossible(s,x1,x2)
Xregister char *s;
X{
X pline(s,x1,x2);
X pline("Program in disorder - perhaps you'd better Quit.");
X}
X
X#ifdef CHDIR
Xstatic
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) setuid(getuid()); /* Ron Wessels */
X (void) setgid(getgid());
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 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
Xstop_occupation()
X{
X if(occupation) {
X pline("You stop %s.", occtxt);
X occupation = 0;
X#ifdef REDO
X multi = 0;
X pushch(0);
X#endif
X }
X}
X
Xwhoami() {
X /*
X * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
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#ifndef DGKMOD
X initoptions();
X#endif
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
Xnewgame() {
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
X (void) signal(SIGINT,done1);
X mklev();
X u.ux = xupstair;
X u.uy = yupstair;
X (void) inshop();
X setsee();
X flags.botlx = 1;
X {
X register struct monst *mtmp;
X
X /* Move the monster from under you or else
X * makedog() will fail when it calls makemon().
X * - ucsfcgl!kneller
X */
X if (mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);
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 return(0);
X}
X
X#ifdef GENIX
Xjhndist(x1,y1,x2,y2)
X{
X int x,y;
X x=x1-x2;
X y=y1-y2;
X return (x*x + y*y);
X}
X#endif
END_OF_unixmain.c
if test 12402 -ne `wc -c version.c <<'END_OF_version.c'
X/* SCCS Id: @(#)version.c 2.1 87/11/09
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include "hack.h"
X#include "date.h"
X
Xdoversion(){
X
X#ifdef BETA
X pline("%s Net%s Beta Version %s - last build %s.",
X#else
X pline("%s Net%s Version %s - last build %s.",
X#endif
X#ifdef UNIX
X "Unix"
X#endif
X#ifdef MSDOS
X "PC"
X#endif
X#ifdef QUEST
X , "Quest"
X#else
X , "Hack"
X#endif
X , VERSION, datestring);
X return(0);
X}
X
X#ifdef DGKMOD
X
X#define pg_line(x) if(page_line(x)) goto quit;
X
XdoMSCversion()
X{
X char buf[BUFSZ];
X
X set_pager(0);
X sprintf(buf, "Behold mortal, the origins of %s Net%s...",
X#ifdef UNIX
X "Unix"
X#endif
X#ifdef MSDOS
X "PC"
X#endif
X#ifdef QUEST
X , "Quest");
X#else
X , "Hack");
X#endif
X pg_line("");
X pg_line(buf); pg_line(""); pg_line("");
X
X pg_line("The original HACK was written by Jay Fenlason with help from");
X pg_line("Kenny Woodland, Mike Thome and Jon Payne.");
X
X pg_line("");
X pg_line("Andries Brouwer did a major re-write and published (at least)");
X pg_line("two versions (1.0.2 and 1.0.3) to the Usenet.");
X
X pg_line("");
X pg_line("PC HACK 3.51K was an MSDOS(tm) version of HACK 1.03.");
X pg_line("The PC implementation was done in Microsoft(tm) C by Don Kneller");
X pg_line("and modified by Ken Arromdee.");
X
X pg_line("");
X pg_line("PC and UNIX HACK were merged by Mike Stephenson and Ken Arromdee");
X pg_line("incorporating many modifications and features made by the above,");
X pg_line("as well as the following honored hackers:");
X
X pg_line("");
X pg_line(" Scott R. Turner Tom Almy John S. Bien");
X pg_line(" Gil Neiger Ralf Brown Eric S. Raymond");
X pg_line(" Eric Backus Roland McGrath Greg Laskin");
X pg_line(" Bruce Holloway Richard P. Hughey Kevin Sweet");
X set_pager(1);
X return(0);
Xquit:
X set_pager(2);
X return(0);
X}
X
X#endif
END_OF_version.c
if test 1830 -ne `wc -c wizard.c <<'END_OF_wizard.c'
X/* SCCS Id: @(#)wizard.c 2.2 87/11/29
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X/* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
X/* - heavily modified to give the wiz balls. (genat!mike) */
X
X#include "hack.h"
Xextern struct permonst pm_wizard;
Xextern struct monst *makemon();
Xextern struct obj *carrying();
X
X#if defined(HARD) || defined(DGKMOD)
X# ifdef SAC
Xchar nasties[] = "cdDeImoPTUVwxXz3&,:;";
X# else
Xchar nasties[] = "cdDeImoPTUVwxXz&,:;";
X# endif
X#define WIZSHOT 2
X#else
X#define WIZSHOT 6 /* one chance in WIZSHOT that wizard will try magic */
X#endif
X
X#define BOLT_LIM 8 /* from this distance D and 1 will try to hit you */
X
Xchar wizapp[] = "@&DNPTUVXcemntx";
X
X#ifdef DGKMOD
X#define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
Xextern char mlarge[];
X
Xmovedist(x0, x1, y0, y1)
X{
X register int absdx, absdy;
X
X absdx = abs(x1 - x0);
X absdy = abs(y1 - y0);
X
X return (absdx + absdy - min(absdx, absdy));
X}
X#endif
X
X/* If he has found the Amulet, make the wizard appear after some time */
Xamulet(){
X register struct obj *otmp;
X register struct monst *mtmp;
X
X if(!flags.made_amulet || !flags.no_of_wizards)
X return;
X /* find wizard, and wake him if necessary */
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40))
X for(otmp = invent; otmp; otmp = otmp->nobj)
X if(otmp->olet == AMULET_SYM && !otmp->spe) {
X mtmp->msleep = 0;
X if(dist(mtmp->mx,mtmp->my) > 2)
X pline(
X "You get the creepy feeling that somebody noticed your taking the Amulet."
X );
X return;
X }
X}
X
Xwiz_hit(mtmp)
Xregister struct monst *mtmp;
X{
X /* if we have stolen or found the amulet, we disappear */
X if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM &&
X mtmp->minvent->spe == 0) {
X /* vanish -- very primitive */
X fall_down(mtmp);
X return(1);
X }
X
X /* if it is lying around someplace, we teleport to it */
X if(!carrying(AMULET_SYM)) {
X register struct obj *otmp;
X
X for(otmp = fobj; otmp; otmp = otmp->nobj)
X if(otmp->olet == AMULET_SYM && !otmp->spe) {
X if((u.ux != otmp->ox || u.uy != otmp->oy) &&
X !m_at(otmp->ox, otmp->oy)) {
X
X /* teleport to it and pick it up */
X mtmp->mx = otmp->ox;
X mtmp->my = otmp->oy;
X freeobj(otmp);
X mpickobj(mtmp, otmp);
X pmon(mtmp);
X return(0);
X }
X goto hithim;
X }
X return(0); /* we don't know where it is */
X }
Xhithim:
X if(rn2(2)) { /* hit - perhaps steal */
X
X /* if hit 1/20 chance of stealing amulet & vanish
X - amulet is on level 26 again. */
X if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd))
X && !rn2(20) && stealamulet(mtmp))
X ;
X }
X else inrange(mtmp); /* try magic */
X return(0);
X}
X
X#ifdef DGKMOD
X/* Check if a monster is carrying a particular item.
X */
Xstruct obj *
Xm_carrying(mtmp, type)
Xstruct monst *mtmp;
Xint type;
X{
X register struct obj *otmp;
X
X for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
X if(otmp->otyp == type)
X return(otmp);
X return((struct obj *) 0);
X}
X
X/* Remove an item from the monster's inventory.
X */
Xm_useup(mon, obj)
Xstruct monst *mon;
Xstruct obj *obj;
X{
X struct obj *otmp, *prev;
X
X prev = ((struct obj *) 0);
X for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
X if (otmp == obj) {
X if (prev)
X prev->nobj = obj->nobj;
X else
X mon->minvent = obj->nobj;
X free((char *) obj);
X break;
X }
X prev = otmp;
X }
X}
X
Xm_throw(x, y, dx, dy, range, obj)
Xregister int x,y,dx,dy,range; /* direction and range */
Xregister struct obj *obj;
X{
X register struct monst *mtmp;
X struct objclass *oclass = &objects[obj->otyp];
X char sym = obj->olet;
X int damage;
X extern char *exclam();
X
X bhitpos.x = x;
X bhitpos.y = y;
X
X if(sym) tmp_at(-1, sym); /* open call */
X while(range-- > 0) {
X bhitpos.x += dx;
X bhitpos.y += dy;
X if(mtmp = m_at(bhitpos.x,bhitpos.y)) {
X damage = index(mlarge, mtmp->data->mlet)
X ? oclass->wldam
X : oclass->wsdam;
X#ifdef KAA
X# ifdef KOPS
X if(obj->otyp == CREAM_PIE) damage = 0;
X# endif
X if(mtmp->data->ac + 8 <= rnd(20))
X miss(oclass->oc_name, mtmp);
X else {
X#endif
X hit(oclass->oc_name, mtmp, exclam(damage));
X mtmp->mhp -= damage;
X if(mtmp->mhp < 1) {
X pline("%s is killed!", (Blind) ? "It" : Monnam(mtmp));
X mondied(mtmp);
X }
X range = 0;
X#ifdef KAA
X# ifdef KOPS
X if(obj->otyp == CREAM_PIE) {
X
X pline("%s is blinded by the pie.", (Blind) ? "It" : Monnam(mtmp));
X if(mtmp->msleep) mtmp->msleep = 0;
X setmangry(mtmp);
X mtmp->mcansee = 0;
X mtmp->mblinded += rnd(25);
X if (mtmp->mblinded <= 0)
X mtmp->mblinded = 127;
X } else
X# endif
X if(obj->otyp == ENORMOUS_ROCK) {
X mksobj_at(ENORMOUS_ROCK, bhitpos.x, bhitpos.y);
X fobj->quan=1;
X stackobj(fobj);
X }
X }
X#endif
X }
X if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
X if (multi)
X nomul(0);
X#ifdef KAA
X/* For giants throwing rocks, the rock which hits you shouldn't disappear. */
X# ifdef KOPS
X/* Cream pies must disappear if they hit or miss. */
X { int hit, blindinc, thitu();
X if (!(hit = thitu(8, (obj->otyp != CREAM_PIE) ? rnd(oclass->wldam) : 0, oclass->oc_name))
X && obj->otyp != CREAM_PIE
X# else
X if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)
X# endif /* KOPS /**/
X || obj->otyp == ENORMOUS_ROCK) {
X#else
X if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)) {
X#endif /* KAA /**/
X mksobj_at(obj->otyp, u.ux, u.uy);
X fobj->quan = 1;
X stackobj(fobj);
X }
X#if defined(KAA) && defined(KOPS)
X if(hit && obj->otyp == CREAM_PIE) {
X if(!Blind) pline("Yeech! You've been creamed.");
X else pline("There's something sticky all over your face.");
X /* blindfold keeps pie filling out of your eyes */
X if (!Blindfolded) {
X u.ucreamed += (blindinc = rnd(25));
X Blinded += blindinc;
X seeoff(0);
X }
X }
X }
X#endif
X range = 0;
X }
X tmp_at(bhitpos.x, bhitpos.y);
X }
X tmp_at(-1, -1);
X}
X#endif
X
X/* Return 1 if it's OK for the monster to move as well as (throw,
X * zap, etc).
X */
Xinrange(mtmp)
Xregister struct monst *mtmp;
X{
X register schar tx,ty;
X#ifdef DGKMOD
X struct obj *otmp;
X register xchar x, y;
X#endif
X /* do nothing if cancelled (but make '1' say something) */
X if(mtmp->data->mlet != '1' && mtmp->mcan) return(1);
X
X /* spit fire only when both in a room or both in a corridor */
X#ifndef RPH
X if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return(1);
X#endif
X tx = u.ux - mtmp->mx;
X ty = u.uy - mtmp->my;
X#ifdef DGKMOD
X if ((!tx || !ty || abs(tx) == abs(ty)) /* straight line or diagonal */
X && movedist(tx, 0, ty, 0) < BOLT_LIM) {
X /* Check if there are any dead squares between. If so,
X * it won't be possible to shoot.
X */
X for (x = mtmp->mx, y = mtmp->my; x != u.ux || y != u.uy;
X x += sgn(tx), y += sgn(ty))
X if (!ACCESSIBLE(levl[x][y].typ))
X return(1);
X
X switch(mtmp->data->mlet) {
X#ifdef KOPS
X case 'O':
X#endif
X#ifdef KAA
X case '9':
X#endif
X case 'K':
X case 'C':
X /* If you're coming toward the monster, the monster
X * should try to soften you up with arrows. If you're
X * going away, you are probably hurt or running. Give
X * chase, but if you're getting too far away, throw.
X */
X x = mtmp->mx;
X y = mtmp->my;
X#ifdef KOPS
X otmp = (mtmp->data->mlet == 'O') ? m_carrying(mtmp, DART)
X# ifdef KAA
X : (mtmp->data->mlet == 'K') ? m_carrying(mtmp, CREAM_PIE)
X# endif
X#else
X otmp = (mtmp->data->mlet == 'K') ? m_carrying(mtmp, DART)
X#endif
X#ifdef KAA
X : (mtmp->data->mlet == '9') ? m_carrying(mtmp, ENORMOUS_ROCK)
X#endif
X : m_carrying(mtmp, CROSSBOW_BOLT);
X if (otmp && (!URETREATING(x,y)
X || !rn2(BOLT_LIM - movedist(x, u.ux, y, u.uy)))) {
X m_throw(mtmp->mx, mtmp->my, sgn(tx), sgn(ty),
X BOLT_LIM, otmp);
X if (!--otmp->quan )
X m_useup(mtmp, otmp);
X return(0);
X }
X break;
X#else
X if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)
X || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){
X switch(mtmp->mappearance) {
X#endif
X case 'D':
X /* spit fire in the direction of @ (not nec. hitting) */
X buzz(-1,mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
X break;
X#ifdef HARD
X case '&':
X demon_hit(mtmp);
X break;
X#endif
X case '1':
X if(rn2(WIZSHOT)) break;
X /* if you zapped wizard with wand of cancellation,
X he has to shake off the effects before he can throw
X spells successfully. Sometimes they fail anyway */
X if(mtmp->mcan ||
X#ifdef HARD
X !rn2(10)
X#else
X !rn2(2)
X#endif
X ) {
X if(canseemon(mtmp))
X pline("%s makes a gesture, then curses.",
X Monnam(mtmp));
X else pline("You hear mumbled cursing.");
X
X if(!rn2(3)) {
X mtmp->mspeed = 0;
X mtmp->minvis = 0;
X }
X if(!rn2(3)) mtmp->mcan = 0;
X
X } else {
X if(canseemon(mtmp)){
X if(!rn2(6) && !Invis) {
X pline("%s hypnotizes you.", Monnam(mtmp));
X nomul(-rn2(3) + 3); /* bug fix by ab@unido */
X break;
X } else
X pline("%s chants an incantation.", Monnam(mtmp));
X } else
X pline("You hear a mumbled incantation.");
X switch(rn2(Invis ? 5 : 6)) {
X case 0:
X /* create a nasty monster from a deep level */
X nasty();
X break;
X case 1:
X pline("\"Destroy the thief, my pets!\"");
X#ifdef HARD
X nasty();
X#endif
X aggravate(); /* aggravate all the monsters */
X /* fall into next case */
X case 2:
X if (flags.no_of_wizards == 1 && !rn2(3)) {
X /* if only 1 wizard, clone himself */
X pline("Double Trouble...");
X clonewiz(mtmp);
X }
X break;
X case 3:
X if(mtmp->mspeed == MSLOW) mtmp->mspeed = 0;
X else mtmp->mspeed = MFAST;
X break;
X case 4:
X mtmp->minvis = 1;
X break;
X case 5:
X /* Only if not Invisible */
X pline("You hear a clap of thunder!");
X /* shoot a bolt of fire or cold, or a sleep ray */
X buzz(-rnd(3),mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
X break;
X }
X }
X }
X if(u.uhp < 1) done_in_by(mtmp);
X }
X return(1);
X}
X
Xaggravate()
X{
X register struct monst *mtmp;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X mtmp->msleep = 0;
X if(mtmp->mfroz && !rn2(5))
X mtmp->mfroz = 0;
X }
X}
X
Xclonewiz(mtmp)
Xregister struct monst *mtmp;
X{
X register struct monst *mtmp2;
X
X if(mtmp2 = makemon(PM_WIZARD, u.ux, u.uy)) {
X flags.no_of_wizards = 2;
X mtmp2->mtame = mtmp2->mpeaceful = 0;
X unpmon(mtmp2);
X mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)];
X pmon(mtmp2);
X }
X}
X
Xnasty() {
X
X#ifdef HARD
X register struct monst *mtmp;
X struct monst *mkmon_at();
X register int i, nastynum, tmp;
X
X nastynum = sizeof(nasties) - 1;
X tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */
X
X for(i = rnd(tmp); i > 0; --i)
X if((mtmp = mkmon_at(nasties[rn2(nastynum)], u.ux, u.uy))) {
X
X mtmp->msleep = 0;
X mtmp->mpeaceful = 0;
X }
X#else
X (void) makemon((struct permonst *)0, u.ux, u.uy);
X#endif
X return(0);
X}
X
X#ifdef HARD
X/* Here, we make trouble for the poor shmuck who actually */
X/* managed to do in the Wizard. */
Xintervene() {
X
X switch(rn2(6)) {
X
X case 0:
X case 1: pline("You feel vaguely nervous.");
X break;
X case 2: pline("You notice a black glow surrounding you.");
X rndcurse();
X break;
X case 3: aggravate();
X break;
X case 4: nasty();
X break;
X case 5: resurrect();
X break;
X }
X}
X
Xwizdead(mtmp)
Xregister struct monst *mtmp;
X{
X flags.no_of_wizards--;
X if(! u.udemigod) {
X
X u.udemigod = TRUE;
X u.udg_cnt = rn1(250, 50);
X
X /* Make the wizard meaner the next time he appears */
X mtmp->data->mlevel++;
X mtmp->data->ac--;
X } else
X mtmp->data->mlevel++;
X}
X
X
X/* Let's resurrect the wizard, for some unexpected fun. */
Xresurrect() {
Xregister struct monst *mtmp;
X
X if(mtmp = makemon(PM_WIZARD, u.ux, u.uy)) {
X
X mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0;
X flags.no_of_wizards++;
X pline("A voice booms out...");
X pline("\"So you thought you could kill me, fool.\"");
X }
X
X}
X#endif /* HARD /**/
END_OF_wizard.c
if test 11805 -ne `wc -c