Invincible women on survival of the fittest to prevent women fights and cheap tower...
[0ad.git] / binaries / data / mods / public / maps / random / corsica.js
blobdb889dbfee64e8d392304f2fc0890d3439dd8f14
1 RMS.LoadLibrary("rmgen");
3 var tGrass = ["medit_grass_field", "medit_grass_field_b", "temp_grass_c"];
4 var tDune = ["medit_grass_field_brown"];
5 var tBigDune = ["medit_grass_field_brown"];
6 var tGrassPForest = "forestfloor_dirty";
7 var tForestFloor = "medit_grass_shrubs";
8 var tGrassA = ["desert_dirt_persia_1", "desert_dirt_persia_2"];
9 var tGrassB = "dirta";
10 var tLushGrass = ["medit_grass_field","medit_grass_field_a"];
12 var tSteepCliffs = ["temp_cliff_b", "temp_cliff_a"];
13 var tCliffs = ["temp_cliff_b", "medit_cliff_italia", "medit_cliff_italia_grass"];
14 var tHill = ["medit_cliff_italia_grass","medit_cliff_italia_grass", "medit_grass_field", "medit_grass_field", "temp_grass"];
15 var tMountain = ["medit_cliff_italia_grass","medit_cliff_italia"];
16 var tMountainTop = ["medit_cliff_italia"];
18 var tDirt = ["medit_dirt", "medit_dirt_b"];
19 var tRoad = ["medit_city_tile","medit_rocks_grass","medit_grass_field_b"];
20 var tRoadWild = ["medit_rocks_grass","medit_grass_field_b"];
21 var tGrassPatch = "medit_dirt_b";
23 var tShoreBlend = ["medit_sand_wet","medit_rocks_wet"];
24 var tShore = ["medit_rocks","medit_sand","medit_sand"];
25 var tSandTransition = ["medit_sand","medit_rocks_grass","medit_rocks_grass","medit_rocks_grass"];
26 var tVeryDeepWater = ["medit_sea_depths","medit_sea_coral_deep"];
27 var tDeepWater = ["medit_sea_coral_deep","tropic_ocean_coral"];
28 var tCreekWater = "medit_sea_coral_plants";
30 // gaia entities
31 var ePine = "gaia/flora_tree_aleppo_pine";
32 var ePalmTall = "gaia/flora_tree_cretan_date_palm_tall";
33 var eFanPalm = "gaia/flora_tree_medit_fan_palm";
34 var eCypress = "gaia/flora_tree_cypress";
35 var eApple = "gaia/flora_tree_apple";
36 var eBush = "gaia/flora_bush_berry";
37 var eFish = "gaia/fauna_fish";
38 var ePig = "gaia/fauna_pig";
39 var eStoneMine = "gaia/geology_stonemine_medit_quarry";
40 var eMetalMine = "gaia/geology_metal_mediterranean_slabs";
42 // decorative props
43 var aFlower1 = "actor|props/flora/decals_flowers_daisies.xml";
44 var aWaterFlower = "actor|props/flora/water_lillies.xml";
45 var aReedsA = "actor|props/flora/reeds_pond_lush_a.xml";
46 var aReedsB = "actor|props/flora/reeds_pond_lush_b.xml";
47 var aRock = "actor|geology/stone_granite_med.xml";
48 var aLargeRock = "actor|geology/stone_granite_large.xml";
49 var aBushA = "actor|props/flora/bush_medit_sm_lush.xml";
50 var aBushB = "actor|props/flora/bush_medit_me_lush.xml";
51 var aPlantA = "actor|props/flora/plant_medit_artichoke.xml";
52 var aPlantB = "actor|props/flora/grass_tufts_a.xml";
53 var aPlantC = "actor|props/flora/grass_soft_tuft_a.xml";
54 var aShorePlantA = "actor|props/flora/reeds_beach.xml";
55 var aShorePlantB = "actor|props/flora/grass_temp_field_brown.xml";
57 var aStandingStone = "actor|props/special/eyecandy/standing_stones.xml";
59 var tForestNicae = [tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + eFanPalm, tForestFloor + TERRAIN_SEPARATOR + ePalmTall, tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor];
60 var tForestNicaeLight = [tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + eFanPalm, tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor];
61 var tForestNicaeScarce = [tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + eFanPalm, tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor];
63 log("Initializing map...");
65 InitMap();
67 var numPlayers = getNumPlayers();
68 var mapSize = getMapSize();
69 var mapArea = mapSize*mapSize;
71 // create tile classes
72 var clCorsica = createTileClass();
73 var clSardinia = createTileClass();
74 var clCreek = createTileClass();
76 var clWater = createTileClass();
78 var clCliffs = createTileClass();
79 var clForest = createTileClass();
80 var clPeak = createTileClass();
82 var clShore = createTileClass();
83 var clPathToShore = createTileClass();
84 var clPlayer = createTileClass();
85 var clBaseResource = createTileClass();
86 var clPassage = createTileClass();
87 var clHill = createTileClass();
88 var clWater = createTileClass();
89 var clDirt = createTileClass();
90 var clRock = createTileClass();
91 var clMetal = createTileClass();
92 var clFood = createTileClass();
93 var clSettlement = createTileClass();
94 var clDune = createTileClass();
96 // on every pixel of the map, set wet sand
97 for (var ix = 0; ix < mapSize; ix++)
99         for (var iz = 0; iz < mapSize; iz++)
100         {
101                 var x = ix / (mapSize + 1.0);
102                 var z = iz / (mapSize + 1.0);
103                         placeTerrain(ix, iz, tVeryDeepWater);
104                 //addToClass(ix,iz,clWater);
105         }
108 // let's decide if we swap
109 var swap = Math.round(Math.random());   // should return about 50/50 a 0 or a 1
110 // let's create Corsica
111 log("Creating Corsica");
112 var CorsicaX = fractionToTiles(0.99);
113 var CorsicaZ = fractionToTiles(0.9);
114 if (swap)
115         CorsicaX = fractionToTiles(0.01);
117 // Okay so the thing here is that we'll make a sort of jagged circle. To achieve this, I'll make a few islands
118 // that will basically be put together
119 // first, let's make a big round island in the corner.
120 // okay so actually subdivided cleverly to make it work and give jagedness with the multiple islands
121 var llx = round(CorsicaX);
122 var llz = round(CorsicaZ);
123 // okay so the circle reaches close to a third of the map
124 var placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.5, 10, llx, llz);
125 var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
126 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,0);
127 createArea(placer, [terrainPainter, paintClass(clCorsica), elevationPainter], null);
128 var nbSubIsland = 5;    // actually 5+1
129 for (var i = 0; i <= nbSubIsland; i++)
131         // radius is "sqrt(this.size / PI)"... so in my case it's "sqrt(fractionofSize(0.33)*2.0/PI), about 0.64, sqrt-ed
132         //Let's round down.
133         // only from π to 3π/2
134         var angle = (i * (-PI/(nbSubIsland*2)) + PI);
135         if (!swap)
136                 angle *= -1;
137         var llx = round (CorsicaX + sqrt(fractionToSize(0.3)*0.55)*sin(angle));
138         var llz = round (CorsicaZ + sqrt(fractionToSize(0.3)*0.55)*cos(angle));
139         var placer = new ClumpPlacer(fractionToSize(0.05)/2, 0.6, 0.03, 10, llx, llz);
140         var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
141         var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,1);
142         createArea(placer, [terrainPainter, paintClass(clCorsica), elevationPainter], null);
144 RMS.SetProgress(10);
146 log("Creating Sardinia");
147 var SardiniaX = fractionToTiles(0.01);
148 var SardiniaZ = fractionToTiles(0.1);
149 if (swap)
150         SardiniaX = fractionToTiles(0.99);
152 var llx = round(SardiniaX);
153 var llz = round(SardiniaZ);
154 // okay so the circle reaches close to a third of the map
155 var placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.5, 10, llx, llz);
156 var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
157 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,0);
158 createArea(placer, [terrainPainter, paintClass(clSardinia), elevationPainter], null);
159 // same as Corsica on the other side
160 for (var i = 0; i <= nbSubIsland; i++)
162         var angle = (i * (-PI/(nbSubIsland*2)));
163         if (!swap)
164                 angle *= -1;
165         var llx = round (SardiniaX + sqrt(fractionToSize(0.3)*0.55)*sin(angle));
166         var llz = round (SardiniaZ + sqrt(fractionToSize(0.3)*0.55)*cos(angle));
167         var placer = new ClumpPlacer(fractionToSize(0.05)/2, 0.6, 0.03, 10, llx, llz);
168         var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
169         var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,1);
170         createArea(placer, [terrainPainter, paintClass(clSardinia), elevationPainter], null);
173 log("Creating Creeks");
175 // okay so now let's make some cleverly designed creeks: this creates a very jagged relief, looks good
176 var nbCreeks = scaleByMapSize(6,15);
177 // inCorsica first
178 var islandX = [SardiniaX,CorsicaX];
179 var islandZ = [SardiniaZ,CorsicaZ];
180 // first: the creeks
181 for (var island = 0; island <= 1; island++)
182         for (var i = 0; i <= nbCreeks; i++)
183         {
184                 var radius = fractionToTiles( (Math.random()/17) + 0.49);
185                 var angle = PI*island + i*(PI/(nbCreeks*2));
186                 if (swap)
187                         angle += PI/2;
188                 fx = radius * cos(angle);
189                 fz = radius * sin(angle);
190                 fx = round(islandX[island] + fx);
191                 fz = round(islandZ[island] + fz);
192                 var size = scaleByMapSize(75,100);
193                 if (Math.random() > 0.5)
194                         size = Math.random() * 40 + 10;
195                 else
196                         size += Math.random() * 20;
197                 var placer = new ClumpPlacer(size, 0.4, 0.01, 10, fx,fz);
198                 var terrainPainter = new TerrainPainter(tSteepCliffs);
199                 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -5,0); // base height is -10
200                 createArea(placer, [terrainPainter, paintClass(clCreek), elevationPainter], null);
201         }
203 var nbBeaches = scaleByMapSize(2,5);
204 for (var island = 0; island <= 1; island++)
206         for (var i = 0; i <= nbBeaches; i++)
207         {
208                 var smallRadius = fractionToTiles( 0.45);
209                 var bigRadius = fractionToTiles( 0.57);
210                 var angle = PI*island + i*(PI/(nbBeaches*2.5)) + PI/(nbBeaches*6) + randFloat(-PI/(nbBeaches*7),PI/(nbBeaches*7));
211                 if (swap)
212                         angle += PI/2;
213                 var startX = smallRadius * cos(angle);
214                 var startZ = smallRadius * sin(angle);
215                 startX = round(islandX[island] + startX);
216                 startZ = round(islandZ[island] + startZ);
218                 var endX = bigRadius * cos(angle);
219                 var endZ = bigRadius * sin(angle);
220                 endX = round(islandX[island] + endX);
221                 endZ = round(islandZ[island] + endZ);
223                 var placer = new ClumpPlacer(130, 0.7, 0.8, 10, round((startX+endX*3)/4),round((startZ+endZ*3)/4));
224                 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -1,5); // base height is -10
225                 createArea(placer, [elevationPainter], null);
227                 straightPassageMaker(startX, startZ,endX,endZ, 25, 18, 4,clShore,null);
228         }
230 RMS.SetProgress(20);
231 log("Creating Main Relief");
232 // Let's make it generally cliffy
233 placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.2, 4,round((CorsicaX * 5 + fractionToTiles(0.5)) / 6.0),round(fractionToTiles(0.8)));
234 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 30,fractionToTiles(0.45));
235 createArea( placer, [elevationPainter],  null);
236 placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.2, 4,round((SardiniaX * 5 + fractionToTiles(0.5)) / 6.0),round(fractionToTiles(0.2)));
237 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 30,fractionToTiles(0.45));
238 createArea( placer, [elevationPainter],  null);
240 log("Creating players");
242 // randomize player order
243 var playerIDs = [];
244 for (var i = 0; i < numPlayers; i++)
246         playerIDs.push(i+1);
248 playerIDs = sortPlayers(playerIDs);
250 // place players
251 var playerX = new Array(numPlayers);
252 var playerZ = new Array(numPlayers);
253 var playerAngle = new Array(numPlayers);
255 var island = 0;
256 var formerTeam = getPlayerTeam(0);
257 var onCorsica = [];
258 var onSardinia = [];
259 for (var o = 0; o < numPlayers; o++)
261         if (getPlayerTeam(o) === formerTeam && formerTeam !== -1)
262         {
263                 // same island
264                 if (island === 0)
265                         onCorsica.push(o);
266                 else
267                         onSardinia.push(o);
268         } else if (getPlayerTeam(o) !== -1){
269                 if (island === 0)
270                 {
271                         island = 1;
272                         onSardinia.push(o);
273                 } else {
274                         island = 0;
275                         onCorsica.push(o);
276                 }
277         } else {
278                 // okay now the less crowded:
279                 if (onCorsica.length > onSardinia.length)
280                         onSardinia.push(o);
281                 else
282                         onCorsica.push(o);
283         }
284         formerTeam = getPlayerTeam(o);
286 // le'ts place the players in a circle around the island.
287 for (var i = 0;i < onCorsica.length; i++)
289         var angle = (i * (PI/(onCorsica.length*2)) + PI + PI/(4*onCorsica.length));
290         if (swap)
291                 angle += PI/2;
292         playerAngle[onCorsica[i]] = angle;
293         playerX[onCorsica[i]] = round( CorsicaX + fractionToTiles(0.36*cos(angle)));
294         playerZ[onCorsica[i]] = round( fractionToTiles(1 + 0.36*sin(angle)));
296 for (var i = 0;i < onSardinia.length; i++)
298         var angle = (i * (PI/(onSardinia.length*2)) + PI/(4*onSardinia.length));
299         if (swap)
300                 angle += PI/2;
301         playerAngle[onSardinia[i]] = angle;
302         playerX[onSardinia[i]] = round( SardiniaX + fractionToTiles(0.36*cos(angle)));
303         playerZ[onSardinia[i]] = round( fractionToTiles(0 + 0.36*sin(angle)));
306 var placer = undefined;
307 var fx = 0; var fz = 0;
308 var ix =0; var iz = 0;
309 for (var i = 0; i < numPlayers; i++)
311         var id = playerIDs[i];
312         log("Creating base for player " + id + "...");
314         // some constants
315         var radius = 23;
317         // get the x and z in tiles
318         fx = playerX[i];
319         fz = playerZ[i];
322         // let's create a nice platform
323         var placer = new ClumpPlacer(PI*radius*radius, 0.95, 0.3, 10, fx,fz);
324         var PlayerArea = createArea(placer, [paintClass(clPlayer)], null);
326         // create the city patch
327         var cityRadius = radius/4;
328         placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.8, 0.3, 10, fx, fz);
329         var painter = new LayeredPainter([tRoadWild,tRoad],[1]);
330         var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, getHeight(fx,fz),10);
331         createArea(placer, [painter,paintClass(clSettlement),elevationPainter], null);
333         // create starting units
334         placeCivDefaultEntities(fx, fz, id, { 'iberWall': false });
336         placeDefaultChicken(fx, fz, clBaseResource);
338         // create berry bushes
339         var bbAngle = randFloat(0, TWO_PI);
340         var bbDist = 11;
341         var bbX = round(fx + bbDist * cos(bbAngle));
342         var bbZ = round(fz + bbDist * sin(bbAngle));
343         var group = new SimpleGroup(
344                 [new SimpleObject(eBush, 5,5, 1,2)],
345                 true, clBaseResource, bbX, bbZ
346         );
347         createObjectGroup(group, 0);
349         // create metal mine
350         // this makes sure it's created on the same level as the player.
351         var mAngle = randFloat(playerAngle[i] + PI/2,playerAngle[i] + PI/3);
352         var mDist = 18;
353         var mX = round(fx + mDist * cos(mAngle));
354         var mZ = round(fz + mDist * sin(mAngle));
355         group = new SimpleGroup(
356                 [new SimpleObject(eMetalMine, 1,1, 0,0),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3), new SimpleObject(ePine, 0,1, 3,3)], true, clBaseResource, mX, mZ );
357         createObjectGroup(group, 0);
358         // create stone mines
359         mAngle += randFloat(PI/8, PI/5);
360         mX = round(fx + mDist * cos(mAngle));
361         mZ = round(fz + mDist * sin(mAngle));
362         group = new SimpleGroup(
363                 [new SimpleObject(eStoneMine, 1,1, 0,2),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3), new SimpleObject(ePine, 0,1, 3,3)], true, clBaseResource, mX, mZ );
364         createObjectGroup(group, 0);
366         group = new SimpleGroup([new SimpleObject(ePine, 1,3, 1,4),new SimpleObject(ePalmTall, 0,1, 1,4),new SimpleObject(eFanPalm, 0,1, 0,2)], true, clForest);
367         createObjectGroups(group, 0, [avoidClasses(clBaseResource,3, clSettlement,0), stayClasses(clPlayer,1)], 150, 1000);
370 RMS.SetProgress(40);
371 log ("making plateaux");
372 // Corsica and Sardinia
374 var SardX = round((SardiniaX*5 + fractionToTiles(0.5))/6.0);
375 var SardZ = round(fractionToTiles(0.1));
376 var CorsX = round((CorsicaX*5 + fractionToTiles(0.5))/6.0);
377 var CorsZ = round(fractionToTiles(0.9));
378 // first level plateaux, puts the player higher
379 placer = new ClumpPlacer(fractionToSize(0.18)*1.8, 0.95, 0.02, 4,CorsX,CorsZ);
380 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 9,1);
381 createArea( placer, [elevationPainter],  null);
382 placer = new ClumpPlacer(fractionToSize(0.18)*1.8, 0.95, 0.02, 4,SardX,SardZ);
383 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 9,1);
384 createArea( placer, [elevationPainter],  null);
385 // second level plateaux, top of the hill
386 if(mapSize > 150)
388         placer = new ClumpPlacer(fractionToSize(0.1), 0.98, 0.04, 4,CorsX,CorsZ);
389         terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
390         elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 8,1);
391         createArea( placer, [terrainPainter,elevationPainter],  null);
392         placer = new ClumpPlacer(fractionToSize(0.1), 0.98, 0.04, 4,SardX,SardZ);
393         terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
394         elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 8,1);
395         createArea( placer, [terrainPainter,elevationPainter],  null);
397 log ("creating passages towards the island");
398 if(mapSize > 150)
400         var nb = scaleByMapSize(1,4);
401         for (var i = 0; i < nb; i++) {
402                 var radius = sqrt(fractionToSize(0.1)/PI);
403                 var angle = PI + i*(PI/(2*nb)) + PI/(4*nb);
404                 if (swap)
405                         angle += PI/2;
406                 var x1 = round(CorsX + (radius+5)*cos(angle));
407                 var y1 = round(CorsZ + (radius+5)*sin(angle));
408                 var x2 = round(CorsX + (radius-4)*cos(angle));
409                 var y2 = round(CorsZ + (radius-4)*sin(angle));
410                 straightPassageMaker(x1, y1, x2, y2, 1, 6, 2, clPassage, tGrass);
411         }
412         for (var i = 0; i < nb; i++) {
413                 var radius = sqrt(fractionToSize(0.1)/PI)+ 2;
414                 var angle = i*(PI/(2*nb)) + PI/(4*nb);
415                 if (swap)
416                         angle += PI/2;
417                 var x1 = round(SardX + (radius+5)*cos(angle));
418                 var y1 = round(SardZ + (radius+5)*sin(angle));
419                 var x2 = round(SardX + (radius-4)*cos(angle));
420                 var y2 = round(SardZ + (radius-4)*sin(angle));
421                 straightPassageMaker(x1, y1, x2, y2, 1, 6, 2, clPassage, tGrass);
422         }
424 for (var i = 0; i <= 3; i++) {
425         var radius = sqrt(fractionToSize(0.18)*1.8/PI) + 2;
426         var angle = PI + i*(PI/7) + PI/9;
427         if (swap)
428                 angle += PI/2;
429         var x1 = round(CorsX + (radius+7)*cos(angle));
430         var y1 = round(CorsZ + (radius+7)*sin(angle));
431         var x2 = round(CorsX + (radius-5)*cos(angle));
432         var y2 = round(CorsZ + (radius-5)*sin(angle));
433         straightPassageMaker(x1, y1, x2, y2, 4, 10, 3, clPassage, tGrass);
435 for (var i = 0; i <= 3; i++) {
436         var radius = sqrt(fractionToSize(0.18)*1.8/PI)+ 2;
437         var angle = i*(PI/7) + PI/9;
438         if (swap)
439                 angle += PI/2;
440         var x1 = round(SardX + (radius+7)*cos(angle));
441         var y1 = round(SardZ + (radius+7)*sin(angle));
442         var x2 = round(SardX + (radius-5)*cos(angle));
443         var y2 = round(SardZ + (radius-5)*sin(angle));
444         straightPassageMaker(x1, y1, x2, y2, 4, 10, 3, clPassage, tGrass);
446 RMS.SetProgress(50);
448 log ("creating bumps");
449 placer = new ClumpPlacer(70, 0.6, 0.1, 4);
450 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 2,3);
451 createAreas( placer, [elevationPainter],  [avoidClasses(clPlayer,2,clPassage, 2), stayClasses(clCorsica,2)],scaleByMapSize(20,100), 5 );
452 createAreas( placer, [elevationPainter],  [avoidClasses(clPlayer,2,clPassage, 2), stayClasses(clSardinia,2)],scaleByMapSize(20,100), 5 );
454 log ("creating anti bumps");
455 placer = new ClumpPlacer(120, 0.3, 0.1, 4);
456 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, -5,6);
457 createAreas( placer, [elevationPainter],  [avoidClasses(clPlayer,2,clPassage, 2,clCorsica,2,clSardinia,2)],scaleByMapSize(20,100), 5 );
460 log("Repainting");
461 var terrTop = createTerrain(tMountainTop);
462 var terrMount = createTerrain(tMountain);
463 var terrHill = createTerrain(tHill);
464 var terrCliff = createTerrain(tCliffs);
465 var terrSteepCliff = createTerrain(tSteepCliffs);
466 var terrGrass = createTerrain(tGrass);
468 var terrShallow = createTerrain(tCreekWater);
469 var terrDeep = createTerrain(tDeepWater);
470 var terrDark = createTerrain(tVeryDeepWater);
471 var terrSand = createTerrain(tShore);
472 var terrWetSand = createTerrain(tShoreBlend);
473 var terrSandTransition = createTerrain(tSandTransition);
474 // first pass: who's water?
475 for (var sandx = 0; sandx < mapSize; sandx++)
476         for (var sandz = 0; sandz < mapSize; sandz++)
477                 if (getHeight(sandx,sandz) < 0)
478                         addToClass(sandx,sandz,clWater);
480 // second pass: who's not water
481 for (var sandx = 0; sandx < mapSize; sandx++) {
482         for (var sandz = 0; sandz < mapSize; sandz++) {
483                 if (getTileClass(clSettlement).countMembersInRadius(sandx,sandz,2) === 0)
484                 {
485                         var height = getHeight(sandx,sandz);
486                         var heightDiff = getHeightDiff(sandx,sandz);
487                         if (height >= 0.5 && height < 1.5 /*&& getTileClass(clWater).countMembersInRadius(sandx,sandz,3) > 0 */ && getTileClass(clShore).countMembersInRadius(sandx,sandz,2) > 0)
488                         {
489                                 terrSandTransition.place(sandx,sandz);
490                         } else if (height >= 1 && getTileClass(clWater).countMembersInRadius(sandx,sandz,3) == 0)
491                         {
492                                 // paint hills or cliffs depending on terrain elevation difference
493                                 if (height > 17 && getTileClass(clPassage).countMembersInRadius(sandx,sandz,2) == 0)
494                                 {
495                                         if (heightDiff < 5)
496                                                 terrHill.place(sandx,sandz);
497                                         else if(heightDiff < 10)
498                                                 terrMount.place(sandx,sandz);
499                                 } else {
500                                         terrGrass.place(sandx,sandz);
501                                 }
502                                 if (height > 25 && heightDiff >= 10 && getTileClass(clPassage).countMembersInRadius(sandx,sandz,2) == 0) {
503                                         terrSteepCliff.place(sandx,sandz);
504                                         addToClass(sandx,sandz,clCliffs);
505                                 } else if(heightDiff >= 10 && getTileClass(clPassage).countMembersInRadius(sandx,sandz,2) == 0) {
506                                         terrCliff.place(sandx,sandz);
507                                         addToClass(sandx,sandz,clCliffs);
508                                 }
509                         } else {
510                                 if (height >= 0 && heightDiff >= 9) {
511                                         terrCliff.place(sandx,sandz);
512                                         addToClass(sandx,sandz,clCliffs);
513                                 } else if (height >= -0.75 && height < 1.5 && heightDiff < 9) {
514                                                 terrSand.place(sandx,sandz);
515                                 } else if (height >= -3  && height < -0.75 && heightDiff < 9) {
516                                         terrWetSand.place(sandx,sandz);
517                                 }  else if (height >= -6  && height < -3 && heightDiff < 9) {
518                                         terrShallow.place(sandx,sandz);
519                                 } else if (height > -10  && height < -6 && heightDiff < 6) {
520                                         terrDeep.place(sandx,sandz);
521                                 }
522                                 if (heightDiff >= 9) {
523                                         terrCliff.place(sandx,sandz);
524                                         addToClass(sandx,sandz,clCliffs);
525                                 }
526                         }
527                 }
528         }
531 RMS.SetProgress(65);
533 log("Creating stone mines...");
534 // create large stone quarries
535 group = new SimpleGroup([new SimpleObject(eStoneMine, 1,1, 0,0),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3)], true, clBaseResource);
536 createObjectGroups(group, 0,[stayClasses(clCorsica, 1),avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1)],  scaleByMapSize(6,25), 1000  );
537 createObjectGroups(group, 0,[stayClasses(clSardinia, 1),avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1)],  scaleByMapSize(6,25), 1000  );
539 log("Creating metal mines...");
540 // create large metal quarries
541 group = new SimpleGroup([new SimpleObject(eMetalMine, 1,1, 0,0),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3)], true, clBaseResource);
542 createObjectGroups(group, 0,[avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1),stayClasses(clCorsica, 1)],  scaleByMapSize(6,25), 1000  );
543 createObjectGroups(group, 0,[avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1),stayClasses(clSardinia, 1)],  scaleByMapSize(6,25), 1000  );
545 log("Creating grass patches...");
546 placer = new ClumpPlacer(20, 0.3, 0.06, 0.5);
547 painter = new TerrainPainter(tLushGrass);
548 createAreas( placer, [painter,paintClass(clForest)], avoidClasses(clWater, 1,clPlayer, 0,clBaseResource, 3,clCliffs,1), scaleByMapSize(10, 40) );
550 log ("creating forests");
551 var TreeGroup = new SimpleGroup([new SimpleObject(ePine, 3,6, 1,3),new SimpleObject(ePalmTall, 1,3, 1,3),new SimpleObject(eFanPalm, 0,2, 0,2),new SimpleObject(eApple, 0,1, 1,2)], true, clForest);
552 createObjectGroups(TreeGroup, 0, [avoidClasses(clWater, 1, clForest, 0,clPlayer, 0,clBaseResource, 2,clCliffs,2), stayClasses(clCorsica, 3)],  scaleByMapSize(350,2500), 100 );
553 createObjectGroups(TreeGroup, 0, [avoidClasses(clWater, 1, clForest, 0,clPlayer, 0,clBaseResource, 2,clCliffs,2), stayClasses(clSardinia, 3)],  scaleByMapSize(350,2500), 100 );
555 RMS.SetProgress(75);
558 // create small decorative rocks
559 log("Creating small decorative rocks...");
560 group = new SimpleGroup( [new SimpleObject(aRock, 1,3, 0,1),new SimpleObject(aStandingStone, 0,2, 0,3)], true );
561 createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0,clBaseResource, 0, clPassage, 2),
562         scaleByMapSize(16, 262), 50
566 // create large decorative rocks
567 log("Creating large decorative rocks...");
568 group = new SimpleGroup( [new SimpleObject(aLargeRock, 1,2, 0,1), new SimpleObject(aRock, 1,3, 0,2)], true
570 createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0,clBaseResource, 0, clPassage, 2),
571         scaleByMapSize(8, 131), 50
573 createObjectGroups( group, 0, borderClasses(clWater, 5,10), scaleByMapSize(100,800), 500);
575 // create decorative grass
576 log("Creating beautification...");
577 group = new SimpleGroup( [new SimpleObject(aPlantA, 3,7, 0,3),new SimpleObject(aPlantB, 3,6, 0,3),new SimpleObject(aPlantC, 1,4, 0,4)], true );
578 createObjectGroups( group, 0, avoidClasses(clWater, 0,clBaseResource, 0, clShore,3), scaleByMapSize(100, 600), 50  );
579 group = new SimpleGroup( [new SimpleObject(aPlantB, 5,20, 0,5),new SimpleObject(aPlantC, 4,10, 0,4)], true );
580 createObjectGroups( group, 0, avoidClasses(clWater, 0,clBaseResource, 0, clShore,3), scaleByMapSize(100, 600), 50  );
582 RMS.SetProgress(80);
584 log("Creating animals...");
585 group = new SimpleGroup( [new SimpleObject(ePig, 2,4, 0,3)] );
586 createObjectGroups( group, 0, avoidClasses(clWater, 3,clBaseResource, 0), scaleByMapSize(20, 100), 50  );
588 group = new SimpleGroup( [new SimpleObject(eFish, 1,2, 0,3)] );
589 createObjectGroups( group, 0, [avoidClasses(clCreek,3,clShore,3),stayClasses(clWater, 3)], scaleByMapSize(50, 150), 100  );
591 RMS.SetProgress(90);
593 RMS.SetProgress(95);
594 if (randFloat(0,1) > 0.5)
595         setSkySet("cumulus");
596 else
597         setSkySet("sunny");
598 setSunColor(0.8,0.66,0.48);
599 setSunElevation(0.828932);
600 if (!swap)
601         setSunRotation(6.3*PI/8);
602 else
603         setSunRotation(2.3*PI/8);
604 setTerrainAmbientColor(0.564706,0.543726,0.419608);
605 setUnitsAmbientColor(0.53,0.55,0.45);
606 setWaterColor(0.2,0.294,0.49);
607 setWaterTint(0.208, 0.659, 0.925);
608 setWaterMurkiness(0.72);
609 setWaterWaviness(2.0);
610 setWaterType("ocean");
611 // Export map data
612 ExportMap();
617 // this function will go from point [x1,z1] to point [x2,z2], while following a curve of width (starting-center-starting)
618 // it can smooth on the side depending on "smooth", which is the distance of the smooth. Tileclass and Terrain set a tileclass/terrain
619 // it effectively can create a smooth path from point [x1,z1] to point [x2,z2], ie Canyon, whatever.
620 // note: NOT efficient for large distances: I'm widely oversampling
621 function straightPassageMaker(x1, z1, x2, z2, startWidth, centerWidth, smooth, tileclass, terrain)
623         var mapSize = g_Map.size;
624         var stepNB = sqrt((x2-x1)*(x2-x1) + (z2-z1)*(z2-z1)) + 2;
626         var startHeight = getHeight(x1,z1);
627         var finishHeight = getHeight(x2,z2);
628         for (var step = 0; step <= stepNB; step+=0.5)
629         {
630                 var ix = ((stepNB-step)*x1 + x2*step) / stepNB;
631                 var iz = ((stepNB-step)*z1 + z2*step) / stepNB;
632                 // 5 at star/end, and 0 at the center
633                 var width = (abs(step - stepNB/2.0) *startWidth + (stepNB/2 - abs(step - stepNB/2.0)) * centerWidth ) / (stepNB/2);
634                 var oldDirection = [x2-x1, z2-z1];
635                 // let's get the perpendicular direction
636                 var direction = [ -oldDirection[1],oldDirection[0] ];
637                 if (abs(direction[0]) > abs(direction[1]))
638                 {
639                         direction[1] = direction[1] / abs(direction[0]);
640                         if (direction[0] > 0)
641                                 direction[0] = 1;
642                         else
643                                 direction[0] = -1;
644                 } else {
645                         direction[0] = direction[0] / abs(direction[1]);
646                         if (direction[1] > 0)
647                                 direction[1] = 1;
648                         else
649                                 direction[1] = -1;
650                 }
651                 for (var po = -Math.floor(width/2.0); po <= Math.floor(width/2.0); po+=0.5)
652                 {
653                         var rx = po*direction[0];
654                         var rz = po*direction[1];
656                         var relativeWidth = abs(po / Math.floor(width/2));
657                         var targetHeight = ((stepNB-step)*startHeight + finishHeight*step) / stepNB;
658                         if (round(ix + rx) < mapSize && round(iz + rz) < mapSize && round(ix + rx) >= 0 && round(iz + rz) >= 0)
659                         {
660                                 // smoothing the sides
661                                 if ( abs(abs(po) - abs(Math.floor(width/2.0))) < smooth)
662                                 {
663                                         var localHeight = getHeight(round(ix + rx), round(iz + rz));
664                                         var localPart = smooth - abs(abs(po) - abs(Math.floor(width/2.0)));
665                                         var targetHeight = (localHeight * localPart + targetHeight * (1/localPart) )/ (localPart + 1/localPart);
666                                 }
668                                 g_Map.setHeight(round(ix + rx), round(iz + rz), targetHeight);
669                                 if (tileclass !== null)
670                                         addToClass(round(ix + rx), round(iz + rz), tileclass);
671                                 if (terrain !== null)
672                                         placeTerrain(round(ix + rx), round(iz + rz), terrain);
673                         }
674                 }
675         }
677 // no need for preliminary rounding
678 function getHeightDiff(x1, z1)
680         var height = getHeight(round(x1),round(z1));
681         var diff = 0;
682         if (z1 + 1 < mapSize)
683                 diff += abs(getHeight(round(x1),round(z1+1)) - height);
684         if (x1 + 1 < mapSize && z1 + 1 < mapSize)
685                 diff += abs(getHeight(round(x1+1),round(z1+1)) - height);
686         if (x1 + 1 < mapSize)
687                 diff += abs(getHeight(round(x1+1),round(z1)) - height);
688         if (x1 + 1 < mapSize && z1 - 1 >= 0)
689                 diff += abs(getHeight(round(x1+1),round(z1-1)) - height);
690         if (z1 - 1 >= 0)
691                 diff += abs(getHeight(round(x1),round(z1-1)) - height);
692         if (x1 - 1 >= 0 && z1 - 1 >= 0)
693                 diff += abs(getHeight(round(x1-1),round(z1-1)) - height);
694         if (x1 - 1 >= 0)
695                 diff += abs(getHeight(round(x1-1),round(z1)) - height);
696         if (x1 - 1 >= 0 && z1 + 1 < mapSize)
697                 diff += abs(getHeight(round(x1-1),round(z1+1)) - height);
698         return diff;
700 function hasTextureInRadius(x1, z1,radius, textureName)
702         for (var xx = x1-radius;xx <= x1 + radius; xx++)
703                 for (var zz = z1-radius;zz <= z1 + radius; zz++)
704                         if (xx !== x1 || zz !== z1)
705                                 if (xx >= 0 && xx < mapSize)
706                                         if (zz >= 0 && zz < mapSize)
707                                         {
708                                                 if (typeof(textureName) != "number")
709                                                 {
710                                                         for (var i in textureName)
711                                                                 if ( g_Map.getTexture(xx,zz) == textureName[i])
712                                                                         return true;
713                                                 } else {
714                                                         if ( g_Map.getTexture(xx,zz) == textureName)
715                                                                 return true;
716                                                 }
717                                         }
718         return false;