diff --git a/board.go b/board.go index 8eedda2..ce37d7c 100644 --- a/board.go +++ b/board.go @@ -3,6 +3,7 @@ package rules import "math/rand" type BoardState struct { + Turn int32 Height int32 Width int32 Food []Point @@ -13,6 +14,7 @@ type BoardState struct { // NewBoardState returns an empty but fully initialized BoardState func NewBoardState(width, height int32) *BoardState { return &BoardState{ + Turn: 0, Height: height, Width: width, Food: []Point{}, @@ -24,6 +26,7 @@ func NewBoardState(width, height int32) *BoardState { // Clone returns a deep copy of prevState that can be safely modified inside Ruleset.CreateNextBoardState func (prevState *BoardState) Clone() *BoardState { nextState := &BoardState{ + Turn: prevState.Turn, Height: prevState.Height, Width: prevState.Width, Food: append([]Point{}, prevState.Food...), diff --git a/cli/commands/play.go b/cli/commands/play.go index 27d5e28..4167091 100644 --- a/cli/commands/play.go +++ b/cli/commands/play.go @@ -134,8 +134,7 @@ var run = func(cmd *cobra.Command, args []string) { snakes := buildSnakesFromOptions() - var ruleset rules.Ruleset - ruleset = getRuleset(Seed, Turn, snakes) + ruleset := getRuleset(Seed, snakes) state := initializeBoardFromArgs(ruleset, snakes) for _, snake := range snakes { Battlesnakes[snake.ID] = snake @@ -143,8 +142,7 @@ var run = func(cmd *cobra.Command, args []string) { for v := false; !v; v, _ = ruleset.IsGameOver(state) { Turn++ - ruleset = getRuleset(Seed, Turn, snakes) - state = createNextBoardState(ruleset, state, snakes) + state = createNextBoardState(ruleset, state, snakes, Turn) if ViewMap { printMap(state, Turn) @@ -178,7 +176,7 @@ var run = func(cmd *cobra.Command, args []string) { } } -func getRuleset(seed int64, gameTurn int32, snakes []Battlesnake) rules.Ruleset { +func getRuleset(seed int64, snakes []Battlesnake) rules.Ruleset { var ruleset rules.Ruleset var royale rules.RoyaleRuleset @@ -193,7 +191,6 @@ func getRuleset(seed int64, gameTurn int32, snakes []Battlesnake) rules.Ruleset royale = rules.RoyaleRuleset{ StandardRuleset: standard, Seed: seed, - Turn: gameTurn, ShrinkEveryNTurns: 10, } ruleset = &royale @@ -261,7 +258,7 @@ func initializeBoardFromArgs(ruleset rules.Ruleset, snakes []Battlesnake) *rules return state } -func createNextBoardState(ruleset rules.Ruleset, state *rules.BoardState, snakes []Battlesnake) *rules.BoardState { +func createNextBoardState(ruleset rules.Ruleset, state *rules.BoardState, snakes []Battlesnake, turn int32) *rules.BoardState { var moves []rules.SnakeMove if Sequential { for _, snake := range snakes { @@ -301,6 +298,9 @@ func createNextBoardState(ruleset rules.Ruleset, state *rules.BoardState, snakes log.Panic("[PANIC]: Error Producing Next Board State") panic(err) } + + state.Turn = turn + return state } diff --git a/royale.go b/royale.go index ecd2c67..ec8a645 100644 --- a/royale.go +++ b/royale.go @@ -10,8 +10,6 @@ type RoyaleRuleset struct { Seed int64 - // TODO: move Turn into BoardState? - Turn int32 ShrinkEveryNTurns int32 } @@ -28,7 +26,7 @@ func (r *RoyaleRuleset) CreateNextBoardState(prevState *BoardState, moves []Snak } // Royale's only job is now to populate the hazards for next turn - StandardRuleset takes care of applying hazard damage. - err = r.populateHazards(nextBoardState, r.Turn) + err = r.populateHazards(nextBoardState, prevState.Turn+1) if err != nil { return nil, err } diff --git a/royale_test.go b/royale_test.go index 8dba985..f15366f 100644 --- a/royale_test.go +++ b/royale_test.go @@ -89,6 +89,7 @@ func TestRoyaleHazards(t *testing.T) { for _, test := range tests { b := &BoardState{ + Turn: test.Turn, Width: test.Width, Height: test.Height, } @@ -97,7 +98,6 @@ func TestRoyaleHazards(t *testing.T) { HazardDamagePerTurn: 1, }, Seed: seed, - Turn: test.Turn, ShrinkEveryNTurns: test.ShrinkEveryNTurns, } @@ -127,46 +127,49 @@ func TestRoyalDamageNextTurn(t *testing.T) { r := RoyaleRuleset{StandardRuleset: StandardRuleset{HazardDamagePerTurn: 30}, Seed: seed, ShrinkEveryNTurns: 10} m := []SnakeMove{{ID: "one", Move: "down"}} - r.Turn = 10 - err := r.populateHazards(base, r.Turn-1) - require.NoError(t, err) - next, err := r.CreateNextBoardState(base, m) + stateAfterTurn := func(prevState *BoardState, turn int32) *BoardState { + nextState := prevState.Clone() + nextState.Turn = turn - 1 + err := r.populateHazards(nextState, turn) + require.NoError(t, err) + nextState.Turn = turn + return nextState + } + + prevState := stateAfterTurn(base, 9) + next, err := r.CreateNextBoardState(prevState, m) require.NoError(t, err) require.Equal(t, NotEliminated, next.Snakes[0].EliminatedCause) require.Equal(t, int32(99), next.Snakes[0].Health) require.Equal(t, Point{9, 0}, next.Snakes[0].Body[0]) require.Equal(t, 10, len(next.Hazards)) // X = 0 - r.Turn = 20 - err = r.populateHazards(base, r.Turn-1) - require.NoError(t, err) - next, err = r.CreateNextBoardState(base, m) + prevState = stateAfterTurn(base, 19) + next, err = r.CreateNextBoardState(prevState, m) require.NoError(t, err) require.Equal(t, NotEliminated, next.Snakes[0].EliminatedCause) require.Equal(t, int32(99), next.Snakes[0].Health) require.Equal(t, Point{9, 0}, next.Snakes[0].Body[0]) require.Equal(t, 20, len(next.Hazards)) // X = 9 - r.Turn = 21 - err = r.populateHazards(base, r.Turn-1) - require.NoError(t, err) - next, err = r.CreateNextBoardState(base, m) + prevState = stateAfterTurn(base, 20) + next, err = r.CreateNextBoardState(prevState, m) require.NoError(t, err) require.Equal(t, NotEliminated, next.Snakes[0].EliminatedCause) require.Equal(t, int32(69), next.Snakes[0].Health) require.Equal(t, Point{9, 0}, next.Snakes[0].Body[0]) require.Equal(t, 20, len(next.Hazards)) - base.Snakes[0].Health = 15 - next, err = r.CreateNextBoardState(base, m) + prevState.Snakes[0].Health = 15 + next, err = r.CreateNextBoardState(prevState, m) require.NoError(t, err) require.Equal(t, EliminatedByOutOfHealth, next.Snakes[0].EliminatedCause) require.Equal(t, int32(0), next.Snakes[0].Health) require.Equal(t, Point{9, 0}, next.Snakes[0].Body[0]) require.Equal(t, 20, len(next.Hazards)) - base.Food = append(base.Food, Point{9, 0}) - next, err = r.CreateNextBoardState(base, m) + prevState.Food = append(prevState.Food, Point{9, 0}) + next, err = r.CreateNextBoardState(prevState, m) require.NoError(t, err) require.Equal(t, Point{9, 0}, next.Snakes[0].Body[0]) require.Equal(t, NotEliminated, next.Snakes[0].EliminatedCause)