Fix rmgen2 bug in rP17903 revealed by the 1* removal in rP20281.
[0ad.git] / binaries / data / mods / public / maps / random / islands.js
blob6dabc27213210c729a988dde44ce9032359d78d5
1 RMS.LoadLibrary("rmgen");
2 RMS.LoadLibrary("rmbiome");
4 TILE_CENTERED_HEIGHT_MAP = true;
6 setSelectedBiome();
8 const tMainTerrain = g_Terrains.mainTerrain;
9 const tForestFloor1 = g_Terrains.forestFloor1;
10 const tForestFloor2 = g_Terrains.forestFloor2;
11 const tCliff = g_Terrains.cliff;
12 const tTier1Terrain = g_Terrains.tier1Terrain;
13 const tTier2Terrain = g_Terrains.tier2Terrain;
14 const tTier3Terrain = g_Terrains.tier3Terrain;
15 const tHill = g_Terrains.hill;
16 const tDirt = g_Terrains.dirt;
17 const tRoad = g_Terrains.road;
18 const tRoadWild = g_Terrains.roadWild;
19 const tTier4Terrain = g_Terrains.tier4Terrain;
20 const tShoreBlend = g_Terrains.shoreBlend;
21 const tShore = g_Terrains.shore;
22 const tWater = g_Terrains.water;
24 const oTree1 = g_Gaia.tree1;
25 const oTree2 = g_Gaia.tree2;
26 const oTree3 = g_Gaia.tree3;
27 const oTree4 = g_Gaia.tree4;
28 const oTree5 = g_Gaia.tree5;
29 const oFruitBush = g_Gaia.fruitBush;
30 const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
31 const oFish = g_Gaia.fish;
32 const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
33 const oStoneLarge = g_Gaia.stoneLarge;
34 const oStoneSmall = g_Gaia.stoneSmall;
35 const oMetalLarge = g_Gaia.metalLarge;
36 const oWood = "gaia/special_treasure_wood";
38 const aGrass = g_Decoratives.grass;
39 const aGrassShort = g_Decoratives.grassShort;
40 const aReeds = g_Decoratives.reeds;
41 const aLillies = g_Decoratives.lillies;
42 const aRockLarge = g_Decoratives.rockLarge;
43 const aRockMedium = g_Decoratives.rockMedium;
44 const aBushMedium = g_Decoratives.bushMedium;
45 const aBushSmall = g_Decoratives.bushSmall;
47 const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
48 const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
50 InitMap();
52 const numPlayers = getNumPlayers();
53 const mapSize = getMapSize();
54 const mapArea = mapSize*mapSize;
56 var clPlayer = createTileClass();
57 var clHill = createTileClass();
58 var clForest = createTileClass();
59 var clDirt = createTileClass();
60 var clRock = createTileClass();
61 var clMetal = createTileClass();
62 var clFood = createTileClass();
63 var clBaseResource = createTileClass();
64 var clSettlement = createTileClass();
65 var clLand = createTileClass();
67 var [playerIDs, playerX, playerZ, playerAngle] = radialPlayerPlacement();
69 for (var i = 0; i < numPlayers; i++)
71         var id = playerIDs[i];
72         log("Creating base for player " + id + "...");
74         var radius = scaleByMapSize(20,29);
75         var shoreRadius = 6;
76         var elevation = 3;
78         var hillSize = PI * radius * radius;
79         // get the x and z in tiles
80         var fx = fractionToTiles(playerX[i]);
81         var fz = fractionToTiles(playerZ[i]);
82         var ix = round(fx);
83         var iz = round(fz);
84         // create the hill
85         var placer = new ClumpPlacer(hillSize, 0.80, 0.1, 10, ix, iz);
86         var terrainPainter = new LayeredPainter(
87                 [tMainTerrain , tMainTerrain, tMainTerrain],            // terrains
88                 [1, shoreRadius]                // widths
89         );
90         var elevationPainter = new SmoothElevationPainter(
91                 ELEVATION_SET,                  // type
92                 elevation,                              // elevation
93                 shoreRadius                             // blend radius
94         );
95         createArea(placer, [terrainPainter, elevationPainter, paintClass(clPlayer)], null);
97         placeCivDefaultEntities(fx, fz, id, { 'iberWall': 'towers' });
99         placeDefaultChicken(fx, fz, clBaseResource);
101         // create berry bushes
102         var bbAngle = randFloat(0, TWO_PI);
103         var bbDist = 12;
104         var bbX = round(fx + bbDist * cos(bbAngle));
105         var bbZ = round(fz + bbDist * sin(bbAngle));
106         var group = new SimpleGroup(
107                 [new SimpleObject(oFruitBush, 5,5, 0,3)],
108                 true, clBaseResource, bbX, bbZ
109         );
110         createObjectGroup(group, 0);
112         // create woods
113         var bbAngle = randFloat(0, TWO_PI);
114         var bbDist = 13;
115         var bbX = round(fx + bbDist * cos(bbAngle));
116         var bbZ = round(fz + bbDist * sin(bbAngle));
117         group = new SimpleGroup(
118                 [new SimpleObject(oWood, 14,14, 0,3)],
119                 true, clBaseResource, bbX, bbZ
120         );
121         createObjectGroup(group, 0);
123         // create metal mine
124         var mAngle = bbAngle;
125         while(abs(mAngle - bbAngle) < PI/3)
126         {
127                 mAngle = randFloat(0, TWO_PI);
128         }
129         var mDist = 12;
130         var mX = round(fx + mDist * cos(mAngle));
131         var mZ = round(fz + mDist * sin(mAngle));
132         group = new SimpleGroup(
133                 [new SimpleObject(oMetalLarge, 1,1, 0,0)],
134                 true, clBaseResource, mX, mZ
135         );
136         createObjectGroup(group, 0);
138         // create stone mines
139         mAngle += randFloat(PI/8, PI/4);
140         mX = round(fx + mDist * cos(mAngle));
141         mZ = round(fz + mDist * sin(mAngle));
142         group = new SimpleGroup(
143                 [new SimpleObject(oStoneLarge, 1,1, 0,2)],
144                 true, clBaseResource, mX, mZ
145         );
146         createObjectGroup(group, 0);
147         var hillSize = PI * radius * radius;
148         // create starting trees
149         var num = 5;
150         var tAngle = randFloat(-PI/3, 4*PI/3);
151         var tDist = randFloat(12, 13);
152         var tX = round(fx + tDist * cos(tAngle));
153         var tZ = round(fz + tDist * sin(tAngle));
154         group = new SimpleGroup(
155                 [new SimpleObject(oTree1, num, num, 0,3)],
156                 false, clBaseResource, tX, tZ
157         );
158         createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
160         placeDefaultDecoratives(fx, fz, aGrassShort, clBaseResource, radius);
162         //create docks
163         var dockLocation = getTIPIADBON([ix, iz], [mapSize / 2, mapSize / 2], [-3 , 2.6], 0.5, 3);
164         if (dockLocation !== undefined)
165                 placeObject(dockLocation[0], dockLocation[1], "structures/" + getCivCode(id-1) + "_dock", id, playerAngle[i] + PI);
168 var landAreas = [];
169 var playerConstraint = new AvoidTileClassConstraint(clPlayer, floor(scaleByMapSize(12,16)));
170 var landConstraint = new AvoidTileClassConstraint(clLand, floor(scaleByMapSize(12,16)));
172 for (var x = 0; x < mapSize; ++x)
173         for (var z = 0; z < mapSize; ++z)
174                 if (playerConstraint.allows(x, z) && landConstraint.allows(x, z))
175                         landAreas.push([x, z]);
177 var chosenPoint;
178 var landAreaLen;
180 log("Creating big islands...");
181 var numIslands = scaleByMapSize(4, 14);
182 for (var i = 0; i < numIslands; ++i)
184         landAreaLen = landAreas.length;
185         if (!landAreaLen)
186                 break;
188         chosenPoint = pickRandom(landAreas);
190         // create big islands
191         placer = new ChainPlacer(floor(scaleByMapSize(4, 8)), floor(scaleByMapSize(8, 14)), floor(scaleByMapSize(25, 60)), 0.07, chosenPoint[0], chosenPoint[1], scaleByMapSize(30,70));
192         //placer = new ClumpPlacer(floor(hillSize*randFloat(0.9,2.1)), 0.80, 0.1, 0.07, chosenPoint[0], chosenPoint[1]);
193         terrainPainter = new LayeredPainter(
194                 [tMainTerrain, tMainTerrain],           // terrains
195                 [2]                                                             // widths
196         );
197         elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3, 6);
198         var newIsland = createAreas(
199                 placer,
200                 [terrainPainter, elevationPainter, paintClass(clLand)],
201                 avoidClasses(clLand, 3, clPlayer, 3),
202                 1, 1
203         );
204         if (newIsland && newIsland.length)
205         {
206                 var n = 0;
207                 for (var j = 0; j < landAreaLen; ++j)
208                 {
209                         var x = landAreas[j][0], z = landAreas[j][1];
210                         if (playerConstraint.allows(x, z) && landConstraint.allows(x, z))
211                                 landAreas[n++] = landAreas[j];
212                 }
213                 landAreas.length = n;
214         }
217 playerConstraint = new AvoidTileClassConstraint(clPlayer, floor(scaleByMapSize(9,12)));
218 landConstraint = new AvoidTileClassConstraint(clLand, floor(scaleByMapSize(9,12)));
220 log("Creating small islands...");
221 numIslands = scaleByMapSize(6, 18) * scaleByMapSize(1,3);
222 for (var i = 0; i < numIslands; ++i)
224         landAreaLen = landAreas.length;
225         if (!landAreaLen)
226                 break;
228         chosenPoint = pickRandom(landAreas);
230         placer = new ChainPlacer(floor(scaleByMapSize(4, 7)), floor(scaleByMapSize(7, 10)), floor(scaleByMapSize(16, 40)), 0.07, chosenPoint[0], chosenPoint[1], scaleByMapSize(22,40));
231         terrainPainter = new LayeredPainter(
232                 [tMainTerrain, tMainTerrain],           // terrains
233                 [2]                                                             // widths
234         );
235         elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3, 6);
236         createAreas(
237                 placer,
238                 [terrainPainter, elevationPainter, paintClass(clLand)],
239                 avoidClasses(clLand, 3, clPlayer, 3),
240                 1, 1
241         );
242         if (newIsland !== undefined)
243         {
244                 var temp = [];
245                 for (var j = 0; j < landAreaLen; ++j)
246                 {
247                         var x = landAreas[j][0], z = landAreas[j][1];
248                         if (playerConstraint.allows(x, z) && landConstraint.allows(x, z))
249                                         temp.push([x, z]);
250                 }
251                 landAreas = temp;
252         }
254 paintTerrainBasedOnHeight(1, 3, 0, tShore);
255 paintTerrainBasedOnHeight(-8, 1, 2, tWater);
257 for (var i = 0; i < numPlayers; i++)
259         var fx = fractionToTiles(playerX[i]);
260         var fz = fractionToTiles(playerZ[i]);
261         var ix = round(fx);
262         var iz = round(fz);
263         // create the city patch
264         var cityRadius = radius/3;
265         placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
266         var painter = new LayeredPainter([tRoadWild, tRoad], [1]);
267         createArea(placer, painter, null);
270 log("Creating bumps...");
271 placer = new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1);
272 painter = new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2);
273 createAreas(
274         placer,
275         painter,
276         [avoidClasses(clPlayer, 0), stayClasses(clLand, 3)],
277         scaleByMapSize(20, 100)
280 log("Creating hills...");
281 placer = new ChainPlacer(1, floor(scaleByMapSize(4, 6)), floor(scaleByMapSize(16, 40)), 0.5);
282 terrainPainter = new LayeredPainter(
283         [tCliff, tHill],                // terrains
284         [2]                                                             // widths
286 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 18, 2);
287 createAreas(
288         placer,
289         [terrainPainter, elevationPainter, paintClass(clHill)],
290         [avoidClasses(clPlayer, 2, clHill, 15), stayClasses(clLand, 0)],
291         scaleByMapSize(4, 13)
294 // calculate desired number of trees for map (based on size)
295 if (currentBiome() == "savanna")
297         var MIN_TREES = 200;
298         var MAX_TREES = 1250;
299         var P_FOREST = 0;
301 else if (currentBiome() == "tropic")
303         var MIN_TREES = 1000;
304         var MAX_TREES = 6000;
305         var P_FOREST = 0.52;
307 else
309         var MIN_TREES = 500;
310         var MAX_TREES = 3000;
311         var P_FOREST = 0.7;
313 var totalTrees = scaleByMapSize(MIN_TREES, MAX_TREES);
314 var numForest = totalTrees * P_FOREST;
315 var numStragglers = totalTrees * (1.0 - P_FOREST);
317 log("Creating forests...");
318 var types = [
319         [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]],
320         [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]]
321 ];      // some variation
323 if (currentBiome() != "savanna")
325         var size = numForest / (scaleByMapSize(3,6) * numPlayers);
326         var num = floor(size / types.length);
327         for (var i = 0; i < types.length; ++i)
328         {
329                 placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), numForest / (num * floor(scaleByMapSize(2,5))), 0.5);
330                 painter = new LayeredPainter(
331                         types[i],               // terrains
332                         [2]                                                                                     // widths
333                         );
334                 createAreas(
335                         placer,
336                         [painter, paintClass(clForest)],
337                         [avoidClasses(clPlayer, 0, clForest, 10, clHill, 0), stayClasses(clLand, 6)],
338                         num
339                 );
340         }
343 RMS.SetProgress(50);
344 log("Creating dirt patches...");
345 var sizes = [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)];
346 var numb = 1;
347 if (currentBiome() == "savanna")
348         numb = 3;
349 for (var i = 0; i < sizes.length; i++)
351         placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), sizes[i], 0.5);
352         painter = new LayeredPainter(
353                 [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],            // terrains
354                 [1,1]                                                                                                                   // widths
355         );
356         createAreas(
357                 placer,
358                 [painter, paintClass(clDirt)],
359                 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 6)],
360                 numb*scaleByMapSize(15, 45)
361         );
364 log("Creating grass patches...");
365 var sizes = [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)];
366 for (var i = 0; i < sizes.length; i++)
368         placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), sizes[i], 0.5);
369         painter = new TerrainPainter(tTier4Terrain);
370         createAreas(
371                 placer,
372                 painter,
373                 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 6)],
374                 numb*scaleByMapSize(15, 45)
375         );
377 RMS.SetProgress(55);
379 log("Creating stone mines...");
380 group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock);
381 createObjectGroupsDeprecated(group, 0,
382         [avoidClasses(clForest, 1, clPlayer, 0, clRock, 10, clHill, 1), stayClasses(clLand, 5)],
383         scaleByMapSize(4,16), 100
386 log("Creating small stone quarries...");
387 group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock);
388 createObjectGroupsDeprecated(group, 0,
389         [avoidClasses(clForest, 1, clPlayer, 0, clRock, 10, clHill, 1), stayClasses(clLand, 5)],
390         scaleByMapSize(4,16), 100
393 log("Creating metal mines...");
394 group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal);
395 createObjectGroupsDeprecated(group, 0,
396         [avoidClasses(clForest, 1, clPlayer, 0, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 5)],
397         scaleByMapSize(4,16), 100
400 RMS.SetProgress(65);
402 log("Creating small decorative rocks...");
403 group = new SimpleGroup(
404         [new SimpleObject(aRockMedium, 1,3, 0,1)],
405         true
407 createObjectGroupsDeprecated(
408         group, 0,
409         [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)],
410         scaleByMapSize(16, 262), 50
413 log("Creating large decorative rocks...");
414 group = new SimpleGroup(
415         [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
416         true
418 createObjectGroupsDeprecated(
419         group, 0,
420         [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)],
421         scaleByMapSize(8, 131), 50
424 RMS.SetProgress(70);
426 log("Creating deer...");
427 group = new SimpleGroup(
428         [new SimpleObject(oMainHuntableAnimal, 5,7, 0,4)],
429         true, clFood
431 createObjectGroupsDeprecated(group, 0,
432         [avoidClasses(clForest, 0, clPlayer, 0, clHill, 1, clFood, 20), stayClasses(clLand, 5)],
433         3 * numPlayers, 50
436 RMS.SetProgress(75);
438 log("Creating sheep...");
439 group = new SimpleGroup(
440         [new SimpleObject(oSecondaryHuntableAnimal, 2,3, 0,2)],
441         true, clFood
443 createObjectGroupsDeprecated(group, 0,
444         [avoidClasses(clForest, 0, clPlayer, 0, clHill, 1, clFood, 20), stayClasses(clLand, 5)],
445         3 * numPlayers, 50
448 log("Creating fruit bush...");
449 group = new SimpleGroup(
450         [new SimpleObject(oFruitBush, 5,7, 0,4)],
451         true, clFood
453 createObjectGroupsDeprecated(group, 0,
454         [avoidClasses(clForest, 0, clPlayer, 8, clHill, 1, clFood, 20), stayClasses(clLand, 5)],
455         randIntInclusive(1, 4) * numPlayers + 2, 50
458 log("Creating fish...");
459 group = new SimpleGroup(
460         [new SimpleObject(oFish, 2,3, 0,2)],
461         true, clFood
463 createObjectGroupsDeprecated(group, 0,
464         avoidClasses(clLand, 4, clForest, 2, clPlayer, 2, clHill, 2, clFood, 20),
465         25 * numPlayers, 60
468 RMS.SetProgress(85);
470 log("Creating straggler trees...");
471 var types = [oTree1, oTree2, oTree4, oTree3];   // some variation
472 var num = floor(numStragglers / types.length);
473 for (var i = 0; i < types.length; ++i)
475         group = new SimpleGroup(
476                 [new SimpleObject(types[i], 1,1, 0,3)],
477                 true, clForest
478         );
479         createObjectGroupsDeprecated(group, 0,
480                 [avoidClasses(clForest, 1, clHill, 1, clPlayer, 0, clMetal, 6, clRock, 6), stayClasses(clLand, 6)],
481                 num
482         );
485 var planetm = 1;
486 if (currentBiome() == "tropic")
487         planetm = 8;
489 log("Creating small grass tufts...");
490 group = new SimpleGroup(
491         [new SimpleObject(aGrassShort, 1,2, 0,1, -PI/8,PI/8)]
493 createObjectGroupsDeprecated(group, 0,
494         [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 6)],
495         planetm * scaleByMapSize(13, 200)
498 RMS.SetProgress(90);
500 log("Creating large grass tufts...");
501 group = new SimpleGroup(
502         [new SimpleObject(aGrass, 2,4, 0,1.8, -PI/8,PI/8), new SimpleObject(aGrassShort, 3,6, 1.2,2.5, -PI/8,PI/8)]
504 createObjectGroupsDeprecated(group, 0,
505         [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 5)],
506         planetm * scaleByMapSize(13, 200)
509 RMS.SetProgress(95);
511 log("Creating bushes...");
512 group = new SimpleGroup(
513         [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)]
515 createObjectGroupsDeprecated(group, 0,
516         [avoidClasses(clHill, 1, clPlayer, 1, clDirt, 1), stayClasses(clLand, 6)],
517         planetm * scaleByMapSize(13, 200), 50
520 setSkySet(pickRandom(["cirrus", "cumulus", "sunny"]));
521 setSunRotation(randFloat(0, TWO_PI));
522 setSunElevation(randFloat(PI/ 5, PI / 3));
523 setWaterWaviness(2);
525 ExportMap();