use std::fmt::Display; use crate::genetics::flow::Flow; #[derive(PartialEq,Eq,Clone)] pub struct Gene { pub plant_source: GeneSource, pub place: String, pub kind: GeneType } pub struct GeneContext { pub flow: Flow } #[derive(PartialEq,Eq,Clone,Copy)] pub enum GeneSource { Peashooter, Sunflower, CherryBomb, PotatoMine, } /// GeneType is an enum that defines behaviour of gene. #[derive(PartialEq,Eq,Clone)] pub enum GeneType { /// Without functional behaviour. Doesn't pass through flow. Structural, /// Only creates flow. Can be set up to not create flow if flow isn't empty. PureProducer { create_flow: fn(GeneContext) -> Flow }, /// Creates or modifies flow. Needs to decide whether to create or modify flow. Producer { create_flow: fn(GeneContext) -> Flow, modify_single: fn(GeneContext) -> Flow, modify_all: fn(GeneContext) -> Flow, decide_modification_type: fn(GeneContext) -> ProduceDecision, }, /// Allows flow to pass through. Transport { distribute_between_children: fn(GeneContext) -> ChildDistribution }, /// Consumes flow, destroying it in process. Consumer { consume: fn(GeneContext) }, /// Modifies flow Modifier { modify_flow: fn(GeneContext) -> Flow }, /// Conditionally passes through flow. Acts like transport. Trigger { check_trigger: fn(GeneContext) -> bool, distribute_between_children: fn(GeneContext) -> ChildDistribution }, /// Observes flow. Acts like transport. Observer { observe: fn(GeneContext), distribute_between_children: fn(GeneContext) -> ChildDistribution }, } pub enum ChildDistribution{ Single, Multiple{amount: usize}, All, Custom{child_indicies: Vec} } pub enum ProduceDecision { Create, ModifyAll, ModifySingle, } impl Gene { pub fn new(plant_source: GeneSource, place_str: impl Into, kind: GeneType) -> Self { Self { plant_source, place: place_str.into(), kind, } } } impl Display for GeneSource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f,"{}",match self { GeneSource::Peashooter => "Peashooter", GeneSource::Sunflower => "Sunflower", GeneSource::CherryBomb => "CherryBomb", GeneSource::PotatoMine => "PotatoMine", }); Ok(()) } } impl Display for Gene { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f,"({}) {}",self.plant_source,self.place); Ok(()) } } impl GeneType { /// Creates pure producer with create function. pub fn pure_producer(flow_function: fn(GeneContext) -> Flow) -> Self { Self::PureProducer { create_flow: flow_function } } /// Creates transport with random distribution. pub fn random_distribution() -> Self { Self::Transport { distribute_between_children: Self::distribute_between_random } } /// Creates transport with distribution between all children. pub fn fill_all() -> Self { Self::Transport { distribute_between_children: Self::distribute_between_all } } /// Creates consumer with consumer function. pub fn consumer(consumer_function: fn(GeneContext)) -> Self { Self::Consumer { consume: consumer_function } } /// Creates modifier with modifier function. pub fn modifier(modifier_function: fn(GeneContext) -> Flow) -> Self { Self::Modifier { modify_flow: modifier_function } } /// Creates trigger with distribution between all children. pub fn trigger_all(trigger_function: fn(GeneContext) -> bool) -> Self { Self::Trigger { check_trigger: trigger_function, distribute_between_children: Self::distribute_between_all } } /// Creates observer with distribution between all children. pub fn observer_all(observer_function: fn(GeneContext)) -> Self { Self::Observer { observe: observer_function, distribute_between_children: Self::distribute_between_all } } fn distribute_between_random(_: GeneContext) -> ChildDistribution { ChildDistribution::Single } fn distribute_between_all(_: GeneContext) -> ChildDistribution { ChildDistribution::All } }