package gr.auth.ee.dsproject.pacman;
import java.util.ArrayList;
import gr.auth.ee.dsproject.node.Globals;
import gr.auth.ee.dsproject.node.Tree;
import gr.auth.ee.dsproject.node.Node89978445;
/**
*
* Title: DataStructures2011
*
*
*
* Description: Data Structures project: year 2011-2012
*
*
*
* Copyright: Copyright (c) 2011
*
*
*
* Company: A.U.Th.
*
*
* @author Michael T. Tsapanos
* @version 1.0
*/
public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature
{
public String getName () {
return "Mine";
}
private int step = 1;
private boolean amPrey;
public Creature (boolean isPrey) {
amPrey = isPrey;
}
/**
* @brief
* For any current position creates a tree for minmax alpha-beta pruning algorithm
* apply the min-max algo and return the move representing by resulting node
* @return
* the move of pacman to play
*/
public int calculateNextPacmanPosition (Room[][] Maze, int[] currPosition)
{
int [] bestPos = {-1, -1}; // Best position in maze to play
int bestMove = 0;
Node89978445 bestNode; // The node with the best evaluation
Node89978445 cur = new Node89978445 (Maze, currPosition); // The node with the current position
//make the tree
createSubTreePacman (cur.getDepth (), cur, Maze, currPosition);
// min-max to find best node and consequently the best position
bestNode = Tree.minmaxAB (cur, Globals.MINMAXTREE_MAX_DEPTH-1, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
bestPos = bestNode.getCurrentPacmanPos();
// convert back to move encoding
if ((bestMove = Node89978445.moveConv (bestPos, currPosition)) != Globals.INVALID_MOVE)
return bestMove;
else
return 0;
}
/**
* @brief
* For any ghost (or root) parent node, create all child nodes representing
* pacman's valid moves.
* @note
* This routine calls createSubTreeGhosts() called back from it recursively.
* The recursion ends when the right depth is reached.
*/
void createSubTreePacman (int depth, Node89978445 parent, Room[][] Maze, int[] curPacmanPosition)
{
if (depth >= Globals.MINMAXTREE_MAX_DEPTH-1)
/*<
* As the depth starts from 0 and MINMAXTREE_MAX_DEPTH
* is strictly even, with this comparison we accept that there
* is no need for a max-depth layer of ghosts-evaluation based nodes.
* As soon as we accept the depth-1 layers max evaluated node.
*/
return;
else {
Node89978445 newNode;
Room[][] newMaze;
int[] nextPosition = {-1, -1};
// scan possible valid moves
for (int move=0 ; move<4 ; ++move) {
if ((nextPosition = Node89978445.pacmanValidMove (parent, move)) != Globals.POSITION_FALSE) {
// Make a copy of the maze in order to simulate next move and move Pacman
newMaze = PacmanUtilities.copy (Maze);
PacmanUtilities.movePacman (newMaze, parent.getCurrentPacmanPos(), nextPosition);
// Create a node for the move in the new stated game maze
newNode = new Node89978445 (newMaze, nextPosition);
Tree.grow (newNode, parent); // add node to the min-max search tree
// call the recursive branch creator
createSubTreeGhosts (newNode.getDepth (), newNode, newMaze, newNode.getCurrentGhostPos());
}
}
}
}
/**
* @brief
* For any parent node, create all child node representing ghosts valid moves.
* @note
* This routine recursively call createSubTreePacman().
* The recursion ends when the right depth is reached.
*/
void createSubTreeGhosts (int depth, Node89978445 parent, Room[][] Maze, int[][] currGhostsPosition)
{
if (depth >= Globals.MINMAXTREE_MAX_DEPTH-1)
/*<
* As the depth starts from 0 and MINMAXTREE_MAX_DEPTH
* is strictly even, with this comparison we accept that there
* is no need for a max-depth layer of ghosts-evaluation based nodes.
* As soon as we accept the depth-1 layers max evaluated node.
*/
return;
else {
Node89978445 newNode;
Room[][] newMaze;
ArrayList ghostMoves;
// Get all possible ghost moves
ghostMoves = PacmanUtilities.allGhostMoves(Maze, currGhostsPosition);
// loop all ghost moves
for (int i=0 ; i -1; j--) {
switch (moves[j]) {
case Room.WEST:
newPos[j][0] = currentPos[j][0];
newPos[j][1] = currentPos[j][1] - 1;
break;
case Room.SOUTH:
newPos[j][0] = currentPos[j][0] + 1;
newPos[j][1] = currentPos[j][1];
break;
case Room.EAST:
newPos[j][0] = currentPos[j][0];
newPos[j][1] = currentPos[j][1] + 1;
break;
case Room.NORTH:
newPos[j][0] = currentPos[j][0] - 1;
newPos[j][1] = currentPos[j][1];
// break;
}
if ((newPos[currentGhost][0] == newPos[j][0]) && (newPos[currentGhost][1] == newPos[j][1])) {
availablePositions[i] = false;
continue;
}
if ((newPos[currentGhost][0] == currentPos[j][0]) && (newPos[currentGhost][1] == currentPos[j][1]) && (newPos[j][0] == currentPos[currentGhost][0])
&& (newPos[j][1] == currentPos[currentGhost][1])) {
availablePositions[i] = false;
}
}
}
}
return availablePositions;
}
public int comBestPos (boolean[] availablePositions, int[] pacmanPosition, int[] currentPos)
{
int[] newVerticalDifference = new int[2];
for (int i = 0; i < 2; i++)
newVerticalDifference[i] = currentPos[i] - pacmanPosition[i];
int[] distanceSquared = new int[4];
for (int i = 0; i < 4; i++) {
if (availablePositions[i] == true) {
switch (i) {
case Room.WEST:
newVerticalDifference[1]--;
break;
case Room.SOUTH:
newVerticalDifference[0]++;
break;
case Room.EAST:
newVerticalDifference[1]++;
break;
case Room.NORTH:
newVerticalDifference[0]--;
break;
}
distanceSquared[i] = newVerticalDifference[0] * newVerticalDifference[0] + newVerticalDifference[1] * newVerticalDifference[1];
} else
distanceSquared[i] = PacmanUtilities.numberOfRows * PacmanUtilities.numberOfRows + PacmanUtilities.numberOfColumns * PacmanUtilities.numberOfColumns + 1;
}
int minDistance = distanceSquared[0];
int minPosition = 0;
for (int i = 1; i < 4; i++) {
if (minDistance > distanceSquared[i]) {
minDistance = distanceSquared[i];
minPosition = i;
}
}
return minPosition;
}
public int[] calculateNextGhostPosition (Room[][] Maze, int[][] currentPos)
{
int[] moves = new int[PacmanUtilities.numberOfGhosts];
int[] pacmanPosition = new int[2];
pacmanPosition = getPacPos(Maze);
for (int i = 0; i < PacmanUtilities.numberOfGhosts; i++) {
moves[i] = comBestPos(comAvPos(Maze, currentPos, moves, i), pacmanPosition, currentPos[i]);
}
return moves;
}
public boolean[] checkCollision (int[] moves, int[][] currentPos)
{
boolean[] collision = new boolean[PacmanUtilities.numberOfGhosts];
int[][] newPos = new int[4][2];
for (int i = 0; i < moves.length; i++) {
if (moves[i] == 0) {
if (currentPos[i][1] > 0) {
newPos[i][0] = currentPos[i][0];
newPos[i][1] = currentPos[i][1] - 1;
} else {
newPos[i][0] = currentPos[i][0];
newPos[i][1] = PacmanUtilities.numberOfColumns - 1;
}
} else if (moves[i] == 1) {
if (currentPos[i][0] < PacmanUtilities.numberOfRows - 1) {
newPos[i][0] = currentPos[i][0] + 1;
newPos[i][1] = currentPos[i][1];
} else {
newPos[i][0] = 0;
newPos[i][1] = currentPos[i][1];
}
} else if (moves[i] == 2) {
if (currentPos[i][1] < PacmanUtilities.numberOfColumns - 1) {
newPos[i][0] = currentPos[i][0];
newPos[i][1] = currentPos[i][1] + 1;
} else {
newPos[i][0] = currentPos[i][0];
newPos[i][1] = 0;
}
} else {
if (currentPos[i][0] > 0) {
newPos[i][0] = currentPos[i][0] - 1;
newPos[i][1] = currentPos[i][1];
} else {
newPos[i][0] = PacmanUtilities.numberOfRows - 1;
newPos[i][1] = currentPos[i][1];
}
}
collision[i] = false;
}
for (int k = 0; k < moves.length; k++) {
}
for (int i = 0; i < moves.length; i++) {
for (int j = i + 1; j < moves.length; j++) {
if (newPos[i][0] == newPos[j][0] && newPos[i][1] == newPos[j][1]) {
collision[j] = true;
}
if (newPos[i][0] == currentPos[j][0] && newPos[i][1] == currentPos[j][1] && newPos[j][0] == currentPos[i][0] && newPos[j][1] == currentPos[i][1]) {
collision[j] = true;
}
}
}
return collision;
}
}