mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-14 02:33:51 +02:00
Merge pull request #455 from nullkiller/deadend-exploration-improvement
After actually checking this branch, I absolutely approve it. AI advances quickly and steadily, and that's the point.
This commit is contained in:
commit
f8a9a0af2b
@ -18,7 +18,6 @@
|
|||||||
#include "../../lib/mapObjects/CBank.h"
|
#include "../../lib/mapObjects/CBank.h"
|
||||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../../lib/mapObjects/CQuest.h"
|
#include "../../lib/mapObjects/CQuest.h"
|
||||||
#include "../../lib/CPathfinder.h"
|
|
||||||
#include "../../lib/mapping/CMapDefines.h"
|
#include "../../lib/mapping/CMapDefines.h"
|
||||||
|
|
||||||
extern boost::thread_specific_ptr<CCallback> cb;
|
extern boost::thread_specific_ptr<CCallback> cb;
|
||||||
@ -431,9 +430,22 @@ bool isBlockVisitObj(const int3 & pos)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp)
|
bool hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp)
|
||||||
|
{
|
||||||
|
for(crint3 dir : int3::getDirs())
|
||||||
|
{
|
||||||
|
int3 tile = pos + dir;
|
||||||
|
if(cbp->isInTheMap(tile) && cbp->getPathsInfo(hero.get())->getPathInfo(tile)->reachable())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp, HeroPtr hero)
|
||||||
{
|
{
|
||||||
//TODO: do not explore dead-end boundaries
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for(int x = pos.x - radious; x <= pos.x + radious; x++)
|
for(int x = pos.x - radious; x <= pos.x + radious; x++)
|
||||||
{
|
{
|
||||||
@ -442,7 +454,7 @@ int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp)
|
|||||||
int3 npos = int3(x, y, pos.z);
|
int3 npos = int3(x, y, pos.z);
|
||||||
if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos))
|
if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos))
|
||||||
{
|
{
|
||||||
if(!boundaryBetweenTwoPoints(pos, npos, cbp))
|
if(hasReachableNeighbor(npos, hero, cbp))
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,33 +463,6 @@ int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool boundaryBetweenTwoPoints(int3 pos1, int3 pos2, CCallback * cbp) //determines if two points are separated by known barrier
|
|
||||||
{
|
|
||||||
int xMin = std::min(pos1.x, pos2.x);
|
|
||||||
int xMax = std::max(pos1.x, pos2.x);
|
|
||||||
int yMin = std::min(pos1.y, pos2.y);
|
|
||||||
int yMax = std::max(pos1.y, pos2.y);
|
|
||||||
|
|
||||||
for(int x = xMin; x <= xMax; ++x)
|
|
||||||
{
|
|
||||||
for(int y = yMin; y <= yMax; ++y)
|
|
||||||
{
|
|
||||||
int3 tile = int3(x, y, pos1.z); //use only on same level, ofc
|
|
||||||
if(std::abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
|
|
||||||
{
|
|
||||||
if(!(cbp->isVisible(tile) && cbp->getTile(tile)->blocked)) //if there's invisible or unblocked tile between, it's good
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; //if all are visible and blocked, we're at dead end
|
|
||||||
}
|
|
||||||
|
|
||||||
int howManyTilesWillBeDiscovered(int radious, int3 pos, crint3 dir)
|
|
||||||
{
|
|
||||||
return howManyTilesWillBeDiscovered(pos + dir, radious, cb.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out)
|
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out)
|
||||||
{
|
{
|
||||||
for(const int3 & tile : tiles)
|
for(const int3 & tile : tiles)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "../../lib/CStopWatch.h"
|
#include "../../lib/CStopWatch.h"
|
||||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../lib/CPathfinder.h"
|
||||||
|
|
||||||
class CCallback;
|
class CCallback;
|
||||||
|
|
||||||
@ -141,8 +142,7 @@ void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const
|
|||||||
void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo);
|
void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo);
|
||||||
void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
|
void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
|
||||||
|
|
||||||
int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp);
|
int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp, HeroPtr hero);
|
||||||
int howManyTilesWillBeDiscovered(int radious, int3 pos, crint3 dir);
|
|
||||||
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out);
|
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out);
|
||||||
|
|
||||||
bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
|
bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
|
||||||
@ -155,7 +155,6 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj);
|
|||||||
ui64 evaluateDanger(const CGObjectInstance * obj);
|
ui64 evaluateDanger(const CGObjectInstance * obj);
|
||||||
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor);
|
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor);
|
||||||
bool isSafeToVisit(HeroPtr h, crint3 tile);
|
bool isSafeToVisit(HeroPtr h, crint3 tile);
|
||||||
bool boundaryBetweenTwoPoints(int3 pos1, int3 pos2, CCallback * cbp);
|
|
||||||
|
|
||||||
bool compareMovement(HeroPtr lhs, HeroPtr rhs);
|
bool compareMovement(HeroPtr lhs, HeroPtr rhs);
|
||||||
bool compareHeroStrength(HeroPtr h1, HeroPtr h2);
|
bool compareHeroStrength(HeroPtr h1, HeroPtr h2);
|
||||||
|
@ -2625,22 +2625,20 @@ void VCAI::buildArmyIn(const CGTownInstance * t)
|
|||||||
|
|
||||||
int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
|
int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
|
||||||
{
|
{
|
||||||
int3 ourPos = h->convertPosition(h->pos, false);
|
|
||||||
std::map<int3, int> dstToRevealedTiles;
|
std::map<int3, int> dstToRevealedTiles;
|
||||||
|
|
||||||
for(crint3 dir : int3::getDirs())
|
for(crint3 dir : int3::getDirs())
|
||||||
{
|
{
|
||||||
int3 tile = hpos + dir;
|
int3 tile = hpos + dir;
|
||||||
if(cb->isInTheMap(tile))
|
if(cb->isInTheMap(tile))
|
||||||
{
|
{
|
||||||
if(ourPos != dir) //don't stand in place
|
if(isBlockVisitObj(tile))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(isSafeToVisit(h, tile) && isAccessibleForHero(tile, h))
|
||||||
{
|
{
|
||||||
if(isSafeToVisit(h, tile) && isAccessibleForHero(tile, h))
|
auto distance = hpos.dist2d(tile); // diagonal movement opens more tiles but spends more mp
|
||||||
{
|
dstToRevealedTiles[tile] = howManyTilesWillBeDiscovered(tile, radius, cb.get(), h) / distance;
|
||||||
if(isBlockVisitObj(tile))
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
dstToRevealedTiles[tile] = howManyTilesWillBeDiscovered(radius, hpos, dir);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2696,7 +2694,7 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
|
|||||||
|
|
||||||
CGPath path;
|
CGPath path;
|
||||||
cb->getPathsInfo(hero)->getPath(path, tile);
|
cb->getPathsInfo(hero)->getPath(path, tile);
|
||||||
float ourValue = (float)howManyTilesWillBeDiscovered(tile, radius, cbp) / (path.nodes.size() + 1); //+1 prevents erratic jumps
|
float ourValue = (float)howManyTilesWillBeDiscovered(tile, radius, cbp, h) / (path.nodes.size() + 1); //+1 prevents erratic jumps
|
||||||
|
|
||||||
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
||||||
{
|
{
|
||||||
@ -2741,7 +2739,7 @@ int3 VCAI::explorationDesperate(HeroPtr h)
|
|||||||
{
|
{
|
||||||
if(cbp->getTile(tile)->blocked) //does it shorten the time?
|
if(cbp->getTile(tile)->blocked) //does it shorten the time?
|
||||||
continue;
|
continue;
|
||||||
if(!howManyTilesWillBeDiscovered(tile, radius, cbp)) //avoid costly checks of tiles that don't reveal much
|
if(!howManyTilesWillBeDiscovered(tile, radius, cbp, h)) //avoid costly checks of tiles that don't reveal much
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto t = sm->firstTileToGet(h, tile);
|
auto t = sm->firstTileToGet(h, tile);
|
||||||
|
Loading…
Reference in New Issue
Block a user