Skip to content

Commit

Permalink
Backporting CleverRaven#51086 In crafting every tool is displayed onl…
Browse files Browse the repository at this point in the history
…y once
  • Loading branch information
BrettDong authored and ZhilkinSerg committed Nov 27, 2021
1 parent 4c58201 commit 57af603
Showing 1 changed file with 64 additions and 2 deletions.
66 changes: 64 additions & 2 deletions src/requirements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ static const trait_id trait_DEBUG_HS( "DEBUG_HS" );

static std::map<requirement_id, requirement_data> requirements_all;

static bool a_satisfies_b( const quality_requirement &a, const quality_requirement &b );
static bool a_satisfies_b( const std::vector<quality_requirement> &a,
const std::vector<quality_requirement> &b );


/** @relates string_id */
template<>
bool string_id<requirement_data>::is_valid() const
Expand Down Expand Up @@ -317,18 +322,75 @@ requirement_data requirement_data::operator*( unsigned scalar ) const
return res;
}

static bool a_satisfies_b( const quality_requirement &a, const quality_requirement &b )
{
return a.type == b.type && a.level >= b.level
&& a.requirement == b.requirement && a.count == b.count;
}

static bool a_satisfies_b( const std::vector<quality_requirement> &a,
const std::vector<quality_requirement> &b )
{
// every b_x is satisfied by some a_x
for( const quality_requirement &b_x : b ) {
bool satisfied = false;
for( const quality_requirement &a_x : a ) {
if( a_satisfies_b( a_x, b_x ) ) {
satisfied = true;
break;
}
}
if( !satisfied ) {
return false;
}
}

return true;
}

requirement_data requirement_data::operator+( const requirement_data &rhs ) const
{
requirement_data res = *this;

res.components.insert( res.components.end(), rhs.components.begin(), rhs.components.end() );
res.tools.insert( res.tools.end(), rhs.tools.begin(), rhs.tools.end() );
res.qualities.insert( res.qualities.end(), rhs.qualities.begin(), rhs.qualities.end() );
/*
TODO: what is / isn't implemented:
I will represent type by letter and level by number, always true: count = 1 && requirement = false
A1 then has type A with level 1, (count = 1, requirement = false)
X) [implemented ? "x" else " "] What's required -> How should it be displayed
1) [x] A1 && A1 -> A1
2) [x] A1 && A2 -> A2
3) [x] (A1 || B1) && A1 -> A1
4) [ ] A1 || A2 -> A1
5) [ ] (A1 || B1) && A2 -> A2
6) [ ] (A1 || B1 || C1) || (A1 || B1) -> A1 || B1 || C1
Note: (1) covers most cases, (2) probably the rest, (3..6) probably isn't anywhere?
It all takes O(n^2), but that's acceptable since n is very small.
@Brambor
*/
for( const std::vector<quality_requirement> &new_quality : rhs.qualities ) {
bool add = true;
for( std::vector<quality_requirement> &old_quality : res.qualities ) {
if( a_satisfies_b( new_quality, old_quality ) ) {
add = false;
old_quality = new_quality;
break;
} else if( a_satisfies_b( old_quality, new_quality ) ) {
add = false;
break;
}
}
if( add ) {
res.qualities.emplace_back( new_quality );
}
}

// combined result is temporary which caller could store via @ref save_requirement
res.id_ = requirement_id::NULL_ID();

// TODO: deduplicate qualities and combine other requirements
// TODO: combine other requirements

// if either operand was blacklisted then their summation should also be
res.blacklisted |= rhs.blacklisted;
Expand Down

0 comments on commit 57af603

Please sign in to comment.