1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +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); addButtonsWithRandToGroup(monsterStrengthGroup, monsterStrengthBtns, 0, 2, WIDE_BTN_WIDTH, 248, 251);
monsterStrengthGroup->onChange = [&](int btnId) 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 // Show random maps btn

View File

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

View File

@ -216,11 +216,11 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
if(waterContent == EWaterContent::RANDOM) 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) 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 //rectangular maps are the future of gaming

View File

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

View File

@ -258,6 +258,7 @@ void CMapGenerator::createConnections()
}); });
if (guardPos.valid()) 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 zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
//zones can make paths only in their own area //zones can make paths only in their own area
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId()); //make connection towards our zone center zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId()); //make connection towards our zone center

View File

@ -403,16 +403,38 @@ void CRmgTemplateZone::addRequiredObject(CGObjectInstance * obj, si32 strength)
void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, 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; CreatureID creId = CreatureID::NONE;
int amount = 0; int amount = 0;
while (true) while (true)
{ {
creId = VLC->creh->pickRandomMonster(gen->rand); creId = VLC->creh->pickRandomMonster(gen->rand);
auto cre = VLC->creh->creatures[creId]; auto cre = VLC->creh->creatures[creId];
amount = std::ceil((float)strength / cre->fightValue); 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
if (strength >= cre->fightValue && amount >= cre->ammMin && amount <= 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; break;
} }
}
auto guard = new CGCreature(); auto guard = new CGCreature();
guard->ID = Obj::MONSTER; guard->ID = Obj::MONSTER;
@ -424,6 +446,119 @@ void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
placeObject(gen, guard, pos); 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) bool CRmgTemplateZone::fill(CMapGenerator* gen)
{ {
int townId = 0; int townId = 0;
@ -515,15 +650,14 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
guardObject (gen, obj.first, obj.second); 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; const double res_mindist = 5;
do {
//TODO: just placeholder to chekc for possible locations
auto obj = new CGResource(); auto obj = new CGResource();
auto restype = static_cast<Res::ERes>(res_gen());
obj->ID = Obj::RESOURCE; obj->ID = Obj::RESOURCE;
obj->subID = static_cast<si32>(restype); obj->subID = static_cast<si32>(Res::ERes::GOLD);
obj->amount = 0; obj->amount = 0;
do {
int3 pos; int3 pos;
if ( ! findPlaceForObject(gen, obj, res_mindist, pos)) if ( ! findPlaceForObject(gen, obj, res_mindist, pos))
@ -531,22 +665,10 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
delete obj; delete obj;
break; break;
} }
placeObject(gen, obj, pos); createTreasurePile (gen, pos);
if ((restype != Res::ERes::WOOD) && (restype != Res::ERes::ORE))
{
guarded_objects.push_back(obj);
}
} while(true); } while(true);
for(const auto &obj : guarded_objects)
{
if ( ! guardObject(gen, obj, 1000))
{
//TODO, DEL obj from map
}
}
auto sel = gen->editManager->getTerrainSelection(); auto sel = gen->editManager->getTerrainSelection();
sel.clearSelection(); sel.clearSelection();
for (auto tile : tileinfo) for (auto tile : tileinfo)

View File

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