Merge 'remotes/trunk'
[0ad.git] / binaries / data / mods / public / maps / random / neareastern_badlands.js
blob6775280e78daec5d25495a29cb713b5b3b6d76f7
1 Engine.LoadLibrary("rmgen");
2 Engine.LoadLibrary("rmgen-common");
3 Engine.LoadLibrary("rmbiome");
5 function* GenerateMap(mapSettings)
7         if (mapSettings.Biome)
8                 setSelectedBiome();
9         else
10                 setBiome("generic/sahara");
13         const tPrimary = g_Terrains.mainTerrain;
14         const tCity = g_Terrains.roadWild;
15         const tCityPlaza = g_Terrains.road;
16         const tSand = g_Terrains.tier3Terrain;
17         const tDunes = g_Terrains.tier4Terrain;
18         const tFineSand = g_Terrains.tier2Terrain;
19         const tCliff = g_Terrains.cliff;
20         const tDirt = g_Terrains.dirt;
21         const tForestFloor = "desert_forestfloor_palms";
22         const tGrass = g_Terrains.forestFloor2;
23         const tGrassSand25 = g_Terrains.shoreBlend;
24         const tShore = g_Terrains.shore;
25         const tWaterDeep = g_Terrains.water;
27         const oBerryBush = "gaia/fruit/grapes";
28         const oCamel = "gaia/fauna_camel";
29         const oFish = g_Gaia.fish;
30         const oGazelle = "gaia/fauna_gazelle";
31         const oGiraffe = "gaia/fauna_giraffe";
32         const oGoat = "gaia/fauna_goat";
33         const oWildebeest = "gaia/fauna_wildebeest";
34         const oStoneLarge = g_Gaia.stoneLarge;
35         const oStoneSmall = g_Gaia.stoneSmall;
36         const oMetalLarge = g_Gaia.metalLarge;
37         const oMetalSmall = g_Gaia.metalSmall;
38         const oOasisTree = "gaia/tree/senegal_date_palm";
39         const oDatePalm = g_Gaia.tree1;
40         const oSDatePalm = g_Gaia.tree2;
42         const aBush1 = g_Decoratives.bushMedium;
43         const aBush2 = "actor|props/flora/bush_desert_dry_a.xml";
44         const aBush3 = g_Decoratives.bushSmall;
45         const aBush4 = "actor|props/flora/plant_desert_a.xml";
46         const aBushes = [aBush1, aBush2, aBush3, aBush4];
47         const aDecorativeRock = g_Decoratives.rockMedium;
49         const pForest = [
50                 tForestFloor + TERRAIN_SEPARATOR + oDatePalm,
51                 tForestFloor + TERRAIN_SEPARATOR + oSDatePalm,
52                 tForestFloor
53         ];
54         const pForestOasis = [
55                 tGrass + TERRAIN_SEPARATOR + oOasisTree,
56                 tGrass + TERRAIN_SEPARATOR + oDatePalm,
57                 tGrass
58         ];
60         const heightLand = 10;
62         const heightOffsetOasis = -11;
63         const heightOffsetHill1 = 16;
64         const heightOffsetHill2 = 16;
65         const heightOffsetHill3 = 16;
66         const heightOffsetBump = 2;
68         globalThis.g_Map = new RandomMap(heightLand, tPrimary);
70         const numPlayers = getNumPlayers();
71         const mapSize = g_Map.getSize();
72         const mapCenter = g_Map.getCenter();
74         const clPlayer = g_Map.createTileClass();
75         const clHill1 = g_Map.createTileClass();
76         const clOasis = g_Map.createTileClass();
77         const clForest = g_Map.createTileClass();
78         const clPatch = g_Map.createTileClass();
79         const clRock = g_Map.createTileClass();
80         const clMetal = g_Map.createTileClass();
81         const clFood = g_Map.createTileClass();
82         const clBaseResource = g_Map.createTileClass();
84         const oasisRadius = scaleByMapSize(14, 40);
86         const [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35));
88         if (!isNomad())
89                 for (let i = 0; i < numPlayers; ++i)
90                         createArea(
91                                 new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.9, 0.5, Infinity,
92                                         playerPosition[i]),
93                                 new TileClassPainter(clPlayer));
95         placePlayerBases({
96                 "PlayerPlacement": [playerIDs, playerPosition],
97                 "PlayerTileClass": clPlayer,
98                 "BaseResourceClass": clBaseResource,
99                 "CityPatch": {
100                         "outerTerrain": tCity,
101                         "innerTerrain": tCityPlaza,
102                         "width": 3,
103                         "radius": 10
104                 },
105                 "StartingAnimal": {
106                 },
107                 "Berries": {
108                         "template": oBerryBush
109                 },
110                 "Mines": {
111                         "types": [
112                                 { "template": oMetalLarge },
113                                 { "template": oStoneLarge }
114                         ]
115                 },
116                 "Trees": {
117                         "template": oDatePalm
118                 }
119                 // No decoratives
120         });
121         yield 10;
123         g_Map.log("Creating dune patches");
124         createAreas(
125                 new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, 0),
126                 [
127                         new TerrainPainter(tDunes),
128                         new TileClassPainter(clPatch)
129                 ],
130                 avoidClasses(clPatch, 2, clPlayer, 0),
131                 scaleByMapSize(5, 20));
132         yield 15;
134         g_Map.log("Creating sand patches");
135         createAreas(
136                 new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0),
137                 [
138                         new TerrainPainter([tSand, tFineSand]),
139                         new TileClassPainter(clPatch)
140                 ],
141                 avoidClasses(clPatch, 2, clPlayer, 0),
142                 scaleByMapSize(15, 50));
143         yield 20;
145         g_Map.log("Creating dirt patches");
146         createAreas(
147                 new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0),
148                 [
149                         new TerrainPainter([tDirt]),
150                         new TileClassPainter(clPatch)
151                 ],
152                 avoidClasses(clPatch, 2, clPlayer, 0),
153                 scaleByMapSize(15, 50));
154         yield 25;
156         g_Map.log("Creating oasis");
157         createArea(
158                 new ClumpPlacer(diskArea(oasisRadius), 0.6, 0.15, 0, mapCenter),
159                 [
160                         new LayeredPainter(
161                                 [
162                                         [tSand, pForest],
163                                         [tGrassSand25, pForestOasis],
164                                         tGrassSand25,
165                                         tShore,
166                                         tWaterDeep
167                                 ],
168                                 [2, 3, 1, 1]),
169                         new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetOasis, 8),
170                         new TileClassPainter(clOasis)
171                 ]);
173         yield 30;
175         g_Map.log("Creating oasis wildlife");
176         let num = Math.round(Math.PI * oasisRadius / 8);
177         let constraint = new AndConstraint([borderClasses(clOasis, 0, 3), avoidClasses(clOasis, 0)]);
178         for (let i = 0; i < num; ++i)
179         {
180                 let animalPosition;
181                 let r = 0;
182                 const angle = 2 * Math.PI / num * i;
183                 do
184                 {
185                         // Work outward until constraint met
186                         animalPosition = Vector2D.add(mapCenter, new Vector2D(r, 0).rotate(-angle)).round();
187                         ++r;
188                 } while (!constraint.allows(animalPosition) && r < mapSize / 2);
190                 createObjectGroup(
191                         new RandomGroup(
192                                 [
193                                         new SimpleObject(oGiraffe, 2, 4, 0, 3),
194                                         new SimpleObject(oWildebeest, 3, 5, 0, 3),
195                                         new SimpleObject(oGazelle, 5, 7, 0, 3)
196                                 ],
197                                 true,
198                                 clFood,
199                                 animalPosition),
200                         0);
201         }
203         g_Map.log("Creating oasis fish");
204         constraint = new AndConstraint([borderClasses(clOasis, 15, 0), avoidClasses(clFood, 5)]);
205         num = Math.round(Math.PI * oasisRadius / 16);
206         for (let i = 0; i < num; ++i)
207         {
208                 let fishPosition;
209                 let r = 0;
210                 const angle = 2 * Math.PI / num * i;
211                 do
212                 {
213                         // Work outward until constraint met
214                         fishPosition = Vector2D.add(mapCenter, new Vector2D(r, 0).rotate(-angle));
215                         ++r;
216                 } while (!constraint.allows(fishPosition) && r < mapSize / 2);
218                 createObjectGroup(
219                         new SimpleGroup([new SimpleObject(oFish, 1, 1, 0, 1)], true, clFood, fishPosition), 0);
220         }
221         yield 35;
223         g_Map.log("Creating level 1 hills");
224         let hillAreas = createAreas(
225                 new ClumpPlacer(scaleByMapSize(50, 300), 0.25, 0.1, 0.5),
226                 [
227                         new LayeredPainter([tCliff, tSand], [1]),
228                         new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill1, 1),
229                         new TileClassPainter(clHill1)
230                 ],
231                 avoidClasses(clOasis, 3, clPlayer, 0, clHill1, 10),
232                 scaleByMapSize(10, 20), 100
233         );
234         yield 40;
236         g_Map.log("Creating small level 1 hills");
237         hillAreas = hillAreas.concat(
238                 createAreas(
239                         new ClumpPlacer(scaleByMapSize(25, 150), 0.25, 0.1, 0.5),
240                         [
241                                 new LayeredPainter([tCliff, tSand], [1]),
242                                 new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill2, 1),
243                                 new TileClassPainter(clHill1)
244                         ],
245                         avoidClasses(clOasis, 3, clPlayer, 0, clHill1, 3),
246                         scaleByMapSize(15, 25),
247                         100));
249         yield 45;
251         g_Map.log("Creating decorative rocks");
252         createObjectGroupsByAreasDeprecated(
253                 new SimpleGroup(
254                         [new RandomObject([aDecorativeRock, aBush2, aBush3], 3, 8, 0, 2)],
255                         true),
256                 0,
257                 borderClasses(clHill1, 0, 3),
258                 scaleByMapSize(40, 200), 50,
259                 hillAreas);
261         yield 50;
263         g_Map.log("Creating level 2 hills");
264         createAreasInAreas(
265                 new ClumpPlacer(scaleByMapSize(25, 150), 0.25, 0.1, 0),
266                 [
267                         new LayeredPainter([tCliff, tSand], [1]),
268                         new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill2, 1)
269                 ],
270                 [stayClasses(clHill1, 0)],
271                 scaleByMapSize(15, 25),
272                 50,
273                 hillAreas);
275         yield 55;
277         g_Map.log("Creating level 3 hills");
278         createAreas(
279                 new ClumpPlacer(scaleByMapSize(12, 75), 0.25, 0.1, 0),
280                 [
281                         new LayeredPainter([tCliff, tSand], [1]),
282                         new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill3, 1)
283                 ],
284                 [stayClasses(clHill1, 0)],
285                 scaleByMapSize(15, 25),
286                 50
287         );
288         yield 60;
290         g_Map.log("Creating bumps");
291         createAreas(
292                 new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 0),
293                 new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2),
294                 avoidClasses(clOasis, 0, clPlayer, 0, clHill1, 2),
295                 scaleByMapSize(100, 200)
296         );
298         yield 65;
300         g_Map.log("Creating forests");
301         const [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.5);
302         num = g_DefaultNumberOfForests;
303         createAreas(
304                 new ClumpPlacer(forestTrees / num, 0.15, 0.1, 0.5),
305                 [
306                         new TerrainPainter([tSand, pForest]),
307                         new TileClassPainter(clForest)
308                 ],
309                 avoidClasses(clPlayer, 1, clOasis, 10, clForest, 10, clHill1, 1),
310                 num,
311                 50);
313         yield 70;
314         g_Map.log("Creating metal mines");
315         createBalancedMetalMines(
316                 oMetalSmall,
317                 oMetalLarge,
318                 clMetal,
319                 avoidClasses(clOasis, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill1, 1)
320         );
322         g_Map.log("Creating stone mines");
323         createBalancedStoneMines(
324                 oStoneSmall,
325                 oStoneLarge,
326                 clRock,
327                 avoidClasses(clOasis, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill1, 1, clMetal, 10)
328         );
329         yield 80;
331         g_Map.log("Creating gazelles");
332         let group = new SimpleGroup([new SimpleObject(oGazelle, 5, 7, 0, 4)], true, clFood);
333         createObjectGroupsDeprecated(group, 0,
334                 avoidClasses(clOasis, 1, clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10),
335                 scaleByMapSize(5, 20), 50
336         );
338         g_Map.log("Creating goats");
339         group = new SimpleGroup([new SimpleObject(oGoat, 2, 4, 0, 3)], true, clFood);
340         createObjectGroupsDeprecated(group, 0,
341                 avoidClasses(clOasis, 1, clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10),
342                 scaleByMapSize(5, 20), 50
343         );
345         g_Map.log("Creating camels");
346         group = new SimpleGroup([new SimpleObject(oCamel, 2, 4, 0, 2)], true, clFood);
347         createObjectGroupsDeprecated(group, 0,
348                 avoidClasses(clOasis, 1, clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10),
349                 scaleByMapSize(5, 20), 50
350         );
351         yield 85;
353         createStragglerTrees(
354                 [oDatePalm, oSDatePalm],
355                 avoidClasses(clOasis, 1, clForest, 0, clHill1, 1, clPlayer, 4, clMetal, 6, clRock, 6),
356                 clForest,
357                 stragglerTrees);
358         yield 90;
360         g_Map.log("Creating bushes");
361         group = new SimpleGroup([new RandomObject(aBushes, 2, 3, 0, 2)]);
362         createObjectGroupsDeprecated(group, 0,
363                 avoidClasses(clOasis, 1, clHill1, 1, clPlayer, 0, clForest, 0),
364                 scaleByMapSize(16, 262)
365         );
367         g_Map.log("Creating more decorative rocks");
368         group = new SimpleGroup([new SimpleObject(aDecorativeRock, 1, 2, 0, 2)]);
369         createObjectGroupsDeprecated(group, 0,
370                 avoidClasses(clOasis, 1, clHill1, 1, clPlayer, 0, clForest, 0),
371                 scaleByMapSize(16, 262)
372         );
374         placePlayersNomad(clPlayer,
375                 avoidClasses(clOasis, 4, clForest, 1, clMetal, 4, clRock, 4, clHill1, 4, clFood, 2));
377         setWaterWaviness(1.0);
378         setWaterType("clap");
379         setWaterHeight(20);
381         return g_Map;