mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Added trivial fuzzy logic to handle creature banks estimation.
Check http://forum.vcmi.eu/viewtopic.php?p=6570#6570 for new library used.
This commit is contained in:
parent
ebfbccdd0e
commit
998d8bf501
110
AI/VCAI/Fuzzy.cpp
Normal file
110
AI/VCAI/Fuzzy.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "StdInc.h"
|
||||
#include "Fuzzy.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
#include "AreaCentroidAlgorithm.cpp"
|
||||
#include "CompoundTerm.cpp"
|
||||
#include "DescriptiveAntecedent.cpp"
|
||||
#include "FuzzyEngine.cpp"
|
||||
#include "FuzzyAnd.cpp"
|
||||
#include "FuzzyOr.cpp"
|
||||
#include "InputLVar.cpp"
|
||||
#include "OutputLVar.cpp"
|
||||
#include "FuzzyAntecedent.cpp"
|
||||
#include "FuzzyConsequent.cpp"
|
||||
#include "FuzzyDefuzzifier.cpp"
|
||||
#include "FuzzyModulation.cpp"
|
||||
#include "FuzzyOperator.cpp"
|
||||
#include "FuzzyOperation.cpp"
|
||||
#include "FuzzyException.cpp"
|
||||
#include "FuzzyExceptions.cpp"
|
||||
#include "FuzzyRule.cpp"
|
||||
#include "HedgeSet.cpp"
|
||||
#include "Hedge.cpp"
|
||||
#include "SingletonTerm.cpp"
|
||||
#include "TrapezoidalTerm.cpp"
|
||||
#include "TriangularTerm.cpp"
|
||||
#include "LinguisticTerm.cpp"
|
||||
#include "LinguisticVariable.cpp"
|
||||
#include "RuleBlock.cpp"
|
||||
#include "ShoulderTerm.cpp"
|
||||
#include "StrOp.cpp"
|
||||
#include "MamdaniRule.cpp"
|
||||
#include "MamdaniConsequent.cpp"
|
||||
|
||||
/*
|
||||
* Fuzzy.cpp, 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
|
||||
*
|
||||
*/
|
||||
|
||||
class BankConfig;
|
||||
class FuzzyEngine;
|
||||
class InputLVar;
|
||||
|
||||
FuzzyHelper fh;
|
||||
|
||||
ui64 evaluateBankConfig (BankConfig * bc)
|
||||
{
|
||||
ui64 danger = 0;
|
||||
BOOST_FOREACH (auto opt, bc->guards)
|
||||
{
|
||||
danger += VLC->creh->creatures[opt.first]->fightValue * opt.second;
|
||||
}
|
||||
return danger;
|
||||
}
|
||||
|
||||
FuzzyHelper::FuzzyHelper()
|
||||
{
|
||||
bankInput = new fl::InputLVar("BankInput");
|
||||
bankDanger = new fl::OutputLVar("BankDanger");
|
||||
bankInput->addTerm(new fl::SingletonTerm ("SET"));
|
||||
|
||||
engine.addRuleBlock (&ruleBlock); //have to be added before the rules are parsed
|
||||
engine.addInputLVar (bankInput);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
bankDanger->addTerm(new fl::TriangularTerm ("Bank" + boost::lexical_cast<std::string>(i), 0, 1));
|
||||
ruleBlock.addRule(new fl::MamdaniRule("if BankInput is SET then BankDanger is Bank" + boost::lexical_cast<std::string>(i), engine));
|
||||
}
|
||||
engine.addOutputLVar (bankDanger);
|
||||
}
|
||||
|
||||
ui64 FuzzyHelper::estimateBankDanger (int ID)
|
||||
{
|
||||
std::vector <ConstTransitivePtr<BankConfig>> & configs = VLC->objh->banksInfo[ID];
|
||||
ui64 val = INFINITY;;
|
||||
switch (configs.size())
|
||||
{
|
||||
case 4:
|
||||
try
|
||||
{
|
||||
int bankVal;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
bankVal = evaluateBankConfig (VLC->objh->banksInfo[ID][i]);
|
||||
bankDanger->term("Bank" + boost::lexical_cast<std::string>(i))->setMinimum(bankVal * 0.5f);
|
||||
bankDanger->term("Bank" + boost::lexical_cast<std::string>(i))->setMaximum(bankVal * 1.5f);
|
||||
}
|
||||
int averageValue = (evaluateBankConfig (VLC->objh->banksInfo[ID][0]) + evaluateBankConfig (VLC->objh->banksInfo[ID][3])) * 0.5;
|
||||
dynamic_cast<fl::SingletonTerm*>(bankInput->term("SET"))->setValue(1);
|
||||
bankInput->setInput (0);
|
||||
engine.process();
|
||||
val = bankDanger->output().defuzzify(); //some expected value of this bank
|
||||
}
|
||||
catch (fl::FuzzyException fe)
|
||||
{
|
||||
tlog1 << fe.name() << ": " << fe.message() << '\n';
|
||||
}
|
||||
case 1: //rare case - Pyramid
|
||||
val = evaluateBankConfig (VLC->objh->banksInfo[ID][0]);
|
||||
break;
|
||||
default:
|
||||
tlog3 << ("Uhnandled bank config!\n");
|
||||
}
|
||||
return val;
|
||||
|
||||
}
|
34
AI/VCAI/Fuzzy.h
Normal file
34
AI/VCAI/Fuzzy.h
Normal file
@ -0,0 +1,34 @@
|
||||
#define INFINITY 1000000000 //definition required by FuzzyLite (?)
|
||||
#define NAN 1000000001
|
||||
#include "FuzzyLite.h"
|
||||
|
||||
/*
|
||||
* Fuzzy.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
|
||||
*
|
||||
*/
|
||||
|
||||
class VCAI;
|
||||
|
||||
template <typename T> bool isinf (T val)
|
||||
{
|
||||
return val == INFINITY || val == -INFINITY;
|
||||
}
|
||||
|
||||
class FuzzyHelper
|
||||
{
|
||||
friend class VCAI;
|
||||
|
||||
fl::FuzzyEngine engine;
|
||||
fl::InputLVar* bankInput;
|
||||
fl::OutputLVar* bankDanger;
|
||||
fl::RuleBlock ruleBlock;
|
||||
|
||||
public:
|
||||
FuzzyHelper();
|
||||
ui64 estimateBankDanger (int ID);
|
||||
};
|
@ -1,12 +1,14 @@
|
||||
#include "StdInc.h"
|
||||
#include "VCAI.h"
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "Fuzzy.h"
|
||||
#include "../../lib/CObjectHandler.h"
|
||||
|
||||
#define I_AM_ELEMENTAR return CGoal(*this).setisElementar(true)
|
||||
|
||||
|
||||
CLogger &aiLogger = tlog6;
|
||||
|
||||
extern FuzzyHelper fh;
|
||||
|
||||
const int ACTUAL_RESOURCE_COUNT = 7;
|
||||
|
||||
const double SAFE_ATTACK_CONSTANT = 2.5;
|
||||
@ -15,6 +17,7 @@ using namespace vstd;
|
||||
//one thread may be turn of AI and another will be handling a side effect for AI2
|
||||
boost::thread_specific_ptr<CCallback> cb;
|
||||
boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
// CCallback *cb;
|
||||
// VCAI *ai;
|
||||
|
||||
@ -72,6 +75,7 @@ namespace Obj
|
||||
MINE = 53,
|
||||
MONSTER = 54,
|
||||
OBELISK = 57,
|
||||
PYRAMID = 63,
|
||||
CRYPT = 84,
|
||||
SHIPWRECK = 85,
|
||||
TRADING_POST = 99,
|
||||
@ -319,22 +323,16 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
|
||||
return cre->getArmyStrength();
|
||||
}
|
||||
case Obj::CRYPT: //crypt
|
||||
{
|
||||
return VLC->creh->creatures[56]->AIValue * 25
|
||||
+ VLC->creh->creatures[58]->AIValue * 20
|
||||
+ VLC->creh->creatures[60]->AIValue * 9
|
||||
+ VLC->creh->creatures[62]->AIValue * 5;
|
||||
}
|
||||
case Obj::CREATURE_BANK: //crebank
|
||||
case Obj::SHIPWRECK: //shipwreck
|
||||
case Obj::DERELICT_SHIP: //derelict ship
|
||||
//TODO estimate danger
|
||||
return 1000000000;
|
||||
case Obj::PYRAMID:
|
||||
return fh.estimateBankDanger (VLC->objh->bankObjToIndex(obj));
|
||||
case Obj::WHIRLPOOL: //whirlpool
|
||||
case Obj::MONOLITH1:
|
||||
case Obj::MONOLITH2:
|
||||
case Obj::MONOLITH3:
|
||||
//TODO mechinism for handling monoliths
|
||||
//TODO mechanism for handling monoliths
|
||||
return 1000000000;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -150,6 +150,8 @@ struct CIssueCommand : CGoal
|
||||
class VCAI : public CAdventureAI
|
||||
{
|
||||
public:
|
||||
friend class FuzzyHelper;
|
||||
|
||||
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
|
||||
std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
||||
std::map<const CGHeroInstance *, std::vector<const CGTownInstance *> > townVisitsThisWeek;
|
||||
|
@ -190,6 +190,25 @@ void CObjectHandler::loadObjects()
|
||||
tlog5 << "\t\tDone loading banks configs \n";
|
||||
}
|
||||
|
||||
int CObjectHandler::bankObjToIndex (const CGObjectInstance * obj)
|
||||
{
|
||||
switch (obj->ID) //find apriopriate key
|
||||
{
|
||||
case 16: //bank
|
||||
return obj->subID;
|
||||
case 24: //derelict ship
|
||||
return 8;
|
||||
case 25: //utopia
|
||||
return 10;
|
||||
case 84: //crypt
|
||||
return 9;
|
||||
case 85: //shipwreck
|
||||
return 7;
|
||||
default:
|
||||
tlog2 << "Unrecognixed Bank indetifier!\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int CGObjectInstance::getOwner() const
|
||||
{
|
||||
//if (state)
|
||||
@ -5688,19 +5707,7 @@ void CGOnceVisitable::searchTomb(const CGHeroInstance *h, ui32 accept) const
|
||||
|
||||
void CBank::initObj()
|
||||
{
|
||||
switch (ID) //find apriopriate key
|
||||
{
|
||||
case 16: //bank
|
||||
index = subID; break;
|
||||
case 24: //derelict ship
|
||||
index = 8; break;
|
||||
case 25: //utopia
|
||||
index = 10; break;
|
||||
case 84: //crypt
|
||||
index = 9; break;
|
||||
case 85: //shipwreck
|
||||
index = 7; break;
|
||||
}
|
||||
index = VLC->objh->bankObjToIndex(this);
|
||||
bc = NULL;
|
||||
daycounter = 0;
|
||||
multiplier = 1;
|
||||
|
@ -1309,6 +1309,7 @@ public:
|
||||
std::vector<ui32> resVals; //default values of resources in gold
|
||||
|
||||
void loadObjects();
|
||||
int bankObjToIndex (const CGObjectInstance * obj);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user