summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorEwy <ewy@ewy.one>2026-09-21 21:40:05 +0200
committerEwy <ewy@ewy.one>2026-09-21 21:40:05 +0200
commit83b2f2e9922f46fe46fd5330e6b38c66d1483ade (patch)
tree21a6a4402fe99e2afabb67f2cc0d41d0c0ea85be /engine
parent1f8364b145dbd0ff9ff7583f50aeb7498967b0f9 (diff)
(wip)
Diffstat (limited to 'engine')
-rw-r--r--engine/action.go83
-rw-r--r--engine/card.go5
-rw-r--r--engine/card/attack.go4
-rw-r--r--engine/card/range.go11
-rw-r--r--engine/game.go34
-rw-r--r--engine/play/play.go1
-rw-r--r--engine/player.go1
-rw-r--r--engine/stack.go10
-rw-r--r--engine/vigour.go43
9 files changed, 139 insertions, 53 deletions
diff --git a/engine/action.go b/engine/action.go
index 38749c7..178c4a0 100644
--- a/engine/action.go
+++ b/engine/action.go
@@ -1,12 +1,17 @@
package engine
type BaseAction struct {
- User *Player
- BaseSource IsCard
+ User *Player
+ BaseSource IsCard
+ Description string
}
-func (b *BaseAction) Actor() *Player {
- return b.User
+func (b *BaseAction) Actor(g *Game) *Player {
+ u := b.User
+ if u == nil {
+ u = g.CurrentPlayer
+ }
+ return u
}
func (b *BaseAction) Source() IsCard {
@@ -17,17 +22,13 @@ func (b *BaseAction) Then(g *Game) {
}
type Action interface {
- Actor() *Player
+ Actor(g *Game) *Player
Source() IsCard
Then(g *Game)
}
-func Interactions(a ...Action) map[InteractionID]Action {
- m := make(map[InteractionID]Action, len(a))
- for i, ac := range a {
- m[InteractionID(i)] = ac
- }
- return m
+func Interactions(a ...Action) []Action {
+ return a
}
type DamageDecision bool
@@ -46,28 +47,24 @@ type DesignateDamage struct {
func (d *DesignateDamage) Then(g *Game) {
}
-type PlayCard struct {
- *BaseAction
-}
-
-func (u *PlayCard) Then(g *Game) {
- g.Actions = Interactions(&PlayCard{}, &UseVigor{})
-}
-
-type PlayAllOutCard struct {
- *BaseAction
-}
-
-func (p *PlayAllOutCard) Then(g *Game) {
- g.Actions = Interactions(&EndTurn{})
-}
-
type ShuffleDeck struct {
*BaseAction
}
func (s *ShuffleDeck) Then(g *Game) {
- g.Actions = Interactions(&DrawCard{})
+ g.Actions = Interactions(&DrawCard{
+ BaseAction: &BaseAction{
+ Description: "Draw a card (or lose 1 life)",
+ },
+ })
+}
+
+func ShuffleDeckAction(g *Game) Action {
+ return &ShuffleDeck{
+ BaseAction: &BaseAction{
+ Description: "Pay 1 life to shuffle your deck",
+ },
+ }
}
type DrawCard struct {
@@ -75,21 +72,37 @@ type DrawCard struct {
}
func (d *DrawCard) Then(g *Game) {
- g.Actions = Interactions(&PlayCard{}, &PlayAllOutCard{}, &UseVigor{})
-}
-
-type UseVigor struct {
- *BaseAction
+ if len(g.CurrentPlayer.DrawPile) < 1 {
+ g.CurrentPlayer.Life.Subtract(1)
+ } else {
+ c := g.Yin.DrawPile.Pop()
+ g.CurrentPlayer.Hand = append(g.CurrentPlayer.Hand, c.Base())
+ }
+ g.Actions = append(VigorActions(g, g.CurrentPlayer), EndTurnAction(g))
}
-func (u *UseVigor) Then(g *Game) {
- g.Actions = Interactions(&PlayCard{}, &UseVigor{})
+func DrawCardAction(g *Game) Action {
+ return &DrawCard{
+ BaseAction: &BaseAction{
+ Description: "Draw a card (or lose 1 life)",
+ },
+ }
}
type EndTurn struct {
*BaseAction
}
+func EndTurnAction(g *Game) Action {
+ return &EndTurn{
+ BaseAction: &BaseAction{
+ User: g.CurrentPlayer,
+ BaseSource: nil,
+ Description: "End your turn",
+ },
+ }
+}
+
func (e *EndTurn) Then(g *Game) {
g.NextTurn()
}
diff --git a/engine/card.go b/engine/card.go
index 52d5a6e..3eb6a8f 100644
--- a/engine/card.go
+++ b/engine/card.go
@@ -11,6 +11,11 @@ func (c *Card) Base() *Card {
return c
}
+func (c *Card) CanPlay(g *Game) bool {
+ panic("unimplemented")
+}
+
type IsCard interface {
Base() *Card
+ CanPlay(g *Game) bool
}
diff --git a/engine/card/attack.go b/engine/card/attack.go
index d05d44a..a07cf8a 100644
--- a/engine/card/attack.go
+++ b/engine/card/attack.go
@@ -7,9 +7,7 @@ import (
type Attack struct {
*engine.Card
-
- MinDistance RangeValue
- MaxDistance RangeValue
+ *Range
AuraDamage DamageValue
LifeDamage DamageValue
diff --git a/engine/card/range.go b/engine/card/range.go
index 3c6a5c9..96c1a3d 100644
--- a/engine/card/range.go
+++ b/engine/card/range.go
@@ -6,6 +6,13 @@ const NoMinimumRange = RangeValue(0)
const NoMaximumRange = RangeValue(10)
type Range struct {
- Min RangeValue
- Max RangeValue
+ MinimumRange, MaximumRange RangeValue
+}
+
+func (r *Range) MinRange() RangeValue {return r.MinimumRange}
+func (r *Range) MaxRange() RangeValue {return r.MaximumRange}
+
+type HasRange interface {
+ MinRange() RangeValue
+ MaxRange() RangeValue
}
diff --git a/engine/game.go b/engine/game.go
index 5130864..8365869 100644
--- a/engine/game.go
+++ b/engine/game.go
@@ -4,6 +4,12 @@ import (
"sakura/engine/pool"
)
+type Turn struct {
+ Player *Player
+ ActionTaken bool
+ Actions []Action
+}
+
type Game struct {
Shadow *pool.Pool
Distance *pool.Pool
@@ -12,9 +18,11 @@ type Game struct {
Stack []IsCard
- Actions map[InteractionID]Action
+ Actions []Action
CurrentPlayer *Player
+
+ History []Turn
}
func (g *Game) propagate() {
@@ -25,7 +33,6 @@ func NewGame() *Game {
g := &Game{
Shadow: pool.New(0, pool.Infinite),
Distance: pool.New(10, 10),
- Actions: nil,
}
g.Yin = NewPlayer(g)
g.Yang = NewPlayer(g)
@@ -52,15 +59,18 @@ func (g *Game) Winner() *Player {
func (g *Game) NextTurn() {
current := g.CurrentPlayer.Opponent(g)
g.CurrentPlayer = current
- g.Actions = Interactions(&ShuffleDeck{
- &BaseAction{
- User: current,
- BaseSource: nil,
- },
- }, &DrawCard{
- &BaseAction{
- User: current,
- BaseSource: nil,
- },
+ g.History = append(g.History, Turn{
+ Player: current,
+ ActionTaken: false,
})
+ g.Actions = Interactions(ShuffleDeckAction(g),DrawCardAction(g)),
+}
+
+func (g *Game) CurrentTurn() Turn {
+ return g.History[len(g.History) - 1]
+}
+
+func (g *Game) ActionToHistory(a Action) {
+ thisTurn := g.History[len(g.History)-1]
+ thisTurn.Actions = append(thisTurn.Actions, a)
}
diff --git a/engine/play/play.go b/engine/play/play.go
index 42d9fa3..78b2c68 100644
--- a/engine/play/play.go
+++ b/engine/play/play.go
@@ -25,6 +25,7 @@ func Attack(g *engine.Game, p *engine.Player, a card.IsAttack) {
BaseAction: &engine.BaseAction{
User: p,
BaseSource: r,
+ Description: "Execute this unknown attack",
},
}
}
diff --git a/engine/player.go b/engine/player.go
index 5f1d7ca..eb7ac49 100644
--- a/engine/player.go
+++ b/engine/player.go
@@ -12,6 +12,7 @@ type Player struct {
Flare *pool.Pool
Hand Stack
MasterDeck Stack
+ DrawPile Stack
Ultimates []*Card
}
diff --git a/engine/stack.go b/engine/stack.go
index d7fc7be..8bcff6f 100644
--- a/engine/stack.go
+++ b/engine/stack.go
@@ -20,3 +20,13 @@ func (s Stack) Filter(predicate func(c IsCard) bool) Stack {
}
return res
}
+
+func (s Stack) Pop() IsCard {
+ if len(s) < 1 {
+ return nil
+ } else {
+ c := s[0]
+ s = s[1:]
+ return c
+ }
+}
diff --git a/engine/vigour.go b/engine/vigour.go
index 62ececd..24732d0 100644
--- a/engine/vigour.go
+++ b/engine/vigour.go
@@ -7,14 +7,40 @@ import (
type Vigour int
type VigorAction struct {
+ *BaseAction
Name string
From func(p *Player) *pool.Pool
To func(p *Player) *pool.Pool
}
+func (v *VigorAction) Then(g *Game) {
+ v.From(v.Actor(g)).Add(-1)
+ v.To(v.Actor(g)).Add(1)
+ v.Actor(g).Vigour -= 1
+}
+
+func (v *VigorAction) Can(p *Player) bool {
+ return p.Vigour > 0 && v.From(p).Has(1) && v.To(p).Fits(1)
+}
+
+func VigorActions(g *Game, p *Player) []Action {
+ var acs []Action
+ for _, a := range Actions {
+ if a.Can(p) {
+ acs = append(acs, a)
+ }
+ }
+ return acs
+}
+
var Actions = []*VigorAction{
{
Name: "Approach",
+ BaseAction: &BaseAction{
+ User: nil,
+ BaseSource: nil,
+ Description: "Move a sakura from Distance to Aura",
+ },
From: func(p *Player) *pool.Pool {
return p.Game.Distance
},
@@ -24,6 +50,11 @@ var Actions = []*VigorAction{
},
{
Name: "Retreat",
+ BaseAction: &BaseAction{
+ User: nil,
+ BaseSource: nil,
+ Description: "Move a sakura from Aura to Distance",
+ },
From: func(p *Player) *pool.Pool {
return p.Aura
},
@@ -33,6 +64,11 @@ var Actions = []*VigorAction{
},
{
Name: "Charge",
+ BaseAction: &BaseAction{
+ User: nil,
+ BaseSource: nil,
+ Description: "Move a sakura from your Aura to Flare",
+ },
From: func(p *Player) *pool.Pool {
return p.Aura
},
@@ -41,7 +77,12 @@ var Actions = []*VigorAction{
},
},
{
- Name: "Recover",
+ Name: "Charge",
+ BaseAction: &BaseAction{
+ User: nil,
+ BaseSource: nil,
+ Description: "Move a sakura from Aura to Flare",
+ },
From: func(p *Player) *pool.Pool {
return p.Game.Shadow
},