Too much crap for one commit
Breaking out console runner into its own file, adding an empty web runner, and starting to test that games and game states are able to represent themselves as images.
This commit is contained in:
parent
3bfa23fff2
commit
3e013ce1a5
47
conway/console.go
Normal file
47
conway/console.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package conway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunConsoleGame(height, width, sleepMs int, mutate bool) (int, error) {
|
||||||
|
sleepInterval := time.Duration(sleepMs * 1000 * 1000)
|
||||||
|
|
||||||
|
game := NewGameOfLife(height, width)
|
||||||
|
err := game.ImportRandomState()
|
||||||
|
if err != nil {
|
||||||
|
return 2, err
|
||||||
|
}
|
||||||
|
|
||||||
|
genTicks, err := game.Generations()
|
||||||
|
if err != nil {
|
||||||
|
return 3, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for genTick := range genTicks {
|
||||||
|
fmt.Printf("\nGeneration %v\n%v\n", genTick.N, time.Now())
|
||||||
|
fmt.Println(game)
|
||||||
|
|
||||||
|
if genTick.Error != nil {
|
||||||
|
return 4, genTick.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(genTick.Message) > 0 {
|
||||||
|
fmt.Println(genTick.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mutate && genTick.N%2 == 0 {
|
||||||
|
game.Mutate()
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(sleepInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
@ -91,7 +91,7 @@ func TestDeadCellWithExactlyThreeLiveNeighborsBecomesAlive(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGameOfLifeCanDisplayItself(t *testing.T) {
|
func TestGameOfLifeCanDisplayItselfAsAString(t *testing.T) {
|
||||||
game := newTestGameOfLife()
|
game := newTestGameOfLife()
|
||||||
|
|
||||||
grid := fmt.Sprintf("%s\n", game)
|
grid := fmt.Sprintf("%s\n", game)
|
||||||
@ -103,6 +103,10 @@ func TestGameOfLifeCanDisplayItself(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGameOfLifeCanDisplayItselfAsAnImage(t *testing.T) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewGameOfLifeHasCorrectDimensions(t *testing.T) {
|
func TestNewGameOfLifeHasCorrectDimensions(t *testing.T) {
|
||||||
game := newTestGameOfLife()
|
game := newTestGameOfLife()
|
||||||
|
|
||||||
@ -172,7 +176,7 @@ func TestGameOfLifeCanImportRandomState(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGameStateCanDisplayItself(t *testing.T) {
|
func TestGameStateCanDisplayItselfAsAString(t *testing.T) {
|
||||||
state := newTestGameState()
|
state := newTestGameState()
|
||||||
|
|
||||||
grid := fmt.Sprintf("%s\n", state)
|
grid := fmt.Sprintf("%s\n", state)
|
||||||
@ -190,6 +194,27 @@ func TestGameStateCanDisplayItself(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGameStateCanDisplayItselfAsAnImage(t *testing.T) {
|
||||||
|
state := newTestGameState()
|
||||||
|
|
||||||
|
img, err := state.Image(1, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds := img.Bounds()
|
||||||
|
if bounds.Max.Y < 16 {
|
||||||
|
t.Errorf("image.Max.Y < 16!: %d", bounds.Max.Y)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if bounds.Max.X < 16 {
|
||||||
|
t.Errorf("image.Max.X < 16!: %d", bounds.Max.X)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewGameStatesAreAllDead(t *testing.T) {
|
func TestNewGameStatesAreAllDead(t *testing.T) {
|
||||||
state := NewGameState(4, 4)
|
state := NewGameState(4, 4)
|
||||||
for x := 0; x < 3; x++ {
|
for x := 0; x < 3; x++ {
|
||||||
|
@ -14,6 +14,7 @@ var (
|
|||||||
height = flag.Int("height", 40, "Game height")
|
height = flag.Int("height", 40, "Game height")
|
||||||
width = flag.Int("width", 80, "Game width")
|
width = flag.Int("width", 80, "Game width")
|
||||||
mutate = flag.Bool("mutate", false, "Mutate every other generation")
|
mutate = flag.Bool("mutate", false, "Mutate every other generation")
|
||||||
|
web = flag.Bool("web", false, "Run server for web-based game")
|
||||||
sleepMs = flag.Int("sleep.ms", 200,
|
sleepMs = flag.Int("sleep.ms", 200,
|
||||||
"Millisecond sleep interval per generation")
|
"Millisecond sleep interval per generation")
|
||||||
)
|
)
|
||||||
@ -21,10 +22,22 @@ var (
|
|||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
retCode, err := RunConsoleGame(*height, *width, *sleepMs, *mutate)
|
var (
|
||||||
|
retCode int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if *web {
|
||||||
|
retCode, err = RunWebGame(*height, *width, *sleepMs, *mutate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
|
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
retCode, err = RunConsoleGame(*height, *width, *sleepMs, *mutate)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
os.Exit(retCode)
|
os.Exit(retCode)
|
||||||
}
|
}
|
||||||
|
@ -3,54 +3,14 @@ package conway
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
rand.Seed(time.Now().UTC().UnixNano())
|
|
||||||
}
|
|
||||||
|
|
||||||
type GameOfLife struct {
|
type GameOfLife struct {
|
||||||
State *GameState
|
State *GameState
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunConsoleGame(height, width, sleepMs int, mutate bool) (int, error) {
|
|
||||||
sleepInterval := time.Duration(sleepMs * 1000 * 1000)
|
|
||||||
|
|
||||||
game := NewGameOfLife(height, width)
|
|
||||||
err := game.ImportRandomState()
|
|
||||||
if err != nil {
|
|
||||||
return 2, err
|
|
||||||
}
|
|
||||||
|
|
||||||
genTicks, err := game.Generations()
|
|
||||||
if err != nil {
|
|
||||||
return 3, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for genTick := range genTicks {
|
|
||||||
fmt.Printf("\nGeneration %v\n%v\n", genTick.N, time.Now())
|
|
||||||
fmt.Println(game)
|
|
||||||
|
|
||||||
if genTick.Error != nil {
|
|
||||||
return 4, genTick.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(genTick.Message) > 0 {
|
|
||||||
fmt.Println(genTick.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
if mutate && genTick.N%2 == 0 {
|
|
||||||
game.Mutate()
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(sleepInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (game *GameOfLife) Mutate() {
|
func (game *GameOfLife) Mutate() {
|
||||||
game.State.Mutate()
|
game.State.Mutate()
|
||||||
}
|
}
|
||||||
@ -142,6 +102,10 @@ func (game *GameOfLife) String() string {
|
|||||||
return fmt.Sprintf("%s\n", game.State)
|
return fmt.Sprintf("%s\n", game.State)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (game *GameOfLife) Image(xMult, yMult int) (*image.Gray16, error) {
|
||||||
|
return game.State.Image(xMult, yMult)
|
||||||
|
}
|
||||||
|
|
||||||
func (game *GameOfLife) emitGenerations(genTicks chan *GenerationTick) {
|
func (game *GameOfLife) emitGenerations(genTicks chan *GenerationTick) {
|
||||||
defer close(genTicks)
|
defer close(genTicks)
|
||||||
n := 0
|
n := 0
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
@ -173,3 +174,7 @@ func (state *GameState) String() string {
|
|||||||
}
|
}
|
||||||
return strings.Join(rows, "\n")
|
return strings.Join(rows, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (state *GameState) Image(xMult, yMult int) (*image.Gray16, error) {
|
||||||
|
return nil, errors.New("Not implemented!")
|
||||||
|
}
|
||||||
|
14
conway/web.go
Normal file
14
conway/web.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package conway
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunWebGame(height, width, sleepMs int, mutate bool) (int, error) {
|
||||||
|
return -1, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user