Random map generator


According to template, there are 3 swamp areas in there.


Trying to test RMG:

  1. 13:45:29 ERROR global [1054] - Failed to find template for 54:172 (creature.nightmare) and assertion crash.

  2. or even server process infinite looping (will try to reproduce in debug mode). No more details yet.
    Here is infinite loop.
    auto itTeam = std::next(teamNumbers[j].begin(), rand.nextInt (teamNumbers[j].size()));
    CMapGenerator::addPlayerInfo ([email protected]=0x28ef24) (lib\rmg\CMapGenerator.cpp:136)


On #1
IIRC this is bug with current WoG localization (game uses objects.txt from WoG.lod instead of something like zobjects.txt). Copying wog overrides file from “wog” mod should fix this. Still haven’t fixed this bug myself:(


I’m not the author of team code. It is convoluted and definitelly needs rework - sometimes you can roll one team or even one player, which results in instant victory. Even if settings are set otherwise. Tried to fix that, but with no succes.


Sorry, will try to fix that bug:)


Fixed bug, it seems that something went wrong during merging develop with branch. Bug wasn’t there before. Code is a bit complicated at this place for a (trivial) task: Generating list of teams and assigning players to teams. Perhaps someone finds a easier solution, but I will keep it, it should work now:)


Good job, Warmonger! Finally we can generate zones… and terrain placement seems to work (tested with many patterns by unit tests)!



I’ll post some examples of (probably) incorrect tile placement when I encounter them again :stuck_out_tongue:


Okay, zone boundaries and connections are ready and should match OH3 guard placement.


One big task is placement of treasure piles. I have some ideas for these, but won’t continue working on RMG for the rest of week at least.

In the meantime, I would like to get some help with map templates (water/underground, town types, mines, treasure values) from Beegee.
Another thing to do is to actually place some interesting objects. This will probably be closely related to Ivan’s progress on adventure map objects.


I think you already know this, here is some info from original H3 templates: heroescommunity.com/viewthread.p … genumber=1

Possible town types for a zone and info like treasure values and mines are currently missing in VCMI template format. Perhaps we should also add a wiki page about it, just like modding formats and use that for discussion. Water / underground can be specified by RMG settings and is not part of template.

You didn’t ask a specific question, so let me know =) I’ll try to answer in 1-2 days.


Will try to find some time to finish it but no promises for now.

What do you need to know about object for RMG? Values I know about are:

  • Object value
  • Max # per zone
  • Max # per map
  • Frequency of object - how often it may be selected by the game.
  • Terrains on which object can be placed
  • Object appearance (blocked tiles & visitable tiles)

Anything else?

First 4 are hardcoded in H3 - we’ll have to recreate such list (I saw that info somewhere on Russian forums) while last 2 can be found in objects.txt so this part is already known.

UPD: found that list:
forum.df2.ru/index.php?showtopic … ntry559149
For those who don’t know Russian - google translate seems to be good enough here.


Good to see this list exists. I’m nor sure about all the values, though.

For example relic artifact - it is said to be worth 20K, but Clash of Dragons / Marathon has some big piles of 120K value and they often spawn 4 relics (30K each). Also, 1400 for a pile of wood sounds like a LOT.
This, or I can’t understand the meaning of template values.

Also, this list needs to be linked in a smart way with object ID and subID, which may be not trivial.

Also, we may probably give up limits of object of certain kind per map, since VCMI can handle any number of them.

EDIT: Okay, I think I figured it out! RMG stops when it reaches lower bound of treasure value. At every step it picks object from 25% to 100% of remaining treasure value. Since the most valuable object is worth 30K, max generated treasure pile is 120K. Above that value treasures just won’t spawn since there are not enough valuable objects to pick.
Close to that value, piles spawn rarely and only if the object with 30K value is rolled.


According to author this list was reverse-engineered from H3. And since he is HotA programmer this is most likely true - list should match H3. How well that list was balanced is a separate question but it should be OK as base.

Actually we can link all of that to sub ID’s - apart from objects that need special handling (towns, heroes, mines, monoliths, etc) there are quite few objects that have sub ID’s. This is full list of objects that have sub ID’s:

artifact, boat, borderGuard, keymasterTent, cartographer, creatureBank, creatureGeneratorCommon, garrison, monolithOneWayEntrance, monolithOneWayExit, monolithTwoWay, mine, monster, resource, seerHut, town, borderGate, hero

In general I agree. But in some cases having per-map limit makes sense. For example obelisks - VCMI should handle 48+ obelisks but it makes no sense gameplay-wise. Probably we should implement per-map limit but use it only in few cases like this one.

And another property that RMG may need - object function (obstacle, treasure, guard, etc)


Could you please translate this formula:

Special objects, like guards, will be handled separately in engine. Most of what we need for now is one list with treasure objects and the other with obstacles. Another issue is to allow for example new monoliths or new keymaster colors, but this is not urgent.
My recent tests show that RMG treats all the treasures equally.



Creature dwelling (separate object for each creature type, 4-slot dwellings will not be generated):
(Creature AI Value)((Creature growth)(1 + (num of zones with home town)/(num of zones with main town)) + (num of zones with home town)/2) - 40
(will be generated only in zones with home town).

*home town - main town that produces this creature.

Should not be a problem - new keymasters/monoliths should be implemented as new subtypes of existing objects. This means that object handler API would need method like “get # of object subtypes”. Will do


Warmonger, can you take a look on this? This is loop that generates map border image:
github.com/vcmi/vcmi/blob/devel … r.cpp#L210

At line 210 that right now looks like this:

else if(j == -1 && i > -1 && i < sizes.y)

I think that this is the typo that causes broken map border on rectangular map. Instead it should check for size.x:

else if(j == -1 && i > -1 && i < sizes.x)


That sounds right, however I never saw that piece of code before :wink:

That formula won’t give less than 400K value for Azure Dragon dwelling on CoD, though they used to spawn with 120K treasure value, too. However, it gives acceptable results for lesser dwellings.
The only way to make it work is to assume that the number of home towns for neutral creatures is always 0. But then the value of dwelling is 78K. But then, Azure Dragon dwelllings tend to spawn alone with value only 78800. Another issue is that the strength of guards can vary for just the same objects.

Reverse-engineering of RMG is not a simple task :stuck_out_tongue:


Forums seems to be down yet again so this is what I found using google cache. Note the very last line - this is likely source of different guards for same objects.

Calculation of guard AI value
zone monsters strength = -1 … 1 (defined in template: none, weak, average or strong)
map monster strength = 2 … 4 (defined before map generation by player)

moster strength = zone strength + map strength (resulting in range 1 … 5)

Then RMG selects values and multipliers according to this table:

moster strength	1     2     3     4     5
value1        	2500  1500  1000  500   0
multiplier1   	0.5   0.75  1.0   1.5   1.5
value2        	7500  7500  7500  5000  5000
multiplier2   	0.5   0.75  1.0   1.0   1.5

strength1 = (treasure value - value1) * multiplier1;
strength2 = (treasure value - value2) * multiplier2;

Guard value = strength1 + strength2

  • If strength1 is negative it won’t be added to guard value

  • If strength2 is negative it won’t be added to guard value

  • If guard value is below 2000 object will not have any guards at all

For zone connection guards calculations are almost identical except for lack of “zone monster strength”. Note that in case of monoliths/subterranean gates guards will be placed on each side of path.

Selection of creatures

Creature is applicable to be used as guard if:
AI Value * (Adv map max + Adv map min) / 2 < Guard value < AI Value * 100

Initial size of guard stack is:
Preferred size = Guard value / AI value

if (preferred size < 4)
size = preferred size
size = rand(0.75, 1.25) * preferred size

Fun part is that I remember post from Sav (same author as everything else here) that placement of neutral dwellings in town-free zones is an obvious bug in RMG :slight_smile:


To summarize RMG <-> objects relation. I’m going to provide access to following info:

As part of object handler:

std::set<si32> knownObjects();
std::set<si32> knownSubobjects(si32 primaryID);

As part of object type:

  1. Test for static decorations
  2. For treasures-only - struct that looks like this:
struct RandomMapInfo
    ui32 value;
    ui32 perZoneLimit;
    ui32 perMapLimit;
    ui32 rarity; // better name?

If value is 0 - then object can not be placed by RMG or have special rules (decorations, towns, etc)

Is that OK? Anything else?


Looks good. However, I ran into more serious issues:

  • Generating objects on RMG side duplicates MapFormatH3M.cpp functionality. Some object factory would be nice, as now constructor of each object class needs to be called separately.
  • I see a need for clone pattern as well to clone existing objects and still hold the info about their properties. Keep in mind that still not all the objects can be easily cloned, for example CArtifact hold pointer to CArtifactInstance in CMap object.
  • Many objects, like a ton of Pandora Box variations, don’t fit in simple config files. They probably need to be hardcoded.

Basically what I want to do is to generate collection of preconfigured object instances and then just draw random objects from it, clone them and place on a map.