aboutsummaryrefslogtreecommitdiff
path: root/go/game/cardImplementations.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/game/cardImplementations.go')
-rw-r--r--go/game/cardImplementations.go232
1 files changed, 199 insertions, 33 deletions
diff --git a/go/game/cardImplementations.go b/go/game/cardImplementations.go
index 271c88ea..cb32ab2c 100644
--- a/go/game/cardImplementations.go
+++ b/go/game/cardImplementations.go
@@ -1,14 +1,12 @@
package game
-type farmerImplementation struct {
- cardImplementationBase
-}
+import (
+ "log"
+)
-type advisorImplementation struct {
- cardImplementationBase
-}
+type advisorImpl struct{ cardImplementationBase }
-func (impl *advisorImplementation) fullActions(u *Unit) []*FullAction {
+func (impl *advisorImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
return func(s *State) {
@@ -23,61 +21,229 @@ func (impl *advisorImplementation) fullActions(u *Unit) []*FullAction {
return []*FullAction{NewFullAction(u, resolvePrototype, "draw 1. exile 1")}
}
-type missionaryImplementation struct {
- cardImplementationBase
-}
+type missionaryImpl struct{ cardImplementationBase }
-func (impl *missionaryImplementation) fullActions(u *Unit) []*FullAction {
+func (impl *missionaryImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
target := a.Targets().sel[0].(*Unit)
return func(s *State) {
- faith, found := target.States[UnitMarks.Faith]
- if !found {
- target.States[UnitMarks.Faith] = 2
- } else {
- target.States[UnitMarks.Faith] = faith + 2
- if faith+2 > target.Card().BuyCost {
- target.controller = u.Controller()
- }
+ target.addMarks(UnitMarks.Faith, 2)
+ if target.Marks(UnitMarks.Faith) > target.Card().BuyCost {
+ target.controller = u.Controller()
}
}
}
return []*FullAction{NewFullAction(u, resolvePrototype, "put faith ...")}
}
-type swordImplementation struct {
- cardImplementationBase
-}
+type swordImpl struct{ cardImplementationBase }
-func (*swordImplementation) onPile(p Permanent) {
+func (*swordImpl) onPile(p Permanent) {
if u, ok := p.(*Unit); ok && !INVALID_ATTACK(u.Attack) {
u.Attack.attacks[0] += 1
}
}
-func (*swordImplementation) onUnpile(p Permanent) {
+func (*swordImpl) onUnpile(p Permanent) {
if u, ok := p.(*Unit); ok && !INVALID_ATTACK(u.Attack) {
u.Attack.attacks[0] -= 1
}
}
-type tidesChangeImplementation struct {
+type tidesChangeImpl struct{ cardImplementation }
+
+func (*tidesChangeImpl) onPlay(s *State, _ *Player, _ *Targets) {
+ s.Map.redistributeStoreCards(s.Rand)
+}
+
+type dejaVuImpl struct{ cardImplementation }
+
+func (*dejaVuImpl) onPlay(s *State, _ *Player, _ *Targets) {
+ for _, p := range s.Players {
+ if !p.IsKraken() {
+ p.Resource = s.Map.ResourceGain
+ }
+ }
+}
+
+type devourThePoorImpl struct{ cardImplementation }
+
+func (*devourThePoorImpl) onPlay(s *State, kraken *Player, _ *Targets) {
+ for _, u := range s.EnemyUnits(kraken) {
+ if u.Card().BuyCost < 7 {
+ s.DestroyPermanent(u)
+ }
+ }
+}
+
+type drownedSailorImpl struct{ cardImplementation }
+
+func (*drownedSailorImpl) onPile(containing Permanent) {
+ if u, ok := containing.(*Unit); ok && u.Movement.Swimming {
+ u.Attack.attacks[0] += 1
+ }
+}
+
+func (*drownedSailorImpl) onUnpile(containing Permanent) {
+ if u, ok := containing.(*Unit); ok && u.Movement.Swimming {
+ u.Attack.attacks[0] -= 1
+ }
+}
+
+func (*drownedSailorImpl) onDrop(sailor Permanent) {
+ sailor.Controller().gameState.DestroyPermanent(sailor)
+}
+
+// TODO: implement death trigger
+// TODO: implement hook for the containing permanent on pile
+type flyingDutchmenImpl struct{ cardImplementation }
+
+type frostPylonAoE struct{}
+
+func (*frostPylonAoE) onEntering(Permanent) {
+ // TODO: prevent actions and grant new full action
+}
+
+func (*frostPylonAoE) onLeaving(Permanent) {
+ // TODO: remove effect
+}
+
+type frostPylon struct {
cardImplementation
+ aoe frostPylonAoE
}
-func (*tidesChangeImplementation) onPlay(s *State, _ *Player, _ *Targets) {
- s.Map.redistributeStoreCards(s.Rand)
+func (*frostPylon) spawnTiles(s *State, kraken *Player) (spawns []*Tile) {
+ for _, u := range s.EnemyUnits(kraken) {
+ spawns = append(spawns, TilesInRange(s.Map, u, 1)...)
+ }
+ return
+}
+
+func (*frostPylon) stateBasedActions(s *State, p Permanent) {
+ if p.Marks(PermanentMarks.Crack) >= 3 {
+ s.DestroyPermanent(p)
+ }
+}
+
+func (i *frostPylon) onEntering(t *Tile) {
+ s := t.Permanent.Controller().gameState
+ for _, tile := range TilesInRange(s.Map, t.Permanent, 1) {
+ tile.addEffect(&i.aoe)
+ }
+}
+
+func (i *frostPylon) onLeaving(t *Tile) {
+ s := t.Permanent.Controller().gameState
+ for _, tile := range TilesInRange(s.Map, t.Permanent, 1) {
+ tile.removeEffect(&i.aoe)
+ }
+}
+
+type giganticHailImpl struct{ cardImplementation }
+
+func (*giganticHailImpl) onPlay(s *State, kraken *Player, _ *Targets) {
+ emptyTiles := s.Map.FreeTiles()
+ choices := len(emptyTiles)
+ for i := 0; i < 3; i++ {
+ if choices == 0 {
+ return
+ }
+
+ choice := s.Rand.Intn(choices - 1)
+ s.AddNewArtifact(NewCard("kraken/ice_berg"), emptyTiles[choice].Position, kraken)
+ emptyTiles[choice] = emptyTiles[choices-1]
+ choices--
+ }
+}
+
+type soldOutImpl struct{ cardImplementation }
+
+func (*soldOutImpl) onPlay(s *State, kraken *Player, _ *Targets) {
+ nStores := len(s.Map.Stores)
+ storePositions := make([]Position, 0, nStores)
+ for pos := range s.Map.Stores {
+ storePositions = append(storePositions, pos)
+ }
+
+ storePos := storePositions[s.Rand.Intn(nStores-1)]
+ s.Map.StoreOn(storePos).MoveInto(s.Exile)
+
+ storeTile := s.Map.TileAt(storePos)
+ storeTile.neutralize()
+}
+
+type supriseImpl struct{ cardImplementation }
+
+func (*supriseImpl) onPlay(s *State, kraken *Player, _ *Targets) {
+ // TODO: implement modification of next spawn tile
+}
+
+type tentacleSlapImpl struct{ cardImplementation }
+
+func (*tentacleSlapImpl) onPlay(s *State, kraken *Player, _ *Targets) {
+ x := 0
+ for _, p := range s.Players {
+ if p.IsKraken() {
+ continue
+ }
+
+ x += p.Hand.Size()
+ p.discardHand()
+ }
+
+ gain := 5 - x
+ if gain > 0 {
+ kraken.gainResource(gain)
+ }
+}
+
+type unholyCannonballImpl struct{ cardImplementation }
+
+func (*unholyCannonballImpl) onPlay(s *State, 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")
+ }
+
+ enemiesInRange2 := []*Unit{}
+ for _, u := range s.EnemyUnits(kraken) {
+ if u.Tile() == nil {
+ continue
+ }
+
+ if IsPositionInRange(u.Tile().Position, krakenTiles[0].Position, 2) {
+ enemiesInRange2 = append(enemiesInRange2, u)
+ break
+ }
+ }
+
+ if len(enemiesInRange2) == 0 {
+ kraken.gainResource(5)
+ } else {
+ for _, u := range enemiesInRange2 {
+ u.addMarks(UnitStates.Panic, 1)
+ }
+ }
}
func init() {
cardImplementations = map[string]cardImplementation{
- "base/advisor": &advisorImplementation{},
- "base/missionary": &missionaryImplementation{},
- "base/sword": &swordImplementation{},
-
- "misc/farmer": &farmerImplementation{},
+ "base/advisor": &advisorImpl{},
+ "base/missionary": &missionaryImpl{},
+ "base/sword": &swordImpl{},
- "kraken/tides_change!": &tidesChangeImplementation{},
+ "kraken/deja_vu!": &dejaVuImpl{},
+ "kraken/devour_the_poor!": &devourThePoorImpl{},
+ "kraken/drowned_sailor": &drownedSailorImpl{},
+ "kraken/flying_dutchmen": &flyingDutchmenImpl{},
+ "kraken/frost_pylon": &frostPylon{},
+ "kraken/gigantic_hail": &giganticHailImpl{},
+ "kraken/sold_out!": &soldOutImpl{},
+ "kraken/suprise!": &supriseImpl{},
+ "kraken/tentacle_slap": &tentacleSlapImpl{},
+ "kraken/tides_change!": &tidesChangeImpl{},
+ "kraken/unholy_cannonball": &unholyCannonballImpl{},
}
}