01/ Introduction to Neural Byte
Computational modeling of natural selection requires a combination of high-fidelity physical kinematics and adaptive agency. Neural Byte is a high-performance, 2D evolutionary simulation written in Rust that models the classic predator-prey ecosystem.
Rather than utilizing hardcoded heuristic behaviors (such as basic seek or avoid algorithms), agents in Neural Byte are controlled by independent **Feedforward Neural Networks** (Multi-Layer Perceptrons). These neural controllers map spatial target vectors onto kinematics steering inputs. Over thousands of generations, selective pressures naturally emerge: prey adapt to locate food particles while dodging predators, and predators evolve sophisticated chasing trajectories.
Interactive Simulation Arena
Live WebAssembly Render (Rust + Macroquad + Egui)
Figure 1: Live evolutionary simulation. Click on individual agents to view active neural paths. Use controls on the right panel to tweak parameters.
03/ Agent Neural Architectures
The brains of the agents are modeled as multi-layer feedforward networks (MLPs). The structure and dimensions of these networks are specialized depending on the agent's ecological role:
Prey Neural Brain
- Input Layer (4 neurons):
- Relative local direction to closest food ($X, Y$)
- Relative local direction to closest predator ($X, Y$)
- Hidden Layer (8 neurons): Activated via ReLU
- Output Layer (2 neurons): Activated via Tanh
- Steering angle force $[-1.0, 1.0]$
- Engine acceleration throttle $[-1.0, 1.0]$
Predator Neural Brain
- Input Layer (3 neurons):
- Relative local direction to closest prey ($X, Y$)
- Proximity distance to the target prey
- Hidden Layer (8 neurons): Activated via ReLU
- Output Layer (2 neurons): Activated via Tanh
- Steering angle force $[-1.0, 1.0]$
- Engine acceleration throttle $[-1.0, 1.0]$
Mathematical Activation & Feedforward Propagation
The feedforward propagation for layer $l$ is calculated using bias vector $\mathbf{b}$ and weight matrix $\mathbf{W}$:
The hidden nodes use the Rectified Linear Unit (ReLU) activation function, which handles vanishing gradients:
To restrict steering force and engine throttle to continuous bounded physical values, output nodes utilize the Hyperbolic Tangent (Tanh) function:
04/ Evolutionary Pressures & Reproduction
In Neural Byte, fitness is not explicitly computed using an objective global loss function. Instead, agent reproduction is entirely resource-dependent:
- Prey: Spawn when their gathered food energy surpasses $100.0$. Spawning divides their energy, passing mutated weights and biases to an offspring.
- Predators: Consume prey to gain $220.0$ energy. If their energy crosses $700.0$, they reproduce. If their energy reaches $0.0$ (due to metabolism), they die.
Gaussian Mutation Strategy
During mitosis, the offspring inherits its parent's network weights $w_{ij}$ and biases $b_i$, with small variations introduced via a Normal (Gaussian) distribution:
Where the standard deviation $\sigma$ (mutation rate) is dynamically adjustable in real-time. This variance allows the agents to slowly scale and adapt their navigation.
05/ Neural Network Feedforward in Rust
Below is a clean Rust snippet demonstrating the feedforward process of an agent's multi-layer perceptron:
pub struct Layer {
pub weights: Vec>,
pub biases: Vec,
}
pub struct FeedForwardNet {
pub layers: Vec,
}
impl FeedForwardNet {
pub fn feedforward(&self, inputs: &[f32]) -> Vec {
let mut current_outputs = inputs.to_vec();
for (i, layer) in self.layers.iter().enumerate() {
let is_output_layer = i == self.layers.len() - 1;
let mut next_outputs = vec![0.0; layer.biases.len()];
for j in 0..layer.biases.len() {
let mut sum = layer.biases[j];
for k in 0..current_outputs.len() {
sum += current_outputs[k] * layer.weights[j][k];
}
// Hidden layers use ReLU, output layer uses Tanh
next_outputs[j] = if is_output_layer {
sum.tanh()
} else {
sum.max(0.0) // ReLU
};
}
current_outputs = next_outputs;
}
current_outputs
}
}