| 
					
				 | 
			
			
				@@ -129,14 +129,20 @@ TacticalAdvantageEngine::TacticalAdvantageEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	try
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		ourShooters = vstd::make_unique<fl::InputVariable>(fl::InputVariable("OurShooters"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		ourWalkers = vstd::make_unique<fl::InputVariable>(fl::InputVariable("OurWalkers"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		ourFlyers = vstd::make_unique<fl::InputVariable>(fl::InputVariable("OurFlyers"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		enemyShooters = vstd::make_unique<fl::InputVariable>(fl::InputVariable("EnemyShooters"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		enemyWalkers = vstd::make_unique<fl::InputVariable>(fl::InputVariable("EnemyWalkers"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		enemyFlyers = vstd::make_unique<fl::InputVariable>(fl::InputVariable("EnemyFlyers"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for(auto val : {ourShooters.get(), ourWalkers.get(), ourFlyers.get(), enemyShooters.get(), enemyWalkers.get(), enemyFlyers.get()})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ourShooters = new fl::InputVariable("OurShooters");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ourWalkers = new fl::InputVariable("OurWalkers");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ourFlyers = new fl::InputVariable("OurFlyers");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		enemyShooters = new fl::InputVariable("EnemyShooters");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		enemyWalkers = new fl::InputVariable("EnemyWalkers");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		enemyFlyers = new fl::InputVariable("EnemyFlyers");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//Tactical advantage calculation
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		std::vector<fl::InputVariable *> helper =
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			ourShooters, ourWalkers, ourFlyers, enemyShooters, enemyWalkers, enemyFlyers
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		};
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for(auto val : helper)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			engine.addInputVariable(val);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			val->addTerm(new fl::Ramp("FEW", 0.6, 0.0));
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -144,10 +150,12 @@ TacticalAdvantageEngine::TacticalAdvantageEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			val->setRange(0.0, 1.0);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		ourSpeed = vstd::make_unique<fl::InputVariable>(fl::InputVariable("OurSpeed"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		enemySpeed = vstd::make_unique<fl::InputVariable>(fl::InputVariable("EnemySpeed"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		ourSpeed = new fl::InputVariable("OurSpeed");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		enemySpeed = new fl::InputVariable("EnemySpeed");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for(auto val : {ourSpeed.get(), enemySpeed.get()})
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		helper = { ourSpeed, enemySpeed };
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for(auto val : helper)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			engine.addInputVariable(val);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			val->addTerm(new fl::Ramp("LOW", 6.5, 3));
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -156,8 +164,8 @@ TacticalAdvantageEngine::TacticalAdvantageEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			val->setRange(0, 25);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		castleWalls = vstd::make_unique<fl::InputVariable>(fl::InputVariable("CastleWalls"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		engine.addInputVariable(castleWalls.get());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		castleWalls = new fl::InputVariable("CastleWalls");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		engine.addInputVariable(castleWalls);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			fl::Rectangle * none = new fl::Rectangle("NONE", CGTownInstance::NONE, CGTownInstance::NONE + (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			castleWalls->addTerm(none);
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -173,8 +181,8 @@ TacticalAdvantageEngine::TacticalAdvantageEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		bankPresent = vstd::make_unique<fl::InputVariable>(fl::InputVariable("Bank"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		engine.addInputVariable(bankPresent.get());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bankPresent = new fl::InputVariable("Bank");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		engine.addInputVariable(bankPresent);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			fl::Rectangle * termFalse = new fl::Rectangle("FALSE", 0.0, 0.5f);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			bankPresent->addTerm(termFalse);
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -183,8 +191,8 @@ TacticalAdvantageEngine::TacticalAdvantageEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			bankPresent->setRange(0, 1);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		threat = vstd::make_unique<fl::OutputVariable>(fl::OutputVariable("Threat"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		engine.addOutputVariable(threat.get());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		threat = new fl::OutputVariable("Threat");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		engine.addOutputVariable(threat);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		threat->addTerm(new fl::Ramp("LOW", 1, MIN_AI_STRENGHT));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		threat->addTerm(new fl::Triangle("MEDIUM", 0.8, 1.2));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		threat->addTerm(new fl::Ramp("HIGH", 1, 1.5));
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -257,13 +265,12 @@ float TacticalAdvantageEngine::getTacticalAdvantage(const CArmedInstance * we, c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if(output < 0 || (output != output))
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fl::scalar tab[] = { bankPresent->getValue(), castleWalls->getValue(), ourWalkers->getValue(), ourShooters->getValue(), ourFlyers->getValue(), ourSpeed->getValue(),
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			enemyWalkers->getValue(), enemyShooters->getValue(), enemyFlyers->getValue(), enemySpeed->getValue() };
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		fl::InputVariable * tab[] = { bankPresent, castleWalls, ourWalkers, ourShooters, ourFlyers, ourSpeed, enemyWalkers, enemyShooters, enemyFlyers, enemySpeed };
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		std::string names[] = { "bankPresent", "castleWalls", "ourWalkers", "ourShooters", "ourFlyers", "ourSpeed", "enemyWalkers", "enemyShooters", "enemyFlyers", "enemySpeed" };
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		std::stringstream log("Warning! Fuzzy engine doesn't cover this set of parameters: ");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		for(int i = 0; i < boost::size(tab); i++)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			log << names[i] << ": " << tab[i] << " ";
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			log << names[i] << ": " << tab[i]->getValue() << " ";
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		logAi->error(log.str());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		assert(false);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -271,6 +278,22 @@ float TacticalAdvantageEngine::getTacticalAdvantage(const CArmedInstance * we, c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return output;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+TacticalAdvantageEngine::~TacticalAdvantageEngine()
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//TODO: smart pointers?
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete ourWalkers;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete ourShooters;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete ourFlyers;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete enemyWalkers;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete enemyShooters;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete enemyFlyers;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete ourSpeed;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete enemySpeed;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete bankPresent;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete castleWalls;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete threat;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 Goals::TSubgoal FuzzyHelper::chooseSolution(Goals::TGoalVec vec)
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -311,19 +334,20 @@ HeroMovementGoalEngineBase::HeroMovementGoalEngineBase() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	try
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		strengthRatio = vstd::make_unique<fl::InputVariable>(fl::InputVariable("strengthRatio")); //hero must be strong enough to defeat guards
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		heroStrength = vstd::make_unique<fl::InputVariable>(fl::InputVariable("heroStrength")); //we want to use weakest possible hero
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		turnDistance = vstd::make_unique<fl::InputVariable>(fl::InputVariable("turnDistance")); //we want to use hero who is near
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		missionImportance = vstd::make_unique<fl::InputVariable>(fl::InputVariable("lockedMissionImportance")); //we may want to preempt hero with low-priority mission
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		value = vstd::make_unique<fl::OutputVariable>(fl::OutputVariable("Value"));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		strengthRatio = new fl::InputVariable("strengthRatio"); //hero must be strong enough to defeat guards
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		heroStrength = new fl::InputVariable("heroStrength"); //we want to use weakest possible hero
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		turnDistance = new fl::InputVariable("turnDistance"); //we want to use hero who is near
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		missionImportance = new fl::InputVariable("lockedMissionImportance"); //we may want to preempt hero with low-priority mission
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		value = new fl::OutputVariable("Value");
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		value->setMinimum(0);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		value->setMaximum(5);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for(auto val : { strengthRatio.get(), heroStrength.get(), turnDistance.get(), missionImportance.get() })
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		std::vector<fl::InputVariable *> helper = { strengthRatio, heroStrength, turnDistance, missionImportance };
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for(auto val : helper)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			engine.addInputVariable(val);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		engine.addOutputVariable(value.get());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		engine.addOutputVariable(value);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		strengthRatio->addTerm(new fl::Ramp("LOW", SAFE_ATTACK_CONSTANT, 0));
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		strengthRatio->addTerm(new fl::Ramp("HIGH", SAFE_ATTACK_CONSTANT, SAFE_ATTACK_CONSTANT * 3));
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -403,6 +427,14 @@ void HeroMovementGoalEngineBase::setSharedFuzzyVariables(Goals::AbstractGoal & g 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+HeroMovementGoalEngineBase::~HeroMovementGoalEngineBase()
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete strengthRatio;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete heroStrength;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete turnDistance;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete missionImportance;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 float FuzzyHelper::evaluate(Goals::VisitTile & g)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return visitTileEngine.evaluate(g);
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -492,9 +524,9 @@ GetObjEngine::GetObjEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	try
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		objectValue = vstd::make_unique<fl::InputVariable>(fl::InputVariable("objectValue")); //value of that object type known by AI
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		objectValue = new fl::InputVariable("objectValue"); //value of that object type known by AI
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		engine.addInputVariable(objectValue.get());
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		engine.addInputVariable(objectValue);
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		//objectValue ranges are based on checking RMG priorities of some objects and trying to guess sane value ranges
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		objectValue->addTerm(new fl::Ramp("LOW", 3000, 0)); //I have feeling that concave shape might work well instead of ramp for objectValue FL terms
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -521,6 +553,11 @@ GetObjEngine::GetObjEngine() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	configure();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+GetObjEngine::~GetObjEngine()
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	delete objectValue;
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 float GetObjEngine::evaluate(Goals::AbstractGoal & goal)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	auto g = dynamic_cast<Goals::GetObj &>(goal);
 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -566,6 +603,10 @@ VisitTileEngine::VisitTileEngine() //so far no VisitTile-specific variables that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	configure();
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+VisitTileEngine::~VisitTileEngine()
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 float VisitTileEngine::evaluate(Goals::AbstractGoal & goal)
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {
 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	auto g = dynamic_cast<Goals::VisitTile &>(goal);
 
			 |