From a5408e152b2300a2775504f3c2cbabf3969d398e Mon Sep 17 00:00:00 2001 From: ston1th Date: Thu, 27 May 2021 01:03:07 +0200 Subject: [PATCH] initial commit --- LICENSE | 24 +++++++ README.md | 9 +++ go.mod | 3 + main.go | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..53d1756 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (C) 2021 Marius Schellenberger +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of the authors and/or contributors may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ston1th BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9e1d3c9 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# GoL - Conway's Game of Life + +Implemented in Go using multithreading and visualization. + +## Usage + +``` +go run main.go | vlc - +``` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2afcd84 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.giftfish.de/ston1th/gol + +go 1.16 diff --git a/main.go b/main.go new file mode 100644 index 0000000..7644f15 --- /dev/null +++ b/main.go @@ -0,0 +1,210 @@ +package main + +import ( + "fmt" + "image" + "image/color" + "image/jpeg" + "math/rand" + "os" + "time" +) + +const ( + //size = 150 + size = 30 + zoom = 8 + fps = 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] { + if !(i == x && j == y) { + n++ + } + } + } + } + if g.grid1.G[x][y] { + 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 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: + } + err := jpeg.Encode(os.Stdout, img, &o) + if err == nil { + os.Stdout.Sync() + } + time.Sleep(time.Millisecond * 16) + } + }() + go func() { + s := size * zoom + r := image.Rect(0, 0, s, s) + for { + img := image.NewNRGBA(r) + grid := <-gc + x := 0 + y := 0 + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + var c color.Color + 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 { + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + gol.Check(i, j) + } + } + gc <- gol.Grid() + gol.Gen++ + fmt.Fprintf(os.Stderr, "\rGeneration: %d", gol.Gen) + time.Sleep(time.Second / fps) + } +}