Mercurial > hg > early-roguelike
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); |