/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */

#include	"hack.h"
#ifdef QUEST
setgd(/* mtmp */) /* struct monst *mtmp; */ {}
gd_move() { return(2); }
gddead(mtmp) struct monst *mtmp; {}
invault(){}

#else


extern struct monst *makemon();
#define	VAULT	6
#define	FCSIZ	(ROWNO+COLNO)
struct fakecorr {
	xchar fx,fy,ftyp;
};

struct egd {
	int fcbeg, fcend;	/* fcend: first unused pos */
	xchar gdx, gdy;		/* goal of guard's walk */
	unsigned gddone:1;
	struct fakecorr fakecorr[FCSIZ];
};

struct permonst pm_guard =
	{ "guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd) };

struct monst *guard;
int gdlevel;
#define	EGD	((struct egd *)(&(guard->mextra[0])))

restfakecorr(){
register int fcx,fcy,fcbeg;
register struct rm *crm;

	while((fcbeg = EGD->fcbeg) < EGD->fcend) {
		fcx = EGD->fakecorr[fcbeg].fx;
		fcy = EGD->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->fakecorr[fcbeg].ftyp;
		if(!crm->typ) crm->seen = 0;
		newsym(fcx,fcy);
		EGD->fcbeg++;
	}
	/* it seems he left the corridor - let the guard disappear */
	mondead(guard);
	guard = 0;
}

setgd(){
register struct monst *mtmp;
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){
		guard = mtmp;
		gdlevel = dlevel;
		return;
	}
	guard = 0;
}

invault(){
register int tmp = inroom(u.ux, u.uy);
	if(tmp < 0 || rooms[tmp].rtype != VAULT) {
		u.uinvault = 0;
		return;
	}
	if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) {
	char buf[BUFSZ];
	register int x,y,dx,dy,gx,gy;

		/* first find the goal for the guard */
		for(dy = 0; dy < ROWNO; dy++)
		  for(y = u.uy-dy; y <= u.uy+dy; y++) {
		    if(y > u.uy-dy) y = u.uy+dy;
		    if(y < 0 || y > ROWNO-1) continue;
		    for(x = u.ux; x < COLNO; x++)
			if(levl[x][y].typ == CORR) goto fnd;
		    for(x = u.ux-1; x > 0; x--)
			if(levl[x][y].typ == CORR) goto fnd;
		}
		impossible();
		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 > DOOR) {
			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(&pm_guard,x,y))) return;
		guard->isgd = guard->mpeaceful = 1;
		EGD->gddone = 0;
		gdlevel = dlevel;
		if(!cansee(guard->mx, guard->my)) {
			mondead(guard);
			guard = 0;
			return;
		}
		EGD->gdx = gx;
		EGD->gdy = gy;
		EGD->fcbeg = 0;
		EGD->fakecorr[0].fx = x;
		EGD->fakecorr[0].fy = y;
		EGD->fakecorr[0].ftyp = levl[x][y].typ;
		levl[x][y].typ = DOOR;
		EGD->fcend = 1;

		pline("Suddenly one of the Vault's guards enters!");
		pmon(guard);
		pline("\"Hello stranger, who are you?\" - ");
		getlin(buf);
		clrlin();
		pline("\"I don't know you.\"");
		if(!u.ugold) pline("\"Please follow me.\"");
		else {
		    pline("\"Most likely all that gold was stolen from this vault.\"");
		    pline("\"Please drop your gold (say d$ ) and follow me.\"");
		}
	}
}

gd_move(){
register int x,y,dx,dy,gx,gy,nx,ny,tmp;
register struct fakecorr *fcp;
register struct rm *crm;
	if(!guard || gdlevel != dlevel){
		pline("Where is the guard?");
		impossible();
		return(2);	/* died */
	}
	if(u.ugold || dist(guard->mx,guard->my) > 2 || EGD->gddone){
		restfakecorr();
		return(0);	/* didnt move */
	}
	x = guard->mx;
	y = guard->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) if(nx != x || ny != y)
	    if(isok(nx,ny))
	    if((tmp = (crm = &levl[nx][ny])->typ) >= SDOOR) {
		register int i;
		for(i = EGD->fcbeg; i < EGD->fcend; i++)
			if(EGD->fakecorr[i].fx == nx &&
			   EGD->fakecorr[i].fy == ny)
				goto nextnxy;
		if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT)
			goto nextnxy;
		/* seems we found a good place to leave him alone */
		EGD->gddone = 1;
		if(tmp >= DOOR) goto newpos;
		crm->typ = (tmp == SCORR) ? CORR : DOOR;
		goto proceed;
	nextnxy:	;
	}
	nx = x;
	ny = y;
	gx = EGD->gdx;
	gy = EGD->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((tmp = (crm = &levl[nx][ny])->typ) != 0) {
	/* in view of the above we must have  tmp < SDOOR */
	/* must be a wall here */
		if(isok(nx+nx-x,ny+ny-y) && levl[nx+nx-x][ny+ny-y].typ > DOOR){
			crm->typ = DOOR;
			goto proceed;
		}
		if(dy && nx != x) {
			nx = x; ny = y+dy; dx = 0;
			continue;
		}
		if(dx && ny != y) {
			ny = y; nx = x+dx; dy = 0;
			continue;
		}
		/* I don't like this, but ... */
		crm->typ = DOOR;
		goto proceed;
	}
	crm->typ = CORR;
proceed:
	fcp = &(EGD->fakecorr[EGD->fcend]);
	if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow");
	fcp->fx = nx;
	fcp->fy = ny;
	fcp->ftyp = tmp;
newpos:
	if(EGD->gddone) nx = ny = 0;
	guard->mx = nx;
	guard->my = ny;
	pmon(guard);
	restfakecorr();
	return(1);
}

gddead(){
	guard = 0;
}


#endif QUEST
