1
0
forked from 0ad/0ad

Clean code of Unknown

- Put the actual functions in `unknownMapFunctions` instead of just the
names
- Inline some functions

Comments by: elexis
Differential Revision: https://code.wildfiregames.com/D5280
This was SVN commit r28105.
This commit is contained in:
phosit 2024-06-08 11:37:27 +00:00
parent 22a8f367f8
commit 06545f5de1

View File

@ -74,26 +74,6 @@ const clShallow = g_Map.createTileClass();
const landElevationPainter = new SmoothElevationPainter(ELEVATION_SET, heightLand, 4); const landElevationPainter = new SmoothElevationPainter(ELEVATION_SET, heightLand, 4);
const unknownMapFunctions = {
"land": [
"Continent",
"Isthmus",
"CentralRiverLand",
"EdgeSeas",
"Gulf",
"Lakes",
"Passes",
"Lowlands",
"Mainland"
],
"naval": [
"CentralSea",
"CentralRiverNaval",
"Archipelago",
"RiversAndLake"
]
};
/** /**
* The player IDs and locations shall only be determined by the landscape functions if it's not a nomad game, * The player IDs and locations shall only be determined by the landscape functions if it's not a nomad game,
* because nomad maps randomize the locations after the terrain generation. * because nomad maps randomize the locations after the terrain generation.
@ -105,172 +85,6 @@ let playerPosition = [];
let g_StartingTreasures = false; let g_StartingTreasures = false;
let g_StartingWalls = true; let g_StartingWalls = true;
function createUnknownMap()
{
const landscape = g_MapSettings.Landscape || pickRandom([...unknownMapFunctions.land, ...unknownMapFunctions.naval]);
global["unknown" + landscape]();
paintUnknownMapBasedOnHeight();
createUnknownPlayerBases();
createUnknownObjects();
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 10));
}
/**
* Chain of islands or many disconnected islands.
*/
function unknownArchipelago()
{
g_StartingWalls = "towers";
g_StartingTreasures = true;
const [pIDs, islandPosition] = playerPlacementCircle(fractionToTiles(0.35));
if (!isNomad())
{
[playerIDs, playerPosition] = [pIDs, islandPosition];
markPlayerArea("large");
}
g_Map.log("Creating islands");
const islandSize = diskArea(scaleByMapSize(17, 29));
for (let i = 0; i < numPlayers; ++i)
createArea(
new ClumpPlacer(islandSize, 0.8, 0.1, Infinity, islandPosition[i]),
landElevationPainter);
const type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3);
if (type == 1)
{
g_Map.log("Creating archipelago");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity),
[
landElevationPainter,
new TileClassPainter(clLand)
],
null,
scaleByMapSize(2, 5) * randIntInclusive(8, 14));
g_Map.log("Creating shore jaggedness with small puddles");
createAreas(
new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, Infinity),
[
new SmoothElevationPainter(ELEVATION_SET, heightLand, 4),
new TileClassPainter(clLand)
],
borderClasses(clLand, 6, 3),
scaleByMapSize(12, 130) * 2,
150);
}
else if (type == 2)
{
g_Map.log("Creating islands");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.6, 1.4), 0.8, 0.1, randFloat(0.0, 0.2)),
[
landElevationPainter,
new TileClassPainter(clLand)
],
avoidClasses(clLand, 3, clPlayerTerritory, 3),
scaleByMapSize(6, 10) * randIntInclusive(8, 14));
g_Map.log("Creating small islands");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.3, 0.7), 0.8, 0.1, 0.07),
[
new SmoothElevationPainter(ELEVATION_SET, heightLand, 6),
new TileClassPainter(clLand)
],
avoidClasses(clLand, 3, clPlayerTerritory, 3),
scaleByMapSize(2, 6) * randIntInclusive(6, 15),
25);
}
else if (type == 3)
{
g_Map.log("Creating tight islands");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity),
[
landElevationPainter,
new TileClassPainter(clLand)
],
avoidClasses(clLand, randIntInclusive(8, 16), clPlayerTerritory, 3),
scaleByMapSize(2, 5) * randIntInclusive(8, 14));
}
}
/**
* Disk shaped mainland with water on the edge.
*/
function unknownContinent()
{
const waterHeight = -5;
if (!isNomad())
{
g_Map.log("Ensuring player area");
[playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25));
markPlayerArea("small");
for (let i = 0; i < numPlayers; ++i)
createArea(
new ChainPlacer(
2,
Math.floor(scaleByMapSize(5, 9)),
Math.floor(scaleByMapSize(5, 20)),
Infinity,
playerPosition[i],
0,
[Math.floor(scaleByMapSize(23, 50))]),
[
landElevationPainter,
new TileClassPainter(clLand)
]);
}
g_Map.log("Creating continent");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, mapCenter),
[
landElevationPainter,
new TileClassPainter(clLand)
]);
if (randBool(1/3))
{
g_Map.log("Creating peninsula (i.e. half the map not being surrounded by water)");
const angle = randomAngle();
const peninsulaPosition1 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.25), 0).rotate(-angle));
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, peninsulaPosition1),
[
landElevationPainter,
new TileClassPainter(clLand)
]);
g_Map.log("Remembering to not paint shorelines into the peninsula");
const peninsulaPosition2 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.35), 0).rotate(-angle));
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.33)), 0.9, 0.01, Infinity, peninsulaPosition2),
new TileClassPainter(clPeninsulaSteam));
}
createShoreJaggedness(waterHeight, clLand, 7);
}
function unknownCentralSea()
{
unknownCentralSeaOrIsthmus(false);
}
function unknownIsthmus()
{
unknownCentralSeaOrIsthmus(true);
}
/** /**
* Creates a huge central river, possibly connecting the riversides with a narrow piece of land. * Creates a huge central river, possibly connecting the riversides with a narrow piece of land.
*/ */
@ -333,16 +147,6 @@ function unknownCentralSeaOrIsthmus(isthmus)
// Don't createShoreJaggedness since it doesn't fit artistically here // Don't createShoreJaggedness since it doesn't fit artistically here
} }
function unknownCentralRiverLand()
{
unknownCentralRiver(true);
}
function unknownCentralRiverNaval()
{
unknownCentralRiver(false);
}
/** /**
* Creates a very small central river. * Creates a very small central river.
*/ */
@ -410,11 +214,153 @@ function unknownCentralRiver(shallows)
avoidClasses(clPlayerTerritory, 3)); avoidClasses(clPlayerTerritory, 3));
} }
/** const unknownMapFunctions = {
* Creates a circular lake in the middle and possibly a river between each player ("pizza slices"). // Chain of islands or many disconnected islands.
*/ "Archipelago": () => {
function unknownRiversAndLake() g_StartingWalls = "towers";
g_StartingTreasures = true;
const [pIDs, islandPosition] = playerPlacementCircle(fractionToTiles(0.35));
if (!isNomad())
{ {
[playerIDs, playerPosition] = [pIDs, islandPosition];
markPlayerArea("large");
}
g_Map.log("Creating islands");
const islandSize = diskArea(scaleByMapSize(17, 29));
for (let i = 0; i < numPlayers; ++i)
createArea(
new ClumpPlacer(islandSize, 0.8, 0.1, Infinity, islandPosition[i]),
landElevationPainter);
switch (randIntInclusive(1, isNomad() ? 2 : 3))
{
case 1:
g_Map.log("Creating archipelago");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity),
[
landElevationPainter,
new TileClassPainter(clLand)
],
null,
scaleByMapSize(2, 5) * randIntInclusive(8, 14));
g_Map.log("Creating shore jaggedness with small puddles");
createAreas(
new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, Infinity),
[
new SmoothElevationPainter(ELEVATION_SET, heightLand, 4),
new TileClassPainter(clLand)
],
borderClasses(clLand, 6, 3),
scaleByMapSize(12, 130) * 2,
150);
break;
case 2:
g_Map.log("Creating islands");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.6, 1.4), 0.8, 0.1, randFloat(0.0, 0.2)),
[
landElevationPainter,
new TileClassPainter(clLand)
],
avoidClasses(clLand, 3, clPlayerTerritory, 3),
scaleByMapSize(6, 10) * randIntInclusive(8, 14));
g_Map.log("Creating small islands");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.3, 0.7), 0.8, 0.1, 0.07),
[
new SmoothElevationPainter(ELEVATION_SET, heightLand, 6),
new TileClassPainter(clLand)
],
avoidClasses(clLand, 3, clPlayerTerritory, 3),
scaleByMapSize(2, 6) * randIntInclusive(6, 15),
25);
break;
default:
g_Map.log("Creating tight islands");
createAreas(
new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity),
[
landElevationPainter,
new TileClassPainter(clLand)
],
avoidClasses(clLand, randIntInclusive(8, 16), clPlayerTerritory, 3),
scaleByMapSize(2, 5) * randIntInclusive(8, 14));
}
},
// Disk shaped mainland with water on the edge.
"Continent": () => {
const waterHeight = -5;
if (!isNomad())
{
g_Map.log("Ensuring player area");
[playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25));
markPlayerArea("small");
for (let i = 0; i < numPlayers; ++i)
createArea(
new ChainPlacer(
2,
Math.floor(scaleByMapSize(5, 9)),
Math.floor(scaleByMapSize(5, 20)),
Infinity,
playerPosition[i],
0,
[Math.floor(scaleByMapSize(23, 50))]),
[
landElevationPainter,
new TileClassPainter(clLand)
]);
}
g_Map.log("Creating continent");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, mapCenter),
[
landElevationPainter,
new TileClassPainter(clLand)
]);
if (randBool(1/3))
{
g_Map.log("Creating peninsula (i.e. half the map not being surrounded by water)");
const angle = randomAngle();
const peninsulaPosition1 =
Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.25), 0).rotate(-angle));
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity,
peninsulaPosition1),
[
landElevationPainter,
new TileClassPainter(clLand)
]);
g_Map.log("Remembering to not paint shorelines into the peninsula");
const peninsulaPosition2 =
Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.35), 0).rotate(-angle));
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.33)), 0.9, 0.01, Infinity,
peninsulaPosition2),
new TileClassPainter(clPeninsulaSteam));
}
createShoreJaggedness(waterHeight, clLand, 7);
},
"CentralSea": unknownCentralSeaOrIsthmus.bind(null, false),
"Isthmus": unknownCentralSeaOrIsthmus.bind(null, true),
"CentralRiverLand": unknownCentralRiver.bind(null, true),
"CentralRiverNaval": unknownCentralRiver.bind(null, false),
// Creates a circular lake in the middle and possibly a river between each player ("pizza slices").
"RiversAndLake": () => {
const waterHeight = -4; const waterHeight = -4;
createArea( createArea(
new MapBoundsPlacer(), new MapBoundsPlacer(),
@ -424,7 +370,8 @@ function unknownRiversAndLake()
if (!isNomad()) if (!isNomad())
{ {
let playerAngle; let playerAngle;
[playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); [playerIDs, playerPosition, playerAngle, startAngle] =
playerPlacementCircle(fractionToTiles(0.35));
markPlayerArea("small"); markPlayerArea("small");
} }
@ -446,10 +393,12 @@ function unknownRiversAndLake()
{ {
g_Map.log("Creating small rivers separating players"); g_Map.log("Creating small rivers separating players");
for (const river of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]) for (const river of distributePointsOnCircle(numPlayers,
startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0])
{ {
createArea( createArea(
new PathPlacer(mapCenter, river, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), new PathPlacer(mapCenter, river, scaleByMapSize(14, 24), 0.4,
3 * scaleByMapSize(1, 3), 0.2, 0.05),
[ [
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4),
new TileClassPainter(clWater) new TileClassPainter(clWater)
@ -484,13 +433,10 @@ function unknownRiversAndLake()
new TileClassPainter(clWater) new TileClassPainter(clWater)
]); ]);
} }
} },
/** // Align players on a land strip with seas bordering on one or both sides that can hold islands.
* Align players on a land strip with seas bordering on one or both sides that can hold islands. "EdgeSeas": () => {
*/
function unknownEdgeSeas()
{
const waterHeight = -4; const waterHeight = -4;
createArea( createArea(
@ -501,7 +447,8 @@ function unknownEdgeSeas()
if (!isNomad()) if (!isNomad())
{ {
playerIDs = sortAllPlayers(); playerIDs = sortAllPlayers();
playerPosition = playerPlacementLine(startAngle + Math.PI / 2, mapCenter, fractionToTiles(0.2)); playerPosition =
playerPlacementLine(startAngle + Math.PI / 2, mapCenter, fractionToTiles(0.2));
// Don't place the shoreline inside the CC, but possibly into the players territory // Don't place the shoreline inside the CC, but possibly into the players territory
markPlayerArea("small"); markPlayerArea("small");
} }
@ -509,8 +456,10 @@ function unknownEdgeSeas()
for (const side of pickRandom([[0], [Math.PI], [0, Math.PI]])) for (const side of pickRandom([[0], [Math.PI], [0, Math.PI]]))
paintRiver({ paintRiver({
"parallel": true, "parallel": true,
"start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(side + startAngle, mapCenter), "start": new Vector2D(mapBounds.left, mapBounds.top)
"end": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(side + startAngle, mapCenter), .rotateAround(side + startAngle, mapCenter),
"end": new Vector2D(mapBounds.left, mapBounds.bottom)
.rotateAround(side + startAngle, mapCenter),
"width": scaleByMapSize(80, randFloat(270, 320)), "width": scaleByMapSize(80, randFloat(270, 320)),
"fadeDist": scaleByMapSize(2, 8), "fadeDist": scaleByMapSize(2, 8),
"deviation": 0, "deviation": 0,
@ -523,13 +472,10 @@ function unknownEdgeSeas()
createExtensionsOrIslands(); createExtensionsOrIslands();
paintTileClassBasedOnHeight(0, heightCliff, 1, clLand); paintTileClassBasedOnHeight(0, heightCliff, 1, clLand);
createShoreJaggedness(waterHeight, clLand, 7, false); createShoreJaggedness(waterHeight, clLand, 7, false);
} },
/** // Land shaped like a concrescent moon around a central lake.
* Land shaped like a concrescent moon around a central lake. "Gulf": () => {
*/
function unknownGulf()
{
const waterHeight = -3; const waterHeight = -3;
createArea( createArea(
@ -544,35 +490,34 @@ function unknownGulf()
playerPosition = playerPlacementCustomAngle( playerPosition = playerPlacementCustomAngle(
fractionToTiles(0.35), fractionToTiles(0.35),
mapCenter, mapCenter,
i => startAngle + 2/3 * Math.PI * (-1 + (numPlayers == 1 ? 1 : 2 * i / (numPlayers - 1))))[0]; i => startAngle + 2/3 * Math.PI *
(-1 + (numPlayers == 1 ? 1 : 2 * i / (numPlayers - 1))))[0];
markPlayerArea("large"); markPlayerArea("large");
} }
const gulfParts = [ for (const gulfPart of
{ "radius": fractionToTiles(0.16), "distance": fractionToTiles(0) }, [
{ "radius": fractionToTiles(0.2), "distance": fractionToTiles(0.2) }, [0.16, 0],
{ "radius": fractionToTiles(0.22), "distance": fractionToTiles(0.49) } [0.2, 0.2],
]; [0.22, 0.49]
])
for (const gulfPart of gulfParts)
{ {
const position = Vector2D.sub(mapCenter, new Vector2D(gulfPart.distance, 0).rotate(-startAngle)).round(); const [radius, distance] = gulfPart.map(fractionToTiles);
const position = Vector2D.sub(mapCenter,
new Vector2D(distance, 0).rotate(-startAngle)).round();
createArea( createArea(
new ClumpPlacer(diskArea(gulfPart.radius), 0.7, 0.05, Infinity, position), new ClumpPlacer(diskArea(radius), 0.7, 0.05, Infinity, position),
[ [
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4),
new TileClassPainter(clWater) new TileClassPainter(clWater)
], ],
avoidClasses(clPlayerTerritory, defaultPlayerBaseRadius())); avoidClasses(clPlayerTerritory, defaultPlayerBaseRadius()));
} }
} },
/** // Mainland style with some small random lakes.
* Mainland style with some small random lakes. "Lakes": () => {
*/
function unknownLakes()
{
const waterHeight = -5; const waterHeight = -5;
createArea( createArea(
@ -592,15 +537,15 @@ function unknownLakes()
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 5), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 5),
new TileClassPainter(clWater) new TileClassPainter(clWater)
], ],
[avoidClasses(clPlayerTerritory, 12), randBool() ? avoidClasses(clWater, 8) : new NullConstraint()], [
avoidClasses(clPlayerTerritory, 12),
randBool() ? avoidClasses(clWater, 8) : []
].flat(),
scaleByMapSize(5, 16)); scaleByMapSize(5, 16));
} },
/** // A large hill leaving players only a small passage to each of the the two neighboring players.
* A large hill leaving players only a small passage to each of the the two neighboring players. "Passes": () => {
*/
function unknownPasses()
{
const heightMountain = 24; const heightMountain = 24;
const waterHeight = -4; const waterHeight = -4;
@ -612,19 +557,23 @@ function unknownPasses()
let startAngle; let startAngle;
if (!isNomad()) if (!isNomad())
{ {
[playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); [playerIDs, playerPosition, playerAngle, startAngle] =
playerPlacementCircle(fractionToTiles(0.35));
markPlayerArea("small"); markPlayerArea("small");
} }
else else
startAngle = randomAngle(); startAngle = randomAngle();
g_Map.log("Creating a mountain range between neighboring players"); g_Map.log("Creating a mountain range between neighboring players");
for (const mountain of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]) for (const mountain of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers,
fractionToTiles(0.5), mapCenter)[0])
{ {
createArea( createArea(
new PathPlacer(mapCenter, mountain, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), new PathPlacer(mapCenter, mountain, scaleByMapSize(14, 24), 0.4,
3 * scaleByMapSize(1, 3), 0.2, 0.05),
[ [
// More smoothing than this often results in the mountainrange becoming passable to one player. // More smoothing than this often results in the mountainrange becoming
// passable to one player.
new SmoothElevationPainter(ELEVATION_SET, heightMountain, 1), new SmoothElevationPainter(ELEVATION_SET, heightMountain, 1),
new TileClassPainter(clWater) new TileClassPainter(clWater)
], ],
@ -638,14 +587,22 @@ function unknownPasses()
} }
g_Map.log("Creating passages between neighboring players"); g_Map.log("Creating passages between neighboring players");
const passes = numPlayers == 2 && distributePointsOnCircle(numPlayers * 3, startAngle, fractionToTiles(0.35), mapCenter)[0]; if (numPlayers > 1)
for (let i = 0; i < numPlayers && numPlayers > 1; ++i) {
const getEndpoints = (() => {
if (numPlayers !== 2)
return i => [i, (i + 1) % numPlayers].map(index => playerPosition[index]);
const passes = distributePointsOnCircle(numPlayers * 3, startAngle,
fractionToTiles(0.35), mapCenter)[0];
return i => [1, 2].map(p => passes[3 * i + p]);
})();
for (let i = 0; i < numPlayers; ++i)
{ {
// For numPlayers > 2 use the playerPosition to not end up inside the mountains. // For numPlayers > 2 use the playerPosition to not end up inside the mountains.
createArea( createArea(
new PathPlacer( new PathPlacer(
numPlayers == 2 ? passes[3 * i + 1] : playerPosition[i], ...getEndpoints(i),
numPlayers == 2 ? passes[3 * i + 2] : playerPosition[(i + 1) % numPlayers],
scaleByMapSize(14, 24), scaleByMapSize(14, 24),
0.4, 0.4,
3 * scaleByMapSize(1, 3), 3 * scaleByMapSize(1, 3),
@ -653,6 +610,7 @@ function unknownPasses()
0.05), 0.05),
new SmoothElevationPainter(ELEVATION_SET, heightLand, 2)); new SmoothElevationPainter(ELEVATION_SET, heightLand, 2));
} }
}
if (randBool(2/5)) if (randBool(2/5))
{ {
@ -674,13 +632,10 @@ function unknownPasses()
new TileClassPainter(clWater) new TileClassPainter(clWater)
]); ]);
} }
} },
/** // Land enclosed by a hill that leaves small areas for civic centers and large central place.
* Land enclosed by a hill that leaves small areas for civic centers and large central place. "Lowlands": () => {
*/
function unknownLowlands()
{
const heightMountain = 30; const heightMountain = 30;
g_Map.log("Creating mountain that is going to separate players"); g_Map.log("Creating mountain that is going to separate players");
@ -692,7 +647,8 @@ function unknownLowlands()
let startAngle; let startAngle;
if (!isNomad()) if (!isNomad())
{ {
[playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); [playerIDs, playerPosition, playerAngle, startAngle] =
playerPlacementCircle(fractionToTiles(0.35));
markPlayerArea("small"); markPlayerArea("small");
} }
else else
@ -705,10 +661,13 @@ function unknownLowlands()
mapSize >= 320 && numPlayers <= 4 || mapSize >= 320 && numPlayers <= 4 ||
mapSize >= 384 && numPlayers <= 5 || mapSize >= 384 && numPlayers <= 5 ||
mapSize >= 448 && numPlayers <= 6) mapSize >= 448 && numPlayers <= 6)
{
valleys *= 2; valleys *= 2;
}
g_Map.log("Creating player valley"); g_Map.log("Creating player valley");
for (const valley of distributePointsOnCircle(valleys, startAngle, fractionToTiles(0.35), mapCenter)[0]) for (const valley of distributePointsOnCircle(valleys, startAngle, fractionToTiles(0.35),
mapCenter)[0])
{ {
createArea( createArea(
new ClumpPlacer(diskArea(scaleByMapSize(18, 32)), 0.65, 0.1, Infinity, valley), new ClumpPlacer(diskArea(scaleByMapSize(18, 32)), 0.65, 0.1, Infinity, valley),
@ -719,7 +678,8 @@ function unknownLowlands()
// Passage from player to center // Passage from player to center
createArea( createArea(
new PathPlacer(mapCenter, valley, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), new PathPlacer(mapCenter, valley, scaleByMapSize(14, 24), 0.4,
3 * scaleByMapSize(1, 3), 0.2, 0.05),
[ [
landElevationPainter, landElevationPainter,
new TileClassPainter(clWater) new TileClassPainter(clWater)
@ -733,13 +693,10 @@ function unknownLowlands()
landElevationPainter, landElevationPainter,
new TileClassPainter(clWater) new TileClassPainter(clWater)
]); ]);
} },
/** // No water, no hills.
* No water, no hills. "Mainland": () => {
*/
function unknownMainland()
{
createArea( createArea(
new MapBoundsPlacer(), new MapBoundsPlacer(),
new ElevationPainter(3)); new ElevationPainter(3));
@ -750,6 +707,7 @@ function unknownMainland()
markPlayerArea("small"); markPlayerArea("small");
} }
} }
};
function centralRiverCoordinates(angle) function centralRiverCoordinates(angle)
{ {
@ -813,19 +771,20 @@ function createExtensionsOrIslands()
*/ */
function markPlayerArea(size) function markPlayerArea(size)
{ {
for (let i = 0; i < numPlayers; ++i) for (const position of playerPosition)
{ {
addCivicCenterAreaToClass(playerPosition[i], clPlayer); addCivicCenterAreaToClass(position, clPlayer);
if (size == "large") if (size == "large")
createArea( createArea(
new ClumpPlacer(diskArea(scaleByMapSize(17, 29) / 3), 0.6, 0.3, Infinity, playerPosition[i]), new ClumpPlacer(diskArea(scaleByMapSize(17, 29) / 3), 0.6, 0.3, Infinity, position),
new TileClassPainter(clPlayerTerritory)); new TileClassPainter(clPlayerTerritory));
} }
} }
function paintUnknownMapBasedOnHeight() (g_MapSettings.Landscape ? unknownMapFunctions[g_MapSettings.Landscape] :
{ pickRandom(Object.values(unknownMapFunctions)))();
paintTerrainBasedOnHeight(heightCliff, 40, 1, tCliff); paintTerrainBasedOnHeight(heightCliff, 40, 1, tCliff);
paintTerrainBasedOnHeight(3, heightCliff, 1, tMainTerrain); paintTerrainBasedOnHeight(3, heightCliff, 1, tMainTerrain);
paintTerrainBasedOnHeight(1, 3, 1, tShore); paintTerrainBasedOnHeight(1, 3, 1, tShore);
@ -837,13 +796,46 @@ function paintUnknownMapBasedOnHeight()
paintTileClassBasedOnHeight(-6, 0, 1, clWater); paintTileClassBasedOnHeight(-6, 0, 1, clWater);
paintTileClassBasedOnHeight(0, heightCliff, 1, clLand); paintTileClassBasedOnHeight(0, heightCliff, 1, clLand);
paintTileClassBasedOnHeight(heightCliff, 40, 1, clHill); paintTileClassBasedOnHeight(heightCliff, 40, 1, clHill);
}
/** placePlayerBases({
* Place resources and decoratives after the player territory was marked. "PlayerPlacement": [playerIDs, playerPosition],
*/ "BaseResourceClass": clBaseResource,
function createUnknownObjects() "Walls": g_StartingWalls,
"CityPatch": {
"outerTerrain": tRoadWild,
"innerTerrain": tRoad,
"painters": [
new TileClassPainter(clPlayer)
]
},
"StartingAnimal": {
},
"Berries": {
"template": oFruitBush
},
"Mines": {
"types": [
{ "template": oMetalLarge },
{ "template": oStoneLarge }
]
},
"Treasures": {
"types": [
{ {
"template": oWoodTreasure,
"count": g_StartingTreasures ? 14 : 0
}
]
},
"Trees": {
"template": oTree1
},
"Decoratives": {
"template": aGrassShort
}
});
// Place resources and decoratives after the player territory was marked.
g_Map.log("Creating bumps"); g_Map.log("Creating bumps");
createAreas( createAreas(
new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity),
@ -880,7 +872,10 @@ function createUnknownObjects()
new LayeredPainter(type, [2]), new LayeredPainter(type, [2]),
new TileClassPainter(clForest) new TileClassPainter(clForest)
], ],
[avoidClasses(clPlayer, 20, clForest, randIntInclusive(5, 15), clHill, 2), stayClasses(clLand, 4)], [
avoidClasses(clPlayer, 20, clForest, randIntInclusive(5, 15), clHill, 2),
stayClasses(clLand, 4)
],
num); num);
Engine.SetProgress(50); Engine.SetProgress(50);
@ -890,16 +885,22 @@ function createUnknownObjects()
createAreas( createAreas(
new ClumpPlacer(patchSize, 0.3, 0.06, 0.5), new ClumpPlacer(patchSize, 0.3, 0.06, 0.5),
[ [
new LayeredPainter([[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new LayeredPainter(
[
[tMainTerrain, tTier1Terrain],
[tTier1Terrain, tTier2Terrain],
[tTier2Terrain, tTier3Terrain]
],
[1, 1]),
new TileClassPainter(clDirt) new TileClassPainter(clDirt)
], ],
[avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)], [avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)],
patchCount); patchCount);
g_Map.log("Creating grass patches"); g_Map.log("Creating grass patches");
for (const size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) for (const patchSize of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)])
createAreas( createAreas(
new ClumpPlacer(size, 0.3, 0.06, 0.5), new ClumpPlacer(patchSize, 0.3, 0.06, 0.5),
new TerrainPainter(tTier4Terrain), new TerrainPainter(tTier4Terrain),
[avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)], [avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)],
patchCount); patchCount);
@ -908,7 +909,13 @@ function createUnknownObjects()
g_Map.log("Creating stone mines"); g_Map.log("Creating stone mines");
createObjectGroupsDeprecated( createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock), new SimpleGroup(
[
new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1),
new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)
],
true,
clRock),
0, 0,
[avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 2), stayClasses(clLand, 3)], [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 2), stayClasses(clLand, 3)],
randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)),
@ -941,7 +948,9 @@ function createUnknownObjects()
g_Map.log("Creating large decorative rocks"); g_Map.log("Creating large decorative rocks");
createObjectGroupsDeprecated( createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], true), new SimpleGroup(
[new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
true),
0, 0,
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 2), stayClasses(clLand, 3)], [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 2), stayClasses(clLand, 3)],
scaleByMapSize(8, 131), scaleByMapSize(8, 131),
@ -990,7 +999,17 @@ function createUnknownObjects()
createObjectGroupsDeprecated( createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(type, 1, 1, 0, 3)], true, clForest), new SimpleGroup([new SimpleObject(type, 1, 1, 0, 3)], true, clForest),
0, 0,
[avoidClasses(clWater, 1, clForest, 1, clHill, 2, clPlayer, 0, clMetal, 6, clRock, 6, clBaseResource, 6), stayClasses(clLand, 4)], [
avoidClasses(
clWater, 1,
clForest, 1,
clHill, 2,
clPlayer, 0,
clMetal, 6,
clRock, 6,
clBaseResource, 6),
stayClasses(clLand, 4)
],
num); num);
const planetm = currentBiome() == "generic/india" ? 8 : 1; const planetm = currentBiome() == "generic/india" ? 8 : 1;
@ -1005,7 +1024,11 @@ function createUnknownObjects()
g_Map.log("Creating large grass tufts"); g_Map.log("Creating large grass tufts");
createObjectGroupsDeprecated( createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(aGrass, 2, 4, 0, 1.8, -Math.PI / 8, Math.PI / 8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5, -Math.PI / 8, Math.PI / 8)]), new SimpleGroup(
[
new SimpleObject(aGrass, 2, 4, 0, 1.8, -Math.PI / 8, Math.PI / 8),
new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5, -Math.PI / 8, Math.PI / 8)
]),
0, 0,
[avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 3)], [avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 3)],
planetm * scaleByMapSize(13, 200)); planetm * scaleByMapSize(13, 200));
@ -1021,7 +1044,8 @@ function createUnknownObjects()
g_Map.log("Creating bushes"); g_Map.log("Creating bushes");
createObjectGroupsDeprecated( createObjectGroupsDeprecated(
new SimpleGroup([new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]), new SimpleGroup(
[new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]),
0, 0,
[avoidClasses(clWater, 1, clHill, 2, clPlayer, 1, clDirt, 1), stayClasses(clLand, 3)], [avoidClasses(clWater, 1, clHill, 2, clPlayer, 1, clDirt, 1), stayClasses(clLand, 3)],
planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200),
@ -1030,49 +1054,8 @@ function createUnknownObjects()
setSkySet(pickRandom(["cirrus", "cumulus", "sunny", "sunny 1", "mountainous", "stratus"])); setSkySet(pickRandom(["cirrus", "cumulus", "sunny", "sunny 1", "mountainous", "stratus"]));
setSunRotation(randomAngle()); setSunRotation(randomAngle());
setSunElevation(Math.PI * randFloat(1/5, 1/3)); setSunElevation(Math.PI * randFloat(1/5, 1/3));
}
function createUnknownPlayerBases() placePlayersNomad(clPlayer,
{ avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 10));
placePlayerBases({
"PlayerPlacement": [playerIDs, playerPosition],
"BaseResourceClass": clBaseResource,
"Walls": g_StartingWalls,
"CityPatch": {
"outerTerrain": tRoadWild,
"innerTerrain": tRoad,
"painters": [
new TileClassPainter(clPlayer)
]
},
"StartingAnimal": {
},
"Berries": {
"template": oFruitBush
},
"Mines": {
"types": [
{ "template": oMetalLarge },
{ "template": oStoneLarge }
]
},
"Treasures": {
"types": [
{
"template": oWoodTreasure,
"count": g_StartingTreasures ? 14 : 0
}
]
},
"Trees": {
"template": oTree1
},
"Decoratives": {
"template": aGrassShort
}
});
}
createUnknownMap();
g_Map.ExportMap(); g_Map.ExportMap();