1 /* NetHack 3.6 extralev.c $NHDT-Date: 1446975468 2015/11/08 09:37:48 $ $NHDT-Branch: master $:$NHDT-Revision: 1.12 $ */
2 /* Copyright 1988, 1989 by Ken Arromdee */
3 /* NetHack may be freely redistributed. See license for details. */
6 * Support code for "rogue"-style level.
16 int nroom
; /* Only meaningful for "real" rooms */
23 static NEARDATA
struct rogueroom r
[3][3];
24 STATIC_DCL
void FDECL(roguejoin
, (int, int, int, int, int));
25 STATIC_DCL
void FDECL(roguecorr
, (int, int, int));
26 STATIC_DCL
void FDECL(miniwalk
, (int, int));
30 roguejoin(x1
, y1
, x2
, y2
, horiz
)
34 register int x
, y
, middle
;
36 middle
= x1
+ rn2(x2
- x1
+ 1);
37 for (x
= min(x1
, middle
); x
<= max(x1
, middle
); x
++)
39 for (y
= min(y1
, y2
); y
<= max(y1
, y2
); y
++)
41 for (x
= min(middle
, x2
); x
<= max(middle
, x2
); x
++)
44 middle
= y1
+ rn2(y2
- y1
+ 1);
45 for (y
= min(y1
, middle
); y
<= max(y1
, middle
); y
++)
47 for (x
= min(x1
, x2
); x
<= max(x1
, x2
); x
++)
49 for (y
= min(middle
, y2
); y
<= max(middle
, y2
); y
++)
59 register int fromx
, fromy
, tox
, toy
;
62 r
[x
][y
].doortable
&= ~DOWN
;
69 fromx
= r
[x
][y
].rlx
+ rn2(r
[x
][y
].dx
);
70 fromy
= r
[x
][y
].rly
+ r
[x
][y
].dy
;
73 if (!IS_WALL(levl
[fromx
][fromy
].typ
))
74 impossible("down: no wall at %d,%d?", fromx
, fromy
);
75 dodoor(fromx
, fromy
, &rooms
[r
[x
][y
].nroom
]);
76 levl
[fromx
][fromy
].doormask
= D_NODOOR
;
80 impossible("down door from %d,%d going nowhere?", x
, y
);
84 r
[x
][y
].doortable
&= ~UP
;
91 tox
= r
[x
][y
].rlx
+ rn2(r
[x
][y
].dx
);
92 toy
= r
[x
][y
].rly
- 1;
95 if (!IS_WALL(levl
[tox
][toy
].typ
))
96 impossible("up: no wall at %d,%d?", tox
, toy
);
97 dodoor(tox
, toy
, &rooms
[r
[x
][y
].nroom
]);
98 levl
[tox
][toy
].doormask
= D_NODOOR
;
101 roguejoin(fromx
, fromy
, tox
, toy
, FALSE
);
103 } else if (dir
== RIGHT
) {
104 r
[x
][y
].doortable
&= ~RIGHT
;
111 fromx
= r
[x
][y
].rlx
+ r
[x
][y
].dx
;
112 fromy
= r
[x
][y
].rly
+ rn2(r
[x
][y
].dy
);
115 if (!IS_WALL(levl
[fromx
][fromy
].typ
))
116 impossible("down: no wall at %d,%d?", fromx
, fromy
);
117 dodoor(fromx
, fromy
, &rooms
[r
[x
][y
].nroom
]);
118 levl
[fromx
][fromy
].doormask
= D_NODOOR
;
122 impossible("right door from %d,%d going nowhere?", x
, y
);
126 r
[x
][y
].doortable
&= ~LEFT
;
133 tox
= r
[x
][y
].rlx
- 1;
134 toy
= r
[x
][y
].rly
+ rn2(r
[x
][y
].dy
);
137 if (!IS_WALL(levl
[tox
][toy
].typ
))
138 impossible("left: no wall at %d,%d?", tox
, toy
);
139 dodoor(tox
, toy
, &rooms
[r
[x
][y
].nroom
]);
140 levl
[tox
][toy
].doormask
= D_NODOOR
;
143 roguejoin(fromx
, fromy
, tox
, toy
, TRUE
);
146 impossible("corridor in direction %d?", dir
);
149 /* Modified walkfrom() from mkmaze.c */
160 #define doorhere (r[x][y].doortable)
161 if (x
> 0 && (!(doorhere
& LEFT
))
162 && (!r
[x
- 1][y
].doortable
|| !rn2(10)))
164 if (x
< 2 && (!(doorhere
& RIGHT
))
165 && (!r
[x
+ 1][y
].doortable
|| !rn2(10)))
167 if (y
> 0 && (!(doorhere
& UP
))
168 && (!r
[x
][y
- 1].doortable
|| !rn2(10)))
170 if (y
< 2 && (!(doorhere
& DOWN
))
171 && (!r
[x
][y
+ 1].doortable
|| !rn2(10)))
173 /* Rogue levels aren't just 3 by 3 mazes; they have some extra
174 * connections, thus that 1/10 chance
179 switch (dir
) { /* Move in direction */
209 /* Rogue levels are structured 3 by 3, with each section containing
210 * a room or an intersection. The minimum width is 2 each way.
211 * One difference between these and "real" Rogue levels: real Rogue
212 * uses 24 rows and NetHack only 23. So we cheat a bit by making the
213 * second row of rooms not as deep.
215 * Each normal space has 6/7 rows and 25 columns in which a room may
216 * actually be placed. Walls go from rows 0-5/6 and columns 0-24.
217 * Not counting walls, the room may go in
218 * rows 1-5 and columns 1-23 (numbering starting at 0). A room
219 * coordinate of this type may be converted to a level coordinate
220 * by adding 1+28*x to the column, and 7*y to the row. (The 1
221 * is because column 0 isn't used [we only use 1-78]).
222 * Room height may be 2-4 (2-5 on last row), length 2-23 (not
228 for (y
= 0; y
< 3; y
++)
229 for (x
= 0; x
< 3; x
++) {
230 /* Note: we want to insure at least 1 room. So, if the
231 * first 8 are all dummies, force the last to be a room.
233 if (!rn2(5) && (nroom
|| (x
< 2 && y
< 2))) {
234 /* Arbitrary: dummy rooms may only go where real
238 here
.rlx
= rn1(22, 2);
239 here
.rly
= rn1((y
== 2) ? 4 : 3, 2);
242 here
.dx
= rn1(22, 2); /* 2-23 long, plus walls */
243 here
.dy
= rn1((y
== 2) ? 4 : 3, 2); /* 2-5 high, plus walls */
245 /* boundaries of room floor */
246 here
.rlx
= rnd(23 - here
.dx
+ 1);
247 here
.rly
= rnd(((y
== 2) ? 5 : 4) - here
.dy
+ 1);
252 miniwalk(rn2(3), rn2(3));
254 for (y
= 0; y
< 3; y
++)
255 for (x
= 0; x
< 3; x
++) {
256 if (here
.real
) { /* Make a room */
257 int lowx
, lowy
, hix
, hiy
;
259 r
[x
][y
].nroom
= nroom
;
262 lowx
= 1 + 26 * x
+ here
.rlx
;
263 lowy
= 7 * y
+ here
.rly
;
264 hix
= 1 + 26 * x
+ here
.rlx
+ here
.dx
- 1;
265 hiy
= 7 * y
+ here
.rly
+ here
.dy
- 1;
266 /* Strictly speaking, it should be lit only if above
267 * level 10, but since Rogue rooms are only
268 * encountered below level 10, use !rn2(7).
270 add_room(lowx
, lowy
, hix
, hiy
, (boolean
) !rn2(7), OROOM
,
275 /* Now, add connecting corridors. */
276 for (y
= 0; y
< 3; y
++)
277 for (x
= 0; x
< 3; x
++) {
278 if (here
.doortable
& DOWN
)
279 roguecorr(x
, y
, DOWN
);
280 if (here
.doortable
& RIGHT
)
281 roguecorr(x
, y
, RIGHT
);
282 if (here
.doortable
& LEFT
)
283 impossible("left end of %d, %d never connected?", x
, y
);
284 if (here
.doortable
& UP
)
285 impossible("up end of %d, %d never connected?", x
, y
);
294 levl
[x
][y
].typ
= CORR
;
296 levl
[x
][y
].typ
= SCORR
;
303 register struct monst
*ghost
;
304 struct obj
*ghostobj
;
305 struct mkroom
*croom
;
309 return; /* Should never happen */
310 croom
= &rooms
[rn2(nroom
)];
313 if (!(ghost
= makemon(&mons
[PM_GHOST
], x
, y
, NO_MM_FLAGS
)))
315 ghost
->msleeping
= 1;
316 ghost
= christen_monst(ghost
, roguename());
319 ghostobj
= mksobj_at(FOOD_RATION
, x
, y
, FALSE
, FALSE
);
320 ghostobj
->quan
= (long) rnd(7);
321 ghostobj
->owt
= weight(ghostobj
);
324 ghostobj
= mksobj_at(MACE
, x
, y
, FALSE
, FALSE
);
325 ghostobj
->spe
= rnd(3);
329 ghostobj
= mksobj_at(TWO_HANDED_SWORD
, x
, y
, FALSE
, FALSE
);
330 ghostobj
->spe
= rnd(5) - 2;
334 ghostobj
= mksobj_at(BOW
, x
, y
, FALSE
, FALSE
);
339 ghostobj
= mksobj_at(ARROW
, x
, y
, FALSE
, FALSE
);
341 ghostobj
->quan
= (long) rn1(10, 25);
342 ghostobj
->owt
= weight(ghostobj
);
347 ghostobj
= mksobj_at(RING_MAIL
, x
, y
, FALSE
, FALSE
);
348 ghostobj
->spe
= rn2(3);
350 ghostobj
->oerodeproof
= TRUE
;
354 ghostobj
= mksobj_at(PLATE_MAIL
, x
, y
, FALSE
, FALSE
);
355 ghostobj
->spe
= rnd(5) - 2;
357 ghostobj
->oerodeproof
= TRUE
;
362 ghostobj
= mksobj_at(FAKE_AMULET_OF_YENDOR
, x
, y
, TRUE
, FALSE
);
363 ghostobj
->known
= TRUE
;