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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
package game
import (
"fmt"
"log"
)
type PlayerNotificationType int
const (
DeclaredActionNotification PlayerNotificationType = iota
ResolvedActionNotification
PriorityNotification
TargetSelectionPrompt
DeclareTriggeredActionsPrompt
DraftPickPrompt
)
func (n PlayerNotificationType) String() string {
switch n {
case DeclaredActionNotification:
return "DeclaredActionNotification"
case ResolvedActionNotification:
return "ResolvedActionNotification"
case PriorityNotification:
return "PriorityNotification"
case TargetSelectionPrompt:
return "TargetSelectionPrompt"
case DeclareTriggeredActionsPrompt:
return "DeclareTriggeredActionsPrompt"
case DraftPickPrompt:
return "DraftPickPrompt"
default:
log.Panicf("Unhandled notification %d", n)
return ""
}
}
func (n PlayerNotification) IsPriorityNotification() bool {
return n.Notification == PriorityNotification
}
type PlayerNotification struct {
Notification PlayerNotificationType
Context any
Error error
}
func (n *PlayerNotification) String() string {
if n.Error != nil {
return fmt.Sprintf("error %v: %v", n.Notification, n.Error)
}
return fmt.Sprintf("%v: %v", n.Notification, n.Context)
}
type TargetSelectionCtx struct {
Action Action
Prompt string
}
func newPriorityNotification() PlayerNotification {
return PlayerNotification{PriorityNotification, nil, nil}
}
func newDeclaredActionNotification(a Action, err error) PlayerNotification {
return PlayerNotification{DeclaredActionNotification, a, err}
}
func newResolvedActionNotification(a Action, err error) PlayerNotification {
return PlayerNotification{ResolvedActionNotification, a, err}
}
func newTargetSelectionPrompt(a Action, desc string) PlayerNotification {
return PlayerNotification{TargetSelectionPrompt, TargetSelectionCtx{a, desc}, nil}
}
func newUpkeepPrompt(p *Player) PlayerNotification {
a := newUpkeepAction(p)
return newTargetSelectionPrompt(a, "Select units to disband")
}
func newBuyPrompt(p *Player) PlayerNotification {
a := newBuyAction(p)
prompt := newTargetSelectionPrompt(a, "Select a card to buy")
return prompt
}
func newHandCardSelectionPrompt(p *Player, min, max int) PlayerNotification {
a := newHandCardSelection(p, min, max)
desc := fmt.Sprintf("Select between %d and %d hand cards", min, max)
return newTargetSelectionPrompt(a, desc)
}
func newDeclareTriggeredActionsPrompt(triggeredActions []*TriggeredAction) PlayerNotification {
return PlayerNotification{DeclareTriggeredActionsPrompt, triggeredActions, nil}
}
func newDraftPickPrompt(pack PileOfCards) PlayerNotification {
return PlayerNotification{DraftPickPrompt, pack, nil}
}
type PlayerControl interface {
Player() *Player
RecvAction() Action
SendNotification(PlayerNotification)
Close()
}
type ChanPlayerControl struct {
player *Player
actions chan Action
notifications chan PlayerNotification
}
func (c *ChanPlayerControl) Player() *Player { return c.player }
func (c *ChanPlayerControl) SendAction(a Action) { c.actions <- a }
func (c *ChanPlayerControl) RecvAction() Action { return <-c.actions }
func (c *ChanPlayerControl) SendNotification(n PlayerNotification) { c.notifications <- n }
func (c *ChanPlayerControl) RecvNotification() *PlayerNotification {
select {
case n := <-c.notifications:
return &n
default:
return nil
}
}
func (c *ChanPlayerControl) Close() {
close(c.actions)
close(c.notifications)
}
func NewChanPlayerControl(p *Player) *ChanPlayerControl {
a := make(chan Action)
n := make(chan PlayerNotification)
return &ChanPlayerControl{p, a, n}
}
func prompt(ctrl PlayerControl, notification PlayerNotification) Action {
ctrl.SendNotification(notification)
return ctrl.RecvAction()
}
func promptBuy(ctrl PlayerControl) Action {
return prompt(ctrl, newBuyPrompt(ctrl.Player()))
}
func promptAction(ctrl PlayerControl) Action {
return prompt(ctrl, newPriorityNotification())
}
|