Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow AI to reuse teleporters that hero is standing on #9578

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/fheroes2/ai/ai_hero_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -876,12 +876,13 @@ namespace
}
}

void AIToTeleports( Heroes & hero, const int32_t startIndex )
void AIToTeleports( Heroes & hero )
{
DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() )

assert( hero.GetPath().empty() );

const int32_t startIndex = hero.GetIndex();
const int32_t indexTo = world.NextTeleport( startIndex );
if ( startIndex == indexTo ) {
DEBUG_LOG( DBG_AI, DBG_WARN, "AI hero " << hero.GetName() << " has nowhere to go through stone liths" )
Expand Down Expand Up @@ -943,12 +944,13 @@ namespace
}
}

void AIToWhirlpools( Heroes & hero, const int32_t startIndex )
void AIToWhirlpools( Heroes & hero )
{
DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() )

assert( hero.GetPath().empty() );

const int32_t startIndex = hero.GetIndex();
const int32_t indexTo = world.NextWhirlpool( startIndex );
if ( startIndex == indexTo ) {
DEBUG_LOG( DBG_AI, DBG_WARN, "AI hero " << hero.GetName() << " has nowhere to go through the whirlpool" )
Expand Down Expand Up @@ -1917,10 +1919,10 @@ void AI::HeroesAction( Heroes & hero, const int32_t dst_index )

// teleports
case MP2::OBJ_STONE_LITHS:
AIToTeleports( hero, dst_index );
AIToTeleports( hero );
break;
case MP2::OBJ_WHIRLPOOL:
AIToWhirlpools( hero, dst_index );
AIToWhirlpools( hero );
break;

// primary skill modification
Expand Down Expand Up @@ -2094,10 +2096,23 @@ void AI::HeroesMove( Heroes & hero )

if ( path.isValidForTeleportation() ) {
const int32_t targetIndex = path.GetFrontIndex();
const Maps::Tile & targetTile = world.getTile( targetIndex );

if ( targetTile.getMainObjectType() == MP2::OBJ_STONE_LITHS ) {
hero.GetPath().clear();
AIToTeleports( hero );
return;
}

if ( targetTile.getMainObjectType() == MP2::OBJ_WHIRLPOOL ) {
hero.GetPath().clear();
AIToWhirlpools( hero );
return;
}

// At the moment, this kind of movement using regular paths generated by AI pathfinder is only possible to the
// towns/castles with the use of Town Gate or Town Portal spells
assert( path.GetFrontFrom() != targetIndex && world.getTile( targetIndex ).getMainObjectType() == MP2::OBJ_CASTLE );
assert( path.GetFrontFrom() != targetIndex && targetTile.getMainObjectType() == MP2::OBJ_CASTLE );

AITownPortal( hero, targetIndex );

Expand Down
15 changes: 14 additions & 1 deletion src/fheroes2/game/difficulty.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2025 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
Expand Down Expand Up @@ -242,6 +242,19 @@ bool Difficulty::allowAIToSplitWeakStacks( const int difficulty )
return true;
}

bool Difficulty::allowAIToReuseTeleporters( const int difficulty )
{
switch ( difficulty ) {
case Difficulty::HARD:
case Difficulty::EXPERT:
case Difficulty::IMPOSSIBLE:
return true;
default:
break;
}
return false;
}

bool Difficulty::allowAIToDevelopCastlesOnDay( const int difficulty, const bool isCampaign, const uint32_t day )
{
switch ( difficulty ) {
Expand Down
3 changes: 3 additions & 0 deletions src/fheroes2/game/difficulty.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ namespace Difficulty
// Returns true if AI should avoid having free slots in the army
bool allowAIToSplitWeakStacks( const int difficulty );

// Returns true if AI to use stone liths or whirlpool while standing on it
bool allowAIToReuseTeleporters( const int difficulty );

bool allowAIToDevelopCastlesOnDay( const int difficulty, const bool isCampaign, const uint32_t day );
bool allowAIToBuildCastleBuilding( const int difficulty, const bool isCampaign, const BuildingType building );
}
4 changes: 2 additions & 2 deletions src/fheroes2/world/world_pathfinding.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2020 - 2024 *
* Copyright (C) 2020 - 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -813,7 +813,7 @@ void AIWorldPathfinder::processCurrentNode( std::vector<int> & nodesToExplore, c
MapsIndexes teleports;

// We shouldn't use teleport at the starting tile
if ( !isFirstNode ) {
if ( !isFirstNode || Difficulty::allowAIToReuseTeleporters( Game::getDifficulty() ) ) {
teleports = world.GetTeleportEndPoints( currentNodeIdx );

if ( teleports.empty() ) {
Expand Down
2 changes: 1 addition & 1 deletion src/fheroes2/world/world_pathfinding.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2020 - 2024 *
* Copyright (C) 2020 - 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down
Loading