Add "has" helper function to TileClass, so that one can find out if the given tile...
[0ad.git] / binaries / data / mods / public / maps / random / mediterranean.js
blob561592b1bac0de281ee1d5319e7de7633bba3b28
1 /**
2  * Heightmap image source:
3  * Imagery by Jesse Allen, NASA's Earth Observatory,
4  * using data from the General Bathymetric Chart of the Oceans (GEBCO)
5  * produced by the British Oceanographic Data Centre.
6  * https://visibleearth.nasa.gov/view.php?id=73934
7  *
8  * Licensing: Public Domain, https://visibleearth.nasa.gov/useterms.php
9  *
10  * The heightmap image is reproduced using:
11  * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/gebco_08_rev_elev_{A,B,C,D}{1..2}_grey_geo.tif
12  * gdal_merge.py -o world.tif gebco_08_rev_elev_{A,B,C,D}{1..2}_grey_geo.tif
13  * lat=46; lon=14; width=58;
14  * gdal_translate -projwin $((lon-width/2)) $((lat+width/2)) $((lon+width/2)) $((lat-width/2)) world.tif mediterranean.tif
15  * convert mediterranean.tif -resize 512 -contrast-stretch 0 mediterranean.png
16  * No further changes should be applied to the image to keep it easily interchangeable.
17  */
19 Engine.LoadLibrary("rmgen");
20 Engine.LoadLibrary("rmgen-common");
21 Engine.LoadLibrary("rmgen2");
22 Engine.LoadLibrary("rmbiome");
24 TILE_CENTERED_HEIGHT_MAP = true;
26 const tWater = "medit_sand_wet";
27 const tSnowedRocks = ["alpine_cliff_b", "alpine_cliff_snow"];
28 setBiome("generic/mediterranean");
30 const heightScale = num => num * g_MapSettings.Size / 320;
32 const heightSeaGround = heightScale(-6);
33 const heightWaterLevel = heightScale(0);
34 const heightShoreline = heightScale(0.5);
35 const heightSnow = heightScale(10);
37 var g_Map = new RandomMap(heightWaterLevel, g_Terrains.mainTerrain);
38 var mapSize = g_Map.getSize();
39 var mapCenter = g_Map.getCenter();
40 var mapBounds = g_Map.getBounds();
42 g_Map.LoadHeightmapImage("mediterranean.png", 0, 40);
43 Engine.SetProgress(15);
45 initTileClasses(["autumn", "desert", "medit", "polar", "steppe", "temp", "shoreline", "africa", "northern_europe", "southern_europe", "western_europe", "eastern_europe"]);
47 var northernTopLeft = new Vector2D(fractionToTiles(0.3), fractionToTiles(0.7));
48 var westernTopLeft = new Vector2D(fractionToTiles(0.7), fractionToTiles(0.47));
49 var africaTop = fractionToTiles(0.33);
51 var climateZones = [
52         {
53                 "tileClass": g_TileClasses.northern_europe,
54                 "position1": new Vector2D(northernTopLeft.x, mapBounds.top),
55                 "position2": new Vector2D(mapBounds.right, northernTopLeft.y),
56                 "biome": "generic/snowy",
57                 "constraint": new NullConstraint()
58         },
59         {
60                 "tileClass": g_TileClasses.western_europe,
61                 "position1": new Vector2D(mapBounds.left, mapBounds.top),
62                 "position2": westernTopLeft,
63                 "biome": "generic/temperate",
64                 "constraint": avoidClasses(g_TileClasses.northern_europe, 0)
65         },
66         {
67                 "tileClass": g_TileClasses.eastern_europe,
68                 "position1": new Vector2D(westernTopLeft.x, mapBounds.top),
69                 "position2": new Vector2D(mapBounds.right, westernTopLeft.y),
70                 "biome": "generic/autumn",
71                 "constraint": avoidClasses(g_TileClasses.northern_europe, 0)
72         },
73         {
74                 "tileClass": g_TileClasses.southern_europe,
75                 "position1": new Vector2D(mapBounds.left, africaTop),
76                 "position2": new Vector2D(mapBounds.right, westernTopLeft.y),
77                 "biome": "generic/mediterranean",
78                 "constraint": new NullConstraint()
79         },
80         {
81                 "tileClass": g_TileClasses.africa,
82                 "position1": new Vector2D(mapBounds.left, africaTop),
83                 "position2": new Vector2D(mapBounds.right, mapBounds.bottom),
84                 "biome": "generic/desert",
85                 "constraint": new NullConstraint()
86         }
89 g_Map.log("Lowering sea ground");
90 createArea(
91         new MapBoundsPlacer(),
92         new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 2),
93         new HeightConstraint(-Infinity, heightWaterLevel));
94 Engine.SetProgress(20);
96 g_Map.log("Smoothing heightmap");
97 createArea(
98         new MapBoundsPlacer(),
99         new SmoothingPainter(1, scaleByMapSize(0.3, 0.8), 1));
100 Engine.SetProgress(25);
102 g_Map.log("Marking water");
103 createArea(
104         new MapBoundsPlacer(),
105         new TileClassPainter(g_TileClasses.water),
106         new HeightConstraint(-Infinity, heightWaterLevel));
107 Engine.SetProgress(30);
109 g_Map.log("Marking land");
110 createArea(
111         new DiskPlacer(fractionToTiles(0.5), mapCenter),
112         new TileClassPainter(g_TileClasses.land),
113         avoidClasses(g_TileClasses.water, 0));
114 Engine.SetProgress(35);
116 g_Map.log("Marking climate zones");
117 for (let zone of climateZones)
119         setBiome(zone.biome);
120         createArea(
121                 new RectPlacer(zone.position1, zone.position2, Infinity),
122                 new TileClassPainter(zone.tileClass),
123                 zone.constraint);
125         createArea(
126                         new RectPlacer(zone.position1, zone.position2, Infinity),
127                         new TerrainPainter(g_Terrains.mainTerrain),
128                         [
129                                 new HeightConstraint(heightWaterLevel, Infinity),
130                                 zone.constraint
131                         ]);
133 Engine.SetProgress(40);
135 g_Map.log("Fuzzing biome borders");
136 for (let zone of climateZones)
138         setBiome(zone.biome);
140         createLayeredPatches(
141                 [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
142                 [
143                         [g_Terrains.mainTerrain, g_Terrains.tier1Terrain],
144                         [g_Terrains.tier1Terrain, g_Terrains.tier2Terrain],
145                         [g_Terrains.tier2Terrain, g_Terrains.tier3Terrain]
146                 ],
147                 [1, 1],
148                 [
149                         avoidClasses(
150                                 g_TileClasses.forest, 2,
151                                 g_TileClasses.water, 2,
152                                 g_TileClasses.mountain, 2,
153                                 g_TileClasses.dirt, 5,
154                                 g_TileClasses.player, 8),
155                         borderClasses(zone.tileClass, 3, 3),
156                 ],
157                 scaleByMapSize(20, 60),
158                 g_TileClasses.dirt);
160 Engine.SetProgress(45);
162 if (!isNomad())
164         g_Map.log("Finding player positions");
166         let [playerIDs, playerPosition] = playerPlacementRandom(
167                 sortAllPlayers(),
168                 [
169                         avoidClasses(g_TileClasses.mountain, 5),
170                         stayClasses(g_TileClasses.land, scaleByMapSize(8, 25))
171                 ]);
173         g_Map.log("Flatten the initial CC area and placing playerbases...");
174         for (let i = 0; i < getNumPlayers(); ++i)
175         {
176                 g_Map.logger.printDuration();
177                 setBiome(climateZones.find(zone => zone.tileClass.has(playerPosition[i])).biome);
179                 createArea(
180                         new ClumpPlacer(diskArea(defaultPlayerBaseRadius() * 0.8), 0.95, 0.6, Infinity, playerPosition[i]),
181                         new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(playerPosition[i]), 6));
183                 createBase(playerIDs[i], playerPosition[i], mapSize >= 384);
184         }
186 Engine.SetProgress(50);
188 for (let zone of climateZones)
190         setBiome(zone.biome);
192         g_Map.log("Painting shoreline");
193         createArea(
194                 new MapBoundsPlacer(),
195                 [
196                         new TerrainPainter(g_Terrains.shore),
197                         new TileClassPainter(g_TileClasses.shoreline)
198                 ],
199                 [
200                         stayClasses(zone.tileClass, 0),
201                         new HeightConstraint(-Infinity, heightShoreline)
202                 ]);
204         g_Map.log("Painting cliffs");
205         createArea(
206                 new MapBoundsPlacer(),
207                 [
208                         new TerrainPainter(g_Terrains.cliff),
209                         new TileClassPainter(g_TileClasses.mountain),
210                 ],
211                 [
212                         stayClasses(zone.tileClass, 0),
213                         avoidClasses(g_TileClasses.water, 2),
214                         new SlopeConstraint(2, Infinity)
215                 ]);
217         g_Map.log("Placing resources");
218         addElements([
219                 {
220                         "func": addMetal,
221                         "avoid": [
222                                 g_TileClasses.berries, 5,
223                                 g_TileClasses.forest, 3,
224                                 g_TileClasses.mountain, 2,
225                                 g_TileClasses.player, 30,
226                                 g_TileClasses.rock, 10,
227                                 g_TileClasses.metal, 25,
228                                 g_TileClasses.water, 4
229                         ],
230                         "stay": [zone.tileClass, 0],
231                         "sizes": ["normal"],
232                         "mixes": ["same"],
233                         "amounts": ["many"]
234                 },
235                 {
236                         "func": addStone,
237                         "avoid": [
238                                 g_TileClasses.berries, 5,
239                                 g_TileClasses.forest, 3,
240                                 g_TileClasses.mountain, 2,
241                                 g_TileClasses.player, 30,
242                                 g_TileClasses.rock, 10,
243                                 g_TileClasses.metal, 25,
244                                 g_TileClasses.water, 4
245                         ],
246                         "stay": [zone.tileClass, 0],
247                         "sizes": ["normal"],
248                         "mixes": ["same"],
249                         "amounts": ["many"]
250                 },
251                 {
252                         "func": addForests,
253                         "avoid": [
254                                 g_TileClasses.berries, 3,
255                                 g_TileClasses.forest, 15,
256                                 g_TileClasses.metal, 3,
257                                 g_TileClasses.mountain, 2,
258                                 g_TileClasses.player, 12,
259                                 g_TileClasses.rock, 2,
260                                 g_TileClasses.water, 2
261                         ],
262                         "stay": [zone.tileClass, 0],
263                         "sizes": ["normal"],
264                         "mixes": ["normal"],
265                         "amounts": ["normal"]
266                 },
267                 {
268                         "func": addSmallMetal,
269                         "avoid": [
270                                 g_TileClasses.berries, 5,
271                                 g_TileClasses.forest, 3,
272                                 g_TileClasses.mountain, 2,
273                                 g_TileClasses.player, 30,
274                                 g_TileClasses.rock, 10,
275                                 g_TileClasses.metal, 15,
276                                 g_TileClasses.water, 4
277                         ],
278                         "stay": [zone.tileClass, 0],
279                         "sizes": ["normal"],
280                         "mixes": ["same"],
281                         "amounts": ["few", "normal", "many"]
282                 },
283                 {
284                         "func": addBerries,
285                         "avoid": [
286                                 g_TileClasses.berries, 30,
287                                 g_TileClasses.forest, 2,
288                                 g_TileClasses.metal, 4,
289                                 g_TileClasses.mountain, 2,
290                                 g_TileClasses.player, 20,
291                                 g_TileClasses.rock, 4,
292                                 g_TileClasses.water, 2
293                         ],
294                         "stay": [zone.tileClass, 0],
295                         "sizes": ["normal"],
296                         "mixes": ["normal"],
297                         "amounts": ["many"]
298                 },
299                 {
300                         "func": addAnimals,
301                         "avoid": [
302                                 g_TileClasses.animals, 10,
303                                 g_TileClasses.forest, 1,
304                                 g_TileClasses.metal, 2,
305                                 g_TileClasses.mountain, 1,
306                                 g_TileClasses.player, 15,
307                                 g_TileClasses.rock, 2,
308                                 g_TileClasses.water, 3
309                         ],
310                         "stay": [zone.tileClass, 0],
311                         "sizes": ["normal"],
312                         "mixes": ["normal"],
313                         "amounts": ["many"]
314                 },
315                                 {
316                         "func": addAnimals,
317                         "avoid": [
318                                 g_TileClasses.animals, 10,
319                                 g_TileClasses.forest, 1,
320                                 g_TileClasses.metal, 2,
321                                 g_TileClasses.mountain, 1,
322                                 g_TileClasses.player, 15,
323                                 g_TileClasses.rock, 2,
324                                 g_TileClasses.water, 1
325                         ],
326                         "stay": [zone.tileClass, 0],
327                         "sizes": ["small"],
328                         "mixes": ["normal"],
329                         "amounts": ["tons"]
330                 },
331                 {
332                         "func": addStragglerTrees,
333                         "avoid": [
334                                 g_TileClasses.berries, 5,
335                                 g_TileClasses.forest, 5,
336                                 g_TileClasses.metal, 2,
337                                 g_TileClasses.mountain, 1,
338                                 g_TileClasses.player, 12,
339                                 g_TileClasses.rock, 2,
340                                 g_TileClasses.water, 3
341                         ],
342                         "stay": [zone.tileClass, 0],
343                         "sizes": ["normal"],
344                         "mixes": ["normal"],
345                         "amounts": ["some"]
346                 },
347                 {
348                         "func": addLayeredPatches,
349                         "avoid": [
350                                 g_TileClasses.dirt, 5,
351                                 g_TileClasses.forest, 2,
352                                 g_TileClasses.mountain, 2,
353                                 g_TileClasses.player, 12,
354                                 g_TileClasses.water, 3
355                         ],
356                         "stay": [zone.tileClass, 0],
357                         "sizes": ["normal"],
358                         "mixes": ["normal"],
359                         "amounts": ["tons"]
360                 },
361                 {
362                         "func": addDecoration,
363                         "avoid": [
364                                 g_TileClasses.forest, 2,
365                                 g_TileClasses.mountain, 2,
366                                 g_TileClasses.player, 12,
367                                 g_TileClasses.water, 4
368                         ],
369                         "stay": [zone.tileClass, 0],
370                         "sizes": ["small"],
371                         "mixes": ["same"],
372                         "amounts": ["normal"]
373                 }
374         ]);
376 Engine.SetProgress(60);
378 g_Map.log("Painting water");
379 createArea(
380         new MapBoundsPlacer(),
381         new TerrainPainter(tWater),
382         new HeightConstraint(-Infinity, heightWaterLevel));
384 g_Map.log("Painting snow on mountains");
385 createArea(
386         new MapBoundsPlacer(),
387         new TerrainPainter(tSnowedRocks),
388         [
389                 new HeightConstraint(heightSnow, Infinity),
390                 avoidClasses(
391                         g_TileClasses.africa, 0,
392                         g_TileClasses.southern_europe, 0,
393                         g_TileClasses.player, 6)
394         ]);
396 Engine.SetProgress(70);
398 g_Map.log("Placing fish...");
399 g_Gaia.fish = "gaia/fauna_fish";
400 addElements([
401         {
402                 "func": addFish,
403                 "avoid": [
404                         g_TileClasses.fish, 10,
405                 ],
406                 "stay": [g_TileClasses.water, 4],
407                 "sizes": ["normal"],
408                 "mixes": ["similar"],
409                 "amounts": ["many"]
410         }
412 Engine.SetProgress(85);
414 g_Map.log("Placing whale...");
415 g_Gaia.fish = "gaia/fauna_whale_fin";
416 addElements([
417         {
418                 "func": addFish,
419                 "avoid": [
420                         g_TileClasses.fish, 2,
421                         g_TileClasses.desert, 50,
422                         g_TileClasses.steppe, 50
423                 ],
424                 "stay": [g_TileClasses.water, 7],
425                 "sizes": ["small"],
426                 "mixes": ["same"],
427                 "amounts": ["scarce"]
428         }
430 Engine.SetProgress(95);
432 placePlayersNomad(
433         g_Map.createTileClass(),
434         [
435                 stayClasses(g_TileClasses.land, 5),
436                 avoidClasses(
437                         g_TileClasses.forest, 2,
438                         g_TileClasses.rock, 4,
439                         g_TileClasses.metal, 4,
440                         g_TileClasses.berries, 2,
441                         g_TileClasses.animals, 2,
442                         g_TileClasses.mountain, 2)
443         ]);
445 setWindAngle(-0.589049);
446 setWaterTint(0.556863, 0.615686, 0.643137);
447 setWaterColor(0.494118, 0.639216, 0.713726);
448 setWaterWaviness(8);
449 setWaterMurkiness(0.87);
450 setWaterType("ocean");
452 setTerrainAmbientColor(0.72, 0.72, 0.82);
454 setSunColor(0.733, 0.746, 0.574);
455 setSunRotation(Math.PI * 0.95);
456 setSunElevation(Math.PI / 6);
458 setSkySet("cumulus");
459 setFogFactor(0);
460 setFogThickness(0);
461 setFogColor(0.69, 0.616, 0.541);
463 setPPEffect("hdr");
464 setPPContrast(0.67);
465 setPPSaturation(0.42);
466 setPPBloom(0.23);
468 g_Map.ExportMap();