trace.gno
3.08 Kb · 92 lines
1package engine
2
3// Vitals is one gnome's numbers during a round.
4type Vitals struct {
5 HP, Block, Counter, Vulnerable, Strength int
6}
7
8// Phase is the part of a beat an event belongs to.
9type Phase int
10
11const (
12 InterruptPhase Phase = iota
13 BlockPhase
14 DamagePhase
15)
16
17type EventKind int
18
19const (
20 Cancelled EventKind = iota // Card was cancelled by the opponent's Interrupt or Parry
21 ParryEnded // Card made its last Parry cancel; its later beats stay empty
22 BlockGained // Side gained N Block from Card
23 CounterGained // Side gained Counter N from Card
24 HitLanded // Card hit the opponent for N damage to HP, Blocked absorbed
25 CounterHit // the opponent's Counter dealt N to Side's HP after Card hit
26 VulnerableApplied // Card applied N Vulnerable to the opponent
27 StrengthGained // Side gained N Strength from Card
28 VulnerableMoved // Card moved Side's N Vulnerable to the opponent, who keeps up to the cap
29 VulnerableGained // Side gained N Vulnerable from Card
30 BlockStripped // Card took the opponent's N Block
31)
32
33// Event is one effect of a round's resolution. Side owns Card. A HitLanded, a
34// VulnerableApplied or a BlockStripped lands on the other gnome, a VulnerableMoved changes
35// both, and every other kind changes Side's own Vitals. N is the change after caps, the damage that
36// reached HP, or the tokens that left the mover.
37type Event struct {
38 Beat int // 1 to 3
39 Phase Phase
40 Tier Tier
41 Step int // from 1 within a beat, phase and tier; equal for effects that resolve together
42 Kind EventKind
43 Side Side
44 Card CardID
45 N int
46 Blocked int // HitLanded and CounterHit: damage absorbed by Block
47 Doubled bool // HitLanded: the defender's Vulnerable doubled it
48 After [2]Vitals // both gnomes once the whole step has resolved
49}
50
51// Trace resolves the round as Resolve does and also returns its events in order.
52func (rs *Ruleset) Trace(s State, a, b Plan) (Outcome, []Event) {
53 var events []Event
54 o := rs.resolve(s, a, b, &events)
55 return o, events
56}
57
58// tracer appends the events of one round. A nil events pointer records nothing.
59type tracer struct {
60 events *[]Event
61 beat int
62 phase Phase
63 tier Tier
64 step int
65 first int // index of the current step's first event
66}
67
68func (t *tracer) at(beat int, phase Phase, tier Tier, step int) {
69 t.beat, t.phase, t.tier, t.step = beat, phase, tier, step
70}
71
72func (t *tracer) emit(kind EventKind, side Side, card CardID, n, blocked int, doubled bool) {
73 if t.events == nil {
74 return
75 }
76 *t.events = append(*t.events, Event{
77 Beat: t.beat, Phase: t.phase, Tier: t.tier, Step: t.step,
78 Kind: kind, Side: side, Card: card, N: n, Blocked: blocked, Doubled: doubled,
79 })
80}
81
82// close stamps the state after the step on every event emitted since the last close.
83func (t *tracer) close(f *[2]Vitals) {
84 if t.events == nil {
85 return
86 }
87 evs := *t.events
88 for i := t.first; i < len(evs); i++ {
89 evs[i].After = *f
90 }
91 t.first = len(evs)
92}