Annotation of early-roguelike/rogue5/rooms.c, Revision 1.1.1.1
1.1 rubenllo 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: }
CVSweb