Skip to content

Commit

Permalink
Lazy allocation for tile memory submaps
Browse files Browse the repository at this point in the history
  • Loading branch information
olanti-p authored and kevingranade committed Jul 8, 2021
1 parent 35d3819 commit 2bf8f19
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 33 deletions.
23 changes: 10 additions & 13 deletions src/map_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include "map_memory.h"
#include "path_info.h"

static const memorized_terrain_tile default_tile{ "", 0, 0 };
static const int default_symbol = 0;
const memorized_terrain_tile mm_submap::default_tile{ "", 0, 0 };
const int mm_submap::default_symbol = 0;

#define MM_SIZE (MAPSIZE * 2)

Expand Down Expand Up @@ -44,16 +44,15 @@ struct reg_coord_pair {
}
};

mm_submap::mm_submap() : empty( true ),
tiles{{ default_tile }}, symbols{{ default_symbol }} {}
mm_submap::mm_submap() {}

mm_region::mm_region() : submaps {{ nullptr }} {}

bool mm_region::is_empty() const
{
for( size_t y = 0; y < MM_REG_SIZE; y++ ) {
for( size_t x = 0; x < MM_REG_SIZE; x++ ) {
if( !submaps[x][y]->empty ) {
if( !submaps[x][y]->is_empty() ) {
return false;
}
}
Expand All @@ -75,39 +74,37 @@ const memorized_terrain_tile &map_memory::get_tile( const tripoint &pos ) const
{
coord_pair p( pos );
const mm_submap &sm = get_submap( p.sm );
return sm.tiles[p.loc.x][p.loc.y];
return sm.tile( p.loc );
}

void map_memory::memorize_tile( const tripoint &pos, const std::string &ter,
const int subtile, const int rotation )
{
coord_pair p( pos );
mm_submap &sm = get_submap( p.sm );
sm.empty = false;
sm.tiles[p.loc.x][p.loc.y] = memorized_terrain_tile{ ter, subtile, rotation };
sm.set_tile( p.loc, memorized_terrain_tile{ ter, subtile, rotation } );
}

int map_memory::get_symbol( const tripoint &pos ) const
{
coord_pair p( pos );
const mm_submap &sm = get_submap( p.sm );
return sm.symbols[p.loc.x][p.loc.y];
return sm.symbol( p.loc );
}

void map_memory::memorize_symbol( const tripoint &pos, const int symbol )
{
coord_pair p( pos );
mm_submap &sm = get_submap( p.sm );
sm.empty = false;
sm.symbols[p.loc.x][p.loc.y] = symbol;
sm.set_symbol( p.loc, symbol );
}

void map_memory::clear_memorized_tile( const tripoint &pos )
{
coord_pair p( pos );
mm_submap &sm = get_submap( p.sm );
sm.symbols[p.loc.x][p.loc.y] = default_symbol;
sm.tiles[p.loc.x][p.loc.y] = default_tile;
sm.set_symbol( p.loc, mm_submap::default_symbol );
sm.set_tile( p.loc, mm_submap::default_tile );
}

bool map_memory::prepare_region( const tripoint &p1, const tripoint &p2 )
Expand Down
67 changes: 58 additions & 9 deletions src/map_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,69 @@ struct memorized_terrain_tile {
std::string tile;
int subtile;
int rotation;

inline bool operator==( const memorized_terrain_tile &rhs ) const {
return ( rotation == rhs.rotation ) && ( subtile == rhs.subtile ) && ( tile == rhs.tile );
}

inline bool operator!=( const memorized_terrain_tile &rhs ) const {
return !( *this == rhs );
}
};

/** Represent a submap-sized chunk of tile memory. */
struct mm_submap {
/** Whether this mm_submap is empty. Empty submaps are skipped during saving. */
bool empty;

memorized_terrain_tile tiles[SEEX][SEEY];
int symbols[SEEX][SEEY];

mm_submap();
public:
static const memorized_terrain_tile default_tile;
static const int default_symbol;

mm_submap();

/** Whether this mm_submap is empty. Empty submaps are skipped during saving. */
bool is_empty() const {
return tiles.empty() && symbols.empty();
}

inline const memorized_terrain_tile &tile( const point &p ) const {
if( tiles.empty() ) {
return default_tile;
} else {
return tiles[p.y * SEEX + p.x];
}
}

inline void set_tile( const point &p, const memorized_terrain_tile &value ) {
if( tiles.empty() ) {
// call 'reserve' first to force allocation of exact size
tiles.reserve( SEEX * SEEY );
tiles.resize( SEEX * SEEY, default_tile );
}
tiles[p.y * SEEX + p.x] = value;
}

inline int symbol( const point &p ) const {
if( symbols.empty() ) {
return default_symbol;
} else {
return symbols[p.y * SEEX + p.x];
}
}

inline void set_symbol( const point &p, int value ) {
if( symbols.empty() ) {
// call 'reserve' first to force allocation of exact size
symbols.reserve( SEEX * SEEY );
symbols.resize( SEEX * SEEY, default_symbol );
}
symbols[p.y * SEEX + p.x] = value;
}

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

void serialize( JsonOut &jsout ) const;
void deserialize( JsonIn &jsin );
private:
std::vector<memorized_terrain_tile> tiles; // holds either 0 or SEEX*SEEY elements
std::vector<int> symbols; // holds either 0 or SEEX*SEEY elements
};

/**
Expand Down
30 changes: 19 additions & 11 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3491,9 +3491,8 @@ struct mm_elem {
memorized_terrain_tile tile;
int symbol;

bool operator==( const mm_elem &rhs ) {
return symbol == rhs.symbol && tile.subtile == rhs.tile.subtile &&
tile.rotation == rhs.tile.rotation && tile.tile == rhs.tile.tile;
bool operator==( const mm_elem &rhs ) const {
return symbol == rhs.symbol && tile == rhs.tile;
}
};

Expand All @@ -3520,7 +3519,8 @@ void mm_submap::serialize( JsonOut &jsout ) const

for( size_t y = 0; y < SEEY; y++ ) {
for( size_t x = 0; x < SEEX; x++ ) {
const mm_elem elem = { tiles[x][y], symbols[x][y] };
point p( x, y );
const mm_elem elem = { tile( p ), symbol( p ) };
if( x == 0 && y == 0 ) {
last = elem;
continue;
Expand Down Expand Up @@ -3563,8 +3563,14 @@ void mm_submap::deserialize( JsonIn &jsin )
}
jsin.end_array();
}
tiles[x][y] = elem.tile;
symbols[x][y] = elem.symbol;
point p( x, y );
// Try to avoid assigning to save up on memory
if( elem.tile != mm_submap::default_tile ) {
set_tile( p, elem.tile );
}
if( elem.symbol != mm_submap::default_symbol ) {
set_symbol( p, elem.symbol );
}
}
}
jsin.end_array();
Expand All @@ -3576,7 +3582,7 @@ void mm_region::serialize( JsonOut &jsout ) const
for( size_t y = 0; y < MM_REG_SIZE; y++ ) {
for( size_t x = 0; x < MM_REG_SIZE; x++ ) {
const shared_ptr_fast<mm_submap> &sm = submaps[x][y];
if( sm->empty ) {
if( sm->is_empty() ) {
jsout.write_null();
} else {
sm->serialize( jsout );
Expand All @@ -3596,7 +3602,6 @@ void mm_region::deserialize( JsonIn &jsin )
if( jsin.test_null() ) {
jsin.skip_null();
} else {
sm->empty = false;
sm->deserialize( jsin );
}
}
Expand Down Expand Up @@ -3644,9 +3649,12 @@ void map_memory::load_legacy( JsonIn &jsin )
if( !sm ) {
sm = allocate_submap( cp.sm );
}
sm->empty = false;
sm->tiles[cp.loc.x][cp.loc.y] = elem.second.tile;
sm->symbols[cp.loc.x][cp.loc.y] = elem.second.symbol;
if( elem.second.tile != mm_submap::default_tile ) {
sm->set_tile( cp.loc, elem.second.tile );
}
if( elem.second.symbol != mm_submap::default_symbol ) {
sm->set_symbol( cp.loc, elem.second.symbol );
}
}
}

Expand Down

0 comments on commit 2bf8f19

Please sign in to comment.