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 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
use std::fmt;
use super::*;
pub use lifespan::*;
pub use offspring::*;
pub use state::*;
pub mod lifespan;
pub mod offspring;
pub mod state;
/// The type of the Entity unique ID.
///
/// It is safe to assume that the library will not be dealing with a number of
/// entities greater than `usize::max_value()` at any given time.
pub type Id = usize;
/// The Trait that describes a generic Entity.
///
/// This is the Trait that defines the shared behavior for all the entities that
/// belong to the Environment. Each of the entities needs to implement this
/// Trait, and can interact with other entities via this Trait.
///
/// The lifetime `'e` is used to specify the lifetime bound of any immutable
/// reference that belongs to the type that implements this trait.
/// So that, if your type includes immutable references with an explicit
/// lifetime, it is possible to propagate the lifetime bound to the Offspring of
/// this Entity without requiring a `'static` lifetime.
/// This lifetime bound does not apply to mutable references, since they cannot
/// be copied without violate uniqueness.
pub trait Entity<'e> {
/// The type of the Entity kind.
type Kind;
/// The type of the graphics Context used to draw the shape of the entities.
type Context;
/// Gets the ID of the Entity.
///
/// The ID must be unique for all the entities. It is considered a logic
/// error for to different entities to share the same ID, in which case the
/// behavior within the Environment is undefined.
fn id(&self) -> Id;
/// Gets the Entity type.
///
/// Each Entity can belong to a specific kind that defines, besides the
/// logical type of the Entity itself, the order in which entities are going
/// to be drawn.
fn kind(&self) -> Self::Kind;
/// Gets the location of the Entity within the Environment.
///
/// If an Entity has no location, it should return None. An Entity can either
/// have a location for its entire lifetime or no location; it is considered
/// a logic error if this method returns None for an Entity that previously
/// had a location, and vice versa.
fn location(&self) -> Option<Location> {
None
}
/// Gets the scope of this Entity.
///
/// The size of the scope defines its radius of influence, i.e. the portion
/// of the Environment that an Entity can see and interact with. The bigger
/// the scope the bigger the portion of the Environment (Neighborhood).
/// A scope equal to 0 means that the Entity is only going to be able to see
/// the Tile where it currently resides, a scope equal to 1 will also include
/// the 8 surrounding tiles, and so on.
/// If None is returned the Entity has no scope at all, and it can neither see
/// nor affect any other tile or surrounding Entity.
/// In other terms, the scope effectively represents the distance from the
/// Tile where the Entity is located, to the farthest Tile it will ever be
/// able to reach.
/// Moreover, only entities that have a location in the Environment can
/// interact with surrounding entities, therefore it is a logic error to
/// return Some from this method if `Entity::location()` returns None, but it
/// is perfectly valid for entities to have a location but no scope.
fn scope(&self) -> Option<Scope> {
None
}
/// Gets the remaining lifespan of the Entity.
///
/// If the concept of lifespan is meaningless for this Entity, it should
/// simply return None.
fn lifespan(&self) -> Option<Lifespan> {
None
}
/// Gets a mutable reference to the remaining lifespan of the Entity.
///
/// It is possible to influence the remaining lifespan of the Entity by
/// changing its value. If the Entity has no lifespan, or it does not allow
/// other entities to affect its own lifespan, None should be returned.
fn lifespan_mut(&mut self) -> Option<&mut Lifespan> {
None
}
/// Gets a reference to a trait that is implemented by the object that
/// represents the state of the Entity.
///
/// The State trait exposes method that enable dynamic typing and allow to
/// downcast the trait to the original concrete type.
/// If the Entity has no meaningful state associated with it, this method
/// should simply return None.
fn state(&self) -> Option<&dyn State> {
None
}
/// Gets a mutable reference to a trait that is implemented by the object that
/// represents the state of the Entity.
///
/// The State trait exposes method that enable dynamic typing and allow to
/// downcast the trait to the original concrete type.
/// If the Entity has no meaningful state associated with it, this method
/// should simply return None.
fn state_mut(&mut self) -> Option<&mut dyn State> {
None
}
/// Allows the Entity to observe the portion of surrounding Environment seen
/// by the Entity according to its scope.
///
/// The larger the scope the bigger the portion of the Environment that the
/// Entity will be allowed to see.
/// The provided Neighborhood represents the squared grid of surrounding
/// cells. Each of these cells can be queried to detect what other entities
/// are currently in that location, and allows to interact with those
/// entities via the methods provided by this trait.
/// This method is called for each generation, and the provided Neighborhood
/// represents a snapshot of the previous generation readonly fields, that
/// is, the Neighborhood will contain the entities according to their
/// location in the previous generation.
/// If the Entity has no scope, the Neighborhood will be None.
/// If any of the operations performed in this method fails, you can bubble
/// up the error to the Environment, which will take care of reporting it to
/// the final user.
///
/// # Note
/// If an Entity's shared property (that is seeable or changeable
/// by other entities, such as location or state) is modified in this method,
/// being it a property of self or of the given neighbor entities, this will
/// be immediately reflected when querying the other entities, but it will not
/// immediately affect the state of the Environment itself. That is, the
/// portion of the Neighborhood presented to other entities will still
/// reflect the locations of the entities as it was during the previous
/// generation, until all the entities have observed their neighborhood.
/// For this reason, it is considered a logic error to change the shared
/// properties here, you should instead record the changes, and apply them in
/// the `Entity::react` method, that is guaranteed to be called for all the
/// entities, only after all the `Entity::observe` have been called.
fn observe(
&mut self,
_: Option<Neighborhood<'_, 'e, Self::Kind, Self::Context>>,
) -> Result<(), Error> {
Ok(())
}
/// Allows to take an action that will affect the Entity itself, and its
/// neighbors, according to the portion of surrounding Environment seen by
/// the Entity according to its scope.
///
/// The larger the scope the bigger the portion of the Environment the Entity
/// will be allowed to see and affect.
/// The provided Neighborhood represents the squared grid of surrounding
/// cells. Each of this cell can be queried to detect what other entities
/// are currently in that location, and allows to interact with those
/// entities via the methods provided by this trait.
/// This method is called for each generation, and the provided Neighborhood
/// represents a snapshot of the previous generation readonly fields, that
/// is, the Neighborhood will contain the entities according to their
/// location in the previous generation.
/// If the Entity has no scope the Neighborhood will be None.
/// If any of the operations performed in this method fails, you can bauble
/// up the error to the Environment, that will take care of reporting it to
/// the final user.
///
/// # Note
/// The same semantic that applies to the `Entity::observe` method applies
/// also to the `Entity::react` method. Therefore, changes to the Entity's
/// shared properties such as location or state, will be immediately
/// reflected when querying neighbors or following entities, while the given
/// Neighborhood is guaranteed to provide a snapshot of the locations of the
/// entities of the previous generation.
fn react(
&mut self,
_: Option<Neighborhood<'_, 'e, Self::Kind, Self::Context>>,
) -> Result<(), Error> {
Ok(())
}
/// Gets the Offspring of the Entity.
///
/// The offspring of an Entity will be introduced in the Environment at
/// every generation. Therefore, the list of entities returned by this method
/// will be taken as is and introduces as is in the Environment. It is the
/// responsibility of the Entity owner to return an offspring only if the
/// Entity did actually generate an offspring in the current generation,
/// otherwise this method should return None.
///
/// The lifetime of the Entity `'e` will be propagated to its Offspring, so
/// that the lifetime bound stipulated when creating the parent Entity, that
/// may contain references as part of the type that implements this trait,
/// will be kept unchanged.
fn offspring(
&mut self,
) -> Option<Offspring<'e, Self::Kind, Self::Context>> {
None
}
/// Draws the Entity using the given graphics Context and according to the
/// given transformation (matrix).
///
/// This method is called for each generation. If you wish to skip drawing
/// the shape of your Entity, this method should simply return `Ok(())`.
fn draw(&self, _: &mut Self::Context, _: Transform) -> Result<(), Error> {
Ok(())
}
}
/// The Entity Trait type alias with explicit lifetime bound.
#[cfg(not(feature = "parallel"))]
pub type EntityTrait<'e, K, C> = dyn Entity<'e, Kind = K, Context = C> + 'e;
/// The Entity Trait type alias with explicit lifetime bound.
#[cfg(feature = "parallel")]
pub type EntityTrait<'e, K, C> =
dyn Entity<'e, Kind = K, Context = C> + 'e + Send + Sync;
impl<'e, K: fmt::Debug, C> fmt::Debug for EntityTrait<'e, K, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Entity")
.field("id", &self.id())
.field("kind", &self.kind())
.finish()
}
}