ui64 evaluateDanger(crint3 tile, const CGHeroInstance *visitor) { const TerrainTile *t = cb->getTile(tile, false); if(!t) //we can know about guard but can't check its tile (the edge of fow) return 190000000; //MUCH ui64 objectDanger = 0, guardDanger = 0; auto visitableObjects = cb->getVisitableObjs(tile); // in some scenarios hero happens to be "under" the object (eg town). Then we consider ONLY the hero. if(vstd::contains_if(visitableObjects, objWithID<Obj::HERO>)) vstd::erase_if(visitableObjects, [](const CGObjectInstance * obj) { return !objWithID<Obj::HERO>(obj); }); if(const CGObjectInstance * dangerousObject = vstd::backOrNull(visitableObjects)) { objectDanger = evaluateDanger(dangerousObject); //unguarded objects can also be dangerous or unhandled if (objectDanger) { //TODO: don't downcast objects AI shouldn't know about! auto armedObj = dynamic_cast<const CArmedInstance*>(dangerousObject); if (armedObj) { float tacticalAdvantage = fh->getTacticalAdvantage(visitor, armedObj); objectDanger *= tacticalAdvantage; //this line tends to go infinite for allied towns (?) } } if (dangerousObject->ID == Obj::SUBTERRANEAN_GATE) { //check guard on the other side of the gate auto it = ai->knownSubterraneanGates.find(dangerousObject); if (it != ai->knownSubterraneanGates.end()) { auto guards = cb->getGuardingCreatures(it->second->visitablePos()); for (auto cre : guards) { vstd::amax (guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre))); } } } } auto guards = cb->getGuardingCreatures(tile); for (auto cre : guards) { vstd::amax (guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre))); //we are interested in strongest monster around } //TODO mozna odwiedzic blockvis nie ruszajac straznika return std::max(objectDanger, guardDanger); }