Invincible women on survival of the fittest to prevent women fights and cheap tower...
[0ad.git] / binaries / data / mods / public / maps / random / deep_forest.js
blob62f9dbf946a1c3125f2ccececbe65f11e75500ac
1 RMS.LoadLibrary("rmgen");
3 // initialize map
4 log("Initializing map...");
5 InitMap();
7 // Setup tile classes
8 var clPlayer = createTileClass();
9 var clPath = createTileClass();
10 var clHill = createTileClass();
11 var clForest = createTileClass();
12 var clBaseResource = createTileClass();
14 // Setup Templates
15 var templateStone = "gaia/geology_stone_temperate";
16 var templateStoneMine = "gaia/geology_stonemine_temperate_quarry";
17 var templateMetal = "gaia/geology_metal_temperate";
18 var templateMetalMine = "gaia/geology_metal_temperate_slabs";
19 var startingResourcees = ["gaia/flora_tree_oak_large", "gaia/flora_bush_temperate", templateStoneMine,
20         "gaia/flora_bush_grapes", "gaia/flora_tree_apple", "gaia/flora_bush_berry", templateMetalMine, "gaia/flora_bush_badlands"];
22 // Setup terrain
23 var terrainWood = ['temp_grass_mossy|gaia/flora_tree_oak', 'temp_forestfloor_pine|gaia/flora_tree_pine', 'temp_mud_plants|gaia/flora_tree_dead',
24         'temp_plants_bog|gaia/flora_tree_oak_large', "temp_dirt_gravel_plants|gaia/flora_tree_aleppo_pine", 'temp_forestfloor_autumn|gaia/flora_tree_carob']; //'temp_forestfloor_autumn|gaia/flora_tree_fig'
25 var terrainWoodBorder = ['temp_grass_plants|gaia/flora_tree_euro_beech', 'temp_grass_mossy|gaia/flora_tree_poplar', 'temp_grass_mossy|gaia/flora_tree_poplar_lombardy',
26         'temp_grass_long|gaia/flora_bush_temperate', 'temp_mud_plants|gaia/flora_bush_temperate', 'temp_mud_plants|gaia/flora_bush_badlands',
27         'temp_grass_long|gaia/flora_tree_apple', 'temp_grass_clovers|gaia/flora_bush_berry', 'temp_grass_clovers_2|gaia/flora_bush_grapes',
28         'temp_grass_plants|gaia/fauna_deer', "temp_grass_long_b|gaia/fauna_rabbit", "temp_grass_plants"];
29 var terrainBase = ['temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b',
30         'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b',
31         'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b',
32         'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b',
33         'temp_grass_b|gaia/fauna_pig', 'temp_dirt_gravel|gaia/fauna_chicken'];
34 var terrainBaseBorder = ["temp_grass_b", "temp_grass_b", "temp_grass", "temp_grass_c", "temp_grass_mossy"];
35 var terrainBaseCenter = ['temp_dirt_gravel', 'temp_dirt_gravel', 'temp_grass_b'];
36 var terrainPath = ['temp_road', "temp_road_overgrown", 'temp_grass_b'];
37 var terrainHill = ["temp_highlands", "temp_highlands", "temp_highlands", "temp_dirt_gravel_b", "temp_cliff_a"];
38 var terrainHillBorder = ["temp_highlands", "temp_highlands", "temp_highlands", "temp_dirt_gravel_b", "temp_dirt_gravel_plants",
39         "temp_highlands", "temp_highlands", "temp_highlands", "temp_dirt_gravel_b", "temp_dirt_gravel_plants",
40         "temp_highlands", "temp_highlands", "temp_highlands", "temp_cliff_b", "temp_dirt_gravel_plants",
41         "temp_highlands", "temp_highlands", "temp_highlands", "temp_cliff_b", "temp_dirt_gravel_plants",
42         "temp_highlands|gaia/fauna_goat"];
45 // Setup map
46 var mapSize = getMapSize();
47 var mapRadius = mapSize/2;
48 var playableMapRadius = mapRadius - 5;
49 var mapCenterX = mapRadius;
50 var mapCenterZ = mapRadius;
52 // Setup players and bases
53 var numPlayers = getNumPlayers();
54 var baseRadius = 20;
55 var minPlayerRadius = min(mapRadius-1.5*baseRadius, 5*mapRadius/8);
56 var maxPlayerRadius = min(mapRadius-baseRadius, 3*mapRadius/4);
57 var playerStartLocX = new Array(numPlayers);
58 var playerStartLocZ = new Array(numPlayers);
59 var playerAngle = new Array(numPlayers);
60 var playerAngleStart = randFloat(0, 2*PI);
61 var playerAngleAddAvrg = 2*PI / numPlayers;
62 var playerAngleMaxOff = playerAngleAddAvrg/4;
64 // Setup eyecandy
65 var templateEC = "other/unfinished_greek_temple";
66 var radiusEC = max(mapRadius/8, baseRadius/2);
68 // Setup paths
69 var pathSucsessRadius = baseRadius/2;
70 var pathAngleOff = PI/2;
71 var pathWidth = 5; // This is not really the path's sickness in tiles but the number of tiles in the clumbs of the path
73 // Setup additional resources
74 var resourceRadius = 2*mapRadius/3; // 3*mapRadius/8;
75 var resourcePerPlayer = [templateStone, templateMetalMine];
77 // Setup woods
78 // For large maps there are memory errors with too many trees.  A density of 256*192/mapArea works with 0 players.
79 // Around each player there is an area without trees so with more players the max density can increase a bit.
80 var maxTreeDensity = min(256 * (192 + 8 * numPlayers) / (mapSize * mapSize), 1); // Has to be tweeked but works ok
81 var bushChance = 1/3; // 1 means 50% chance in deepest wood, 0.5 means 25% chance in deepest wood
83 RMS.SetProgress(2);
85 // Place bases
86 for (var i=0; i < numPlayers; i++)
88         playerAngle[i] = (playerAngleStart + i*playerAngleAddAvrg + randFloat(0, playerAngleMaxOff))%(2*PI);
89         var x = round(mapCenterX + randFloat(minPlayerRadius, maxPlayerRadius)*cos(playerAngle[i]));
90         var z = round(mapCenterZ + randFloat(minPlayerRadius, maxPlayerRadius)*sin(playerAngle[i]));
91         playerStartLocX[i] = x;
92         playerStartLocZ[i] = z;
93         // Place starting entities
94         placeCivDefaultEntities(x, z, i+1);
95         // Place base texture
96         var placer = new ClumpPlacer(2*baseRadius*baseRadius, 2/3, 1/8, 10, x, z);
97         var painter = [new LayeredPainter([terrainBaseBorder, terrainBase, terrainBaseCenter], [baseRadius/4, baseRadius/4]), paintClass(clPlayer)];
98         createArea(placer, painter);
99         // Place starting resources
100         var distToSL = 10;
101         var resStartAngle = playerAngle[i] + PI;
102         var resAddAngle = 2*PI / startingResourcees.length;
103         for (var rIndex = 0; rIndex < startingResourcees.length; rIndex++)
104         {
105                 var angleOff = randFloat(-resAddAngle/2, resAddAngle/2);
106                 var placeX = x + distToSL*cos(resStartAngle + rIndex*resAddAngle + angleOff);
107                 var placeZ = z + distToSL*sin(resStartAngle + rIndex*resAddAngle + angleOff);
108                 placeObject(placeX, placeZ, startingResourcees[rIndex], 0, randFloat(0, 2*PI));
109                 addToClass(round(placeX), round(placeZ), clBaseResource);
110         }
113 RMS.SetProgress(10);
115 // Place paths
116 var doublePaths = true;
117 if (numPlayers > 4)
118         doublePaths = false;
119 var doublePathMayPlayers = 4;
120 if (doublePaths == true)
121         var maxI = numPlayers+1;
122 else
123         var maxI = numPlayers;
124 for (var i = 0; i < maxI; i++)
126         if (doublePaths == true)
127                 var minJ = 0;
128         else
129                 var minJ = i+1;
130         for (var j = minJ; j < numPlayers+1; j++)
131         {
132                 // Setup start and target coordinates
133                 if (i < numPlayers)
134                 {
135                         var x = playerStartLocX[i];
136                         var z = playerStartLocZ[i];
137                 }
138                 else
139                 {
140                         var x = mapCenterX;
141                         var z = mapCenterZ;
142                 };
143                 if (j < numPlayers)
144                 {
145                         var targetX = playerStartLocX[j];
146                         var targetZ = playerStartLocZ[j];
147                 }
148                 else
149                 {
150                         var targetX = mapCenterX;
151                         var targetZ = mapCenterZ;
152                 };
153                 // Prepare path placement
154                 var angle = getAngle(x, z, targetX, targetZ);
155                 x += round(pathSucsessRadius*cos(angle));
156                 z += round(pathSucsessRadius*sin(angle));
157                 var targetReached = false;
158                 var tries = 0;
159                 // Placing paths
160                 while (targetReached == false && tries < 2*mapSize)
161                 {
162                         var placer = new ClumpPlacer(pathWidth, 1, 1, 1, x, z);
163                         var painter = [new TerrainPainter(terrainPath), new ElevationPainter(-randFloat()), paintClass(clPath)];
164                         createArea(placer, painter, avoidClasses(clHill, 0, clBaseResource, 4));
165                         // addToClass(x, z, clPath); // Not needed...
166                         // Set vars for next loop
167                         angle = getAngle(x, z, targetX, targetZ);
168                         if (doublePaths == true) // Bended paths
169                         {
170                                 x += round(cos(angle + randFloat(-pathAngleOff/2, 3*pathAngleOff/2)));
171                                 z += round(sin(angle + randFloat(-pathAngleOff/2, 3*pathAngleOff/2)));
172                         }
173                         else // Straight paths
174                         {
175                                 x += round(cos(angle + randFloat(-pathAngleOff, pathAngleOff)));
176                                 z += round(sin(angle + randFloat(-pathAngleOff, pathAngleOff)));
177                         }
178                         if (getDistance(x, z, targetX, targetZ) < pathSucsessRadius)
179                                 targetReached = true;
180                         tries++;
182                 }
183         }
186 RMS.SetProgress(50);
188 // Place expansion resources
189 for (var i=0; i < numPlayers; i++)
191         for (var rIndex = 0; rIndex < resourcePerPlayer.length; rIndex++)
192         {
193                 if (numPlayers > 1)
194                         var angleDist = (playerAngle[(i+1)%numPlayers] - playerAngle[i] + 2*PI)%(2*PI);
195                 else
196                         var angleDist = 2*PI;
197                 var placeX = round(mapCenterX + resourceRadius*cos(playerAngle[i] + (rIndex+1)*angleDist/(resourcePerPlayer.length+1)));
198                 var placeZ = round(mapCenterX + resourceRadius*sin(playerAngle[i] + (rIndex+1)*angleDist/(resourcePerPlayer.length+1)));
199                 placeObject(placeX, placeZ, resourcePerPlayer[rIndex], 0, randFloat(0, 2*PI));
200                 var placer = new ClumpPlacer(40, 1/2, 1/8, 1, placeX, placeZ);
201                 var painter = [new LayeredPainter([terrainHillBorder, terrainHill], [1]), new ElevationPainter(1+randFloat()), paintClass(clHill)];
202                 createArea(placer, painter);
203         }
206 RMS.SetProgress(60);
208 // Place eyecandy
209 placeObject(mapCenterX, mapCenterZ, templateEC, 0, randFloat(0, 2*PI));
210 var placer = new ClumpPlacer(radiusEC*radiusEC, 1/2, 1/8, 1, mapCenterX, mapCenterZ);
211 var painter = [new LayeredPainter([terrainHillBorder, terrainHill], [radiusEC/4]), new ElevationPainter(1+randFloat()), paintClass(clHill)];
212 createArea(placer, painter);
214 // Woods and general hight map
215 for (var x = 0; x < mapSize; x++)
217         for (var z = 0;z < mapSize;z++)
218         {
219                 // Some variables
220                 var radius = Math.pow(Math.pow(mapCenterX - x - 0.5, 2) + Math.pow(mapCenterZ - z - 0.5, 2), 1/2); // The 0.5 is a correction for the entities placed on the center of tiles
221                 var minDistToSL = mapSize;
222                 for (var i=0; i < numPlayers; i++)
223                         minDistToSL = min(minDistToSL, getDistance(playerStartLocX[i], playerStartLocZ[i], x, z));
224                 // Woods tile based
225                 var tDensFactSL = max(min((minDistToSL - baseRadius) / baseRadius, 1), 0);
226                 var tDensFactRad = abs((resourceRadius - radius) / resourceRadius);
227                 var tDensFactEC = max(min((radius - radiusEC) / radiusEC, 1), 0);
228                 var tDensActual = maxTreeDensity * tDensFactSL * tDensFactRad * tDensFactEC;
229                 if (randFloat() < tDensActual && radius < playableMapRadius)
230                 {
231                         if (tDensActual < bushChance*randFloat()*maxTreeDensity)
232                         {
233                                 var placer = new ClumpPlacer(1, 1.0, 1.0, 1, x, z);
234                                 var painter = [new TerrainPainter(terrainWoodBorder), new ElevationPainter(randFloat()), paintClass(clForest)];
235                                 createArea(placer, painter, avoidClasses(clPath, 1, clHill, 0));
236                         }
237                         else
238                         {
239                                 var placer = new ClumpPlacer(1, 1.0, 1.0, 1, x, z);
240                                 var painter = [new TerrainPainter(terrainWood), new ElevationPainter(randFloat()), paintClass(clForest)];
241                                 createArea(placer, painter, avoidClasses(clPath, 2, clHill, 1));
242                         }
243                 }
244                 // General hight map
245                 var hVarMiddleHill = mapSize/64 * (1+cos(3*PI/2 * radius/mapRadius));
246                 var hVarHills = 5*(1+sin(x/10)*sin(z/10));
247                 setHeight(x, z, getHeight(x, z) + hVarMiddleHill + hVarHills + 1);
248         }
251 RMS.SetProgress(95);
254 // Export map data
255 ExportMap();