diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2023-01-25 21:10:44 +0100 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-01-27 16:43:44 +0100 |
| commit | 8720ebf9c74d9e11001772b5c00c293fa3a8b9e5 (patch) | |
| tree | 70013771c425746318d290b5cadad0bbc1a48abb /go/game/state.go | |
| parent | 73d40903aecad3efcf7c6055c133f0db86558203 (diff) | |
| download | muhqs-game-8720ebf9c74d9e11001772b5c00c293fa3a8b9e5.tar.gz muhqs-game-8720ebf9c74d9e11001772b5c00c293fa3a8b9e5.zip | |
intermediate commit
Diffstat (limited to 'go/game/state.go')
| -rw-r--r-- | go/game/state.go | 101 |
1 files changed, 68 insertions, 33 deletions
diff --git a/go/game/state.go b/go/game/state.go index 1a6ae093..29267c28 100644 --- a/go/game/state.go +++ b/go/game/state.go @@ -6,6 +6,7 @@ import ( "math/rand" "strconv" "strings" + "time" ) type State struct { @@ -17,15 +18,17 @@ type State struct { DiscardPiles []*DiscardPile Players []*Player ActivePlayerId int + ActivePhase PhaseType Permanents []Permanent Units []*Unit Artifacts []*Artifact - Rand rand.Rand + Rand *rand.Rand } func NewState() *State { s := &State{} s.Stack = NewStack(s) + s.Rand = rand.New(rand.NewSource(time.Now().UnixNano())) return s } @@ -38,33 +41,32 @@ func (s *State) Loop() []*Player { winners := []*Player{} for len(winners) == 0 { for i, p := range s.Players { - log.Printf("Starting %s turn %d\n", p.Name, p.Turn) s.ActivePlayerId = i p.Turn++ if p.Deck.IsEmpty() { log.Printf("Shuffle %s pile into the deck\n", p.Name) p.DiscardPile.MoveInto(p.Deck) - p.Deck.Shuffle() + p.Deck.Shuffle(s.Rand) } - log.Printf("%s draw\n", p.Name) + s.ActivePhase = drawPhase p.Draw() - log.Printf("%s Upkeep\n", p.Name) + s.ActivePhase = upkeepPhase p.Upkeep() s.PhaseChange(i) - log.Printf("%s Actions\n", p.Name) + s.ActivePhase = actionPhase p.ActionPhase() s.PhaseChange(i) - log.Printf("%s Buystep\n", p.Name) - p.BuyStep() + s.ActivePhase = buyPhase + p.BuyPhase() s.PhaseChange(i) - log.Printf("%s Discard\n", p.Name) - p.DiscardStep() + s.ActivePhase = discardPhase + p.DiscardPhase() winners = s.Map.WinCondition(s) } @@ -75,7 +77,7 @@ func (s *State) Loop() []*Player { func (s *State) PushAction(a Action) { if !a.PayCosts(s) { - log.Fatalf("Cost for a could not be paid") + log.Fatalf("Cost for %s could not be paid", a) } s.Stack.Push(a) } @@ -84,6 +86,11 @@ func (s *State) DeclareAction(a Action) { if !s.Stack.IsEmpty() { log.Fatalf("Slow action can not be declared while other actions are on the stack") } + + if s.ActivePhase != actionPhase { + log.Fatalf("Slow action can not be declared during one's actions phase") + } + s.PushAction(a) } @@ -101,14 +108,14 @@ func (s *State) AllPassing() bool { case *PassPriorityAction: log.Printf("%s passed %d/%d\n", p.Name, i, nPlayers) default: - s.Stack.Push(a) + s.DeclareAction(a) return false } } return true } -func (s *State) PhaseChange(activePlaerId int) { +func (s *State) PhaseChange(activePlayerId int) { log.Println("Phase change") for !s.AllPassing() { s.Stack.Resolve() @@ -122,19 +129,6 @@ func (s *State) broadcastNotification(n PlayerNotification) { } } -func (s *State) Upkeep(p *Player) { - p.Ressource += s.Map.RessourceGain - // TODO: handle upkeep trigger - for _, unit := range s.Units { - if unit.Controller != p { - continue - } - - // TODO: let players decide if they want to pay the upkeep - p.Ressource -= unit.Upkeep - } -} - func (s *State) AddPermanent(perm Permanent) { s.Permanents = append(s.Permanents, perm) switch p := perm.(type) { @@ -191,6 +185,7 @@ func (s *State) DestroyPermanent(p Permanent) { case *Artifact: s.Artifacts = removePtr(s.Artifacts, p) } + p.GetOwner().DiscardPile.AddCard(p.GetCard()) } func (s *State) Fight(p1, p2 Permanent) { @@ -208,26 +203,49 @@ func (s *State) MoveUnit(u *Unit, t *Tile) { u.move(s, t) } -func (s *State) EnemyUnits(player *Player) []*Unit { - // TODO: support coop / teams - enemyUnits := []*Unit{} +func (s *State) FilterUnits(filter func(*Unit) bool) []*Unit { + units := []*Unit{} for _, u := range s.Units { - if u.GetController() != player { - enemyUnits = append(enemyUnits, u) + if filter(u) { + units = append(units, u) } } - return enemyUnits + return units +} + +func (s *State) OwnUnits(player *Player) []*Unit { + return s.FilterUnits(func(u *Unit) bool { + return u.GetController() == player + }) +} + +func (s *State) EnemyUnits(player *Player) []*Unit { + return s.FilterUnits(func(u *Unit) bool { + // TODO: support coop / teams + return u.GetController() != player + }) } func (s *State) ResolvePlay(p *Player, c *Card, targets interface{}) { switch c.Type { case UnitType: s.AddNewUnit(c, targets.(Position), p) + case ArtifactType: + s.AddNewArtifact(c, targets.(Position), p) + default: + log.Printf("Resolving unhandled card type: %s\n", c.Type.String()) + } + + if !c.IsPermanent() { + p.DiscardPile.AddCard(c) } - p.DiscardPile.AddCard(c) } func (s *State) SpawnTiles(p *Player) []*Tile { + if p.Name == "The Kraken" { + return s.KrakenSpawnTiles() + } + spawns := s.Map.FilterTiles(func(t *Tile) bool { if t.Type != TileTypes.Spawn { return false @@ -238,3 +256,20 @@ func (s *State) SpawnTiles(p *Player) []*Tile { return spawns } + +func (s *State) AvailableSpawnTiles(p *Player, c *Card) []*Tile { + if !c.IsPermanent() { + log.Fatalf("AvailableSpawnTiles called for %s", c.Type.String()) + } + + candidates := s.SpawnTiles(p) + tiles := []*Tile{} + + for _, candidate := range candidates { + if candidate.IsAvailableForCard(c) { + tiles = append(tiles, candidate) + } + } + + return tiles +} |
