This repository has been archived by the owner on Dec 30, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
caller.go
98 lines (81 loc) · 2.19 KB
/
caller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package loteria
import (
"fmt"
)
type (
// Caller defines the actor in charge of announcing the cards.
Caller struct {
deck Deck
players map[PlayerName]Board
boards map[BoardID]PlayerName
gameStarted bool
gameFinished bool
}
)
// NewCaller returns a new caller with a shuffled deck of cards.
func NewCaller() Caller {
deck := NewDeck()
deck.Shuffle()
return Caller{
deck: deck,
players: map[PlayerName]Board{},
boards: map[BoardID]PlayerName{},
}
}
// AddPlayer adds the player to the game and it assigns the player a random
// board.
func (c *Caller) AddPlayer(name PlayerName) (Player, error) {
if c.gameStarted {
return Player{}, fmt.Errorf("game is in progress, can't add more players")
}
if _, ok := c.players[name]; ok {
return Player{}, fmt.Errorf("player %s is already part of the game", name)
}
board := NewRandomBoard()
if _, ok := c.boards[board.ID()]; ok {
// XXX retry a few times instead of returning right away
return Player{}, fmt.Errorf("board was already assigned to another player")
}
c.boards[board.ID()] = name
c.players[name] = board
return NewPlayer(name, board), nil
}
// Announce announces a card from the deck.
func (c *Caller) Announce() (Card, error) {
// XXX Must have at least one player to start the game.
if c.gameFinished {
return blankCard, fmt.Errorf("game already finished")
}
c.gameStarted = true
card, err := c.deck.Select()
if err != nil {
c.gameFinished = true
return card, err
}
// We update our internal boards to use them later in `Loteria` for
// confirming the player really won.
for name, board := range c.players {
if board.Mark(card) == nil {
c.players[name] = board
}
}
return card, nil
}
// Loteria determines if the player is really the winner
func (c *Caller) Loteria(name PlayerName) error {
if !c.gameStarted {
return fmt.Errorf("game has not started yet")
}
if c.gameFinished { // XXX consider if name = already winner
return fmt.Errorf("game already finished")
}
board, ok := c.players[name]
if !ok {
return fmt.Errorf("player not part of the game")
}
if !board.IsWinner() {
return fmt.Errorf("board is not a winner one")
}
c.gameFinished = true
return nil
}