1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

New rule for placement of unguarded treasures

This commit is contained in:
DjWarmonger 2014-12-26 16:17:39 +01:00
parent 121c39a994
commit 5fbd856a4c
2 changed files with 87 additions and 69 deletions

View File

@ -138,7 +138,8 @@ CRmgTemplateZone::CRmgTemplateZone() :
matchTerrainToTown(true), matchTerrainToTown(true),
townType(ETownType::NEUTRAL), townType(ETownType::NEUTRAL),
terrainType (ETerrainType::GRASS), terrainType (ETerrainType::GRASS),
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL) zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
minGuardedValue(0)
{ {
terrainTypes = getDefaultTerrainTypes(); terrainTypes = getDefaultTerrainTypes();
} }
@ -714,6 +715,7 @@ bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float m
int maxValue = treasureInfo.max; int maxValue = treasureInfo.max;
int minValue = treasureInfo.min; int minValue = treasureInfo.min;
bool needsGuard = treasureInfo.max >= minGuardedValue;
ui32 desiredValue = gen->rand.nextInt(minValue, maxValue); ui32 desiredValue = gen->rand.nextInt(minValue, maxValue);
//quantize value to let objects with value equal to max spawn too //quantize value to let objects with value equal to max spawn too
@ -724,24 +726,27 @@ bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float m
{ {
treasures[info.nextTreasurePos] = nullptr; treasures[info.nextTreasurePos] = nullptr;
for (auto treasurePos : treasures) if (needsGuard) //we will need to create perimeter around treasure objects
{ {
gen->foreach_neighbour (treasurePos.first, [gen, &boundary](int3 pos) for (auto treasurePos : treasures)
{ {
boundary.insert(pos); gen->foreach_neighbour(treasurePos.first, [gen, &boundary](int3 pos)
}); {
} boundary.insert(pos);
for (auto treasurePos : treasures) });
{ }
//leaving only boundary around objects for (auto treasurePos : treasures)
vstd::erase_if_present (boundary, treasurePos.first); {
} //leaving only boundary around objects
vstd::erase_if_present(boundary, treasurePos.first);
}
for (auto tile : boundary) for (auto tile : boundary)
{ {
//we can't extend boundary anymore //we can't extend boundary anymore
if (!(gen->isBlocked(tile) || gen->isPossible(tile))) if (!(gen->isBlocked(tile) || gen->isPossible(tile)))
break; break;
}
} }
ObjectInfo oi = getRandomObject(gen, info, desiredValue, maxValue, currentValue); ObjectInfo oi = getRandomObject(gen, info, desiredValue, maxValue, currentValue);
@ -869,61 +874,65 @@ bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float m
//update boundary around our objects, including knowledge about objects visitable from bottom //update boundary around our objects, including knowledge about objects visitable from bottom
boundary.clear(); boundary.clear();
for (auto tile : info.visitableFromBottomPositions)
{
gen->foreach_neighbour (tile, [tile, &boundary](int3 pos)
{
if (pos.y >= tile.y) //don't block these objects from above
boundary.insert(pos);
});
}
for (auto tile : info.visitableFromTopPositions)
{
gen->foreach_neighbour (tile, [&boundary](int3 pos)
{
boundary.insert(pos);
});
}
for (auto tile : boundary) //guard must be standing there if (needsGuard)
{ {
if (gen->isFree(tile)) //this tile could be already blocked, don't place a monster here for (auto tile : info.visitableFromBottomPositions)
{ {
guardPos = tile; gen->foreach_neighbour(tile, [tile, &boundary](int3 pos)
break;
}
}
if (guardPos.valid())
{
for (auto treasure : treasures)
{
int3 visitableOffset = treasure.second->getVisitableOffset();
placeObject(gen, treasure.second, treasure.first + visitableOffset);
}
if (addMonster(gen, guardPos, currentValue, false))
{//block only if the object is guarded
for (auto tile : boundary)
{ {
if (gen->isPossible(tile)) if (pos.y >= tile.y) //don't block these objects from above
gen->setOccupied (tile, ETileType::BLOCKED); boundary.insert(pos);
}
//do not spawn anything near monster
gen->foreach_neighbour (guardPos, [gen](int3 pos)
{
if (gen->isPossible(pos))
gen->setOccupied(pos, ETileType::FREE);
}); });
} }
} for (auto tile : info.visitableFromTopPositions)
else //we couldn't make a connection to this location, block it
{
for (auto treasure : treasures)
{ {
if (gen->isPossible(treasure.first)) gen->foreach_neighbour(tile, [&boundary](int3 pos)
gen->setOccupied (treasure.first, ETileType::BLOCKED); {
boundary.insert(pos);
});
}
delete treasure.second; for (auto tile : boundary) //guard must be standing there
{
if (gen->isFree(tile)) //this tile could be already blocked, don't place a monster here
{
guardPos = tile;
break;
}
}
if (guardPos.valid())
{
for (auto treasure : treasures)
{
int3 visitableOffset = treasure.second->getVisitableOffset();
placeObject(gen, treasure.second, treasure.first + visitableOffset);
}
if (addMonster(gen, guardPos, currentValue, false))
{//block only if the object is guarded
for (auto tile : boundary)
{
if (gen->isPossible(tile))
gen->setOccupied(tile, ETileType::BLOCKED);
}
//do not spawn anything near monster
gen->foreach_neighbour(guardPos, [gen](int3 pos)
{
if (gen->isPossible(pos))
gen->setOccupied(pos, ETileType::FREE);
});
}
}
else //we couldn't make a connection to this location, block it
{
for (auto treasure : treasures)
{
if (gen->isPossible(treasure.first))
gen->setOccupied(treasure.first, ETileType::BLOCKED);
delete treasure.second;
}
} }
} }
@ -1235,6 +1244,12 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
void CRmgTemplateZone::createTreasures(CMapGenerator* gen) void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
{ {
int mapMonsterStrength = gen->mapGenOptions->getMonsterStrength();
int monsterStrength = zoneMonsterStrength + mapMonsterStrength - 1; //array index from 0 to 4
static int minGuardedValues[] = { 6500, 4167, 3000, 1833, 1333 };
minGuardedValue = minGuardedValues[monsterStrength];
auto valueComparator = [](const CTreasureInfo & lhs, const CTreasureInfo & rhs) -> bool auto valueComparator = [](const CTreasureInfo & lhs, const CTreasureInfo & rhs) -> bool
{ {
return lhs.max > rhs.max; return lhs.max > rhs.max;
@ -1264,7 +1279,7 @@ void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
}); });
int3 pos; int3 pos;
if (!findPlaceForTreasurePile(gen, minDistance, pos)) if (!findPlaceForTreasurePile(gen, minDistance, pos, t.max))
{ {
break; break;
} }
@ -1426,11 +1441,13 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
return true; return true;
} }
bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, float min_dist, int3 &pos) bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, float min_dist, int3 &pos, int value)
{ {
float best_distance = 0; float best_distance = 0;
bool result = false; bool result = false;
bool needsGuard = value > minGuardedValue;
//logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist; //logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist;
for(auto tile : possibleTiles) for(auto tile : possibleTiles)
{ {
@ -1439,9 +1456,9 @@ bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, float min_di
if ((dist >= min_dist) && (dist > best_distance)) if ((dist >= min_dist) && (dist > best_distance))
{ {
bool allTilesAvailable = true; bool allTilesAvailable = true;
gen->foreach_neighbour (tile, [&gen, &allTilesAvailable](int3 neighbour) gen->foreach_neighbour (tile, [&gen, &allTilesAvailable, needsGuard](int3 neighbour)
{ {
if (!(gen->isPossible(neighbour) || gen->shouldBeBlocked(neighbour))) if (!(gen->isPossible(neighbour) || gen->shouldBeBlocked(neighbour) || (!needsGuard && gen->isFree(neighbour))))
{ {
allTilesAvailable = false; //all present tiles must be already blocked or ready for new objects allTilesAvailable = false; //all present tiles must be already blocked or ready for new objects
} }
@ -1456,7 +1473,7 @@ bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, float min_di
} }
if (result) if (result)
{ {
gen->setOccupied(pos, ETileType::BLOCKED); //block that tile gen->setOccupied(pos, ETileType::BLOCKED); //block that tile //FIXME: why?
} }
return result; return result;
} }

View File

@ -196,6 +196,7 @@ private:
EMonsterStrength::EMonsterStrength zoneMonsterStrength; EMonsterStrength::EMonsterStrength zoneMonsterStrength;
std::vector<CTreasureInfo> treasureInfo; std::vector<CTreasureInfo> treasureInfo;
std::vector<ObjectInfo> possibleObjects; std::vector<ObjectInfo> possibleObjects;
int minGuardedValue;
//content info //content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects; std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
@ -214,7 +215,7 @@ private:
void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
bool isAccessibleFromAnywhere (CMapGenerator* gen, ObjectTemplate &appearance, int3 &tile, const std::set<int3> &tilesBlockedByObject) const; bool isAccessibleFromAnywhere (CMapGenerator* gen, ObjectTemplate &appearance, int3 &tile, const std::set<int3> &tilesBlockedByObject) const;
bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos); bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos);
bool findPlaceForTreasurePile(CMapGenerator* gen, float min_dist, int3 &pos); bool findPlaceForTreasurePile(CMapGenerator* gen, float min_dist, int3 &pos, int value);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos); bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void setTemplateForObject(CMapGenerator* gen, CGObjectInstance* obj); void setTemplateForObject(CMapGenerator* gen, CGObjectInstance* obj);
bool areAllTilesAvailable(CMapGenerator* gen, CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const; bool areAllTilesAvailable(CMapGenerator* gen, CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const;