// Cloned by Yuwei Chen on 28 Nov 2020 from Mind "Jorge's World" by Jorge Blanco
// Please leave this clone trail here.
AB.newDiv("selectdiv"),AB.newDiv("speedDiv"),AB.newDiv("otherStategyDiv"),$("#selectdiv").css({"padding-left":"30vw",color:"white"}),$("#speedDiv").css({"padding-left":"30vw",color:"white"}),$("#otherStategyDiv").css({"padding-left":"30vw",color:"white"}),$("#selectdiv").html("<div>H - using distance Chebyshev with Last Enemy Move <br> G - using distance from Last Agent Move <br><br></div><div>Note: if stuck press 'resume'</div>Pick strategy: <span id='actorlist'><select onchange='setStragety(this)'><option value='punish'>1 Punish visited spots/close to enemy</option><option value='dontPunish'>2 Dont punish visited spots/close to enemy</option></select><button onclick='startAgain();'>re-play</button></span>"),$("#otherStategyDiv").html("<span id='actorlist'><input type='checkbox' value='manhatan' onclick='useManhatan(this);'>G + H Manhattan (NY)<br> </span>"),$("#speedDiv").html("Set speed: <span id='actorlist'><select onchange='setSpeed(this)'><option value='100'>100</option><option value='300'>300</option><option value='50'>50</option><option value='1'>1</option></select></span>");var fistMoveAgent=null,lastMoveAgent=null,firstMoveEnemy=null,startPositionEnemy=null,lastMoveEnemy=null,openSet=[],closedSet=[],grid=new Grid,strategyScores={1:{d:[],m:[]},2:{d:[],m:[]}},strategySelectType=1,useManhatanGH=!1;const average=e=>Math.round(e.reduce((e,t)=>e+t,0)/e.length*100)/100;function setStragety(e){var t=e.value;"punish"==t?strategySelectType=1:"dontPunish"==t&&(strategySelectType=2),startAgain()}function useManhatan(e){useManhatanGH=e.checked}function setSpeed(e){AB.controlPause(),AB.clockTick=e.value,AB.controlRun()}function startAgain(){AB.controlPause(),AB.step=0,AB.abortRun=!1,goodsteps=-2,badsteps=0,ei=firstMoveEnemy.x,ej=firstMoveEnemy.y,ai=fistMoveAgent.x,aj=fistMoveAgent.y,AB.world.takeAction(4),grid=new Grid,AB.controlRun()}function pushToOpenSet(e){this.openSet.push(e)}function getNextNode(e,t){var n=grid.getAvailableFourMoves(e,t);console.log("Number of next moves (ignore past walls) "+n.length),e.g=0;for(var s=0;s<n.length;s++){var o=n[s];if(null!==o){var a=o.move;a.resetGFH();var i=0;useManhatanGH?(i=e.g+e.manhattanDistance(a),console.log("manhattan Distance g")):(i=e.g+e.distanceUsingStart(a,lastMoveAgent),console.log("distance from last agent move")),console.log("tempG "+i),1==strategySelectType&&(i-=a.visited,console.log("punish past visited spot by "+a.visited),a.badstep()&&(i-=1,console.log("punish spot as moving in to the bad spot area")));var l=!1;openSet.includes(a)?i>a.g&&(a.g=i,l=!0,console.log("Found a position in OPENSET with a bigger G "+a.x+"-"+a.y)):(a.g=i,l=!0,openSet.push(o)),l&&(useManhatanGH?(a.h=t.manhattanDistance(a),console.log("manhattan Distance h")):(a.h=t.distanceChebyshev(a),console.log("Chebyshev Distance h")),a.f=a.g+a.h,console.log("Calculate F "+a.f+" g:"+a.g+"h:"+a.h),o)}}var r=this.getOpenSetNodeBiggestF();return null===r?(console.log("No next Move ???????"),null):(this.clearOpenSet(),r)}function getOpenSetNodeBiggestF(){for(var e=0,t=0;t<this.openSet.length;t++){var n=this.openSet[t].move,s=this.openSet[e].move;n.f>s.f&&(e=t),n.f==s.f&&(e=n.distanceEnemyX>s.distanceEnemyX&&n.distanceEnemyY>s.distanceEnemyX?t:AB.randomPick(e,t))}return openSet.length>e?openSet[e]:0}function removeFromOpenSet(e){for(var t=this.openSet.length-1;t>=0;t--)if(this.openSet[t]==e)return void this.openSet.splice(t,1)}function clearOpenSet(){this.openSet=[]}function printStatusDistanceToEnemy(e){var t="";e.type==ACTION_UP?t=" up ":e.type==ACTION_DOWN?t=" down ":e.type==ACTION_RIGHT?t=" right ":e.type==ACTION_LEFT&&(t=" left ");var n="<h2> Next Move ("+e.move.x+","+e.move.y+"): "+t+"</h2>";e.move.badstep()?(n+="<span style='background: red; color: white;'>DANGER</span>",n+="<br>"):(n+="<span style='background: green; color: white;'>KEEP RUNNING</span>",n+="<br>"),AB.msg(n,3)}function Grid(){this.maze=null,this.mazeMaxX=0,this.mazeMaxY=0,this.getAvailableFourMoves=function(e,t){var n=[],s=this.getElementPositionGrow(e.x,e.y+1);!0===s.wall||t.areSame(s)||(console.log("Possible H -> next up "+s.x+"-"+s.y),s.distanceEnemy(t),n.push({type:ACTION_UP,move:s}));var o=this.getElementPositionGrow(e.x,e.y-1);!0===o.wall||t.areSame(o)||(console.log("Possible H -> next down "+o.x+"-"+o.y),o.distanceEnemy(t),n.push({type:ACTION_DOWN,move:o}));var a=this.getElementPositionGrow(e.x+1,e.y);!0===a.wall||t.areSame(a)||(console.log("Possible H -> next right "+a.x+"-"+a.y),a.distanceEnemy(t),n.push({type:ACTION_RIGHT,move:a}));var i=this.getElementPositionGrow(e.x-1,e.y);return!0===i.wall||t.areSame(i)||(console.log("Possible H -> next left "+i.x+"-"+i.y),i.distanceEnemy(t),n.push({type:ACTION_LEFT,move:i})),n},this.growGridIfNeedTo=function(e,t){null===this.maze?(this.maze=Array.from({length:e+2},()=>Array.from({length:t+2},()=>null)),this.mazeMaxX=this.maze.length,this.mazeMaxY=this.maze[0].length):this.grow(e,t)},this.grow=function(e,t){var n=this.mazeMaxX<e?e:this.mazeMaxX,s=this.mazeMaxY<t?t:this.mazeMaxY,o=Array.from({length:n+2},()=>Array.from({length:s+2},()=>null));if(n>0&&s>0){for(var a=0;a<this.mazeMaxX;a++)for(var i=0;i<this.mazeMaxY;i++)o[a][i]=this.maze[a][i];this.maze=o,this.mazeMaxX=this.maze.length,this.mazeMaxY=this.maze[0].length}else console.log("cols and rows have no value in [function grow] -???")},this.markWall=function(e){var t=this.getElementPositionGrow(e.x,e.y);t.wall=!0,this.maze[t.x][t.y]=t,console.log("Wall marked "+t.x+"-"+t.y)},this.markNoWall=function(e){var t=this.getElementPositionGrow(e.x,e.y);t.wall=!1,t.visited+=1,this.maze[t.x][t.y]=t,console.log("No Wall marked "+t.x+"-"+t.y)},this.getElementPositionGrow=function(e,t){var n=null;return this.maze&&this.maze.length>e&&this.maze[0].length>t?n=this.maze[e][t]:(this.growGridIfNeedTo(e,t),n=this.maze[e][t]),null===n&&(n=new Spot(e,t)),n}}function Spot(e,t){this.x=e,this.y=t,this.distanceEnemyX=null,this.distanceEnemyY=null,this.samePosition=0,this.visited=0,this.f=0,this.g=0,this.h=0,this.wall=null,this.neighbors={},this.isEmpty=function(){return null===this.wall},this.clone=function(){var e=new Spot(this.x,this.y);return e.samePosition=this.samePosition,e.visited=this.visited,e.f=this.f,e.g=this.g,e.h=this.h,e.wall=this.wall,e},this.areSame=function(e){return this.x==e.x&&this.y===e.y},this.manhattanDistance=function(e){return null===e?-1:Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},this.distanceUsingStart=function(e,t){var n=this.x-e.x,s=this.y-e.y,o=t.x-e.x,a=t.y-e.y;return Math.abs(n*a-o*s)},this.distanceChebyshev=function(e,t){var n=Math.abs(this.x-e.x),s=Math.abs(this.y-e.y);return 1*(n+s)+-1*Math.min(n,s)},this.resetGFH=function(){this.f=0,this.g=0,this.h=0},this.distanceEnemy=function(e){this.distanceEnemyX=Math.abs(this.x-e.x),this.distanceEnemyY=Math.abs(this.y-e.y)},this.badstep=function(){return this.distanceEnemyX<=2&&this.distanceEnemyY<=2}}AB.world.endRun=function(){musicPause(),AB.abortRun?(AB.msg(" <br> <font color=red> <B> Agent trapped. Final score zero. </B> </font> ",3),useManhatanGH?strategyScores[strategySelectType].m.push(0):strategyScores[strategySelectType].d.push(0)):(AB.msg(" <br> <font color=green> <B> Run over. </B> </font> ",3),useManhatanGH?strategyScores[strategySelectType].m.push(AB.world.getScore()):strategyScores[strategySelectType].d.push(AB.world.getScore())),AB.msg("<br><br><span>Strategy 1: "+average(strategyScores[1].d)+"% /"+strategyScores[1].d.length+" - NY - "+average(strategyScores[1].m)+"% /"+strategyScores[1].m.length+" </span><br><span>Strategy 2: "+average(strategyScores[2].d)+"% /"+strategyScores[2].d.length+" - NY - "+average(strategyScores[2].m)+"% /"+strategyScores[2].m.length+" </span>",4)},AB.mind.getAction=function(e){var t=grid.getElementPositionGrow(e[0],e[1]);grid.markNoWall(t),console.log("Current agent "+t.x+"-"+t.y);var n=grid.getElementPositionGrow(e[2],e[3]);grid.markNoWall(n),console.log("Current enemy "+n.x+"-"+n.y),null===lastMoveAgent?(lastMoveAgent=t.clone(),fistMoveAgent=t.clone()):lastMoveAgent.areSame(t)?closedSet.push(lastMoveAgent):(grid.markWall(lastMoveAgent),console.log("Agent hit a wall last move "+lastMoveAgent.x+"-"+lastMoveAgent.y)),null===lastMoveEnemy?(lastMoveEnemy=n.clone(),firstMoveEnemy=n.clone()):lastMoveEnemy.areSame(n)&&(n.samePosition++,console.log("Enemy has not moved "+n.x+"-"+n.y+" past "+n.samePosition+" moves"));var s=getNextNode(t,n);return s?(lastMoveAgent=s.move,printStatusDistanceToEnemy(s),s.type):(console.log("Agent has no more moves open - stay in the same place"),4)};