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