Add parameters for food spawn chance and min food.
This commit is contained in:
parent
c6d9ba12ab
commit
ca4b6c5dce
2 changed files with 88 additions and 20 deletions
18
standard.go
18
standard.go
|
|
@ -6,15 +6,16 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StandardRuleset struct{}
|
type StandardRuleset struct {
|
||||||
|
FoodSpawnChance int32 // [0, 100]
|
||||||
|
MinimumFood int32
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BoardSizeSmall = 7
|
BoardSizeSmall = 7
|
||||||
BoardSizeMedium = 11
|
BoardSizeMedium = 11
|
||||||
BoardSizeLarge = 19
|
BoardSizeLarge = 19
|
||||||
|
|
||||||
FoodSpawnChance = 0.15
|
|
||||||
|
|
||||||
SnakeMaxHealth = 100
|
SnakeMaxHealth = 100
|
||||||
SnakeStartSize = 3
|
SnakeStartSize = 3
|
||||||
|
|
||||||
|
|
@ -173,7 +174,7 @@ func (r *StandardRuleset) placeFoodFixed(b *BoardState) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StandardRuleset) placeFoodRandomly(b *BoardState) error {
|
func (r *StandardRuleset) placeFoodRandomly(b *BoardState) error {
|
||||||
return r.spawnFood(b, len(b.Snakes))
|
return r.spawnFood(b, int32(len(b.Snakes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StandardRuleset) isKnownBoardSize(b *BoardState) bool {
|
func (r *StandardRuleset) isKnownBoardSize(b *BoardState) bool {
|
||||||
|
|
@ -518,14 +519,17 @@ func (r *StandardRuleset) growSnake(snake *Snake) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StandardRuleset) maybeSpawnFood(b *BoardState) error {
|
func (r *StandardRuleset) maybeSpawnFood(b *BoardState) error {
|
||||||
if len(b.Food) == 0 || rand.Float32() <= FoodSpawnChance {
|
numCurrentFood := int32(len(b.Food))
|
||||||
|
if numCurrentFood < r.MinimumFood {
|
||||||
|
return r.spawnFood(b, r.MinimumFood-numCurrentFood)
|
||||||
|
} else if r.FoodSpawnChance > 0 && int32(rand.Intn(100)) < r.FoodSpawnChance {
|
||||||
return r.spawnFood(b, 1)
|
return r.spawnFood(b, 1)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StandardRuleset) spawnFood(b *BoardState, n int) error {
|
func (r *StandardRuleset) spawnFood(b *BoardState, n int32) error {
|
||||||
for i := 0; i < n; i++ {
|
for i := int32(0); i < n; i++ {
|
||||||
unoccupiedPoints := r.getUnoccupiedPoints(b, false)
|
unoccupiedPoints := r.getUnoccupiedPoints(b, false)
|
||||||
if len(unoccupiedPoints) > 0 {
|
if len(unoccupiedPoints) > 0 {
|
||||||
newFood := unoccupiedPoints[rand.Intn(len(unoccupiedPoints))]
|
newFood := unoccupiedPoints[rand.Intn(len(unoccupiedPoints))]
|
||||||
|
|
|
||||||
|
|
@ -1828,22 +1828,89 @@ func TestGetEvenUnoccupiedPoints(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaybeSpawnFood(t *testing.T) {
|
func TestMaybeSpawnFoodMinimum(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
MinimumFood int32
|
||||||
|
Food []Point
|
||||||
|
ExpectedFood int
|
||||||
|
}{
|
||||||
|
// Use pre-tested seeds and results
|
||||||
|
{0, []Point{}, 0},
|
||||||
|
{1, []Point{}, 1},
|
||||||
|
{9, []Point{}, 9},
|
||||||
|
{7, []Point{{4, 5}, {4, 4}, {4, 1}}, 7},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
r := StandardRuleset{MinimumFood: test.MinimumFood}
|
||||||
|
b := &BoardState{
|
||||||
|
Height: 11,
|
||||||
|
Width: 11,
|
||||||
|
Snakes: []Snake{
|
||||||
|
{Body: []Point{{1, 0}, {1, 1}}},
|
||||||
|
{Body: []Point{{0, 1}, {0, 2}, {0, 3}}},
|
||||||
|
},
|
||||||
|
Food: test.Food,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.maybeSpawnFood(b)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, test.ExpectedFood, len(b.Food))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaybeSpawnFoodZeroChance(t *testing.T) {
|
||||||
|
r := StandardRuleset{FoodSpawnChance: 0}
|
||||||
|
b := &BoardState{
|
||||||
|
Height: 11,
|
||||||
|
Width: 11,
|
||||||
|
Snakes: []Snake{
|
||||||
|
{Body: []Point{{1, 0}, {1, 1}}},
|
||||||
|
{Body: []Point{{0, 1}, {0, 2}, {0, 3}}},
|
||||||
|
},
|
||||||
|
Food: []Point{},
|
||||||
|
}
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
err := r.maybeSpawnFood(b)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, len(b.Food), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaybeSpawnFoodHundredChance(t *testing.T) {
|
||||||
|
r := StandardRuleset{FoodSpawnChance: 100}
|
||||||
|
b := &BoardState{
|
||||||
|
Height: 11,
|
||||||
|
Width: 11,
|
||||||
|
Snakes: []Snake{
|
||||||
|
{Body: []Point{{1, 0}, {1, 1}}},
|
||||||
|
{Body: []Point{{0, 1}, {0, 2}, {0, 3}}},
|
||||||
|
},
|
||||||
|
Food: []Point{},
|
||||||
|
}
|
||||||
|
for i := 1; i <= 22; i++ {
|
||||||
|
err := r.maybeSpawnFood(b)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, i, len(b.Food))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaybeSpawnFoodHalfChance(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Seed int64
|
Seed int64
|
||||||
Food []Point
|
Food []Point
|
||||||
ExpectedFood []Point
|
ExpectedFood int32
|
||||||
}{
|
}{
|
||||||
// Use pre-tested seeds and results
|
// Use pre-tested seeds and results
|
||||||
{123, []Point{}, []Point{{2, 3}}},
|
{123, []Point{}, 1},
|
||||||
{456, []Point{{4, 4}}, []Point{{4, 4}}},
|
{12345, []Point{}, 0},
|
||||||
{789, []Point{{4, 4}}, []Point{{4, 4}}},
|
{456, []Point{{4, 4}}, 1},
|
||||||
{1024, []Point{}, []Point{{1, 2}}},
|
{789, []Point{{4, 4}}, 2},
|
||||||
{511, []Point{{4, 4}}, []Point{{4, 4}, {4, 1}}},
|
{511, []Point{{4, 4}}, 1},
|
||||||
{165, []Point{{4, 4}}, []Point{{4, 4}, {4, 2}}},
|
{165, []Point{{4, 4}}, 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
r := StandardRuleset{}
|
r := StandardRuleset{FoodSpawnChance: 50}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
b := &BoardState{
|
b := &BoardState{
|
||||||
Height: 4,
|
Height: 4,
|
||||||
|
|
@ -1858,10 +1925,7 @@ func TestMaybeSpawnFood(t *testing.T) {
|
||||||
rand.Seed(test.Seed)
|
rand.Seed(test.Seed)
|
||||||
err := r.maybeSpawnFood(b)
|
err := r.maybeSpawnFood(b)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, len(test.ExpectedFood), len(b.Food), "Seed %d", test.Seed)
|
require.Equal(t, test.ExpectedFood, int32(len(b.Food)), "Seed %d", test.Seed)
|
||||||
for i, e := range test.ExpectedFood {
|
|
||||||
require.Equal(t, e, b.Food[i], "Seed %d", test.Seed)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue