// Sanchit Shreepraksh Akhauri 20210205
//Agent Mind
// Cloned by Sanchit Akhauri on 20 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.newRun = function()
{
};
AB.mind.endRun = function()
{
};
var agentIntelligent = true; // Samchit : -Defines Agent as smart or simple
// Sanchit : -Stores position of co-ordinates which are closed
var agentclosedList = new Array(gridsize);
// Sanchit : - Stores position of co-ordinates which are open to access and not in closed list.
var agentopenList = {};
// Sanchit : - A Utility Function to check whether destination cell has
// been reached or not
function isAgentDestination(row, col) {
if (row == targeti && col == targetj)
return (true);
else
return (false);
}
// Sanchit : - A Utility Function to trace the path from the source
// to destination
var agentfinalpath = [];
function traceAgentPath(agentcellDetails) {
agentfinalpath = [];
var row = targeti;
var col = targetj;
var Path = [];
var temp = "";
//Stores the co-orinates of parents from distination to source in path variable
while (!(agentcellDetails[row][col].parent_i == row
&& agentcellDetails[row][col].parent_j == col)) {
Path.push(new pair(row, col));
var temp_row = agentcellDetails[row][col].parent_i;
var temp_col = agentcellDetails[row][col].parent_j;
row = temp_row;
col = temp_col;
temp = temp + " ( "+temp_row+" "+temp_col+" )";
}
Path.push(new pair(row, col));
// Stores values from path variable to finalpath variable in the order from enemy to agent
while (Path.length > 0){
agentfinalpath.push(Path.pop());
}
}
function updateAgentOpenList(i, j, agentopen_i, agentopen_j, agentcellDetails) { // Sanchit : - this function updates the value of successor in openList
// To store the 'g', 'h' and 'f' of the 8 successors
var gNew, hNew, fNew;
var foundDest =false; // Flag to inform if the destination is found
if (isValid(i, j)) {
// If the destination cell is the same as the
// current successor
if (isAgentDestination(i, j, destination)) {
// Set the Parent of the destination cell
agentcellDetails[i][j].parent_i = agentopen_i;
agentcellDetails[i][j].parent_j = agentopen_j;
traceAgentPath(agentcellDetails, destination);
foundDest = true;
}
// If the successor is already on the closed
// list or if it is blocked, then ignore it.
// Else do the following
else if (closedList[i][j] == false &&
!occupied(i, j)) {
gNew = agentcellDetails[agentopen_i][agentopen_j].g + 1.0;
hNew = heuristicAgent(i, j);
fNew = gNew + hNew;
if (agentcellDetails[i][j].f == Number.MAX_VALUE ||
agentcellDetails[i][j].f > fNew) {
agentopenList[i + " " + j] = new pPair(fNew, i, j);
// Update the details of this cell
agentcellDetails[i][j].f = fNew;
agentcellDetails[i][j].g = gNew;
agentcellDetails[i][j].h = hNew;
agentcellDetails[i][j].parent_i = agentopen_i;
agentcellDetails[i][j].parent_j = agentopen_j;
}
}
}
return foundDest;
}
AB.mind.getAction = function ( x ) // x is an array of [ ai, aj, ei, ej ]
{
agentIntelligent = true;
var ai = parseInt(x[0]);
var aj = parseInt(x[1]);
var tempi = ai;
var tempj = aj;
// Store co-ordinates of the agent
destination.i = ai;
destination.j = aj;
// Stores position of co-ordinates which are closed
agentclosedList = Array.from({ length: gridsize }, () => Array.from({ length: gridsize }, () => false));
//Store details of each square
var agentcellDetails = new Array(gridsize);
agentcellDetails = Array.from({ length: gridsize }, () => new Array(gridsize));
agentcellDetails = Array.from({ length: gridsize }, () => Array.from({ length: gridsize }, () =>
new Details(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, -1, -1)));
//Update agentcellDetails value of agent starting point
var i = destination.i;
var j = destination.j;
agentcellDetails[i][j].f = 0.0;
agentcellDetails[i][j].g = 0.0;
agentcellDetails[i][j].h = 0.0;
agentcellDetails[i][j].parent_i = i;
agentcellDetails[i][j].parent_j = j;
//Store f(n) and co-ordinates value in agentopenList
agentopenList = {};
agentopenList[i + " " + j] = (new pPair(0.0, i, j));
while (Object.keys(agentopenList).length > 0) { // While tere is value in agentopenList run the loop
//Pop the first value in agentopenList
var firstKey = Object.keys(agentopenList)[0];
var p = agentopenList[firstKey];
delete agentopenList[firstKey];
// Add this vertex to the closed list
agentopen_i = p.set.i;
agentopen_j = p.set.j;
agentclosedList[agentopen_i][agentopen_j] = true;
// Update agentopenList value with successor co-ordinates which are valid, break if the target is found
if (updateAgentOpenList(agentopen_i + 1, agentopen_j, agentopen_i, agentopen_j, agentcellDetails)) break;
if (updateAgentOpenList(agentopen_i, agentopen_j + 1, agentopen_i, agentopen_j, agentcellDetails)) break;
if (updateAgentOpenList(agentopen_i - 1, agentopen_j, agentopen_i, agentopen_j, agentcellDetails)) break;
if (updateAgentOpenList(agentopen_i, agentopen_j - 1, agentopen_i, agentopen_j, agentcellDetails)) break;
}
if (agentfinalpath.length > 2) { // If finalpath's length is greater than 2 then the value in 1 index contains the next step.
var bestPositionAgent = agentfinalpath[1];
if(!occupied(bestPositionAgent.i,bestPositionAgent.j)){
ai = bestPositionAgent.i;
aj = bestPositionAgent.j
}
}
else{ // If final path is zero then no possible path is possible from the agent to the target
changeTargetValue(); // Change the target in this case
return ( AB.randomIntAtoB (0,3) ); // Return random movement
}
setupAgentLine(agentfinalpath); // calls setupAgentLine function
// Returns ndirection to next step depending on value from finalPath
if ( aj > tempj ) return ACTION_UP;
if ( aj < tempj ) return ACTION_DOWN;
if (ai > tempi ) return ACTION_RIGHT;
if ( ai < tempi ) return ACTION_LEFT;
return ( AB.randomIntAtoB (0,3) );
};
// Heuristic evaluation function
function heuristicAgent(ai,aj){
// return Manhattan distance
axisj_distance = aj - targetj;
axisi_distance = ai - targeti;
var result = Math.abs(axisi_distance) + Math.abs(axisj_distance);
return result
}
function setupAgentLine(finalPath) { // Sanchit : - This function draws the A* path from agent to the target every time agent takes a step
const material = new THREE.LineBasicMaterial( { color: 0x0000FF } );
const points = [];
for(var i=1;i<finalPath.length;i++)
points.push( translate(finalPath[i].i, finalPath[i].j));
const geometry = new THREE.BufferGeometry().setFromPoints( points );
const line = new THREE.Line( geometry, material );
ABWorld.scene.add(line);
setTimeout(() => {
geometry.dispose();
material.dispose();
ABWorld.scene.remove(line);
},AB.clockTick);
}