Skip to content

Commit

Permalink
add temp_crafting_inventory - lightweight alternative to the `inven…
Browse files Browse the repository at this point in the history
…tory` for crafting queries
  • Loading branch information
Aivean committed Dec 25, 2020
1 parent cf05d62 commit 8c0324a
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 3 deletions.
38 changes: 38 additions & 0 deletions src/temp_crafting_inventory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

#include "temp_crafting_inventory.h"

temp_crafting_inventory::temp_crafting_inventory( const read_only_visitable &v )
{
add_all_ref( v );
}

size_t temp_crafting_inventory::size() const
{
return items.size();
}

void temp_crafting_inventory::clear()
{
items.clear();
temp_owned_items.clear();
}

void temp_crafting_inventory::add_item_ref( item &item )
{
items.insert( &item );
}

item &temp_crafting_inventory::add_item_copy( const item &item )
{
const auto iter = temp_owned_items.insert( item );
items.insert( &( *iter ) );
return *iter;
}

void temp_crafting_inventory::add_all_ref( const read_only_visitable &v )
{
v.visit_items( [&]( item * it, item * ) {
add_item_ref( *it );
return VisitResponse::SKIP;
} );
}
53 changes: 53 additions & 0 deletions src/temp_crafting_inventory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once
#ifndef CATA_SRC_TEMP_CRAFTING_INVENTORY_H
#define CATA_SRC_TEMP_CRAFTING_INVENTORY_H

#include "colony.h"
#include "item.h"
#include "visitable.h"

/**
* A transient add-only list of item references and temporary pseudo-items, that implements `read_only_visitable`
* and thus can answer crafting queries (see crafting.cpp and requirement_data::can_make_with_inventory).
*/
class temp_crafting_inventory : public read_only_visitable
{
public:
temp_crafting_inventory() = default;
temp_crafting_inventory( const read_only_visitable & );

size_t size() const;

void clear();

/**
* Adds item reference to this container.
* @note container doesn't own the added reference, meaning added item should outlive this container.
*/
void add_item_ref( item &item );

/**
* Adds all (top-level) items from the given visitable.
* @note container doesn't own the added references, meaning added items should outlive this container.
*/
void add_all_ref( const read_only_visitable &v );

/**
* Adds item copy to this container.
* Container will own a copy of the given item.
* @return reference to the added item within the container
*/
item &add_item_copy( const item &item );

// inherited from visitable
VisitResponse visit_items( const std::function<VisitResponse( item *, item * )> &func ) const
override;

private:
// list of all items in this container
cata::colony<item *> items;
// copies of "owned" items added by `add_item_copy`
cata::colony<item> temp_owned_items;
};

#endif // CATA_SRC_TEMP_CRAFTING_INVENTORY_H
20 changes: 20 additions & 0 deletions src/visitable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "point.h"
#include "string_id.h"
#include "submap.h"
#include "temp_crafting_inventory.h"
#include "units.h"
#include "value_ptr.h"
#include "veh_type.h"
Expand Down Expand Up @@ -393,6 +394,18 @@ VisitResponse inventory::visit_items(
return VisitResponse::NEXT;
}

/** @relates visitable */
VisitResponse temp_crafting_inventory::visit_items(
const std::function<VisitResponse( item *, item * )> &func ) const
{
for( item *it : items ) {
if( visit_internal( func, it ) == VisitResponse::ABORT ) {
return VisitResponse::ABORT;
}
}
return VisitResponse::NEXT;
}

/** @relates visitable */
VisitResponse Character::visit_items( const std::function<VisitResponse( item *, item * )> &func )
const
Expand Down Expand Up @@ -763,6 +776,13 @@ int read_only_visitable::charges_of( const itype_id &what, int limit,
const std::function<bool( const item & )> &filter,
const std::function<void( int )> &visitor ) const
{
if( what == itype_UPS ) {
int qty = 0;
qty = sum_no_wrap( qty, charges_of( itype_UPS_off ) );
qty = sum_no_wrap( qty, static_cast<int>( charges_of( itype_adv_UPS_off ) / 0.6 ) );
return std::min( qty, limit );
}

return charges_of_internal( *this, *this, what, limit, filter, visitor );
}

Expand Down
15 changes: 12 additions & 3 deletions tests/crafting_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "recipe_dictionary.h"
#include "requirements.h"
#include "ret_val.h"
#include "temp_crafting_inventory.h"
#include "type_id.h"
#include "value_ptr.h"

Expand Down Expand Up @@ -319,9 +320,17 @@ static void prep_craft( const recipe_id &rid, const std::vector<item> &tools,
player_character.get_skill_level( r.skill_used ) ) );
player_character.moves--;
const inventory &crafting_inv = player_character.crafting_inventory();
bool can_craft = r.deduped_requirements().can_make_with_inventory(
crafting_inv, r.get_component_filter() );
REQUIRE( can_craft == expect_craftable );

SECTION( "can craft with crafting inv" ) {
bool can_craft = r.deduped_requirements().can_make_with_inventory(
crafting_inv, r.get_component_filter() );
REQUIRE( can_craft == expect_craftable );
}
SECTION( "can craft with temp inv" ) {
bool can_craft = r.deduped_requirements().can_make_with_inventory(
temp_crafting_inventory( crafting_inv ), r.get_component_filter() );
REQUIRE( can_craft == expect_craftable );
}
}

static time_point midnight = calendar::turn_zero + 0_hours;
Expand Down
40 changes: 40 additions & 0 deletions tests/temp_crafting_inv_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "catch/catch.hpp"

#include "temp_crafting_inventory.h"
#include "../src/temp_crafting_inventory.h"

TEST_CASE( "temp_crafting_inv_test_amount", "[crafting][inventory]" )
{
temp_crafting_inventory inv;
CHECK( inv.size() == 0 );

item gum( "test_gum", calendar::turn_zero, item::default_charges_tag{} );

inv.add_item_ref( gum );
CHECK( inv.size() == 1 );

CHECK( inv.amount_of( itype_id( "test_gum" ) ) == 1 );
CHECK( inv.has_amount( itype_id( "test_gum" ), 1 ) );
CHECK( inv.has_charges( itype_id( "test_gum" ), 10 ) );
CHECK_FALSE( inv.has_charges( itype_id( "test_gum" ), 11 ) );

inv.clear();
CHECK( inv.size() == 0 );
}

TEST_CASE( "temp_crafting_inv_test_quality", "[crafting][inventory]" )
{
temp_crafting_inventory inv;
inv.add_item_copy( item( "test_halligan" ) );

CHECK( inv.has_quality( quality_id( "HAMMER" ), 1 ) );
CHECK( inv.has_quality( quality_id( "HAMMER" ), 2 ) );
CHECK_FALSE( inv.has_quality( quality_id( "HAMMER" ), 3 ) );
CHECK( inv.has_quality( quality_id( "DIG" ), 1 ) );
CHECK_FALSE( inv.has_quality( quality_id( "AXE" ) ) );

inv.add_item_copy( item( "test_fire_ax" ) );
CHECK( inv.has_quality( quality_id( "AXE" ) ) );

CHECK( inv.max_quality( quality_id( "PRY" ) ) == 4 );
}

0 comments on commit 8c0324a

Please sign in to comment.