--- deliantra/server/random_maps/rogue_layout.C 2006/08/29 08:01:36 1.2
+++ deliantra/server/random_maps/rogue_layout.C 2010/06/30 20:51:02 1.13
@@ -1,189 +1,230 @@
+/*
+ * 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 */
#include
#include
-#include
+#include
-typedef struct {
+typedef struct
+{
int x;
- int y; /* coordinates of room centers */
+ int y; /* coordinates of room centers */
int sx;
- int sy; /* sizes */
- int ax,ay,zx,zy; /* coordinates of extrema of the rectangle */
+ int sy; /* sizes */
+ int ax, ay, zx, zy; /* coordinates of extrema of the rectangle */
- int rtype; /* circle or rectangular */
+ 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);
-
-
-int surround_check(char **layout,int i,int j,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, char **maze, int xsize, int ysize);
+
+int
+surround_check (char **layout, int i, int j, int Xsize, int Ysize)
+{
/* 1 = wall to left,
- 2 = wall to right,
- 4 = wall above
- 8 = wall below */
+ 2 = wall to right,
+ 4 = wall above
+ 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) && (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;
+
return surround_index;
}
-
/* actually make the layout: 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) {
- int i,j;
- Room * Rooms = 0;
+void
+roguelike_layout_gen (Layout maze, int options)
+{
+ int i, j;
Room *walk;
- int nrooms=0;
- int tries=0;
+ int nrooms = 0;
+ int tries = 0;
- /* allocate that array, write walls everywhere up */
- char **maze = (char **)malloc(sizeof(char*)*xsize);
- for(i=0;iw;
+ 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)
+ {
+ maze->clear ();
+ maze->border ();
+
+ maze[(xsize - 1) / 2][(ysize - 1) / 2 ] = '>';
+ maze[(xsize - 1) / 2][(ysize - 1) / 2 + 1] = '<';
+
+ return;
+ }
- if(xsize < 11 || ysize < 11) {
- for(i=1;i';
- maze[(xsize-1)/2][(ysize-1)/2+1]='<';
- return maze;
- }
+ maze->fill ('#');
/* decide on the number of rooms */
- nrooms = RANDOM() % 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)) tries++;
- else i++;
- }
-
- if(i==0) { /* no can do! */
- for(i=1;i';
- maze[(xsize-1)/2][(ysize-1)/2+1]='<';
- free(Rooms);
- return maze;
- }
-
-
+ i = 0;
+ while (tries < 450 && i < nrooms)
+ {
+ /* try to place the room */
+ if (!roguelike_place_room (rooms, xsize, ysize, nrooms))
+ tries++;
+ else
+ i++;
+ }
+
+ 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, xsize, ysize);
/* 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) {
- /* 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
- * other exit one space up/down, depending which is a space
- * and not a wall.
- */
- if (maze[walk->x][walk->y+1] == '.')
- maze[walk->x][walk->y+1] = '>';
- else
- maze[walk->x][walk->y-1] = '>';
- }
+
+ 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
+ * other exit one space up/down, depending which is a space
+ * and not a wall.
+ */
+ if (maze[walk->x][walk->y + 1] == '.')
+ maze[walk->x][walk->y + 1] = '>';
+ else
+ maze[walk->x][walk->y - 1] = '>';
+ }
else
maze[walk->x][walk->y] = '>';
/* convert all the '.' to 0, we're through with the '.' */
- for(i=0;i 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;
+ if (sx < 3 || sy < 3)
+ return 0;
/* check overlap with existing rooms */
- for(walk=Rooms;walk->x!=0;walk++) {
- int dx = abs(tx - walk->x);
- int dy = abs(ty - walk->y);
- if( (dx < (walk->sx + sx)/2 + 2) &&
- (dy < (walk->sy + sy)/2 + 2))
- return 0;
- }
+ for (walk = rooms; walk->x != 0; walk++)
+ {
+ int dx = abs (tx - walk->x);
+ int dy = abs (ty - walk->y);
+
+ if ((dx < (walk->sx + sx) / 2 + 2) && (dy < (walk->sy + sy) / 2 + 2))
+ return 0;
+ }
/* 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++);
+ for (walk = rooms; walk->x != 0; walk++)
+ ;
+
walk->x = tx;
walk->y = ty;
walk->sx = sx;
@@ -192,143 +233,182 @@
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) {
- int making_circle=0;
- int i,j;
+static void
+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++) {
- /* first decide what shape to make */
- switch(options) {
- case 1:
- making_circle=0;
- break;
- case 2:
- making_circle = 1;
- break;
- default:
- making_circle = ((RANDOM()%3 == 0)? 1:0);
- break;
- }
+ for (walk = rooms; walk->x != 0; walk++)
+ {
+ /* first decide what shape to make */
+ switch (options)
+ {
+ case 1:
+ making_circle = 0;
+ break;
+ case 2:
+ making_circle = 1;
+ break;
+ default:
+ making_circle = ((rmg_rndm (3) == 0) ? 1 : 0);
+ break;
+ }
- if(walk->sx < walk->sy)
- R = walk->sx/2;
- else
- R = walk->sy/2;
-
- /* enscribe a rectangle */
- for(i=walk->ax;izx;i++)
- for(j=walk->ay;jzy;j++) {
- if(!making_circle || ((int)(0.5+hypot(walk->x-i,walk->y-j))) <=R)
- maze[i][j]='.';
- }
- }
+ if (walk->sx < walk->sy)
+ R = walk->sx / 2;
+ else
+ 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] = '.';
+ }
}
-
-
-static void roguelike_link_rooms(Room *Rooms,char **maze,int xsize,int ysize){
+static void
+roguelike_link_rooms (Room *rooms, char **maze, int xsize, int ysize)
+{
Room *walk;
- int i,j;
+ int i, j;
+
/* link each room to the previous room */
- if(Rooms[1].x==0) return; /* only 1 room */
-
- for(walk = Rooms +1; walk->x !=0; walk++) {
- int x1=walk->x;
- int y1=walk->y;
- int x2=(walk-1)->x;
- int y2=(walk-1)->y;
- int in_wall=0;
- if(RANDOM()%2) { /* connect in x direction first */
- /* horizontal connect */
- /* swap (x1,y1) (x2,y2) if necessary */
-
- if(x2 < x1) {
- int tx=x2,ty=y2;
- x2 = x1; y2 = y1;
- x1 = tx; y1 = ty;
- }
+ if (rooms[1].x == 0)
+ return; /* only 1 room */
+ for (walk = rooms + 1; walk->x != 0; walk++)
+ {
+ int x1 = walk->x;
+ int y1 = walk->y;
+ int x2 = (walk - 1)->x;
+ int y2 = (walk - 1)->y;
+ int in_wall = 0;
+
+ if (rmg_rndm (2))
+ { /* connect in x direction first */
+ /* horizontal connect */
+ /* swap (x1,y1) (x2,y2) if necessary */
+
+ if (x2 < x1)
+ {
+ int tx = x2, ty = y2;
+
+ x2 = x1;
+ y2 = y1;
+ x1 = tx;
+ y1 = ty;
+ }
+
+
+ j = y1;
+ for (i = x1; i < x2; i++)
+ {
+ if (in_wall == 0 && maze[i][j] == '#')
+ {
+ in_wall = 1;
+ maze[i][j] = 'D';
+ }
+ else if (in_wall && maze[i][j] == '.')
+ {
+ in_wall = 0;
+ maze[i - 1][j] = 'D';
+ }
+ else if (maze[i][j] != 'D' && maze[i][j] != '.')
+ maze[i][j] = 0;
+ }
+
+ 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++)
+ {
+ if (in_wall == 0 && maze[i][j] == '#')
+ {
+ in_wall = 1;
+ maze[i][j] = 'D';
+ }
+ else if (in_wall && maze[i][j] == '.')
+ {
+ in_wall = 0;
+ maze[i][j - 1] = 'D';
+ }
+ else if (maze[i][j] != 'D' && maze[i][j] != '.')
+ maze[i][j] = 0;
+ }
- j = y1;
- for(i=x1;i