Пример #1
0
void AICastleDefense(Castle & c)
{
    if(c.isCastle())
    {
        if(!c.isBuild(BUILD_LEFTTURRET))
		c.BuyBuilding(BUILD_LEFTTURRET);

        if(!c.isBuild(BUILD_RIGHTTURRET))
		c.BuyBuilding(BUILD_RIGHTTURRET);

        if(!c.isBuild(BUILD_MOAT))
    		c.BuyBuilding(BUILD_MOAT);

        if(!c.isBuild(BUILD_CAPTAIN) && NULL == c.GetHeroes().Guest())
		c.BuyBuilding(BUILD_CAPTAIN);

        if(!c.isBuild(BUILD_TAVERN) && Race::KNGT == c.GetRace())
		c.BuyBuilding(BUILD_TAVERN);

        if(!c.isBuild(BUILD_SPEC))
		c.BuyBuilding(BUILD_SPEC);
    }
    c.RecruitAllMonster();
}
Пример #2
0
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;
}
Пример #3
0
void AI::CastlePreBattle(Castle & castle)
{
    Heroes* hero = castle.GetHeroes().GuardFirst();
    if(hero && castle.GetArmy().isValid())
	hero->GetArmy().JoinStrongestFromArmy(castle.GetArmy());
}
Пример #4
0
void AI::CastleTurn(Castle & castle)
{
    // skip neutral town
    if(castle.GetColor() != Color::NONE)
    {
	s32 range = Game::GetViewDistance(castle.isCastle() ? Game::VIEW_CASTLE : Game::VIEW_TOWN);
	const Heroes* enemy = NULL;

	// find enemy hero
	for(s32 y = -range; y <= range; ++y)
    	    for(s32 x = -range; x <= range; ++x)
	{
    	    if(!y && !x) continue;
	    const Point & center = castle.GetCenter();

    	    if(Maps::isValidAbsPoint(center.x + x, center.y + y))
    	    {
        	const Maps::Tiles & tile = world.GetTiles(Maps::GetIndexFromAbsPoint(center.x + x, center.y + y));

        	if(MP2::OBJ_HEROES == tile.GetObject())
		    enemy = tile.GetHeroes();

		if(enemy && castle.GetColor() == enemy->GetColor())
		    enemy = NULL;

		if(enemy) break;
	    }
	}

	enemy ? AICastleDefense(castle) : AICastleDevelopment(castle);

	Kingdom & kingdom = castle.GetKingdom();
	bool can_recruit = castle.isCastle() && kingdom.GetHeroes().size() < Kingdom::GetMaxHeroes();

	// part II
	if(enemy &&
	    castle.GetArmy().isValid() &&
	    Army::TroopsStrongerEnemyTroops(castle.GetArmy(), enemy->GetArmy()))
	{
    	    if(!castle.GetHeroes().Guest() && can_recruit)
    	    {
        	Recruits & rec = kingdom.GetRecruits();

        	if(rec.GetHero1()) castle.RecruitHero(rec.GetHero1());
        	else
        	if(rec.GetHero2()) castle.RecruitHero(rec.GetHero2());
    	    }

    	    if(castle.GetHeroes().Guest())
		castle.GetHeroes().Guest()->SetModes(AI::HEROES_HUNTER);
	}

	// part III
	AIKingdom & ai = AIKingdoms::Get(castle.GetColor());
	if(ai.capital != &castle &&
	    castle.GetArmy().isValid() &&
	    ! castle.GetHeroes().Guest() &&
	    2 < castle.GetArmy().GetCount() &&
	    150 < castle.GetArmy().GetHitPoints() &&
	    can_recruit)
	{
    	    Recruits & rec = kingdom.GetRecruits();

    	    if(rec.GetHero1()) castle.RecruitHero(rec.GetHero1());
    	    else
    	    if(rec.GetHero2()) castle.RecruitHero(rec.GetHero2());

    	    if(castle.GetHeroes().Guest())
		castle.GetHeroes().Guest()->SetModes(AI::HEROES_HUNTER|AI::HEROES_SCOUTER);
	}
    }
}