Code viewer for World: before 01

// Cloned by Zoro on 10 Nov 2024 from World "A * way 01 (clone by Zoro) (clone by Zoro)" by Zoro 
// Please leave this clone trail here.
 


// Cloned by Zoro on 10 Nov 2024 from World "A * way 01 (clone by Zoro)" by Zoro 
// Please leave this clone trail here.
 


// Cloned by Zoro on 10 Nov 2024 from World "A * way 01" by Zoro 
// Please leave this clone trail here.
 
let cols = 13;
let rows = 10;
let w, h;
let grid = [];
let cars = [];
let destinations = [];
const colors = ["red", "blue", "green", "yellow"]; // Colors for the cars

function setup() {
  createCanvas(900, 600);
  w = width / cols;
  h = height / rows;
  initializeGrid();

  // Create one car and destination for testing
  let car = createCar(0);
  cars.push(car);
  let destination = createDestination(car);
  destinations.push(destination);
  
  // Calculate the original path using A* without avoiding walls
  let originalPath = findShortestPathAStar(car, destination);
  car.path = originalPath; // Store path in car object
  console.log(`Car 0 original path:`, originalPath.map(p => `(${p.i},${p.j})`));
}

function draw() {
  background(220);
  displayGrid();

  // Display cars, destinations, and paths
  for (let i = 0; i < cars.length; i++) {
    let car = cars[i];
    let destination = destinations[i];

    // Display the car
    car.show();

    // Display the destination with the car's color
    fill(car.color);
    noStroke();
    rect(destination.i * w, destination.j * h, w, h);

    // Draw the planned path from car to destination
    stroke(car.color);
    strokeWeight(2);
    noFill();
    beginShape();
    for (let pos of car.path) {
      vertex((pos.i + 0.5) * w, (pos.j + 0.5) * h);
    }
    endShape();
  }
}

function initializeGrid() {
  for (let i = 0; i < cols; i++) {
    grid[i] = [];
    for (let j = 0; j < rows; j++) {
      grid[i][j] = new Spot(i, j);
      grid[i][j].wall = !(i % 3 === 0 || j % 3 === 0); // Randomly place walls
    }
  }
}

function displayGrid() {
  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      grid[i][j].show();
    }
  }
}

function Spot(i, j) {
  this.i = i;
  this.j = j;
  this.wall = false;

  this.show = function() {
    if (this.wall) {
      fill(0); // Black for walls
    } else {
      fill(255); // White for paths
    }
    stroke(0);
    rect(this.i * w, this.j * h, w, h);
  };
}

function createCar(carIndex) {
  let i, j;
  do {
    i = floor(random(cols));
    j = floor(random(rows));
  } while (grid[i][j].wall || isOccupied(i, j)); 

  return new Car(i, j, colors[carIndex]);
}

function isOccupied(i, j) {
  return cars.some(car => car.i === i && car.j === j);
}

function createDestination(car) {
  let i, j;
  do {
    i = floor(random(cols));
    j = floor(random(rows));
  } while (grid[i][j].wall || (i === car.i && j === car.j) || isDestinationOccupied(i, j));

  return { i, j, color: car.color };
}

function isDestinationOccupied(i, j) {
  return destinations.some(dest => dest.i === i && dest.j === j);
}

function Car(startI, startJ, carColor) {
  this.i = startI;
  this.j = startJ;
  this.color = carColor;
  this.path = [];

  this.show = function() {
    fill(this.color);
    noStroke();
    ellipse((this.i + 0.5) * w, (this.j + 0.5) * h, w / 2, h / 2);
  };
}

function findShortestPathAStar(car, destination) {
  let start = grid[car.i][car.j];
  let end = grid[destination.i][destination.j];

  if (!start || !end) {
    return [];
  }

  let openSet = [];
  let closedSet = new Set();
  let cameFrom = {};

  openSet.push({
    node: start,
    g: 0,
    h: manhattanDistance(start.i, start.j, end.i, end.j),
    f: 0
  });
  cameFrom[`${start.i},${start.j}`] = null;

  let directions = [
    [0, 1], [0, -1], [1, 0], [-1, 0]
  ];

  while (openSet.length > 0) {
    openSet.sort((a, b) => a.f - b.f);
    let current = openSet.shift();
    let currentNode = current.node;

    if (currentNode === end) {
      let path = [];
      while (currentNode !== null) {
        path.unshift(currentNode);
        currentNode = cameFrom[`${currentNode.i},${currentNode.j}`];
      }
      return path;
    }

    closedSet.add(`${currentNode.i},${currentNode.j}`);

    for (let dir of directions) {
      let ni = currentNode.i + dir[0];
      let nj = currentNode.j + dir[1];

      if (ni >= 0 && ni < cols && nj >= 0 && nj < rows) {
        let neighbor = grid[ni][nj];
        let g = current.g + 1;
        let h = manhattanDistance(ni, nj, end.i, end.j);
        let f = g + h;

        let existing = openSet.find(n => n.node.i === ni && n.node.j === nj);
        if (!existing || existing.f > f) {
          openSet.push({ node: neighbor, g, h, f });
          cameFrom[`${neighbor.i},${neighbor.j}`] = currentNode;
        }
      }
    }
  }
  return [];
}

function manhattanDistance(x1, y1, x2, y2) {
  return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}