card.gno
2.38 Kb · 86 lines
1// Package engine holds the duel rules. The same source compiles as Go and as Gno, so it
2// stays inside the Go 1.17 subset: no generics, no min or max builtins, no range over
3// an integer, no maps and no imports.
4package engine
5
6const beatsPerRound = 3
7
8// Tier orders effects inside a phase.
9type Tier int
10
11const (
12 Quick Tier = iota
13 Normal
14 Slow
15)
16
17type EffectKind int
18
19const (
20 GainBlock EffectKind = iota
21 GainCounter
22 Hit // deal N damage
23 HitBlock // deal damage equal to your Block
24 ApplyVulnerable
25 GainStrength
26 VulnerableIfCancelled // apply N Vulnerable if this card cancelled a card this beat
27 MoveVulnerable // Block phase: move all your Vulnerable to the opponent
28 GainVulnerable // gain N Vulnerable yourself
29 HitPerVulnerable // deal N damage, and N more for each Vulnerable on you
30 BlockPerVulnerable // Block phase: gain N Block, and N more for each Vulnerable on you
31 StripBlock // the opponent loses all Block at the end of the step
32 HitHardest // deal the HP the hardest opponent hit took from you this round, up to N
33 HitIfNotAttacked // deal N damage if no opponent attack lands this beat
34)
35
36type Effect struct {
37 Kind EffectKind
38 N int
39}
40
41// CardID indexes Ruleset.Cards.
42type CardID int
43
44type Card struct {
45 Name string
46 Cost int
47 Tier Tier
48 Special bool // spent once played; basics are not
49 Rare bool // the clan's signature card; a deck holds exactly one
50 Interrupt bool
51 Parry int // Parry N: attacks it cancels while active; 0 for no Parry
52 Block []Effect // Block phase
53 Damage []Effect // Damage phase, in printed order
54 OnCancel []Effect // Block phase of the beat the card is cancelled on
55 // CancelDamage resolves in the card's tier, in the Damage phase of the beat it is
56 // cancelled on.
57 CancelDamage []Effect
58}
59
60// Attack reports whether the card's text deals damage, including when it is cancelled.
61func (c *Card) Attack() bool {
62 return dealsDamage(c.Damage) || dealsDamage(c.CancelDamage)
63}
64
65func dealsDamage(effects []Effect) bool {
66 for _, e := range effects {
67 if e.Kind.isHit() {
68 return true
69 }
70 }
71 return false
72}
73
74func (k EffectKind) isHit() bool {
75 return k == Hit || k == HitBlock || k == HitPerVulnerable || k == HitHardest || k == HitIfNotAttacked
76}
77
78// Plan is the ordered cards of one round; their costs sum to 3.
79type Plan []CardID
80
81type Side int
82
83const (
84 SideA Side = iota
85 SideB
86)