Annotation of early-roguelike/rogue5/passages.c, Revision 1.1.1.1
1.1 rubenllo 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:
383: * Number a passageway square and its brethren
384: */
385:
386: void
387: numpass(int y, int x)
388: {
389: int *fp;
390: struct room *rp;
391: int ch;
392:
393: if (x >= NUMCOLS || x < 0 || y >= NUMLINES || y <= 0)
394: return;
395: fp = &flat(y, x);
396: if (*fp & F_PNUM)
397: return;
398: if (newpnum)
399: {
400: pnum++;
401: newpnum = FALSE;
402: }
403: /*
404: * check to see if it is a door or secret door, i.e., a new exit,
405: * or a numerable type of place
406: */
407: if ((ch = chat(y, x)) == DOOR ||
408: (!(*fp & F_REAL) && (ch == '|' || ch == '-')))
409: {
410: rp = &passages[pnum];
411: rp->r_exit[rp->r_nexits].y = y;
412: rp->r_exit[rp->r_nexits++].x = x;
413: }
414: else if (!(*fp & F_PASS))
415: return;
416: *fp |= pnum;
417: /*
418: * recurse on the surrounding places
419: */
420: numpass(y + 1, x);
421: numpass(y - 1, x);
422: numpass(y, x + 1);
423: numpass(y, x - 1);
424: }
CVSweb