Code viewer for World: Part-2 Assignment 1 (clone...

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



const WALLMOVENO = 10, WALLMOVETICK = 1000;


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_PATH = "/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 = 30; // 30, 

// 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 = 18756435,//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
//wallCutOff = AB.randomFloatAtoB(0, 0.6);
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
const 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;

var wall_texture, agent_texture, enemy_texture, maze_texture, path_texture;

var ei, ej, ai, aj;

var badsteps;

var goodsteps;



GRID = new Array(gridsize),
closedSet = [],
openSet = [],
path = [],
mazePieces = [],
nextBestSquare = null;




function loadResources() // asynchronous file loads - call initScene() when all finished
{
  var e = new THREE.TextureLoader,
  t = new THREE.TextureLoader,
  i = new THREE.TextureLoader,
  s = new THREE.TextureLoader,
  a = new THREE.TextureLoader;
  e.load(TEXTURE_WALL, function (e) 
  {
    e.minFilter = THREE.LinearFilter, 
    wall_texture = e,
    wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
  }), t.load(TEXTURE_AGENT, function (e) 
  {
    e.minFilter = THREE.LinearFilter,
    agent_texture = e,
    wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
  }), i.load(TEXTURE_ENEMY, function (e) 
  {
    e.minFilter = THREE.LinearFilter,
    enemy_texture = e, wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
  }), s.load(TEXTURE_MAZE, function (e) 
  {
    e.minFilter = THREE.LinearFilter,
    maze_texture = e,
    wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
  }), a.load(TEXTURE_PATH, function (e)
  {
    e.minFilter = THREE.LinearFilter,
    path_texture = e,
    wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
  });
}



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 Box(e, t, GRID_WALL, true),
  GRID[e][t].show()) : GRID[e][t] = new Box(e, t, GRID_BLANK, false);
  for (var s = 1; s <= NOBOXES; s++) e = AB.randomIntAtoB(1, gridsize - 2),
  t = AB.randomIntAtoB(1, gridsize - 2),
  GRID[e][t] = new Box(e, t, GRID_MAZE, true),
  GRID[e][t].show(), mazePieces.push(GRID[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].isWall && !mazePieces.includes(GRID[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 (ei === e && ej === t || (ai === e && aj === t || !(!GRID[e][t].isWall && !mazePieces.includes(GRID[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 = true;
  });
}



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 Astar() 
{
  for (const e of path) e.highlight(false);
  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 s = openSet[t], 
    a = GRID[ai][aj];
    if (s === a) 
    {
      for (var n = s; n.previous !== e;) n.highlight(true), path.push(n), n = n.previous;
      return n;
    }
    openSet.splice(openSet.indexOf(s), 1), closedSet.push(s);
    var r = s.neighbors;
    for (i = 0; i < r.length; i++) 
    {
      var o = r[i];
      if (!closedSet.includes(o) && !o.isWall) 
      {
        var u = s.g + (Math.abs(o.i - s.i) + Math.abs(o.j - s.j)),
        d = false;
        openSet.includes(o) ? u < o.g && (o.g = u, d = true) : (o.g = u, d = true, openSet.push(o)), d && (o.h = Math.abs(o.i - a.i) + Math.abs(o.j - a.j), o.f = o.g + o.h, o.previous = s);
      }
    }
  }
}




function moveLogicalEnemy() 
{
  do 
  {
    nextBestSquare = Astar();
  } 
  while (!nextBestSquare);
  ei === nextBestSquare.i && ej === nextBestSquare.j || (ai === nextBestSquare.i && aj === nextBestSquare.j || !(!GRID[nextBestSquare.i][nextBestSquare.j].isWall && !mazePieces.includes(GRID[nextBestSquare.i][nextBestSquare.j]))) || (ei = nextBestSquare.i, ej = nextBestSquare.j), nextBestSquare = null;
}



function moveLogicalAgent(e)
{
  var t = ai, i = aj;
  e == ACTION_LEFT ? t-- : e == ACTION_RIGHT ? t++ : e == ACTION_UP ? i++ : e == ACTION_DOWN && i--, ei === t && ej === i || (ai === t && aj === i || !(!GRID[t][i].isWall && !mazePieces.includes(GRID[t][i]))) || (ai = t, aj = i);
}
timer = setInterval(function () 
{
  for (var e = 0; e < 10; e++) 
  {
    var t, i, s = mazePieces[AB.randomIntAtoB(0, mazePieces.length - 1)];
    do 
    {
      t = AB.randomIntAtoB(1, gridsize - 2), i = AB.randomIntAtoB(1, gridsize - 2);
    } while ((ei === t && ej === i || (ai === t && aj === i || !(!GRID[t][i].isWall && !mazePieces.includes(GRID[t][i])))) && t == s.i && i == s.j);
    s.removeMazePiece(), mazePieces.splice(mazePieces.indexOf(s), 1);
    var a = GRID[s.i][s.j];
    a.squareType = GRID_BLANK,
    a.isWall = false,
    a.f = 0,
    a.g = 0,
    a.h = 0,
    GRID[s.i][s.j] = a;
    var n = GRID[t][i];
    n.squareType = GRID_MAZE, n.isWall = true, n.f = 0, n.g = 0, n.h = 0, n.show(), mazePieces.push(n), GRID[t][i] = n, nextBestSquare = Astar();
  }
},1000);


function Box(a, t, i, s) 
{
  this.uniqueId,
  this.mazePieceId,
  this.i = a,
  this.j = t,
  this.f = 0,
  this.g = 0,
  this.h = 0,
  this.neighbors = [],
  this.previous = void 0,
  this.squareType = i,
  this.isWall = s,
  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}), this.mazePieceId = thecube.uuid), 
    thecube.position.copy(translate(this.i, this.j)), ABWorld.scene.add(thecube);
  }, 
  this.removeMazePiece = function () 
  {
    var e = ABWorld.scene.getObjectByProperty("uuid", this.mazePieceId);
    ABWorld.scene.remove(a),
    this.mazePieceId = null;
  }, 
  this.highlight = function (a) 
  {
    if (a) thehighlightedshape = new THREE.BoxGeometry(squaresize, 0.001, squaresize),thehighlightedpiece = new THREE.Mesh(thehighlightedshape),thehighlightedpiece.material = new THREE.MeshBasicMaterial({map: path_texture}), thehighlightedpiece.position.copy(translate(this.i, this.j)),ABWorld.scene.add(thehighlightedpiece),this.uniqueId = thehighlightedpiece.uuid;
    else 
    {
      var t = ABWorld.scene.getObjectByProperty("uuid", this.uniqueId);
      ABWorld.scene.remove(t),
      this.uniqueId = null;
    }
  }, 
  this.addNeighbors = function (a) 
  {
    this.i < gridsize - 1 && this.neighbors.push(a[this.i + 1][this.j]),
    this.i > 0 && this.neighbors.push(a[this.i - 1][this.j]),
    this.j < gridsize - 1 && this.neighbors.push(a[this.i][this.j + 1]), this.j > 0 && this.neighbors.push(a[this.i][this.j - 1]);
  };
}



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) 
{
  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 = 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];
}, 
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].isWall && !mazePieces.includes(GRID[ai - 1][aj])))) && (ei === ai + 1 && ej === aj || (ai === ai + 1 && aj === aj || !(!GRID[ai + 1][aj].isWall && !mazePieces.includes(GRID[ai + 1][aj])))) && (ei === ai && ej === aj + 1 || (ai === ai && aj === aj + 1 || !(!GRID[ai][aj + 1].isWall && !mazePieces.includes(GRID[ai][aj + 1])))) && (ei === ai && ej === aj - 1 || (ai === ai && aj === aj - 1 || !(!GRID[ai][aj - 1].isWall && !mazePieces.includes(GRID[ai][aj - 1])))) && (AB.abortRun = true,
  goodsteps = 0,
  musicPause(),
  soundAlarm());
}, 
AB.world.endRun = function () 
{
  musicPause(),
  AB.msg(AB.abortRun ? "<br> <font color=red> <B> Laden Is Trapped. Final Score Zero. </B> </font>" : "<br> <font color=Red> <B> Chase Over. </B> </font>", 5);
}, 
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();
}