Created
January 2, 2019 02:56
-
-
Save LOZORD/115f2f81c7bffae3efa5ff9f4db38132 to your computer and use it in GitHub Desktop.
An attempt at implementing a simple cellular automaton based on Wolfram's patterns (e.g. Rule 30).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"image" | |
"image/color" | |
"image/png" | |
"log" | |
"math/rand" | |
"os" | |
"time" | |
) | |
var ( | |
seedFlag = flag.Int64("seed", 0, "Seed value to use for random number generation.") | |
) | |
const ( | |
dim = 1024 | |
) | |
func main() { | |
flag.Parse() | |
ts := time.Now().Unix() | |
seed := *seedFlag | |
if seed == 0 { | |
seed = ts | |
} | |
rng := rand.New(rand.NewSource(seed)) | |
img := image.NewRGBA64(image.Rect(0, 0, dim, dim)) | |
populate(img, rng) | |
evolve(img) | |
outPath := fmt.Sprintf("wolf_%d.png", ts) | |
outFile, err := os.Create(outPath) | |
if err != nil { | |
log.Fatalf("failed to create file: %v", err) | |
} | |
defer outFile.Close() | |
if err := png.Encode(outFile, img); err != nil { | |
log.Fatalf("failed to encode image: %v", err) | |
} | |
} | |
func populate(img *image.RGBA64, rng *rand.Rand) { | |
minY := img.Bounds().Min.Y | |
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { | |
img.Set(x, minY, populateColor(x, minY, rng)) | |
} | |
} | |
func populateColor(x, y int, rng *rand.Rand) color.Color { | |
if rng.Float32() >= 0.5 { | |
return color.White | |
} | |
return color.Black | |
} | |
func evolve(img *image.RGBA64) { | |
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { | |
for y := img.Bounds().Min.Y + 1; y < img.Bounds().Max.Y; y++ { | |
lc, cc, rc := children(img, x, y) | |
img.Set(x, y, chooseColor(lc, cc, rc)) | |
} | |
} | |
} | |
func children(img image.Image, x, y int) (lc, cc, rc color.Color) { | |
if (image.Point{x - 1, y - 1}).In(img.Bounds()) { | |
lc = img.At(x-1, y-1) | |
} else { | |
lc = color.Black | |
} | |
if (image.Point{x, y - 1}).In(img.Bounds()) { | |
cc = img.At(x, y-1) | |
} else { | |
cc = color.Black | |
} | |
if (image.Point{x + 1, y - 1}).In(img.Bounds()) { | |
rc = img.At(x+1, y-1) | |
} else { | |
rc = color.Black | |
} | |
return | |
} | |
// This produces different patterns based on the seed row. | |
func chooseColor(lc, cc, rc color.Color) color.Color { | |
if isBlack(cc) { | |
return color.White | |
} | |
if !isBlack(lc) || !isBlack(rc) { | |
return color.Black | |
} | |
return color.Black | |
} | |
func isBlack(c color.Color) bool { | |
cr, cg, cb, ca := c.RGBA() | |
br, bg, bb, ba := color.Black.RGBA() | |
return cr == br && cg == bg && cb == bb && ca == ba | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment