From 7503a591756081e06137db7707c690ffffb04553 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Thu, 24 Jul 2025 05:42:50 -0400 Subject: check the wincondition after the state based actions --- go/game/player.go | 25 ++++++++++------- go/game/stack.go | 17 ++++++++++-- go/game/state.go | 83 +++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/go/game/player.go b/go/game/player.go index f7f5be7c..2edbe923 100644 --- a/go/game/player.go +++ b/go/game/player.go @@ -111,7 +111,7 @@ func (p *Player) reduceResource(amount int) { } } -func (p *Player) upkeep() { +func (p *Player) upkeep() []*Player { p.gainResource(p.ResourceGain()) // TODO: handle upkeep triggers @@ -125,7 +125,7 @@ func (p *Player) upkeep() { } } if !controllsUnits { - return + return nil } a, err := prompt(p.Ctrl, newUpkeepPrompt(p)) @@ -139,30 +139,33 @@ func (p *Player) upkeep() { // FIXME: upkeep action is special paying is part of its effect p.gameState.declareAction(a) - p.gameState.stack.resolve() + return p.gameState.stack.resolve() } -func (p *Player) actionPhase() { +func (p *Player) actionPhase() []*Player { for { a, err := promptAction(p.Ctrl) if err != nil { // FIXME } if _, ok := a.(*PassPriority); ok { - return + return nil } if a == nil { log.Fatal("Received nil action from ", p.Name) } p.gameState.declareAction(a) - p.gameState.stack.resolve() + w := p.gameState.stack.resolve() + if len(w) > 0 { + return w + } } } -func (p *Player) buyPhase() { +func (p *Player) buyPhase() []*Player { s := p.gameState if p.Store.Size() == 0 && s.Map().HasStores() && len(p.knownStores) == 0 { - return + return nil } a, err := promptBuy(p.Ctrl) if err != nil { @@ -170,13 +173,15 @@ func (p *Player) buyPhase() { } if _, ok := a.(*PassPriority); ok { - return + return nil } if a.Targets().HasSelections() { s.declareAction(a) - s.stack.resolve() + return s.stack.resolve() } + + return nil } func (p *Player) discardHand() { diff --git a/go/game/stack.go b/go/game/stack.go index a4ba6a49..62783bf2 100644 --- a/go/game/stack.go +++ b/go/game/stack.go @@ -45,11 +45,22 @@ func (s *Stack) pop() { } } -func (s *Stack) resolve() { +func (s *Stack) resolve() []*Player { for !s.IsEmpty() { - for !s.gameState.allPassing(false) { + for { + passing, w := s.gameState.allPassing(false) + if len(w) > 0 { + return w + } + if passing { + break + } } s.pop() - s.gameState.stateBasedActions() + w := s.gameState.stateBasedActions() + if len(w) > 0 { + return w + } } + return nil } diff --git a/go/game/state.go b/go/game/state.go index 16670263..73374c6a 100644 --- a/go/game/state.go +++ b/go/game/state.go @@ -154,8 +154,7 @@ func (s *LocalState) Loop() []*Player { s._map.distributeStoreCards(poc, s.Rand) } - winners := []*Player{} - for len(winners) == 0 { + for { for _, p := range s.players { s.activePlayerId = p.Id p.Turn++ @@ -170,27 +169,44 @@ func (s *LocalState) Loop() []*Player { p.Draw() s.activePhase = Phases.UpkeepPhase - p.upkeep() - s.phaseChange() + winners := p.upkeep() + if len(winners) > 0 { + return winners + } + winners = s.phaseChange() + if len(winners) > 0 { + return winners + } s.activePhase = Phases.ActionPhase - p.actionPhase() - s.phaseChange() + winners = p.actionPhase() + if len(winners) > 0 { + return winners + } + winners = s.phaseChange() + if len(winners) > 0 { + return winners + } s.activePhase = Phases.BuyPhase - p.buyPhase() - s.phaseChange() + winners = p.buyPhase() + if len(winners) > 0 { + return winners + } + winners = s.phaseChange() + if len(winners) > 0 { + return winners + } s.activePhase = Phases.DiscardStep p.discardStep() - s.endOfTurn() - - winners = s._map.WinCondition(s) + winners = s.endOfTurn() + if len(winners) > 0 { + return winners + } } } - - return winners } func (s *LocalState) addTrigger(trigger Trigger) { @@ -232,7 +248,7 @@ func (s *LocalState) handleTriggers() { } } -func (s *LocalState) stateBasedActions() { +func (s *LocalState) stateBasedActions() []*Player { for _, p := range s.permanents { p.Card().Impl.stateBasedActions(s, p) @@ -242,6 +258,9 @@ func (s *LocalState) stateBasedActions() { } s.handleTriggers() + + w := s._map.WinCondition(s) + return w } func (s *LocalState) IsValidPlay(a *PlayAction) error { @@ -273,7 +292,7 @@ func (s *LocalState) IsValidMove(a *MoveAction) error { u := a.Source().(*Unit) tile := relaxedTileTarget(a, a.Target().sel[0]) - if !slices.Contains(u.MoveRangeTiles(s._map), tile) { + if !slices.Contains(u.MoveRangeTiles(), tile) { return fmt.Errorf("Unit %s@%v can not move to %s", u.card.Name, u.tile.Position, tile.Position.String()) } @@ -508,7 +527,7 @@ func (s *LocalState) orderTriggeredActions(triggeredActions []*TriggeredAction) return orderedActions } -func (s *LocalState) allPassing(skipFirst bool) bool { +func (s *LocalState) allPassing(skipFirst bool) (bool, []*Player) { nPlayers := len(s.players) i := 0 if skipFirst { @@ -516,7 +535,10 @@ func (s *LocalState) allPassing(skipFirst bool) bool { } for ; i < nPlayers; i++ { p := s.players[(i+s.activePlayerId-1)%nPlayers] - s.stateBasedActions() + w := s.stateBasedActions() + if len(w) > 0 { + return false, w + } p.Ctrl.SendNotification(newPriorityNotification()) _a, err := p.Ctrl.RecvAction() if err != nil { @@ -530,18 +552,31 @@ func (s *LocalState) allPassing(skipFirst bool) bool { log.Fatal("received nil action from ", p.Name, " at ", s.activePhase) default: s.declareAction(a) - return false + return false, nil } } - return true + return true, nil } -func (s *LocalState) phaseChange() { +func (s *LocalState) phaseChange() []*Player { skipFirst := true - for !s.allPassing(skipFirst) { - s.stack.resolve() + for { + passing, w := s.allPassing(skipFirst) + if len(w) > 0 { + return w + } + if passing { + break + } + + w = s.stack.resolve() + if len(w) > 0 { + return w + } + skipFirst = false } + return nil } func (s *LocalState) broadcastNotification(n PlayerNotification) { @@ -825,7 +860,7 @@ func (s *LocalState) addEotEffect(e effect) { s.eotEffects = append(s.eotEffects, e) } -func (s *LocalState) endOfTurn() { +func (s *LocalState) endOfTurn() []*Player { // Move all outstanding equipment cards to the discard pile for _, e := range s.outstandingEquipment { s.ActivePlayer().DiscardPile.AddCard(e) @@ -837,7 +872,7 @@ func (s *LocalState) endOfTurn() { s.eotEffects = nil s.events = append(s.events, newEotEvent()) - s.stateBasedActions() + return s.stateBasedActions() } // ResolveAction resolves an action without using the stack. -- cgit v1.2.3