diff srogue/passages.c @ 36:2128c7dc8a40

Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 25 Nov 2010 12:21:41 +0000
parents
children 7f5f5f1ba09c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/passages.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,281 @@
+/*
+ * Draw the connecting passages
+ *
+ * @(#)passages.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * do_passages:
+ *	Draw all the passages on a level.
+ */
+
+do_passages()
+{
+	reg struct rdes *r1, *r2;
+	reg int i, j;
+	reg int roomcount;
+	static struct rdes {
+		bool conn[MAXROOMS];		/* possible to connect to room i */
+		bool isconn[MAXROOMS];		/* connection was made to room i */
+		bool	ingraph;			/* this room in graph already? */
+	} rdes[MAXROOMS] = {
+		{{ 0, 1, 0, 1, 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 1, 0, 1, 0, 1, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 1, 0, 0, 0, 1, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 1, 0, 0, 0, 1, 0, 1, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 1, 0, 1, 0, 1, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 1, 0, 1, 0, 0, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 0, 1, 0, 0, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 0, 0, 1, 0, 1, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 0, 0, 0, 1, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+	};
+
+	/*
+	 * reinitialize room graph description
+	 */
+	for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++) {
+		for (j = 0; j < MAXROOMS; j++)
+			r1->isconn[j] = FALSE;
+		r1->ingraph = FALSE;
+	}
+
+	/*
+	 * starting with one room, connect it to a random adjacent room and
+	 * then pick a new room to start with.
+	 */
+	roomcount = 1;
+	r1 = &rdes[rnd(MAXROOMS)];
+	r1->ingraph = TRUE;
+	do {
+		/*
+		 * find a room to connect with
+		 */
+		j = 0;
+		for (i = 0; i < MAXROOMS; i++)
+			if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
+				r2 = &rdes[i];
+		/*
+		 * if no adjacent rooms are outside the graph, pick a new room
+		 * to look from
+		 */
+		if (j == 0) {
+			do {
+				r1 = &rdes[rnd(MAXROOMS)];
+			} until (r1->ingraph);
+		}
+		/*
+		 * otherwise, connect new room to the graph, and draw a tunnel
+		 * to it
+		 */
+		else {
+			r2->ingraph = TRUE;
+			i = r1 - rdes;
+			j = r2 - rdes;
+			conn(i, j);
+			r1->isconn[j] = TRUE;
+			r2->isconn[i] = TRUE;
+			roomcount++;
+		}
+	} while (roomcount < MAXROOMS);
+
+	/*
+	 * attempt to add passages to the graph a random number of times so
+	 * that there isn't just one unique passage through it.
+	 */
+	for (roomcount = rnd(5); roomcount > 0; roomcount--) {
+		r1 = &rdes[rnd(MAXROOMS)];	/* a random room to look from */
+		/*
+		 * find an adjacent room not already connected
+		 */
+		j = 0;
+		for (i = 0; i < MAXROOMS; i++)
+			if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
+				r2 = &rdes[i];
+		/*
+		 * if there is one, connect it and look for the next added
+		 * passage
+		 */
+		if (j != 0) {
+			i = r1 - rdes;
+			j = r2 - rdes;
+			conn(i, j);
+			r1->isconn[j] = TRUE;
+			r2->isconn[i] = TRUE;
+		}
+	}
+}
+
+/*
+ * conn:
+ *	Cconnect two rooms.
+ */
+
+conn(r1, r2)
+int r1, r2;
+{
+	reg struct room *rpf, *rpt;
+	reg char rmt, direc;
+	reg int distance, turn_spot, turn_distance, rm;
+	struct coord curr, turn_delta, spos, epos;
+
+	if (r1 < r2) {
+		rm = r1;
+		if (r1 + 1 == r2)
+			direc = 'r';
+		else
+			direc = 'd';
+	}
+	else {
+		rm = r2;
+		if (r2 + 1 == r1)
+			direc = 'r';
+		else
+			direc = 'd';
+	}
+	rpf = &rooms[rm];
+	/*
+	 * Set up the movement variables, in two cases:
+	 * first drawing one down.
+	 */
+	if (direc == 'd') {
+		rmt = rm + 3;				/* room # of dest */
+		rpt = &rooms[rmt];			/* room pointer of dest */
+		delta.x = 0;				/* direction of move */
+		delta.y = 1;
+		spos.x = rpf->r_pos.x;			/* start of move */
+		spos.y = rpf->r_pos.y;
+		epos.x = rpt->r_pos.x;			/* end of move */
+		epos.y = rpt->r_pos.y;
+		if (!rf_on(rpf,ISGONE)) {		/* if not gone pick door pos */
+			spos.x += rnd(rpf->r_max.x-2)+1;
+			spos.y += rpf->r_max.y-1;
+		}
+		if (!rf_on(rpt,ISGONE))
+			epos.x += rnd(rpt->r_max.x-2)+1;
+		distance = abs(spos.y - epos.y) - 1;	/* distance to move */
+		turn_delta.y = 0;						/* direction to turn */
+		turn_delta.x = (spos.x < epos.x ? 1 : -1);
+		turn_distance = abs(spos.x - epos.x);	/* how far to turn */
+		turn_spot = rnd(distance-1) + 1;		/* where turn starts */
+	}
+	else if (direc == 'r') {		/* setup for moving right */
+		rmt = rm + 1;
+		rpt = &rooms[rmt];
+		delta.x = 1;
+		delta.y = 0;
+		spos.x = rpf->r_pos.x;
+		spos.y = rpf->r_pos.y;
+		epos.x = rpt->r_pos.x;
+		epos.y = rpt->r_pos.y;
+		if (!rf_on(rpf,ISGONE)) {
+			spos.x += rpf->r_max.x-1;
+			spos.y += rnd(rpf->r_max.y-2)+1;
+		}
+		if (!rf_on(rpt,ISGONE))
+			epos.y += rnd(rpt->r_max.y-2)+1;
+		distance = abs(spos.x - epos.x) - 1;
+		turn_delta.y = (spos.y < epos.y ? 1 : -1);
+		turn_delta.x = 0;
+		turn_distance = abs(spos.y - epos.y);
+		turn_spot = rnd(distance-1) + 1;
+	}
+	else {
+		msg("Error in connection tables.");
+	}
+	/*
+	 * Draw in the doors on either side of the passage
+	 * or just put #'s if the rooms are gone. Set up
+	 * pointers to the connected room.
+	 */
+	rpf->r_ptr[rpf->r_nexits] = rpt;
+	if (rf_on(rpf,ISGONE)) {
+		cmov(spos);
+		addch('#');		/* gone "from" room */
+	}
+	else
+		door(rpf, &spos);	/* add the door */
+	rpt->r_ptr[rpt->r_nexits] = rpf;
+	if (rf_on(rpt,ISGONE)) {
+		cmov(epos);
+		addch('#');		/* gone "to" room */
+	}
+	else
+		door(rpt, &epos);	/* add door */
+	/*
+	 * Get ready to move...
+	 */
+	curr.x = spos.x;
+	curr.y = spos.y;
+	while(distance > 0) {
+		/*
+		 * Move to new position
+		 */
+		curr.x += delta.x;
+		curr.y += delta.y;
+		/*
+		 * Check if we are at the turn place, if so do the turn
+		 */
+		if (distance == turn_spot && turn_distance > 0) {
+			while(turn_distance-- > 0) {
+				cmov(curr);
+				addch(PASSAGE);
+				curr.x += turn_delta.x;
+				curr.y += turn_delta.y;
+			}
+		}
+		/*
+		 * Continue digging along
+		 */
+		cmov(curr);
+		addch(PASSAGE);
+		distance--;
+	}
+	curr.x += delta.x;
+	curr.y += delta.y;
+	if (!ce(curr, epos)) {
+		msg("Warning, connectivity problem on this level.");
+	}
+}
+
+/*
+ * Add a door or possibly a secret door
+ * also enters the door in the exits array of the room.
+ */
+
+door(rm, cp)
+struct room *rm;
+struct coord *cp;
+{
+	cmov(*cp);
+	addch(rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR);
+	rm->r_exit[rm->r_nexits++] = *cp;
+}
+
+
+/*
+ * add_pass:
+ *	add the passages to the current window (wizard command)
+ */
+add_pass()
+{
+	reg int y, x, ch;
+
+	for (y = 1; y < LINES - 3; y++)
+		for (x = 0; x < COLS; x++)
+			if ((ch = mvinch(y, x)) == PASSAGE || ch == DOOR ||
+			  ch == SECRETDOOR)
+				mvwaddch(cw, y, x, ch);
+}