1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use std::fmt::Debug;
use compute::{Population, Redis, Updates};
use rustc_serialize::{Decodable, Encodable};

/// The state that represents an `Agent`.
pub trait State: Decodable + Encodable + Debug + Send + Sync + Clone + PartialEq {}
impl<T> State for T where T: Decodable + Encodable + Debug + Send + Sync + Clone + PartialEq {}

/// An message that agents can queue for themselves or for others.
pub trait Update
    : Decodable + Encodable + Debug + Send + Sync + Clone + PartialEq {
}
impl<T> Update for T where T: Decodable + Encodable + Debug + Send + Sync + Clone + PartialEq {}

/// Struct containing a unique id and a state.
#[derive(RustcDecodable, RustcEncodable, Debug, PartialEq, Clone)]
pub struct Agent<S: State> {
    pub id: u64,
    pub state: S,
}

/// This trait's implementation defines the main logic of a simulation.
///
/// A single simulation step consists of two synchronized phases:
///
/// 1. `decide`: this is a _read-only_ phase where agents decide on what _updates_ to apply. The
///    updates themselves are _not_ applied in this phase.
/// 2. `update`: this is a phase where agents consider queued updates and compute a new state
///    accordingly.
pub trait Simulation: Sized + Send + Sync + Clone {
    type State: State;
    type World: State;
    type Update: Update;

    /// Called whenever a new agent is spawned.
    /// You can use this to, for example, build an index of agents by state values.
    fn on_spawns<R: Redis>(&self,
                           agents: Vec<Agent<Self::State>>,
                           population: &Population<Self, R>)
                           -> () {
    }

    /// Called whenever an agent is killed.
    /// You can use this to, for example, remove an agent from an index.
    fn on_deaths<R: Redis>(&self,
                           agents: Vec<Agent<Self::State>>,
                           population: &Population<Self, R>)
                           -> () {
    }

    /// Computes updates for the specified agents and/or other agents.
    fn decide<R: Redis>(&self,
                        agent: &Agent<Self::State>,
                        world: &Self::World,
                        population: &Population<Self, R>,
                        updates: &mut Updates<Self>)
                        -> ();

    /// Compute a final updated state given a starting state and updates.
    ///
    /// If there is some update you want to do every step, things will run faster if you implement it here directly rather than using an `Update`.
    fn update(&self, state: &mut Self::State, updates: Vec<Self::Update>) -> bool;

    /// Compute updates for the world.
    fn world_decide<R: Redis>(&self,
                              world: &Self::World,
                              population: &Population<Self, R>,
                              updates: &mut Updates<Self>)
                              -> () {
    }

    /// Compute a final state for the world given updates.
    fn world_update(&self, world: Self::World, updates: Vec<Self::Update>) -> Self::World {
        world
    }
}