diff options
| -rw-r--r-- | data/characters.go | 16 | ||||
| -rw-r--r-- | data/cirno/cards.go | 1 | ||||
| -rw-r--r-- | data/cirno/cirno.go | 9 | ||||
| -rw-r--r-- | data/dummy/cards.go | 18 | ||||
| -rw-r--r-- | data/dummy/dummy.go | 9 | ||||
| -rw-r--r-- | data/marisa/marisa.go | 9 | ||||
| -rw-r--r-- | data/reimu/reimu.go | 9 | ||||
| -rw-r--r-- | engine/card/attack.go | 11 | ||||
| -rw-r--r-- | engine/card/card.go | 16 | ||||
| -rw-r--r-- | engine/card/damage.go | 5 | ||||
| -rw-r--r-- | engine/card/range.go | 11 | ||||
| -rw-r--r-- | engine/character/character.go | 15 | ||||
| -rw-r--r-- | engine/game/game.go | 33 | ||||
| -rw-r--r-- | engine/player/action.go | 12 | ||||
| -rw-r--r-- | engine/player/player.go | 34 | ||||
| -rw-r--r-- | engine/player/vigour.go | 52 | ||||
| -rw-r--r-- | engine/pool/pool.go | 58 | ||||
| -rw-r--r-- | engine/pool/pool_test.go | 76 | ||||
| -rw-r--r-- | go.mod | 8 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | server.go | 9 | ||||
| -rw-r--r-- | server/server.go | 11 |
22 files changed, 426 insertions, 0 deletions
diff --git a/data/characters.go b/data/characters.go new file mode 100644 index 0000000..6ad9e62 --- /dev/null +++ b/data/characters.go @@ -0,0 +1,16 @@ +package data + +import ( + "sakura/data/cirno" + "sakura/data/dummy" + "sakura/data/marisa" + "sakura/data/reimu" + "sakura/engine/character" +) + +var Characters = []*character.Character{ + marisa.Marisa, + reimu.Reimu, + cirno.Cirno, + dummy.Dummy, +} diff --git a/data/cirno/cards.go b/data/cirno/cards.go new file mode 100644 index 0000000..78c49bc --- /dev/null +++ b/data/cirno/cards.go @@ -0,0 +1 @@ +package cirno diff --git a/data/cirno/cirno.go b/data/cirno/cirno.go new file mode 100644 index 0000000..3d9bf4b --- /dev/null +++ b/data/cirno/cirno.go @@ -0,0 +1,9 @@ +package cirno + +import "sakura/engine/character" + +var Cirno = &character.Character{ + Name: "Cirno", + Cards: nil, + Ultimates: nil, +} diff --git a/data/dummy/cards.go b/data/dummy/cards.go new file mode 100644 index 0000000..04342b2 --- /dev/null +++ b/data/dummy/cards.go @@ -0,0 +1,18 @@ +package dummy + +import "sakura/engine/card" + +var Cards = []card.IsCard{ + &card.Attack{ + Card: &card.Card{ + Name: "Tap", + AllOut: true, + Text: "Attack a little", + Flavor: "", + }, + MinDistance: card.NoMinimumRange, + MaxDistance: card.NoMaximumRange, + AuraDamage: 1, + HealthDamage: 1, + }, +} diff --git a/data/dummy/dummy.go b/data/dummy/dummy.go new file mode 100644 index 0000000..aaf98e4 --- /dev/null +++ b/data/dummy/dummy.go @@ -0,0 +1,9 @@ +package dummy + +import "sakura/engine/character" + +var Dummy = &character.Character{ + Name: "Dummy", + Cards: Cards, + Ultimates: nil, +} diff --git a/data/marisa/marisa.go b/data/marisa/marisa.go new file mode 100644 index 0000000..45f6f00 --- /dev/null +++ b/data/marisa/marisa.go @@ -0,0 +1,9 @@ +package marisa + +import "sakura/engine/character" + +var Marisa = &character.Character{ + Name: "Marisa", + Cards: nil, + Ultimates: nil, +} diff --git a/data/reimu/reimu.go b/data/reimu/reimu.go new file mode 100644 index 0000000..ead2e5e --- /dev/null +++ b/data/reimu/reimu.go @@ -0,0 +1,9 @@ +package reimu + +import "sakura/engine/character" + +var Reimu = &character.Character{ + Name: "Reimu", + Cards: nil, + Ultimates: nil, +} diff --git a/engine/card/attack.go b/engine/card/attack.go new file mode 100644 index 0000000..19ad196 --- /dev/null +++ b/engine/card/attack.go @@ -0,0 +1,11 @@ +package card + +type Attack struct { + *Card + + MinDistance RangeValue + MaxDistance RangeValue + + AuraDamage DamageValue + HealthDamage DamageValue +} diff --git a/engine/card/card.go b/engine/card/card.go new file mode 100644 index 0000000..f2dce83 --- /dev/null +++ b/engine/card/card.go @@ -0,0 +1,16 @@ +package card + +type Card struct { + Name string + AllOut bool + Text string + Flavor string +} + +func (c *Card) Base() *Card { + return c +} + +type IsCard interface { + Base() *Card +} diff --git a/engine/card/damage.go b/engine/card/damage.go new file mode 100644 index 0000000..fccb073 --- /dev/null +++ b/engine/card/damage.go @@ -0,0 +1,5 @@ +package card + +type DamageValue int + +const Unselectable = DamageValue(-1) diff --git a/engine/card/range.go b/engine/card/range.go new file mode 100644 index 0000000..3c6a5c9 --- /dev/null +++ b/engine/card/range.go @@ -0,0 +1,11 @@ +package card + +type RangeValue int + +const NoMinimumRange = RangeValue(0) +const NoMaximumRange = RangeValue(10) + +type Range struct { + Min RangeValue + Max RangeValue +} diff --git a/engine/character/character.go b/engine/character/character.go new file mode 100644 index 0000000..66671ae --- /dev/null +++ b/engine/character/character.go @@ -0,0 +1,15 @@ +package character + +import ( + "sakura/engine/card" +) + +type Character struct { + Name string + Cards []card.IsCard + Ultimates []card.IsCard +} + +func (c *Character) String() string { + return c.Name +} diff --git a/engine/game/game.go b/engine/game/game.go new file mode 100644 index 0000000..7f3fa76 --- /dev/null +++ b/engine/game/game.go @@ -0,0 +1,33 @@ +package game + +import ( + "sakura/engine/player" + "sakura/engine/pool" +) + +type Game struct { + Shadow *pool.Pool + Distance *pool.Pool + Yin *player.Player + Yang *player.Player + + Must []player.PlayerAction + May []player.PlayerAction +} + +func (g *Game) propagate() { + g.Distance.OverflowsTo = g.Shadow +} + +func New() *Game { + g := &Game{ + Shadow: pool.New(0, pool.Infinite), + Distance: pool.New(0, 10), + Must: nil, + May: nil, + } + g.Yin = player.New(g) + g.Yang = player.New(g) + g.propagate() + return g +} diff --git a/engine/player/action.go b/engine/player/action.go new file mode 100644 index 0000000..0d8aa58 --- /dev/null +++ b/engine/player/action.go @@ -0,0 +1,12 @@ +package player + +type Action int + +const ( + _ = iota +) + +type PlayerAction struct { + Player *Player + Action Action +} diff --git a/engine/player/player.go b/engine/player/player.go new file mode 100644 index 0000000..9dece55 --- /dev/null +++ b/engine/player/player.go @@ -0,0 +1,34 @@ +package player + +import ( + "sakura/engine/card" + "sakura/engine/game" + "sakura/engine/pool" +) + +type Player struct { + Game *game.Game + Vigour *Vigour + Life *pool.Pool + Aura *pool.Pool + Flare *pool.Pool + MasterDeck []*card.Card + Ultimates []*card.Card +} + +func (p *Player) propagate(g *game.Game) { + p.Game = g + p.Aura.SubtractsTo = g.Shadow + p.Flare.SubtractsTo = g.Shadow + p.Life.SubtractsTo = p.Flare +} + +func New(g *game.Game) *Player { + p := &Player{ + Life: pool.New(pool.Empty, 10), + Aura: pool.New(3, 5), + Flare: pool.New(pool.Empty, pool.Infinite), + } + p.propagate(g) + return p +} diff --git a/engine/player/vigour.go b/engine/player/vigour.go new file mode 100644 index 0000000..1d4022e --- /dev/null +++ b/engine/player/vigour.go @@ -0,0 +1,52 @@ +package player + +import ( + "sakura/engine/pool" +) + +type Vigour int + +type VigorAction struct { + Name string + From func(p *Player) *pool.Pool + To func(p *Player) *pool.Pool +} + +var Actions = []*VigorAction{ + { + Name: "Approach", + From: func(p *Player) *pool.Pool { + return p.Game.Distance + }, + To: func(p *Player) *pool.Pool { + return p.Aura + }, + }, + { + Name: "Retreat", + From: func(p *Player) *pool.Pool { + return p.Aura + }, + To: func(p *Player) *pool.Pool { + return p.Game.Distance + }, + }, + { + Name: "Charge", + From: func(p *Player) *pool.Pool { + return p.Aura + }, + To: func(p *Player) *pool.Pool { + return p.Flare + }, + }, + { + Name: "Recover", + From: func(p *Player) *pool.Pool { + return p.Game.Shadow + }, + To: func(p *Player) *pool.Pool { + return p.Aura + }, + }, +} diff --git a/engine/pool/pool.go b/engine/pool/pool.go new file mode 100644 index 0000000..2179a12 --- /dev/null +++ b/engine/pool/pool.go @@ -0,0 +1,58 @@ +package pool + +const Infinite = -1 +const Empty = 0 + +type Pool struct { + OverflowsTo *Pool + SubtractsTo *Pool + Max int + Value int +} + +func (p *Pool) Add(amount int) { + p.Value += amount + if p.Max == Infinite { + return + } + + if p.Value > p.Max { + overflow := p.Value - p.Max + p.Value = p.Max + p.OverflowsTo.Add(overflow) + } +} + +func (p *Pool) Subtract(amount int) { + if p.SubtractsTo != nil { + forward := amount + if forward > p.Value { + forward = p.Value + } + p.SubtractsTo.Add(forward) + } + + if p.Value == Infinite { + return + } + + p.Value -= amount + if p.Value < 0 { + p.Value = 0 + } +} + +func (p *Pool) Fits(amount int) bool { + return p.Value+amount <= p.Max +} + +func (p *Pool) Has(amount int) bool { + return p.Value >= amount +} + +func New(start, max int) *Pool { + return &Pool{ + Max: max, + Value: start, + } +} diff --git a/engine/pool/pool_test.go b/engine/pool/pool_test.go new file mode 100644 index 0000000..4dd0ea5 --- /dev/null +++ b/engine/pool/pool_test.go @@ -0,0 +1,76 @@ +package pool + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestPool_Add(t *testing.T) { + p := &Pool{ + Max: 10, + Value: 3, + } + p.Add(4) +} + +func TestPool_Add_Overflows(t *testing.T) { + shad := &Pool{ + Max: 5, + Value: 0, + } + dist := &Pool{ + OverflowsTo: shad, + Max: 5, + Value: 0, + } + dist.Add(8) + assert.Equal(t, shad.Value, 3) +} + +func TestPool_Subtract(t *testing.T) { + p := &Pool{ + Max: 10, + Value: 8, + } + p.Subtract(6) + assert.Equal(t, 2, p.Value) +} + +func TestPool_Subtract_Empties(t *testing.T) { + p := &Pool{ + Max: 10, + Value: 4, + } + p.Subtract(8) + assert.Equal(t, 0, p.Value) +} + +func TestPool_Subtract_Flows(t *testing.T) { + dest := &Pool{ + Value: 0, + Max: Infinite, + } + p := &Pool{ + SubtractsTo: dest, + Max: Infinite, + Value: 10, + } + p.Subtract(8) + assert.Equal(t, 8, dest.Value) + assert.Equal(t, 2, p.Value) +} + +func TestPool_Subtract_Flows_Empties(t *testing.T) { + dest := &Pool{ + Value: 0, + Max: Infinite, + } + p := &Pool{ + SubtractsTo: dest, + Max: Infinite, + Value: 5, + } + p.Subtract(8) + assert.Equal(t, 5, dest.Value) + assert.Equal(t, 0, p.Value) +} @@ -0,0 +1,8 @@ +module sakura + +go 1.27 + +require ( + github.com/stretchr/testify v1.12.1 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect +) @@ -0,0 +1,4 @@ +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= diff --git a/server.go b/server.go new file mode 100644 index 0000000..f8c1fe8 --- /dev/null +++ b/server.go @@ -0,0 +1,9 @@ +//go:build server + +package main + +import "sakura/server" + +func main() { + server.Start() +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..8230f87 --- /dev/null +++ b/server/server.go @@ -0,0 +1,11 @@ +package server + +import ( + "fmt" + "sakura/data" +) + +func Start() { + fmt.Println("Server started") + fmt.Printf("Characters: %v\n", data.Characters) +} |
