Code viewer for World: photucopy

// Cloned by Paul Jones on 9 Nov 2022 from World "Enemy versus Agent Game (clone by Aoife Doherty)" by Aoife Doherty 
// Please leave this clone trail here.
 
AB.clockTick=100;

AB.maxSteps=1000;

AB.screenshotStep=50;

const show3d=!0;

TEXTURE_WALL="/uploads/starter/door.jpg";
TEXTURE_MAZE="/uploads/paul6991/wall.jpg";

TEXTURE_AGENT="/uploads/paul6991/joker.jpg";
TEXTURE_ENEMY="/uploads/paul6991/batman.jpg";

MUSIC_BACK="/uploads/paul6991/james_bond_theme.mp3";
SOUND_ALARM="/uploads/paul6991/avengers_theme.mp3";

gridsize=20;

NOBOXES = Math.trunc(gridsize*gridsize/3);

squaresize=100;

spheresize=55;

MAXPOS=gridsize*squaresize;

SKYCOLOR=14548957;

startRadiusConst=.8*MAXPOS;

maxRadiusConst=10*MAXPOS;

ABHandler.MAXCAMERAPOS=maxRadiusConst;

ABHandler.GROUNDZERO=!0;

const SKYBOX_ARRAY=["/uploads/paul6991/nz.png",
"/uploads/paul6991/pz.png",
"/uploads/paul6991/ny.png",
"/uploads/paul6991/py.png",
"/uploads/paul6991/nx.png",
"/uploads/paul6991/px.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;
var theagent,theenemy;
var wall_texture,agent_texture,enemy_texture,maze_texture;
var ei,ej,ai,aj;
var badsteps,goodsteps;

var GRID=new Array(gridsize);
var shownPath=[],path=[];

function loadResources(){
    var e=new THREE.TextureLoader;
    var a=new THREE.TextureLoader;
    var t=new THREE.TextureLoader;
    var 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()
{
    if ( wall_texture && agent_texture && enemy_texture && maze_texture )   return true; 
	else return false;
}

function occupied(e,a)
{
     if ( ( ei == e ) && ( ej == a ) ) return true;		// variable objects 
     if ( ( ai == e ) && ( aj == a ) ) return true;

     if ( GRID[e][a] == GRID_WALL ) return true;		// fixed objects	 
     if ( GRID[e][a] == GRID_MAZE ) return true;		 
	 
     return false;
     
}

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
    
    var v = new THREE.Vector3();
	
	v.y = 0;	
	v.x = ( e * squaresize ) - ( MAXPOS/2 );   		 
	v.z = ( a * squaresize ) - ( MAXPOS/2 );   	
	
	return v;
}

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++){
            if (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);
                i.material=new THREE.MeshBasicMaterial({map:wall_texture});
                
                i.position.copy(translate(e,a));
                ABWorld.scene.add(i);
                
            }
            else
                GRID[e][a]=GRID_BLANK;
            
        }
        
    }
    //set up maze  
                
    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);
        i.material=new THREE.MeshBasicMaterial({map:maze_texture});
        
        i.position.copy(translate(e,a));
        ABWorld.scene.add(i);
    }
    
    //set up enemy
    do
    {
        e=AB.randomIntAtoB(1,gridsize-2);
        a=AB.randomIntAtoB(1,gridsize-2);
    }
    
    while(occupied(e,a));
    
    ei=e;
    ej=a;
    
    // t=new THREE.SphereGeometry(spheresize,BOXHEIGHT,spheresize);
    // theenemy=new THREE.Mesh(t);
    // theenemy.material=new THREE.MeshBasicMaterial({map:enemy_texture});
    // ABWorld.scene.add(theenemy);
    // drawEnemy();
    
     t    = new THREE.BoxGeometry ( squaresize, BOXHEIGHT, squaresize );			 
	 theenemy = new THREE.Mesh( t );
 	 theenemy.material =  new THREE.MeshBasicMaterial( { map: enemy_texture } );
	 ABWorld.scene.add(theenemy);
	 drawEnemy();
    
    //set up agent
    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);
    theagent.material=new THREE.MeshBasicMaterial({map:agent_texture});
    ABWorld.scene.add(theagent);
    drawAgent();
    
    
    //finally skybox
    ABWorld.scene.background=new THREE.CubeTextureLoader().load(SKYBOX_ARRAY,function()
    {
        ABWorld.render();
        AB.removeLoading();
        AB.runReady=!0
    })
}
    //--------draw 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 delete element from the array
function removeFromArray(e,a)
{
    for(var t=e.length-1;t>=0;t--)
        if (e[t] == a)
            e.splice(t,1)
        
        // Could use indexOf here instead to be more efficient
//   for (var i = arr.length - 1; i >= 0; i--) 
//     if (arr[i] == elt) 
//       arr.splice(i, 1);
}

function MakeSpot(e,a)
{
    // Location
    this.i=e;
    this.j=a;
    
    // f, g, and h values for 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)
    {
        // To figure out who are the neighbors
        var a=this.i;
        var 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])
     
    //   for better understanding
    // if (i < cols - 1)   this.neighbors.push(grid[i + 1][j]);
    // if (i > 0)          this.neighbors.push(grid[i - 1][j]);
    // if (j < rows - 1)   this.neighbors.push(grid[i][j + 1]);
    // if (j > 0)          this.neighbors.push(grid[i][j - 1]);
    }
}

function heuristic(e,a)
{
    return Math.abs(e.i-a.i)+Math.abs(e.j-a.j)
}


//fucntion to show path chosen

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(){
    var e=new Array(gridsize),a=[],t=[];
    for(var 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=[],d=n;for(s.push(d);d.previous;)s.push(d.previous),d=d.previous;highlightPath(s,190);var u=s.length-2;occupied(s[u].i,s[u].j)||(ei=s[u].i,ej=s[u].j);break}removeFromArray(a,n),t.push(n);var c=n.neighbors;for(i=0;i<c.length;i++){var l=c[i];if(l[i]===e[ai][aj]){l.previous=n;break}if(!t.includes(l)&&!l.wall){var h=n.g+heuristic(l,n),p=!1;a.includes(l)?h<l.g&&(l.g=h,p=!0):(l.g=h,p=!0,a.push(l)),p&&(l.h=heuristic(l,e[ai][aj]),l.f=l.g+l.h,l.previous=n)}}}}

function moveLogicalAgent(e)
{
    var a=ai;
    var t=aj;
    if (e==ACTION_LEFT) a--;
    else if (e==ACTION_RIGHT)   a++;
    else if (e==ACTION_UP)  t++;
    else if (e==ACTION_DOWN)    t--;
    
    if (!occupied(a,t))
    {
        ai=a;
        aj=t;
    }
}

// --- key handling --------------------------------------------------------------------------------------
// This is hard to see while the Mind is also moving the agent:
// AB.mind.getAction() and AB.world.takeAction() are constantly running in a loop at the same time 
// have to turn off Mind actions to really see user key control 

// we will handle these keys:     
    
    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))}
        if ( ! AB.runReady ) return true; 		// not ready yet 

   // if not one of our special keys, send it to default key handling:
	
	    if ( ! ourKeys ( e ) ) return true;
	
	// else handle key and prevent default handling:
	
	if ( e.keyCode == 37 )   moveLogicalAgent ( ACTION_LEFT 	);   
    if ( e.keyCode == 38 )   moveLogicalAgent ( ACTION_DOWN  	); 	 
    if ( e.keyCode == 39 )   moveLogicalAgent ( ACTION_RIGHT 	); 	 
    if ( e.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 

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


// --- score: -----------------------------------

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();
    var 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=false;
    badsteps=0;
    goodsteps=0;
    if (show3d)
    {
        BOXHEIGHT=squaresize;
        ABWorld.init3d(startRadiusConst,maxRadiusConst,14548957);
    }
    else
    {
        BOXHEIGHT = 1;
	    ABWorld.init2d ( startRadiusConst, maxRadiusConst, SKYCOLOR  ); 
    }
	 
	 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();
    if ( badstep()) badsteps++;
    goodsteps++;
    
    drawAgent();
    drawEnemy();
    updateStatusAfter();agentBlocked()&&(AB.abortRun=!0,goodsteps=0,musicPause(),soundAlarm())};
    
AB.world.endRun=function()
{
    musicPause();
    if (AB.abortRun)
        AB.msg(" <br> <font color=red> <B> Indiana Jones 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("/uploads/aoifemariedoherty/adiossapito1.mp3").play()}