Code viewer for World: Agent and Enemy move2
// Abdelshafa Abdala

//Student ID number:  21269020

// A* practical (2)


const WALLMOVENO=20;

WALLMOVETICK=   5e3;

AB.clockTick       = 200;    

	// Speed of run: Step every n milliseconds. Default 100.
	
AB.maxSteps        = 1e3;    

	// 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.
var start,end,diagonal=!0,
openSet=[],
closedSet=[],
neighbors=[],
path=[];



//---- global constants: -------------------------------------------------------

	const show3d = !0;						// Switch between 3d and 2d view (both using Three.js) 


 const TEXTURE_WALL 	= '/uploads/rania/door6.jpg' ;
 const TEXTURE_MAZE 	= '/uploads/rania/latin9.gif' ;
 const TEXTURE_AGENT 	= '/uploads/starter/pacman.jpg';
 const TEXTURE_ENEMY 	= '/uploads/rania/ghost1.jpg';




 
	const MUSIC_BACK  = '/uploads/rania/Ultimate.mp3' ;
	const SOUND_ALARM = '/uploads/rania/mixkit-classic-winner-alarm-1997.wav' ;




gridsize=  150,
NOBOXES=Math.trunc(gridsize*gridsize/7),
	
	

 squaresize = 100; 		
// size of square in pixels

const MAXPOS = gridsize * squaresize;		// length of one side in pixels 
	
const SKYCOLOR 	= 14548957;				// a number, not a string 

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

wallCutOff=AB.randomFloatAtoB(0,.6)

ABHandler.MAXCAMERAPOS=maxRadiusConst,ABHandler.GROUNDZERO=!0;

//--- change ABWorld defaults: -------------------------------




 const SKYBOX_ARRAY = [										 
                "/uploads/rania/dawnmountain-xpos2.jpg",
                "/uploads/rania/dawnmountain-xpos2.jpg",
                "/uploads/rania/dawnmountain-xpos2.jpg",
                "/uploads/rania/dawnmountain-xpos2.jpg",
                "/uploads/rania/dawnmountain-xpos2.jpg",
                "/uploads/rania/dawnmountain-xpos2.jpg"
                ];


// ===================================================================================================================
// === End of tweaker's box ==========================================================================================
// ===================================================================================================================


// You will need to be some sort of JavaScript programmer to change things below the tweaker's box.









//--- Mind can pick one of these actions -----------------

const ACTION_LEFT 			= 0;		   
const ACTION_RIGHT 			= 1;
const ACTION_UP 			= 2;		 
const ACTION_DOWN 			= 3;
const ACTION_STAYSTILL 		= 4;



// contents of a grid square

const GRID_BLANK 	= 0;
const GRID_WALL 	= 1;
const GRID_MAZE 	= 2;
const VERBOSE_LOG   =!1;
 
 
 
 

var BOXHEIGHT,theagent,theenemy,wall_texture,agent_texture,enemy_texture,maze_texture,ei,ej,ai,aj,badsteps,goodsteps,GRID=new Array(gridsize),shownPath=[],path=[];

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||(GRID[e][a]==GRID_WALL||GRID[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++)

for(a=0;a<gridsize;a++)0==e||e==gridsize-1||0==a||a==gridsize-1?(GRID[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)):GRID[e][a]=GRID_BLANK;
for
(
var r=1;r<=NOBOXES;r++)e=AB.randomIntAtoB(1,gridsize-2),
a=AB.randomIntAtoB(1,gridsize-2),GRID[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);

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

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

                                
function MakeSpot(e,a){this.i=e,this.j=a,this.f=0,this.g=0,this.h=0,this.neighbors=[],
this.previous=void 0,this.wall=GRID[e][a]!==GRID_BLANK,this.addNeighbors=function(e)
                                
{
var a=this.i,
t=this.j;
a<gridsize-1&&this.neighbors.push(e[a+1][t]),
t<gridsize-1&&this.neighbors.push(e[a][t+1]),
a>0&&this.neighbors.push(e[a-1][t]),t>0&&this.neighbors.push(e[a][t-1])}}

                                    
function heuristic(e,a)
{
    return Math.abs(e.i-a.i)+Math.abs(e.j-a.j)}
                                    
function euc_heuristic(e,a)
{
    return Math.sqrt(Math.pow(e.i-a.i,2)+Math.pow(e.j-a.j,2))}
                                    
function oct_heuristic(e,a)
{
    return Math.max(Math.abs(e.i-a.i),Math.abs(e.j-a.j))+(Math.sqrt(2)-1)*Math.min(Math.abs(e.i-a.i),Math.abs(e.j-a.j))}
function chebyshev_heuristic(e,a)
{
    return Math.max((Math.abs(e.i-a.i),Math.abs(e.j-a.j)))}
                                    
function highlightPath(e,a)
{
                                        
for(
var t=0;t<e.length-1;t++)shape=new THREE.BoxGeometry(squaresize,.1,squaresize),
ShownPath=new THREE.Mesh(shape),
ShownPath.material=new THREE.MeshBasicMaterial({color:a}),
ShownPath.position.copy(translate(e[t].i,e[t].j)),
ABWorld.scene.add(ShownPath),
shownPath.push(ShownPath)}
                                            
function moveLogicalEnemy()

                          
{
for
(
var e=new Array(gridsize),a=[],t=[],i=0;i<shownPath.length;i++)ABWorld.scene.remove(shownPath[i]);
                                                    
for(i=0;i<gridsize;i++)e[i]=new Array(gridsize);
for(i=0;i<gridsize;i++)
                                                    
for
(
var r=0;r<gridsize;r++)e[i][r]=new MakeSpot(i,r);
                                                        
for(i=0;i<gridsize;i++)for(r=0;r<gridsize;r++)e[i][r].addNeighbors(e);
for(a.push(e[ei][ej]);a.length>0;){var o=0;for(i=0;i<a.length;i++)a[i].f<a[o].f&&(o=i);

                                                        
var n=a[o];
if(n===e[ai][aj])
{
var s=[],u=n;
                                                            
for(s.push(u);u.previous;)s.push(u.previous),u=u.previous;highlightPath(s,255);
                                                            
var d=s.length-2;occupied(s[d].i,s[d].j)||(ei=s[d].i,ej=s[d].j);
                                                            
break}removeFromArray(a,n),t.push(n);
var h=n.neighbors;
                                                            
for(i=0;i<h.length;i++){var c=h[i];if(c[i]===e[ai][aj]){c.previous=n;
                                                            
break}if(!t.includes(c)&&!c.wall){var l=n.g+heuristic(c,n),p=!1;
                                                            
a.includes(c)?l<c.g&&(c.g=l,p=!0):(c.g=l,p=!0,
a.push(c)),p&&(c.h=heuristic(c,e[ai][aj]),c.f=c.g+c.h,c.previous=n)}}}}
                                                            
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+"   x = ("+a.toString()+")   a = ("+e+") ")}
                                                                        
function updateStatusAfter()
{
    var e=AB.world.getState(),a=goodsteps/AB.step*100;
    
                                                                        

AB.msg("   y = ("+e.toString()+") <br> Bad steps: "+badsteps+"   Good steps: "+goodsteps+"   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=yellow> <B> Agent trapped. Final score zero. </B> </font>   ",3):AB.msg(" <br> <font color=coral> <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("/uploads/rania/Ultimate.mp3");
function musicPlay(){backmusic.play()}function musicPause(){backmusic.pause()}
function soundAlarm(){new Audio("/uploads/rania/mixkit-classic-winner-alarm-1997.wav").play()}