This is extralev.c in view mode; [Download] [Up]
/* SCCS Id: @(#)extralev.c 3.0 88/04/11 */ /* Copyright 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ #define MONATTK_H /* comment line for pre-compiled headers */ /* block some unused #defines to avoid overloading some cpp's */ #include "hack.h" #ifdef REINCARNATION struct rogueroom { xchar rlx, rly; xchar dx, dy; boolean real; uchar doortable; int nroom; /* Only meaningful for "real" rooms */ }; #define UP 1 #define DOWN 2 #define LEFT 4 #define RIGHT 8 static struct rogueroom r[3][3]; static void FDECL(roguejoin,(int,int,int,int,int)); static void FDECL(roguecorr,(int,int,int)); static void FDECL(miniwalk,(int,int)); static void roguejoin(x1,y1,x2,y2, horiz) int x1,y1,x2,y2; int horiz; { register int x,y,middle; #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif if (horiz) { middle = x1 + rn2(x2-x1+1); for(x=MIN(x1,middle); x<=MAX(x1,middle); x++) corr(x, y1); for(y=MIN(y1,y2); y<=MAX(y1,y2); y++) corr(middle,y); for(x=MIN(middle,x2); x<=MAX(middle,x2); x++) corr(x, y2); } else { middle = y1 + rn2(y2-y1+1); for(y=MIN(y1,middle); y<=MAX(y1,middle); y++) corr(x1, y); for(x=MIN(x1,x2); x<=MAX(x1,x2); x++) corr(x, middle); for(y=MIN(middle,y2); y<=MAX(middle,y2); y++) corr(x2,y); } } static void roguecorr(x, y, dir) int x,y,dir; { register int fromx, fromy, tox, toy; if (dir==DOWN) { r[x][y].doortable &= ~DOWN; if (!r[x][y].real) { fromx = r[x][y].rlx; fromy = r[x][y].rly; fromx += 1 + 26*x; fromy += 7*y; } else { fromx = r[x][y].rlx + rn2(r[x][y].dx); fromy = r[x][y].rly + r[x][y].dy; fromx += 1 + 26*x; fromy += 7*y; if (!IS_WALL(levl[fromx][fromy].typ)) impossible("down: no wall at %d,%d?",fromx, fromy); dodoor(fromx, fromy, &rooms[r[x][y].nroom]); levl[fromx][fromy].doormask = D_NODOOR; mnewsym(fromx,fromy); fromy++; } if(y >= 2) { impossible("down door from %d,%d going nowhere?",x,y); return; } y++; r[x][y].doortable &= ~UP; if (!r[x][y].real) { tox = r[x][y].rlx; toy = r[x][y].rly; tox += 1 + 26*x; toy += 7*y; } else { tox = r[x][y].rlx + rn2(r[x][y].dx); toy = r[x][y].rly - 1; tox += 1 + 26*x; toy += 7*y; if (!IS_WALL(levl[tox][toy].typ)) impossible("up: no wall at %d,%d?",tox,toy); dodoor(tox, toy, &rooms[r[x][y].nroom]); levl[tox][toy].doormask = D_NODOOR; mnewsym(tox,toy); toy--; } roguejoin(fromx, fromy, tox, toy, FALSE); return; } else if (dir == RIGHT) { r[x][y].doortable &= ~RIGHT; if (!r[x][y].real) { fromx = r[x][y].rlx; fromy = r[x][y].rly; fromx += 1 + 26*x; fromy += 7*y; } else { fromx = r[x][y].rlx + r[x][y].dx; fromy = r[x][y].rly + rn2(r[x][y].dy); fromx += 1 + 26*x; fromy += 7*y; if (!IS_WALL(levl[fromx][fromy].typ)) impossible("down: no wall at %d,%d?",fromx, fromy); dodoor(fromx, fromy, &rooms[r[x][y].nroom]); levl[fromx][fromy].doormask = D_NODOOR; mnewsym(fromx,fromy); fromx++; } if(x >= 2) { impossible("right door from %d,%d going nowhere?",x,y); return; } x++; r[x][y].doortable &= ~LEFT; if (!r[x][y].real) { tox = r[x][y].rlx; toy = r[x][y].rly; tox += 1 + 26*x; toy += 7*y; } else { tox = r[x][y].rlx - 1; toy = r[x][y].rly + rn2(r[x][y].dy); tox += 1 + 26*x; toy += 7*y; if (!IS_WALL(levl[tox][toy].typ)) impossible("left: no wall at %d,%d?",tox,toy); dodoor(tox, toy, &rooms[r[x][y].nroom]); levl[tox][toy].doormask = D_NODOOR; mnewsym(tox,toy); tox--; } roguejoin(fromx, fromy, tox, toy, TRUE); return; } else impossible("corridor in direction %d?",dir); } /* Modified walkfrom() from mkmaze.c */ static void miniwalk(x, y) int x,y; { register int q, dir; int dirs[4]; while(1) { q = 0; #define doorhere (r[x][y].doortable) if (x>0 && (!(doorhere & LEFT)) && (!r[x-1][y].doortable || !rn2(10))) dirs[q++] = 0; if (x<2 && (!(doorhere & RIGHT)) && (!r[x+1][y].doortable || !rn2(10))) dirs[q++] = 1; if (y>0 && (!(doorhere & UP)) && (!r[x][y-1].doortable || !rn2(10))) dirs[q++] = 2; if (y<2 && (!(doorhere & DOWN)) && (!r[x][y+1].doortable || !rn2(10))) dirs[q++] = 3; /* Rogue levels aren't just 3 by 3 mazes; they have some extra * connections, thus that 1/10 chance */ if (!q) return; dir = dirs[rn2(q)]; switch(dir) { /* Move in direction */ case 0: doorhere |= LEFT; x--; doorhere |= RIGHT; break; case 1: doorhere |= RIGHT; x++; doorhere |= LEFT; break; case 2: doorhere |= UP; y--; doorhere |= DOWN; break; case 3: doorhere |= DOWN; y++; doorhere |= UP; break; } miniwalk(x,y); } } void makeroguerooms() { register struct mkroom *croom; register int x,y; int x2, y2; /* Rogue levels are structured 3 by 3, with each section containing * a room or an intersection. The minimum width is 2 each way. * One difference between these and "real" Rogue levels: real Rogue * uses 24 rows and NetHack only 23. So we cheat a bit by making the * second row of rooms not as deep. * * Each normal space has 6/7 rows and 25 columns in which a room may * actually be placed. Walls go from rows 0-5/6 and columns 0-24. * Not counting walls, the room may go in * rows 1-5 and columns 1-23 (numbering starting at 0). A room * coordinate of this type may be converted to a level coordinate * by adding 1+28*x to the column, and 7*y to the row. (The 1 * is because column 0 isn't used [we only use 1-78]). * Room height may be 2-4 (2-5 on last row), length 2-23 (not * counting walls) */ #define here r[x][y] nroom = 0; for(y=0; y<3; y++) for(x=0; x<3; x++) { /* Note: we want to insure at least 1 room. So, if the * first 8 are all dummies, force the last to be a room. */ if (!rn2(5) && (nroom || (x<2 && y<2))) { /* Arbitrary: dummy rooms may only go where real * ones do. */ here.real = FALSE; here.rlx = rn1(22, 2); here.rly = rn1((y==2)?4:3, 2); } else { here.real = TRUE; here.dx = rn1(22, 2); /* 2-23 long, plus walls */ here.dy = rn1((y==2)?4:3, 2); /* 2-5 high, plus walls */ /* boundaries of room floor */ here.rlx = rnd(23 - here.dx + 1); here.rly = rnd(((y==2) ? 5 : 4)- here.dy + 1); nroom++; } here.doortable = 0; } miniwalk(rn2(3), rn2(3)); nroom = 0; for(y=0; y<3; y++) for(x=0; x<3; x++) { if (here.real) { /* Make a room */ r[x][y].nroom = nroom; croom = &rooms[nroom]; /* Illumination. Strictly speaking, it should be lit * only if above level 10, but since Rogue rooms are * only encountered below level 10... */ if (!rn2(7)) { for(x2 = 1+26*x+here.rlx-1; x2 <= 1+26*x+here.rlx+here.dx; x2++) for(y2 = 7*y+here.rly-1; y2 <= 7*y+here.rly+here.dy; y2++) levl[x2][y2].lit = 1; croom->rlit = 1; } else croom->rlit = 0; croom->lx = 1 + 26*x + here.rlx; croom->ly = 7*y + here.rly; croom->hx = 1 + 26*x + here.rlx + here.dx - 1; croom->hy = 7*y + here.rly + here.dy - 1; /* Walls, doors, and floors. */ #define lowx croom->lx #define lowy croom->ly #define hix croom->hx #define hiy croom->hy for(x2 = lowx-1; x2 <= hix+1; x2++) for(y2 = lowy-1; y2 <= hiy+1; y2 += (hiy-lowy+2)) { levl[x2][y2].scrsym = HWALL_SYM; levl[x2][y2].typ = HWALL; } for(x2 = lowx-1; x2 <= hix+1; x2 += (hix-lowx+2)) for(y2 = lowy; y2 <= hiy; y2++) { levl[x2][y2].scrsym = VWALL_SYM; levl[x2][y2].typ = VWALL; } for(x2 = lowx; x2 <= hix; x2++) for(y2 = lowy; y2 <= hiy; y2++) { levl[x2][y2].scrsym = ROOM_SYM; levl[x2][y2].typ = ROOM; } levl[lowx-1][lowy-1].typ = TLCORNER; levl[hix+1][lowy-1].typ = TRCORNER; levl[lowx-1][hiy+1].typ = BLCORNER; levl[hix+1][hiy+1].typ = BRCORNER; levl[lowx-1][lowy-1].scrsym = TLCORN_SYM; levl[hix+1][lowy-1].scrsym = TRCORN_SYM; levl[lowx-1][hiy+1].scrsym = BLCORN_SYM; levl[hix+1][hiy+1].scrsym = BRCORN_SYM; /* Misc. */ smeq[nroom] = nroom; croom->rtype = OROOM; croom++; croom->hx = -1; nroom++; } } /* Now, add connecting corridors. */ for(y=0; y<3; y++) for(x=0; x<3; x++) { if (here.doortable & DOWN) roguecorr(x, y, DOWN); if (here.doortable & RIGHT) roguecorr(x, y, RIGHT); if (here.doortable & LEFT) impossible ("left end of %d, %d never connected?",x,y); if (here.doortable & UP) impossible ("up end of %d, %d never connected?",x,y); } } void corr(x,y) int x, y; { if (rn2(50)) { levl[x][y].typ = CORR; levl[x][y].scrsym = CORR_SYM; } else { levl[x][y].typ = SCORR; levl[x][y].scrsym = ' '; /* _not_ STONE_SYM */ } } void makerogueghost() { register struct monst *ghost; struct obj *ghostobj; struct mkroom *croom; int x,y; if (!nroom) return; /* Should never happen */ croom = &rooms[rn2(nroom)]; x = somex(croom); y = somey(croom); if (!(ghost = makemon(&mons[PM_GHOST], x, y))) return; ghost->msleep = 1; Strcpy((char *)ghost->mextra, roguename()); if (rn2(4)) { ghostobj = mksobj_at(FOOD_RATION,x,y); ghostobj->quan = rnd(7); ghostobj->owt = weight(ghostobj); } if (rn2(2)) { ghostobj = mksobj_at(MACE,x,y); ghostobj->spe = rnd(3); if (rn2(4)) curse(ghostobj); } else { ghostobj = mksobj_at(TWO_HANDED_SWORD,x,y); ghostobj->spe = rnd(5) - 2; if (rn2(4)) curse(ghostobj); } ghostobj = mksobj_at(BOW,x,y); ghostobj->spe = 1; if (rn2(4)) curse(ghostobj); ghostobj = mksobj_at(ARROW,x,y); ghostobj->spe = 0; ghostobj->quan = rn1(10,25); ghostobj->owt = weight(ghostobj); if (rn2(4)) curse(ghostobj); if (rn2(2)) { ghostobj = mksobj_at(RING_MAIL,x,y); ghostobj->spe = rn2(3); if (!rn2(3)) ghostobj->rustfree = 1; if (rn2(4)) curse(ghostobj); } else { ghostobj = mksobj_at(PLATE_MAIL,x,y); ghostobj->spe = rnd(5) - 2; if (!rn2(3)) ghostobj->rustfree = 1; if (rn2(4)) curse(ghostobj); } if (rn2(2)) { ghostobj = mksobj_at(AMULET_OF_YENDOR,x,y); ghostobj->spe = -1; ghostobj->known = TRUE; } } #endif /* REINCARNATION /**/
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.