ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/vault.c

This is vault.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)vault.c	3.0	88/10/25
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

#include "hack.h"
#include "vault.h"

static void FDECL(restfakecorr,(struct monst *));
OSTATIC boolean FDECL(in_vault,(int,int));
OSTATIC struct monst *NDECL(findgd);
static boolean FDECL(in_fcorridor, (struct monst *,int,int));

#ifdef OVLB

static void
restfakecorr(grd) 
register struct monst *grd;
{
	register int fcx, fcy, fcbeg;
	register struct rm *crm;

	while((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
		fcx = EGD(grd)->fakecorr[fcbeg].fx;
		fcy = EGD(grd)->fakecorr[fcbeg].fy;
		if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) ||
		   m_at(fcx,fcy))
			return;
		crm = &levl[fcx][fcy];
		crm->typ = EGD(grd)->fakecorr[fcbeg].ftyp;
		if(!crm->typ) crm->seen = 0;
		newsym(fcx,fcy);
		if(cansee(fcx,fcy)) prl(fcx,fcy);
		EGD(grd)->fcbeg++;
	}
	/* it seems he left the corridor - let the guard disappear */
	mongone(grd);
}

static boolean
in_fcorridor(grd, x, y)
register struct monst *grd;
int x, y; 
{
	register int fci;

	for(fci = EGD(grd)->fcbeg; fci < EGD(grd)->fcend; fci++)
		if(x == EGD(grd)->fakecorr[fci].fx &&
				y == EGD(grd)->fakecorr[fci].fy)
			return(TRUE);
	return(FALSE);
}

XSTATIC 
struct monst *
findgd() {

	register struct monst *mtmp;

	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
	    if(mtmp->isgd && EGD(mtmp)->gdlevel == dlevel)
		return(mtmp);
	return((struct monst *)0);
}

#endif /* OVLB */
#ifdef OVL0

XSTATIC
boolean
in_vault(x, y)
int x, y;
{
    register int roomno = inroom(x, y);

    if(roomno < 0) return(FALSE);
    return(rooms[roomno].rtype == VAULT);
}

void
invault() {

#ifdef BSD_43_BUG
    int dummy;		/* hack to avoid schain botch */
#endif
    struct monst *guard;

    if(!in_vault(u.ux, u.uy)) {
	u.uinvault = 0;
	return;
    }

    guard = findgd();
    if(++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
	char buf[BUFSZ];
	register int x, y, dd, gx, gy;

	/* first find the goal for the guard */
	for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) {
	  for(y = u.uy-dd; y <= u.uy+dd; y++) {
	    if(y < 0 || y > ROWNO-1) continue;
	    for(x = u.ux-dd; x <= u.ux+dd; x++) {
	      if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd)
		x = u.ux+dd;
	      if(x < 0 || x > COLNO-1) continue;
	      if(levl[x][y].typ == CORR) goto fnd;
	    }
	  }
	}
	impossible("Not a single corridor on this level??");
	tele();
	return;
fnd:
	gx = x; gy = y;

	/* next find a good place for a door in the wall */
	x = u.ux; y = u.uy;
	while(levl[x][y].typ == ROOM) {
		register int dx,dy;

		dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
		dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
		if(abs(gx-x) >= abs(gy-y))
			x += dx;
		else
			y += dy;
	}

	/* make something interesting happen */
	if(!(guard = makemon(&mons[PM_GUARD], x, y))) return;
	guard->isgd = 1;
	guard->mpeaceful = 1;
	EGD(guard)->gddone = 0;
	EGD(guard)->ogx = x;
	EGD(guard)->ogy = y;
	EGD(guard)->gdlevel = dlevel;
	EGD(guard)->warncnt = 0;

	if(!cansee(guard->mx, guard->my)) {
		mongone(guard);
		return;
	}

	reset_faint();			/* if fainted - wake up */
	pline("Suddenly one of the Vault's guards enters!");
	pmon(guard);
	stop_occupation();		/* if occupied, stop it *now* */
	do {
		pline("\"Hello stranger, who are you?\" - ");
		getlin(buf);
	} while (!letter(buf[0]));

	if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) {
		verbalize("Oh, yes, of course.  Sorry to have disturbed you.");
		mongone(guard);
		return;
	}
	clrlin();
	verbalize("I don't know you.");
	if(!u.ugold)
	    verbalize("Please follow me.");
	else {
	    verbalize("Most likely all that gold was stolen from this vault.");
	    verbalize("Please drop that gold and follow me.");
	}
	EGD(guard)->gdx = gx;
	EGD(guard)->gdy = gy;
	EGD(guard)->fcbeg = 0;
	EGD(guard)->fakecorr[0].fx = x;
	EGD(guard)->fakecorr[0].fy = y;
	EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
	levl[x][y].typ = DOOR;
	levl[x][y].doormask = D_NODOOR;
	EGD(guard)->fcend = 1;
	EGD(guard)->warncnt = 1;
    }
}

#endif /* OVL0 */
#ifdef OVLB

/*
 * return  1: he moved,  0: he didn't,  -1: let m_move do it,  -2: died
 */
int
gd_move(grd)
register struct monst *grd;
{
	int x, y, nx, ny, m, n;
	int dx, dy, gx, gy, i, fci;
	uchar typ;
	struct fakecorridor *fcp;
	register struct rm *crm;
	register struct gold *gold;
	register boolean goldincorridor = FALSE;

#ifdef __GNULINT__
	m = n = 0;
#endif
	if(EGD(grd)->gdlevel != dlevel) return(-1);
	if(!grd->mpeaceful && in_vault(grd->mx, grd->my) &&
			!in_vault(u.ux, u.uy)) {
		rloc(grd);
		goto letknow;
	}
	if(!grd->mpeaceful) return(-1);
	if(abs(EGD(grd)->ogx - grd->mx) > 1 || 
			abs(EGD(grd)->ogy - grd->my) > 1)
		return(-1);	/* teleported guard - treat as monster */
	if(EGD(grd)->fcend == 1) {
	    if(in_vault(u.ux, u.uy) && 
			(u.ugold || um_dist(grd->mx, grd->my, 1))) {
		if(EGD(grd)->warncnt == 3)
			pline("\"Again, %sfollow me!\"", 
				u.ugold ? "drop that gold and " : "");
		if(EGD(grd)->warncnt == 6) {
			register int m = grd->mx, n = grd->my;
			verbalize("You've been warned, knave!");
			mnexto(grd);
			levl[m][n].typ = EGD(grd)->fakecorr[0].ftyp;
			newsym(m,n);
			if(cansee(m,n)) prl(m,n);
			grd->mpeaceful = 0;
			return(-1);
		}
		/* not fair to get mad when (s)he's fainted */
		if(!is_fainted()) EGD(grd)->warncnt++;
		return(0);
	    }
	    if(!in_vault(u.ux,u.uy) && u.ugold) { /* player teleported */
		register int m = grd->mx, n = grd->my;
		rloc(grd);
		levl[m][n].typ = EGD(grd)->fakecorr[0].ftyp;
		newsym(m,n);
		if(!Blind) prl(m,n);
		grd->mpeaceful = 0;
letknow:
		if(!cansee(grd->mx, grd->my))
		    You("hear the shrill sound of a guard's whistle.");
		else
		    You(um_dist(grd->mx, grd->my, 2) ?
			"see an angry %s approaching." :
			"are confronted by an angry %s.",
			lmonnam(grd)+4);
		return(-1);
	    }
	}
	if(u.ugold && (in_fcorridor(grd, u.ux, u.uy) || /*cover 'blind' spot*/
		    (EGD(grd)->fcend > 1 && in_vault(u.ux, u.uy)))) {
		if(EGD(grd)->warncnt < 6) {
			EGD(grd)->warncnt = 6;
			verbalize("Drop all your gold, scoundrel!");
			return(0);
		} else {
			verbalize("So be it, rogue!");
			grd->mpeaceful = 0;
			return(-1);
		}	
	} 
	for(fci = EGD(grd)->fcbeg; fci < EGD(grd)->fcend; fci++)
	    if(g_at(EGD(grd)->fakecorr[fci].fx, EGD(grd)->fakecorr[fci].fy)){
		m = EGD(grd)->fakecorr[fci].fx;
		n = EGD(grd)->fakecorr[fci].fy;
		goldincorridor = TRUE; 
	    }
	if(goldincorridor && !EGD(grd)->gddone) {
		x = grd->mx;
		y = grd->my;
		if(m == x && n == y) mpickgold(grd);
		else if(m == u.ux && n == u.uy) {
		    gold = g_at(u.ux, u.uy);
 		    grd->mgold += gold->amount;
		    freegold(gold);
		} else {
		    /* just for insurance... */
		    if(MON_AT(m, n) && m != grd->mx && n != grd->my) {
			verbalize("Out of my way, scum!");
			rloc(m_at(m, n));
		    }
		    remove_monster(grd->mx, grd->my);
		    place_monster(grd, m, n);
		    pmon(grd);
		    mpickgold(grd);
		}
		pline("The %s%s picks the gold.", lmonnam(grd)+4,
				grd->mpeaceful ? " calms down and" : "");
		if(x != grd->mx || y != grd->my) {
		    remove_monster(grd->mx, grd->my);
		    place_monster(grd, x, y);
		    pmon(grd);
		}
		goldincorridor = FALSE;
		if(!grd->mpeaceful) return(-1);
		else {
		    EGD(grd)->warncnt = 5;
		    return(0);
		}
	}
	if(um_dist(grd->mx, grd->my, 1) || EGD(grd)->gddone) {
		restfakecorr(grd);
		return(0);	/* didn't move */
	}
	x = grd->mx;
	y = grd->my;
	/* look around (hor & vert only) for accessible places */
	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
	  if((nx == x || ny == y) && (nx != x || ny != y) && isok(nx, ny)) {

	    typ = (crm = &levl[nx][ny])->typ;
	    if(!IS_STWALL(typ) && !IS_POOL(typ)) {

		for(i = EGD(grd)->fcbeg; i < EGD(grd)->fcend; i++)
		    if(EGD(grd)->fakecorr[i].fx == nx && 
				EGD(grd)->fakecorr[i].fy == ny)
			goto nextnxy;

		if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT)
			continue;

		/* seems we found a good place to leave him alone */
		EGD(grd)->gddone = 1;
		if(ACCESSIBLE(typ)) goto newpos;
#ifdef STUPID
		if (typ == SCORR)
		    crm->typ = CORR;
		else
		    crm->typ = DOOR;
#else
		crm->typ = (typ == SCORR) ? CORR : DOOR;
#endif
		if(crm->typ == DOOR) crm->doormask = D_NODOOR;
		goto proceed;
	    }
	  }
nextnxy:	;
	}
	nx = x;
	ny = y;
	gx = EGD(grd)->gdx;
	gy = EGD(grd)->gdy;
	dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
	dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
	if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy;

	while((typ = (crm = &levl[nx][ny])->typ) != 0) {
	/* in view of the above we must have IS_WALL(typ) or typ == POOL */
	/* must be a wall here */
		if(isok(nx+nx-x,ny+ny-y) && !IS_POOL(typ) &&
		    SPACE_POS(levl[nx+nx-x][ny+ny-y].typ)){
			crm->typ = DOOR;
			crm->doormask = D_NODOOR;
			goto proceed;
		}
		if(dy && nx != x) {
			nx = x; ny = y+dy;
			continue;
		}
		if(dx && ny != y) {
			ny = y; nx = x+dx; dy = 0;
			continue;
		}
		/* I don't like this, but ... */
		crm->typ = DOOR;
		crm->doormask = D_NODOOR;
		goto proceed;
	}
	crm->typ = CORR;
proceed:
	if(cansee(nx,ny)) {
		mnewsym(nx,ny);
		prl(nx,ny);
	}
	fcp = &(EGD(grd)->fakecorr[EGD(grd)->fcend]);
	if(EGD(grd)->fcend++ == FCSIZ) panic("fakecorr overflow");
	fcp->fx = nx;
	fcp->fy = ny;
	fcp->ftyp = typ;
newpos:
	if(EGD(grd)->gddone) {
		/* The following is a kluge.  We need to keep     */
		/* the guard around in order to be able to make   */
		/* the fake corridor disappear as the player      */
		/* moves out of it, but we also need the guard    */
		/* out of the way.  We send the guard to never-   */
		/* never land.  We set ogx ogy to mx my in order  */
		/* to avoid a check at the top of this function.  */
		/* At the end of the process, the guard is killed */
		/* in restfakecorr().				  */
		remove_monster(grd->mx, grd->my);
		place_monster(grd, 0, 0);
		EGD(grd)->ogx = grd->mx;
		EGD(grd)->ogy = grd->my;
		restfakecorr(grd);
		if(in_fcorridor(grd, u.ux, u.uy) || cansee(grd->mx, grd->my))
		    pline("Suddenly, the guard disappears.");
		return(-2);
	}
	EGD(grd)->ogx = grd->mx;	/* update old positions */
	EGD(grd)->ogy = grd->my;
	remove_monster(grd->mx, grd->my);
	place_monster(grd, nx, ny);
	pmon(grd);
	restfakecorr(grd);
	return(1);
}

/* Routine when dying or quitting with a vault guard around */
void
paygd() {

	struct monst *guard;
	register int i;
	int gx,gy;
	char buf[BUFSZ];

	guard = findgd();
	if (!u.ugold || !guard) return;

	if (u.uinvault) {
	    Your("%ld zorkmid%s goes into the Magic Memory Vault.",
		u.ugold, plur(u.ugold));
	    mkgold(u.ugold, u.ux, u.uy);
	    u.ugold = 0L;
	} else {
	    if(guard->mpeaceful) { /* he has no "right" to your gold */
		mongone(guard);
		return;
	    }
	    mnexto(guard);
	    pmon(guard);
	    pline("%s remits your gold to the vault.", Monnam(guard));
	    for(i=0; i<=nroom; i++)
		if (rooms[i].rtype==VAULT) break;
	    if (i > nroom) {
		impossible("no vault?");
		return;
	    }
	    gx = rooms[i].lx + rn2(2);
	    gy = rooms[i].ly + rn2(2);
	    mkgold(u.ugold, gx, gy);
	    u.ugold = 0L;
	    Sprintf(buf,
		"To Croesus: here's the gold recovered from the %s %s...",
		player_mon()->mname, plname);
	    make_engr_at(gx, gy, buf);
	}
	mongone(guard);
}

boolean
gd_sound() {  /* prevent "You hear footsteps.." when inappropriate */
	register struct monst *grd = findgd();

	return(grd == (struct monst *)0);
}

#endif /* OVLB */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.