|
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 (); }