ExpertSystem.cpp 4.9 KB

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