diff --git a/mods/human_friendly_design.js b/mods/human_friendly_design.js new file mode 100644 index 00000000..716961dd --- /dev/null +++ b/mods/human_friendly_design.js @@ -0,0 +1,899 @@ +elements.human.tick = function(pixel) { + if (isEmpty(pixel.x, pixel.y+1)) { + createPixel("body", pixel.x, pixel.y+1); + var color = pixel.color; + changePixel(pixel,"head"); + pixel.color = color; + if (pixel.bodyColor) { + pixelMap[pixel.x][pixel.y+1].color = pixel.bodyColor; + } + } + else if (isEmpty(pixel.x, pixel.y-1)) { + createPixel("head", pixel.x, pixel.y-1); + pixelMap[pixel.x][pixel.y-1].color = pixel.color; + changePixel(pixel,"body"); + if (pixel.bodyColor) { + pixel.color = pixel.bodyColor; + } + } +} + +elements.body.tick = function(pixel) { + if (tryMove(pixel, pixel.x, pixel.y+1)) { // Fall + if (!isEmpty(pixel.x, pixel.y-2, true)) { // Drag head down + var headpixel = pixelMap[pixel.x][pixel.y-2]; + if (headpixel.element === "head") { + if (isEmpty(pixel.x, pixel.y-1)) { + movePixel(pixelMap[pixel.x][pixel.y-2], pixel.x, pixel.y-1); + } + else { + swapPixels(pixelMap[pixel.x][pixel.y-2], pixelMap[pixel.x][pixel.y-1]); + } + } + } + } + doHeat(pixel); + doBurning(pixel); + doElectricity(pixel); + if (pixel.dead) { + // Turn into rotten_meat if pixelTicks-dead > 500 + if (pixelTicks-pixel.dead > 200 && Math.random() < 0.1) { + changePixel(pixel,"rotten_meat"); + } + return + } + + // Find the head + if (!isEmpty(pixel.x, pixel.y-1, true) && pixelMap[pixel.x][pixel.y-1].element == "head") { + var head = pixelMap[pixel.x][pixel.y-1]; + if (head.dead) { // If head is dead, kill body + pixel.dead = head.dead; + } + else if (head.panic > 0) { + pixel.panic = head.panic; + delete head.panic; + } + } + else { var head = null } + if (head && Math.random() < 0.25) { + let y = Math.random() < 0.5 ? 0 : -1; + for (let x = 1; x < 10; x++) { + let x2 = pixel.x+(x*pixel.dir); + let y2 = pixel.y+y; + if (!isEmpty(x2,y2,true)) { + let seenPixel = pixelMap[x2][y2]; + if (elements.human.reactions[seenPixel.element] && elements.human.reactions[seenPixel.element].attr1 && elements.human.reactions[seenPixel.element].attr1.panic) { + pixel.panic += elements.human.reactions[seenPixel.element].attr1.panic; + pixel.dir *= -1; + break; + } + else if (seenPixel.dead || seenPixel.temp > 200) { + pixel.panic += 5; + pixel.dir *= -1; + if (seenPixel.panic) delete seenPixel.panic; + break; + } + } + } + } + if (pixel.burning) { + pixel.panic += 0.1; + if (head && pixelTicks-pixel.burnStart > 240) { + pixel.color = head.color; + } + } + if (pixel.charge) { + pixel.panic += 1; + } + else if (pixel.panic > 0) { + pixel.panic -= 0.1; + if (pixel.panic < 0) { pixel.panic = 0; } + else if (pixel.panic > 50) { pixel.panic = 50; } + } + + if (isEmpty(pixel.x, pixel.y-1)) { + // create blood if decapitated 10% chance + if (Math.random() < 0.1 && !pixel.charge) { + createPixel("blood", pixel.x, pixel.y-1); + // set dead to true 15% chance + if (Math.random() < 0.15) { + pixel.dead = pixelTicks; + } + } + } + else if (head === null) { return } + else if (Math.random() < 0.1*(isEmpty(pixel.x, pixel.y+1) ? 1 : pixel.panic+1)) { // Move 10% chance + var movesToTry = [ + [1*pixel.dir,0], + [1*pixel.dir,-1], + ]; + let moved = false; + // While movesToTry is not empty, tryMove(pixel, x, y) with a random move, then remove it. if tryMove returns true, break. + while (movesToTry.length > 0) { + var move = movesToTry.splice(Math.floor(Math.random() * movesToTry.length), 1)[0]; + if (isEmpty(pixel.x+move[0], pixel.y+move[1]-1)) { + var origx = pixel.x+move[0]; + var origy = pixel.y+move[1]; + if (tryMove(pixel, pixel.x+move[0], pixel.y+move[1]) && pixel.x===origx && pixel.y===origy) { + movePixel(head, head.x+move[0], head.y+move[1]); + moved = true; + break; + } + } + else if (!isEmpty(pixel.x+move[0], pixel.y+move[1], true)) { + var hitPixel = pixelMap[pixel.x+move[0]][pixel.y+move[1]]; + if (hitPixel.element === "body" || hitPixel.element === "head" && hitPixel.panic < pixel.panic) { + // interact with other human + hitPixel.panic = pixel.panic; + } + } + } + // 15% chance to change direction + if (Math.random() < 0.15 || !moved) { + pixel.dir *= -1; + } + // homeostasis + if (pixel.temp > 37) { pixel.temp -= 1; } + else if (pixel.temp < 37) { pixel.temp += 1; } + } + +} + +elements.portal_in.tick = function(pixel) { + // if (Math.random() > 0.1) return; + if (!ticktemp.portal_out) ticktemp.portal_out = {}; + let channel = parseInt(pixel.channel) || 0; + if (!ticktemp.portal_out[channel]) { + ticktemp.portal_out[channel] = currentPixels.filter((p) => { + return elements[p.element].id === elements.portal_out.id && ( + isEmpty(p.x,p.y+1) || isEmpty(p.x,p.y-1) || + isEmpty(p.x+1,p.y) || isEmpty(p.x-1,p.y) + ) && + (parseInt(p.channel) || 0) === parseInt(channel) + }); + } + if (ticktemp.portal_out[channel].length) { + shuffleArray(squareCoordsShuffle); + let r; + for (var i = 0; i < squareCoordsShuffle.length; i++) { + var coord = squareCoordsShuffle[i]; + var x = pixel.x+coord[0]; + var y = pixel.y+coord[1]; + if (!isEmpty(x,y,true) && elements[pixelMap[x][y].element].movable) { + r = pixelMap[x][y]; + break; + } + } + if (r !== undefined || pixel.charge) { + let portal_out = choose(ticktemp.portal_out[channel]); + if (portal_out.del) return; + if (r !== undefined) { + shuffleArray(squareCoordsShuffle); + for (var j = 0; j < squareCoordsShuffle.length; j++) { + var coord2 = squareCoordsShuffle[j]; + var x2 = portal_out.x+coord2[0]; + var y2 = portal_out.y+coord2[1]; + if (isEmpty(x2,y2) && r.element !== "head" && r.element !== "body") { + tryMove(r,x2,y2); + } + else if (isEmpty(x2,y2) && (r.element === "head" || r.element === "body")) { + if (r.element === "head" && !isEmpty(r.x,r.y+1)) { + if (pixelMap[r.x][r.y+1].element === "body") { + r.element = "human" + r.bodyColor = pixelMap[r.x][r.y+1].color + deletePixel(r.x,r.y+1) + tryMove(r,x2,y2); + } + else { + tryMove(r,x2,y2); + } + } + else if (r.element === "body" && !isEmpty(r.x,r.y-1)) { + if (pixelMap[r.x][r.y-1].element === "head") { + r.element = "human" + r.bodyColor = r.color + r.color = pixelMap[r.x][r.y-1].color + deletePixel(r.x,r.y-1) + tryMove(r,x2,y2); + } + else { + tryMove(r,x2,y2); + } + } + } + break; + } + } + if (pixel.charge && !portal_out.charge && !portal_out.chargeCD) { + portal_out.charge = pixel.charge; + } + } + }; + doElectricity(pixel); +} + +elements.pipe.tick = function(pixel) { + if (!pixel.stage && pixelTicks-pixel.start > 60) { + for (var i = 0; i < squareCoords.length; i++) { + var coord = squareCoords[i]; + var x = pixel.x+coord[0]; + var y = pixel.y+coord[1]; + if (!isEmpty(x,y,true) && elements[pixelMap[x][y].element].movable) { + deletePixel(x,y) + } + if (isEmpty(x,y)) { + createPixel("pipe_wall",x,y); + } + } + pixel.stage = 1; + } + else if (pixel.stage === 1 && pixelTicks-pixel.start > 70) { //uninitialized + for (var i = 0; i < adjacentCoords.length; i++) { + var coord = adjacentCoords[i]; + var x = pixel.x+coord[0]; + var y = pixel.y+coord[1]; + if (isEmpty(x,y)) { + pixel.stage = 2; //blue + pixel.color = pixelColorPick(pixel,"#000036"); + break; + } + } + } + else if (pixel.stage > 1 && pixelTicks % 3 === pixel.stage-2) { //initialized + for (var i = 0; i < squareCoords.length; i++) { + var coord = squareCoords[i]; + var x = pixel.x+coord[0]; + var y = pixel.y+coord[1]; + if (!isEmpty(x,y,true) && pixelMap[x][y].element === "pipe") { + var newPixel = pixelMap[x][y]; + if (newPixel.stage === 1) { + var newColor; + switch (pixel.stage) { + case 2: newPixel.stage = 3; newColor = "#003600"; break; //green + case 3: newPixel.stage = 4; newColor = "#360000"; break; //red + case 4: newPixel.stage = 2; newColor = "#000036"; break; //blue + } + newPixel.color = pixelColorPick(newPixel,newColor); + } + } + } + var moved = false; + shuffleArray(squareCoordsShuffle); + for (var i = 0; i < squareCoordsShuffle.length; i++) { + var coord = squareCoordsShuffle[i]; + var x = pixel.x+coord[0]; + var y = pixel.y+coord[1]; + if (!isEmpty(x,y,true)) { + var newPixel = pixelMap[x][y]; + if (newPixel.element === "pipe") { + var nextStage; + switch (pixel.stage) { + case 2: nextStage = 4; break; //green + case 3: nextStage = 2; break; //red + case 4: nextStage = 3; break; //blue + } + if (pixel.con && !newPixel.con && newPixel.stage === nextStage) { //transfer to adjacent pipe + newPixel.con = pixel.con; + newPixel.con.x = newPixel.x; + newPixel.con.y = newPixel.y; + pixel.con = null; + moved = true; + break; + } + } + else if (!pixel.con && elements[newPixel.element].movable && newPixel.element !== "head" && newPixel.element !== "body") { //suck up pixel + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + else if (!pixel.con && elements[newPixel.element].movable && (newPixel.element === "head" || newPixel.element === "body")) { + if (newPixel.element === "head") { + if (!isEmpty(newPixel.x,newPixel.y+1)) { + if (pixelMap[newPixel.x][newPixel.y+1].element === "body") { + newPixel.element = "human" + newPixel.bodyColor = pixelMap[newPixel.x][newPixel.y+1].color + deletePixel(newPixel.x,newPixel.y+1) + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + else { + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + } + else { + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + } + else if (newPixel.element === "body") { + if (!isEmpty(newPixel.x,newPixel.y-1)) { + if (pixelMap[newPixel.x][newPixel.y-1].element === "head") { + newPixel.element = "human" + newPixel.bodyColor = newPixel.color + newPixel.color = pixelMap[newPixel.x][newPixel.y-1].color + deletePixel(newPixel.x,newPixel.y-1) + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + else { + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + } + else { + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + } + else { + pixel.con = newPixel; + deletePixel(newPixel.x,newPixel.y); + pixel.con.x = pixel.x; + pixel.con.y = pixel.y; + pixel.con.del; + moved = true; + break; + } + } + } + } + if (pixel.con && !moved) { // move to same stage if none other + for (var i = 0; i < squareCoordsShuffle.length; i++) { + var coord = squareCoordsShuffle[i]; + var x = pixel.x+coord[0]; + var y = pixel.y+coord[1]; + if (isEmpty(x,y)) { + delete pixel.con.del; + pixel.con.x = x; + pixel.con.y = y; + pixelMap[x][y] = pixel.con; + currentPixels.push(pixel.con); + pixel.con = null; + break; + } + if (!isEmpty(x,y,true) && pixelMap[x][y].element === "pipe") { + var newPixel = pixelMap[x][y]; + if (pixel.con && !newPixel.con && newPixel.stage === pixel.stage) { + newPixel.con = pixel.con; + newPixel.con.x = newPixel.x; + newPixel.con.y = newPixel.y; + pixel.con = null; + break; + } + } + } + } + } + doDefaults(pixel); +} + +elements.drag.tool = function(pixel) { + if (dragStart === null) { + dragStart = pixelTicks; + draggingPixels = []; + } + if (pixelTicks === dragStart && !pixel.drag && (elements[pixel.element].movable || shiftDown) && pixel.element !== "head") { + pixel.drag = true; + draggingPixels.push(pixel); + } +} + +elements.drag.perTick = function() { + if (!draggingPixels) { return; } + for (var j = 0; j < (shiftDown ? 3 : 1); j++) { + for (var i = 0; i < draggingPixels.length; i++) { + var pixel = draggingPixels[i]; + if (pixel.del) { continue } + const x = pixel.x; + const y = pixel.y; + const [mX, mY] = [mousePos.x, mousePos.y]; + const empty = checkForEmptyPixels(x, y); + let bestVal = Math.sqrt(Math.pow(mX - x, 2) + Math.pow(mY - y, 2)); + let best = null; + for (const pixelPair of empty) { + const x_ = x + pixelPair[0]; + const y_ = y + pixelPair[1]; + const c = Math.sqrt(Math.pow(mX - x_, 2) + Math.pow(mY - y_, 2)); + if (c < bestVal) { + bestVal = c; + best = pixelPair; + } + } + if (best) { + if (pixel.element !== "body") { + tryMove(pixel, x + best[0], y + best[1], undefined, true); + } + else if (pixel.element === "body") { + if (!isEmpty(pixel.x,pixel.y-1)) { + var headPixel = pixelMap[pixel.x][pixel.y-1] + if (headPixel.element === "head") { + if (isEmpty(x + best[0], y + best[1] - 1)) { + tryMove(headPixel, x + best[0], y + best[1] - 1, undefined, true); + tryMove(pixel, x + best[0], y + best[1], undefined, true); + } + } + } + else {tryMove(pixel, x + best[0], y + best[1], undefined, true);} + } + } + } + } +} + +mouse1Action = function(e,mouseX=undefined,mouseY=undefined,startPos) { + if (currentElement === "erase") { mouse2Action(e,mouseX,mouseY,startPos); return; } + else if (currentElement === "pick") { mouseMiddleAction(e,mouseX,mouseY); return; } + // If x and y are undefined, get the mouse position + if (mouseX === undefined && mouseY === undefined) { + // var canvas = document.getElementById("game"); + // var ctx = canvas.getContext("2d"); + lastPos = mousePos; + mousePos = getMousePos(canvas, e); + var mouseX = mousePos.x; + var mouseY = mousePos.y; + } + var cooldowned = false; + if (mouseSize===1 && elements[currentElement].cooldown && !paused) { + if (pixelTicks-lastPlace < elements[currentElement].cooldown) { + return; + } + cooldowned = true; + } + lastPlace = pixelTicks; + if (cooldowned && !startPos) { + var coords = mouseRange(mouseX,mouseY); + } + else { + startPos = startPos || lastPos + var coords = lineCoords(startPos.x,startPos.y,mouseX,mouseY); + } + // if (!((cooldowned && startPos.x===lastPos.x && startPos.y===lastPos.y) || ((elements[currentElement].tool || elements[currentElement].category==="tools") && !elements[currentElement].canPlace))) { + // } + // else { var coords = mouseRange(mouseX,mouseY); } + var element = elements[currentElement]; + var mixList = []; + // For each x,y in coords + var done = {}; + for (var i = 0; i < coords.length; i++) { + var x = coords[i][0]; + var y = coords[i][1]; + if (!done[x]) { + done[x] = {} + } + if (done[x][y]) { continue; } + done[x][y] = true; + + if (mode === "replace" && (!elements[currentElement].tool || elements[currentElement].canPlace)) { + if (outOfBounds(x,y)) { + continue; + } + // Remove pixel at position from currentPixels + if (!isEmpty(x,y,true)) { + if (!(currentElement === pixelMap[x][y].element && pixelMap[x][y].start === pixelTicks-1)) { + deletePixel(x,y); + } + } + } + + if (currentElement === "mix") { + if (!isEmpty(x,y,true)) { + var pixel = pixelMap[x][y]; + if (!(elements[pixel.element].movable !== true || elements[pixel.element].noMix === true) || shiftDown) { + mixList.push(pixel); + } + } + continue; + } + else if (elements[currentElement].tool && !(elements[currentElement].canPlace && isEmpty(x,y))) { + // run the tool function on the pixel + if (!isEmpty(x,y,true)) { + var pixel = pixelMap[x][y]; + // if the current element has an ignore property and the pixel's element is in the ignore property, don't do anything + if (elements[currentElement].ignore && elements[currentElement].ignore.indexOf(pixel.element) !== -1) { + continue; + } + elements[currentElement].tool(pixel); + } + continue; + } + if (isEmpty(x, y)) { + if (currentPixels.length < maxPixelCount) { + createPixel(currentElement,x,y); + if (pixelMap[x][y] && currentElement === pixelMap[x][y].element && (elements[currentElement].customColor || elements[currentElement].singleColor)) { + pixelMap[x][y].color = pixelColorPick(pixelMap[x][y],currentColorMap[currentElement]); + } + if (currentElementProp) { + for (var key in currentElementProp) { + pixelMap[x][y][key] = currentElementProp[key] + } + } + } + } + else if (!outOfBounds(x,y)) { + if (elements[currentElement].extinguish) { + var pixel = pixelMap[x][y]; + if (pixel.burning && elements[pixel.element].burning !== true) { + delete pixel.burning; + delete pixel.burnStart; + } + } + } + } + if (currentElement === "mix") { + // 1. repeat for each pixel in mixList + // 2. choose 2 random pixels and swap their x and y + // 3. remove pixel from mixList + for (var i = 0; i < mixList.length; i++) { + var pixel1 = mixList[Math.floor(Math.random()*mixList.length)]; + var pixel2 = mixList[Math.floor(Math.random()*mixList.length)]; + if (pixel1.element !== "head" && pixel2.element !== "head" && pixel1.element !== "body" && pixel2.element !== "body") { + swapPixels(pixel1,pixel2); + } + else if (pixel1.element !== "head" && pixel2.element !== "head" && (pixel1.element === "body" || pixel2.element === "body")) { + if (pixel1.element === "body") { + if (!isEmpty(pixel1.x,pixel1.y-1, true)) { + var headPixel1 = pixelMap[pixel1.x][pixel1.y-1] + if (headPixel1.element === "head") { + if (!isEmpty(pixel2.x,pixel2.y-1, true)) { + var headPixel2 = pixelMap[pixel2.x][pixel2.y-1] + if (headPixel2.element !== "body" && !(elements[headPixel2.element].movable !== true || elements[headPixel2.element].noMix === true)) { + swapPixels(pixel1,pixel2); + swapPixels(headPixel1,headPixel2); + } + } + else if (isEmpty(pixel2.x,pixel2.y-1)) { + swapPixels(pixel1,pixel2) + tryMove(headPixel1, pixel1.x, pixel1.y-1) + } + } + } + } + else if (pixel2.element === "body") { + if (!isEmpty(pixel2.x,pixel2.y-1, true)) { + var headPixel1 = pixelMap[pixel2.x][pixel2.y-1] + if (headPixel1.element === "head") { + if (!isEmpty(pixel1.x,pixel1.y-1, true)) { + var headPixel2 = pixelMap[pixel1.x][pixel1.y-1] + if (headPixel2.element !== "body" && !(elements[headPixel2.element].movable !== true || elements[headPixel2.element].noMix === true)) { + swapPixels(pixel1,pixel2); + swapPixels(headPixel1,headPixel2); + } + } + else if (isEmpty(pixel1.x,pixel1.y-1)) { + swapPixels(pixel1,pixel2); + tryMove(headPixel1, pixel2.x,pixel2.y-1) + } + } + } + } + } + mixList.splice(mixList.indexOf(pixel1),1); + mixList.splice(mixList.indexOf(pixel2),1); + if (elements[pixel1.element].onMix) { + elements[pixel1.element].onMix(pixel1,pixel2); + } + if (elements[pixel2.element].onMix) { + elements[pixel2.element].onMix(pixel2,pixel1); + } + } + + } +} + +pixelTick = function(pixel,custom=null) { + if (pixel.start === pixelTicks) {return} + btemp = {}; + if (elements[pixel.element] === undefined) { + pixel.invalidElement = pixel.element; + changePixel(pixel,"unknown"); + return; + } + var info = elements[pixel.element]; + btemp.info = info; + btemp.pixel = pixel; + if (custom) { var behavior = custom; } + else if (pixel.charge && info.behaviorOn) { var behavior = info.behaviorOn; } + else { var behavior = info.behavior; } + if (pixel.flipX) { behavior = flipBehavior(behavior,"x"); } + if (pixel.flipY) { behavior = flipBehavior(behavior,"y"); } + if (pixel.r) { behavior = rotateBehavior(behavior,pixel.r); } + var x = pixel.x; + var y = pixel.y; + var move1Spots = []; btemp.move1Spots = move1Spots; + var move2Spots = []; btemp.move2Spots = move2Spots; + var supportSpots = []; btemp.supportSpots = supportSpots; + var swapSpots = []; btemp.swapSpots = swapSpots; + btemp.mixSpots = []; + btemp.move = true; + // Parse behavior +var height = behavior.length; +for (var by = 0; by < behavior.length; by++) { +var behaviorby = behavior[by]; +var width = behaviorby.length; +for (var bx = 0; bx < behaviorby.length; bx++) { + var b0 = behaviorby[bx]; + if (b0 === "XX") {continue} + //if (b.includes(" OR ")) { + // b = b.split(" OR ")[Math.floor(Math.random()*b.split(" OR ").length)]; + //} + // Loop through b0.split(" AND ") + if (b0.indexOf(" AND ") !== -1) { var andsplit = b0.split(" AND "); } + else { var andsplit = [b0]; } + for (var i = 0; i < andsplit.length; i++) { + var b = andsplit[i]; + if (b.indexOf(":") !== -1) { + var arg = b.split(":")[1].split(/[\:\%]/)[0]; + if (b.indexOf("%") === -1) { + b = b.split(/[\:\%]/)[0]; + } + } + else { var arg = null;} + btemp.arg = arg; + // If b has "%" followed by a number in it, it's a chance to move + if (b.indexOf("%") !== -1) { + // Split the string at the "%" and use the second half as the chance (float) + var chance = parseFloat(b.split("%")[1]); + //console.log(b+": "+(Math.random()*100 < chance)); + b = b.split(/[\:\%]/)[0]; + } + else { var chance = 100; } + if (chance===100 || Math.random()*100 < chance) { + var newCoords = behaviorCoords(x,y,bx,by,width,height); + btemp.newCoords = newCoords; + if (behaviorRules[b]) { + behaviorRules[b](); + continue; + } + } + } + } + } + if (btemp.deleted) {return;} + if (supportSpots.length > 0) { + var supportCount = 0; + var allEmpty = true; + for (var i = 0; i < supportSpots.length; i++) { + var bx = supportSpots[i].x; + var by = supportSpots[i].y; + var arg = supportSpots[i].arg; + if (!isEmpty(bx,by,true)) { + if (info.ignore && info.ignore.indexOf(pixelMap[bx][by].element) !== -1) {continue;} + if ((arg === null && !validDensitySwaps[info.state][elements[pixelMap[bx][by].element].state]) || pixelMap[bx][by].element == arg) { + supportCount++; + } + } + } + if (supportCount == supportSpots.length) { + btemp.move = false; + } + } + + var moved = false; + + if (swapSpots.length > 0) { + var coords = swapSpots[Math.floor(Math.random()*swapSpots.length)]; + if (pixelMap[coords.x][coords.y] !== undefined) { + swapPixels(pixel,pixelMap[coords.x][coords.y]); + btemp.move = false; + moved = true; + } + } + + if (btemp.mixSpots.length > 0) { + for (var i = 0; i < btemp.mixSpots.length; i++) { + var coord1 = choose(btemp.mixSpots); + var coord2 = choose(btemp.mixSpots); + var exists1 = !isEmpty(coord1.x,coord1.y,true); + var exists2 = !isEmpty(coord2.x,coord2.y,true); + if (isEmpty(coord1.x,coord1.y) && exists2) { + var pixel1 = pixelMap[coord2.x][coord2.y] + if (pixel1.element !== "head" && pixel1.element !== "body") { + tryMove(pixel1,coord1.x,coord1.y); + } + else if (pixel1.element !== "head" && pixel1.element === "body") { + if (!isEmpty(pixel1.x,pixel1.y-1, true)) { + var headPixel1 = pixelMap[pixel1.x][pixel1.y-1] + if (headPixel1.element === "head") { + if (!isEmpty(coord1.x,coord1.y-1, true)) { + var headPixel2 = pixelMap[coord1.x][coord1.y-1] + if (headPixel2.element !== "body" && !(elements[headPixel2.element].movable !== true || elements[headPixel2.element].noMix === true)) { + tryMove(pixel1,coord1.x,coord1.y); + swapPixels(headPixel1,headPixel2); + } + } + else if (isEmpty(coord1.x,coord1.y-1)) { + tryMove(pixel1,coord1.x,coord1.y); + tryMove(headPixel1, pixel1.x, pixel1.y-1) + } + } + } + } + } + else if (exists1 && isEmpty(coord2.x,coord2.y)) { + var pixel1 = pixelMap[coord1.x][coord1.y] + if (pixel1.element !== "head" && pixel1.element !== "body") { + tryMove(pixel1,coord2.x,coord2.y); + } + else if (pixel1.element !== "head" && pixel1.element === "body") { + if (!isEmpty(pixel1.x,pixel1.y-1, true)) { + var headPixel1 = pixelMap[pixel1.x][pixel1.y-1] + if (headPixel1.element === "head") { + if (!isEmpty(coord2.x,coord2.y-1, true)) { + var headPixel2 = pixelMap[coord2.x][coord2.y-1] + if (headPixel2.element !== "body" && !(elements[headPixel2.element].movable !== true || elements[headPixel2.element].noMix === true)) { + tryMove(pixel1,coord2.x,coord2.y); + swapPixels(headPixel1,headPixel2); + } + } + else if (isEmpty(coord2.x,coord2.y-1)) { + tryMove(pixel1,coord2.x,coord2.y); + tryMove(headPixel1, pixel1.x, pixel1.y-1) + } + } + } + } + } + else if (exists1 && exists2) { + var pixel1 = pixelMap[coord1.x][coord1.y]; + var pixel2 = pixelMap[coord2.x][coord2.y]; + if (pixel1.element !== "head" && pixel2.element !== "head" && pixel1.element !== "body" && pixel2.element !== "body") { + swapPixels(pixel1,pixel2); + } + else if (pixel1.element !== "head" && pixel2.element !== "head" && (pixel1.element === "body" || pixel2.element === "body")) { + if (pixel1.element === "body") { + if (!isEmpty(pixel1.x,pixel1.y-1, true)) { + var headPixel1 = pixelMap[pixel1.x][pixel1.y-1] + if (headPixel1.element === "head") { + if (!isEmpty(pixel2.x,pixel2.y-1, true)) { + var headPixel2 = pixelMap[pixel2.x][pixel2.y-1] + if (headPixel2.element !== "body" && !(elements[headPixel2.element].movable !== true || elements[headPixel2.element].noMix === true)) { + swapPixels(pixel1,pixel2); + swapPixels(headPixel1,headPixel2); + } + } + else if (isEmpty(pixel2.x,pixel2.y-1)) { + swapPixels(pixel1,pixel2) + tryMove(headPixel1, pixel1.x, pixel1.y-1) + } + } + } + } + else if (pixel2.element === "body") { + if (!isEmpty(pixel2.x,pixel2.y-1, true)) { + var headPixel1 = pixelMap[pixel2.x][pixel2.y-1] + if (headPixel1.element === "head") { + if (!isEmpty(pixel1.x,pixel1.y-1, true)) { + var headPixel2 = pixelMap[pixel1.x][pixel1.y-1] + if (headPixel2.element !== "body" && !(elements[headPixel2.element].movable !== true || elements[headPixel2.element].noMix === true)) { + swapPixels(pixel1,pixel2); + swapPixels(headPixel1,headPixel2); + } + } + else if (isEmpty(pixel1.x,pixel1.y-1)) { + swapPixels(pixel1,pixel2); + tryMove(headPixel1, pixel2.x,pixel2.y-1) + } + } + } + } + } + if (elements[pixel1.element].onMix) { + elements[pixel1.element].onMix(pixel1,pixel2); + } + if (elements[pixel2.element].onMix) { + elements[pixel2.element].onMix(pixel2,pixel1); + } + } + } + } + + if (btemp.sticking) { + btemp.move = false; + } + + // Move First Priority + if (btemp.move) { + if (move1Spots.length > 0) { + // While move1Spots is not empty + while (move1Spots.length > 0) { + // coords = random item of move1Spots + var j = Math.floor(Math.random()*move1Spots.length); + var coords = move1Spots[j]; + var nx = coords.x; + var ny = coords.y; + moved = tryMove(pixel,nx,ny,btemp.leaveBehind1 || btemp.leaveBehind); + if (moved) { + break; + } + else { + // remove coords from move1Spots + move1Spots.splice(j,1); + } + + + } + } + // Move Second Priority + if (!moved && move2Spots.length > 0) { + // While move2Spots is not empty + while (move2Spots.length > 0) { + // coords = random item of move2Spots + var j = Math.floor(Math.random()*move2Spots.length); + var coords = move2Spots[j]; + var nx = coords.x; + var ny = coords.y; + moved = tryMove(pixel,nx,ny,btemp.leaveBehind2 || btemp.leaveBehind); + if (moved) { + if (btemp.C2 && elements[btemp.C2]) { + changePixel(pixel,btemp.C2); + } + break; + } + else { + // remove coords from move2Spots + move2Spots.splice(j,1); + } + } + } + } + doAirDensity(pixel); + + + // Change tempearture if needed (unused) + /*if (info.tempChange != undefined) { + pixel.temp += info.tempChange; + pixelTempCheck(pixel); + }*/ + + // Burning + doBurning(pixel); + + // Heat Transfer + if (info.insulate !== true) { + doHeat(pixel); + } + + // Electricity Transfer + doElectricity(pixel); + + // Staining + if (info.stain) { + doStaining(pixel); + } + +} \ No newline at end of file