From c71b9d8ba1427b8f16a8cd996fce5c5d8f671d8f Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Fri, 4 Nov 2022 12:26:53 +0900 Subject: [PATCH 01/11] Nonrigid nested container can't fill charges item --- src/character_attire.cpp | 140 ++++++++++++++++++++++++++++++--------- src/character_attire.h | 7 ++ 2 files changed, 115 insertions(+), 32 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 47a98225f7208..6ebbcb7b005ce 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2230,6 +2230,61 @@ void outfit::pickup_stash( const item &newit, int &remaining_charges, bool ignor } } +std::vector> get_child_pocket_with_parent( + const item_pocket *pocket, pocket_with_parent_data *parent ); + +std::vector> get_child_pocket_with_parent( + const item_pocket *pocket, pocket_with_parent_data *parent ) +{ + std::vector> ret; + if( pocket != nullptr ) { + std::unique_ptr pocket_data = std::make_unique(); + pocket_data->pocket = const_cast( pocket ); + if( parent != nullptr ) { + pocket_data->parent_data = parent; + pocket_data->nest_level = parent->nest_level + 1; + } + for( const item *contained : pocket->all_items_top() ) { + for( const item_pocket *pocket_nest : contained->get_all_contained_pockets() ) { + std::vector> child = get_child_pocket_with_parent( + pocket_nest, &*pocket_data ); + for( std::unique_ptr &pock_d : child ) { + ret.emplace_back( std::move( pock_d ) ); + } + } + } + ret.emplace_back( std::move( pocket_data ) ); + } + return ret; +} + +std::vector> outfit::get_all_pocket_with_parent( + Character &guy ) +{ + std::vector> ret; + std::vector pockets; + + // Collect all pockets + std::list items; + item_location carried_item = guy.get_wielded_item(); + if( carried_item != item_location::nowhere ) { + items.emplace_back( &*carried_item ); + } + for( item &i : guy.worn.worn ) { + items.emplace_back( &i ); + } + for( item *i : items ) { + for( const item_pocket *pocket : i->get_all_contained_pockets() ) { + std::vector> child = get_child_pocket_with_parent( pocket, + nullptr ); + for( std::unique_ptr &pock_d : child ) { + ret.emplace_back( std::move( pock_d ) ); + } + } + } + return ret; +} + void outfit::add_stash( Character &guy, const item &newit, int &remaining_charges, bool ignore_pkt_settings ) { @@ -2245,52 +2300,73 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge // Crawl Next : worn items pickup_stash( newit, remaining_charges, ignore_pkt_settings ); } else { - item_pocket *found_pocket; - std::vector pockets; + + //item copy for test can contain item temp_it = item( newit ); temp_it.charges = 1; // Collect all pockets - std::list items; - item_location carried_item = guy.get_wielded_item(); - if( carried_item != item_location::nowhere ) { - items.emplace_back( &*carried_item ); - } - for( item &i : worn ) { - items.emplace_back( &i ); - } - for( item *i : items ) { - for( const item_pocket *pocket : i->get_all_contained_pockets() ) { - if( pocket->can_contain( temp_it ).success() ) { - // Top-level( wielded, worn ) pockets may be stored - found_pocket = const_cast( pocket ); - pockets.emplace_back( found_pocket ); - } - for( const item *contained : pocket->all_items_ptr( item_pocket::pocket_type::CONTAINER ) ) { - for( const item_pocket *pocket_nest : contained->get_all_contained_pockets() ) { - if( pocket_nest->can_contain( temp_it ).success() && pocket_nest->rigid() ) { - // Nested pocket with rigid() can only be stored - found_pocket = const_cast( pocket_nest ); - pockets.emplace_back( found_pocket ); - } - } - } + std::vector> pockets_with_parent; + std::vector> pockets_with_parent_working; + pockets_with_parent_working = get_all_pocket_with_parent( guy ); + + for( std::unique_ptr &pocket_data_ptr : pockets_with_parent_working ) { + item_pocket *pocket = pocket_data_ptr->pocket; + if( pocket->can_contain( temp_it ).success() ) { + pockets_with_parent.emplace_back( std::move( pocket_data_ptr ) ); } } - // Sort by item_pocket::better_pocket - std::sort( pockets.begin(), pockets.end(), [newit, temp_it]( item_pocket * lhs, - item_pocket * rhs ) { - return rhs->better_pocket( *lhs, newit, false ); + std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, + temp_it]( std::unique_ptr &lhs, + std::unique_ptr &rhs ) { + item_pocket &lpp = *lhs->pocket; + item_pocket *lpd = lhs->pocket; + item_pocket *rpd = rhs->pocket; + + if( lpd->settings.priority() != rpd->settings.priority() ) { + return lpd->settings.priority() > rpd->settings.priority(); + } + + if( lpd->rigid() != rpd->rigid() ) { + return rpd->rigid(); + } + + if( lhs->nest_level != rhs->nest_level ) { + return lhs->nest_level < rhs->nest_level; + } + + return rpd->better_pocket( lpp, temp_it, false ); } ); int amount = remaining_charges; int num_contained = 0; - for( item_pocket *&pocket : pockets ) { + for( std::unique_ptr &pocket_data_ptr : pockets_with_parent ) { if( amount <= num_contained || remaining_charges <= 0 ) { break; } - const int filled_count = pocket->fill_with( newit, guy, remaining_charges, false, false ); + int filled_count = 0; + item_pocket *pocke = pocket_data_ptr->pocket; + if( pocke == nullptr ) { + continue; + } + if( pocke->rigid() ) { + //Rigid container allow loading under no conditions because do not depend on the capacity of the parent's pocket. + filled_count = pocke->fill_with( newit, guy, remaining_charges, false, false ); + } else { + pocket_with_parent_data *parent_data = pocket_data_ptr->parent_data; + int remain_vol = std::min( pocke->charges_per_remaining_volume( temp_it ), 65535 ); + int remain_weight = std::min( pocke->charges_per_remaining_weight( temp_it ), 65535 ); + while( parent_data != nullptr ) { + item_pocket *parent_pocke; + parent_pocke = parent_data->pocket; + remain_vol = std::min( parent_pocke->charges_per_remaining_volume( temp_it ), remain_vol ); + remain_weight = std::min( parent_pocke->charges_per_remaining_weight( temp_it ), remain_weight ); + parent_data = parent_data->parent_data; + } + int charges = std::min( { remain_vol, remain_weight, remaining_charges } ) ; + filled_count = pocke->fill_with( newit, guy, charges, false, false ); + } num_contained += filled_count; remaining_charges -= filled_count; } diff --git a/src/character_attire.h b/src/character_attire.h index 995ac105fcc8c..82d98a2ae86e0 100644 --- a/src/character_attire.h +++ b/src/character_attire.h @@ -57,6 +57,12 @@ struct dispose_option { std::function action; }; +struct pocket_with_parent_data { + item_pocket *pocket = nullptr; + pocket_with_parent_data *parent_data = nullptr; + int nest_level = 0; +}; + class outfit { private: @@ -207,6 +213,7 @@ class outfit // used for npc generation void set_fitted(); std::vector available_pockets() const; + std::vector> get_all_pocket_with_parent( Character &guy ); void write_text_memorial( std::ostream &file, const std::string &indent, const char *eol ) const; std::string get_armor_display( bodypart_id bp, unsigned int truncate = 0 ) const; void activate_combat_items( npc &guy ); From ed568cd9fa45a99882cc2e190db6abc3511e5f5a Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Fri, 4 Nov 2022 13:16:31 +0900 Subject: [PATCH 02/11] Add const to some variables --- src/character_attire.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 6ebbcb7b005ce..8b3aa97697068 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2320,9 +2320,9 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, temp_it]( std::unique_ptr &lhs, std::unique_ptr &rhs ) { - item_pocket &lpp = *lhs->pocket; - item_pocket *lpd = lhs->pocket; - item_pocket *rpd = rhs->pocket; + const item_pocket &lpp = *lhs->pocket; + const item_pocket *lpd = lhs->pocket; + const item_pocket *rpd = rhs->pocket; if( lpd->settings.priority() != rpd->settings.priority() ) { return lpd->settings.priority() > rpd->settings.priority(); @@ -2339,7 +2339,7 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge return rpd->better_pocket( lpp, temp_it, false ); } ); - int amount = remaining_charges; + const int amount = remaining_charges; int num_contained = 0; for( std::unique_ptr &pocket_data_ptr : pockets_with_parent ) { if( amount <= num_contained || remaining_charges <= 0 ) { From 12245df48d461f0afdbab59a6bb83c815735cbe5 Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Fri, 4 Nov 2022 21:45:04 +0900 Subject: [PATCH 03/11] Adopt item_location style Use item_location instead of unique structure and unique_ptr --- src/character_attire.cpp | 98 +++++++++++++++++++++------------------- src/character_attire.h | 9 +--- 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 8b3aa97697068..dbe7ac91c523f 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2230,39 +2230,43 @@ void outfit::pickup_stash( const item &newit, int &remaining_charges, bool ignor } } -std::vector> get_child_pocket_with_parent( - const item_pocket *pocket, pocket_with_parent_data *parent ); +static std::vector> + get_child_pocket_with_parent( + const item_pocket *pocket, item_location parent, item_location it, int nest_level ); -std::vector> get_child_pocket_with_parent( - const item_pocket *pocket, pocket_with_parent_data *parent ) +std::vector> get_child_pocket_with_parent( + const item_pocket *pocket, item_location parent, item_location it, int nest_level ) { - std::vector> ret; + std::vector> ret; if( pocket != nullptr ) { - std::unique_ptr pocket_data = std::make_unique(); - pocket_data->pocket = const_cast( pocket ); - if( parent != nullptr ) { - pocket_data->parent_data = parent; - pocket_data->nest_level = parent->nest_level + 1; + std::tuple pocket_data = { pocket, item_location(), nest_level + 1 }; + item_location new_parent = item_location( it ); + + if( parent != item_location::nowhere ) { + std::get<1>( pocket_data ) = item_location( parent, it.get_item() ); } for( const item *contained : pocket->all_items_top() ) { for( const item_pocket *pocket_nest : contained->get_all_contained_pockets() ) { - std::vector> child = get_child_pocket_with_parent( - pocket_nest, &*pocket_data ); - for( std::unique_ptr &pock_d : child ) { - ret.emplace_back( std::move( pock_d ) ); + std::vector> child = + get_child_pocket_with_parent( + pocket_nest, + new_parent, + item_location( it, const_cast( contained ) ), + std::get<2>( pocket_data ) ); + for( std::tuple &pock_d : child ) { + ret.emplace_back( pock_d ); } } } - ret.emplace_back( std::move( pocket_data ) ); + ret.emplace_back( pocket_data ); } return ret; } -std::vector> outfit::get_all_pocket_with_parent( +std::vector> outfit::get_all_pocket_with_parent( Character &guy ) { - std::vector> ret; - std::vector pockets; + std::vector> ret; // Collect all pockets std::list items; @@ -2275,10 +2279,11 @@ std::vector> outfit::get_all_pocket_wit } for( item *i : items ) { for( const item_pocket *pocket : i->get_all_contained_pockets() ) { - std::vector> child = get_child_pocket_with_parent( pocket, - nullptr ); - for( std::unique_ptr &pock_d : child ) { - ret.emplace_back( std::move( pock_d ) ); + std::vector> child = + get_child_pocket_with_parent( pocket, + item_location::nowhere, item_location( guy, i ), 0 ); + for( std::tuple &pock_d : child ) { + ret.emplace_back( pock_d ); } } } @@ -2306,23 +2311,26 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge temp_it.charges = 1; // Collect all pockets - std::vector> pockets_with_parent; - std::vector> pockets_with_parent_working; + std::vector> pockets_with_parent; + std::vector> pockets_with_parent_working; pockets_with_parent_working = get_all_pocket_with_parent( guy ); - for( std::unique_ptr &pocket_data_ptr : pockets_with_parent_working ) { - item_pocket *pocket = pocket_data_ptr->pocket; + for( std::tuple &pocket_data : + pockets_with_parent_working ) { + const item_pocket *pocket = std::get<0>( pocket_data ); if( pocket->can_contain( temp_it ).success() ) { - pockets_with_parent.emplace_back( std::move( pocket_data_ptr ) ); + pockets_with_parent.emplace_back( pocket_data ); } } std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, - temp_it]( std::unique_ptr &lhs, - std::unique_ptr &rhs ) { - const item_pocket &lpp = *lhs->pocket; - const item_pocket *lpd = lhs->pocket; - const item_pocket *rpd = rhs->pocket; + temp_it]( std::tuple &lhs, + std::tuple &rhs ) { + const item_pocket *lpd = std::get<0>( lhs ); + const item_pocket *rpd = std::get<0>( rhs ); + const item_pocket &lpp = *lpd; + const int lp_nlvl = std::get<2>( lhs ); + const int rp_nlvl = std::get<2>( rhs ); if( lpd->settings.priority() != rpd->settings.priority() ) { return lpd->settings.priority() > rpd->settings.priority(); @@ -2332,8 +2340,8 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge return rpd->rigid(); } - if( lhs->nest_level != rhs->nest_level ) { - return lhs->nest_level < rhs->nest_level; + if( lp_nlvl != rp_nlvl ) { + return lp_nlvl < rp_nlvl; } return rpd->better_pocket( lpp, temp_it, false ); @@ -2341,30 +2349,26 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge const int amount = remaining_charges; int num_contained = 0; - for( std::unique_ptr &pocket_data_ptr : pockets_with_parent ) { + for( std::tuple pocket_data_ptr : pockets_with_parent ) { if( amount <= num_contained || remaining_charges <= 0 ) { break; } int filled_count = 0; - item_pocket *pocke = pocket_data_ptr->pocket; + item_pocket *pocke = const_cast( std::get<0>( pocket_data_ptr ) ); if( pocke == nullptr ) { continue; } if( pocke->rigid() ) { - //Rigid container allow loading under no conditions because do not depend on the capacity of the parent's pocket. + // Rigid container allow to fill unconditionally till volume limit + // because do not depend on the capacity of the parent's pocket. filled_count = pocke->fill_with( newit, guy, remaining_charges, false, false ); } else { - pocket_with_parent_data *parent_data = pocket_data_ptr->parent_data; - int remain_vol = std::min( pocke->charges_per_remaining_volume( temp_it ), 65535 ); - int remain_weight = std::min( pocke->charges_per_remaining_weight( temp_it ), 65535 ); - while( parent_data != nullptr ) { - item_pocket *parent_pocke; - parent_pocke = parent_data->pocket; - remain_vol = std::min( parent_pocke->charges_per_remaining_volume( temp_it ), remain_vol ); - remain_weight = std::min( parent_pocke->charges_per_remaining_weight( temp_it ), remain_weight ); - parent_data = parent_data->parent_data; + item_location parent_data = std::get<1>( pocket_data_ptr ); + int max_contain_value = pocke->remaining_capacity_for_item( newit ); + if( parent_data.has_parent() && parent_data.parents_can_contain_recursive( &temp_it ) ) { + max_contain_value = parent_data.max_charges_by_parent_recursive( temp_it ); } - int charges = std::min( { remain_vol, remain_weight, remaining_charges } ) ; + const int charges = std::min( max_contain_value, remaining_charges ) ; filled_count = pocke->fill_with( newit, guy, charges, false, false ); } num_contained += filled_count; diff --git a/src/character_attire.h b/src/character_attire.h index 82d98a2ae86e0..acb9143d87a58 100644 --- a/src/character_attire.h +++ b/src/character_attire.h @@ -57,12 +57,6 @@ struct dispose_option { std::function action; }; -struct pocket_with_parent_data { - item_pocket *pocket = nullptr; - pocket_with_parent_data *parent_data = nullptr; - int nest_level = 0; -}; - class outfit { private: @@ -213,7 +207,8 @@ class outfit // used for npc generation void set_fitted(); std::vector available_pockets() const; - std::vector> get_all_pocket_with_parent( Character &guy ); + std::vector> get_all_pocket_with_parent( + Character &guy ); void write_text_memorial( std::ostream &file, const std::string &indent, const char *eol ) const; std::string get_armor_display( bodypart_id bp, unsigned int truncate = 0 ) const; void activate_combat_items( npc &guy ); From 7bc6f0e15482c13c93f9cc0f9ed3522fc8ac6a55 Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sat, 5 Nov 2022 02:56:12 +0900 Subject: [PATCH 04/11] Fix logical error and adjust for unit tests --- src/character_attire.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index dbe7ac91c523f..9b8557298a188 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2335,15 +2335,12 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge if( lpd->settings.priority() != rpd->settings.priority() ) { return lpd->settings.priority() > rpd->settings.priority(); } - - if( lpd->rigid() != rpd->rigid() ) { - return rpd->rigid(); - } - if( lp_nlvl != rp_nlvl ) { return lp_nlvl < rp_nlvl; } - + if( lpd->rigid() != rpd->rigid() ) { + return lpd->rigid(); + } return rpd->better_pocket( lpp, temp_it, false ); } ); @@ -2365,8 +2362,12 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge } else { item_location parent_data = std::get<1>( pocket_data_ptr ); int max_contain_value = pocke->remaining_capacity_for_item( newit ); - if( parent_data.has_parent() && parent_data.parents_can_contain_recursive( &temp_it ) ) { - max_contain_value = parent_data.max_charges_by_parent_recursive( temp_it ); + if( parent_data.has_parent() ) { + if( parent_data.parents_can_contain_recursive( &temp_it ) ) { + max_contain_value = parent_data.max_charges_by_parent_recursive( temp_it ); + } else { + max_contain_value = 0; + } } const int charges = std::min( max_contain_value, remaining_charges ) ; filled_count = pocke->fill_with( newit, guy, charges, false, false ); From c6c07b34c1b9728880cdb0f44beb8d6f88ef3ac7 Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sat, 5 Nov 2022 03:10:08 +0900 Subject: [PATCH 05/11] Optimize to Clang-tidy (clang-12, tiles) --- src/character_attire.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 9b8557298a188..d7c47f4396c82 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2232,10 +2232,10 @@ void outfit::pickup_stash( const item &newit, int &remaining_charges, bool ignor static std::vector> get_child_pocket_with_parent( - const item_pocket *pocket, item_location parent, item_location it, int nest_level ); + const item_pocket *pocket, item_location &parent, item_location it, int nest_level ); std::vector> get_child_pocket_with_parent( - const item_pocket *pocket, item_location parent, item_location it, int nest_level ) + const item_pocket *pocket, item_location &parent, item_location it, int nest_level ) { std::vector> ret; if( pocket != nullptr ) { @@ -2279,9 +2279,10 @@ std::vector> outfit::get_all } for( item *i : items ) { for( const item_pocket *pocket : i->get_all_contained_pockets() ) { + item_location loc = item_location(); std::vector> child = get_child_pocket_with_parent( pocket, - item_location::nowhere, item_location( guy, i ), 0 ); + loc, item_location( guy, i ), 0 ); for( std::tuple &pock_d : child ) { ret.emplace_back( pock_d ); } From 7e9f194b706efde1a48d71b24ada1e4b290aba4c Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sat, 5 Nov 2022 18:40:53 +0900 Subject: [PATCH 06/11] Improved readability Recreate structure using item_location Fix logical bug --- src/character_attire.cpp | 78 ++++++++++++++++++---------------------- src/character_attire.h | 9 +++-- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index d7c47f4396c82..94b0855248df2 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2230,30 +2230,25 @@ void outfit::pickup_stash( const item &newit, int &remaining_charges, bool ignor } } -static std::vector> - get_child_pocket_with_parent( - const item_pocket *pocket, item_location &parent, item_location it, int nest_level ); - -std::vector> get_child_pocket_with_parent( - const item_pocket *pocket, item_location &parent, item_location it, int nest_level ) +static std::vector get_child_pocket_with_parent( + const item_pocket *pocket, const item_location &parent, item_location it, const int nested_level ) { - std::vector> ret; + std::vector ret; if( pocket != nullptr ) { - std::tuple pocket_data = { pocket, item_location(), nest_level + 1 }; - item_location new_parent = item_location( it ); + pocket_data_with_parent pocket_data = { pocket, item_location::nowhere, nested_level }; + const item_location new_parent = item_location( it ); if( parent != item_location::nowhere ) { - std::get<1>( pocket_data ) = item_location( parent, it.get_item() ); + pocket_data.parent = item_location( parent, it.get_item() ); } + for( const item *contained : pocket->all_items_top() ) { + const item_location poc_loc = item_location( it, const_cast( contained ) ); for( const item_pocket *pocket_nest : contained->get_all_contained_pockets() ) { - std::vector> child = - get_child_pocket_with_parent( - pocket_nest, - new_parent, - item_location( it, const_cast( contained ) ), - std::get<2>( pocket_data ) ); - for( std::tuple &pock_d : child ) { + std::vector child = + get_child_pocket_with_parent( pocket_nest, new_parent, + poc_loc, nested_level + 1 ); + for( pocket_data_with_parent &pock_d : child ) { ret.emplace_back( pock_d ); } } @@ -2263,10 +2258,10 @@ std::vector> get_child_pocke return ret; } -std::vector> outfit::get_all_pocket_with_parent( - Character &guy ) +std::vector outfit::get_all_pocket_with_parent( + Character &guy ) { - std::vector> ret; + std::vector ret; // Collect all pockets std::list items; @@ -2279,11 +2274,10 @@ std::vector> outfit::get_all } for( item *i : items ) { for( const item_pocket *pocket : i->get_all_contained_pockets() ) { - item_location loc = item_location(); - std::vector> child = - get_child_pocket_with_parent( pocket, - loc, item_location( guy, i ), 0 ); - for( std::tuple &pock_d : child ) { + item_location loc = item_location::nowhere; + std::vector child = + get_child_pocket_with_parent( pocket, loc, item_location( guy, i ), 0 ); + for( pocket_data_with_parent &pock_d : child ) { ret.emplace_back( pock_d ); } } @@ -2306,38 +2300,35 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge // Crawl Next : worn items pickup_stash( newit, remaining_charges, ignore_pkt_settings ); } else { - //item copy for test can contain item temp_it = item( newit ); temp_it.charges = 1; // Collect all pockets - std::vector> pockets_with_parent; - std::vector> pockets_with_parent_working; + std::vector pockets_with_parent; + std::vector pockets_with_parent_working; pockets_with_parent_working = get_all_pocket_with_parent( guy ); - for( std::tuple &pocket_data : - pockets_with_parent_working ) { - const item_pocket *pocket = std::get<0>( pocket_data ); + for( pocket_data_with_parent &pocket_data : pockets_with_parent_working ) { + const item_pocket *pocket = pocket_data.pocket_ptr; if( pocket->can_contain( temp_it ).success() ) { pockets_with_parent.emplace_back( pocket_data ); } } - std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, - temp_it]( std::tuple &lhs, - std::tuple &rhs ) { - const item_pocket *lpd = std::get<0>( lhs ); - const item_pocket *rpd = std::get<0>( rhs ); + std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, temp_it] + ( pocket_data_with_parent & lhs, pocket_data_with_parent & rhs ) { + const item_pocket *lpd = lhs.pocket_ptr; + const item_pocket *rpd = rhs.pocket_ptr; const item_pocket &lpp = *lpd; - const int lp_nlvl = std::get<2>( lhs ); - const int rp_nlvl = std::get<2>( rhs ); + const int lp_nested_lvl = lhs.nested_level; + const int rp_nested_lvl = rhs.nested_level; if( lpd->settings.priority() != rpd->settings.priority() ) { return lpd->settings.priority() > rpd->settings.priority(); } - if( lp_nlvl != rp_nlvl ) { - return lp_nlvl < rp_nlvl; + if( lp_nested_lvl != rp_nested_lvl ) { + return lp_nested_lvl < rp_nested_lvl; } if( lpd->rigid() != rpd->rigid() ) { return lpd->rigid(); @@ -2347,12 +2338,12 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge const int amount = remaining_charges; int num_contained = 0; - for( std::tuple pocket_data_ptr : pockets_with_parent ) { + for( pocket_data_with_parent pocket_data_ptr : pockets_with_parent ) { if( amount <= num_contained || remaining_charges <= 0 ) { break; } int filled_count = 0; - item_pocket *pocke = const_cast( std::get<0>( pocket_data_ptr ) ); + item_pocket *pocke = const_cast( pocket_data_ptr.pocket_ptr ); if( pocke == nullptr ) { continue; } @@ -2361,8 +2352,9 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge // because do not depend on the capacity of the parent's pocket. filled_count = pocke->fill_with( newit, guy, remaining_charges, false, false ); } else { - item_location parent_data = std::get<1>( pocket_data_ptr ); int max_contain_value = pocke->remaining_capacity_for_item( newit ); + item_location parent_data = pocket_data_ptr.parent; + if( parent_data.has_parent() ) { if( parent_data.parents_can_contain_recursive( &temp_it ) ) { max_contain_value = parent_data.max_charges_by_parent_recursive( temp_it ); diff --git a/src/character_attire.h b/src/character_attire.h index acb9143d87a58..571fb3dd437b0 100644 --- a/src/character_attire.h +++ b/src/character_attire.h @@ -57,6 +57,12 @@ struct dispose_option { std::function action; }; +struct pocket_data_with_parent { + const item_pocket *pocket_ptr; + item_location parent; + int nested_level; +}; + class outfit { private: @@ -207,8 +213,7 @@ class outfit // used for npc generation void set_fitted(); std::vector available_pockets() const; - std::vector> get_all_pocket_with_parent( - Character &guy ); + std::vector get_all_pocket_with_parent( Character &guy ); void write_text_memorial( std::ostream &file, const std::string &indent, const char *eol ) const; std::string get_armor_display( bodypart_id bp, unsigned int truncate = 0 ) const; void activate_combat_items( npc &guy ); From 6710685434df6ee7805569dae15ea2382e20a8ad Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sun, 6 Nov 2022 03:49:59 +0900 Subject: [PATCH 07/11] Clang-tidy (clang-12, tiles) challenge Add const and reference modifiers --- src/character_attire.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 94b0855248df2..6606a2cf9b0d2 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2248,7 +2248,7 @@ static std::vector get_child_pocket_with_parent( std::vector child = get_child_pocket_with_parent( pocket_nest, new_parent, poc_loc, nested_level + 1 ); - for( pocket_data_with_parent &pock_d : child ) { + for( const pocket_data_with_parent &pock_d : child ) { ret.emplace_back( pock_d ); } } @@ -2277,7 +2277,7 @@ std::vector outfit::get_all_pocket_with_parent( item_location loc = item_location::nowhere; std::vector child = get_child_pocket_with_parent( pocket, loc, item_location( guy, i ), 0 ); - for( pocket_data_with_parent &pock_d : child ) { + for( const pocket_data_with_parent &pock_d : child ) { ret.emplace_back( pock_d ); } } @@ -2309,7 +2309,7 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge std::vector pockets_with_parent_working; pockets_with_parent_working = get_all_pocket_with_parent( guy ); - for( pocket_data_with_parent &pocket_data : pockets_with_parent_working ) { + for( const pocket_data_with_parent &pocket_data : pockets_with_parent_working ) { const item_pocket *pocket = pocket_data.pocket_ptr; if( pocket->can_contain( temp_it ).success() ) { pockets_with_parent.emplace_back( pocket_data ); @@ -2317,7 +2317,7 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge } std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, temp_it] - ( pocket_data_with_parent & lhs, pocket_data_with_parent & rhs ) { + ( const pocket_data_with_parent & lhs, const pocket_data_with_parent & rhs ) { const item_pocket *lpd = lhs.pocket_ptr; const item_pocket *rpd = rhs.pocket_ptr; const item_pocket &lpp = *lpd; @@ -2338,7 +2338,7 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge const int amount = remaining_charges; int num_contained = 0; - for( pocket_data_with_parent pocket_data_ptr : pockets_with_parent ) { + for( const pocket_data_with_parent &pocket_data_ptr : pockets_with_parent ) { if( amount <= num_contained || remaining_charges <= 0 ) { break; } @@ -2353,7 +2353,7 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge filled_count = pocke->fill_with( newit, guy, remaining_charges, false, false ); } else { int max_contain_value = pocke->remaining_capacity_for_item( newit ); - item_location parent_data = pocket_data_ptr.parent; + const item_location parent_data = pocket_data_ptr.parent; if( parent_data.has_parent() ) { if( parent_data.parents_can_contain_recursive( &temp_it ) ) { From d951bfbb0988c8965ee3b5fb9eca990e705c4227 Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sun, 13 Nov 2022 04:10:24 +0900 Subject: [PATCH 08/11] Apply suggestions from code review Changed from individual emplace_back to insert. Suggested by mqrause Co-authored-by: mqrause <38702195+mqrause@users.noreply.github.com> --- src/character_attire.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 6606a2cf9b0d2..63ec0704675b3 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2248,9 +2248,7 @@ static std::vector get_child_pocket_with_parent( std::vector child = get_child_pocket_with_parent( pocket_nest, new_parent, poc_loc, nested_level + 1 ); - for( const pocket_data_with_parent &pock_d : child ) { - ret.emplace_back( pock_d ); - } + ret.insert( ret.end(), child.begin(), child.end() ); } } ret.emplace_back( pocket_data ); @@ -2277,9 +2275,7 @@ std::vector outfit::get_all_pocket_with_parent( item_location loc = item_location::nowhere; std::vector child = get_child_pocket_with_parent( pocket, loc, item_location( guy, i ), 0 ); - for( const pocket_data_with_parent &pock_d : child ) { - ret.emplace_back( pock_d ); - } + ret.insert( ret.end(), child.begin(), child.end() ); } } return ret; From 85699b486650c751ad0f617fa57e7ccbef0e08c5 Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sun, 13 Nov 2022 04:12:45 +0900 Subject: [PATCH 09/11] Add files via upload get_child_pocket_with_parent func migrates from outfit scope to Character scope get_child_pocket_with_parent func has new filter and sort function arguments --- src/character.h | 18 +++++++++++ src/character_attire.cpp | 68 ++++++++++++++++++---------------------- src/character_attire.h | 7 ----- 3 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/character.h b/src/character.h index b7ca12b00358f..f21a1a2189efd 100644 --- a/src/character.h +++ b/src/character.h @@ -390,6 +390,12 @@ struct needs_rates { float kcal = 0.0f; }; +struct pocket_data_with_parent { + const item_pocket *pocket_ptr; + item_location parent; + int nested_level; +}; + class Character : public Creature, public visitable { public: @@ -2037,6 +2043,18 @@ class Character : public Creature, public visitable std::pair best_pocket( const item &it, const item *avoid = nullptr, bool ignore_settings = false ); + /** + * Collect all pocket data (with parent and nest levels added) that the character has. + * @param filter only collect pockets that match the filter. + * @param sort_func customizable sorting function. + * + * @returns pocket_data_with_parent vector to return. + */ + std::vector get_all_pocket_with_parent( + const std::function &filter = return_true, + const std::function + *sort_func = nullptr ); + /** * Checks if character stats and skills meet minimum requirements for the item. * Prints an appropriate message if requirements not met. diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 63ec0704675b3..2370c5e0f0b1e 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2241,6 +2241,7 @@ static std::vector get_child_pocket_with_parent( if( parent != item_location::nowhere ) { pocket_data.parent = item_location( parent, it.get_item() ); } + ret.emplace_back( pocket_data ); for( const item *contained : pocket->all_items_top() ) { const item_location poc_loc = item_location( it, const_cast( contained ) ); @@ -2251,33 +2252,47 @@ static std::vector get_child_pocket_with_parent( ret.insert( ret.end(), child.begin(), child.end() ); } } - ret.emplace_back( pocket_data ); } return ret; } -std::vector outfit::get_all_pocket_with_parent( - Character &guy ) +std::vector Character::get_all_pocket_with_parent( + const std::function &filter, + const std::function + *sort_func ) + { std::vector ret; + const auto sort_pockets_func = [ sort_func ] + ( const pocket_data_with_parent & l, const pocket_data_with_parent & r ) { + const auto sort_pockets = *sort_func; + return sort_pockets( l, r ); + }; // Collect all pockets std::list items; - item_location carried_item = guy.get_wielded_item(); + item_location carried_item = get_wielded_item(); if( carried_item != item_location::nowhere ) { items.emplace_back( &*carried_item ); } - for( item &i : guy.worn.worn ) { - items.emplace_back( &i ); + for( item_location &loc : worn.top_items_loc( *this ) ) { + items.emplace_back( loc.get_item() ); } for( item *i : items ) { for( const item_pocket *pocket : i->get_all_contained_pockets() ) { item_location loc = item_location::nowhere; std::vector child = - get_child_pocket_with_parent( pocket, loc, item_location( guy, i ), 0 ); - ret.insert( ret.end(), child.begin(), child.end() ); + get_child_pocket_with_parent( pocket, loc, item_location( *this, i ), 0 ); + for( const pocket_data_with_parent &pock_d : child ) { + if( filter( pock_d.pocket_ptr ) ) { + ret.emplace_back( pock_d ); + } + } } } + if( sort_func ) { + std::sort( ret.begin(), ret.end(), sort_pockets_func ); + } return ret; } @@ -2302,35 +2317,14 @@ void outfit::add_stash( Character &guy, const item &newit, int &remaining_charge // Collect all pockets std::vector pockets_with_parent; - std::vector pockets_with_parent_working; - pockets_with_parent_working = get_all_pocket_with_parent( guy ); - - for( const pocket_data_with_parent &pocket_data : pockets_with_parent_working ) { - const item_pocket *pocket = pocket_data.pocket_ptr; - if( pocket->can_contain( temp_it ).success() ) { - pockets_with_parent.emplace_back( pocket_data ); - } - } - - std::sort( pockets_with_parent.begin(), pockets_with_parent.end(), [newit, temp_it] - ( const pocket_data_with_parent & lhs, const pocket_data_with_parent & rhs ) { - const item_pocket *lpd = lhs.pocket_ptr; - const item_pocket *rpd = rhs.pocket_ptr; - const item_pocket &lpp = *lpd; - const int lp_nested_lvl = lhs.nested_level; - const int rp_nested_lvl = rhs.nested_level; - - if( lpd->settings.priority() != rpd->settings.priority() ) { - return lpd->settings.priority() > rpd->settings.priority(); - } - if( lp_nested_lvl != rp_nested_lvl ) { - return lp_nested_lvl < rp_nested_lvl; - } - if( lpd->rigid() != rpd->rigid() ) { - return lpd->rigid(); - } - return rpd->better_pocket( lpp, temp_it, false ); - } ); + auto const pocket_filter = [&temp_it]( item_pocket const * pck ) { + return pck->can_contain( temp_it ).success(); + }; + const std::function + &sort_f = [&temp_it]( const pocket_data_with_parent & a, const pocket_data_with_parent & b ) { + return b.pocket_ptr->better_pocket( *a.pocket_ptr, temp_it, false ); + }; + pockets_with_parent = guy.get_all_pocket_with_parent( pocket_filter, &sort_f ); const int amount = remaining_charges; int num_contained = 0; diff --git a/src/character_attire.h b/src/character_attire.h index 571fb3dd437b0..995ac105fcc8c 100644 --- a/src/character_attire.h +++ b/src/character_attire.h @@ -57,12 +57,6 @@ struct dispose_option { std::function action; }; -struct pocket_data_with_parent { - const item_pocket *pocket_ptr; - item_location parent; - int nested_level; -}; - class outfit { private: @@ -213,7 +207,6 @@ class outfit // used for npc generation void set_fitted(); std::vector available_pockets() const; - std::vector get_all_pocket_with_parent( Character &guy ); void write_text_memorial( std::ostream &file, const std::string &indent, const char *eol ) const; std::string get_armor_display( bodypart_id bp, unsigned int truncate = 0 ) const; void activate_combat_items( npc &guy ); From f0466a7fdc89ac881323a395207c6cfcee9d7165 Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sun, 13 Nov 2022 13:37:53 +0900 Subject: [PATCH 10/11] Tune some code Suggested by mqrause Erase a redundant line break --- src/character_attire.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 2370c5e0f0b1e..5a4e733a048ee 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2231,7 +2231,8 @@ void outfit::pickup_stash( const item &newit, int &remaining_charges, bool ignor } static std::vector get_child_pocket_with_parent( - const item_pocket *pocket, const item_location &parent, item_location it, const int nested_level ) + const item_pocket *pocket, const item_location &parent, item_location it, const int nested_level, + const std::function &filter = return_true ) { std::vector ret; if( pocket != nullptr ) { @@ -2241,14 +2242,16 @@ static std::vector get_child_pocket_with_parent( if( parent != item_location::nowhere ) { pocket_data.parent = item_location( parent, it.get_item() ); } - ret.emplace_back( pocket_data ); + if( filter( pocket_data.pocket_ptr ) ) { + ret.emplace_back( pocket_data ); + } for( const item *contained : pocket->all_items_top() ) { const item_location poc_loc = item_location( it, const_cast( contained ) ); for( const item_pocket *pocket_nest : contained->get_all_contained_pockets() ) { std::vector child = get_child_pocket_with_parent( pocket_nest, new_parent, - poc_loc, nested_level + 1 ); + poc_loc, nested_level + 1, filter ); ret.insert( ret.end(), child.begin(), child.end() ); } } @@ -2260,7 +2263,6 @@ std::vector Character::get_all_pocket_with_parent( const std::function &filter, const std::function *sort_func ) - { std::vector ret; const auto sort_pockets_func = [ sort_func ] @@ -2269,25 +2271,26 @@ std::vector Character::get_all_pocket_with_parent( return sort_pockets( l, r ); }; - // Collect all pockets - std::list items; + std::list locs; item_location carried_item = get_wielded_item(); if( carried_item != item_location::nowhere ) { - items.emplace_back( &*carried_item ); + locs.emplace_back( carried_item ); } - for( item_location &loc : worn.top_items_loc( *this ) ) { - items.emplace_back( loc.get_item() ); + for( item_location &worn_loc : top_items_loc( ) ) { + if( worn_loc != item_location::nowhere ) { + locs.emplace_back( worn_loc ); + } } - for( item *i : items ) { + + for( item_location &loc : locs ) { + item *i = loc.get_item(); + if( !i ) { + continue; + } for( const item_pocket *pocket : i->get_all_contained_pockets() ) { - item_location loc = item_location::nowhere; std::vector child = - get_child_pocket_with_parent( pocket, loc, item_location( *this, i ), 0 ); - for( const pocket_data_with_parent &pock_d : child ) { - if( filter( pock_d.pocket_ptr ) ) { - ret.emplace_back( pock_d ); - } - } + get_child_pocket_with_parent( pocket, item_location::nowhere, loc, 0, filter ); + ret.insert( ret.end(), child.begin(), child.end() ); } } if( sort_func ) { From 67f859f6efd6e0558b3b18da9557662ad02fa22c Mon Sep 17 00:00:00 2001 From: EI IKaO <109350502+EIIKaO@users.noreply.github.com> Date: Sun, 13 Nov 2022 17:11:55 +0900 Subject: [PATCH 11/11] Update src/character_attire.cpp Erase dupulicated checks Co-authored-by: mqrause <38702195+mqrause@users.noreply.github.com> --- src/character_attire.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 5a4e733a048ee..6d6ac645e4e04 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2283,11 +2283,7 @@ std::vector Character::get_all_pocket_with_parent( } for( item_location &loc : locs ) { - item *i = loc.get_item(); - if( !i ) { - continue; - } - for( const item_pocket *pocket : i->get_all_contained_pockets() ) { + for( const item_pocket *pocket : loc->get_all_contained_pockets() ) { std::vector child = get_child_pocket_with_parent( pocket, item_location::nowhere, loc, 0, filter ); ret.insert( ret.end(), child.begin(), child.end() );