/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.ktmqv8Msca1/rev.1413
*
* authors:
* Markell
*
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
int[][] maze;
float[][] light;
int[] stack = new int[0];
int res = 10;
int w, h;
int px, py, pDir;
int p2x, p2y, p2Dir;
int renderDist = 8;
boolean loopsPossible = true;
int loopPercentage = 10;
boolean lightsOut = true;
boolean[] keys = new boolean[256];
//stack <--> array conversions
//id = y*width + x
//y = (id-x) / width
//x = id % width
void setup() {
size(410,410);
//size(300 + res, 300 + res);
w = width/res;
h = height/res;
maze = new int[w][h];
light = new float[w][h];
generateMaze();
drawMaze();
}
void draw() {
drawMaze();
drawPlayer();
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
light[i][j] *= .995;
}
}
if(keys[87]) { //W
move(pDir);
keys[87] = false;
}
if(keys[83]) { //S
move((pDir + 2) % 4);
keys[83] = false;
}
if(keys[65]) { //A
pDir--;
if (pDir < 0) pDir = 3;
keys[65] = false;
}
if(keys[68]) { //D
pDir++;
pDir %= 4;
keys[68] = false;
}
if(keys[UP]) { //W
move2(p2Dir);
keys[UP] = false;
}
if(keys[DOWN]) { //S
move2((p2Dir + 2) % 4);
keys[DOWN] = false;
}
if(keys[LEFT]) { //A
p2Dir--;
if (p2Dir < 0) p2Dir = 3;
keys[LEFT] = false;
}
if(keys[RIGHT]) { //D
p2Dir++;
p2Dir %= 4;
keys[RIGHT] = false;
}
if(keys[76]) { //L
if (lightsOut == false) {
lightsOut = true;
}
else {
lightsOut = false;
}
}
generateLights(pDir, renderDist, px, py);
generateLights(p2Dir, renderDist, p2x, p2y);
}
void keyReleased() {
keys[keyCode] = false;
}
void keyPressed() {
keys[keyCode] = true;
}
void move2(int dir) {
switch(dir) {
case 0:
if (p2y-1 > 0 && maze[p2x][p2y-1] != 0) p2y--;
break;
case 1:
if (p2x+1 < w-1 && maze[p2x+1][p2y] != 0) p2x++;
break;
case 2:
if (p2y+1 < h-1 && maze[p2x][p2y+1] != 0) p2y++;
break;
case 3:
if (p2x-1 > 0 && maze[p2x-1][p2y] != 0) p2x--;
break;
default:
break;
}
if (maze[p2x][p2y] == 2) {
println("You won!");
generateMaze();
}
}
void move(int dir) {
switch(dir) {
case 0:
if (py-1 > 0 && maze[px][py-1] != 0) py--;
break;
case 1:
if (px+1 < w-1 && maze[px+1][py] != 0) px++;
break;
case 2:
if (py+1 < h-1 && maze[px][py+1] != 0) py++;
break;
case 3:
if (px-1 > 0 && maze[px-1][py] != 0) px--;
break;
default:
break;
}
if (maze[px][py] == 2) {
println("You won!");
generateMaze();
}
}
void generateLights(int dir, float L, int x, int y) {
if (maze[x][y] != 0 && L > 0) {
if (L > light[x][y]) light[x][y] = L;
switch(dir) {
case 0:
if (y-1 > 0 && maze[x][y-1] != 0) generateLights(dir, L-1, x, y-1);
if (x+1 < w-1 && maze[x+1][y] != 0) generateLights(1, L/3, x+1, y);
if (x-1 > 0 && maze[x-1][y] != 0) generateLights(3, L/3, x-1, y);
break;
case 1:
if (x+1 < w-1 && maze[x+1][y] != 0) generateLights(dir, L-1, x+1, y);
if (y-1 > 0 && maze[x][y-1] != 0) generateLights(0, L/3, x, y-1);
if (y+1 < h-1 && maze[x][y+1] != 0) generateLights(2, L/3, x, y+1);
break;
case 2:
if (y+1 < h-1 && maze[x][y+1] != 0) generateLights(dir, L-1, x, y+1);
if (x+1 < w-1 && maze[x+1][y] != 0) generateLights(1, L/3, x+1, y);
if (x-1 > 0 && maze[x-1][y] != 0) generateLights(3, L/3, x-1, y);
break;
case 3:
if (x-1 > 0 && maze[x-1][y] != 0) generateLights(dir, L-1, x-1, y);
if (y-1 > 0 && maze[x][y-1] != 0) generateLights(0, L/3, x, y-1);
if (y+1 < h-1 && maze[x][y+1] != 0) generateLights(2, L/3, x, y+1);
break;
default:
break;
}
}
}
void generateMaze() {
int x = int(random(w-1));
while (x % 2 == 0)
x = int(random(w-1));
int y = int(random(h-1));
while (y % 2 == 0)
y = int(random(h-1));
maze = new int[w][h];
light = new float[w][h];
px = x; py = y;
maze[x][y] = 1;
stack = append(stack, y*w +x);
recursion(x, y);
p2x = int(random(w-1)); p2y = int(random(h-1));
while(dist(px,py,p2x,p2y) < 10 || maze[p2x][p2y] != 1) {
p2x = int(random(w-1)); p2y = int(random(h-1));
}
println(p2x + ", " + p2y);
int gx = (int)random(w-1);
int gy = (int)random(h-1);
while (dist (x, y, gx, gy) < 10 || maze[gx][gy] != 1) {
gx = (int)random(w-1);
gy = (int)random(h-1);
}
maze[gx][gy] = 2;
}
void recursion(int x, int y) {
int dir[] = new int[4];
dir[0] = int(random(3));
int n = 1;
while (n < 4) {
dir[n] = (dir[n-1] + 1) % 4;
n++;
}
boolean success = false;
for (int i = 0; i < 4; i++) {
switch(dir[i]) {
case 0:
if (y-2 < 0 || maze[x][y-2] != 0) {
float p = random(100);
if (loopsPossible)
if (p < loopPercentage && y-2 > 0) maze[x][y-1] = 1;
continue;
}
if (maze[x][y-2] == 0) {
maze[x][y-2] = 1;
maze[x][y-1] = 1;
stack = append(stack, (y-2)*w +x);
recursion(x, y-2);
success = true;
}
break;
case 1:
if (x+2 > w-2 || maze[x+2][y] != 0) {
float p = random(100);
if (loopsPossible)
if (p < loopPercentage && x+2 < w-2) maze[x+1][y] = 1;
continue;
}
if (maze[x+2][y] == 0) {
maze[x+2][y] = 1;
maze[x+1][y] = 1;
stack = append(stack, y*w +x+2);
recursion(x+2, y);
success = true;
}
break;
case 2:
if (y+2 > h-2 || maze[x][y+2] != 0) {
float p = random(100);
if (loopsPossible)
if (p < loopPercentage && y+2 < h-2) maze[x][y+1] = 1;
continue;
}
if (maze[x][y+2] == 0) {
maze[x][y+2] = 1;
maze[x][y+1] = 1;
stack = append(stack, (y+2)*w +x);
recursion(x, y+2);
success = true;
}
break;
case 3:
if (x-2 < 0 || maze[x-2][y] != 0) {
float p = random(100);
if (loopsPossible)
if (p < loopPercentage && x-2 > 0) maze[x-1][y] = 1;
continue;
}
if (maze[x-2][y] == 0) {
maze[x-2][y] = 1;
maze[x-1][y] = 1;
stack = append(stack, y*w +x-2);
recursion(x-2, y);
success = true;
}
break;
default:
break;
}
break;
}
if (!success) {
stack = shorten(stack);
if (stack.length != 0) {
int i = stack.length-1;
recursion(stack[i] % w, (stack[i] - (stack[i] % w)) / w);
}
}
}
void drawPlayer() {
fill(255, 0, 0);
rect(px*res, py*res, res, res);
stroke(0, 0, 255);
switch(pDir) {
case 0:
line(px*res + res/2, py*res + res/2, px*res + res/2, py*res);
break;
case 1:
line(px*res + res/2, py*res + res/2, px*res + res, py*res + res/2);
break;
case 2:
line(px*res + res/2, py*res + res/2, px*res + res/2, py*res + res);
break;
case 3:
line(px*res + res/2, py*res + res/2, px*res, py*res + res/2);
break;
default:
break;
}
noStroke();
fill(0, 0, 255);
rect(p2x*res, p2y*res, res, res);
stroke(255, 0, 0);
switch(p2Dir) {
case 0:
line(p2x*res + res/2, p2y*res + res/2, p2x*res + res/2, p2y*res);
break;
case 1:
line(p2x*res + res/2, p2y*res + res/2, p2x*res + res, p2y*res + res/2);
break;
case 2:
line(p2x*res + res/2, p2y*res + res/2, p2x*res + res/2, p2y*res + res);
break;
case 3:
line(p2x*res + res/2, p2y*res + res/2, p2x*res, p2y*res + res/2);
break;
default:
break;
}
stroke(0);
}
void drawMaze() {
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
if (maze[i][j] == 0) fill(0);
if (lightsOut) {
if (maze[i][j] == 1) fill(light[i][j]*255/renderDist);
if (maze[i][j] == 2) fill(light[i][j]*255/renderDist, light[i][j]*240/renderDist, 0);
}
else {
if (maze[i][j] == 1) fill(255);
if (maze[i][j] == 2) fill(255, 240, 0);
}
noStroke();
rect(i*res, j*res, res, res);
}
}
}