Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib/game: custom life-like rules #22

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions cmd/vita/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
"strconv"
"sync"

"github.com/acifani/vita/lib/game"
Expand All @@ -15,6 +16,8 @@ var (
population = flag.Int("pop", 45, "initial population percent of the universe")
number = flag.Int("n", 1, "number of universes to run in parallel")
rules = flag.String("rules", "conway", "rules to use for the universe")
b = flag.String("B", "3", "born")
s = flag.String("S", "23", "survive")
)

func main() {
Expand All @@ -35,11 +38,13 @@ func runSingleUniverse() {
universe := game.NewUniverse(uint32(*height), uint32(*width))
switch *rules {
case "dayandnight":
universe.Rules = game.DayAndNightRules
universe.Rules = universe.DayAndNightRules
case "seeds":
universe.Rules = game.SeedsRules
universe.Rules = universe.SeedsRules
case "wrap":
universe.Rules = game.ConwayRulesWrap
universe.Rules = universe.ConwayRulesWrap
case "custom":
universe.Rules = universe.NewLifeLikeRules(convertStringToUint8(*b), convertStringToUint8(*s), true)
default:
// just use conway
}
Expand Down Expand Up @@ -76,10 +81,10 @@ func createParallelUniverses() []*game.ParallelUniverse {
for col := 0; col < *number; col++ {
u := game.NewParallelUniverse(uint32(*height), uint32(*width))
switch *rules {
case "dayandnight":
u.Rules = game.DayAndNightRules
case "seeds":
u.Rules = game.SeedsRules
// case "dayandnight":
// u.Rules = game.DayAndNightRules
// case "seeds":
// u.Rules = game.SeedsRules
default:
// just use conway
}
Expand Down Expand Up @@ -160,3 +165,16 @@ func callMultiTick(wg *sync.WaitGroup, u *game.ParallelUniverse) {
wg.Done()
}()
}

func convertStringToUint8(input string) []uint8 {
output := make([]uint8, len(input))
for i, c := range input {
n, err := strconv.Atoi(string(c))
if err != nil {
panic(err)
}
output[i] = uint8(n)
}

return output
}
36 changes: 36 additions & 0 deletions lib/game/rules.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
package game

func (u *Universe) NewLifeLikeRules(B, S []uint8, wraps bool) func(cell uint8, row, column uint32) uint8 {
rule := NewRule(B, S)
return func(cell uint8, row, column uint32) uint8 {
var neighbors uint8
if wraps {
neighbors = u.MooreNeighbors(row, column)
} else {
neighbors = u.MooreNeighborsWrap(row, column)
}
return rule(cell, neighbors)
}
}

func NewRule(B, S []uint8) func(cell uint8, liveNeighbors uint8) uint8 {
return func(cell uint8, liveNeighbors uint8) uint8 {
if cell == Dead && contains(B, liveNeighbors) {
return Alive
}

if cell == Alive && contains(S, liveNeighbors) {
return Alive
}

return Dead
}
}

func contains(slice []uint8, candidate uint8) bool {
for _, element := range slice {
if element == candidate {
return true
}
}
return false
}

// ConwayRules implements the classic Game of Life rules.
func (u *Universe) ConwayRules(cell uint8, row, column uint32) uint8 {
return RuleB3S23(cell, u.MooreNeighbors(row, column))
Expand Down