Code viewer for World: Cat and Mouse (clone by test)

// Cloned by test on 10 Dec 2020 from World "Cat and Mouse" by Jack O'Brien 
// Please leave this clone trail here.
 
AB.clockTick=100,AB.maxSteps=1e3,AB.screenshotStep=10;const show3d=!1,TEXTURE_WALL="/uploads/jobrien14/red-brick.jpg",TEXTURE_MAZE="/uploads/jobrien14/trashcan2.png",TEXTURE_AGENT="/uploads/jobrien14/mouse.png",TEXTURE_ENEMY="/uploads/jobrien14/angry_cat.jpg",MUSIC_BACK="/uploads/starter/Defense.Line.mp3",SOUND_ALARM="/uploads/starter/air.horn.mp3",gridsize=20,NOBOXES=Math.trunc(gridsize*gridsize/3),squaresize=2e3,MAXPOS=gridsize*squaresize,SKYCOLOR=14548957,startRadiusConst=.8*MAXPOS,maxRadiusConst=10*MAXPOS;ABHandler.MAXCAMERAPOS=maxRadiusConst,ABHandler.GROUNDZERO=!0;const SKYBOX_ARRAY=["/uploads/starter/sky_pos_z.jpg","/uploads/starter/sky_neg_z.jpg","/uploads/starter/sky_pos_y.jpg","/uploads/starter/sky_neg_y.jpg","/uploads/starter/sky_pos_x.jpg","/uploads/starter/sky_neg_x.jpg"];var myGrid=new Array(gridsize),openSet=[],closedSet=[],Path=[],Best=[],showDirectLine=!0,showBresenhamLine=!0;function spot(e,t){this.i=e,this.j=t,this.wall=!1,this.maze=!1,this.f=0,this.g=0,this.h=0,this.previous=void 0,this.addNeighbors=function(e){this.neighbors=[];var t=this.i,i=this.j;t<e-1&&this.neighbors.push(myGrid[t+1][i]),t>1&&this.neighbors.push(myGrid[t-1][i]),i<e-1&&this.neighbors.push(myGrid[t][i+1]),i>1&&this.neighbors.push(myGrid[t][i-1]),t>1&&i>1&&this.neighbors.push(myGrid[t-1][i-1]),t<e-1&&i>1&&this.neighbors.push(myGrid[t+1][i-1]),t>1&&i<e-1&&this.neighbors.push(myGrid[t-1][i+1]),t<e-1&&i<e-1&&this.neighbors.push(myGrid[t+1][i+1])},this.addBlockingNeighbors=function(e){this.blockingNeighbors=[];var t=this.i,i=this.j;t<e-1&&this.blockingNeighbors.push(myGrid[t+1][i]),t>1&&this.blockingNeighbors.push(myGrid[t-1][i]),i<e-1&&this.blockingNeighbors.push(myGrid[t][i+1]),i>1&&this.blockingNeighbors.push(myGrid[t][i-1])},this.addDiagonalNeighbors=function(e){this.diagonalNeighbors=[];var t=this.i,i=this.j;t>1&&i>1&&this.diagonalNeighbors.push(myGrid[t-1][i-1]),t<e-1&&i>1&&this.diagonalNeighbors.push(myGrid[t+1][i-1]),t>1&&i<e-1&&this.diagonalNeighbors.push(myGrid[t-1][i+1]),t<e-1&&i<e-1&&this.diagonalNeighbors.push(myGrid[t+1][i+1])}}function listNeighbors(e){console.log(e.neighbors.length+" Neighbors:");for(let t=0;t<=e.neighbors.length-1;t++)console.log("X: "+e.neighbors[t].i+"; Y: "+e.neighbors[t].j)}function listPath(e){console.log("Path: ");for(let t=0;t<=e.length-1;t++)console.log("X: "+e[t].i+"; Y: "+e[t].j)}function drawPath(e,t){var i=new THREE.Geometry,o=new THREE.LineBasicMaterial({color:t});if(null!==e&&e.length>1){for(let t=0;t<e.length-1;t++)i.vertices.push(translate(e[t].i,e[t].j)),i.vertices.push(translate(e[t+1].i,e[t+1].j));var n=new THREE.LineSegments(i,o);ABWorld.scene.add(n),setTimeout(()=>{i.dispose(),o.dispose(),ABWorld.scene.remove(n)},AB.clockTick)}}const 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,theagent,theenemy,wall_texture,agent_texture,enemy_texture,maze_texture,ei,ej,ai,aj,enemyLocation,agentLocation,badsteps,goodsteps,GRID=new Array(gridsize);function loadResources(){var e=new THREE.TextureLoader,t=new THREE.TextureLoader,i=new THREE.TextureLoader,o=new THREE.TextureLoader;e.load(TEXTURE_WALL,function(e){e.minFilter=THREE.LinearFilter,wall_texture=e,asynchFinished()&&initScene()}),t.load(TEXTURE_AGENT,function(e){e.minFilter=THREE.LinearFilter,agent_texture=e,asynchFinished()&&initScene()}),i.load(TEXTURE_ENEMY,function(e){e.minFilter=THREE.LinearFilter,enemy_texture=e,asynchFinished()&&initScene()}),o.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,t){return ei==e&&ej==t||(ai==e&&aj==t||(GRID[e][t]==GRID_WALL||GRID[e][t]==GRID_MAZE))}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;for(o=0;o<gridsize;o++)GRID[o]=new Array(gridsize),myGrid[o]=new Array(gridsize);for(o=0;o<gridsize;o++)for(n=0;n<gridsize;n++)0===o||o==gridsize-1||0===n||n==gridsize-1?(GRID[o][n]=GRID_WALL,myGrid[o][n]=new spot(o,n),myGrid[o][n].wall=!0,e=new THREE.BoxGeometry(squaresize,BOXHEIGHT,squaresize),(t=new THREE.Mesh(e)).material=new THREE.MeshBasicMaterial({map:wall_texture}),t.position.copy(translate(o,n)),ABWorld.scene.add(t)):(GRID[o][n]=GRID_BLANK,myGrid[o][n]=new spot(o,n));for(var i=1;i<=NOBOXES;i++)o=AB.randomIntAtoB(1,gridsize-2),n=AB.randomIntAtoB(1,gridsize-2),GRID[o][n]=GRID_MAZE,myGrid[o][n].maze=!0,e=new THREE.BoxGeometry(squaresize,BOXHEIGHT,squaresize),(t=new THREE.Mesh(e)).material=new THREE.MeshBasicMaterial({map:maze_texture}),t.position.copy(translate(o,n)),ABWorld.scene.add(t);for(var o=0;o<=gridsize-2;o++)for(var n=0;n<=gridsize-2;n++)myGrid[o][n].addNeighbors(gridsize),myGrid[o][n].addBlockingNeighbors(gridsize);do{o=AB.randomIntAtoB(1,gridsize-2),n=AB.randomIntAtoB(1,gridsize-2)}while(occupied(o,n));(enemyLocation=new spot(ei=o,ej=n)).addNeighbors(gridsize),e=new THREE.BoxGeometry(squaresize,BOXHEIGHT,squaresize),(theenemy=new THREE.Mesh(e)).material=new THREE.MeshBasicMaterial({map:enemy_texture}),ABWorld.scene.add(theenemy),drawEnemy();do{o=AB.randomIntAtoB(1,gridsize-2),n=AB.randomIntAtoB(1,gridsize-2)}while(occupied(o,n));(agentLocation=new spot(ai=o,aj=n)).addNeighbors(gridsize),agentLocation.addBlockingNeighbors(gridsize),agentLocation.addDiagonalNeighbors(gridsize),e=new THREE.BoxGeometry(squaresize,BOXHEIGHT,squaresize),(theagent=new THREE.Mesh(e)).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,AB.msg("Enemy: <button class='altbutton' onclick='showDirect()'>Direct Line</button> <button class='altbutton' onclick='showBresenham()'>Bresenham's Line</button><br><br>\t\t         Agent: <button class='altbutton' onclick='showPath()'>Path</button> <button class='altbutton' onclick='showFullPath()'>Full Search Path</button><br>")})}function showDirect(){showDirectLine=!showDirectLine}function showBresenham(){showBresenhamLine=!showBresenhamLine}function showPath(){showPathAgent?showPathAgent=!1:showPathAgent=!0}function showFullPath(){showAllAgent?showAllAgent=!1:showAllAgent=!0}function resetValues(e){for(let t=0;t<e.length;t++)e[t].f=0,e[t].g=0,e[t].h=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 lowLine(e,t){let i=t.i-e.i,o=t.j-e.j,n=1;o<0&&(n=-1,o=-o);let r=2*o-i,s=e.j,a=[];for(var h=e.i;h<=t.i;h++)a.push(new spot(h,s)),r>0?(s+=n,r+=2*(o-i)):r+=2*o;return a}function highLine(e,t){let i=t.i-e.i,o=t.j-e.j,n=1;i<0&&(n=-1,i=-i);let r=2*i-o,s=e.i,a=[];for(var h=e.j;h<=t.j;h++)a.push(new spot(s,h)),r>0?(s+=n,r+=2*(i-o)):r+=2*i;return a}function bresenhams(e,t){return Math.abs(t.j-e.j)<Math.abs(t.i-e.i)?e.i>t.i?lowLine(t,e):lowLine(e,t):e.j>t.j?highLine(t,e):highLine(e,t)}function aStar(e,t){var i=countBlocks(bresenhams(e,t));return Math.sqrt(Math.pow(e.i-t.i,2)+Math.pow(e.j-t.j,2))+.75*i}function removeFromArray(e,t){for(var i=e.length-1;i>=0;i--)e[i]==t&&e.splice(i,1)}function path(){for(openSet=[],closedSet=[],(enemyLocation=new spot(ei,ej)).addNeighbors(gridsize),openSet.push(enemyLocation);openSet.length>0;){for(var e=0,t=0;t<openSet.length;t++)openSet[t].f<openSet[e].f&&(e=t);var i=openSet[e];if(agentLocation.blockingNeighbors.includes(i)&&agentBlocked()>=3){for((Path=[]).push(o=i);o.previous;)Path.push(o.previous),o=o.previous;return Path}if(agentLocation.diagonalNeighbors.includes(i)){for((Path=[]).push(o=i);o.previous;)Path.push(o.previous),o=o.previous;return Path}if(agentLocation.neighbors.includes(i)){var o;for((Path=[]).push(o=i);o.previous;)Path.push(o.previous),o=o.previous;return Path}removeFromArray(openSet,i),closedSet.push(i);var n=i.neighbors;if(n)for(t=0;t<n.length;t++){var r=n[t];aStar(r,agentLocation);if(!occupied(r.i,r.j)&&!closedSet.includes(r)){var s=i.g+aStar(r,i),a=!1;openSet.includes(r)?s<r.g&&(r.g=s,a=!0):(r.g=s,a=!0,openSet.push(r)),a&&(r.h=aStar(r,agentLocation),r.f=r.g+r.h,r.previous=i)}}var h=i;for((Path=[]).push(h);h.previous;)Path.push(h.previous),h=h.previous;drawPath(Path,16711680)}}function countBlocks(e){var t=0;for(let i=0;i<e.length;i++)!0===myGrid[e[i].i][e[i].j].maze&&t++;return t}function moveLogicalEnemy(e){var t=path();if(drawPath(t,65280),1==showDirectLine){var i=[];i.push(t[0]),i.push(t[t.length-1]),drawPath(i,255)}1==showBresenhamLine&&drawPath(bresenhams(t[0],t[t.length-1]),16766720);for(let e=0;e<t.length-1;e++)ei=t[e].i,ej=t[e].j}function moveLogicalAgent(e){var t=ai,i=aj;e==ACTION_LEFT?t--:e==ACTION_RIGHT?t++:e==ACTION_UP?i++:e==ACTION_DOWN&&i--,occupied(t,i)||((agentLocation=new spot(ai=t,aj=i)).addNeighbors(gridsize),agentLocation.addBlockingNeighbors(gridsize),agentLocation.addDiagonalNeighbors(gridsize))}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(){var e=0;return occupied(ai-1,aj)&&e++,occupied(ai+1,aj)&&e++,occupied(ai,aj+1)&&e++,occupied(ai,aj-1)&&e++,e}function updateStatusBefore(e){var t=AB.world.getState();removeFromArray(t,t[t.length-1]),AB.msg(" Step: "+AB.step+" &nbsp; x = ("+t.toString()+") &nbsp; a = ("+e+") ",2)}function updateStatusAfter(){var e=AB.world.getState();removeFromArray(e,e[e.length-1]);var t=goodsteps/AB.step*100;AB.msg(" &nbsp; y = ("+e.toString()+") <br> Bad steps: "+badsteps+" &nbsp; Good steps: "+goodsteps+" &nbsp; Score: "+t.toFixed(2)+"% ",3)}function soundAlarm(){new Audio(SOUND_ALARM).play()}AB.world.newRun=function(){AB.loadingScreen(),AB.runReady=!1,badsteps=0,goodsteps=0,BOXHEIGHT=1,ABWorld.init2d(startRadiusConst,maxRadiusConst,14548957),loadResources(),document.onkeydown=keyHandler},AB.world.getState=function(){return[ai,aj,ei,ej,myGrid]},AB.world.takeAction=function(e){updateStatusBefore(e),moveLogicalAgent(e),AB.step%2==0&&moveLogicalEnemy(),badstep()?badsteps++:goodsteps++,drawAgent(),drawEnemy(),updateStatusAfter(),agentBlocked()>=4&&(AB.abortRun=!0,goodsteps=0,soundAlarm())},AB.world.endRun=function(){AB.abortRun?AB.msg(" <br> <font color=red> <B> Agent trapped. Final score zero. </B> </font>   ",4):AB.msg(" <br> <font color=green> <B> Run over. </B> </font>   ",4)},AB.world.getScore=function(){var e=goodsteps/AB.maxSteps*100;return Math.round(100*e)/100};