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