From b3dc2d1258cc86e1a681c3829fe52d26a03dc996 Mon Sep 17 00:00:00 2001 From: Grimsace Date: Wed, 4 Feb 2026 15:15:47 -0600 Subject: [PATCH] fixed rng --- main.go | 23 ++++++++++++----------- roads.go | 28 ++++++++++++++-------------- seed.go | 17 +++++++++++++++++ 3 files changed, 43 insertions(+), 25 deletions(-) create mode 100644 seed.go diff --git a/main.go b/main.go index ccf4b99..39bfa55 100644 --- a/main.go +++ b/main.go @@ -110,16 +110,16 @@ func main() { if canvasImg.Image == nil || heightmapImg.Image == nil { // Initial image generation - - noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, settings.Seed) + seedProvider := NewSeedProvider(settings.Seed) + noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, seedProvider.Next()) var lakeImage image.Image - lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed) + lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, seedProvider.Next()) var riverImage image.Image - riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, settings.Seed, noiseImg) + riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, seedProvider.Next(), noiseImg) finalImage := riverImage.(*image.RGBA) @@ -134,7 +134,7 @@ func main() { } allWaterPixels := append(flatLakePixels, riverPixels...) - roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels) + roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels, seedProvider.Next()) for y := 0; y < roadImage.Bounds().Max.Y; y++ { for x := 0; x < roadImage.Bounds().Max.X; x++ { r, g, b, a := roadImage.At(x, y).RGBA() @@ -144,7 +144,7 @@ func main() { } } - treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed) + treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, seedProvider.Next()) darkenedHeightmap := DarkenLakeAreas(noiseImg, allWaterPixels) @@ -378,13 +378,14 @@ func main() { steps := 8 currentStep := 0 + seedProvider := NewSeedProvider(settings.Seed) // Step 1: Generating Heightmap currentStep++ fyne.Do(func() { progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Heightmap", currentStep, steps)) progressBar.SetValue(float64(currentStep) / float64(steps)) }) - noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, settings.Seed) + noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, seedProvider.Next()) // Step 2: Generating Lakes currentStep++ @@ -393,7 +394,7 @@ func main() { progressBar.SetValue(float64(currentStep) / float64(steps)) }) var lakeImage image.Image - lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed) + lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, seedProvider.Next()) // Step 3: Generating Rivers currentStep++ @@ -402,7 +403,7 @@ func main() { progressBar.SetValue(float64(currentStep) / float64(steps)) }) var riverImage image.Image - riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, settings.Seed, noiseImg) + riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, seedProvider.Next(), noiseImg) finalImage := riverImage.(*image.RGBA) @@ -419,7 +420,7 @@ func main() { progressBar.SetValue(float64(currentStep) / float64(steps)) }) var roadImage *image.RGBA - roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels) // Draw roadImage over finalImage + roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels, seedProvider.Next()) // Draw roadImage over finalImage for y := 0; y < roadImage.Bounds().Max.Y; y++ { for x := 0; x < roadImage.Bounds().Max.X; x++ { r, g, b, a := roadImage.At(x, y).RGBA() @@ -451,7 +452,7 @@ func main() { progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Trees", currentStep, steps)) progressBar.SetValue(float64(currentStep) / float64(steps)) }) - treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed) + treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, seedProvider.Next()) // Step 8: Finalizing Images currentStep++ diff --git a/roads.go b/roads.go index 3b8b9bf..4c5cc55 100644 --- a/roads.go +++ b/roads.go @@ -22,7 +22,7 @@ type Road struct { Importance int } -func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point) ([]image.Point, *image.RGBA) { +func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point, seed int64) ([]image.Point, *image.RGBA) { img := image.NewRGBA(image.Rect(0, 0, width, height)) // Transparent background for y := 0; y < height; y++ { @@ -31,15 +31,15 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, } } - rand.Seed(settings.Seed) + randSrc := rand.New(rand.NewSource(seed)) roadColor := color.RGBA{R: 139, G: 69, B: 19, A: 255} - pois := generatePOIs(width, height, settings, allWaterPixels) + pois := generatePOIs(width, height, settings, allWaterPixels, randSrc) if len(pois) == 0 { return nil, img } - roads := connectPOIs(pois, width, height, settings) + roads := connectPOIs(pois, width, height, settings, randSrc) assignRoadWidths(roads, settings) var allRoadPixels []image.Point @@ -51,7 +51,7 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, return allRoadPixels, img } -func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.Point) []*PointOfInterest { +func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.Point, randSrc *rand.Rand) []*PointOfInterest { numPOIs := settings.NumRoads / 2 if numPOIs == 0 { return nil @@ -80,24 +80,24 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image. found := false for j := 0; j < 100; j++ { // 100 retries to find a land spot if i < numExits { - side := rand.Intn(4) + side := randSrc.Intn(4) switch side { case 0: // Top - x = rand.Intn(width) + x = randSrc.Intn(width) y = 0 case 1: // Bottom - x = rand.Intn(width) + x = randSrc.Intn(width) y = height - 1 case 2: // Left x = 0 - y = rand.Intn(height) + y = randSrc.Intn(height) case 3: // Right x = width - 1 - y = rand.Intn(height) + y = randSrc.Intn(height) } } else { - angle := rand.Float64() * 2 * math.Pi - r := rand.Float64() * radius + angle := randSrc.Float64() * 2 * math.Pi + r := randSrc.Float64() * radius x = int(float64(centerX) + r*math.Cos(angle)) y = int(float64(centerY) + r*math.Sin(angle)) } @@ -115,7 +115,7 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image. return pois } -func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings) []*Road { +func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, randSrc *rand.Rand) []*Road { if len(pois) < 2 { return nil } @@ -194,7 +194,7 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings) midX := (fromNode.X + closest.X) / 2 midY := (fromNode.Y + closest.Y) / 2 dist := math.Sqrt(math.Pow(float64(fromNode.X-closest.X), 2) + math.Pow(float64(fromNode.Y-closest.Y), 2)) - offset := dist * (settings.RoadCurvyness / 100.0) * (rand.Float64() - 0.5) + offset := dist * (settings.RoadCurvyness / 100.0) * (randSrc.Float64() - 0.5) controlX := int(float64(midX) + offset) controlY := int(float64(midY) + offset) diff --git a/seed.go b/seed.go new file mode 100644 index 0000000..409f3c0 --- /dev/null +++ b/seed.go @@ -0,0 +1,17 @@ +package main + +import "math/rand" + +type SeedProvider struct { + rand *rand.Rand +} + +func NewSeedProvider(seed int64) *SeedProvider { + return &SeedProvider{ + rand: rand.New(rand.NewSource(seed)), + } +} + +func (sp *SeedProvider) Next() int64 { + return sp.rand.Int63() +}