1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-17 00:07:41 +02:00

Implemented A* algorithm to draw shortest roads - but not correct roads yet.

This commit is contained in:
DjWarmonger
2015-05-25 16:37:57 +02:00
13 changed files with 761 additions and 75 deletions

View File

@ -13,6 +13,8 @@
#include "CZonePlacer.h"
#include "../mapObjects/CObjectClassesHandler.h"
static const int3 dirs4[] = {int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0)};
void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo)
{
for(const int3 &dir : dirs)
@ -23,6 +25,16 @@ void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3&
}
}
void CMapGenerator::foreachDirectNeighbour(const int3& pos, std::function<void(int3& pos)> foo)
{
for(const int3 &dir : dirs4)
{
int3 n = pos + dir;
if(map->isInTheMap(n))
foo(n);
}
}
CMapGenerator::CMapGenerator() :
zonesTotal(0), monolithIndex(0)
@ -132,7 +144,7 @@ std::string CMapGenerator::getMapDescription() const
std::stringstream ss;
ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
", levels %s, humans %d, computers %d, water %s, monster %s, second expansion map") % mapGenOptions->getMapTemplate()->getName() %
", levels %s, humans %d, computers %d, water %s, monster %s, VCMI map") % mapGenOptions->getMapTemplate()->getName() %
randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions->getPlayerCount()) %
static_cast<int>(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] %
monsterStrengthStr[monsterStrengthIndex]);
@ -266,7 +278,49 @@ void CMapGenerator::fillZones()
createObstaclesCommon2();
//place actual obstacles matching zone terrain
for (auto it : zones)
{
it.second->createObstacles2(this);
}
#define PRINT_MAP_BEFORE_ROADS true
if (PRINT_MAP_BEFORE_ROADS) //enable to debug
{
std::ofstream out("road debug");
int levels = map->twoLevel ? 2 : 1;
int width = map->width;
int height = map->height;
for (int k = 0; k < levels; k++)
{
for (int j = 0; j<height; j++)
{
for (int i = 0; i<width; i++)
{
char t = '?';
switch (getTile(int3(i, j, k)).getTileType())
{
case ETileType::FREE:
t = ' '; break;
case ETileType::BLOCKED:
t = '#'; break;
case ETileType::POSSIBLE:
t = '-'; break;
case ETileType::USED:
t = 'O'; break;
}
out << t;
}
out << std::endl;
}
out << std::endl;
}
out << std::endl;
}
for (auto it : zones)
{
it.second->connectRoads(this); //draw roads after everything else has been placed
}
//find place for Grail
if (treasureZones.empty())
@ -421,8 +475,11 @@ void CMapGenerator::createConnections()
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true);
//zones can make paths only in their own area
zoneA->crunchPath (this, guardPos, posA, zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center
zoneB->crunchPath (this, guardPos, posB, zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
zoneA->crunchPath(this, guardPos, posA, zoneA->getFreePaths()); //make connection towards our zone center
zoneB->crunchPath(this, guardPos, posB, zoneB->getFreePaths()); //make connection towards other zone center
zoneA->addRoadNode(guardPos);
zoneB->addRoadNode(guardPos);
break; //we're done with this connection
}
}
@ -516,6 +573,13 @@ void CMapGenerator::addHeaderInfo()
addPlayerInfo();
}
void CMapGenerator::checkIsOnMap(const int3& tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
}
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
{
return zones;
@ -523,67 +587,74 @@ std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
bool CMapGenerator::isBlocked(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].isBlocked();
}
bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
}
bool CMapGenerator::isPossible(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].isPossible();
}
bool CMapGenerator::isFree(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].isFree();
}
bool CMapGenerator::isUsed(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].isUsed();
}
bool CMapGenerator::isRoad(const int3& tile) const
{
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].isRoad();
}
void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
tiles[tile.x][tile.y][tile.z].setOccupied(state);
}
CTileInfo CMapGenerator::getTile(const int3& tile) const
void CMapGenerator::setRoad(const int3& tile, ERoadType::ERoadType roadType)
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
tiles[tile.x][tile.y][tile.z].setRoadType(roadType);
}
CTileInfo CMapGenerator::getTile(const int3& tile) const
{
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z];
}
void CMapGenerator::setNearestObjectDistance(int3 &tile, float value)
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
}
float CMapGenerator::getNearestObjectDistance(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
checkIsOnMap(tile);
return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
}