Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parametric mapgen part 3: Support mapgen parameters in nests #50681

Merged
merged 8 commits into from
Aug 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions data/json/mapgen_palettes/house_w_palette.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
{
"type": "palette",
"id": "house_w_nest_palette",
"parameters": {
"house_w_nest_carpet_type": {
"type": "ter_str_id",
"scope": "nest",
"default": {
"distribution": [ [ "t_carpet_yellow", 2 ], [ "t_carpet_green", 2 ], [ "t_carpet_purple", 1 ], [ "t_carpet_red", 1 ], [ "t_floor", 2 ] ]
}
}
},
"furniture": {
"A": "f_stool",
"B": "f_chair",
Expand Down Expand Up @@ -67,10 +76,7 @@
"=": "t_region_groundcover_barren",
"2": "t_region_groundcover_barren",
"5": "t_region_groundcover_barren",
"6": "t_carpet_red",
"7": "t_carpet_green",
"8": "t_carpet_purple",
"9": "t_carpet_yellow"
"6": { "param": "house_w_nest_carpet_type" }
},
"toilets": { "t": { } },
"liquids": { "g": { "liquid": "water_clean", "amount": [ 0, 100 ] } }
Expand Down
6 changes: 0 additions & 6 deletions data/mods/No_Hope/Mapgen/map_extras/mapgen_updates.json
Original file line number Diff line number Diff line change
Expand Up @@ -470,11 +470,5 @@
},
"npcs": { "@": { "class": "raider" } }
}
},
{
"type": "mapgen",
"method": "json",
"update_mapgen_id": "bandits_rv",
"object": { "place_nested": [ { "chunks": [ "bandits_rv" ], "x": 0, "y": 0 } ] }
}
]
9 changes: 9 additions & 0 deletions doc/MAPGEN.md
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,15 @@ single overmap tile. Then a default value will be chosen independently for
each OMT. This has the advantage that you are no longer forced to select a
`"fallback"` value when using that parameter in mapgen.

The third option for scope is `"scope": "nest"`. This only makes sense when
used in nested mapgen (although it is not an error to use it elsewhere, so that
the same palette may be used for nested and non-nested mapgen). When the scope
is `nest`, the value of the parameter is chosen for a particular nested chunk.
For example, suppose a nest defines a carpet across several tiles, you can use
a parameter to ensure that the carpet is the same colour for all the tiles
within that nest, but another instance of the same `nested_mapgen_id` elsewhere
in the same OMT might choose a different colour.


## Rotate the map with "rotation"

Expand Down
107 changes: 99 additions & 8 deletions src/mapgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ class mapgen_basic_container
// Not needed anymore, pointers are now stored in weights_ (or not used at all)
mapgens_.clear();
}
void finalize_parameters() {
for( auto &mapgen_function_ptr : weights_ ) {
mapgen_function_ptr.obj->finalize_parameters();
}
}
void check_consistency() {
for( auto &mapgen_function_ptr : weights_ ) {
mapgen_function_ptr.obj->check();
Expand Down Expand Up @@ -321,9 +326,15 @@ class mapgen_factory
omw.second.setup();
inp_mngr.pump_events();
}
// Dummy entry, overmap terrain null should never appear and is therefore never generated.
// Dummy entry, overmap terrain null should never appear and is
// therefore never generated.
mapgens_.erase( "null" );
}
void finalize_parameters() {
for( std::pair<const std::string, mapgen_basic_container> &omw : mapgens_ ) {
omw.second.finalize_parameters();
}
}
void check_consistency() {
// Cache all strings that may get looked up here so we don't have to go through
// all the sources for them upon each loop.
Expand Down Expand Up @@ -394,7 +405,21 @@ void calculate_mapgen_weights() // TODO: rename as it runs jsonfunction setup
inp_mngr.pump_events();
}
}

// Having set up all the mapgens we can now perform a second
// pass of finalizing their parameters
oter_mapgen.finalize_parameters();
for( auto &pr : nested_mapgen ) {
for( weighted_object<int, std::shared_ptr<mapgen_function_json_nested>> &ptr : pr.second ) {
ptr.obj->finalize_parameters();
inp_mngr.pump_events();
}
}
for( auto &pr : update_mapgen ) {
for( auto &ptr : pr.second ) {
ptr->finalize_parameters();
inp_mngr.pump_events();
}
}
}

void check_mapgen_definitions()
Expand Down Expand Up @@ -599,6 +624,13 @@ static bool common_check_bounds( const jmapgen_int &x, const jmapgen_int &y,
return true;
}

void mapgen_function_json_base::merge_non_nest_parameters_into(
mapgen_parameters &params, const std::string &outer_context ) const
{
const std::string context = string_format( "%s within %s", context_, outer_context );
params.check_and_merge( parameters, context, mapgen_parameter_scope::nest );
}

bool mapgen_function_json_base::check_inbounds( const jmapgen_int &x, const jmapgen_int &y,
const JsonObject &jso ) const
{
Expand Down Expand Up @@ -801,6 +833,11 @@ void mapgen_function_json_base::setup_setmap( const JsonArray &parray )

}

void mapgen_function_json_base::finalize_parameters_common()
{
objects.merge_parameters_into( parameters, context_ );
}

mapgen_arguments mapgen_function_json_base::get_args(
const mapgendata &md, mapgen_parameter_scope scope ) const
{
Expand Down Expand Up @@ -988,7 +1025,10 @@ class mapgen_value
if( const distribution_source *other =
dynamic_cast<const distribution_source *>( &o ) ) {
if( list != other->list ) {
debugmsg( "inconsistent default value distributions for %s", context );
const std::string my_list = list.to_debug_string();
const std::string other_list = other->list.to_debug_string();
debugmsg( "inconsistent default value distributions for %s (%s vs %s)",
context, my_list, other_list );
}
} else {
debugmsg( "inconsistent default types for %s", context );
Expand Down Expand Up @@ -1111,13 +1151,16 @@ mapgen_arguments mapgen_parameters::get_args(
}

void mapgen_parameters::check_and_merge( const mapgen_parameters &other,
const std::string &context )
const std::string &context, mapgen_parameter_scope up_to_scope )
{
for( const std::pair<const std::string, mapgen_parameter> &p : other.map ) {
const mapgen_parameter &other_param = p.second;
if( other_param.scope() >= up_to_scope ) {
continue;
}
auto insert_result = map.insert( p );
if( !insert_result.second ) {
const std::string &name = p.first;
const mapgen_parameter &other_param = p.second;
const mapgen_parameter &this_param = insert_result.first->second;
this_param.check_consistent_with(
other_param, string_format( "parameter %s in %s", name, context ) );
Expand Down Expand Up @@ -2265,6 +2308,31 @@ class jmapgen_nested : public jmapgen_piece
int phase() const override {
return 1;
}
void merge_parameters_into( mapgen_parameters &params,
const std::string &outer_context ) const override {
auto merge_from = [&]( const std::string & name ) {
if( name == "null" ) {
return;
}
const auto iter = nested_mapgen.find( name );
if( iter == nested_mapgen.end() ) {
debugmsg( "Unknown nested mapgen function id %s", name );
return;
}
using Obj = weighted_object<int, std::shared_ptr<mapgen_function_json_nested>>;
for( const Obj &nested : iter->second ) {
nested.obj->merge_non_nest_parameters_into( params, outer_context );
}
};

for( const weighted_object<int, std::string> &name : entries ) {
merge_from( name.obj );
}

for( const weighted_object<int, std::string> &name : else_entries ) {
merge_from( name.obj );
}
}
void apply( const mapgendata &dat, const jmapgen_int &x, const jmapgen_int &y
) const override {
const std::string *res = neighbors.test( dat ) ? entries.pick() : else_entries.pick();
Expand Down Expand Up @@ -2762,6 +2830,21 @@ void update_mapgen_function_json::setup()
setup_common();
}

void mapgen_function_json::finalize_parameters()
{
finalize_parameters_common();
}

void mapgen_function_json_nested::finalize_parameters()
{
finalize_parameters_common();
}

void update_mapgen_function_json::finalize_parameters()
{
finalize_parameters_common();
}

/*
* Parse json, pre-calculating values for stuff, then cheerfully throw json away. Faster than regular mapf, in theory
*/
Expand Down Expand Up @@ -2971,6 +3054,14 @@ void jmapgen_objects::check( const std::string &context, const mapgen_parameters
}
}

void jmapgen_objects::merge_parameters_into( mapgen_parameters &params,
const std::string &outer_context ) const
{
for( const jmapgen_obj &obj : objects ) {
obj.second->merge_parameters_into( params, outer_context );
}
}

/////////////////////////////////////////////////////////////////////////////////
///// 3 - mapgen (gameplay)
///// stuff below is the actual in-game map generation (ill)logic
Expand Down Expand Up @@ -3198,12 +3289,12 @@ void mapgen_function_json_nested::nest( const mapgendata &md, const point &offse
mapgendata md_with_params( md, get_args( md, mapgen_parameter_scope::nest ) );

for( const jmapgen_setmap &elem : setmap_points ) {
elem.apply( md, offset );
elem.apply( md_with_params, offset );
}

objects.apply( md, offset );
objects.apply( md_with_params, offset );

resolve_regional_terrain_and_furniture( md );
resolve_regional_terrain_and_furniture( md_with_params );
}

/*
Expand Down
13 changes: 13 additions & 0 deletions src/mapgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class mapgen_function
public:
virtual ~mapgen_function() = default;
virtual void setup() { } // throws
virtual void finalize_parameters() { }
virtual void check() const { }
virtual void generate( mapgendata & ) = 0;
virtual mapgen_parameters get_mapgen_params( mapgen_parameter_scope ) const {
Expand Down Expand Up @@ -182,6 +183,10 @@ class jmapgen_piece
}
/** Sanity-check this piece */
virtual void check( const std::string &/*context*/, const mapgen_parameters & ) const { }

virtual void merge_parameters_into( mapgen_parameters &,
const std::string &/*outer_context*/ ) const {}

/** Place something on the map from mapgendata &dat, at (x,y). */
virtual void apply( const mapgendata &dat, const jmapgen_int &x, const jmapgen_int &y
) const = 0;
Expand Down Expand Up @@ -321,6 +326,8 @@ struct jmapgen_objects {
void finalize();
void check( const std::string &context, const mapgen_parameters & ) const;

void merge_parameters_into( mapgen_parameters &, const std::string &outer_context ) const;

void apply( const mapgendata &dat ) const;
void apply( const mapgendata &dat, const point &offset ) const;

Expand All @@ -343,6 +350,8 @@ struct jmapgen_objects {
class mapgen_function_json_base
{
public:
void merge_non_nest_parameters_into( mapgen_parameters &,
const std::string &outer_context ) const;
bool check_inbounds( const jmapgen_int &x, const jmapgen_int &y, const JsonObject &jso ) const;
size_t calc_index( const point &p ) const;
bool has_vehicle_collision( const mapgendata &dat, const point &offset ) const;
Expand All @@ -360,6 +369,7 @@ class mapgen_function_json_base
// Returns true if the mapgen qualifies at this point already
virtual bool setup_internal( const JsonObject &jo ) = 0;
virtual void setup_setmap_internal() { }
void finalize_parameters_common();

void check_common() const;

Expand All @@ -380,6 +390,7 @@ class mapgen_function_json : public mapgen_function_json_base, public virtual ma
{
public:
void setup() override;
void finalize_parameters() override;
void check() const override;
void generate( mapgendata & ) override;
mapgen_parameters get_mapgen_params( mapgen_parameter_scope ) const override;
Expand All @@ -405,6 +416,7 @@ class update_mapgen_function_json : public mapgen_function_json_base

void setup();
bool setup_update( const JsonObject &jo );
void finalize_parameters();
void check() const;
bool update_map( const tripoint_abs_omt &omt_pos, const point &offset,
mission *miss, bool verify = false ) const;
Expand All @@ -420,6 +432,7 @@ class mapgen_function_json_nested : public mapgen_function_json_base
{
public:
void setup();
void finalize_parameters();
void check() const;
mapgen_function_json_nested( const json_source_location &jsrcloc, const std::string &context );
~mapgen_function_json_nested() override = default;
Expand Down
9 changes: 8 additions & 1 deletion src/mapgen_parameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ template <typename Id> class mapgen_value;
class mapgendata;

enum class mapgen_parameter_scope {
// Should be ordered from most general to most specific
overmap_special,
omt,
nest,
Expand All @@ -20,6 +21,11 @@ struct enum_traits<mapgen_parameter_scope> {
static constexpr mapgen_parameter_scope last = mapgen_parameter_scope::last;
};

inline bool operator<( mapgen_parameter_scope l, mapgen_parameter_scope r )
{
return static_cast<int>( l ) < static_cast<int>( r );
}

class mapgen_parameter
{
public:
Expand All @@ -45,7 +51,8 @@ struct mapgen_parameters {

mapgen_parameters params_for_scope( mapgen_parameter_scope scope ) const;
mapgen_arguments get_args( const mapgendata &, mapgen_parameter_scope scope ) const;
void check_and_merge( const mapgen_parameters &, const std::string &context );
void check_and_merge( const mapgen_parameters &, const std::string &context,
mapgen_parameter_scope up_to_scope = mapgen_parameter_scope::last );
};

#endif // CATA_SRC_MAPGEN_PARAMETER_H
2 changes: 1 addition & 1 deletion src/overmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4162,7 +4162,7 @@ void overmap::place_special(

overmap_special_placements[location] = special.id;
ter_set( location, tid );
mapgen_args_index.emplace( location, mapgen_args_p );
mapgen_args_index[location] = mapgen_args_p;
if( is_safe_zone ) {
safe_at_worldgen.emplace( location );
}
Expand Down
5 changes: 5 additions & 0 deletions src/string_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ class string_id
return !is_null();
}

friend std::ostream &operator<<( std::ostream &os, const string_id &s ) {
os << s.str();
return os;
}

private:
// generic_factory version that corresponds to the _cid
mutable int64_t _version = INVALID_VERSION;
Expand Down
11 changes: 11 additions & 0 deletions src/weighted_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <climits>
#include <cstdlib>
#include <functional>
#include <sstream>
#include <vector>

template <typename W, typename T> struct weighted_object {
Expand Down Expand Up @@ -183,6 +184,16 @@ template <typename W, typename T> struct weighted_list {
return objects.empty();
}

std::string to_debug_string() const {
std::ostringstream os;
os << "[ ";
for( const weighted_object<W, T> &o : objects ) {
os << o.obj << ":" << o.weight << ", ";
}
os << "]";
return os.str();
}

friend bool operator==( const weighted_list &l, const weighted_list &r ) {
return l.objects == r.objects;
}
Expand Down