Skip to content

Commit

Permalink
Merge pull request #73774 from Procyonae/Backport70423And70685
Browse files Browse the repository at this point in the history
Backport #70423 and #70685
  • Loading branch information
kevingranade authored May 14, 2024
2 parents e73175f + 9c0d221 commit 42bd923
Show file tree
Hide file tree
Showing 12 changed files with 492 additions and 176 deletions.
51 changes: 51 additions & 0 deletions src/cata_utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,57 @@ std::map<K, V> map_without_keys( const std::map<K, V> &original, const std::vect
return filtered;
}

template<typename Map, typename Set>
bool map_equal_ignoring_keys( const Map &lhs, const Map &rhs, const Set &ignore_keys )
{
// Since map and set are sorted, we can do this as a single pass with only conditional checks into remove_keys
if( ignore_keys.empty() ) {
return lhs == rhs;
}

auto lbegin = lhs.begin();
auto lend = lhs.end();
auto rbegin = rhs.begin();
auto rend = rhs.end();

for( ; lbegin != lend && rbegin != rend; ++lbegin, ++rbegin ) {
// Sanity check keys
if( lbegin->first != rbegin->first ) {
while( lbegin != lend && ignore_keys.count( lbegin->first ) == 1 ) {
++lbegin;
}
if( lbegin == lend ) {
break;
}
if( rbegin->first != lbegin->first ) {
while( rbegin != rend && ignore_keys.count( rbegin->first ) == 1 ) {
++rbegin;
}
if( rbegin == rend ) {
break;
}
}
// If we've skipped ignored keys and the keys still don't match,
// then the maps are unequal.
if( lbegin->first != rbegin->first ) {
return false;
}
}
if( lbegin->second != rbegin->second && ignore_keys.count( lbegin->first ) != 1 ) {
return false;
}
// Either the values were equal, or the key was ignored.
}
// At least one map ran out of keys. The other may still have ignored keys in it.
while( lbegin != lend && ignore_keys.count( lbegin->first ) ) {
++lbegin;
}
while( rbegin != rend && ignore_keys.count( rbegin->first ) ) {
++rbegin;
}
return lbegin == lend && rbegin == rend;
}

int modulo( int v, int m );

/** Add elements from one set to another */
Expand Down
26 changes: 18 additions & 8 deletions src/catacharset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,21 +415,31 @@ std::u32string utf8_to_utf32( const std::string_view str )
std::vector<std::string> utf8_display_split( const std::string &s )
{
std::vector<std::string> result;
std::string current_glyph;
std::vector<std::string_view> parts;
utf8_display_split_into( s, parts );
result.reserve( parts.size() );
for( std::string_view part : parts ) {
result.emplace_back( part );
}
return result;
}

void utf8_display_split_into( const std::string &s, std::vector<std::string_view> &result )
{
const char *pos = s.c_str();
const char *glyph_begin = pos;
const char *glyph_end = pos;
int len = s.length();
while( len > 0 ) {
const char *old_pos = pos;
const uint32_t ch = UTF8_getch( &pos, &len );
const int width = mk_wcwidth( ch );
if( width > 0 && !current_glyph.empty() ) {
result.push_back( current_glyph );
current_glyph.clear();
if( width > 0 && glyph_begin != glyph_end ) {
result.emplace_back( glyph_begin, std::distance( glyph_begin, glyph_end ) );
glyph_begin = glyph_end;
}
current_glyph += std::string( old_pos, pos );
glyph_end = pos;
}
result.push_back( current_glyph );
return result;
result.emplace_back( glyph_begin, std::distance( glyph_begin, glyph_end ) );
}

int center_text_pos( const char *text, int start_pos, int end_pos )
Expand Down
1 change: 1 addition & 0 deletions src/catacharset.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ std::u32string utf8_to_utf32( std::string_view str );
// Split the given string into displayed characters. Each element of the returned vector
// contains one 'regular' codepoint and all subsequent combining characters.
std::vector<std::string> utf8_display_split( const std::string & );
void utf8_display_split_into( const std::string &, std::vector<std::string_view> & );

/**
* UTF8-Wrapper over std::string.
Expand Down
36 changes: 18 additions & 18 deletions src/field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ field_entry *field::find_field( const field_type_id &field_type_to_find, const b
if( !_displayed_field_type ) {
return nullptr;
}
const auto it = _field_type_list.find( field_type_to_find );
if( it != _field_type_list.end() && ( !alive_only || it->second.is_field_alive() ) ) {
const auto it = _field_type_list->find( field_type_to_find );
if( it != _field_type_list->end() && ( !alive_only || it->second.is_field_alive() ) ) {
return &it->second;
}
return nullptr;
Expand All @@ -137,8 +137,8 @@ const field_entry *field::find_field( const field_type_id &field_type_to_find,
if( !_displayed_field_type ) {
return nullptr;
}
const auto it = _field_type_list.find( field_type_to_find );
if( it != _field_type_list.end() && ( !alive_only || it->second.is_field_alive() ) ) {
const auto it = _field_type_list->find( field_type_to_find );
if( it != _field_type_list->end() && ( !alive_only || it->second.is_field_alive() ) ) {
return &it->second;
}
return nullptr;
Expand All @@ -159,8 +159,8 @@ bool field::add_field( const field_type_id &field_type_to_add, const int new_int
if( !field_type_to_add ) {
return false;
}
auto it = _field_type_list.find( field_type_to_add );
if( it != _field_type_list.end() ) {
auto it = _field_type_list->find( field_type_to_add );
if( it != _field_type_list->end() ) {
//Already exists, but lets update it. This is tentative.
int prev_intensity = it->second.get_field_intensity();
if( !it->second.is_field_alive() ) {
Expand All @@ -180,8 +180,8 @@ bool field::add_field( const field_type_id &field_type_to_add, const int new_int

bool field::remove_field( const field_type_id &field_to_remove )
{
const auto it = _field_type_list.find( field_to_remove );
if( it == _field_type_list.end() ) {
const auto it = _field_type_list->find( field_to_remove );
if( it == _field_type_list->end() ) {
return false;
}
remove_field( it );
Expand All @@ -190,9 +190,9 @@ bool field::remove_field( const field_type_id &field_to_remove )

void field::remove_field( std::map<field_type_id, field_entry>::iterator const it )
{
_field_type_list.erase( it );
_field_type_list->erase( it );
_displayed_field_type = fd_null;
for( auto &fld : _field_type_list ) {
for( auto &fld : *_field_type_list ) {
if( !_displayed_field_type || fld.first.obj().priority >= _displayed_field_type.obj().priority ) {
_displayed_field_type = fld.first;
}
Expand All @@ -201,7 +201,7 @@ void field::remove_field( std::map<field_type_id, field_entry>::iterator const i

void field::clear()
{
_field_type_list.clear();
_field_type_list->clear();
_displayed_field_type = fd_null;
}

Expand All @@ -211,27 +211,27 @@ Returns the number of fields existing on the current tile.
*/
unsigned int field::field_count() const
{
return _field_type_list.size();
return _field_type_list->size();
}

std::map<field_type_id, field_entry>::iterator field::begin()
{
return _field_type_list.begin();
return _field_type_list->begin();
}

std::map<field_type_id, field_entry>::const_iterator field::begin() const
{
return _field_type_list.begin();
return _field_type_list->begin();
}

std::map<field_type_id, field_entry>::iterator field::end()
{
return _field_type_list.end();
return _field_type_list->end();
}

std::map<field_type_id, field_entry>::const_iterator field::end() const
{
return _field_type_list.end();
return _field_type_list->end();
}

/*
Expand All @@ -250,14 +250,14 @@ description_affix field::displayed_description_affix() const

int field::displayed_intensity() const
{
auto it = _field_type_list.find( _displayed_field_type );
auto it = _field_type_list->find( _displayed_field_type );
return it->second.get_field_intensity();
}

int field::total_move_cost() const
{
int current_cost = 0;
for( const auto &fld : _field_type_list ) {
for( const auto &fld : *_field_type_list ) {
current_cost += fld.second.get_intensity_level().move_cost;
}
return current_cost;
Expand Down
3 changes: 2 additions & 1 deletion src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <vector>

#include "calendar.h"
#include "cata_lazy.h"
#include "color.h"
#include "enums.h"
#include "field_type.h"
Expand Down Expand Up @@ -180,7 +181,7 @@ class field

private:
// A pointer lookup table of all field effects on the current tile.
std::map<field_type_id, field_entry> _field_type_list;
lazy<std::map<field_type_id, field_entry>> _field_type_list;
//_displayed_field_type currently is equal to the last field added to the square. You can modify this behavior in the class functions if you wish.
field_type_id _displayed_field_type;
};
Expand Down
31 changes: 21 additions & 10 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ item::item( const itype_id &id, time_point turn, solitary_tag tag )

safe_reference<item> item::get_safe_reference()
{
return anchor.reference_to( this );
return anchor->reference_to( this );
}

static const item *get_most_rotten_component( const item &craft )
Expand Down Expand Up @@ -587,10 +587,10 @@ item::item( const recipe *rec, int qty, item &component )
}

item::item( const item & ) = default;
item::item( item && ) noexcept( map_is_noexcept ) = default;
item::item( item && ) noexcept = default;
item::~item() = default;
item &item::operator=( const item & ) = default;
item &item::operator=( item && ) noexcept( list_is_noexcept ) = default;
item &item::operator=( item && ) noexcept = default;

item item::make_corpse( const mtype_id &mt, time_point turn, const std::string &name,
const int upgrade_time )
Expand Down Expand Up @@ -1436,7 +1436,8 @@ bool item::stacks_with( const item &rhs, bool check_components, bool combine_liq
itype_variant().id != rhs.itype_variant().id ) ) {
return false;
}
if( ammo_remaining() != 0 && rhs.ammo_remaining() != 0 && is_money() ) {
const std::set<ammotype> ammo = ammo_types();
if( is_money( ammo ) && ammo_remaining( ammo ) != 0 && rhs.ammo_remaining() != 0 ) {
// Dealing with nonempty cash cards
// TODO: Fix cash cards not showing total value. Until that is fixed do not stack cash cards.
// When that is fixed just change this to true.
Expand Down Expand Up @@ -1488,11 +1489,11 @@ bool item::stacks_with( const item &rhs, bool check_components, bool combine_liq
}
// Guns that differ only by dirt/shot_counter can still stack,
// but other item_vars such as label/note will prevent stacking
const std::vector<std::string> ignore_keys = { "dirt", "shot_counter", "spawn_location_omt" };
if( map_without_keys( item_vars, ignore_keys ) != map_without_keys( rhs.item_vars, ignore_keys ) ) {
static const std::set<std::string> ignore_keys = { "dirt", "shot_counter", "spawn_location_omt" };
if( !map_equal_ignoring_keys( item_vars, rhs.item_vars, ignore_keys ) ) {
return false;
}
const std::string omt_loc_var = "spawn_location_omt";
static const std::string omt_loc_var = "spawn_location_omt";
const bool this_has_location = has_var( omt_loc_var );
const bool that_has_location = has_var( omt_loc_var );
if( this_has_location != that_has_location ) {
Expand Down Expand Up @@ -8601,7 +8602,12 @@ bool item::ready_to_revive( map &here, const tripoint &pos ) const

bool item::is_money() const
{
return ammo_types().count( ammo_money );
return is_money( ammo_types() );
}

bool item::is_money( const std::set<ammotype> &ammo ) const
{
return ammo.count( ammo_money );
}

bool item::is_cash_card() const
Expand Down Expand Up @@ -10670,7 +10676,8 @@ int item::shots_remaining( const Character *carrier ) const
return ret;
}

int item::ammo_remaining( const Character *carrier, const bool include_linked ) const
int item::ammo_remaining( const std::set<ammotype> &ammo, const Character *carrier,
const bool include_linked ) const
{
int ret = 0;

Expand All @@ -10692,7 +10699,6 @@ int item::ammo_remaining( const Character *carrier, const bool include_linked )
}
}

std::set<ammotype> ammo = ammo_types();
// Non ammo using item that uses charges
if( ammo.empty() ) {
ret += charges;
Expand Down Expand Up @@ -10729,6 +10735,11 @@ int item::ammo_remaining( const Character *carrier, const bool include_linked )

return ret;
}
int item::ammo_remaining( const Character *carrier, const bool include_linked ) const
{
std::set<ammotype> ammo = ammo_types();
return ammo_remaining( ammo, carrier, include_linked );
}

int item::ammo_remaining( const bool include_linked ) const
{
Expand Down
25 changes: 17 additions & 8 deletions src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <vector>

#include "calendar.h"
#include "cata_lazy.h"
#include "cata_utility.h"
#include "compatibility.h"
#include "enums.h"
Expand Down Expand Up @@ -192,9 +193,9 @@ class item : public visitable

item();

item( item && ) noexcept( map_is_noexcept );
item( item && ) noexcept;
item( const item & );
item &operator=( item && ) noexcept( list_is_noexcept );
item &operator=( item && ) noexcept;
item &operator=( const item & );

explicit item( const itype_id &id, time_point turn = calendar::turn, int qty = -1 );
Expand Down Expand Up @@ -352,6 +353,10 @@ class item : public visitable
bool ready_to_revive( map &here, const tripoint &pos ) const;

bool is_money() const;
private:
bool is_money( const std::set<ammotype> &ammo ) const;
public:

bool is_cash_card() const;
bool is_software() const;
bool is_software_storage() const;
Expand Down Expand Up @@ -2375,6 +2380,10 @@ class item : public visitable
*/
int ammo_remaining( const Character *carrier = nullptr, bool include_linked = false ) const;
int ammo_remaining( bool include_linked ) const;
private:
int ammo_remaining( const std::set<ammotype> &ammo, const Character *carrier = nullptr,
bool include_linked = false ) const;
public:

/**
* ammo capacity for a specific ammo
Expand Down Expand Up @@ -2995,21 +3004,21 @@ class item : public visitable
const itype *type;
item_components components;
/** What faults (if any) currently apply to this item */
std::set<fault_id> faults;
cata::heap<std::set<fault_id>> faults;

private:
item_contents contents;
/** `true` if item has any of the flags that require processing in item::process_internal.
* This flag is reset to `true` if item tags are changed.
*/
bool requires_tags_processing = true;
FlagsSetType item_tags; // generic item specific flags
FlagsSetType inherited_tags_cache;
safe_reference_anchor anchor;
std::map<std::string, std::string> item_vars;
cata::heap<FlagsSetType> item_tags; // generic item specific flags
cata::heap<FlagsSetType> inherited_tags_cache;
lazy<safe_reference_anchor> anchor;
cata::heap<std::map<std::string, std::string>> item_vars;
const mtype *corpse = nullptr;
std::string corpse_name; // Name of the late lamented
std::set<matec_id> techniques; // item specific techniques
cata::heap<std::set<matec_id>> techniques; // item specific techniques

// Select a random variant from the possibilities
// Intended to be called when no explicit variant is set
Expand Down
Loading

0 comments on commit 42bd923

Please sign in to comment.