1use brink_format::{DefinitionId, Value};
9
10use crate::rng::StoryRng;
11use crate::story::Context;
12
13pub trait ContextAccess {
24 fn global(&self, idx: u32) -> &Value;
25 fn set_global(&mut self, idx: u32, value: Value);
26
27 fn visit_count(&self, id: DefinitionId) -> u32;
28 fn increment_visit(&mut self, id: DefinitionId);
29
30 fn turn_count(&self, id: DefinitionId) -> Option<u32>;
31 fn set_turn_count(&mut self, id: DefinitionId, turn: u32);
32
33 fn turn_index(&self) -> u32;
34 fn increment_turn_index(&mut self);
35
36 fn rng_seed(&self) -> i32;
37 fn set_rng_seed(&mut self, seed: i32);
38
39 fn previous_random(&self) -> i32;
40 fn set_previous_random(&mut self, val: i32);
41
42 fn next_random<R: StoryRng>(&self, seed: i32) -> i32;
43 fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32>;
44}
45
46impl ContextAccess for Context {
47 #[inline]
48 fn global(&self, idx: u32) -> &Value {
49 &self.globals[idx as usize]
50 }
51
52 #[inline]
53 fn set_global(&mut self, idx: u32, value: Value) {
54 self.globals[idx as usize] = value;
55 }
56
57 #[inline]
58 fn visit_count(&self, id: DefinitionId) -> u32 {
59 self.visit_counts.get(&id).copied().unwrap_or(0)
60 }
61
62 #[inline]
63 fn increment_visit(&mut self, id: DefinitionId) {
64 *self.visit_counts.entry(id).or_insert(0) += 1;
65 }
66
67 #[inline]
68 fn turn_count(&self, id: DefinitionId) -> Option<u32> {
69 self.turn_counts.get(&id).copied()
70 }
71
72 #[inline]
73 fn set_turn_count(&mut self, id: DefinitionId, turn: u32) {
74 self.turn_counts.insert(id, turn);
75 }
76
77 #[inline]
78 fn turn_index(&self) -> u32 {
79 self.turn_index
80 }
81
82 #[inline]
83 fn increment_turn_index(&mut self) {
84 self.turn_index += 1;
85 }
86
87 #[inline]
88 fn rng_seed(&self) -> i32 {
89 self.rng_seed
90 }
91
92 #[inline]
93 fn set_rng_seed(&mut self, seed: i32) {
94 self.rng_seed = seed;
95 }
96
97 #[inline]
98 fn previous_random(&self) -> i32 {
99 self.previous_random
100 }
101
102 #[inline]
103 fn set_previous_random(&mut self, val: i32) {
104 self.previous_random = val;
105 }
106
107 #[inline]
108 fn next_random<R: StoryRng>(&self, seed: i32) -> i32 {
109 let mut rng = R::from_seed(seed);
110 rng.next_int()
111 }
112
113 fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32> {
114 let mut rng = R::from_seed(seed);
115 (0..count).map(|_| rng.next_int()).collect()
116 }
117}
118
119#[expect(unused_variables)]
127pub trait WriteObserver {
128 fn on_set_global(&mut self, idx: u32, value: &Value) {}
129 fn on_increment_visit(&mut self, id: DefinitionId, new_count: u32) {}
130 fn on_set_turn_count(&mut self, id: DefinitionId, turn: u32) {}
131 fn on_increment_turn_index(&mut self, new_value: u32) {}
132 fn on_set_rng_seed(&mut self, new_seed: i32) {}
133 fn on_set_previous_random(&mut self, new_val: i32) {}
134}
135
136pub struct ObservedContext<'a, 'o> {
141 context: &'a mut Context,
142 observer: &'o mut dyn WriteObserver,
143}
144
145impl<'a, 'o> ObservedContext<'a, 'o> {
146 pub fn new(context: &'a mut Context, observer: &'o mut dyn WriteObserver) -> Self {
147 Self { context, observer }
148 }
149}
150
151impl ContextAccess for ObservedContext<'_, '_> {
152 #[inline]
153 fn global(&self, idx: u32) -> &Value {
154 self.context.global(idx)
155 }
156
157 #[inline]
158 fn set_global(&mut self, idx: u32, value: Value) {
159 self.context.set_global(idx, value.clone());
160 self.observer.on_set_global(idx, &value);
161 }
162
163 #[inline]
164 fn visit_count(&self, id: DefinitionId) -> u32 {
165 self.context.visit_count(id)
166 }
167
168 #[inline]
169 fn increment_visit(&mut self, id: DefinitionId) {
170 self.context.increment_visit(id);
171 let new_count = self.context.visit_count(id);
172 self.observer.on_increment_visit(id, new_count);
173 }
174
175 #[inline]
176 fn turn_count(&self, id: DefinitionId) -> Option<u32> {
177 self.context.turn_count(id)
178 }
179
180 #[inline]
181 fn set_turn_count(&mut self, id: DefinitionId, turn: u32) {
182 self.context.set_turn_count(id, turn);
183 self.observer.on_set_turn_count(id, turn);
184 }
185
186 #[inline]
187 fn turn_index(&self) -> u32 {
188 self.context.turn_index()
189 }
190
191 #[inline]
192 fn increment_turn_index(&mut self) {
193 self.context.increment_turn_index();
194 self.observer
195 .on_increment_turn_index(self.context.turn_index());
196 }
197
198 #[inline]
199 fn rng_seed(&self) -> i32 {
200 self.context.rng_seed()
201 }
202
203 #[inline]
204 fn set_rng_seed(&mut self, seed: i32) {
205 self.context.set_rng_seed(seed);
206 self.observer.on_set_rng_seed(seed);
207 }
208
209 #[inline]
210 fn previous_random(&self) -> i32 {
211 self.context.previous_random()
212 }
213
214 #[inline]
215 fn set_previous_random(&mut self, val: i32) {
216 self.context.set_previous_random(val);
217 self.observer.on_set_previous_random(val);
218 }
219
220 #[inline]
221 fn next_random<R: StoryRng>(&self, seed: i32) -> i32 {
222 Context::next_random::<R>(seed)
223 }
224
225 fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32> {
226 Context::random_sequence::<R>(seed, count)
227 }
228}