use brink_format::{DefinitionId, Value};
use crate::rng::StoryRng;
use crate::story::Context;
pub trait ContextAccess {
fn global(&self, idx: u32) -> &Value;
fn set_global(&mut self, idx: u32, value: Value);
fn visit_count(&self, id: DefinitionId) -> u32;
fn increment_visit(&mut self, id: DefinitionId);
fn turn_count(&self, id: DefinitionId) -> Option<u32>;
fn set_turn_count(&mut self, id: DefinitionId, turn: u32);
fn turn_index(&self) -> u32;
fn increment_turn_index(&mut self);
fn rng_seed(&self) -> i32;
fn set_rng_seed(&mut self, seed: i32);
fn previous_random(&self) -> i32;
fn set_previous_random(&mut self, val: i32);
fn next_random<R: StoryRng>(&self, seed: i32) -> i32;
fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32>;
}
impl ContextAccess for Context {
#[inline]
fn global(&self, idx: u32) -> &Value {
&self.globals[idx as usize]
}
#[inline]
fn set_global(&mut self, idx: u32, value: Value) {
self.globals[idx as usize] = value;
}
#[inline]
fn visit_count(&self, id: DefinitionId) -> u32 {
self.visit_counts.get(&id).copied().unwrap_or(0)
}
#[inline]
fn increment_visit(&mut self, id: DefinitionId) {
*self.visit_counts.entry(id).or_insert(0) += 1;
}
#[inline]
fn turn_count(&self, id: DefinitionId) -> Option<u32> {
self.turn_counts.get(&id).copied()
}
#[inline]
fn set_turn_count(&mut self, id: DefinitionId, turn: u32) {
self.turn_counts.insert(id, turn);
}
#[inline]
fn turn_index(&self) -> u32 {
self.turn_index
}
#[inline]
fn increment_turn_index(&mut self) {
self.turn_index += 1;
}
#[inline]
fn rng_seed(&self) -> i32 {
self.rng_seed
}
#[inline]
fn set_rng_seed(&mut self, seed: i32) {
self.rng_seed = seed;
}
#[inline]
fn previous_random(&self) -> i32 {
self.previous_random
}
#[inline]
fn set_previous_random(&mut self, val: i32) {
self.previous_random = val;
}
#[inline]
fn next_random<R: StoryRng>(&self, seed: i32) -> i32 {
let mut rng = R::from_seed(seed);
rng.next_int()
}
fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32> {
let mut rng = R::from_seed(seed);
(0..count).map(|_| rng.next_int()).collect()
}
}
#[expect(unused_variables)]
pub trait WriteObserver {
fn on_set_global(&mut self, idx: u32, value: &Value) {}
fn on_increment_visit(&mut self, id: DefinitionId, new_count: u32) {}
fn on_set_turn_count(&mut self, id: DefinitionId, turn: u32) {}
fn on_increment_turn_index(&mut self, new_value: u32) {}
fn on_set_rng_seed(&mut self, new_seed: i32) {}
fn on_set_previous_random(&mut self, new_val: i32) {}
}
pub struct ObservedContext<'a, 'o> {
context: &'a mut Context,
observer: &'o mut dyn WriteObserver,
}
impl<'a, 'o> ObservedContext<'a, 'o> {
pub fn new(context: &'a mut Context, observer: &'o mut dyn WriteObserver) -> Self {
Self { context, observer }
}
}
impl ContextAccess for ObservedContext<'_, '_> {
#[inline]
fn global(&self, idx: u32) -> &Value {
self.context.global(idx)
}
#[inline]
fn set_global(&mut self, idx: u32, value: Value) {
self.context.set_global(idx, value.clone());
self.observer.on_set_global(idx, &value);
}
#[inline]
fn visit_count(&self, id: DefinitionId) -> u32 {
self.context.visit_count(id)
}
#[inline]
fn increment_visit(&mut self, id: DefinitionId) {
self.context.increment_visit(id);
let new_count = self.context.visit_count(id);
self.observer.on_increment_visit(id, new_count);
}
#[inline]
fn turn_count(&self, id: DefinitionId) -> Option<u32> {
self.context.turn_count(id)
}
#[inline]
fn set_turn_count(&mut self, id: DefinitionId, turn: u32) {
self.context.set_turn_count(id, turn);
self.observer.on_set_turn_count(id, turn);
}
#[inline]
fn turn_index(&self) -> u32 {
self.context.turn_index()
}
#[inline]
fn increment_turn_index(&mut self) {
self.context.increment_turn_index();
self.observer
.on_increment_turn_index(self.context.turn_index());
}
#[inline]
fn rng_seed(&self) -> i32 {
self.context.rng_seed()
}
#[inline]
fn set_rng_seed(&mut self, seed: i32) {
self.context.set_rng_seed(seed);
self.observer.on_set_rng_seed(seed);
}
#[inline]
fn previous_random(&self) -> i32 {
self.context.previous_random()
}
#[inline]
fn set_previous_random(&mut self, val: i32) {
self.context.set_previous_random(val);
self.observer.on_set_previous_random(val);
}
#[inline]
fn next_random<R: StoryRng>(&self, seed: i32) -> i32 {
Context::next_random::<R>(seed)
}
fn random_sequence<R: StoryRng>(&self, seed: i32, count: usize) -> Vec<i32> {
Context::random_sequence::<R>(seed, count)
}
}