|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 27887 (0x6cef)
Types: TextFile
Names: »rooms.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Rog-O-Matic/rooms.c«
/*
* rooms.c: Rog-O-Matic XIV (CMU) Thu Jan 31 20:22:14 1985 - mlm
* Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin
*
* Contains functions which deal with the geometry of
* the dungeon levels, rooms, and passages.
*/
# include <curses.h>
# include <ctype.h>
# include "types.h"
# include "globals.h"
# define sign(x) ((x)?(x)>0?1:-1:0)
# define EXPLORED 01
# define HASROOM 02
int levelmap[9];
/*
* newlevel: Clear old data structures and set up for a new level.
*/
newlevel ()
{ int i, j;
initstufflist (); /* Delete the list of items */
droppedscare = 0; /* Old stuff gone */
maxobj = 22; /* Reset maximum # of objs */
newmonsterlevel (); /* Do new monster stuff */
exploredlevel = 0; /* New level */
aggravated = 0; /* Old monsters gone */
beingstalked = 0; /* Old monsters gone */
darkdir = NONE; darkturns = 0; /* Not arching old monster */
stairrow = NONE; staircol = 0; /* Get rid of old stairs */
missedstairs = 0;
newdoors = doorlist; /* Clear door list */
goalr = goalc = NONE; /* Old goal invalid */
trapr = trapc = NONE; /* Old traps are gone */
foundarrowtrap = foundtrapdoor = 0; /* Old traps are gone */
teleported = 0; /* Not teleported yet */
attempt = 0; /* Haven't search for doors yet */
usesynch = 0; /* Force a new inventory */
compression = Level < 13; /* Set move compression */
newarmor = newweapon = newring = 1; /* Reevaluate our items */
foundnew (); /* Reactivate all rules */
/*
* Clear the highlevel map
*/
for (i = 0; i < 9; i++) levelmap[i] = 0;
for (i = 0; i < 9; i ++) for (j = 0; j < 9; j ++) zonemap[i][j] = (i == j);
zone = NONE;
/*
* Clear the lowlevel map
*/
for (i = 1; i < 23; i++)
for (j = 0; j < 80; j++) /* Forall screen positions */
{ scrmap[i][j] = 0;
timessearched[i][j] = 0;
updatepos (screen[i][j], i, j);
}
atrow0 = atrow;
atcol0 = atcol;
set (ROOM);
setnewgoal ();
timestosearch = k_door / 5;
}
/* routine to find the rooms:
* room[i] = 0 -- nothing in sector
* ROOM -- room found already
* CANGO -- halls, but no room in sector
*/
static struct {int top,bot,left,right;} bounds[9]=
/* top bot left right */
/*0*/ {{ 1, 6, 0, 25},
/*1*/ { 1, 6, 27, 51},
/*2*/ { 1, 6, 53, 79},
/*3*/ { 8, 14, 0, 25},
/*4*/ { 8, 14, 27, 51},
/*5*/ { 8, 14, 53, 79},
/*6*/ {16, 22, 0, 25},
/*7*/ {16, 22, 27, 51},
/*8*/ {16, 22, 53, 79}};
markmissingrooms ()
{ register rm,i,j;
for (rm=0; rm<9; ++rm)
{ room[rm]=0;
for (i=bounds[rm].top; i<=bounds[rm].bot; ++i)
for (j=bounds[rm].left; j<=bounds[rm].right; ++j)
if (onrc(ROOM,i,j)) { room[rm]=ROOM; goto nextroom; }
else if (onrc(BEEN,i,j)) { room[rm]=BEEN; goto nextroom; }
nextroom: ;
}
}
/*
* whichroom: Return the zone number of a square (0..8) or -1, as follows:
*
* room 0 | room 1 | room 2
* -------+--------+-------
* room 3 | room 4 | room 5
* -------+--------+-------
* room 6 | room 7 | room 8
*/
int whichroom (r,c)
register int r,c;
{ register int rm;
for (rm=0; rm<9; ++rm)
if (r >= bounds[rm].top && r <= bounds[rm].bot &&
c >= bounds[rm].left && c <= bounds[rm].right)
return(rm);
return (-1);
}
/*
* nametrap: look around for a trap and set its type.
*/
nametrap (ttype, standingonit)
int ttype, standingonit;
{ register int i, r, c, tdir = NONE, monsteradj = 0;
if (standingonit)
{ r=atrow; c=atcol; }
else if (blinded) /* Cant see, dont bother */
return;
else
{ /* Look all around and see what there is next to us */
for (i = 0; i < 8; i++)
{ r = atdrow(i); c = atdcol(i);
if (seerc ('^', r, c)) /* Aha, a trap! */
{ if (tdir != NONE) return; /* Second trap, ambigous case */
else tdir = i; /* First trap, record direction */
}
else if (isupper(screen[r][c])) /* Trap could be under monster */
monsteradj++;
}
/* See one trap, set (r,c) to the trap location */
if (tdir != NONE)
{ r = atdrow(tdir); c = atdcol(tdir); }
/* See no traps, if there is a monster adjacent, he could be on it */
else if (monsteradj)
return;
/* Cant ever sit on a trap door or a teleport trap */
else if (ttype == TRAPDOR || ttype == TELTRAP)
return;
/* Cant see trap anywhere else, we must be sitting on it */
else
{ r = atrow; c = atcol; }
}
/* Record last arror trap found (for cheating against 3.6) */
if (ttype == ARROW) { foundarrowtrap = 1; trapr = r; trapc = c; }
else if (ttype == TRAPDOR) { foundtrapdoor = 1; }
/* If a trapdor, reactivate rules */
if (ttype == TRAPDOR) foundnew ();
/* Set the trap type */
unsetrc (TELTRAP|TRAPDOR|BEARTRP|GASTRAP|ARROW|DARTRAP, r, c);
setrc (TRAP | ttype, r, c);
}
/*
* findstairs: Look for STAIRS somewhere and set the stairs to that square.
*/
findstairs (notr, notc)
int notr, notc;
{ register int r, c;
stairrow = staircol = NONE;
for (r = 2; r < 22; r++)
for (c = 1; c < 79; c++)
if ((seerc ('%', r, c) || onrc (STAIRS, r, c)) &&
r != notr && c != notc)
{ setrc (STAIRS, r, c); stairrow = r; staircol = c; }
}
/*
* downright: Find a square from which we cannot go down or right.
*/
downright (drow, dcol)
int *drow, *dcol;
{ register int i=atrow, j=atcol;
while (i < 23 && j < 79)
{ if (onrc (CANGO, i, j+1)) j++;
else if (onrc (CANGO, i+1, j)) i++;
else { *drow = i; *dcol = j; return (1); }
}
return (0);
}
/*
* Try to light up the situation
*/
lightroom ()
{ int obj;
/* not in a room nor on door or room lit?? */
if (blinded || !darkroom ())
return (0);
if ((obj = havenamed (scroll, "light")) >=0 && reads (obj))
return (1);
if ((obj = havewand ("light")) >=0 && point (obj, 0))
return (1);
return (0);
}
/*
* darkroom: Are we in a dark room?
*/
darkroom ()
{ register int dir, dir2, drow, dcol;
if (!on (DOOR | ROOM))
return (0);
for (dir=0; dir<8; dir++)
if (seerc ('.', (drow = atdrow(dir)), (dcol = atdcol(dir))))
for (dir2=0; dir2<8; dir2++)
if (seerc (' ', drow+deltr[dir2], dcol+deltc[dir2]))
return (1);
return (0);
}
/*
* currentrectangle: infer room extent based on clues from walls
* NOTE: When a door appears on the screen, currentrectangle
* should be re-initialised. LGCH
*/
# define fT 1
# define fB 2
# define fL 4
# define fR 8
static int curt, curb, curl, curr;
currentrectangle ()
{ int flags = fT + fB + fL + fR, r, c, any = 1;
/*
* DEFINITION: curt is the current top of the room. This is the
* topmost row which is known to be a room square. The wall location
* is therefore curt-1. curb: bottom. curl: left. curr: right
* Since we discover new info when we step on a square on the
* extremity of the known room area, the following statement was
* modified by LGCH to use >=, <= instead of >, <
*/
if ((atrow >= curb || atrow <= curt || atcol <= curl || atcol >= curr)
&& on (ROOM))
{ curt = curb = atrow;
curl = curr = atcol;
while (any)
{ any = 0;
if (flags & fT)
for (r = curt - 1, c = curl - 1; c <= curr + 1; c++)
if (onrc (ROOM, r, c)) { curt--; any = 1; break; }
else if (seerc ('-', r, c)) { flags &= ~fT; break; }
if (flags & fB)
for (r = curb + 1, c = curl - 1; c <= curr + 1; c++)
if (onrc (ROOM, r, c)) { curb++; any = 1; break; }
else if (seerc ('-', r, c)) { flags &= ~fB; break; }
if (flags & fL)
for (r = curt, c = curl - 1; r <= curb; r++)
if (onrc (ROOM, r, c)) { curl--; any = 1; break; }
else if (seerc ('|', r, c)) { flags &= ~fL; break; }
if (flags & fR)
for (r = curt, c = curr + 1; r <= curb; r++)
if (onrc (ROOM, r, c)) { curr++; any = 1; break; }
else if (seerc ('|', r, c)) { flags &= ~fR; break; }
}
for (r = curt; r <= curb; r++)
for (c = curl; c <= curr; c++)
{ setrc (ROOM + CANGO, r, c);
unsetrc (HALL, r, c);
}
# define ckdoor(FLAG, NODOOR, STATIC, INC, S1, S2, I1, I2) \
if (0 == (flags & FLAG)) \
{ any = 0; \
if (NODOOR) any = 1; \
else \
for (STATIC = S2, INC = I1; INC <= I2; INC++) \
if (onrc (DOOR, r, c)) { any = 1; break; } \
if (any) \
{ for (STATIC = S2, INC = I1; INC <= I2; INC++) \
setrc (SEEN+WALL, r, c); \
for (STATIC = S1, INC = I1; INC <= I2; INC++) \
setrc (BOUNDARY, r, c); /* Room boundary LGCH */ \
} \
else \
{ for (STATIC = S2, INC = I1; INC <= I2; INC++) \
setrc (BOUNDARY, r, c); /* Unseen wall or door LGCH */ \
} \
}
if (curt <= 2) flags &= ~fT; /* Wall must be on screen edge */
if (curb >= 21) flags &= ~fB;
if (curl <= 1) flags &= ~fL;
if (curr >= 78) flags &= ~fR;
ckdoor (fT, curt<6, r, c, curt, curt-1, curl-1, curr+1)
ckdoor (fB, curb>17, r, c, curb, curb+1, curl-1, curr+1)
ckdoor (fL, curl<24, c, r, curl, curl-1, curt-1, curb+1)
ckdoor (fR, curr>56, c, r, curr, curr+1, curt-1, curb+1)
/* Fill in the corners of the room without seeing them */
/* Prevents looking at corners to find missing doors */
if ((flags & fT+fR) == 0) setrc (SEEN + WALL, curt-1, curr+1);
if ((flags & fT+fL) == 0) setrc (SEEN + WALL, curt-1, curl-1);
if ((flags & fB+fR) == 0) setrc (SEEN + WALL, curb+1, curr+1);
if ((flags & fB+fL) == 0) setrc (SEEN + WALL, curb+1, curl-1);
}
}
clearcurrect()
{ curl = curr = curt = curb = 0;
}
/*
* updateat: We have moved, record results of our passge...
*
* Bug if monster is chasing us: +######A@
* Bug if teleported horiz or vert. Infers cango
*/
updateat ()
{ register int dr = atrow - atrow0, dc = atcol - atcol0;
register int i, r, c;
int dist, newzone, sum;
/*
* Record passage from one zone to the next
*/
newzone = whichroom (atrow, atcol);
if (newzone != NONE && zone != NONE && newzone != zone)
{ new_arch = 1;
zonemap[zone][newzone] = zonemap[newzone][zone] = 1;
if ((levelmap[zone] & (EXPLORED | HASROOM)) == 0)
{ for (i = 0, sum = 0; i < 9; i++) sum += zonemap[zone][i];
if (sum >= 3) markexplored (atrow0, atcol0);
}
}
if (newzone != NONE)
zone = newzone;
/*
* Check for teleport, else if we moved multiple squares, mark them as BEEN
*/
if (direc (dr, dc) != movedir || dr && dc && abs(dr) != abs(dc))
teleport ();
else
{ dist = (abs(dr)>abs(dc)) ? abs(dr) : abs(dc);
dr = (dr > 0) ? 1 : (dr < 0) ? -1 : 0;
dc = (dc > 0) ? 1 : (dc < 0) ? -1 : 0;
for (r = atrow0, c = atcol0;
dist >= 0 && (onrc(DOOR,r,c) || !onrc(WALL,r,c));
r += dr, c += dc, dist--)
{ setrc (BEEN | SEEN | CANGO, r, c);
if (!onrc (TRAP, r, c)) setrc (SAFE, r, c);
}
}
/* Mark surrounding area according to what we see */
if (!on (HALL | DOOR | ROOM) && !blinded)
{ int i, rr, cc;
int halls = 0, rooms = 0, rm;
char *terrain = "nothing";
for (i=0; i<8; i += 2)
{ rr = atdrow(i); cc = atdcol(i);
if (onrc (HALL, rr, cc))
halls++;
else if (onrc (ROOM, rr, cc))
rooms++;
}
if (seerc ('|', atrow-1, atcol) && seerc ('|', atrow+1, atcol) ||
seerc ('-', atrow, atcol-1) && seerc ('-', atrow, atcol+1))
{ set (DOOR | SAFE); unset (HALL | ROOM); terrain = "door";
if ((rm = whichroom (atrow, atcol)) != NONE) levelmap[rm] |= HASROOM;
}
else if (halls > 0)
{ set (HALL | SAFE); unset (DOOR | ROOM); terrain = "hall"; }
else if (rooms > 0)
{ set (ROOM); unset (HALL | DOOR); terrain = "room"; }
else
return;
dwait (D_INFORM, "Inferring %s at %d,%d.", terrain, atrow, atcol);
}
else if (on (DOOR | ROOM) && !isexplored (atrow, atcol) && !darkroom ())
{ markexplored (atrow, atcol);
}
}
/*
* updatepos: Something changed on the screen, update the screen map
*/
updatepos (ch, row, col)
register char ch;
register int row, col;
{ char oldch = screen[row][col], *monster, functionchar();
int seenbefore = onrc (EVERCLR, row, col);
int couldgo = onrc (CANGO, row, col);
int unseen = !onrc (SEEN, row, col);
int rm = whichroom (row, col);
if (mlistlen && ch != oldch) deletemonster (row, col);
if (unseen) { foundnew (); }
switch (ch)
{ case '@':
setrc (SEEN | CANGO | BEEN | EVERCLR, row, col);
unsetrc (MONSTER | SLEEPER, row, col);
atrow = row;
atcol = col;
break;
case '#':
if (!onrc (HALL, row, col))
{ foundnew ();
timestosearch = k_door / 5;
}
if (onrc (STUFF, row, col)) deletestuff (row, col);
setrc (SEEN | CANGO | SAFE | HALL | EVERCLR, row, col);
unsetrc (DOOR | ROOM | TRAP | ARROW | TRAPDOR | TELTRAP | GASTRAP |
BEARTRP | DARTRAP | MONSTER | SCAREM | WALL | SLEEPER | STAIRS,
row, col);
break;
case '+':
if (!onrc (DOOR, row, col))
{ foundnew ();
timestosearch = k_door / 5;
teleported = 0; /* Dont give up on this level yet */
*newdoors++ = row; *newdoors++ = col;
}
if (onrc (STUFF, row, col)) deletestuff (row, col);
setrc (SEEN | CANGO | SAFE | DOOR | WALL | EVERCLR, row, col);
unsetrc (ROOM | TRAP | ARROW | TRAPDOR | TELTRAP | GASTRAP | BEARTRP |
DARTRAP | MONSTER | SCAREM | SLEEPER, row, col);
clearcurrect(); /* LGCH: redo currentrectangle */
break;
/*
* Room floor: there are many cases of what a room floor means,
* depending on the version of Rogue, whether the room is lit, whether
* we are in the room or not, and whether or not we were shooting
* missiles last turn.
*/
case '.':
/* The square cant be any of these */
unsetrc (HALL | DOOR | MONSTER | SCAREM | WALL | TRAP | ARROW |
TRAPDOR | TELTRAP | GASTRAP | BEARTRP | DARTRAP, row, col);
if (!onrc (ROOM, row, col)) /* New room? */
unmarkexplored (row, col);
if (rm != NONE) levelmap[rm] |= HASROOM; /* Room here */
/* If older Rogue, or our last position or a moving missile or */
/* in the same room, then a floor '.' means no stuff there */
if ((version < RV52A ||
oldch == '@' ||
oldch == ')' && functionchar (lastcmd) == 't' ||
(on (ROOM) && whichroom (row, col) == whichroom (atrow, atcol))) &&
onrc (STUFF, row, col))
{ deletestuff (row, col); }
/* If the stairs moved, look for them */
if (oldch == '@' && onrc (STAIRS, row, col)) findstairs (row, col);
/* Record whether this square has been clear of monsters */
if (!isupper (oldch)) setrc (EVERCLR, row, col);
/* Safe if we have been there, but not if the stuff was an arrow */
if (onrc (BEEN, row, col)) setrc (SAFE, row, col);
else if (oldch == ')' && functionchar (lastcmd) == 't')
unsetrc (SAFE, row, col);
setrc (SEEN | CANGO | ROOM, row, col); /* Square must be these */
break;
case '-':
case '|':
setrc (SEEN | WALL | EVERCLR, row, col);
unsetrc (CANGO | HALL | DOOR | ROOM | SLEEPER, row, col);
break;
case ':':
case '?':
case '!':
case ')':
case ']':
case '/':
case '=':
case ',': /* HAH! *//* HAH HAH! *//* HAH HAH HAH! */
case '*':
setrc (SEEN | CANGO | SAFE | EVERCLR, row, col);
unsetrc (DOOR | TRAP | ARROW | TRAPDOR | TELTRAP | GASTRAP | BEARTRP |
DARTRAP | MONSTER | WALL | SLEEPER, row, col);
if (ch != '?') unsetrc (SCAREM, row, col);
if (!onrc (BEEN, row, col) || !onrc(STAIRS, row, col) || !cosmic)
{ addstuff (ch, row, col); unsetrc (STAIRS, row, col); }
setnewgoal ();
break;
case '%':
if (!onrc (STAIRS, row, col)) foundnew ();
if ((!cosmic || onrc (BEEN, row, col)) && onrc (STUFF, row, col))
deletestuff (row, col);
setrc (SEEN | CANGO | SAFE | ROOM | STAIRS | EVERCLR, row, col);
unsetrc (DOOR | HALL | TRAP | ARROW | TRAPDOR | TELTRAP | GASTRAP |
BEARTRP | DARTRAP | MONSTER | SCAREM | SLEEPER,
row, col);
stairrow = row;
staircol = col;
setnewgoal ();
break;
case '^':
setrc (SEEN | CANGO | ROOM | TRAP | EVERCLR, row, col);
if (onrc (STUFF, row, col)) deletestuff (row, col);
unsetrc (SAFE | HALL | DOOR | MONSTER | SCAREM | WALL | SLEEPER,
row, col);
break;
case ' ':
unsetrc (MONSTER | WALL, row, col);
break;
default:
if (isupper (ch))
{ monster = monname (ch);
setrc (SEEN | CANGO | MONSTER, row, col);
unsetrc (SCAREM, row, col);
if (onrc (WALL, row, col)) /* Infer DOOR here */
{ if (!onrc (DOOR, row, col))
{ foundnew ();
timestosearch = k_door / 5;
setrc (DOOR, row, col); /* MLM */
unsetrc (WALL, row, col); /* MLM */
}
}
if (!revvideo && ch != oldch) /* R5.2 MLM */
{ blinded = 0;
if (seenbefore)
addmonster (ch, row, col, AWAKE);
else if (!onrc (HALL | DOOR, row, col) && !aggravated &&
(streq (monster, "floating eye") ||
streq (monster, "ice monster") ||
streq (monster, "leprechaun") ||
streq (monster, "nymph") ||
(version < RV52A && (ch == 'T' || ch == 'P'))))
{ addmonster (ch, row, col, ASLEEP);
setrc (SLEEPER, row, col);
}
else if (onrc (HALL | DOOR, row, col) || aggravated)
{ addmonster (ch, row, col, AWAKE);
setrc (EVERCLR, row, col);
}
else
addmonster (ch, row, col, 0);
}
}
break;
}
/* If the stairs moved, look for the real stairs */
if ((!onrc (STAIRS, row, col) && (row==stairrow && col==staircol)) ||
(stairrow != NONE && !onrc (STAIRS, stairrow, staircol)))
findstairs (row, col);
if (!couldgo && onrc (CANGO, row, col))
setnewgoal ();
}
/*
* teleport: We have just been teleported. Reset whatever is necessary to
* avoid doing silly things.
*/
teleport ()
{ register int r = atrow0, c = atcol0;
goalr = goalc = NONE; setnewgoal ();
hitstokill = 0; darkdir = NONE; darkturns = 0;
if (movedir >= 0 && movedir < 8 && !confused)
{ teleported++;
while (r > 1 && r < 23 && c > 0 && c < 79)
{ if (onrc (WALL | DOOR | HALL, r, c)) break;
if (onrc (TRAP, r, c))
{ if (!onrc (ARROW|DARTRAP|GASTRAP|BEARTRP|TRAPDOR|TELTRAP, r, c))
saynow ("Assuming teleport trap at %d, %d", r, c);
break;
}
r += deltr[movedir]; c += deltc[movedir];
}
}
}
/*
* mapinfer: Rewritten by Michael Mauldin. August 19, 1983.
* Infer bit settings after reading a scroll of magic mapping.
* Because the mapping scroll gives extra information (in particular
* we now know all the room squares so we can plan run-away paths
* properly) it is best to process the entire map making extra
* inferences.
*/
mapinfer()
{ register r, c, inroom;
dwait (D_CONTROL, "Map read: inferring rooms.");
for (r=1; r<23; r++)
{ inroom = 0;
for (c=0; c<80; c++)
{ if (seerc ('|', r, c) || (seerc ('+', r, c) && !seerc('-', r, c-1)))
{ inroom = !inroom; }
else if (inroom)
{ setrc (ROOM | CANGO, r, c); }
else
{ setrc (SEEN, r, c); }
}
}
}
/*
* markexplored: If we are in a room, mark the location as explored.
*/
markexplored (row, col)
int row, col;
{ register int rm = whichroom (row, col);
if (rm != NONE && !(levelmap[rm] & EXPLORED))
{ levelmap[rm] |= EXPLORED;
if (!(levelmap[rm] & HASROOM))
saynow ("Assuming room %d is gone.", zone);
}
}
/*
* unmarkexplored: If we are in a room, unmark the location as explored.
*/
unmarkexplored (row, col)
int row, col;
{ register int rm = whichroom (row, col);
if (rm != NONE) levelmap[rm] &= ~EXPLORED;
}
/*
* isexplored: If we are in a room, return true if it has been explored.
*/
isexplored (row, col)
int row, col;
{ register int rm = whichroom (row, col);
return (rm != NONE ? levelmap[rm] & EXPLORED : 0);
}
/*
* haveexplored: Have we explored n rooms?
*/
haveexplored (n)
int n;
{ register int rm, count = 0;
for (rm = 0; rm < 9; rm++)
if (levelmap[rm] & EXPLORED)
count++;
return (count >= n);
}
/*
* printexplored: List the explored rooms
*/
printexplored ()
{ register int rm;
at (0,0);
printw ("Rooms explored: ");
for (rm = 0; rm < 9; rm++)
{ if (levelmap[rm] & EXPLORED)
{ printw (" %d", rm);
}
}
clrtoeol ();
at (row, col);
refresh ();
}
/*
* inferhall: When a door appears on the screen where no door was before,
* check whether we can infer a hall between it an a neighbouring room.
* The technique is simple: We first determine whether the hall is already
* known, and if it is not, we scan away from the room looking for another
* wall. If we find one, then we look for a door and if we find THAT then
* we infer a hall between the matching doors. Of course, this means that
* we must set CANGO bits so that exploration can use the guessed hall. So
* we set CANGO for the complete rectangle joining the two doors and then
* rely on the CANGO bits being unset again where we actually see blank
* space.
*/
inferhall (r, c)
register int r, c;
{ register int i, j, k;
int inc, rm, end1, end2, end, dropout = 0, dir= NONE;
for (k = 0; k < 8; k += 2)
{ if (onrc (HALL, r + deltr[k], c + deltc[k])) /* Hall has been seen */
return;
else if (onrc (ROOM, r + deltr[k], c + deltc[k])) /* Room is over here */
dir = k;
}
dwait (D_SEARCH, "Room direction %d", dir);
if (dir < 0) return;
if (dir % 4 == 0) /* If horizontal dir */
{ inc = -deltc[dir]; rm = whichroom (r, c);
end1 = bounds[rm].top; end2 = bounds[rm].bot;
if (inc < 0) end = bounds[rm-1].left;
else end = bounds[rm+1].right;
end = end * inc;
for (j = c+inc; j*inc < end; j += inc)
{ for (i = end1; i <= end2; i++)
{ if (debug (D_SCREEN | D_SEARCH | D_INFORM)) mvaddch (i, j, 'h');
if (onrc (DOOR | WALL | ROOM | HALL, i, j))
{ /* Modified only to find doors on vertical walls */
if (onrc (DOOR,i,j) && (onrc (WALL,i-1,j) || onrc (WALL,i+1,j)))
connectdoors (r, c+inc, i, j-inc);
dropout = 1;
}
}
if (dropout)
break;
}
}
else
{ inc = -deltr[dir]; rm = whichroom (r, c);
end1 = bounds[rm].left; end2 = bounds[rm].right;
if (inc < 0) end = bounds[rm-3].top;
else end = bounds[rm+3].bot;
end = end * inc;
for (i = r+inc; i*inc < end; i += inc)
{ for (j = end1; j <= end2; j++)
{ if (debug (D_SCREEN | D_SEARCH | D_INFORM)) mvaddch (i, j, 'v');
if (onrc (DOOR | WALL | ROOM | HALL, i, j))
{ /* Modified only to find doors on horizontal walls */
if (onrc (DOOR,i,j) && (onrc (WALL,i,j-1) || onrc (WALL,i,j+1)))
connectdoors (r+inc, c, i-inc, j);
dropout = 1;
}
}
if (dropout) break;
}
}
/* NOTE: If we set SEEN here on the three squares beyond the door, then
* we can prevent Rogomatic's persistence in searching out every
* corridor that leads to a secret door at the other end. Or, we could set
* a bit on the door to make it a preferred exploration target so that
* Rogomatic would ALWAYS search out every corridor leading to a secret
* door at the other end. The latter alternative is probably better
* unless we implement the inferred corridors so that we can infer a
* corridor which has a secret door and therefore we can traverse it
* more easily one way than the other. NOTE that we must have a flag to
* indicate why the search for a corridor failed: if it found a wall
* then we know there is a secret door; if it stopped for another reason
* then we don't know what we may find - maybe a room, maybe a path to a
* corridor.
*/
dwait (D_SEARCH | D_CONTROL, "Hall search done.");
}
connectdoors (r1, c1, r2, c2)
register int r1, c1, r2, c2;
{ register int r, c;
int endr = max (r1, r2), endc = max (c1, c2);
dwait (D_INFORM, "Inferring hall (%d,%d) to (%d,%d)", r1, c1, r2, c2);
for (r = min (r1, r2); r <= endr; r++)
for (c = min (c1, c2); c <= endc; c++)
setrc (CANGO|SAFE, r, c); /* Can go (somewhere) here */
for (r = min (r1, r2) - 1; r <= endr + 1; r++)
for (c = min (c1, c2) - 1; c <= endc + 1; c++)
setrc (SEEN, r, c); /* Nothing to see here */
}
/*
* canbedoor: Called from setpsd() to check that a dead end could in fact
* lead to a room. Only checks that there is enough empty space next to a
* square. Does NOT check that this square is in fact a dead end.
*
* September 25, 1983 Michael L. Mauldin
*/
canbedoor (deadr, deadc)
int deadr, deadc;
{ register int r, c, dr, dc, k, count;
/* Check all orthogonal directions around the square */
for (k=0; k < 8; k+=2)
{ dr = deltr[k]; dc = deltc[k];
r = deadr+dr; c = deadc+dc;
/* If there are four blank squares, then it could be a door */
for (count=0; count < 4 && seerc (' ',r,c); count++)
{ r+=dr; c+=dc; }
if (count >= 4) return (1);
}
/* Not enough room in any direction */
return (0);
}
/*
* mazedoor: Return true if this could be a door to a maze
*/
mazedoor (row, col)
int row, col;
{ register int r=row, c=col, dr, dc, k=0, dir = NONE;
if (onrc (HALL,r,c+1)) {dir=0; k++; dr=0; dc=1;}
if (onrc (HALL,r-1,c)) {dir=2; k++; dr= -1; dc=0;}
if (onrc (HALL,r+1,c)) {dir=6; k++; dr=1; dc=0;}
if (onrc (HALL,r,c-1)) {dir=4; k++; dr=0, dc= -1;}
if (k != 1) return (0);
/* Fail if no adjacent hall, or not double corridor */
if ((onrc (HALL, r+dr+dr, c+dc+dc) == 0))
return (0);
/* Must have two sets of double corridor */
if (! (((onrc (HALL, r+dr+deltr[(dir+1)&7], c+dc+deltc[(dir+1)&7])) &&
(onrc (HALL, r+dr+deltr[(dir+2)&7], c+dc+deltc[(dir+2)&7]))) ||
((onrc (HALL, r+dr+deltr[(dir-1)&7], c+dc+deltc[(dir-1)&7])) &&
(onrc (HALL, r+dr+deltr[(dir-2)&7], c+dc+deltc[(dir-2)&7])))))
return (0);
/* If there are four blank squares, then it could be a door */
for (r = row-dr, c = col-dc, k=0; k < 4 && seerc (' ',r,c); k++)
{ r-=dr; c-=dc; }
if (k >= 4) return (1);
/* Not enough room for room */
return (0);
}
/*
* nextto: Is there a square type orthogonally adjacent?
*/
nextto (type,r,c)
register int type, r, c;
{ register int result;
if (result = onrc (type, r-1, c)) return (result);
if (result = onrc (type, r+1, c)) return (result);
if (result = onrc (type, r, c-1)) return (result);
if (result = onrc (type, r, c+1)) return (result);
return (0);
}
/*
* nexttowall: Is there a wall adjacent wall?
* |
* e.g. ########| <---- there should be a door here.
* |
* Fuzzy: Replaces knowisdoor (), October 17, 1983.
*/
nexttowall (r,c)
register int r, c;
{ return (onrc (DOOR | WALL, r-1, c) == WALL ||
onrc (DOOR | WALL, r+1, c) == WALL ||
onrc (DOOR | WALL, r, c-1) == WALL ||
onrc (DOOR | WALL, r, c+1) == WALL);
}
/*
* dumpmazedoor: Show all squares for which mazedoor(r,c) is true.
*/
dumpmazedoor ()
{ register int r, c;
for (r=2; r<22; r++)
{ for (c=1; c<79; c++)
{ if (((scrmap[r][c] & (BEEN|DOOR|HALL|ROOM|WALL|STAIRS)) == 0) &&
mazedoor (r, c))
mvaddch (r, c, 'M');
}
}
at (row, col);
}
/*
* foundnew: Reactivate rules which new new squares to work
*/
foundnew ()
{ new_mark = new_findroom = new_search = new_stairs = 1;
reusepsd = teleported = 0;
cancelmove (SECRETDOOR);
unrest ();
}