package game import ( "fmt" "log" ) type PlayerNotificationType int const ( DeclaredActionNotification PlayerNotificationType = iota ResolvedActionNotification PriorityNotification TargetSelectionPrompt DeclareTriggeredActionsPrompt ) 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" default: log.Panicf("Unhandled notification %d", n) return "" } } func (n PlayerNotification) IsPriorityNotification() bool { return n.Notification == PriorityNotification } type PlayerNotification struct { Notification PlayerNotificationType Context interface{} 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} } type PlayerControl interface { Player() *Player RecvAction() Action SendNotification(PlayerNotification) } 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 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()) }