-
-
Save jacmoe/c8ca0f2e9150688388e95fa07e211b22 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var reducePath = function (x, y, entryOffset, rangeOffset, entryRequiredWall, entryDisallowedWall) { | |
var rangeEntryRequiredDirections = [entryDisallowedWall, OppositeDirections[entryDisallowedWall]]; | |
var rangeEntryDisallowedDirections = [entryRequiredWall, OppositeDirections[entryRequiredWall]]; | |
var endDisallowedDirections = [OppositeDirections[entryRequiredWall], OppositeDirections[entryDisallowedWall]]; | |
var endRequiredDirections = [entryRequiredWall, entryDisallowedWall]; | |
var tile = tiles[x][y]; | |
var color = tile.color; | |
var entry = tiles[x+entryOffset[0]][y+entryOffset[1]]; | |
// make sure theres a path from below | |
if (!entry.walls[entryRequiredWall] || | |
entry.walls[entryDisallowedWall]) { | |
return false; | |
} | |
// seed the next tile and starting tile for evaluation | |
var endX = x+rangeOffset[0]; | |
var endY = y+rangeOffset[1]; | |
var end = tiles[endX][endY]; | |
var entry = tiles[endX+entryOffset[0]][endY+entryOffset[1]]; | |
// loop while the next tile continues as the boundary of the "U" | |
while (end.walls[rangeEntryRequiredDirections[0]] && | |
!end.walls[rangeEntryDisallowedDirections[0]] && | |
!end.walls[rangeEntryDisallowedDirections[1]]) { | |
if (entry.color !== EMPTY_COLOR) { | |
// if the entry to the tile isn't a U, it must have walls | |
// on both sides perpindicular to the entry direction | |
var dirs = Object.keys(entry.walls); | |
if (dirs.length !== 2 || dirs[0] != OppositeDirections[dirs[1]]) { | |
return false; | |
} | |
} | |
endX += rangeOffset[0]; | |
endY += rangeOffset[1]; | |
end = tiles[endX][endY]; | |
entry = tiles[endX+entryOffset[0]][endY+entryOffset[1]]; | |
} | |
var endWallDirs = Object.keys(end.walls); | |
if (endWallDirs.length !== 2) { | |
// end wall must be a corner | |
return false; | |
} | |
for (var key in endWallDirs) { | |
if (key === entryDisallowedWall) { | |
continue; | |
} else if (!tile.walls[key] && key !== OppositeDirections[entryDisallowedWall]) { | |
// if the wall doesn't exist on the origin and it's not blocking off | |
// the direction we're collapsing into, it should be safe | |
continue; | |
} | |
return false; | |
} | |
var endDown = tiles[endX+entryOffset[0]][endY+entryOffset[1]]; | |
if (endDown.color === EMPTY_COLOR || | |
!endDown.walls[OppositeDirections[entryRequiredWall]] || | |
endDown.walls[entryDisallowedWall]) { | |
return false; | |
} | |
var startWalls = {}; | |
for (var key in tile.walls) { | |
startWalls = tile.walls[key]; | |
delete startWalls[entryDisallowedWall]; | |
} | |
for (var xOffset = 0, xIters = Math.abs(endX - x); xOffset <= xIters; xOffset++) { | |
var changeX = Math.min(x, endX) + xOffset; | |
for (var yOffset = 0, yIters = Math.abs(endY - y); yOffset <= yIters; yOffset++) { | |
var changeY = Math.min(y, endY) + yOffset; | |
var entryX = changeX+entryOffset[0]; | |
var entryY = changeY+entryOffset[1]; | |
entry = tiles[entryX][entryY]; | |
entry.walls[entryDisallowedWall] = true; | |
var checkOffset, checkIters, checkMin, checkMax; | |
if (rangeOffset[0] !== 0) { | |
checkOffset = xOffset; | |
checkIters = xIters; | |
checkMin = rangeOffset[0] > 0 ? xIters : 0; | |
checkMax = rangeOffset[0] > 0 ? 0 : xIters; | |
} else { | |
checkOffset = yOffset; | |
checkIters = yIters; | |
checkMin = rangeOffset[1] > 0 ? yIters : 0; | |
checkMax = rangeOffset[1] > 0 ? 0 : yIters; | |
} | |
if (checkOffset > 0 && checkOffset < checkIters) { | |
if (entry.color === EMPTY_COLOR) { | |
entry.walls[OppositeDirections[entryDisallowedWall]] = true; | |
} | |
entry.walls[entryRequiredWall] = true; | |
entry.walls[OppositeDirections[entryRequiredWall]] = true; | |
} | |
if (checkOffset !== checkMin) { | |
delete entry.walls[entryRequiredWall]; | |
} | |
if (checkOffset !== checkMax) { | |
delete entry.walls[OppositeDirections[entryRequiredWall]]; | |
} | |
entry.color = color; | |
tile = tiles[changeX][changeY]; | |
tile.walls = {}; | |
tile.color = EMPTY_COLOR; | |
} | |
} | |
return true; | |
}; | |
var reduceNorth = function(x, y) { | |
var entryOffset = [0, -1]; | |
var rangeOffset = [1, 0]; | |
var entryRequiredWall = Directions.EAST; | |
var entryDisallowedWall = Directions.SOUTH; | |
return reducePath(x, y, entryOffset, rangeOffset, entryRequiredWall, entryDisallowedWall); | |
}; | |
var reduceSouth = function(x, y) { | |
var entryOffset = [0, 1]; | |
var rangeOffset = [1, 0]; | |
var entryRequiredWall = Directions.EAST; | |
var entryDisallowedWall = Directions.NORTH; | |
return reducePath(x, y, entryOffset, rangeOffset, entryRequiredWall, entryDisallowedWall); | |
}; | |
var reduceEast = function(x, y) { | |
var entryOffset = [1, 0]; | |
var rangeOffset = [0, 1]; | |
var entryRequiredWall = Directions.SOUTH; | |
var entryDisallowedWall = Directions.WEST; | |
return reducePath(x, y, entryOffset, rangeOffset, entryRequiredWall, entryDisallowedWall); | |
}; | |
var reduceWest = function(x, y) { | |
var entryOffset = [-1, 0]; | |
var rangeOffset = [0, 1]; | |
var entryRequiredWall = Directions.SOUTH; | |
var entryDisallowedWall = Directions.EAST; | |
return reducePath(x, y, entryOffset, rangeOffset, entryRequiredWall, entryDisallowedWall); | |
}; | |
var reduceSlack = function() { | |
var count = 0; | |
do { | |
var found = false; | |
for (var x = 0; x <= MAX_X; x++) { | |
for (var y = 0; y <= MAX_Y; y++) { | |
var tile = tiles[x][y]; | |
var walls = tile.walls; | |
var dirs = Object.keys(walls); | |
var singleFound = false; | |
if (dirs.length !== 2) continue; | |
if (walls[Directions.NORTH]) { | |
if (walls[Directions.WEST]) { | |
if (y < MAX_Y) { | |
// top left corner could mean merging a slack path south | |
singleFound = reduceSouth(x, y); | |
} | |
if (!singleFound && x < MAX_X) { | |
// top left corner could mean merging a slack path east | |
singleFound = reduceEast(x, y); | |
} | |
} else if (walls[Directions.EAST] && x > 0) { | |
// top right corner could mean merging a slack path west | |
singleFound = reduceWest(x, y); | |
} | |
} else if (walls[Directions.SOUTH] && y > 0 && walls[Directions.WEST]) { | |
// bottom left corner could mean merging a slack path north | |
singleFound = reduceNorth(x, y); | |
} | |
if (singleFound) { | |
found = true; | |
count++; | |
} | |
if (SHOULD_DEMO && count > 10) { | |
return false; | |
} | |
} | |
} | |
} while (found); | |
return true; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment