comparison rogue5/rooms.c @ 33:f502bf60e6e4

Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author elwin
date Mon, 24 May 2010 20:10:59 +0000
parents
children
comparison
equal deleted inserted replaced
32:2dcd75e6a736 33:f502bf60e6e4
1 /*
2 * Create the layout for the new level
3 *
4 * @(#)rooms.c 4.45 (Berkeley) 02/05/99
5 *
6 * Rogue: Exploring the Dungeons of Doom
7 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
8 * All rights reserved.
9 *
10 * See the file LICENSE.TXT for full copyright and licensing information.
11 */
12
13 #include <ctype.h>
14 #include <curses.h>
15 #include "rogue.h"
16
17 typedef struct spot { /* position matrix for maze positions */
18 int nexits;
19 coord exits[4];
20 int used;
21 } SPOT;
22
23 #define GOLDGRP 1
24
25 /*
26 * do_rooms:
27 * Create rooms and corridors with a connectivity graph
28 */
29
30 void
31 do_rooms(void)
32 {
33 int i;
34 struct room *rp;
35 THING *tp;
36 int left_out;
37 coord top;
38 coord bsze; /* maximum room size */
39 coord mp;
40
41 bsze.x = NUMCOLS / 3;
42 bsze.y = NUMLINES / 3;
43 /*
44 * Clear things for a new level
45 */
46 for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
47 {
48 rp->r_goldval = 0;
49 rp->r_nexits = 0;
50 rp->r_flags = 0;
51 }
52 /*
53 * Put the gone rooms, if any, on the level
54 */
55 left_out = rnd(4);
56 for (i = 0; i < left_out; i++)
57 rooms[rnd_room()].r_flags |= ISGONE;
58 /*
59 * dig and populate all the rooms on the level
60 */
61 for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)
62 {
63 /*
64 * Find upper left corner of box that this room goes in
65 */
66 top.x = (i % 3) * bsze.x + 1;
67 top.y = (i / 3) * bsze.y;
68 if (rp->r_flags & ISGONE)
69 {
70 /*
71 * Place a gone room. Make certain that there is a blank line
72 * for passage drawing.
73 */
74 do
75 {
76 rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1;
77 rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1;
78 rp->r_max.x = -NUMCOLS;
79 rp->r_max.y = -NUMLINES;
80 } until (rp->r_pos.y > 0 && rp->r_pos.y < NUMLINES-1);
81 continue;
82 }
83 /*
84 * set room type
85 */
86 if (rnd(10) < level - 1)
87 {
88 rp->r_flags |= ISDARK; /* dark room */
89 if (rnd(15) == 0)
90 rp->r_flags = ISMAZE; /* maze room */
91 }
92 /*
93 * Find a place and size for a random room
94 */
95 if (rp->r_flags & ISMAZE)
96 {
97 rp->r_max.x = bsze.x - 1;
98 rp->r_max.y = bsze.y - 1;
99 if ((rp->r_pos.x = top.x) == 1)
100 rp->r_pos.x = 0;
101 if ((rp->r_pos.y = top.y) == 0)
102 {
103 rp->r_pos.y++;
104 rp->r_max.y--;
105 }
106 }
107 else
108 do
109 {
110 rp->r_max.x = rnd(bsze.x - 4) + 4;
111 rp->r_max.y = rnd(bsze.y - 4) + 4;
112 rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
113 rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
114 } until (rp->r_pos.y != 0);
115 draw_room(rp);
116 /*
117 * Put the gold in
118 */
119 if (rnd(2) == 0 && (!amulet || level >= max_level))
120 {
121 THING *gold;
122
123 gold = new_item();
124 gold->o_goldval = rp->r_goldval = GOLDCALC;
125 find_floor(rp, &rp->r_gold, FALSE, FALSE);
126 gold->o_pos = rp->r_gold;
127 chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
128 gold->o_flags = ISMANY;
129 gold->o_group = GOLDGRP;
130 gold->o_type = GOLD;
131 attach(lvl_obj, gold);
132 }
133 /*
134 * Put the monster in
135 */
136 if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
137 {
138 tp = new_item();
139 find_floor(rp, &mp, FALSE, TRUE);
140 new_monster(tp, randmonster(FALSE), &mp);
141 give_pack(tp);
142 }
143 }
144 }
145
146 /*
147 * draw_room:
148 * Draw a box around a room and lay down the floor for normal
149 * rooms; for maze rooms, draw maze.
150 */
151
152 void
153 draw_room(const struct room *rp)
154 {
155 int y, x;
156
157 if (rp->r_flags & ISMAZE)
158 do_maze(rp);
159 else
160 {
161 vert(rp, rp->r_pos.x); /* Draw left side */
162 vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */
163 horiz(rp, rp->r_pos.y); /* Draw top */
164 horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */
165
166 /*
167 * Put the floor down
168 */
169 for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
170 for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
171 chat(y, x) = FLOOR;
172 }
173 }
174
175 /*
176 * vert:
177 * Draw a vertical line
178 */
179
180 void
181 vert(const struct room *rp, int startx)
182 {
183 int y;
184
185 for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
186 chat(y, startx) = '|';
187 }
188
189 /*
190 * horiz:
191 * Draw a horizontal line
192 */
193
194 void
195 horiz(const struct room *rp, int starty)
196 {
197 int x;
198
199 for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
200 chat(starty, x) = '-';
201 }
202
203 /*
204 * do_maze:
205 * Dig a maze
206 */
207
208 static int Maxy, Maxx, Starty, Startx;
209
210 static SPOT maze[NUMLINES/3+1][NUMCOLS/3+1];
211
212
213 void
214 do_maze(const struct room *rp)
215 {
216 SPOT *sp;
217 int starty, startx;
218 coord pos;
219
220 for (sp = &maze[0][0]; sp <= &maze[NUMLINES / 3][NUMCOLS / 3]; sp++)
221 {
222 sp->used = FALSE;
223 sp->nexits = 0;
224 }
225
226 Maxy = rp->r_max.y;
227 Maxx = rp->r_max.x;
228 Starty = rp->r_pos.y;
229 Startx = rp->r_pos.x;
230 starty = (rnd(rp->r_max.y) / 2) * 2;
231 startx = (rnd(rp->r_max.x) / 2) * 2;
232 pos.y = starty + Starty;
233 pos.x = startx + Startx;
234 putpass(&pos);
235 dig(starty, startx);
236 }
237
238 /*
239 * dig:
240 * Dig out from around where we are now, if possible
241 */
242
243 void
244 dig(int y, int x)
245 {
246 coord *cp;
247 int cnt, newy, newx, nexty = 0, nextx = 0;
248 coord pos;
249 coord del[4] = {
250 {2, 0}, {-2, 0}, {0, 2}, {0, -2}
251 };
252
253 for (;;)
254 {
255 cnt = 0;
256 for (cp = del; cp <= &del[3]; cp++)
257 {
258 newy = y + cp->y;
259 newx = x + cp->x;
260 if (newy < 0 || newy > Maxy || newx < 0 || newx > Maxx)
261 continue;
262 if (flat(newy + Starty, newx + Startx) & F_PASS)
263 continue;
264 if (rnd(++cnt) == 0)
265 {
266 nexty = newy;
267 nextx = newx;
268 }
269 }
270 if (cnt == 0)
271 return;
272 accnt_maze(y, x, nexty, nextx);
273 accnt_maze(nexty, nextx, y, x);
274 if (nexty == y)
275 {
276 pos.y = y + Starty;
277 if (nextx - x < 0)
278 pos.x = nextx + Startx + 1;
279 else
280 pos.x = nextx + Startx - 1;
281 }
282 else
283 {
284 pos.x = x + Startx;
285 if (nexty - y < 0)
286 pos.y = nexty + Starty + 1;
287 else
288 pos.y = nexty + Starty - 1;
289 }
290 putpass(&pos);
291 pos.y = nexty + Starty;
292 pos.x = nextx + Startx;
293 putpass(&pos);
294 dig(nexty, nextx);
295 }
296 }
297
298 /*
299 * accnt_maze:
300 * Account for maze exits
301 */
302
303 void
304 accnt_maze(int y, int x, int ny, int nx)
305 {
306 SPOT *sp;
307 coord *cp;
308
309 sp = &maze[y][x];
310 for (cp = sp->exits; cp < &sp->exits[sp->nexits]; cp++)
311 if (cp->y == ny && cp->x == nx)
312 return;
313 cp->y = ny;
314 cp->x = nx;
315 }
316
317 /*
318 * rnd_pos:
319 * Pick a random spot in a room
320 */
321
322 void
323 rnd_pos(const struct room *rp, coord *cp)
324 {
325 cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
326 cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
327 }
328
329 /*
330 * find_floor:
331 * Find a valid floor spot in this room. If rp is NULL, then
332 * pick a new room each time around the loop.
333 */
334 int
335 find_floor(const struct room *rp, coord *cp, int limit, int monst)
336 {
337 PLACE *pp;
338 int cnt;
339 int compchar = 0;
340 int pickroom;
341
342 pickroom = (rp == NULL);
343
344 if (!pickroom)
345 compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR);
346 cnt = limit;
347 for (;;)
348 {
349 if (limit && cnt-- == 0)
350 return FALSE;
351 if (pickroom)
352 {
353 rp = &rooms[rnd_room()];
354 compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR);
355 }
356 rnd_pos(rp, cp);
357 pp = INDEX(cp->y, cp->x);
358 if (monst)
359 {
360 if (pp->p_monst == NULL && step_ok(pp->p_ch))
361 return TRUE;
362 }
363 else if (pp->p_ch == compchar)
364 return TRUE;
365 }
366 }
367
368 /*
369 * enter_room:
370 * Code that is executed whenver you appear in a room
371 */
372
373 void
374 enter_room(const coord *cp)
375 {
376 struct room *rp;
377 THING *tp;
378 int y, x;
379 chtype ch;
380
381 rp = proom = roomin(cp);
382 door_open(rp);
383 if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
384 for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
385 {
386 move(y, rp->r_pos.x);
387 for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
388 {
389 tp = moat(y, x);
390 ch = chat(y, x);
391 if (tp == NULL)
392 if (CCHAR(inch()) != ch)
393 addch(ch);
394 else
395 move(y, x + 1);
396 else
397 {
398 tp->t_oldch = ch;
399 if (!see_monst(tp))
400 if (on(player, SEEMONST))
401 {
402 standout();
403 addch(tp->t_disguise);
404 standend();
405 }
406 else
407 addch(ch);
408 else
409 addch(tp->t_disguise);
410 }
411 }
412 }
413 }
414
415 /*
416 * leave_room:
417 * Code for when we exit a room
418 */
419
420 void
421 leave_room(const coord *cp)
422 {
423 PLACE *pp;
424 struct room *rp;
425 int y, x;
426 int floor;
427 int ch;
428
429 rp = proom;
430
431 if (rp->r_flags & ISMAZE)
432 return;
433
434 if (rp->r_flags & ISGONE)
435 floor = PASSAGE;
436 else if (!(rp->r_flags & ISDARK) || on(player, ISBLIND))
437 floor = FLOOR;
438 else
439 floor = ' ';
440
441 proom = &passages[flat(cp->y, cp->x) & F_PNUM];
442 for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
443 for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
444 {
445 move(y, x);
446 switch ( ch = CCHAR(inch()) )
447 {
448 case FLOOR:
449 if (floor == ' ' && ch != ' ')
450 addch(' ');
451 break;
452 default:
453 /*
454 * to check for monster, we have to strip out
455 * standout bit
456 */
457 if (isupper(toascii(ch)))
458 {
459 if (on(player, SEEMONST))
460 {
461 standout();
462 addch(ch);
463 standend();
464 break;
465 }
466 pp = INDEX(y,x);
467 addch(pp->p_ch == DOOR ? DOOR : floor);
468 }
469 }
470 }
471 door_open(rp);
472 }