use xmrs::core::fixed::fixed::Q15;
use xmrs::core::xorshift::XorShift32;
use xmrs::prelude::Cell;
#[derive(Clone)]
pub(crate) struct StateHumanizeEkn {
last_front: Option<usize>,
rng: XorShift32,
fire_intent: Option<(u8, Cell, Option<usize>)>,
suppress_next_natural: bool,
}
impl StateHumanizeEkn {
pub fn new(seed: u32) -> Self {
Self {
last_front: None,
rng: XorShift32::new(Some(seed.max(1))),
fire_intent: None,
suppress_next_natural: false,
}
}
pub fn reseed(&mut self, seed: u32) {
self.rng = XorShift32::new(Some(seed.max(1)));
}
pub fn note_euclidian_triggered(&mut self, front_instr: usize) {
self.last_front = Some(front_instr);
}
pub fn clear_euclidian(&mut self) {
self.last_front = None;
self.fire_intent = None;
}
pub fn armed_front(&self) -> Option<usize> {
self.last_front
}
pub fn roll(&mut self, probability: Q15, advance_max_ticks: u8) -> Option<u8> {
if probability == Q15::ZERO || advance_max_ticks == 0 {
return None;
}
let r = (self.rng.next().unwrap() & 0x7FFF) as i16;
if r < probability.raw() {
let advance = 1u8 + (self.rng.next().unwrap() % advance_max_ticks as u32) as u8;
Some(advance)
} else {
None
}
}
pub fn schedule_fire(&mut self, tick_within_row: u8, cell: Cell, track_instr: Option<usize>) {
self.fire_intent = Some((tick_within_row, cell, track_instr));
self.suppress_next_natural = true;
}
pub fn take_fire_intent_at(&mut self, current_tick: u8) -> Option<(Cell, Option<usize>)> {
match &self.fire_intent {
Some((scheduled_tick, _, _)) if *scheduled_tick == current_tick => {
self.fire_intent.take().map(|(_, cell, ti)| (cell, ti))
}
_ => None,
}
}
pub fn take_suppress(&mut self) -> bool {
core::mem::replace(&mut self.suppress_next_natural, false)
}
}