Code viewer for World: Facebook
AB.clockTick = 100, AB.maxSteps = 1e3, AB.screenshotStep = 50;
const show3d = !0,
    TEXTURE_AGENT = "/uploads/drummk2/Laurie_Strode.jpg",
    TEXTURE_ENEMY = "/uploads/drummk2/Michael_Myers.jpg",
    TEXTURE_MAZE = "/uploads/starter/latin.jpg",
    TEXTURE_PATH = "/uploads/drummk2/Pool_Of_Blood.jpg",
    TEXTURE_WALL = "/uploads/drummk2/Dark_Brick_Wall.jpg",
    MUSIC_BACK = "/uploads/drummk2/Creepy.mp3",
    SOUND_ALARM = "/uploads/starter/air.horn.mp3",
    gridsize = 50,
    NOBOXES = Math.trunc(gridsize * gridsize / 8),
    squaresize = 100,
    MAXPOS = gridsize * squaresize,
    SKYCOLOR = 14548957,
    startRadiusConst = .8 * MAXPOS,
    maxRadiusConst = 10 * MAXPOS,
    wallCutOff = AB.randomFloatAtoB(0, .6);
ABHandler.MAXCAMERAPOS = maxRadiusConst, ABHandler.GROUNDZERO = !0;
const SKYBOX_ARRAY = ["/uploads/starter/sky_pos_z.jpg", "/uploads/starter/sky_neg_z.jpg", "/uploads/starter/sky_pos_y.jpg", "/uploads/starter/sky_neg_y.jpg", "/uploads/starter/sky_pos_x.jpg", "/uploads/starter/sky_neg_x.jpg"];

function Square(e, t, i, n) {
    this.uniqueId, this.i = e, this.j = t, this.f = 0, this.g = 0, this.h = 0, this.neighbors = [], this.previous = void 0, this.squareType = i, this.isWall = n, this.show = function() {
        shape = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), thecube = new THREE.Mesh(shape), this.squareType == GRID_WALL ? thecube.material = new THREE.MeshBasicMaterial({
            map: wall_texture
        }) : this.squareType == GRID_MAZE && (thecube.material = new THREE.MeshBasicMaterial({
            map: maze_texture
        })), thecube.position.copy(translate(this.i, this.j)), ABWorld.scene.add(thecube)
    }, this.highlight = function(e) {
        if (e) shape = new THREE.BoxGeometry(squaresize, .001, squaresize), thecube = new THREE.Mesh(shape), thecube.material = new THREE.MeshBasicMaterial({
            map: path_texture
        }), thecube.position.copy(translate(this.i, this.j)), ABWorld.scene.add(thecube), this.uniqueId = thecube.uuid;
        else {
            var t = ABWorld.scene.getObjectByProperty("uuid", this.uniqueId);
            ABWorld.scene.remove(t), this.uniqueId = null
        }
    }, this.addNeighbors = function(e) {
        this.i < gridsize - 1 && this.neighbors.push(e[this.i + 1][this.j]), this.i > 0 && this.neighbors.push(e[this.i - 1][this.j]), this.j < gridsize - 1 && this.neighbors.push(e[this.i][this.j + 1]), this.j > 0 && this.neighbors.push(e[this.i][this.j - 1])
    }
}
const ACTION_LEFT = 0,
    ACTION_RIGHT = 1,
    ACTION_UP = 2,
    ACTION_DOWN = 3,
    ACTION_STAYSTILL = 4,
    GRID_BLANK = 0,
    GRID_WALL = 1,
    GRID_MAZE = 2;
var BOXHEIGHT, theagent, theenemy, wall_texture, agent_texture, enemy_texture, maze_texture, path_texture, ei, ej, ai, aj, badsteps, goodsteps, GRID = new Array(gridsize),
    closedSet = [],
    openSet = [],
    path = [];

function loadResources() {
    var e = new THREE.TextureLoader,
        t = new THREE.TextureLoader,
        i = new THREE.TextureLoader,
        n = new THREE.TextureLoader,
        s = new THREE.TextureLoader;
    e.load(TEXTURE_WALL, function(e) {
        e.minFilter = THREE.LinearFilter, wall_texture = e, asynchFinished() && initScene()
    }), t.load(TEXTURE_AGENT, function(e) {
        e.minFilter = THREE.LinearFilter, agent_texture = e, asynchFinished() && initScene()
    }), i.load(TEXTURE_ENEMY, function(e) {
        e.minFilter = THREE.LinearFilter, enemy_texture = e, asynchFinished() && initScene()
    }), n.load(TEXTURE_MAZE, function(e) {
        e.minFilter = THREE.LinearFilter, maze_texture = e, asynchFinished() && initScene()
    }), s.load(TEXTURE_PATH, function(e) {
        e.minFilter = THREE.LinearFilter, path_texture = e, asynchFinished() && initScene()
    })
}

function asynchFinished() {
    return wall_texture && agent_texture && enemy_texture && maze_texture && path_texture
}

function occupied(e, t) {
    return ei === e && ej === t || (ai === e && aj === t || (GRID[e][t].squareType === GRID_WALL || GRID[e][t].squareType === GRID_MAZE))
}

function translate(e, t) {
    var i = new THREE.Vector3;
    return i.y = 0, i.x = e * squaresize - MAXPOS / 2, i.z = t * squaresize - MAXPOS / 2, i
}

function initScene() {
    var e, t, i;
    for (e = 0; e < gridsize; e++) GRID[e] = new Array(gridsize);
    for (e = 0; e < gridsize; e++)
        for (t = 0; t < gridsize; t++) 0 === e || e === gridsize - 1 || 0 === t || t === gridsize - 1 ? (GRID[e][t] = new Square(e, t, GRID_WALL, !0), GRID[e][t].show()) : GRID[e][t] = new Square(e, t, GRID_BLANK, !1);
    for (var n = 1; n <= NOBOXES; n++) e = AB.randomIntAtoB(1, gridsize - 2), t = AB.randomIntAtoB(1, gridsize - 2), GRID[e][t] = new Square(e, t, GRID_MAZE, !0), GRID[e][t].show();
    for (e = 0; e < gridsize; e++)
        for (t = 0; t < gridsize; t++) GRID[e][t].addNeighbors(GRID);
    do {
        e = AB.randomIntAtoB(1, gridsize - 2), t = AB.randomIntAtoB(1, gridsize - 2)
    } while (occupied(e, t));
    ei = e, ej = t, i = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), (theenemy = new THREE.Mesh(i)).material = new THREE.MeshBasicMaterial({
        map: enemy_texture
    }), ABWorld.scene.add(theenemy), drawEnemy();
    do {
        e = AB.randomIntAtoB(1, gridsize - 2), t = AB.randomIntAtoB(1, gridsize - 2)
    } while (occupied(e, t));
    ai = e, aj = t, i = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), (theagent = new THREE.Mesh(i)).material = new THREE.MeshBasicMaterial({
        map: agent_texture
    }), ABWorld.scene.add(theagent), drawAgent(), ABWorld.scene.background = (new THREE.CubeTextureLoader).load(SKYBOX_ARRAY, function() {
        ABWorld.render(), AB.removeLoading(), AB.runReady = !0
    })
}

function drawEnemy() {
    theenemy.position.copy(translate(ei, ej)), ABWorld.lookat.copy(theenemy.position)
}

function drawAgent() {
    theagent.position.copy(translate(ai, aj)), ABWorld.follow.copy(theagent.position)
}

function heuristic(e, t) {
    return Math.abs(e.i - t.i) + Math.abs(e.j - t.j)
}

function determineNextStep() {
    console.log("Determining the ideal move from (" + ei + ", " + ej + ").");
    for (const e of path) e.highlight(!1);
    closedSet.splice(0, closedSet.length), openSet.splice(0, openSet.length), path.splice(0, path.length);
    var e = GRID[ei][ej];
    for (openSet.push(e); openSet.length > 0;) {
        for (var t = 0, i = 0; i < openSet.length; i++) openSet[i].f < openSet[t].f && (t = i);
        var n = openSet[t],
            s = GRID[ai][aj];
        if (n === s) {
            for (var a = n; a.previous !== e;) a.highlight(!0), path.push(a), a = a.previous;
            return console.log("Search complete - moving to (" + a.i + ", " + a.j + ")."), a
        }
        openSet.splice(openSet.indexOf(n), 1), closedSet.push(n);
        var r = n.neighbors;
        for (i = 0; i < r.length; i++) {
            var o = r[i];
            if (!closedSet.includes(o) && !o.isWall) {
                var u = n.g + heuristic(o, n),
                    d = !1;
                openSet.includes(o) ? u < o.g && (o.g = u, d = !0) : (o.g = u, d = !0, openSet.push(o)), d && (o.h = heuristic(o, s), o.f = o.g + o.h, o.previous = n)
            }
        }
    }
}

function moveLogicalEnemy() {
    var e = determineNextStep();
    occupied(e.i, e.j) || (ei = e.i, ej = e.j)
}

function moveLogicalAgent(e) {
    var t = ai,
        i = aj;
    e == ACTION_LEFT ? t-- : e == ACTION_RIGHT ? t++ : e == ACTION_UP ? i++ : e == ACTION_DOWN && i--, occupied(t, i) || (ai = t, aj = i)
}
var OURKEYS = [37, 38, 39, 40];

function ourKeys(e) {
    return OURKEYS.includes(e.keyCode)
}

function keyHandler(e) {
    return !AB.runReady || (!ourKeys(e) || (37 == e.keyCode && moveLogicalAgent(ACTION_LEFT), 38 == e.keyCode && moveLogicalAgent(ACTION_DOWN), 39 == e.keyCode && moveLogicalAgent(ACTION_RIGHT), 40 == e.keyCode && moveLogicalAgent(ACTION_UP), e.stopPropagation(), e.preventDefault(), !1))
}

function badstep() {
    return Math.abs(ei - ai) < 2 && Math.abs(ej - aj) < 2
}

function agentBlocked() {
    return occupied(ai - 1, aj) && occupied(ai + 1, aj) && occupied(ai, aj + 1) && occupied(ai, aj - 1)
}

function updateStatusBefore(e) {
    var t = AB.world.getState();
    AB.msg("Step: " + AB.step + " &nbsp; x = (" + t.toString() + ") &nbsp; a = (" + e + ") ")
}

function updateStatusAfter() {
    var e = AB.world.getState(),
        t = goodsteps / AB.step * 100;
    AB.msg(" &nbsp; y = (" + e.toString() + ") <br> Bad steps: " + badsteps + " &nbsp; Good steps: " + goodsteps + " &nbsp; Score: " + t.toFixed(2) + "% ", 2)
}
AB.world.newRun = function() {
    AB.loadingScreen(), AB.runReady = !1, badsteps = 0, goodsteps = 0, BOXHEIGHT = squaresize, ABWorld.init3d(startRadiusConst, maxRadiusConst, 14548957), loadResources(), document.onkeydown = keyHandler
}, AB.world.getState = function() {
    return [ai, aj, ei, ej]
}, AB.world.takeAction = function(e) {
    updateStatusBefore(e), moveLogicalAgent(e), AB.step % 2 == 0 && moveLogicalEnemy(), badstep() ? badsteps++ : goodsteps++, drawAgent(), drawEnemy(), updateStatusAfter(), agentBlocked() && (AB.abortRun = !0, goodsteps = 0, musicPause(), soundAlarm())
}, AB.world.endRun = function() {
    musicPause(), AB.msg(AB.abortRun ? "<br> <font color=red> <B> Agent trapped. Final score zero. </B> </font>" : "<br> <font color=green> <B> Run over. </B> </font>", 3)
}, AB.world.getScore = function() {
    var e = goodsteps / AB.maxSteps * 100;
    return Math.round(100 * e) / 100
};
var backmusic = AB.backgroundMusic(MUSIC_BACK);

function musicPlay() {
    backmusic.play()
}

function musicPause() {
    backmusic.pause()
}

function soundAlarm() {
    new Audio(SOUND_ALARM).play()
}