29 #define LOG_NG LOG_STREAM(info, log_engine)
32 #define ERR_WML LOG_STREAM(err, log_wml)
41 width_(cfg_[
"map_width"].to_int(50)),
42 height_(cfg_[
"map_height"].to_int(50)),
43 village_density_(cfg_[
"village_density"].to_int(0)),
44 flipx_chance_(cfg_[
"flipx_chance"].to_int()),
45 flipy_chance_(cfg_[
"flipy_chance"].to_int())
66 y = params.height_ - y - 1;
75 return res[
"map_data"];
89 , starting_positions_()
93 , res_(params.
cfg_.child_or_empty(
"settings"))
98 "deprecated_message",
config {
99 "what",
"scenario_generation=cave",
101 "message",
"Use the Lua cave generator instead, with scenario_generation=lua and create_scenario= (see wiki for details).",
106 LOG_NG <<
"creating random cave with seed: " << seed;
110 LOG_NG <<
"creating scenario....";
113 LOG_NG <<
"placing chambers...";
118 LOG_NG <<
"placing passages...";
123 LOG_NG <<
"outputting map....";
130 if(
size == 0 || locs.count(loc) != 0 || !params.on_board(loc))
136 if(
static_cast<int>(rng_() % 100) < (100l -
static_cast<long>(jagged))) {
137 build_chamber(adj,locs,
size-1,jagged);
147 if (ch.has_attribute(
"chance") &&
static_cast<int>(rng_() % 100) < ch[
"chance"].to_int()) {
151 const std::string &xpos = ch[
"x"];
152 const std::string &ypos = ch[
"y"];
154 std::size_t min_xpos = 0, min_ypos = 0, max_xpos = params.width_, max_ypos = params.height_;
157 const std::vector<std::string>& items =
utils::split(xpos,
'-');
158 if(items.empty() ==
false) {
160 min_xpos = std::stoi(items.front()) - 1;
161 max_xpos = std::stoi(items.back());
162 }
catch(
const std::invalid_argument&) {
163 lg::log_to_chat() <<
"Invalid min/max coordinates in cave_map_generator: " << items.front() <<
", " << items.back() <<
"\n";
164 ERR_WML <<
"Invalid min/max coordinates in cave_map_generator: " << items.front() <<
", " << items.back();
171 const std::vector<std::string>& items =
utils::split(ypos,
'-');
172 if(items.empty() ==
false) {
174 min_ypos = std::stoi(items.front()) - 1;
175 max_ypos = std::stoi(items.back());
176 }
catch(
const std::invalid_argument&) {
177 lg::log_to_chat() <<
"Invalid min/max coordinates in cave_map_generator: " << items.front() <<
", " << items.back() <<
"\n";
178 ERR_WML <<
"Invalid min/max coordinates in cave_map_generator: " << items.front() <<
", " << items.back();
182 const std::size_t x = translate_x(min_xpos + (rng_()%(max_xpos-min_xpos)));
183 const std::size_t y = translate_y(min_ypos + (rng_()%(max_ypos-min_ypos)));
185 int chamber_size = ch[
"size"].to_int(3);
186 int jagged_edges = ch[
"jagged"].to_int();
190 build_chamber(new_chamber.
center,new_chamber.
locs,chamber_size,jagged_edges);
192 auto items = ch.optional_child(
"items");
193 new_chamber.
items = items ? &*items :
nullptr;
195 const std::string &
id = ch[
"id"];
197 chamber_ids_[
id] = chambers_.size();
200 chambers_.push_back(new_chamber);
202 for(
const config &
p : ch.child_range(
"passage"))
204 const std::string &
dst =
p[
"destination"];
207 const std::map<std::string,std::size_t>::const_iterator itor = chamber_ids_.find(
dst);
208 if(itor == chamber_ids_.end())
211 assert(itor->second < chambers_.size());
213 passages_.emplace_back(new_chamber.
center, chambers_[itor->second].center,
p);
220 for(std::set<map_location>::const_iterator
i =
c.locs.begin();
i !=
c.locs.end(); ++
i) {
221 set_terrain(*
i,params.clear_);
224 if (
c.items ==
nullptr ||
c.locs.empty())
return;
226 std::size_t
index = 0;
227 for(
const auto [child_key, child_cfg] :
c.items->all_children_view())
231 config* object_filter =
nullptr;
233 if (
auto of = object->optional_child(
"filter")) {
234 object_filter = &*of;
238 if (!child_cfg[
"same_location_as_previous"].to_bool()) {
239 index = rng_()%
c.locs.size();
241 std::string loc_var = child_cfg[
"store_location_as"];
243 std::set<map_location>::const_iterator loc =
c.locs.begin();
244 std::advance(loc,
index);
246 cfg[
"x"] = loc->x + 1;
247 cfg[
"y"] = loc->y + 1;
250 filter[
"x"] = loc->x + 1;
251 filter[
"y"] = loc->y + 1;
255 (*object_filter)[
"x"] = loc->x + 1;
256 (*object_filter)[
"y"] = loc->y + 1;
260 if (child_key ==
"side" && !child_cfg[
"no_castle"].to_bool()) {
261 place_castle(child_cfg[
"side"].to_int(-1), *loc);
264 res_.add_child(child_key, cfg);
266 if(!loc_var.empty()) {
268 temp[
"name"] =
"prestart";
270 xcfg[
"name"] = loc_var +
"_x";
271 xcfg[
"value"] = loc->x + 1;
273 ycfg[
"name"] = loc_var +
"_y";
274 ycfg[
"value"] = loc->y + 1;
283 double laziness, std::size_t windiness,
285 map_(mapdata),
wall_(wall), laziness_(laziness), windiness_(windiness), rng_(rng)
288 virtual double cost(
const map_location& loc,
const double so_far)
const;
305 res *=
static_cast<double>(rng_()%windiness_);
313 const std::string& chance =
p.cfg[
"chance"];
314 if(!chance.empty() &&
static_cast<int>(rng_()%100) < std::stoi(chance)) {
318 int windiness =
p.cfg[
"windiness"].to_int();
319 double laziness = std::max<double>(1.0,
p.cfg[
"laziness"].to_double());
325 int width = std::max<int>(1,
p.cfg[
"width"].to_int());
326 int jagged =
p.cfg[
"jagged"].to_int();
328 for(std::vector<map_location>::const_iterator
i = rt.
steps.begin();
i != rt.
steps.end(); ++
i) {
329 std::set<map_location> locs;
330 build_chamber(*
i,locs,width,jagged);
331 for(std::set<map_location>::const_iterator j = locs.begin(); j != locs.end(); ++j) {
332 set_terrain(*j, params.clear_);
339 if (params.on_board(loc)) {
342 if(
c == params.clear_ ||
c == params.wall_ ||
c == params.village_) {
344 if (
t == params.clear_ &&
static_cast<int>(rng_() % 1000) < params.village_density_ )
355 if (starting_position != -1) {
356 set_terrain(loc, params.keep_);
361 starting_positions_.insert(t_translation::starting_positions::value_type(std::to_string(starting_position), coord));
365 set_terrain(adj, params.castle_);
static lg::log_domain log_engine("engine")
static lg::log_domain log_wml("wml")
cave_map_generator(const config &game_config)
std::string create_map(utils::optional< uint32_t > randomseed={})
Creates a new map and returns it.
config create_scenario(utils::optional< uint32_t > randomseed={})
std::string config_name() const
Return a friendly name for the generator used to differentiate between different configs of the same ...
t_translation::terrain_code wall_
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(config_key_type key)
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
static const int default_border
The default border style for a map.
Encapsulates the map of the game.
std::string id
Text to match against addon_info.tags()
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Standard logging facilities (interface).
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
const terrain_code CAVE_WALL
std::string write_game_map(const ter_map &map, const starting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const terrain_code DWARVEN_KEEP
const terrain_code UNDERGROUND_VILLAGE
const terrain_code DWARVEN_CASTLE
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
std::vector< std::string > split(const config_attribute_value &val)
This module contains various pathfinding functions and utilities.
rect dst
Location on the final composed sheet.
std::set< map_location > locs
void set_terrain(map_location loc, const t_translation::terrain_code &t)
std::vector< chamber > chambers_
void place_chamber(const chamber &c)
cave_map_generator_job(const cave_map_generator ¶ms, utils::optional< uint32_t > randomseed={})
const cave_map_generator & params
void build_chamber(map_location loc, std::set< map_location > &locs, std::size_t size, std::size_t jagged)
std::size_t translate_x(std::size_t x) const
void place_passage(const passage &p)
t_translation::starting_positions starting_positions_
std::size_t translate_y(std::size_t y) const
t_translation::ter_map map_
std::vector< passage > passages_
void place_castle(int starting_position, const map_location &loc)
Encapsulates the map of the game.
const t_translation::ter_map & map_
virtual double cost(const map_location &loc, const double so_far) const
t_translation::terrain_code wall_
passage_path_calculator(const t_translation::ter_map &mapdata, const t_translation::terrain_code &wall, double laziness, std::size_t windiness, std::mt19937 &rng)
Structure which holds a single route between one location and another.
std::vector< map_location > steps
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...