Code viewer for World: Part-1 Assignment 1clone b...

// Cloned by Raj Vibhute on 9 Nov 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.
// ====================================================================================================================

AB.clockTick = 100; // 100;

    // Speed of run: Step every n milliseconds. Default 100.

AB.maxSteps = 1000;

  // Length of run: Maximum length of run in steps. Default 1000.

AB.screenshotStep = 50;

  // Take screenshot on this step. (All resources should have finished loading.) Default 50.



//---- global constants: -------------------------------------------------------
    const show3d = true, 




// All Images 
TEXTURE_WALL = "/uploads/starter/door.jpg",
TEXTURE_MAZE = "/uploads/starter/latin.jpg", 
TEXTURE_AGENT = "/uploads/rajv261/Agent.jpeg", 
TEXTURE_ENEMY = "/uploads/rajv261/Enemy11.jpeg", 
TEXTURE_Arrow = "/uploads/rajv261/Enemy.jpeg",


//Music Tracks
MUSIC_BACK = "/uploads/rajv261/Rifle-Automatic-Fire-A-www.fesliyanstudios.com.mp3", 
SOUND_ALARM = "/uploads/rajv261/Big-Grenade-Explosion-www.fesliyanstudios.com.mp3", 




gridsize = 20; // 20, 

// number of squares along side of world  
  
NOBOXES = Math.trunc(gridsize * gridsize / 10 ),   // 10 

// density of maze - number of internal boxes
// (bug) use trunc or can get a non-intege

squaresize = 100, // size of square in pixels

MAXPOS = gridsize * squaresize, // length of one side in pixels 

SKYCOLOR = 14548957, // a number, not a string 



startRadiusConst = 0.8 * MAXPOS,  // distance from centre to start the camera at
maxRadiusConst = 10 * MAXPOS;   // maximum distance from camera we will render things



// Changes in AB World
ABHandler.MAXCAMERAPOS = maxRadiusConst, ABHandler.GROUNDZERO = true;

const SKYBOX_ARRAY = [										 
                "/uploads/starter/posx.jpg",
                "/uploads/starter/negx.jpg",
                "/uploads/starter/posy.jpg",
                "/uploads/starter/negy.jpg",
                "/uploads/starter/posz.jpg",
                "/uploads/starter/negz.jpg"
                ];




//Actions picked by Mind
ACTION_LEFT = 0,
ACTION_RIGHT = 1, 
ACTION_UP = 2,
ACTION_DOWN = 3,
ACTION_STAYSTILL = 4,


// contents of a grid square
GRID_BLANK = 0,
GRID_WALL = 1,
GRID_MAZE = 2;


var BOXHEIGHT;

var theagent, theenemy, shape, thecube, thestar;

var wall_texture, agent_texture, enemy_texture, maze_texture, arrow_texture;

var ei, ej, ai, aj;

var badsteps;
var goodsteps;
var start, end;


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



function loadResources()  // asynchronous file loads - call initScene() when all finished
{
  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, !!(wall_texture && agent_texture && enemy_texture && maze_texture && arrow_texture) && initScene();
  }), 
  
  t.load(TEXTURE_AGENT, function (e) 
  {
    e.minFilter = THREE.LinearFilter, agent_texture = e, !!(wall_texture && agent_texture && enemy_texture && maze_texture && arrow_texture) && initScene();
  }),
  
  a.load(TEXTURE_ENEMY, function (e) 
  {
    e.minFilter = THREE.LinearFilter, enemy_texture = e, !!(wall_texture && agent_texture && enemy_texture && maze_texture && arrow_texture) && initScene();
  }), 
  
  r.load(TEXTURE_MAZE, function (e) 
  
  {
    e.minFilter = THREE.LinearFilter, maze_texture = e, !!(wall_texture && agent_texture && enemy_texture && maze_texture && arrow_texture) && initScene();
  }), 
  
  n.load(TEXTURE_Arrow, function (e) 
  {
    e.minFilter = THREE.LinearFilter, arrow_texture = e, !!(wall_texture && agent_texture && enemy_texture && maze_texture && arrow_texture) && initScene();
  });
}



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;
}



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


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 = true, 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 = false;
  for (var a = 0; a <= NOBOXES; a++) 
  e === xi[a] && t === xj[a] && (this.wall = true);
  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]);
  };
}



// all file loads have returned

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 (ei == e && ej == t || (ai == e && aj == t || !!GRID[e][t].wall));
  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 (ei == e && ej == t || (ai == e && aj == t || !!GRID[e][t].wall));
  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 = true;
  });
}


// ----- Moving objects ----- //

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 to draw path ----- //
function drawPath() 
{
  for (var e = 0; e < path.length - 2; e++) if (path.length > 2) 
  {
    var t = path[e];
    shape = new THREE.BoxGeometry(squaresize, 0.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);
  }
}



// ----- A* for enemy ----- //
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 + (Math.abs(n.i - a.i) + Math.abs(n.j - a.j)), i = false;
        openSet.includes(n) ? o < n.g && (n.g = o, i = true) : (n.g = o, i = true, openSet.push(n)),
        i && (n.h = Math.abs(n.i - end.i) + Math.abs(n.j - end.j),
        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);
}



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);
  }
}


// ----- Actions ----- //
function moveLogicalEnemy() 
{
  AStar(), drawPath();
  var e = path.length,
  t = path[e - 2];
  ei == t.i && ej == t.j || (ai == t.i && aj == t.j || !!GRID[t.i][t.j].wall) || (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--,ei == t && ej == a || (ai == t && aj == a || !!GRID[t][a].wall) || (ai = t, aj = a);
}


var OURKEYS = [37, 38, 39, 40];
function keyHandler ( event )   
{
  if ( ! AB.runReady ) return true;     // not ready yet 

   // if not one of our special keys, send it to default key handling:
  
  if ( ! ourKeys ( event ) ) return true;
  
  // else handle key and prevent default handling:
  
  if ( event.keyCode == 37 )   moveLogicalAgent ( ACTION_LEFT   );   
    if ( event.keyCode == 38 )   moveLogicalAgent ( ACTION_DOWN   );   
    if ( event.keyCode == 39 )   moveLogicalAgent ( ACTION_RIGHT  );   
    if ( event.keyCode == 40 )   moveLogicalAgent ( ACTION_UP   );   
  
  // when the World is embedded in an iframe in a page, we want arrow key events handled by World and not passed up to parent 

  event.stopPropagation(); event.preventDefault(); return false;
}



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 = false, 
  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(), 
  Math.abs(ei - ai) < 2 && Math.abs(ej - aj) < 2 ? badsteps++ : goodsteps++, 
  drawAgent(),
  drawEnemy(),
  updateStatusAfter(), 
  (ei == ai - 1 && ej == aj || (ai == ai - 1 && aj == aj || !!GRID[ai - 1][aj].wall)) && (ei == ai + 1 && ej == aj || (ai == ai + 1 && aj == aj || !!GRID[ai + 1][aj].wall)) && (ei == ai && ej == aj + 1 || (ai == ai && aj == aj + 1 || !!GRID[ai][aj + 1].wall)) && (ei == ai && ej == aj - 1 || (ai == ai && aj == aj - 1 || !!GRID[ai][aj - 1].wall)) && (AB.abortRun = true, 
  goodsteps = 0, 
  musicPause(), 
  soundAlarm()), 
  sleep(100).then(() => {
    removePath();
  });
}, AB.world.endRun = function () 
{
  musicPause(),
  AB.abortRun ? AB.msg(" <br> <font color=red> <B> Laden 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;
};





// ----- music and sound effects -----//
var backmusic = AB.backgroundMusic(MUSIC_BACK);
function musicPlay() 
{
  backmusic.play();
}


function musicPause() 
{
  backmusic.pause();
}


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