public int Step( TectonicParameters parameters ) { // Determine whether this hex should be sunk bool sink = Random.value < parameters.SinkProbability; int result = parameters.LandBudget; // For each region . . . for (int i = 0; i < _regions.Count; i++) { MapRegionRect region = _regions[i]; // Get a chunk size to use within the bounds of the region based // of the minimum and maximum chunk sizes. int regionDensity = Random.Range( parameters.RegionDensityMin, parameters.RegionDensityMax + 1 ); // If hex is to be sunk, sink hex and decrement decrement // land budget if sinking results in a hex below water // level. if (sink) { result = SinkTerrain( result, regionDensity, region, parameters.HighRiseProbability, parameters.ElevationMin, parameters.WaterLevelGlobal, parameters.JitterProbability, parameters.HexSize ); } // Else, raise hex and increment land budget if raising // results in a hex above the water level. else { result = RaiseTerrain( result, regionDensity, region, parameters.HighRiseProbability, parameters.ElevationMax, parameters.WaterLevelGlobal, parameters.JitterProbability, parameters.HexSize ); if (result == 0) { return(result); } } } return(result); }
/// <summary> /// Generate a HexMap using the standard RootGen algorithm. /// </summary> /// <param name="config"> /// The configuration data for the map to be generated. /// </param> /// <returns> ///A randomly generated HexMap object. /// </returns> public HexMap GenerateMap( RootGenConfig config, bool editMode = true ) { string diagnostics = "Generate Map Performance Diagnostics\n\n"; HexMap result = HexMap.CreateHexMapGameObject(); int seed; if (config.useFixedSeed) { seed = config.seed; } else { config.seed = Random.Range(0, int.MaxValue); config.seed ^= (int)System.DateTime.Now.Ticks; config.seed ^= (int)Time.time; config.seed &= int.MaxValue; seed = config.seed; } // Snapshot the initial random state before consuming the random // sequence. Random.State snapshot = RandomState.Snapshot(seed); result.Initialize( new Rect(0, 0, config.width, config.height), seed, config.hexSize, config.wrapping, editMode ); foreach (Hex hex in result.Hexes) { hex.WaterLevel = config.waterLevel; } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); HexMapTectonics hexMapTectonics = new HexMapTectonics( result, config.regionBorder, config.mapBorderX, config.mapBorderZ, config.numRegions ); int landBudget = Mathf.RoundToInt( result.SizeSquared * config.landPercentage * 0.01f ); TectonicParameters tectonicParameters = new TectonicParameters( config.hexSize, config.highRiseProbability, config.jitterProbability, config.sinkProbability, config.elevationMax, config.elevationMin, config.waterLevel, landBudget, config.maximumRegionDensity, config.minimumRegionDensity ); string logString = "Tectonic Statistics\n"; for (int i = 0; i < MAX_TECTONIC_STEPS; i++) { tectonicParameters.LandBudget = hexMapTectonics.Step( tectonicParameters ); //result.Draw(config.hexSize); logString += "Step " + i + ", Land Hexes: " + result.LandHexes.Count + " / Land Budget: " + tectonicParameters.LandBudget + " Total: " + (result.LandHexes.Count + tectonicParameters.LandBudget) + "\n"; if (tectonicParameters.LandBudget == 0) { break; } } RootLog.Log(logString, Severity.Information, "Diagnostics"); // If land budget is greater than 0, all land hexes specified to // be allocated were not allocated successfully. Log a warning, // decrement the remaining land budget from the result, and return // the result as the number of land hexes allocated. if (tectonicParameters.LandBudget > 0) { RootLog.Log( "Failed to use up " + tectonicParameters.LandBudget + " land budget.", Severity.Warning, "MapGenerator" ); } stopwatch.Stop(); diagnostics += "Generate Tectonics: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); HexMapErosion erosion = new HexMapErosion(result); int erodibleHexes = erosion.ErodibleHexes.Count; // Calculate the target number of uneroded hexes. int targetUnerodedHexes = (int)( erodibleHexes * (100 - config.erosionPercentage) * 0.01f ); while (erosion.ErodibleHexes.Count > targetUnerodedHexes) { erosion.Step( config.hexSize ); } stopwatch.Stop(); diagnostics += "Generate Erosion: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); HexMapClimate hexMapClimate = new HexMapClimate( result, config.startingMoisture ); ClimateParameters climateParameters = new ClimateParameters( config.hemisphere, config.windDirection, config.evaporationFactor, config.highTemperature, config.lowTemperature, config.precipitationFactor, config.runoffFactor, config.seepageFactor, config.temperatureJitter, config.windStrength, config.hexSize, config.elevationMax, config.waterLevel ); for (int i = 0; i < config.initialClimateSteps; i++) { hexMapClimate.Step(climateParameters); } List <ClimateData> climates = hexMapClimate.List; stopwatch.Stop(); diagnostics += "Generate Climate: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); HexMapRivers hexMapRivers = new HexMapRivers( result, climates, config.waterLevel, config.elevationMax ); for (int i = 0; i < config.numInitialRivers; i++) { hexMapRivers.StartRiver(); } for (int i = 0; i < config.numInitialRiverSteps; i++) { hexMapRivers.Step( config.waterLevel, config.elevationMax, config.extraLakeProbability, config.hexSize, climates ); } result.RiverDigraph = hexMapRivers.RiverDigraph; stopwatch.Stop(); diagnostics += "Generate Rivers: " + stopwatch.Elapsed + "\n"; stopwatch.Start(); hexMapClimate.RefreshTerrainTypes( climateParameters, result.RiverDigraph ); stopwatch.Stop(); diagnostics += "Assign Terrain Types: " + stopwatch.Elapsed + "\n"; RootLog.Log( diagnostics, Severity.Information, "Diagonstics" ); // Restore the snapshot of the random state taken before consuming // the random sequence. Random.state = snapshot; return(result); }