Skip to content

Commit

Permalink
Merge pull request #32242 from jbytheway/generic_inbounds_overhaul
Browse files Browse the repository at this point in the history
point / tripoint / rectangle / box refactoring and enhancements
  • Loading branch information
kevingranade authored Jul 8, 2019
2 parents f8ee22c + 28cbd6f commit 3b8996a
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 82 deletions.
14 changes: 5 additions & 9 deletions src/editmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,9 @@
#define dbg(x) DebugLog((DebugLevel)(x),D_GAME) << __FILE__ << ":" << __LINE__ << ": "

static constexpr tripoint editmap_boundary_min( 0, 0, -OVERMAP_DEPTH );
static constexpr tripoint editmap_boundary_max( MAPSIZE_X, MAPSIZE_Y, OVERMAP_HEIGHT );
static constexpr tripoint editmap_clearance_min( tripoint_zero );
static constexpr tripoint editmap_clearance_max( 1, 1, 0 );
static constexpr tripoint editmap_boundary_max( MAPSIZE_X, MAPSIZE_Y, OVERMAP_HEIGHT + 1 );

static constexpr box editmap_boundaries( editmap_boundary_min, editmap_boundary_max );
static constexpr box editmap_clearance( editmap_clearance_min, editmap_clearance_max );

static const ter_id undefined_ter_id( -1 );
static const furn_id undefined_furn_id( -1 );
Expand Down Expand Up @@ -1429,7 +1426,7 @@ tripoint editmap::recalc_target( shapetype shape )
for( int y = origin.y - radius; y <= origin.y + radius; y++ ) {
const tripoint p( x, y, z );
if( rl_dist( p, origin ) <= radius ) {
if( generic_inbounds( p, editmap_boundaries, editmap_clearance ) ) {
if( editmap_boundaries.contains_half_open( p ) ) {
target_list.push_back( p );
}
}
Expand Down Expand Up @@ -1461,7 +1458,7 @@ tripoint editmap::recalc_target( shapetype shape )
for( int y = sy; y <= ey; y++ ) {
if( shape == editmap_rect_filled || x == sx || x == ex || y == sy || y == ey ) {
const tripoint p( x, y, z );
if( generic_inbounds( p, editmap_boundaries, editmap_clearance ) ) {
if( editmap_boundaries.contains_half_open( p ) ) {
target_list.push_back( p );
}
}
Expand Down Expand Up @@ -1871,9 +1868,8 @@ int editmap::mapgen_retarget()
if( const cata::optional<tripoint> vec = ctxt.get_direction( action ) ) {
tripoint ptarget = tripoint( target.x + ( vec->x * SEEX * 2 ), target.y + ( vec->y * SEEY * 2 ),
target.z );
if( generic_inbounds( ptarget, editmap_boundaries, editmap_clearance ) &&
generic_inbounds( { ptarget.x + SEEX, ptarget.y + SEEY, ptarget.z },
editmap_boundaries, editmap_clearance ) ) {
if( editmap_boundaries.contains_half_open( ptarget ) &&
editmap_boundaries.contains_half_open( ptarget + point( SEEX, SEEY ) ) ) {
target = ptarget;

target_list.clear();
Expand Down
2 changes: 1 addition & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3768,7 +3768,7 @@ std::unordered_set<tripoint> game::get_fishable_locations( int distance, const t
}

// This point is out of bounds, so bail.
if( !generic_inbounds( current_point, fishing_boundaries ) ) {
if( !fishing_boundaries.contains_inclusive( current_point ) ) {
continue;
}

Expand Down
24 changes: 10 additions & 14 deletions src/lightmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,8 @@

static constexpr point lightmap_boundary_min( point_zero );
static constexpr point lightmap_boundary_max( LIGHTMAP_CACHE_X, LIGHTMAP_CACHE_Y );
static constexpr point lightmap_clearance_min( point_zero );
static constexpr point lightmap_clearance_max( 1, 1 );

const rectangle lightmap_boundaries( lightmap_boundary_min, lightmap_boundary_max );
const rectangle lightmap_clearance( lightmap_clearance_min, lightmap_clearance_max );

const efftype_id effect_onfire( "onfire" );
const efftype_id effect_haslight( "haslight" );
Expand Down Expand Up @@ -324,9 +321,9 @@ void map::generate_lightmap( const int zlev )
if( !outside_cache[p.x][p.y] ) {
// Apply light sources for external/internal divide
for( int i = 0; i < 4; ++i ) {
if( generic_inbounds( { p.x + dir_x[i], p.y + dir_y[i] },
lightmap_boundaries, lightmap_clearance
) && outside_cache[p.x + dir_x[i]][p.y + dir_y[i]]
point neighbour = p.xy() + point( dir_x[i], dir_y[i] );
if( lightmap_boundaries.contains_half_open( neighbour )
&& outside_cache[neighbour.x][neighbour.y]
) {
if( light_transparency( p ) > LIGHT_TRANSPARENCY_SOLID ) {
update_light_quadrants(
Expand Down Expand Up @@ -606,17 +603,16 @@ map::apparent_light_info map::apparent_light_helper( const level_cache &map_cach

four_quadrants seen_from( 0 );
for( const offset_and_quadrants &oq : adjacent_offsets ) {
const int neighbour_x = p.x + oq.offset.x;
const int neighbour_y = p.y + oq.offset.y;
const point neighbour = p.xy() + oq.offset;

if( !generic_inbounds( { neighbour_x, neighbour_y }, lightmap_boundaries, lightmap_clearance ) ) {
if( !lightmap_boundaries.contains_half_open( neighbour ) ) {
continue;
}
if( is_opaque( neighbour_x, neighbour_y ) ) {
if( is_opaque( neighbour.x, neighbour.y ) ) {
continue;
}
if( map_cache.seen_cache[neighbour_x][neighbour_y] == 0 &&
map_cache.camera_cache[neighbour_x][neighbour_y] == 0 ) {
if( map_cache.seen_cache[neighbour.x][neighbour.y] == 0 &&
map_cache.camera_cache[neighbour.x][neighbour.y] == 0 ) {
continue;
}
// This is a non-opaque visible neighbour, so count visibility from the relevant
Expand Down Expand Up @@ -1499,7 +1495,7 @@ void map::apply_light_ray( bool lit[LIGHTMAP_CACHE_X][LIGHTMAP_CACHE_Y],
t += ay;

// TODO: clamp coordinates to map bounds before this method is called.
if( generic_inbounds( { x, y }, lightmap_boundaries, lightmap_clearance ) ) {
if( lightmap_boundaries.contains_half_open( point( x, y ) ) ) {
float current_transparency = transparency_cache[x][y];
bool is_opaque = ( current_transparency == LIGHT_TRANSPARENCY_SOLID );
if( !lit[x][y] ) {
Expand Down Expand Up @@ -1531,7 +1527,7 @@ void map::apply_light_ray( bool lit[LIGHTMAP_CACHE_X][LIGHTMAP_CACHE_Y],
y += dy;
t += ax;

if( generic_inbounds( { x, y }, lightmap_boundaries, lightmap_clearance ) ) {
if( lightmap_boundaries.contains_half_open( point( x, y ) ) ) {
float current_transparency = transparency_cache[x][y];
bool is_opaque = ( current_transparency == LIGHT_TRANSPARENCY_SOLID );
if( !lit[x][y] ) {
Expand Down
14 changes: 4 additions & 10 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7521,27 +7521,21 @@ const std::vector<tripoint> &map::trap_locations( const trap_id &type ) const
bool map::inbounds( const tripoint &p ) const
{
static constexpr tripoint map_boundary_min( 0, 0, -OVERMAP_DEPTH );
static constexpr tripoint map_boundary_max( MAPSIZE_Y, MAPSIZE_X, OVERMAP_HEIGHT );
static constexpr tripoint map_clearance_min( tripoint_zero );
static constexpr tripoint map_clearance_max( 1, 1, 0 );
static constexpr tripoint map_boundary_max( MAPSIZE_Y, MAPSIZE_X, OVERMAP_HEIGHT + 1 );

static constexpr box map_boundaries( map_boundary_min, map_boundary_max );
static constexpr box map_clearance( map_clearance_min, map_clearance_max );

return generic_inbounds( p, map_boundaries, map_clearance );
return map_boundaries.contains_half_open( p );
}

bool tinymap::inbounds( const tripoint &p ) const
{
constexpr tripoint map_boundary_min( 0, 0, -OVERMAP_DEPTH );
constexpr tripoint map_boundary_max( SEEY * 2, SEEX * 2, OVERMAP_HEIGHT );
constexpr tripoint map_clearance_min( tripoint_zero );
constexpr tripoint map_clearance_max( 1, 1, 0 );
constexpr tripoint map_boundary_max( SEEY * 2, SEEX * 2, OVERMAP_HEIGHT + 1 );

constexpr box map_boundaries( map_boundary_min, map_boundary_max );
constexpr box map_clearance( map_clearance_min, map_clearance_max );

return generic_inbounds( p, map_boundaries, map_clearance );
return map_boundaries.contains_half_open( p );
}

// set up a map just long enough scribble on it
Expand Down
14 changes: 7 additions & 7 deletions src/mapgen_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4282,10 +4282,10 @@ void mapgen_lake_shore( map *m, oter_id, mapgendata dat, const time_point &turn,
const int sector_length = SEEX * 2 / 3;

// Define the corners of the map. These won't change.
const point nw_corner( 0, 0 );
const point ne_corner( SEEX * 2 - 1, 0 );
const point se_corner( SEEX * 2 - 1, SEEY * 2 - 1 );
const point sw_corner( 0, SEEY * 2 - 1 );
static constexpr point nw_corner( 0, 0 );
static constexpr point ne_corner( SEEX * 2 - 1, 0 );
static constexpr point se_corner( SEEX * 2 - 1, SEEY * 2 - 1 );
static constexpr point sw_corner( 0, SEEY * 2 - 1 );

// Define the four points that make up our polygon that we'll later pull line segments from for
// the actual shoreline.
Expand Down Expand Up @@ -4443,7 +4443,7 @@ void mapgen_lake_shore( map *m, oter_id, mapgendata dat, const time_point &turn,
line_segments.push_back( { sw, nw } );
}

const rectangle map_boundaries( nw_corner, se_corner );
static constexpr rectangle map_boundaries( nw_corner, se_corner );

// This will draw our shallow water coastline from the "from" point to the "to" point.
// It buffers the points a bit for a thicker line. It also clears any furniture that might
Expand All @@ -4453,7 +4453,7 @@ void mapgen_lake_shore( map *m, oter_id, mapgendata dat, const time_point &turn,
for( auto &p : points ) {
std::vector<point> buffered_points = closest_points_first( 1, p.x, p.y );
for( const point &bp : buffered_points ) {
if( !generic_inbounds( bp, map_boundaries ) ) {
if( !map_boundaries.contains_inclusive( bp ) ) {
continue;
}
// Use t_null for now instead of t_water_sh, because sometimes our extended terrain
Expand Down Expand Up @@ -4504,7 +4504,7 @@ void mapgen_lake_shore( map *m, oter_id, mapgendata dat, const time_point &turn,

visited.emplace( current_point );

if( !generic_inbounds( current_point, map_boundaries ) ) {
if( !map_boundaries.contains_inclusive( current_point ) ) {
continue;
}

Expand Down
13 changes: 6 additions & 7 deletions src/overmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1403,15 +1403,14 @@ std::vector<point> overmap::find_extras( const int z, const std::string &text )

bool overmap::inbounds( const tripoint &p, int clearance )
{
const tripoint overmap_boundary_min( 0, 0, -OVERMAP_DEPTH );
const tripoint overmap_boundary_max( OMAPX, OMAPY, OVERMAP_HEIGHT );
const tripoint overmap_clearance_min( 0 + clearance, 0 + clearance, 0 );
const tripoint overmap_clearance_max( 1 + clearance, 1 + clearance, 0 );
static constexpr tripoint overmap_boundary_min( 0, 0, -OVERMAP_DEPTH );
static constexpr tripoint overmap_boundary_max( OMAPX, OMAPY, OVERMAP_HEIGHT + 1 );

const box overmap_boundaries( overmap_boundary_min, overmap_boundary_max );
const box overmap_clearance( overmap_clearance_min, overmap_clearance_max );
static constexpr box overmap_boundaries( overmap_boundary_min, overmap_boundary_max );
box stricter_boundaries = overmap_boundaries;
stricter_boundaries.shrink( tripoint( clearance, clearance, 0 ) );

return generic_inbounds( p, overmap_boundaries, overmap_clearance );
return stricter_boundaries.contains_half_open( p );
}

const scent_trace &overmap::scent_at( const tripoint &loc ) const
Expand Down
27 changes: 27 additions & 0 deletions src/point.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "point.h"

#include <sstream>

std::string point::to_string() const
{
std::ostringstream os;
os << *this;
return os.str();
}

std::string tripoint::to_string() const
{
std::ostringstream os;
os << *this;
return os.str();
}

std::ostream &operator<<( std::ostream &os, const point &pos )
{
return os << "(" << pos.x << "," << pos.y << ")";
}

std::ostream &operator<<( std::ostream &os, const tripoint &pos )
{
return os << "(" << pos.x << "," << pos.y << "," << pos.z << ")";
}
65 changes: 38 additions & 27 deletions src/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ struct point {

return *this;
}

std::string to_string() const;
};

std::ostream &operator<<( std::ostream &, const point & );

void serialize( const point &p, JsonOut &jsout );
void deserialize( point &p, JsonIn &jsin );

Expand Down Expand Up @@ -144,14 +148,17 @@ struct tripoint {
return *this;
}

point xy() const {
return point( x, y );
}

std::string to_string() const;

void serialize( JsonOut &jsout ) const;
void deserialize( JsonIn &jsin );
};

inline std::ostream &operator<<( std::ostream &os, const tripoint &pos )
{
return os << pos.x << "," << pos.y << "," << pos.z;
}
std::ostream &operator<<( std::ostream &, const tripoint & );

// Make tripoint hashable so it can be used as an unordered_set or unordered_map key,
// or a component of one.
Expand Down Expand Up @@ -210,6 +217,16 @@ struct rectangle {
point p_max;
constexpr rectangle() = default;
constexpr rectangle( const point &P_MIN, const point &P_MAX ) : p_min( P_MIN ), p_max( P_MAX ) {}

constexpr bool contains_half_open( const point &p ) const {
return p.x >= p_min.x && p.x < p_max.x &&
p.y >= p_min.y && p.y < p_max.y;
}

constexpr bool contains_inclusive( const point &p ) const {
return p.x >= p_min.x && p.x <= p_max.x &&
p.y >= p_min.y && p.y <= p_max.y;
}
};

struct box {
Expand All @@ -219,6 +236,23 @@ struct box {
constexpr box( const tripoint &P_MIN, const tripoint &P_MAX ) : p_min( P_MIN ), p_max( P_MAX ) {}
explicit constexpr box( const rectangle &R, int Z1, int Z2 ) :
p_min( tripoint( R.p_min, Z1 ) ), p_max( tripoint( R.p_max, Z2 ) ) {}

constexpr bool contains_half_open( const tripoint &p ) const {
return p.x >= p_min.x && p.x < p_max.x &&
p.y >= p_min.y && p.y < p_max.y &&
p.z >= p_min.z && p.z < p_max.z;
}

constexpr bool contains_inclusive( const tripoint &p ) const {
return p.x >= p_min.x && p.x <= p_max.x &&
p.y >= p_min.y && p.y <= p_max.y &&
p.z >= p_min.z && p.z <= p_max.z;
}

void shrink( const tripoint &amount ) {
p_min += amount;
p_max -= amount;
}
};

static constexpr tripoint tripoint_min { INT_MIN, INT_MIN, INT_MIN };
Expand All @@ -241,29 +275,6 @@ static constexpr point point_north_west{ -1, -1 };
static constexpr box box_zero( tripoint_zero, tripoint_zero );
static constexpr rectangle rectangle_zero( point_zero, point_zero );

/** Checks if given tripoint is inbounds of given min and max tripoints using given clearance **/
inline bool generic_inbounds( const tripoint &p,
const box &boundaries,
const box &clearance = box_zero )
{
return p.x >= boundaries.p_min.x + clearance.p_min.x &&
p.x <= boundaries.p_max.x - clearance.p_max.x &&
p.y >= boundaries.p_min.y + clearance.p_min.y &&
p.y <= boundaries.p_max.y - clearance.p_max.y &&
p.z >= boundaries.p_min.z + clearance.p_min.z &&
p.z <= boundaries.p_max.z - clearance.p_max.z;
}

/** Checks if given point is inbounds of given min and max point using given clearance **/
inline bool generic_inbounds( const point &p,
const rectangle &boundaries,
const rectangle &clearance = rectangle_zero )
{
return generic_inbounds( tripoint( p, 0 ),
box( boundaries, 0, 0 ),
box( clearance, 0, 0 ) );
}

struct sphere {
int radius = 0;
tripoint center = tripoint_zero;
Expand Down
12 changes: 5 additions & 7 deletions src/scent_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,13 @@ bool scent_map::inbounds( const tripoint &p ) const
if( !scent_map_z_level_inbounds ) {
return false;
}
const point scent_map_boundary_min( point_zero );
const point scent_map_boundary_max( MAPSIZE_X, MAPSIZE_Y );
const point scent_map_clearance_min( point_zero );
const point scent_map_clearance_max( 1, 1 );
static constexpr point scent_map_boundary_min( point_zero );
static constexpr point scent_map_boundary_max( MAPSIZE_X, MAPSIZE_Y );

const rectangle scent_map_boundaries( scent_map_boundary_min, scent_map_boundary_max );
const rectangle scent_map_clearance( scent_map_clearance_min, scent_map_clearance_max );
static constexpr rectangle scent_map_boundaries(
scent_map_boundary_min, scent_map_boundary_max );

return generic_inbounds( { p.x, p.y }, scent_map_boundaries, scent_map_clearance );
return scent_map_boundaries.contains_half_open( p.xy() );
}

void scent_map::update( const tripoint &center, map &m )
Expand Down
Loading

0 comments on commit 3b8996a

Please sign in to comment.