comparison urogue/passages.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 passages.c - Draw the connecting passages
3
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
10 All rights reserved.
11
12 Based on "Rogue: Exploring the Dungeons of Doom"
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14 All rights reserved.
15
16 See the file LICENSE.TXT for full copyright and licensing information.
17 */
18
19 #include <stdlib.h>
20 #include "rogue.h"
21
22 #define cmov(xy) move((xy).y, (xy).x)
23
24 /*
25 do_passages()
26 Draw all the passages on a level.
27 */
28
29 void
30 do_passages(void)
31 {
32 struct rdes *r1, *r2 = NULL;
33 int i, j;
34 int roomcount;
35
36 static struct rdes rdes[MAXROOMS] =
37 {
38 {{ 0, 1, 0, 1, 0, 0, 0, 0, 0},
39 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
40 {{ 1, 0, 1, 0, 1, 0, 0, 0, 0},
41 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
42 {{ 0, 1, 0, 0, 0, 1, 0, 0, 0},
43 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
44 {{ 1, 0, 0, 0, 1, 0, 1, 0, 0},
45 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
46 {{ 0, 1, 0, 1, 0, 1, 0, 1, 0},
47 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
48 {{ 0, 0, 1, 0, 1, 0, 0, 0, 1},
49 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
50 {{ 0, 0, 0, 1, 0, 0, 0, 1, 0},
51 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
52 {{ 0, 0, 0, 0, 1, 0, 1, 0, 1},
53 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0},
54 {{ 0, 0, 0, 0, 0, 1, 0, 1, 0},
55 { 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0}
56 };
57
58 /* reinitialize room graph description */
59
60 for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++)
61 {
62 for (j = 0; j < MAXROOMS; j++)
63 r1->isconn[j] = FALSE;
64
65 r1->ingraph = FALSE;
66 }
67
68 /*
69 * starting with one room, connect it to a random adjacent room and
70 * then pick a new room to start with.
71 */
72
73 roomcount = 1;
74 r1 = &rdes[rnd(MAXROOMS)];
75 r1->ingraph = TRUE;
76
77 do
78 {
79 j = 0;
80
81 for (i = 0; i < MAXROOMS; i++)
82 if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
83 r2 = &rdes[i];
84
85 /*
86 * if no adjacent rooms are outside the graph, pick a new
87 * room to look from
88 */
89
90 if (j == 0)
91 do
92 {
93 r1 = &rdes[rnd(MAXROOMS)];
94 }
95 while (!r1->ingraph);
96
97 /*
98 * otherwise, connect new room to the graph, and draw a
99 * tunnel to it
100 */
101 else
102 {
103 r2->ingraph = TRUE;
104 i = (int)(r1 - rdes);
105 j = (int)(r2 - rdes);
106 conn(i, j);
107 r1->isconn[j] = TRUE;
108 r2->isconn[i] = TRUE;
109 roomcount++;
110 }
111 }
112 while (roomcount < MAXROOMS);
113
114 /*
115 * attempt to add passages to the graph a random number of times so
116 * that there isn't just one unique passage through it.
117 */
118
119 for (roomcount = rnd(5); roomcount > 0; roomcount--)
120 {
121 r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
122
123 /*
124 * find an adjacent room not already connected
125 */
126
127 j = 0;
128 for (i = 0; i < MAXROOMS; i++)
129 if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
130 r2 = &rdes[i];
131
132 /*
133 * if there is one, connect it and look for the next added
134 * passage
135 */
136
137 if (j != 0)
138 {
139 i = (int)(r1 - rdes);
140 j = (int)(r2 - rdes);
141 conn(i, j);
142 r1->isconn[j] = TRUE;
143 r2->isconn[i] = TRUE;
144 }
145 }
146 }
147
148 /*
149 conn()
150 Draw a corridor from a room in a certain direction.
151 */
152
153 void
154 conn(int r1, int r2)
155 {
156 struct room *rpf, *rpt = NULL;
157 int rmt;
158 int distance = 0, turn_spot = 0, turn_distance = 0;
159 int rm;
160 char direc;
161 coord delt = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
162
163 if (r1 < r2)
164 {
165 rm = r1;
166
167 if (r1 + 1 == r2)
168 direc = 'r';
169 else
170 direc = 'd';
171 }
172 else
173 {
174 rm = r2;
175
176 if (r2 + 1 == r1)
177 direc = 'r';
178 else
179 direc = 'd';
180 }
181
182 rpf = &rooms[rm];
183
184 /*
185 * Set up the movement variables, in two cases: first drawing one
186 * down.
187 */
188
189 if (direc == 'd')
190 {
191 rmt = rm + 3; /* room # of dest */
192 rpt = &rooms[rmt]; /* room pointer of dest */
193 delt.x = 0; /* direction of move */
194 delt.y = 1;
195 spos.x = rpf->r_pos.x; /* start of move */
196 spos.y = rpf->r_pos.y;
197 epos.x = rpt->r_pos.x; /* end of move */
198 epos.y = rpt->r_pos.y;
199
200 if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
201 {
202 spos.x += rnd(rpf->r_max.x - 2) + 1;
203 spos.y += rpf->r_max.y - 1;
204 }
205
206 if (!(rpt->r_flags & ISGONE))
207 epos.x += rnd(rpt->r_max.x - 2) + 1;
208
209 distance = abs(spos.y - epos.y) - 1; /* distance to move */
210 turn_delta.y = 0; /* direction to turn */
211 turn_delta.x = (spos.x < epos.x ? 1 : -1);
212 turn_distance = abs(spos.x - epos.x); /* how far to turn */
213 turn_spot = rnd(distance - 1) + 1; /* where turn starts */
214 }
215 else if (direc == 'r') /* setup for moving right */
216 {
217 rmt = rm + 1;
218 rpt = &rooms[rmt];
219 delt.x = 1;
220 delt.y = 0;
221 spos.x = rpf->r_pos.x;
222 spos.y = rpf->r_pos.y;
223 epos.x = rpt->r_pos.x;
224 epos.y = rpt->r_pos.y;
225
226 if (!(rpf->r_flags & ISGONE))
227 {
228 spos.x += rpf->r_max.x - 1;
229 spos.y += rnd(rpf->r_max.y - 2) + 1;
230 }
231
232 if (!(rpt->r_flags & ISGONE))
233 epos.y += rnd(rpt->r_max.y - 2) + 1;
234
235 distance = abs(spos.x - epos.x) - 1;
236 turn_delta.y = (spos.y < epos.y ? 1 : -1);
237 turn_delta.x = 0;
238 turn_distance = abs(spos.y - epos.y);
239 turn_spot = rnd(distance - 1) + 1;
240 }
241 else
242 debug("Error in connection tables.");
243
244 /*
245 * Draw in the doors on either side of the passage or just put #'s if
246 * the rooms are gone.
247 */
248
249 if (!(rpf->r_flags & ISGONE))
250 door(rpf, &spos);
251 else
252 {
253 cmov(spos);
254 addch('#');
255 }
256
257 if (!(rpt->r_flags & ISGONE))
258 door(rpt, &epos);
259 else
260 {
261 cmov(epos);
262 addch('#');
263 }
264
265 /* Get ready to move... */
266
267 curr.x = spos.x;
268 curr.y = spos.y;
269
270 while (distance)
271 {
272 /* Move to new position */
273
274 curr.x += delt.x;
275 curr.y += delt.y;
276
277 /* Check if we are at the turn place, if so do the turn */
278
279 if (distance == turn_spot && turn_distance > 0)
280 while (turn_distance--)
281 {
282 cmov(curr);
283 addch(PASSAGE);
284 curr.x += turn_delta.x;
285 curr.y += turn_delta.y;
286 }
287
288 /* Continue digging along */
289
290 cmov(curr);
291 addch(PASSAGE);
292 distance--;
293 }
294
295 curr.x += delt.x;
296 curr.y += delt.y;
297
298 if (!ce(curr, epos))
299 msg("Warning, connectivity problem on this level.");
300 }
301
302 /*
303 door()
304 Add a door or possibly a secret door also enters the door in the exits
305 array of the room.
306 */
307
308 void
309 door(struct room *rm, coord *cp)
310 {
311 char a_door;
312
313 cmov(*cp);
314
315 a_door = (rnd(10)<level - 1 && rnd(100) < 20) ? SECRETDOOR : DOOR;
316
317 addch(a_door);
318
319 rm->r_exit[rm->r_nexits++] = *cp;
320 }