@@ -80,3 +80,31 @@ Team 0.00 Mine 1 Team 0.00 Mine 0 77 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 77 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 94 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 94 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 61 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 14 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 4 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 12 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 97 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 97 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 22 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 22 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 104 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 7 | |||
Team 0.00 Mine 0 Team 0.00 Mine 1 7 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 64 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 64 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 67 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 67 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 63 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 63 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 65 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 65 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 79 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 79 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 61 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 61 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 80 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 80 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 78 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 71 | |||
Team 0.00 Mine 1 Team 0.00 Mine 0 71 |
@@ -10,6 +10,8 @@ | |||
package gr.auth.ee.dsproject.node; | |||
import gr.auth.ee.dsproject.pacman.PacmanUtilities; | |||
/** | |||
* @class Globals | |||
* @brief | |||
@@ -69,5 +71,5 @@ public class Globals { | |||
public static final int[] FALSE_POS = {-1, -1}; | |||
public static final int MAX_DISTANCE = 100; | |||
public static final int MAX_DISTANCE = PacmanUtilities.numberOfRows + PacmanUtilities.numberOfColumns - 1; | |||
} |
@@ -1,115 +0,0 @@ | |||
/** | |||
* @file MinMaxTree.java | |||
* @brief | |||
* File containing the Pacman Min-Max Tree class. | |||
* | |||
* @author Christos Choutouridis 8997 cchoutou@ece.auth.gr | |||
* @author Konstantina Tsechelidou 8445 konstsec@ece.auth.gr | |||
*/ | |||
package gr.auth.ee.dsproject.node; | |||
/** | |||
* @brief | |||
* A tree-like data structure containing move nodes to apply the min-max | |||
* algorithm. | |||
* @note | |||
* This is NOT a real tree. We do not insert node based on a key etc... | |||
*/ | |||
public class MinMaxTree | |||
{ | |||
private Node89978445 root; | |||
/* | |||
* ============ Constructors ============== | |||
*/ | |||
/** | |||
* @brief | |||
* The simple constructor. Just initialize the root to null | |||
*/ | |||
public MinMaxTree () { | |||
root = null; // No root yet | |||
} | |||
/** | |||
* @brief | |||
* A constructor with root | |||
*/ | |||
public MinMaxTree (Node89978445 root) { | |||
setRoot (root); | |||
} | |||
/* | |||
* ========= setter ============ | |||
*/ | |||
/** Set root */ | |||
public Node89978445 setRoot (Node89978445 root) { | |||
return this.root = root; | |||
} | |||
/* | |||
* ========== Tree-like methods ============= | |||
*/ | |||
/** | |||
* @brief | |||
* Insert a node to a parent directly. | |||
* This is NOT a real tree. We do not insert node based on a key | |||
* @param node Node to insert | |||
* @param parent The parent in witch to insert | |||
* @return Reference to inserted node | |||
* If insert fail, returns null | |||
*/ | |||
public static Node89978445 insert (Node89978445 node, Node89978445 parent) { | |||
if (parent.children.add (node)) { | |||
node.parent = parent; | |||
return node; | |||
} | |||
else | |||
return null; | |||
} | |||
/** | |||
* @brief | |||
* Find the child with the minimum evaluation value of a | |||
* specific parent and return a reference to it | |||
* @param parent The parent of children we scan | |||
* @return Reference to the child with the minimum evaluation value | |||
* If parent has no children null. | |||
*/ | |||
public static Node89978445 minChild (Node89978445 parent) | |||
{ | |||
Node89978445 node = null; | |||
double ev, min = Globals.EVAL_MAX+1; | |||
for (int i=0 ; i<parent.children.size() ; ++i) { | |||
if ((ev = parent.children.get(i).getEvaluation()) < min) { | |||
min = ev; | |||
node = parent.children.get (i); | |||
} | |||
} | |||
return node; | |||
} | |||
/** | |||
* @brief | |||
* Find the child with the maximum evaluation value of a | |||
* specific parent and return a reference to it | |||
* @param parent The parent of children we scan | |||
* @return Reference to the child with the maximum evaluation value | |||
* If parent has no children null. | |||
*/ | |||
public static Node89978445 maxChild (Node89978445 parent) | |||
{ | |||
Node89978445 node = null; | |||
double ev, max = Globals.EVAL_MIN-1; | |||
for (int i=0 ; i<parent.children.size() ; ++i) { | |||
if ((ev = parent.children.get(i).getEvaluation()) > max) { | |||
max = ev; | |||
node = parent.children.get (i); | |||
} | |||
} | |||
return node; | |||
} | |||
} |
@@ -25,18 +25,16 @@ import gr.auth.ee.dsproject.pacman.Room; | |||
*/ | |||
public class Node89978445 | |||
{ | |||
double nodeEvaluation; /**< | |||
* Pacman's current move evaluation | |||
* This is used also as the "return status" of the object | |||
*/ | |||
int[] nodeXY; // Pacman's current x,y coordinate | |||
int[][] currentGhostPos; // Array holding the Ghost (x,y) pairs | |||
double nodeEvaluation; /*< | |||
* Pacman's current move evaluation | |||
* This is used also as the "return status" of the object | |||
*/ | |||
int[] nodeXY; // Pacman's current x,y coordinate | |||
int[][] curGhostPos; // Array holding the Ghost (x,y) pairs | |||
int[][] flagPos; // Array holding the flag (x,y) pairs | |||
boolean[] currentFlagStatus; // Array holding the flag capture status | |||
Room[][] Maze; // copy of the current Maze | |||
int[][] flagPos; // Array holding the flag (x,y) pairs | |||
boolean[] curFlagStatus; // Array holding the flag capture status | |||
Room[][] Maze; // copy of the current Maze | |||
/* | |||
* Tree navigation references. These variables are handled by | |||
@@ -65,10 +63,10 @@ public class Node89978445 | |||
parent = null; | |||
// allocate objects | |||
currentGhostPos = new int [PacmanUtilities.numberOfGhosts][2]; | |||
flagPos = new int [PacmanUtilities.numberOfFlags][2]; | |||
currentFlagStatus = new boolean[PacmanUtilities.numberOfFlags]; | |||
children = new ArrayList<Node89978445> (); | |||
curGhostPos = new int [PacmanUtilities.numberOfGhosts][2]; | |||
flagPos = new int [PacmanUtilities.numberOfFlags][2]; | |||
curFlagStatus = new boolean[PacmanUtilities.numberOfFlags]; | |||
children = new ArrayList<Node89978445> (); | |||
} | |||
/** | |||
@@ -85,10 +83,18 @@ public class Node89978445 | |||
parent = null; | |||
// allocate objects | |||
currentGhostPos = new int [PacmanUtilities.numberOfGhosts][2]; | |||
flagPos = new int [PacmanUtilities.numberOfFlags][2]; | |||
currentFlagStatus = new boolean[PacmanUtilities.numberOfFlags]; | |||
children = new ArrayList<Node89978445> (); | |||
curGhostPos = new int [PacmanUtilities.numberOfGhosts][2]; | |||
flagPos = new int [PacmanUtilities.numberOfFlags][2]; | |||
curFlagStatus = new boolean[PacmanUtilities.numberOfFlags]; | |||
children = new ArrayList<Node89978445> (); | |||
// calculate helper arrays | |||
curGhostPos = findGhosts (); | |||
flagPos = findFlags (); | |||
curFlagStatus = checkFlags (); | |||
//Evaluate the position | |||
nodeEvaluation = evaluate (); | |||
} | |||
/* | |||
@@ -123,10 +129,15 @@ public class Node89978445 | |||
{ | |||
// If already evaluated do not re-evaluate the move | |||
if (nodeEvaluation == Globals.NO_EVAL) { | |||
// Safety filters | |||
if (Maze == null) | |||
return Globals.NO_EVAL; | |||
if (nodeXY == Globals.FALSE_POS) | |||
return Globals.NO_EVAL; | |||
// calculate helper arrays | |||
currentGhostPos = findGhosts (); | |||
curGhostPos = findGhosts (); | |||
flagPos = findFlags (); | |||
currentFlagStatus = checkFlags (); | |||
curFlagStatus = checkFlags (); | |||
return nodeEvaluation = evaluate (); | |||
} | |||
@@ -134,16 +145,30 @@ public class Node89978445 | |||
return nodeEvaluation; | |||
} | |||
public int[] getCurentPacmanPos () { | |||
public int[] getCurrentPacmanPos () { | |||
return nodeXY; | |||
} | |||
public int[][] getCurrentGhostPos () { | |||
return currentGhostPos; | |||
return curGhostPos; | |||
} | |||
public int getDepth () { | |||
return depth; | |||
} | |||
/* | |||
* ============= Helper API ============ | |||
*/ | |||
public static int moveConv (int[] nextPos, int[] curPos) | |||
{ | |||
int dx = nextPos[0] - curPos[0]; | |||
int dy = nextPos[1] - curPos[1]; | |||
if (dx < 0) return Room.NORTH; | |||
else if (dx > 0) return Room.SOUTH; | |||
else if (dy < 0) return Room.WEST; | |||
else return Room.EAST; | |||
} | |||
/** | |||
* @param creature creature's (x,y) | |||
* @return | |||
@@ -273,9 +298,17 @@ public class Node89978445 | |||
} | |||
/* | |||
* ============ evaluation helper methods ============== | |||
* ============ private evaluation helper methods ============== | |||
*/ | |||
private enum Creature { | |||
GHOST, PACMAN | |||
} | |||
/** | |||
* @brief | |||
* Check if the requested ghost move is valid | |||
*/ | |||
private int[] ghostValidMove (int[] ghost, int move) | |||
{ | |||
int[] newPos = new int[2]; | |||
@@ -299,7 +332,7 @@ public class Node89978445 | |||
/** | |||
* @brief | |||
* Check if the requested move is valid | |||
* Check if the requested pacman move is valid | |||
*/ | |||
private int[] pacmanValidMove (int[] pacman, int move) | |||
{ | |||
@@ -328,12 +361,14 @@ public class Node89978445 | |||
/** | |||
* @brief | |||
* A Breadth-first search to find the shortest path distance | |||
* from a ghost to a point in the maze | |||
* @param ghost Ghost (x, y) | |||
* @param xy The x, y coordinate in Maze | |||
* @return | |||
* from an origin point to another point in the maze as if a | |||
* a creature could walk through | |||
* @param origin origin (x, y) | |||
* @param xy The x, y coordinate in Maze | |||
* @param creature The type of creature for whom the path is for | |||
* @return The number of steps from origin to xy | |||
*/ | |||
private int ghostMoveDist (int[] ghost, int[] xy) | |||
private int moveDist (int[] origin, int[] xy, Creature creature) | |||
{ | |||
int move; | |||
int steps, qStepItems; // distance and group counters | |||
@@ -342,10 +377,10 @@ public class Node89978445 | |||
int c = PacmanUtilities.numberOfColumns; // helper for shorting names | |||
int[] xyItem = new int [2]; // Coordinates of the current position of the algo | |||
int[] xyNext = new int [2]; // Coordinates of the next valid position of the algo | |||
Queue2D q = new Queue2D (r+c - 1); // Queue to feed with possible position | |||
Queue2D q = new Queue2D (Globals.MAX_DISTANCE - 1); // Queue to feed with possible position | |||
int [][] dist = new int [r][c]; | |||
/*< | |||
* 2D array holding all the distances from the ghost to each square of the maze | |||
* 2D array holding all the distances from the origin to each square of the maze | |||
*/ | |||
// If target square is inside a box abort with max distance | |||
@@ -362,8 +397,8 @@ public class Node89978445 | |||
} | |||
} | |||
// loop data | |||
dist [ghost[0]][ghost[1]] = 0; //starting point is the ghost position | |||
q.insert (ghost); // feed first loop data | |||
dist [origin[0]][origin[1]] = 0; //starting point is the origin position | |||
q.insert (origin); // feed first loop data | |||
qStepItems = 1; // init counters | |||
steps = 1; | |||
/* | |||
@@ -380,94 +415,12 @@ public class Node89978445 | |||
--qStepItems; // mark the removal of the item | |||
for (move=0 ; move<4 ; ++move) { | |||
// loop every valid next position for the current position | |||
if ((xyNext = ghostValidMove (xyItem, move)) != Globals.FALSE_POS) { | |||
if (dist[xyNext[0]][xyNext[1]] == -1) { | |||
// If we haven't been there | |||
dist[xyNext[0]][xyNext[1]] = steps; // mark the distance | |||
if ((xyNext[0] == xy[0]) && (xyNext[1] == xy[1])) { | |||
/* | |||
* first match: | |||
* The first time we reach destination we have count the | |||
* distance. No need any other try | |||
*/ | |||
done = true; | |||
break; | |||
} | |||
else { | |||
// If we are not there yet, feed queue with another position | |||
q.insert (xyNext); | |||
} | |||
} | |||
switch (creature) { | |||
case GHOST: xyNext = ghostValidMove (xyItem, move); break; | |||
case PACMAN: xyNext = pacmanValidMove (xyItem, move); break; | |||
default: xyNext = Globals.FALSE_POS; | |||
} | |||
} | |||
} | |||
else { | |||
// We are done with group, mark how many are for the next one | |||
if ((qStepItems = q.size()) <= 0) | |||
return dist[xy[0]][xy[1]]; // fail safe return | |||
++steps; // Update distance counter | |||
} | |||
} | |||
return dist[xy[0]][xy[1]]; | |||
} | |||
/** | |||
* @brief | |||
* A Breadth-first search to find the shortest path distance | |||
* from the pacman to a point in the maze. The point will normaly | |||
* represent a flag | |||
* @param pacman Pacman's (x, y) | |||
* @param xy The x, y coordinate in Maze | |||
* @return | |||
*/ | |||
private int pacmanMoveDist (int[] pacman, int[] xy) | |||
{ | |||
int move; | |||
int steps, qStepItems; // distance and group counters | |||
boolean done = false; // algo ending flag | |||
int r = PacmanUtilities.numberOfRows; // helper for shorting names | |||
int c = PacmanUtilities.numberOfColumns; // helper for shorting names | |||
int[] xyItem = new int [2]; // Coordinates of the current position of the algo | |||
int[] xyNext = new int [2]; // Coordinates of the next valid position of the algo | |||
Queue2D q = new Queue2D (r+c - 1); // Queue to feed with possible position | |||
int [][] dist = new int [r][c]; | |||
/* | |||
* 2D array holding all the distances from pacman to each square of the maze | |||
*/ | |||
// If target square is inside a box abort with max distance | |||
if (isInsideBox (xy)) | |||
return Globals.MAX_DISTANCE; | |||
/* | |||
* init data for algorithm | |||
*/ | |||
for (int i=0 ; i<r ; ++i) { | |||
for (int j=0 ; j<c ; ++j) { | |||
dist[i][j] = -1; | |||
// dist array starts with -1 | |||
} | |||
} | |||
// loop data | |||
dist [pacman[0]][pacman[1]] = 0; //starting point is the pacman position | |||
q.insert (pacman); // feed first loop data | |||
qStepItems = 1; // init counters | |||
steps = 1; | |||
/* | |||
* Main loop of the algorithm | |||
* | |||
* For every position we check the valid moves, we apply to them | |||
* the step number and we push them to queue. We group the items in | |||
* queue with their step number by measuring how many we push them for | |||
* the current steps variable value. | |||
*/ | |||
while (done == false) { | |||
if (qStepItems>0) { // Have we any item on the current group? | |||
xyItem = q.remove (); //load an item of the current group | |||
--qStepItems; // mark the removal of the item | |||
for (move=0 ; move<4 ; ++move) { | |||
// loop every valid next position for the current position | |||
if ((xyNext = pacmanValidMove (xyItem, move)) != Globals.FALSE_POS) { | |||
if (xyNext != Globals.FALSE_POS) { | |||
if (dist[xyNext[0]][xyNext[1]] == -1) { | |||
// If we haven't been there | |||
dist[xyNext[0]][xyNext[1]] = steps; // mark the distance | |||
@@ -515,7 +468,7 @@ public class Node89978445 | |||
// Find ghost distances, min and average | |||
for (i=0, averGhostDist=0 ; i<PacmanUtilities.numberOfGhosts ; ++i) { | |||
ghostDist [i] = ghostMoveDist (currentGhostPos[i], nodeXY); | |||
ghostDist [i] = moveDist (curGhostPos[i], nodeXY, Creature.GHOST); | |||
averGhostDist += ghostDist [i]; | |||
if (minGhostDist > ghostDist[i]) | |||
minGhostDist = ghostDist[i]; | |||
@@ -528,8 +481,8 @@ public class Node89978445 | |||
// Find flag distances and min | |||
for (i=0 ; i<PacmanUtilities.numberOfFlags ; ++i) { | |||
if (currentFlagStatus[i] == false) { | |||
flagDist[i] = pacmanMoveDist (nodeXY, flagPos[i]); | |||
if (curFlagStatus[i] == false) { | |||
flagDist[i] = moveDist (nodeXY, flagPos[i], Creature.PACMAN); | |||
if (minFlagDist > flagDist[i]) | |||
minFlagDist = flagDist[i]; | |||
} | |||
@@ -0,0 +1,100 @@ | |||
/** | |||
* @file MinMaxTree.java | |||
* @brief | |||
* File containing the Pacman Min-Max Tree class. | |||
* | |||
* @author Christos Choutouridis 8997 cchoutou@ece.auth.gr | |||
* @author Konstantina Tsechelidou 8445 konstsec@ece.auth.gr | |||
*/ | |||
package gr.auth.ee.dsproject.node; | |||
/** | |||
* @brief | |||
* A tree-like data structure containing move nodes to apply the min-max | |||
* algorithm. | |||
* @note | |||
* This is NOT a real tree. We do not insert node based on a key etc... | |||
*/ | |||
public class Tree | |||
{ | |||
/* | |||
* ============ Constructor ============== | |||
*/ | |||
/** | |||
* @brief | |||
* The simple constructor. Do nothing (this is a static class) | |||
*/ | |||
public Tree () { } | |||
/* | |||
* ========== private helpers ============== | |||
*/ | |||
private static double min (double x, double y) { | |||
return (x < y) ? x : y; | |||
} | |||
private static double max (double x, double y) { | |||
return (x > y) ? x : y; | |||
} | |||
/* | |||
* ========== Tree-like public methods ============= | |||
*/ | |||
/** | |||
* @brief | |||
* Insert a node to a parent directly. | |||
* This is NOT a real tree. We do not insert node based on a key | |||
* @param node Node to insert | |||
* @param parent The parent in witch to insert | |||
* @return Reference to inserted node | |||
* If insert fail, returns null | |||
*/ | |||
public static Node89978445 grow (Node89978445 node, Node89978445 parent) { | |||
if (parent.children.add (node)) { | |||
node.parent = parent; | |||
node.depth = parent.depth + 1; | |||
return node; | |||
} | |||
else | |||
return null; | |||
} | |||
public static Node89978445 minmaxAB (Node89978445 node, int depth, double a, double b, boolean maxingPlayer) | |||
{ | |||
double v, ev; | |||
Node89978445 vNode = null; | |||
if ((depth == 0) || (node.children.isEmpty())) | |||
return node; | |||
if (maxingPlayer) { | |||
v = Globals.EVAL_MIN - 1; | |||
for (int i=0 ; i<node.children.size() ; ++i) { | |||
ev = minmaxAB (node.children.get (i), depth-1, a, b, false).getEvaluation(); | |||
if (ev > v) { | |||
v = ev; | |||
vNode = node.children.get (i); | |||
} | |||
a = max (v, a); | |||
if (b <= a) | |||
break; | |||
} | |||
return vNode; | |||
} | |||
else { | |||
v = Globals.EVAL_MAX + 1; | |||
for (int i=0 ; i<node.children.size() ; ++i) { | |||
ev = minmaxAB(node.children.get (i), depth-1, a, b, true).getEvaluation(); | |||
if (ev < v) { | |||
v = ev; | |||
vNode = node.children.get (i); | |||
} | |||
b = min (v, b); | |||
if (b <= a) | |||
break; | |||
} | |||
return vNode; | |||
} | |||
} | |||
} |
@@ -3,7 +3,7 @@ package gr.auth.ee.dsproject.pacman; | |||
import java.util.ArrayList; | |||
import gr.auth.ee.dsproject.node.Globals; | |||
import gr.auth.ee.dsproject.node.MinMaxTree; | |||
import gr.auth.ee.dsproject.node.Tree; | |||
import gr.auth.ee.dsproject.node.Node89978445; | |||
/** | |||
@@ -38,33 +38,42 @@ public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature | |||
private int step = 1; | |||
private boolean amPrey; | |||
public Creature (boolean isPrey) | |||
{ | |||
public Creature (boolean isPrey) { | |||
amPrey = isPrey; | |||
} | |||
/** | |||
* @brief | |||
* Create node for each one of the possible moves (0, 1, 2, 3) and | |||
* evaluate these moves. | |||
* | |||
*/ | |||
public int calculateNextPacmanPosition (Room[][] Maze, int[] currPosition) | |||
{ | |||
Node89978445 cur = new Node89978445 (Maze, currPosition); | |||
MinMaxTree mmTree = new MinMaxTree (cur); /*< | |||
* Plant a tree with dummy root | |||
* Null parent and no evaluation | |||
*/ | |||
createSubTreePacman (0, cur, Maze, currPosition); //make the tree | |||
// min-max | |||
return 0; | |||
int [] bestPos = {-1, -1}; // Best position in maze to play | |||
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, Globals.EVAL_MIN - 1, Globals.EVAL_MAX + 1, true); | |||
bestPos = bestNode.getCurrentPacmanPos(); | |||
// convert back to move encoding | |||
return Node89978445.moveConv (bestPos, currPosition); | |||
} | |||
/** | |||
* | |||
*/ | |||
void createSubTreePacman (int depth, Node89978445 parent, Room[][] Maze, int[] curPacmanPosition) | |||
{ | |||
if (++depth > Globals.MINMAXTREE_MAX_DEPTH) | |||
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; | |||
@@ -76,23 +85,31 @@ public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature | |||
if ((nextPosition = Node89978445.pacmanValidMove (parent, move)) != Globals.FALSE_POS) { | |||
// Make a copy of the maze in order to simulate next move and move Pacman | |||
newMaze = PacmanUtilities.copy (Maze); | |||
PacmanUtilities.movePacman (newMaze, parent.getCurentPacmanPos(), nextPosition); | |||
PacmanUtilities.movePacman (newMaze, parent.getCurrentPacmanPos(), nextPosition); | |||
// Create a node for the move in the new stated game maze | |||
newNode = new Node89978445 (newMaze, nextPosition); | |||
newNode.getEvaluation(); | |||
MinMaxTree.insert (newNode, parent); // add node to the min-max tree | |||
Tree.grow (newNode, parent); // add node to the min-max tree | |||
// call the recursive ranch creator | |||
createSubTreeGhosts (depth, newNode, newMaze, newNode.getCurrentGhostPos()); | |||
createSubTreeGhosts (newNode.getDepth (), newNode, newMaze, newNode.getCurrentGhostPos()); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* | |||
*/ | |||
void createSubTreeGhosts (int depth, Node89978445 parent, Room[][] Maze, int[][] currGhostsPosition) | |||
{ | |||
if (++depth > Globals.MINMAXTREE_MAX_DEPTH) | |||
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; | |||
@@ -103,19 +120,17 @@ public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature | |||
ghostMoves = PacmanUtilities.allGhostMoves(Maze, currGhostsPosition); | |||
// loop all ghost moves | |||
int s = ghostMoves.size(); | |||
for (int i=0 ; i<s ; ++i) { | |||
for (int i=0 ; i<ghostMoves.size() ; ++i) { | |||
// Make a copy of the maze in order to simulate next move and move ghosts | |||
newMaze = PacmanUtilities.copy (Maze); | |||
PacmanUtilities.moveGhosts(newMaze, currGhostsPosition, ghostMoves.get(i)); | |||
// Create a node for the move in the new stated game maze | |||
newNode = new Node89978445 (newMaze, parent.getCurentPacmanPos()); | |||
newNode.getEvaluation(); | |||
MinMaxTree.insert (newNode, parent); // add node to the min-max tree | |||
newNode = new Node89978445 (newMaze, parent.getCurrentPacmanPos()); | |||
Tree.grow (newNode, parent); // add node to the min-max tree | |||
//recursive call for the rest of the tree | |||
//createSubTreePacman (depth, newNode, newMaze, parent.getCurentPacmanPos()); | |||
createSubTreePacman (newNode.getDepth (), newNode, newMaze, parent.getCurrentPacmanPos()); | |||
} | |||
} | |||
} | |||