Skip to content

Instantly share code, notes, and snippets.

@LOZORD
Created January 2, 2019 02:56
Show Gist options
  • Save LOZORD/115f2f81c7bffae3efa5ff9f4db38132 to your computer and use it in GitHub Desktop.
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).
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