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