Compare commits

..

4 Commits

Author SHA1 Message Date
2b709d4d05 auto reset checking across 2 generations at a time 2024-04-17 11:17:19 +02:00
a9d600aaed Revert "bugfix: clear before next gen"
This reverts commit a65dcddbc7.
2024-04-17 08:18:22 +02:00
de00ca4af9 uint typing and scale factor 2024-04-17 08:11:23 +02:00
a65dcddbc7 bugfix: clear before next gen 2024-04-17 08:09:37 +02:00
3 changed files with 55 additions and 28 deletions

View File

@ -7,17 +7,17 @@ import (
) )
type Cell struct { type Cell struct {
x int x uint
y int y uint
live bool live bool
} }
func (c *Cell) NeighborCount(arr [][]Cell) int { func (c *Cell) NeighborCount(arr [][]Cell) uint {
// Read grid dimensions // Read grid dimensions
width := len(arr) width := uint(len(arr))
height := len(arr[0]) height := uint(len(arr[0]))
count := 0 count := uint(0)
// Iterate through 3x3 neighboring grid // Iterate through 3x3 neighboring grid
for i := -1; i <= 1; i++ { for i := -1; i <= 1; i++ {
for j := -1; j <= 1; j++ { for j := -1; j <= 1; j++ {
@ -26,8 +26,8 @@ func (c *Cell) NeighborCount(arr [][]Cell) int {
continue continue
} }
// Get neighbor coordinates // Get neighbor coordinates
nx := (c.x + i + width) % width nx := uint(int(c.x+width)+i) % width
ny := (c.y + j + height) % height ny := uint(int(c.y+height)+j) % height
// Count if neighbor is alive // Count if neighbor is alive
if arr[nx][ny].live { if arr[nx][ny].live {
count++ count++
@ -37,7 +37,18 @@ func (c *Cell) NeighborCount(arr [][]Cell) int {
return count return count
} }
func initGrid(width, height int, parent ...[][]Cell) ([][]Cell, error) { func compareGrids(a, b [][]Cell) bool {
for i := 0; i < len(a); i++ {
for j := 0; j < len(a[0]); j++ {
if a[i][j].live != b[i][j].live {
return false
}
}
}
return true
}
func initGrid(width, height uint, parent ...[][]Cell) ([][]Cell, error) {
exists := len(parent) == 1 exists := len(parent) == 1
if exists && len(parent) > 1 { if exists && len(parent) > 1 {
return nil, errors.New("Too many parents specified") return nil, errors.New("Too many parents specified")
@ -45,10 +56,10 @@ func initGrid(width, height int, parent ...[][]Cell) ([][]Cell, error) {
// Make first dimension // Make first dimension
cells := make([][]Cell, width) cells := make([][]Cell, width)
for i := 0; i < width; i++ { for i := uint(0); i < width; i++ {
// Make second dimension // Make second dimension
cells[i] = make([]Cell, height) cells[i] = make([]Cell, height)
for j := 0; j < height; j++ { for j := uint(0); j < height; j++ {
// Make cells // Make cells
cells[i][j].x = i cells[i][j].x = i
cells[i][j].y = j cells[i][j].y = j
@ -63,22 +74,34 @@ func initGrid(width, height int, parent ...[][]Cell) ([][]Cell, error) {
return cells, nil return cells, nil
} }
func setup(callback func([][]Cell), width, height int, FPS time.Duration) chan bool { func setup(callback func([][]Cell), scale, width, height uint, FPS time.Duration) chan bool {
// Initialize grid // Initialize grid at specified scale
grid, _ := initGrid(width, height) gridWidth := width / scale
gridHeight := height / scale
grid, _ := initGrid(gridWidth, gridHeight)
// Prepare ticker and finishing flag // Prepare ticker and finishing flag
ticker := time.NewTicker((1000 / FPS) * time.Millisecond) ticker := time.NewTicker((1000 / FPS) * time.Millisecond)
done := make(chan bool) done := make(chan bool)
// Run game loop // Run game loop
var parent [][]Cell
go func() { go func() {
for { for {
select { select {
case <-done: case <-done:
return return
case <-ticker.C: case <-ticker.C:
grid = draw(grid, callback) temp := draw(grid, callback)
if parent != nil && compareGrids(parent, temp) {
parent = nil
grid, _ = initGrid(gridWidth, gridHeight)
} else {
parent, _ = initGrid(gridWidth, gridHeight, grid)
grid = temp
}
} }
} }
}() }()
@ -88,10 +111,13 @@ func setup(callback func([][]Cell), width, height int, FPS time.Duration) chan b
} }
func draw(grid [][]Cell, callback func([][]Cell)) [][]Cell { func draw(grid [][]Cell, callback func([][]Cell)) [][]Cell {
generation, _ := initGrid(len(grid), len(grid[0]), grid) width := uint(len(grid))
height := uint(len(grid[0]))
generation, _ := initGrid(width, height, grid)
// Iterate through grid // Iterate through grid
for i := 0; i < len(grid); i++ { for i := uint(0); i < width; i++ {
for j := 0; j < len(grid[0]); j++ { for j := uint(0); j < height; j++ {
// Count neighbors // Count neighbors
cout := grid[i][j].NeighborCount(grid) cout := grid[i][j].NeighborCount(grid)
// Get state // Get state

15
main.go
View File

@ -8,15 +8,15 @@ import (
"github.com/joho/godotenv" "github.com/joho/godotenv"
) )
func output(client *resty.Client, url string, width, height int, arr [][]Cell) { func output(client *resty.Client, url string, scale, width, height uint, arr [][]Cell) {
goterm.MoveCursor(1, 4) goterm.MoveCursor(1, 4)
// Prepare instructions for matrix // Prepare instructions for matrix
instructions := make([]interface{}, 0) instructions := make([]interface{}, 0)
// Append all live cells as pixel instructions // Append all live cells as pixel instructions
for j := 0; j < height; j++ { for j := 0; j < int(height/scale); j++ {
for i := 0; i < width; i++ { for i := 0; i < int(width/scale); i++ {
if arr[i][j].live { if arr[i][j].live {
instructions = append(instructions, Pixel{X: i, Y: j, Endpoint: PIXEL}) instructions = append(instructions, Rectangle{X: i * int(scale), Y: j * int(scale), W: scale, H: scale, Endpoint: RECTANGLE})
goterm.Print("X") goterm.Print("X")
continue continue
} }
@ -34,7 +34,8 @@ func output(client *resty.Client, url string, width, height int, arr [][]Cell) {
} }
func main() { func main() {
const FPS = 10 const FPS = 2
const SCALE = 2
// Try loading .env file if it exists // Try loading .env file if it exists
godotenv.Load(".env") godotenv.Load(".env")
@ -53,8 +54,8 @@ func main() {
// Run Game of Life // Run Game of Life
done := setup(func(c [][]Cell) { done := setup(func(c [][]Cell) {
output(client, url, width, height, c) output(client, url, SCALE, width, height, c)
}, width, height, FPS) }, SCALE, width, height, FPS)
// Wait for user input to quit // Wait for user input to quit
fmt.Scanln() fmt.Scanln()

View File

@ -5,7 +5,7 @@ import (
"os" "os"
) )
func loadMatrixData() (string, int, int) { func loadMatrixData() (string, uint, uint) {
// Remote server info // Remote server info
API_SERVER_IP, _ := getEnvFallback("API_SERVER_IP", "localhost") API_SERVER_IP, _ := getEnvFallback("API_SERVER_IP", "localhost")
API_SERVER_PORT, _ := getEnvFallback("API_SERVER_PORT", "8080") API_SERVER_PORT, _ := getEnvFallback("API_SERVER_PORT", "8080")
@ -22,8 +22,8 @@ func loadMatrixData() (string, int, int) {
url := fmt.Sprintf("http://%s:%s", API_SERVER_IP, API_SERVER_PORT) url := fmt.Sprintf("http://%s:%s", API_SERVER_IP, API_SERVER_PORT)
// Calculate combined resolution // Calculate combined resolution
width := PUBLIC_LED_WIDTH * PUBLIC_LED_CHAIN width := uint(PUBLIC_LED_WIDTH * PUBLIC_LED_CHAIN)
height := PUBLIC_LED_HEIGHT * PUBLIC_LED_PARALLEL height := uint(PUBLIC_LED_HEIGHT * PUBLIC_LED_PARALLEL)
return url, width, height return url, width, height
} }