ExpertSystem.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "StdInc.h"
  2. #include "GeneralAI.h"
  3. #include "../../CCallback.h"
  4. #include "ExpertSystem.h"
  5. /*
  6. * ExpertSystem.cpp, part of VCMI engine
  7. *
  8. * Authors: listed in file AUTHORS in main folder
  9. *
  10. * License: GNU General Public License v2.0 or later
  11. * Full text of license available in license.txt file, in main folder
  12. *
  13. */
  14. template <typename ruleType, typename facts> template <typename cond> void ExpertSystemShell<ruleType, facts>::DataDrivenReasoning(runType type)
  15. {
  16. std::vector<ruleType>::iterator ir;
  17. std::list<fact>::iterator iF;
  18. std::vector<std::pair<cond, input*>>::iterator ic;
  19. bool factWasAdded = false; //carry it over inner loop
  20. switch (type)
  21. {
  22. case ANY_GOAL: //first produced decision ends reasoning
  23. {
  24. int goalCounter = 0;
  25. while(!goalCounter) //we reach goal or can't modify knowledge anymore
  26. {
  27. for (ir = knowledge.begin(); ir != knowledge.end(); ir++)
  28. {
  29. for (iF = factList.begin(); iF != factList.end(); iF++)
  30. {
  31. for (ic = ir->conditions.begin(); ic != ir->conditions.end(), ic++)
  32. {
  33. if (ic->first.object.matchesFact(iF->object)) //condition matches held object
  34. {
  35. (ic->second = *iF);
  36. ++(ir->conditionCounter);
  37. }
  38. }
  39. if (ir->conditions.size() >= ir->conditionCounter());
  40. {
  41. ir->fireRule(); //all conditions matched
  42. ir->conditionCounter = 0; //do it here or in rule itself?
  43. if (dynamic_cast<&Goal>(*ir))
  44. ++goalCounter;
  45. }
  46. }
  47. //modify set until something happens (hopefully!)
  48. for (iF = factsToAdd.begin(); iF != factsToAdd.end(); iF++)
  49. factList.insert(*iF);
  50. if (factsToAdd.size())
  51. {
  52. factsToAdd.clear();
  53. factWasAdded = true;
  54. }
  55. }
  56. for (iF = factsToErase.begin(); iF != factsToErase.end(); iF++) //remove facts discarded in this run
  57. factList.erase(knowledge.find(*iF));
  58. factsToErase.clear(); //erase only after all rules had a chance to trigger
  59. for (ir = rulesToErase.begin(); ir != rulesToErase.end(); ir++)
  60. knowledge.erase(knowledge.find(*ir));
  61. rulesToErase.clear();
  62. for (ir = rulesToAdd.begin(); ir != rulesToAdd.end(); ir++)
  63. knowledge.insert(*ir);
  64. if (!(factWasAdded || rulesToAdd.size())) //we can't do anything more
  65. break;
  66. rulesToAdd.clear();
  67. };
  68. }
  69. break;
  70. }
  71. }
  72. void BonusRule::fireRule()
  73. {
  74. for (std::vector<std::pair<BonusCondition, BonusHolder*>>::iterator it = cons.begin(); it != cons.end(); it++)
  75. {
  76. switch (it->first.parameter)
  77. { //compare fact with condition
  78. case BonusCondition::type:
  79. if (!it->first.functor(it->second->object->type, it->first.value)) return;
  80. break;
  81. case BonusCondition::subtype: //probably suprfluous, Selector already handles that
  82. if (!it->first.functor(it->second->object->subtype, it->first.value)) return;
  83. break;
  84. case BonusCondition::val:
  85. if (!it->first.functor(it->second->object->val, it->first.value)) return;
  86. break;
  87. case BonusCondition::duration:
  88. if (!it->first.functor(it->second->object->duration, it->first.value)) return;
  89. break;
  90. case BonusCondition::source: //likely to handle by selector
  91. if (!it->first.functor(it->second->object->source, it->first.value)) return;
  92. break;
  93. case BonusCondition::id:
  94. if (!it->first.functor(it->second->object->sid, it->first.value)) return;
  95. break;
  96. case BonusCondition::valType: //ever needed?
  97. if (!it->first.functor(it->second->object->valType, it->first.value)) return;
  98. break;
  99. case BonusCondition::additionalInfo:
  100. if (!it->first.functor(it->second->object->additionalInfo, it->first.value)) return;
  101. break;
  102. case BonusCondition::effectRange:
  103. if (!it->first.functor(it->second->object->effectRange, it->first.value)) return;
  104. break;
  105. default: //ignore or accept?
  106. break;
  107. };
  108. }
  109. //TODO: add new fact or modify existing one
  110. }
  111. TLogic operator&&(const TLogic &first, const TLogic &second)
  112. {
  113. return LogicConjunction(first, second);
  114. }
  115. TLogic operator||(const TLogic &first, const TLogic &second)
  116. {
  117. return LogicAlternative(first, second);
  118. }
  119. template <typename input, typename conType> void Rule<input, conType>::refreshRule(std::vector<conType> &conditionSet)
  120. {//replace conditions with new vector
  121. cons.clear();
  122. std::pair <conType,input*> para;
  123. para.second = NULL;
  124. for (std::vector<conType>::iterator it = conditionSet.begin(); it != conditionSet.end(); it++)
  125. {
  126. para.first = *it;
  127. cons.push_back(para); //pointer to condition and null fact
  128. }
  129. }
  130. template <typename input, typename conType> void Rule<input, conType>::refreshRule()
  131. {//clear matching facts
  132. for (std::vector<std::pair<conType, input*>>::iterator it = cons.begin(); it != cons.end(); it++)
  133. it->second = NULL;
  134. }
  135. bool BonusCondition::matchesFact(Bonus &fact)
  136. {
  137. if (object(&fact)) //Bonus(fact) matches local Selector(object)
  138. return true;
  139. return false;
  140. }