Code viewer for World: Amazon

// Cloned by MrDheer on 24 Sep 2022 from World "Complex World" by Starter user 
// Please leave this clone trail here.
 



// ==== Starter World =================================================================================================
// This code is designed for use on the Ancient Brain site.
// This code may be freely copied and edited by anyone on the Ancient Brain site.
// To include a working run of this program on another site, see the "Embed code" links provided on Ancient Brain.
// ====================================================================================================================



// =============================================================================================
// More complex starter World 
// 3d-effect Maze World (really a 2-D problem)
// Movement is on a semi-visible grid of squares 
//
// This more complex World shows:
// - Skybox
// - Internal maze (randomly drawn each time)
// - Enemy actively chases agent
// - Music/audio
// - 2D world (clone this and set show3d = false)
// - User keyboard control (clone this and comment out Mind actions to see)
// =============================================================================================


// =============================================================================================
// Scoring:
// Bad steps = steps where enemy is within one step of agent.
// Good steps = steps where enemy is further away. 
// Score = good steps as percentage of all steps.
//
// There are situations where agent is trapped and cannot move.
// If this happens, you score zero.
// =============================================================================================


 





// ===================================================================================================================
// === Start of tweaker's box ======================================================================================== 
// ===================================================================================================================

// The easiest things to modify are in this box.
// You should be able to change things in this box without being a JavaScript programmer.
// Go ahead and change some of these. What's the worst that could happen?

AB.clockTick = 100, AB.maxSteps = 1e3, AB.screenshotStep = 50;

const show3d = !0,
    TEXTURE_WALL = "/uploads/duadur2/wallB.jpg",
    TEXTURE_MAZE = "/uploads/starter/latin.jpg",
    TEXTURE_AGENT = "/uploads/starter/pacman.jpg",
    TEXTURE_ENEMY = "/uploads/starter/ghost.3.png",
    TEXTURE_Arrow = "/uploads/duadur2/star.jpg",
    MUSIC_BACK = "/uploads/starter/Defense.Line.mp3",
    SOUND_ALARM = "/uploads/starter/air.horn.mp3",
    gridsize = 20,
    NOBOXES = Math.trunc(gridsize * gridsize / 10),
    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,
   
//   Contents of Grid Square
    GRID_BLANK = 0,
    GRID_WALL = 1,
    GRID_MAZE = 2;

var BOXHEIGHT;		// 3d or 2d box height 

var GRID 	= new Array(gridsize);			// can query GRID about whether squares are occupied, will in fact be initialised as a 2D array   

var theagent, theenemy;
  
var wall_texture, agent_texture, enemy_texture, maze_texture; 


// enemy and agent position on squares
var ei, ej, ai, aj;

var badsteps;
var goodsteps;
GRID = new Array(gridsize),
   
    xi = [],
    xj = [],
    starArray = [],
    openSet = [],
    closedSet = [],
    path = [];

function loadResources() {
    var e = new THREE.TextureLoader,
        t = new THREE.TextureLoader,
        a = new THREE.TextureLoader,
        r = new THREE.TextureLoader,
        n = 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()
    }), a.load(TEXTURE_ENEMY, function(e) {
        e.minFilter = THREE.LinearFilter, enemy_texture = e, asynchFinished() && initScene()
    }), r.load(TEXTURE_MAZE, function(e) {
        e.minFilter = THREE.LinearFilter, maze_texture = e, asynchFinished() && initScene()
    }), n.load(TEXTURE_Arrow, function(e) {
        e.minFilter = THREE.LinearFilter, arrow_texture = e, asynchFinished() && initScene()
    })
}

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

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

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

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

// Different Over Here
function removeFromArray(e, t) {
    for (var a = e.length - 1; a >= 0; a--) e[a] == t && e.splice(a, 1)
}

// Different Over Here
function Spot(e, t) {
    this.i = e, this.j = t, this.f = 0, this.g = 0, this.h = 0, this.neighbors = [], 
    this.previous = void 0, 0 === e || e === gridsize - 1 || 0 === t || t === gridsize - 1 ? 
    (this.wall = !0, shape = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), 
    (thecube = new THREE.Mesh(shape)).material = new THREE.MeshBasicMaterial({
        map: wall_texture
    }), thecube.position.copy(translate(e, t)), ABWorld.scene.add(thecube)) : this.wall = !1;
    
    for (var a = 0; a <= NOBOXES; a++) e === xi[a] && t === xj[a] && (this.wall = !0);
    this.addNeighbors = function(e) {
        var t = this.i,
            a = this.j;
        t < gridsize - 1 && this.neighbors.push(e[t + 1][a]), 
        t > 0 && this.neighbors.push(e[t - 1][a]), 
        a < gridsize - 1 && this.neighbors.push(e[t][a + 1]), 
        a > 0 && this.neighbors.push(e[t][a - 1])
    }
}

function initScene() {
    var e, t;
    for (e = 0; e < gridsize; e++) GRID[e] = new Array(gridsize);
    for (var a = 0, r = 1; r <= NOBOXES; r++) e = AB.randomIntAtoB(1, gridsize - 2),
    t = AB.randomIntAtoB(1, gridsize - 2), xi[a] = e, xj[a] = t,
    shape = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), 
    (thecube = new THREE.Mesh(shape)).material = new THREE.MeshBasicMaterial({
        map: maze_texture
    }), thecube.position.copy(translate(e, t)), ABWorld.scene.add(thecube), a++;
    
    for (e = 0; e < gridsize; e++)
        for (t = 0; t < gridsize; t++) GRID[e][t] = new Spot(e, t);
    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, shape = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), (theenemy = new THREE.Mesh(shape)).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, shape = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), (theagent = new THREE.Mesh(shape)).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)
}

// Different Over Here
function drawPath() {
    for (var e = 0; e < path.length - 2; e++)
        if (path.length > 2) {
            var t = path[e];
            shape = new THREE.BoxGeometry(squaresize, .1, squaresize), (thestar = new THREE.Mesh(shape)).material = new THREE.MeshBasicMaterial({
                map: arrow_texture
            }), starArray[e] = thestar.uuid, thestar.position.copy(translate(t.i, t.j)), ABWorld.scene.add(thestar)
        }
}

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

// Different Over Here
function AStar() {
    for (openSet = [], closedSet = [], path = [], start = GRID[ei][ej], end = GRID[ai][aj], openSet.push(start); openSet.length > 0;) {
        for (var e = 0, t = 0; t < openSet.length; t++) openSet[t].f < openSet[e].f && (e = t);
        var a = openSet[e];
        if (a === end) {
            console.log("success - found path");
            break
        }
        removeFromArray(openSet, a), closedSet.push(a);
        var r = a.neighbors;
        for (t = 0; t < r.length; t++) {
            var n = r[t];
            if (!closedSet.includes(n) && !n.wall) {
                var o = a.g + heuristic(n, a),
                    i = !1;
                openSet.includes(n) ? o < n.g && (n.g = o, i = !0) : (n.g = o, i = !0, openSet.push(n)), i && (n.h = heuristic(n, end), n.f = n.g + n.h, n.previous = a)
            }
        }
        var s = a;
        for ((path = []).push(s); s.previous;) path.push(s.previous), s = s.previous
    }
    for (t = 0; t < gridsize; t++)
        for (var u = 0; u < gridsize; u++) 0 !== GRID[t][u].f && (GRID[t][u].f = 0, GRID[t][u].g = 0, GRID[t][u].h = 0, GRID[t][u].previous = void 0)
}

// Different Over Here
function removePath() {
    console.log("removing");
    for (var e = 0; e < starArray.length; e++) {
        var t = starArray[e];
        const a = ABWorld.scene.getObjectByProperty("uuid", t);
        ABWorld.scene.remove(a)
    }
}

function moveLogicalEnemy() {
    AStar(), drawPath();
    var e = path.length,
        t = path[e - 2];
    occupied(t.i, t.j) || (ei = t.i, ej = t.j)
}

function sleep(e) {
    return new Promise(t => setTimeout(t, e))
}

function moveLogicalAgent(e) {
    var t = ai,
        a = aj;
    e == ACTION_LEFT ? t-- : e == ACTION_RIGHT ? t++ : e == ACTION_UP ? a++ : e == ACTION_DOWN && a--, occupied(t, a) || (ai = t, aj = a)
}
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) {
    AB.world.getState();
    AB.msg(" Step: " + AB.step + " &nbsp; a = (" + e + ") ")
}

function updateStatusAfter() {
    AB.world.getState();
    var e = goodsteps / AB.step * 100;
    AB.msg(" Bad steps: " + badsteps + " &nbsp; Good steps: " + goodsteps + " &nbsp; Score: " + e.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, GRID]
}, 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()), sleep(100).then(() => {
        removePath()
    })
}, 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()
}