diff --git a/conway/.gitignore b/conway/.gitignore
deleted file mode 100644
index 7103906..0000000
--- a/conway/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/web_assets/web_assets
diff --git a/conway/Makefile b/conway/Makefile
deleted file mode 100644
index a13870d..0000000
--- a/conway/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-LIBS := \
- github.com/meatballhat/box-o-sand/conway
-TARGETS := \
- $(LIBS) \
- github.com/meatballhat/box-o-sand/conway/conways-game-of-life
-
-all: test
-
-test: build
- go test -x -v -test.parallel=4 $(LIBS)
-
-build: web_assets.go deps
- go install -x $(TARGETS)
-
-web_assets.go: $(wildcard web_assets/*.*)
- ./gen-web-assets
-
-clean:
- go clean -x -i $(TARGETS)
-
-deps:
- go get -n -x $(TARGETS)
-
-.PHONY: all build clean deps test
diff --git a/conway/console.go b/conway/console.go
deleted file mode 100644
index 57a1673..0000000
--- a/conway/console.go
+++ /dev/null
@@ -1,47 +0,0 @@
-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
-}
diff --git a/conway/conway_test.go b/conway/conway_test.go
deleted file mode 100644
index 1879beb..0000000
--- a/conway/conway_test.go
+++ /dev/null
@@ -1,593 +0,0 @@
-package conway_test
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "image/png"
- "math/rand"
- "net/http"
- "regexp"
- "strings"
- "testing"
-)
-
-import (
- . "github.com/meatballhat/box-o-sand/conway"
-)
-
-var TEST_SIMPLE_INITIAL_STATE = NewGameState(16, 16)
-
-func init() {
- s := TEST_SIMPLE_INITIAL_STATE
- s.Set(0, 0, 1)
- s.Set(0, 1, 1)
- s.Set(0, 2, 1)
- s.Set(1, 0, 1)
- s.Set(1, 1, 1)
- s.Set(2, 2, 1)
- s.Set(3, 0, 1)
- s.Set(3, 2, 1)
- s.Set(13, 13, 1)
- s.Set(13, 14, 1)
- s.Set(14, 14, 1)
- s.Set(14, 15, 1)
- s.Set(15, 13, 1)
- s.Set(15, 15, 1)
-}
-
-func newTestGameState() *GameState {
- state := NewGameState(16, 16)
- state.Import(TEST_SIMPLE_INITIAL_STATE)
- return state
-}
-
-func newTestGameOfLife() *GameOfLife {
- game := NewGameOfLife(16, 16)
- game.State.Import(TEST_SIMPLE_INITIAL_STATE)
- return game
-}
-
-func TestLiveCellWithFewerThanTwoLiveNeighborsDies(t *testing.T) {
- game := newTestGameOfLife()
-
- game.EvaluateGeneration()
-
- cell := game.State.Get(3, 2)
- if cell.Value != 0 {
- t.Errorf("%v != 0", cell.Value)
- return
- }
-}
-
-func TestLiveCellWithTwoOrThreeLiveNeighborsLivesOn(t *testing.T) {
- game := newTestGameOfLife()
-
- game.EvaluateGeneration()
-
- cell := game.State.Get(0, 2)
- if cell.Value != 1 {
- t.Errorf("%v != 1", cell.Value)
- return
- }
-}
-
-func TestLiveCellWithMoreThanThreeLiveNeighborsDies(t *testing.T) {
- game := newTestGameOfLife()
-
- game.EvaluateGeneration()
-
- cell := game.State.Get(0, 1)
- if cell.Value != 0 {
- t.Errorf("%v != 0", cell.Value)
- return
- }
-}
-
-func TestDeadCellWithExactlyThreeLiveNeighborsBecomesAlive(t *testing.T) {
- game := newTestGameOfLife()
-
- game.EvaluateGeneration()
-
- cell := game.State.Get(3, 1)
- if cell.Value != 1 {
- t.Errorf("%v != 1", cell.Value)
- return
- }
-}
-
-func TestGameOfLifeCanDisplayItselfAsAString(t *testing.T) {
- game := newTestGameOfLife()
-
- grid := fmt.Sprintf("%s\n", game)
-
- gridLen := len(grid)
- if gridLen < 256 {
- t.Errorf("%v < 256", gridLen)
- t.Fail()
- }
-}
-
-func TestGameOfLifeCanDisplayItselfAsAnImage(t *testing.T) {
- game := newTestGameOfLife()
-
- img, err := game.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 TestNewGameOfLifeHasCorrectDimensions(t *testing.T) {
- game := newTestGameOfLife()
-
- if game.State.Height() != 16 || game.State.Width() != 16 {
- t.Fail()
- }
-}
-
-func TestNewGameOfLifeHasGameStateOfSameDimensions(t *testing.T) {
- game := newTestGameOfLife()
-
- if len(game.State.Rows) < 16 {
- t.Fail()
- }
-
- if len(game.State.Rows[0].Cells) < 16 {
- t.Fail()
- }
-}
-
-func TestGameStateCanImportState(t *testing.T) {
- game := newTestGameOfLife()
-
- if game.State.Get(0, 0).Value != 1 {
- t.Fail()
- }
-
- if game.State.Get(1, 0).Value != 1 {
- t.Fail()
- }
-
- if game.State.Get(0, 1).Value != 1 {
- t.Fail()
- }
-
- if game.State.Get(1, 1).Value != 1 {
- t.Fail()
- }
-
- if game.State.Get(2, 2).Value != 1 {
- t.Fail()
- }
-}
-
-func TestGameOfLifeCanImportRandomState(t *testing.T) {
- game := newTestGameOfLife()
-
- err := game.ImportRandomState()
- if err != nil {
- t.Error(err)
- return
- }
-
- zeroCount := 0
-
- for y := 0; y < 16; y++ {
- for x := 0; x < 16; x++ {
- cell := game.State.Get(x, y)
- if cell.Value == 0 {
- zeroCount++
- }
- }
- }
-
- if zeroCount == 256 {
- t.Fail()
- }
-}
-
-func TestGameStateCanDisplayItselfAsAString(t *testing.T) {
- state := newTestGameState()
-
- grid := fmt.Sprintf("%s\n", state)
- lenGrid := len(grid)
-
- if lenGrid < 256 {
- t.Errorf("%v < 256", lenGrid)
- return
- }
-
- nLines := strings.Count(grid, "\n")
- if nLines < 16 {
- t.Errorf("%v < 16 (lines)", nLines)
- return
- }
-}
-
-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) {
- state := NewGameState(4, 4)
- for x := 0; x < 3; x++ {
- for y := 0; y < 3; y++ {
- if state.Get(x, y).Value != 0 {
- t.Fail()
- }
- }
- }
-}
-
-func TestGameStateCanGetCellValueByCoords(t *testing.T) {
- state := NewGameState(8, 8)
- if state.Get(2, 2).Value != 0 {
- t.Fail()
- }
-}
-
-func TestGameStateCanSetCellValueByCoords(t *testing.T) {
- state := NewGameState(8, 8)
- state.Set(2, 5, 1)
-
- if state.Get(2, 5).Value != 1 {
- t.Fail()
- }
-}
-
-func TestGameStateCanEnlivenCellsByCoords(t *testing.T) {
- state := NewGameState(8, 8)
- state.Enliven(0, 1)
-
- if state.Get(0, 1).Value != 1 {
- t.Fail()
- }
-}
-
-func TestGameStateCanDeadenCellsByCoords(t *testing.T) {
- state := NewGameState(8, 8)
-
- state.Enliven(0, 1)
-
- if state.Get(0, 1).Value != 1 {
- t.Fail()
- }
-
- state.Deaden(0, 1)
-
- if state.Get(0, 1).Value != 0 {
- t.Fail()
- }
-}
-
-func TestNewGenerationScoreCardIsAllZeros(t *testing.T) {
- gen := NewGenerationScoreCard(4, 4)
-
- for y := 0; y < gen.Height(); y++ {
- for x := 0; x < gen.Width(); x++ {
- if gen.Get(x, y).Value != 0 {
- t.Fail()
- }
- }
- }
-}
-
-func TestGenerationScoreCardCalculateResultsInCorrectNeighborCounts(t *testing.T) {
- genScore := NewGenerationScoreCard(16, 16)
-
- state := newTestGameState()
-
- genScore.Calculate(state)
-
- cell := genScore.Get(0, 0)
- if cell.Value != 4 {
- t.Errorf("[0, 0] value %v != 4", cell.Value)
- return
- }
-
- cell = genScore.Get(3, 2)
- if cell.Value != 1 {
- t.Errorf("[3, 2] value %d != 1", cell.Value)
- return
- }
-}
-
-func TestStateCanMutate(t *testing.T) {
- state := newTestGameState()
-
- curCksum, err := state.Checksum()
- if err != nil {
- t.Error(err)
- return
- }
-
- state.Mutate()
-
- newCksum, err := state.Checksum()
- if err != nil {
- t.Error(err)
- return
- }
-
- if curCksum == newCksum {
- t.Errorf("Checksum did not change! %v", newCksum)
- }
-}
-
-func TestStateProvidesCellIteratorChannel(t *testing.T) {
- state := newTestGameState()
-
- cells, err := state.Cells()
- if err != nil {
- t.Error(err)
- return
- }
-
- cellCount := 0
- for _ = range cells {
- cellCount++
- }
-
- if cellCount != 256 {
- t.Fail()
- }
-}
-
-func TestGameStateCellsCanHaveTheirValueSet(t *testing.T) {
- state := newTestGameState()
-
- cells, err := state.Cells()
- if err != nil {
- t.Error(err)
- return
- }
-
- for cell := range cells {
- cell.Value = 1
- }
-
- cells, err = state.Cells()
- if err != nil {
- t.Error(err)
- return
- }
-
- for cell := range cells {
- if cell.Value != 1 {
- t.Fail()
- }
- }
-}
-
-func TestGameStateCellsCanBeFetchedByXAndYCoords(t *testing.T) {
- state := newTestGameState()
-
- if state.Get(3, 4) == nil {
- t.Fail()
- }
-}
-
-func TestGameOfLifeEmitsGenerationTicksUntilStasis(t *testing.T) {
- game := newTestGameOfLife()
-
- genTicks, err := game.Generations()
- if err != nil {
- t.Error(err)
- return
- }
-
- nGens := 0
-
- for gen := range genTicks {
- if gen.N > 3000 {
- t.Errorf("%v is too many generations!", gen.N)
- return
- }
- nGens = gen.N
- }
-
- if nGens < 3 {
- t.Errorf("%v is too few generations!", nGens)
- }
-}
-
-func TestGameStateCoordsAreNeverOutOfBounds(t *testing.T) {
- state := newTestGameState()
-
- oobX, oobY := state.Width()+rand.Intn(99), state.Height()+rand.Intn(99)
-
- newVal := rand.Intn(9999)
-
- state.Set(oobX, oobY, newVal)
- cell := state.Get(oobX, oobY)
-
- if cell == nil {
- t.Fail()
- }
-
- if cell.Value != newVal {
- t.Errorf("(%d, %d) != %d: %d", oobX, oobY, newVal, cell.Value)
- }
-}
-
-type testResponseWriter struct {
- Status int
- Headers http.Header
- Body []byte
-}
-
-func (w *testResponseWriter) WriteHeader(status int) {
- w.Status = status
-}
-
-func (w *testResponseWriter) Header() http.Header {
- return w.Headers
-}
-
-func (w *testResponseWriter) Write(bytes []byte) (int, error) {
- w.Body = append(w.Body, bytes[:]...)
- return len(bytes), nil
-}
-
-func newTestResponseWriter() *testResponseWriter {
- return &testResponseWriter{
- Body: []byte(""),
- Headers: make(map[string][]string),
- }
-}
-
-func TestHandleWebGameRootReturnsIndexPageForGET(t *testing.T) {
- req, err := http.NewRequest("GET", "http://localhost:9775/", nil)
- if err != nil {
- t.Error(err)
- return
- }
-
- w := newTestResponseWriter()
- HandleWebGameRoot(w, req)
-
- if w.Status != http.StatusOK {
- t.Errorf("response status != %d: %d", http.StatusOK, w.Status)
- return
- }
-
- matched, err := regexp.MatchString("
Conway's Game of Life
", string(w.Body))
- if err != nil {
- t.Error(err)
- return
- }
-
- if !matched {
- t.Errorf("Body did not match expected element")
- return
- }
-}
-
-func TestHandleWebGameRootReturns405ForNonGET(t *testing.T) {
- req, err := http.NewRequest("OPTIONS", "http://localhost:9775/", nil)
- if err != nil {
- t.Error(err)
- return
- }
-
- w := newTestResponseWriter()
- HandleWebGameRoot(w, req)
-
- if w.Status != http.StatusMethodNotAllowed {
- t.Fail()
- return
- }
-
- matched, err := regexp.MatchString("Nope", string(w.Body))
- if err != nil {
- t.Error(err)
- return
- }
-
- if !matched {
- t.Fail()
- return
- }
-}
-
-func TestHandleWebGameStateGETReturnsRandomImage(t *testing.T) {
- req, err := http.NewRequest("GET", "http://localhost:9775/state", nil)
- if err != nil {
- t.Error(err)
- return
- }
-
- w := newTestResponseWriter()
- HandleWebGameState(w, req)
-
- if w.Status != http.StatusOK {
- t.Errorf("status != %d: %d", http.StatusOK, w.Status)
- return
- }
-
- webState := &WebGameState{}
- err = json.Unmarshal(w.Body, webState)
- if err != nil {
- t.Error(err)
- return
- }
-
- imgB64 := []byte(webState.Img)
- imgBytes := make([]byte, len(imgB64))
-
- _, err = base64.StdEncoding.Decode(imgBytes, imgB64)
- if err != nil {
- t.Error(err)
- return
- }
-
- img, err := png.Decode(bytes.NewBuffer(imgBytes))
- if err != nil {
- t.Error(err)
- return
- }
-
- bounds := img.Bounds()
-
- if bounds.Max.Y < 80 || bounds.Max.X < 80 {
- t.Errorf("Image has incorrect bounds: %+v", bounds)
- return
- }
-}
-
-func TestHandleWebGameStatePOSTWithStateReturnsNextGeneration(t *testing.T) {
- state := newTestGameState()
- webGameState := &WebGameState{State: state, Img: ""}
-
- stateJson, err := json.Marshal(webGameState)
- if err != nil {
- t.Error(err)
- return
- }
-
- reqBuf := bytes.NewBuffer(stateJson)
-
- req, err := http.NewRequest("POST", "http://localhost:9975/state", reqBuf)
- if err != nil {
- t.Errorf("err != nil: %+v", err)
- return
- }
-
- w := newTestResponseWriter()
- HandleWebGameState(w, req)
-
- if w.Status != http.StatusCreated {
- t.Errorf("response status != %d: %d", http.StatusCreated, w.Status)
- return
- }
-}
diff --git a/conway/conways-game-of-life/main.go b/conway/conways-game-of-life/main.go
deleted file mode 100644
index f099de6..0000000
--- a/conway/conways-game-of-life/main.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package main
-
-import (
- "flag"
- "fmt"
- "os"
-)
-
-import (
- . "github.com/meatballhat/box-o-sand/conway"
-)
-
-var (
- height = flag.Int("height", 40, "Game height")
- width = flag.Int("width", 80, "Game width")
- mutate = flag.Bool("mutate", false, "Mutate every other generation")
- web = flag.Bool("web", false, "Run a web-based game.")
- addr = flag.String("addr", ":9775",
- "Address for server of web-based game (ignored if running a console game.)")
- sleepMs = flag.Int("sleep.ms", 200,
- "Millisecond sleep interval per generation")
-)
-
-func main() {
- flag.Parse()
-
- var (
- retCode int
- err error
- )
-
- if *web {
- retCode, err = RunWebGame(*addr, *height, *width, *sleepMs, *mutate)
- if err != nil {
- 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)
-}
diff --git a/conway/doc.go b/conway/doc.go
deleted file mode 100644
index cc0c940..0000000
--- a/conway/doc.go
+++ /dev/null
@@ -1,4 +0,0 @@
-/*
-Conway's Game of Life in Go (console and web.)
-*/
-package conway
diff --git a/conway/game_of_life.go b/conway/game_of_life.go
deleted file mode 100644
index 1a5ff6e..0000000
--- a/conway/game_of_life.go
+++ /dev/null
@@ -1,190 +0,0 @@
-package conway
-
-import (
- "errors"
- "fmt"
- "image"
- "math/rand"
-)
-
-type GameOfLife struct {
- State *GameState
-}
-
-func (game *GameOfLife) Mutate() {
- game.State.Mutate()
-}
-
-func (game *GameOfLife) Checksum() (string, error) {
- return game.State.Checksum()
-}
-
-func NewGameOfLife(height, width int) *GameOfLife {
- return &GameOfLife{
- State: NewGameState(height, width),
- }
-}
-
-func (game *GameOfLife) EvaluateGeneration() error {
- height, width := game.State.Height(), game.State.Width()
-
- genScore := NewGenerationScoreCard(height, width)
- genScore.Calculate(game.State)
-
- cells, err := genScore.Cells()
- if err != nil {
- return err
- }
-
- for cell := range cells {
- score := cell.Value
-
- cell := game.State.Get(cell.X, cell.Y)
-
- if cell.Value == 1 {
- if score < 2 {
- game.State.Deaden(cell.X, cell.Y)
- continue
- }
-
- if score == 2 || score == 3 {
- continue
- }
-
- if score > 3 {
- game.State.Deaden(cell.X, cell.Y)
- continue
- }
- } else if cell.Value == 0 {
-
- if score == 3 {
- game.State.Enliven(cell.X, cell.Y)
- continue
- } else {
- continue
- }
- }
- }
-
- return nil
-}
-
-func (game *GameOfLife) ImportState(state *GameState) {
- game.State.Import(state)
-}
-
-func (game *GameOfLife) ImportRandomState() error {
- height := game.State.Height()
- width := game.State.Width()
-
- if height < 0 || width < 0 {
- errStr := fmt.Sprintf("current game has invalid dimensions! %vx%v",
- height, width)
- return errors.New(errStr)
- }
-
- randState := NewGameState(height, width)
-
- cells, err := randState.Cells()
- if err != nil {
- return err
- }
-
- for cell := range cells {
- cell.Value = rand.Intn(2)
- }
-
- game.ImportState(randState)
- return nil
-}
-
-func (game *GameOfLife) String() string {
- return fmt.Sprintf("%s\n", game.State)
-}
-
-func (game *GameOfLife) Image(xMult, yMult int) (*image.Gray, error) {
- return game.State.Image(xMult, yMult)
-}
-
-func (game *GameOfLife) emitGenerations(genTicks chan *GenerationTick) {
- defer close(genTicks)
- n := 0
-
- checksums := make([]string, 4)
- checksums[0], checksums[1], checksums[2], checksums[3] = "foo", "bar", "baz", "qwx"
- ck, err := game.Checksum()
- if err != nil {
- genTicks <- &GenerationTick{
- N: n,
- Error: err,
- Message: "NAY NAY",
- }
- }
- pushChecksum(ck, checksums)
-
- for {
- game.EvaluateGeneration()
-
- curChecksum, err := game.Checksum()
- if err != nil {
- genTicks <- &GenerationTick{
- N: n,
- Error: err,
- Message: "Failed to calculate current game checksum",
- }
- break
- }
-
- if checksums[0] == curChecksum || checksums[1] == curChecksum {
- genTicks <- &GenerationTick{
- N: n,
- Error: nil,
- Message: "Stasis!",
- }
- break
- }
-
- if checksums[2] == curChecksum {
- genTicks <- &GenerationTick{
- N: n,
- Error: nil,
- Message: "Stasis with 2-period oscillator(s)!",
- }
- break
- }
-
- if checksums[3] == curChecksum {
- genTicks <- &GenerationTick{
- N: n,
- Error: nil,
- Message: "Stasis with 3-period oscillator(s)!",
- }
- break
- }
-
- pushChecksum(curChecksum, checksums)
-
- genTicks <- &GenerationTick{
- N: n,
- Error: nil,
- Message: "",
- }
-
- n++
- }
-}
-
-func (game *GameOfLife) Generations() (<-chan *GenerationTick, error) {
- genTicks := make(chan *GenerationTick)
- go game.emitGenerations(genTicks)
- return (<-chan *GenerationTick)(genTicks), nil
-}
-
-func pushChecksum(checksum string, checksums []string) {
- head := make([]string, 3)
- copy(head, checksums[:3])
- checksums[0] = checksum
- checksums[1] = head[0]
- checksums[2] = head[1]
- checksums[3] = head[2]
-}
diff --git a/conway/game_state.go b/conway/game_state.go
deleted file mode 100644
index 70ba6ef..0000000
--- a/conway/game_state.go
+++ /dev/null
@@ -1,206 +0,0 @@
-package conway
-
-import (
- "crypto/sha1"
- "errors"
- "fmt"
- "image"
- "image/color"
- "image/draw"
- "math"
- "math/rand"
- "strings"
-)
-
-const (
- deadCell = "■"
- liveCell = " "
-)
-
-type GameStateCell struct {
- Value int `json:"v"`
- X int `json:"x"`
- Y int `json:"y"`
-}
-
-type GameStateRow struct {
- Y int `json:"y"`
- Cells []*GameStateCell `json:"c"`
-}
-
-type GameState struct {
- Rows []*GameStateRow `json:"r"`
-}
-
-func NewGameState(height, width int) *GameState {
- state := &GameState{}
- for i := 0; i < height; i++ {
- row := &GameStateRow{Y: i}
- for j := 0; j < width; j++ {
- row.Cells = append(row.Cells, &GameStateCell{
- Value: 0,
- X: j,
- Y: i,
- })
- }
- state.Rows = append(state.Rows, row)
- }
- return state
-}
-
-func (state *GameState) Height() int {
- return len(state.Rows)
-}
-
-func (state *GameState) Width() int {
- if len(state.Rows) < 1 {
- return -1
- }
- return len(state.Rows[0].Cells)
-}
-
-func (state *GameState) GetRow(y int) *GameStateRow {
- lenRows := len(state.Rows)
-
- if y < 0 {
- return state.GetRow(lenRows + y)
- }
-
- if y+1 > lenRows {
- return state.GetRow(y % lenRows)
- }
-
- return state.Rows[y]
-}
-
-func (state *GameState) Set(x, y, value int) {
- cell := state.Get(x, y)
- cell.Value = value
-}
-
-func (state *GameState) Get(x, y int) *GameStateCell {
- row := state.GetRow(y)
- lenCells := len(row.Cells)
-
- if x < 0 {
- return state.Get(lenCells+x, row.Y)
- }
-
- if x+1 > lenCells {
- return state.Get(x%lenCells, row.Y)
- }
-
- return row.Cells[x]
-}
-
-func (state *GameState) Enliven(x, y int) {
- state.Set(x, y, 1)
-}
-
-func (state *GameState) Deaden(x, y int) {
- state.Set(x, y, 0)
-}
-
-func (state *GameState) Import(other *GameState) {
- for y, row := range other.Rows {
- for x, cell := range row.Cells {
- state.Set(x, y, cell.Value)
- }
- }
-}
-
-func (state *GameState) Cells() (<-chan *GameStateCell, error) {
- height := state.Height()
- width := state.Width()
-
- if height < 0 || width < 0 {
- return nil, errors.New("state has invalid dimensions!")
- }
-
- cells := make(chan *GameStateCell)
-
- go func(state *GameState, c chan *GameStateCell) {
- defer close(c)
- height := state.Height()
- width := state.Width()
-
- for y := 0; y < height; y++ {
- for x := 0; x < width; x++ {
- c <- state.Get(x, y)
- }
- }
- }(state, cells)
-
- return (<-chan *GameStateCell)(cells), nil
-}
-
-func (state *GameState) Mutate() {
- randX := rand.Intn(state.Width())
- randY := rand.Intn(state.Height())
-
- cell := state.Get(randX, randY)
- state.Set(randX, randY, int(math.Abs(float64(cell.Value-1))))
-}
-
-func (state *GameState) Checksum() (string, error) {
- ck := sha1.New()
- cells, err := state.Cells()
- if err != nil {
- return "", err
- }
-
- for cell := range cells {
- fmt.Fprintf(ck, "%v", cell.Value)
- }
- return fmt.Sprintf("%x", ck.Sum(nil)), nil
-}
-
-func (state *GameState) String() string {
- var rows []string
-
- height := state.Height()
- width := state.Width()
-
- for y := 0; y < height; y++ {
- var cells []string
- for x := 0; x < width; x++ {
- stringVal := deadCell
-
- cell := state.Get(x, y)
- if cell.Value == 1 {
- stringVal = liveCell
- }
- cells = append(cells, stringVal)
- }
- rows = append(rows, strings.Join(cells, ""))
- }
- return strings.Join(rows, "\n")
-}
-
-func (state *GameState) Image(xMult, yMult int) (*image.Gray, error) {
- img := image.NewGray(image.Rect(0, 0,
- (state.Height()*xMult)+1, (state.Width()*yMult)+1))
- draw.Draw(img, img.Bounds(), &image.Uniform{color.Gray16{0xff}},
- image.ZP, draw.Src)
-
- cells, err := state.Cells()
- if err != nil {
- return nil, err
- }
-
- black := &image.Uniform{color.Black}
- white := &image.Uniform{color.White}
-
- for cell := range cells {
- color := white
- if cell.Value == 1 {
- color = black
- }
-
- square := image.Rect((cell.X*xMult)+1, (cell.Y*yMult)+1,
- (cell.X*xMult)+xMult, (cell.Y*yMult)+yMult)
- draw.Draw(img, square, color, image.ZP, draw.Src)
- }
-
- return img, nil
-}
diff --git a/conway/gen-web-assets b/conway/gen-web-assets
deleted file mode 100755
index 2223023..0000000
--- a/conway/gen-web-assets
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-set -e
-
-case "$1" in
- "shell")
-cat > _tmp.go < web_assets.go
-rm -v _tmp.go
- ;;
- *)
-cd web_assets
-go build -x .
-./web_assets index.html > _tmp.go
-gofmt < _tmp.go > ../web_assets.go
-rm -vf _tmp.go
- ;;
-esac
diff --git a/conway/generation_score_card.go b/conway/generation_score_card.go
deleted file mode 100644
index 8c308f5..0000000
--- a/conway/generation_score_card.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package conway
-
-var (
- neighbors = []neighbor{
- neighbor{-1, -1},
- neighbor{-1, 0},
- neighbor{-1, 1},
- neighbor{0, -1},
- neighbor{0, 1},
- neighbor{1, -1},
- neighbor{1, 0},
- neighbor{1, 1},
- }
-)
-
-type GenerationScoreCard struct {
- GameState
-}
-
-type neighbor struct {
- X int
- Y int
-}
-
-func NewGenerationScoreCard(height, width int) *GenerationScoreCard {
- genScore := &GenerationScoreCard{}
- for i := 0; i < height; i++ {
- row := &GameStateRow{Y: i}
- for j := 0; j < width; j++ {
- row.Cells = append(row.Cells, &GameStateCell{
- Value: 0,
- X: j,
- Y: i,
- })
- }
- genScore.Rows = append(genScore.Rows, row)
- }
- return genScore
-}
-
-func (genScore *GenerationScoreCard) Calculate(state *GameState) error {
- stateCells, err := state.Cells()
- if err != nil {
- return err
- }
-
- for stateCell := range stateCells {
- if stateCell.Value == 0 {
- continue
- }
-
- for _, neighbor := range neighbors {
- xTarget := stateCell.X + neighbor.X
- yTarget := stateCell.Y + neighbor.Y
-
- cell := genScore.Get(xTarget, yTarget)
- genScore.Set(xTarget, yTarget, cell.Value+1)
- }
- }
-
- return nil
-}
diff --git a/conway/generation_tick.go b/conway/generation_tick.go
deleted file mode 100644
index af25e9e..0000000
--- a/conway/generation_tick.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package conway
-
-type GenerationTick struct {
- N int
- Error error
- Message string
-}
diff --git a/conway/web.go b/conway/web.go
deleted file mode 100644
index b339a6e..0000000
--- a/conway/web.go
+++ /dev/null
@@ -1,272 +0,0 @@
-package conway
-
-import (
- "bytes"
- "compress/gzip"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "image/png"
- "io/ioutil"
- "log"
- "math/rand"
- "net/http"
- "net/url"
- "strconv"
- "time"
-)
-
-type WebGameParams struct {
- Height int
- Width int
- Xmul int
- Ymul int
-}
-
-type WebGameState struct {
- State *GameState `json:"s"`
- Img string `json:"i"`
-}
-
-type webAssetStrings struct {
- IndexHTML []byte
- NormalizeCSS []byte
- JqueryMinJS []byte
-}
-
-var WebAssets webAssetStrings
-
-func init() {
- rand.Seed(time.Now().UTC().UnixNano())
- idxHt, err := fromGzB64(gameOfLifeIndexHtml)
- if err != nil {
- log.Fatal("Failed to decode internal index.html: ", err)
- }
-
- WebAssets.IndexHTML = idxHt
-
- normCss, err := fromGzB64(normalizeCss)
- if err != nil {
- log.Fatal("Failed to decode internal normalize.css: ", err)
- }
- WebAssets.NormalizeCSS = normCss
-
- jqmin, err := fromGzB64(jqueryMinJs)
- if err != nil {
- log.Fatal("Failed to decode internal jquery.min.js: ", err)
- }
- WebAssets.JqueryMinJS = jqmin
-}
-
-func fromGzB64(input string) ([]byte, error) {
- decoded, err := base64.StdEncoding.DecodeString(input)
- if err != nil {
- return []byte(""), err
- }
-
- buf := bytes.NewBuffer(decoded)
- zReader, err := gzip.NewReader(buf)
- if err != nil {
- return []byte(""), err
- }
-
- defer zReader.Close()
-
- gunzipped, err := ioutil.ReadAll(zReader)
- if err != nil {
- return []byte(""), err
- }
-
- return gunzipped, nil
-}
-
-func NewWebGameParams(q url.Values) *WebGameParams {
- params := &WebGameParams{
- Height: 50,
- Width: 50,
- Xmul: 10,
- Ymul: 10,
- }
-
- h := q.Get("h")
- if len(h) > 0 {
- if i, err := strconv.Atoi(h); err == nil {
- params.Height = i
- }
- }
-
- w := q.Get("w")
- if len(w) > 0 {
- if i, err := strconv.Atoi(w); err == nil {
- params.Width = i
- }
- }
-
- xm := q.Get("xm")
- if len(xm) > 0 {
- if i, err := strconv.Atoi(xm); err == nil {
- params.Xmul = i
- }
- }
-
- ym := q.Get("ym")
- if len(ym) > 0 {
- if i, err := strconv.Atoi(ym); err == nil {
- params.Ymul = i
- }
- }
-
- return params
-}
-
-func handle405(method, uri string, w http.ResponseWriter) {
- w.Header().Set("Content-Type", "text/plain")
- w.WriteHeader(http.StatusMethodNotAllowed)
- w.Write([]byte(fmt.Sprintf("Nope. %v not allowed at %v\n", method, uri)))
-}
-
-func handle500(err error, w http.ResponseWriter) {
- log.Println("ERROR:", err)
- w.Header().Set("Content-Type", "text/plain")
- w.WriteHeader(http.StatusInternalServerError)
- w.Write([]byte(fmt.Sprintf("We exploded!: %v\n", err)))
-}
-
-func HandleWebGameRoot(w http.ResponseWriter, req *http.Request) {
- if req.Method != "GET" {
- handle405(req.Method, req.RequestURI, w)
- return
- }
-
- w.Header().Set("Content-Type", "text/html")
- w.WriteHeader(http.StatusOK)
- w.Write(WebAssets.IndexHTML)
- return
-}
-
-func HandleWebGameStatic(w http.ResponseWriter, req *http.Request) {
- if req.Method != "GET" {
- handle405(req.Method, req.RequestURI, w)
- return
- }
-
- if req.URL.Path == "/static/normalize.css" {
- w.Header().Set("Content-Type", "text/css")
- w.WriteHeader(http.StatusOK)
- w.Write(WebAssets.NormalizeCSS)
- return
- }
-
- if req.URL.Path == "/static/jquery.min.js" {
- w.Header().Set("Content-Type", "text/javascript")
- w.WriteHeader(http.StatusOK)
- w.Write(WebAssets.JqueryMinJS)
- return
- }
-
- w.Header().Set("Content-Type", "text/plain")
- w.WriteHeader(http.StatusNotFound)
- w.Write([]byte(fmt.Sprintf("Don't have: %v\n", req.URL.Path)))
-}
-
-func HandleWebGameState(w http.ResponseWriter, req *http.Request) {
- switch req.Method {
- case "GET":
- handleWebGameStateGET(w, req)
- return
- case "POST":
- handleWebGameStatePOST(w, req)
- return
- default:
- handle405(req.Method, req.RequestURI, w)
- return
- }
-}
-
-func handleWebGameStateGET(w http.ResponseWriter, req *http.Request) {
- q := req.URL.Query()
- params := NewWebGameParams(q)
-
- game := NewGameOfLife(params.Height, params.Width)
- err := game.ImportRandomState()
- if err != nil {
- handle500(err, w)
- return
- }
-
- sendWebGameStateJSONPayload(w, http.StatusOK, game, params)
-}
-
-func handleWebGameStatePOST(w http.ResponseWriter, req *http.Request) {
- q := req.URL.Query()
- params := NewWebGameParams(q)
-
- defer func() {
- r := recover()
- if r != nil {
- handle500(errors.New(fmt.Sprintf("OH NOES! %v", r)), w)
- }
- }()
-
- body, err := ioutil.ReadAll(req.Body)
- if err != nil {
- handle500(err, w)
- }
-
- webGameState := &WebGameState{}
- err = json.Unmarshal(body, webGameState)
- if err != nil {
- handle500(err, w)
- }
-
- height, width := webGameState.State.Height(), webGameState.State.Width()
- game := NewGameOfLife(height, width)
- game.ImportState(webGameState.State)
-
- game.EvaluateGeneration()
-
- sendWebGameStateJSONPayload(w, http.StatusCreated, game, params)
-}
-
-func sendWebGameStateJSONPayload(w http.ResponseWriter, status int, game *GameOfLife, params *WebGameParams) {
- img, err := game.Image(params.Xmul, params.Ymul)
-
- if err != nil {
- handle500(err, w)
- return
- }
-
- log.Println("Serving state image.")
-
- var pngBuf bytes.Buffer
- err = png.Encode(&pngBuf, img)
- if err != nil {
- handle500(err, w)
- }
-
- imgB64 := base64.StdEncoding.EncodeToString(pngBuf.Bytes())
- webGameState := &WebGameState{State: game.State, Img: imgB64}
- wgsJson, err := json.Marshal(webGameState)
-
- if err != nil {
- handle500(err, w)
- }
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(status)
- w.Write(wgsJson)
-}
-
-func RunWebGame(address string, height, width, sleepMs int, mutate bool) (int, error) {
- http.HandleFunc("/", HandleWebGameRoot)
- http.HandleFunc("/state", HandleWebGameState)
- http.HandleFunc("/static/", HandleWebGameStatic)
-
- fmt.Printf("Serving on %v\n", address)
- err := http.ListenAndServe(address, nil)
- if err != nil {
- return 1, err
- }
- return 0, nil
-}
diff --git a/conway/web_assets.go b/conway/web_assets.go
deleted file mode 100644
index f375e58..0000000
--- a/conway/web_assets.go
+++ /dev/null
@@ -1,646 +0,0 @@
-package conway
-
-// WARNING: GENERATED FILE, NERDS! 2012-12-26 10:57:04.843003 -0500 EST
-
-const (
- gameOfLifeIndexHtml = `
-H4sIAAAJbogC/5RV32/bNhB+719xUwJIxlQpCboBsRW/dMOWYWiDxAO2p4GRzjJdilTJU1ov8P8+
-Ur8tu0HjB1ni3X3f3cfjMfnhl4/vV//c/QobKsTyTdL8ASQbZJl7sa/ESeDyvZJf2M438BsrENQa
-/uRrTOLG2DgKLj8B7Uq88Qi/Upwa44FGceMZ2gk0G0TyYKNxfePFhhjxNJZKF0zw/zCqveMWyqSa
-lzQG27In1qx6YHQ6IGw/V6h3UcFltDXeMokbr+8BanwA0ko/WDCEG3jeL4bF2yK3S563eNOurSuZ
-ElcSSlVWwkbcSk6ciTo6mMFz6wdwHuVIfzx8/BD4daLohxY7BCXv2tB7NKWSBmcd4f6IJVcr9cHm
-3MDXMCEIpcpDplIZCvpvgJ5xtOZSiQxpLnO+3gXPZg61k01JVkKEcDUbu3cpBBkjFgK1SVQmhO3n
-v3+/Hyfgfk9MN3hWr+MSv4myOADhawim1TU/g7TiBaqKgj4z6/WCQAuwlf10cTGh2I++9uOC/a1R
-0u8XXtiUV5R3sEvWijILul4LwUVFZpRg33G1hQ8Gp+55XV1jPw/8s/rzX17k/gjBKdg7RgJlThtI
-4PJQ0QlUYkGAZ+6UtpDuHPqziJWlzXilgoEvVZIYl6j92Yh2UHUgZ0Q68O1JtY3vu4LmvGA5xqXM
-F4/M4M/vQh9+BJSpyvCv+9ugKXoMq5EqLVudjjbk/KAV+qDTJ3MAbWrB0taXCp5+eqmhur1y3TSB
-KIUdhq+AsO2hq0Og7m06sdysnI7RblI9qmw3KtbZ39rxmcs5pCgJ9ZFMZ/2WjeIKpnNuYy6AVaSG
-yr7wjDZzuLy4eld+XZykEbimY5JJdxxRvSVVzuHqcoxasiyz46gxXY8tj0pnqBuDDQGjBM/g7Pr6
-emBulXNi1RdW3N1YidOo1TLjT3Vn94n1Qiaby29dadbSOY3jtRLDPjiaisiOA2d2zeAt7+wziZvl
-036u77zlg31O/ZLYUh3RTlT1Tnj3rxaxrtvmX9/h/wcAAP//rQ2TxtsHAAA=`
- normalizeCss = `
-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`
- jqueryMinJs = `
-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
-f8vzG5z8/wAAAP//TQkipcVtAQA=`
-)
diff --git a/conway/web_assets/gen.go b/conway/web_assets/gen.go
deleted file mode 100644
index 3109bac..0000000
--- a/conway/web_assets/gen.go
+++ /dev/null
@@ -1,183 +0,0 @@
-package main
-
-import (
- "bufio"
- "bytes"
- "compress/gzip"
- "encoding/base64"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "strings"
- "text/template"
- "time"
-)
-
-const b64Width = 76
-
-var (
- webAssetsTmpl = template.Must(template.New("web_assets").Parse("" +
- "package conway\n" +
- "// WARNING: GENERATED FILE, NERDS! {{.Now}}\n" +
- "\n" +
- "const (\n" +
- " gameOfLifeIndexHtml = `{{.IndexHTML}}`\n" +
- " normalizeCss = `{{.NormalizeCSS}}`\n" +
- " jqueryMinJs = `{{.JqueryMinJS}}`\n" +
- ")\n"))
- normalizeCssUrl = "http://necolas.github.com/normalize.css/2.0.1/normalize.css"
- jqueryMinJsUrl = "http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"
-)
-
-type webAssetStrings struct {
- IndexHTML string
- NormalizeCSS string
- JqueryMinJS string
- Now time.Time
-}
-
-func die(err error) {
- log.Fatal("CRUD:", err)
-}
-
-func toB64(input []byte) string {
- var (
- err error
- out bytes.Buffer
- )
- encoded := base64.StdEncoding.EncodeToString(input)
- lenEncoded := len(encoded)
-
- outbuf := bufio.NewWriter(&out)
- inbuf := strings.NewReader(encoded)
-
- outbuf.WriteByte('\n')
- if err != nil {
- die(err)
- }
-
- nWritten := 0
- for {
- for n := 0; n < b64Width; n++ {
- c, err := inbuf.ReadByte()
- if err == io.EOF {
- break
- }
-
- if err != nil {
- die(err)
- }
-
- err = outbuf.WriteByte(c)
- if err != nil {
- die(err)
- }
-
- nWritten++
- }
-
- _, err := inbuf.ReadByte()
- if err == io.EOF {
- break
- }
-
- if err != nil {
- die(err)
- }
-
- err = inbuf.UnreadByte()
- if err != nil {
- die(err)
- }
-
- err = outbuf.WriteByte('\n')
- if err != nil {
- die(err)
- }
- }
-
- if nWritten != lenEncoded {
- die(errors.New(fmt.Sprintf("base64-encoded length = %d, but wrote %d",
- lenEncoded, nWritten)))
- }
-
- outbuf.Flush()
- return string(out.Bytes())
-}
-
-func toGz(input []byte) []byte {
- var buf bytes.Buffer
-
- zwriter, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)
- if err != nil {
- die(err)
- }
-
- zbuf := bufio.NewWriter(zwriter)
-
- toWrite := len(input)
- for written := 0; written < toWrite; {
- n, err := zbuf.Write(input[written:])
- if err != nil {
- die(err)
- }
- written += n
- }
-
- zbuf.Flush()
- zwriter.Close()
- return buf.Bytes()
-}
-
-func fetchUrl(url string) []byte {
- resp, err := http.Get(url)
- if err != nil {
- die(err)
- }
-
- defer resp.Body.Close()
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- die(err)
- }
-
- return body
-}
-
-func fetchIndexHtml(indexHtmlPath string) []byte {
- fd, err := os.Open(indexHtmlPath)
- if err != nil {
- die(err)
- }
-
- body, err := ioutil.ReadAll(fd)
- if err != nil {
- die(err)
- }
-
- return body
-}
-
-func toB64Gz(input []byte) string {
- return string(toB64(toGz(input)))
-}
-
-func main() {
- if len(os.Args) < 2 {
- die(errors.New(fmt.Sprintf("Usage: %s ", os.Args[0])))
- }
-
- assets := &webAssetStrings{
- IndexHTML: toB64Gz(fetchIndexHtml(os.Args[1])),
- NormalizeCSS: toB64Gz(fetchUrl(normalizeCssUrl)),
- JqueryMinJS: toB64Gz(fetchUrl(jqueryMinJsUrl)),
- Now: time.Now(),
- }
-
- webAssetsTmpl.Execute(os.Stdout, assets)
-}
diff --git a/conway/web_assets/index.html b/conway/web_assets/index.html
deleted file mode 100644
index 238659d..0000000
--- a/conway/web_assets/index.html
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
- Conway's Game of Life
-
-
-
-
-
-
-
-
Conway's Game of Life
-
-
-
-
-
-
-
-
-