improve terminology in game controller
This commit is contained in:
parent
492c4199bb
commit
711724bc4d
4
game.go
4
game.go
@ -22,7 +22,7 @@ type action struct {
|
|||||||
|
|
||||||
// gameActor is an actor that updates a game's state and relays changes to all
|
// gameActor is an actor that updates a game's state and relays changes to all
|
||||||
// observers.
|
// observers.
|
||||||
func gameActor(ctx context.Context, g *game.Game, dealer, chall person, join <-chan person) {
|
func gameActor(ctx context.Context, g *game.Match, dealer, chall person, join <-chan person) {
|
||||||
// Games should generally be on the order of minutes. A four hour game is
|
// Games should generally be on the order of minutes. A four hour game is
|
||||||
// definitely expired.
|
// definitely expired.
|
||||||
ctx, stop := context.WithTimeoutCause(ctx, 4*time.Hour, errGameExpired)
|
ctx, stop := context.WithTimeoutCause(ctx, 4*time.Hour, errGameExpired)
|
||||||
@ -80,7 +80,7 @@ func playerActor(ctx context.Context, p person, actions chan<- action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func broadcast(ctx context.Context, g *game.Game, dealer, chall person, obs []person) {
|
func broadcast(ctx context.Context, g *game.Match, dealer, chall person, obs []person) {
|
||||||
// TODO(zeph): this probably should return an error or some other signal
|
// TODO(zeph): this probably should return an error or some other signal
|
||||||
// if a player drops so that the actor knows to quit
|
// if a player drops so that the actor knows to quit
|
||||||
if err := wsjson.Write(ctx, dealer.conn, g.DTO(dealer.id)); err != nil {
|
if err := wsjson.Write(ctx, dealer.conn, g.DTO(dealer.id)); err != nil {
|
||||||
|
119
game/game.go
119
game/game.go
@ -1,3 +1,12 @@
|
|||||||
|
// Package game implements a controller for Buckshot Roulette matches.
|
||||||
|
//
|
||||||
|
// The terminology of this package is as follows:
|
||||||
|
// - A match is a pairing of two players, the dealer and challenger.
|
||||||
|
// It ends when the challenger wins three rounds or the dealer wins once.
|
||||||
|
// - A round is an instance of gameplay. Both players start each round with
|
||||||
|
// the same HP, and it continues until either player reaches zero.
|
||||||
|
// - A game is a set of 2-8 shells and 1-4 items delivered to each player.
|
||||||
|
// The challenger always moves first at the start of each game.
|
||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -7,47 +16,61 @@ import (
|
|||||||
"git.sunturtle.xyz/studio/shotgun/serve"
|
"git.sunturtle.xyz/studio/shotgun/serve"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Game struct {
|
type Match struct {
|
||||||
rng RNG
|
// rng is the PRNG state used for this match.
|
||||||
|
rng RNG
|
||||||
|
// players are the players in the match. The first element is the dealer
|
||||||
|
// and the second is the challenger.
|
||||||
players [2]Player
|
players [2]Player
|
||||||
shells []bool
|
// shells is the list of remaining shells in the current game. It always
|
||||||
round uint
|
// uses shellArray as its backing array.
|
||||||
group uint
|
shells []bool
|
||||||
turn uint
|
// round is the round number. Once it reaches 3, the match is over.
|
||||||
hp int8
|
round uint
|
||||||
damage int8
|
// game is the game number. May be nice for metrics eventually.
|
||||||
reveal bool
|
game uint
|
||||||
prev *bool
|
// turn is the turn number. When even, it is the dealer's turn.
|
||||||
|
turn uint
|
||||||
|
// hp is the starting and max HP of both players in the current round.
|
||||||
|
hp int8
|
||||||
|
// damage is the amount of damage a live shell will deal this turn.
|
||||||
|
damage int8
|
||||||
|
// reveal indicates whether the current player has revealed the shell that
|
||||||
|
// will fire next.
|
||||||
|
reveal bool
|
||||||
|
// prev is a pointer to the element of shellArray which was fired last this
|
||||||
|
// game, or nil if none has been.
|
||||||
|
prev *bool
|
||||||
|
|
||||||
// Backing storage for shells.
|
// shellArray is the backing storage for shells and prev.
|
||||||
shellArray [8]bool
|
shellArray [8]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new game started at round 1.
|
// New creates a new match started at round 1.
|
||||||
func New(dealer, challenger player.ID) *Game {
|
func New(dealer, challenger player.ID) *Match {
|
||||||
g := &Game{
|
g := &Match{
|
||||||
rng: NewRNG(),
|
rng: NewRNG(),
|
||||||
players: [2]Player{
|
players: [2]Player{
|
||||||
{id: dealer},
|
{id: dealer},
|
||||||
{id: challenger},
|
{id: challenger},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
g.StartRound()
|
g.NextRound()
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartRound starts the next round of a game.
|
// NextRound starts the next round of a match.
|
||||||
func (g *Game) StartRound() {
|
func (g *Match) NextRound() {
|
||||||
g.hp = int8(g.rng.Intn(3) + 2)
|
g.hp = int8(g.rng.Intn(3) + 2)
|
||||||
g.players[0].StartRound(g.hp)
|
g.players[0].StartRound(g.hp)
|
||||||
g.players[1].StartRound(g.hp)
|
g.players[1].StartRound(g.hp)
|
||||||
g.round++
|
g.round++
|
||||||
g.group = 0
|
g.game = 0
|
||||||
g.StartGroup()
|
g.NextGame()
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartGroup starts the next shell group of a round.
|
// NextGame starts the next game of a round.
|
||||||
func (g *Game) StartGroup() {
|
func (g *Match) NextGame() {
|
||||||
items := g.rng.Intn(4) + 1
|
items := g.rng.Intn(4) + 1
|
||||||
g.players[0].StartGroup(&g.rng, items)
|
g.players[0].StartGroup(&g.rng, items)
|
||||||
g.players[1].StartGroup(&g.rng, items)
|
g.players[1].StartGroup(&g.rng, items)
|
||||||
@ -60,14 +83,14 @@ func (g *Game) StartGroup() {
|
|||||||
}
|
}
|
||||||
g.shells = g.shellArray[:shells]
|
g.shells = g.shellArray[:shells]
|
||||||
ShuffleSlice(&g.rng, g.shells)
|
ShuffleSlice(&g.rng, g.shells)
|
||||||
g.group++
|
g.game++
|
||||||
g.turn = 0
|
g.turn = 0
|
||||||
g.prev = nil
|
g.prev = nil
|
||||||
g.NextTurn()
|
g.NextTurn()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextTurn advances the turn.
|
// NextTurn advances the turn but not the match or round state.
|
||||||
func (g *Game) NextTurn() {
|
func (g *Match) NextTurn() {
|
||||||
g.turn++
|
g.turn++
|
||||||
g.damage = 1
|
g.damage = 1
|
||||||
g.reveal = false
|
g.reveal = false
|
||||||
@ -79,20 +102,21 @@ func (g *Game) NextTurn() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentPlayer gets the index of the current player, either 0 or 1.
|
// CurrentPlayer gets the current player.
|
||||||
func (g *Game) CurrentPlayer() *Player {
|
func (g *Match) CurrentPlayer() *Player {
|
||||||
return &g.players[g.turn%2]
|
return &g.players[g.turn%2]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opponent returns the player who is not the current player.
|
// Opponent returns the player who is not the current player.
|
||||||
func (g *Game) Opponent() *Player {
|
func (g *Match) Opponent() *Player {
|
||||||
return &g.players[g.turn%2^1]
|
return &g.players[g.turn%2^1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply uses an item by index for the current player.
|
// Apply uses an item by index for the current player.
|
||||||
// This may cause the group to end.
|
// This may cause the current game to end, but does not start the next game
|
||||||
|
// if so.
|
||||||
// Returns ErrWrongTurn if id does not correspond to the current player.
|
// Returns ErrWrongTurn if id does not correspond to the current player.
|
||||||
func (g *Game) Apply(id player.ID, item int) error {
|
func (g *Match) Apply(id player.ID, item int) error {
|
||||||
cur := g.CurrentPlayer()
|
cur := g.CurrentPlayer()
|
||||||
if cur.id != id {
|
if cur.id != id {
|
||||||
return ErrWrongTurn
|
return ErrWrongTurn
|
||||||
@ -106,10 +130,10 @@ func (g *Game) Apply(id player.ID, item int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopShell removes a shell from the shotgun.
|
// popShell removes a shell from the shotgun.
|
||||||
// This may cause the shotgun to be empty, but does not start the next group
|
// This may cause the shotgun to be empty, but does not start the next game
|
||||||
// if so.
|
// if so.
|
||||||
func (g *Game) PopShell() bool {
|
func (g *Match) popShell() bool {
|
||||||
g.prev = &g.shells[0]
|
g.prev = &g.shells[0]
|
||||||
g.shells = g.shells[1:]
|
g.shells = g.shells[1:]
|
||||||
return *g.prev
|
return *g.prev
|
||||||
@ -117,7 +141,7 @@ func (g *Game) PopShell() bool {
|
|||||||
|
|
||||||
// Peek returns the current turn's shell if it is revealed for the player with
|
// Peek returns the current turn's shell if it is revealed for the player with
|
||||||
// the given ID, or nil otherwise.
|
// the given ID, or nil otherwise.
|
||||||
func (g *Game) Peek(id player.ID) *bool {
|
func (g *Match) Peek(id player.ID) *bool {
|
||||||
if len(g.shells) == 0 || id != g.CurrentPlayer().id || !g.reveal {
|
if len(g.shells) == 0 || id != g.CurrentPlayer().id || !g.reveal {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -125,12 +149,13 @@ func (g *Game) Peek(id player.ID) *bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Empty returns whether the shotgun is empty.
|
// Empty returns whether the shotgun is empty.
|
||||||
func (g *Game) Empty() bool {
|
func (g *Match) Empty() bool {
|
||||||
return len(g.shells) == 0
|
return len(g.shells) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Winner returns the player who won, or nil if the round is not over.
|
// Winner returns the player who won the current round, or nil if the round is
|
||||||
func (g *Game) Winner() *Player {
|
// not over.
|
||||||
|
func (g *Match) Winner() *Player {
|
||||||
if g.players[0].hp <= 0 {
|
if g.players[0].hp <= 0 {
|
||||||
return &g.players[1]
|
return &g.players[1]
|
||||||
}
|
}
|
||||||
@ -141,10 +166,9 @@ func (g *Game) Winner() *Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shoot fires the shotgun, at the opponent if self is false and at the current
|
// Shoot fires the shotgun, at the opponent if self is false and at the current
|
||||||
// player if self is true. Afterward, the round may be over, or the shotgun may
|
// player if self is true. Afterward, the round or game may be over.
|
||||||
// be empty.
|
|
||||||
// Returns ErrWrongTurn if id does not correspond to the current player.
|
// Returns ErrWrongTurn if id does not correspond to the current player.
|
||||||
func (g *Game) Shoot(id player.ID, self bool) error {
|
func (g *Match) Shoot(id player.ID, self bool) error {
|
||||||
cur := g.CurrentPlayer()
|
cur := g.CurrentPlayer()
|
||||||
if cur.id != id {
|
if cur.id != id {
|
||||||
return ErrWrongTurn
|
return ErrWrongTurn
|
||||||
@ -153,7 +177,7 @@ func (g *Game) Shoot(id player.ID, self bool) error {
|
|||||||
if self {
|
if self {
|
||||||
target = g.CurrentPlayer()
|
target = g.CurrentPlayer()
|
||||||
}
|
}
|
||||||
live := g.PopShell()
|
live := g.popShell()
|
||||||
if live {
|
if live {
|
||||||
target.hp -= g.damage
|
target.hp -= g.damage
|
||||||
g.NextTurn()
|
g.NextTurn()
|
||||||
@ -163,10 +187,10 @@ func (g *Game) Shoot(id player.ID, self bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concede sets the player with the given ID to zero health. The returned
|
// Concede sets the player with the given ID to zero health and ends the match.
|
||||||
// Boolean indicates whether the game has ended. (It will be false if id does
|
// The returned bool indicates whether the match has ended. (It will be false
|
||||||
// not correspond to either player.)
|
// if id does not correspond to either player.)
|
||||||
func (g *Game) Concede(id player.ID) bool {
|
func (g *Match) Concede(id player.ID) bool {
|
||||||
switch id {
|
switch id {
|
||||||
case g.players[0].id:
|
case g.players[0].id:
|
||||||
g.players[0].hp = 0
|
g.players[0].hp = 0
|
||||||
@ -175,11 +199,12 @@ func (g *Game) Concede(id player.ID) bool {
|
|||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
g.round = 3
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DTO returns the current game state as viewed by the given player.
|
// DTO returns the current match state as viewed by the given player.
|
||||||
func (g *Game) DTO(id player.ID) serve.Game {
|
func (g *Match) DTO(id player.ID) serve.Game {
|
||||||
return serve.Game{
|
return serve.Game{
|
||||||
Players: [2]serve.Player{
|
Players: [2]serve.Player{
|
||||||
g.players[0].DTO(),
|
g.players[0].DTO(),
|
||||||
@ -193,7 +218,7 @@ func (g *Game) DTO(id player.ID) serve.Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ShellCounts returns the number of live and blank shells.
|
// ShellCounts returns the number of live and blank shells.
|
||||||
func (g *Game) ShellCounts() serve.ShellCounts {
|
func (g *Match) ShellCounts() serve.ShellCounts {
|
||||||
var counts serve.ShellCounts
|
var counts serve.ShellCounts
|
||||||
for _, s := range g.shells {
|
for _, s := range g.shells {
|
||||||
if s {
|
if s {
|
||||||
|
@ -25,7 +25,7 @@ func TestNewGame(t *testing.T) {
|
|||||||
{len(g.shells) < 2 || len(g.shells) > 8, "bad shells count %d, want 2-8", []any{len(g.shells)}},
|
{len(g.shells) < 2 || len(g.shells) > 8, "bad shells count %d, want 2-8", []any{len(g.shells)}},
|
||||||
{&g.shells[0] != &g.shellArray[0], "shells[0] is %p, want %p", []any{&g.shells[0], &g.shellArray[0]}},
|
{&g.shells[0] != &g.shellArray[0], "shells[0] is %p, want %p", []any{&g.shells[0], &g.shellArray[0]}},
|
||||||
{g.round != 1, "first round is %d, want 1", []any{g.round}},
|
{g.round != 1, "first round is %d, want 1", []any{g.round}},
|
||||||
{g.group != 1, "first group is %d, want 1", []any{g.group}},
|
{g.game != 1, "first group is %d, want 1", []any{g.game}},
|
||||||
{g.turn != 1, "first turn is %d, want 1", []any{g.turn}},
|
{g.turn != 1, "first turn is %d, want 1", []any{g.turn}},
|
||||||
{g.hp < 2 || g.hp > 4, "hp is %d, want 2-4", []any{g.hp}},
|
{g.hp < 2 || g.hp > 4, "hp is %d, want 2-4", []any{g.hp}},
|
||||||
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
||||||
@ -54,7 +54,7 @@ func TestGameStartRound(t *testing.T) {
|
|||||||
{len(g.shells) < 2 || len(g.shells) > 8, "bad shells count %d, want 2-8", []any{len(g.shells)}},
|
{len(g.shells) < 2 || len(g.shells) > 8, "bad shells count %d, want 2-8", []any{len(g.shells)}},
|
||||||
{&g.shells[0] != &g.shellArray[0], "shells[0] is %p, want %p", []any{&g.shells[0], &g.shellArray[0]}},
|
{&g.shells[0] != &g.shellArray[0], "shells[0] is %p, want %p", []any{&g.shells[0], &g.shellArray[0]}},
|
||||||
{g.round != i, "round is %d, want %d", []any{g.round, i}},
|
{g.round != i, "round is %d, want %d", []any{g.round, i}},
|
||||||
{g.group != 1, "group is %d, want 1", []any{g.group}},
|
{g.game != 1, "group is %d, want 1", []any{g.game}},
|
||||||
{g.turn != 1, "turn is %d, want 1", []any{g.turn}},
|
{g.turn != 1, "turn is %d, want 1", []any{g.turn}},
|
||||||
{g.hp < 2 || g.hp > 4, "hp is %d, want 2-4", []any{g.hp}},
|
{g.hp < 2 || g.hp > 4, "hp is %d, want 2-4", []any{g.hp}},
|
||||||
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
||||||
@ -68,13 +68,13 @@ func TestGameStartRound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// H*ck with the game state as if a round is played.
|
// H*ck with the game state as if a round is played.
|
||||||
g.players[0].hp = 0
|
g.players[0].hp = 0
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
g.group = 2
|
g.game = 2
|
||||||
g.turn = 3
|
g.turn = 3
|
||||||
g.damage = 2
|
g.damage = 2
|
||||||
// Start the next round and check again.
|
// Start the next round and check again.
|
||||||
g.StartRound()
|
g.NextRound()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ func TestGameStartGroup(t *testing.T) {
|
|||||||
{&g.shells[0] != &g.shellArray[0], "shells[0] is %p, want %p", []any{&g.shells[0], &g.shellArray[0]}},
|
{&g.shells[0] != &g.shellArray[0], "shells[0] is %p, want %p", []any{&g.shells[0], &g.shellArray[0]}},
|
||||||
{counts.Live != counts.Blank && counts.Live+1 != counts.Blank, "imbalanced live/blank %d/%d", []any{counts.Live, counts.Blank}},
|
{counts.Live != counts.Blank && counts.Live+1 != counts.Blank, "imbalanced live/blank %d/%d", []any{counts.Live, counts.Blank}},
|
||||||
{g.round != 1, "round is %d, want 1", []any{g.round}},
|
{g.round != 1, "round is %d, want 1", []any{g.round}},
|
||||||
{g.group != i, "group is %d, want %d", []any{g.group, i}},
|
{g.game != i, "group is %d, want %d", []any{g.game, i}},
|
||||||
{g.turn != 1, "turn is %d, want 1", []any{g.turn}},
|
{g.turn != 1, "turn is %d, want 1", []any{g.turn}},
|
||||||
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
||||||
{g.reveal, "revealed at start", nil},
|
{g.reveal, "revealed at start", nil},
|
||||||
@ -108,13 +108,13 @@ func TestGameStartGroup(t *testing.T) {
|
|||||||
// H*ck with the game state.
|
// H*ck with the game state.
|
||||||
g.players[0].items[0] = ItemNone
|
g.players[0].items[0] = ItemNone
|
||||||
g.players[1].items[0] = ItemNone
|
g.players[1].items[0] = ItemNone
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
g.turn = 3
|
g.turn = 3
|
||||||
g.damage = 2
|
g.damage = 2
|
||||||
g.reveal = true
|
g.reveal = true
|
||||||
// Now advance the group.
|
// Now advance the group.
|
||||||
g.StartGroup()
|
g.NextGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ func TestGameNextTurn(t *testing.T) {
|
|||||||
args []any
|
args []any
|
||||||
}{
|
}{
|
||||||
{g.round != 1, "round is %d, want 1", []any{g.round}},
|
{g.round != 1, "round is %d, want 1", []any{g.round}},
|
||||||
{g.group != 1, "group is %d, want 1", []any{g.group}},
|
{g.game != 1, "group is %d, want 1", []any{g.game}},
|
||||||
{g.turn != i, "turn is %d, want %d", []any{g.turn, i}},
|
{g.turn != i, "turn is %d, want %d", []any{g.turn, i}},
|
||||||
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
{g.damage != 1, "damage is %d, want 1", []any{g.damage}},
|
||||||
{g.reveal, "revealed at start", nil},
|
{g.reveal, "revealed at start", nil},
|
||||||
@ -191,13 +191,13 @@ func TestGamePlayers(t *testing.T) {
|
|||||||
func TestGamePopShell(t *testing.T) {
|
func TestGamePopShell(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
g := New(player.ID{1}, player.ID{2})
|
g := New(player.ID{1}, player.ID{2})
|
||||||
if live := g.PopShell(); live != g.shellArray[0] {
|
if live := g.popShell(); live != g.shellArray[0] {
|
||||||
t.Errorf("first pop %t, wanted %t", live, g.shellArray[0])
|
t.Errorf("first pop %t, wanted %t", live, g.shellArray[0])
|
||||||
}
|
}
|
||||||
if g.prev != &g.shellArray[0] {
|
if g.prev != &g.shellArray[0] {
|
||||||
t.Errorf("first prev is %p, wanted %p", g.prev, &g.shellArray[0])
|
t.Errorf("first prev is %p, wanted %p", g.prev, &g.shellArray[0])
|
||||||
}
|
}
|
||||||
if live := g.PopShell(); live != g.shellArray[1] {
|
if live := g.popShell(); live != g.shellArray[1] {
|
||||||
t.Errorf("second pop %t, wanted %t", live, g.shellArray[1])
|
t.Errorf("second pop %t, wanted %t", live, g.shellArray[1])
|
||||||
}
|
}
|
||||||
if g.prev != &g.shellArray[1] {
|
if g.prev != &g.shellArray[1] {
|
||||||
@ -207,7 +207,7 @@ func TestGamePopShell(t *testing.T) {
|
|||||||
if g.Empty() {
|
if g.Empty() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
}
|
}
|
||||||
if !g.Empty() {
|
if !g.Empty() {
|
||||||
t.Errorf("popped too many shells")
|
t.Errorf("popped too many shells")
|
||||||
@ -221,7 +221,7 @@ func TestGamePeek(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
g := New(dealer, chall)
|
g := New(dealer, chall)
|
||||||
for !g.Empty() {
|
for !g.Empty() {
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
}
|
}
|
||||||
if g.Peek(dealer) != nil || g.Peek(chall) != nil {
|
if g.Peek(dealer) != nil || g.Peek(chall) != nil {
|
||||||
t.Errorf("peeked a shell when empty")
|
t.Errorf("peeked a shell when empty")
|
||||||
@ -268,7 +268,7 @@ func TestGameEmpty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
// We don't care about anything but the shells list.
|
// We don't care about anything but the shells list.
|
||||||
g := Game{shells: c.shells}
|
g := Match{shells: c.shells}
|
||||||
if got := g.Empty(); got != c.want {
|
if got := g.Empty(); got != c.want {
|
||||||
t.Errorf("empty reported %t, wanted %t", got, c.want)
|
t.Errorf("empty reported %t, wanted %t", got, c.want)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ func NewItem(rng *RNG) Item {
|
|||||||
return Item(rng.Intn(5)) + 1
|
return Item(rng.Intn(5)) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Item) Apply(g *Game) bool {
|
func (i Item) Apply(g *Match) bool {
|
||||||
switch i {
|
switch i {
|
||||||
case ItemNone:
|
case ItemNone:
|
||||||
return false
|
return false
|
||||||
@ -33,9 +33,9 @@ func (i Item) Apply(g *Game) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case ItemBeer:
|
case ItemBeer:
|
||||||
g.PopShell()
|
g.popShell()
|
||||||
if g.Empty() {
|
if g.Empty() {
|
||||||
g.StartGroup()
|
g.NextGame()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case ItemCuff:
|
case ItemCuff:
|
||||||
|
Loading…
Reference in New Issue
Block a user