genetics-vs-zombies/rust-pvz-genetics/src/genetics/gene.rs
2026-04-01 10:59:14 +05:00

144 lines
4.3 KiB
Rust

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<usize>}
}
pub enum ProduceDecision {
Create,
ModifyAll,
ModifySingle,
}
impl Gene {
pub fn new(plant_source: GeneSource, place_str: impl Into<String>, 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
}
}