// Cloned by Mohamed Hafez on 24 Nov 2020 from Mind "Complex Mind mine" by Mohamed Hafez
// Please leave this clone trail here.
// Cloned by Mohamed Hafez on 13 Nov 2020 from Mind "Complex Mind (clone by Mohamed Hafez)" by Mohamed Hafez
// Please leave this clone trail here.
// Cloned by Mohamed Hafez on 8 Nov 2020 from Mind "Complex Mind" by Starter user
// Please leave this clone trail here.
// =================================================================================================
// Sample Mind for more complex starter World
// =================================================================================================
// World tells us agent position and enemy position
// World does not tell us of existence of walls
// if return invalid move (not empty square) World just ignores it and we miss a turn
AB.mind.getAction = function ( x) // x is an array of inputs from world
{
var ai = x[0];
var aj = x[1];
var ei = x[2];
var ej = x[3];
var agentalgorithm2= x[4]; //[MH] to decide which algorithm to run
var m1 = x[5]; // [MH] value of lower spot
var m2= x[6]; // [MH] value of right spot
var m3= x[7]; //[MH] value of left spot
var m4= x[8]; //[MH] value of upper spot
var gridsize =x[9]; //[MH] Gridsize
//[MH] Parameters for Mind A* Algorithm
var openSet2 = [];
var closedSet2 = [];
var start2;
var end2;
var GRIDMIND=x[10];
var si;
var sj;
//[MH] Parameter for other mind algorithm
var max2=[];
//[MH] Function to calculate heuristic for A*
function heuristic(a, b)
{
return ( Math.sqrt(Math.pow((a.i - b.i),2) + Math.pow((a.j - b.j),2)) );
}
function removeFromArray(arr, elt)
{
// 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 occupied ( i, j ) // is this square occupied
{
if ( ( ei == i ) && ( ej == j ) ) return true; // variable objects
if ( ( ai == i ) && ( aj == j ) ) return true;
if ( GRIDMIND[i][j].value == 1 ) return true; // fixed objects //[MH] Adding .value since we are dealing with object now
if ( GRIDMIND[i][j].value == 2 ) return true; //[MH] Adding .value since we are dealing with object now
return false;
}
}
//[MH] Default algorithm
if (agentalgorithm2==1)
{
// Random Algorithm
if ( ej < aj ) return ( AB.randomPick ( ACTION_UP, AB.randomPick(ACTION_RIGHT,ACTION_LEFT) ));
if ( ej > aj ) return ( AB.randomPick ( ACTION_DOWN, AB.randomPick(ACTION_RIGHT,ACTION_LEFT) ));
if ( ei < ai ) return ( AB.randomPick ( ACTION_RIGHT, AB.randomPick(ACTION_UP,ACTION_DOWN) ));
if ( ei > ai ) return ( AB.randomPick ( ACTION_LEFT, AB.randomPick(ACTION_UP,ACTION_DOWN) ));
return ( AB.randomIntAtoB (0,3) );
}
//[MH] Agent algorithm to escape from Enemy by going far and avoid being stucked by the wall
if (agentalgorithm2==3)
{
//[MH] Distance between neigbors spots and enemy to choose hte one which is far from enemy
var bfsm=[];
bfsm[0]=Math.sqrt(Math.pow(ai-ei,2 ) + Math.pow(aj+1-ej,2)) ;
bfsm[1]=Math.sqrt(Math.pow(ai+1-ei,2 ) + Math.pow(aj-ej,2)) ;
bfsm[2]=Math.sqrt(Math.pow(ai-ei,2 ) + Math.pow(aj-1-ej,2)) ;
bfsm[3]=Math.sqrt(Math.pow(ai-1-ei,2 ) + Math.pow(aj-ej,2)) ;
//[MH] ignore neigbors who are wall or maze
if(m1>0) bfsm[2]=0;
if(m2>0) bfsm[1]=0;
if(m3>0) bfsm[3]=0;
if(m4>0) bfsm[0]=0;
//[MH] Choose neighors with highest distance from Enemy
var max = Math.max.apply(null, bfsm);
for (var f = 0; f < bfsm.length; f++ )
{
if (bfsm[f]==max)
{
max2.push(f);
}
}
return AB.randomElementOfArray ( max2 );
}
//[MH] A* Alogrithm for Mind
if (agentalgorithm2==2)
{
openSet2=[];
closedSet2=[];
start2 = GRIDMIND[ai][aj]; //[MH] Start point is mind location
//[MH] Grid is divided in 9 Qs and purpose of function to know enemy and agent are in which Q
function quarter(i,j)
{
if ( (i>=0) && (i<=gridsize/3) && (j>=0) && (j<=gridsize/3 )) return 1;
if ( (i>=gridsize/3) && (i<=2*gridsize/3) && (j>=0) && (j<gridsize/3 )) return 2;
if ( (i>=2*gridsize/3) && (i<=gridsize) && (j>=0) && (j<=gridsize/3 )) return 3;
if ( (i>=0) && (i<gridsize/3) && (j>=gridsize/3) && (j<=2*gridsize/3 )) return 4;
if ( (i>=gridsize/3) && (i<=2*gridsize/3) && (j>=gridsize/3) && (j<=2*gridsize/3 )) return 5;
if ( (i>2*gridsize/3) && (i<=gridsize) && (j>=gridsize/3) && (j<=2*gridsize/3 )) return 6;
if ( (i>=0) && (i<=gridsize/3) && (j>=2*gridsize/3) && (j<=gridsize)) return 7;
if ( (i>=gridsize/3) && (i<=2*gridsize/3) && (j>2*gridsize/3) && (j<=gridsize)) return 8;
if ( (i>=2*gridsize/3) && (i<=gridsize) && (j>=2*gridsize/3) && (j<=gridsize)) return 9;
}
//[MH] Parameters to give range of i,j for each Q of the 9Qs
var Q1=[0,gridsize/3,0,gridsize/3];
var Q2=[gridsize/3,2*gridsize/3,0,gridsize/3];
var Q3=[2*gridsize/3,gridsize,0,gridsize/3];
var Q4=[0,gridsize/3,gridsize/3,2*gridsize/3];
var Q5=[gridsize/3,2*gridsize/3,gridsize/3,2*gridsize/3];
var Q6=[2*gridsize/3,gridsize,gridsize/3,2*gridsize/3];
var Q7=[0,gridsize/3,2*gridsize/3,gridsize];
var Q8=[gridsize/3,2*gridsize/3,2*gridsize/3,gridsize];
var Q9=[2*gridsize/3,gridsize,2*gridsize/3,gridsize];
//[MH] Get a random location in each of the Qs
while (1<2)
{
var Q11=AB.randomIntAtoB (Q1[0],Q1[1] );
var Q12=AB.randomIntAtoB (Q1[2],Q1[3] );
if (!occupied(Q11,Q12)) break;
}
while (1<2)
{
var Q21=AB.randomIntAtoB (Q2[0],Q2[1] );
var Q22=AB.randomIntAtoB (Q2[2],Q2[3] );
if (!occupied(Q21,Q22)) break;
}
while(1<2)
{
var Q31=AB.randomIntAtoB (Q3[0],Q3[1] );
var Q32=AB.randomIntAtoB (Q3[2],Q3[3] );
if (!occupied(Q31,Q32)) break;
}
while(1<2)
{
var Q41=AB.randomIntAtoB (Q4[0],Q4[1] );
var Q42=AB.randomIntAtoB (Q4[2],Q4[3] );
if (!occupied(Q41,Q42)) break;
}
while(1<2)
{
var Q51=AB.randomIntAtoB (Q5[0],Q5[1] );
var Q52=AB.randomIntAtoB (Q5[2],Q5[3] );
if (!occupied(Q51,Q52)) break;
}
while(1<2)
{
var Q61=AB.randomIntAtoB (Q6[0],Q6[1] );
var Q62=AB.randomIntAtoB (Q6[2],Q6[3] );
if (!occupied(Q61,Q62)) break;
}
while(1<2)
{
var Q71=AB.randomIntAtoB (Q7[0],Q7[1] );
var Q72=AB.randomIntAtoB (Q7[2],Q7[3] );
if (!occupied(Q71,Q72)) break;
}
while(1<2)
{
var Q81=AB.randomIntAtoB (Q8[0],Q8[1] );
var Q82=AB.randomIntAtoB (Q8[2],Q8[3] );
if (!occupied(Q81,Q82)) break;
}
while(1<2)
{
var Q91=AB.randomIntAtoB (Q9[0],Q9[1] );
var Q92=AB.randomIntAtoB (Q9[2],Q9[3] );
if (!occupied(Q91,Q92)) break;
}
//[MH] Decision the End target for the mind A* Based on enemy and agent location on the gird
if (quarter(ei,ej)==1) end2=GRIDMIND[Q91][Q92];
if (quarter(ei,ej)==3) end2=GRIDMIND[Q71][Q72];
if (quarter(ei,ej)==7) end2=GRIDMIND[Q31][Q32];
if (quarter(ei,ej)==9) end2=GRIDMIND[Q11][Q12];
if (quarter(ei,ej)==2)
{
if (quarter(ai,aj)==1 || quarter(ai,aj)==4 || quarter(ai,aj)==7) end2=GRIDMIND[Q71][Q72];
if (quarter(ai,aj)==3 || quarter(ai,aj)==6 || quarter(ai,aj)==9) end2=GRIDMIND[Q91][Q92];
if (quarter(ai,aj)==2 || quarter(ai,aj)==5 || quarter(ai,aj)==8) end2=GRIDMIND[Q71][Q72];
}
if (quarter(ei,ej)==4)
{
if (quarter(ai,aj)==1 || quarter(ai,aj)==2 || quarter(ai,aj)==3) end2=GRIDMIND[Q31][Q32];
if (quarter(ai,aj)==7 || quarter(ai,aj)==8 || quarter(ai,aj)==9) end2=GRIDMIND[Q91][Q92];
if (quarter(ai,aj)==4 || quarter(ai,aj)==5 || quarter(ai,aj)==6) end2=GRIDMIND[Q31][Q32];
}
if (quarter(ei,ej)==6)
{
if (quarter(ai,aj)==1 || quarter(ai,aj)==2 || quarter(ai,aj)==3) end2=GRIDMIND[Q11][Q12];
if (quarter(ai,aj)==7 || quarter(ai,aj)==8 || quarter(ai,aj)==9) end2=GRIDMIND[Q71][Q72];
if (quarter(ai,aj)==4 || quarter(ai,aj)==5 || quarter(ai,aj)==6) end2=GRIDMIND[Q11][Q12];
}
if (quarter(ei,ej)==8)
{
if (quarter(ai,aj)==1 || quarter(ai,aj)==4 || quarter(ai,aj)==7) end2=GRIDMIND[Q11][Q12];
if (quarter(ai,aj)==3 || quarter(ai,aj)==6 || quarter(ai,aj)==9) end2=GRIDMIND[Q31][Q32];
if (quarter(ai,aj)==2 || quarter(ai,aj)==5 || quarter(ai,aj)==8) end2=GRIDMIND[Q11][Q12];
}
if (quarter(ei,ej)==5)
{
//[MH] if enemy is in center of grid , go around the grid from Q2 to Q3 to Q6 to Q7 to Q9 to Q8 to Q9 to Q6
if (quarter(ai,aj)==1) end2=GRIDMIND[Q21][Q22];
if (quarter(ai,aj)==2) end2=GRIDMIND[Q31][Q32];
if (quarter(ai,aj)==3) end2=GRIDMIND[Q61][Q62];
if (quarter(ai,aj)==4) end2=GRIDMIND[Q71][Q72];
if (quarter(ai,aj)==6) end2=GRIDMIND[Q91][Q92];
if (quarter(ai,aj)==7) end2=GRIDMIND[Q81][Q82];
if (quarter(ai,aj)==8) end2=GRIDMIND[Q91][Q92];
if (quarter(ai,aj)==9) end2=GRIDMIND[Q61][Q62];
if (quarter(ai,aj)==5)
{
//[MH] if both enemy and agent are in center of grid , choose next Q to start with based on location of enemy and agent
if (ai<ei && aj<ej) end2= GRIDMIND[Q11][Q12];
if (ai<ei && aj>ej) end2= GRIDMIND[Q71][Q72];
if (ai>ei && aj>ej) end2= GRIDMIND[Q91][Q92];
if (ai>ei && aj<ej) end2= GRIDMIND[Q31][Q32];
if (ai<ei) end2= GRIDMIND[Q41][Q42];
if (ai>ei) end2= GRIDMIND[Q61][Q62];
if (aj<ej) end2= GRIDMIND[Q21][Q22];
if (aj>ej) end2= GRIDMIND[Q81][Q82];
}
}
//[MH] Start A* with agent location
openSet2.push(start2);
// [MH] Clear values of A*
for ( var i = 0; i < gridsize ; i++ )
{
for ( var j = 0; j < gridsize ; j++ )
{
GRIDMIND[i][j].g=0;
GRIDMIND[i][j].f=0;
GRIDMIND[i][j].h=0;
GRIDMIND[i][j].previou=undefined;
}
}
//[MH] Define enemy spot on grid with value 3
GRIDMIND[ei][ej].value=3;
//[MH] A* Algorithm start
while (openSet2.length > 0)
{
// Best next option
var winner2 = 0;
for (var i = 0; i < openSet2.length; i++)
if (openSet2[i].f < openSet2[winner2].f)
winner2 = i;
var current2 = openSet2[winner2];
// Did I finish?
if (current2 === end2)
{
console.log("success - found path2");
break;
}
// Best option moves from openSet to closedSet
removeFromArray(openSet2, current2);
closedSet2.push(current2);
// Check all the neighbors
var neighbors2 = current2.neighbors;
//--- start of for loop -----------
for (var i = 0; i < neighbors2.length; i++)
{
var neighbor2 = neighbors2[i];
// Valid next spot?
if (!closedSet2.includes(neighbor2) && (neighbor2.value)!==2 && (neighbor2.value)!==1 && (neighbor2.value)!==3) // [MH] Discard walls and mazes and enemy
{
var tempG2 = current2.g + heuristic(neighbor2, current2);
// Is this a better path than before?
var newPath2 = false;
if (openSet2.includes(neighbor2))
{
if (tempG2 < neighbor2.g)
{
neighbor2.g = tempG2;
newPath2 = true;
}
}
else
{
neighbor2.g = tempG2;
newPath2 = true;
openSet2.push(neighbor2);
}
// Yes, it's a better path
if (newPath2 == true)
{
neighbor2.h = heuristic(neighbor2, end2);
neighbor2.f = neighbor2.g + neighbor2.h;
neighbor2.previou = current2;
}
}
}
}
//[MH] Get Path from Agent to Grid random location (end2)
var path2 = [];
var temp2 = current2;
path2.push(temp2);
while (temp2.previou)
{
path2.push(temp2.previou);
temp2 = temp2.previou;
}
si=path2[path2.length-2].i; //[MH] new location for agent , Lenght-2 to discard myself otherwise will not move
sj=path2[path2.length-2].j; //[MH] new location for agent , Lenght-2 to discard myself otherwise will not move
if (si<ai) return 0;
if (si>ai) return 1;
if (sj<aj) return 3;
if (sj>aj) return 2;
else return AB.randomIntAtoB (0,3);
}
};