Random-map-script cleanup.

Move duplicate code of the area- and object-group placing methods to
retryPlacing and two coordinate-randomization functions.
Remove three unused functions (println obsolete since 0e0ed94926,
chooseRand and its helper argsToArray since before 34f1817869).
Inline local calls to GetMapSize() and IsCircularMap(). Keep unused
isCircularMap for API access. Cache variables when retrying.
Map-generation can finish 2% faster.

This was SVN commit r17728.
This commit is contained in:
elexis 2016-02-02 16:33:36 +00:00
parent fdc67768f0
commit 6052716a78

View File

@ -10,12 +10,12 @@ const FALLBACK_CIV = "athen";
function fractionToTiles(f)
{
return getMapSize() * f;
return g_Map.size * f;
}
function tilesToFraction(t)
{
return t / getMapSize();
return t / g_Map.size;
}
function fractionToSize(f)
@ -30,7 +30,7 @@ function sizeToFraction(s)
function scaleByMapSize(min, max)
{
return min + ((max-min) * (getMapSize()-MIN_MAP_SIZE) / (MAX_MAP_SIZE-MIN_MAP_SIZE));
return min + (max - min) * (g_Map.size - MIN_MAP_SIZE) / (MAX_MAP_SIZE - MIN_MAP_SIZE);
}
function cos(x)
@ -82,245 +82,200 @@ function min(a, b)
return a < b ? a : b;
}
function println(x)
{
print(x);
print("\n");
}
function argsToArray(x)
{
var numArgs = x.length;
if (numArgs != 1)
{
var ret = new Array(numArgs);
for (var i=0; i < numArgs; i++)
{
ret[i] = x[i];
}
return ret;
}
else
{
return x[0];
}
}
function chooseRand()
{
if (arguments.length==0)
{
throw("chooseRand: requires at least 1 argument");
}
var ar = argsToArray(arguments);
return ar[randInt(ar.length)];
}
// "Inside-out" implementation of Fisher-Yates shuffle
/**
* "Inside-out" implementation of Fisher-Yates shuffle
*/
function shuffleArray(source)
{
if (!source.length)
return [];
var result = [source[0]];
for (var i = 1; i < source.length; i++)
let result = [source[0]];
for (let i = 1; i < source.length; ++i)
{
var j = randInt(0, i);
let j = randInt(0, i);
result[i] = result[j];
result[j] = source[i];
}
return result;
}
function createAreas(centeredPlacer, painter, constraint, num, retryFactor)
/**
* Retries the given function with those arguments as often as specified.
*/
function retryPlacing(placeFunc, placeArgs, retryFactor, amount, getResult)
{
if (retryFactor === undefined)
{
retryFactor = 10;
}
var maxFail = num * retryFactor;
var good = 0;
var bad = 0;
var result = [];
var halfSize = getMapSize()/2;
while(good < num && bad <= maxFail)
{
if (isCircularMap())
{ // Polar coordinates
var r = halfSize * Math.sqrt(randFloat()); // uniform distribution
var theta = randFloat(0, 2 * PI);
centeredPlacer.x = Math.floor(r * Math.cos(theta)) + halfSize;
centeredPlacer.z = Math.floor(r * Math.sin(theta)) + halfSize;
}
else
{ // Rectangular coordinates
centeredPlacer.x = randInt(getMapSize());
centeredPlacer.z = randInt(getMapSize());
}
var area = g_Map.createArea(centeredPlacer, painter, constraint);
if (area !== undefined)
{
good++;
result.push(area);
}
else
{
bad++;
}
}
return result;
}
let maxFail = amount * retryFactor;
function createAreasInAreas(centeredPlacer, painter, constraint, num, retryFactor, areas)
{
if (retryFactor === undefined)
{
retryFactor = 10;
}
var maxFail = num * retryFactor;
var good = 0;
var bad = 0;
var result = [];
var numAreas = areas.length;
while(good < num && bad <= maxFail && numAreas)
{
// Choose random point from area
var i = randInt(numAreas);
var size = areas[i].points.length;
var pt = areas[i].points[randInt(size)];
centeredPlacer.x = pt.x;
centeredPlacer.z = pt.z;
var area = g_Map.createArea(centeredPlacer, painter, constraint);
if (area !== undefined)
{
good++;
result.push(area);
}
else
{
bad++;
}
}
return result;
}
let results = [];
let good = 0;
let bad = 0;
function createObjectGroups(placer, player, constraint, num, retryFactor)
{
if (retryFactor === undefined)
while (good < amount && bad <= maxFail)
{
retryFactor = 10;
}
var maxFail = num * retryFactor;
var good = 0;
var bad = 0;
var halfSize = getMapSize()/2 - 3;
while(good < num && bad <= maxFail)
{
if (isCircularMap())
{ // Polar coordinates
var r = halfSize * Math.sqrt(randFloat()); // uniform distribution
var theta = randFloat(0, 2 * PI);
placer.x = Math.floor(r * Math.cos(theta)) + halfSize;
placer.z = Math.floor(r * Math.sin(theta)) + halfSize;
}
else
{ // Rectangular coordinates
placer.x = randInt(getMapSize());
placer.z = randInt(getMapSize());
}
var result = createObjectGroup(placer, player, constraint);
let result = placeFunc(placeArgs);
if (result !== undefined)
{
good++;
++good;
if (getResult)
results.push(result);
}
else
{
bad++;
}
++bad;
}
return good;
return getResult ? results : good;
}
function createObjectGroupsByAreas(placer, player, constraint, num, retryFactor, areas)
/**
* Helper function for randomly placing areas and groups on the map.
*/
function randomizePlacerCoordinates(placer, halfMapSize)
{
if (retryFactor === undefined)
if (!!g_MapSettings.CircularMap)
{
retryFactor = 10;
// Polar coordinates
let r = halfMapSize * Math.sqrt(randFloat()); // uniform distribution
let theta = randFloat(0, 2 * PI);
placer.x = Math.floor(r * Math.cos(theta)) + halfMapSize;
placer.z = Math.floor(r * Math.sin(theta)) + halfMapSize;
}
var maxFail = num * retryFactor;
var good = 0;
var bad = 0;
var numAreas = areas.length;
while(good < num && bad <= maxFail && numAreas)
else
{
// Choose random point from area
var i = randInt(numAreas);
var size = areas[i].points.length;
var pt = areas[i].points[randInt(size)];
placer.x = pt.x;
placer.z = pt.z;
var result = createObjectGroup(placer, player, constraint);
if (result !== undefined)
{
good++;
}
else
{
bad++;
}
// Rectangular coordinates
placer.x = randInt(g_Map.size);
placer.z = randInt(g_Map.size);
}
return good;
}
/**
* Helper function for randomly placing areas and groups in the given areas.
*/
function randomizePlacerCoordinatesFromAreas(placer, areas)
{
let i = randInt(areas.length);
let pt = areas[i].points[randInt(areas[i].points.length)];
placer.x = pt.x;
placer.z = pt.z;
}
/**
* Attempts to place the given number of areas in random places of the map.
* Returns actually placed areas.
*/
function createAreas(centeredPlacer, painter, constraint, amount, retryFactor = 10)
{
let placeFunc = function (args) {
randomizePlacerCoordinates(args.placer, args.halfMapSize);
return g_Map.createArea(args.placer, args.painter, args.constraint);
};
let args = {
"placer": centeredPlacer,
"painter": painter,
"constraint": constraint,
"halfMapSize": g_Map.size / 2
};
return retryPlacing(placeFunc, args, retryFactor, amount, true);
}
/**
* Attempts to place the given number of areas in random places of the given areas.
* Returns actually placed areas.
*/
function createAreasInAreas(centeredPlacer, painter, constraint, amount, retryFactor, areas)
{
if (!areas.length)
return [];
let placeFunc = function (args) {
randomizePlacerCoordinatesFromAreas(args.placer, args.areas);
return g_Map.createArea(args.placer, args.painter, args.constraint);
};
let args = {
"placer": centeredPlacer,
"painter": painter,
"constraint": constraint,
"areas": areas,
"halfMapSize": g_Map.size / 2
};
return retryPlacing(placeFunc, args, retryFactor, amount, true);
}
/**
* Attempts to place the given number of groups in random places of the map.
* Returns the number of actually placed groups.
*/
function createObjectGroups(placer, player, constraint, amount, retryFactor = 10)
{
let placeFunc = function (args) {
randomizePlacerCoordinates(args.placer, args.halfMapSize);
return createObjectGroup(args.placer, args.player, args.constraint);
};
let args = {
"placer": placer,
"player": player,
"constraint": constraint,
"halfMapSize": g_Map.size / 2 - 3
};
return retryPlacing(placeFunc, args, retryFactor, amount, false);
}
/**
* Attempts to place the given number of groups in random places of the given areas.
* Returns the number of actually placed groups.
*/
function createObjectGroupsByAreas(placer, player, constraint, amount, retryFactor, areas)
{
if (!areas.length)
return 0;
let placeFunc = function (args) {
randomizePlacerCoordinatesFromAreas(args.placer, args.areas);
return createObjectGroup(args.placer, args.player, args.constraint);
};
let args = {
"placer": placer,
"player": player,
"constraint": constraint,
"areas": areas
};
return retryPlacing(placeFunc, args, retryFactor, amount, false);
}
function createTerrain(terrain)
{
if (terrain instanceof Array)
{
var terrainList = [];
for (var i = 0; i < terrain.length; ++i)
{
terrainList.push(createTerrain(terrain[i]));
}
return new RandomTerrain(terrainList);
}
else
{
if (!(terrain instanceof Array))
return createSimpleTerrain(terrain);
}
let terrainList = [];
for (let i = 0; i < terrain.length; ++i)
terrainList.push(createTerrain(terrain[i]));
return new RandomTerrain(terrainList);
}
function createSimpleTerrain(terrain)
{
if (typeof(terrain) == "string")
{ // Split string by pipe | character, this allows specifying terrain + tree type in single string
var params = terrain.split(TERRAIN_SEPARATOR, 2);
if (params.length != 2)
{
return new SimpleTerrain(terrain);
}
else
{
return new SimpleTerrain(params[0], params[1]);
}
}
else
{
if (typeof(terrain) != "string")
throw("createSimpleTerrain expects string as input, received "+terrain);
}
// Split string by pipe | character, this allows specifying terrain + tree type in single string
let params = terrain.split(TERRAIN_SEPARATOR, 2);
if (params.length != 2)
return new SimpleTerrain(terrain);
return new SimpleTerrain(params[0], params[1]);
}
function placeObject(x, z, type, player, angle)
@ -420,7 +375,7 @@ function primeSortPlayers(playerIndices)
if (!playerIndices.length)
return [];
let prime = []
let prime = [];
for (let i = 0; i < Math.ceil(playerIndices.length / 2); ++i)
{
prime.push(playerIndices[i]);