use std::fmt::{self, Debug, Display, Formatter};
use std::marker::PhantomData;
use std::usize;
use uuid::Uuid;
use container::EntityContainer;
use cell::{Cell, CellState};
use entity::{Entity, EntityState, MutEntityState};
use generator::Generator;
use action::{CellAction, SelfAction, EntityAction};
#[derive(Clone)]
pub struct UniverseConf {
pub view_distance: usize,
pub size: usize,
pub iter_cells: bool,
}
impl Default for UniverseConf {
fn default() -> UniverseConf {
UniverseConf {
view_distance: 1,
size: 8000,
iter_cells: false,
}
}
}
pub struct Universe<C: CellState, E: EntityState<C>, M: MutEntityState, CA: CellAction<C>, EA: EntityAction<C, E>> {
pub conf: UniverseConf,
pub cell_mutator: fn(usize, &[Cell<C>]) -> Option<C>,
pub entity_driver: fn(
universe_index: usize,
entity: &Entity<C, E, M>,
entities: &EntityContainer<C, E, M>,
cells: &[Cell<C>],
cell_action_executor: &mut FnMut(CA, usize),
self_action_executor: &mut FnMut(SelfAction<C, E, EA>),
entity_action_executor: &mut FnMut(EA, usize, Uuid)
),
pub seq: usize,
pub cells: Vec<Cell<C>>,
pub entities: EntityContainer<C, E, M>,
pub average_actions_per_cycle: usize,
pub total_actions: usize,
pub average_unique_entities_modified_per_cycle: usize,
pub total_entity_modifications: usize,
__phantom_ca: PhantomData<CA>,
__phantom_ea: PhantomData<EA>,
}
impl<C: CellState, E: EntityState<C>, M: MutEntityState, CA: CellAction<C>, EA: EntityAction<C, E>> Universe<C, E, M, CA, EA> {
pub fn new(
conf: UniverseConf, gen: &mut Generator<C, E, M, CA, EA>,
cell_mutator: fn(usize, &[Cell<C>]) -> Option<C>,
entity_driver: fn(
universe_index: usize,
entity: &Entity<C, E, M>,
entities: &EntityContainer<C, E, M>,
cells: &[Cell<C>],
cell_action_executor: &mut FnMut(CA, usize),
self_action_executor: &mut FnMut(SelfAction<C, E, EA>),
entity_action_executor: &mut FnMut(EA, usize, Uuid)
)
) -> Universe<C, E, M, CA, EA> {
assert!(conf.size > 0);
let universe_size = conf.size;
let mut universe = Universe {
conf: conf,
cell_mutator: cell_mutator,
entity_driver: entity_driver,
seq: 0,
cells: Vec::new(),
entities: EntityContainer::new(universe_size),
average_actions_per_cycle: 0,
total_actions: 0,
average_unique_entities_modified_per_cycle: 0,
total_entity_modifications: 0,
__phantom_ca: PhantomData,
__phantom_ea: PhantomData,
};
let (cells, entities) = gen.gen(&universe.conf);
universe.cells = cells;
for (universe_index, entity_vec) in entities.into_iter().enumerate() {
for entity in entity_vec {
universe.entities.insert(entity, universe_index);
}
}
universe
}
}
impl<
C: CellState, E: EntityState<C>, M: MutEntityState, CA: CellAction<C>, EA: EntityAction<C, E>
> Debug for Universe<C, E, M, CA, EA> where C:Display, E:Display {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
let length = self.conf.size * self.conf.size;
let mut buf = String::with_capacity(length);
buf.push_str(&format!("{}", self.seq));
for i in 0..length {
if i % self.conf.size == 0 {
buf.push('\n');
}
let entities = self.entities.get_entities_at(i);
if entities.len() > 0 { let entity_index = entities[0];
let entity_state = unsafe { &self.entities.get(entity_index).state };
buf.push_str(&format!("{}", entity_state));
} else {
buf.push_str(&format!("{}", self.cells[i].state));
}
}
buf.push('\n');
write!(formatter, "{}", buf)
}
}