aboutsummaryrefslogtreecommitdiff
path: root/go/game/cardImplementations.go
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2024-12-27 12:40:19 +0100
committerFlorian Fischer <florian.fischer@muhq.space>2025-01-27 16:43:58 +0100
commit4e2ab55d345fd5e5c5d2d5bc56948611b15564d5 (patch)
treec6998ac54687c442ad0baa541edd0fbf917b1308 /go/game/cardImplementations.go
parent5aa8e7ddbc41aed55e7918e6afaec0b5c07fa510 (diff)
downloadmuhqs-game-4e2ab55d345fd5e5c5d2d5bc56948611b15564d5.tar.gz
muhqs-game-4e2ab55d345fd5e5c5d2d5bc56948611b15564d5.zip
introduce game.State interface abstraction
This allows to not use the internal game state directly from client code.
Diffstat (limited to 'go/game/cardImplementations.go')
-rw-r--r--go/game/cardImplementations.go74
1 files changed, 37 insertions, 37 deletions
diff --git a/go/game/cardImplementations.go b/go/game/cardImplementations.go
index 8213432b..9797af4c 100644
--- a/go/game/cardImplementations.go
+++ b/go/game/cardImplementations.go
@@ -65,12 +65,12 @@ type advisorImpl struct{ cardImplementationBase }
func (*advisorImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
controller := u.Controller()
controller.DrawN(1)
cards := controller.PromptHandCardSelection(0, 1)
if cards != nil {
- controller.Hand.MoveCard(cards[0], s.Exile)
+ controller.Hand.MoveCard(cards[0], s.Exile())
}
}
}
@@ -83,7 +83,7 @@ func (*missionaryImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
target := a.Target().sel[0].(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
target.adjustMarks(UnitMarks.Faith, 2)
if target.Marks(UnitMarks.Faith) > target.Card().BuyCosts.Costs(s) {
target.controller = u.Controller()
@@ -109,14 +109,14 @@ func (*greatSwordImpl) onUnpile(p Permanent) { adjustMelee(p, -2) }
type misinformationImpl struct{ cardImplementationBase }
func (*misinformationImpl) onPlay(a *PlayAction) {
- a.GameState().Exile.AddCard(a.Card)
+ a.GameState().Exile().AddCard(a.Card)
}
type pioneerImpl struct{ cardImplementationBase }
func (*pioneerImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
- return func(s *State) {
+ return func(s *LocalState) {
target := a.Target().sel[0]
if artifact, ok := target.(*Artifact); ok {
s.destroyPermanent(artifact)
@@ -138,7 +138,7 @@ type recruiterImpl struct{ cardImplementationBase }
func (*recruiterImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
t := a.Target().sel[0].(*Tile)
s.addNewUnit(NewCard("base/recruit"), t.Position, u.Controller())
}
@@ -156,7 +156,7 @@ func (*recruiterImpl) additionalSpawnsFor(p Permanent, ct CardType) []*Tile {
}
s := p.Controller().gameState
- return TilesInRange(s.Map, p, 1)
+ return TilesInRange(s.Map(), p, 1)
}
type shieldImpl struct{ cardImplementationBase }
@@ -169,7 +169,7 @@ type taxCollectorImpl struct{ cardImplementationBase }
func (*taxCollectorImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
controller := u.Controller()
controller.gainResource(2)
}
@@ -188,7 +188,7 @@ type wormtongueImpl struct{ cardImplementationBase }
func (*wormtongueImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
- return func(s *State) {
+ return func(s *LocalState) {
t := a.Target().sel[0].(*Player)
t.DiscardPile.AddCard(NewCard("base/misinformation"))
}
@@ -270,7 +270,7 @@ type mineImpl struct{ cardImplementationBase }
func (*mineImpl) onPlay(a *PlayAction) {
stolen := 0
- for _, player := range a.GameState().Players {
+ for _, player := range a.GameState().Players() {
if a.Controller() == player || !a.Controller().IsEnemy(player) {
continue
}
@@ -315,7 +315,7 @@ func (*selectImpl) onPlay(a *PlayAction) {
p.DrawN(1)
cards := p.PromptHandCardSelection(0, 1)
if cards != nil {
- p.Hand.MoveCard(cards[0], a.GameState().Exile)
+ p.Hand.MoveCard(cards[0], a.GameState().Exile())
}
}
@@ -350,7 +350,7 @@ func (*transmuteImpl) playTargets() TargetDesc {
func (*transmuteImpl) onPlay(a *PlayAction) {
storeCard := a.targets.Cur().sel[0].(*Card)
a.Controller().Store.MoveCard(storeCard, a.Controller().Hand)
- a.GameState().Exile.AddCard(a.Card)
+ a.GameState().Exile().AddCard(a.Card)
}
// ====== Nautics Set ======
@@ -358,7 +358,7 @@ func (*transmuteImpl) onPlay(a *PlayAction) {
var fishTrapAoE areaEffect = newGrantFullActionEffect("nautics/fisher",
func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
controller := u.Controller()
controller.gainResource(2)
}
@@ -370,18 +370,18 @@ type fishTrapImpl struct {
}
func (*fishTrapImpl) additionalSpawnsFor(Permanent, CardType) []*Tile { return nil }
-func (*fishTrapImpl) stateBasedActions(*State, Permanent) {}
+func (*fishTrapImpl) stateBasedActions(*LocalState, Permanent) {}
func (i *fishTrapImpl) onEntering(t *Tile) {
s := t.Permanent.Controller().gameState
- for _, tile := range TilesInRange(s.Map, t.Permanent, 1) {
+ for _, tile := range TilesInRange(s.Map(), t.Permanent, 1) {
tile.addEffect(i.aoe)
}
}
func (i *fishTrapImpl) onLeaving(t *Tile) {
s := t.Permanent.Controller().gameState
- for _, tile := range TilesInRange(s.Map, t.Permanent, 1) {
+ for _, tile := range TilesInRange(s.Map(), t.Permanent, 1) {
tile.removeEffect(i.aoe)
}
}
@@ -392,7 +392,7 @@ func (*fisherImpl) fullActions(u *Unit) []*FullAction {
s := u.Controller().gameState
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
t := a.Target().sel[0].(*Tile)
s.addNewArtifact(NewCard("nautics/fish_trap"), t.Position, u.Controller())
}
@@ -437,9 +437,9 @@ func (*tidesChangeImpl) onPlay(a *PlayAction) {
type dejaVuImpl struct{ cardImplementationBase }
func (*dejaVuImpl) onPlay(a *PlayAction) {
- for _, p := range a.GameState().Players {
+ for _, p := range a.GameState().Players() {
if !p.IsKraken() {
- p.Resource = a.GameState().Map.ResourceGain
+ p.Resource = a.GameState().Map().ResourceGain
}
}
}
@@ -460,7 +460,7 @@ type dolphinImpl struct{ cardImplementationBase }
func (*dolphinImpl) fullActions(u *Unit) []*FullAction {
s := u.Controller().gameState
resolvePrototype := func(a Action) ActionResolveFunc {
- return func(s *State) {
+ return func(s *LocalState) {
t := a.Target().sel[0].(*Unit)
// 1. +1 Attack
@@ -498,8 +498,8 @@ func (*drownedSailorImpl) onDrop(sailor Permanent) {
// TODO: implement hook for the containing permanent on pile to change AI
type flyingDutchmenImpl struct{ cardImplementationBase }
-func (*flyingDutchmenImpl) onETB(s *State, p Permanent) {
- s.addTrigger(newEnemyDeathTrigger(p, func(s *State) {
+func (*flyingDutchmenImpl) onETB(s *LocalState, p Permanent) {
+ s.addTrigger(newEnemyDeathTrigger(p, func(s *LocalState) {
sailor := NewCard("kraken/drowned_sailor")
if p.Tile().IsAvailableForCard(sailor) {
addPermanentToPile(p, NewUnit(sailor, nil, p.Controller()))
@@ -522,9 +522,9 @@ type frostPylonImpl struct {
aoe frostPylonAoE
}
-func (*frostPylonImpl) spawnTiles(s *State, kraken *Player) (spawns []*Tile) {
+func (*frostPylonImpl) spawnTiles(s *LocalState, kraken *Player) (spawns []*Tile) {
for _, u := range s.EnemyUnits(kraken) {
- candiates := TilesInRange(s.Map, u, 1)
+ candiates := TilesInRange(s.Map(), u, 1)
for _, candidate := range candiates {
if candidate.IsFree() {
spawns = append(spawns, candidate)
@@ -534,7 +534,7 @@ func (*frostPylonImpl) spawnTiles(s *State, kraken *Player) (spawns []*Tile) {
return
}
-func (*frostPylonImpl) stateBasedActions(s *State, p Permanent) {
+func (*frostPylonImpl) stateBasedActions(s *LocalState, p Permanent) {
if p.Marks(PermanentMarks.Crack) >= 3 {
s.destroyPermanent(p)
}
@@ -542,14 +542,14 @@ func (*frostPylonImpl) stateBasedActions(s *State, p Permanent) {
func (i *frostPylonImpl) onEntering(t *Tile) {
s := t.Permanent.Controller().gameState
- for _, tile := range TilesInRange(s.Map, t.Permanent, 1) {
+ for _, tile := range TilesInRange(s.Map(), t.Permanent, 1) {
tile.addEffect(&i.aoe)
}
}
func (i *frostPylonImpl) onLeaving(t *Tile) {
s := t.Permanent.Controller().gameState
- for _, tile := range TilesInRange(s.Map, t.Permanent, 1) {
+ for _, tile := range TilesInRange(s.Map(), t.Permanent, 1) {
tile.removeEffect(&i.aoe)
}
}
@@ -562,7 +562,7 @@ func (*giganticHailImpl) playTargets() TargetDesc { return INVALID_TARGET_DESC }
func (*giganticHailImpl) onPlay(a *PlayAction) {
s := a.GameState()
- emptyTiles := s.Map.FreeTiles()
+ emptyTiles := s.Map().FreeTiles()
choices := len(emptyTiles)
for i := 0; i < 3; i++ {
if choices == 0 {
@@ -580,16 +580,16 @@ type soldOutImpl struct{ cardImplementationBase }
func (*soldOutImpl) onPlay(a *PlayAction) {
s := a.GameState()
- nStores := len(s.Map.Stores)
+ nStores := len(s.Stores())
storePositions := make([]Position, 0, nStores)
- for pos := range s.Map.Stores {
+ for pos := range s.Map().Stores {
storePositions = append(storePositions, pos)
}
storePos := storePositions[s.Rand.Intn(nStores-1)]
- s.Map.StoreOn(storePos).MoveInto(s.Exile)
+ s.Map().StoreOn(storePos).MoveInto(s.Exile())
- storeTile := s.Map.TileAt(storePos)
+ storeTile := s.Map().TileAt(storePos)
storeTile.neutralize()
}
@@ -605,7 +605,7 @@ func (*tentacleSlapImpl) playTargets() TargetDesc { return INVALID_TARGET_DESC }
func (*tentacleSlapImpl) onPlay(a *PlayAction) {
x := 0
- for _, p := range a.GameState().Players {
+ for _, p := range a.GameState().Players() {
if p.IsKraken() {
continue
}
@@ -627,7 +627,7 @@ func (*unholyCannonballImpl) playTargets() TargetDesc { return INVALID_TARGET_DE
func (*unholyCannonballImpl) onPlay(a *PlayAction) {
s := a.GameState()
kraken := a.Controller()
- krakenTiles := s.Map.FilterTiles(func(t *Tile) bool { return t.Raw == "the kraken" })
+ 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")
}
@@ -658,7 +658,7 @@ type illusionistImpl struct{ cardImplementationBase }
func (*illusionistImpl) fullActions(u *Unit) []*FullAction {
resolvePrototype := func(a Action) ActionResolveFunc {
u := a.Source().(*Unit)
- return func(s *State) {
+ return func(s *LocalState) {
t := a.Target().sel[0].(*Tile)
s.addNewUnit(NewCard("exp1/illusion"), t.Position, u.Controller())
}
@@ -672,8 +672,8 @@ func (*illusionistImpl) fullActions(u *Unit) []*FullAction {
type illusionImpl struct{ cardImplementationBase }
-func (*illusionImpl) onETB(s *State, p Permanent) {
- s.addTrigger(newTargetedTrigger(p, true, func(s *State) {
+func (*illusionImpl) onETB(s *LocalState, p Permanent) {
+ s.addTrigger(newTargetedTrigger(p, true, func(s *LocalState) {
s.destroyPermanent(p)
}, p.Card().getEffects()[0]))
}