ExpertSystem.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #include "../../global.h"
  2. #include "../../CCallback.h"
  3. #include "../../lib/HeroBonus.h"
  4. #include <boost/bind.hpp>
  5. #include <vector>
  6. #include <list>
  7. /*
  8. * ExpertSystem.h, part of VCMI engine
  9. *
  10. * Authors: listed in file AUTHORS in main folder
  11. *
  12. * License: GNU General Public License v2.0 or later
  13. * Full text of license available in license.txt file, in main folder
  14. *
  15. */
  16. struct Bonus;
  17. template <typename fact> class AIholder;
  18. template <typename input, typename output> class Rule;
  19. typedef Rule<Bonus, Bonus> BRule;
  20. typedef boost::function<bool(int, si32)> TLogic;
  21. bool greaterThan (int prop, si32 val);
  22. enum conditionType {LESS_THAN, EQUAL, GREATER_THAN, UNEQUAL, PRESENT};
  23. template <typename ruleType, typename fact> class ExpertSystemShell
  24. {
  25. enum runType {ANY_GOAL, TRESHOLD, FULL}; //Treshold - stop when received decision has high AI value
  26. private:
  27. ICallback* m_cb;
  28. protected:
  29. std::vector<ruleType> knowledge;
  30. std::vector<ruleType*> rulesToErase;
  31. std::vector<ruleType*> rulesToAdd;
  32. std::vector<fact*> factsToErase;
  33. std::vector<fact*> factsToAdd;
  34. ui16 goalCounter; //count / evaluate achieved goals for runType
  35. public:
  36. ExpertSystemShell(){goalCounter = 0;};
  37. std::list<fact> facts; //facts are AIholders with actual game objects, for eg. "my bonus is worthless"
  38. template <typename t1> void getKnowledge(const t1 &a1){};
  39. void getNextRule(){};
  40. void addRule(ruleType &rule){rulesToAdd.insert(rule);};
  41. void removeRule(ruleType &rule){rulesToErase.insert(rule);};
  42. template <typename t2> void returnGoals(const t2 &a2){};
  43. template <typename cond> void DataDrivenReasoning(runType type);
  44. };
  45. template <typename ruleType, typename fact> class Blackboard : public ExpertSystemShell <ruleType, fact>
  46. //handle Bonus info coming from different sections of the game
  47. {
  48. public:
  49. Blackboard(){this->goalCounter = 0;}; //template magic, do not touch!
  50. std::vector<ExpertSystemShell*> experts; //modules responsible for different tasks
  51. };
  52. template <typename input> class condition
  53. {//compares selected object parameter with value using functor. universal (?) logic handler
  54. public:
  55. input object; //what the fact is, or what it's like (CSelector)
  56. si32 value;
  57. ui8 parameter;
  58. TLogic functor; //value of selected parameter, condition value
  59. condition(){object = NULL; value = 0; parameter = 0; functor = greaterThan;};
  60. bool matchesFact(input &fact){return false;};
  61. };
  62. template <typename input, typename conType> class Rule
  63. {
  64. friend class ExpertSystemShell <input, conType>;
  65. public:
  66. bool fired; //if conditions of rule were met and it produces some output
  67. ui8 conditionCounter;
  68. protected:
  69. std::vector<std::pair<conType, input*>> cons; //conditions and matching facts
  70. input decision;
  71. virtual void canBeFired(); //if this data makes any sense for rule - type check
  72. virtual bool checkCondition(); //if condition is true or false
  73. virtual bool checkCondition(std::vector<input*> &feed);
  74. virtual void fireRule(); //use paired conditions and facts by default
  75. virtual void fireRule(ExpertSystemShell<input, conType> &system);
  76. virtual void fireRule(std::vector<input*> &feed);
  77. virtual void refreshRule();
  78. virtual void refreshRule(std::vector<conType> &conditionSet); //in case conditions were erased
  79. public:
  80. Rule(){fired = false; conditionCounter = 0; decision = NULL;};
  81. template <typename givenInput> bool matchesInput() //if condition and data match type
  82. {return dynamic_cast<input*>(&givenInput);};
  83. };
  84. template <typename input, typename output> class Goal : public Rule <input, output>
  85. {
  86. protected:
  87. boost::function<void(output)> decision(); //do something with AI eventually
  88. public:
  89. void fireRule(){};
  90. };
  91. template <typename input, typename output> class Weight : public Rule <input, output>
  92. {
  93. public:
  94. float multiplier; //multiply input by value and return to output
  95. void fireTule(){};
  96. };
  97. template <typename input> class AIholder
  98. { //stores certain condition and its temporal value
  99. public:
  100. si32 aiValue;
  101. input *object;
  102. AIholder(){object = NULL; aiValue = 0;}
  103. AIholder(input &o){object = o; aiValue = 0;}
  104. AIholder(input &o, si32 val){object = 0; aiValue = val;}
  105. };
  106. class BonusSystemExpert : public ExpertSystemShell <BRule, Bonus>
  107. { //TODO: less templates?
  108. enum effectType {POSITIVE=1, NEGATIVE=2, EXCLUDING=4, ENEMY=8, ALLY=16}; //what is the influence of bonus and for who
  109. };
  110. class BonusCondition : public condition<CSelector> //used to test rule
  111. {
  112. public:
  113. enum Parameter
  114. {
  115. type, subtype, val, duration, source, id, valType, additionalInfo, effectRange, limiter //?
  116. };
  117. bool matchesFact(Bonus &fact);
  118. };
  119. class BonusHolder : public AIholder<Bonus>
  120. {
  121. public:
  122. BonusHolder(Bonus &bonus){object = &bonus; aiValue = bonus.val;}
  123. BonusHolder(Bonus &bonus, si32 val){object = &bonus; aiValue = val;}
  124. };
  125. class BonusRule : public Rule <BonusHolder, BonusCondition>
  126. {
  127. protected:
  128. void fireRule();
  129. };
  130. inline bool greaterThan (int prop, si32 val) //does it make any sense to keep functors inline?
  131. {
  132. if ((si32)prop > val)
  133. return true;
  134. return false;
  135. }
  136. inline bool lessThan (int prop, si32 val)
  137. {
  138. if ((si32)prop < val)
  139. return true;
  140. return false;
  141. }
  142. inline bool eqal (int prop, si32 val)
  143. {
  144. if ((si32)prop == val)
  145. return true;
  146. return false;
  147. }
  148. inline bool unequal (int prop, si32 val)
  149. {
  150. if ((si32)prop != val)
  151. return true;
  152. return false;
  153. }
  154. inline bool present (int prop, si32 val=0)
  155. //inline bool present (int prop) //TODO: can we use function with less arguments?
  156. {
  157. return(prop); //unfixable warning :(
  158. }
  159. class LogicConjunction
  160. {
  161. const TLogic first, second; //TODO: universal argument list of functions?
  162. public:
  163. LogicConjunction(const TLogic First, const TLogic Second)
  164. :first(First), second(Second)
  165. {
  166. }
  167. bool operator()(int prop, si32 val) const
  168. {
  169. return first(prop,val) && second(prop,val);
  170. }
  171. };
  172. TLogic operator&&(const TLogic &first, const TLogic &second);
  173. class LogicAlternative
  174. {
  175. const TLogic first, second;
  176. public:
  177. LogicAlternative(const TLogic First, const TLogic Second)
  178. :first(First), second(Second)
  179. {
  180. }
  181. bool operator()(int prop, si32 val) const
  182. {
  183. return first(prop,val) || second(prop,val);
  184. }
  185. };
  186. TLogic operator||(const TLogic &first, const TLogic &second);
  187. class KnowledgeHandler///I'd opt for one omniscent knowledge manager, so no templates here
  188. {
  189. public:
  190. std::list<BonusRule> knowledge; //permanent storage of rules
  191. void parseKnowledge(std::string &filename){};
  192. void addKnowledge(ExpertSystemShell<BRule,Bonus> &expert);
  193. void addFacts(ExpertSystemShell<BRule,Bonus> &expert);
  194. };