1 /* SCCS Id: @(#)extralev.c 3.4 2001/09/06 */
2 /* Copyright 1988, 1989 by Ken Arromdee */
3 /* NetHack may be freely redistributed. See license for details. */
6 * Support code for "rogue"-style level.
18 int nroom
; /* Only meaningful for "real" rooms */
25 static NEARDATA
struct rogueroom r
[3][3];
26 STATIC_DCL
void roguejoin(int,int,int,int,int);
27 STATIC_DCL
void roguecorr(int,int,int);
28 STATIC_DCL
void miniwalk(int,int);
32 roguejoin(x1
,y1
,x2
,y2
, horiz
)
36 register int x
,y
,middle
;
38 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
41 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
44 middle
= x1
+ rn2(x2
-x1
+1);
45 for(x
=MIN(x1
,middle
); x
<=MAX(x1
,middle
); x
++)
47 for(y
=MIN(y1
,y2
); y
<=MAX(y1
,y2
); y
++)
49 for(x
=MIN(middle
,x2
); x
<=MAX(middle
,x2
); x
++)
52 middle
= y1
+ rn2(y2
-y1
+1);
53 for(y
=MIN(y1
,middle
); y
<=MAX(y1
,middle
); y
++)
55 for(x
=MIN(x1
,x2
); x
<=MAX(x1
,x2
); x
++)
57 for(y
=MIN(middle
,y2
); y
<=MAX(middle
,y2
); y
++)
67 register int fromx
, fromy
, tox
, toy
;
70 r
[x
][y
].doortable
&= ~DOWN
;
72 fromx
= r
[x
][y
].rlx
; fromy
= r
[x
][y
].rly
;
73 fromx
+= 1 + 26*x
; fromy
+= 7*y
;
75 fromx
= r
[x
][y
].rlx
+ rn2(r
[x
][y
].dx
);
76 fromy
= r
[x
][y
].rly
+ r
[x
][y
].dy
;
77 fromx
+= 1 + 26*x
; fromy
+= 7*y
;
78 if (!IS_WALL(levl
[fromx
][fromy
].typ
))
79 impossible("down: no wall at %d,%d?",fromx
,
81 dodoor(fromx
, fromy
, &rooms
[r
[x
][y
].nroom
]);
82 levl
[fromx
][fromy
].doormask
= D_NODOOR
;
86 impossible("down door from %d,%d going nowhere?",x
,y
);
90 r
[x
][y
].doortable
&= ~UP
;
92 tox
= r
[x
][y
].rlx
; toy
= r
[x
][y
].rly
;
93 tox
+= 1 + 26*x
; toy
+= 7*y
;
95 tox
= r
[x
][y
].rlx
+ rn2(r
[x
][y
].dx
);
96 toy
= r
[x
][y
].rly
- 1;
97 tox
+= 1 + 26*x
; toy
+= 7*y
;
98 if (!IS_WALL(levl
[tox
][toy
].typ
))
99 impossible("up: no wall at %d,%d?",tox
,toy
);
100 dodoor(tox
, toy
, &rooms
[r
[x
][y
].nroom
]);
101 levl
[tox
][toy
].doormask
= D_NODOOR
;
104 roguejoin(fromx
, fromy
, tox
, toy
, FALSE
);
106 } else if (dir
== RIGHT
) {
107 r
[x
][y
].doortable
&= ~RIGHT
;
109 fromx
= r
[x
][y
].rlx
; fromy
= r
[x
][y
].rly
;
110 fromx
+= 1 + 26*x
; fromy
+= 7*y
;
112 fromx
= r
[x
][y
].rlx
+ r
[x
][y
].dx
;
113 fromy
= r
[x
][y
].rly
+ rn2(r
[x
][y
].dy
);
114 fromx
+= 1 + 26*x
; fromy
+= 7*y
;
115 if (!IS_WALL(levl
[fromx
][fromy
].typ
))
116 impossible("down: no wall at %d,%d?",fromx
,
118 dodoor(fromx
, fromy
, &rooms
[r
[x
][y
].nroom
]);
119 levl
[fromx
][fromy
].doormask
= D_NODOOR
;
123 impossible("right door from %d,%d going nowhere?",x
,y
);
127 r
[x
][y
].doortable
&= ~LEFT
;
129 tox
= r
[x
][y
].rlx
; toy
= r
[x
][y
].rly
;
130 tox
+= 1 + 26*x
; toy
+= 7*y
;
132 tox
= r
[x
][y
].rlx
- 1;
133 toy
= r
[x
][y
].rly
+ rn2(r
[x
][y
].dy
);
134 tox
+= 1 + 26*x
; toy
+= 7*y
;
135 if (!IS_WALL(levl
[tox
][toy
].typ
))
136 impossible("left: no wall at %d,%d?",tox
,toy
);
137 dodoor(tox
, toy
, &rooms
[r
[x
][y
].nroom
]);
138 levl
[tox
][toy
].doormask
= D_NODOOR
;
141 roguejoin(fromx
, fromy
, tox
, toy
, TRUE
);
143 } else impossible("corridor in direction %d?",dir
);
146 /* Modified walkfrom() from mkmaze.c */
157 #define doorhere (r[x][y].doortable)
158 if (x
>0 && (!(doorhere
& LEFT
)) &&
159 (!r
[x
-1][y
].doortable
|| !rn2(10)))
161 if (x
<2 && (!(doorhere
& RIGHT
)) &&
162 (!r
[x
+1][y
].doortable
|| !rn2(10)))
164 if (y
>0 && (!(doorhere
& UP
)) &&
165 (!r
[x
][y
-1].doortable
|| !rn2(10)))
167 if (y
<2 && (!(doorhere
& DOWN
)) &&
168 (!r
[x
][y
+1].doortable
|| !rn2(10)))
170 /* Rogue levels aren't just 3 by 3 mazes; they have some extra
171 * connections, thus that 1/10 chance
175 switch(dir
) { /* Move in direction */
176 case 0: doorhere
|= LEFT
;
180 case 1: doorhere
|= RIGHT
;
184 case 2: doorhere
|= UP
;
188 case 3: doorhere
|= DOWN
;
200 /* Rogue levels are structured 3 by 3, with each section containing
201 * a room or an intersection. The minimum width is 2 each way.
202 * One difference between these and "real" Rogue levels: real Rogue
203 * uses 24 rows and NetHack only 23. So we cheat a bit by making the
204 * second row of rooms not as deep.
206 * Each normal space has 6/7 rows and 25 columns in which a room may
207 * actually be placed. Walls go from rows 0-5/6 and columns 0-24.
208 * Not counting walls, the room may go in
209 * rows 1-5 and columns 1-23 (numbering starting at 0). A room
210 * coordinate of this type may be converted to a level coordinate
211 * by adding 1+28*x to the column, and 7*y to the row. (The 1
212 * is because column 0 isn't used [we only use 1-78]).
213 * Room height may be 2-4 (2-5 on last row), length 2-23 (not
219 for(y
=0; y
<3; y
++) for(x
=0; x
<3; x
++) {
220 /* Note: we want to insure at least 1 room. So, if the
221 * first 8 are all dummies, force the last to be a room.
223 if (!rn2(5) && (nroom
|| (x
<2 && y
<2))) {
224 /* Arbitrary: dummy rooms may only go where real
228 here
.rlx
= rn1(22, 2);
229 here
.rly
= rn1((y
==2)?4:3, 2);
232 here
.dx
= rn1(22, 2); /* 2-23 long, plus walls */
233 here
.dy
= rn1((y
==2)?4:3, 2); /* 2-5 high, plus walls */
235 /* boundaries of room floor */
236 here
.rlx
= rnd(23 - here
.dx
+ 1);
237 here
.rly
= rnd(((y
==2) ? 5 : 4)- here
.dy
+ 1);
242 miniwalk(rn2(3), rn2(3));
244 for(y
=0; y
<3; y
++) for(x
=0; x
<3; x
++) {
245 if (here
.real
) { /* Make a room */
246 int lowx
, lowy
, hix
, hiy
;
248 r
[x
][y
].nroom
= nroom
;
251 lowx
= 1 + 26*x
+ here
.rlx
;
252 lowy
= 7*y
+ here
.rly
;
253 hix
= 1 + 26*x
+ here
.rlx
+ here
.dx
- 1;
254 hiy
= 7*y
+ here
.rly
+ here
.dy
- 1;
255 /* Strictly speaking, it should be lit only if above
256 * level 10, but since Rogue rooms are only
257 * encountered below level 10, use !rn2(7).
259 add_room(lowx
, lowy
, hix
, hiy
,
260 (boolean
) !rn2(7), OROOM
, FALSE
, FALSE
, FALSE
);
264 /* Now, add connecting corridors. */
265 for(y
=0; y
<3; y
++) for(x
=0; x
<3; x
++) {
266 if (here
.doortable
& DOWN
)
267 roguecorr(x
, y
, DOWN
);
268 if (here
.doortable
& RIGHT
)
269 roguecorr(x
, y
, RIGHT
);
270 if (here
.doortable
& LEFT
)
271 impossible ("left end of %d, %d never connected?",x
,y
);
272 if (here
.doortable
& UP
)
273 impossible ("up end of %d, %d never connected?",x
,y
);
282 levl
[x
][y
].typ
= CORR
;
284 levl
[x
][y
].typ
= SCORR
;
291 register struct monst
*ghost
;
292 struct obj
*ghostobj
;
293 struct mkroom
*croom
;
296 if (!nroom
) return; /* Should never happen */
297 croom
= &rooms
[rn2(nroom
)];
298 x
= somex(croom
); y
= somey(croom
);
299 if (!(ghost
= makemon(&mons
[PM_GHOST
], x
, y
, NO_MM_FLAGS
)))
301 ghost
->msleeping
= 1;
302 ghost
= christen_monst(ghost
, roguename());
305 ghostobj
= mksobj_at(FOOD_RATION
, x
, y
, FALSE
, FALSE
, FALSE
);
307 ghostobj
->quan
= (long) rnd(7);
308 ghostobj
->owt
= weight(ghostobj
);
312 ghostobj
= mksobj_at(MACE
, x
, y
, FALSE
, FALSE
, FALSE
);
314 ghostobj
->spe
= rnd(3);
315 if (rn2(4)) curse(ghostobj
);
318 ghostobj
= mksobj_at(TWO_HANDED_SWORD
, x
, y
, FALSE
, FALSE
, FALSE
);
320 ghostobj
->spe
= rnd(5) - 2;
321 if (rn2(4)) curse(ghostobj
);
324 ghostobj
= mksobj_at(BOW
, x
, y
, FALSE
, FALSE
, FALSE
);
327 if (rn2(4)) curse(ghostobj
);
330 ghostobj
= mksobj_at(ARROW
, x
, y
, FALSE
, FALSE
, FALSE
);
333 ghostobj
->quan
= (long) rn1(10,25);
334 ghostobj
->owt
= weight(ghostobj
);
335 if (rn2(4)) curse(ghostobj
);
339 ghostobj
= mksobj_at(RING_MAIL
, x
, y
, FALSE
, FALSE
, FALSE
);
341 ghostobj
->spe
= rn2(3);
342 if (!rn2(3)) ghostobj
->oerodeproof
= TRUE
;
343 if (rn2(4)) curse(ghostobj
);
346 ghostobj
= mksobj_at(PLATE_MAIL
, x
, y
, FALSE
, FALSE
, FALSE
);
348 ghostobj
->spe
= rnd(5) - 2;
349 if (!rn2(3)) ghostobj
->oerodeproof
= TRUE
;
350 if (rn2(4)) curse(ghostobj
);
354 ghostobj
= mksobj_at(FAKE_AMULET_OF_YENDOR
, x
, y
, TRUE
, FALSE
, FALSE
);
356 ghostobj
->known
= TRUE
;
360 #endif /* REINCARNATION */