diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2023-02-08 12:44:07 +0100 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-01-27 16:43:48 +0100 |
| commit | 5dae3b7e97669bc6ad5dfc61bbb1903aeb03aaf3 (patch) | |
| tree | 62ce4be85d1014d797cfadbebe38e6a11872dbf3 /go | |
| parent | bb7810a4bb0ee1a3c21de67e857ca41596646da3 (diff) | |
| download | muhqs-game-5dae3b7e97669bc6ad5dfc61bbb1903aeb03aaf3.tar.gz muhqs-game-5dae3b7e97669bc6ad5dfc61bbb1903aeb03aaf3.zip | |
intermediate commit
* detect tokens and do not add them to pile of cards
* only add spells not already in exile to their owners discard pile
* add the played card to onPlay callback
Diffstat (limited to 'go')
| -rw-r--r-- | go/game/card.go | 25 | ||||
| -rw-r--r-- | go/game/cardImplementations.go | 56 | ||||
| -rw-r--r-- | go/game/cardParsing.go | 6 | ||||
| -rw-r--r-- | go/game/pileOfCards.go | 9 | ||||
| -rw-r--r-- | go/game/state.go | 9 | ||||
| -rw-r--r-- | go/game/store.go | 11 |
6 files changed, 80 insertions, 36 deletions
diff --git a/go/game/card.go b/go/game/card.go index c1c74490..a6abffd1 100644 --- a/go/game/card.go +++ b/go/game/card.go @@ -80,7 +80,7 @@ type cardImplementation interface { onEntering(*Tile) onLeaving(*Tile) - onPlay(*State, *Player, *Targets) + onPlay(*State, *Card, *Player, *Targets) onPile(containing Permanent) onUnpile(containing Permanent) onDrop(dropped Permanent) @@ -98,12 +98,12 @@ func (*cardImplementationBase) freeActions(Permanent) []*FreeAction { return nil func (*cardImplementationBase) stateBasedActions(*State, Permanent) {} -func (*cardImplementationBase) onEntering(*Tile) {} -func (*cardImplementationBase) onLeaving(*Tile) {} -func (*cardImplementationBase) onPlay(*State, *Player, *Targets) {} -func (*cardImplementationBase) onPile(Permanent) {} -func (*cardImplementationBase) onUnpile(Permanent) {} -func (*cardImplementationBase) onDrop(Permanent) {} +func (*cardImplementationBase) onEntering(*Tile) {} +func (*cardImplementationBase) onLeaving(*Tile) {} +func (*cardImplementationBase) onPlay(*State, *Card, *Player, *Targets) {} +func (*cardImplementationBase) onPile(Permanent) {} +func (*cardImplementationBase) onUnpile(Permanent) {} +func (*cardImplementationBase) onDrop(Permanent) {} // Map of all card implementations var cardImplementations map[string]cardImplementation @@ -312,6 +312,17 @@ func (c *Card) IsPermanent() bool { c.Type == CardTypes.Potion } +func (c *Card) IsToken() bool { + if v, found := c.Values["token"]; found { + b, ok := v.(bool) + if !ok { + log.Fatalf("Invalid value for %s token value: %v", c.Name, v) + } + return b + } + return false +} + func (c *Card) IsBuyable() bool { return c.BuyCost != NOT_BUYABLE } diff --git a/go/game/cardImplementations.go b/go/game/cardImplementations.go index 63c97ca7..3a7a729a 100644 --- a/go/game/cardImplementations.go +++ b/go/game/cardImplementations.go @@ -4,6 +4,14 @@ import ( "log" ) +func adjustMelee(p Permanent, damage int) { + if u, ok := p.(*Unit); ok && !INVALID_ATTACK(u.Attack) { + u.Attack.attacks[0] += damage + } +} + +// ====== Base Set ====== + type advisorImpl struct{ cardImplementationBase } func (*advisorImpl) fullActions(u *Unit) []*FullAction { @@ -39,18 +47,22 @@ func (*missionaryImpl) fullActions(u *Unit) []*FullAction { type swordImpl struct{ cardImplementationBase } -func (*swordImpl) onPile(p Permanent) { - if u, ok := p.(*Unit); ok && !INVALID_ATTACK(u.Attack) { - u.Attack.attacks[0] += 1 - } -} +func (*swordImpl) onPile(p Permanent) { adjustMelee(p, 1) } +func (*swordImpl) onUnpile(p Permanent) { adjustMelee(p, -1) } -func (*swordImpl) onUnpile(p Permanent) { - if u, ok := p.(*Unit); ok && !INVALID_ATTACK(u.Attack) { - u.Attack.attacks[0] -= 1 - } +type greatSwordImpl struct{ cardImplementationBase } + +func (*greatSwordImpl) onPile(p Permanent) { adjustMelee(p, 2) } +func (*greatSwordImpl) onUnpile(p Permanent) { adjustMelee(p, -2) } + +type misinformationImpl struct{ cardImplementation } + +func (*misinformationImpl) onPlay(s *State, c *Card, _ *Player, _ *Targets) { + s.Exile.AddCard(c) } +// ====== Nautics Set ====== + type fishTrapAoE struct{} func (*fishTrapAoE) onEntering(p Permanent) { @@ -147,15 +159,17 @@ func (*sailorImpl) onUnpile(containing Permanent) { } } +// ====== Kraken Set ====== + type tidesChangeImpl struct{ cardImplementation } -func (*tidesChangeImpl) onPlay(s *State, _ *Player, _ *Targets) { +func (*tidesChangeImpl) onPlay(s *State, _ *Card, _ *Player, _ *Targets) { s.Map.redistributeStoreCards(s.Rand) } type dejaVuImpl struct{ cardImplementation } -func (*dejaVuImpl) onPlay(s *State, _ *Player, _ *Targets) { +func (*dejaVuImpl) onPlay(s *State, _ *Card, _ *Player, _ *Targets) { for _, p := range s.Players { if !p.IsKraken() { p.Resource = s.Map.ResourceGain @@ -165,7 +179,7 @@ func (*dejaVuImpl) onPlay(s *State, _ *Player, _ *Targets) { type devourThePoorImpl struct{ cardImplementation } -func (*devourThePoorImpl) onPlay(s *State, kraken *Player, _ *Targets) { +func (*devourThePoorImpl) onPlay(s *State, _ *Card, kraken *Player, _ *Targets) { for _, u := range s.EnemyUnits(kraken) { if u.Card().BuyCost < 7 { s.DestroyPermanent(u) @@ -233,7 +247,7 @@ func (i *frostPylonImpl) onLeaving(t *Tile) { type giganticHailImpl struct{ cardImplementation } -func (*giganticHailImpl) onPlay(s *State, kraken *Player, _ *Targets) { +func (*giganticHailImpl) onPlay(s *State, _ *Card, kraken *Player, _ *Targets) { emptyTiles := s.Map.FreeTiles() choices := len(emptyTiles) for i := 0; i < 3; i++ { @@ -250,7 +264,7 @@ func (*giganticHailImpl) onPlay(s *State, kraken *Player, _ *Targets) { type soldOutImpl struct{ cardImplementation } -func (*soldOutImpl) onPlay(s *State, kraken *Player, _ *Targets) { +func (*soldOutImpl) onPlay(s *State, _ *Card, kraken *Player, _ *Targets) { nStores := len(s.Map.Stores) storePositions := make([]Position, 0, nStores) for pos := range s.Map.Stores { @@ -266,13 +280,13 @@ func (*soldOutImpl) onPlay(s *State, kraken *Player, _ *Targets) { type supriseImpl struct{ cardImplementation } -func (*supriseImpl) onPlay(s *State, kraken *Player, _ *Targets) { +func (*supriseImpl) onPlay(s *State, _ *Card, kraken *Player, _ *Targets) { kraken.Ctrl.(*KrakenControl).activeSuprise = true } type tentacleSlapImpl struct{ cardImplementation } -func (*tentacleSlapImpl) onPlay(s *State, kraken *Player, _ *Targets) { +func (*tentacleSlapImpl) onPlay(s *State, _ *Card, kraken *Player, _ *Targets) { x := 0 for _, p := range s.Players { if p.IsKraken() { @@ -291,7 +305,7 @@ func (*tentacleSlapImpl) onPlay(s *State, kraken *Player, _ *Targets) { type unholyCannonballImpl struct{ cardImplementation } -func (*unholyCannonballImpl) onPlay(s *State, kraken *Player, _ *Targets) { +func (*unholyCannonballImpl) onPlay(s *State, _ *Card, kraken *Player, _ *Targets) { krakenTiles := s.Map.FilterTiles(func(t *Tile) bool { return t.Raw == "the kraken" }) if len(krakenTiles) != 1 { log.Fatal("No kraken tile found in Map") @@ -320,9 +334,11 @@ func (*unholyCannonballImpl) onPlay(s *State, kraken *Player, _ *Targets) { func init() { cardImplementations = map[string]cardImplementation{ - "base/advisor": &advisorImpl{}, - "base/missionary": &missionaryImpl{}, - "base/sword": &swordImpl{}, + "base/advisor": &advisorImpl{}, + "base/missionary": &missionaryImpl{}, + "base/sword": &swordImpl{}, + "base/greatsword": &greatSwordImpl{}, + "base/misinformation": &misinformationImpl{}, "nautics/captain": &captainImpl{}, "nautics/fish_trap": &fishTrapImpl{}, diff --git a/go/game/cardParsing.go b/go/game/cardParsing.go index de1c7be4..315de293 100644 --- a/go/game/cardParsing.go +++ b/go/game/cardParsing.go @@ -16,7 +16,7 @@ type dynamicCardImplementation struct { _stateBasedActions func(*State, Permanent) _onEntering func(*Tile) _onLeaving func(*Tile) - _onPlay func(*State, *Player, *Targets) + _onPlay func(*State, *Card, *Player, *Targets) _onPile func(Permanent) _onUnpile func(Permanent) _onDrop func(Permanent) @@ -61,9 +61,9 @@ func (impl *dynamicCardImplementation) onLeaving(t *Tile) { } } -func (impl *dynamicCardImplementation) onPlay(s *State, p *Player, t *Targets) { +func (impl *dynamicCardImplementation) onPlay(s *State, c *Card, p *Player, t *Targets) { if impl._onPlay != nil { - impl._onPlay(s, p, t) + impl._onPlay(s, c, p, t) } } diff --git a/go/game/pileOfCards.go b/go/game/pileOfCards.go index 427bba47..0a5eaa97 100644 --- a/go/game/pileOfCards.go +++ b/go/game/pileOfCards.go @@ -41,11 +41,16 @@ func (poc *PileOfCardsBase) Cards() []*Card { } func (poc *PileOfCardsBase) AddCards(cards []*Card) { - poc.cards = append(poc.cards, cards...) + for _, card := range cards { + poc.AddCard(card) + } } func (poc *PileOfCardsBase) AddCard(card *Card) { - poc.cards = append(poc.cards, card) + // Tokens can not be part of any pile of cards + if !card.IsToken() { + poc.cards = append(poc.cards, card) + } } func (poc *PileOfCardsBase) RemoveCard(card *Card) { diff --git a/go/game/state.go b/go/game/state.go index 5a4714f7..7a54ddc0 100644 --- a/go/game/state.go +++ b/go/game/state.go @@ -392,14 +392,15 @@ func (s *State) resolvePlay(p *Player, c *Card, targets *Targets) { s.addNewEquipment(c, tile.Position, p) } case CardTypes.Spell: - c.Impl.onPlay(s, p, targets) + c.Impl.onPlay(s, c, p, targets) default: log.Printf("Resolving unhandled card type: %s\n", c.Type.String()) } - if c.IsPermanent() { - } else { - p.DiscardPile.AddCard(c) + if c.Type == CardTypes.Spell { + if !s.Exile.Contains(c) { + p.DiscardPile.AddCard(c) + } } } diff --git a/go/game/store.go b/go/game/store.go index 46c136e0..73153980 100644 --- a/go/game/store.go +++ b/go/game/store.go @@ -1,5 +1,9 @@ package game +import ( + "log" +) + type Store struct { PileOfCardsBase } @@ -8,3 +12,10 @@ func NewStore() *Store { s := &Store{PileOfCardsBase{[]*Card{}}} return s } + +func (s *Store) AddCard(card *Card) { + if !card.IsBuyable() { + log.Fatalf("Non buyable card %s can not be added to a store", card.Name) + } + s.PileOfCardsBase.AddCard(card) +} |
