diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2023-02-20 21:13:47 +0100 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-01-27 16:43:51 +0100 |
| commit | 74ae4f091755544906bb2bb38bd360cc4d7b6237 (patch) | |
| tree | 01dc6ae303daaa671edbc2223091a5ffb64e6f1e /go | |
| parent | 14f7b0274a20ffc8189d18de5031defcc15e9890 (diff) | |
| download | muhqs-game-74ae4f091755544906bb2bb38bd360cc4d7b6237.tar.gz muhqs-game-74ae4f091755544906bb2bb38bd360cc4d7b6237.zip | |
implement equip action
Diffstat (limited to 'go')
| -rw-r--r-- | go/TODO | 1 | ||||
| -rw-r--r-- | go/client/game.go | 53 | ||||
| -rw-r--r-- | go/game/action.go | 63 | ||||
| -rw-r--r-- | go/game/cardImplementations.go | 16 | ||||
| -rw-r--r-- | go/game/unit.go | 27 |
5 files changed, 142 insertions, 18 deletions
@@ -4,7 +4,6 @@ * implement artifcat action * move * implement equipment actions - * equip * drop * implement target disjunction * implement Pile UI hint diff --git a/go/client/game.go b/go/client/game.go index 5ae2fbe8..f4e0f817 100644 --- a/go/client/game.go +++ b/go/client/game.go @@ -10,6 +10,7 @@ import ( "muhq.space/muhqs-game/go/game" "muhq.space/muhqs-game/go/ui" + "muhq.space/muhqs-game/go/utils" ) const ( @@ -214,14 +215,48 @@ func (g *Game) addPermActionChoice(perm game.Permanent, x, y int) { p := perms[c.GetChoosen(x, y)] g.addActionChoice(p, x, y) } - g.choice = ui.NewPermChoice(x, y, perms, onClick) - g.AddWidget(g.choice) + g.addChoice(ui.NewPermChoice(x, y, perms, onClick)) } else { g.selectedObject = perms[0] g.addActionChoice(perms[0], x, y) } } +func (g *Game) declareOrPromptTargets(a game.Action) { + if a.Targets() != nil && a.Targets().RequireSelection() { + g.addPrompt(a, fmt.Sprintf("Select targets for %v", a)) + } else { + g.declareAction(a) + } +} + +func (g *Game) addActionCostChoice(a game.Action, x, y int) { + u := a.Source().(*game.Unit) + if u.AvailMoveActions > 0 && u.AvailAttackActions == 0 { + game.UseMoveAction(a) + } else if u.AvailAttackActions > 0 && u.AvailMoveActions == 0 { + game.UseAttackAction(a) + } + + if !a.NeedsActionCostChoice() { + g.declareOrPromptTargets(a) + return + } + + choices := []string{"move", "attack"} + onClick := func(c *ui.Choice, x, y int) { + g.removeChoice() + switch choices[c.GetChoosen(x, y)] { + case "move": + game.UseMoveAction(a) + case "attack": + game.UseAttackAction(a) + } + g.declareOrPromptTargets(a) + } + g.addChoice(ui.NewChoice(x, y, utils.TypedSliceToInterfaceSlice(choices), onClick)) +} + func (g *Game) addActionChoice(perm game.Permanent, x, y int) { actions := perm.CurrentlyAvailActions() if len(actions) > 0 { @@ -229,17 +264,21 @@ func (g *Game) addActionChoice(perm game.Permanent, x, y int) { onClick := func(c *ui.Choice, x, y int) { g.removeChoice() a := actions[c.GetChoosen(x, y)] - if a.Targets() != nil && a.Targets().RequireSelection() { - g.addPrompt(a, fmt.Sprintf("Select targets for %v", a)) + if a.NeedsActionCostChoice() { + g.addActionCostChoice(a, x, y) } else { - g.declareAction(a) + g.declareOrPromptTargets(a) } } - g.choice = ui.NewActionChoice(x, y, actions, onClick) - g.AddWidget(g.choice) + g.addChoice(ui.NewActionChoice(x, y, actions, onClick)) } } +func (g *Game) addChoice(choice *ui.Choice) { + g.choice = choice + g.AddWidget(choice) +} + func (g *Game) removeChoice() { g.RemoveWidget(g.choice) g.choice = nil diff --git a/go/game/action.go b/go/game/action.go index f00c21cd..b8bc8d6e 100644 --- a/go/game/action.go +++ b/go/game/action.go @@ -15,6 +15,7 @@ type Action interface { Targets() *Targets Target() *Target // Shortcut for to select the first target + NeedsActionCostChoice() bool CheckTargets(*State) error PayCosts(s *State) bool resolve(s *State) @@ -23,14 +24,15 @@ type Action interface { 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) {} -func (*PassPriority) String() string { return "pass" } -func NewPassPriority(p *Player) Action { return &PassPriority{p} } +func (a *PassPriority) Source() interface{} { return a.player } +func (*PassPriority) Targets() *Targets { return nil } +func (*PassPriority) Target() *Target { return nil } +func (*PassPriority) NeedsActionCostChoice() bool { return false } +func (*PassPriority) CheckTargets(*State) error { return nil } +func (*PassPriority) PayCosts(*State) bool { return true } +func (*PassPriority) resolve(*State) {} +func (*PassPriority) String() string { return "pass" } +func NewPassPriority(p *Player) Action { return &PassPriority{p} } type TargetSelection struct { player *Player @@ -40,6 +42,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 (*TargetSelection) NeedsActionCostChoice() bool { return false } func (sel *TargetSelection) CheckTargets(s *State) error { return sel.targets.CheckTargets(s) } func (*TargetSelection) PayCosts(*State) bool { return true } func (*TargetSelection) resolve(*State) {} @@ -206,6 +209,32 @@ func genFullActionCost(u *Unit) ActionCostFunc { } } +type EquipAction struct { + ActionBase + equipment *Equipment +} + +func NewEquipAction(u *Unit, e *Equipment) *EquipAction { + a := &EquipAction{ + ActionBase{ + source: u, + Card: u.Card(), + }, + e, + } + + a.resolveFunc = func(s *State) { + u.equip(e) + } + + return a +} + +func (a *EquipAction) String() string { + u := a.source.(*Unit) + return fmt.Sprintf("%s equip %v", u.FmtWController(), a.equipment) +} + type AttackAction struct { ActionBase } @@ -428,3 +457,21 @@ func newUpkeepAction(p *Player) *UpkeepAction { return a } + +func (a *ActionBase) NeedsActionCostChoice() bool { + return a.costFunc == nil +} + +func UseMoveAction(a Action) { + switch a := a.(type) { + case *EquipAction: + a.costFunc = genMoveActionCost(a.Source().(*Unit)) + } +} + +func UseAttackAction(a Action) { + switch a := a.(type) { + case *EquipAction: + a.costFunc = genAttackActionCost(a.Source().(*Unit)) + } +} diff --git a/go/game/cardImplementations.go b/go/game/cardImplementations.go index 7055fe03..67b52315 100644 --- a/go/game/cardImplementations.go +++ b/go/game/cardImplementations.go @@ -5,8 +5,20 @@ import ( ) func adjustMelee(p Permanent, damage int) { - if u, ok := p.(*Unit); ok && !INVALID_ATTACK(u.Attack) { - u.Attack.attacks[0] += damage + log.Println("adjusting melee") + u, ok := p.(*Unit) + if !ok { + return + } + + if INVALID_ATTACK(u.Attack) { + u.Attack.attacks = append(u.Attack.attacks, 1) + } else { + if u.Attack.attacks[0]+damage == 0 { + u.Attack.attacks = nil + } else { + u.Attack.attacks[0] += damage + } } } diff --git a/go/game/unit.go b/go/game/unit.go index 5b071d7b..99c7c28d 100644 --- a/go/game/unit.go +++ b/go/game/unit.go @@ -200,6 +200,24 @@ func (u *Unit) AvailSlowActions() (actions []Action) { } } + if u.AvailAttackActions > 0 || u.AvailMoveActions > 0 { + for _, tile := range TilesInRange(m, u, 1) { + if tile.Permanent == nil { + continue + } + + if equipment, ok := tile.Permanent.(*Equipment); ok { + actions = append(actions, NewEquipAction(u, equipment)) + } + + for _, perm := range tile.Permanent.Pile() { + if equipment, ok := perm.(*Equipment); ok { + actions = append(actions, NewEquipAction(u, equipment)) + } + } + } + } + return actions } @@ -278,3 +296,12 @@ func (u *Unit) addDamage(damage int) { u.permanentBase.addDamage(damage) } + +func (u *Unit) equip(e *Equipment) { + if e.containingPerm != nil { + removePermanentFromPile(e.containingPerm, e) + } else { + leaveTile(e) + } + addPermanentToPile(u, e) +} |
