restructuring

This commit is contained in:
Simon Gardling
2021-04-01 10:33:05 -04:00
parent f8b16c720b
commit 41ba5f248c
6 changed files with 231 additions and 122 deletions

107
src/agent.rs Normal file
View File

@@ -0,0 +1,107 @@
use crate::{
grid::{Grid, PopulationConfig},
util::wrap,
};
use rand::{seq::SliceRandom, Rng};
use std::f32::consts::TAU;
// A single Physarum agent. The x and y positions are continuous, hence we use floating point numbers instead of integers.
#[derive(Debug)]
pub struct Agent {
pub x: f32,
pub y: f32,
pub angle: f32,
pub population_id: usize,
pub i: usize,
}
impl Agent {
// Construct a new agent with random parameters.
pub fn new<R: Rng + ?Sized>(width: usize, height: usize, id: usize, rng: &mut R, i: usize) -> Self {
let (x, y, angle) = rng.gen::<(f32, f32, f32)>();
Agent {
x: x * width as f32,
y: y * height as f32,
angle: angle * TAU,
population_id: id,
i,
}
}
#[inline]
pub fn tick(&mut self, grid: &Grid) {
let (width, height) = (grid.width, grid.height);
let PopulationConfig {
sensor_distance,
sensor_angle,
rotation_angle,
step_distance,
..
} = grid.config;
let xc = self.x + fastapprox::faster::cos(self.angle) * sensor_distance;
let yc = self.y + fastapprox::faster::sin(self.angle) * sensor_distance;
let agent_add_sens = self.angle + sensor_angle;
let agent_sub_sens = self.angle - sensor_angle;
let xl = self.x + fastapprox::faster::cos(agent_sub_sens) * sensor_distance;
let yl = self.y + fastapprox::faster::sin(agent_sub_sens) * sensor_distance;
let xr = self.x + fastapprox::faster::cos(agent_add_sens) * sensor_distance;
let yr = self.y + fastapprox::faster::sin(agent_add_sens) * sensor_distance;
// We sense from the buffer because this is where we previously combined data from all the grid.
let center = grid.get_buf(xc, yc);
let left = grid.get_buf(xl, yl);
let right = grid.get_buf(xr, yr);
// Rotate and move logic
let mut rng = rand::thread_rng();
let mut direction: f32 = 0.0;
if (center > left) && (center > right) {
direction = 0.0;
} else if (center < left) && (center < right) {
direction = *[-1.0, 1.0].choose(&mut rng).unwrap();
} else if left < right {
direction = 1.0;
} else if right < left {
direction = -1.0;
}
let delta_angle = rotation_angle * direction;
self.angle = wrap(self.angle + delta_angle, TAU);
self.x = wrap(
self.x + step_distance * fastapprox::faster::cos(self.angle),
width as f32,
);
self.y = wrap(
self.y + step_distance * fastapprox::faster::sin(self.angle),
height as f32,
);
}
}
impl Clone for Agent {
fn clone(&self) -> Agent {
Agent {
x: self.x,
y: self.y,
angle: self.angle,
population_id: self.population_id,
i: self.i,
}
}
}
impl PartialEq for Agent {
fn eq(&self, other: &Self) -> bool {
self.x == other.x
&& self.y == other.y
&& self.angle == other.angle
&& self.population_id == other.population_id
&& self.i == other.i
}
}