From d7ee7b97fb56c1389c3e7400ee4dd04d2b8a7d34 Mon Sep 17 00:00:00 2001 From: bvanvugt <1531419+bvanvugt@users.noreply.github.com> Date: Mon, 7 Dec 2020 18:11:00 -0800 Subject: [PATCH] New "feast" game mode (alpha) --- feast.go | 41 ++++++++++++++++++++ feast_test.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 feast.go create mode 100644 feast_test.go diff --git a/feast.go b/feast.go new file mode 100644 index 0000000..0f916f3 --- /dev/null +++ b/feast.go @@ -0,0 +1,41 @@ +package rules + +import () + +type FeastRuleset struct { + StandardRuleset +} + +func (r *FeastRuleset) CreateInitialBoardState(width int32, height int32, snakeIDs []string) (*BoardState, error) { + initialBoardState, err := r.StandardRuleset.CreateInitialBoardState(width, height, snakeIDs) + if err != nil { + return nil, err + } + + err = r.fillBoardWithFood(initialBoardState) + if err != nil { + return nil, err + } + + return initialBoardState, nil +} + +func (r *FeastRuleset) CreateNextBoardState(prevState *BoardState, moves []SnakeMove) (*BoardState, error) { + nextState, err := r.StandardRuleset.CreateNextBoardState(prevState, moves) + if err != nil { + return nil, err + } + + err = r.fillBoardWithFood(nextState) + if err != nil { + return nil, err + } + + return nextState, nil +} + +func (r *FeastRuleset) fillBoardWithFood(b *BoardState) error { + unoccupiedPoints := r.getUnoccupiedPoints(b, true) + b.Food = append(b.Food, unoccupiedPoints...) + return nil +} diff --git a/feast_test.go b/feast_test.go new file mode 100644 index 0000000..c3eb74f --- /dev/null +++ b/feast_test.go @@ -0,0 +1,105 @@ +package rules + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFeastRulesetInterface(t *testing.T) { + var _ Ruleset = (*FeastRuleset)(nil) +} + +func TestFeastCreateInitialBoardState(t *testing.T) { + tests := []struct { + Height int32 + Width int32 + IDs []string + ExpectedNumFood int + Err error + }{ + {1, 1, []string{}, 1, nil}, + {1, 1, []string{"one"}, 0, nil}, + {2, 2, []string{"one"}, 3, nil}, + {2, 2, []string{"one", "two"}, 2, nil}, + {11, 1, []string{"one", "two"}, 9, nil}, + {11, 11, []string{}, 121, nil}, + {11, 11, []string{"one", "two", "three", "four", "five"}, 116, nil}, + } + + r := FeastRuleset{} + for testNum, test := range tests { + state, err := r.CreateInitialBoardState(test.Width, test.Height, test.IDs) + require.Equal(t, test.Err, err) + if err != nil { + require.Nil(t, state) + continue + } + require.NotNil(t, state) + require.Equal(t, test.Width, state.Width) + require.Equal(t, test.Height, state.Height) + require.Equal(t, len(test.IDs), len(state.Snakes)) + for i, id := range test.IDs { + require.Equal(t, id, state.Snakes[i].ID) + } + require.Len(t, state.Food, test.ExpectedNumFood, testNum) + } +} + +func TestFeastCreateNextBoardState(t *testing.T) { + tests := []struct { + prevState *BoardState + moves []SnakeMove + expectedError error + expectedState *BoardState + }{ + { + &BoardState{ + Width: 3, + Height: 3, + Snakes: []Snake{ + { + ID: "one", + Body: []Point{{0, 0}, {1, 0}, {2, 0}}, + Health: 100, + }, + { + ID: "two", + Body: []Point{{2, 2}, {1, 2}, {0, 2}}, + Health: 100, + }, + }, + Food: []Point{}, + }, + []SnakeMove{ + {ID: "one", Move: MoveDown}, + {ID: "two", Move: MoveUp}, + }, + nil, + &BoardState{ + Width: 3, + Height: 3, + Snakes: []Snake{ + { + ID: "one", + Body: []Point{{0, 1}, {0, 0}, {1, 0}}, + Health: 99, + }, + { + ID: "two", + Body: []Point{{2, 1}, {2, 2}, {1, 2}}, + Health: 99, + }, + }, + Food: []Point{{0, 2}, {1, 1}, {2, 0}}, + }, + }, + } + + r := FeastRuleset{} + for _, test := range tests { + nextState, err := r.CreateNextBoardState(test.prevState, test.moves) + require.Equal(t, test.expectedError, err) + require.Equal(t, test.expectedState, nextState) + } +}