// 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=false;
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="";
gridsize=30;
NOBOXES =Math.trunc(gridsize*gridsize/5);
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/aoifemariedoherty/bluecloud_rt.jpg","/uploads/aoifemariedoherty/bluecloud_lf.jpg","/uploads/aoifemariedoherty/bluecloud_up.jpg","/uploads/aoifemariedoherty/bluecloud_dn.jpg","/uploads/aoifemariedoherty/bluecloud_bk.jpg","/uploads/aoifemariedoherty/bluecloud_ft.jpg"];
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 GRID=newArray(gridsize);var theagent,theenemy;var wall_texture,agent_texture,enemy_texture,maze_texture;var ei,ej,ai,aj;var badsteps,goodsteps;var shownPath=[],path=[];//for A*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 )returntrue;elsereturnfalse;}function occupied(e,a){return ei==e&&ej==a||(ai==e&&aj==a||(GRID[e][a]==GRID_WALL||GRID[e][a]==GRID_MAZE))// ==============for better understanding of code=============// 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
// ==============for better understanding of code=============// 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;var t;//shapevar i;//thecube// set up GRID as 2D arrayfor(e=0;e<gridsize;e++){
GRID[e]=newArray(gridsize);}//set up wallsfor(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 enemydo{
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();//set up agentdo{
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 skyboxABWorld.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 arrayfunction removeFromArray(e,a){for(var t=e.length-1;t>=0;t--)// Could use indexOf here instead to be more efficientif(e[t]== a)
e.splice(t,1)}functionMakeSpot(e,a){// Locationthis.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=undefined;if(GRID[e][a]!== GRID_BLANK)this.wall=GRID[e][a]//this.wall=GRID[e][a]!==GRID_BLANK;this.addNeighbors=function(e){// To figure out who are the neighborsvar a=this.i;var t=this.j;// for better understandingif(a < gridsize -1)this.neighbors.push(e[a +1][t]);if(a >0)this.neighbors.push(e[a -1][t]);if(t < gridsize -1)this.neighbors.push(e[a][t +1]);if(t >0)this.neighbors.push(e[a][t -1]);}}function heuristic(e,a){returnMath.abs(e.i-a.i)+Math.abs(e.j-a.j)}//fucntion to show path chosenfunction highlightPath(e){for(var i=0;i<e.length-1;i++){
shape=new THREE.BoxGeometry(squaresize,.1,squaresize);ShownPath=new THREE.Mesh(shape);ShownPath.material=new THREE.MeshBasicMaterial({color:'palegreen'});ShownPath.position.copy(translate(e[i].i,e[i].j));ABWorld.scene.add(ShownPath);
shownPath.push(ShownPath);}}var k=[]//testing variablefunction moveLogicalEnemy(){var e=newArray(gridsize);var a=[];var t=[];for(i=0;i<shownPath.length;i++)ABWorld.scene.remove(shownPath[i]);for(i=0;i<gridsize;i++)
e[i]=newArray(gridsize);for(i=0;i<gridsize;i++)for(var r=0;r<gridsize;r++)
e[i][r]=newMakeSpot(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++)if(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);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=false;// if (a.includes(l))// {// if (h<l.g)// {// l.g=h;// p=true;// }// else// {// l.g=h;// p=true;// a.push(l);// }}// if (p == true)// {// l.h=heuristic(l,e[ai][aj]);// l.f=l.g+l.h;// l.previous=n;// }// }if(!t.includes(l)&&!l.wall){var h=n.g+heuristic(l,n);
p=false;
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--;elseif(e==ACTION_RIGHT) a++;elseif(e==ACTION_UP) t++;elseif(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 )returntrue;// not ready yet // if not one of our special keys, send it to default key handling:if(! ourKeys ( e ))returntrue;// 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();returnfalse;}// --- score: -----------------------------------function badstep()// is the enemy within one square of the agent{if((Math.abs(ei - ai)<2)&&(Math.abs(ej - aj)<2))returntrue;elsereturnfalse;}function agentBlocked()// agent is blocked on all sides, run over{return(occupied(ai-1,aj)&&
occupied(ai+1,aj)&&
occupied(ai,aj+1)&&
occupied(ai,aj-1));}function updateStatusBefore(e)// this is called before anyone has moved on this step, agent has just proposed an action// update status to show old state and proposed move{var a=AB.world.getState();//AB.msg(" Step: "+AB.step+" x = ("+a.toString()+") a = ("+e+") ")
AB.msg (" Step: "+ AB.step +" x = ("+ a.toString()+") a = ("+ e +") ");}function updateStatusAfter()// agent and enemy have moved, can calculate score{// new state after both have movedvar 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=!1;
badsteps=0;
goodsteps=0;if(show3d){
BOXHEIGHT=squaresize;ABWorld.init3d(startRadiusConst,maxRadiusConst,14548957);}else{
BOXHEIGHT =1;ABWorld.init2d ( startRadiusConst, maxRadiusConst, SKYCOLOR );}
loadResources();// aynch file loads // calls initScene() when it returns
document.onkeydown=keyHandler
};
AB.world.getState=function(){var x =[ ai, aj, ei, ej ];return( x );};
AB.world.takeAction=function(e){
updateStatusBefore(e);
moveLogicalAgent(e);if( AB.step%2==0)
moveLogicalEnemy();if( badstep()) badsteps++;else goodsteps++;
drawAgent();
drawEnemy();
updateStatusAfter();if( 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);else AB.msg(" <br> <font color=green> <B> Run over. </B> </font> ",3);};
AB.world.getScore=function(){// only called at end - do not use AB.step because it may have just incremented past AB.maxStepsvar e=goodsteps/AB.maxSteps*100;// float like 93.4372778 var x=Math.round(100*e)/100;return x
};var backmusic=AB.backgroundMusic("/uploads/paul6991/james_bond_theme.mp3");function musicPlay(){backmusic.play();}function musicPause(){backmusic.pause();}function soundAlarm(){var alarm=newAudio( SOUND_ALARM );
alarm.play();}