Skip to content

Commit

Permalink
Cache pathfinding results to speed up calculations (#1541)
Browse files Browse the repository at this point in the history
  • Loading branch information
idshibanov authored Sep 9, 2020
1 parent 20023e1 commit 8bc3ee3
Show file tree
Hide file tree
Showing 22 changed files with 485 additions and 442 deletions.
2 changes: 1 addition & 1 deletion VisualStudio/common.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>src\engine;src\fheroes2\gui;src\fheroes2\maps;src\fheroes2\kingdom;src\fheroes2\game;src\fheroes2\dialog;src\fheroes2\system;src\fheroes2\spell;src\fheroes2\monster;src\fheroes2\castle;src\fheroes2\agg;src\fheroes2\heroes;src\fheroes2\resource;src\fheroes2\ai;src\fheroes2\army;src\fheroes2\battle;src\fheroes2\pocketpc;src\fheroes2\objects;src\fheroes2\test;src\fheroes2\image;src\thirdparty\libsmacker;..\zlib\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>src\engine;src\fheroes2\gui;src\fheroes2\maps;src\fheroes2\kingdom;src\fheroes2\game;src\fheroes2\dialog;src\fheroes2\system;src\fheroes2\spell;src\fheroes2\monster;src\fheroes2\castle;src\fheroes2\agg;src\fheroes2\heroes;src\fheroes2\resource;src\fheroes2\ai;src\fheroes2\army;src\fheroes2\battle;src\fheroes2\pocketpc;src\fheroes2\objects;src\fheroes2\world;src\fheroes2\test;src\fheroes2\image;src\thirdparty\libsmacker;..\zlib\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;WITH_ZLIB;WITH_MIXER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
Expand Down
9 changes: 5 additions & 4 deletions fheroes2.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@
<ClCompile Include="src\fheroes2\heroes\heroes_recruits.cpp" />
<ClCompile Include="src\fheroes2\heroes\heroes_spell.cpp" />
<ClCompile Include="src\fheroes2\heroes\route.cpp" />
<ClCompile Include="src\fheroes2\heroes\route_pathfind.cpp" />
<ClCompile Include="src\fheroes2\heroes\skill.cpp" />
<ClCompile Include="src\fheroes2\kingdom\color.cpp" />
<ClCompile Include="src\fheroes2\kingdom\kingdom.cpp" />
Expand All @@ -332,8 +331,6 @@
<ClCompile Include="src\fheroes2\kingdom\race.cpp" />
<ClCompile Include="src\fheroes2\kingdom\speed.cpp" />
<ClCompile Include="src\fheroes2\kingdom\week.cpp" />
<ClCompile Include="src\fheroes2\kingdom\world.cpp" />
<ClCompile Include="src\fheroes2\kingdom\world_loadmap.cpp" />
<ClCompile Include="src\fheroes2\maps\ground.cpp" />
<ClCompile Include="src\fheroes2\maps\maps.cpp" />
<ClCompile Include="src\fheroes2\maps\maps_actions.cpp" />
Expand Down Expand Up @@ -371,6 +368,9 @@
<ClCompile Include="src\fheroes2\system\settings.cpp" />
<ClCompile Include="src\fheroes2\test\test.cpp" />
<ClCompile Include="src\fheroes2\test\test_monstersprite.cpp" />
<ClCompile Include="src\fheroes2\world\world.cpp" />
<ClCompile Include="src\fheroes2\world\world_loadmap.cpp" />
<ClCompile Include="src\fheroes2\world\world_pathfinding.cpp" />
<ClCompile Include="src\thirdparty\libsmacker\smacker.c" />
<ClCompile Include="src\thirdparty\libsmacker\smk_bitstream.c" />
<ClCompile Include="src\thirdparty\libsmacker\smk_hufftree.c" />
Expand Down Expand Up @@ -486,7 +486,6 @@
<ClInclude Include="src\fheroes2\kingdom\race.h" />
<ClInclude Include="src\fheroes2\kingdom\speed.h" />
<ClInclude Include="src\fheroes2\kingdom\week.h" />
<ClInclude Include="src\fheroes2\kingdom\world.h" />
<ClInclude Include="src\fheroes2\maps\ground.h" />
<ClInclude Include="src\fheroes2\maps\maps.h" />
<ClInclude Include="src\fheroes2\maps\maps_actions.h" />
Expand Down Expand Up @@ -524,6 +523,8 @@
<ClInclude Include="src\fheroes2\system\players.h" />
<ClInclude Include="src\fheroes2\system\settings.h" />
<ClInclude Include="src\fheroes2\test\test.h" />
<ClInclude Include="src\fheroes2\world\world.h" />
<ClInclude Include="src\fheroes2\world\world_pathfinding.h" />
<ClInclude Include="src\tools\palette_h2.h" />
<ClInclude Include="src\thirdparty\libsmacker\smacker.h" />
<ClInclude Include="src\thirdparty\libsmacker\smk_bitstream.h" />
Expand Down
4 changes: 2 additions & 2 deletions src/fheroes2/ai/simple/ai_simple_heroes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ namespace AI
if ( task.size() >= HERO_MAX_SHEDULED_TASK )
break;
const int positionIndex = ( *it ).first;
const uint32_t distance = hero.GetPath().Calculate( positionIndex, PATHFINDING_LIMIT );
const uint32_t distance = world.getDistance( hero.GetIndex(), positionIndex, hero.GetLevelSkill( Skill::Secondary::PATHFINDING ) );

if ( distance ) {
DEBUG( DBG_AI, DBG_INFO,
Expand Down Expand Up @@ -482,7 +482,7 @@ namespace AI

if ( HeroesValidObject( hero, index ) ) {
DEBUG( DBG_AI, DBG_TRACE, hero.GetName() << ", looking for: " << MP2::StringObject( world.GetTiles( index ).GetObject() ) << "(" << index << ")" );
if ( hero.GetPath().Calculate( index, PATHFINDING_LIMIT ) )
if ( hero.GetPath().Calculate( index ) )
break;

DEBUG( DBG_AI, DBG_TRACE, hero.GetName() << " say: unable to get object: " << index << ", remove task..." );
Expand Down
4 changes: 2 additions & 2 deletions src/fheroes2/dialog/dialog_quickinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ std::string ShowGroundInfo( const Maps::Tiles & tile, bool show, const Heroes *
std::string str = Maps::Ground::String( tile.GetGround() );

if ( show && hero ) {
int dir = Direction::Get( hero->GetIndex(), tile.GetIndex() );
int dir = Maps::GetDirection( hero->GetIndex(), tile.GetIndex() );
if ( dir != Direction::UNKNOWN ) {
uint32_t cost = ( tile.isRoad( dir ) ) ? Maps::Ground::roadPenalty : Maps::Ground::GetPenalty( tile, hero->GetLevelSkill( Skill::Secondary::PATHFINDING ) );
uint32_t cost = tile.isRoad() ? Maps::Ground::roadPenalty : Maps::Ground::GetPenalty( tile, hero->GetLevelSkill( Skill::Secondary::PATHFINDING ) );

if ( cost ) {
str.append( "\n" );
Expand Down
2 changes: 0 additions & 2 deletions src/fheroes2/game/game_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,6 @@ bool Game::Load( const std::string & fn )

fz >> World::Get() >> Settings::Get() >> GameOver::Result::Get() >> GameStatic::Data::Get() >> MonsterStaticData::Get() >> end_check;

World::Get().PostFixLoad();

if ( fz.fail() || ( end_check != SAV2ID2 && end_check != SAV2ID3 ) ) {
DEBUG( DBG_GAME, DBG_WARN, "invalid load file: " << fn );
return false;
Expand Down
3 changes: 1 addition & 2 deletions src/fheroes2/gui/interface_gamearea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,8 @@ void Interface::GameArea::Redraw( fheroes2::Image & dst, int flag ) const
if ( pathEnd != nextStep ) {
const Maps::Tiles & tileTo = world.GetTiles( currentStep->GetIndex() );
uint32_t cost = Maps::Ground::GetPenalty( tileTo, pathfinding );
const int direction = currentStep->GetDirection();

if ( world.GetTiles( currentStep->GetFrom() ).isRoad( direction ) || tileTo.isRoad( Direction::Reflect( direction ) ) )
if ( world.GetTiles( currentStep->GetFrom() ).isRoad() && tileTo.isRoad() )
cost = Maps::Ground::roadPenalty;

index = Route::Path::GetIndexSprite( ( *currentStep ).GetDirection(), ( *nextStep ).GetDirection(), cost );
Expand Down
11 changes: 0 additions & 11 deletions src/fheroes2/heroes/direction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,6 @@ std::string Direction::String( int direct )
return res.empty() ? str_direct[0] : res;
}

int Direction::Get( s32 from, s32 to )
{
const Directions directions = Direction::All();

for ( Directions::const_iterator it = directions.begin(); it != directions.end(); ++it )
if ( to == Maps::GetDirectionIndex( from, *it ) )
return *it;

return to == from ? CENTER : UNKNOWN;
}

bool Direction::ShortDistanceClockWise( int from, int to )
{
switch ( from ) {
Expand Down
1 change: 0 additions & 1 deletion src/fheroes2/heroes/direction.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ namespace Direction

std::string String( int );

int Get( s32 from, s32 to );
int Reflect( int direct );

bool ShortDistanceClockWise( int direct1, int direct2 );
Expand Down
13 changes: 3 additions & 10 deletions src/fheroes2/heroes/heroes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1297,17 +1297,10 @@ int Heroes::GetDirection( void ) const
int Heroes::GetRangeRouteDays( s32 dst ) const
{
const u32 maxMovePoints = GetMaxMovePoints();
const u32 limit = maxMovePoints * 5 / 100; // limit ~5 day

// approximate distance, this restriction calculation
if ( ( 4 * maxMovePoints / 100 ) < Maps::GetApproximateDistance( GetIndex(), dst ) ) {
DEBUG( DBG_GAME, DBG_INFO, "distance limit" );
return 0;
}

Route::Path test( *this );
// approximate limit, this restriction path finding algorithm
uint32_t total = test.Calculate( dst, limit );
uint32_t total = world.getDistance( GetIndex(), dst, GetLevelSkill( Skill::Secondary::PATHFINDING ) );
DEBUG( DBG_GAME, DBG_TRACE, "path distance: " << total );
if ( total > 0 ) {
if ( move_point >= total )
return 1;
Expand All @@ -1323,7 +1316,7 @@ int Heroes::GetRangeRouteDays( s32 dst ) const
return 4;
}
else {
DEBUG( DBG_GAME, DBG_INFO, "iteration limit: " << limit );
DEBUG( DBG_GAME, DBG_TRACE, "unreachable point: " << dst );
}

return 0;
Expand Down
19 changes: 12 additions & 7 deletions src/fheroes2/heroes/route.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Route::Path & Route::Path::operator=( const Path & p )

int Route::Path::GetFrontDirection( void ) const
{
return empty() ? ( dst != hero->GetIndex() ? Direction::Get( hero->GetIndex(), dst ) : Direction::CENTER ) : front().GetDirection();
return empty() ? ( dst != hero->GetIndex() ? Maps::GetDirection( hero->GetIndex(), dst ) : Direction::CENTER ) : front().GetDirection();
}

u32 Route::Path::GetFrontPenalty( void ) const
Expand Down Expand Up @@ -120,11 +120,16 @@ s32 Route::Path::GetDestinedIndex( void ) const
}

/* return length path */
uint32_t Route::Path::Calculate( const s32 & dst_index, int limit /* -1 */ )
uint32_t Route::Path::Calculate( const s32 & destIndex )
{
dst = dst_index;
const int fromIndex = hero->GetIndex();
const uint32_t skill = hero->GetLevelSkill( Skill::Secondary::PATHFINDING );

return Find( hero->GetIndex(), dst, hero->isShipMaster(), limit, hero->GetLevelSkill( Skill::Secondary::PATHFINDING ) );
dst = destIndex;

std::list<Step>::operator=( world.getPath( fromIndex, dst, skill, false ) );

return world.getDistance( fromIndex, dst, skill );
}

void Route::Path::Reset( void )
Expand All @@ -139,18 +144,18 @@ void Route::Path::Reset( void )

bool Route::Path::isComplete( void ) const
{
return dst == hero->GetIndex() || ( empty() && Direction::UNKNOWN != Direction::Get( hero->GetIndex(), dst ) );
return dst == hero->GetIndex() || ( empty() && Direction::UNKNOWN != Maps::GetDirection( hero->GetIndex(), dst ) );
}

bool Route::Path::isValid( void ) const
{
return !empty();
return !empty() && front().GetDirection() != Direction::UNKNOWN;
}

int Route::Path::GetIndexSprite( int from, int to, int mod )
{
// ICN::ROUTE
// start index 1, 25, 49, 73, 97, 121 (size arrow path)
// start index 1, 25, 49, 73, 97, 121 (path arrow size)
int index = 1;

switch ( mod ) {
Expand Down
3 changes: 1 addition & 2 deletions src/fheroes2/heroes/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace Route
int GetFrontDirection( void ) const;
u32 GetFrontPenalty( void ) const;
u32 GetTotalPenalty( void ) const;
uint32_t Calculate( const s32 &, int limit = -1 );
uint32_t Calculate( const s32 & destIndex );

void Show( void )
{
Expand Down Expand Up @@ -105,7 +105,6 @@ namespace Route
static int GetIndexSprite( int from, int to, int mod );

private:
uint32_t Find( int32_t from, int32_t to, bool fromWater = false, int limit = -1, int pathfinding = Skill::Level::NONE );

friend StreamBase & operator<<( StreamBase &, const Path & );
friend StreamBase & operator>>( StreamBase &, Path & );
Expand Down
Loading

0 comments on commit 8bc3ee3

Please sign in to comment.