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