--- deliantra/server/random_maps/random_map.C 2006/09/10 16:06:37 1.3
+++ deliantra/server/random_maps/random_map.C 2010/03/26 00:59:21 1.46
@@ -1,484 +1,156 @@
-
/*
- * static char *rcsid_random_map_c =
- * "$Id: random_map.C,v 1.3 2006/09/10 16:06:37 root Exp $";
+ * This file is part of Deliantra, the Roguelike Realtime MMORPG.
+ *
+ * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ * Copyright (©) 2001 Mark Wedel & Crossfire Development Team
+ * Copyright (©) 1992 Frank Tore Johansen
+ *
+ * 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
*/
-/*
- CrossFire, A Multiplayer game for X-windows
-
- Copyright (C) 2001 Mark Wedel & Crossfire Development Team
- Copyright (C) 1992 Frank Tore Johansen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 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 GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- The authors can be reached via e-mail at crossfire-devel@real-time.com
-*/
-
#include
#include
#include
-#include
-#include
#include
#include
#include
-void
-dump_layout (char **layout, RMParms * RP)
-{
- {
- int i, j;
-
- for (i = 0; i < RP->Xsize; i++)
- {
- for (j = 0; j < RP->Ysize; j++)
- {
- if (layout[i][j] == 0)
- layout[i][j] = ' ';
- printf ("%c", layout[i][j]);
- if (layout[i][j] == ' ')
- layout[i][j] = 0;
- }
- printf ("\n");
- }
- }
- printf ("\n");
-}
-EXTERN FILE *logfile;
-mapstruct *
-generate_random_map (const char *OutFileName, RMParms * RP)
-{
- char **layout, buf[HUGE_BUF];
- mapstruct *theMap;
- int i;
-
- /* pick a random seed, or use the one from the input file */
- if (RP->random_seed == 0)
- RP->random_seed = time (0);
-
- SRANDOM (RP->random_seed);
-
- write_map_parameters_to_string (buf, RP);
-
- if (RP->difficulty == 0)
- {
- RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
- if (RP->difficulty_increase > 0.001)
- {
- RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
- if (RP->difficulty < 1)
- RP->difficulty = 1;
- }
- }
- else
- RP->difficulty_given = 1;
-
- if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
- RP->Xsize = MIN_RANDOM_MAP_SIZE + RANDOM () % 25 + 5;
- if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
- RP->Ysize = MIN_RANDOM_MAP_SIZE + RANDOM () % 25 + 5;
-
- if (RP->expand2x > 0)
- {
- RP->Xsize /= 2;
- RP->Ysize /= 2;
- }
-
- layout = layoutgen (RP);
+#define CEDE coroapi::cede_to_tick ()
-#ifdef RMAP_DEBUG
- dump_layout (layout, RP);
-#endif
-
- /* increment these for the current map */
- RP->dungeon_level += 1;
- /* allow constant-difficulty maps. */
- /* difficulty+=1; */
-
- /* rotate the layout randomly */
- layout = rotate_layout (layout, RANDOM () % 4, RP);
-#ifdef RMAP_DEBUG
- dump_layout (layout, RP);
-#endif
-
- /* allocate the map and set the floor */
- theMap = make_map_floor (layout, RP->floorstyle, RP);
+static void symmetrize_layout (Layout maze, random_map_params *RP);
+static void rotate_layout (Layout maze, int rotation);
- /* set the name of the map. */
- strcpy (theMap->path, OutFileName);
-
- /* set region */
- theMap->region = RP->region;
-
- /* create walls unless the wallstyle is "none" */
- if (strcmp (RP->wallstyle, "none"))
- {
- make_map_walls (theMap, layout, RP->wallstyle, RP);
-
- /* place doors unless doorstyle or wallstyle is "none" */
- if (strcmp (RP->doorstyle, "none"))
- put_doors (theMap, layout, RP->doorstyle, RP);
-
- }
-
- /* create exits unless the exitstyle is "none" */
- if (strcmp (RP->exitstyle, "none"))
- place_exits (theMap, layout, RP->exitstyle, RP->orientation, RP);
-
- place_specials_in_map (theMap, layout, RP);
-
- /* create monsters unless the monsterstyle is "none" */
- if (strcmp (RP->monsterstyle, "none"))
- place_monsters (theMap, RP->monsterstyle, RP->difficulty, RP);
-
- /* treasures needs to have a proper difficulty set for the map. */
- theMap->difficulty = calculate_difficulty (theMap);
-
- /* create treasure unless the treasurestyle is "none" */
- if (strcmp (RP->treasurestyle, "none"))
- place_treasure (theMap, layout, RP->treasurestyle, RP->treasureoptions, RP);
-
- /* create decor unless the decorstyle is "none" */
- if (strcmp (RP->decorstyle, "none"))
- put_decor (theMap, layout, RP->decorstyle, RP->decoroptions, RP);
-
- /* generate treasures, etc. */
- fix_auto_apply (theMap);
-
- unblock_exits (theMap, layout, RP);
-
- /* free the layout */
- for (i = 0; i < RP->Xsize; i++)
- free (layout[i]);
- free (layout);
-
- theMap->msg = strdup_local (buf);
-
- return theMap;
-}
-
-
-/* function selects the layout function and gives it whatever
- arguments it needs. */
-char **
-layoutgen (RMParms * RP)
+void
+dump_layout (Layout layout)
{
- char **maze = 0;
- int oxsize = RP->Xsize, oysize = RP->Ysize;
-
- if (RP->symmetry == RANDOM_SYM)
- RP->symmetry_used = (RANDOM () % (XY_SYM)) + 1;
- else
- RP->symmetry_used = RP->symmetry;
-
- if (RP->symmetry_used == Y_SYM || RP->symmetry_used == XY_SYM)
- RP->Ysize = RP->Ysize / 2 + 1;
- if (RP->symmetry_used == X_SYM || RP->symmetry_used == XY_SYM)
- RP->Xsize = RP->Xsize / 2 + 1;
-
- if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
- RP->Xsize = MIN_RANDOM_MAP_SIZE + RANDOM () % 5;
- if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
- RP->Ysize = MIN_RANDOM_MAP_SIZE + RANDOM () % 5;
- RP->map_layout_style = 0;
-
- /* Redo this - there was a lot of redundant code of checking for preset
- * layout style and then random layout style. Instead, figure out
- * the numeric layoutstyle, so there is only one area that actually
- * calls the code to make the maps.
- */
- if (strstr (RP->layoutstyle, "onion"))
- {
- RP->map_layout_style = ONION_LAYOUT;
- }
-
- if (strstr (RP->layoutstyle, "maze"))
- {
- RP->map_layout_style = MAZE_LAYOUT;
- }
-
- if (strstr (RP->layoutstyle, "spiral"))
- {
- RP->map_layout_style = SPIRAL_LAYOUT;
- }
-
- if (strstr (RP->layoutstyle, "rogue"))
- {
- RP->map_layout_style = ROGUELIKE_LAYOUT;
- }
-
- if (strstr (RP->layoutstyle, "snake"))
- {
- RP->map_layout_style = SNAKE_LAYOUT;
- }
-
- if (strstr (RP->layoutstyle, "squarespiral"))
+ for (int j = 0; j < layout->h; j++)
{
- RP->map_layout_style = SQUARE_SPIRAL_LAYOUT;
- }
- /* No style found - choose one ranomdly */
- if (RP->map_layout_style == 0)
- {
- RP->map_layout_style = (RANDOM () % NROFLAYOUTS) + 1;
- }
-
- switch (RP->map_layout_style)
- {
-
- case ONION_LAYOUT:
- maze = map_gen_onion (RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
- if (!(RANDOM () % 3) && !(RP->layoutoptions1 & OPT_WALLS_ONLY))
- roomify_layout (maze, RP);
- break;
-
- case MAZE_LAYOUT:
- maze = maze_gen (RP->Xsize, RP->Ysize, RANDOM () % 2);
- if (!(RANDOM () % 2))
- doorify_layout (maze, RP);
- break;
-
- case SPIRAL_LAYOUT:
- maze = map_gen_spiral (RP->Xsize, RP->Ysize, RP->layoutoptions1);
- if (!(RANDOM () % 2))
- doorify_layout (maze, RP);
- break;
-
- case ROGUELIKE_LAYOUT:
- /* Don't put symmetry in rogue maps. There isn't much reason to
- * do so in the first place (doesn't make it any more interesting),
- * but more importantly, the symmetry code presumes we are symmetrizing
- * spirals, or maps with lots of passages - making a symmetric rogue
- * map fails because its likely that the passages the symmetry process
- * creates may not connect the rooms.
- */
- RP->symmetry_used = NO_SYM;
- RP->Ysize = oysize;
- RP->Xsize = oxsize;
- maze = roguelike_layout_gen (RP->Xsize, RP->Ysize, RP->layoutoptions1);
- /* no doorifying... done already */
- break;
-
- case SNAKE_LAYOUT:
- maze = make_snake_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
- if (RANDOM () % 2)
- roomify_layout (maze, RP);
- break;
+ for (int i = 0; i < layout->w; i++)
+ putc (layout[i][j] ? layout[i][j] : ' ', stdout);
- case SQUARE_SPIRAL_LAYOUT:
- maze = make_square_spiral_layout (RP->Xsize, RP->Ysize, RP->layoutoptions1);
- if (RANDOM () % 2)
- roomify_layout (maze, RP);
- break;
+ putc ('\n', stdout);
}
- maze = symmetrize_layout (maze, RP->symmetry_used, RP);
-#ifdef RMAP_DEBUG
- dump_layout (maze, RP);
-#endif
- if (RP->expand2x)
- {
- maze = expand2x (maze, RP->Xsize, RP->Ysize);
- RP->Xsize = RP->Xsize * 2 - 1;
- RP->Ysize = RP->Ysize * 2 - 1;
- }
- return maze;
+ putc ('\n', stdout);
}
-
-/* takes a map and makes it symmetric: adjusts Xsize and
-Ysize to produce a symmetric map. */
-
-char **
-symmetrize_layout (char **maze, int sym, RMParms * RP)
+/* takes a map and makes it symmetric: adjusts Xsize and
+ * Ysize to produce a symmetric map.
+ */
+static void
+symmetrize_layout (Layout layout, random_map_params *RP)
{
- int i, j;
- char **sym_maze;
- int Xsize_orig, Ysize_orig;
-
- Xsize_orig = RP->Xsize;
- Ysize_orig = RP->Ysize;
- RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used. */
- if (sym == NO_SYM)
- {
- RP->Xsize = Xsize_orig;
- RP->Ysize = Ysize_orig;
- return maze;
- }
- /* pick new sizes */
- RP->Xsize = ((sym == X_SYM || sym == XY_SYM) ? RP->Xsize * 2 - 3 : RP->Xsize);
- RP->Ysize = ((sym == Y_SYM || sym == XY_SYM) ? RP->Ysize * 2 - 3 : RP->Ysize);
-
- sym_maze = (char **) calloc (sizeof (char *), RP->Xsize);
- for (i = 0; i < RP->Xsize; i++)
- sym_maze[i] = (char *) calloc (sizeof (char), RP->Ysize);
+ if (RP->symmetry_used == SYMMETRY_NONE)
+ return;
- if (sym == X_SYM)
- for (i = 0; i < RP->Xsize / 2 + 1; i++)
- for (j = 0; j < RP->Ysize; j++)
+ Layout sym_layout (
+ RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY ? layout->w * 2 - 3 : layout->w,
+ RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY ? layout->h * 2 - 3 : layout->h
+ );
+
+ if (RP->symmetry_used == SYMMETRY_X)
+ for (int i = 0; i < sym_layout->w / 2 + 1; i++)
+ for (int j = 0; j < sym_layout->h; j++)
{
- sym_maze[i][j] = maze[i][j];
- sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
- };
- if (sym == Y_SYM)
- for (i = 0; i < RP->Xsize; i++)
- for (j = 0; j < RP->Ysize / 2 + 1; j++)
- {
- sym_maze[i][j] = maze[i][j];
- sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
+ sym_layout[i ][j] =
+ sym_layout[sym_layout->w - i - 1][j] = layout[i][j];
}
- if (sym == XY_SYM)
- for (i = 0; i < RP->Xsize / 2 + 1; i++)
- for (j = 0; j < RP->Ysize / 2 + 1; j++)
+
+ if (RP->symmetry_used == SYMMETRY_Y)
+ for (int i = 0; i < sym_layout->w; i++)
+ for (int j = 0; j < sym_layout->h / 2 + 1; j++)
{
- sym_maze[i][j] = maze[i][j];
- sym_maze[i][RP->Ysize - j - 1] = maze[i][j];
- sym_maze[RP->Xsize - i - 1][j] = maze[i][j];
- sym_maze[RP->Xsize - i - 1][RP->Ysize - j - 1] = maze[i][j];
+ sym_layout[i][j ] =
+ sym_layout[i][sym_layout->h - j - 1] = layout[i][j];
+ }
+
+ if (RP->symmetry_used == SYMMETRY_XY)
+ for (int i = 0; i < sym_layout->w / 2 + 1; i++)
+ for (int j = 0; j < sym_layout->h / 2 + 1; j++)
+ {
+ sym_layout[i ][j ] =
+ sym_layout[i ][sym_layout->h - j - 1] =
+ sym_layout[sym_layout->w - i - 1][j ] =
+ sym_layout[sym_layout->w - i - 1][sym_layout->h - j - 1] = layout[i][j];
}
- /* delete the old maze */
- for (i = 0; i < Xsize_orig; i++)
- free (maze[i]);
- free (maze);
+
+ layout.swap (sym_layout);
+ sym_layout.free ();
+
/* reconnect disjointed spirals */
- if (RP->map_layout_style == SPIRAL_LAYOUT)
- connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
- /* reconnect disjointed nethackmazes: the routine for
+ /* reconnect disjointed nethacklayouts: the routine for
spirals will do the trick? */
- if (RP->map_layout_style == ROGUELIKE_LAYOUT)
- connect_spirals (RP->Xsize, RP->Ysize, sym, sym_maze);
-
- return sym_maze;
+ if (RP->map_layout_style == LAYOUT_SPIRAL
+ || RP->map_layout_style == LAYOUT_ROGUELIKE)
+ connect_spirals (layout->w, layout->h, RP->symmetry_used, layout);
}
-
/* takes a map and rotates it. This completes the
onion layouts, making them possibly centered on any wall.
It'll modify Xsize and Ysize if they're swapped.
*/
-
-char **
-rotate_layout (char **maze, int rotation, RMParms * RP)
+static void
+rotate_layout (Layout layout, int rotation)
{
- char **new_maze;
- int i, j;
+ int w = layout->w;
+ int h = layout->h;
switch (rotation)
{
- case 0:
- return maze;
- break;
- case 2: /* a reflection */
- {
- char *newmaze = (char *) malloc (sizeof (char) * RP->Xsize * RP->Ysize);
-
- for (i = 0; i < RP->Xsize; i++)
- { /* make a copy */
- for (j = 0; j < RP->Ysize; j++)
- {
- newmaze[i * RP->Ysize + j] = maze[i][j];
- }
- }
- for (i = 0; i < RP->Xsize; i++)
- { /* copy a reflection back */
- for (j = 0; j < RP->Ysize; j++)
- {
- maze[i][j] = newmaze[(RP->Xsize - i - 1) * RP->Ysize + RP->Ysize - j - 1];
- }
- }
- free (newmaze);
- return maze;
- break;
- }
- case 1:
- case 3:
- {
- int swap;
- new_maze = (char **) calloc (sizeof (char *), RP->Ysize);
- for (i = 0; i < RP->Ysize; i++)
- {
- new_maze[i] = (char *) calloc (sizeof (char), RP->Xsize);
- }
- if (rotation == 1) /* swap x and y */
- for (i = 0; i < RP->Xsize; i++)
- for (j = 0; j < RP->Ysize; j++)
- new_maze[j][i] = maze[i][j];
-
- if (rotation == 3)
- { /* swap x and y */
- for (i = 0; i < RP->Xsize; i++)
- for (j = 0; j < RP->Ysize; j++)
- new_maze[j][i] = maze[RP->Xsize - i - 1][RP->Ysize - j - 1];
- }
-
- /* delete the old layout */
- for (i = 0; i < RP->Xsize; i++)
- free (maze[i]);
- free (maze);
-
- swap = RP->Ysize;
- RP->Ysize = RP->Xsize;
- RP->Xsize = swap;
- return new_maze;
- break;
- }
- }
- return NULL;
-}
-
-/* take a layout and make some rooms in it.
- --works best on onions.*/
-void
-roomify_layout (char **maze, RMParms * RP)
-{
- int tries = RP->Xsize * RP->Ysize / 30;
- int ti;
+ case 2: /* a reflection */
+ {
+ Layout new_layout (w, h);
- for (ti = 0; ti < tries; ti++)
- {
- int dx, dy; /* starting location for looking at creating a door */
- int cx, cy; /* results of checking on creating walls. */
+ for (int i = 0; i < w; i++) /* copy a reflection back */
+ for (int j = 0; j < h; j++)
+ new_layout[i][j] = layout[w - i - 1][h - j - 1];
- dx = RANDOM () % RP->Xsize;
- dy = RANDOM () % RP->Ysize;
- cx = can_make_wall (maze, dx, dy, 0, RP); /* horizontal */
- cy = can_make_wall (maze, dx, dy, 1, RP); /* vertical */
- if (cx == -1)
- {
- if (cy != -1)
- make_wall (maze, dx, dy, 1);
- continue;
+ layout.swap (new_layout);
+ new_layout.free ();
}
- if (cy == -1)
+ break;
+
+ case 1:
+ case 3:
{
- make_wall (maze, dx, dy, 0);
- continue;
+ Layout new_layout (h, w);
+
+ if (rotation == 1) /* swap x and y */
+ for (int i = 0; i < w; i++)
+ for (int j = 0; j < h; j++)
+ new_layout[j][i] = layout[i][j];
+
+ if (rotation == 3) /* swap x and y */
+ for (int i = 0; i < w; i++)
+ for (int j = 0; j < h; j++)
+ new_layout[j][i] = layout[w - i - 1][h - j - 1];
+
+ layout.swap (new_layout);
+ new_layout.free ();
}
- if (cx < cy)
- make_wall (maze, dx, dy, 0);
- else
- make_wall (maze, dx, dy, 1);
+ break;
}
}
/* checks the layout to see if I can stick a horizontal(dir = 0) wall
(or vertical, dir == 1)
here which ends up on other walls sensibly. */
-
-int
-can_make_wall (char **maze, int dx, int dy, int dir, RMParms * RP)
+static int
+can_make_wall (char **maze, int dx, int dy, int dir, random_map_params *RP)
{
int i1;
int length = 0;
@@ -551,11 +223,51 @@
return -1; /* can't make horiz. wall here */
length++;
}
+
return length;
}
+
return -1;
}
+/* take a layout and make some rooms in it.
+ --works best on onions.*/
+static void
+roomify_layout (char **maze, random_map_params *RP)
+{
+ int tries = RP->Xsize * RP->Ysize / 30;
+ int ti;
+
+ for (ti = 0; ti < tries; ti++)
+ {
+ int dx, dy; /* starting location for looking at creating a door */
+ int cx, cy; /* results of checking on creating walls. */
+
+ dx = rmg_rndm (RP->Xsize);
+ dy = rmg_rndm (RP->Ysize);
+
+ cx = can_make_wall (maze, dx, dy, 0, RP); /* horizontal */
+ cy = can_make_wall (maze, dx, dy, 1, RP); /* vertical */
+ if (cx == -1)
+ {
+ if (cy != -1)
+ make_wall (maze, dx, dy, 1);
+
+ continue;
+ }
+
+ if (cy == -1)
+ {
+ make_wall (maze, dx, dy, 0);
+ continue;
+ }
+
+ if (cx < cy)
+ make_wall (maze, dx, dy, 0);
+ else
+ make_wall (maze, dx, dy, 1);
+ }
+}
int
make_wall (char **maze, int x, int y, int dir)
@@ -563,49 +275,44 @@
maze[x][y] = 'D'; /* mark a door */
switch (dir)
{
- case 0: /* horizontal */
- {
- int i1;
+ case 0: /* horizontal */
+ {
+ int i1;
- for (i1 = x - 1; maze[i1][y] == 0; i1--)
- maze[i1][y] = '#';
- for (i1 = x + 1; maze[i1][y] == 0; i1++)
- maze[i1][y] = '#';
- break;
- }
- case 1: /* vertical */
- {
- int i1;
+ for (i1 = x - 1; maze[i1][y] == 0; i1--)
+ maze[i1][y] = '#';
+ for (i1 = x + 1; maze[i1][y] == 0; i1++)
+ maze[i1][y] = '#';
+ break;
+ }
+ case 1: /* vertical */
+ {
+ int i1;
- for (i1 = y - 1; maze[x][i1] == 0; i1--)
- maze[x][i1] = '#';
- for (i1 = y + 1; maze[x][i1] == 0; i1++)
- maze[x][i1] = '#';
- break;
- }
+ for (i1 = y - 1; maze[x][i1] == 0; i1--)
+ maze[x][i1] = '#';
+ for (i1 = y + 1; maze[x][i1] == 0; i1++)
+ maze[x][i1] = '#';
+ break;
+ }
}
return 0;
}
/* puts doors at appropriate locations in a layout. */
-
-void
-doorify_layout (char **maze, RMParms * RP)
+static void
+doorify_layout (char **maze, random_map_params *RP)
{
int ndoors = RP->Xsize * RP->Ysize / 60; /* reasonable number of doors. */
- char *doorlist_x;
- char *doorlist_y;
int doorlocs = 0; /* # of available doorlocations */
- int i, j;
-
- doorlist_x = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize);
- doorlist_y = (char *) malloc (sizeof (int) * RP->Xsize * RP->Ysize);
+ uint16 *doorlist_x = salloc (RP->Xsize * RP->Ysize);
+ uint16 *doorlist_y = salloc (RP->Xsize * RP->Ysize);
/* make a list of possible door locations */
- for (i = 1; i < RP->Xsize - 1; i++)
- for (j = 1; j < RP->Ysize - 1; j++)
+ for (int i = 1; i < RP->Xsize - 1; i++)
+ for (int j = 1; j < RP->Ysize - 1; j++)
{
int sindex = surround_flag (maze, i, j, RP);
@@ -616,37 +323,36 @@
doorlocs++;
}
}
+
while (ndoors > 0 && doorlocs > 0)
{
- int di;
- int sindex;
+ int di = rmg_rndm (doorlocs);
+ int i = doorlist_x[di];
+ int j = doorlist_y[di];
+ int sindex = surround_flag (maze, i, j, RP);
- di = RANDOM () % doorlocs;
- i = doorlist_x[di];
- j = doorlist_y[di];
- sindex = surround_flag (maze, i, j, RP);
if (sindex == 3 || sindex == 12) /* these are possible door sindex */
{
maze[i][j] = 'D';
ndoors--;
}
+
/* reduce the size of the list */
doorlocs--;
doorlist_x[di] = doorlist_x[doorlocs];
doorlist_y[di] = doorlist_y[doorlocs];
}
- free (doorlist_x);
- free (doorlist_y);
-}
+ sfree (doorlist_x, RP->Xsize * RP->Ysize);
+ sfree (doorlist_y, RP->Xsize * RP->Ysize);
+}
void
-write_map_parameters_to_string (char *buf, RMParms * RP)
+write_map_parameters_to_string (char *buf, random_map_params *RP)
{
+ char small_buf[16384];
- char small_buf[256];
-
- sprintf (buf, "xsize %d\nysize %d\n", RP->Xsize, RP->Ysize);
+ sprintf (buf, "xsize %d\nysize %d\n", RP->xsize, RP->ysize);
if (RP->wallstyle[0])
{
@@ -696,9 +402,9 @@
strcat (buf, small_buf);
}
- if (RP->final_map[0])
+ if (RP->final_map.length ())
{
- sprintf (small_buf, "final_map %s\n", RP->final_map);
+ sprintf (small_buf, "final_map %s\n", &RP->final_map);
strcat (buf, small_buf);
}
@@ -708,9 +414,9 @@
strcat (buf, small_buf);
}
- if (RP->this_map[0])
+ if (RP->this_map.length ())
{
- sprintf (small_buf, "origin_map %s\n", RP->this_map);
+ sprintf (small_buf, "origin_map %s\n", &RP->this_map);
strcat (buf, small_buf);
}
@@ -726,14 +432,12 @@
strcat (buf, small_buf);
}
-
if (RP->layoutoptions2)
{
sprintf (small_buf, "layoutoptions2 %d\n", RP->layoutoptions2);
strcat (buf, small_buf);
}
-
if (RP->layoutoptions3)
{
sprintf (small_buf, "layoutoptions3 %d\n", RP->layoutoptions3);
@@ -746,14 +450,13 @@
strcat (buf, small_buf);
}
-
if (RP->difficulty && RP->difficulty_given)
{
sprintf (small_buf, "difficulty %d\n", RP->difficulty);
strcat (buf, small_buf);
}
- if (RP->difficulty_increase != 1.0)
+ if (fabs (RP->difficulty_increase - 1.f) >= (1.f / 1024.f))
{
sprintf (small_buf, "difficulty_increase %f\n", RP->difficulty_increase);
strcat (buf, small_buf);
@@ -791,12 +494,6 @@
sprintf (small_buf, "origin_y %d\n", RP->origin_y);
strcat (buf, small_buf);
}
- if (RP->random_seed)
- {
- /* Add one so that the next map is a bit different */
- sprintf (small_buf, "random_seed %d\n", RP->random_seed + 1);
- strcat (buf, small_buf);
- }
if (RP->treasureoptions)
{
@@ -804,24 +501,34 @@
strcat (buf, small_buf);
}
+ if (RP->random_seed)
+ {
+ sprintf (small_buf, "random_seed %u\n", RP->random_seed);
+ strcat (buf, small_buf);
+ }
+ if (RP->custom)
+ {
+ sprintf (small_buf, "custom %s\n", RP->custom);
+ strcat (buf, small_buf);
+ }
}
void
write_parameters_to_string (char *buf,
int xsize_n,
int ysize_n,
- char *wallstyle_n,
- char *floorstyle_n,
- char *monsterstyle_n,
- char *treasurestyle_n,
- char *layoutstyle_n,
- char *decorstyle_n,
- char *doorstyle_n,
- char *exitstyle_n,
- char *final_map_n,
- char *exit_on_final_map_n,
- char *this_map_n,
+ const char *wallstyle_n,
+ const char *floorstyle_n,
+ const char *monsterstyle_n,
+ const char *treasurestyle_n,
+ const char *layoutstyle_n,
+ const char *decorstyle_n,
+ const char *doorstyle_n,
+ const char *exitstyle_n,
+ const char *final_map_n,
+ const char *exit_on_final_map_n,
+ const char *this_map_n,
int layoutoptions1_n,
int layoutoptions2_n,
int layoutoptions3_n,
@@ -832,10 +539,13 @@
int difficulty_given_n,
int decoroptions_n,
int orientation_n,
- int origin_x_n, int origin_y_n, int random_seed_n, int treasureoptions_n, float difficulty_increase)
+ int origin_x_n,
+ int origin_y_n,
+ uint32_t random_seed_n,
+ int treasureoptions_n,
+ float difficulty_increase)
{
-
- char small_buf[256];
+ char small_buf[16384];
sprintf (buf, "xsize %d\nysize %d\n", xsize_n, ysize_n);
@@ -911,7 +621,6 @@
strcat (buf, small_buf);
}
-
if (layoutoptions2_n)
{
sprintf (small_buf, "layoutoptions2 %d\n", layoutoptions2_n);
@@ -976,10 +685,11 @@
sprintf (small_buf, "origin_y %d\n", origin_y_n);
strcat (buf, small_buf);
}
+
if (random_seed_n)
{
/* Add one so that the next map is a bit different */
- sprintf (small_buf, "random_seed %d\n", random_seed_n + 1);
+ sprintf (small_buf, "random_seed %u\n", random_seed_n + 1);
strcat (buf, small_buf);
}
@@ -988,22 +698,278 @@
sprintf (small_buf, "treasureoptions %d\n", treasureoptions_n);
strcat (buf, small_buf);
}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+LayoutData::LayoutData (int w, int h)
+: w(w), h(h)
+{
+ int size = (sizeof (char *) + sizeof (char) * h) * w;
+ col = (char **)salloc (size);
+ char *data = (char *)(col + w);
+
+ for (int x = w; x--; )
+ col [x] = data + x * h;
}
-/* copy an object with an inventory... i.e., duplicate the inv too. */
-void
-copy_object_with_inv (object *src_ob, object *dest_ob)
+LayoutData::~LayoutData ()
+{
+ int size = (sizeof (char *) + sizeof (char) * h) * w;
+
+ sfree ((char *)col, size);
+}
+
+void LayoutData::clear (char fill)
+{
+ memset (col [0], fill, w * h);
+}
+
+void LayoutData::border (char fill)
+{
+ for (int i = 0; i < w; i++) col [i][0] = col [i][h - 1] = fill;
+ for (int j = 0; j < h; j++) col [0][j] = col [w - 1][j] = fill;
+}
+
+/* function selects the layout function and gives it whatever
+ arguments it needs. */
+static Layout
+layoutgen (random_map_params *RP)
+{
+ Layout layout (RP);
+
+ switch (RP->map_layout_style)
+ {
+ case LAYOUT_ONION:
+ map_gen_onion (layout, RP->layoutoptions1, RP->layoutoptions2);
+
+ if (!(rmg_rndm (3)) && !(RP->layoutoptions1 & RMOPT_WALLS_ONLY))
+ roomify_layout (layout, RP);
+
+ break;
+
+ case LAYOUT_MAZE:
+ maze_gen (layout, rmg_rndm (2));
+
+ if (!(rmg_rndm (2)))
+ doorify_layout (layout, RP);
+
+ break;
+
+ case LAYOUT_SPIRAL:
+ map_gen_spiral (layout, RP->layoutoptions1);
+
+ if (!(rmg_rndm (2)))
+ doorify_layout (layout, RP);
+
+ break;
+
+ case LAYOUT_ROGUELIKE:
+ /* Don't put symmetry in rogue maps. There isn't much reason to
+ * do so in the first place (doesn't make it any more interesting),
+ * but more importantly, the symmetry code presumes we are symmetrizing
+ * spirals, or maps with lots of passages - making a symmetric rogue
+ * map fails because its likely that the passages the symmetry process
+ * creates may not connect the rooms.
+ */
+ RP->symmetry_used = SYMMETRY_NONE;
+ roguelike_layout_gen (layout, RP->layoutoptions1);
+ /* no doorifying... done already */
+ break;
+
+ case LAYOUT_SNAKE:
+ make_snake_layout (layout, RP->layoutoptions1);
+
+ if (rmg_rndm (2))
+ roomify_layout (layout, RP);
+
+ break;
+
+ case LAYOUT_SQUARE_SPIRAL:
+ make_square_spiral_layout (layout, RP->layoutoptions1);
+
+ if (rmg_rndm (2))
+ roomify_layout (layout, RP);
+
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* rotate the layout randomly */
+ rotate_layout (layout, rmg_rndm (4));
+
+ symmetrize_layout (layout, RP);
+
+#ifdef RMAP_DEBUG
+ dump_layout (layout);
+#endif
+
+ if (RP->expand2x)
+ expand2x (layout);
+
+ return layout;
+}
+
+bool
+maptile::generate_random_map (random_map_params *RP)
{
- object *walk, *tmp;
+ char buf[16384];
+ int i;
+
+ RP->Xsize = RP->xsize;
+ RP->Ysize = RP->ysize;
+
+ /* pick a random seed, or use the one from the input file */
+ RP->random_seed = RP->random_seed
+ ? RP->random_seed + RP->dungeon_level
+ : time (0);
+
+ // we run "single-threaded"
+ rmg_rndm.seed (RP->random_seed);
+
+ write_map_parameters_to_string (buf, RP);
+
+ if (RP->difficulty == 0)
+ {
+ RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
- copy_object (src_ob, dest_ob);
+ if (RP->difficulty_increase > 0.001)
+ RP->difficulty = (int) ((float) RP->dungeon_level * RP->difficulty_increase);
+
+ if (RP->difficulty < 1)
+ RP->difficulty = 1;
+ }
+ else
+ RP->difficulty_given = 1;
+
+ if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
+ RP->Xsize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
+
+ if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
+ RP->Ysize = MIN_RANDOM_MAP_SIZE + rmg_rndm (25) + 5;
+
+ if (RP->symmetry == SYMMETRY_RANDOM)
+ RP->symmetry_used = rmg_rndm (SYMMETRY_XY) + 1;
+ else
+ RP->symmetry_used = RP->symmetry;
+
+ if (RP->symmetry_used == SYMMETRY_Y || RP->symmetry_used == SYMMETRY_XY)
+ RP->Ysize = RP->Ysize / 2 + 1;
+
+ if (RP->symmetry_used == SYMMETRY_X || RP->symmetry_used == SYMMETRY_XY)
+ RP->Xsize = RP->Xsize / 2 + 1;
- for (walk = src_ob->inv; walk != NULL; walk = walk->below)
+ if (RP->expand2x > 0)
{
- tmp = get_object ();
- copy_object (walk, tmp);
- insert_ob_in_ob (tmp, dest_ob);
+ RP->Xsize /= 2;
+ RP->Ysize /= 2;
}
+
+ RP->map_layout_style = LAYOUT_NONE;
+
+ /* Redo this - there was a lot of redundant code of checking for preset
+ * layout style and then random layout style. Instead, figure out
+ * the numeric layoutstyle, so there is only one area that actually
+ * calls the code to make the maps.
+ */
+ if (strstr (RP->layoutstyle, "onion"))
+ RP->map_layout_style = LAYOUT_ONION;
+ else if (strstr (RP->layoutstyle, "maze"))
+ RP->map_layout_style = LAYOUT_MAZE;
+ else if (strstr (RP->layoutstyle, "spiral"))
+ RP->map_layout_style = LAYOUT_SPIRAL;
+ else if (strstr (RP->layoutstyle, "rogue"))
+ RP->map_layout_style = LAYOUT_ROGUELIKE;
+ else if (strstr (RP->layoutstyle, "snake"))
+ RP->map_layout_style = LAYOUT_SNAKE;
+ else if (strstr (RP->layoutstyle, "squarespiral"))
+ RP->map_layout_style = LAYOUT_SQUARE_SPIRAL;
+ else if (RP->map_layout_style == LAYOUT_NONE)
+ RP->map_layout_style = rmg_rndm (NROFLAYOUTS - 1) + 1; /* No style found - choose one randomly */
+ else
+ abort ();
+
+ Layout layout = layoutgen (RP);
+
+#ifdef RMAP_DEBUG
+ dump_layout (layout);
+#endif
+
+ /* increment these for the current map */
+ ++RP->dungeon_level;
+
+ // need to patch RP becasue following code doesn't use the Layout object
+ RP->Xsize = layout->w;
+ RP->Ysize = layout->h;
+
+ /* allocate the map and set the floor */
+ make_map_floor (layout, RP->floorstyle, RP);
+
+ /* set region */
+ default_region = RP->region;
+
+ CEDE;
+
+ place_specials_in_map (this, layout, RP);
+
+ CEDE;
+
+ /* create walls unless the wallstyle is "none" */
+ if (strcmp (RP->wallstyle, "none"))
+ {
+ make_map_walls (this, layout, RP->wallstyle, RP);
+
+ /* place doors unless doorstyle or wallstyle is "none" */
+ if (strcmp (RP->doorstyle, "none"))
+ put_doors (this, layout, RP->doorstyle, RP);
+ }
+
+ CEDE;
+
+ /* create exits unless the exitstyle is "none" */
+ if (strcmp (RP->exitstyle, "none"))
+ place_exits (this, layout, RP->exitstyle, RP->orientation, RP);
+
+ CEDE;
+
+ /* create monsters unless the monsterstyle is "none" */
+ if (strcmp (RP->monsterstyle, "none"))
+ place_monsters (this, RP->monsterstyle, RP->difficulty, RP);
+
+ CEDE;
+
+ /* treasures needs to have a proper difficulty set for the map. */
+ difficulty = estimate_difficulty ();
+
+ CEDE;
+
+ /* create treasure unless the treasurestyle is "none" */
+ place_treasure (this, layout, RP->treasurestyle, RP->treasureoptions, RP);
+
+ CEDE;
+
+ /* create decor unless the decorstyle is "none" */
+ if (strcmp (RP->decorstyle, "none"))
+ put_decor (this, layout, RP->decorstyle, RP->decoroptions, RP);
+
+ CEDE;
+
+ /* generate treasures, etc. */
+ fix_auto_apply ();
+
+ CEDE;
+
+ unblock_exits (this, layout, RP);
+
+ msg = strdup (buf);
+ in_memory = MAP_ACTIVE;
+
+ CEDE;
+
+ return 1;
}
+