From 8216bf951108d9c97aefa417ea11e5a4f9c72fda Mon Sep 17 00:00:00 2001 From: elexis Date: Wed, 7 Feb 2018 02:12:19 +0000 Subject: [PATCH] Arbitrarily constrain the random playerbase location function. Decrease the minimum distance between players progressively to find suitable locations. Assume that constraint to be constant and compute possible locations in advance, improving performance drastically, refs #5011. This was SVN commit r21134. --- .../mods/public/maps/random/rmgen2/setup.js | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/binaries/data/mods/public/maps/random/rmgen2/setup.js b/binaries/data/mods/public/maps/random/rmgen2/setup.js index 18171088c0..4bbe1b82a7 100644 --- a/binaries/data/mods/public/maps/random/rmgen2/setup.js +++ b/binaries/data/mods/public/maps/random/rmgen2/setup.js @@ -311,34 +311,47 @@ function placeRadial(playerIDs, distance, startAngle) /** * Choose arbitrary starting locations. */ -function placeRandom(playerIDs) +function placeRandom(playerIDs, constraints = undefined) { - var locations = []; - var attempts = 0; - var resets = 0; - var mapCenter = g_Map.getCenter(); + let locations = []; + let attempts = 0; + let resets = 0; + + let mapCenter = g_Map.getCenter(); + let playerMinDist = fractionToTiles(0.25); + let borderDistance = tilesToFraction(0.08); + + let area = createArea(new MapBoundsPlacer(), undefined, new AndConstraint(constraints)); for (let i = 0; i < getNumPlayers(); ++i) { - let position = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(randFloat(0, 0.42)), 0).rotate(randomAngle())).round(); + let position = pickRandom(area.points); // Minimum distance between initial bases must be a quarter of the map diameter - if (locations.some(loc => loc.distanceTo(position) < fractionToTiles(0.25))) + if (locations.some(loc => loc.distanceTo(position) < playerMinDist) || + position.distanceTo(mapCenter) > mapCenter.x + borderDistance) { --i; ++attempts; // Reset if we're in what looks like an infinite loop - if (attempts > 100) + if (attempts > 500) { locations = []; i = -1; attempts = 0; ++resets; + // Reduce minimum player distance progressively + if (resets % 25 == 0) + playerMinDist *= 0.975; + // If we only pick bad locations, stop trying to place randomly - if (resets == 100) + if (resets == 500) + { + error("Could not place playerbases!"); return undefined; + } } continue; }