home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)extralev.c 3.1 92/05/27 */
- /* Copyright 1988, 1989 by Ken Arromdee */
- /* NetHack may be freely redistributed. See license for details. */
-
- #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 NEARDATA 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;
- 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;
- 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;
- 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;
- 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 int x,y;
- /* 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 */
- int lowx, lowy, hix, hiy;
-
- r[x][y].nroom = nroom;
- smeq[nroom] = nroom;
-
- lowx = 1 + 26*x + here.rlx;
- lowy = 7*y + here.rly;
- hix = 1 + 26*x + here.rlx + here.dx - 1;
- hiy = 7*y + here.rly + here.dy - 1;
- /* Strictly speaking, it should be lit only if above
- * level 10, but since Rogue rooms are only
- * encountered below level 10, use !rn2(7).
- */
-
- add_room(lowx, lowy, hix, hiy, !rn2(7), OROOM, FALSE);
- }
- }
-
- /* 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;
- } else {
- levl[x][y].typ = SCORR;
- }
- }
-
- 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,FALSE);
- ghostobj->quan = (long) rnd(7);
- ghostobj->owt = weight(ghostobj);
- }
- if (rn2(2)) {
- ghostobj = mksobj_at(MACE,x,y,FALSE);
- ghostobj->spe = rnd(3);
- if (rn2(4)) curse(ghostobj);
- } else {
- ghostobj = mksobj_at(TWO_HANDED_SWORD,x,y,FALSE);
- ghostobj->spe = rnd(5) - 2;
- if (rn2(4)) curse(ghostobj);
- }
- ghostobj = mksobj_at(BOW,x,y,FALSE);
- ghostobj->spe = 1;
- if (rn2(4)) curse(ghostobj);
-
- ghostobj = mksobj_at(ARROW,x,y,FALSE);
- ghostobj->spe = 0;
- ghostobj->quan = (long) rn1(10,25);
- ghostobj->owt = weight(ghostobj);
- if (rn2(4)) curse(ghostobj);
-
- if (rn2(2)) {
- ghostobj = mksobj_at(RING_MAIL,x,y,FALSE);
- ghostobj->spe = rn2(3);
- if (!rn2(3)) ghostobj->oerodeproof = TRUE;
- if (rn2(4)) curse(ghostobj);
- } else {
- ghostobj = mksobj_at(PLATE_MAIL,x,y,FALSE);
- ghostobj->spe = rnd(5) - 2;
- if (!rn2(3)) ghostobj->oerodeproof = TRUE;
- if (rn2(4)) curse(ghostobj);
- }
- if (rn2(2)) {
- ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR,x,y,TRUE);
- ghostobj->known = TRUE;
- }
- }
- #endif /* REINCARNATION /**/
-
- /*extralev.c*/
-