Unify 5 copies of the tributary river placement code, refs #4805.
[0ad.git] / binaries / data / mods / public / maps / random / unknown_land.js
blob515d801e3a4798644210edf9478611e8334060a1
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 clWater = createTileClass();
60 var clDirt = createTileClass();
61 var clRock = createTileClass();
62 var clMetal = createTileClass();
63 var clFood = createTileClass();
64 var clBaseResource = createTileClass();
65 var clSettlement = createTileClass();
66 var clLand = createTileClass();
67 var clShallow = createTileClass();
69 initTerrain(tWater);
71 var md = randIntInclusive(2,13);
72 var needsAdditionalWood = false;
73 //*****************************************************************************************************************************
74 if (md == 2) //continent
76         var [playerIDs, playerX, playerZ, playerAngle] = radialPlayerPlacement(0.25);
78         for (var i = 0; i < numPlayers; i++)
79         {
80                 var fx = fractionToTiles(playerX[i]);
81                 var fz = fractionToTiles(playerZ[i]);
82                 var ix = round(fx);
83                 var iz = round(fz);
85                 addCivicCenterAreaToClass(ix, iz, clPlayer);
87                 var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 9)), floor(scaleByMapSize(5, 20)), 1, ix, iz, 0, [floor(scaleByMapSize(23, 50))]);
88                 var elevationPainter = new SmoothElevationPainter(
89                         ELEVATION_SET,                  // type
90                         3,                              // elevation
91                         4                               // blend radius
92                 );
93                 createArea(placer, [elevationPainter, paintClass(clLand)], null);
94         }
96         var fx = fractionToTiles(0.5);
97         var fz = fractionToTiles(0.5);
98         ix = round(fx);
99         iz = round(fz);
101         var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 12)), floor(scaleByMapSize(60, 700)), 1, ix, iz, 0, [floor(mapSize * 0.33)]);
102         var terrainPainter = new LayeredPainter(
103                 [tWater, tShore, tMainTerrain],         // terrains
104                 [4, 2]          // widths
105         );
106         var elevationPainter = new SmoothElevationPainter(
107                 ELEVATION_SET,                  // type
108                 3,                              // elevation
109                 4                               // blend radius
110         );
111         createArea(placer, [terrainPainter, elevationPainter, paintClass(clLand)], null);
113         var clPeninsulaSteam = createTileClass();
115         if (randBool(1/3)) // peninsula
116         {
117                 var angle = randFloat(0, TWO_PI);
119                 var fx = fractionToTiles(0.5 + 0.25*cos(angle));
120                 var fz = fractionToTiles(0.5 + 0.25*sin(angle));
121                 ix = round(fx);
122                 iz = round(fz);
124                 var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 12)), floor(scaleByMapSize(60, 700)), 1, ix, iz, 0, [floor(mapSize * 0.33)]);
125                 var terrainPainter = new LayeredPainter(
126                         [tWater, tShore, tMainTerrain],         // terrains
127                         [4, 2]          // widths
128                 );
129                 var elevationPainter = new SmoothElevationPainter(
130                         ELEVATION_SET,                  // type
131                         3,                              // elevation
132                         4                               // blend radius
133                 );
134                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clLand)], null);
136                 var fx = fractionToTiles(0.5 + 0.35*cos(angle));
137                 var fz = fractionToTiles(0.5 + 0.35*sin(angle));
138                 ix = round(fx);
139                 iz = round(fz);
141                 var placer = new ClumpPlacer(mapArea * 0.3, 0.9, 0.01, 10, ix, iz);
142                 createArea(placer, [paintClass(clPeninsulaSteam)], null);
143         }
145 //********************************************************************************************************
146 else if (md == 3) //central sea
148         var playerIDs = primeSortAllPlayers();
149         var playerPos = placePlayersRiver();
150         var playerX = [];
151         var playerZ = [];
152         var playerAngle = [];
154         var mdd1 = randIntInclusive(1,2);
155         if (mdd1 == 1) //vertical
156                 for (var i = 0; i < numPlayers; i++)
157                 {
158                         playerZ[i] = playerPos[i];
159                         playerX[i] = 0.2 + 0.6*(i%2);
160                 }
161         else //horizontal
162                 for (var i = 0; i < numPlayers; i++)
163                 {
164                         playerZ[i] = 0.2 + 0.6*(i%2);
165                         playerX[i] = playerPos[i];
166                 }
168         paintRiver({
169                 "horizontal": mdd1 != 1,
170                 "parallel": false,
171                 "position": 0.5,
172                 "width": randFloat(0.22, 0.3) + scaleByMapSize(1, 4) / 20,
173                 "fadeDist": 0.025,
174                 "deviation": 0,
175                 "waterHeight": -3,
176                 "landHeight": 3,
177                 "meanderShort": 20,
178                 "meanderLong": 0,
179                 "waterFunc": (ix, iz, height) => {
180                         placeTerrain(ix, iz, height < -1.5 ? tWater : tShore);
181                         if (height < 0)
182                                 addToClass(ix, iz, clWater);
183                 },
184                 "landFunc": (ix, iz, shoreDist1, shoreDist2) => {
185                         setHeight(ix, iz, 3.1);
186                         addToClass(ix, iz, clLand);
187                 }
188         });
190         // linked
191         if (mdd1 == 1) //vertical
192         {
193                 var placer = new PathPlacer(1, fractionToTiles(0.5), fractionToTiles(0.99), fractionToTiles(0.5), scaleByMapSize(randIntInclusive(16,24),randIntInclusive(100,140)), 0.5, 3*(scaleByMapSize(1,4)), 0.1, 0.01);
194         }
195         else
196         {
197                 var placer = new PathPlacer(fractionToTiles(0.5), 1, fractionToTiles(0.5), fractionToTiles(0.99), scaleByMapSize(randIntInclusive(16,24),randIntInclusive(100,140)), 0.5, 3*(scaleByMapSize(1,4)), 0.1, 0.01);
198         }
199         var terrainPainter = new LayeredPainter(
200                 [tMainTerrain, tMainTerrain, tMainTerrain],             // terrains
201                 [1, 3]                                                          // widths
202         );
203         var elevationPainter = new SmoothElevationPainter(
204                 ELEVATION_SET,                  // type
205                 3.1,                            // elevation
206                 4                               // blend radius
207         );
208         createArea(placer, [terrainPainter, elevationPainter, unPaintClass(clWater)], null);
210         var mdd2 = randIntInclusive(1,7);
211         if (mdd2 == 1)
212         {
213                 log("Creating islands...");
214                 placer = new ChainPlacer(floor(scaleByMapSize(4, 7)), floor(scaleByMapSize(7, 10)), floor(scaleByMapSize(16, 40)), 0.07);
215                 terrainPainter = new LayeredPainter(
216                         [tMainTerrain, tMainTerrain],           // terrains
217                         [2]                                                             // widths
218                 );
219                 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3.1, 4);
220                 createAreas(
221                         placer,
222                         [terrainPainter, elevationPainter, paintClass(clLand)],
223                         avoidClasses(clLand, 3, clPlayer, 3),
224                         scaleByMapSize(2, 5)*randIntInclusive(8,14)
225                 );
226         }
227         else if (mdd2 == 2)
228         {
229                 log("Creating extentions...");
230                 placer = new ClumpPlacer(randIntInclusive(scaleByMapSize(13,24),scaleByMapSize(24,45))*randIntInclusive(scaleByMapSize(13,24),scaleByMapSize(24,45)), 0.80, 0.1, 10);
231                 terrainPainter = new LayeredPainter(
232                         [tMainTerrain, tMainTerrain],           // terrains
233                         [2]                                                             // widths
234                 );
235                 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3.1, 4);
236                 createAreas(
237                         placer,
238                         [terrainPainter, elevationPainter, paintClass(clLand)],
239                         null,
240                         scaleByMapSize(2, 5)*randIntInclusive(8,14)
241                 );
242         }
244 //********************************************************************************************************
245 else if (md == 4) //central river
248         for (var ix = 0; ix < mapSize; ix++)
249         {
250                 for (var iz = 0; iz < mapSize; iz++)
251                 {
252                         var x = ix / (mapSize + 1.0);
253                         var z = iz / (mapSize + 1.0);
254                                 setHeight(ix, iz, 3);
255                 }
256         }
258         var playerIDs = primeSortAllPlayers();
259         var playerPos = placePlayersRiver();
261         var playerX = [];
262         var playerZ = [];
263         var playerAngle = [];
265         var mdd1 = randIntInclusive(1,2);
266         if (mdd1 == 1) //horizontal
267                 for (var i = 0; i < numPlayers; i++)
268                 {
269                         playerZ[i] = 0.25 + 0.5*(i%2);
270                         playerX[i] = playerPos[i];
271                 }
272         else //vertical
273                 for (var i = 0; i < numPlayers; i++)
274                 {
275                         playerZ[i] = playerPos[i];
276                         playerX[i] = 0.25 + 0.5*(i%2);
277                 }
279         log("Creating the main river");
281         if (mdd1 == 2)
282                 var placer = new PathPlacer(fractionToTiles(0.5), 1, fractionToTiles(0.5) , fractionToTiles(0.99), scaleByMapSize(14,24), 0.5, 3*(scaleByMapSize(1,4)), 0.1, 0.01);
283         else
284                 var placer = new PathPlacer(1, fractionToTiles(0.5), fractionToTiles(0.99), fractionToTiles(0.5), scaleByMapSize(14,24), 0.5, 3*(scaleByMapSize(1,4)), 0.1, 0.01);
286         var terrainPainter = new LayeredPainter(
287                 [tShore, tWater, tWater],               // terrains
288                 [1, 3]                                                          // widths
289         );
290         var elevationPainter = new SmoothElevationPainter(
291                 ELEVATION_SET,                  // type
292                 -4,                             // elevation
293                 4                               // blend radius
294         );
295         createArea(placer, [terrainPainter, elevationPainter], avoidClasses(clPlayer, 4));
297         if (mdd1 == 1)
298                 placer = new ClumpPlacer(floor(PI*scaleByMapSize(10,20)*scaleByMapSize(10,20)/4), 0.95, 0.6, 10, 1, fractionToTiles(0.5));
299         else
300                 placer = new ClumpPlacer(floor(PI*scaleByMapSize(10,20)*scaleByMapSize(10,20)/4), 0.95, 0.6, 10, fractionToTiles(0.5), 1);
302         var painter = new LayeredPainter([tWater, tWater], [1]);
303         var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -4, 2);
304         createArea(placer, [painter, elevationPainter], avoidClasses(clPlayer, 8));
306         if (mdd1 == 1)
307                 placer = new ClumpPlacer(floor(PI*scaleByMapSize(10,20)*scaleByMapSize(10,20)/4), 0.95, 0.6, 10, fractionToTiles(0.99), fractionToTiles(0.5));
308         else
309                 placer = new ClumpPlacer(floor(PI*scaleByMapSize(10,20)*scaleByMapSize(10,20)/4), 0.95, 0.6, 10, fractionToTiles(0.5), fractionToTiles(0.99));
311         var painter = new LayeredPainter([tWater, tWater], [1]);
312         var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -4, 2);
313         createArea(placer, [painter, elevationPainter], avoidClasses(clPlayer, 8));
315         log("Creating the shallows of the main river");
317         for (var i = 0; i <= randIntInclusive(1, scaleByMapSize(4,8)); i++)
318         {
319                 var cLocation = randFloat(0.15,0.85);
320                 if (mdd1 == 1)
321                         createShallowsPassage(floor(fractionToTiles(cLocation)), floor(fractionToTiles(0.35)), floor(fractionToTiles(cLocation)), floor(fractionToTiles(0.65)), scaleByMapSize(4,8), -2, -2, 2, clShallow, undefined, -4);
322                 else
323                         createShallowsPassage(floor(fractionToTiles(0.35)), floor(fractionToTiles(cLocation)), floor(fractionToTiles(0.65)), floor(fractionToTiles(cLocation)), scaleByMapSize(4,8), -2, -2, 2, clShallow, undefined, -4);
324         }
326         if (randBool())
327         {
328                 for (var i = 0; i < numPlayers; i++)
329                 {
330                         var fx = fractionToTiles(playerX[i]);
331                         var fz = fractionToTiles(playerZ[i]);
332                         var ix = round(fx);
333                         var iz = round(fz);
334                         // create the city patch
335                         var cityRadius = scaleByMapSize(17,29)/3;
336                         placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
337                         createArea(placer, paintClass(clPlayer), null);
338                 }
340                 createTributaryRivers(
341                         mdd1 == 1,
342                         randIntInclusive(8, scaleByMapSize(12, 16)),
343                         scaleByMapSize(10, 20),
344                         -4,
345                         [-6, -1.5],
346                         0.2 * Math.PI,
347                         clWater,
348                         clShallow,
349                         avoidClasses(clPlayer, 3));
350         }
352 //********************************************************************************************************
353 else if (md == 5) //rivers and lake
355         var [playerIDs, playerX, playerZ] = radialPlayerPlacement();
357         for (var i = 0; i < numPlayers; i++)
358         {
359                 var fx = fractionToTiles(playerX[i]);
360                 var fz = fractionToTiles(playerZ[i]);
361                 var ix = round(fx);
362                 var iz = round(fz);
364                 addCivicCenterAreaToClass(ix, iz, clPlayer);
365         }
367         for (var ix = 0; ix < mapSize; ix++)
368         {
369                 for (var iz = 0; iz < mapSize; iz++)
370                 {
371                         var x = ix / (mapSize + 1.0);
372                         var z = iz / (mapSize + 1.0);
373                                 setHeight(ix, iz, 3);
374                 }
375         }
376         var mdd1 = randIntInclusive(1,2);
377         if (mdd1 == 1) //lake
378         {
379                 var fx = fractionToTiles(0.5);
380                 var fz = fractionToTiles(0.5);
381                 ix = round(fx);
382                 iz = round(fz);
384                 var lSize = sqrt(sqrt(sqrt(scaleByMapSize(1, 6))));
386                 var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 16)), floor(scaleByMapSize(35, 200)), 1, ix, iz, 0, [floor(mapSize * 0.17 * lSize)]);
387                 var terrainPainter = new LayeredPainter(
388                         [tShore, tWater, tWater, tWater],               // terrains
389                         [1, 4, 2]               // widths
390                 );
391                 var elevationPainter = new SmoothElevationPainter(
392                         ELEVATION_SET,                  // type
393                         -4,                             // elevation
394                         4                               // blend radius
395                 );
396                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null);
398                 log("Creating shore jaggedness...");
399                 placer = new ChainPlacer(2, floor(scaleByMapSize(4, 6)), 3, 1);
400                 terrainPainter = new LayeredPainter(
401                         [tCliff, tHill],                // terrains
402                         [2]                                                             // widths
403                 );
404                 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3, 4);
405                 createAreas(
406                         placer,
407                         [terrainPainter, elevationPainter, unPaintClass(clWater)],
408                         borderClasses(clWater, 4, 7),
409                         scaleByMapSize(12, 130) * 2, 150
410                 );
411         }
413         if (randBool(1/3) &&(mdd1 == 1))//island
414         {
415                 var placer = new ClumpPlacer(mapArea * 0.006 * lSize, 0.7, 0.1, 10, ix, iz);
416                 var terrainPainter = new LayeredPainter(
417                         [tShore, tWater, tWater, tWater],               // terrains
418                         [1, 4, 2]               // widths
419                 );
420                 var elevationPainter = new SmoothElevationPainter(
421                         ELEVATION_SET,                  // type
422                         3,                              // elevation
423                         4                               // blend radius
424                 );
425                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null);
426         }
428 //********************************************************************************************************
429 else if (md == 6) //edge seas
432         for (var ix = 0; ix < mapSize; ix++)
433         {
434                 for (var iz = 0; iz < mapSize; iz++)
435                 {
436                         var x = ix / (mapSize + 1.0);
437                         var z = iz / (mapSize + 1.0);
438                                 setHeight(ix, iz, 3);
439                 }
440         }
442         var mdd1 = randIntInclusive(1,2);
444         var playerIDs = sortAllPlayers();
446         // place players
447         var playerX = [];
448         var playerZ = [];
449         var playerPos = [];
451         for (var i = 0; i < numPlayers; i++)
452         {
453                 playerPos[i] = (i + 1) / (numPlayers + 1);
454                 if (mdd1 == 1) //horizontal
455                 {
456                         playerX[i] = playerPos[i];
457                         playerZ[i] = 0.4 + 0.2*(i%2);
458                 }
459                 else //vertical
460                 {
461                         playerX[i] = 0.4 + 0.2*(i%2);
462                         playerZ[i] = playerPos[i];
463                 }
465                 var fx = fractionToTiles(playerX[i]);
466                 var fz = fractionToTiles(playerZ[i]);
467                 var ix = round(fx);
468                 var iz = round(fz);
470                 addCivicCenterAreaToClass(ix, iz, clPlayer);
471         }
473         var mdd2 = randIntInclusive(1,3);
474         var fadedistance = 7;
476         if (mdd1 == 1)
477         {
478                 if ((mdd2 == 1)||(mdd2 == 3))
479                 {
480                         var distance = randFloat(0., 0.1);
481                         for (var ix = 0; ix < mapSize; ix++)
482                         {
483                                 for (var iz = 0; iz < mapSize; iz++)
484                                 {
485                                         if (iz > (0.69+distance) * mapSize)
486                                         {
487                                                 if (iz < (0.69+distance) * mapSize + fadedistance)
488                                                 {
489                                                         setHeight(ix, iz, 3 - 7 * (iz - (0.69+distance) * mapSize) / fadedistance);
490                                                         if (3 - 7 * (iz - (0.69+distance) * mapSize) / fadedistance < 0.5)
491                                                                 addToClass(ix, iz, clWater);
492                                                 }
493                                                 else
494                                                 {
495                                                         setHeight(ix, iz, -4);
496                                                         addToClass(ix, iz, clWater);
497                                                 }
498                                         }
499                                 }
501                         }
502                 }
503                 if ((mdd2 == 2)||(mdd2 == 3))
504                 {
505                         var distance = randFloat(0., 0.1);
506                         for (var ix = 0; ix < mapSize; ix++)
507                         {
508                                 for (var iz = 0; iz < mapSize; iz++)
509                                 {
510                                         if (iz < (0.31-distance) * mapSize)
511                                         {
512                                                 if (iz > (0.31-distance) * mapSize - fadedistance)
513                                                 {
514                                                         setHeight(ix, iz, 3 - 7 * ((0.31-distance) * mapSize - iz) / fadedistance);
515                                                         if (3 - 7 * ((0.31-distance) * mapSize - iz) / fadedistance < 0.5)
516                                                                 addToClass(ix, iz, clWater);
517                                                 }
518                                                 else
519                                                 {
520                                                         setHeight(ix, iz, -4);
521                                                         addToClass(ix, iz, clWater);
522                                                 }
523                                         }
524                                 }
525                         }
526                 }
527         }
528         else //vertical
529         {
530                 if ((mdd2 == 1)||(mdd2 == 3))
531                 {
532                         var distance = randFloat(0., 0.1);
533                         for (var ix = 0; ix < mapSize; ix++)
534                         {
535                                 for (var iz = 0; iz < mapSize; iz++)
536                                 {
537                                         if (ix > (0.69+distance) * mapSize)
538                                         {
539                                                 if (ix < (0.69+distance) * mapSize + fadedistance)
540                                                 {
541                                                         setHeight(ix, iz, 3 - 7 * (ix - (0.69+distance) * mapSize) / fadedistance);
542                                                         if (3 - 7 * (ix - (0.69+distance) * mapSize) / fadedistance < 0.5)
543                                                                 addToClass(ix, iz, clWater);
544                                                 }
545                                                 else
546                                                 {
547                                                         setHeight(ix, iz, -4);
548                                                         addToClass(ix, iz, clWater);
549                                                 }
550                                         }
551                                 }
552                         }
553                 }
554                 if ((mdd2 == 2)||(mdd2 == 3))
555                 {
556                         var distance = randFloat(0., 0.1);
557                         for (var ix = 0; ix < mapSize; ix++)
558                         {
559                                 for (var iz = 0; iz < mapSize; iz++)
560                                 {
561                                         if (ix < (0.31-distance) * mapSize)
562                                         {
563                                                 if (ix > (0.31-distance) * mapSize - fadedistance)
564                                                 {
565                                                         setHeight(ix, iz, 3 - 7 * ((0.31-distance) * mapSize - ix) / fadedistance);
566                                                         if (3 - 7 * ((0.31-distance) * mapSize - ix) / fadedistance < 0.5)
567                                                                 addToClass(ix, iz, clWater);
568                                                 }
569                                                 else
570                                                 {
571                                                         setHeight(ix, iz, -4);
572                                                         addToClass(ix, iz, clWater);
573                                                 }
574                                         }
575                                 }
576                         }
577                 }
578         }
580         log("Creating shore jaggedness...");
581         placer = new ChainPlacer(2, floor(scaleByMapSize(4, 6)), 3, 1);
582         terrainPainter = new LayeredPainter(
583                 [tCliff, tHill],                // terrains
584                 [2]                                                             // widths
585         );
586         elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -5, 4);
587         createAreas(
588                 placer,
589                 [terrainPainter, elevationPainter, paintClass(clWater)],
590                 [avoidClasses(clPlayer, 20), borderClasses(clWater, 6, 4)],
591                 scaleByMapSize(7, 130) * 2, 150
592         );
594         placer = new ChainPlacer(2, floor(scaleByMapSize(4, 6)), 3, 1);
595         terrainPainter = new LayeredPainter(
596                 [tCliff, tHill],                // terrains
597                 [2]                                                             // widths
598         );
599         elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3, 4);
600         createAreas(
601                 placer,
602                 [terrainPainter, elevationPainter, unPaintClass(clWater)],
603                 borderClasses(clWater, 4, 7),
604                 scaleByMapSize(12, 130) * 2, 150
605         );
607         var mdd3 = randIntInclusive(1,5);
608         if (mdd3 == 1)
609         {
610                 log("Creating islands...");
611                 placer = new ChainPlacer(floor(scaleByMapSize(4, 7)), floor(scaleByMapSize(7, 10)), floor(scaleByMapSize(16, 40)), 0.07);
612                 terrainPainter = new LayeredPainter(
613                         [tMainTerrain, tMainTerrain],           // terrains
614                         [2]                                                             // widths
615                 );
616                 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3.1, 4);
617                 createAreas(
618                         placer,
619                         [terrainPainter, elevationPainter, paintClass(clLand)],
620                         avoidClasses(clLand, 3, clPlayer, 3),
621                         scaleByMapSize(2, 5)*randIntInclusive(8,14)
622                 );
623         }
624         else if (mdd3 == 2)
625         {
626                 log("Creating extentions...");
627                 placer = new ChainPlacer(floor(scaleByMapSize(4, 7)), floor(scaleByMapSize(7, 10)), floor(scaleByMapSize(16, 40)), 0.07);
628                 terrainPainter = new LayeredPainter(
629                         [tMainTerrain, tMainTerrain],           // terrains
630                         [2]                                                             // widths
631                 );
632                 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3.1, 4);
633                 createAreas(
634                         placer,
635                         [terrainPainter, elevationPainter, paintClass(clLand)],
636                         null,
637                         scaleByMapSize(2, 5)*randIntInclusive(8,14)
638                 );
639         }
641 //********************************************************************************************************
642 else if (md == 7) //gulf
644         for (var ix = 0; ix < mapSize; ix++)
645         {
646                 for (var iz = 0; iz < mapSize; iz++)
647                 {
648                         var x = ix / (mapSize + 1.0);
649                         var z = iz / (mapSize + 1.0);
650                                 setHeight(ix, iz, 3);
651                 }
652         }
654         var mdd1 = randFloat(0,4);
656         var playerIDs = sortAllPlayers();
658         // place players
659         var playerX = [];
660         var playerZ = [];
661         var playerAngle = [];
663         var startAngle = -PI/6 + (mdd1-1)*PI/2;
664         for (var i = 0; i < numPlayers; i++)
665         {
666                 playerAngle[i] = startAngle + Math.PI * 2/3 * (numPlayers == 1 ? 1 : 2 * i / (numPlayers - 1));
667                 playerX[i] = 0.5 + 0.35*cos(playerAngle[i]);
668                 playerZ[i] = 0.5 + 0.35*sin(playerAngle[i]);
669         }
671         for (var i = 0; i < numPlayers; i++)
672         {
673                 var fx = fractionToTiles(playerX[i]);
674                 var fz = fractionToTiles(playerZ[i]);
675                 var ix = round(fx);
676                 var iz = round(fz);
677                 // create the city patch
678                 var cityRadius = scaleByMapSize(17,29)/3;
679                 placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
680                 createArea(placer, paintClass(clPlayer), null);
681         }
683         fx = fractionToTiles(0.5);
684         fz = fractionToTiles(0.5);
685         ix = round(fx);
686         iz = round(fz);
688         var lSize = 1;
690         var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 16)), floor(scaleByMapSize(35, 200)), 1, ix, iz, 0, [floor(mapSize * 0.17 * lSize)]);
691         var terrainPainter = new LayeredPainter(
692                 [tMainTerrain, tMainTerrain, tMainTerrain, tMainTerrain],               // terrains
693                 [1, 4, 2]               // widths
694         );
696         var elevationPainter = new SmoothElevationPainter(
697                 ELEVATION_SET,                  // type
698                 -3,                             // elevation
699                 4                               // blend radius
700         );
701         createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], avoidClasses(clPlayer,floor(scaleByMapSize(15,25))));
703         fx = fractionToTiles(0.5 - 0.2*cos(mdd1*PI/2));
704         fz = fractionToTiles(0.5 - 0.2*sin(mdd1*PI/2));
705         ix = round(fx);
706         iz = round(fz);
708         var lSize = sqrt(sqrt(sqrt(scaleByMapSize(1, 6))));
710         var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 16)), floor(scaleByMapSize(35, 120)), 1, ix, iz, 0, [floor(mapSize * 0.18 * lSize)]);
711         var terrainPainter = new LayeredPainter(
712                 [tMainTerrain, tMainTerrain, tMainTerrain, tMainTerrain],               // terrains
713                 [1, 4, 2]               // widths
714         );
715         var elevationPainter = new SmoothElevationPainter(
716                 ELEVATION_SET,                  // type
717                 -3,                             // elevation
718                 4                               // blend radius
719         );
720         createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], avoidClasses(clPlayer,floor(scaleByMapSize(15,25))));
722         fx = fractionToTiles(0.5 - 0.49*cos(mdd1*PI/2));
723         fz = fractionToTiles(0.5 - 0.49*sin(mdd1*PI/2));
724         ix = round(fx);
725         iz = round(fz);
727         var lSize = sqrt(sqrt(sqrt(scaleByMapSize(1, 6))));
729         var placer = new ChainPlacer(2, floor(scaleByMapSize(5, 16)), floor(scaleByMapSize(35, 100)), 1, ix, iz, 0, [floor(mapSize * 0.19 * lSize)]);
730         var terrainPainter = new LayeredPainter(
731                 [tMainTerrain, tMainTerrain, tMainTerrain, tMainTerrain],               // terrains
732                 [1, 4, 2]               // widths
733         );
734         var elevationPainter = new SmoothElevationPainter(
735                 ELEVATION_SET,                  // type
736                 -3,                             // elevation
737                 4                               // blend radius
738         );
739         createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], avoidClasses(clPlayer,floor(scaleByMapSize(15,25))));
741 //********************************************************************************************************
742 else if (md == 8) //lakes
744         var [playerIDs, playerX, playerZ, playerAngle] = radialPlayerPlacement();
746         for (var ix = 0; ix < mapSize; ix++)
747         {
748                 for (var iz = 0; iz < mapSize; iz++)
749                 {
750                         var x = ix / (mapSize + 1.0);
751                         var z = iz / (mapSize + 1.0);
752                                 setHeight(ix, iz, 3);
753                 }
754         }
756         for (var i = 0; i < numPlayers; i++)
757         {
758                 var fx = fractionToTiles(playerX[i]);
759                 var fz = fractionToTiles(playerZ[i]);
760                 var ix = round(fx);
761                 var iz = round(fz);
762                 // create the city patch
763                 var cityRadius = scaleByMapSize(17,29)/3;
764                 placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
765                 createArea(placer, paintClass(clPlayer), null);
766         }
768         var lakeAreas = [];
769         var playerConstraint = new AvoidTileClassConstraint(clPlayer, 20);
770         var waterConstraint = new AvoidTileClassConstraint(clWater, 8);
772         for (var x = 0; x < mapSize; ++x)
773                 for (var z = 0; z < mapSize; ++z)
774                         if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z))
775                                 lakeAreas.push([x, z]);
777         var chosenPoint;
778         var lakeAreaLen;
780         log("Creating lakes...");
781         var numLakes = scaleByMapSize(5, 16);
782         for (var i = 0; i < numLakes; ++i)
783         {
784                 lakeAreaLen = lakeAreas.length;
785                 if (!lakeAreaLen)
786                         break;
788                 chosenPoint = pickRandom(lakeAreas);
790                 placer = new ChainPlacer(1, floor(scaleByMapSize(4, 8)), floor(scaleByMapSize(40, 180)), 0.7, chosenPoint[0], chosenPoint[1]);
791                 terrainPainter = new LayeredPainter(
792                         [tShore, tWater, tWater],               // terrains
793                         [1, 3]                                                          // widths
794                 );
795                 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -5, 5);
796                 var newLake = createAreas(
797                         placer,
798                         [terrainPainter, elevationPainter, paintClass(clWater)],
799                         avoidClasses(clPlayer, 20, clWater, 8),
800                         1, 1
801                 );
803                 if (newLake && newLake.length)
804                 {
805                         var n = 0;
806                         for (var j = 0; j < lakeAreaLen; ++j)
807                         {
808                                 var x = lakeAreas[j][0], z = lakeAreas[j][1];
809                                 if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z))
810                                         lakeAreas[n++] = lakeAreas[j];
811                         }
812                         lakeAreas.length = n;
813                 }
814         }
816 //********************************************************************************************************
817 else if (md == 9) //passes
819         var [playerIDs, playerX, playerZ, playerAngle, startAngle] = radialPlayerPlacement();
821         for (var ix = 0; ix < mapSize; ix++)
822         {
823                 for (var iz = 0; iz < mapSize; iz++)
824                 {
825                         var x = ix / (mapSize + 1.0);
826                         var z = iz / (mapSize + 1.0);
827                                 setHeight(ix, iz, 3);
828                 }
829         }
831         log ("Creating ranges...");
832         for (var m = 0; m < numPlayers; m++)
833         {
834                 var tang = startAngle + (m+0.5)*TWO_PI/(numPlayers);
835                 var placer = new PathPlacer(fractionToTiles(0.5), fractionToTiles(0.5), fractionToTiles(0.5 + 0.49*cos(tang)), fractionToTiles(0.5 + 0.49*sin(tang)), scaleByMapSize(14,24), 0.4, 3*(scaleByMapSize(1,3)), 0.2, 0.05);
836                 var terrainPainter = new LayeredPainter(
837                         [tShore, tWater, tWater],               // terrains
838                         [1, 3]                                                          // widths
839                 );
840                 var elevationPainter = new SmoothElevationPainter(
841                         ELEVATION_SET,                  // type
842                         24,                             // elevation
843                         3                               // blend radius
844                 );
845                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], avoidClasses(clPlayer, 5));
846                 placer = new ClumpPlacer(floor(PI*scaleByMapSize(10,50)*scaleByMapSize(10,50)/5), 0.95, 0.6, 10, fractionToTiles(0.5 + 0.49*cos(tang)), fractionToTiles(0.5 + 0.49*sin(tang)));
847                 var painter = new LayeredPainter([tWater, tWater], [1]);
848                 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 24, 0);
849                 createArea(placer, [painter, elevationPainter], avoidClasses(clPlayer, 5));
851                 var placer = new PathPlacer(fractionToTiles(0.5 + 0.3*cos(tang) - 0.1 * cos(tang+PI/2)), fractionToTiles(0.5 + 0.3*sin(tang) - 0.1 * sin(tang+PI/2)), fractionToTiles(0.5 + 0.3*cos(tang) + 0.1 * cos(tang+PI/2)), fractionToTiles(0.5 + 0.3*sin(tang) + 0.1 * sin(tang+PI/2)), scaleByMapSize(14,24), 0.4, 3*(scaleByMapSize(1,3)), 0.2, 0.05);
852                 var painter = new LayeredPainter([tCliff, tCliff], [1]);
853                 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 3, 2);
854                 createArea(placer, [painter, elevationPainter], null);
855         }
856         var mdd1 = randIntInclusive (1,3);
857         if (mdd1 <= 2)
858         {
859                 var fx = fractionToTiles(0.5);
860                 var fz = fractionToTiles(0.5);
861                 ix = round(fx);
862                 iz = round(fz);
864                 var placer = new ClumpPlacer(mapArea * 0.005, 0.7, 0.1, 10, ix, iz);
865                 var terrainPainter = new LayeredPainter(
866                         [tShore, tWater, tWater, tWater],               // terrains
867                         [1, 4, 2]               // widths
868                 );
869                 var elevationPainter = new SmoothElevationPainter(
870                         ELEVATION_SET,                  // type
871                         24,                             // elevation
872                         4                               // blend radius
873                 );
874                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null);
875         }
876         else
877         {
878                 var fx = fractionToTiles(0.5);
879                 var fz = fractionToTiles(0.5);
880                 ix = round(fx);
881                 iz = round(fz);
883                 var lSize = sqrt(sqrt(sqrt(scaleByMapSize(1, 6))));
885                 var placer = new ClumpPlacer(mapArea * 0.03 * lSize, 0.7, 0.1, 10, ix, iz);
886                 var terrainPainter = new LayeredPainter(
887                         [tShore, tWater, tWater, tWater],               // terrains
888                         [1, 4, 2]               // widths
889                 );
890                 var elevationPainter = new SmoothElevationPainter(
891                         ELEVATION_SET,                  // type
892                         -4,                             // elevation
893                         3                               // blend radius
894                 );
895                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null);
896         }
898 //********************************************************************************************************
899 else if (md == 10) //lowlands
901         var [playerIDs, playerX, playerZ, playerAngle, startAngle] = radialPlayerPlacement();
903         for (var ix = 0; ix < mapSize; ix++)
904         {
905                 for (var iz = 0; iz < mapSize; iz++)
906                 {
907                         var x = ix / (mapSize + 1.0);
908                         var z = iz / (mapSize + 1.0);
909                                 setHeight(ix, iz, 30);
910                 }
911         }
913         var radius = scaleByMapSize(18,32);
914         var cliffRadius = 2;
915         var elevation = 20;
916         var hillSize = PI * radius * radius;
918         var split = 1;
919         if ((mapSize / 64 == 2)&&(numPlayers <= 2))
920         {
921                 split = 2;
922         }
923         else if ((mapSize / 64 == 3)&&(numPlayers <= 3))
924         {
925                 split = 2;
926         }
927         else if ((mapSize / 64 == 4)&&(numPlayers <= 4))
928         {
929                 split = 2;
930         }
931         else if ((mapSize / 64 == 5)&&(numPlayers <= 4))
932         {
933                 split = 2;
934         }
935         else if ((mapSize / 64 == 6)&&(numPlayers <= 5))
936         {
937                 split = 2;
938         }
939         else if ((mapSize / 64 == 7)&&(numPlayers <= 6))
940         {
941                 split = 2;
942         }
944         for (var i = 0; i < numPlayers*split; i++)
945         {
946                 var tang = startAngle + (i)*TWO_PI/(numPlayers*split);
947                 var fx = fractionToTiles(0.5 + 0.35*cos(tang));
948                 var fz = fractionToTiles(0.5 + 0.35*sin(tang));
949                 var ix = round(fx);
950                 var iz = round(fz);
951                 // create the hill
952                 var placer = new ClumpPlacer(hillSize, 0.65, 0.1, 10, ix, iz);
953                 var terrainPainter = new LayeredPainter(
954                         [tMainTerrain, tMainTerrain],           // terrains
955                         [cliffRadius]           // widths
956                 );
957                 var elevationPainter = new SmoothElevationPainter(
958                         ELEVATION_SET,                  // type
959                         3,                              // elevation
960                         cliffRadius                             // blend radius
961                 );
962                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clLand)], null);
963         }
965         var fx = fractionToTiles(0.5);
966         var fz = fractionToTiles(0.5);
967         ix = round(fx);
968         iz = round(fz);
970         var lSize = sqrt(sqrt(sqrt(scaleByMapSize(1, 6))));
972         var placer = new ClumpPlacer(mapArea * 0.091 * lSize, 0.7, 0.1, 10, ix, iz);
973         var terrainPainter = new LayeredPainter(
974                 [tMainTerrain, tMainTerrain, tMainTerrain, tMainTerrain],               // terrains
975                 [1, 4, 2]               // widths
976         );
977         var elevationPainter = new SmoothElevationPainter(
978                 ELEVATION_SET,                  // type
979                 3,                              // elevation
980                 4                               // blend radius
981         );
982         createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null);
984         for (var m = 0; m < numPlayers*split; m++)
985         {
986                 var tang = startAngle + m*TWO_PI/(numPlayers*split);
987                 var placer = new PathPlacer(fractionToTiles(0.5), fractionToTiles(0.5), fractionToTiles(0.5 + 0.35*cos(tang)), fractionToTiles(0.5 + 0.35*sin(tang)), scaleByMapSize(14,24), 0.4, 3*(scaleByMapSize(1,3)), 0.2, 0.05);
988                 var terrainPainter = new LayeredPainter(
989                         [tMainTerrain, tMainTerrain, tMainTerrain],             // terrains
990                         [1, 3]                                                          // widths
991                 );
992                 var elevationPainter = new SmoothElevationPainter(
993                         ELEVATION_SET,                  // type
994                         3,                              // elevation
995                         4                               // blend radius
996                 );
997                 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null);
998         }
1000 //********************************************************************************************************
1001 else //mainland
1003         var [playerIDs, playerX, playerZ, playerAngle] = radialPlayerPlacement();
1005         for (var ix = 0; ix < mapSize; ix++)
1006         {
1007                 for (var iz = 0; iz < mapSize; iz++)
1008                 {
1009                         var x = ix / (mapSize + 1.0);
1010                         var z = iz / (mapSize + 1.0);
1011                                 setHeight(ix, iz, 3);
1012                 }
1013         }
1017 paintTerrainBasedOnHeight(3.12, 40, 1, tCliff);
1018 paintTerrainBasedOnHeight(3, 3.12, 1, tMainTerrain);
1019 paintTerrainBasedOnHeight(1, 3, 1, tShore);
1020 paintTerrainBasedOnHeight(-8, 1, 2, tWater);
1021 unPaintTileClassBasedOnHeight(0, 3.12, 1, clWater);
1022 unPaintTileClassBasedOnHeight(-6, 0, 1, clLand);
1023 paintTileClassBasedOnHeight(-6, 0, 1, clWater);
1024 paintTileClassBasedOnHeight(0, 3.12, 1, clLand);
1025 paintTileClassBasedOnHeight(3.12, 40, 1, clHill);
1027 for (var i = 0; i < numPlayers; i++)
1029         var id = playerIDs[i];
1030         log("Creating base for player " + id + "...");
1032         var radius = scaleByMapSize(17,29);
1033         var shoreRadius = 4;
1034         var elevation = 3;
1036         var hillSize = PI * radius * radius;
1037         // get the x and z in tiles
1038         var fx = fractionToTiles(playerX[i]);
1039         var fz = fractionToTiles(playerZ[i]);
1040         var ix = round(fx);
1041         var iz = round(fz);
1043         placeCivDefaultEntities(fx, fz, id);
1044         placeDefaultChicken(fx, fz, clBaseResource);
1046         // create berry bushes
1047         var bbAngle = randFloat(0, TWO_PI);
1048         var bbDist = 12;
1049         var bbX = round(fx + bbDist * cos(bbAngle));
1050         var bbZ = round(fz + bbDist * sin(bbAngle));
1051         var group = new SimpleGroup(
1052                 [new SimpleObject(oFruitBush, 5,5, 0,3)],
1053                 true, clBaseResource, bbX, bbZ
1054         );
1055         createObjectGroup(group, 0);
1056         if (needsAdditionalWood)
1057         {
1058                 // create woods
1059                 var bbAngle = randFloat(0, TWO_PI);
1060                 var bbDist = 13;
1061                 var bbX = round(fx + bbDist * cos(bbAngle));
1062                 var bbZ = round(fz + bbDist * sin(bbAngle));
1063                 group = new SimpleGroup(
1064                         [new SimpleObject(oWood, 14,14, 0,3)],
1065                         true, clBaseResource, bbX, bbZ
1066                 );
1067                 createObjectGroup(group, 0);
1068         }
1070         // create metal mine
1071         var mAngle = bbAngle;
1072         while(abs(mAngle - bbAngle) < PI/3)
1073         {
1074                 mAngle = randFloat(0, TWO_PI);
1075         }
1076         var mDist = 12;
1077         var mX = round(fx + mDist * cos(mAngle));
1078         var mZ = round(fz + mDist * sin(mAngle));
1079         group = new SimpleGroup(
1080                 [new SimpleObject(oMetalLarge, 1,1, 0,0)],
1081                 true, clBaseResource, mX, mZ
1082         );
1083         createObjectGroup(group, 0);
1085         // create stone mines
1086         mAngle += randFloat(PI/8, PI/4);
1087         mX = round(fx + mDist * cos(mAngle));
1088         mZ = round(fz + mDist * sin(mAngle));
1089         group = new SimpleGroup(
1090                 [new SimpleObject(oStoneLarge, 1,1, 0,2)],
1091                 true, clBaseResource, mX, mZ
1092         );
1093         createObjectGroup(group, 0);
1094         var hillSize = PI * radius * radius;
1095         // create starting trees
1096         var num = floor(hillSize / 100);
1097         var tAngle = randFloat(-PI/3, 4*PI/3);
1098         var tDist = randFloat(11, 13);
1099         var tX = round(fx + tDist * cos(tAngle));
1100         var tZ = round(fz + tDist * sin(tAngle));
1101         group = new SimpleGroup(
1102                 [new SimpleObject(oTree1, num, num, 0,5)],
1103                 false, clBaseResource, tX, tZ
1104         );
1105         createObjectGroup(group, 0, avoidClasses(clBaseResource,2));
1107         placeDefaultDecoratives(fx, fz, aGrassShort, clBaseResource, radius);
1110 for (var i = 0; i < numPlayers; i++)
1112         var fx = fractionToTiles(playerX[i]);
1113         var fz = fractionToTiles(playerZ[i]);
1114         var ix = round(fx);
1115         var iz = round(fz);
1116         // create the city patch
1117         var cityRadius = radius/3;
1118         placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
1119         var painter = new LayeredPainter([tRoadWild, tRoad], [1]);
1120         createArea(placer, [painter, paintClass(clPlayer)], null);
1123 log("Creating bumps...");
1124 placer = new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1);
1125 painter = new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2);
1126 createAreas(
1127         placer,
1128         painter,
1129         [avoidClasses(clWater, 2, clPlayer, 10), stayClasses(clLand, 3)],
1130         randIntInclusive(0,scaleByMapSize(200, 400))
1133 log("Creating hills...");
1134 placer = new ChainPlacer(1, floor(scaleByMapSize(4, 6)), floor(scaleByMapSize(16, 40)), 0.5);
1135 terrainPainter = new LayeredPainter(
1136         [tCliff, tHill],                // terrains
1137         [2]                                                             // widths
1139 elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 18, 2);
1140 createAreas(
1141         placer,
1142         [terrainPainter, elevationPainter, paintClass(clHill)],
1143         [avoidClasses(clPlayer, 20, clHill, randIntInclusive(6, 18)), stayClasses(clLand, 0)],
1144         randIntInclusive(0, scaleByMapSize(4, 8))*randIntInclusive(1, scaleByMapSize(4, 9))
1147 var multiplier = sqrt(randFloat(0.5,1.2)*randFloat(0.5,1.2));
1148 // calculate desired number of trees for map (based on size)
1149 if (currentBiome() == "savanna")
1151         var MIN_TREES = floor(200*multiplier);
1152         var MAX_TREES = floor(1250*multiplier);
1153         var P_FOREST = 0;
1155 else if (currentBiome() == "tropic")
1157         var MIN_TREES = floor(1000*multiplier);
1158         var MAX_TREES = floor(6000*multiplier);
1159         var P_FOREST = randFloat(0.5, 0.7);
1161 else
1163         var MIN_TREES = floor(500*multiplier);
1164         var MAX_TREES = floor(3000*multiplier);
1165         var P_FOREST = randFloat(0.5,0.8);
1167 var totalTrees = scaleByMapSize(MIN_TREES, MAX_TREES);
1168 var numForest = totalTrees * P_FOREST;
1169 var numStragglers = totalTrees * (1.0 - P_FOREST);
1171 log("Creating forests...");
1172 var types = [
1173         [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]],
1174         [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]]
1175 ];      // some variation
1177 if (currentBiome() != "savanna")
1179         var size = numForest / (scaleByMapSize(3,6) * numPlayers);
1180         var num = floor(size / types.length);
1181         for (var i = 0; i < types.length; ++i)
1182         {
1183                 placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), numForest / num, 0.5);
1184                 painter = new LayeredPainter(
1185                         types[i],               // terrains
1186                         [2]                                                                                     // widths
1187                         );
1188                 createAreas(
1189                         placer,
1190                         [painter, paintClass(clForest)],
1191                         [avoidClasses(clPlayer, 20, clForest, randIntInclusive(5, 15), clHill, 0), stayClasses(clLand, 4)],
1192                         num
1193                 );
1194         }
1197 RMS.SetProgress(50);
1198 log("Creating dirt patches...");
1199 var sizes = [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)];
1200 var numb = 1;
1201 if (currentBiome() == "savanna")
1202         numb = 3;
1203 for (var i = 0; i < sizes.length; i++)
1205         placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), sizes[i], 0.5);
1206         painter = new LayeredPainter(
1207                 [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]],            // terrains
1208                 [1,1]                                                                                                                   // widths
1209         );
1210         createAreas(
1211                 placer,
1212                 [painter, paintClass(clDirt)],
1213                 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)],
1214                 numb*scaleByMapSize(15, 45)
1215         );
1218 log("Creating grass patches...");
1219 var sizes = [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)];
1220 for (var i = 0; i < sizes.length; i++)
1222         placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), sizes[i], 0.5);
1223         painter = new TerrainPainter(tTier4Terrain);
1224         createAreas(
1225                 placer,
1226                 painter,
1227                 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)],
1228                 numb*scaleByMapSize(15, 45)
1229         );
1231 RMS.SetProgress(55);
1233 log("Creating stone mines...");
1234 group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock);
1235 createObjectGroupsDeprecated(group, 0,
1236         [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), stayClasses(clLand, 4)],
1237         randIntInclusive(scaleByMapSize(2,9),scaleByMapSize(9,40)), 100
1240 log("Creating small stone quarries...");
1241 group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock);
1242 createObjectGroupsDeprecated(group, 0,
1243         [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), stayClasses(clLand, 4)],
1244         randIntInclusive(scaleByMapSize(2,9),scaleByMapSize(9,40)), 100
1247 log("Creating metal mines...");
1248 group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal);
1249 createObjectGroupsDeprecated(group, 0,
1250         [avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 4)],
1251         randIntInclusive(scaleByMapSize(2,9),scaleByMapSize(9,40)), 100
1254 RMS.SetProgress(65);
1256 log("Creating small decorative rocks...");
1257 group = new SimpleGroup(
1258         [new SimpleObject(aRockMedium, 1,3, 0,1)],
1259         true
1261 createObjectGroupsDeprecated(
1262         group, 0,
1263         [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 4)],
1264         scaleByMapSize(16, 262), 50
1267 log("Creating large decorative rocks...");
1268 group = new SimpleGroup(
1269         [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
1270         true
1272 createObjectGroupsDeprecated(
1273         group, 0,
1274         [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 4)],
1275         scaleByMapSize(8, 131), 50
1277 RMS.SetProgress(70);
1279 log("Creating deer...");
1280 group = new SimpleGroup(
1281         [new SimpleObject(oMainHuntableAnimal, 5,7, 0,4)],
1282         true, clFood
1284 createObjectGroupsDeprecated(group, 0,
1285         [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), stayClasses(clLand, 4)],
1286         randIntInclusive(numPlayers+3, 5*numPlayers+4), 50
1289 log("Creating berry bush...");
1290 group = new SimpleGroup(
1291         [new SimpleObject(oFruitBush, 5,7, 0,4)],
1292         true, clFood
1294 createObjectGroupsDeprecated(group, 0,
1295         [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), stayClasses(clLand, 4)],
1296         randIntInclusive(1, 4) * numPlayers + 2, 50
1298 RMS.SetProgress(75);
1300 log("Creating sheep...");
1301 group = new SimpleGroup(
1302         [new SimpleObject(oSecondaryHuntableAnimal, 2,3, 0,2)],
1303         true, clFood
1305 createObjectGroupsDeprecated(group, 0,
1306         [avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), stayClasses(clLand, 4)],
1307         randIntInclusive(numPlayers+3, 5*numPlayers+4), 50
1310 log("Creating fish...");
1311 group = new SimpleGroup(
1312         [new SimpleObject(oFish, 2,3, 0,2)],
1313         true, clFood
1315 createObjectGroupsDeprecated(group, 0,
1316         avoidClasses(clLand, 5, clForest, 0, clPlayer, 0, clHill, 0, clFood, 20),
1317         randIntInclusive(15, 40) * numPlayers, 60
1319 RMS.SetProgress(85);
1321 log("Creating straggler trees...");
1322 var types = [oTree1, oTree2, oTree4, oTree3];   // some variation
1323 var num = floor(numStragglers / types.length);
1324 for (var i = 0; i < types.length; ++i)
1326         group = new SimpleGroup(
1327                 [new SimpleObject(types[i], 1,1, 0,3)],
1328                 true, clForest
1329         );
1330         createObjectGroupsDeprecated(group, 0,
1331                 [avoidClasses(clWater, 1, clForest, 7, clHill, 1, clPlayer, 0, clMetal, 6, clRock, 6), stayClasses(clLand, 4)],
1332                 num
1333         );
1336 var planetm = 1;
1337 if (currentBiome() == "tropic")
1338         planetm = 8;
1340 log("Creating small grass tufts...");
1341 group = new SimpleGroup(
1342         [new SimpleObject(aGrassShort, 1,2, 0,1, -PI/8,PI/8)]
1344 createObjectGroupsDeprecated(group, 0,
1345         [avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 4)],
1346         planetm * scaleByMapSize(13, 200)
1348 RMS.SetProgress(90);
1350 log("Creating large grass tufts...");
1351 group = new SimpleGroup(
1352         [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)]
1354 createObjectGroupsDeprecated(group, 0,
1355         [avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 4)],
1356         planetm * scaleByMapSize(13, 200)
1358 RMS.SetProgress(95);
1360 log("Creating shallow flora...");
1361 group = new SimpleGroup(
1362         [new SimpleObject(aLillies, 1,2, 0,2), new SimpleObject(aReeds, 2,4, 0,2)]
1364 createObjectGroupsDeprecated(group, 0,
1365         stayClasses(clShallow, 1),
1366         60 * scaleByMapSize(13, 200), 80
1369 log("Creating bushes...");
1370 group = new SimpleGroup(
1371         [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)]
1373 createObjectGroupsDeprecated(group, 0,
1374         [avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1), stayClasses(clLand, 3)],
1375         planetm * scaleByMapSize(13, 200), 50
1378 setSkySet(pickRandom(["cirrus", "cumulus", "sunny", "sunny 1", "mountainous", "stratus"]));
1379 setSunRotation(randFloat(0, TWO_PI));
1380 setSunElevation(randFloat(PI/ 5, PI / 3));
1382 ExportMap();