Skip to content

Instantly share code, notes, and snippets.

@Leko
Last active August 29, 2015 14:24
Show Gist options
  • Save Leko/a4c8bac6683ad804a40b to your computer and use it in GitHub Desktop.
Save Leko/a4c8bac6683ad804a40b to your computer and use it in GitHub Desktop.
LifeGame for Go
// Run: go build /path/to/lifegame/go/index.go; ./index
// Environment variables:
// - LIFEGAME_WIDTH: int(default is terminal width)
// - LIFEGAME_HEIGHT: int(default is terminal height)
package main
import (
"fmt"
"math/rand"
"os"
"os/exec"
"strconv"
"strings"
"time"
)
const FPS = 20
const LIVE = 1
const DEAD = 0
var WIDTH = width()
var HEIGHT = height()
func main() {
rand.Seed(time.Now().UnixNano())
board := make([]int, WIDTH*HEIGHT)
// random cell birth
for i := 0; i < (WIDTH*HEIGHT)/3; i++ {
board[rand.Intn(WIDTH*HEIGHT)] = 1
}
// main loop
for true {
board = simulate(board)
fmt.Println(render(board))
time.Sleep((1000 / FPS) * time.Millisecond)
}
}
func width() int {
width, _ := strconv.Atoi(size()[1])
return width
}
func height() int {
height, _ := strconv.Atoi(size()[0])
return height
}
func size() []string {
cmd := exec.Command("stty", "size")
cmd.Stdin = os.Stdin
out, _ := cmd.Output()
sizes := strings.Split(strings.Trim(string(out), "\n"), " ")
width := os.Getenv("LIFEGAME_WIDTH")
height := os.Getenv("LIFEGAME_HEIGHT")
if width != "" {
sizes[0] = width
}
if height != "" {
sizes[1] = height
}
fmt.Println(sizes)
return sizes
}
func render(board []int) string {
str := ""
for i := 0; i < HEIGHT; i++ {
for j := 0; j < WIDTH; j++ {
cell := " "
if board[i*HEIGHT+j] == LIVE {
cell = "#"
}
str += cell
}
str += "\n"
}
return str
}
func simulate(board []int) []int {
next := make([]int, WIDTH*HEIGHT)
for i := 0; i < HEIGHT; i++ {
for j := 0; j < WIDTH; j++ {
idx := i*HEIGHT + j
neighbor := moore_neighborhood(board, i, j)
birth := (board[idx] == DEAD && neighbor == 3)
stay := (board[idx] == LIVE && 2 <= neighbor && neighbor <= 3)
if birth || stay {
next[idx] = LIVE
}
}
}
return next
}
func moore_neighborhood(board []int, y int, x int) int {
living := 0
for i := y - 1; i <= y+1; i++ {
for j := x - 1; j <= x+1; j++ {
idx := i*HEIGHT + j
if i < 0 || i >= HEIGHT || j < 0 || j >= WIDTH || (i == y && j == x) {
continue
}
if board[idx] == LIVE {
living++
}
}
}
return living
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment