xxxxxxxxxx
289
//IDEA FOR FUTURE:
//MAKE A POINT WHICH EXERTS A FORCE (VECTOR) ON THE CRAWLING CRAYON, LIKE GRAVITY OR ELECTROMAGNETISM SO THE CRAYON IS DRAWN TO OR REPULSED IN CERTAIN DIRECTIONS. COMBINATION OF RANDOMNESS AND NONRANDOMNESS.
//Also, have the move number influence the movement as well: Periods of volatility and periods of order for more heterogeneity. use a normal distribution with a modal point t? x-axis is time. Let user define SD/ probability curve with a function.
//[[0,1],[0,-1],[1,0],[-1,0]];
//[[0,1],[0,-1],[1,0],[-1,0],[1,1],[1,-1],[-1,1],[-1,-1]];
//[[2,1],[2,-1],[-2,1],[-2,-1],[1,2],[1,-2],[-1,2],[-1,-2]];
//[[2,1],[2,-1],[-2,1],[-2,-1]];
h = 2
possibleDirs = [[h,1],[h,-1],[-h,1],[-h,-1]];
orderedDirs = [[h,1],[h,-1],[-h,1],[-h,-1]];
moves = 0;
movesSinceBacktrack = 0;
function setup() {
yMargin = 0;
emptyColor = [0,0,0]
maze = []
mazeW = 360;
mazeH = 360;
cellSize = 2;
startX = floor(random(mazeW));
startY = floor(random(mazeH));
posX = startX;
posY = startY;
currDir = [0,1]; //Vector
currHue = 10;
currSat = 100;
currVal = 0;
hueDiff = 0.0005;
satDiff = 0.0;
valDiff = 0.01;
hueMin = 0;
hueMax = 360;
satMin = 0;
satMax = 100;
valMin = 0;
valMax = 100;
turnP = 0.00;
hueBounce = false;
satBounce = true;
valBounce = true;
step = false;
order = false;
limitMoves = true;
moveLimit = 30000;
cum = 0;
cumDiff = 0.1;
cumDiffMultiplier = 0.5; //Smaller: continuous; larger: bimodal btwn volatile and stable.
cumDiffTheta = 0; //Dont change
cumDiffThetaDiff = 0.0001; //Rapidity of volatility-stability cycles.
iWantToDrawTheTrail = true;
trailLength = 500;
trail = [[posX,posY]]; //creates a list of the last trailLength # of steps
branches = [[posX,posY,currHue,currSat,currVal]]; //Tracks every time a turn is made.
createCanvas(mazeW * cellSize, mazeH * cellSize + yMargin);
colorMode(HSB);
for (let x = 0; x < mazeW; x++){
maze[x]=[];
for (let y = 0; y < mazeH; y++){
maze[x][y]=emptyColor; //List stores color in HSV
}
}
noLoop();
}
function attemptTurn(){
possibleDirs.push(possibleDirs.shift())
if (order == false){
availDirs = possibleDirs.map((x) => x);
for (var dir in availDirs){
r = floor(random(availDirs.length))
if (facingEmpty(availDirs[r])){
currDir = availDirs[r];
branches.push([posX,posY,currHue, currSat, currVal])
return true;
}
availDirs.splice(r,1);
}
return false;
} else {
for (var i in orderedDirs){
if (facingEmpty(orderedDirs[i])){
currDir = orderedDirs[i];
branches.push([posX,posY,currHue, currSat, currVal])
return true;
}
}
return false;
}
}
function facingEmpty(dir){
desiredPos = [posX + dir[0], posY + dir[1]];
if (desiredPos[0] >= mazeW || desiredPos[0] < 0 ||desiredPos[1] >= mazeH || desiredPos[1] < 0){
return false;
}
if (maze[desiredPos[0]][desiredPos[1]] == emptyColor){
return true;
} else {
return false;
}
}
function drawTrail(){
trailStep = 1;
while(trailStep < trailLength){
posX = trail[trail.length-trailStep][0]
posY = trail[trail.length-trailStep][1]
fill(0,0,100,(trailStep)/trailLength)
rect(posX*cellSize,posY*cellSize + yMargin,cellSize,cellSize)
trailStep++;
}
}
function backTrack(){
movesSinceBacktrack = 0;
while (true){
//console.log(branches[branches.length-1])
posX = branches[branches.length-1][0]
posY = branches[branches.length-1][1]
if (attemptTurn() == false){
if (branches.length > 1){
branches.pop();
return true;
} else {
return false;
}
} else{
currHue = branches[branches.length-1][2]
currSat = branches[branches.length-1][3]
currVal = branches[branches.length-1][4]
return true;
}
}
}
function moveInCurrDir(){
posX += currDir[0]
posY += currDir[1]
//Assign color to current pos.
movesSinceBacktrack++;
if (hueBounce && (currHue + hueDiff < hueMin || currHue + hueDiff >=hueMax)){
hueDiff = -hueDiff;
}
if (satBounce && (currSat + satDiff < satMin || currSat + satDiff >=satMax)){
satDiff = -satDiff;
}
if (valBounce && (currVal + valDiff < valMin || currVal + valDiff >=valMax)){
valDiff = -valDiff;
}
currHue = currHue + hueDiff
currSat = currSat + satDiff
currVal = currVal + valDiff
if (currHue < hueMin){
currHue = hueMax - (hueMin-currHue)
}
if (currHue > hueMax){
currHue = hueMin + (currHue- hueMax)
}
if (currSat < satMin){
currHue = satMax - (satMin-currSat)
}
if (currSat > satMax){
currSat = hueSat + (currSat- satMax)
}
if (currVal < valMin){
currHue = valMax - (valMin-currVal)
}
if (currVal > valMax){
currVal = valMin + (currVal- valMax)
}
maze[posX][posY] = [currHue, currSat,currVal];
if (trail.length>trailLength) { trail.splice(0,1); }
trail.push([posX,posY])
}
function logisticalCurve(coeff,val){
return 1/(1+(2.71^(-coeff*(val-0.5))));
}
function crawl(){
if (limitMoves == false || moves < moveLimit){
if (facingEmpty(currDir)){
//If empty, move to desired cell.
moveInCurrDir();
//Roll dice to turn.
if (random() < cum){
//Dice roll succeeds; turn if able.
attemptTurn();
//Restart cum, which increments by cumDiff.
cum = 0;
cumDiff = cumDiffMultiplier * sin(cumDiffTheta);
console.log(cumDiff)
}
//Progress along the volatility-stability cycle.
console.log("cumDiffTheta",cumDiffTheta)
cumDiffTheta += cumDiffThetaDiff ;
cum += cumDiff;
} else {
//If not empty, attempt turn.
if (attemptTurn()){
moveInCurrDir();
} else {
if (backTrack() == false){
return false;
}
}
}
moves++;
return true;
} else {
console.log("Predetermined move limit reached.")
return false;
}
}
function drawSquare(x,y){
fill(maze[x][y][0],maze[x][y][1],maze[x][y][2])
rect(x*cellSize,y*cellSize + yMargin,cellSize,cellSize)
}
function draw() {
if (step == false){
while (crawl() == true){}
}
background(55);
fill(255)
textSize(32)
stroke(255)
text("Moves: "+str(moves),32,32);
text("Moves since backtrack: "+str(movesSinceBacktrack),32,64)
strokeWeight(0)
for (var x = 0; x < mazeW; x++){
for (var y = 0; y < mazeH; y++){
drawSquare(x,y)
}
}
if (iWantToDrawTheTrail) {drawTrail();}
//Draw curPos outline
fill(0,0,0,0);
strokeWeight(3)
stroke(255);
rect(posX*cellSize,posY*cellSize+yMargin,cellSize,cellSize);
}
function keyPressed(){
if (step){
crawl();
redraw();
}
}
function mousePressed(){
if (mouseButton == RIGHT) {
saveCanvas(canvas,'crawl','jpg');
}
}