Rename TeamRuleset -> SquadRuleset
This commit is contained in:
parent
d0400fcb18
commit
01eaf6267d
2 changed files with 468 additions and 0 deletions
128
squad.go
Normal file
128
squad.go
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package rules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type SquadRuleset struct {
|
||||
StandardRuleset
|
||||
|
||||
SquadMap map[string]string
|
||||
|
||||
// These are intentionally designed so that they default to a standard game.
|
||||
AllowBodyCollisions bool
|
||||
SharedElimination bool
|
||||
SharedHealth bool
|
||||
SharedLength bool
|
||||
}
|
||||
|
||||
const EliminatedBySquad = "squad-eliminated"
|
||||
|
||||
func (r *SquadRuleset) CreateNextBoardState(prevState *BoardState, moves []SnakeMove) (*BoardState, error) {
|
||||
nextBoardState, err := r.StandardRuleset.CreateNextBoardState(prevState, moves)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: LOG?
|
||||
err = r.resurrectSquadBodyCollisions(nextBoardState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: LOG?
|
||||
err = r.shareSquadAttributes(nextBoardState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nextBoardState, nil
|
||||
}
|
||||
|
||||
func (r *SquadRuleset) areSnakesOnSameSquad(snake *Snake, other *Snake) bool {
|
||||
return r.areSnakeIDsOnSameSquad(snake.ID, other.ID)
|
||||
}
|
||||
|
||||
func (r *SquadRuleset) areSnakeIDsOnSameSquad(snakeID string, otherID string) bool {
|
||||
return r.SquadMap[snakeID] == r.SquadMap[otherID]
|
||||
}
|
||||
|
||||
func (r *SquadRuleset) resurrectSquadBodyCollisions(b *BoardState) error {
|
||||
if !r.AllowBodyCollisions {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(b.Snakes); i++ {
|
||||
snake := &b.Snakes[i]
|
||||
if snake.EliminatedCause == EliminatedByCollision {
|
||||
if snake.EliminatedBy == "" {
|
||||
return errors.New("snake eliminated by collision and eliminatedby is not set")
|
||||
}
|
||||
if snake.ID != snake.EliminatedBy && r.areSnakeIDsOnSameSquad(snake.ID, snake.EliminatedBy) {
|
||||
snake.EliminatedCause = NotEliminated
|
||||
snake.EliminatedBy = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SquadRuleset) shareSquadAttributes(b *BoardState) error {
|
||||
if !(r.SharedElimination || r.SharedLength || r.SharedHealth) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(b.Snakes); i++ {
|
||||
snake := &b.Snakes[i]
|
||||
if snake.EliminatedCause != NotEliminated {
|
||||
continue
|
||||
}
|
||||
|
||||
for j := 0; j < len(b.Snakes); j++ {
|
||||
other := &b.Snakes[j]
|
||||
if r.areSnakesOnSameSquad(snake, other) {
|
||||
if r.SharedHealth {
|
||||
if snake.Health < other.Health {
|
||||
snake.Health = other.Health
|
||||
}
|
||||
}
|
||||
if r.SharedLength {
|
||||
if len(snake.Body) == 0 || len(other.Body) == 0 {
|
||||
return errors.New("found snake of zero length")
|
||||
}
|
||||
for len(snake.Body) < len(other.Body) {
|
||||
r.growSnake(snake)
|
||||
}
|
||||
}
|
||||
if r.SharedElimination {
|
||||
if snake.EliminatedCause == NotEliminated && other.EliminatedCause != NotEliminated {
|
||||
snake.EliminatedCause = EliminatedBySquad
|
||||
// We intentionally do not set snake.EliminatedBy because there might be multiple culprits.
|
||||
snake.EliminatedBy = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SquadRuleset) IsGameOver(b *BoardState) (bool, error) {
|
||||
snakesRemaining := []*Snake{}
|
||||
for i := 0; i < len(b.Snakes); i++ {
|
||||
if b.Snakes[i].EliminatedCause == NotEliminated {
|
||||
snakesRemaining = append(snakesRemaining, &b.Snakes[i])
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(snakesRemaining); i++ {
|
||||
if !r.areSnakesOnSameSquad(snakesRemaining[i], snakesRemaining[0]) {
|
||||
// There are multiple squads remaining
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
// no snakes or single squad remaining
|
||||
return true, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue