polyominoGenerator = function() {
var Point = function(x, y) {
for(i = 0; i < arguments.length; i += 2) {
pointArray[i/2] = Point(arguments[i], arguments[i+1]);
var PieceSpecial = function(array) {
for(var i = 0; i < array.length; i += 2) {
pointArray.push(Point(array[i], array[i+1]));
this.returnPolyominos = function (num) {
if(typeof num != "number") {
console.error("For some reason what you entered is not a number.");
return generatePolyominos(num);
var generatePolyominos = function(num) {
var start_time = Date.now();
pieceArray[0] = Piece(0, 0);
var end_time = Date.now();
prevPolyominos = generatePolyominos(num - 1);
for(var i = 0; i < prevPolyominos.length; i++) {
testPolyominos.push(copyPolyomino(prevPolyominos[i]));
testPolyominos.push(rotatePointsClockWise(copyPolyomino(prevPolyominos[i])));
testPolyominos.push(flipPointsVertically(rotatePointsClockWise(copyPolyomino(prevPolyominos[i]))));
testPolyominos.push(flipPointsHorizontally(rotatePointsClockWise(copyPolyomino(prevPolyominos[i]))));
testPolyominos.push(rotatePointsClockWise(rotatePointsClockWise(copyPolyomino(prevPolyominos[i]))));
testPolyominos.push(flipPointsVertically(rotatePointsClockWise(rotatePointsClockWise(copyPolyomino(prevPolyominos[i])))));
testPolyominos.push(flipPointsHorizontally(rotatePointsClockWise(rotatePointsClockWise(copyPolyomino(prevPolyominos[i])))));
testPolyominos.push(rotatePointsClockWise(rotatePointsClockWise(rotatePointsClockWise(copyPolyomino(prevPolyominos[i])))));
testPolyominos.push(flipPointsVertically(rotatePointsClockWise(rotatePointsClockWise(rotatePointsClockWise(copyPolyomino(prevPolyominos[i]))))));
testPolyominos.push(flipPointsHorizontally(rotatePointsClockWise(rotatePointsClockWise(rotatePointsClockWise(copyPolyomino(prevPolyominos[i]))))));
for(var j = 0; j < testPolyominos.length; j++) {
testPolyominos[j] = normalizePolyomino(testPolyominos[j]);
newPolyominos = checkAndAddNewPiece(testPolyominos[j], newPolyominos);
var end_time = Date.now();
var checkAndAddNewPiece = function(polycopy, newPolyominos) {
for(var j = 0; j < polycopy.pointArray.length; j++) {
for(var k = 0 ; k < 2; k++) {
var newpoint = Point(polycopy.pointArray[j].x + 1, polycopy.pointArray[j].y);
if(pointArrayContains(newpoint, polycopy.pointArray)) continue;
var newPointArray = copyPointArray(polycopy.pointArray);
newPointArray.push(newpoint);
pointArray: newPointArray
if(!PieceContains(newPiece, newPolyominos)) {
newPolyominos.push(newPiece);
var newpoint = Point(polycopy.pointArray[j].x, polycopy.pointArray[j].y + 1);
if(pointArrayContains(newpoint, polycopy.pointArray)) continue;
var newPointArray = copyPointArray(polycopy.pointArray);
newPointArray.push(newpoint);
pointArray: newPointArray
if(!PieceContains(newPiece, newPolyominos)) {
newPolyominos.push(newPiece);
var rotatePointsClockWise = function(piece) {
for(i = 0; i < piece.pointArray.length; i++) {
piece.pointArray[i] = Point(piece.pointArray[i].y, -piece.pointArray[i].x);
var flipPointsVertically = function(piece) {
for(i = 0; i < piece.pointArray.length; i++) {
piece.pointArray[i] = Point(-piece.pointArray[i].x, piece.pointArray[i].y);
var flipPointsHorizontally = function(piece) {
for(i = 0; i < piece.pointArray.length; i++) {
piece.pointArray[i] = Point(piece.pointArray[i].x, -piece.pointArray[i].y);
var pieceEquals = function(pieceA, pieceB) {
var pieceARotated = rotatePointsClockWise(copyPolyomino(pieceA)),
pieceARotatedTwice = rotatePointsClockWise(copyPolyomino(pieceARotated)),
pieceARotatedThrice = rotatePointsClockWise(copyPolyomino(pieceARotatedTwice)),
pieceAFlippedVertically = flipPointsVertically(copyPolyomino(pieceA)),
pieceAFlippedHorizontally = flipPointsHorizontally(copyPolyomino(pieceA)),
pieceAR1FV = flipPointsVertically(rotatePointsClockWise(copyPolyomino(pieceA))),
pieceAR1FH = flipPointsHorizontally(rotatePointsClockWise(copyPolyomino(pieceA))),
pieceAR2FV = flipPointsVertically(rotatePointsClockWise(copyPolyomino(pieceARotated))),
pieceAR2FH = flipPointsHorizontally(rotatePointsClockWise(copyPolyomino(pieceARotated))),
pieceAR3FV = flipPointsVertically(rotatePointsClockWise(copyPolyomino(pieceARotatedTwice))),
pieceAR3FH = flipPointsHorizontally(rotatePointsClockWise(copyPolyomino(pieceARotatedTwice))),
pointArrayA = pieceA.pointArray,
pointArrayB = pieceB.pointArray,
pointArrayARotated = normalizePoints(pieceARotated.pointArray),
pointArrayARotatedTwice = normalizePoints(pieceARotatedTwice.pointArray),
pointArrayARotatedThrice = normalizePoints(pieceARotatedThrice.pointArray),
pointArrayAFlippedVertically = normalizePoints(pieceAFlippedVertically.pointArray),
pointArrayAFlippedHorizontally = normalizePoints(pieceAFlippedHorizontally.pointArray),
pointArrayAR1FV = normalizePoints(pieceAR1FV.pointArray),
pointArrayAR1FH = normalizePoints(pieceAR1FH.pointArray),
pointArrayAR2FV = normalizePoints(pieceAR2FV.pointArray),
pointArrayAR2FH = normalizePoints(pieceAR2FH.pointArray),
pointArrayAR3FV = normalizePoints(pieceAR3FV.pointArray),
pointArrayAR3FH = normalizePoints(pieceAR3FH.pointArray);
return samePointArray(pointArrayA, pointArrayB)
samePointArray(pointArrayARotated, pointArrayB)
samePointArray(pointArrayARotatedTwice, pointArrayB)
samePointArray(pointArrayARotatedThrice, pointArrayB)
samePointArray(pointArrayAFlippedHorizontally, pointArrayB)
samePointArray(pointArrayAFlippedVertically, pointArrayB)
samePointArray(pointArrayAR1FV, pointArrayB)
samePointArray(pointArrayAR1FH, pointArrayB)
samePointArray(pointArrayAR2FV, pointArrayB)
samePointArray(pointArrayAR2FH, pointArrayB)
samePointArray(pointArrayAR3FV, pointArrayB)
samePointArray(pointArrayAR3FH, pointArrayB);
var pointArrayContains = function (point, pointArray) {
for(var i = 0; i < pointArray.length; i++) {
if(pointsEqual(point, pointArray[i])) {
var pointsEqual = function(pointA, pointB) {
return pointA.x === pointB.x && pointA.y === pointB.y;
var copyPolyomino = function(polyomino) {
var array = copyPointArray(polyomino.pointArray);
for(var i = 0; i < array.length; i++) {
numArray.push(array[i].x);
numArray.push(array[i].y);
var copiedPiece = PieceSpecial(numArray);
var copyPointArray = function(pointArray) {
for(var i = 0; i < pointArray.length; i++) {
newArray.push(Point(pointArray[i].x, pointArray[i].y));
var PieceContains = function(Piece, pieceArray) {
for(var i = 0; i < pieceArray.length; i++) {
if(pieceEquals(Piece, pieceArray[i])) {
var samePointArray = function(pointArrayA, pointArrayB) {
if (pointArrayA.length !== pointArrayB.length) {
alert("You stupid! The pieces aren't even the same kind!")
for(var i = 0; i < pointArrayA.length; i++) {
if(!pointArrayContains(pointArrayA[i], pointArrayB)) {
var normalizePoints = function(pointArray) {
var minX = Number.POSITIVE_INFINITY,
minY = Number.POSITIVE_INFINITY;
for(var i = 0; i < pointArray.length; i++) {
if(pointArray[i].x < minX) {
if(pointArray[i].y < minY) {
for(var i = 0; i < pointArray.length; i++) {
pointArray[i].x += (-minX);
for(var i = 0; i < pointArray.length; i++) {
pointArray[i].y += (-minY);
var normalizePolyomino = function(piece) {
pointArray: normalizePoints(piece.pointArray)