rlifesrc_lib/
save.rs

1//! Saves the world.
2
3use crate::{
4    cells::{Coord, State},
5    config::Config,
6    error::Error,
7    poly_world::PolyWorld,
8    rules::Rule,
9    search::{Algorithm, SetCell},
10    world::World,
11};
12use serde::{Deserialize, Serialize};
13use std::time::Duration;
14
15use std::collections::BTreeMap;
16
17/// A representation of reasons for setting a cell which can be easily serialized.
18#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub enum ReasonSer {
20    /// Known before the search starts,
21    Known,
22
23    /// Decides the state of a cell by choice.
24    Decide,
25
26    /// Deduced from the rule when constitifying another cell.
27    Rule(Coord),
28
29    /// Deduced from symmetry.
30    Sym(Coord),
31
32    /// Deduced from conflicts.
33    Deduce,
34
35    /// Deduced from a learnt clause.
36    Clause(Vec<Coord>),
37
38    /// Tries another state of a cell when the original state
39    /// leads to a conflict.
40    ///
41    /// Remembers the number of remaining states to try.
42    ///
43    /// Only used in Generations rules.
44    TryAnother(usize),
45}
46
47/// A representation of setting a cell which can be easily serialized.
48#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub struct SetCellSer {
50    /// The coordinates of the set cell.
51    pub(crate) coord: Coord,
52
53    /// The state.
54    pub(crate) state: State,
55
56    /// The reason for setting a cell.
57    pub(crate) reason: ReasonSer,
58}
59
60/// A representation of the world which can be easily serialized.
61#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
62#[serde(default)]
63pub struct WorldSer {
64    /// World configuration.
65    pub config: Config,
66
67    /// Number of conflicts during the search.
68    pub conflicts: u64,
69
70    /// A stack to records the cells whose values are set during the search.
71    ///
72    /// The cells in this table always have known states.
73    pub set_stack: Vec<SetCellSer>,
74
75    /// The position of the next cell to be examined in the [`set_stack`](#structfield.set_stack).
76    ///
77    /// Be careful when modifying this value.
78    /// If you have changed other things in the saved file, please set this value to `0`,
79    /// otherwise rlifesrc might gives the wrong result.
80    pub check_index: u32,
81
82    /// Time used in searching. This field is handled by the frontend.
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub timing: Option<Duration>,
85
86    /// A field for saving extra information.
87    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
88    pub extra: BTreeMap<String, String>,
89}
90
91impl WorldSer {
92    /// Restores the world from the [`WorldSer`].
93    pub fn deser<R: Rule, A: Algorithm<R>>(&self, world: &mut World<R, A>) -> Result<(), Error> {
94        for &SetCellSer {
95            coord,
96            state,
97            ref reason,
98        } in &self.set_stack
99        {
100            let cell = world.find_cell(coord).ok_or(Error::SetCellError(coord))?;
101            if let Some(old_state) = cell.state.get() {
102                if old_state != state {
103                    return Err(Error::SetCellError(coord));
104                }
105            } else if state.0 >= world.rule.gen() {
106                return Err(Error::InvalidState(coord, state));
107            } else {
108                let reason = A::deser_reason(world, reason)?;
109                let cell = cell;
110                world.set_cell(cell, state, reason).ok();
111            }
112        }
113        world.conflicts = self.conflicts;
114        if self.check_index < self.set_stack.len() as u32 {
115            world.check_index = self.check_index;
116        }
117        Ok(())
118    }
119
120    /// Restores the world from the [`WorldSer`].
121    pub fn world(&self) -> Result<PolyWorld, Error> {
122        let mut world = self.config.world()?;
123        world.deser(self)?;
124        Ok(world)
125    }
126}
127
128impl<R: Rule, A: Algorithm<R>> World<R, A> {
129    /// Saves the world as a [`WorldSer`].
130    #[inline]
131    pub fn ser(&self) -> WorldSer {
132        WorldSer {
133            config: self.config.clone(),
134            conflicts: self.conflicts,
135            set_stack: self.set_stack.iter().map(SetCell::ser).collect(),
136            check_index: self.check_index,
137            timing: None,
138            extra: BTreeMap::new(),
139        }
140    }
141
142    /// Restores the world from the [`WorldSer`].
143    #[inline]
144    pub fn deser(&mut self, ser: &WorldSer) -> Result<(), Error> {
145        ser.deser(self)
146    }
147}