xxxxxxxxxx
169
// Number of cars in the population
const populationSize = 100;
// Length of the circular track
const trackRadius = 200;
// Maximum number of iterations
const maxIterations = 500;
// Mutation rate
const mutationRate = 0.01;
// Array to store the cars
let cars = [];
// Best car
let bestCar;
// Helper function to calculate the distance between two points
function calculateDistance(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
// Car class
class Car {
constructor() {
this.position = createVector(trackRadius, 0);
this.velocity = createVector(0, 0);
this.angle = 0;
this.fitness = 0;
this.finished = false;
this.crashed = false;
// Array of random instructions for the car
this.instructions = [];
for (let i = 0; i < maxIterations; i++) {
this.instructions.push(p5.Vector.random2D());
}
}
// Update the car's position and check for collisions
update() {
if (!this.finished && !this.crashed) {
this.position.add(this.velocity);
this.velocity.limit(3);
this.angle = this.velocity.heading();
// Check if the car has reached the finish line
const distance = calculateDistance(0, 0, this.position.x, this.position.y);
if (distance < trackRadius) {
this.finished = true;
}
// Check for collisions with the track boundary
if (distance > trackRadius + 10 || this.position.x < 0 || this.position.y < 0) {
this.crashed = true;
}
}
}
// Apply the next instruction to the car's velocity
applyInstruction(instruction) {
this.velocity.add(instruction);
}
// Calculate the fitness of the car
calculateFitness() {
const distance = calculateDistance(0, 0, this.position.x, this.position.y);
this.fitness = map(distance, 0, trackRadius, trackRadius, 0);
if (this.finished) {
this.fitness *= 10;
}
if (this.crashed) {
this.fitness /= 10;
}
}
// Create a copy of the car with mutated instructions
makeCopy() {
const copy = new Car();
copy.instructions = this.instructions.slice();
for (let i = 0; i < copy.instructions.length; i++) {
if (random() < mutationRate) {
copy.instructions[i] = p5.Vector.random2D();
}
}
return copy;
}
}
function setup() {
createCanvas(600, 600);
// Create the initial population of cars
for (let i = 0; i < populationSize; i++) {
cars.push(new Car());
}
}
function draw() {
background(220);
// Update and draw the cars
for (let i = 0; i < cars.length; i++) {
const car = cars[i];
car.update();
car.calculateFitness();
if (!car.crashed) {
push();
translate(width / 2, height / 2);
rotate(car.angle);
fill(0, 255, 0);
rect(trackRadius - 10, -5, 20, 10);
pop();
}
}
// Find the best car
let maxFitness = 0;
for (let i = 0; i < cars.length; i++) {
const car = cars[i];
if (car.fitness > maxFitness) {
maxFitness = car.fitness;
bestCar = car;
}
}
// Draw the best car in a different color
if (bestCar) {
push();
translate(width / 2, height / 2);
rotate(bestCar.angle);
fill(255, 0, 0);
rect(trackRadius - 10, -5, 20, 10);
pop();
}
// Generate the next generation of cars
const nextGeneration = [];
for (let i = 0; i < cars.length; i++) {
const parent = selectParent(cars);
const child = parent.makeCopy();
nextGeneration.push(child);
}
cars = nextGeneration;
}
// Select a parent car based on fitness
function selectParent(cars) {
let totalFitness = 0;
for (let i = 0; i < cars.length; i++) {
totalFitness += cars[i].fitness;
}
let rand = random(totalFitness);
let sum = 0;
for (let i = 0; i < cars.length; i++) {
sum += cars[i].fitness;
if (sum > rand) {
return cars[i];
}
}
}