aboutsummaryrefslogtreecommitdiff
path: root/go/game/state.go
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2023-01-24 00:27:50 +0100
committerFlorian Fischer <florian.fischer@muhq.space>2025-01-27 16:43:44 +0100
commit73d40903aecad3efcf7c6055c133f0db86558203 (patch)
treee9c8f00fb186e270da92f273f570579f2d0b0d95 /go/game/state.go
parentfbba48698d8f8b83dfd7d914b0e37338e0d4e2ef (diff)
downloadmuhqs-game-73d40903aecad3efcf7c6055c133f0db86558203.tar.gz
muhqs-game-73d40903aecad3efcf7c6055c133f0db86558203.zip
intermediate commit
Diffstat (limited to 'go/game/state.go')
-rw-r--r--go/game/state.go187
1 files changed, 164 insertions, 23 deletions
diff --git a/go/game/state.go b/go/game/state.go
index 5cab9458..1a6ae093 100644
--- a/go/game/state.go
+++ b/go/game/state.go
@@ -2,21 +2,25 @@ package game
import (
"image/color"
+ "log"
"math/rand"
+ "strconv"
+ "strings"
)
type State struct {
- Decks []*Deck
- Stores []*Store
- Map *Map
- Stack *Stack
- Hands []*Hand
- DiscardPiles []*DiscardPile
- Players []*Player
- Permanents []Permanent
- Units []*Unit
- Artifacts []*Artifact
- Rand rand.Rand
+ Decks []*Deck
+ Stores []*Store
+ Map *Map
+ Stack *Stack
+ Hands []*Hand
+ DiscardPiles []*DiscardPile
+ Players []*Player
+ ActivePlayerId int
+ Permanents []Permanent
+ Units []*Unit
+ Artifacts []*Artifact
+ Rand rand.Rand
}
func NewState() *State {
@@ -25,15 +29,138 @@ func NewState() *State {
return s
}
-func (s *State) AddNewPlayer(name string, deck *Deck, color color.Color) {
- p := NewPlayer(len(s.Players), name, deck, s, color)
+func (s *State) AddNewPlayer(name string, deck *Deck, store *Store, color color.Color) {
+ p := NewPlayer(len(s.Players)+1, name, deck, store, s, color)
s.Players = append(s.Players, p)
}
-func (s *State) AddNewUnit(card string, pos Position, owner *Player) {
- unit := NewUnit(card, s.Map.TileAt(pos), owner)
- s.Permanents = append(s.Permanents, unit)
- s.Units = append(s.Units, unit)
+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()
+ }
+
+ log.Printf("%s draw\n", p.Name)
+ p.Draw()
+
+ log.Printf("%s Upkeep\n", p.Name)
+ p.Upkeep()
+ s.PhaseChange(i)
+
+ log.Printf("%s Actions\n", p.Name)
+ p.ActionPhase()
+ s.PhaseChange(i)
+
+ log.Printf("%s Buystep\n", p.Name)
+ p.BuyStep()
+ s.PhaseChange(i)
+
+ log.Printf("%s Discard\n", p.Name)
+ p.DiscardStep()
+
+ winners = s.Map.WinCondition(s)
+ }
+ }
+
+ return winners
+}
+
+func (s *State) PushAction(a Action) {
+ if !a.PayCosts(s) {
+ log.Fatalf("Cost for a could not be paid")
+ }
+ s.Stack.Push(a)
+}
+
+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")
+ }
+ s.PushAction(a)
+}
+
+func (s *State) DeclareFastAction(a Action) {
+ s.PushAction(a)
+}
+
+func (s *State) AllPassing() bool {
+ nPlayers := len(s.Players)
+ for i := 0; i < nPlayers; i++ {
+ p := s.Players[(i+s.ActivePlayerId)%nPlayers]
+ p.Ctrl.SendNotification(NewPriorityNotification())
+ a := p.Ctrl.RecvAction()
+ switch a.(type) {
+ case *PassPriorityAction:
+ log.Printf("%s passed %d/%d\n", p.Name, i, nPlayers)
+ default:
+ s.Stack.Push(a)
+ return false
+ }
+ }
+ return true
+}
+
+func (s *State) PhaseChange(activePlaerId int) {
+ log.Println("Phase change")
+ for !s.AllPassing() {
+ s.Stack.Resolve()
+ }
+}
+
+func (s *State) broadcastNotification(n PlayerNotification) {
+ log.Printf("broadcasting %v\n", n)
+ for _, p := range s.Players {
+ p.Ctrl.SendNotification(n)
+ }
+}
+
+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) {
+ case *Unit:
+ s.Units = append(s.Units, p)
+ case *Artifact:
+ s.Artifacts = append(s.Artifacts, p)
+ }
+}
+
+func (s *State) AddNewUnit(card *Card, pos Position, owner *Player) {
+ s.AddPermanent(NewUnit(card, s.Map.TileAt(pos), owner))
+}
+
+func (s *State) AddNewArtifact(card *Card, pos Position, owner *Player) {
+ s.AddPermanent(NewArtifact(card, s.Map.TileAt(pos), owner))
+}
+
+func (s *State) AddNewPermFromPath(cardPath string, pos Position, owner *Player) {
+ card := NewCard(cardPath)
+ switch card.Type {
+ case UnitType:
+ s.AddNewUnit(card, pos, owner)
+ case ArtifactType:
+ s.AddNewArtifact(card, pos, owner)
+ }
}
func (s *State) removePermanent(p Permanent) {
@@ -66,12 +193,6 @@ func (s *State) DestroyPermanent(p Permanent) {
}
}
-func (s *State) AddNewArtifact(card string, pos Position, owner *Player) {
- artifact := NewArtifact(card, s.Map.TileAt(pos), owner)
- s.Permanents = append(s.Permanents, artifact)
- s.Artifacts = append(s.Artifacts, artifact)
-}
-
func (s *State) Fight(p1, p2 Permanent) {
p1.Fight(p2)
p2.Fight(p1)
@@ -97,3 +218,23 @@ func (s *State) EnemyUnits(player *Player) []*Unit {
}
return enemyUnits
}
+
+func (s *State) ResolvePlay(p *Player, c *Card, targets interface{}) {
+ switch c.Type {
+ case UnitType:
+ s.AddNewUnit(c, targets.(Position), p)
+ }
+ p.DiscardPile.AddCard(c)
+}
+
+func (s *State) SpawnTiles(p *Player) []*Tile {
+ spawns := s.Map.FilterTiles(func(t *Tile) bool {
+ if t.Type != TileTypes.Spawn {
+ return false
+ }
+
+ return strings.HasSuffix(t.Raw, strconv.Itoa(p.Id)) || t.Raw == "player spawn"
+ })
+
+ return spawns
+}