/* deleteNodeOfId deletes the node from the list that is holding a polygon with a certain id * Parameter: (int) idToDelete is the id of the polygon being held by the node to be deleted * Return: none */ public void deleteNodeOfId(int idToDelete) { AIFringeSearchNode tempFront = frontOfList; if (frontOfList != null) { if (doesIDMatch(frontOfList.getPolygon().getID(), idToDelete) == true) { frontOfList = frontOfList.getNextNode(); numberOfNodesHeld--; return; } AIFringeSearchNode tempback = tempFront.getNextNode(); while ((tempback.getNextNode() != null) && (doesIDMatch(tempback.getPolygon().getID(), idToDelete) == false)) { tempFront = tempback; tempback = tempFront.getNextNode(); } if (doesIDMatch(tempback.getPolygon().getID(), idToDelete) == true) { tempFront.setNextNode(tempback.getNextNode()); } numberOfNodesHeld--; } }
/* getNodeOnList returns node from list that contains a specified polygon * Parameter: (AIPolygon) polygonToCheck is the polygon being held by the node to be returned * Return: (AIFringeSearchNode) * node on list that is holding polygonToCheck */ public AIFringeSearchNode getNodeOnList(AIPolygon polygonToCheck) { AIFringeSearchNode tempFront = frontOfList; if (tempFront == null) { return(null); } if (doesIDMatch(polygonToCheck.getID(), tempFront.getPolygon().getID()) == true) { return(tempFront); } AIFringeSearchNode tempBack = tempFront.getNextNode(); while ((tempBack != null) && (tempBack.getNextNode() != null) && (doesIDMatch(polygonToCheck.getID(), tempBack.getPolygon().getID()) == false)) { tempFront = tempBack; tempBack = tempFront.getNextNode(); } if (tempBack == null) { return(null); } if (doesIDMatch(polygonToCheck.getID(), tempBack.getPolygon().getID()) == true) { return(tempBack); } return(null); }
/* * fringeSearch method will preform the fringe search * Parameter: none * Return: none */ void fringeSearch() { AIFringeSearchNode tempNode = fringeList.getNodeOnList(startingPolygon); // the first polygon in the list fLimit = tempNode.getHCost(); //the first limit AIFringeSearchList curList = fringeList; //the current list that will be looked at AIFringeSearchList nextList = new AIFringeSearchList(goalPosition); //the list that the not good polygons will be put into while (goalFound == false && (curList.isEmpty() == false || nextList.isEmpty() == false)) { fMin = float.MaxValue; //reset the fMin firstMin = false; //reset the firstMin while (curList.isEmpty() == false) //goes until the current list is empty { tempNode = curList.popNode(); nodesVisited++; if (tempNode.getTotalCost() > fLimit) // the node is no good and the limit must be incresed { fMin = getMin(tempNode.getTotalCost(), fMin); nextList.pushAtTheEnd(tempNode); //adds the node at the end of the nextList continue; } if (tempNode.getPolygon().getHasGoal() == true) //goal node was found { finalSolutionStart = tempNode; return; } for (int count = tempNode.getPolygon().getNeighborsHeld() - 1; count >= 0; count--) { AIFringeSearchNode childNode = new AIFringeSearchNode(polygonArray[tempNode.getPolygon().getNeighborAt(count)], tempNode, (tempNode.getGFromStartNode() + (tempNode.getPolygon().getCenterVector() - polygonArray[tempNode.getPolygon().getNeighborAt(count)].getCenterVector()).magnitude), goalPosition); if (tempNode.getParentNode() == null || tempNode.getParentNode().getPolygon().getID() != childNode.getPolygon().getID()) //checks to see if the parentNode is the child node trying to be added in { if (cache[tempNode.getPolygon().getNeighborAt(count)] != null) //checks to see if the polygon has already been seen { if (childNode.getGFromStartNode() >= cache[tempNode.getPolygon().getNeighborAt(count)].getGFromStartNode()) { continue; } } if (curList.isNodeOnList(childNode.getPolygon()) == true) //checks to see if the polygon is already on the list { curList.deleteNodeOfId(childNode.getPolygon().getID()); //deletes the node } curList.enqueue(childNode.getPolygon(), childNode.getParentNode(), childNode.getGFromStartNode()); //adds the node at the front of the current list cache[tempNode.getPolygon().getNeighborAt(count)] = childNode; } } if (curList.getSize() > maxQueueSize) { maxQueueSize = curList.getSize(); } } fLimit = fMin; //sets the new Min AIFringeSearchList tempList = curList; curList = nextList; nextList = tempList; } }
//used for debugging void printFinalSolutionRecursively(AIFringeSearchNode currentNode) { if (currentNode != null) { printFinalSolutionRecursively(currentNode.getParentNode()); polygonFinalCount++; } }
/* * addAfter will make a new polygon and add it right after the node being passed in * Parameter: (AIPolygon)polygonToAdd is the polygon for the new node * (AIFringeSearchNode)parentNode is the node that will be the parent of this node * (float)gCostToAdd is the cost to get to this node * Return: none */ public void addAfter(AIPolygon polygonToAdd, AIFringeSearchNode nodeToAddAfter, float gCostToAdd) { AIFringeSearchNode tempNode = new AIFringeSearchNode(polygonToAdd, nodeToAddAfter, gCostToAdd, goalPosition); tempNode.setNextNode(nodeToAddAfter.getNextNode()); nodeToAddAfter.setNextNode(tempNode); numberOfNodesHeld++; }
/* * enqueue method will place a node in the front of the list * Parameter: (AIPolygon)polygonToAdd is the polygon for the new node * (AIFringeSearchNode)parentNode is the node that will be the parent of this node * (float)gCostToAdd is the cost to get to this node * Return: none */ public void enqueue(AIPolygon polygonToAdd, AIFringeSearchNode parentNode, float gCostToAdd) { AIFringeSearchNode tempNode = new AIFringeSearchNode(polygonToAdd, parentNode, gCostToAdd, goalPosition); tempNode.setNextNode(frontOfList); frontOfList = tempNode; numberOfNodesHeld++; }
/* * popNode will remove a node from the front of the the list * Parameter: none * Return: (AIFringeSearchNode) * the node that was removed from the front of the list */ public AIFringeSearchNode popNode() { AIFringeSearchNode temp = frontOfList; frontOfList = temp.getNextNode(); numberOfNodesHeld--; return(temp); }
/* The method AIFringeSearchNode is a contructor for the class * Parameter: AIPolygon polygonToAdd * AIFringeSearchNode parentToAdd * float gCostToAdd * Vector3 goalPositionToAdd */ public AIFringeSearchNode(AIPolygon polygonToAdd, AIFringeSearchNode parentToAdd, float gCostToAdd, Vector3 goalPositionToAdd) { polygonBeingHeld = polygonToAdd; parentNode = parentToAdd; gFromStartingNode = gCostToAdd; nextNode = null; childrenPlaced = false; goalPosition = new Vector3(goalPositionToAdd.x, goalPositionToAdd.y, goalPositionToAdd.z); calculateCost(gFromStartingNode, goalPosition); }
/* * addFinalsolutionPolygons method is a recusive method that will look at the parent of each node passed in until * the node passed in is null, then it will add each Node's polygon to the finalSolutionArray in order * from start until end * Parameter: (AIFringeSearchNode)currentNode is the node that needs to be checked and then have its parent passed * (ref int)counter is the current count of polygons in the FinalSolution array used to access the next index * Return: none */ void addFinalSolutionPolygons(AIFringeSearchNode currentNode, ref int counter) { if (currentNode != null) { addFinalSolutionPolygons(currentNode.getParentNode(), ref counter); finalSolutionArray [counter] = currentNode.getPolygon(); if (counter != 0) { finalPathCost += (finalSolutionArray[counter].getCenterVector() - finalSolutionArray[counter - 1].getCenterVector()).magnitude; } counter++; } }
/* * getNodeAtIndex method will get a node at a certian index in the list * Parameter: (int)index is the index in the list that the caller wants the node of * Return: (AIFringeSearchNode) * the node that was at the index being passed int */ public AIFringeSearchNode getNodeAtIndex(int index) { if (index == 0) { return(frontOfList); } AIFringeSearchNode temp = frontOfList; for (int count = 0; count < index; count++) { temp = temp.getNextNode(); } return(temp); }
/* * pushAtTheEnd method will take a node and push it at the back of the lsit * parameter: (AIFringeSearchNode)nodeToPush is the node the caller wants at the back of the list * Return: none */ public void pushAtTheEnd(AIFringeSearchNode nodeToPush) { if (frontOfList == null) { nodeToPush.setNextNode(frontOfList); frontOfList = nodeToPush; numberOfNodesHeld++; return; } AIFringeSearchNode tempNode = getNodeAtIndex(getSize() - 1); nodeToPush.setNextNode(tempNode.getNextNode()); tempNode.setNextNode(nodeToPush); numberOfNodesHeld++; }
/* The method setParentNode sets the parent node of the curretn node * Parameter: AIFringeSearchNode newParentNode - node to be set as parent * */ public void setParentNode(AIFringeSearchNode newParentNode) { parentNode = newParentNode; }
/* The method setNextNode sets the next node of the current node * AIFringeSearchNode newNextNode - node to be set as next */ public void setNextNode(AIFringeSearchNode newNextNode) { nextNode = newNextNode; }
/* * AIFringeSearchList's constructor will set up the initial values for the instance variables * Parameter: (Vector3)goalPositionToAdd is the position of the goal */ public AIFringeSearchList(Vector3 goalPositionToAdd) { frontOfList = null; numberOfNodesHeld = 0; goalPosition = goalPositionToAdd; }