void Interface::Basic::EventDefaultAction(void)
{
    Heroes* hero = GetFocusHeroes();

    if(hero)
    {
	const Maps::Tiles & tile = world.GetTiles(hero->GetIndex());

	// 1. action object
	if(MP2::isActionObject(hero->GetMapsObject(), hero->isShipMaster()) &&
	    (! MP2::isMoveObject(hero->GetMapsObject()) || hero->CanMove()))
	{
	    hero->Action(hero->GetIndex());
	    if(MP2::OBJ_STONELIGHTS == tile.GetObject(false) || MP2::OBJ_WHIRLPOOL == tile.GetObject(false))
		SetRedraw(REDRAW_HEROES);
	    SetRedraw(REDRAW_GAMEAREA);
	}
	else
	// 2. continue
        if(hero->GetPath().isValid())
    	    hero->SetMove(true);
	else
	// 3. hero dialog
	    Game::OpenHeroesDialog(*hero);
    }
    else
    // 4. town dialog
    if(GetFocusCastle())
    {
	Game::OpenCastleDialog(*GetFocusCastle());
    }
}
Beispiel #2
0
s32  GetRandomHeroesPosition(Heroes & hero, u32 scoute)
{
    Maps::Indexes v = Maps::GetAroundIndexes(hero.GetIndex(), scoute, true);
    Maps::Indexes res;

    v.resize(std::distance(v.begin(),
	std::remove_if(v.begin(), v.end(), std::ptr_fun(&Maps::TileIsUnderProtection))));

#if defined(ANDROID)
    const MapsIndexes::const_reverse_iterator crend = v.rend();

    for(MapsIndexes::const_reverse_iterator
	it = v.rbegin(); it != crend && res.size() < 4; ++it)
#else
    for(MapsIndexes::const_reverse_iterator
	it = v.rbegin(); it != v.rend() && res.size() < 4; ++it)
#endif
    {
        if(world.GetTiles(*it).isPassable(&hero, Direction::CENTER, true) &&
	    hero.GetPath().Calculate(*it))
	    res.push_back(*it);
    }

    const s32 result = res.size() ? *Rand::Get(res) : -1;

    if(0 <= result)
    {
	DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) <<
                ", hero: " << hero.GetName() << ", added task: " << result);
    }

    return result;
}
Beispiel #3
0
bool HeroesTownGate(Heroes & hero, const Castle* castle)
{
    if(castle)
    {
        Interface::Basic & I = Interface::Basic::Get();

        const s32 src = hero.GetIndex();
        const s32 dst = castle->GetIndex();

        if(!Maps::isValidAbsIndex(src) || !Maps::isValidAbsIndex(dst))
            return false;

        AGG::PlaySound(M82::KILLFADE);
        hero.GetPath().Hide();
        hero.FadeOut();

        Cursor::Get().Hide();
        hero.Move2Dest(dst);

        I.gameArea.SetCenter(hero.GetCenter());
        GameFocus::SetRedraw();
        I.Redraw();

        AGG::PlaySound(M82::KILLFADE);
        hero.GetPath().Hide();
        hero.FadeIn();

        // educate spells
        if(! Settings::Get().ExtHeroLearnSpellsWithDay()) castle->MageGuildEducateHero(hero);

        return true;
    }
    return false;
}
Beispiel #4
0
bool ActionSpellSetGuardian(Heroes & hero, const Spell & spell, u8 id)
{
    Maps::Tiles & tile = world.GetTiles(hero.GetIndex());

    if(MP2::OBJ_MINES != tile.GetObject(false))
    {
        Dialog::Message("", _("You must be standing on the entrance to a mine (sawmills and alchemists don't count) to cast this spell."), Font::BIG, Dialog::OK);
        return false;
    }

    const u16 count = hero.GetPower() * spell.ExtraValue();

    if(count)
    {
        Maps::TilesAddon* addon = tile.FindObject(MP2::OBJ_MINES);

        if(addon)
            addon->tmp = spell();

        if(spell == Spell::HAUNT)
        {
            world.CaptureObject(tile.GetIndex(), Color::UNUSED);
            tile.SetObject(MP2::OBJ_ABANDONEDMINE);
        }

        Army::Troop troop = world.GetCapturedObject(tile.GetIndex()).GetTroop();
        troop.Set(Monster(spell), count);
    }

    return false;
}
int Interface::Basic::EventDigArtifact(void)
{
    Heroes* hero = GetFocusHeroes();

    if(hero)
    {
	if(hero->isShipMaster())
    	    Dialog::Message("", _("Try looking on land!!!"), Font::BIG, Dialog::OK);
	else
	if(hero->GetMaxMovePoints() <= hero->GetMovePoints())
	{
	    if(world.GetTiles(hero->GetIndex()).GoodForUltimateArtifact())
    	    {
    		AGG::PlaySound(M82::DIGSOUND);

    		hero->ResetMovePoints();

    		if(world.DiggingForUltimateArtifact(hero->GetCenter()))
    		{
        	    AGG::PlaySound(M82::TREASURE);
        	    const Artifact & ultimate = world.GetUltimateArtifact().GetArtifact();
        	    hero->PickupArtifact(ultimate);
        	    std::string msg(_("After spending many hours digging here, you have uncovered the %{artifact}"));
        	    StringReplace(msg, "%{artifact}", ultimate.GetName());
        	    Dialog::ArtifactInfo(_("Congratulations!"), msg, ultimate());

        	    // set all obelisks visited
		    Kingdom & kingdom = world.GetKingdom(hero->GetColor());
		    const MapsIndexes obelisks = Maps::GetObjectPositions(MP2::OBJ_OBELISK, true);
    
        	    for(MapsIndexes::const_iterator
			it = obelisks.begin(); it != obelisks.end(); ++it)
			if(!hero->isVisited(world.GetTiles(*it), Visit::GLOBAL))
                	hero->SetVisited(*it, Visit::GLOBAL);

    	            kingdom.PuzzleMaps().Update(kingdom.CountVisitedObjects(MP2::OBJ_OBELISK), world.CountObeliskOnMaps());
    		}
    		else
        	    Dialog::Message("", _("Nothing here. Where could it be?"), Font::BIG, Dialog::OK);

    		Cursor::Get().Hide();
    		iconsPanel.RedrawIcons(ICON_HEROES);
    		Cursor::Get().Show();
    		Display::Get().Flip();

		// check game over for ultimate artifact
		return GameOver::Result::Get().LocalCheckGameOver();
    	    }
    	    else
		Dialog::Message("", _("Try searching on clear ground."), Font::BIG, Dialog::OK);
	}
    }
    else
        Dialog::Message("", _("Digging for artifacts requires a whole day, try again tomorrow."), Font::BIG, Dialog::OK);

    return Game::CANCEL;
}
Beispiel #6
0
bool ActionSpellSummonBoat(Heroes & hero)
{
    u8 chance = 0;

    switch(hero.GetLevelSkill(Skill::Secondary::WISDOM))
    {
    case Skill::Level::BASIC:
        chance = 50;
        break;
    case Skill::Level::ADVANCED:
        chance = 75;
        break;
    case Skill::Level::EXPERT:
        chance = 100;
        break;
    default:
        chance = 30;
        break;
    }

    const s32 center = hero.GetIndex();

    // find water
    s32 dst_water = -1;
    const MapsIndexes & v = Maps::ScanAroundObject(center, MP2::OBJ_ZERO);
    for(MapsIndexes::const_iterator
            it = v.begin(); it != v.end(); ++it)
    {
        if(world.GetTiles(*it).isWater()) {
            dst_water = *it;
            break;
        }
    }

    const MapsIndexes & boats = Maps::GetObjectPositions(center, MP2::OBJ_BOAT, false);

    if(boats.empty())
    {
        DEBUG(DBG_GAME, DBG_WARN, "free boat: " << "not found");
    }
    else
    {
        const s32 & src = boats.front();

        if(Rand::Get(1, 100) <= chance &&
                Maps::isValidAbsIndex(src) && Maps::isValidAbsIndex(dst_water))
        {
            world.GetTiles(src).SetObject(MP2::OBJ_ZERO);
            world.GetTiles(dst_water).SetObject(MP2::OBJ_BOAT);
        }
        else
            DialogSpellFailed(Spell::SUMMONBOAT);
    }

    return true;
}
Beispiel #7
0
void AIHeroesAddedRescueTask(Heroes & hero)
{
    AIHero & ai_hero = AIHeroes::Get(hero);
    Queue & task = ai_hero.sheduled_visit;

    DEBUG(DBG_AI, DBG_TRACE, hero.GetName());

    u32 scoute = hero.GetScoute();

    switch(Settings::Get().GameDifficulty())
    {
        case Difficulty::NORMAL:    scoute += 2; break;
        case Difficulty::HARD:      scoute += 3; break;
        case Difficulty::EXPERT:    scoute += 4; break;
        case Difficulty::IMPOSSIBLE:scoute += 6; break;
        default: break;
    }

    // find unchartered territory
    s32 index = FindUncharteredTerritory(hero, scoute);
    const Maps::Tiles & tile = world.GetTiles(hero.GetIndex());

    if(index < 0)
    {
	// check teleports
	if(MP2::OBJ_STONELIGHTS == tile.GetObject(false) ||
	    MP2::OBJ_WHIRLPOOL == tile.GetObject(false))
	{
	    AI::HeroesAction(hero, hero.GetIndex());
	}
	else
	{
	    // random
	    index = GetRandomHeroesPosition(hero, scoute);
	}
    }

    if(0 <= index) task.push_back(index);
}
void Interface::Basic::MoveHeroFromArrowKeys(Heroes & hero, int direct)
{
    if(Maps::isValidDirection(hero.GetIndex(), direct))
    {
        s32 dst = Maps::GetDirectionIndex(hero.GetIndex(), direct);
        const Maps::Tiles & tile = world.GetTiles(dst);
        bool allow = false;

        switch(tile.GetObject())
        {
            case MP2::OBJN_CASTLE:
            {
                const Castle* to_castle = world.GetCastle(hero.GetCenter());
                if(to_castle)
                {
                    dst = to_castle->GetIndex();
                    allow = true;
                }
                break;
            }

            case MP2::OBJ_BOAT:
            case MP2::OBJ_CASTLE:
            case MP2::OBJ_HEROES:
            case MP2::OBJ_MONSTER:
                allow = true;
                break;

            default:
                allow = (tile.isPassable(&hero, Direction::CENTER, false) ||
                                MP2::isActionObject(tile.GetObject(), hero.isShipMaster()));
                break;
        }

        if(allow) ShowPathOrStartMoveHero(&hero, dst);
    }
}
Beispiel #9
0
void AI::HeroesActionNewPosition(Heroes & hero)
{
    AIHero & ai_hero = AIHeroes::Get(hero);
    //AIKingdom & ai_kingdom = AIKingdoms::Get(hero.GetColor());
    Queue & task = ai_hero.sheduled_visit;

    const u8 objs[] = { MP2::OBJ_ARTIFACT, MP2::OBJ_RESOURCE, MP2::OBJ_CAMPFIRE, MP2::OBJ_TREASURECHEST, 0 };
    Maps::Indexes pickups = Maps::ScanAroundObjects(hero.GetIndex(), objs);

    if(pickups.size() && hero.GetPath().isValid() &&
	pickups.end() == std::find(pickups.begin(), pickups.end(), hero.GetPath().GetDestinationIndex()))
	hero.GetPath().Reset();

    for(MapsIndexes::const_iterator
	it = pickups.begin(); it != pickups.end(); ++it)
	if(*it != hero.GetPath().GetDestinationIndex())
	    task.push_front(*it);
}
Beispiel #10
0
bool ActionSpellDimensionDoor(Heroes & hero)
{
    const u8 distance = Spell::CalculateDimensionDoorDistance(hero.GetPower(), hero.GetArmy().GetHitPoints());

    Interface::Basic & I = Interface::Basic::Get();
    Cursor & cursor = Cursor::Get();

    // center hero
    cursor.Hide();
    I.gameArea.SetCenter(hero.GetCenter());
    GameFocus::SetRedraw();
    I.Redraw();

    const s32 src = hero.GetIndex();
    // get destination
    const s32 dst = I.GetDimensionDoorDestination(src, distance, hero.isShipMaster());

    if(Maps::isValidAbsIndex(src) && Maps::isValidAbsIndex(dst))
    {
        AGG::PlaySound(M82::KILLFADE);
        hero.GetPath().Reset();
        hero.FadeOut();

        hero.SpellCasted(Spell::DIMENSIONDOOR);

        cursor.Hide();
        hero.Move2Dest(dst, true);

        I.gameArea.SetCenter(hero.GetCenter());
        GameFocus::SetRedraw();
        I.Redraw();

        AGG::PlaySound(M82::KILLFADE);
        hero.FadeIn();

        hero.ActionNewPosition();

        return false; /* SpellCasted apply */
    }

    return false;
}
Beispiel #11
0
bool ActionSpellTownGate(Heroes & hero)
{
    const Kingdom & kingdom = world.GetKingdom(hero.GetColor());
    const KingdomCastles & castles = kingdom.GetCastles();
    KingdomCastles::const_iterator it;

    const Castle* castle = NULL;
    const s32 center = hero.GetIndex();
    s32 min = -1;

    // find the nearest castle
    for(it = castles.begin(); it != castles.end(); ++it) if(*it && !(*it)->GetHeroes().Guest())
        {
            const u16 min2 = Maps::GetApproximateDistance(center, (*it)->GetIndex());
            if(0 > min || min2 < min)
            {
                min = min2;
                castle = *it;
            }
        }

    Interface::Basic & I = Interface::Basic::Get();
    Cursor & cursor = Cursor::Get();

    // center hero
    cursor.Hide();
    I.gameArea.SetCenter(hero.GetCenter());
    GameFocus::SetRedraw();
    I.Redraw();

    if(!castle)
    {
        Dialog::Message("", _("No avaialble town. Spell Failed!!!"), Font::BIG, Dialog::OK);
        return false;
    }

    return HeroesTownGate(hero, castle);
}
Beispiel #12
0
s32  FindUncharteredTerritory(Heroes & hero, const u8 & scoute)
{
    Maps::Indexes v = Maps::GetAroundIndexes(hero.GetIndex(), scoute, true);
    Maps::Indexes res;

    v.resize(std::distance(v.begin(),
	std::remove_if(v.begin(), v.end(), std::ptr_fun(&Maps::TileIsUnderProtection))));


#if (__GNUC__ == 3 && __GNUC_MINOR__ == 4)
    const MapsIndexes::const_reverse_iterator crend = v.rend();

    for(MapsIndexes::const_reverse_iterator
	it = v.rbegin(); it != crend && res.size() < 4; ++it)
#else
    MapsIndexes::reverse_iterator it = v.rbegin();
    for(; it != v.rend() && (res.size() < 4); ++it)
#endif
    {
	// find fogs
	if(world.GetTiles(*it).isFog(hero.GetColor()) &&
    	    world.GetTiles(*it).isPassable(&hero, Direction::CENTER, true) &&
	    hero.GetPath().Calculate(*it))
	    res.push_back(*it);
    }

    const s32 result = res.size() ? *Rand::Get(res) : -1;

    if(0 <= result)
    {
	DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) <<
                ", hero: " << hero.GetName() << ", added task: " << result);
    }

    return result;
}
Beispiel #13
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;
}
Beispiel #14
0
void AIHeroesAddedTask(Heroes & hero)
{
    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;

    // load minimal distance tasks
    std::vector<IndexDistance> objs;
    objs.reserve(ai_objects.size());

    for(std::map<s32, int>::const_iterator
	it = ai_objects.begin(); it != ai_objects.end(); ++it)
    {
	const Maps::Tiles & tile = world.GetTiles((*it).first);

	if(hero.isShipMaster())
	{
	    if(MP2::OBJ_COAST != tile.GetObject() &&
		! tile.isWater()) continue;

	    // check previous positions
	    if(MP2::OBJ_COAST == (*it).second &&
		hero.isVisited(world.GetTiles((*it).first))) continue;
	}
	else
	{
	    if(tile.isWater() && MP2::OBJ_BOAT != tile.GetObject()) continue;
	}

	objs.push_back(IndexDistance((*it).first,
			    Maps::GetApproximateDistance(hero.GetIndex(), (*it).first)));
    }

    DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) <<
		    ", hero: " << hero.GetName() << ", task prepare: " << objs.size());

    std::sort(objs.begin(), objs.end(), IndexDistance::Shortest);

    for(std::vector<IndexDistance>::const_iterator
	it = objs.begin(); it != objs.end(); ++it)
    {
	if(task.size() >= HERO_MAX_SHEDULED_TASK) break;
	const bool validobj = AI::HeroesValidObject(hero, (*it).first);

	if(validobj &&
	    hero.GetPath().Calculate((*it).first))
	{
	    DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) <<
		    ", hero: " << hero.GetName() << ", added tasks: " <<
		    MP2::StringObject(ai_objects[(*it).first]) << ", index: " << (*it).first <<
		    ", distance: " << (*it).second);

	    task.push_back((*it).first);
	    ai_objects.erase((*it).first);
	}
	else
	{
	    DEBUG(DBG_AI, DBG_TRACE, Color::String(hero.GetColor()) <<
		    ", hero: " << hero.GetName() << (!validobj ? ", invalid: " : ", impossible: ") <<
		    MP2::StringObject(ai_objects[(*it).first]) << ", index: " << (*it).first <<
		    ", distance: " << (*it).second);
	}
    }

    if(task.empty())
	AIHeroesAddedRescueTask(hero);
}
bool PassableFromToTile(const Heroes & hero, s32 from, const s32 & to, int direct, s32 dst)
{
    const Maps::Tiles & fromTile = world.GetTiles(from);
    const Maps::Tiles & toTile = world.GetTiles(to);

    // check start point
    if(hero.GetIndex() == from)
    {
	if(MP2::isActionObject(fromTile.GetObject(false), hero.isShipMaster()))
	{
	    // check direct from object
	    if(! (direct & fromTile.GetPassable()))
		return false;
	}
	else
	{
	    // check from tile direct
	    if(! fromTile.isPassable(&hero, direct, (hero.isControlAI() ? AI::HeroesSkipFog() : false)))
		return false;
	}
    }
    else
    {
	if(MP2::isActionObject(fromTile.GetObject(), hero.isShipMaster()))
	{
	    // check direct from object
	    if(! (direct & fromTile.GetPassable()))
		return false;
	}
	else
	{
	    // check from tile direct
	    if(! fromTile.isPassable(&hero, direct, (hero.isControlAI() ? AI::HeroesSkipFog() : false)))
		return false;
	}
    }

    if(fromTile.isWater() && !toTile.isWater())
    {
	switch(toTile.GetObject())
	{
	    case MP2::OBJ_BOAT:
            case MP2::OBJ_MONSTER:
            case MP2::OBJ_HEROES:
                return false;

	    case MP2::OBJ_COAST:
		return toTile.GetIndex() == dst;

	    default: break;
	}
    }
    else
    if(!fromTile.isWater() && toTile.isWater())
    {
	switch(toTile.GetObject())
	{
	    case MP2::OBJ_BOAT:
                return true;

            case MP2::OBJ_HEROES:
		return toTile.GetIndex() == dst;

	    default: break;
	}
    }

    // check corner water/coast
    if(hero.isShipMaster() && 
	(direct & (Direction::TOP_LEFT | Direction::TOP_RIGHT | Direction::BOTTOM_RIGHT | Direction::BOTTOM_LEFT)))
    {
	switch(direct)
	{
	    case Direction::TOP_LEFT:
		if((Maps::isValidDirection(from, Direction::TOP) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::TOP)).isWater()) ||
		   (Maps::isValidDirection(from, Direction::LEFT) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::LEFT)).isWater()))
		    return false;
		break;

	    case Direction::TOP_RIGHT:
		if((Maps::isValidDirection(from, Direction::TOP) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::TOP)).isWater()) ||
		   (Maps::isValidDirection(from, Direction::RIGHT) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::RIGHT)).isWater()))
		    return false;
		break;

	    case Direction::BOTTOM_RIGHT:
		if((Maps::isValidDirection(from, Direction::BOTTOM) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::BOTTOM)).isWater()) ||
		   (Maps::isValidDirection(from, Direction::RIGHT) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::RIGHT)).isWater()))
		    return false;
		break;

	    case Direction::BOTTOM_LEFT:
		if((Maps::isValidDirection(from, Direction::BOTTOM) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::BOTTOM)).isWater()) ||
		   (Maps::isValidDirection(from, Direction::LEFT) &&
		    ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::LEFT)).isWater()))
		    return false;
		break;

	    default: break;
	}
    }

    return PassableToTile(hero, toTile, direct, dst);
}
Beispiel #16
0
bool ActionSpellVisions(Heroes & hero)
{
    const u16 dist = hero.GetVisionsDistance();
    const MapsIndexes & monsters = Maps::ScanDistanceObject(hero.GetIndex(), MP2::OBJ_MONSTER, dist);

    if(monsters.size())
    {
        for(MapsIndexes::const_iterator
                it = monsters.begin(); it != monsters.end(); ++it)
        {
            const Maps::Tiles & tile = world.GetTiles(*it);
            const Army::Troop & troop = tile.QuantityTroop();

            u32 join = troop.GetCount();
            Funds cost;

            const u8 reason = Army::GetJoinSolution(hero, tile, join, cost.gold);
            std::string hdr, msg;

            hdr = std::string("%{count} ") + String::Lower(troop.GetPluralName(join));
            String::Replace(hdr, "%{count}", join);

            switch(reason)
            {
            case 0:
                msg = _("I fear these creatures are in the mood for a fight.");
                break;

            case 1:
                msg = _("The creatures are willing to join us!");
                break;

            case 2:
                if(join == troop.GetCount())
                    msg = _("All the creatures will join us...");
                else
                {
                    msg = ngettext("The creature will join us...", "%{count} of the creatures will join us...", join);
                    String::Replace(msg, "%{count}", join);
                }
                msg.append("\n");
                msg.append("\n for a fee of %{gold} gold.");
                String::Replace(msg, "%{gold}", cost.gold);
                break;

            default:
                msg = _("These weak creatures will surely flee before us.");
                break;
            }

            Dialog::Message(hdr, msg, Font::BIG, Dialog::OK);
        }
    }
    else
    {
        std::string msg = _("You must be within %{count} spaces of a monster for the Visions spell to work.");
        String::Replace(msg, "%{count}", dist);
        Dialog::Message("", msg, Font::BIG, Dialog::OK);
        return false;
    }

    hero.SetModes(Heroes::VISIONS);

    return true;
}