123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * BonusSelector.h, part of VCMI engine
- *
- * Authors: listed in file AUTHORS in main folder
- *
- * License: GNU General Public License v2.0 or later
- * Full text of license available in license.txt file, in main folder
- *
- */
- #pragma once
- #include "Bonus.h"
- VCMI_LIB_NAMESPACE_BEGIN
- class CSelector : std::function<bool(const Bonus*)>
- {
- using TBase = std::function<bool(const Bonus*)>;
- public:
- CSelector() = default;
- template<typename T>
- CSelector(const T &t, //SFINAE trick -> include this c-tor in overload resolution only if parameter is class
- //(includes functors, lambdas) or function. Without that VC is going mad about ambiguities.
- typename std::enable_if_t < std::is_class_v<T> || std::is_function_v<T> > *dummy = nullptr)
- : TBase(t)
- {}
- CSelector(std::nullptr_t)
- {}
- CSelector And(CSelector rhs) const
- {
- //lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer)
- auto thisCopy = *this;
- return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); };
- }
- CSelector Or(CSelector rhs) const
- {
- auto thisCopy = *this;
- return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) || rhs(b); };
- }
- CSelector Not() const
- {
- auto thisCopy = *this;
- return [thisCopy](const Bonus *b) mutable { return !thisCopy(b); };
- }
- bool operator()(const Bonus *b) const
- {
- return TBase::operator()(b);
- }
- operator bool() const
- {
- return !!static_cast<const TBase&>(*this);
- }
- };
- template<typename T>
- class CSelectFieldEqual
- {
- T Bonus::*ptr;
- public:
- CSelectFieldEqual(T Bonus::*Ptr)
- : ptr(Ptr)
- {
- }
- CSelector operator()(const T &valueToCompareAgainst) const
- {
- auto ptr2 = ptr; //We need a COPY because we don't want to reference this (might be outlived by lambda)
- return [ptr2, valueToCompareAgainst](const Bonus *bonus)
- {
- return bonus->*ptr2 == valueToCompareAgainst;
- };
- }
- };
- class DLL_LINKAGE CWillLastTurns
- {
- int turnsRequested;
- public:
- CWillLastTurns(int turnsRequested):
- turnsRequested(turnsRequested)
- {}
- bool operator()(const Bonus *bonus) const
- {
- return turnsRequested <= 0 //every present effect will last zero (or "less") turns
- || !Bonus::NTurns(bonus) //so do every not expriing after N-turns effect
- || bonus->turnsRemain > turnsRequested;
- }
- };
- class DLL_LINKAGE CWillLastDays
- {
- int daysRequested;
- public:
- CWillLastDays(int daysRequested):
- daysRequested(daysRequested)
- {}
- bool operator()(const Bonus *bonus) const
- {
- if(daysRequested <= 0 || Bonus::Permanent(bonus) || Bonus::OneBattle(bonus))
- return true;
- else if(Bonus::OneDay(bonus))
- return false;
- else if(Bonus::NDays(bonus) || Bonus::OneWeek(bonus))
- {
- return bonus->turnsRemain > daysRequested;
- }
- return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations
- }
- };
- namespace Selector
- {
- extern DLL_LINKAGE const CSelectFieldEqual<BonusType> & type();
- extern DLL_LINKAGE const CSelectFieldEqual<BonusSubtypeID> & subtype();
- extern DLL_LINKAGE const CSelectFieldEqual<CAddInfo> & info();
- extern DLL_LINKAGE const CSelectFieldEqual<BonusSource> & sourceType();
- extern DLL_LINKAGE const CSelectFieldEqual<BonusSource> & targetSourceType();
- extern DLL_LINKAGE const CSelectFieldEqual<BonusLimitEffect> & effectRange();
- CWillLastTurns DLL_LINKAGE turns(int turns);
- CWillLastDays DLL_LINKAGE days(int days);
- CSelector DLL_LINKAGE typeSubtype(BonusType Type, BonusSubtypeID Subtype);
- CSelector DLL_LINKAGE typeSubtypeInfo(BonusType type, BonusSubtypeID subtype, const CAddInfo & info);
- CSelector DLL_LINKAGE source(BonusSource source, BonusSourceID sourceID);
- CSelector DLL_LINKAGE sourceTypeSel(BonusSource source);
- CSelector DLL_LINKAGE valueType(BonusValueType valType);
- CSelector DLL_LINKAGE typeSubtypeValueType(BonusType Type, BonusSubtypeID Subtype, BonusValueType valType);
- /**
- * Selects all bonuses
- * Usage example: Selector::all.And(<functor>).And(<functor>)...)
- */
- extern DLL_LINKAGE CSelector all;
- /**
- * Selects nothing
- * Usage example: Selector::none.Or(<functor>).Or(<functor>)...)
- */
- extern DLL_LINKAGE CSelector none;
- }
- VCMI_LIB_NAMESPACE_END
|