Code viewer for Mind: Complex Mind (clone by yil...
// Cloned by yilin li on 25 Oct 2021 from World "Enemy Chase Agents" by Minhui Chen 
// Please leave this clone trail here.
AB.clockTick = 100,
AB.maxSteps = 1e3,
AB.screenshotStep = 50;
const show3d = !0,
TEXTURE_WALL = "/uploads/minhui96/wall.jpg",
TEXTURE_MAZE = "/uploads/minhui96/maze.jpg",
TEXTURE_AGENT = "/uploads/minhui96/agent.jpg",
TEXTURE_ENEMY = "/uploads/minhui96/enemy.png",
MUSIC_BACK = "/uploads/starter/Defense.Line.mp3",
SOUND_ALARM = "/uploads/starter/air.horn.mp3",
gridsize = 50,
NOBOXES = Math.trunc(gridsize * gridsize / 3),
squaresize = 100,
MAXPOS = gridsize * squaresize,
SKYCOLOR = 14548957,
startRadiusConst = .8 * MAXPOS,
maxRadiusConst = 10 * MAXPOS;
ABHandler.MAXCAMERAPOS = maxRadiusConst,
ABHandler.GROUNDZERO = !0;
const SKYBOX_ARRAY = ["/uploads/starter/dawnmountain-xpos.png", "/uploads/starter/dawnmountain-xneg.png", "/uploads/starter/dawnmountain-ypos.png", "/uploads/starter/dawnmountain-yneg.png", "/uploads/starter/dawnmountain-zpos.png", "/uploads/starter/dawnmountain-zneg.png"],
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, ei, ej, ai, aj, badsteps, goodsteps, pathline, occ = new Array(gridsize),
GRID = new Array(gridsize);
function loadResources() {
    var e = new THREE.TextureLoader,
    a = new THREE.TextureLoader,
    t = new THREE.TextureLoader,
    i = new THREE.TextureLoader;
    e.load(TEXTURE_WALL,
    function(e) {
        e.minFilter = THREE.LinearFilter,
        wall_texture = e,
        asynchFinished() && initScene()
    }),
    a.load(TEXTURE_AGENT,
    function(e) {
        e.minFilter = THREE.LinearFilter,
        agent_texture = e,
        asynchFinished() && initScene()
    }),
    t.load(TEXTURE_ENEMY,
    function(e) {
        e.minFilter = THREE.LinearFilter,
        enemy_texture = e,
        asynchFinished() && initScene()
    }),
    i.load(TEXTURE_MAZE,
    function(e) {
        e.minFilter = THREE.LinearFilter,
        maze_texture = e,
        asynchFinished() && initScene()
    })
}
function asynchFinished() {
    return !! (wall_texture && agent_texture && enemy_texture && maze_texture)
}
function occupied(e, a) {
    return ei == e && ej == a || (ai == e && aj == a || (occ[e][a] == GRID_WALL || occ[e][a] == GRID_MAZE))
}
function translate(e, a) {
    var t = new THREE.Vector3;
    return t.y = 0,
    t.x = e * squaresize - MAXPOS / 2,
    t.z = a * squaresize - MAXPOS / 2,
    t
}
function initScene() {
    var e, a, t, i;
    for (e = 0; e < gridsize; e++) GRID[e] = new Array(gridsize);
    for (e = 0; e < gridsize; e++) occ[e] = new Array(gridsize);
    for (e = 0; e < gridsize; e++) for (a = 0; a < gridsize; a++) 0 === e || e == gridsize - 1 || 0 === a || a == gridsize - 1 ? (occ[e][a] = GRID_WALL, t = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), (i = new THREE.Mesh(t)).material = new THREE.MeshBasicMaterial({
        map: wall_texture
    }), i.position.copy(translate(e, a)), ABWorld.scene.add(i)) : occ[e][a] = GRID_BLANK;
    for (var o = 1; o <= NOBOXES; o++) e = AB.randomIntAtoB(1, gridsize - 2),
    a = AB.randomIntAtoB(1, gridsize - 2),
    occ[e][a] = GRID_MAZE,
    t = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize),
    (i = new THREE.Mesh(t)).material = new THREE.MeshBasicMaterial({
        map: maze_texture
    }),
    i.position.copy(translate(e, a)),
    ABWorld.scene.add(i);
    for (e = 0; e < gridsize; e++) for (a = 0; a < gridsize; a++) GRID[e][a] = new Spot(e, a);
    for (e = 0; e < gridsize; e++) for (a = 0; a < gridsize; a++) GRID[e][a].addNeighbors(GRID);
    console.table(GRID);
    do {
        e = AB.randomIntAtoB(1, gridsize - 2), a = AB.randomIntAtoB(1, gridsize - 2)
    } while ( occupied ( e , a ));
    ei = e,
    ej = a,
    t = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize),
    (theenemy = new THREE.Mesh(t)).material = new THREE.MeshBasicMaterial({
        map: enemy_texture
    }),
    ABWorld.scene.add(theenemy),
    drawEnemy();
    do {
        e = AB.randomIntAtoB(1, gridsize - 2), a = AB.randomIntAtoB(1, gridsize - 2)
    } while ( occupied ( e , a ));
    ai = e,
    aj = a,
    t = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize),
    (theagent = new THREE.Mesh(t)).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)
}
const linecolor = 6750003;
function heuristic(e, a) {
    var t = new THREE.Vector3(e.i, 0, e.j),
    i = new THREE.Vector3(a.i, 0, a.j);
    return t.distanceTo(i)
}
function removeFromArray(e, a) {
    for (var t = e.length - 1; t >= 0; t--) e[t] == a && e.splice(t, 1)
}
function Spot(e, a) {
    this.i = e,
    this.j = a,
    this.f = 0,
    this.g = 0,
    this.h = 0,
    this.neighbors = [],
    this.previous = void 0,
    0 === occ[e][a] ? this.obstacle = !1 : this.obstacle = !0,
    this.addNeighbors = function(e) {
        var a = this.i,
        t = this.j;
        a < gridsize - 1 && this.neighbors.push(e[a + 1][t]),
        a > 0 && this.neighbors.push(e[a - 1][t]),
        t < gridsize - 1 && this.neighbors.push(e[a][t + 1]),
        t > 0 && this.neighbors.push(e[a][t - 1]),
        a > 0 && t > 0 && this.neighbors.push(e[a - 1][t - 1]),
        a < gridsize - 1 && t > 0 && this.neighbors.push(e[a + 1][t - 1]),
        a > 0 && t < gridsize - 1 && this.neighbors.push(e[a - 1][t + 1]),
        a < gridsize - 1 && t < gridsize - 1 && this.neighbors.push(e[a + 1][t + 1])
    }
}
function trap() {
    return ! 1 === GRID[ai - 1][aj].obstacle && !0 === GRID[ai + 1][aj].obstacle && !0 === GRID[ai][aj - 1].obstacle && !0 === GRID[ai][aj + 1].obstacle ? 0 : !0 === GRID[ai - 1][aj].obstacle && !1 === GRID[ai + 1][aj].obstacle && !0 === GRID[ai][aj - 1].obstacle && !0 === GRID[ai][aj + 1].obstacle ? 1 : !0 === GRID[ai - 1][aj].obstacle && !0 === GRID[ai + 1][aj].obstacle && !1 === GRID[ai][aj - 1].obstacle && !0 === GRID[ai][aj + 1].obstacle ? 2 : !0 === GRID[ai - 1][aj].obstacle && !0 === GRID[ai + 1][aj].obstacle && !0 === GRID[ai][aj - 1].obstacle && !1 === GRID[ai][aj + 1].obstacle ? 3 : 4
}
function enemyPath() {
    var e, a, t = [],
    o = [],
    n = [];
    switch (e = GRID[ei][ej], trap()) {
    case 0:
        a = GRID[ai - 1][aj];
        break;
    case 1:
        a = GRID[ai + 1][aj];
        break;
    case 2:
        a = GRID[ai][aj - 1];
        break;
    case 3:
        a = GRID[ai][aj + 1];
        break;
    case 4:
        a = GRID[ai][aj]
    }
    t.push(e);
    for (var r = !1; t.length > 0;) {
        var s = 0;
        for (i = 0; i < t.length; i++) t[i].f < t[s].f && (s = i);
        var c = t[s];
        if (c === a) {
            console.log("Done"),
            r = !0;
            break
        }
        removeFromArray(t, c),
        o.push(c);
        var u = c.neighbors;
        for (i = 0; i < u.length; i++) {
            var d = u[i];
            if (!o.includes(d) && !d.obstacle) {
                var l = c.g + heuristic(d, c);
                console.log("tempG" + l),
                console.log("tempG" + l);
                var g = !1;
                t.includes(d) ? l < d.g && (d.g = l, g = !0) : (d.g = l, g = !0, t.push(d)),
                g && (d.h = heuristic(d, a), d.f = d.g + d.h, console.log("FFFF:" + d.f), d.previous = c)
            }
        }
    }
    if (!1 === r) return console.log("fail"),
    n;
    console.log("time for find path: 0"),
    console.log("enemy current: " + ei + "," + ej);
    var p = c,
    A = c;
    for (n.push(p); p.previous;) n.push(p.previous),
    p = p.previous,
    A.previous = void 0,
    A = p;
    return n
}
function drawPath(e) {
    pathline && ABWorld.scene.remove(pathline),
    e.pop();
    var a = [];
    for (const i of e) {
        var t = translate(i.i, i.j);
        a.push(t)
    }
    var i = new THREE.LineBasicMaterial({
        color: linecolor
    }),
    o = (new THREE.BufferGeometry).setFromPoints(a);
    pathline = new THREE.Line(o, i),
    ABWorld.scene.add(pathline)
}
function moveLogicalEnemy() {
    var e, a, t = enemyPath();
    if (! (t.length > 0)) return console.log("Fail!");
    t.pop(),
    e = t[t.length - 1].i,
    a = t[t.length - 1].j,
    drawPath(t),
    occupied(e, a) || (ei = e, ej = a),
    console.log("enemy moveto:" + ei + "," + ej)
}
function moveLogicalAgent(e) {
    var a = ai,
    t = aj;
    e == ACTION_LEFT ? a--:e == ACTION_RIGHT ? a++:e == ACTION_UP ? t++:e == ACTION_DOWN && t--,
    occupied(a, t) || (ai = a, aj = t)
}
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 a = AB.world.getState();
    AB.msg(" Step: " + AB.step + " &nbsp; x = (" + a.toString() + ") &nbsp; a = (" + e + ") ")
}
function updateStatusAfter() {
    var e = AB.world.getState(),
    a = goodsteps / AB.step * 100;
    AB.msg(" &nbsp; y = (" + e.toString() + ") <br> Bad steps: " + badsteps + " &nbsp; Good steps: " + goodsteps + " &nbsp; Score: " + a.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.abortRun ? AB.msg(" <br> <font color=red> <B> Agent trapped. Final score zero. </B> </font>   ", 3) : AB.msg(" <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()
}