Mercurial > hg > early-roguelike
comparison rogue5/passages.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 * Draw the connecting passages | |
3 * | |
4 * @(#)passages.c 4.22 (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 <stdlib.h> | |
14 #include <curses.h> | |
15 #include "rogue.h" | |
16 | |
17 /* | |
18 * do_passages: | |
19 * Draw all the passages on a level. | |
20 */ | |
21 | |
22 void | |
23 do_passages(void) | |
24 { | |
25 struct rdes *r1, *r2 = NULL; | |
26 int i, j; | |
27 int roomcount; | |
28 struct rdes | |
29 { | |
30 int conn[MAXROOMS]; /* possible to connect to room i? */ | |
31 int isconn[MAXROOMS]; /* connection been made to room i? */ | |
32 int ingraph; /* this room in graph already? */ | |
33 } rdes[MAXROOMS] = { | |
34 { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
35 { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
36 { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
37 { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
38 { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
39 { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
40 { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
41 { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
42 { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 }, | |
43 }; | |
44 | |
45 /* | |
46 * reinitialize room graph description | |
47 */ | |
48 for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++) | |
49 { | |
50 for (j = 0; j < MAXROOMS; j++) | |
51 r1->isconn[j] = FALSE; | |
52 r1->ingraph = FALSE; | |
53 } | |
54 | |
55 /* | |
56 * starting with one room, connect it to a random adjacent room and | |
57 * then pick a new room to start with. | |
58 */ | |
59 roomcount = 1; | |
60 r1 = &rdes[rnd(MAXROOMS)]; | |
61 r1->ingraph = TRUE; | |
62 do | |
63 { | |
64 /* | |
65 * find a room to connect with | |
66 */ | |
67 j = 0; | |
68 for (i = 0; i < MAXROOMS; i++) | |
69 if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0) | |
70 r2 = &rdes[i]; | |
71 /* | |
72 * if no adjacent rooms are outside the graph, pick a new room | |
73 * to look from | |
74 */ | |
75 if (j == 0) | |
76 { | |
77 do | |
78 r1 = &rdes[rnd(MAXROOMS)]; | |
79 until (r1->ingraph); | |
80 } | |
81 /* | |
82 * otherwise, connect new room to the graph, and draw a tunnel | |
83 * to it | |
84 */ | |
85 else | |
86 { | |
87 r2->ingraph = TRUE; | |
88 i = (int)(r1 - rdes); | |
89 j = (int)(r2 - rdes); | |
90 conn(i, j); | |
91 r1->isconn[j] = TRUE; | |
92 r2->isconn[i] = TRUE; | |
93 roomcount++; | |
94 } | |
95 } while (roomcount < MAXROOMS); | |
96 | |
97 /* | |
98 * attempt to add passages to the graph a random number of times so | |
99 * that there isn't always just one unique passage through it. | |
100 */ | |
101 for (roomcount = rnd(5); roomcount > 0; roomcount--) | |
102 { | |
103 r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */ | |
104 /* | |
105 * find an adjacent room not already connected | |
106 */ | |
107 j = 0; | |
108 for (i = 0; i < MAXROOMS; i++) | |
109 if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0) | |
110 r2 = &rdes[i]; | |
111 /* | |
112 * if there is one, connect it and look for the next added | |
113 * passage | |
114 */ | |
115 if (j != 0) | |
116 { | |
117 i = (int)(r1 - rdes); | |
118 j = (int)(r2 - rdes); | |
119 conn(i, j); | |
120 r1->isconn[j] = TRUE; | |
121 r2->isconn[i] = TRUE; | |
122 } | |
123 } | |
124 passnum(); | |
125 } | |
126 | |
127 /* | |
128 * conn: | |
129 * Draw a corridor from a room in a certain direction. | |
130 */ | |
131 | |
132 void | |
133 conn(int r1, int r2) | |
134 { | |
135 struct room *rpf, *rpt = NULL; | |
136 int rmt; | |
137 int distance = 0, turn_spot, turn_distance = 0; | |
138 int rm; | |
139 int direc; | |
140 static coord del, turn_delta; | |
141 coord curr, spos, epos; | |
142 | |
143 if (r1 < r2) | |
144 { | |
145 rm = r1; | |
146 if (r1 + 1 == r2) | |
147 direc = 'r'; | |
148 else | |
149 direc = 'd'; | |
150 } | |
151 else | |
152 { | |
153 rm = r2; | |
154 if (r2 + 1 == r1) | |
155 direc = 'r'; | |
156 else | |
157 direc = 'd'; | |
158 } | |
159 rpf = &rooms[rm]; | |
160 /* | |
161 * Set up the movement variables, in two cases: | |
162 * first drawing one down. | |
163 */ | |
164 if (direc == 'd') | |
165 { | |
166 rmt = rm + 3; /* room # of dest */ | |
167 rpt = &rooms[rmt]; /* room pointer of dest */ | |
168 del.x = 0; /* direction of move */ | |
169 del.y = 1; | |
170 spos.x = rpf->r_pos.x; /* start of move */ | |
171 spos.y = rpf->r_pos.y; | |
172 epos.x = rpt->r_pos.x; /* end of move */ | |
173 epos.y = rpt->r_pos.y; | |
174 if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */ | |
175 do | |
176 { | |
177 spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1; | |
178 spos.y = rpf->r_pos.y + rpf->r_max.y - 1; | |
179 } while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS)); | |
180 if (!(rpt->r_flags & ISGONE)) | |
181 do | |
182 { | |
183 epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1; | |
184 } while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS)); | |
185 distance = abs(spos.y - epos.y) - 1; /* distance to move */ | |
186 turn_delta.y = 0; /* direction to turn */ | |
187 turn_delta.x = (spos.x < epos.x ? 1 : -1); | |
188 turn_distance = abs(spos.x - epos.x); /* how far to turn */ | |
189 } | |
190 else if (direc == 'r') /* setup for moving right */ | |
191 { | |
192 rmt = rm + 1; | |
193 rpt = &rooms[rmt]; | |
194 del.x = 1; | |
195 del.y = 0; | |
196 spos.x = rpf->r_pos.x; | |
197 spos.y = rpf->r_pos.y; | |
198 epos.x = rpt->r_pos.x; | |
199 epos.y = rpt->r_pos.y; | |
200 if (!(rpf->r_flags & ISGONE)) | |
201 do | |
202 { | |
203 spos.x = rpf->r_pos.x + rpf->r_max.x - 1; | |
204 spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1; | |
205 } while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS)); | |
206 if (!(rpt->r_flags & ISGONE)) | |
207 do | |
208 { | |
209 epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1; | |
210 } while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS)); | |
211 distance = abs(spos.x - epos.x) - 1; | |
212 turn_delta.y = (spos.y < epos.y ? 1 : -1); | |
213 turn_delta.x = 0; | |
214 turn_distance = abs(spos.y - epos.y); | |
215 } | |
216 #ifdef MASTER | |
217 else | |
218 debug("error in connection tables"); | |
219 #endif | |
220 | |
221 turn_spot = rnd(distance - 1) + 1; /* where turn starts */ | |
222 | |
223 /* | |
224 * Draw in the doors on either side of the passage or just put #'s | |
225 * if the rooms are gone. | |
226 */ | |
227 if (!(rpf->r_flags & ISGONE)) | |
228 door(rpf, &spos); | |
229 else | |
230 putpass(&spos); | |
231 if (!(rpt->r_flags & ISGONE)) | |
232 door(rpt, &epos); | |
233 else | |
234 putpass(&epos); | |
235 /* | |
236 * Get ready to move... | |
237 */ | |
238 curr.x = spos.x; | |
239 curr.y = spos.y; | |
240 while (distance > 0) | |
241 { | |
242 /* | |
243 * Move to new position | |
244 */ | |
245 curr.x += del.x; | |
246 curr.y += del.y; | |
247 /* | |
248 * Check if we are at the turn place, if so do the turn | |
249 */ | |
250 if (distance == turn_spot) | |
251 while (turn_distance--) | |
252 { | |
253 putpass(&curr); | |
254 curr.x += turn_delta.x; | |
255 curr.y += turn_delta.y; | |
256 } | |
257 /* | |
258 * Continue digging along | |
259 */ | |
260 putpass(&curr); | |
261 distance--; | |
262 } | |
263 curr.x += del.x; | |
264 curr.y += del.y; | |
265 if (!ce(curr, epos)) | |
266 msg("warning, connectivity problem on this level"); | |
267 } | |
268 | |
269 /* | |
270 * putpass: | |
271 * add a passage character or secret passage here | |
272 */ | |
273 | |
274 void | |
275 putpass(const coord *cp) | |
276 { | |
277 PLACE *pp; | |
278 | |
279 pp = INDEX(cp->y, cp->x); | |
280 pp->p_flags |= F_PASS; | |
281 if (rnd(10) + 1 < level && rnd(40) == 0) | |
282 pp->p_flags &= ~F_REAL; | |
283 else | |
284 pp->p_ch = PASSAGE; | |
285 } | |
286 | |
287 /* | |
288 * door: | |
289 * Add a door or possibly a secret door. Also enters the door in | |
290 * the exits array of the room. | |
291 */ | |
292 | |
293 void | |
294 door(struct room *rm, const coord *cp) | |
295 { | |
296 PLACE *pp; | |
297 | |
298 rm->r_exit[rm->r_nexits++] = *cp; | |
299 | |
300 if (rm->r_flags & ISMAZE) | |
301 return; | |
302 | |
303 pp = INDEX(cp->y, cp->x); | |
304 if (rnd(10) + 1 < level && rnd(5) == 0) | |
305 { | |
306 if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) | |
307 pp->p_ch = '-'; | |
308 else | |
309 pp->p_ch = '|'; | |
310 pp->p_flags &= ~F_REAL; | |
311 } | |
312 else | |
313 pp->p_ch = DOOR; | |
314 } | |
315 | |
316 #ifdef MASTER | |
317 /* | |
318 * add_pass: | |
319 * Add the passages to the current window (wizard command) | |
320 */ | |
321 | |
322 void | |
323 add_pass(void) | |
324 { | |
325 PLACE *pp; | |
326 int y, x; | |
327 int ch; | |
328 | |
329 for (y = 1; y < NUMLINES - 1; y++) | |
330 for (x = 0; x < NUMCOLS; x++) | |
331 { | |
332 pp = INDEX(y, x); | |
333 if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR || | |
334 (!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-'))) | |
335 { | |
336 ch = pp->p_ch; | |
337 if (pp->p_flags & F_PASS) | |
338 ch = PASSAGE; | |
339 pp->p_flags |= F_SEEN; | |
340 move(y, x); | |
341 if (pp->p_monst != NULL) | |
342 pp->p_monst->t_oldch = pp->p_ch; | |
343 else if (pp->p_flags & F_REAL) | |
344 addch(ch); | |
345 else | |
346 { | |
347 standout(); | |
348 addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR); | |
349 standend(); | |
350 } | |
351 } | |
352 } | |
353 } | |
354 #endif | |
355 | |
356 /* | |
357 * passnum: | |
358 * Assign a number to each passageway | |
359 */ | |
360 static int pnum; | |
361 static int newpnum; | |
362 | |
363 void | |
364 passnum(void) | |
365 { | |
366 struct room *rp; | |
367 int i; | |
368 | |
369 pnum = 0; | |
370 newpnum = FALSE; | |
371 for (rp = passages; rp < &passages[MAXPASS]; rp++) | |
372 rp->r_nexits = 0; | |
373 for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) | |
374 for (i = 0; i < rp->r_nexits; i++) | |
375 { | |
376 newpnum++; | |
377 numpass(rp->r_exit[i].y, rp->r_exit[i].x); | |
378 } | |
379 } | |
380 | |
381 /* | |
382 * numpass: | |