diff --git a/game/game.go b/game/game.go index fa83ade..383dd14 100644 --- a/game/game.go +++ b/game/game.go @@ -113,8 +113,8 @@ func (g *Match) Opponent() *Player { } // Apply uses an item by index for the current player. -// This may cause the current game to end, but does not start the next game -// if so. +// If this causes the current game to end (a beer discharges the last shell), +// returns ErrGameEnded but does not start the next game. // Returns ErrWrongTurn if id does not correspond to the current player. func (g *Match) Apply(id player.ID, item int) error { cur := g.CurrentPlayer() @@ -127,6 +127,9 @@ func (g *Match) Apply(id player.ID, item int) error { if cur.items[item].Apply(g) { cur.items[item] = ItemNone } + if g.Empty() { + return ErrGameEnded + } return nil } @@ -175,7 +178,9 @@ func (g *Match) MatchWinner() *Player { } // Shoot fires the shotgun, at the opponent if self is false and at the current -// player if self is true. Afterward, the round or game may be over. +// player if self is true. Advances the turn if appropriate. +// Returns ErrRoundEnded if this causes the round to end. +// Returns ErrGameEnded if this causes the game but not the round to end. // Returns ErrWrongTurn if id does not correspond to the current player. func (g *Match) Shoot(id player.ID, self bool) error { cur := g.CurrentPlayer() @@ -189,27 +194,37 @@ func (g *Match) Shoot(id player.ID, self bool) error { live := g.popShell() if live { target.hp -= g.damage - g.NextTurn() - } else if !self { + if target.hp <= 0 { + // If the target is the challenger, the match is over as well. + if target == &g.players[1] { + g.round = 3 + } + return ErrRoundEnded + } + } + if g.Empty() { + return ErrGameEnded + } + if !self || live { g.NextTurn() } return nil } // Concede sets the player with the given ID to zero health and ends the match. -// The returned bool indicates whether the match has ended. (It will be false -// if id does not correspond to either player.) -func (g *Match) Concede(id player.ID) bool { +// The returned error is ErrRoundEnded if id corresponds to either player and +// ErrWrongTurn otherwise. +func (g *Match) Concede(id player.ID) error { switch id { case g.players[0].id: g.players[0].hp = 0 case g.players[1].id: g.players[1].hp = 0 default: - return false + return ErrWrongTurn } g.round = 3 - return true + return ErrRoundEnded } // DTO returns the current match state as viewed by the given player. @@ -239,4 +254,8 @@ func (g *Match) ShellCounts() serve.ShellCounts { return counts } -var ErrWrongTurn = errors.New("not your turn") +var ( + ErrWrongTurn = errors.New("not your turn") + ErrGameEnded = errors.New("the shotgun is empty") + ErrRoundEnded = errors.New("someone h*ckin died") +)