Skip to content

Commit

Permalink
Unlimited map memory (CleverRaven#47253)
Browse files Browse the repository at this point in the history
* Encapsulate map::drawsq() arguments and clarify their meaning

* Split map memory into submap-sized chunks

Note: this naive implementation significantly lowers FPS

* Optimize map memory access

Move memorized submaps that would be
affected during drawing into a 2d array.

* Save/load memorized submaps; migrate old mm file

* Remove leftovers from map memory limit

* Some map memory cleanup

* Don't save empty mm submaps

* Deallocate far-away mm submaps on save; report save failure

* Rework tests for map memory

* Don't re-allocate region if old region contains required submaps

* Remove map_memory.h from avatar.h

* Rename memorized_submap -> mm_submap

* Rename mm_submap::clean -> mm_submap::empty, add comments.

* Improve drawsq_params interface

* Remove map_memory.h from lru_cache.cpp

* Add function for rectangle overlapping

* Save mm_submaps in regions

* Fix save/load not using avatar's global pos, improve docs.

* When saving, compress mm_submaps using RLE

* Simplify map rendering in ascii mode

Collect map::draw code in one place, simplify indexing/bound checks.
Remove the "batch drawing" optimization: it doesn't help with drawing, but harms code clarity. Instead, convert all relevant draw methods to use 'wputch' and rely on caller to position the cursor properly.

* Memorize off-screen tiles in ascii mode

* Fix copypasted code

* Fix tile memory saving code, minor cleanup.

* Add debug logging for tile memory operations

* Fix broken saving for tile memory submaps with z != 0

* Lazy allocation for tile memory submaps

Co-authored-by: olanti-p <olanti-p@yandex.ru>
  • Loading branch information
2 people authored and esotericist committed Sep 4, 2021
1 parent bd09f28 commit 25a94d4
Show file tree
Hide file tree
Showing 25 changed files with 1,170 additions and 405 deletions.
3 changes: 1 addition & 2 deletions src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1114,8 +1114,7 @@ cata::optional<tripoint> choose_adjacent_highlight( const std::string &message,
if( !valid.empty() ) {
hilite_cb = make_shared_fast<game::draw_callback_t>( [&]() {
for( const tripoint &pos : valid ) {
here.drawsq( g->w_terrain, player_character, pos,
true, true, player_character.pos() + player_character.view_offset );
here.drawsq( g->w_terrain, pos, drawsq_params().highlight( true ) );
}
} );
g->add_draw_callback( hilite_cb );
Expand Down
9 changes: 6 additions & 3 deletions src/animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ void draw_bullet_curses( map &m, const tripoint &t, const char bullet, const tri

shared_ptr_fast<game::draw_callback_t> bullet_cb = make_shared_fast<game::draw_callback_t>( [&]() {
if( p != nullptr && p->z == vp.z ) {
m.drawsq( g->w_terrain, player_character, *p, false, true, vp );
m.drawsq( g->w_terrain, *p, drawsq_params().center( vp ) );
}
mvwputch( g->w_terrain, t.xy() - vp.xy() + point( POSX, POSY ), c_red, bullet );
} );
Expand Down Expand Up @@ -628,7 +628,10 @@ namespace
void draw_line_curses( game &g, const tripoint &center, const std::vector<tripoint> &ret,
bool noreveal )
{

avatar &player_character = get_avatar();
map &here = get_map();
drawsq_params params = drawsq_params().highlight( true ).center( center );
for( const tripoint &p : ret ) {
const Creature *critter = g.critter_at( p, true );

Expand All @@ -645,7 +648,7 @@ void draw_line_curses( game &g, const tripoint &center, const std::vector<tripoi
mvwputch( w, point( k, j ), col, sym );
} else {
// This function reveals tile at p and writes it to the player's memory
get_map().drawsq( g.w_terrain, player_character, p, true, true, center );
here.drawsq( g.w_terrain, p, params );
}
}
}
Expand Down Expand Up @@ -685,7 +688,7 @@ void draw_line_curses( game &g, const std::vector<tripoint> &points )
avatar &player_character = get_avatar();
map &here = get_map();
for( const tripoint &p : points ) {
here.drawsq( g.w_terrain, player_character, p, true, true );
here.drawsq( g.w_terrain, p, drawsq_params().highlight( true ) );
}

const tripoint p = points.empty() ? tripoint {POSX, POSY, 0} :
Expand Down
46 changes: 21 additions & 25 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "kill_tracker.h"
#include "make_static.h"
#include "map.h"
#include "map_memory.h"
#include "martialarts.h"
#include "messages.h"
#include "mission.h"
Expand Down Expand Up @@ -117,12 +118,17 @@ static const json_character_flag json_flag_ALARMCLOCK( "ALARMCLOCK" );

avatar::avatar()
{
player_map_memory = std::make_unique<map_memory>();
show_map_memory = true;
active_mission = nullptr;
grab_type = object_type::NONE;
calorie_diary.push_front( daily_calories{} );
}

avatar::~avatar() = default;
avatar::avatar( avatar && ) = default;
avatar &avatar::operator=( avatar && ) = default;

void avatar::toggle_map_memory()
{
show_map_memory = !show_map_memory;
Expand All @@ -133,55 +139,45 @@ bool avatar::should_show_map_memory()
return show_map_memory;
}

void avatar::serialize_map_memory( JsonOut &jsout ) const
bool avatar::save_map_memory()
{
player_map_memory.store( jsout );
return player_map_memory->save( get_map().getabs( pos() ) );
}

void avatar::deserialize_map_memory( JsonIn &jsin )
void avatar::load_map_memory()
{
player_map_memory.load( jsin );
player_map_memory->load( get_map().getabs( pos() ) );
}

memorized_terrain_tile avatar::get_memorized_tile( const tripoint &pos ) const
void avatar::prepare_map_memory_region( const tripoint &p1, const tripoint &p2 )
{
return player_map_memory.get_tile( pos );
player_map_memory->prepare_region( p1, p2 );
}

const memorized_terrain_tile &avatar::get_memorized_tile( const tripoint &pos ) const
{
return player_map_memory->get_tile( pos );
}

void avatar::memorize_tile( const tripoint &pos, const std::string &ter, const int subtile,
const int rotation )
{
player_map_memory.memorize_tile( max_memorized_tiles(), pos, ter, subtile, rotation );
player_map_memory->memorize_tile( pos, ter, subtile, rotation );
}

void avatar::memorize_symbol( const tripoint &pos, const int symbol )
{
player_map_memory.memorize_symbol( max_memorized_tiles(), pos, symbol );
player_map_memory->memorize_symbol( pos, symbol );
}

int avatar::get_memorized_symbol( const tripoint &p ) const
{
return player_map_memory.get_symbol( p );
}

size_t avatar::max_memorized_tiles() const
{
// Only check traits once a turn since this is called a huge number of times.
if( current_map_memory_turn != calendar::turn ) {
current_map_memory_turn = calendar::turn;
float map_memory_capacity_multiplier =
mutation_value( "map_memory_capacity_multiplier" );
if( has_active_bionic( bio_memory ) ) {
map_memory_capacity_multiplier = 50;
}
current_map_memory_capacity = 2 * SEEX * 2 * SEEY * 100 * map_memory_capacity_multiplier;
}
return current_map_memory_capacity;
return player_map_memory->get_symbol( p );
}

void avatar::clear_memorized_tile( const tripoint &pos )
{
player_map_memory.clear_memorized_tile( pos );
player_map_memory->clear_memorized_tile( pos );
}

std::vector<mission *> avatar::get_active_missions() const
Expand Down
22 changes: 12 additions & 10 deletions src/avatar.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "game_constants.h"
#include "json.h"
#include "magic_teleporter_list.h"
#include "map_memory.h"
#include "memory_fast.h"
#include "player.h"
#include "point.h"
Expand All @@ -42,6 +41,8 @@ namespace catacurses
class window;
} // namespace catacurses
enum class character_type : int;
class map_memory;
struct memorized_terrain_tile;

namespace debug_menu
{
Expand Down Expand Up @@ -70,13 +71,18 @@ class avatar : public player
{
public:
avatar();
avatar( const avatar & ) = delete;
avatar( avatar && );
~avatar();
avatar &operator=( const avatar & ) = delete;
avatar &operator=( avatar && );

void store( JsonOut &json ) const;
void load( const JsonObject &data );
void serialize( JsonOut &json ) const override;
void deserialize( JsonIn &jsin ) override;
void serialize_map_memory( JsonOut &jsout ) const;
void deserialize_map_memory( JsonIn &jsin );
bool save_map_memory();
void load_map_memory();

// newcharacter.cpp
bool create( character_type type, const std::string &tempname = "" );
Expand All @@ -97,17 +103,16 @@ class avatar : public player

void toggle_map_memory();
bool should_show_map_memory();
void prepare_map_memory_region( const tripoint &p1, const tripoint &p2 );
/** Memorizes a given tile in tiles mode; finalize_tile_memory needs to be called after it */
void memorize_tile( const tripoint &pos, const std::string &ter, int subtile,
int rotation );
/** Returns last stored map tile in given location in tiles mode */
memorized_terrain_tile get_memorized_tile( const tripoint &p ) const;
const memorized_terrain_tile &get_memorized_tile( const tripoint &p ) const;
/** Memorizes a given tile in curses mode; finalize_terrain_memory_curses needs to be called after it */
void memorize_symbol( const tripoint &pos, int symbol );
/** Returns last stored map tile in given location in curses mode */
int get_memorized_symbol( const tripoint &p ) const;
/** Returns the amount of tiles survivor can remember. */
size_t max_memorized_tiles() const;
void clear_memorized_tile( const tripoint &pos );

nc_color basic_symbol_color() const override;
Expand Down Expand Up @@ -290,11 +295,8 @@ class avatar : public player
std::string total_daily_calories_string() const;

private:
map_memory player_map_memory;
std::unique_ptr<map_memory> player_map_memory;
bool show_map_memory;
/** Used in max_memorized_tiles to cache memory capacity. **/
mutable time_point current_map_memory_turn = calendar::before_time_starts;
mutable size_t current_map_memory_capacity = 0;

friend class debug_menu::mission_debug;
/**
Expand Down
16 changes: 16 additions & 0 deletions src/cata_tiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,22 @@ void cata_tiles::draw( const point &dest, const tripoint &center, int width, int

const level_cache &ch = here.access_cache( center.z );

// Map memory should be at least the size of the view range
// so that new tiles can be memorized, and at least the size of the display
// since at farthest zoom displayed area may be bigger than view range.
const point min_mm_reg = point(
std::min( o.x, min_visible_x ),
std::min( o.y, min_visible_y )
);
const point max_mm_reg = point(
std::max( s.x + o.x, max_visible_x ),
std::max( s.y + o.y, max_visible_y )
);
you.prepare_map_memory_region(
here.getabs( tripoint( min_mm_reg, center.z ) ),
here.getabs( tripoint( max_mm_reg, center.z ) )
);

//set up a default tile for the edges outside the render area
visibility_type offscreen_type = visibility_type::DARK;
if( cache.u_is_boomered ) {
Expand Down
3 changes: 1 addition & 2 deletions src/construction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,7 @@ void place_construction( const construction_group_str_id &group )
shared_ptr_fast<game::draw_callback_t> draw_valid = make_shared_fast<game::draw_callback_t>( [&]() {
map &here = get_map();
for( auto &elem : valid ) {
here.drawsq( g->w_terrain, player_character, elem.first, true, false,
player_character.pos() + player_character.view_offset );
here.drawsq( g->w_terrain, elem.first, drawsq_params().highlight( true ).show_items( true ) );
}
} );
g->add_draw_callback( draw_valid );
Expand Down
10 changes: 10 additions & 0 deletions src/coordinate_conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,13 @@ tripoint omt_to_seg_copy( const tripoint &p )
{
return tripoint( divide( p.x, SEG_SIZE ), divide( p.y, SEG_SIZE ), p.z );
}

point sm_to_mmr_remain( int &x, int &y )
{
return point( divide( x, MM_REG_SIZE, x ), divide( y, MM_REG_SIZE, y ) );
}

tripoint mmr_to_sm_copy( const tripoint &p )
{
return tripoint( p.x * MM_REG_SIZE, p.y * MM_REG_SIZE, p.z );
}
6 changes: 6 additions & 0 deletions src/coordinate_conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* For documentation on coordinate systems in general see
* doc/POINTS_COORDINATES.md.
*
* This file provides static translation functions, named like this:
@code
static point <from>_to_<to>_copy(int x, int y);
Expand Down Expand Up @@ -165,5 +166,10 @@ inline point ms_to_omt_remain( point &p )
}
// overmap terrain to map segment.
tripoint omt_to_seg_copy( const tripoint &p );
// Submap to memory map region.
point sm_to_mmr_remain( int &x, int &y );
// Memory map region to submap.
// Note: this produces sm coords of top-left corner of the region.
tripoint mmr_to_sm_copy( const tripoint &p );

#endif // CATA_SRC_COORDINATE_CONVERSIONS_H
14 changes: 14 additions & 0 deletions src/cuboid_rectangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ struct half_open_rectangle : rectangle<Point> {
return Traits::x( p ) >= Traits::x( p_min ) && Traits::x( p ) < Traits::x( p_max ) &&
Traits::y( p ) >= Traits::y( p_min ) && Traits::y( p ) < Traits::y( p_max );
}
constexpr bool overlaps( const rectangle<Point> &r ) const {
using Traits = point_traits<Point>;
return !( Traits::x( r.p_min ) >= Traits::x( p_max ) ||
Traits::y( r.p_min ) >= Traits::y( p_max ) ||
Traits::x( p_min ) >= Traits::x( r.p_max ) ||
Traits::y( p_min ) >= Traits::y( r.p_max ) );
}
};

template<typename Point, decltype( std::declval<rectangle<Point>>(), int() ) = 0>
Expand All @@ -48,6 +55,13 @@ struct inclusive_rectangle : rectangle<Point> {
return Traits::x( p ) >= Traits::x( p_min ) && Traits::x( p ) <= Traits::x( p_max ) &&
Traits::y( p ) >= Traits::y( p_min ) && Traits::y( p ) <= Traits::y( p_max );
}
constexpr bool overlaps( const rectangle<Point> &r ) const {
using Traits = point_traits<Point>;
return !( Traits::x( r.p_min ) > Traits::x( p_max ) ||
Traits::y( r.p_min ) > Traits::y( p_max ) ||
Traits::x( p_min ) > Traits::x( r.p_max ) ||
Traits::y( p_min ) > Traits::y( r.p_max ) );
}
};

// Clamp p to the rectangle r.
Expand Down
3 changes: 3 additions & 0 deletions src/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,9 @@ static std::ostream &operator<<( std::ostream &out, DebugClass cl )
if( cl & D_SDL ) {
out << "SDL ";
}
if( cl & D_MMAP ) {
out << "MMAP ";
}
}
return out;
}
Expand Down
2 changes: 2 additions & 0 deletions src/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ enum DebugClass {
D_NPC = 1 << 5,
/** SDL & tiles & anything graphical */
D_SDL = 1 << 6,
/** Related to tile memory (map_memory.cpp) */
D_MMAP = 1 << 7,

DC_ALL = ( 1 << 30 ) - 1
};
Expand Down
Loading

0 comments on commit 25a94d4

Please sign in to comment.