Refactor RoyaleRuleset and move hazard damage into StandardRuleset (#50)

* move hazard damage into StandardRuleset

* OutOfBounds -> Hazards

* remove "out of bounds" in comment

* add cases for eating food to hazard damage test
This commit is contained in:
Rob O'Dwyer 2021-08-17 16:47:06 -07:00 committed by GitHub
parent dabbe7dfb5
commit e416384007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 341 additions and 288 deletions

View file

@ -10,19 +10,16 @@ type RoyaleRuleset struct {
Seed int64
// TODO: move Turn into BoardState?
Turn int32
ShrinkEveryNTurns int32
DamagePerTurn int32
// Output
OutOfBounds []Point
}
func (r *RoyaleRuleset) Name() string { return "royale" }
func (r *RoyaleRuleset) CreateNextBoardState(prevState *BoardState, moves []SnakeMove) (*BoardState, error) {
if r.ShrinkEveryNTurns < 1 {
return nil, errors.New("royale game must shrink at least every turn")
if r.StandardRuleset.HazardDamagePerTurn < 1 {
return nil, errors.New("royale damage per turn must be greater than zero")
}
nextBoardState, err := r.StandardRuleset.CreateNextBoardState(prevState, moves)
@ -30,26 +27,8 @@ func (r *RoyaleRuleset) CreateNextBoardState(prevState *BoardState, moves []Snak
return nil, err
}
// Algorithm:
// - Populate OOB for last turn
// - Apply damage to snake heads that are OOB
// - Re-populate OOB for this turn
// ---> This means damage on board shrinks doesn't hit until the following turn.
// TODO: LOG?
err = r.populateOutOfBounds(nextBoardState, r.Turn-1)
if err != nil {
return nil, err
}
// TODO: LOG?
err = r.damageOutOfBounds(nextBoardState)
if err != nil {
return nil, err
}
// TODO: LOG?
err = r.populateOutOfBounds(nextBoardState, r.Turn)
// 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)
if err != nil {
return nil, err
}
@ -57,11 +36,11 @@ func (r *RoyaleRuleset) CreateNextBoardState(prevState *BoardState, moves []Snak
return nextBoardState, nil
}
func (r *RoyaleRuleset) populateOutOfBounds(b *BoardState, turn int32) error {
r.OutOfBounds = []Point{}
func (r *RoyaleRuleset) populateHazards(b *BoardState, turn int32) error {
b.Hazards = []Point{}
if r.ShrinkEveryNTurns < 1 {
return errors.New("royale game must shrink at least every turn")
return errors.New("royale game can't shrink more frequently than every turn")
}
if turn < r.ShrinkEveryNTurns {
@ -89,34 +68,7 @@ func (r *RoyaleRuleset) populateOutOfBounds(b *BoardState, turn int32) error {
for x := int32(0); x < b.Width; x++ {
for y := int32(0); y < b.Height; y++ {
if x < minX || x > maxX || y < minY || y > maxY {
r.OutOfBounds = append(r.OutOfBounds, Point{x, y})
}
}
}
return nil
}
func (r *RoyaleRuleset) damageOutOfBounds(b *BoardState) error {
if r.DamagePerTurn < 1 {
return errors.New("royale damage per turn must be greater than zero")
}
for i := 0; i < len(b.Snakes); i++ {
snake := &b.Snakes[i]
if snake.EliminatedCause == NotEliminated {
head := snake.Body[0]
for _, p := range r.OutOfBounds {
if head == p {
// Snake is now out of bounds, reduce health
snake.Health = snake.Health - r.DamagePerTurn
if snake.Health < 0 {
snake.Health = 0
}
if r.StandardRuleset.snakeIsOutOfHealth(snake) {
snake.EliminatedCause = EliminatedByOutOfHealth
}
}
b.Hazards = append(b.Hazards, Point{x, y})
}
}
}