package game import ( "golang.org/x/exp/slices" ) // A WinCondition determines if there are winners using the current game state. type WinCondition interface { check(*LocalState) []*Player String() string } type winCondition struct { condition func(*LocalState) []*Player desc string } func (w *winCondition) check(s *LocalState) []*Player { return w.condition(s) } func (w *winCondition) String() string { return w.desc } // DummyWinCondition always return an empty winner slice. var DummyWinCondition = &winCondition{ condition: func(*LocalState) []*Player { return []*Player{} }, desc: "dummy wincondition", } // KingGame reports all players without an enemy king. var KingGame = &winCondition{ condition: func(s *LocalState) []*Player { foundKings := map[*Player]struct{}{} for _, u := range s.Units() { if u.card.Name != "King" { continue } foundKings[u.owner] = struct{}{} } if len(foundKings) == len(s.Players()) { return []*Player{} } loosers := make([]*Player, 2, len(s.Players())) copy(loosers, s.Players()) for p := range foundKings { i := slices.Index(loosers, p) loosers[i] = loosers[len(loosers)-1] loosers = loosers[:len(loosers)-1] } if len(loosers) == len(s.Players()) { return s.Players() } winners := []*Player{} for _, p := range s.Players() { if !slices.Contains(loosers, p) { winners = append(winners, p) } } return winners }, desc: "Destroy the enemy King", } // DeathMatch returns the players without enemy units. var DeathMatch = &winCondition{ condition: func(s *LocalState) []*Player { winners := []*Player{} for _, p := range s.players { if len(s.EnemyUnits(p)) == 0 { winners = append(winners, p) } } return winners }, desc: "Destroy all enemy units", }