gol/main.go
2021-05-27 07:39:32 +02:00

214 lines
3.1 KiB
Go

package main
import (
"fmt"
"image"
"image/color"
"image/jpeg"
"math/rand"
"os"
"time"
)
const (
// Grid size
//size = 150
size = 30
// Image zoom value
zoom = 8
// Generations per second
gps = 2
)
type Grid struct {
G [size][size]bool
}
func (g *Grid) Blinker() {
g.G[14][13] = true
g.G[14][14] = true
g.G[14][15] = true
}
func (g *Grid) Bipole() {
g.G[14][14] = true
g.G[14][15] = true
g.G[15][14] = true
g.G[16][17] = true
g.G[17][16] = true
g.G[17][17] = true
}
func (g *Grid) Tripole() {
g.G[14][14] = true
g.G[14][15] = true
g.G[15][14] = true
g.G[16][15] = true
g.G[16][17] = true
g.G[17][18] = true
g.G[18][17] = true
g.G[18][18] = true
}
func (g *Grid) Pulsator() {
for i := 10; i < 20; i++ {
g.G[i][14] = true
}
}
func (g *Grid) Glider() {
g.G[1][0] = true
g.G[2][1] = true
g.G[2][2] = true
g.G[1][2] = true
g.G[0][2] = true
}
func (g *Grid) Random() {
rand.Seed(size)
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
g.G[i][j] = rand.Intn(2) == 1
}
}
}
/*
func (g *Grid) Pentomino() {
g.G[75][74] = true
g.G[76][74] = true
g.G[74][75] = true
g.G[75][75] = true
g.G[75][76] = true
}
*/
type GOL struct {
grid1 *Grid
grid2 *Grid
Gen int
}
func NewGOL() (g *GOL) {
g = &GOL{grid1: new(Grid), grid2: new(Grid)}
g.grid1.Blinker()
//g.grid1.Bipole()
//g.grid1.Tripole()
//g.grid1.Pulsator()
//g.grid1.Random()
//g.grid1.Pentomino()
return
}
func min(i int) int {
if i == -1 {
return i + 1
}
return i
}
func max(i int) int {
if i == size {
return i - 1
}
return i
}
func (g *GOL) check(x, y int) {
n := 0
for i := min(x - 1); i <= max(x+1); i++ {
for j := min(y - 1); j <= max(y+1); j++ {
if g.grid1.G[i][j] {
n++
}
}
}
if g.grid1.G[x][y] {
n--
switch n {
case 0, 1:
g.grid2.G[x][y] = false
case 2, 3:
g.grid2.G[x][y] = true
default:
g.grid2.G[x][y] = false
}
} else {
if n == 3 {
g.grid2.G[x][y] = true
}
}
}
func (g *GOL) grid() (gr *Grid) {
gr = new(Grid)
for i := 0; i < size; i++ {
gr.G[i] = g.grid1.G[i]
}
g.grid1, g.grid2 = g.grid2, new(Grid)
return
}
func (g *GOL) Calc() (gr *Grid) {
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
g.check(i, j)
}
}
g.Gen++
return g.grid()
}
func main() {
gol := NewGOL()
gc := make(chan *Grid, 10)
ic := make(chan image.Image, 10)
go func() {
o := jpeg.Options{100}
img := <-ic
for {
select {
case img = <-ic:
default:
}
if jpeg.Encode(os.Stdout, img, &o) == nil {
os.Stdout.Sync()
}
time.Sleep(time.Millisecond * 16)
}
}()
go func() {
s := size * zoom
r := image.Rect(0, 0, s, s)
for {
img := image.NewGray(r)
grid := <-gc
x := 0
y := 0
var c color.Color
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
if grid.G[i][j] {
c = color.Black
} else {
c = color.White
}
for a := 0; a < zoom; a++ {
for b := 0; b < zoom; b++ {
img.Set(x+a, y+b, c)
}
}
y += zoom
}
x += zoom
y = 0
}
ic <- img
}
}()
for {
gc <- gol.Calc()
fmt.Fprintf(os.Stderr, "\rGeneration: %d", gol.Gen)
time.Sleep(time.Second / gps)
}
}