rules

package module
v1.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2023 License: AGPL-3.0 Imports: 5 Imported by: 9

README

BattlesnakeOfficial/rules

codecov

Battlesnake rules and game logic, implemented as a Go module. This code is used in production at play.battlesnake.com. Issues and contributions welcome!

CLI for Running Battlesnake Games Locally

This repo provides a simple CLI tool to run games locally against your dev environment.

Installation

Download precompiled binaries here:
https://github.com/BattlesnakeOfficial/rules/releases

Install as a Go package. Requires Go 1.18 or higher. [Download]

go install github.com/BattlesnakeOfficial/rules/cli/battlesnake@latest

Compile from source. Also requires Go 1.18 or higher.

git clone git@github.com:BattlesnakeOfficial/rules.git
cd rules
go build -o battlesnake ./cli/battlesnake/main.go
Usage

Example command to run a game locally:

battlesnake play -W 11 -H 11 --name <SNAKE_NAME> --url <SNAKE_URL> -g solo -v

For more details, see the CLI README.

FAQ

Can I run games locally?

Yes! See the included CLI.

How is this different from the old Battlesnake engine?

The old game engine was re-written in early 2020 to handle a higher volume of concurrent games. As part of that rebuild we moved the game logic into a separate Go module that gets compiled into the production engine.

This provides two benefits: it makes it much simpler/easier to build new game modes, and it allows the community to get more involved in game development (without the maintenance overhead of the entire game engine).

Feedback
  • Do you have an issue or suggestions for this repository? Head over to our Feedback Repository today and let us know!

Documentation

Index

Constants

View Source
const (
	MoveUp    = "up"
	MoveDown  = "down"
	MoveRight = "right"
	MoveLeft  = "left"

	BoardSizeSmall   = 7
	BoardSizeMedium  = 11
	BoardSizeLarge   = 19
	BoardSizeXLarge  = 21
	BoardSizeXXLarge = 25

	SnakeMaxHealth = 100
	SnakeStartSize = 3

	// Snake state constants
	NotEliminated                   = ""
	EliminatedByCollision           = "snake-collision"
	EliminatedBySelfCollision       = "snake-self-collision"
	EliminatedByOutOfHealth         = "out-of-health"
	EliminatedByHeadToHeadCollision = "head-collision"
	EliminatedByOutOfBounds         = "wall-collision"
	EliminatedByHazard              = "hazard"

	// Error constants
	ErrorTooManySnakes   = RulesetError("too many snakes for fixed start positions")
	ErrorNoRoomForSnake  = RulesetError("not enough space to place snake")
	ErrorNoRoomForFood   = RulesetError("not enough space to place food")
	ErrorNoMoveFound     = RulesetError("move not provided for snake")
	ErrorZeroLengthSnake = RulesetError("snake is length zero")
	ErrorEmptyRegistry   = RulesetError("empty registry")
	ErrorNoStages        = RulesetError("no stages")
	ErrorStageNotFound   = RulesetError("stage not found")
	ErrorMapNotFound     = RulesetError("map not found")

	// Ruleset / game type names
	GameTypeConstrictor        = "constrictor"
	GameTypeRoyale             = "royale"
	GameTypeSolo               = "solo"
	GameTypeStandard           = "standard"
	GameTypeWrapped            = "wrapped"
	GameTypeWrappedConstrictor = "wrapped_constrictor"

	// Game creation parameter names
	ParamGameType            = "name"
	ParamFoodSpawnChance     = "foodSpawnChance"
	ParamMinimumFood         = "minimumFood"
	ParamHazardDamagePerTurn = "damagePerTurn"
	ParamHazardMap           = "hazardMap"
	ParamHazardMapAuthor     = "hazardMapAuthor"
	ParamShrinkEveryNTurns   = "shrinkEveryNTurns"
	ParamAllowBodyCollisions = "allowBodyCollisions"
	ParamSharedElimination   = "sharedElimination"
	ParamSharedHealth        = "sharedHealth"
	ParamSharedLength        = "sharedLength"
)
View Source
const (
	StageSpawnFoodStandard    = "spawn_food.standard"
	StageGameOverStandard     = "game_over.standard"
	StageStarvationStandard   = "starvation.standard"
	StageFeedSnakesStandard   = "feed_snakes.standard"
	StageMovementStandard     = "movement.standard"
	StageHazardDamageStandard = "hazard_damage.standard"
	StageEliminationStandard  = "elimination.standard"

	StageGameOverSoloSnake           = "game_over.solo_snake"
	StageSpawnFoodNoFood             = "spawn_food.no_food"
	StageSpawnHazardsShrinkMap       = "spawn_hazards.shrink_map"
	StageModifySnakesAlwaysGrow      = "modify_snakes.always_grow"
	StageMovementWrapBoundaries      = "movement.wrap_boundaries"
	StageModifySnakesShareAttributes = "modify_snakes.share_attributes"
)

Variables

View Source
var GlobalRand globalRand

A Rand implementation that just uses the global math/rand generator.

View Source
var MaxRand maxRand

A Rand implementation that always returns the maximum value for any method.

View Source
var MinRand minRand

A Rand implementation that always returns the minimum value for any method.

Functions

func DamageHazardsStandard added in v1.0.28

func DamageHazardsStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func EliminateSnake added in v1.1.14

func EliminateSnake(s *Snake, cause, by string, turn int)

EliminateSnake updates a snake's state to reflect that it was eliminated. - "cause" identifies what type of event caused the snake to be eliminated - "by" identifies which snake (if any, use empty string "" if none) eliminated the snake. - "turn" is the turn number that this snake was eliminated on.

func EliminateSnakesStandard added in v1.0.28

func EliminateSnakesStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func FeedSnakesStandard added in v1.0.28

func FeedSnakesStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func GameOverSolo added in v1.0.28

func GameOverSolo(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func GameOverStandard added in v1.0.28

func GameOverStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func GrowSnakesConstrictor added in v1.0.28

func GrowSnakesConstrictor(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func InitializeSnakes added in v1.1.0

func InitializeSnakes(b *BoardState, snakeIDs []string)

Adds all snakes without body coordinates to the board. This allows GameMaps to access the list of snakes and perform initial placement.

func IsInitialization added in v1.0.33

func IsInitialization(b *BoardState, settings Settings, moves []SnakeMove) bool

IsInitialization checks whether the current state means the game is initialising (turn zero). Useful for StageFuncs that need to apply different behaviour on initialisation.

func MoveSnakesStandard added in v1.0.28

func MoveSnakesStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func MoveSnakesWrapped added in v1.0.28

func MoveSnakesWrapped(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func NewRulesetBuilder added in v1.0.28

func NewRulesetBuilder() *rulesetBuilder

NewRulesetBuilder returns an instance of a builder for the Ruleset types.

func NewSeedRand added in v1.1.2

func NewSeedRand(seed int64) *seedRand

func PlaceFoodAutomatically added in v1.0.21

func PlaceFoodAutomatically(rand Rand, b *BoardState) error

PlaceFoodAutomatically initializes the array of food based on the size of the board and the number of snakes.

func PlaceFoodFixed deprecated added in v1.0.21

func PlaceFoodFixed(rand Rand, b *BoardState) error

Deprecated: will be replaced by maps.PlaceFoodFixed

func PlaceFoodRandomly added in v1.0.21

func PlaceFoodRandomly(rand Rand, b *BoardState, n int) error

PlaceFoodRandomly adds up to n new food to the board in random unoccupied squares

func PlaceManySnakesDistributed added in v1.1.11

func PlaceManySnakesDistributed(rand Rand, b *BoardState, snakeIDs []string) error

PlaceManySnakesDistributed is a placement algorithm that works for up to 16 snakes It is intended for use on large boards and distributes snakes relatively evenly, and randomly, across quadrants.

func PlaceSnake added in v1.0.21

func PlaceSnake(b *BoardState, snakeID string, body []Point) error

PlaceSnake adds a snake to the board with the given ID and body coordinates.

func PlaceSnakesAutomatically added in v1.0.21

func PlaceSnakesAutomatically(rand Rand, b *BoardState, snakeIDs []string) error

PlaceSnakesAutomatically initializes the array of snakes based on the provided snake IDs and the size of the board.

func PlaceSnakesFixed added in v1.0.21

func PlaceSnakesFixed(rand Rand, b *BoardState, snakeIDs []string) error

func PlaceSnakesRandomly added in v1.0.21

func PlaceSnakesRandomly(rand Rand, b *BoardState, snakeIDs []string) error

func PopulateHazardsRoyale added in v1.0.28

func PopulateHazardsRoyale(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func ReduceSnakeHealthStandard added in v1.0.28

func ReduceSnakeHealthStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func RegisterPipelineStage added in v1.0.33

func RegisterPipelineStage(s string, fn StageFunc)

RegisterPipelineStage adds a stage to the global stage registry. It will panic if the a stage has already been registered with the same name.

func RemoveFoodConstrictor added in v1.0.28

func RemoveFoodConstrictor(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

func SpawnFoodStandard deprecated added in v1.0.28

func SpawnFoodStandard(b *BoardState, settings Settings, moves []SnakeMove) (bool, error)

Deprecated: handled by maps.Standard

Types

type BoardState

type BoardState struct {
	Turn    int
	Height  int
	Width   int
	Food    []Point
	Snakes  []Snake
	Hazards []Point

	// Generic game-level state for maps and rules stages to persist data between turns.
	GameState map[string]string

	// Numeric state keyed to specific points, also persisted between turns.
	PointState map[Point]int
}

BoardState represents the internal state of a game board. NOTE: use NewBoardState to construct these to ensure fields are initialized correctly and that tests are resilient to changes to this type.

func CreateDefaultBoardState added in v1.0.21

func CreateDefaultBoardState(rand Rand, width int, height int, snakeIDs []string) (*BoardState, error)

CreateDefaultBoardState is a convenience function for fully initializing a "default" board state with snakes and food. In a real game, the engine may generate the board without calling this function, or customize the results based on game-specific settings.

func NewBoardState added in v1.0.21

func NewBoardState(width, height int) *BoardState

NewBoardState returns an empty but fully initialized BoardState

func (*BoardState) Clone added in v1.0.21

func (prevState *BoardState) Clone() *BoardState

Clone returns a deep copy of prevState that can be safely modified without affecting the original

func (*BoardState) WithFood added in v1.2.0

func (state *BoardState) WithFood(food []Point) *BoardState

Builder method to set Food and return the modified BoardState.

func (*BoardState) WithGameState added in v1.2.0

func (state *BoardState) WithGameState(gameState map[string]string) *BoardState

Builder method to set State and return the modified BoardState.

func (*BoardState) WithHazards added in v1.2.0

func (state *BoardState) WithHazards(hazards []Point) *BoardState

Builder method to set Hazards and return the modified BoardState.

func (*BoardState) WithPointState added in v1.2.0

func (state *BoardState) WithPointState(pointState map[Point]int) *BoardState

Builder method to set PointState and return the modified BoardState.

func (*BoardState) WithSnakes added in v1.2.0

func (state *BoardState) WithSnakes(snakes []Snake) *BoardState

Builder method to set Snakes and return the modified BoardState.

func (*BoardState) WithTurn added in v1.2.0

func (state *BoardState) WithTurn(turn int) *BoardState

Builder method to set Turn and return the modified BoardState.

type Pipeline added in v1.0.33

type Pipeline interface {
	// Execute runs the pipeline stages and produces a next game state.
	//
	// If any stage produces an error or an ended game state, the pipeline
	// immediately stops at that stage.
	//
	// Errors should be checked and the other results ignored if error is non-nil.
	//
	// If the pipeline is already in an error state (this can be checked by calling Err()),
	// this error will be immediately returned and the pipeline will not run.
	//
	// After the pipeline runs, the results will be the result of the last stage that was executed.
	Execute(*BoardState, Settings, []SnakeMove) (bool, *BoardState, error)

	// Err provides a way to check for errors before/without calling Execute.
	// Err returns an error if the Pipeline is in an error state.
	// If this error is not nil, this error will also be returned from Execute, so it is
	// optional to call Err.
	// The idea is to reduce error-checking verbosity for the majority of cases where a
	// Pipeline is immediately executed after construction (i.e. NewPipeline(...).Execute(...)).
	Err() error
}

Pipeline is an ordered sequences of game stages which are executed to produce the next game state.

If a stage produces an error or an ended game state, the pipeline is halted at that stage.

func NewPipeline added in v1.0.33

func NewPipeline(stageNames ...string) Pipeline

NewPipeline constructs an instance of Pipeline using the global registry. It is a convenience wrapper for NewPipelineFromRegistry when you want to use the default, global registry.

func NewPipelineFromRegistry added in v1.0.33

func NewPipelineFromRegistry(registry map[string]StageFunc, stageNames ...string) Pipeline

NewPipelineFromRegistry constructs an instance of Pipeline, using the specified registry of pipeline stage functions.

The order of execution for the pipeline stages will correspond to the order that the stage names are provided.

Example:

NewPipelineFromRegistry(r, s, "stage1", "stage2")

... will result in stage "stage1" running first, then stage "stage2" running after.

An error will be returned if an unregistered stage name is used (a name that is not mapped in the registry).

type Point

type Point struct {
	X     int `json:"X"`
	Y     int `json:"Y"`
	TTL   int `json:"TTL,omitempty"`
	Value int `json:"Value,omitempty"`
}

func GetEvenUnoccupiedPoints added in v1.1.0

func GetEvenUnoccupiedPoints(b *BoardState) []Point

func GetUnoccupiedPoints added in v1.1.0

func GetUnoccupiedPoints(b *BoardState, includePossibleMoves bool, includeHazards bool) []Point

func (Point) GoString added in v1.1.2

func (p Point) GoString() string

Makes it easier to copy sample points out of Go logs and test failures.

type Rand added in v1.1.0

type Rand interface {
	Intn(n int) int
	// Range produces a random integer in the range of [min,max] (inclusive)
	// For example, Range(1,3) could produce the values 1, 2 or 3.
	// Panics if max < min (like how Intn(n) panics for n <=0)
	Range(min, max int) int
	Shuffle(n int, swap func(i, j int))
}

type RandomPositionBucket added in v1.1.20

type RandomPositionBucket struct {
	// contains filtered or unexported fields
}

func (*RandomPositionBucket) Fill added in v1.1.20

func (rpb *RandomPositionBucket) Fill(p ...Point)

func (*RandomPositionBucket) Take added in v1.1.20

func (rpb *RandomPositionBucket) Take(rand Rand) (Point, error)

type Ruleset

type Ruleset interface {
	// Returns the name of the ruleset, if applicable.
	Name() string

	// Returns the settings used by the ruleset.
	Settings() Settings

	// Processes the next turn of the ruleset, returning whether the game has ended, the next BoardState, or an error.
	// For turn zero (initialization), moves will be left empty.
	Execute(prevState *BoardState, moves []SnakeMove) (gameOver bool, nextState *BoardState, err error)
}

type RulesetError added in v1.0.17

type RulesetError string

func (RulesetError) Error added in v1.0.17

func (err RulesetError) Error() string

type Settings added in v1.0.28

type Settings struct {
	// contains filtered or unexported fields
}

Settings contains all settings relevant to a game. The settings are stored as raw string values, which should not be accessed directly. Calling code should instead use the Int/Bool methods to parse them.

func NewSettings added in v1.2.0

func NewSettings(params map[string]string) Settings

func NewSettingsWithParams added in v1.2.0

func NewSettingsWithParams(params ...string) Settings

func (Settings) Bool added in v1.2.0

func (settings Settings) Bool(paramName string, defaultValue bool) bool

Bool returns the boolean value for the specified parameter. If the parameter doesn't exist, the default value will be returned. If the parameter does exist, but is not "true", false will be returned.

func (Settings) GetRand added in v1.1.2

func (settings Settings) GetRand(turn int) Rand

Get a random number generator initialized based on the seed and current turn.

func (Settings) Int added in v1.2.0

func (settings Settings) Int(paramName string, defaultValue int) int

Int returns the int value for the specified parameter. If the parameter doesn't exist, the default value will be returned. If the parameter does exist, but is not a valid int, the default value will be returned.

func (Settings) Seed added in v1.1.2

func (settings Settings) Seed() int64

func (Settings) WithRand added in v1.1.0

func (settings Settings) WithRand(rand Rand) Settings

func (Settings) WithSeed added in v1.1.2

func (settings Settings) WithSeed(seed int64) Settings

type Snake

type Snake struct {
	ID               string
	Body             []Point
	Health           int
	EliminatedCause  string
	EliminatedOnTurn int
	EliminatedBy     string
}

type SnakeMove

type SnakeMove struct {
	ID   string
	Move string
}

type StageFunc added in v1.0.28

type StageFunc func(*BoardState, Settings, []SnakeMove) (bool, error)

StageFunc represents a single stage of an ordered pipeline and applies custom logic to the board state each turn. It is expected to modify the boardState directly. The return values are a boolean (to indicate whether the game has ended as a result of the stage) and an error if any errors occurred during the stage.

Errors should be treated as meaning the stage failed and the board state is now invalid.

type StageRegistry added in v1.0.33

type StageRegistry map[string]StageFunc

StageRegistry is a mapping of stage names to stage functions

func (StageRegistry) RegisterPipelineStage added in v1.0.33

func (sr StageRegistry) RegisterPipelineStage(s string, fn StageFunc)

RegisterPipelineStage adds a stage to the registry. If a stage has already been mapped it will be overwritten by the newly registered function.

func (StageRegistry) RegisterPipelineStageError added in v1.0.33

func (sr StageRegistry) RegisterPipelineStageError(s string, fn StageFunc) error

RegisterPipelineStageError adds a stage to the registry. If a stage has already been mapped an error will be returned.

Directories

Path Synopsis
cli
commands
This file uses material from the Wikipedia article <a href="https://en.wikipedia.org/wiki/List_of_snakes_by_common_name">"List of snakes by common name"</a>, which is released under the <a href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share-Alike License 3.0</a>.
This file uses material from the Wikipedia article <a href="https://en.wikipedia.org/wiki/List_of_snakes_by_common_name">"List of snakes by common name"</a>, which is released under the <a href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share-Alike License 3.0</a>.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL