xxxxxxxxxx
let grid = [];
let cellSize = 5;
let cols, rows;
let current;
let stack = [];
let vs = []
function setup() {
cols = 140;
rows = 140;
createCanvas(cols*cellSize + cellSize, rows*cellSize + cellSize); // Increased to accommodate extra row and column
// Initialize grid with walls (1 = wall, 0 = path)
for (let y = 0; y < rows; y++) {
grid[y] = [];
for (let x = 0; x < cols; x++) {
grid[y][x] = 1;
}
}
// Start at (1,1)
current = {x: 1, y: 1};
grid[current.y][current.x] = 0;
// Generate maze
generateMaze();
// Set start and end points
grid[1][1] = 0; // Start point
for (let y = 0; y < 100000; y++) {grid = cull_dead_ends(grid, 17)}
grid = mark_holes(grid)
let results = find_path_dfs(grid, [1, 1], [rows-3,cols-3])
//print(results[1],results[2] )
vs = results[0]
}
function draw() {
background(100);
translate(cellSize, cellSize)
// Draw maze including extra row and column of walls
for (let y = 0; y <= rows-2; y++) {
for (let x = 0; x <= cols-2; x++) {
if (x === cols || y === rows) {
// Draw extra wall row/column
fill(100);
} else {
fill(grid[y][x] === 1 ? 0 : 255);
//if(vs[y][x] == 1){fill(100, 100, 255)}
if(grid[y][x] == 7){
if((x + y) %2 == 1)fill(255, 255, 255)
if((x + y) %2 == 0)fill(0, 0, 0)
}
if(x == cols-2)fill(0, 0, 0)
if(y == rows-2)fill(0, 0, 0)
}
noStroke();
rect(x * cellSize, y * cellSize, cellSize, cellSize);
}
}
fill(0, 255, 0); // Start is green
rect(cellSize, cellSize, cellSize, cellSize);
fill(255, 0, 0); // End is red
rect((cols-3) * cellSize, (rows-3) * cellSize, cellSize, cellSize);
if(0){
let out = '';
for (let y = 0; y < rows-1; y++) {
let s = '';
for (let x = 0; x < cols-1; x++) {
if(x == rows-3 && y == cols-3){
s += 'S';
continue;
}
if(x == 1 && y == 1){
s += 'E';
continue;
}
s += grid[y][x] === 1 ? '#' : '_'
}
out += (s + '\n')
}
print(out)
}
noLoop()
}
function generateMaze() {
stack.push(current);
let emergencec = 0;
let rushfl = true;
while (stack.length > 0) {
emergencec +=1
if(emergencec>1000000)break;
let tc = stack.length-1
///if(!rushfl){tc = max(0, stack.length-10); rushfl = true}
if(!rushfl){tc = max(0, 0); rushfl = true}
current = stack[tc];
stack.splice(tc, 1)
let neighbors = getUnvisitedNeighbors(current);
if (neighbors.length > 0) {
stack.push(current);
//let next = random(neighbors);
let next = weightedRandomDirection(neighbors, [random(),random(),random(),random(),]);
// Remove wall between current and next
let midX = (current.x + next.x) / 2;
let midY = (current.y + next.y) / 2;
grid[midY][midX] = 0; // Create path through wall
grid[next.y][next.x] = 0; // Make next cell a path
stack.push(next);
}else{
rushfl = false
}
}
}
function getUnvisitedNeighbors(cell) {
let neighbors = [];
let directions = [
{x: 0, y: -2}, // Up
{x: 2, y: 0}, // Right
{x: 0, y: 2}, // Down
{x: -2, y: 0} // Left
];
for (let dir of directions) {
let newX = cell.x + dir.x;
let newY = cell.y + dir.y;
// Check if the neighbor and the wall between are within bounds
if (newX > 0 && newX < cols-1 && newY > 0 && newY < rows-1) {
// Check if the neighbor cell is still a wall
if (grid[newY][newX] === 1) {
// Check if moving to this neighbor won't break the outer wall
if (newX !== cols-1 && newY !== rows-1 && newX !== 0 && newY !== 0) {
neighbors.push({x: newX, y: newY});
}
}
}
}
return neighbors;
}
function weightedRandomDirection(neighbors, probabilities) {
// Map each neighbor to its direction type
let directions = neighbors.map(n => {
if (n.x > current.x) return 'right';
if (n.x < current.x) return 'left';
if (n.y > current.y) return 'down';
return 'up';
});
// Create direction-probability pairs
let dirProbs = {
'up': probabilities[0],
'right': probabilities[1],
'down': probabilities[2],
'left': probabilities[3]
};
// Calculate total probability for available directions
let totalProb = 0;
let availableProbs = [];
for (let i = 0; i < directions.length; i++) {
let prob = dirProbs[directions[i]];
availableProbs.push(prob);
totalProb += prob;
}
if (totalProb > 0) {
availableProbs = availableProbs.map(p => p / totalProb);
} else {
availableProbs = availableProbs.map(() => 1 / directions.length);
}
let r = random(1);
let cumulativeProb = 0;
for (let i = 0; i < availableProbs.length; i++) {
cumulativeProb += availableProbs[i];
if (r <= cumulativeProb) {
return neighbors[i];
}
}
return neighbors[neighbors.length - 1];
}
function find_path_dfs(g, startp, endp){
let visited = []
let st = [startp,]
let max_count = 100000
let scount = 0
let forkscount = 0
let directions = [
[0,-1],
[1, 0],
[0, 1],
[-1,0],
];
for (let y = 0; y < g.length; y++) {
visited[y] = [];
for (let x = 0; x < g[0].length; x++) {
visited[y][x] = 0;
}
}
while(st.length > 0 && scount < max_count){
let new_p = st.pop()
if(new_p[0] == endp[0] && new_p[1] == endp[1]){break;}
let good_directions = directions.map((t)=> [t[0]+new_p[0], t[1]+new_p[1]]).filter(t=> visited[t[1]][t[0]]==0 && g[t[1]][t[0]]==0)
if(good_directions.length == 0){forkscount+=1; continue;}
good_directions = sort_to_p(good_directions, endp)
good_directions.map(t => {st.push(t); visited[t[1]][t[0]] = 1})
scount+=1;
}
return [visited, scount, forkscount]
}
function cull_dead_ends(m, stepsk = 10){
let n = m.length
let p = [floor(random(n)),floor(random(n))]
if(set_in(p, [[1, 1], [n-3,n-3]])){return m}
if(m[p[0]][p[1]] != 0){return m}
let directions = [
[0,-1],
[1, 0],
[0, 1],
[-1,0],
];
let good_directions = directions.map((t)=> [t[0]+p[0], t[1]+p[1]]).filter(t=>m[t[0]][t[1]]==0)
if(good_directions.length != 1){return m}
let erase_those = [[p], good_directions[0], ]
let do_it = false;
for(let i=0; i<stepsk; i+=1){
p = erase_those[erase_those.length-1]
good_directions = directions.map((t)=> [t[0]+p[0], t[1]+p[1]]).filter(t => m[t[0]][t[1]]==0 && (!set_in(t, erase_those)))
if(good_directions.length >= 2 || set_in(p, [[1, 1], [n-3,n-3]])){
do_it = true
erase_those.pop()
break
}
erase_those.push([good_directions[0][0], good_directions[0][1],])
}
if(do_it){
erase_those.map(t => m[t[0]][t[1]] = 1)
}
return m
}
function set_in(it, s){
let out = s.some(t => t[0] == it[0] && t[1] == it[1])
return out
}
function sort_to_p(s, p) {
let new_s = [s];
new_s.sort((point1, point2) => {
// Calculate distance from p to point1
const dx1 = point1[0] - p[0];
const dy1 = point1[1] - p[1];
const dist1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
// Calculate distance from p to point2
const dx2 = point2[0] - p[0];
const dy2 = point2[1] - p[1];
const dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
// Return negative for descending order (furthest first)
return dist2 - dist1;
});
return new_s;
}
function mark_holes(g){
let n = g.length
let directions = [
[0,-1],
[1, 0],
[0, 1],
[-1,0],
[-1,-1],
[1,-1],
[-1,1],
[1, 1],
];
for (let y = 1; y <= n-2; y++) {
for (let x = 1; x <= n-2; x++) {
if(g[x][y] != 1) continue;
good_directions = directions.map((t)=> [t[0]+x, t[1]+y]).filter(t => g[t[0]][t[1]]!=0)
if(good_directions.length > 7){ g[x][y] = 7;}
}
}
return g
}