1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

More experiments WIP.

This commit is contained in:
AlexVinS 2015-01-18 16:19:00 +03:00
parent eb60d9737f
commit 76193c4c5c
4 changed files with 120 additions and 47 deletions

View File

@ -433,8 +433,11 @@ void CMapGenerator::createConnections()
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true); zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true);
//zones can make paths only in their own area //zones can make paths only in their own area
zoneA->crunchRoad(this, guardPos, posA, zoneA->getFreePaths()); //make connection towards our zone center zoneA->crunchPath(this, guardPos, posA, zoneA->getFreePaths()); //make connection towards our zone center
zoneB->crunchRoad(this, guardPos, posB, zoneB->getFreePaths()); //make connection towards other 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 break; //we're done with this connection
} }
} }
@ -528,6 +531,13 @@ void CMapGenerator::addHeaderInfo()
addPlayerInfo(); 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 std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
{ {
return zones; return zones;
@ -535,67 +545,74 @@ std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
bool CMapGenerator::isBlocked(const int3 &tile) const bool CMapGenerator::isBlocked(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isBlocked(); return tiles[tile.x][tile.y][tile.z].isBlocked();
} }
bool CMapGenerator::shouldBeBlocked(const int3 &tile) const bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].shouldBeBlocked(); return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
} }
bool CMapGenerator::isPossible(const int3 &tile) const bool CMapGenerator::isPossible(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isPossible(); return tiles[tile.x][tile.y][tile.z].isPossible();
} }
bool CMapGenerator::isFree(const int3 &tile) const bool CMapGenerator::isFree(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isFree(); return tiles[tile.x][tile.y][tile.z].isFree();
} }
bool CMapGenerator::isUsed(const int3 &tile) const bool CMapGenerator::isUsed(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isUsed(); 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) void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
tiles[tile.x][tile.y][tile.z].setOccupied(state); 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)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % 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]; return tiles[tile.x][tile.y][tile.z];
} }
void CMapGenerator::setNearestObjectDistance(int3 &tile, float value) void CMapGenerator::setNearestObjectDistance(int3 &tile, float value)
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value); tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
} }
float CMapGenerator::getNearestObjectDistance(const int3 &tile) const float CMapGenerator::getNearestObjectDistance(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) checkIsOnMap(tile);
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance(); return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
} }

View File

@ -73,7 +73,11 @@ public:
bool isPossible(const int3 &tile) const; bool isPossible(const int3 &tile) const;
bool isFree(const int3 &tile) const; bool isFree(const int3 &tile) const;
bool isUsed(const int3 &tile) const; bool isUsed(const int3 &tile) const;
bool isRoad(const int3 &tile) const;
void setOccupied(const int3 &tile, ETileType::ETileType state); void setOccupied(const int3 &tile, ETileType::ETileType state);
void setRoad(const int3 &tile, ERoadType::ERoadType roadType);
CTileInfo getTile(const int3 & tile) const; CTileInfo getTile(const int3 & tile) const;
float getNearestObjectDistance(const int3 &tile) const; float getNearestObjectDistance(const int3 &tile) const;
@ -100,6 +104,7 @@ private:
//int questArtsRemaining; //int questArtsRemaining;
int monolithIndex; int monolithIndex;
std::vector<ArtifactID> questArtifacts; std::vector<ArtifactID> questArtifacts;
void checkIsOnMap(const int3 &tile) const; //throws
/// Generation methods /// Generation methods
std::string getMapDescription() const; std::string getMapDescription() const;

View File

@ -33,6 +33,11 @@ CRmgTemplateZone::CTownInfo::CTownInfo() : townCount(0), castleCount(0), townDen
} }
void CRmgTemplateZone::addRoadNode(const int3& node)
{
roadNodes.insert(node);
}
int CRmgTemplateZone::CTownInfo::getTownCount() const int CRmgTemplateZone::CTownInfo::getTownCount() const
{ {
return townCount; return townCount;
@ -111,6 +116,12 @@ bool CTileInfo::isFree() const
{ {
return occupied == ETileType::FREE; return occupied == ETileType::FREE;
} }
bool CTileInfo::isRoad() const
{
return roadType != ERoadType::NO_ROAD;
}
bool CTileInfo::isUsed() const bool CTileInfo::isUsed() const
{ {
return occupied == ETileType::USED; return occupied == ETileType::USED;
@ -692,6 +703,8 @@ bool CRmgTemplateZone::crunchRoad(CMapGenerator* gen, const int3& src, const int
if(crunchPath(gen, src, dst, &currentClearedTiles, true)) if(crunchPath(gen, src, dst, &currentClearedTiles, true))
{ {
roads.insert(std::begin(currentClearedTiles), std::end(currentClearedTiles)); roads.insert(std::begin(currentClearedTiles), std::end(currentClearedTiles));
roads.insert(src);
roads.insert(dst);
if(nullptr != clearedTiles) if(nullptr != clearedTiles)
clearedTiles->insert(std::begin(currentClearedTiles), std::end(currentClearedTiles)); clearedTiles->insert(std::begin(currentClearedTiles), std::end(currentClearedTiles));
@ -700,7 +713,8 @@ bool CRmgTemplateZone::crunchRoad(CMapGenerator* gen, const int3& src, const int
} }
else else
{ {
return false; logGlobal->warnStream() << boost::format("Failed to crunch road from %s to %s") %src %dst;
return crunchPath(gen, src, dst, clearedTiles, false);
} }
} }
@ -1265,6 +1279,7 @@ bool CRmgTemplateZone::placeMines (CMapGenerator* gen)
bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen) bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
{ {
logGlobal->traceStream() << "Creating required objects"; logGlobal->traceStream() << "Creating required objects";
for(const auto &obj : requiredObjects) for(const auto &obj : requiredObjects)
{ {
int3 pos; int3 pos;
@ -1275,24 +1290,9 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
return false; return false;
} }
switch (obj.first->ID)
{
case Obj::TOWN:
case Obj::MONOLITH_TWO_WAY:
case Obj::SUBTERRANEAN_GATE:
{
crunchRoad(gen, this->pos, pos + obj.first->getVisitableOffset(), &freePaths);
}
break;
default:
break;
}
placeObject (gen, obj.first, pos); placeObject (gen, obj.first, pos);
guardObject (gen, obj.first, obj.second, (obj.first->ID == Obj::MONOLITH_TWO_WAY), true); guardObject (gen, obj.first, obj.second, (obj.first->ID == Obj::MONOLITH_TWO_WAY), true);
//paths to required objects constitute main paths of zone. otherwise they just may lead to middle and create dead zones //paths to required objects constitute main paths of zone. otherwise they just may lead to middle and create dead zones
} }
for (const auto &obj : closeObjects) for (const auto &obj : closeObjects)
@ -1481,18 +1481,45 @@ void CRmgTemplateZone::createObstacles2(CMapGenerator* gen)
} }
void CRmgTemplateZone::drawRoads(CMapGenerator* gen) void CRmgTemplateZone::drawRoads(CMapGenerator* gen)
{
auto doDrawRoad = []()
{
};
while(!roadNodes.empty())
{
int3 node = *roadNodes.begin();
roadNodes.erase(node);
if(roads.empty())
{
//start road network
roads.insert(node);
}
else
{
int3 cross = *RandomGeneratorUtil::nextItem(roads, gen->rand);
crunchRoad(gen, node, cross, &freePaths);
}
}
}
void CRmgTemplateZone::buildRoads(CMapGenerator* gen)
{ {
std::vector<int3> tiles; std::vector<int3> tiles;
for (auto tile : roads) for (auto tile : roads)
{ {
tiles.push_back (tile); if(gen->map->isInTheMap(tile))
tiles.push_back (tile);
} }
gen->editManager->getTerrainSelection().setSelection(tiles); gen->editManager->getTerrainSelection().setSelection(tiles);
gen->editManager->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand); gen->editManager->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand);
} }
bool CRmgTemplateZone::fill(CMapGenerator* gen) bool CRmgTemplateZone::fill(CMapGenerator* gen)
{ {
initTerrainType(gen); initTerrainType(gen);
@ -1503,11 +1530,11 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
placeMines(gen); placeMines(gen);
createRequiredObjects(gen); createRequiredObjects(gen);
drawRoads(gen);
buildRoads(gen);
fractalize(gen); //after required objects are created and linked with their own paths fractalize(gen); //after required objects are created and linked with their own paths
createTreasures(gen); createTreasures(gen);
drawRoads(gen);
logGlobal->infoStream() << boost::format ("Zone %d filled successfully") %id; logGlobal->infoStream() << boost::format ("Zone %d filled successfully") %id;
return true; return true;
} }
@ -1718,6 +1745,24 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
auto artid = sh->quest->m5arts.front(); auto artid = sh->quest->m5arts.front();
logGlobal->warnStream() << boost::format("Placed Seer Hut at %s, quest artifact %d is %s") % object->pos % artid % VLC->arth->artifacts[artid]->Name(); logGlobal->warnStream() << boost::format("Placed Seer Hut at %s, quest artifact %d is %s") % object->pos % artid % VLC->arth->artifacts[artid]->Name();
} }
switch (object->ID)
{
case Obj::TOWN:
case Obj::RANDOM_TOWN:
case Obj::MONOLITH_TWO_WAY:
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
case Obj::MONOLITH_ONE_WAY_EXIT:
case Obj::SUBTERRANEAN_GATE:
{
roadNodes.insert(pos + object->getVisitableOffset());
}
break;
default:
break;
}
} }
void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard) void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard)

View File

@ -47,10 +47,12 @@ public:
bool isPossible() const; bool isPossible() const;
bool isFree() const; bool isFree() const;
bool isUsed() const; bool isUsed() const;
bool isRoad() const;
void setOccupied(ETileType::ETileType value); void setOccupied(ETileType::ETileType value);
ETerrainType getTerrainType() const; ETerrainType getTerrainType() const;
ETileType::ETileType getTileType() const; ETileType::ETileType getTileType() const;
void setTerrainType(ETerrainType value); void setTerrainType(ETerrainType value);
void setRoadType(ERoadType::ERoadType value); void setRoadType(ERoadType::ERoadType value);
private: private:
float nearestObjectDistance; float nearestObjectDistance;
@ -168,7 +170,7 @@ public:
void createObstacles1(CMapGenerator* gen); void createObstacles1(CMapGenerator* gen);
void createObstacles2(CMapGenerator* gen); void createObstacles2(CMapGenerator* gen);
bool crunchPath(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr, bool forRoad = false); bool crunchPath(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr, bool forRoad = false);
bool crunchRoad(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr);
std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object); std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
void addConnection(TRmgTemplateZoneId otherZone); void addConnection(TRmgTemplateZoneId otherZone);
@ -181,7 +183,7 @@ public:
ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue); ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard = false); void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard = false);
void addRoadNode(const int3 & node);
private: private:
//template info //template info
TRmgTemplateZoneId id; TRmgTemplateZoneId id;
@ -218,9 +220,11 @@ private:
std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
std::set<int3> roads; std::set<int3> roadNodes; //tiles to be connected with roads
std::set<int3> roads; //all tiles with roads
void drawRoads(CMapGenerator* gen); void drawRoads(CMapGenerator* gen); //fills "roads" according to "roadNodes"
void buildRoads(CMapGenerator* gen); //actually updates tiles
bool pointIsIn(int x, int y); bool pointIsIn(int x, int y);
void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
@ -233,4 +237,6 @@ private:
void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos); void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance = true); void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance = true);
bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false, bool addToFreePaths = false); bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false, bool addToFreePaths = false);
//TODO:replace with A*-based algorithm on whole road network
bool crunchRoad(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr);
}; };