Skip to content

Instantly share code, notes, and snippets.

@xmichael446
Last active November 14, 2022 09:41
Show Gist options
  • Save xmichael446/edf37525445635d1b7d475df3e30ad33 to your computer and use it in GitHub Desktop.
Save xmichael446/edf37525445635d1b7d475df3e30ad33 to your computer and use it in GitHub Desktop.
Fish simulation in rust
use std::{thread, time::Duration};
use std::fmt::Formatter;
use rand::Rng;
const INITIAL_FISH_AMOUNT: u32 = 20;
const LIFETIME_CONSTRAINTS: (u32, u32) = (10, 50);
#[derive(PartialEq, Clone)]
enum Gender {
Male,
Female,
Other,
}
#[derive(Clone)]
struct Fish {
name: String,
gender: Gender,
age: u32,
lifetime: u32,
mother: Option<Box<Fish>>,
father: Option<Box<Fish>>,
}
struct Aquarium {
fish: Vec<Fish>,
}
struct Logger {}
impl Logger {
fn collision(&self, first: &Fish, second: &Fish) {
println!("------------- COLLISION -------------");
print!("{first}\n{second}");
println!("------------- COLLISION -------------");
}
fn birth(&self, fish: &Fish) {
println!("------------- BIRTH -------------");
print!("{fish}");
println!("------------- BIRTH -------------");
}
fn death(&self, fish: &Fish) {
println!("------------- DEATH -------------");
print!("{fish}");
println!("------------- DEATH -------------");
}
}
impl Fish {
pub fn new(name: String, gender: Gender, lifetime: u32, mother: Option<Box<Fish>>, father: Option<Box<Fish>>) -> Self {
Fish { name, gender, lifetime, father, mother, age: 0 }
}
fn can_marry(&self, other: &Fish) -> bool {
self.gender != other.gender
}
fn is_male(&self) -> bool {
self.gender == Gender::Male
}
fn is_female(&self) -> bool {
self.gender == Gender::Female
}
fn should_die(&self) -> bool {
self.age == self.lifetime
}
fn increment_age(&mut self) {
self.age += 1
}
}
impl std::fmt::Display for Fish {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "name: {}\nage: {}\nlifetime: {}\n", self.name, self.age, self.lifetime)
}
}
fn take<T>(v: &mut Vec<T>, index: usize) -> Option<T> {
if v.get(index).is_none() {
None
} else {
Some(v.swap_remove(index))
}
}
impl Aquarium {
fn generate_fish(&self, father: Option<Box<Fish>>, mother: Option<Box<Fish>>) -> Fish {
let g: u32 = rand::thread_rng().gen_range(0..2);
let gender = match g {
0 => Gender::Male,
1 => Gender::Female,
_ => Gender::Other
};
let name = match gender {
Gender::Male => String::from("Michael"),
Gender::Female => String::from("Qizi"),
Gender::Other => String::from("how the hell?")
};
let (start, stop) = LIFETIME_CONSTRAINTS;
let lifetime = rand::thread_rng().gen_range(start..stop);
let f = Fish::new(name, gender, lifetime, father, mother);
return f;
}
fn fill(&mut self, amount: u32) {
for _ in 0..amount {
self.fish.push(self.generate_fish(None, None));
}
}
fn get_random(&self) -> Fish {
let i = rand::thread_rng().gen_range(0..self.fish.len());
take(&mut self.fish.clone(), i).unwrap()
}
}
fn main() {
let mut aquarium = Aquarium { fish: vec![] };
aquarium.fill(INITIAL_FISH_AMOUNT);
let logger = Logger {};
let mut collisions: Vec<u32> = Vec::new();
let mut iteration: u32 = 0;
loop {
for _ in 1..6 {
let n: u32 = rand::thread_rng().gen_range(1..6) + iteration;
collisions.push(n);
}
collisions.sort_by(|a, b| b.cmp(a));
for c in collisions.iter() {
if c < &iteration { break; }
if c != &iteration || c < &iteration { continue; }
let f1 = aquarium.get_random();
let f2 = aquarium.get_random();
logger.collision(&f1, &f2);
if !f1.can_marry(&f2) { continue; }
let father: Box<Fish> = if f1.is_male() { Box::new(f1.clone()) } else { Box::new(f2.clone()) };
let mother: Box<Fish> = if f1.is_female() { Box::new(f1.clone()) } else { Box::new(f2.clone()) };
let new_fish = aquarium.generate_fish(Some(father), Some(mother));
aquarium.fish.push(new_fish.clone());
logger.birth(&new_fish);
}
for i in 0..aquarium.fish.len() {
aquarium.fish[i].increment_age();
if aquarium.fish[i].should_die() {
logger.death(&aquarium.fish[i].clone());
}
}
aquarium.fish.retain(|f| {!f.should_die()});
iteration += 1;
thread::sleep(Duration::from_millis(2000));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment