示例#1
0
bool AI::BattleMagicTurn(Arena & arena, const Unit & b, Actions & a, const Unit* enemy)
{
    const HeroBase* hero = b.GetCommander();

    if(b.Modes(SP_BERSERKER) || !hero || hero->Modes(Heroes::SPELLCASTED) || !hero->HaveSpellBook() ||
	arena.isDisableCastSpell(Spell(), NULL) || a.HaveCommand(Battle::MSG_BATTLE_CAST))
	return false;

    const Force & my_army = arena.GetForce(b.GetArmyColor(), false);
    const Force & enemy_army = arena.GetForce(b.GetArmyColor(), true);

    Units friends(my_army, true);
    Units enemies(enemy_army, true);

    // sort strongest
    friends.SortStrongest();

    // troop bad spell - clean
    {
	// sort strongest
	Units::iterator it = std::find_if(friends.begin(), friends.end(),
					    std::bind2nd(std::mem_fun(&Unit::Modes), IS_BAD_MAGIC));
	if(it != friends.end())
	{
	    if(AIApplySpell(Spell::DISPEL, *it, *hero, a)) return true;
	    if(AIApplySpell(Spell::CURE, *it, *hero, a)) return true;
	}
    }

    // area damage spell
    {
	const u8 areasp[] = { Spell::METEORSHOWER, Spell::FIREBLAST, Spell::CHAINLIGHTNING, Spell::FIREBALL, Spell::COLDRING };
	s16 dst = AIAreaSpellDst(*hero);

	if(Board::isValidIndex(dst))
	for(u8 ii = 0; ii < ARRAY_COUNT(areasp); ++ii)
	{
	    if(hero->CanCastSpell(areasp[ii]))
	    {
		a.push_back(Battle::Command(MSG_BATTLE_CAST, areasp[ii], dst));
		return true;
	    }
	}
    }

    // if handfighting
    if(enemy)
    {
	// kill dragons
	if(enemy->isDragons() &&
	    !b.Modes(SP_DRAGONSLAYER) && AIApplySpell(Spell::DRAGONSLAYER, &b, *hero, a)) return true;

	// curse
	if(!enemy->Modes(SP_CURSE) && AIApplySpell(Spell::CURSE, enemy, *hero, a)) return true;
	// enemy good spell - clean
	if(enemy->Modes(IS_GOOD_MAGIC) && AIApplySpell(Spell::DISPEL, enemy, *hero, a)) return true;

	// up defense
	if(!b.Modes(SP_STEELSKIN) && !b.Modes(SP_STONESKIN) && AIApplySpell(Spell::STEELSKIN, &b, *hero, a)) return true;
	if(!b.Modes(SP_STONESKIN) && !b.Modes(SP_STEELSKIN) && AIApplySpell(Spell::STONESKIN, &b, *hero, a)) return true;
    }

    // my army blessing
    if(b.isArchers())
    {
	if(!b.Modes(SP_BLESS) && AIApplySpell(Spell::BLESS, &b, *hero, a)) return true;
	if(!b.Modes(SP_BLOODLUST) && AIApplySpell(Spell::BLOODLUST, &b, *hero, a)) return true;
    }

    // up speed
    if(hero->HaveSpell(Spell::HASTE) && !enemy)
    {
	// sort strongest
	Units::iterator it = std::find_if(friends.begin(), friends.end(),
					    std::not1(std::bind2nd(std::mem_fun(&Unit::Modes), SP_HASTE)));
	if(it != friends.end() &&
		AIApplySpell(Spell::HASTE, *it, *hero, a)) return true;
    }

    // shield spell conditions
    {
	Units::iterator it = std::find_if(enemies.begin(), enemies.end(),
					    std::mem_fun(&Unit::isArchers));

	const Castle* castle = Arena::GetCastle();

	// find enemy archers
	if(it != enemies.end() ||
	// or archers tower
	    (castle && castle->GetColor() != b.GetColor() && castle->isCastle()))
	{
	    // find strongest archers
	    for(it = friends.begin(); it != friends.end(); ++it)
		if((*it)->isArchers() && ! (*it)->Modes(SP_SHIELD)) break;

	    // or other strongest friends
	    if(it == friends.end())
		it = std::find_if(friends.begin(), friends.end(),
				std::not1(std::bind2nd(std::mem_fun(&Unit::Modes), SP_SHIELD)));

	    if(it != friends.end() &&
		    AIApplySpell(Spell::SHIELD, *it, *hero, a)) return true;
	}
    }


    // enemy army spell
    {
	// find mirror image or summon elem
	Units::iterator it = std::find_if(enemies.begin(), enemies.end(),
					    std::bind2nd(std::mem_fun(&Unit::Modes), CAP_MIRRORIMAGE | CAP_SUMMONELEM));

	if(it != enemies.end())
	{
	    if(AIApplySpell(Spell::ARROW, *it, *hero, a)) return true;
	    if(AIApplySpell(Spell::LIGHTNINGBOLT, *it, *hero, a)) return true;
	}

	// find good magic
	it = std::find_if(enemies.begin(), enemies.end(),
					std::bind2nd(std::mem_fun(&Unit::Modes), IS_GOOD_MAGIC));

	if(it != enemies.end())
	{
	    // slow
	    if((*it)->Modes(SP_HASTE) && AIApplySpell(Spell::SLOW, *it, *hero, a)) return true;
	    // curse
	    if((*it)->Modes(SP_CURSE) && AIApplySpell(Spell::CURSE, *it, *hero, a)) return true;
	    //
	    if(AIApplySpell(Spell::DISPEL, *it, *hero, a)) return true;
	}

	// check undead
	if(std::count_if(friends.begin(), friends.end(), std::mem_fun(&Unit::isUndead)) <
		    std::count_if(enemies.begin(), enemies.end(), std::mem_fun(&Unit::isUndead)))
	{
	    if(AIApplySpell(Spell::HOLYSHOUT, NULL, *hero, a)) return true;
	    if(AIApplySpell(Spell::HOLYWORD, NULL, *hero, a)) return true;
	}

	// check alife
	if(std::count_if(friends.begin(), friends.end(), std::mem_fun(&Unit::isAlive)) <
		    std::count_if(enemies.begin(), enemies.end(), std::mem_fun(&Unit::isAlive)))
	{
	    if(AIApplySpell(Spell::DEATHRIPPLE, NULL, *hero, a)) return true;
	    if(AIApplySpell(Spell::DEATHWAVE, NULL, *hero, a)) return true;
	}

	Unit* stats = *Rand::Get(enemies);

	if(AIApplySpell(Spell::LIGHTNINGBOLT, stats, *hero, a)) return true;
	if(AIApplySpell(Spell::ARROW, stats, *hero, a)) return true;
    }

/*
    FIX: Damage Spell:
*/

    if(AIApplySpell(Spell::ARMAGEDDON, NULL, *hero, a)) return true;
    if(AIApplySpell(Spell::ELEMENTALSTORM, NULL, *hero, a)) return true;

    return false;
}