rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

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}