Hello BSD Games maintainers,

In case there's interest in adding the dodecahedron cave back to wump
without waiting for the other changes mentioned above, I've created a
patch for this.

I used the OpenBSD wump source files to copy these functions. The
OpenBSD dodecahedral_cave_init() creates a 20 room cave with three
tunnels from each room, and creates 2 bats and 2 pits. The nodes are
randomly assigned room numbers to give the appearance of change, but
the layout of the tunnel assignment guarantees each room will have 3
tunnels, and all rooms will be connected.

I adjusted the OpenBSD source in `dodecahedral_cave_init()` to use
`random()` instead of the BSD `arc4random()`, and I changed the
initialization loops to use the variables `room_num` and `link_num` to
match the format of the existing debug call in the same function. The
initial values for bat_num and pit_num were changed to -1 to ensure
the proper default values will be set in `main()` for both oldstyle
and regular play. I added the OpenBSD documentation for the `-o`
option into the wump.6 manpage as well.

I've been playing with this patch on my Debian 12 system, and it works
as I'd expect it to.

Please let me know if you have any questions, or if there's a better
way to submit a patch or discuss this change.

Thanks for your time,

Paul
diff --git a/wump/wump.6 b/wump/wump.6
index 67ae2c3..2d52203 100644
--- a/wump/wump.6
+++ b/wump/wump.6
@@ -40,7 +40,7 @@
 .Nd hunt the wumpus in an underground cave
 .Sh SYNOPSIS
 .Nm
-.Op Fl h
+.Op Fl ho
 .Op Fl a Ar arrows
 .Op Fl b Ar bats
 .Op Fl p Ar pits
@@ -69,6 +69,10 @@ The default is three.
 .It Fl h
 Play the hard version -- more pits, more bats, and a generally more
 dangerous cave.
+.It Fl o
+Play the original version, where there are twenty rooms arranged on the
+vertices of a dodecahedron, connected by the edges.
+In this case, the default is two pits and two bat rooms.
 .It Fl p
 Specifies the number of rooms in the cave which contain bottomless pits.
 The default is three.
diff --git a/wump/wump.c b/wump/wump.c
index ec21a14..d7fda7c 100644
--- a/wump/wump.c
+++ b/wump/wump.c
@@ -99,13 +99,14 @@ int player_loc = -1;			/* player location */
 int wumpus_loc = -1;			/* The Bad Guy location */
 int level = EASY;			/* level of play */
 int arrows_left;			/* arrows unshot */
+int oldstyle = 0;			/* dodecahedral cave? */
 
 #ifdef DEBUG
 int debug = 0;
 #endif
 
-int pit_num = PIT_COUNT;		/* # pits in cave */
-int bat_num = BAT_COUNT;		/* # bats */
+int pit_num = -1;		/* # pits in cave */
+int bat_num = -1;		/* # bats */
 int room_num = ROOMS_IN_CAVE;		/* # rooms in cave */
 int link_num = LINKS_IN_ROOM;		/* links per room  */
 int arrow_num = NUMBER_OF_ARROWS;	/* arrow inventory */
@@ -116,6 +117,7 @@ int	bats_nearby(void);
 void	cave_init(void);
 void	clear_things_in_cave(void);
 void	display_room_stats(void);
+void	dodecahedral_cave_init(void);
 int	gcd(int, int);
 int	getans(const char *);
 void	initialize_things_in_cave(void);
@@ -148,9 +150,9 @@ main(argc, argv)
 	setregid(getgid(), getgid());
 
 #ifdef DEBUG
-	while ((c = getopt(argc, argv, "a:b:hp:r:t:d")) != -1)
+	while ((c = getopt(argc, argv, "a:b:hop:r:t:d")) != -1)
 #else
-	while ((c = getopt(argc, argv, "a:b:hp:r:t:")) != -1)
+	while ((c = getopt(argc, argv, "a:b:hop:r:t:")) != -1)
 #endif
 		switch (c) {
 		case 'a':
@@ -167,6 +169,9 @@ main(argc, argv)
 		case 'h':
 			level = HARD;
 			break;
+		case 'o':
+			oldstyle = 1;
+			break;
 		case 'p':
 			pit_num = atoi(optarg);
 			break;
@@ -196,6 +201,21 @@ main(argc, argv)
 			usage();
 	}
 
+	if (oldstyle) {
+		room_num = 20;
+		link_num = 3;
+		/* Original game had exactly 2 bats and 2 pits */
+		if (bat_num < 0)
+			bat_num = 2;
+		if (pit_num < 0)
+			pit_num = 2;
+	} else {
+		if (bat_num < 0)
+			bat_num = BAT_COUNT;
+		if (pit_num < 0)
+			pit_num = PIT_COUNT;
+	}
+
 	if (link_num > MAX_LINKS_IN_ROOM ||
 	    link_num > room_num - (room_num / 4)) {
 		(void)fprintf(stderr,
@@ -221,7 +241,10 @@ main(argc, argv)
 	}
 
 	instructions();
-	cave_init();
+	if (oldstyle)
+		dodecahedral_cave_init();
+	else
+		cave_init();
 
 	/* and we're OFF!  da dum, da dum, da dum, da dum... */
 	(void)printf(
@@ -244,10 +267,13 @@ quiver holds %d custom super anti-evil Wumpus arrows.  Good luck.\n",
 
 		if (!getans("\nCare to play another game? (y-n) "))
 			exit(0);
-		if (getans("In the same cave? (y-n) "))
-			clear_things_in_cave();
-		else
-			cave_init();
+		clear_things_in_cave();
+		if (!getans("In the same cave? (y-n) ")) {
+			if (oldstyle)
+				dodecahedral_cave_init();
+			else
+				cave_init();
+		}
 	}
 	/* NOTREACHED */
 	return (0);
@@ -609,6 +635,73 @@ try_again:		link = (random() % room_num) + 1;
 #endif
 }
 
+void
+dodecahedral_cave_init()
+{
+	int vert[20][3] = {
+		{1, 4, 7},
+		{0, 2, 9},
+		{1, 3, 11},
+		{2, 4, 13},
+		{0, 3, 5},
+		{4, 6, 14},
+		{5, 7, 16},
+		{0, 6, 8},
+		{7, 9, 17},
+		{1, 8, 10},
+		{9, 11, 18},
+		{2, 10, 12},
+		{11, 13, 19},
+		{3, 12, 14},
+		{5, 13, 15},
+		{14, 16, 19},
+		{6, 15, 17},
+		{8, 16, 18},
+		{10, 17, 19},
+		{12, 15, 18},
+	};
+	int loc[20];
+	int i, j, temp;
+
+	srandom((int)time((time_t *)0));
+
+	if (room_num != 20 || link_num != 3)
+		errx(1, "wrong parameters for dodecahedron");
+	for (i = 0; i < room_num; i++)
+		loc[i] = i;
+	for (i = 0; i < room_num; i++) {
+		j = (random() % (room_num - i));
+		if (j) {
+			temp = loc[i];
+			loc[i] = loc[i + j];
+			loc[i + j] = temp;
+		}
+	}
+	/* cave is offset by 1 */
+	for (i = 0; i < room_num; i++) {
+		for (j = 0; j < link_num; j++)
+			cave[loc[i] + 1].tunnel[j] = loc[vert[i][j]] + 1;
+	}
+
+	/*
+	 * now that we're done, sort the tunnels in each of the rooms to
+	 * make it easier on the intrepid adventurer.
+	 */
+	for (i = 1; i <= room_num; ++i)
+		qsort(cave[i].tunnel, (u_int)link_num,
+		    sizeof(cave[i].tunnel[0]), int_compare);
+
+#ifdef DEBUG
+	if (debug)
+		for (i = 1; i <= room_num; ++i) {
+			(void)printf("<room %d  has tunnels to ", i);
+			for (j = 0; j < link_num; ++j)
+				(void)printf("%d ", cave[i].tunnel[j]);
+			(void)printf(">\n");
+		}
+#endif
+}
+
 void
 clear_things_in_cave()
 {

Reply via email to