The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cave_map_generator.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Map-generator for caves.
18  */
19 
20 #include "global.hpp"
21 
22 #include "cave_map_generator.hpp"
23 #include "log.hpp"
24 #include "map/map.hpp"
25 #include "pathfind/pathfind.hpp"
27 #include "util.hpp"
28 #include "seed_rng.hpp"
29 
30 static lg::log_domain log_engine("engine");
31 #define LOG_NG LOG_STREAM(info, log_engine)
32 
34  wall_(t_translation::CAVE_WALL),
35  clear_(t_translation::CAVE),
37  castle_(t_translation::DWARVEN_CASTLE),
39  cfg_(cfg ? cfg : config()),
40  width_(50),
41  height_(50),
42  village_density_(0),
43  flipx_chance_(cfg_["flipx_chance"]),
44  flipy_chance_(cfg_["flipy_chance"])
45 {
46  width_ = cfg_["map_width"];
47  height_ = cfg_["map_height"];
48 
49  village_density_ = cfg_["village_density"];
50 }
51 
53 {
54  return "";
55 }
56 
58 {
59  if(flipx_) {
60  x = params.width_ - x - 1;
61  }
62 
63  return x;
64 }
65 
67 {
68  if(flipy_) {
69  y = params.height_ - y - 1;
70  }
71 
72  return y;
73 }
74 
75 std::string cave_map_generator::create_map(boost::optional<boost::uint32_t> randomseed)
76 {
77  const config res = create_scenario(randomseed);
78  return res["map_data"];
79 }
80 
81 config cave_map_generator::create_scenario(boost::optional<boost::uint32_t> randomseed)
82 {
83  cave_map_generator_job job(*this, randomseed);
84  return job.res_;
85 }
86 
87 cave_map_generator::cave_map_generator_job::cave_map_generator_job(const cave_map_generator& pparams, boost::optional<boost::uint32_t> randomseed)
88  : params(pparams)
89  , flipx_(false)
90  , flipy_(false)
91  , map_(t_translation::t_map(params.width_ + 2 * gamemap::default_border,
92  t_translation::t_list(params.height_ + 2 * gamemap::default_border, params.wall_)))
93  , starting_positions_()
94  , chamber_ids_()
95  , chambers_()
96  , passages_()
97  , res_(params.cfg_.child_or_empty("settings"))
98  , rng_() //initialises with rand()
99 {
100  uint32_t seed = randomseed.get_ptr() ? *randomseed.get_ptr() : seed_rng::next_seed();
101  rng_.seed(seed);
102  std::cerr << "creating random cave with seed:" << seed;
103  flipx_ = int(rng_() % 100) < params.flipx_chance_;
104  flipy_ = int(rng_() % 100) < params.flipy_chance_;
105 
106  LOG_NG << "creating scenario....\n";
108 
109  LOG_NG << "placing chambers...\n";
110  for(std::vector<chamber>::const_iterator c = chambers_.begin(); c != chambers_.end(); ++c) {
111  place_chamber(*c);
112  }
113 
114  LOG_NG << "placing passages...\n";
115 
116  for(std::vector<passage>::const_iterator p = passages_.begin(); p != passages_.end(); ++p) {
117  place_passage(*p);
118  }
119  LOG_NG << "outputting map....\n";
120 
122 }
123 
124 void cave_map_generator::cave_map_generator_job::build_chamber(map_location loc, std::set<map_location>& locs, size_t size, size_t jagged)
125 {
126  if(size == 0 || locs.count(loc) != 0 || !params.on_board(loc))
127  return;
128 
129  locs.insert(loc);
130 
131  map_location adj[6];
132  get_adjacent_tiles(loc,adj);
133  for(size_t n = 0; n != 6; ++n) {
134  if(int(rng_() % 100) < (100l - static_cast<long>(jagged))) {
135  build_chamber(adj[n],locs,size-1,jagged);
136  }
137  }
138 }
139 
141 {
142  for (const config &ch : params.cfg_.child_range("chamber"))
143  {
144  // If there is only a chance of the chamber appearing, deal with that here.
145  if (ch.has_attribute("chance") && int(rng_() % 100) < ch["chance"].to_int()) {
146  continue;
147  }
148 
149  const std::string &xpos = ch["x"];
150  const std::string &ypos = ch["y"];
151 
152  size_t min_xpos = 0, min_ypos = 0, max_xpos = params.width_, max_ypos = params.height_;
153 
154  if (!xpos.empty()) {
155  const std::vector<std::string>& items = utils::split(xpos, '-');
156  if(items.empty() == false) {
157  min_xpos = std::stoi(items.front()) - 1;
158  max_xpos = std::stoi(items.back());
159  }
160  }
161 
162  if (!ypos.empty()) {
163  const std::vector<std::string>& items = utils::split(ypos, '-');
164  if(items.empty() == false) {
165  min_ypos = std::stoi(items.front()) - 1;
166  max_ypos = std::stoi(items.back());
167  }
168  }
169  const size_t x = translate_x(min_xpos + (rng_()%(max_xpos-min_xpos)));
170  const size_t y = translate_y(min_ypos + (rng_()%(max_ypos-min_ypos)));
171 
172  int chamber_size = ch["size"].to_int(3);
173  int jagged_edges = ch["jagged"];
174 
175  chamber new_chamber;
176  new_chamber.center = map_location(x,y);
177  build_chamber(new_chamber.center,new_chamber.locs,chamber_size,jagged_edges);
178 
179  const config &items = ch.child("items");
180  new_chamber.items = items ? &items : nullptr;
181 
182  const std::string &id = ch["id"];
183  if (!id.empty()) {
184  chamber_ids_[id] = chambers_.size();
185  }
186 
187  chambers_.push_back(new_chamber);
188 
189  for(const config &p : ch.child_range("passage"))
190  {
191  const std::string &dst = p["destination"];
192 
193  // Find the destination of this passage
194  const std::map<std::string,size_t>::const_iterator itor = chamber_ids_.find(dst);
195  if(itor == chamber_ids_.end())
196  continue;
197 
198  assert(itor->second < chambers_.size());
199 
200  passages_.push_back(passage(new_chamber.center, chambers_[itor->second].center, p));
201  }
202  }
203 }
204 
206 {
207  for(std::set<map_location>::const_iterator i = c.locs.begin(); i != c.locs.end(); ++i) {
208  set_terrain(*i,params.clear_);
209  }
210 
211  if (c.items == nullptr || c.locs.empty()) return;
212 
213  size_t index = 0;
214  for (const config::any_child &it : c.items->all_children_range())
215  {
216  config cfg = it.cfg;
217  config &filter = cfg.child("filter");
218  config* object_filter = nullptr;
219  if (config &object = cfg.child("object")) {
220  if (config &of = object.child("filter"))
221  object_filter = &of;
222  }
223 
224  if (!it.cfg["same_location_as_previous"].to_bool()) {
225  index = rng_()%c.locs.size();
226  }
227  std::string loc_var = it.cfg["store_location_as"];
228 
229  std::set<map_location>::const_iterator loc = c.locs.begin();
230  std::advance(loc,index);
231 
232  cfg["x"] = loc->x + 1;
233  cfg["y"] = loc->y + 1;
234 
235  if (filter) {
236  filter["x"] = loc->x + 1;
237  filter["y"] = loc->y + 1;
238  }
239 
240  if (object_filter) {
241  (*object_filter)["x"] = loc->x + 1;
242  (*object_filter)["y"] = loc->y + 1;
243  }
244 
245  // If this is a side, place a castle for the side
246  if (it.key == "side" && !it.cfg["no_castle"].to_bool()) {
247  place_castle(it.cfg["side"].to_int(-1), *loc);
248  }
249 
250  res_.add_child(it.key, cfg);
251 
252  if(!loc_var.empty()) {
253  config &temp = res_.add_child("event");
254  temp["name"] = "prestart";
255  config &xcfg = temp.add_child("set_variable");
256  xcfg["name"] = loc_var + "_x";
257  xcfg["value"] = loc->x + 1;
258  config &ycfg = temp.add_child("set_variable");
259  ycfg["name"] = loc_var + "_y";
260  ycfg["value"] = loc->y + 1;
261  }
262  }
263 }
264 
266 {
268  const t_translation::t_terrain & wall,
269  double laziness, size_t windiness,
270  boost::random::mt19937& rng) :
271  map_(mapdata), wall_(wall), laziness_(laziness), windiness_(windiness), rng_(rng)
272  {}
273 
274  virtual double cost(const map_location& loc, const double so_far) const;
275 private:
278  double laziness_;
279  size_t windiness_;
280  boost::random::mt19937& rng_;
281 };
282 
283 double passage_path_calculator::cost(const map_location& loc, const double) const
284 {
285  double res = 1.0;
287  res = laziness_;
288  }
289 
290  if(windiness_ > 1) {
291  res *= double(rng_()%windiness_);
292  }
293 
294  return res;
295 }
296 
298 {
299  const std::string& chance = p.cfg["chance"];
300  if(chance != "" && int(rng_()%100) < std::stoi(chance)) {
301  return;
302  }
303 
304 
305  int windiness = p.cfg["windiness"];
306  double laziness = std::max<double>(1.0, p.cfg["laziness"].to_double());
307 
308  passage_path_calculator calc(map_, params.wall_, laziness, windiness, rng_);
309 
310  pathfind::plain_route rt = a_star_search(p.src, p.dst, 10000.0, &calc, params.width_, params.height_);
311 
312  int width = std::max<int>(1, p.cfg["width"].to_int());
313  int jagged = p.cfg["jagged"];
314 
315  for(std::vector<map_location>::const_iterator i = rt.steps.begin(); i != rt.steps.end(); ++i) {
316  std::set<map_location> locs;
317  build_chamber(*i,locs,width,jagged);
318  for(std::set<map_location>::const_iterator j = locs.begin(); j != locs.end(); ++j) {
319  set_terrain(*j, params.clear_);
320  }
321  }
322 }
323 
325 {
326  if (params.on_board(loc)) {
328 
329  if(c == params.clear_ || c == params.wall_ || c == params.village_) {
330  // Change this terrain.
331  if ( t == params.clear_ && int(rng_() % 1000) < params.village_density_ )
332  // Override with a village.
333  c = params.village_;
334  else
335  c = t;
336  }
337  }
338 }
339 
341 {
342  if (starting_position != -1) {
343  set_terrain(loc, params.keep_);
344 
347  , loc.y + gamemap::default_border);
348  starting_positions_.insert(t_translation::tstarting_positions::value_type(std::to_string(starting_position), coord));
349  }
350 
351  map_location adj[6];
352  get_adjacent_tiles(loc,adj);
353  for(size_t n = 0; n != 6; ++n) {
354  set_terrain(adj[n], params.castle_);
355  }
356 }
357 
child_itors child_range(const std::string &key)
Definition: config.cpp:613
Contains an x and y coordinate used for starting positions in maps.
Definition: translation.hpp:97
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator *calc, const size_t width, const size_t height, const teleport_map *teleports, bool border)
std::string create_map(boost::optional< boost::uint32_t > randomseed=boost::none)
Creates a new map and returns it.
t_translation::tstarting_positions starting_positions_
const t_terrain UNDERGROUND_VILLAGE
config create_scenario(boost::optional< boost::uint32_t > randomseed=boost::none)
std::string write_game_map(const t_map &map, const tstarting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const GLfloat * c
Definition: glew.h:12741
GLuint coord
Definition: glew.h:6175
variant map_
Definition: formula.cpp:306
std::string config_name() const
Return a friendly name for the generator used to differentiate between different configs of the same ...
boost::uint32_t uint32_t
Definition: xbrz.hpp:45
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:274
static const int default_border
The default border style for a map.
Definition: map.hpp:201
const GLfloat * params
Definition: glew.h:1499
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
const std::vector< std::string > items
GLdouble GLdouble t
Definition: glew.h:1366
cave_map_generator_job(const cave_map_generator &params, boost::optional< boost::uint32_t > randomseed=boost::none)
GLdouble l
Definition: glew.h:6966
boost::random::mt19937 & rng_
t_translation::t_terrain wall_
std::vector< std::vector< t_terrain > > t_map
Definition: translation.hpp:76
std::vector< map_location > steps
Definition: pathfind.hpp:135
GLuint id
Definition: glew.h:1647
Structure which holds a single route between one location and another.
Definition: pathfind.hpp:132
all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:1127
GLenum GLenum dst
Definition: glew.h:2392
Encapsulates the map of the game.
Definition: map.hpp:37
const t_terrain DWARVEN_CASTLE
config & add_child(const std::string &key)
Definition: config.cpp:743
virtual double cost(const map_location &loc, const double so_far) const
GLfloat GLfloat p
Definition: glew.h:12766
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
Templates and utility-routines for strings and numbers.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:47
void place_castle(int starting_position, const map_location &loc)
Encapsulates the map of the game.
Definition: location.hpp:38
GLuint res
Definition: glew.h:9258
void build_chamber(map_location loc, std::set< map_location > &locs, size_t size, size_t jagged)
const t_terrain CAVE
std::map< std::string, tfilter >::iterator itor
Definition: filter.cpp:199
static lg::log_domain log_engine("engine")
GLuint index
Definition: glew.h:1782
const t_terrain CAVE_WALL
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
const t_terrain DWARVEN_KEEP
GLsizeiptr size
Definition: glew.h:1649
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
passage_path_calculator(const t_translation::t_map &mapdata, const t_translation::t_terrain &wall, double laziness, size_t windiness, boost::random::mt19937 &rng)
uint32_t next_seed()
Definition: seed_rng.cpp:52
GLclampd n
Definition: glew.h:5903
t_translation::t_terrain wall_
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
void set_terrain(map_location loc, const t_translation::t_terrain &t)
Standard logging facilities (interface).
#define c
Definition: glew.h:12743
GLint GLint GLint GLint GLint GLint GLsizei width
Definition: glew.h:1220
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
#define LOG_NG
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
cave_map_generator(const config &game_config)
This module contains various pathfinding functions and utilities.
GLsizei const GLcharARB ** string
Definition: glew.h:4503
const t_translation::t_map & map_
std::vector< t_terrain > t_list
Definition: translation.hpp:75