--- deliantra/server/random_maps/rogue_layout.C 2007/01/18 19:42:10 1.5
+++ deliantra/server/random_maps/rogue_layout.C 2010/07/05 00:07:21 1.17
@@ -1,8 +1,30 @@
+/*
+ * This file is part of Deliantra, the Roguelike Realtime MMORPG.
+ *
+ * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ * Copyright (©) Crossfire Development Team (restored, original file without copyright notice)
+ *
+ * Deliantra is free software: you can redistribute it and/or modify it under
+ * the terms of the Affero GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the Affero GNU General Public License
+ * and the GNU General Public License along with this program. If not, see
+ * .
+ *
+ * The authors can be reached via e-mail to
+ */
-/* generate a rogue/nethack-like layout */
+/* generate a rogue/nethack-like maze */
#include
#include
-#include
+#include
typedef struct
{
@@ -16,13 +38,12 @@
int rtype; /* circle or rectangular */
} Room;
-static int roguelike_place_room (Room * Rooms, int xsize, int ysize, int nrooms);
-static void roguelike_make_rooms (Room * Rooms, char **maze, int options);
-static void roguelike_link_rooms (Room * Rooms, char **maze, int xsize, int ysize);
-
+static int roguelike_place_room (Room *rooms, int xsize, int ysize, int nrooms);
+static void roguelike_make_rooms (Room *rooms, char **maze, int options);
+static void roguelike_link_rooms (Room *rooms, layout &maze);
int
-surround_check (char **layout, int i, int j, int Xsize, int Ysize)
+surround_check (layout &maze, int i, int j)
{
/* 1 = wall to left,
2 = wall to right,
@@ -30,95 +51,88 @@
8 = wall below */
int surround_index = 0;
- if ((i > 0) && (layout[i - 1][j] != 0 && layout[i - 1][j] != '.'))
- surround_index += 1;
- if ((i < Xsize - 1) && (layout[i + 1][j] != 0 && layout[i + 1][j] != '.'))
- surround_index += 2;
- if ((j > 0) && (layout[i][j - 1] != 0 && layout[i][j - 1] != '.'))
- surround_index += 4;
- if ((j < Ysize - 1) && (layout[i][j + 1] != 0 && layout[i][j + 1] != '.'))
- surround_index += 8;
+ if ((i > 0) && (maze[i - 1][j] != 0 && maze[i - 1][j] != '.')) surround_index |= 1;
+ if ((i < maze.w - 1) && (maze[i + 1][j] != 0 && maze[i + 1][j] != '.')) surround_index |= 2;
+ if ((j > 0) && (maze[i][j - 1] != 0 && maze[i][j - 1] != '.')) surround_index |= 4;
+ if ((j < maze.h - 1) && (maze[i][j + 1] != 0 && maze[i][j + 1] != '.')) surround_index |= 8;
+
return surround_index;
}
-
-/* actually make the layout: we work by a reduction process:
+/* actually make the maze: we work by a reduction process:
* first we make everything a wall, then we remove areas to make rooms
*/
-
-char **
-roguelike_layout_gen (int xsize, int ysize, int options)
+void
+roguelike_layout_gen (layout &maze, int options)
{
int i, j;
- Room *Rooms = 0;
Room *walk;
int nrooms = 0;
int tries = 0;
- /* allocate that array, write walls everywhere up */
- char **maze = (char **) malloc (sizeof (char *) * xsize);
-
- for (i = 0; i < xsize; i++)
- {
- maze[i] = (char *) malloc (sizeof (char) * ysize);
- for (j = 0; j < ysize; j++)
- maze[i][j] = '#';
- }
+ int xsize = maze.w;
+ int ysize = maze.h;
/* minimum room size is basically 5x5: if xsize/ysize is
less than 3x that then hollow things out, stick in
a stairsup and stairs down, and exit */
-
if (xsize < 11 || ysize < 11)
{
- for (i = 1; i < xsize - 1; i++)
- for (j = 1; j < ysize - 1; j++)
- maze[i][j] = 0;
- maze[(xsize - 1) / 2][(ysize - 1) / 2] = '>';
+ maze.clear ();
+ maze.border ();
+
+ maze[(xsize - 1) / 2][(ysize - 1) / 2 ] = '>';
maze[(xsize - 1) / 2][(ysize - 1) / 2 + 1] = '<';
- return maze;
+
+ return;
}
+ maze.fill ('#');
+
/* decide on the number of rooms */
- nrooms = rndm (10) + 6;
- Rooms = (Room *) calloc (nrooms + 1, sizeof (Room));
+ nrooms = rmg_rndm (10) + 6;
+ Room *rooms = salloc0 (nrooms + 1);
/* actually place the rooms */
i = 0;
while (tries < 450 && i < nrooms)
{
/* try to place the room */
- if (!roguelike_place_room (Rooms, xsize, ysize, nrooms))
+ if (!roguelike_place_room (rooms, xsize, ysize, nrooms))
tries++;
else
i++;
}
- if (i == 0)
- { /* no can do! */
- for (i = 1; i < xsize - 1; i++)
- for (j = 1; j < ysize - 1; j++)
- maze[i][j] = 0;
- maze[(xsize - 1) / 2][(ysize - 1) / 2] = '>';
- maze[(xsize - 1) / 2][(ysize - 1) / 2 + 1] = '<';
- free (Rooms);
- return maze;
- }
+ if (i == 0) /* no can do! */
+ {
+ maze.clear ();
+ maze.border ();
+ maze [(xsize - 1) / 2][(ysize - 1) / 2 ] = '>';
+ maze [(xsize - 1) / 2][(ysize - 1) / 2 + 1] = '<';
+
+ sfree (rooms, nrooms + 1);
+ return;
+ }
/* erase the areas occupied by the rooms */
- roguelike_make_rooms (Rooms, maze, options);
+ roguelike_make_rooms (rooms, maze, options);
- roguelike_link_rooms (Rooms, maze, xsize, ysize);
+ roguelike_link_rooms (rooms, maze);
/* put in the stairs */
- maze[Rooms->x][Rooms->y] = '<';
+ maze[rooms->x][rooms->y] = '<';
+
/* get the last one */
- for (walk = Rooms; walk->x != 0; walk++);
+ for (walk = rooms; walk->x != 0; walk++)
+ ;
+
/* back up one */
walk--;
- if (walk == Rooms)
+
+ if (walk == rooms)
{
/* In this case, there is only a single room. We don't want to
* clobber are up exit (above) with a down exit, so put the
@@ -139,9 +153,10 @@
{
if (maze[i][j] == '.')
maze[i][j] = 0;
+
if (maze[i][j] == 'D')
{ /* remove bad door. */
- int si = surround_check (maze, i, j, xsize, ysize);
+ int si = surround_check (maze, i, j);
if (si != 3 && si != 12)
{
@@ -153,16 +168,12 @@
}
}
- free (Rooms);
- return maze;
+ sfree (rooms, nrooms + 1);
}
-
-
static int
-roguelike_place_room (Room * Rooms, int xsize, int ysize, int nrooms)
+roguelike_place_room (Room *rooms, int xsize, int ysize, int nrooms)
{
-
int tx, ty; /* trial center locations */
int sx, sy; /* trial sizes */
int ax, ay; /* min coords of rect */
@@ -172,18 +183,16 @@
Room *walk;
/* decide on the base x and y sizes */
-
x_basesize = xsize / isqrt (nrooms);
y_basesize = ysize / isqrt (nrooms);
-
- tx = RANDOM () % xsize;
- ty = RANDOM () % ysize;
+ tx = rmg_rndm (xsize);
+ ty = rmg_rndm (ysize);
/* generate a distribution of sizes centered about basesize */
- sx = (RANDOM () % x_basesize) + (RANDOM () % x_basesize) + (RANDOM () % x_basesize);
- sy = (RANDOM () % y_basesize) + (RANDOM () % y_basesize) + (RANDOM () % y_basesize);
- sy = (int) (sy * .5); /* renormalize */
+ sx = rmg_rndm (x_basesize) + rmg_rndm (x_basesize) + rmg_rndm (x_basesize);
+ sy = rmg_rndm (y_basesize) + rmg_rndm (y_basesize) + rmg_rndm (y_basesize);
+ sy >>= 1; /* renormalize */
/* find the corners */
ax = tx - sx / 2;
@@ -193,17 +202,15 @@
zy = ty + sy / 2 + sy % 2;
/* check to see if it's in the map */
- if (zx > xsize - 1 || ax < 1)
- return 0;
- if (zy > ysize - 1 || ay < 1)
- return 0;
+ if (zx > xsize - 1 || ax < 1) return 0;
+ if (zy > ysize - 1 || ay < 1) return 0;
/* no small fish */
if (sx < 3 || sy < 3)
return 0;
/* check overlap with existing rooms */
- for (walk = Rooms; walk->x != 0; walk++)
+ for (walk = rooms; walk->x != 0; walk++)
{
int dx = abs (tx - walk->x);
int dy = abs (ty - walk->y);
@@ -215,30 +222,30 @@
/* if we've got here, presumably the room is OK. */
/* get a pointer to the first free room */
- for (walk = Rooms; walk->x != 0; walk++);
- walk->x = tx;
- walk->y = ty;
+ for (walk = rooms; walk->x; walk++)
+ ;
+
+ walk->x = tx;
+ walk->y = ty;
walk->sx = sx;
walk->sy = sy;
walk->ax = ax;
walk->ay = ay;
walk->zx = zx;
walk->zy = zy;
- return 1; /* success */
+ return 1; /* success */
}
-
/* write all the rooms into the maze */
static void
-roguelike_make_rooms (Room * Rooms, char **maze, int options)
+roguelike_make_rooms (Room *rooms, char **maze, int options)
{
int making_circle = 0;
- int i, j;
int R;
Room *walk;
- for (walk = Rooms; walk->x != 0; walk++)
+ for (walk = rooms; walk->x; walk++)
{
/* first decide what shape to make */
switch (options)
@@ -250,7 +257,7 @@
making_circle = 1;
break;
default:
- making_circle = ((rndm (3) == 0) ? 1 : 0);
+ making_circle = ((rmg_rndm (3) == 0) ? 1 : 0);
break;
}
@@ -260,28 +267,24 @@
R = walk->sy / 2;
/* enscribe a rectangle */
- for (i = walk->ax; i < walk->zx; i++)
- for (j = walk->ay; j < walk->zy; j++)
- {
- if (!making_circle || ((int) (0.5 + hypot (walk->x - i, walk->y - j))) <= R)
- maze[i][j] = '.';
- }
+ for (int i = walk->ax; i < walk->zx; i++)
+ for (int j = walk->ay; j < walk->zy; j++)
+ if (!making_circle || ((int) (0.5 + hypot (walk->x - i, walk->y - j))) <= R)
+ maze[i][j] = '.';
}
}
-
-
static void
-roguelike_link_rooms (Room * Rooms, char **maze, int xsize, int ysize)
+roguelike_link_rooms (Room *rooms, layout &maze)
{
Room *walk;
int i, j;
/* link each room to the previous room */
- if (Rooms[1].x == 0)
+ if (rooms[1].x == 0)
return; /* only 1 room */
- for (walk = Rooms + 1; walk->x != 0; walk++)
+ for (walk = rooms + 1; walk->x != 0; walk++)
{
int x1 = walk->x;
int y1 = walk->y;
@@ -289,7 +292,7 @@
int y2 = (walk - 1)->y;
int in_wall = 0;
- if (rndm (2))
+ if (rmg_rndm (2))
{ /* connect in x direction first */
/* horizontal connect */
/* swap (x1,y1) (x2,y2) if necessary */
@@ -321,12 +324,16 @@
else if (maze[i][j] != 'D' && maze[i][j] != '.')
maze[i][j] = 0;
}
- j = MIN (y1, y2);
+
+ j = min (y1, y2);
+
if (maze[i][j] == '.')
in_wall = 0;
+
if (maze[i][j] == 0 || maze[i][j] == '#')
in_wall = 1;
- for ( /* j set already */ ; j < MAX (y1, y2); j++)
+
+ for ( /* j set already */ ; j < max (y1, y2); j++)
{
if (in_wall == 0 && maze[i][j] == '#')
{
@@ -374,12 +381,15 @@
maze[i][j] = 0;
}
- i = MIN (x1, x2);
+ i = min (x1, x2);
+
if (maze[i][j] == '.')
in_wall = 0;
+
if (maze[i][j] == 0 || maze[i][j] == '#')
in_wall = 1;
- for ( /* i set already */ ; i < MAX (x1, x2); i++)
+
+ for ( /* i set already */ ; i < max (x1, x2); i++)
{
if (in_wall == 0 && maze[i][j] == '#')
{
@@ -400,3 +410,4 @@
}
}
+