diff options
Diffstat (limited to 'go/game/cardImplementations.go')
| -rw-r--r-- | go/game/cardImplementations.go | 232 |
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{}, } } |
