-
Notifications
You must be signed in to change notification settings - Fork 0
/
game.go
114 lines (104 loc) · 2.68 KB
/
game.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
// Game defines the logic of the maumau game
type Game struct {
GameState
Events []Event `json:"-"`
RedoEvents []Event `json:"-"`
}
// GameState includes all properties of the game, which are having
// a state. The is just changed by an event.
type GameState struct {
Stack *CardStack `json:"stack,omitempty"`
Heap *CardStack `json:"heap,omitempty"`
HeapHead Card `json:"heap_head,omitempty"`
Players []*Player `json:"players,omitempty"`
ActivePlayer int `json:"active_player"`
NrCards int `json:"nr_cards,omitempty"`
}
func newGame() *Game {
return &Game{
GameState: GameState{
Stack: &CardStack{},
Heap: &CardStack{},
ActivePlayer: 0,
NrCards: 6,
},
}
}
// Event takes an event and adds that to the game
// to get a new state Init() has to be called
func (g *Game) Event(e Event) {
// every new event clears the redo slice
g.RedoEvents = []Event{}
g.Events = append(g.Events, e)
}
// Init clears the internal state
func (g *Game) Init() {
g.Stack = &CardStack{}
g.Heap = &CardStack{}
g.Players = []*Player{}
}
// State executes all events and creates a new state for
// the Stack, Heap and the Players
func (g *Game) State() {
g.Init()
for _, e := range g.Events {
e(&g.GameState)
}
g.HeapHead = g.Heap.peek()
}
// Player returns the player matching to the given ID.
// when no ID is availiable a nil pointer is returned.
func (g *GameState) Player(id string) (*Player, bool) {
for _, p := range g.Players {
if id == p.ID {
return p, true
}
}
return nil, false
}
// NextPlayer takes the current player ID and returns the
// next player at the table. If there is no ID a nil pointer
// is returned
func (g *GameState) NextPlayer(id string) (*Player, bool) {
found := -1
// index of the current player
for i, p := range g.Players {
if id == p.ID {
found = i
break
}
}
if found == -1 {
return nil, false
}
next := found + 1
if len(g.Players)-1 == found {
// if current player is the last in the slice
// the first player is next
next = 0
}
return g.Players[next], true
}
// SetActivePlayer takes an ID to set the active player
// all other players will set es not active.
// if there is no ID, false ist returned
func (g *GameState) SetActivePlayer(id string) bool {
// first check if there is a player to the id
// if not nothing should be changed.
_, ok := g.Player(id)
if !ok {
return false
}
for _, p := range g.Players {
if id == p.ID {
p.Active = true
} else {
p.Active = false
}
}
return true
}
// Event is a function, which takes a pointer to the game
// When the game calculates the state all events are called
type Event func(g *GameState)