/* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * * Copyright (©) 2005,2006,2007,2008,2009,2010 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 */ #ifndef RANDOM_MAP_H #define RANDOM_MAP_H #include "util.h" struct random_map_params : zero_initialised { char wall_name[512]; int xsize, ysize; int expand2x; int layoutoptions1; int layoutoptions2; int layoutoptions3; int symmetry; int difficulty; int difficulty_given; float difficulty_increase; int dungeon_level; int dungeon_depth; int orientation; uint32_t random_seed; uint64_t total_map_hp; int map_layout_style; int symmetry_used; HV *hv; shstr_tmp as_shstr () const; // fetch something from the options hash SV *get_sv (const char *option) const; const_utf8_string get_str (const char *option, const_utf8_string fallback = "") const; IV get_iv (const char *option, IV fallback = 0) const; UV get_uv (const char *option, UV fallback = 0) const; NV get_nv (const char *option, NV fallback = 0) const; void set (const char *option, SV *value) const; void set (const char *option, const_utf8_string value) const; void set (const char *option, IV value) const; void set (const char *option, UV value) const; void set (const char *option, NV value) const; void set (const char *option, int value) const { set (option, (IV)value); } // "private", adjusted sizes int Xsize; int Ysize; random_map_params (); random_map_params (random_map_params *RP); random_map_params (HV *hv); ~random_map_params (); }; enum { LAYOUT_NONE, LAYOUT_ONION, LAYOUT_MAZE, LAYOUT_SPIRAL, LAYOUT_ROGUELIKE, LAYOUT_SNAKE, LAYOUT_SQUARE_SPIRAL, LAYOUT_CAVE, LAYOUT_CASTLE, LAYOUT_MULTIPLE, NROFLAYOUTS, }; /* * Move these defines out of room_gen_onion.c to here, as * other files (like square_spiral) also uses them. options: 0 Pick random options below 1 "centered" 2 linear doors (default is nonlinear) 4 bottom "centered" 8 bottom-right centered 16 irregularly/randomly spaced layers (default: regular) 32 outer wall off: i.e., no outer wall. */ enum { RMOPT_RANDOM = 0, RMOPT_CENTERED = 1, RMOPT_LINEAR = 2, RMOPT_BOTTOM_C = 4, RMOPT_BOTTOM_R = 8, RMOPT_IRR_SPACE = 16, RMOPT_WALL_OFF = 32, RMOPT_WALLS_ONLY = 64, RMOPT_NO_DOORS = 256, /* Place walls insead of doors. Produces broken map. */ }; /* symmetry definitions--used in this file AND in treasure.c: the numerical values matter so don't change them. */ enum { SYMMETRY_RANDOM, SYMMETRY_NONE, SYMMETRY_X, SYMMETRY_Y, SYMMETRY_XY, }; // 12 has been experimentally :( determined ot be a lot more stable // than 11 or 10, leading to the assumption that something inherently // needs a minimum size of at least 12 #define MIN_RANDOM_MAP_SIZE 12 // we often use signed chars for coordinates (and U8 for distances) #define MAX_RANDOM_MAP_SIZE 120 // reference // // \0 floor only // # wall // D door // < up // > down // C "center" (of onion maze) // . ?? (rogue) // // use this in new code INTERFACE_CLASS(layout) struct layout { typedef char cell; cell **data; int w, h; layout (int w, int h); layout (layout ©); // reference rect in other layout - will not keep the data alive, // so never swap with it's orig, or free the orig when in use. layout (layout &orig, int x1, int y1, int x2, int y2); ~layout (); operator cell **() const { return data; } void swap (layout &maze) { ::swap (maze.data, data); ::swap (maze.w , w ); ::swap (maze.h , h ); ::swap (maze.size, size); } MTH void swap (layout *maze) { swap (*maze); } // for debugging, print maze to stdout MTH void print () const; // simple inpainting MTH void fill (char fill); MTH void clear () { fill (0); } MTH void border (char fill = '#'); MTH void rect (int x1, int y1, int x2, int y2, char fill); // x2, y2 exclusive MTH void fill_rect (int x1, int y1, int x2, int y2, char fill); // x2, y2 exclusive MTH void fill_rand (int perc); // makes sure all areas are connected // perturb = 0 - very horz/vert tunnels // perturb = 1 - straight but round // perturb = 2 - snaky tunnels MTH void isolation_remover (int perturb = 2); // generates a cave, subtype 0 is a rough cave, randomly open or closed MTH void gen_cave (int subtype); MTH void gen_castle (); // generates straightish structures // helper functions to modify the maze MTH void erode_1_2 (int c1, int c2 = -1, int repeat = 1); MTH void doorify (); MTH void roomify (); // make some rooms in it, works best on onions MTH void expand2x (); MTH void symmetrize (int symmetry); MTH void rotate (int rotation); // rotate by 1=90, 2=180, 3=270 degrees void generate (random_map_params *RP); private: int size; void alloc (int w, int h); }; // utility functions, to use rmg_rndm instead of rndm. static inline int rmg_find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop) { swap (rmg_rndm, rndm); int i = find_free_spot (ob, m, x, y, start, stop); swap (rmg_rndm, rndm); return i; } // a simple point helper struct struct point { short x; short y; point () { } point (int x, int y) : x(x), y(y) { } }; // something like a vector or stack, but without // out of bounds checking template struct fixed_stack { T *data; int size; int max; fixed_stack () : size (0), data (0) { } fixed_stack (int max) : size (0), max (max) { data = salloc (max); } void reset (int new_max) { sfree (data, max); size = 0; max = new_max; data = salloc (max); } void free () { sfree (data, max); data = 0; } ~fixed_stack () { sfree (data, max); } T &operator[](int idx) { return data [idx]; } void push (T v) { data [size++] = v; } T &pop () { return data [--size]; } T remove (int idx) { T v = data [idx]; data [idx] = data [--size]; return v; } }; #endif