void AI::HeroesLevelUp(Heroes & hero) { if(4 < hero.GetLevel() && !hero.Modes(AI::HEROES_HUNTER)) hero.SetModes(AI::HEROES_HUNTER); if(9 < hero.GetLevel() && hero.Modes(AI::HEROES_SCOUTER)) hero.ResetModes(AI::HEROES_SCOUTER); }
void Kingdom::ApplyPlayWithStartingHero(void) { if(isPlay() && castles.size()) { // get first castle Castle* first = castles.GetFirstCastle(); if(NULL == first) first = castles.front(); // check manual set hero (castle position + point(0, 1))? const Point & cp = (first)->GetCenter(); Heroes* hero = world.GetTiles(cp.x, cp.y + 1).GetHeroes(); // and move manual set hero to castle if(hero && hero->GetColor() == GetColor()) { bool patrol = hero->Modes(Heroes::PATROL); hero->SetFreeman(0); hero->Recruit(*first); if(patrol) { hero->SetModes(Heroes::PATROL); hero->SetCenterPatrol(cp); } } else if(Settings::Get().GameStartWithHeroes()) { Heroes* hero = world.GetFreemanHeroes(first->GetRace()); if(hero && AllowRecruitHero(false, 0)) hero->Recruit(*first); } } }
void AI::HeroesTurn(Heroes & hero) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", start: " << (hero.Modes(Heroes::SHIPMASTER) ? "SHIPMASTER," : "") << (hero.Modes(AI::HEROES_SCOUTER) ? "SCOUTER," : "") << (hero.Modes(AI::HEROES_HUNTER) ? "HUNTER," : "") << (hero.Modes(Heroes::PATROL) ? "PATROL," : "") << (hero.Modes(AI::HEROES_WAITING) ? "WAITING," : "") << (hero.Modes(AI::HEROES_STUPID) ? "STUPID" : "")); Interface::StatusWindow & status = Interface::Basic::Get().GetStatusWindow(); while(hero.MayStillMove() && !hero.Modes(AI::HEROES_WAITING|AI::HEROES_STUPID)) { // turn indicator status.RedrawTurnProgress(3); // get task for heroes AI::HeroesGetTask(hero); // turn indicator status.RedrawTurnProgress(5); // heroes AI turn AI::HeroesMove(hero); // turn indicator status.RedrawTurnProgress(7); } DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", end"); }
std::string AI::HeroesString(const Heroes & hero) { std::ostringstream os; AIHero & ai_hero = AIHeroes::Get(hero); Queue & task = ai_hero.sheduled_visit; os << "flags : " << (hero.Modes(AI::HEROES_SCOUTER) ? "SCOUTER," : "") << (hero.Modes(AI::HEROES_HUNTER) ? "HUNTER," : "") << (hero.Modes(AI::HEROES_WAITING) ? "WAITING," : "") << (hero.Modes(AI::HEROES_STUPID) ? "STUPID" : "") << std::endl; os << "ai primary target: " << ai_hero.primary_target << std::endl << "ai sheduled visit: "; for(Queue::const_iterator it = task.begin(); it != task.end(); ++it) os << *it << "(" << MP2::StringObject(world.GetTiles(*it).GetObject()) << "), "; os << std::endl; return os.str(); }
// get priority object for AI independent of distance (1 day) bool AIHeroesPriorityObject(const Heroes & hero, s32 index) { Maps::Tiles & tile = world.GetTiles(index); if(MP2::OBJ_CASTLE == tile.GetObject()) { const Castle* castle = world.GetCastle(Maps::GetPoint(index)); if(castle) { if(hero.GetColor() == castle->GetColor()) { // maybe need join army return hero.Modes(AI::HEROES_HUNTER) && castle->GetArmy().isValid() && ! hero.isVisited(world.GetTiles(castle->GetIndex())); } else if(! hero.isFriends(castle->GetColor())) return AI::HeroesValidObject(hero, index); } } else if(MP2::OBJ_HEROES == tile.GetObject()) { // kill enemy hero const Heroes* hero2 = tile.GetHeroes(); return hero2 && ! hero.isFriends(hero2->GetColor()) && AI::HeroesValidObject(hero, index); } switch(tile.GetObject()) { case MP2::OBJ_MONSTER: case MP2::OBJ_SAWMILL: case MP2::OBJ_MINES: case MP2::OBJ_ALCHEMYLAB: case MP2::OBJ_ARTIFACT: case MP2::OBJ_RESOURCE: case MP2::OBJ_CAMPFIRE: case MP2::OBJ_TREASURECHEST: return AI::HeroesValidObject(hero, index); default: break; } return false; }
void Interface::Basic::EventSwitchHeroSleeping(void) { Heroes* hero = GetFocusHeroes(); if(hero) { if(hero->Modes(Heroes::SLEEPER)) hero->ResetModes(Heroes::SLEEPER); else { hero->SetModes(Heroes::SLEEPER); hero->GetPath().Reset(); } SetRedraw(REDRAW_HEROES); } }
bool AI::HeroesGetTask(Heroes & hero) { std::vector<s32> results; results.reserve(5); const Settings & conf = Settings::Get(); AIHero & ai_hero = AIHeroes::Get(hero); AIKingdom & ai_kingdom = AIKingdoms::Get(hero.GetColor()); Queue & task = ai_hero.sheduled_visit; IndexObjectMap & ai_objects = ai_kingdom.scans; const u8 objs1[] = { MP2::OBJ_ARTIFACT, MP2::OBJ_RESOURCE, MP2::OBJ_CAMPFIRE, MP2::OBJ_TREASURECHEST, 0 }; const u8 objs2[] = { MP2::OBJ_SAWMILL, MP2::OBJ_MINES, MP2::OBJ_ALCHEMYLAB, 0 }; const u8 objs3[] = { MP2::OBJ_CASTLE, MP2::OBJ_HEROES, MP2::OBJ_MONSTER, 0 }; // rescan path hero.RescanPath(); Castle* castle = hero.inCastle(); // if hero in castle if(castle) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", in castle"); castle->RecruitAllMonster(); hero.GetArmy().UpgradeTroops(*castle); // recruit army if(hero.Modes(AI::HEROES_HUNTER)) hero.GetArmy().JoinStrongestFromArmy(castle->GetArmy()); else if(hero.Modes(AI::HEROES_SCOUTER)) hero.GetArmy().KeepOnlyWeakestTroops(castle->GetArmy()); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", " << hero.GetArmy().String()); } // patrol task if(hero.Modes(Heroes::PATROL)) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", is patrol mode"); // goto patrol center if(hero.GetCenterPatrol() != hero.GetCenter() && hero.GetPath().Calculate(Maps::GetIndexFromAbsPoint(hero.GetCenterPatrol()))) return true; // scan enemy hero if(hero.GetSquarePatrol()) { const Maps::Indexes & results = Maps::ScanAroundObject(Maps::GetIndexFromAbsPoint(hero.GetCenterPatrol()), hero.GetSquarePatrol(), MP2::OBJ_HEROES); for(MapsIndexes::const_iterator it = results.begin(); it != results.end(); ++it) { const Heroes* enemy = world.GetTiles(*it).GetHeroes(); if(enemy && ! enemy->isFriends(hero.GetColor())) { if(hero.GetPath().Calculate(enemy->GetIndex())) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", find enemy"); return true; } } } } // can pickup objects if(conf.ExtHeroPatrolAllowPickup()) { const Maps::Indexes & results = Maps::ScanAroundObjects(hero.GetIndex(), hero.GetSquarePatrol(), objs1); for(MapsIndexes::const_iterator it = results.begin(); it != results.end(); ++it) if(AI::HeroesValidObject(hero, *it) && hero.GetPath().Calculate(*it)) { ai_objects.erase(*it); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ": find object: " << MP2::StringObject(world.GetTiles(*it).GetObject()) << "(" << *it << ")"); return true; } } // random move /* // disable move: https://sourceforge.net/tracker/?func=detail&aid=3157397&group_id=96859&atid=616180 { Maps::ScanAroundObject(hero.GetIndex(), hero.GetSquarePatrol(), MP2::OBJ_ZERO); if(results.size()) { std::random_shuffle(results.begin(), results.end()); std::vector<s32>::const_iterator it = results.begin(); for(; it != results.end(); ++it) if(world.GetTiles(*it).isPassable(&hero, Direction::CENTER, true) && hero.GetPath().Calculate(*it)) { DEBUG(DBG_AI, Color::String(hero.GetColor()) << ", Patrol " << hero.GetName() << ": move: " << *it); return; } } } */ hero.SetModes(AI::HEROES_STUPID); return false; } if(ai_hero.fix_loop > 3) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ": loop"); hero.SetModes(hero.Modes(AI::HEROES_WAITING) ? AI::HEROES_STUPID : AI::HEROES_WAITING); return false; } // primary target if(Maps::isValidAbsIndex(ai_hero.primary_target)) { if(hero.GetIndex() == ai_hero.primary_target) { ai_hero.primary_target = -1; hero.GetPath().Reset(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", reset path"); } else { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", primary target: " << ai_hero.primary_target << ", " << MP2::StringObject(world.GetTiles(ai_hero.primary_target).GetObject())); const Castle* castle = NULL; if(NULL != (castle = world.GetCastle(Maps::GetPoint(ai_hero.primary_target))) && NULL != castle->GetHeroes().Guest() && castle->isFriends(hero.GetColor())) { hero.SetModes(AI::HEROES_WAITING); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", castle busy.."); } // make path if(ai_hero.primary_target != hero.GetPath().GetDestinationIndex() && !hero.GetPath().Calculate(ai_hero.primary_target)) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", path unknown, primary target reset"); ai_hero.primary_target = -1; } } if(hero.GetPath().isValid()) return true; } // scan heroes and castle const Maps::Indexes & enemies = Maps::ScanAroundObjects(hero.GetIndex(), hero.GetScoute(), objs3); for(MapsIndexes::const_iterator it = enemies.begin(); it != enemies.end(); ++it) if(AIHeroesPriorityObject(hero, *it) && hero.GetPath().Calculate(*it)) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", set primary target: " << MP2::StringObject(world.GetTiles(*it).GetObject()) << "(" << *it << ")"); ai_hero.primary_target = *it; return true; } // check destination if(hero.GetPath().isValid()) { if(! AI::HeroesValidObject(hero, hero.GetPath().GetDestinationIndex())) hero.GetPath().Reset(); else if(hero.GetPath().size() < 5) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", continue short"); ai_hero.fix_loop++; return true; } } // scan 2x2 pickup objects Maps::Indexes pickups = Maps::ScanAroundObjects(hero.GetIndex(), 2, objs1); // scan 3x3 capture objects const Maps::Indexes & captures = Maps::ScanAroundObjects(hero.GetIndex(), 3, objs2); if(captures.size()) pickups.insert(pickups.end(), captures.begin(), captures.end()); if(pickups.size()) { hero.GetPath().Reset(); for(MapsIndexes::const_iterator it = pickups.begin(); it != pickups.end(); ++it) if(AI::HeroesValidObject(hero, *it)) { task.push_front(*it); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", find object: " << MP2::StringObject(world.GetTiles(*it).GetObject()) << "(" << *it << ")"); } } if(hero.GetPath().isValid()) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", continue"); ai_hero.fix_loop++; return true; } if(task.empty()) { // get task from kingdom DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", empty task"); AIHeroesAddedTask(hero); } else // remove invalid task task.remove_if(std::not1(std::bind1st(std::ptr_fun(&AIHeroesValidObject2), &hero))); // random shuffle if(1 < task.size() && Rand::Get(1)) { Queue::iterator it1, it2; it2 = it1 = task.begin(); ++it2; std::swap(*it1, *it2); } // find passable index while(task.size()) { const s32 & index = task.front(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", look for: " << MP2::StringObject(world.GetTiles(index).GetObject()) << "(" << index << ")"); if(hero.GetPath().Calculate(index)) break; DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " say: unable get object: " << index << ", remove task..."); task.pop_front(); } // success if(task.size()) { const s32 & index = task.front(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " go to: " << index); ai_objects.erase(index); task.pop_front(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", route: " << hero.GetPath().String()); return true; } else if(hero.Modes(AI::HEROES_WAITING)) { hero.GetPath().Reset(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " say: unknown task., help my please.."); hero.ResetModes(AI::HEROES_WAITING); hero.SetModes(AI::HEROES_STUPID); } else { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " say: waiting..."); hero.SetModes(AI::HEROES_WAITING); } return false; }
bool AI::HeroesCanMove(const Heroes & hero) { return hero.MayStillMove() && ! hero.Modes(HEROES_MOVED); }