@@ -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 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 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; | package gr.auth.ee.dsproject.node; | ||||
import gr.auth.ee.dsproject.pacman.PacmanUtilities; | |||||
/** | /** | ||||
* @class Globals | * @class Globals | ||||
* @brief | * @brief | ||||
@@ -69,5 +71,5 @@ public class Globals { | |||||
public static final int[] FALSE_POS = {-1, -1}; | 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 | 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 | * Tree navigation references. These variables are handled by | ||||
@@ -65,10 +63,10 @@ public class Node89978445 | |||||
parent = null; | parent = null; | ||||
// allocate objects | // 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; | parent = null; | ||||
// allocate objects | // 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 already evaluated do not re-evaluate the move | ||||
if (nodeEvaluation == Globals.NO_EVAL) { | 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 | // calculate helper arrays | ||||
currentGhostPos = findGhosts (); | |||||
curGhostPos = findGhosts (); | |||||
flagPos = findFlags (); | flagPos = findFlags (); | ||||
currentFlagStatus = checkFlags (); | |||||
curFlagStatus = checkFlags (); | |||||
return nodeEvaluation = evaluate (); | return nodeEvaluation = evaluate (); | ||||
} | } | ||||
@@ -134,16 +145,30 @@ public class Node89978445 | |||||
return nodeEvaluation; | return nodeEvaluation; | ||||
} | } | ||||
public int[] getCurentPacmanPos () { | |||||
public int[] getCurrentPacmanPos () { | |||||
return nodeXY; | return nodeXY; | ||||
} | } | ||||
public int[][] getCurrentGhostPos () { | public int[][] getCurrentGhostPos () { | ||||
return currentGhostPos; | |||||
return curGhostPos; | |||||
} | |||||
public int getDepth () { | |||||
return depth; | |||||
} | } | ||||
/* | /* | ||||
* ============= Helper API ============ | * ============= 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) | * @param creature creature's (x,y) | ||||
* @return | * @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) | private int[] ghostValidMove (int[] ghost, int move) | ||||
{ | { | ||||
int[] newPos = new int[2]; | int[] newPos = new int[2]; | ||||
@@ -299,7 +332,7 @@ public class Node89978445 | |||||
/** | /** | ||||
* @brief | * @brief | ||||
* Check if the requested move is valid | |||||
* Check if the requested pacman move is valid | |||||
*/ | */ | ||||
private int[] pacmanValidMove (int[] pacman, int move) | private int[] pacmanValidMove (int[] pacman, int move) | ||||
{ | { | ||||
@@ -328,12 +361,14 @@ public class Node89978445 | |||||
/** | /** | ||||
* @brief | * @brief | ||||
* A Breadth-first search to find the shortest path distance | * 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 move; | ||||
int steps, qStepItems; // distance and group counters | int steps, qStepItems; // distance and group counters | ||||
@@ -342,10 +377,10 @@ public class Node89978445 | |||||
int c = PacmanUtilities.numberOfColumns; // 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[] 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 | 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]; | 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 | // If target square is inside a box abort with max distance | ||||
@@ -362,8 +397,8 @@ public class Node89978445 | |||||
} | } | ||||
} | } | ||||
// loop data | // 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 | qStepItems = 1; // init counters | ||||
steps = 1; | steps = 1; | ||||
/* | /* | ||||
@@ -380,94 +415,12 @@ public class Node89978445 | |||||
--qStepItems; // mark the removal of the item | --qStepItems; // mark the removal of the item | ||||
for (move=0 ; move<4 ; ++move) { | for (move=0 ; move<4 ; ++move) { | ||||
// loop every valid next position for the current position | // 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 (dist[xyNext[0]][xyNext[1]] == -1) { | ||||
// If we haven't been there | // If we haven't been there | ||||
dist[xyNext[0]][xyNext[1]] = steps; // mark the distance | dist[xyNext[0]][xyNext[1]] = steps; // mark the distance | ||||
@@ -515,7 +468,7 @@ public class Node89978445 | |||||
// Find ghost distances, min and average | // Find ghost distances, min and average | ||||
for (i=0, averGhostDist=0 ; i<PacmanUtilities.numberOfGhosts ; ++i) { | 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]; | averGhostDist += ghostDist [i]; | ||||
if (minGhostDist > ghostDist[i]) | if (minGhostDist > ghostDist[i]) | ||||
minGhostDist = ghostDist[i]; | minGhostDist = ghostDist[i]; | ||||
@@ -528,8 +481,8 @@ public class Node89978445 | |||||
// Find flag distances and min | // Find flag distances and min | ||||
for (i=0 ; i<PacmanUtilities.numberOfFlags ; ++i) { | 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]) | if (minFlagDist > flagDist[i]) | ||||
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 java.util.ArrayList; | ||||
import gr.auth.ee.dsproject.node.Globals; | 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; | 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 int step = 1; | ||||
private boolean amPrey; | private boolean amPrey; | ||||
public Creature (boolean isPrey) | |||||
{ | |||||
public Creature (boolean isPrey) { | |||||
amPrey = 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) | 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) | 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; | return; | ||||
else { | else { | ||||
Node89978445 newNode; | 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) { | if ((nextPosition = Node89978445.pacmanValidMove (parent, move)) != Globals.FALSE_POS) { | ||||
// Make a copy of the maze in order to simulate next move and move Pacman | // Make a copy of the maze in order to simulate next move and move Pacman | ||||
newMaze = PacmanUtilities.copy (Maze); | 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 | // Create a node for the move in the new stated game maze | ||||
newNode = new Node89978445 (newMaze, nextPosition); | 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 | // 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) | 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; | return; | ||||
else { | else { | ||||
Node89978445 newNode; | Node89978445 newNode; | ||||
@@ -103,19 +120,17 @@ public class Creature implements gr.auth.ee.dsproject.pacman.AbstractCreature | |||||
ghostMoves = PacmanUtilities.allGhostMoves(Maze, currGhostsPosition); | ghostMoves = PacmanUtilities.allGhostMoves(Maze, currGhostsPosition); | ||||
// loop all ghost moves | // 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 | // Make a copy of the maze in order to simulate next move and move ghosts | ||||
newMaze = PacmanUtilities.copy (Maze); | newMaze = PacmanUtilities.copy (Maze); | ||||
PacmanUtilities.moveGhosts(newMaze, currGhostsPosition, ghostMoves.get(i)); | PacmanUtilities.moveGhosts(newMaze, currGhostsPosition, ghostMoves.get(i)); | ||||
// Create a node for the move in the new stated game maze | // 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 | //recursive call for the rest of the tree | ||||
//createSubTreePacman (depth, newNode, newMaze, parent.getCurentPacmanPos()); | |||||
createSubTreePacman (newNode.getDepth (), newNode, newMaze, parent.getCurrentPacmanPos()); | |||||
} | } | ||||
} | } | ||||
} | } | ||||