Opened 6 years ago

Last modified 5 years ago

#5003 new defect

Add Constraint, TileClass and failFraction to rmgen Wall Builder

Reported by: elexis Owned by:
Priority: Must Have Milestone: Backlog
Component: Maps Keywords:
Cc: Patch:

Description

Some overlasting problems with walls (mostly the Iberian walls since these are present on most maps) is that the wall builder library has no way to figure out where it's sensible to be placed and where not.

For instance walls can be placed in water, on top of mountains, cliffs and into forests.

If it would use the same concepts as otherwhere in rmgen, namely only placing walls if a custom Constraint is set, marking placed walls with a custom TileClass so that the entities, terrain textures and elevation placed afterwards can avoid the walls if desired.

Similar to the createObjectGroups and createAreas calls, a different wall angle could be tried if the first attempt failed.

Attachments (1)

wall.jpg (728.1 KB ) - added by elexis 6 years ago.

Download all attachments as: .zip

Change History (6)

by elexis, 6 years ago

Attachment: wall.jpg added

comment:1 by elexis, 6 years ago

https://trac.wildfiregames.com/raw-attachment/ticket/5003/wall.jpg

Just returning the points where something was placed is sufficient to do avoid the areas in a not too precise manner (as it doesn't consider the obstruction size), but sufficient for rmgen.

comment:2 by elexis, 6 years ago

In 21554:

Simple support for Constraints in the Wall Builder random map library, so that one can place walls while avoiding collisions, refs #5003.

Return the placed entities, so that one can parse and elegantly avoid them afterwards, in particular determine gate positions.
placeCircularWall uses the startAngle as orientation, since that is much easier to pass than the opposite vector of the center of the wall.

comment:3 by FeXoR, 5 years ago

So for this to work we need a function getObstructedTiles(EntityList) right?

To determine the obstructed tiles we need: Obstructions and their relative position vector (likely deduced from Entity template or string), placement position vector and angle.

So template string I guess?

Last edited 5 years ago by FeXoR (previous) (diff)

comment:4 by elexis, 5 years ago

Constraints were already implemented above. When one wants to avoid a list of entities, one can use the EntitiesObstructionPlacer, but one could also avoid tileClasses, heights, or any other Constraint

So what's remaining TODO would be failFraction. For example one could pass 80% for iberian starting walls, so that if the 20% of the wall pieces don't satisfy the constraint, it does not place any entity. (The map could still decide to try the 'towers' starting variant).

Retry loops would be useful, so that if one irregular iberian wallset generation doesn't meet the constraint at one place, it can try a different set of starting walls, and retry up to N times.

Also I wonder if it wouldn't be reasonable to split that thing into multiple WallPlacer classes that implement a common interface and split the shared code.

Also should figure out whether we can rename it to something more abstract, as one can use this library equally with non-wall entities (sheep-fortress for instance). (It's something like a sequential or linear entity placer I suppose, whereas the CityPainter is an area-based entity-placer)

The ticket also speaks about marking tiles with a TileClass. But that should only be added if it's not done with a lot of duplication. As the function return the placed entities, one can already paint on the tiles using a createArea call, like Jebel Barkal does:

let entitiesWalls = placeCircularWall(
...

createArea(
	new EntitiesObstructionPlacer(entitiesWalls, 0, Infinity),
	new TileClassPainter(clWall));

comment:5 by FeXoR, 5 years ago

EntitiesObstructionPlacer works on the tile grid. That's OK for tileclasses (the obvious way to go here) but not that much for finer control like chicken or other small entities (where more than one can fit on a tile not colliding).

I'm leaning towards only using the tile grid because that should be OK for random maps.

However, this also increases the dependency of libs (in this case wall_builder depend on tileclasses, placers etc.). I don't really like this for many reasons. The main thing is that stuff get's entangled and you can't use one functionality of the libs without being forced to use others you might actually want to avoid (e.g. for performance reasons). Also layering the API gets harder and harder with every added dependency between libs.

Sure we can create a big blob of intertwined functionality that works great if one follows the idea of the entire blob but the functions become useless if one wants to only use parts of it.

Note: See TracTickets for help on using tickets.