brd

package
v0.1.8 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2022 License: Apache-2.0 Imports: 5 Imported by: 1

Documentation

Overview

Package brd has representations of a backgammon playing board, checkers, dice, etc.

It has everything you need to play a game except intelligence about which moves to make and when to offer or accept a double.

You must seen the "math/rand" module's PRNG before using this module.

Index

Constants

View Source
const (
	BorneOffWhitePip = 0
	BorneOffRedPip   = 25
	BarWhitePip      = 26
	BarRedPip        = 27
	MaxPip           = BarRedPip
)
View Source
const (
	IgnoreRollValidity  = true
	EnforceRollValidity = !IgnoreRollValidity
)

Variables

This section is empty.

Functions

func OptionallyReturnBoardsToPool added in v0.1.7

func OptionallyReturnBoardsToPool(all []*Board, keeper *Board)

Optional performance helper: Gives the garbage collector less work to do by returning all but keeper to the free pool.

Types

type Analysis added in v0.1.4

type Analysis interface {
	Summary() string // for human consumption
}

type AnalyzedBoard added in v0.1.4

type AnalyzedBoard struct {
	Board    *Board
	Analysis Analysis // optional
}

func (AnalyzedBoard) String added in v0.1.4

func (b AnalyzedBoard) String() string

type Board

type Board struct {
	// Zero values may appear anywhere. We use [4]Die instead of []Die for
	// efficiency's sake and to make deep copying easy:
	Roll           Roll // unused
	RollUsed       Roll // used
	Roller         Checker
	Stakes         int
	MatchScore     Score // zero value means we are not doing tournament play. NB: Use SetScore()
	WhiteCanDouble bool
	RedCanDouble   bool
	Pips           Points28 // red borne off, the 24 points of the board, white borne off, red bar, white bar. Pips[1:25] are the 24 pips.
}

See http://www.gammonlife.com/rules/backgammon-rules.htm for a picture of a board with points annotated [1, 24]. The standard starting position has two white checkers on 1 and two red checkers on 24. We also have a notion of point 0, the red checkers that have borne off (during the end stage of the game, bearing off), and point 25, the white checkers that have borne off.

A deep copy of a Board is the very same as a shallow copy. No slices, maps, pointers, funcs, channels, etc.

func New

func New(paranoid bool) *Board

func (*Board) BlotLiability

func (b *Board) BlotLiability(player Checker, includeUnhittable bool) (result int)

Returns a pip count for the sum of the pip counts of the player's blots.

If includeUnhittable is true, this treat a blot as a liability even if the opponent has no change to hit it (e.g., if White is not on the bar and is entirely home, a Red blot outside of White's home is unhittable).

func (*Board) Equals

func (b *Board) Equals(o Board) bool

func (Board) Invalidity

func (b Board) Invalidity(ignoreRoll bool) string

func (*Board) LegalContinuations

func (b *Board) LegalContinuations() []*Board

Read-only method using a pointer receiver to be performant.

Enumerates all legal Board continuations without duplicates. The result is guaranteed to be non-empty (sometimes it's just []*Board{b}).

The resulting Boards have the same Roller and the same dice (though they may be shifted from Roll to RollUsed). You must call TakeTurn() next.

See also OptionallyReturnBoardsToPool().

func (*Board) LengthOfMaxPrime

func (b *Board) LengthOfMaxPrime(player Checker) (result int)

A 4-prime, e.g., is four consecutive made Points.

func (*Board) NumCheckersHome

func (b *Board) NumCheckersHome(player Checker) (result int)

func (*Board) NumPointsBlocked

func (b *Board) NumPointsBlocked(player Checker) (result int)

func (*Board) PipCount

func (b *Board) PipCount(player Checker) (result int)

func (*Board) PipCountOfFarthestChecker

func (b *Board) PipCountOfFarthestChecker(player Checker) int

func (*Board) PlayGame

func (b *Board) PlayGame(logState interface{}, chooser Chooser, logger func(interface{}, *Board), offerDouble, acceptDouble func(*Board) bool) (Checker, int, Score)

Read-only method using a pointer receiver to be performant. The function that are parameters use pointers and slices for efficiency's sake but must not mutate their arguments.

Invariant: the game is not yet over.

Calls logger, if non-nil, for each Board, including b at the start.

Does not attempt doubling for the starting board.

Returns the victor and the stakes (which is 1, 2 (gammon), or 3 (backgammon) multiplied by the final Board's Stakes) and the match score.

TODO(chandler37): Perhaps also wrap this up with a "you cannot cheat or accidentally mess things up" version that never lets you mutate state (i.e., deep copies the []*Board and never gives a *Board)?

func (*Board) Racing

func (b *Board) Racing() bool

A "race" is when it is impossible for either player to hit the other.

func (*Board) SetScore

func (b *Board) SetScore(score Score)

func (Board) String

func (b Board) String() string

func (*Board) TakeTurn

func (b *Board) TakeTurn(offerDouble, acceptDouble func(*Board) bool) (victor Checker, stakes int, score Score)

Flips the Roller, offers a double, rolls new dice, alters the MatchScore.

offerDouble and acceptDouble may be nil.

Invariant: the receiver was returned by LegalContinuations()

Mutates the receiver.

type Checker

type Checker uint8

Each player has 15 Checkers. A checker is either on a point, on the bar, or borne off.

const (
	NoChecker Checker = iota
	White
	Red
)

func (Checker) OtherColor

func (c Checker) OtherColor() Checker

func (Checker) String

func (c Checker) String() string

type Chooser

type Chooser func([]*Board) []AnalyzedBoard

An intelligence (a player) has to make decisions about the doubling cube and choose moves. A Chooser is just the part that chooses moves after the doubling phase.

Element zero of the returned slice is the best move, element len(result)-1 is the worst. If the analyses indicate a tie, it doesn't affect game play. If you want to choose randomly from tied Boards, you must shuffle them yourself.

You are free to return a subset of the input, e.g. a single Board, the Kth: []AnalyzedBoard{AnalyzedBoard{Board:input[K]}}. You must return at least one.

Your output must not contain nil Board pointers. You must not mutate the Boards pointed to by the input.

type Die

type Die uint8 // zero: this die is not in play. 1-6: that many pips. 7+: insanity
const ZeroDie Die = 0

type Point

type Point int8

A point, sometimes called a pip, is represented on the board by a triangle. Zero or more checkers, all of like color, may occupy a point/pip. Values are [-15, 15] where -3 means there are three White checkers and 15 means there are fifteen Red checkers and 0 means there are no checkers.

func NewPoint added in v0.1.5

func NewPoint(n int, color Checker) Point

Returns a Point with n checkers on it of the given color.

func (*Point) Add

func (p *Point) Add(checker Checker) error

func (Point) MadeBy

func (p Point) MadeBy(player Checker) bool

A made point is a Point with two or more Checkers of the same color on it.

func (Point) Num added in v0.1.5

func (p Point) Num(player Checker) int

func (Point) NumCheckers added in v0.1.5

func (p Point) NumCheckers() int

func (Point) NumRed added in v0.1.5

func (p Point) NumRed() int

func (Point) NumWhite added in v0.1.5

func (p Point) NumWhite() int

func (*Point) Reset

func (p *Point) Reset(n int, checker Checker)

Clears the Point and then places n checkers of the given color (or no color) on it.

func (Point) String

func (p Point) String() string

func (*Point) Subtract

func (p *Point) Subtract()

type Points28

type Points28 [MaxPip + 1]Point

type Roll

type Roll [4]Die

You roll two dice but a doublet (e.g., <6 6>) gives you four moves (e.g., <6 6 6 6>). Invariants: Once you see ZeroDie, you will always see ZeroDie.

func (Roll) Dice

func (r Roll) Dice() (result []Die)

Returns the dice.

Roll{6, 6, 6, 6}.Dice() => []Die{6, 6, 6, 6} Roll{6, 1}.Dice() => []Die{6, 1}

func (*Roll) Equals

func (r *Roll) Equals(o Roll) bool

<6 5> is the same as <5 6>

func (*Roll) New

func (r *Roll) New(toBeCleared *Roll)

Board.RollUsed is tightly coupled to Board.Roll, so we handle both here.

func (Roll) String

func (r Roll) String() string

func (Roll) UniqueDice

func (r Roll) UniqueDice() []Die

Returns the unique dice.

Roll{6, 6, 6, 6}.UniqueDice() => []Die{6}

func (Roll) Use

func (r Roll) Use(die Die, recipient *Roll) Roll

Returns a new Roll the same as r minus die. Mutates recipient to add a die.

type Score

type Score struct {
	WhiteScore                int
	RedScore                  int
	NoCrawfordRule            bool
	AlreadyPlayedCrawfordGame bool // TODO(chandler37): a test case where the crawford game is the last game, and another where the crawford game is not the last.
	Goal                      int  // zero means we are not playing a match, just looking to maximize points.
}

A match to 5 using the Crawford rule would be Score{Goal: 5}. The Crawford rule is a standard so our zero value uses it.

func (*Score) CrawfordRuleAppliesNextGame

func (s *Score) CrawfordRuleAppliesNextGame() bool

func (*Score) Equals

func (s *Score) Equals(o Score) bool

func (Score) String

func (s Score) String() string

func (*Score) Update

func (s *Score) Update(victor Checker, stakes int)

Jump to

Keyboard shortcuts

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