use crate::{
cells::{CellRef, State},
rules::Rule,
search::{private::Sealed, Algorithm, Reason as TraitReason, SetCell},
world::World,
};
use typebool::Bool;
#[cfg(feature = "serde")]
use crate::{error::Error, save::ReasonSer};
#[cfg(doc)]
use crate::cells::LifeCell;
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
pub struct LifeSrc;
impl Sealed for LifeSrc {}
impl<R: Rule> Algorithm<R> for LifeSrc {
type Reason = Reason;
type ConflReason = ();
fn new() -> Self {
Self
}
#[inline]
fn confl_from_cell(_cell: CellRef<R>) -> Self::ConflReason {}
#[inline]
fn confl_from_sym(_cell: CellRef<R>, _sym: CellRef<R>) -> Self::ConflReason {}
#[inline]
fn init_front(world: World<R, Self>) -> World<R, Self> {
world
}
#[inline]
fn set_cell(
world: &mut World<R, Self>,
cell: CellRef<R>,
state: State,
reason: Self::Reason,
) -> Result<(), Self::ConflReason> {
world.set_cell_impl(cell, state, reason)
}
#[inline]
fn go(world: &mut World<R, Self>, step: &mut u64) -> bool {
world.go(step)
}
#[inline]
fn retreat(world: &mut World<R, Self>) -> bool {
world.retreat_impl()
}
#[cfg(feature = "serde")]
#[cfg_attr(any(docs_rs, github_io), doc(cfg(feature = "serde")))]
#[inline]
fn deser_reason(_world: &World<R, Self>, ser: &ReasonSer) -> Result<Self::Reason, Error> {
Ok(match *ser {
ReasonSer::Known => Reason::Known,
ReasonSer::Decide => Reason::Decide,
ReasonSer::TryAnother(n) => Reason::TryAnother(n),
_ => Reason::Deduce,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Reason {
Known,
Decide,
Deduce,
TryAnother(usize),
}
impl<R: Rule> TraitReason<R> for Reason {
const KNOWN: Self = Self::Known;
const DECIDED: Self = Self::Decide;
#[inline]
fn from_cell(_cell: CellRef<R>) -> Self {
Self::Deduce
}
#[inline]
fn from_sym(_cell: CellRef<R>) -> Self {
Self::Deduce
}
#[inline]
fn is_decided(&self) -> bool {
matches!(self, Self::Decide | Self::TryAnother(_))
}
#[cfg(feature = "serde")]
#[cfg_attr(any(docs_rs, github_io), doc(cfg(feature = "serde")))]
#[inline]
fn ser(&self) -> ReasonSer {
match self {
Self::Known => ReasonSer::Known,
Self::Decide => ReasonSer::Decide,
Self::Deduce => ReasonSer::Deduce,
Self::TryAnother(n) => ReasonSer::TryAnother(*n),
}
}
}
impl<R: Rule> World<R, LifeSrc> {
pub(crate) fn set_cell_impl(
&mut self,
cell: CellRef<R>,
state: State,
reason: Reason,
) -> Result<(), ()> {
cell.state.set(Some(state));
let mut result = Ok(());
cell.update_desc(Some(state), true);
if state == !cell.background {
self.cell_count[cell.coord.2 as usize] += 1;
if let Some(max) = self.config.max_cell_count {
if self.cell_count() > max {
result = Err(());
}
}
}
if cell.is_front && state == cell.background {
self.front_cell_count -= 1;
if self.non_empty_front && self.front_cell_count == 0 {
result = Err(());
}
}
self.set_stack.push(SetCell::new(cell, reason));
result
}
fn retreat_impl(&mut self) -> bool {
while let Some(SetCell { cell, reason }) = self.set_stack.pop() {
match reason {
Reason::Decide => {
let (state, reason) = if R::IsGen::VALUE {
let State(j) = cell.state.get().unwrap();
(
State((j + 1) % self.rule.gen()),
Reason::TryAnother(self.rule.gen() - 2),
)
} else {
(!cell.state.get().unwrap(), Reason::Deduce)
};
self.check_index = self.set_stack.len() as u32;
self.next_unknown = cell.next;
self.clear_cell(cell);
if self.set_cell_impl(cell, state, reason).is_ok() {
return true;
}
}
Reason::TryAnother(n) => {
let State(j) = cell.state.get().unwrap();
let state = State((j + 1) % self.rule.gen());
let reason = if n == 1 {
Reason::Deduce
} else {
Reason::TryAnother(n - 1)
};
self.check_index = self.set_stack.len() as u32;
self.next_unknown = cell.next;
self.clear_cell(cell);
if self.set_cell_impl(cell, state, reason).is_ok() {
return true;
}
}
Reason::Known => {
break;
}
Reason::Deduce => {
self.clear_cell(cell);
}
}
}
self.set_stack.clear();
self.check_index = 0;
self.next_unknown = None;
false
}
fn go(&mut self, step: &mut u64) -> bool {
loop {
*step += 1;
if self.proceed().is_ok() {
return true;
} else {
self.conflicts += 1;
if !self.retreat_impl() {
return false;
}
}
}
}
}