commit 8d765322abc3dd25ca669da5e80c7613ee64cf43
parent acd0f134c93b5e793f93f1b515ef6232e1f19621
Author: Brian C. Lane <bcl@brianlane.com>
Date: Wed, 27 Nov 2019 09:13:33 -0800
Add rule maps instead of constants
This uses a map of the allowed neighbors instead of an array because it
makes checking it much simpler, just use the 'ok' result of the map
lookup.
Diffstat:
M | main.go | | | 42 | ++++++++++++++++++++++++------------------ |
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/main.go b/main.go
@@ -26,6 +26,7 @@ type cmdlineArgs struct {
Border bool // Border around cells
Font string // Path to TTF to use for status bar
FontSize int // Size of font in points
+ Rule string // Rulestring to use
}
/* commandline defaults */
@@ -38,6 +39,7 @@ var cfg = cmdlineArgs{
Border: false,
Font: "/usr/share/fonts/liberation/LiberationMono-Regular.ttf",
FontSize: 14,
+ Rule: "B3/S23",
}
/* parseArgs handles parsing the cmdline args and setting values in the global cfg struct */
@@ -50,6 +52,7 @@ func parseArgs() {
flag.BoolVar(&cfg.Border, "border", cfg.Border, "Border around cells")
flag.StringVar(&cfg.Font, "font", cfg.Font, "Path to TTF to use for status bar")
flag.IntVar(&cfg.FontSize, "font-size", cfg.FontSize, "Size of font in points")
+ flag.StringVar(&cfg.Rule, "rule", cfg.Rule, "Rulestring Bn.../Sn... (B3/S23)")
flag.Parse()
}
@@ -75,6 +78,8 @@ type LifeGame struct {
cells [][]*Cell
liveCells int
age int64
+ birth map[int]bool
+ stayAlive map[int]bool
// Graphics
window *sdl.Window
@@ -99,6 +104,11 @@ func (g *LifeGame) cleanup() {
// InitializeCells resets the world to a random state
func (g *LifeGame) InitializeCells() {
+ var err error
+ if g.birth, g.stayAlive, err = ParseRulestring(cfg.Rule); err != nil {
+ log.Fatalf("Failed to parse the rule string (%s): %s\n", cfg.Rule, err)
+ }
+
if cfg.Seed == 0 {
seed := time.Now().UnixNano()
log.Printf("seed = %d\n", seed)
@@ -125,25 +135,11 @@ func (g *LifeGame) InitializeCells() {
func (g *LifeGame) checkState(c *Cell) {
liveCount := g.liveNeighbors(c)
if c.alive {
- // 1. Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
- if liveCount < 2 {
- c.aliveNext = false
- }
-
- // 2. Any live cell with two or three live neighbours lives on to the next generation.
- if liveCount == 2 || liveCount == 3 {
- c.aliveNext = true
- }
-
- // 3. Any live cell with more than three live neighbours dies, as if by overpopulation.
- if liveCount > 3 {
- c.aliveNext = false
- }
+ // Stay alive if the number of neighbors is in stayAlive
+ _, c.aliveNext = g.stayAlive[liveCount]
} else {
- // 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
- if liveCount == 3 {
- c.aliveNext = true
- }
+ // Birth a new cell if number of neighbors is in birth
+ _, c.aliveNext = g.birth[liveCount]
}
}
@@ -387,6 +383,16 @@ func InitializeGame() *LifeGame {
return game
}
+// ParseRulestring parses the rules that control the game
+//
+// Rulestrings are of the form Bn.../Sn... which list the number of neighbors to birth a new one,
+// and the number of neighbors to stay alive.
+//
+func ParseRulestring(rule string) (birth map[int]bool, stayAlive map[int]bool, err error) {
+
+ return map[int]bool{3: true}, map[int]bool{2: true, 3: true}, nil
+}
+
func main() {
parseArgs()