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

Improve place_nested: Fuzzy neighbor matching and an else option #24431

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions data/json/mapgen/lab/lab_common.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@
"object": {
"mapgensize": [ 24, 24 ],
"place_nested": [
{ "chunks": [ "sub_t_concrete_wall" ], "x": 11, "y": 23, "neighbors": { "south": ["empty_rock"] } },
{ "chunks": [ "sub_t_concrete_wall" ], "x": 12, "y": 23, "neighbors": { "south": ["empty_rock"] } },
{ "chunks": [ "sub_t_concrete_wall" ], "x": 23, "y": 11, "neighbors": { "east": ["empty_rock"] } },
{ "chunks": [ "sub_t_concrete_wall" ], "x": 23, "y": 12, "neighbors": { "east": ["empty_rock"] } },
{ "chunks": [ "lab_north_wall" ], "x": 0, "y": 0, "neighbors": { "north": ["empty_rock"] } },
{ "chunks": [ "lab_west_wall" ], "x": 0, "y": 0, "neighbors": { "west": ["empty_rock"] } }
{ "else_chunks": [ "sub_t_concrete_wall" ], "x": 11, "y": 23, "neighbors": { "south": ["lab"] } },
{ "else_chunks": [ "sub_t_concrete_wall" ], "x": 12, "y": 23, "neighbors": { "south": ["lab"] } },
{ "else_chunks": [ "sub_t_concrete_wall" ], "x": 23, "y": 11, "neighbors": { "east": ["lab"] } },
{ "else_chunks": [ "sub_t_concrete_wall" ], "x": 23, "y": 12, "neighbors": { "east": ["lab"] } },
{ "else_chunks": [ "lab_north_wall" ], "x": 0, "y": 0, "neighbors": { "north": ["lab"] } },
{ "else_chunks": [ "lab_west_wall" ], "x": 0, "y": 0, "neighbors": { "west": ["lab"] } }
]
}
},
Expand Down
24 changes: 12 additions & 12 deletions data/json/mapgen/lab/lab_floorplan_cross.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,18 +174,18 @@
"object": {
"mapgensize": [ 24, 24 ],
"place_nested": [
{ "chunks": [ "lab_nw_rock" ], "x": 0, "y": 0, "neighbors": { "north": "empty_rock" } },
{ "chunks": [ "lab_nw_rock" ], "x": 0, "y": 0, "neighbors": { "west": "empty_rock" } },
{ "chunks": [ "lab_ne_rock" ], "x": 13, "y": 0, "neighbors": { "north": "empty_rock" } },
{ "chunks": [ "lab_ne_rock" ], "x": 13, "y": 0, "neighbors": { "east": "empty_rock" } },
{ "chunks": [ "lab_sw_rock" ], "x": 0, "y": 13, "neighbors": { "south": "empty_rock" } },
{ "chunks": [ "lab_sw_rock" ], "x": 0, "y": 13, "neighbors": { "west": "empty_rock" } },
{ "chunks": [ "lab_se_rock" ], "x": 13, "y": 13, "neighbors": { "south": "empty_rock" } },
{ "chunks": [ "lab_se_rock" ], "x": 13, "y": 13, "neighbors": { "east": "empty_rock" } },
{ "chunks": [ [ "lab_n_rock", 100 ], [ "lab_n_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "north": "empty_rock" } },
{ "chunks": [ [ "lab_w_rock", 100 ], [ "lab_w_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "west": "empty_rock" } },
{ "chunks": [ [ "lab_s_rock", 100 ], [ "lab_s_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "south": "empty_rock" } },
{ "chunks": [ [ "lab_e_rock", 100 ], [ "lab_e_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "east": "empty_rock" } }
{ "else_chunks": [ "lab_nw_rock" ], "x": 0, "y": 0, "neighbors": { "north": "lab" } },
{ "else_chunks": [ "lab_nw_rock" ], "x": 0, "y": 0, "neighbors": { "west": "lab" } },
{ "else_chunks": [ "lab_ne_rock" ], "x": 13, "y": 0, "neighbors": { "north": "lab" } },
{ "else_chunks": [ "lab_ne_rock" ], "x": 13, "y": 0, "neighbors": { "east": "lab" } },
{ "else_chunks": [ "lab_sw_rock" ], "x": 0, "y": 13, "neighbors": { "south": "lab" } },
{ "else_chunks": [ "lab_sw_rock" ], "x": 0, "y": 13, "neighbors": { "west": "lab" } },
{ "else_chunks": [ "lab_se_rock" ], "x": 13, "y": 13, "neighbors": { "south": "lab" } },
{ "else_chunks": [ "lab_se_rock" ], "x": 13, "y": 13, "neighbors": { "east": "lab" } },
{ "else_chunks": [ [ "lab_n_rock", 100 ], [ "lab_n_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "north": "lab" } },
{ "else_chunks": [ [ "lab_w_rock", 100 ], [ "lab_w_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "west": "lab" } },
{ "else_chunks": [ [ "lab_s_rock", 100 ], [ "lab_s_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "south": "lab" } },
{ "else_chunks": [ [ "lab_e_rock", 100 ], [ "lab_e_vault", 30 ] ], "x": 0, "y": 0, "neighbors": { "east": "lab" } }
]
}
},
Expand Down
12 changes: 6 additions & 6 deletions data/json/mapgen/lab/lab_floorplans.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
"place_nested": [
{ "chunks": [ "lab_spawn_9x9_crossdoors" ], "x": 1, "y": 1 },
{ "chunks": [ "lab_spawn_9x9_crossdoors" ], "x": 14, "y": 1 },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "east": ["lab", "lab_stairs", "ice_lab", "ice_lab_stairs"] } },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "south": ["lab", "lab_stairs", "ice_lab", "ice_lab_stairs"] } }
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "east": ["lab"] } },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "south": ["lab"] } }
]
}
},
Expand Down Expand Up @@ -133,8 +133,8 @@
},
"place_nested": [
{ "chunks": [ [ "null", 90 ], [ "lab_hulk_smash", 10 ] ], "x": 0, "y": 0 },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "east": ["lab", "lab_stairs", "ice_lab", "ice_lab_stairs"] } },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "south": ["lab", "lab_stairs", "ice_lab", "ice_lab_stairs"] } }
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "east": ["lab"] } },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "south": ["lab"] } }
]
}
},
Expand Down Expand Up @@ -232,8 +232,8 @@
},
"place_nested": [
{ "chunks": [ [ "null", 90 ], [ "lab_hulk_smash", 10 ] ], "x": 0, "y": 0 },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "east": ["lab", "lab_stairs", "ice_lab", "ice_lab_stairs"] } },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "south": ["lab", "lab_stairs", "ice_lab", "ice_lab_stairs"] } }
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "east": ["lab"] } },
{ "chunks": [ "lab_north_doors" ], "x": 11, "y": 0, "neighbors": { "south": ["lab"] } }
]
}
},
Expand Down
117 changes: 53 additions & 64 deletions src/mapgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,18 @@ class jmapgen_computer : public jmapgen_piece {
}
};

static void load_weighted_entries(JsonObject &jsi, std::string json_key, weighted_int_list<std::string>& list) {
JsonArray jarr = jsi.get_array( json_key );
while( jarr.has_more() ) {
if( jarr.test_array() ) {
JsonArray inner = jarr.next_array();
list.add( inner.get_string( 0 ), inner.get_int( 1 ) );
} else {
list.add( jarr.next_string(), 100 );
}
}
}

/**
* Calls another mapgen call inside the current one.
* Note: can't use regular overmap ids.
Expand All @@ -1239,40 +1251,39 @@ class jmapgen_nested : public jmapgen_piece {
return true;
}

bool all_directions_match = true;
for( om_direction::type dir : om_direction::all ) {
int index = static_cast<int>( dir );
const std::set<oter_str_id> &allowed_neighbors = neighbors[index];
if( !allowed_neighbors.empty() && allowed_neighbors.count( dat.neighbor_at( dir ).id() ) == 0 ) {
return false;

if (allowed_neighbors.empty()) {
continue; // no constraints on this direction, skip.
}
}

return true;
bool this_direction_matches = false;
for( oter_str_id allowed_neighbor : allowed_neighbors ) {
this_direction_matches |= is_ot_subtype(allowed_neighbor.c_str(), dat.neighbor_at( dir ).id() );
}
all_directions_match &= this_direction_matches;
}
return all_directions_match;
}
};

public:
weighted_int_list<std::string> entries;
weighted_int_list<std::string> else_entries;
neighborhood_check neighbors;
jmapgen_nested( JsonObject &jsi ) : jmapgen_piece(), neighbors( jsi.get_object( "neighbors" ) )
{
JsonArray jarr = jsi.get_array( "chunks" );
while( jarr.has_more() ) {
if( jarr.test_array() ) {
JsonArray inner = jarr.next_array();
entries.add( inner.get_string( 0 ), inner.get_int( 1 ) );
} else {
entries.add( jarr.next_string(), 100 );
}
}
load_weighted_entries(jsi, "chunks", entries);
load_weighted_entries(jsi, "else_chunks", else_entries);
}
void apply( const mapgendata &dat, const jmapgen_int &x, const jmapgen_int &y, const float d ) const override
{
const std::string *res = entries.pick();
const std::string *res = neighbors.test( dat ) ? entries.pick() : else_entries.pick();
if( res == nullptr || res->empty() || *res == "null" ) {
return;
}

if( !neighbors.test( dat ) ) {
// This will be common when neighbors.test(...) is false, since else_entires is often empty.
return;
}

Expand Down Expand Up @@ -2837,32 +2848,22 @@ ___DEEE|.R.|...,,...|sss\n",
rotate(3);
}
} else if (tw != 0 || rw != 0 || lw != 0 || bw != 0) { // Sewers!
// @todo: This checks if id is a laboratory the hard-coded way. Get rid of the hardcode.
const auto is_lab = []( const oter_id &id ) {
return is_ot_type( "lab", id ) ||
is_ot_type( "lab_stairs", id ) ||
is_ot_type( "lab_core", id ) ||
is_ot_type( "ice_lab", id ) ||
is_ot_type( "ice_lab_stairs", id ) ||
is_ot_type( "ice_lab_core", id );
};

for (int i = 0; i < SEEX * 2; i++) {
for (int j = 0; j < SEEY * 2; j++) {
ter_set(i, j, t_rock_floor);
if (((i < lw || i > SEEX * 2 - 1 - rw) && j > SEEY - 3 && j < SEEY + 2) ||
((j < tw || j > SEEY * 2 - 1 - bw) && i > SEEX - 3 && i < SEEX + 2)) {
ter_set(i, j, t_sewage);
}
if( ( i == 0 && is_lab( t_east ) ) || i == SEEX * 2 - 1 ) {
if( ( i == 0 && is_ot_subtype( "lab", t_east ) ) || i == SEEX * 2 - 1 ) {
if (ter(i, j) == t_sewage) {
ter_set(i, j, t_bars);
} else if (j == SEEY - 1 || j == SEEY) {
ter_set(i, j, t_door_metal_c);
} else {
ter_set(i, j, t_concrete_wall);
}
} else if( ( j == 0 && is_lab( t_north ) ) || j == SEEY * 2 - 1 ) {
} else if( ( j == 0 && is_ot_subtype( "lab", t_north ) ) || j == SEEY * 2 - 1 ) {
if (ter(i, j) == t_sewage) {
ter_set(i, j, t_bars);
} else if (i == SEEX - 1 || i == SEEX) {
Expand All @@ -2875,18 +2876,11 @@ ___DEEE|.R.|...,,...|sss\n",
}
} else { // We're below ground, and no sewers
// Set up the boundaries of walls (connect to adjacent lab squares)
// Are we in an ice lab?
if ( ice_lab ) {
tw = is_ot_type("ice_lab", t_north) ? 0 : 2;
rw = is_ot_type("ice_lab", t_east) ? 1 : 2;
bw = is_ot_type("ice_lab", t_south) ? 1 : 2;
lw = is_ot_type("ice_lab", t_west) ? 0 : 2;
} else {
tw = is_ot_type("lab", t_north) ? 0 : 2;
rw = is_ot_type("lab", t_east) ? 1 : 2;
bw = is_ot_type("lab", t_south) ? 1 : 2;
lw = is_ot_type("lab", t_west) ? 0 : 2;
}
tw = is_ot_subtype("lab", t_north) ? 0 : 2;
rw = is_ot_subtype("lab", t_east) ? 1 : 2;
bw = is_ot_subtype("lab", t_south) ? 1 : 2;
lw = is_ot_subtype("lab", t_west) ? 0 : 2;

int boarders = 0;
if (tw == 0 ) {
boarders++;
Expand Down Expand Up @@ -2927,14 +2921,14 @@ ___DEEE|.R.|...,,...|sss\n",
}
const auto predicate = [this]( const tripoint &p ) { return ter( p ) == t_rock_floor; };
const auto range = points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } );
if (t_above == "lab_stairs" || t_above == "ice_lab_stairs") {
if (is_ot_subtype("stairs", t_above)) {
if( const auto p = random_point( range, predicate ) ) {
remove_trap( *p );
ter_set( *p, t_stairs_up );
}
}

if (terrain_type == "lab_stairs" || terrain_type == "ice_lab_stairs") {
if (is_ot_subtype("stairs", terrain_type)) {
if( const auto p = random_point( range, predicate ) ) {
remove_trap( *p );
ter_set( *p, t_stairs_down );
Expand Down Expand Up @@ -2990,12 +2984,12 @@ ___DEEE|.R.|...,,...|sss\n",
}
}

if (t_above == "lab_stairs" || t_above == "ice_lab_stairs") {
if (is_ot_subtype("stairs", t_above)) {
if( const auto p = random_point( points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } ), [this]( const tripoint &n ) { return ter( n ) == t_rock_floor; } ) ) {
ter_set( *p, t_stairs_up );
}
}
if (terrain_type == "lab_stairs" || terrain_type == "ice_lab_stairs") {
if (is_ot_subtype("stairs", terrain_type)) {
if( const auto p = random_point( points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } ), [this]( const tripoint &n ) { return ter( n ) == t_rock_floor; } ) ) {
ter_set( *p, t_stairs_down );
}
Expand All @@ -3022,7 +3016,7 @@ ___DEEE|.R.|...,,...|sss\n",
}
}
}
if (t_above == "lab_stairs" || t_above == "ice_lab_stairs") {
if (is_ot_subtype("stairs", t_above)) {
ter_set(rng(SEEX - 1, SEEX), rng(SEEY - 1, SEEY), t_stairs_up);
}
// Top left
Expand Down Expand Up @@ -3067,7 +3061,7 @@ ___DEEE|.R.|...,,...|sss\n",
ter_set(SEEX - 1, SEEY * 2 - 1, t_door_metal_c);
ter_set(SEEX , SEEY * 2 - 1, t_door_metal_c);
}
if (terrain_type == "lab_stairs" || terrain_type == "ice_lab_stairs") { // Stairs going down
if (is_ot_subtype("stairs", terrain_type)) { // Stairs going down
std::vector<point> stair_points;
if (tw != 0) {
stair_points.push_back(point(SEEX - 1, 2));
Expand Down Expand Up @@ -3119,7 +3113,7 @@ ___DEEE|.R.|...,,...|sss\n",
}
}
}
if (t_above == "lab_stairs" || t_above == "ice_lab_stairs") {
if (is_ot_subtype("stairs", t_above)) {
ter_set(SEEX - 1, SEEY - 1, t_stairs_up);
ter_set(SEEX , SEEY - 1, t_stairs_up);
ter_set(SEEX - 1, SEEY , t_stairs_up);
Expand Down Expand Up @@ -3154,7 +3148,7 @@ ___DEEE|.R.|...,,...|sss\n",
ter_set(SEEX - 1, SEEY * 2 - 1, t_door_metal_c);
ter_set(SEEX , SEEY * 2 - 1, t_door_metal_c);
}
if (terrain_type == "lab_stairs" || terrain_type == "ice_lab_stairs") {
if (is_ot_subtype("stairs", terrain_type)) {
ter_set(SEEX - 3 + 5 * rng(0, 1), SEEY - 3 + 5 * rng(0, 1), t_stairs_down);
}
break;
Expand All @@ -3173,7 +3167,7 @@ ___DEEE|.R.|...,,...|sss\n",
}
science_room(this, lw, tw, SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw,
zlevel, rng(0, 3));
if (t_above == "lab_stairs" || t_above == "ice_lab_stairs") {
if (is_ot_subtype("stairs", t_above)) {
if( const auto p = random_point( points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } ), [this]( const tripoint &n ) { return ter( n ) == t_rock_floor; } ) ) {
ter_set( *p, t_stairs_up );
}
Expand All @@ -3186,7 +3180,7 @@ ___DEEE|.R.|...,,...|sss\n",
ter_set(SEEX - 1, SEEY * 2 - 1, t_door_metal_c);
ter_set(SEEX , SEEY * 2 - 1, t_door_metal_c);
}
if (terrain_type == "lab_stairs" || terrain_type == "ice_lab_stairs") {
if (is_ot_subtype("stairs", terrain_type)) {
if( const auto p = random_point( points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } ), [this]( const tripoint &n ) { return ter( n ) == t_rock_floor; } ) ) {
ter_set( *p, t_stairs_down );
}
Expand Down Expand Up @@ -3273,18 +3267,13 @@ ___DEEE|.R.|...,,...|sss\n",
if ( ice_lab ) {
int temperature = -20 + 30 * zlevel;
set_temperature(x, y, temperature);

tw = is_ot_type("ice_lab", t_north) ? 0 : 2;
rw = is_ot_type("ice_lab", t_east) ? 1 : 2;
bw = is_ot_type("ice_lab", t_south) ? 1 : 2;
lw = is_ot_type("ice_lab", t_west) ? 0 : 2;
} else {
tw = is_ot_type("lab", t_north) ? 0 : 2;
rw = is_ot_type("lab", t_east) ? 1 : 2;
bw = is_ot_type("lab", t_south) ? 1 : 2;
lw = is_ot_type("lab", t_west) ? 0 : 2;
}

tw = is_ot_subtype("lab", t_north) ? 0 : 2;
rw = is_ot_subtype("lab", t_east) ? 1 : 2;
bw = is_ot_subtype("lab", t_south) ? 1 : 2;
lw = is_ot_subtype("lab", t_west) ? 0 : 2;

const std::string function_key = "lab_finale_1level";
const auto fmapit = oter_mapgen.find( function_key );
const int hardcoded_finale_map_weight = 500; // weight of all hardcoded maps.
Expand Down Expand Up @@ -3531,12 +3520,12 @@ ___DEEE|.R.|...,,...|sss\n",
} // end use_hardcoded_lab_finale

// Handle stairs in the unlikely case they are needed.
if (t_above == "lab_stairs" || t_above == "ice_lab_stairs") {
if (is_ot_subtype("stairs", t_above)) {
if( const auto p = random_point( points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } ), [this]( const tripoint &n ) { return ter( n ) == t_rock_floor; } ) ) {
ter_set( *p, t_stairs_up );
}
}
if (terrain_type == "lab_stairs" || terrain_type == "ice_lab_stairs") {
if (is_ot_subtype("stairs", terrain_type)) {
if( const auto p = random_point( points_in_rectangle( { lw, tw, abs_sub.z }, { SEEX * 2 - 1 - rw, SEEY * 2 - 1 - bw, abs_sub.z } ), [this]( const tripoint &n ) { return ter( n ) == t_rock_floor; } ) ) {
ter_set( *p, t_stairs_down );
}
Expand Down