diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2023-08-03 19:41:20 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-08-20 15:57:07 +0200 |
| commit | a3e558ff022fb9c38e9edcf2ced51cfa95b8de4c (patch) | |
| tree | f907aee0ba70ca8347f6ec88458f0faea0413462 | |
| parent | 49a5eda54785976028e360ef1af311dfcc8e1560 (diff) | |
| download | muhqs-game-a3e558ff022fb9c38e9edcf2ced51cfa95b8de4c.tar.gz muhqs-game-a3e558ff022fb9c38e9edcf2ced51cfa95b8de4c.zip | |
add skeleton for triggers and triggered actions
| -rw-r--r-- | go/game/action.go | 23 | ||||
| -rw-r--r-- | go/game/state.go | 47 | ||||
| -rw-r--r-- | go/game/trigger.go | 90 |
3 files changed, 159 insertions, 1 deletions
diff --git a/go/game/action.go b/go/game/action.go index fbabb06b..4f433845 100644 --- a/go/game/action.go +++ b/go/game/action.go @@ -79,6 +79,29 @@ func (a *ActionBase) CheckTargets(s *State) error { return a.targets.CheckTargets(s) } +type TriggeredAction struct { + ActionBase + event Event +} + +func newTriggeredAction(event Event, source Trigger, resolveFunc ActionResolveFunc, + costFunc ActionCostFunc, +) *TriggeredAction { + return &TriggeredAction{ + ActionBase: ActionBase{ + source: source, + Card: source.Card(), + resolveFunc: resolveFunc, + costFunc: costFunc, + }, + event: event, + } +} + +func (a *TriggeredAction) String() string { + return fmt.Sprintf("%v ! %v", a.event, a.source) +} + type PileDropAction struct { ActionBase pile []Permanent diff --git a/go/game/state.go b/go/game/state.go index 49ee0c06..6bb3dbf0 100644 --- a/go/game/state.go +++ b/go/game/state.go @@ -9,6 +9,7 @@ import ( "time" "golang.org/x/exp/slices" + "muhq.space/muhqs-game/go/utils" ) type State struct { @@ -24,6 +25,8 @@ type State struct { Rand *rand.Rand eotEffects []effect outstandingEquipment []*Card + events []Event + triggers []Trigger } func NewState() *State { @@ -96,6 +99,39 @@ func (s *State) Loop() []*Player { return winners } +func (s *State) removeTriggers(triggers []Trigger) { + for _, t := range triggers { + s.triggers = utils.RemoveFromUnorderedSlice(s.triggers, t) + } +} + +func (s *State) handleTriggers() { + var actions []Action + var triggersToRemove []Trigger + + for _, e := range s.events { + for _, t := range s.triggers { + a, remove := t.trigger(s, e) + if a != nil { + actions = append(actions, a...) + } + if remove { + triggersToRemove = append(triggersToRemove, t) + } + } + } + + // Reset occured events + s.events = nil + + s.removeTriggers(triggersToRemove) + + orderedActions := s.orderTriggeredActions(actions) + for _, a := range orderedActions { + s.declareAction(a) + } +} + func (s *State) stateBasedActions() { for _, p := range s.Permanents { p.Card().Impl.stateBasedActions(s, p) @@ -104,6 +140,8 @@ func (s *State) stateBasedActions() { s.destroyPermanent(p) } } + + s.handleTriggers() } func (s *State) IsValidPlay(a *PlayAction) error { @@ -322,6 +360,11 @@ func (s *State) declareAction(a Action) { s.broadcastNotification(newDeclaredActionNotification(a, err)) } +func (s *State) orderTriggeredActions(actions []Action) []Action { + // TODO: implement ordering + return actions +} + func (s *State) allPassing(skipFirst bool) bool { nPlayers := len(s.Players) i := 0 @@ -600,6 +643,8 @@ func (s *State) endOfTurn() { for _, e := range s.eotEffects { e.end(s) } + s.eotEffects = nil - s.eotEffects = []effect{} + s.events = append(s.events, newEotEvent()) + s.stateBasedActions() } diff --git a/go/game/trigger.go b/go/game/trigger.go new file mode 100644 index 00000000..39901d71 --- /dev/null +++ b/go/game/trigger.go @@ -0,0 +1,90 @@ +package game + +import ( + "fmt" + "log" +) + +type eventType int + +const ( + destruction eventType = iota + eot + sacrifice + play +) + +var EventTypes = struct { + Destruction eventType + Eot eventType + Sacrifice eventType + Play eventType +}{ + Destruction: destruction, + Eot: eot, + Play: play, +} + +func (e eventType) String() string { + switch e { + case destruction: + return "destruction" + case eot: + return "eot" + case sacrifice: + return "sacrifice" + case play: + return "play" + } + + log.Panicf("Unknown evenType", e) + return "" +} + +type Event struct { + eventType eventType + sources []interface{} +} + +func (e Event) String() string { + if len(e.sources) == 0 { + return e.eventType.String() + } + + return fmt.Sprintf("%v:%v", e.sources, e.eventType) +} + +func newEotEvent() Event { + return Event{eventType: eot} +} + +type Trigger interface { + Card() *Card + String() string + trigger(*State, Event) ([]Action, bool) +} + +type triggerBase struct { + card *Card + condition func(*State, Event) (bool, bool) + resolveFunc ActionResolveFunc + costFunc ActionCostFunc + desc string +} + +func (t *triggerBase) Card() *Card { + return t.card +} + +func (t *triggerBase) String() string { + return t.desc +} + +func (t *triggerBase) trigger(s *State, e Event) ([]Action, bool) { + triggered, remove := t.condition(s, e) + if !triggered { + return nil, remove + } + + return []Action{newTriggeredAction(e, t, t.resolveFunc, t.costFunc)}, remove +} |
