Recursive puzzle

This sketch simulates a recursive sliding puzzle. Click the screen to increase or decrease the level of recursion. Original photo by Sukanto Debnath: http://www.flickr.com/photos/sukanto_debnath/2354607553

by Javier Graciá Carpio

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

JavaScript

var sketch = function (p) {
    // Global variables
    var img, puzzle, step;
    var pieceSize = 64;
    var minPieceSize = pieceSize;
    var nSteps = 16;

    // Load the image before the sketch is run
    p.preload = function () {
        // Picture from Sukanto Debnath
        // http://www.flickr.com/photos/sukanto_debnath/2354607553
        img = p.loadImage("http://farm3.staticflickr.com/2340/2354607553_9996a0c8fc.jpg");
    };

    // Initial setup
    p.setup = function () {
        // Resize the image to fit the pieces size
        img.resize(pieceSize * Math.floor(img.width / pieceSize), pieceSize * Math.floor(img.height / pieceSize));

        // Create the canvas
        var canvas = p.createCanvas(img.width, img.height);
        p.frameRate(20);

        // Initiate a new puzzle each time the mouse is pressed inside the canvas
        canvas.mousePressed(newPuzzle);

        // Initiate a new puzzle
        newPuzzle();
    };

    // Execute the sketch
    p.draw = function () {
        // Clean the canvas
        p.background(255);

        // Paint the puzzle
        puzzle.paint();

        // Move the puzzle piece and all its sub-puzzles
        puzzle.movePiece(nSteps);
        step++;

        // Calculate the next movement
        if (step === nSteps) {
            puzzle.nextMove();
            step = 0;
        }
    };

    //
    // This function starts a new puzzle
    //
    function newPuzzle() {
        // Decrease or increment the minimum piece size
        minPieceSize /= 4;

        if (minPieceSize < 4) {
            minPieceSize = 64;
        }

        // Initiate the puzzle and start the step counter
        puzzle = new Puzzle(p.createVector(0, 0), pieceSize, img);
        puzzle.nextMove();
        step = 0;
    }

    //
    // The Hole class
    //
    function Hole(pos, size) {
        this.pos = pos.copy();
        this.size = size;
        this.movementDir = p.createVector();
    }

    //
    // Calculate the next...