commit 495a7cce2010b54b2a0cb0a9d0a2bcb520c0f390 Author: Arek Date: Tue Feb 11 22:30:13 2025 +0100 Init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f16fa55 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode/** diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..cec9082 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,3 @@ +* + +!.gitignore diff --git a/cmd/gol/gol.go b/cmd/gol/gol.go new file mode 100644 index 0000000..091a6c3 --- /dev/null +++ b/cmd/gol/gol.go @@ -0,0 +1,54 @@ +package main + +import ( + "gol/gol" + "gol/term" + "os" + "os/signal" + "syscall" + "time" +) + +func main() { + front := gol.New(20, 40) + back := gol.New(20, 40) + + // glider + front[0][3] = true + front[1][4] = true + front[2][2] = true + front[2][3] = true + front[2][4] = true + + // cross + + front[16][21] = true + front[17][21] = true + front[18][21] = true + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + + term.StartFullscreen() + term.TurnCursor(term.CursorOff) + + loop := func() { + ticker := time.NewTicker(250 * time.Millisecond) + for { + term.GoHome() + front.PrintMe() + front.NextGen(back) + front, back = back, front + select { + case <-sigs: // przerwanie + return + case <-ticker.C: // upłynął czas do kolejnej generacji + } + } + } + defer func() { + term.FinishFullscreen() + term.TurnCursor(term.CursorOn) + }() + loop() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..127e86e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gol + +go 1.19 diff --git a/gol/types.go b/gol/types.go new file mode 100644 index 0000000..8d30793 --- /dev/null +++ b/gol/types.go @@ -0,0 +1,95 @@ +package gol + +import "fmt" + +type Arena [][]bool + +func New(ysize, xsize int) Arena { + var arena = make([][]bool, ysize) + for i := 0; i < ysize; i++ { + arena[i] = make([]bool, xsize) + } + return arena +} + +func (a Arena) PrintMe() { + for i := 0; i < len(a); i++ { + for j := 0; j < len(a[0]); j++ { + if a[i][j] { + fmt.Print("\ue0b6\ue0b4") + } else { + //fmt.Print("\ue0b7\ue0b5") + fmt.Print("\u2022\u2022") + } + } + fmt.Println() + } +} + +func (a Arena) NextGen(to Arena) { + for y := 0; y < len(a); y++ { + for x := 0; x < len(a[0]); x++ { + to[y][x] = a.Life(x, y) + } + } +} + +func (a Arena) Life(x, y int) bool { + count := a.countN(x, y) + current := a[y][x] + if !current && count == 3 { + return true + } + if current && (count == 2 || count == 3) { + return true + } + return false +} + +type pair struct { + x int + y int +} + +func (a Arena) countN(x, y int) int { + ysize := len(a) + xsize := len(a[0]) + + xb := x - 1 + if xb < 0 { + xb = xsize - 1 + } + xa := x + 1 + if xa == xsize { + xa = 0 + } + + yb := y - 1 + if yb < 0 { + yb = ysize - 1 + } + + ya := y + 1 + if ya == ysize { + ya = 0 + } + + neigh := [8]pair{ + {xb, yb}, + {x, yb}, + {xa, yb}, + {xb, y}, + {xa, y}, + {xb, ya}, + {x, ya}, + {xa, ya}, + } + + count := 0 + for _, p := range neigh { + if a[p.y][p.x] { + count++ + } + } + return count +} diff --git a/term/term.go b/term/term.go new file mode 100644 index 0000000..969dd7d --- /dev/null +++ b/term/term.go @@ -0,0 +1,57 @@ +package term + +import "fmt" + +type CursorFlag bool + +const ( + CursorOn CursorFlag = true + CursorOff CursorFlag = false +) + +func TurnCursor(onOff CursorFlag) { + if onOff == CursorOn { + fmt.Printf("\033[?25h") + } else { + fmt.Printf("\033[?25l") + } +} + +func ClearScreen() { + fmt.Printf("\033[2J") +} + +func ResetTerminal() { + fmt.Printf("\033c") +} + +func GoHome() { + fmt.Printf("\033[H") +} + +func SaveCursor() { + fmt.Printf("\033[s") +} + +func RestoreCursor() { + fmt.Printf("\033[u") +} + +func EnableAlternateScreen() { + fmt.Printf("\033[?1049h") +} + +func DisableAlternateScreen() { + fmt.Printf("\033[?1049l") +} + +func StartFullscreen() { + SaveCursor() + EnableAlternateScreen() + ClearScreen() +} + +func FinishFullscreen() { + DisableAlternateScreen() + RestoreCursor() +}