BonusSelector.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * BonusSelector.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "Bonus.h"
  12. VCMI_LIB_NAMESPACE_BEGIN
  13. class CSelector : std::function<bool(const Bonus*)>
  14. {
  15. using TBase = std::function<bool(const Bonus*)>;
  16. public:
  17. CSelector() = default;
  18. template<typename T>
  19. CSelector(const T &t, //SFINAE trick -> include this c-tor in overload resolution only if parameter is class
  20. //(includes functors, lambdas) or function. Without that VC is going mad about ambiguities.
  21. typename std::enable_if_t < std::is_class_v<T> || std::is_function_v<T> > *dummy = nullptr)
  22. : TBase(t)
  23. {}
  24. CSelector(std::nullptr_t)
  25. {}
  26. CSelector And(CSelector rhs) const
  27. {
  28. //lambda may likely outlive "this" (it can be even a temporary) => we copy the OBJECT (not pointer)
  29. auto thisCopy = *this;
  30. return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) && rhs(b); };
  31. }
  32. CSelector Or(CSelector rhs) const
  33. {
  34. auto thisCopy = *this;
  35. return [thisCopy, rhs](const Bonus *b) mutable { return thisCopy(b) || rhs(b); };
  36. }
  37. CSelector Not() const
  38. {
  39. auto thisCopy = *this;
  40. return [thisCopy](const Bonus *b) mutable { return !thisCopy(b); };
  41. }
  42. bool operator()(const Bonus *b) const
  43. {
  44. return TBase::operator()(b);
  45. }
  46. operator bool() const
  47. {
  48. return !!static_cast<const TBase&>(*this);
  49. }
  50. };
  51. template<typename T>
  52. class CSelectFieldEqual
  53. {
  54. T Bonus::*ptr;
  55. public:
  56. CSelectFieldEqual(T Bonus::*Ptr)
  57. : ptr(Ptr)
  58. {
  59. }
  60. CSelector operator()(const T &valueToCompareAgainst) const
  61. {
  62. auto ptr2 = ptr; //We need a COPY because we don't want to reference this (might be outlived by lambda)
  63. return [ptr2, valueToCompareAgainst](const Bonus *bonus)
  64. {
  65. return bonus->*ptr2 == valueToCompareAgainst;
  66. };
  67. }
  68. };
  69. class DLL_LINKAGE CWillLastTurns
  70. {
  71. int turnsRequested;
  72. public:
  73. CWillLastTurns(int turnsRequested):
  74. turnsRequested(turnsRequested)
  75. {}
  76. bool operator()(const Bonus *bonus) const
  77. {
  78. return turnsRequested <= 0 //every present effect will last zero (or "less") turns
  79. || !Bonus::NTurns(bonus) //so do every not expriing after N-turns effect
  80. || bonus->turnsRemain > turnsRequested;
  81. }
  82. };
  83. class DLL_LINKAGE CWillLastDays
  84. {
  85. int daysRequested;
  86. public:
  87. CWillLastDays(int daysRequested):
  88. daysRequested(daysRequested)
  89. {}
  90. bool operator()(const Bonus *bonus) const
  91. {
  92. if(daysRequested <= 0 || Bonus::Permanent(bonus) || Bonus::OneBattle(bonus))
  93. return true;
  94. else if(Bonus::OneDay(bonus))
  95. return false;
  96. else if(Bonus::NDays(bonus) || Bonus::OneWeek(bonus))
  97. {
  98. return bonus->turnsRemain > daysRequested;
  99. }
  100. return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations
  101. }
  102. };
  103. namespace Selector
  104. {
  105. extern DLL_LINKAGE const CSelectFieldEqual<BonusType> & type();
  106. extern DLL_LINKAGE const CSelectFieldEqual<BonusSubtypeID> & subtype();
  107. extern DLL_LINKAGE const CSelectFieldEqual<CAddInfo> & info();
  108. extern DLL_LINKAGE const CSelectFieldEqual<BonusSource> & sourceType();
  109. extern DLL_LINKAGE const CSelectFieldEqual<BonusSource> & targetSourceType();
  110. extern DLL_LINKAGE const CSelectFieldEqual<BonusLimitEffect> & effectRange();
  111. CWillLastTurns DLL_LINKAGE turns(int turns);
  112. CWillLastDays DLL_LINKAGE days(int days);
  113. CSelector DLL_LINKAGE typeSubtype(BonusType Type, BonusSubtypeID Subtype);
  114. CSelector DLL_LINKAGE typeSubtypeInfo(BonusType type, BonusSubtypeID subtype, const CAddInfo & info);
  115. CSelector DLL_LINKAGE source(BonusSource source, BonusSourceID sourceID);
  116. CSelector DLL_LINKAGE sourceTypeSel(BonusSource source);
  117. CSelector DLL_LINKAGE valueType(BonusValueType valType);
  118. CSelector DLL_LINKAGE typeSubtypeValueType(BonusType Type, BonusSubtypeID Subtype, BonusValueType valType);
  119. /**
  120. * Selects all bonuses
  121. * Usage example: Selector::all.And(<functor>).And(<functor>)...)
  122. */
  123. extern DLL_LINKAGE CSelector all;
  124. /**
  125. * Selects nothing
  126. * Usage example: Selector::none.Or(<functor>).Or(<functor>)...)
  127. */
  128. extern DLL_LINKAGE CSelector none;
  129. }
  130. VCMI_LIB_NAMESPACE_END