void Battle::EagleEyeSkillAction(HeroBase & hero, const SpellStorage & spells, bool local)
{
    if(spells.empty() ||
	!hero.HaveSpellBook()) return;

    SpellStorage new_spells;
    new_spells.reserve(10);

    const Skill::Secondary eagleeye(Skill::Secondary::EAGLEEYE, hero.GetLevelSkill(Skill::Secondary::EAGLEEYE));

    // filter spells
    for(SpellStorage::const_iterator
	it = spells.begin(); it != spells.end(); ++it)
    {
	const Spell & sp = *it;
    	if(!hero.HaveSpell(sp))
	{
	    switch(eagleeye.Level())
	    {
		case Skill::Level::BASIC:
		    // 20%
		    if(3 > sp.Level() && eagleeye.GetValues() >= Rand::Get(1, 100)) new_spells.push_back(sp);
		    break;
		case Skill::Level::ADVANCED:
		    // 30%
		    if(4 > sp.Level() && eagleeye.GetValues() >= Rand::Get(1, 100)) new_spells.push_back(sp);
		    break;
		case Skill::Level::EXPERT:
		    // 40%
		    if(5 > sp.Level() && eagleeye.GetValues() >= Rand::Get(1, 100)) new_spells.push_back(sp);
		    break;
		default: break;
    	    }
	}
    }

    // add new spell
    for(SpellStorage::const_iterator
	it = new_spells.begin(); it != new_spells.end(); ++it)
    {
	const Spell & sp = *it;
	if(local)
	{
	    std::string msg = _("Through eagle-eyed observation, %{name} is able to learn the magic spell %{spell}.");
	    String::Replace(msg, "%{name}", hero.GetName());
	    String::Replace(msg, "%{spell}", sp.GetName());
	    Game::PlayPickupSound();
	    Dialog::SpellInfo("", msg, sp);
	}
    }

    hero.AppendSpellsToBook(new_spells, true);
}
void Heroes::ScholarAction(Heroes & hero1, Heroes & hero2)
{
    if(! hero1.HaveSpellBook() || ! hero2.HaveSpellBook())
    {
	DEBUG(DBG_GAME, DBG_INFO, "spell_book disabled");
	return;
    }
    else
    if(! Settings::Get().ExtWorldEyeEagleAsScholar())
    {
	DEBUG(DBG_GAME, DBG_WARN, "EyeEagleAsScholar settings disabled");
	return;
    }

    const u8 scholar1 = hero1.GetLevelSkill(Skill::Secondary::EAGLEEYE);
    const u8 scholar2 = hero2.GetLevelSkill(Skill::Secondary::EAGLEEYE);
    u8 scholar = 0;

    Heroes* teacher = NULL;
    Heroes* learner = NULL;

    if(scholar1 && scholar1 >= scholar2)
    {
	teacher = &hero1;
	learner = &hero2;
	scholar = scholar1;
    }
    else
    if(scholar2 && scholar2 >= scholar1)
    {
	teacher = &hero2;
	learner = &hero1;
	scholar = scholar2;
    }
    else
    {
	DEBUG(DBG_GAME, DBG_WARN, "Eagle Eye skill not found");
	return;
    }

    // skip bag artifacts
    SpellStorage teach = teacher->spell_book.SetFilter(SpellBook::ALL);
    SpellStorage learn = learner->spell_book.SetFilter(SpellBook::ALL);

    // remove_if for learn spells
    if(learn.size())
    {
	SpellStorage::iterator
	    res = std::remove_if(learn.begin(), learn.end(), std::bind1st(HeroesHaveSpell(), teacher));
	learn.resize(std::distance(learn.begin(), res));
    }

    if(learn.size())
    {
	SpellStorage::iterator
	    res = std::remove_if(learn.begin(), learn.end(), std::not1(std::bind1st(HeroesCanTeachSpell(), teacher)));
	learn.resize(std::distance(learn.begin(), res));
    }

    // remove_if for teach spells
    if(teach.size())
    {
	SpellStorage::iterator
	    res = std::remove_if(teach.begin(), teach.end(), std::bind1st(HeroesHaveSpell(), learner));
	teach.resize(std::distance(teach.begin(), res));
    }

    if(teach.size())
    {
	SpellStorage::iterator
	    res = std::remove_if(teach.begin(), teach.end(), std::not1(std::bind1st(HeroesCanTeachSpell(), teacher)));
	teach.resize(std::distance(teach.begin(), res));
    }

    std::string message, spells1, spells2;

    // learning
    for(SpellStorage::const_iterator
	it = learn.begin(); it != learn.end(); ++it)
    {
	teacher->AppendSpellToBook(*it);
	if(spells1.size())
	    spells1.append(it + 1 == learn.end() ? _(" and ") : ", ");
	spells1.append((*it).GetName());
    }

    // teacher
    for(SpellStorage::const_iterator
	it = teach.begin(); it != teach.end(); ++it)
    {
	learner->AppendSpellToBook(*it);
	if(spells2.size())
	    spells2.append(it + 1 == teach.end() ? _(" and ") : ", ");
	spells2.append((*it).GetName());
    }


    if((CONTROL_HUMAN & teacher->GetControl()) || (CONTROL_HUMAN & learner->GetControl()))
    {
	if(spells1.size() && spells2.size())
	    message = _("%{teacher}, whose %{level} %{scholar} knows many magical secrets, learns %{spells1} from %{learner}, and teaches %{spells2} to %{learner}.");
	else
	if(spells1.size())
	    message = _("%{teacher}, whose %{level} %{scholar} knows many magical secrets, learns %{spells1} from %{learner}.");
	else
	if(spells2.size())
	    message = _("%{teacher}, whose %{level} %{scholar} knows many magical secrets, teaches %{spells2} to %{learner}.");

	if(message.size())
	{
	    StringReplace(message, "%{teacher}", teacher->GetName());
	    StringReplace(message, "%{learner}", learner->GetName());
	    StringReplace(message, "%{level}", Skill::Level::String(scholar));
	    StringReplace(message, "%{scholar}", Skill::Secondary::String(Skill::Secondary::EAGLEEYE));
	    StringReplace(message, "%{spells1}", spells1);
	    StringReplace(message, "%{spells2}", spells2);

	    Dialog::Message(_("Scholar Ability"), message, Font::BIG, Dialog::OK);
	}
    }
}
void HeroBase::AppendSpellsToBook(const SpellStorage & spells, bool without_wisdom)
{
    for(SpellStorage::const_iterator
	it = spells.begin(); it != spells.end(); ++it)
	AppendSpellToBook(*it, without_wisdom);
}