/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #ifdef NO_DEBUG_SEARCH #undef err_when #undef err_here #undef err_if #undef err_else #undef err_now #define err_when(cond) #define err_here() #define err_if(cond) #define err_else #define err_now(msg) #undef DEBUG #endif NodePriorityQueue SeekPath::open_node_list; NodePriorityQueue SeekPath::closed_node_list; //-------- Begin of function NodePriorityQueue::reset_priority_queue -------// void NodePriorityQueue::reset_priority_queue() { size = 0U; memset(elements, 0, sizeof(Node*)*(MAX_ARRAY_SIZE)); } //-------- End of function NodePriorityQueue::reset_priority_queue ---------// //-------- Begin of function NodePriorityQueue::insert_node -------// void NodePriorityQueue::insert_node(Node *insertNode) { UINT i = ++size; register int f=insertNode->node_f; Node **localElements = elements; while(i>1 && localElements[i/2]->node_f > f) { localElements[i] = localElements[i/2]; i /= 2; } localElements[i] = insertNode; } //-------- End of function NodePriorityQueue::insert_node ---------// //-------- Begin of function NodePriorityQueue::return_min -------// Node* NodePriorityQueue::return_min() { if(!size) return NULL; UINT i, child, doubleI; UINT localSize = size--; Node **localElements = elements; Node *minElement = localElements[1]; Node *lastElement = localElements[localSize]; int lastF = lastElement->node_f; //--------- doubleI = i*2 ---------// for(i=1, doubleI=2; doubleI<=localSize; i=child, doubleI=i<<1) { child = doubleI; if(child!=localSize && localElements[child+1]->node_f < localElements[child]->node_f) child++; if(lastF > localElements[child]->node_f) localElements[i] = localElements[child]; else break; } localElements[i] = lastElement; return minElement; } //-------- End of function NodePriorityQueue::return_min ---------// //-------- Begin of function SeekPath::return_best_node -------// // return : the best node. // NULL if no more node on the open node list. There is no // possible path between the starting and destination points. // Node* SeekPath::return_best_node() { Node *tempNode = open_node_list.return_min(); if(tempNode) closed_node_list.insert_node(tempNode); return tempNode; } //-------- End of function SeekPath::return_best_node ---------// //----- Begin of function SeekPath::return_closest_node -------// // Return the node that is closest to the destination. // Node* SeekPath::return_closest_node() { Node *nodePtr; Node *shortestNode; int shortestDistance=0x7FFFFFFF; shortestNode = open_node_list.return_min(); if(shortestNode) shortestDistance = shortestNode->node_h; nodePtr = closed_node_list.return_min(); if(nodePtr && nodePtr->node_hnode_h; } //--------------------------------------------------------------------------------// // there may be some nodes with the same shortest Distance from the destination node. // However, one should be closer to the starting node. The following is used to find // out the closer node. //--------------------------------------------------------------------------------// if(!shortestNode) return NULL; nodePtr = shortestNode->parent_node; while(nodePtr) { if(nodePtr->node_h <= shortestDistance) { shortestDistance = nodePtr->node_h; shortestNode = nodePtr; } else break; nodePtr=nodePtr->parent_node; } return shortestNode; } //----- End of function SeekPath::return_closest_node -------//