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