1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00
- Some primitive way to randomize treasures
This commit is contained in:
DjWarmonger 2014-06-04 10:16:08 +02:00
parent 6221f4ac2c
commit 62e9f13b08
7 changed files with 169 additions and 44 deletions

View File

@ -1709,7 +1709,7 @@ CRandomMapTab::CRandomMapTab()
addButtonsWithRandToGroup(monsterStrengthGroup, monsterStrengthBtns, 0, 2, WIDE_BTN_WIDTH, 248, 251);
monsterStrengthGroup->onChange = [&](int btnId)
{
mapGenOptions.setMonsterStrength(static_cast<EMonsterStrength::EMonsterStrength>(btnId));
mapGenOptions.setMonsterStrength(static_cast<EMonsterStrength::EMonsterStrength>(btnId + EMonsterStrength::GLOBAL_WEAK)); //value 2 to 4
};
// Show random maps btn

View File

@ -70,12 +70,12 @@
},
"connections" :
[
{ "a" : "1", "b" : "3", "guard" : 2000 },
{ "a" : "1", "b" : "5", "guard" : 8000 },
{ "a" : "2", "b" : "4", "guard" : 2000 },
{ "a" : "2", "b" : "5", "guard" : 8000 },
{ "a" : "3", "b" : "5", "guard" : 4000 },
{ "a" : "4", "b" : "5", "guard" : 4000 }
{ "a" : "1", "b" : "3", "guard" : 3000 },
{ "a" : "1", "b" : "5", "guard" : 9000 },
{ "a" : "2", "b" : "4", "guard" : 3000 },
{ "a" : "2", "b" : "5", "guard" : 9000 },
{ "a" : "3", "b" : "5", "guard" : 6000 },
{ "a" : "4", "b" : "5", "guard" : 6000 }
]
},
"Golden Ring" :
@ -111,12 +111,12 @@
},
"connections" :
[
{ "a" : "1", "b" : "4", "guard" : 2000 },
{ "a" : "1", "b" : "5", "guard" : 2000 },
{ "a" : "2", "b" : "6", "guard" : 2000 },
{ "a" : "2", "b" : "7", "guard" : 2000 },
{ "a" : "3", "b" : "8", "guard" : 2000 },
{ "a" : "3", "b" : "9", "guard" : 2000 },
{ "a" : "1", "b" : "4", "guard" : 2500 },
{ "a" : "1", "b" : "5", "guard" : 2500 },
{ "a" : "2", "b" : "6", "guard" : 2500 },
{ "a" : "2", "b" : "7", "guard" : 2500 },
{ "a" : "3", "b" : "8", "guard" : 2500 },
{ "a" : "3", "b" : "9", "guard" : 2500 },
{ "a" : "4", "b" : "10", "guard" : 20000 },
{ "a" : "5", "b" : "12", "guard" : 20000 },
{ "a" : "6", "b" : "10", "guard" : 20000 },

View File

@ -216,11 +216,11 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
if(waterContent == EWaterContent::RANDOM)
{
waterContent = static_cast<EWaterContent::EWaterContent>(rand.nextInt(EWaterContent::LAST_ITEM));
waterContent = static_cast<EWaterContent::EWaterContent>(rand.nextInt(EWaterContent::NONE, EWaterContent::ISLANDS));
}
if(monsterStrength == EMonsterStrength::RANDOM)
{
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(EMonsterStrength::LAST_ITEM));
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(EMonsterStrength::GLOBAL_WEAK, EMonsterStrength::GLOBAL_STRONG));
}
//rectangular maps are the future of gaming

View File

@ -23,8 +23,7 @@ namespace EWaterContent
RANDOM = -1,
NONE,
NORMAL,
ISLANDS,
LAST_ITEM = ISLANDS
ISLANDS
};
}
@ -32,11 +31,13 @@ namespace EMonsterStrength
{
enum EMonsterStrength
{
RANDOM = -1,
WEAK,
NORMAL,
STRONG,
LAST_ITEM = STRONG
RANDOM = -2,
ZONE_WEAK = -1,
ZONE_NORMAL = 0,
ZONE_STRONG = 1,
GLOBAL_WEAK = 2,
GLOBAL_NORMAL = 3,
GLOBAL_STRONG = 4
};
}

View File

@ -258,6 +258,7 @@ void CMapGenerator::createConnections()
});
if (guardPos.valid())
{
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
//zones can make paths only in their own area
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId()); //make connection towards our zone center

View File

@ -403,15 +403,37 @@ void CRmgTemplateZone::addRequiredObject(CGObjectInstance * obj, si32 strength)
void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
{
//precalculate actual (randomized) monster strength based on this post
//http://forum.vcmi.eu/viewtopic.php?p=12426#12426
int zoneMonsterStrength = 0; //TODO: range -1..1 based on template settings
int mapMonsterStrength = gen->mapGenOptions->getMonsterStrength();
int monsterStrength = zoneMonsterStrength + mapMonsterStrength - 1; //array index from 0 to 4
static const int value1[] = {2500, 1500, 1000, 500, 0};
static const int value2[] = {7500, 7500, 7500, 5000, 5000};
static const float multiplier1[] = {0.5, 0.75, 1.0, 1.5, 1.5};
static const float multiplier2[] = {0.5, 0.75, 1.0, 1.0, 1.5};
int strength1 = std::max(0.f, (strength - value1[monsterStrength]) * multiplier1[monsterStrength]);
int strength2 = std::max(0.f, (strength - value2[monsterStrength]) * multiplier2[monsterStrength]);
strength = strength1 + strength2;
if (strength < 2000)
return; //no guard at all
CreatureID creId = CreatureID::NONE;
int amount = 0;
while (true)
{
creId = VLC->creh->pickRandomMonster(gen->rand);
auto cre = VLC->creh->creatures[creId];
amount = std::ceil((float)strength / cre->fightValue);
if (strength >= cre->fightValue && amount >= cre->ammMin && amount <= 100) //at leats one full monster. size between minimum size of given stack and 100
if ((cre->AIValue * (cre->ammMin + cre->ammMax) / 2 < strength) && (strength < cre->AIValue * 100)) //at leats one full monster. size between minimum size of given stack and 100
{
amount = strength / cre->AIValue;
if (amount >= 4)
amount *= gen->rand.nextDouble(0.75, 1.25);
break;
}
}
auto guard = new CGCreature();
@ -424,6 +446,119 @@ void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
placeObject(gen, guard, pos);
}
bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
{
//TODO: read treasure values from template
const int maxValue = 5000;
const int minValue = 1500;
static const Res::ERes woodOre[] = {Res::ERes::WOOD, Res::ERes::ORE};
static const Res::ERes preciousRes[] = {Res::ERes::CRYSTAL, Res::ERes::GEMS, Res::ERes::MERCURY, Res::ERes::SULFUR};
static auto res_gen = gen->rand.getIntRange(Res::ERes::WOOD, Res::ERes::GOLD);
int currentValue = 0;
CGObjectInstance * object = nullptr;
while (currentValue < minValue)
{
int remaining = maxValue - currentValue;
int nextValue = gen->rand.nextInt (0.25f * remaining, remaining);
if (nextValue >= 20000)
{
auto obj = new CGArtifact();
obj->ID = Obj::RANDOM_RELIC_ART;
obj->subID = 0;
auto a = new CArtifactInstance(); //TODO: probably some refactoring could help here
gen->map->addNewArtifactInstance(a);
obj->storedArtifact = a;
object = obj;
currentValue += 20000;
}
else if (nextValue >= 10000)
{
auto obj = new CGArtifact();
obj->ID = Obj::RANDOM_MAJOR_ART;
obj->subID = 0;
auto a = new CArtifactInstance();
gen->map->addNewArtifactInstance(a);
obj->storedArtifact = a;
object = obj;
currentValue += 10000;
}
else if (nextValue >= 5000)
{
auto obj = new CGArtifact();
obj->ID = Obj::RANDOM_MINOR_ART;
obj->subID = 0;
auto a = new CArtifactInstance();
gen->map->addNewArtifactInstance(a);
obj->storedArtifact = a;
object = obj;
currentValue += 5000;
}
else if (nextValue >= 2000)
{
auto obj = new CGArtifact();
obj->ID = Obj::RANDOM_TREASURE_ART;
obj->subID = 0;
auto a = new CArtifactInstance();
gen->map->addNewArtifactInstance(a);
obj->storedArtifact = a;
object = obj;
currentValue += 2000;
}
else if (nextValue >= 1500)
{
auto obj = new CGPickable();
obj->ID = Obj::TREASURE_CHEST;
obj->subID = 0;
object = obj;
currentValue += 1500;
}
else if (nextValue >= 1400)
{
auto obj = new CGResource();
auto restype = static_cast<Res::ERes>(preciousRes[gen->rand.nextInt (0,3)]); //TODO: how about dedicated function to pick random element of array?
obj->ID = Obj::RESOURCE;
obj->subID = static_cast<si32>(restype);
obj->amount = 0;
object = obj;
currentValue += 1400;
}
else if (nextValue >= 1000)
{
auto obj = new CGResource();
auto restype = static_cast<Res::ERes>(woodOre[gen->rand.nextInt (0,1)]);
obj->ID = Obj::RESOURCE;
obj->subID = static_cast<si32>(restype);
obj->amount = 0;
object = obj;
currentValue += 1000;
}
else if (nextValue >= 750)
{
auto obj = new CGResource();
obj->ID = Obj::RESOURCE;
obj->subID = static_cast<si32>(Res::ERes::GOLD);
obj->amount = 0;
object = obj;
currentValue += 750;
}
else //no possible treasure left (should not happen)
break;
//TODO: generate actual zone and not just all objects on a pile
placeObject(gen, object, pos);
}
if (object)
{
guardObject (gen, object, currentValue);
return true;
}
else //we did not place eveyrthing successfully
return false;
}
bool CRmgTemplateZone::fill(CMapGenerator* gen)
{
int townId = 0;
@ -515,15 +650,14 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
guardObject (gen, obj.first, obj.second);
}
}
std::vector<CGObjectInstance*> guarded_objects;
static auto res_gen = gen->rand.getIntRange(Res::ERes::WOOD, Res::ERes::GOLD);
const double res_mindist = 5;
//TODO: just placeholder to chekc for possible locations
auto obj = new CGResource();
obj->ID = Obj::RESOURCE;
obj->subID = static_cast<si32>(Res::ERes::GOLD);
obj->amount = 0;
do {
auto obj = new CGResource();
auto restype = static_cast<Res::ERes>(res_gen());
obj->ID = Obj::RESOURCE;
obj->subID = static_cast<si32>(restype);
obj->amount = 0;
int3 pos;
if ( ! findPlaceForObject(gen, obj, res_mindist, pos))
@ -531,22 +665,10 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
delete obj;
break;
}
placeObject(gen, obj, pos);
createTreasurePile (gen, pos);
if ((restype != Res::ERes::WOOD) && (restype != Res::ERes::ORE))
{
guarded_objects.push_back(obj);
}
} while(true);
for(const auto &obj : guarded_objects)
{
if ( ! guardObject(gen, obj, 1000))
{
//TODO, DEL obj from map
}
}
auto sel = gen->editManager->getTerrainSelection();
sel.clearSelection();
for (auto tile : tileinfo)

View File

@ -114,6 +114,7 @@ public:
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
void addMonster(CMapGenerator* gen, int3 &pos, si32 strength);
bool createTreasurePile (CMapGenerator* gen, int3 &pos);
bool fill(CMapGenerator* gen);
void createBorder(CMapGenerator* gen);
bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone);