aboutsummaryrefslogtreecommitdiff
path: root/go/game/action.go
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2023-02-15 13:13:06 +0100
committerFlorian Fischer <florian.fischer@muhq.space>2025-01-27 16:43:49 +0100
commitf9ab2cfdb25eb3fcd85868a2e375326a9c8b6022 (patch)
treeb96f16e6cf4a6dcf93b9557a7219179ab2f46c8d /go/game/action.go
parent805cbf397589e5cb861f866713c2eb4bec9ce40b (diff)
downloadmuhqs-game-f9ab2cfdb25eb3fcd85868a2e375326a9c8b6022.tar.gz
muhqs-game-f9ab2cfdb25eb3fcd85868a2e375326a9c8b6022.zip
intermediate commit
* fix a lot of target and action bugs * check target selection before adding it to the prompt * use the store view for stores on the map * fix card highlighting in CardGrid * Only prompt for Upkeep-/DiscardActions if appropriate * Add helper for areaEffects granting new FullActions * Add Target() helper selecting the first target to the Action interface * Fix BuyAction and DiscardAction targets * Remember the stores a player has seen
Diffstat (limited to 'go/game/action.go')
-rw-r--r--go/game/action.go77
1 files changed, 33 insertions, 44 deletions
diff --git a/go/game/action.go b/go/game/action.go
index 65eb03b6..77e9743f 100644
--- a/go/game/action.go
+++ b/go/game/action.go
@@ -2,8 +2,6 @@ package game
import (
"fmt"
-
- "golang.org/x/exp/slices"
)
type (
@@ -15,6 +13,7 @@ type (
type Action interface {
Source() interface{}
Targets() *Targets
+ Target() *Target // Shortcut for to select the first target
CheckTargets(*State) error
PayCosts(s *State) bool
@@ -26,6 +25,7 @@ type PassPriority struct{ player *Player }
func (a *PassPriority) Source() interface{} { return a.player }
func (*PassPriority) Targets() *Targets { return nil }
+func (*PassPriority) Target() *Target { return nil }
func (*PassPriority) CheckTargets(*State) error { return nil }
func (*PassPriority) PayCosts(*State) bool { return true }
func (*PassPriority) Resolve(*State) {}
@@ -39,6 +39,7 @@ type TargetSelection struct {
func (sel *TargetSelection) Source() interface{} { return sel.player }
func (sel *TargetSelection) Targets() *Targets { return sel.targets }
+func (sel *TargetSelection) Target() *Target { return sel.targets.ts[0] }
func (sel *TargetSelection) CheckTargets(s *State) error { return sel.targets.CheckTargets(s) }
func (*TargetSelection) PayCosts(*State) bool { return true }
func (*TargetSelection) Resolve(*State) {}
@@ -50,7 +51,8 @@ func newTargetSelection(player *Player, targets *Targets) Action {
func newHandCardSelection(p *Player, min, max int) Action {
a := &TargetSelection{player: p}
- a.targets = newTargets(newTarget(p.gameState, newTargetDesc("hand card"), a))
+ targetDesc := TargetDesc{"hand card", fmt.Sprintf("%d-%d", min, max)}
+ a.targets = newTargets(newTarget(p.gameState, targetDesc, a))
return a
}
@@ -62,23 +64,15 @@ type ActionBase struct {
costFunc ActionCostFunc
}
-func (a *ActionBase) Source() interface{} {
- return a.source
-}
-
-func (a *ActionBase) Resolve(s *State) {
- a.resolveFunc(s)
-}
-
-func (a *ActionBase) PayCosts(s *State) bool {
- return a.costFunc(s)
-}
-
-func (a *ActionBase) Targets() *Targets {
- return a.targets
-}
-
+func (a *ActionBase) Source() interface{} { return a.source }
+func (a *ActionBase) Resolve(s *State) { a.resolveFunc(s) }
+func (a *ActionBase) PayCosts(s *State) bool { return a.costFunc(s) }
+func (a *ActionBase) Targets() *Targets { return a.targets }
+func (a *ActionBase) Target() *Target { return a.targets.ts[0] }
func (a *ActionBase) CheckTargets(s *State) error {
+ if a.targets == nil {
+ return nil
+ }
return a.targets.CheckTargets(s)
}
@@ -144,7 +138,7 @@ type MoveAction struct {
var moveActionTargetDesc = TargetDesc{"available tile", "1"}
func (a *MoveAction) targetTile() *Tile {
- t := a.Targets().ts[0]
+ t := a.Target()
if tile, ok := t.sel[0].(*Tile); ok {
return tile
}
@@ -203,7 +197,7 @@ func NewAttackAction(u *Unit) *AttackAction {
a.targets = newTargets(newTarget(u.Controller().gameState, attackActionTargetDesc, a))
a.resolveFunc = func(s *State) {
- s.Fight(u, a.targets.ts[0].sel[0].(Permanent))
+ s.Fight(u, a.Target().sel[0].(Permanent))
}
a.costFunc = func(*State) bool {
@@ -223,7 +217,7 @@ func (a *AttackAction) String() string {
return fmt.Sprintf("attack %v", u.Attack)
}
- target := a.targets.ts[0].sel[0].(Permanent)
+ target := a.Target().sel[0].(Permanent)
return fmt.Sprintf("%s x %v", u.FmtWController(), target.Tile().Position)
}
@@ -261,7 +255,7 @@ func NewFullAction(u *Unit, proto ActionFuncPrototype, desc string) *FullAction
func (a *FullAction) String() string {
u := a.source.(*Unit)
- if a.targets.RequireSelection() {
+ if a.targets == nil || a.targets.RequireSelection() {
return fmt.Sprintf("↻ %s", a.desc)
}
@@ -302,12 +296,12 @@ func (a *FreeAction) String() string {
return fmt.Sprintf("%v: %s free_action@%v", p.Controller(), p.Card().Name, a.targets)
}
-var buyActionTargetDesc = TargetDesc{"store card", "1"}
+var buyActionTargetDesc = TargetDesc{"store card", "?"}
type BuyAction struct{ TargetSelection }
func (a *BuyAction) card() *Card {
- return a.Targets().ts[0].sel[0].(*Card)
+ return a.Target().sel[0].(*Card)
}
func (a *BuyAction) CheckTargets(s *State) error {
@@ -333,7 +327,7 @@ func (a *BuyAction) PayCosts(*State) bool {
}
func (a *BuyAction) String() string {
- if a.Targets().RequireSelection() {
+ if !a.Targets().HasSelections() {
return fmt.Sprintf("%s buy", a.player.Name)
}
@@ -354,7 +348,7 @@ type UpkeepAction struct {
func (a *UpkeepAction) PayCosts(*State) bool {
costs := 0
- for _, t := range a.targets.ts[0].sel {
+ for _, t := range a.Target().sel {
u := t.(*Unit)
costs += u.UpkeepCost()
}
@@ -368,31 +362,26 @@ func (a *UpkeepAction) PayCosts(*State) bool {
}
func (a *UpkeepAction) Resolve(*State) {
- s := a.player.gameState
+ p := a.player
+ s := p.gameState
+ for _, i := range a.Target().sel {
+ u := i.(*Unit)
+ s.DestroyPermanent(u)
+ }
+
+ // Keep and pay for the rest
for _, u := range s.Units {
- if u.Controller() != a.player {
+ if u.Controller() != p {
continue
}
- if !slices.Contains(a.targets.ts[0].sel, interface{}(u)) {
- s.DestroyPermanent(u)
- }
+ p.Resource -= u.upkeep
+ u.onUpkeep()
}
}
func (a *UpkeepAction) String() string {
- disbanding := []*Unit{}
- for _, u := range a.player.gameState.Units {
- if u.Controller() != a.player {
- continue
- }
-
- if !slices.Contains(a.targets.ts[0].sel, interface{}(u)) {
- disbanding = append(disbanding, u)
- }
- }
-
- return fmt.Sprintf("upkeep disbanding: %v", disbanding)
+ return fmt.Sprintf("upkeep disbanding: %v", a.Target().sel)
}
func newUpkeepAction(p *Player) *UpkeepAction {