Page MenuHomeWildfire Games

Mapgen: Alpine Valley
Needs RevisionPublic

Authored by aeonios on May 17 2018, 11:51 PM.

Details

Reviewers
elexis
Stan
vladislavbelov
wraitii
fabio
Group Reviewers
Restricted Owners Package(Owns No Changed Paths)
Summary
  • I modified the Alpine Valley script to create maps very similar in style to the handcrafted "Alpine Valleys" map. It captures about 90% of the artistic conventions of the original, and also picks one of three random environment settings (morning, afternoon, evening).
  • I added a few library functions to support the needed functionality.
  • I drastically simplified the old mountain range generator from the Alpine Valleys script and moved it into its own file in rmgen-common. It now creates random points, orders them by shortest-cycle, and then connects them, culling edges that cause a contiguous edge to exceed the specified maximum length. With proper settings I have never seen it completely trap a player, but it does sometimes create unreachable areas at the edge of the map (which the old generator was not immune to either). So far I have not seen this cause trouble for the AI. It also now creates much nicer wavy mountains rather than straight-line strips, and successfully creates more ranges on average than the old generator did.

Note: The preview image will also need to be updated, but I have no idea where to find that.

Test Plan

Test to ensure that the Alpine Valleys script successfully generates maps, and that they meet the team's quality standards.

Diff Detail

Repository
rP 0 A.D. Public Repository
Lint
Lint Skipped
Unit
Unit Tests Skipped
Build Status
Buildable 6078
Build 10121: Vulcan BuildJenkins

Event Timeline

aeonios created this revision.May 17 2018, 11:51 PM
aeonios edited the summary of this revision. (Show Details)May 17 2018, 11:54 PM

Some screenshots:

This is a far shot of a typical (size: normal) map without fog or dof:

As you can see it also creates random lakes stocked with fish:

A few other shots of various details (evening env set):



Stan added a reviewer: Restricted Owners Package.May 18 2018, 12:27 AM
Vulcan added a subscriber: Vulcan.May 18 2018, 12:32 AM

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (curly):
|    | Unnecessary { after 'for' condition.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/math.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/math.js
|  62|  62| 	let points = [];
|  63|  63| 	let mapSize = g_Map.getSize();
|  64|  64| 	for (let i = 0; i < pointCount; ++i)
|  65|    |-	{
|    |  65|+	
|  66|  66| 		points[i] = new Vector2D(randIntExclusive(0, mapSize), randIntExclusive(0, mapSize));
|  67|    |-	}
|    |  67|+	
|  68|  68| 	return points;
|  69|  69| }
|  70|  70| 
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|  20|  20| var tShore = "alpine_shore_rocks_icy";
|  21|  21| 
|  22|  22| var oPine = "gaia/flora_tree_pine";
|  23|    |-var oAleppoPine = "gaia/flora_tree_aleppo_pine"
|    |  23|+var oAleppoPine = "gaia/flora_tree_aleppo_pine";
|  24|  24| var oWinterPine = "gaia/flora_tree_pine_w";
|  25|  25| var oBerryBush = "gaia/flora_bush_berry";
|  26|  26| var oSheep = "gaia/fauna_sheep";
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|  26|  26| var oSheep = "gaia/fauna_sheep";
|  27|  27| var oDeer = "gaia/fauna_deer";
|  28|  28| var oRabbit = "gaia/fauna_rabbit";
|  29|    |-var oBear = "gaia/fauna_bear"
|    |  29|+var oBear = "gaia/fauna_bear";
|  30|  30| var oFish = "gaia/fauna_fish";
|  31|  31| var oStoneLarge = "gaia/geology_stonemine_alpine_quarry";
|  32|  32| var oStoneSmall = "gaia/geology_stone_alpine_a";
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|  38|  38| var aRockMedium = "actor|geology/stone_granite_med.xml";
|  39|  39| var aBushMedium = "actor|props/flora/bush_medit_me.xml";
|  40|  40| var aBushSmall = "actor|props/flora/bush_medit_sm.xml";
|  41|    |-	
|    |  41|+
|  42|  42| 
|  43|  43| var heightLand = 3;
|  44|  44| var heightLake = -5;
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 239| 239| 
| 240| 240| // Create grassland forests
| 241| 241| createForests(
| 242|    |- [tPrimary, tForestFloor, tForestFloor, pForest, pForest],
|    | 242|+	[tPrimary, tForestFloor, tForestFloor, pForest, pForest],
| 243| 243|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clSnow, 1, clRoughSnow, 1, clFarm, 3), stayClasses(clGrass, 0), nearClasses(clHill, 7)],
| 244| 244|  clForest,
| 245| 245|  forestTrees * 0.65);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 240| 240| // Create grassland forests
| 241| 241| createForests(
| 242| 242|  [tPrimary, tForestFloor, tForestFloor, pForest, pForest],
| 243|    |- [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clSnow, 1, clRoughSnow, 1, clFarm, 3), stayClasses(clGrass, 0), nearClasses(clHill, 7)],
|    | 243|+	[avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clSnow, 1, clRoughSnow, 1, clFarm, 3), stayClasses(clGrass, 0), nearClasses(clHill, 7)],
| 244| 244|  clForest,
| 245| 245|  forestTrees * 0.65);
| 246| 246|  
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 241| 241| createForests(
| 242| 242|  [tPrimary, tForestFloor, tForestFloor, pForest, pForest],
| 243| 243|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clSnow, 1, clRoughSnow, 1, clFarm, 3), stayClasses(clGrass, 0), nearClasses(clHill, 7)],
| 244|    |- clForest,
|    | 244|+	clForest,
| 245| 245|  forestTrees * 0.65);
| 246| 246|  
| 247| 247| createStragglerTrees(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 242| 242|  [tPrimary, tForestFloor, tForestFloor, pForest, pForest],
| 243| 243|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clSnow, 1, clRoughSnow, 1, clFarm, 3), stayClasses(clGrass, 0), nearClasses(clHill, 7)],
| 244| 244|  clForest,
| 245|    |- forestTrees * 0.65);
|    | 245|+	forestTrees * 0.65);
| 246| 246|  
| 247| 247| createStragglerTrees(
| 248| 248| 	[oPine, oAleppoPine],
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 243| 243|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clSnow, 1, clRoughSnow, 1, clFarm, 3), stayClasses(clGrass, 0), nearClasses(clHill, 7)],
| 244| 244|  clForest,
| 245| 245|  forestTrees * 0.65);
| 246|    |- 
|    | 246|+
| 247| 247| createStragglerTrees(
| 248| 248| 	[oPine, oAleppoPine],
| 249| 249| 	[avoidClasses(clForest, 2, clHill, 1, clPlayer, 12, clWater, 3, clSnow, 1, clFarm, 3), nearClasses(clForest, 7)],
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 252| 252| 
| 253| 253| // Create snowdrift forests
| 254| 254| createForests(
| 255|    |- [tSecondary, tSnowyForestFloor, tSnowyForestFloor, pForestSnow, pForestSnow],
|    | 255|+	[tSecondary, tSnowyForestFloor, tSnowyForestFloor, pForestSnow, pForestSnow],
| 256| 256|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clHill, 7)],
| 257| 257|  clForest,
| 258| 258|  forestTrees * 0.35);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 253| 253| // Create snowdrift forests
| 254| 254| createForests(
| 255| 255|  [tSecondary, tSnowyForestFloor, tSnowyForestFloor, pForestSnow, pForestSnow],
| 256|    |- [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clHill, 7)],
|    | 256|+	[avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clHill, 7)],
| 257| 257|  clForest,
| 258| 258|  forestTrees * 0.35);
| 259| 259|  
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 254| 254| createForests(
| 255| 255|  [tSecondary, tSnowyForestFloor, tSnowyForestFloor, pForestSnow, pForestSnow],
| 256| 256|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clHill, 7)],
| 257|    |- clForest,
|    | 257|+	clForest,
| 258| 258|  forestTrees * 0.35);
| 259| 259|  
| 260| 260| createStragglerTrees(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 255| 255|  [tSecondary, tSnowyForestFloor, tSnowyForestFloor, pForestSnow, pForestSnow],
| 256| 256|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clHill, 7)],
| 257| 257|  clForest,
| 258|    |- forestTrees * 0.35);
|    | 258|+	forestTrees * 0.35);
| 259| 259|  
| 260| 260| createStragglerTrees(
| 261| 261| 	[oWinterPine],
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 256| 256|  [avoidClasses(clPlayer, 20, clForest, 3, clWater, 2, clHill, 0, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clHill, 7)],
| 257| 257|  clForest,
| 258| 258|  forestTrees * 0.35);
| 259|    |- 
|    | 259|+
| 260| 260| createStragglerTrees(
| 261| 261| 	[oWinterPine],
| 262| 262| 	[avoidClasses(clForest, 2, clHill, 1, clPlayer, 12, clWater, 3, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clForest, 7)],
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 262| 262| 	[avoidClasses(clForest, 2, clHill, 1, clPlayer, 12, clWater, 3, clFarm, 3), stayClasses(clSnow, 0), nearClasses(clForest, 7)],
| 263| 263| 	clForest,
| 264| 264| 	stragglerTrees * 0.35);
| 265|    |-	
|    | 265|+
| 266| 266| Engine.SetProgress(65);
| 267| 267| 
| 268| 268| g_Map.log("Creating stone mines");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 267| 267| 
| 268| 268| g_Map.log("Creating stone mines");
| 269| 269| createMines(
| 270|    |- [
|    | 270|+	[
| 271| 271|   [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
| 272| 272|  ],
| 273| 273|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 25, clRock, 25, clHill, 3, clFarm, 5),
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 2 spaces.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 268| 268| g_Map.log("Creating stone mines");
| 269| 269| createMines(
| 270| 270|  [
| 271|    |-  [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
|    | 271|+		[new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
| 272| 272|  ],
| 273| 273|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 25, clRock, 25, clHill, 3, clFarm, 5),
| 274| 274|  clRock);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 269| 269| createMines(
| 270| 270|  [
| 271| 271|   [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
| 272|    |- ],
|    | 272|+	],
| 273| 273|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 25, clRock, 25, clHill, 3, clFarm, 5),
| 274| 274|  clRock);
| 275| 275| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 270| 270|  [
| 271| 271|   [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
| 272| 272|  ],
| 273|    |- avoidClasses(clWater, 3, clForest, 1, clPlayer, 25, clRock, 25, clHill, 3, clFarm, 5),
|    | 273|+	avoidClasses(clWater, 3, clForest, 1, clPlayer, 25, clRock, 25, clHill, 3, clFarm, 5),
| 274| 274|  clRock);
| 275| 275| 
| 276| 276| g_Map.log("Creating metal mines");
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 271| 271|   [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)]
| 272| 272|  ],
| 273| 273|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 25, clRock, 25, clHill, 3, clFarm, 5),
| 274|    |- clRock);
|    | 274|+	clRock);
| 275| 275| 
| 276| 276| g_Map.log("Creating metal mines");
| 277| 277| createMines(
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 275| 275| 
| 276| 276| g_Map.log("Creating metal mines");
| 277| 277| createMines(
| 278|    |- [
|    | 278|+	[
| 279| 279|   [new SimpleObject(oMetalLarge, 1,1, 0,4)]
| 280| 280|  ],
| 281| 281|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 2 spaces.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 276| 276| g_Map.log("Creating metal mines");
| 277| 277| createMines(
| 278| 278|  [
| 279|    |-  [new SimpleObject(oMetalLarge, 1,1, 0,4)]
|    | 279|+		[new SimpleObject(oMetalLarge, 1,1, 0,4)]
| 280| 280|  ],
| 281| 281|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
| 282| 282|  clMetal
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 276| 276| g_Map.log("Creating metal mines");
| 277| 277| createMines(
| 278| 278|  [
| 279|    |-  [new SimpleObject(oMetalLarge, 1,1, 0,4)]
|    | 279|+  [new SimpleObject(oMetalLarge, 1, 1, 0,4)]
| 280| 280|  ],
| 281| 281|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
| 282| 282|  clMetal
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 276| 276| g_Map.log("Creating metal mines");
| 277| 277| createMines(
| 278| 278|  [
| 279|    |-  [new SimpleObject(oMetalLarge, 1,1, 0,4)]
|    | 279|+  [new SimpleObject(oMetalLarge, 1,1, 0, 4)]
| 280| 280|  ],
| 281| 281|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
| 282| 282|  clMetal
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 277| 277| createMines(
| 278| 278|  [
| 279| 279|   [new SimpleObject(oMetalLarge, 1,1, 0,4)]
| 280|    |- ],
|    | 280|+	],
| 281| 281|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
| 282| 282|  clMetal
| 283| 283| );
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 278| 278|  [
| 279| 279|   [new SimpleObject(oMetalLarge, 1,1, 0,4)]
| 280| 280|  ],
| 281|    |- avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
|    | 281|+	avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
| 282| 282|  clMetal
| 283| 283| );
| 284| 284| Engine.SetProgress(70);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 1 tab but found 1 space.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 279| 279|   [new SimpleObject(oMetalLarge, 1,1, 0,4)]
| 280| 280|  ],
| 281| 281|  avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 3, clFarm, 5),
| 282|    |- clMetal
|    | 282|+	clMetal
| 283| 283| );
| 284| 284| Engine.SetProgress(70);
| 285| 285| 
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 322| 322| 	],
| 323| 323| 	avoidClasses(clWater, 3, clForest, 0, clPlayer, 25, clHill, 3, clFood, 10),
| 324| 324| 	clFood);
| 325|    |-	
|    | 325|+
| 326| 326| createFood(
| 327| 327| 	[
| 328| 328| 		[new SimpleObject(oBear, 1,1, 0,4)]
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 325| 325| 	
| 326| 326| createFood(
| 327| 327| 	[
| 328|    |-		[new SimpleObject(oBear, 1,1, 0,4)]
|    | 328|+		[new SimpleObject(oBear, 1, 1, 0,4)]
| 329| 329| 	],
| 330| 330| 	[
| 331| 331| 		scaleByMapSize(1, 7)
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/alpine_valley.js
| 325| 325| 	
| 326| 326| createFood(
| 327| 327| 	[
| 328|    |-		[new SimpleObject(oBear, 1,1, 0,4)]
|    | 328|+		[new SimpleObject(oBear, 1,1, 0, 4)]
| 329| 329| 	],
| 330| 330| 	[
| 331| 331| 		scaleByMapSize(1, 7)

binaries/data/mods/public/maps/random/alpine_valley.js
|  95| }else·if·(env·==·1)
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Closing curly brace appears on the same line as the subsequent block.

binaries/data/mods/public/maps/random/alpine_valley.js
| 109| {
|    | [NORMAL] ESLintBear (brace-rules/brace-on-same-line):
|    | Closing curly brace appears on the same line as the subsequent block.

binaries/data/mods/public/maps/random/alpine_valley.js
|  23| var·oAleppoPine·=·"gaia/flora_tree_aleppo_pine"
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/maps/random/alpine_valley.js
|  29| var·oBear·=·"gaia/fauna_bear"
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
|    | [NORMAL] ESLintBear (space-unary-ops):
|    | Unexpected space after unary operator '-'.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  32|  32|  * Constants needed for heightmap_manipulation.js
|  33|  33|  */
|  34|  34| const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE; // Engine limit, Roughly 700 meters
|  35|    |-const MIN_HEIGHT = - SEA_LEVEL;
|    |  35|+const MIN_HEIGHT = -SEA_LEVEL;
|  36|  36| 
|  37|  37| /**
|  38|  38|  * Length of one tile of the terrain grid in metres.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  68|  68| 	let obstructionSize =
|  69|  69| 		obstruction.Static ?
|  70|  70| 			new Vector2D(obstruction.Static["@depth"], obstruction.Static["@width"]) :
|  71|    |-		// Used for gates, should consider the position too
|    |  71|+			// Used for gates, should consider the position too
|  72|  72| 		obstruction.Obstructions ?
|  73|  73| 			new Vector2D(
|  74|  74| 				Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 2.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  69|  69| 		obstruction.Static ?
|  70|  70| 			new Vector2D(obstruction.Static["@depth"], obstruction.Static["@width"]) :
|  71|  71| 		// Used for gates, should consider the position too
|  72|    |-		obstruction.Obstructions ?
|    |  72|+			obstruction.Obstructions ?
|  73|  73| 			new Vector2D(
|  74|  74| 				Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|  75|  75| 				Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  70|  70| 			new Vector2D(obstruction.Static["@depth"], obstruction.Static["@width"]) :
|  71|  71| 		// Used for gates, should consider the position too
|  72|  72| 		obstruction.Obstructions ?
|  73|    |-			new Vector2D(
|    |  73|+				new Vector2D(
|  74|  74| 				Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|  75|  75| 				Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|  76|  76| 			new Vector2D(0, 0);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  71|  71| 		// Used for gates, should consider the position too
|  72|  72| 		obstruction.Obstructions ?
|  73|  73| 			new Vector2D(
|  74|    |-				Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|    |  74|+					Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|  75|  75| 				Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|  76|  76| 			new Vector2D(0, 0);
|  77|  77| 
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 5 tabs but found 4.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  72|  72| 		obstruction.Obstructions ?
|  73|  73| 			new Vector2D(
|  74|  74| 				Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|  75|    |-				Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|    |  75|+					Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|  76|  76| 			new Vector2D(0, 0);
|  77|  77| 
|  78|  78| 	return obstructionSize.div(TERRAIN_TILE_SIZE).add(new Vector2D(2, 2).mult(margin));
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|  73|  73| 			new Vector2D(
|  74|  74| 				Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|  75|  75| 				Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|  76|    |-			new Vector2D(0, 0);
|    |  76|+				new Vector2D(0, 0);
|  77|  77| 
|  78|  78| 	return obstructionSize.div(TERRAIN_TILE_SIZE).add(new Vector2D(2, 2).mult(margin));
|  79|  79| }
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '/*' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
| 249| 249| /**
| 250| 250|  * Create an avoid constraint for the given classes by the given distances
| 251| 251|  */
| 252|    |-function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
|    | 252|+function avoidClasses(/* class1, dist1, class2, dist2, etc*/)
| 253| 253| {
| 254| 254| 	let ar = [];
| 255| 255| 	for (let i = 0; i < arguments.length/2; ++i)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '/*' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
| 265| 265| /**
| 266| 266|  * Create a stay constraint for the given classes by the given distances
| 267| 267|  */
| 268|    |-function stayClasses(/*class1, dist1, class2, dist2, etc*/)
|    | 268|+function stayClasses(/* class1, dist1, class2, dist2, etc*/)
| 269| 269| {
| 270| 270| 	let ar = [];
| 271| 271| 	for (let i = 0; i < arguments.length/2; ++i)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '/*' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
| 281| 281| /**
| 282| 282|  * Create a constraint to stay near the given classes by the given distances
| 283| 283|  */
| 284|    |-function nearClasses(/*class1, dist1, class2, dist2, etc*/)
|    | 284|+function nearClasses(/* class1, dist1, class2, dist2, etc*/)
| 285| 285| {
| 286| 286| 	let ar = [];
| 287| 287| 	for (let i = 0; i < arguments.length/2; ++i)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '/*' in comment.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/library.js
| 297| 297| /**
| 298| 298|  * Create a border constraint for the given classes by the given distances
| 299| 299|  */
| 300|    |-function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/)
|    | 300|+function borderClasses(/* class1, idist1, odist1, class2, idist2, odist2, etc*/)
| 301| 301| {
| 302| 302| 	let ar = [];
| 303| 303| 	for (let i = 0; i < arguments.length/3; ++i)

binaries/data/mods/public/maps/random/rmgen/library.js
|  75| »   »   »   »   Object.keys(obstruction.Obstructions).reduce((width,·key)·=>·width·+·+obstruction.Obstructions[key]["@width"],·0))·:
|    | [NORMAL] JSHintBear:
|    | Confusing plusses.

Link to build: https://jenkins.wildfiregames.com/job/differential/503/display/redirect

Successful build - Chance fights ever on the side of the prudent.

Link to build: https://jenkins.wildfiregames.com/job/differential/504/display/redirect

aeonios updated this revision to Diff 6565.May 18 2018, 2:16 AM

Minor fixes, reduce redundant painting. Also simplified the mountain range generator to use a terrain painter rather than a layered painter (for which there was no point).

Successful build - Chance fights ever on the side of the prudent.

Link to build: https://jenkins.wildfiregames.com/job/differential/505/display/redirect

I am a fan of the original map (at least the one from the last three years), so if there are changes, they should be definite improvements and I'm not sure they are.
(It's hard to find out exactly what changed because everything was changed and everything moved.)

There are maps with 100% snow coverage adjacent to areas with 0% coverage which seems unrealistic, while I like the snow patches on the current revision much.
These mountain types are arguably better than what the map currently does, but they are also overused on many maps and this would become a map where they are used in 50% of the map area.
If they had to be used, they could be smaller.

I'm also personally bored by "random resources + random mountains + random lakes" maps that only differ by the chosen set of models and textures and would prefer to invest time on unique features.
The main objective was to simplify the mountainrange logic?

binaries/data/mods/public/maps/random/alpine_valley.js
167

This is Alpine Valleys. Alpine Lakes exists already.

binaries/data/mods/public/maps/random/rmgen-common/mountain_range_builder.js
2

I had put the prottoype into the mapfile rather than the library because maps should be unique and I don't think a second map will use the exact same concept anytime soon.

binaries/data/mods/public/maps/random/rmgen/library.js
295

I wanted to remove these proxies rather than add new (see last 6 months of revision history on this file).
The argument listing could be moved to the constructor.

binaries/data/mods/public/maps/random/rmgen/math.js
60

We have a function picking a random coordinate already in g_Map.
The library complexity should be reduced while keeping the same features.

In D1497#61355, @elexis wrote:

I am a fan of the original map (at least the one from the last three years), so if there are changes, they should be definite improvements and I'm not sure they are.
(It's hard to find out exactly what changed because everything was changed and everything moved.)

You could just try generating maps with it and see what it produces. :P

There are maps with 100% snow coverage adjacent to areas with 0% coverage which seems unrealistic, while I like the snow patches on the current revision much.
These mountain types are arguably better than what the map currently does, but they are also overused on many maps and this would become a map where they are used in 50% of the map area.
If they had to be used, they could be smaller.

Admittedly it's sub-optimal. The handcrafted version made a much more specific use of the contrast between snow and grass, which is unfortunately probably not practical to reproduce using mapgen. The maps are pretty boring without that contrast, however. I'm working on trying to improve it somehow or other, but I'm ultimately not sure what I'll be able to achieve by it.

I'm also personally bored by "random resources + random mountains + random lakes" maps that only differ by the chosen set of models and textures and would prefer to invest time on unique features.

Maps like what? I've played around with a lot of the different mapgen maps and none of them are even close to this.

The main objective was to simplify the mountainrange logic?

Well, no. Originally I had intended to improve ardennes forest to more closely resemble the real thing, but I wanted long, contiguous (pathable) mountain ranges and didn't have the means to generate them. The mountain range generator in this map came the closest to what I wanted but was still a far cry from producing anything acceptable, since the mountains it generated were more like straight line cliffs and it would never produce more than say 2 or 3 lines at most even with over 1000 possible edges to start with. My simplifications were more or less just a side effect of getting it to produce more ranges more consistently and making them look more mountain-like. This method also reduces collisions between ranges so they don't cross each other or get squashed together nearly as much, which was a major problem with the old method in the event that its sanity checks were removed.

niektb added a subscriber: niektb.EditedMay 18 2018, 10:11 AM

One thing that always bugged me was that Alpine Valleys only used one single texture for the mountain (yet never came around to actually change that), any change you could change that for this RMS? :) (unless everybody else disagrees with me ofc :))

Btw, I see a little texture glitch (?) on the very first screenshot, left-side little to the bottom. The transition from snow to grass features two perfect straight lines and a perfect straight angle connects them (if you understand what I mean)

Also, it seems like you use only one texture for everything (so one snow texture, one grass texture etc). Maybe introduce a little more eyecandy there?

You can also try to create a more fluent transition from grass to snow by using a intermediate bordering texture (a technique I used often in creating maps)

I think elexis means maps with triggers/special map features that play completely different

aeonios marked 2 inline comments as done.May 18 2018, 11:03 AM
In D1497#61364, @niektb wrote:

One thing that always bugged me was that Alpine Valleys only used one single texture for the mountain (yet never came around to actually change that), any change you could change that for this RMS? :) (unless everybody else disagrees with me ofc :))

I hadn't really thought about it, but you're right the mountain texture is pretty monotonous. I'll look into that next.

Btw, I see a little texture glitch (?) on the very first screenshot, left-side little to the bottom. The transition from snow to grass features two perfect straight lines and a perfect straight angle connects them (if you understand what I mean)

Eh, that's a limitation of the map generator interface. Ultimately I decided to split it back up into summer and winter variants rather than trying to get the snow and grass to mix in any sort of coherent way.

Also, it seems like you use only one texture for everything (so one snow texture, one grass texture etc). Maybe introduce a little more eyecandy there?

Yes I've already done a bunch of work in adding variety to the ground textures. It became more or less a necessity when splitting them into summer and winter.

I think elexis means maps with triggers/special map features that play completely different

I don't think this map ever had any such thing, but my audience is ranked/serious games. I'm not really interested in nonsense like Jebel Barkal. Of course I'm not against developing library functionality to support those sorts of maps, but I'm not really interested in creating any myself.

binaries/data/mods/public/maps/random/alpine_valley.js
167

I considered removing it and just calling this "The Alps". Alps maps without lakes are pretty awkward anyway.

binaries/data/mods/public/maps/random/rmgen-common/mountain_range_builder.js
2

I put it into a library because I fully intend to use it elsewhere, albeit with very different settings.

binaries/data/mods/public/maps/random/rmgen/library.js
295

NO. No no no no no no no no no no. To be fair I think these proxies should be moved to Constraint.js rather than having them clutter up the main library, but constructing a new instance for every single constraint would be insane. These proxies are extremely convenient, not having them isn't a real option. Good libraries should make coding easier, not harder.

binaries/data/mods/public/maps/random/rmgen/math.js
60

That's true. I could probably just move this to g_Map and have it use the existing random point function. I wanted a way to generate large numbers of points with one line of code though. I don't really want to have to use a loop every time I want multiple points. Also the existing features are.. lacking in a lot of ways. I had to make custom implementations of 'createbumps' and 'createpatches' because the library versions were more or less useless.

I'm also personally bored by "random resources + random mountains + random lakes" maps that only differ by the chosen set of models and textures and would prefer to invest time on unique features.

Maps like what? I've played around with a lot of the different mapgen maps and none of them are even close to this.

It seems most maps are just different combinations of randomized resources lakes and hills and only differ at textures and models.
What I like to see for 0 A.D. are truly unique maps that are entirely different than every other map. Ambush in Alpha 19, Red Sea, Mediterranean in Alpha 20, Danubius and Extinct Volcano in A21, Jebel Barkal, Elephantine, Lower Nubia, Hellas in Alpha 22 for instance.
(There are considerably many players who just want mainland forever though)

The uniqueness part of this map (patched or not) is the mountainranges.
The patched variant visually reminds me of Empire and Stronghold.
I think texturing can be improved with more patches of textures and combining more textures in the terrain variables.

What I really liked about this map and would prefer to keep is the narrow gaps, that there are only one or two gaps where players can meet and the small mountains spread everywhere:


binaries/data/mods/public/maps/random/rmgen/library.js
295

NO. No no no no no no no no no no.

YES, yes yes yes yes yes yes yes yes yes yes

As I said the argument listing should be moved to the constructor if we need this feature:
new NearTileClassesConstraint(clFoo, 2, clBar, 3)

These proxies are extremely convenient, not having them isn't a real option.

But you didn't notice that most proxies like paintClasses were removed already?

Good libraries should make coding easier, not harder.

Making it easier also implies reducing the complexity while keeping the same features rather than extending the complexity for no reaosn.

constructing a new instance for every single constraint would be insane

Claiming that this function doesn't create a constraint is insane for each function too.

aeonios marked 2 inline comments as done.May 18 2018, 1:11 PM

It seems most maps are just different combinations of randomized resources lakes and hills and only differ at textures and models.
What I like to see for 0 A.D. are truly unique maps that are entirely different than every other map. Ambush in Alpha 19, Red Sea, Mediterranean in Alpha 20, Danubius and Extinct Volcano in A21, Jebel Barkal, Elephantine, Lower Nubia, Hellas in Alpha 22 for instance.
(There are considerably many players who just want mainland forever though)

Most of the maps aren't very random at all. They use a very strict construction formula that basically only differs in the number of players placed on the map. A lot of the maps you mention here have terrible gameplay as well. Mediterranean is bad in every imaginable way. Extinct Volcano is hideously ugly and the texture creates a false impression of cliffs and things where there are none. Aside from the city, Jebel Barkal is an extremely boring map, and also not applicable to ranked games. Elephantine is basically always the same map, nothing random about it. Same with lower nubia, with the additional problem that it's horribly imbalanced to the point of being unplayable for whoever gets stuck in the north. Hellas is kind of interesting but it often generates terrain that's extremely frustrating to play on.

Out of all of those you listed only Red Sea and Ambush actually generate good, playable maps, and out of those only Ambush actually creates real interesting variety. What's the point of a 'random' map that isn't actually random?

The uniqueness part of this map (patched or not) is the mountainranges.
The patched variant visually reminds me of Empire and Stronghold.
I think texturing can be improved with more patches of textures and combining more textures in the terrain variables.
What I really liked about this map and would prefer to keep is the narrow gaps, that there are only one or two gaps where players can meet and the small mountains spread everywhere:

Empire and stronghold are strict formula maps. They basically always have the same number of entrances to every base and area. This script varies widely, sometimes it produces maps that are heavily choked and sometimes producing maps that are more open. The non-patched version wasn't much different. The spacing between the freestanding mountains in the patched version is only 4 tiles. A lot of the time the ranges also curve together and close things off almost entirely.

Take this variant for example:


South has a lot of chokepoints but they're all tight spaces, north has only one larger chokepoint. The old version does put the "hill" things closer to the starting points, but I gave mountains a minimum distance purposefully to ensure that players would have room to build things.

As for the resources being random, that's not something I decided on, it's a direct consequence of the resource placing script not offering any customizations and also of object placement in general being unreliable. The old version used its own resource placement code, but in messing with it I found that it would very often end up with little to no metal or stone, or way too much, or way too much close to one player and none next to the other. The library functions aren't any better, either. Because they frequently fail to place objects and do absolutely nothing to ensure the number or distribution of resources that actually succeed in being placed, there's no way to guarantee anything regarding resources or balance. That's something that seriously needs fixing but I haven't gotten around to looking at it.

binaries/data/mods/public/maps/random/rmgen/library.js
295

Hmm, let's see.. I could type "nearClasses(x, 1, y, 2, z, 3)" or I could type "new NearTileClassesConstraint(x, 1, y, 2, z, 3)". One of those things is short and sweet and the other is incredibly asinine.

I don't know anything about paintClasses but I do know that if you feed a texture array into a layeredpainter like you would for random painting with a terrainpainter it unceremoniously crashes. If paintclasses would allow you to avoid that then getting rid of them was the wrong thing to do.

In terms of complexity the wrapper functions don't really add any, and in terms of performance I suspect that both ways would end up doing the exact same thing. Except that forcing every map to use the raw classes would require rewriting every single map and also require a serious restructuring of the constraint classes that would accomplish exactly nothing except to increase the amount of typing and likelihood of error on the part of map script designers.

There are plenty of features that are either broken or suck, and this isn't one of them.

aeonios updated this revision to Diff 6567.May 18 2018, 1:38 PM

Moved back to summer/winter variants and improved the texture variation and the way decorations are placed.

Rearranged some of the library functions to clean things up.

Removed the old alpine lakes/valley scripts and replaced them with the current script, renamed to 'the_high_alps'.

Added a new preview image for the script.

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Default...
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/Constraint.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/Constraint.js
|   4|   4| 
|   5|   5| /**
|   6|   6|  * The following functions are for easily creating constraints in batches.
|   7|    |- */ 
|    |   7|+ */
|   8|   8| 
|   9|   9| /**
|  10|  10|  * Create an avoid constraint for the given classes by the given distances
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/Constraint.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/Constraint.js
|  86|  86| function AndConstraint(constraints)
|  87|  87| {
|  88|  88| 	if (constraints instanceof Array)
|  89|    |-		this.constraints = constraints
|    |  89|+		this.constraints = constraints;
|  90|  90| 	else if (!constraints)
|  91|  91| 		this.constraints = [];
|  92|  92| 	else
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/Constraint.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/Constraint.js
| 136| 136| 
| 137| 137| AvoidAreasConstraint.prototype.allows = function(position)
| 138| 138| {
| 139|    |-	return this.areas.every(area => !area.contains(position))
|    | 139|+	return this.areas.every(area => !area.contains(position));
| 140| 140| };
| 141| 141| 
| 142| 142| /**

binaries/data/mods/public/maps/random/rmgen/Constraint.js
|  89| »   »   this.constraints·=·constraints
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/maps/random/rmgen/Constraint.js
| 139| »   return·this.areas.every(area·=>·!area.contains(position))
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/RandomMap.js
|    |++++| /mnt/data/jenkins-phabricator/workspace/differential/binaries/data/mods/public/maps/random/rmgen/RandomMap.js
| 217| 217| 	for (let i = 0; i < pointCount; ++i)
| 218| 218| 		points[i] = this.randomCoordinate(passableOnly);
| 219| 219| 	return points;
| 220|    |-}
|    | 220|+};
| 221| 221| 
| 222| 222| /**
| 223| 223|  * Returns a random point on the map.

binaries/data/mods/public/maps/random/rmgen/RandomMap.js
| 220| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

Link to build: https://jenkins.wildfiregames.com/job/differential/507/display/redirect

Eh, that's a limitation of the map generator interface. Ultimately I decided to split it back up into summer and winter variants rather than trying to get the snow and grass to mix in any sort of coherent way.

Nah, that's not what I mean. I know 0 A.D. blends textures really poorly and that the Random Map painter is even worse at painting textures. (I've written Random Maps myself too :) )
I was trying to describe the marked area in my image :P

Using LayeredPainters instead of TerrainPainters and painting things with patches helps with that.

binaries/data/mods/public/maps/random/rmgen/Constraint.js
22 ↗(On Diff #6567)

Into the constructors of the constraints. The contraints would have to loop then I guess.
Also I'd take this as a single diff.

binaries/data/mods/public/maps/random/rmgen/RandomMap.js
220 ↗(On Diff #6567)

Unneeded library complexity
new Array(3).fill(0).map(i => g_Map.randomCoordinate(passableOnly))
(in case the fill is needed).

In D1497#61397, @niektb wrote:

Eh, that's a limitation of the map generator interface. Ultimately I decided to split it back up into summer and winter variants rather than trying to get the snow and grass to mix in any sort of coherent way.

Nah, that's not what I mean. I know 0 A.D. blends textures really poorly and that the Random Map painter is even worse at painting textures. (I've written Random Maps myself too :) )
I was trying to describe the marked area in my image :P

Oh that. That's what happens when it runs into a constraint, which in this case was "minimum distance to other snow area". The real problem is what happens if I remove that constraint. :| There was really no winning.

In D1497#61398, @elexis wrote:

Using LayeredPainters instead of TerrainPainters and painting things with patches helps with that.

Eh, I -am- painting with patches here. The problem with a layeredpainter is that it doesn't know the difference between "snow bordering mountains" and "snow bordering grass". That's an important distinction, assuming that I could even find a good transition texture to use between snow and grass, which is dubious at best.

elexis requested changes to this revision.Jan 4 2019, 6:55 PM

Refs https://wildfiregames.com/forum/index.php?/topic/20392-alpine-valleys-rework/

As mentioned, the map depicted on the screenshot is an entirely different one than the overwritten one and IMO the overwritten one is worth preserving in both artistic, but especially gameplay character (only actually random labyrinth map). It looks more like a replacement for Alpine Lakes than Alpine Valleys.
If there is a strong opinion on the way the labyrinth / mountains are painted, that could be discussed maybe.
But what is depicted on the (representative?) screenshot is essentially a new, different map, not an improvement, so I'd recommend to introduce it as a new map and have the current Alpine Valleys untouched or only refactored or improved without reducing its labyrinth character.

This revision now requires changes to proceed.Jan 4 2019, 6:55 PM