mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Implemented A* algorithm to draw shortest roads - but not correct roads yet.
This commit is contained in:
commit
6d502ef1a1
@ -482,6 +482,23 @@ enum class ETeleportChannelType
|
||||
MIXED
|
||||
};
|
||||
|
||||
|
||||
namespace ERiverType
|
||||
{
|
||||
enum ERiverType
|
||||
{
|
||||
NO_RIVER, CLEAR_RIVER, ICY_RIVER, MUDDY_RIVER, LAVA_RIVER
|
||||
};
|
||||
}
|
||||
|
||||
namespace ERoadType
|
||||
{
|
||||
enum ERoadType
|
||||
{
|
||||
NO_ROAD, DIRT_ROAD, GRAVEL_ROAD, COBBLESTONE_ROAD
|
||||
};
|
||||
}
|
||||
|
||||
class Obj
|
||||
{
|
||||
public:
|
||||
|
@ -255,6 +255,8 @@
|
||||
<Unit filename="mapObjects/ObjectTemplate.h" />
|
||||
<Unit filename="mapping/CCampaignHandler.cpp" />
|
||||
<Unit filename="mapping/CCampaignHandler.h" />
|
||||
<Unit filename="mapping/CDrawRoadsOperation.cpp" />
|
||||
<Unit filename="mapping/CDrawRoadsOperation.h" />
|
||||
<Unit filename="mapping/CMap.cpp" />
|
||||
<Unit filename="mapping/CMap.h" />
|
||||
<Unit filename="mapping/CMapEditManager.cpp" />
|
||||
|
@ -231,6 +231,7 @@
|
||||
<ClCompile Include="mapping\CMapEditManager.cpp" />
|
||||
<ClCompile Include="mapping\MapFormatH3M.cpp" />
|
||||
<ClCompile Include="mapping\MapFormatJson.cpp" />
|
||||
<ClCompile Include="mapping\CDrawRoadsOperation.cpp" />
|
||||
<ClCompile Include="registerTypes\RegisterTypes.cpp" />
|
||||
<ClCompile Include="registerTypes\TypesClientPacks1.cpp" />
|
||||
<ClCompile Include="registerTypes\TypesClientPacks2.cpp" />
|
||||
|
353
lib/mapping/CDrawRoadsOperation.cpp
Normal file
353
lib/mapping/CDrawRoadsOperation.cpp
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* CDrawRoadsOperation.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CDrawRoadsOperation.h"
|
||||
|
||||
const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::patterns =
|
||||
{
|
||||
//single tile. fall-back pattern
|
||||
{
|
||||
{
|
||||
"-","-","-",
|
||||
"-","+","-",
|
||||
"-","-","-"
|
||||
},
|
||||
{14,14},
|
||||
{9,9},
|
||||
false,
|
||||
false
|
||||
},
|
||||
//Road straight with angle
|
||||
{
|
||||
{
|
||||
"?","-","+",
|
||||
"-","+","+",
|
||||
"+","+","?"
|
||||
},
|
||||
{2,5},
|
||||
{-1,-1},
|
||||
true,
|
||||
true
|
||||
},
|
||||
//Turn
|
||||
{
|
||||
{
|
||||
"?","-","?",
|
||||
"-","+","+",
|
||||
"?","+","?"
|
||||
},
|
||||
{0,1},
|
||||
{0,3},
|
||||
true,
|
||||
true
|
||||
},
|
||||
//Dead end horizontal
|
||||
{
|
||||
{
|
||||
"?","-","?",
|
||||
"-","+","+",
|
||||
"?","-","?"
|
||||
},
|
||||
{15,15},{11,12},
|
||||
true,
|
||||
false
|
||||
},
|
||||
//Dead end vertical
|
||||
{
|
||||
{
|
||||
"?","-","?",
|
||||
"-","+","-",
|
||||
"?","+","?"
|
||||
},
|
||||
{14,14},{9,10},
|
||||
false,
|
||||
true
|
||||
},
|
||||
//T-cross horizontal
|
||||
{
|
||||
{
|
||||
"?","+","?",
|
||||
"-","+","+",
|
||||
"?","+","?"
|
||||
},
|
||||
{6,7},{7,8},
|
||||
true,
|
||||
false
|
||||
},
|
||||
//T-cross vertical
|
||||
{
|
||||
{
|
||||
"?","-","?",
|
||||
"+","+","+",
|
||||
"?","+","?"
|
||||
},
|
||||
{8,9},{5,6},
|
||||
false,
|
||||
true
|
||||
},
|
||||
//Straight Horizontal
|
||||
{
|
||||
{
|
||||
"?","-","?",
|
||||
"+","+","+",
|
||||
"?","-","?"
|
||||
},
|
||||
{12,13},{11,12},
|
||||
false,
|
||||
false
|
||||
},
|
||||
//Straight Vertical
|
||||
{
|
||||
{
|
||||
"?","+","?",
|
||||
"-","+","-",
|
||||
"?","+","?"
|
||||
},
|
||||
{10,11},{9,10},
|
||||
false,
|
||||
false
|
||||
},
|
||||
//X-cross
|
||||
{
|
||||
{
|
||||
"?","+","?",
|
||||
"+","+","+",
|
||||
"?","+","?"
|
||||
},
|
||||
{16,16},{4,4},
|
||||
false,
|
||||
false
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static bool ruleIsNone(const std::string & rule)
|
||||
{
|
||||
return rule == "-";
|
||||
}
|
||||
|
||||
static bool ruleIsSomething(const std::string & rule)
|
||||
{
|
||||
return rule == "+";
|
||||
}
|
||||
|
||||
static bool ruleIsAny(const std::string & rule)
|
||||
{
|
||||
return rule == "?";
|
||||
}
|
||||
|
||||
///CDrawRoadsOperation
|
||||
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen):
|
||||
CMapOperation(map),terrainSel(terrainSel), roadType(roadType), gen(gen)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::execute()
|
||||
{
|
||||
std::set<int3> invalidated;
|
||||
|
||||
for(const auto & pos : terrainSel.getSelectedItems())
|
||||
{
|
||||
auto & tile = map->getTile(pos);
|
||||
tile.roadType = roadType;
|
||||
|
||||
auto rect = extendTileAroundSafely(pos);
|
||||
rect.forEach([&invalidated](const int3 & pos)
|
||||
{
|
||||
invalidated.insert(pos);
|
||||
});
|
||||
}
|
||||
|
||||
updateTiles(invalidated);
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::undo()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::redo()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
std::string CDrawRoadsOperation::getLabel() const
|
||||
{
|
||||
return "Draw Roads";
|
||||
}
|
||||
|
||||
bool CDrawRoadsOperation::canApplyPattern(const RoadPattern & pattern) const
|
||||
{
|
||||
//TODO: this method should be virtual for river support
|
||||
return pattern.roadMapping.first >= 0;
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::flipPattern(RoadPattern& pattern, int flip) const
|
||||
{
|
||||
//todo: use cashing here and also in terrain patterns
|
||||
|
||||
if(flip == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(flip == FLIP_PATTERN_HORIZONTAL || flip == FLIP_PATTERN_BOTH)
|
||||
{
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
int y = i * 3;
|
||||
std::swap(pattern.data[y], pattern.data[y + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
if(flip == FLIP_PATTERN_VERTICAL || flip == FLIP_PATTERN_BOTH)
|
||||
{
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
std::swap(pattern.data[i], pattern.data[6 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CDrawRoadsOperation::needUpdateTile(const TerrainTile & tile) const
|
||||
{
|
||||
return tile.roadType != ERoadType::NO_ROAD; //TODO: this method should be virtual for river support
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::updateTiles(std::set<int3> & invalidated)
|
||||
{
|
||||
for(int3 coord : invalidated)
|
||||
{
|
||||
TerrainTile & tile = map->getTile(coord);
|
||||
ValidationResult result(false);
|
||||
|
||||
if(!needUpdateTile(tile))
|
||||
continue;
|
||||
|
||||
int bestPattern = -1;
|
||||
|
||||
for(int k = 0; k < patterns.size(); ++k)
|
||||
{
|
||||
result = validateTile(patterns[k], coord);
|
||||
|
||||
if(result.result)
|
||||
{
|
||||
bestPattern = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bestPattern != -1)
|
||||
{
|
||||
updateTile(tile, patterns[bestPattern], result.flip);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
bool CDrawRoadsOperation::tileHasSomething(const int3& pos) const
|
||||
{
|
||||
//TODO: this method should be virtual for river support
|
||||
|
||||
return map->getTile(pos).roadType != ERoadType::NO_ROAD;
|
||||
}
|
||||
|
||||
|
||||
void CDrawRoadsOperation::updateTile(TerrainTile & tile, const RoadPattern & pattern, const int flip)
|
||||
{
|
||||
//TODO: this method should be virtual for river support
|
||||
|
||||
const std::pair<int, int> & mapping = pattern.roadMapping;
|
||||
|
||||
tile.roadDir = gen->nextInt(mapping.first, mapping.second);
|
||||
tile.extTileFlags = (tile.extTileFlags & 0xCF) | (flip << 4);
|
||||
}
|
||||
|
||||
CDrawRoadsOperation::ValidationResult CDrawRoadsOperation::validateTile(const RoadPattern & pattern, const int3 & pos)
|
||||
{
|
||||
ValidationResult result(false);
|
||||
|
||||
if(!canApplyPattern(pattern))
|
||||
return result;
|
||||
|
||||
|
||||
for(int flip = 0; flip < 4; ++flip)
|
||||
{
|
||||
if((flip == FLIP_PATTERN_BOTH) && !(pattern.hasHFlip && pattern.hasVFlip))
|
||||
continue;
|
||||
if((flip == FLIP_PATTERN_HORIZONTAL) && !pattern.hasHFlip)
|
||||
continue;
|
||||
if((flip == FLIP_PATTERN_VERTICAL) && !(pattern.hasVFlip))
|
||||
continue;
|
||||
|
||||
RoadPattern flipped = pattern;
|
||||
|
||||
flipPattern(flipped, flip);
|
||||
|
||||
bool validated = true;
|
||||
|
||||
for(int i = 0; i < 9; ++i)
|
||||
{
|
||||
if(4 == i)
|
||||
continue;
|
||||
int cx = pos.x + (i % 3) - 1;
|
||||
int cy = pos.y + (i / 3) - 1;
|
||||
|
||||
int3 currentPos(cx, cy, pos.z);
|
||||
|
||||
bool hasSomething;
|
||||
|
||||
if(!map->isInTheMap(currentPos))
|
||||
{
|
||||
hasSomething = true; //road/river can go out of map
|
||||
}
|
||||
else
|
||||
{
|
||||
hasSomething = tileHasSomething(currentPos);
|
||||
}
|
||||
|
||||
if(ruleIsSomething(flipped.data[i]))
|
||||
{
|
||||
if(!hasSomething)
|
||||
{
|
||||
validated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ruleIsNone(flipped.data[i]))
|
||||
{
|
||||
if(hasSomething)
|
||||
{
|
||||
validated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(ruleIsAny(flipped.data[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(validated)
|
||||
{
|
||||
result.result = true;
|
||||
result.flip = flip;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
58
lib/mapping/CDrawRoadsOperation.h
Normal file
58
lib/mapping/CDrawRoadsOperation.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* CDrawRoadsOperation.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "CMap.h"
|
||||
#include "CMapEditManager.h"
|
||||
|
||||
|
||||
class CDrawRoadsOperation : public CMapOperation
|
||||
{
|
||||
public:
|
||||
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen);
|
||||
void execute() override;
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
std::string getLabel() const override;
|
||||
private:
|
||||
|
||||
struct RoadPattern
|
||||
{
|
||||
std::string data[9];
|
||||
std::pair<int, int> roadMapping, riverMapping;
|
||||
bool hasHFlip, hasVFlip;
|
||||
};
|
||||
|
||||
struct ValidationResult
|
||||
{
|
||||
ValidationResult(bool result): result(result), flip(0){};
|
||||
bool result;
|
||||
int flip;
|
||||
};
|
||||
|
||||
static const std::vector<RoadPattern> patterns;
|
||||
|
||||
void flipPattern(RoadPattern & pattern, int flip) const;
|
||||
|
||||
void updateTiles(std::set<int3> & invalidated);
|
||||
|
||||
ValidationResult validateTile(const RoadPattern & pattern, const int3 & pos);
|
||||
void updateTile(TerrainTile & tile, const RoadPattern & pattern, const int flip);
|
||||
|
||||
bool canApplyPattern(const RoadPattern & pattern) const;
|
||||
bool needUpdateTile(const TerrainTile & tile) const;
|
||||
bool tileHasSomething(const int3 & pos) const;
|
||||
|
||||
CTerrainSelection terrainSel;
|
||||
ERoadType::ERoadType roadType;
|
||||
CRandomGenerator * gen;
|
||||
};
|
@ -261,22 +261,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
namespace ERiverType
|
||||
{
|
||||
enum ERiverType
|
||||
{
|
||||
NO_RIVER, CLEAR_RIVER, ICY_RIVER, MUDDY_RIVER, LAVA_RIVER
|
||||
};
|
||||
}
|
||||
|
||||
namespace ERoadType
|
||||
{
|
||||
enum ERoadType
|
||||
{
|
||||
NO_ROAD, DIRT_ROAD, GRAVEL_ROAD, COBBLESTONE_ROAD
|
||||
};
|
||||
}
|
||||
|
||||
/// The terrain tile describes the terrain type and the visual representation of the terrain.
|
||||
/// Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it.
|
||||
struct DLL_LINKAGE TerrainTile
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "../mapObjects/CObjectClassesHandler.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "CDrawRoadsOperation.h"
|
||||
|
||||
MapRect::MapRect() : x(0), y(0), z(0), width(0), height(0)
|
||||
{
|
||||
@ -132,6 +133,18 @@ std::string CMapOperation::getLabel() const
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
MapRect CMapOperation::extendTileAround(const int3 & centerPos) const
|
||||
{
|
||||
return MapRect(int3(centerPos.x - 1, centerPos.y - 1, centerPos.z), 3, 3);
|
||||
}
|
||||
|
||||
MapRect CMapOperation::extendTileAroundSafely(const int3 & centerPos) const
|
||||
{
|
||||
return extendTileAround(centerPos) & MapRect(int3(0, 0, centerPos.z), map->width, map->height);
|
||||
}
|
||||
|
||||
|
||||
CMapUndoManager::CMapUndoManager() : undoRedoLimit(10)
|
||||
{
|
||||
|
||||
@ -226,6 +239,13 @@ void CMapEditManager::drawTerrain(ETerrainType terType, CRandomGenerator * gen/*
|
||||
terrainSel.clearSelection();
|
||||
}
|
||||
|
||||
void CMapEditManager::drawRoad(ERoadType::ERoadType roadType, CRandomGenerator* gen)
|
||||
{
|
||||
execute(make_unique<CDrawRoadsOperation>(map, terrainSel, roadType, gen ? gen : &(this->gen)));
|
||||
terrainSel.clearSelection();
|
||||
}
|
||||
|
||||
|
||||
void CMapEditManager::insertObject(CGObjectInstance * obj, const int3 & pos)
|
||||
{
|
||||
execute(make_unique<CInsertObjectOperation>(map, obj, pos));
|
||||
@ -960,16 +980,6 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
|
||||
return tiles;
|
||||
}
|
||||
|
||||
MapRect CDrawTerrainOperation::extendTileAround(const int3 & centerPos) const
|
||||
{
|
||||
return MapRect(int3(centerPos.x - 1, centerPos.y - 1, centerPos.z), 3, 3);
|
||||
}
|
||||
|
||||
MapRect CDrawTerrainOperation::extendTileAroundSafely(const int3 & centerPos) const
|
||||
{
|
||||
return extendTileAround(centerPos) & MapRect(int3(0, 0, centerPos.z), map->width, map->height);
|
||||
}
|
||||
|
||||
CDrawTerrainOperation::ValidationResult::ValidationResult(bool result, const std::string & transitionReplacement /*= ""*/)
|
||||
: result(result), transitionReplacement(transitionReplacement)
|
||||
{
|
||||
|
@ -113,7 +113,14 @@ public:
|
||||
virtual void redo() = 0;
|
||||
virtual std::string getLabel() const = 0; /// Returns a display-able name of the operation.
|
||||
|
||||
protected:
|
||||
protected:
|
||||
MapRect extendTileAround(const int3 & centerPos) const;
|
||||
MapRect extendTileAroundSafely(const int3 & centerPos) const; /// doesn't exceed map size
|
||||
|
||||
static const int FLIP_PATTERN_HORIZONTAL = 1;
|
||||
static const int FLIP_PATTERN_VERTICAL = 2;
|
||||
static const int FLIP_PATTERN_BOTH = 3;
|
||||
|
||||
CMap * map;
|
||||
};
|
||||
|
||||
@ -161,7 +168,11 @@ public:
|
||||
|
||||
/// Draws terrain at the current terrain selection. The selection will be cleared automatically.
|
||||
void drawTerrain(ETerrainType terType, CRandomGenerator * gen = nullptr);
|
||||
void insertObject(CGObjectInstance * obj, const int3 & pos);
|
||||
|
||||
/// Draws roads at the current terrain selection. The selection will be cleared automatically.
|
||||
void drawRoad(ERoadType::ERoadType roadType, CRandomGenerator * gen = nullptr);
|
||||
|
||||
void insertObject(CGObjectInstance * obj, const int3 & pos);
|
||||
|
||||
CTerrainSelection & getTerrainSelection();
|
||||
CObjectSelection & getObjectSelection();
|
||||
@ -326,8 +337,6 @@ private:
|
||||
void updateTerrainTypes();
|
||||
void invalidateTerrainViews(const int3 & centerPos);
|
||||
InvalidTiles getInvalidTiles(const int3 & centerPos) const;
|
||||
MapRect extendTileAround(const int3 & centerPos) const;
|
||||
MapRect extendTileAroundSafely(const int3 & centerPos) const; /// doesn't exceed map size
|
||||
|
||||
void updateTerrainViews();
|
||||
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
||||
@ -339,10 +348,6 @@ private:
|
||||
bool isSandType(ETerrainType terType) const;
|
||||
void flipPattern(TerrainViewPattern & pattern, int flip) const;
|
||||
|
||||
static const int FLIP_PATTERN_HORIZONTAL = 1;
|
||||
static const int FLIP_PATTERN_VERTICAL = 2;
|
||||
static const int FLIP_PATTERN_BOTH = 3;
|
||||
|
||||
CTerrainSelection terrainSel;
|
||||
ETerrainType terType;
|
||||
CRandomGenerator * gen;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -66,13 +66,18 @@ public:
|
||||
void createConnections();
|
||||
void findZonesForQuestArts();
|
||||
void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
||||
void foreachDirectNeighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
||||
|
||||
bool isBlocked(const int3 &tile) const;
|
||||
bool shouldBeBlocked(const int3 &tile) const;
|
||||
bool isPossible(const int3 &tile) const;
|
||||
bool isFree(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 setRoad(const int3 &tile, ERoadType::ERoadType roadType);
|
||||
|
||||
CTileInfo getTile(const int3 & tile) const;
|
||||
|
||||
float getNearestObjectDistance(const int3 &tile) const;
|
||||
@ -99,6 +104,7 @@ private:
|
||||
//int questArtsRemaining;
|
||||
int monolithIndex;
|
||||
std::vector<ArtifactID> questArtifacts;
|
||||
void checkIsOnMap(const int3 &tile) const; //throws
|
||||
|
||||
/// Generation methods
|
||||
std::string getMapDescription() const;
|
||||
|
@ -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
|
||||
{
|
||||
return townCount;
|
||||
@ -81,7 +86,7 @@ void CRmgTemplateZone::CTownInfo::setCastleDensity(int value)
|
||||
castleDensity = value;
|
||||
}
|
||||
|
||||
CTileInfo::CTileInfo():nearestObjectDistance(INT_MAX), terrain(ETerrainType::WRONG)
|
||||
CTileInfo::CTileInfo():nearestObjectDistance(INT_MAX), terrain(ETerrainType::WRONG),roadType(ERoadType::NO_ROAD)
|
||||
{
|
||||
occupied = ETileType::POSSIBLE; //all tiles are initially possible to place objects or passages
|
||||
}
|
||||
@ -111,6 +116,12 @@ bool CTileInfo::isFree() const
|
||||
{
|
||||
return occupied == ETileType::FREE;
|
||||
}
|
||||
|
||||
bool CTileInfo::isRoad() const
|
||||
{
|
||||
return roadType != ERoadType::NO_ROAD;
|
||||
}
|
||||
|
||||
bool CTileInfo::isUsed() const
|
||||
{
|
||||
return occupied == ETileType::USED;
|
||||
@ -135,6 +146,13 @@ void CTileInfo::setTerrainType(ETerrainType value)
|
||||
terrain = value;
|
||||
}
|
||||
|
||||
void CTileInfo::setRoadType(ERoadType::ERoadType value)
|
||||
{
|
||||
roadType = value;
|
||||
// setOccupied(ETileType::FREE);
|
||||
}
|
||||
|
||||
|
||||
CRmgTemplateZone::CRmgTemplateZone() :
|
||||
id(0),
|
||||
type(ETemplateZoneType::PLAYER_START),
|
||||
@ -517,11 +535,11 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
}
|
||||
|
||||
//connect with all the paths
|
||||
crunchPath(gen, node, findClosestTile(freePaths, node), id, &freePaths);
|
||||
crunchPath(gen, node, findClosestTile(freePaths, node), &freePaths);
|
||||
//connect with nearby nodes
|
||||
for (auto nearbyNode : nearbyNodes)
|
||||
{
|
||||
crunchPath(gen, node, nearbyNode, id, &freePaths);
|
||||
crunchPath(gen, node, nearbyNode, &freePaths);
|
||||
}
|
||||
}
|
||||
for (auto node : nodes)
|
||||
@ -590,7 +608,7 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen)
|
||||
//logGlobal->infoStream() << boost::format ("Zone %d subdivided fractally") %id;
|
||||
}
|
||||
|
||||
bool CRmgTemplateZone::crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set<int3>* clearedTiles)
|
||||
bool CRmgTemplateZone::crunchPath(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles)
|
||||
{
|
||||
/*
|
||||
make shortest path with free tiles, reachning dst or closest already free tile. Avoid blocks.
|
||||
@ -611,7 +629,8 @@ do not leave zone border
|
||||
}
|
||||
|
||||
auto lastDistance = distance;
|
||||
gen->foreach_neighbour (currentPos, [this, gen, ¤tPos, dst, &distance, &result, &end, clearedTiles](int3 &pos)
|
||||
|
||||
auto processNeighbours = [this, gen, ¤tPos, dst, &distance, &result, &end, clearedTiles](int3 &pos)
|
||||
{
|
||||
if (!result) //not sure if lambda is worth it...
|
||||
{
|
||||
@ -643,15 +662,18 @@ do not leave zone border
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
gen->foreach_neighbour (currentPos,processNeighbours);
|
||||
|
||||
int3 anotherPos(-1, -1, -1);
|
||||
|
||||
if (!(result || distance < lastDistance)) //we do not advance, use more advaced pathfinding algorithm?
|
||||
if (!(result || distance < lastDistance)) //we do not advance, use more advanced pathfinding algorithm?
|
||||
{
|
||||
//try any nearby tiles, even if its not closer than current
|
||||
float lastDistance = 2 * distance; //start with significantly larger value
|
||||
gen->foreach_neighbour(currentPos, [this, gen, ¤tPos, dst, &lastDistance, &anotherPos, &end, clearedTiles](int3 &pos)
|
||||
|
||||
auto processNeighbours2 = [this, gen, ¤tPos, dst, &lastDistance, &anotherPos, &end, clearedTiles](int3 &pos)
|
||||
{
|
||||
if (currentPos.dist2dSQ(dst) < lastDistance) //try closest tiles from all surrounding unused tiles
|
||||
{
|
||||
@ -666,7 +688,11 @@ do not leave zone border
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
gen->foreach_neighbour (currentPos,processNeighbours2);
|
||||
|
||||
|
||||
if (anotherPos.valid())
|
||||
{
|
||||
if (clearedTiles)
|
||||
@ -686,6 +712,82 @@ do not leave zone border
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CRmgTemplateZone::createRoad(CMapGenerator* gen, const int3& src, const int3& dst)
|
||||
{
|
||||
//A* algorithm taken from Wiki http://en.wikipedia.org/wiki/A*_search_algorithm
|
||||
|
||||
std::set<int3> closed; // The set of nodes already evaluated.
|
||||
std::set<int3> open{src}; // The set of tentative nodes to be evaluated, initially containing the start node
|
||||
std::map<int3, int3> cameFrom; // The map of navigated nodes.
|
||||
std::map<int3, int> distances;
|
||||
|
||||
int3 currentNode = src;
|
||||
|
||||
cameFrom[src] = int3(-1, -1, -1); //first node points to finish condition
|
||||
distances[src] = 0;
|
||||
// Cost from start along best known path.
|
||||
// Estimated total cost from start to goal through y.
|
||||
|
||||
while (open.size())
|
||||
{
|
||||
int3 currentNode = *boost::min_element(open, [&distances](const int3 &pos1, const int3 &pos2) -> bool
|
||||
{
|
||||
return distances[pos1], distances[pos2];
|
||||
});
|
||||
|
||||
vstd::erase_if_present(open, currentNode);
|
||||
closed.insert(currentNode);
|
||||
|
||||
if (currentNode == dst || gen->isRoad(currentNode))
|
||||
{
|
||||
// The goal node was reached. Trace the path using
|
||||
// the saved parent information and return path
|
||||
int3 backTracking = currentNode;
|
||||
while (cameFrom[backTracking].valid())
|
||||
{
|
||||
// add node to path
|
||||
roads.insert(backTracking);
|
||||
gen->setRoad(backTracking, ERoadType::COBBLESTONE_ROAD);
|
||||
logGlobal->traceStream() << boost::format("Setting road at tile %s") % backTracking;
|
||||
// do the same for the predecessor
|
||||
backTracking = cameFrom[backTracking];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gen->foreach_neighbour(currentNode, [gen, this, &open, &closed, &cameFrom, ¤tNode, &distances](int3& pos)
|
||||
{
|
||||
int distance = distances[currentNode] + 1;
|
||||
int bestDistanceSoFar = 1e6; //FIXME: boost::limits
|
||||
auto it = distances.find(pos);
|
||||
if (it != distances.end())
|
||||
bestDistanceSoFar = it->second;
|
||||
|
||||
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
||||
{
|
||||
if (gen->map->checkForVisitableDir(currentNode, &gen->map->getTile(pos), pos))
|
||||
//if (gen->isFree(pos))
|
||||
{
|
||||
if (vstd::contains(this->tileinfo, pos))
|
||||
{
|
||||
cameFrom[pos] = currentNode;
|
||||
open.insert(pos);
|
||||
distances[pos] = distance;
|
||||
logGlobal->traceStream() << boost::format("Found connection between node %s and %s, current distance %d") % currentNode % pos % distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
logGlobal->warnStream() << boost::format("Failed to create road from %s to %s") % src %dst;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CRmgTemplateZone::addRequiredObject(CGObjectInstance * obj, si32 strength)
|
||||
{
|
||||
requiredObjects.push_back(std::make_pair(obj, strength));
|
||||
@ -919,7 +1021,7 @@ bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float m
|
||||
gen->setOccupied(tile, ETileType::BLOCKED); //so that crunch path doesn't cut through objects
|
||||
}
|
||||
|
||||
if (!crunchPath (gen, closestTile, closestFreeTile, id))
|
||||
if (!crunchPath (gen, closestTile, closestFreeTile))
|
||||
{
|
||||
//we can't connect this pile, just block it off and start over
|
||||
for (auto treasure : treasures)
|
||||
@ -1246,6 +1348,7 @@ bool CRmgTemplateZone::placeMines (CMapGenerator* gen)
|
||||
bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
|
||||
{
|
||||
logGlobal->traceStream() << "Creating required objects";
|
||||
|
||||
for(const auto &obj : requiredObjects)
|
||||
{
|
||||
int3 pos;
|
||||
@ -1254,11 +1357,11 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
|
||||
logGlobal->errorStream() << boost::format("Failed to fill zone %d due to lack of space") %id;
|
||||
//TODO CLEANUP!
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
placeObject (gen, obj.first, pos);
|
||||
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)
|
||||
@ -1446,6 +1549,52 @@ void CRmgTemplateZone::createObstacles2(CMapGenerator* gen)
|
||||
}
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::connectRoads(CMapGenerator* gen)
|
||||
{
|
||||
logGlobal->debug("Started building roads");
|
||||
|
||||
std::set<int3> processed;
|
||||
|
||||
while(!roadNodes.empty())
|
||||
{
|
||||
int3 node = *roadNodes.begin();
|
||||
roadNodes.erase(node);
|
||||
if(roads.empty())
|
||||
{
|
||||
//start road network
|
||||
roads.insert(node);
|
||||
logGlobal->debugStream() << "First node of road network: " << node;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto comparator = [=](int3 lhs, int3 rhs) { return node.dist2dSQ(lhs) < node.dist2dSQ(rhs); };
|
||||
|
||||
int3 cross = * boost::range::min_element(processed, comparator);
|
||||
logGlobal->debugStream() << "Building road from " << node << " to " << cross;
|
||||
createRoad(gen, node, cross);
|
||||
}
|
||||
|
||||
processed.insert(node);
|
||||
}
|
||||
|
||||
drawRoads(gen);
|
||||
|
||||
logGlobal->debug("Finished building roads");
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::drawRoads(CMapGenerator* gen)
|
||||
{
|
||||
std::vector<int3> tiles;
|
||||
for (auto tile : roads)
|
||||
{
|
||||
if(gen->map->isInTheMap(tile))
|
||||
tiles.push_back (tile);
|
||||
}
|
||||
gen->editManager->getTerrainSelection().setSelection(tiles);
|
||||
gen->editManager->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand);
|
||||
}
|
||||
|
||||
|
||||
bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
||||
{
|
||||
initTerrainType(gen);
|
||||
@ -1458,7 +1607,7 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
||||
placeMines(gen);
|
||||
createRequiredObjects(gen);
|
||||
createTreasures(gen);
|
||||
|
||||
|
||||
logGlobal->infoStream() << boost::format ("Zone %d filled successfully") %id;
|
||||
return true;
|
||||
}
|
||||
@ -1669,6 +1818,24 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
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(object->visitablePos());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard)
|
||||
@ -1715,7 +1882,7 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
|
||||
{
|
||||
//crunching path may fail if center of the zone is directly over wide object
|
||||
//make sure object is accessible before surrounding it with blocked tiles
|
||||
if (crunchPath (gen, tile, findClosestTile(freePaths, tile), id, addToFreePaths ? &freePaths : nullptr))
|
||||
if (crunchPath (gen, tile, findClosestTile(freePaths, tile), addToFreePaths ? &freePaths : nullptr))
|
||||
{
|
||||
guardTile = tile;
|
||||
break;
|
||||
|
@ -47,15 +47,18 @@ public:
|
||||
bool isPossible() const;
|
||||
bool isFree() const;
|
||||
bool isUsed() const;
|
||||
bool isRoad() const;
|
||||
void setOccupied(ETileType::ETileType value);
|
||||
ETerrainType getTerrainType() const;
|
||||
ETileType::ETileType getTileType() const;
|
||||
void setTerrainType(ETerrainType value);
|
||||
|
||||
|
||||
void setRoadType(ERoadType::ERoadType value);
|
||||
private:
|
||||
float nearestObjectDistance;
|
||||
ETileType::ETileType occupied;
|
||||
ETerrainType terrain;
|
||||
ERoadType::ERoadType roadType;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTreasureInfo
|
||||
@ -166,7 +169,8 @@ public:
|
||||
void createTreasures(CMapGenerator* gen);
|
||||
void createObstacles1(CMapGenerator* gen);
|
||||
void createObstacles2(CMapGenerator* gen);
|
||||
bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set<int3>* clearedTiles = nullptr);
|
||||
bool crunchPath(CMapGenerator* gen, const int3 &src, const int3 &dst, std::set<int3>* clearedTiles = nullptr);
|
||||
|
||||
std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
|
||||
|
||||
void addConnection(TRmgTemplateZoneId otherZone);
|
||||
@ -179,6 +183,8 @@ public:
|
||||
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 addRoadNode(const int3 & node);
|
||||
void connectRoads(CMapGenerator * gen); //fills "roads" according to "roadNodes"
|
||||
|
||||
private:
|
||||
//template info
|
||||
@ -215,6 +221,12 @@ private:
|
||||
std::set<int3> possibleTiles; //optimization purposes for treasure generation
|
||||
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> roadNodes; //tiles to be connected with roads
|
||||
std::set<int3> roads; //all tiles with roads
|
||||
|
||||
bool createRoad(CMapGenerator* gen, const int3 &src, const int3 &dst);
|
||||
void drawRoads(CMapGenerator * gen); //actually updates tiles
|
||||
|
||||
bool pointIsIn(int x, int y);
|
||||
void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
|
||||
|
@ -27,13 +27,13 @@
|
||||
<Depends filename="lib/VCMI_lib.cbp" />
|
||||
</Project>
|
||||
<Project filename="test/Test.cbp">
|
||||
<Depends filename="client/VCMI_client.cbp" />
|
||||
<Depends filename="server/VCMI_server.cbp" />
|
||||
<Depends filename="AI/EmptyAI/EmptyAI.cbp" />
|
||||
<Depends filename="AI/VCAI/VCAI.cbp" />
|
||||
<Depends filename="AI/StupidAI/StupidAI.cbp" />
|
||||
<Depends filename="AI/BattleAI/BattleAI.cbp" />
|
||||
<Depends filename="lib/VCMI_lib.cbp" />
|
||||
<Depends filename="client/VCMI_client.cbp" />
|
||||
</Project>
|
||||
<Project filename="scripting/erm/ERM.cbp">
|
||||
<Depends filename="lib/VCMI_lib.cbp" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user