Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/maps/random/unknown.js
Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
const clFood = g_Map.createTileClass(); | const clFood = g_Map.createTileClass(); | ||||
const clPeninsulaSteam = g_Map.createTileClass(); | const clPeninsulaSteam = g_Map.createTileClass(); | ||||
const clBaseResource = g_Map.createTileClass(); | const clBaseResource = g_Map.createTileClass(); | ||||
const clLand = g_Map.createTileClass(); | const clLand = g_Map.createTileClass(); | ||||
const clShallow = g_Map.createTileClass(); | 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. | ||||
* The locations should only determined by the landscape functions to avoid placing bodies of water and resources into civic centers and the starting resources. | * The locations should only determined by the landscape functions to avoid placing bodies of water and resources into civic centers and the starting resources. | ||||
*/ | */ | ||||
let playerIDs = sortAllPlayers(); | let playerIDs = sortAllPlayers(); | ||||
let playerPosition = []; | let playerPosition = []; | ||||
let g_StartingTreasures = false; | let g_StartingTreasures = false; | ||||
let g_StartingWalls = true; | let g_StartingWalls = true; | ||||
function createUnknownMap() | /** | ||||
* Creates a huge central river, possibly connecting the riversides with a narrow piece of land. | |||||
*/ | |||||
function unknownCentralSeaOrIsthmus(isthmus) | |||||
{ | { | ||||
const landscape = g_MapSettings.Landscape || pickRandom([...unknownMapFunctions.land, ...unknownMapFunctions.naval]); | const waterHeight = -3; | ||||
global["unknown" + landscape](); | |||||
paintUnknownMapBasedOnHeight(); | const startAngle = randomAngle(); | ||||
createUnknownPlayerBases(); | const [riverStart, riverEnd] = centralRiverCoordinates(startAngle); | ||||
createUnknownObjects(); | paintRiver({ | ||||
"parallel": false, | |||||
"start": riverStart, | |||||
"end": riverEnd, | |||||
"width": fractionToTiles(scaleByMapSize(0.27, 0.42) + randFloat(0, 0.08)), | |||||
"fadeDist": scaleByMapSize(3, 12), | |||||
"deviation": 0, | |||||
"heightRiverbed": waterHeight, | |||||
"heightLand": heightLand, | |||||
"meanderShort": 20, | |||||
"meanderLong": 0, | |||||
"waterFunc": (position, height, riverFraction) => { | |||||
if (height < 0) | |||||
clWater.add(position); | |||||
}, | |||||
"landFunc": (position, shoreDist1, shoreDist2) => { | |||||
g_Map.setHeight(position, 3.1); | |||||
clLand.add(position); | |||||
} | |||||
}); | |||||
placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 10)); | if (!isNomad()) | ||||
{ | |||||
[playerIDs, playerPosition] = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.6)); | |||||
markPlayerArea("small"); | |||||
} | |||||
if (isthmus) | |||||
{ | |||||
g_Map.log("Creating isthmus (i.e. connecting the two riversides with a big land passage)"); | |||||
const [isthmusStart, isthmusEnd] = centralRiverCoordinates(startAngle + Math.PI / 2); | |||||
createArea( | |||||
new PathPlacer( | |||||
isthmusStart, | |||||
isthmusEnd, | |||||
scaleByMapSize(randIntInclusive(16, 24), randIntInclusive(100, 140)), | |||||
0.5, | |||||
3 * scaleByMapSize(1, 4), | |||||
0.1, | |||||
0.01), | |||||
[ | |||||
landElevationPainter, | |||||
new TileClassPainter(clLand), | |||||
new TileClassUnPainter(clWater) | |||||
]); | |||||
} | |||||
createExtensionsOrIslands(); | |||||
// Don't createShoreJaggedness since it doesn't fit artistically here | |||||
} | } | ||||
/** | /** | ||||
* Chain of islands or many disconnected islands. | * Creates a very small central river. | ||||
*/ | */ | ||||
function unknownArchipelago() | function unknownCentralRiver(shallows) | ||||
{ | |||||
const waterHeight = -4; | |||||
const heightShallow = -2; | |||||
createArea( | |||||
new MapBoundsPlacer(), | |||||
new ElevationPainter(heightLand)); | |||||
const startAngle = randomAngle(); | |||||
if (!isNomad()) | |||||
{ | |||||
[playerIDs, playerPosition] = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.5)); | |||||
markPlayerArea("large"); | |||||
} | |||||
g_Map.log("Creating the main river"); | |||||
const [coord1, coord2] = centralRiverCoordinates(startAngle); | |||||
createArea( | |||||
new PathPlacer(coord1, coord2, scaleByMapSize(14, 24), 0.5, scaleByMapSize(3, 12), 0.1, 0.01), | |||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), | |||||
avoidClasses(clPlayerTerritory, 4)); | |||||
g_Map.log("Creating small water spots at the map border to ensure separation of players"); | |||||
for (const coord of [coord1, coord2]) | |||||
createArea( | |||||
new ClumpPlacer(diskArea(scaleByMapSize(5, 10)), 0.95, 0.6, Infinity, coord), | |||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 2), | |||||
avoidClasses(clPlayerTerritory, 8)); | |||||
if (shallows) | |||||
{ | |||||
g_Map.log("Creating the shallows of the main river"); | |||||
for (let i = 0; i <= randIntInclusive(1, scaleByMapSize(4, 8)); ++i) | |||||
{ | { | ||||
const location = fractionToTiles(randFloat(0.15, 0.85)); | |||||
createPassage({ | |||||
"start": new Vector2D(location, mapBounds.top).rotateAround(startAngle, mapCenter), | |||||
"end": new Vector2D(location, mapBounds.bottom).rotateAround(startAngle, mapCenter), | |||||
"startWidth": scaleByMapSize(8, 12), | |||||
"endWidth": scaleByMapSize(8, 12), | |||||
"smoothWidth": 2, | |||||
"startHeight": heightShallow, | |||||
"endHeight": heightShallow, | |||||
"constraints": new HeightConstraint(-Infinity, heightShallow), | |||||
"tileClass": clShallow | |||||
}); | |||||
} | |||||
} | |||||
if (randBool(2/3)) | |||||
createTributaryRivers( | |||||
startAngle, | |||||
randIntInclusive(8, scaleByMapSize(12, 16)), | |||||
scaleByMapSize(10, 20), | |||||
-4, | |||||
[-6, -1.5], | |||||
Math.PI / 5, | |||||
clWater, | |||||
clShallow, | |||||
avoidClasses(clPlayerTerritory, 3)); | |||||
} | |||||
const unknownMapFunctions = { | |||||
// Chain of islands or many disconnected islands. | |||||
"Archipelago": () => { | |||||
g_StartingWalls = "towers"; | g_StartingWalls = "towers"; | ||||
g_StartingTreasures = true; | g_StartingTreasures = true; | ||||
const [pIDs, islandPosition] = playerPlacementCircle(fractionToTiles(0.35)); | const [pIDs, islandPosition] = playerPlacementCircle(fractionToTiles(0.35)); | ||||
if (!isNomad()) | if (!isNomad()) | ||||
{ | { | ||||
[playerIDs, playerPosition] = [pIDs, islandPosition]; | [playerIDs, playerPosition] = [pIDs, islandPosition]; | ||||
markPlayerArea("large"); | markPlayerArea("large"); | ||||
} | } | ||||
g_Map.log("Creating islands"); | g_Map.log("Creating islands"); | ||||
const islandSize = diskArea(scaleByMapSize(17, 29)); | const islandSize = diskArea(scaleByMapSize(17, 29)); | ||||
for (let i = 0; i < numPlayers; ++i) | for (let i = 0; i < numPlayers; ++i) | ||||
createArea( | createArea( | ||||
new ClumpPlacer(islandSize, 0.8, 0.1, Infinity, islandPosition[i]), | new ClumpPlacer(islandSize, 0.8, 0.1, Infinity, islandPosition[i]), | ||||
landElevationPainter); | landElevationPainter); | ||||
const type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3); | const type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3); | ||||
if (type == 1) | if (type == 1) | ||||
{ | { | ||||
g_Map.log("Creating archipelago"); | g_Map.log("Creating archipelago"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity), | new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity), | ||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
], | ], | ||||
null, | null, | ||||
scaleByMapSize(2, 5) * randIntInclusive(8, 14)); | scaleByMapSize(2, 5) * randIntInclusive(8, 14)); | ||||
g_Map.log("Creating shore jaggedness with small puddles"); | g_Map.log("Creating shore jaggedness with small puddles"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, Infinity), | new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, Infinity), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), | new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
], | ], | ||||
borderClasses(clLand, 6, 3), | borderClasses(clLand, 6, 3), | ||||
scaleByMapSize(12, 130) * 2, | scaleByMapSize(12, 130) * 2, | ||||
150); | 150); | ||||
} | } | ||||
else if (type == 2) | else if (type == 2) | ||||
{ | { | ||||
g_Map.log("Creating islands"); | g_Map.log("Creating islands"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(islandSize * randFloat(0.6, 1.4), 0.8, 0.1, randFloat(0.0, 0.2)), | new ClumpPlacer(islandSize * randFloat(0.6, 1.4), 0.8, 0.1, randFloat(0.0, 0.2)), | ||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
], | ], | ||||
avoidClasses(clLand, 3, clPlayerTerritory, 3), | avoidClasses(clLand, 3, clPlayerTerritory, 3), | ||||
scaleByMapSize(6, 10) * randIntInclusive(8, 14)); | scaleByMapSize(6, 10) * randIntInclusive(8, 14)); | ||||
g_Map.log("Creating small islands"); | g_Map.log("Creating small islands"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(islandSize * randFloat(0.3, 0.7), 0.8, 0.1, 0.07), | new ClumpPlacer(islandSize * randFloat(0.3, 0.7), 0.8, 0.1, 0.07), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), | new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
], | ], | ||||
avoidClasses(clLand, 3, clPlayerTerritory, 3), | avoidClasses(clLand, 3, clPlayerTerritory, 3), | ||||
scaleByMapSize(2, 6) * randIntInclusive(6, 15), | scaleByMapSize(2, 6) * randIntInclusive(6, 15), | ||||
25); | 25); | ||||
} | } | ||||
else if (type == 3) | else if (type == 3) | ||||
{ | { | ||||
g_Map.log("Creating tight islands"); | g_Map.log("Creating tight islands"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity), | new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity), | ||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
], | ], | ||||
avoidClasses(clLand, randIntInclusive(8, 16), clPlayerTerritory, 3), | avoidClasses(clLand, randIntInclusive(8, 16), clPlayerTerritory, 3), | ||||
scaleByMapSize(2, 5) * randIntInclusive(8, 14)); | scaleByMapSize(2, 5) * randIntInclusive(8, 14)); | ||||
} | } | ||||
} | }, | ||||
/** | // Disk shaped mainland with water on the edge. | ||||
* Disk shaped mainland with water on the edge. | "Continent": () => { | ||||
*/ | |||||
function unknownContinent() | |||||
{ | |||||
const waterHeight = -5; | const waterHeight = -5; | ||||
if (!isNomad()) | if (!isNomad()) | ||||
{ | { | ||||
g_Map.log("Ensuring player area"); | g_Map.log("Ensuring player area"); | ||||
[playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25)); | [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25)); | ||||
markPlayerArea("small"); | markPlayerArea("small"); | ||||
for (let i = 0; i < numPlayers; ++i) | for (let i = 0; i < numPlayers; ++i) | ||||
createArea( | createArea( | ||||
new ChainPlacer( | new ChainPlacer( | ||||
2, | 2, | ||||
Math.floor(scaleByMapSize(5, 9)), | Math.floor(scaleByMapSize(5, 9)), | ||||
Math.floor(scaleByMapSize(5, 20)), | Math.floor(scaleByMapSize(5, 20)), | ||||
Infinity, | Infinity, | ||||
playerPosition[i], | playerPosition[i], | ||||
0, | 0, | ||||
[Math.floor(scaleByMapSize(23, 50))]), | [Math.floor(scaleByMapSize(23, 50))]), | ||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
]); | ]); | ||||
} | } | ||||
g_Map.log("Creating continent"); | g_Map.log("Creating continent"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, mapCenter), | ||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
]); | ]); | ||||
if (randBool(1/3)) | if (randBool(1/3)) | ||||
{ | { | ||||
g_Map.log("Creating peninsula (i.e. half the map not being surrounded by water)"); | g_Map.log("Creating peninsula (i.e. half the map not being surrounded by water)"); | ||||
const angle = randomAngle(); | const angle = randomAngle(); | ||||
const peninsulaPosition1 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.25), 0).rotate(-angle)); | const peninsulaPosition1 = | ||||
Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.25), 0).rotate(-angle)); | |||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, peninsulaPosition1), | new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, | ||||
peninsulaPosition1), | |||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
]); | ]); | ||||
g_Map.log("Remembering to not paint shorelines into the peninsula"); | g_Map.log("Remembering to not paint shorelines into the peninsula"); | ||||
const peninsulaPosition2 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.35), 0).rotate(-angle)); | const peninsulaPosition2 = | ||||
Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.35), 0).rotate(-angle)); | |||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.33)), 0.9, 0.01, Infinity, peninsulaPosition2), | new ClumpPlacer(diskArea(fractionToTiles(0.33)), 0.9, 0.01, Infinity, | ||||
peninsulaPosition2), | |||||
new TileClassPainter(clPeninsulaSteam)); | new TileClassPainter(clPeninsulaSteam)); | ||||
} | } | ||||
createShoreJaggedness(waterHeight, clLand, 7); | 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. | |||||
*/ | |||||
function unknownCentralSeaOrIsthmus(isthmus) | |||||
{ | |||||
const waterHeight = -3; | |||||
const startAngle = randomAngle(); | |||||
const [riverStart, riverEnd] = centralRiverCoordinates(startAngle); | |||||
paintRiver({ | |||||
"parallel": false, | |||||
"start": riverStart, | |||||
"end": riverEnd, | |||||
"width": fractionToTiles(scaleByMapSize(0.27, 0.42) + randFloat(0, 0.08)), | |||||
"fadeDist": scaleByMapSize(3, 12), | |||||
"deviation": 0, | |||||
"heightRiverbed": waterHeight, | |||||
"heightLand": heightLand, | |||||
"meanderShort": 20, | |||||
"meanderLong": 0, | |||||
"waterFunc": (position, height, riverFraction) => { | |||||
if (height < 0) | |||||
clWater.add(position); | |||||
}, | }, | ||||
"landFunc": (position, shoreDist1, shoreDist2) => { | |||||
g_Map.setHeight(position, 3.1); | |||||
clLand.add(position); | |||||
} | |||||
}); | |||||
if (!isNomad()) | |||||
{ | |||||
[playerIDs, playerPosition] = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.6)); | |||||
markPlayerArea("small"); | |||||
} | |||||
if (isthmus) | |||||
{ | |||||
g_Map.log("Creating isthmus (i.e. connecting the two riversides with a big land passage)"); | |||||
const [isthmusStart, isthmusEnd] = centralRiverCoordinates(startAngle + Math.PI / 2); | |||||
createArea( | |||||
new PathPlacer( | |||||
isthmusStart, | |||||
isthmusEnd, | |||||
scaleByMapSize(randIntInclusive(16, 24), randIntInclusive(100, 140)), | |||||
0.5, | |||||
3 * scaleByMapSize(1, 4), | |||||
0.1, | |||||
0.01), | |||||
[ | |||||
landElevationPainter, | |||||
new TileClassPainter(clLand), | |||||
new TileClassUnPainter(clWater) | |||||
]); | |||||
} | |||||
createExtensionsOrIslands(); | |||||
// Don't createShoreJaggedness since it doesn't fit artistically here | |||||
} | |||||
function unknownCentralRiverLand() | |||||
{ | |||||
unknownCentralRiver(true); | |||||
} | |||||
function unknownCentralRiverNaval() | |||||
{ | |||||
unknownCentralRiver(false); | |||||
} | |||||
/** | |||||
* Creates a very small central river. | |||||
*/ | |||||
function unknownCentralRiver(shallows) | |||||
{ | |||||
const waterHeight = -4; | |||||
const heightShallow = -2; | |||||
createArea( | |||||
new MapBoundsPlacer(), | |||||
new ElevationPainter(heightLand)); | |||||
const startAngle = randomAngle(); | "CentralSea": unknownCentralSeaOrIsthmus.bind(null, false), | ||||
"Isthmus": unknownCentralSeaOrIsthmus(null, true), | |||||
if (!isNomad()) | "CentralRiverLand": unknownCentralRiver.bind(null, true), | ||||
{ | "CentralRiverNaval": unknownCentralRiver.bind(null, false), | ||||
[playerIDs, playerPosition] = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.5)); | |||||
markPlayerArea("large"); | |||||
} | |||||
g_Map.log("Creating the main river"); | // Creates a circular lake in the middle and possibly a river between each player ("pizza slices"). | ||||
const [coord1, coord2] = centralRiverCoordinates(startAngle); | "RiversAndLake": () => { | ||||
createArea( | |||||
new PathPlacer(coord1, coord2, scaleByMapSize(14, 24), 0.5, scaleByMapSize(3, 12), 0.1, 0.01), | |||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), | |||||
avoidClasses(clPlayerTerritory, 4)); | |||||
g_Map.log("Creating small water spots at the map border to ensure separation of players"); | |||||
for (const coord of [coord1, coord2]) | |||||
createArea( | |||||
new ClumpPlacer(diskArea(scaleByMapSize(5, 10)), 0.95, 0.6, Infinity, coord), | |||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 2), | |||||
avoidClasses(clPlayerTerritory, 8)); | |||||
if (shallows) | |||||
{ | |||||
g_Map.log("Creating the shallows of the main river"); | |||||
for (let i = 0; i <= randIntInclusive(1, scaleByMapSize(4, 8)); ++i) | |||||
{ | |||||
const location = fractionToTiles(randFloat(0.15, 0.85)); | |||||
createPassage({ | |||||
"start": new Vector2D(location, mapBounds.top).rotateAround(startAngle, mapCenter), | |||||
"end": new Vector2D(location, mapBounds.bottom).rotateAround(startAngle, mapCenter), | |||||
"startWidth": scaleByMapSize(8, 12), | |||||
"endWidth": scaleByMapSize(8, 12), | |||||
"smoothWidth": 2, | |||||
"startHeight": heightShallow, | |||||
"endHeight": heightShallow, | |||||
"constraints": new HeightConstraint(-Infinity, heightShallow), | |||||
"tileClass": clShallow | |||||
}); | |||||
} | |||||
} | |||||
if (randBool(2/3)) | |||||
createTributaryRivers( | |||||
startAngle, | |||||
randIntInclusive(8, scaleByMapSize(12, 16)), | |||||
scaleByMapSize(10, 20), | |||||
-4, | |||||
[-6, -1.5], | |||||
Math.PI / 5, | |||||
clWater, | |||||
clShallow, | |||||
avoidClasses(clPlayerTerritory, 3)); | |||||
} | |||||
/** | |||||
* Creates a circular lake in the middle and possibly a river between each player ("pizza slices"). | |||||
*/ | |||||
function unknownRiversAndLake() | |||||
{ | |||||
const waterHeight = -4; | const waterHeight = -4; | ||||
createArea( | createArea( | ||||
new MapBoundsPlacer(), | new MapBoundsPlacer(), | ||||
new ElevationPainter(heightLand)); | new ElevationPainter(heightLand)); | ||||
let startAngle; | let startAngle; | ||||
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"); | ||||
} | } | ||||
const lake = randBool(3/4); | const lake = randBool(3/4); | ||||
if (lake) | if (lake) | ||||
{ | { | ||||
g_Map.log("Creating lake"); | g_Map.log("Creating lake"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.17)), 0.7, 0.1, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.17)), 0.7, 0.1, Infinity, mapCenter), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), | new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), | ||||
new TileClassPainter(clWater) | new TileClassPainter(clWater) | ||||
]); | ]); | ||||
createShoreJaggedness(waterHeight, clWater, 3); | createShoreJaggedness(waterHeight, clWater, 3); | ||||
} | } | ||||
// TODO: On nomad because the resource imbalances per island are too drastic | // TODO: On nomad because the resource imbalances per island are too drastic | ||||
{ | { | ||||
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) | ||||
], | ], | ||||
avoidClasses(clPlayer, 5)); | avoidClasses(clPlayer, 5)); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(scaleByMapSize(4, 22)), 0.95, 0.6, Infinity, river), | new ClumpPlacer(diskArea(scaleByMapSize(4, 22)), 0.95, 0.6, Infinity, river), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 0), | new SmoothElevationPainter(ELEVATION_SET, waterHeight, 0), | ||||
new TileClassPainter(clWater) | new TileClassPainter(clWater) | ||||
], | ], | ||||
avoidClasses(clPlayer, 5)); | avoidClasses(clPlayer, 5)); | ||||
} | } | ||||
g_Map.log("Creating small lake"); | g_Map.log("Creating small lake"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.04)), 0.7, 0.1, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.04)), 0.7, 0.1, Infinity, mapCenter), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), | new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), | ||||
new TileClassPainter(clWater) | new TileClassPainter(clWater) | ||||
]); | ]); | ||||
} | } | ||||
if (!isNomad && lake && randBool(2/3)) | if (!isNomad && lake && randBool(2/3)) | ||||
{ | { | ||||
g_Map.log("Creating small central island"); | g_Map.log("Creating small central island"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, Infinity, mapCenter), | ||||
[ | [ | ||||
landElevationPainter, | landElevationPainter, | ||||
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( | ||||
new MapBoundsPlacer(), | new MapBoundsPlacer(), | ||||
new ElevationPainter(heightLand)); | new ElevationPainter(heightLand)); | ||||
const startAngle = randomAngle(); | const startAngle = randomAngle(); | ||||
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"); | ||||
} | } | ||||
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, | ||||
"heightRiverbed": waterHeight, | "heightRiverbed": waterHeight, | ||||
"heightLand": heightLand, | "heightLand": heightLand, | ||||
"meanderShort": 20, | "meanderShort": 20, | ||||
"meanderLong": 0 | "meanderLong": 0 | ||||
}); | }); | ||||
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( | ||||
new MapBoundsPlacer(), | new MapBoundsPlacer(), | ||||
new ElevationPainter(heightLand)); | new ElevationPainter(heightLand)); | ||||
const startAngle = randomAngle(); | const startAngle = randomAngle(); | ||||
if (!isNomad()) | if (!isNomad()) | ||||
{ | { | ||||
g_Map.log("Determining player locations"); | g_Map.log("Determining player locations"); | ||||
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 [radius, distance] = gulfPart.map(fractionToTiles); | ||||
const position = Vector2D.sub(mapCenter, new Vector2D(gulfPart.distance, 0).rotate(-startAngle)).round(); | 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( | ||||
new MapBoundsPlacer(), | new MapBoundsPlacer(), | ||||
new ElevationPainter(heightLand)); | new ElevationPainter(heightLand)); | ||||
if (!isNomad()) | if (!isNomad()) | ||||
{ | { | ||||
[playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); | [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); | ||||
markPlayerArea("large"); | markPlayerArea("large"); | ||||
} | } | ||||
g_Map.log("Creating lakes"); | g_Map.log("Creating lakes"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(scaleByMapSize(160, 700), 0.2, 0.1, Infinity), | new ClumpPlacer(scaleByMapSize(160, 700), 0.2, 0.1, Infinity), | ||||
[ | [ | ||||
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; | ||||
createArea( | createArea( | ||||
new MapBoundsPlacer(), | new MapBoundsPlacer(), | ||||
new ElevationPainter(heightLand)); | new ElevationPainter(heightLand)); | ||||
let playerAngle; | let playerAngle; | ||||
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) | ||||
], | ], | ||||
avoidClasses(clPlayer, 5)); | avoidClasses(clPlayer, 5)); | ||||
// Small mountain at the map border between the players to ensure separation of players | // Small mountain at the map border between the players to ensure separation of players | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(scaleByMapSize(4, 22)), 0.95, 0.6, Infinity, mountain), | new ClumpPlacer(diskArea(scaleByMapSize(4, 22)), 0.95, 0.6, Infinity, mountain), | ||||
new SmoothElevationPainter(ELEVATION_SET, heightMountain, 0), | new SmoothElevationPainter(ELEVATION_SET, heightMountain, 0), | ||||
avoidClasses(clPlayer, 5)); | avoidClasses(clPlayer, 5)); | ||||
} | } | ||||
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]; | const passes = numPlayers == 2 && | ||||
distributePointsOnCircle(numPlayers * 3, startAngle, fractionToTiles(0.35), mapCenter)[0]; | |||||
for (let i = 0; i < numPlayers && numPlayers > 1; ++i) | for (let i = 0; i < numPlayers && numPlayers > 1; ++i) | ||||
Lint: no-unmodified-loop-condition: 'numPlayers' is not modified in this loop. | |||||
{ | { | ||||
// 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], | numPlayers == 2 ? passes[3 * i + 1] : playerPosition[i], | ||||
numPlayers == 2 ? passes[3 * i + 2] : playerPosition[(i + 1) % numPlayers], | 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), | ||||
0.2, | 0.2, | ||||
0.05), | 0.05), | ||||
new SmoothElevationPainter(ELEVATION_SET, heightLand, 2)); | new SmoothElevationPainter(ELEVATION_SET, heightLand, 2)); | ||||
} | } | ||||
if (randBool(2/5)) | if (randBool(2/5)) | ||||
{ | { | ||||
g_Map.log("Create central lake"); | g_Map.log("Create central lake"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.1)), 0.7, 0.1, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.1)), 0.7, 0.1, Infinity, mapCenter), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 3), | new SmoothElevationPainter(ELEVATION_SET, waterHeight, 3), | ||||
new TileClassPainter(clWater) | new TileClassPainter(clWater) | ||||
]); | ]); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
g_Map.log("Fill area between the paths"); | g_Map.log("Fill area between the paths"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, Infinity, mapCenter), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, heightMountain, 4), | new SmoothElevationPainter(ELEVATION_SET, heightMountain, 4), | ||||
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"); | ||||
createArea( | createArea( | ||||
new MapBoundsPlacer(), | new MapBoundsPlacer(), | ||||
new ElevationPainter(heightMountain)); | new ElevationPainter(heightMountain)); | ||||
let playerAngle; | let playerAngle; | ||||
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 valleys enclosed by the mountain"); | g_Map.log("Creating valleys enclosed by the mountain"); | ||||
let valleys = numPlayers; | let valleys = numPlayers; | ||||
if (mapSize >= 128 && numPlayers <= 2 || | if (mapSize >= 128 && numPlayers <= 2 || | ||||
mapSize >= 192 && numPlayers <= 3 || | mapSize >= 192 && numPlayers <= 3 || | ||||
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), | ||||
[ | [ | ||||
new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), | new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), | ||||
new TileClassPainter(clLand) | new TileClassPainter(clLand) | ||||
]); | ]); | ||||
// 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) | ||||
]); | ]); | ||||
} | } | ||||
g_Map.log("Creating the big central area"); | g_Map.log("Creating the big central area"); | ||||
createArea( | createArea( | ||||
new ClumpPlacer(diskArea(fractionToTiles(0.18)), 0.7, 0.1, Infinity, mapCenter), | new ClumpPlacer(diskArea(fractionToTiles(0.18)), 0.7, 0.1, Infinity, mapCenter), | ||||
[ | [ | ||||
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)); | ||||
if (!isNomad()) | if (!isNomad()) | ||||
{ | { | ||||
[playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); | [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); | ||||
markPlayerArea("small"); | markPlayerArea("small"); | ||||
} | } | ||||
} | } | ||||
}; | |||||
function centralRiverCoordinates(angle) | function centralRiverCoordinates(angle) | ||||
{ | { | ||||
return [ | return [ | ||||
new Vector2D(mapBounds.left + 1, mapCenter.y), | new Vector2D(mapBounds.left + 1, mapCenter.y), | ||||
new Vector2D(mapBounds.right - 1, mapCenter.y) | new Vector2D(mapBounds.right - 1, mapCenter.y) | ||||
].map(v => v.rotateAround(angle, mapCenter)); | ].map(v => v.rotateAround(angle, mapCenter)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | function createExtensionsOrIslands() | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Prevent impassable terrain and resource collisions at the the civic center and starting resources. | * Prevent impassable terrain and resource collisions at the the civic center and starting resources. | ||||
*/ | */ | ||||
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(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); | ||||
paintTerrainBasedOnHeight(-8, 1, 2, tWater); | paintTerrainBasedOnHeight(-8, 1, 2, tWater); | ||||
unPaintTileClassBasedOnHeight(0, heightCliff, 1, clWater); | unPaintTileClassBasedOnHeight(0, heightCliff, 1, clWater); | ||||
unPaintTileClassBasedOnHeight(-6, 0, 1, clLand); | unPaintTileClassBasedOnHeight(-6, 0, 1, clLand); | ||||
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), | ||||
new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), | new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), | ||||
[avoidClasses(clWater, 2, clPlayer, 10), stayClasses(clLand, 3)], | [avoidClasses(clWater, 2, clPlayer, 10), stayClasses(clLand, 3)], | ||||
randIntInclusive(0, scaleByMapSize(1, 2) * 200)); | randIntInclusive(0, scaleByMapSize(1, 2) * 200)); | ||||
g_Map.log("Creating hills"); | g_Map.log("Creating hills"); | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), | new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), | ||||
[ | [ | ||||
new LayeredPainter([tCliff, tHill], [2]), | new LayeredPainter([tCliff, tHill], [2]), | ||||
new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), | new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), | ||||
new TileClassPainter(clHill) | new TileClassPainter(clHill) | ||||
], | ], | ||||
[avoidClasses(clPlayer, 15, clHill, randIntInclusive(6, 18)), stayClasses(clLand, 0)], | [avoidClasses(clPlayer, 15, clHill, randIntInclusive(6, 18)), stayClasses(clLand, 0)], | ||||
randIntInclusive(0, scaleByMapSize(4, 8))*randIntInclusive(1, scaleByMapSize(4, 9)) | randIntInclusive(0, scaleByMapSize(4, 8))*randIntInclusive(1, scaleByMapSize(4, 9)) | ||||
); | ); | ||||
Engine.SetProgress(30); | Engine.SetProgress(30); | ||||
g_Map.log("Creating forests"); | g_Map.log("Creating forests"); | ||||
const [numForest, numStragglers] = getTreeCounts(...rBiomeTreeCount(1)); | const [numForest, numStragglers] = getTreeCounts(...rBiomeTreeCount(1)); | ||||
let types = [ | let types = [ | ||||
[[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], | [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], | ||||
[[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] | [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] | ||||
]; | ]; | ||||
const size = numForest / (scaleByMapSize(2, 8) * numPlayers); | const size = numForest / (scaleByMapSize(2, 8) * numPlayers); | ||||
let num = Math.floor(size / types.length); | let num = Math.floor(size / types.length); | ||||
for (const type of types) | for (const type of types) | ||||
createAreas( | createAreas( | ||||
new ClumpPlacer(numForest / num, 0.1, 0.1, Infinity), | new ClumpPlacer(numForest / num, 0.1, 0.1, Infinity), | ||||
[ | [ | ||||
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); | ||||
g_Map.log("Creating dirt patches"); | g_Map.log("Creating dirt patches"); | ||||
const patchCount = (currentBiome() == "generic/savanna" ? 3 : 1) * scaleByMapSize(15, 45); | const patchCount = (currentBiome() == "generic/savanna" ? 3 : 1) * scaleByMapSize(15, 45); | ||||
for (const patchSize of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) | for (const patchSize of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) | ||||
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 size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) | ||||
Lint: no-shadow 'size' is already declared in the upper scope on line 860 column 7. Lint: no-shadow: 'size' is already declared in the upper scope on line 860 column 7. | |||||
createAreas( | createAreas( | ||||
new ClumpPlacer(size, 0.3, 0.06, 0.5), | new ClumpPlacer(size, 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); | ||||
Engine.SetProgress(55); | Engine.SetProgress(55); | ||||
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)), | ||||
100); | 100); | ||||
g_Map.log("Creating small stone quarries"); | g_Map.log("Creating small stone quarries"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], true, clRock), | new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], 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)), | ||||
100); | 100); | ||||
g_Map.log("Creating metal mines"); | g_Map.log("Creating metal mines"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), | new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), | ||||
0, | 0, | ||||
[avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 2), stayClasses(clLand, 3)], | [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 2), stayClasses(clLand, 3)], | ||||
randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), | randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), | ||||
100); | 100); | ||||
Engine.SetProgress(65); | Engine.SetProgress(65); | ||||
g_Map.log("Creating small decorative rocks"); | g_Map.log("Creating small decorative rocks"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(aRockMedium, 1, 3, 0, 1)], true), | new SimpleGroup([new SimpleObject(aRockMedium, 1, 3, 0, 1)], 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(16, 262), | scaleByMapSize(16, 262), | ||||
50); | 50); | ||||
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), | ||||
50); | 50); | ||||
Engine.SetProgress(70); | Engine.SetProgress(70); | ||||
g_Map.log("Creating deer"); | g_Map.log("Creating deer"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], true, clFood), | new SimpleGroup([new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], true, clFood), | ||||
0, | 0, | ||||
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], | [avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], | ||||
randIntInclusive(numPlayers + 3, 5 * numPlayers + 4), | randIntInclusive(numPlayers + 3, 5 * numPlayers + 4), | ||||
50); | 50); | ||||
g_Map.log("Creating berry bush"); | g_Map.log("Creating berry bush"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(oFruitBush, 5, 7, 0, 4)], true, clFood), | new SimpleGroup([new SimpleObject(oFruitBush, 5, 7, 0, 4)], true, clFood), | ||||
0, | 0, | ||||
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], | [avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], | ||||
randIntInclusive(1, 4) * numPlayers + 2, | randIntInclusive(1, 4) * numPlayers + 2, | ||||
50); | 50); | ||||
Engine.SetProgress(75); | Engine.SetProgress(75); | ||||
g_Map.log("Creating sheep"); | g_Map.log("Creating sheep"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)], true, clFood), | new SimpleGroup([new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)], true, clFood), | ||||
0, | 0, | ||||
[avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], | [avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], | ||||
randIntInclusive(numPlayers + 3, 5 * numPlayers + 4), | randIntInclusive(numPlayers + 3, 5 * numPlayers + 4), | ||||
50); | 50); | ||||
g_Map.log("Creating fish"); | g_Map.log("Creating fish"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), | new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), | ||||
0, | 0, | ||||
avoidClasses(clLand, 4, clForest, 0, clPlayer, 0, clHill, 2, clFood, 20), | avoidClasses(clLand, 4, clForest, 0, clPlayer, 0, clHill, 2, clFood, 20), | ||||
randIntInclusive(15, 40) * numPlayers, | randIntInclusive(15, 40) * numPlayers, | ||||
60); | 60); | ||||
Engine.SetProgress(85); | Engine.SetProgress(85); | ||||
g_Map.log("Creating straggler trees"); | g_Map.log("Creating straggler trees"); | ||||
types = [g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree4]; | types = [g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree4]; | ||||
num = Math.floor(numStragglers / types.length); | num = Math.floor(numStragglers / types.length); | ||||
for (const type of types) | for (const type of types) | ||||
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; | ||||
g_Map.log("Creating small grass tufts"); | g_Map.log("Creating small grass tufts"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(aGrassShort, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)]), | new SimpleGroup([new SimpleObject(aGrassShort, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)]), | ||||
0, | 0, | ||||
[avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 3)], | [avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 3)], | ||||
planetm * scaleByMapSize(13, 200)); | planetm * scaleByMapSize(13, 200)); | ||||
Engine.SetProgress(90); | Engine.SetProgress(90); | ||||
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)); | ||||
Engine.SetProgress(95); | Engine.SetProgress(95); | ||||
g_Map.log("Creating shallow flora"); | g_Map.log("Creating shallow flora"); | ||||
createObjectGroupsDeprecated( | createObjectGroupsDeprecated( | ||||
new SimpleGroup([new SimpleObject(aLillies, 1, 2, 0, 2), new SimpleObject(aReeds, 2, 4, 0, 2)]), | new SimpleGroup([new SimpleObject(aLillies, 1, 2, 0, 2), new SimpleObject(aReeds, 2, 4, 0, 2)]), | ||||
0, | 0, | ||||
stayClasses(clShallow, 1), | stayClasses(clShallow, 1), | ||||
60 * scaleByMapSize(13, 200), | 60 * scaleByMapSize(13, 200), | ||||
80); | 80); | ||||
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), | ||||
50); | 50); | ||||
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() | |||||
{ | |||||
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(); | placePlayersNomad(clPlayer, | ||||
avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 10)); | |||||
g_Map.ExportMap(); | g_Map.ExportMap(); |
Wildfire Games · Phabricator
'numPlayers' is not modified in this loop.