summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/characters.go16
-rw-r--r--data/cirno/cards.go1
-rw-r--r--data/cirno/cirno.go9
-rw-r--r--data/dummy/cards.go18
-rw-r--r--data/dummy/dummy.go9
-rw-r--r--data/marisa/marisa.go9
-rw-r--r--data/reimu/reimu.go9
-rw-r--r--engine/card/attack.go11
-rw-r--r--engine/card/card.go16
-rw-r--r--engine/card/damage.go5
-rw-r--r--engine/card/range.go11
-rw-r--r--engine/character/character.go15
-rw-r--r--engine/game/game.go33
-rw-r--r--engine/player/action.go12
-rw-r--r--engine/player/player.go34
-rw-r--r--engine/player/vigour.go52
-rw-r--r--engine/pool/pool.go58
-rw-r--r--engine/pool/pool_test.go76
-rw-r--r--go.mod8
-rw-r--r--go.sum4
-rw-r--r--server.go9
-rw-r--r--server/server.go11
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)
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..92ef75b
--- /dev/null
+++ b/go.mod
@@ -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
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..c233683
--- /dev/null
+++ b/go.sum
@@ -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)
+}