00001 /* $Id: aystar.h 11700 2007-12-25 23:42:52Z rubidium $ */ 00002 00011 #ifndef AYSTAR_H 00012 #define AYSTAR_H 00013 00014 #include "queue.h" 00015 #include "tile_type.h" 00016 00017 //#define AYSTAR_DEBUG 00018 enum { 00019 AYSTAR_FOUND_END_NODE, 00020 AYSTAR_EMPTY_OPENLIST, 00021 AYSTAR_STILL_BUSY, 00022 AYSTAR_NO_PATH, 00023 AYSTAR_LIMIT_REACHED, 00024 AYSTAR_DONE 00025 }; 00026 00027 enum{ 00028 AYSTAR_INVALID_NODE = -1, 00029 }; 00030 00031 struct AyStarNode { 00032 TileIndex tile; 00033 int direction; 00034 uint user_data[2]; 00035 }; 00036 00037 // The resulting path has nodes looking like this. 00038 struct PathNode { 00039 AyStarNode node; 00040 // The parent of this item 00041 PathNode *parent; 00042 }; 00043 00044 // For internal use only 00045 // We do not save the h-value, because it is only needed to calculate the f-value. 00046 // h-value should _always_ be the distance left to the end-tile. 00047 struct OpenListNode { 00048 int g; 00049 PathNode path; 00050 }; 00051 00052 struct AyStar; 00053 /* 00054 * This function is called to check if the end-tile is found 00055 * return values can be: 00056 * AYSTAR_FOUND_END_NODE : indicates this is the end tile 00057 * AYSTAR_DONE : indicates this is not the end tile (or direction was wrong) 00058 */ 00059 /* 00060 * The 2nd parameter should be OpenListNode, and NOT AyStarNode. AyStarNode is 00061 * part of OpenListNode and so it could be accessed without any problems. 00062 * The good part about OpenListNode is, and how AIs use it, that you can 00063 * access the parent of the current node, and so check if you, for example 00064 * don't try to enter the file tile with a 90-degree curve. So please, leave 00065 * this an OpenListNode, it works just fine -- TrueLight 00066 */ 00067 typedef int32 AyStar_EndNodeCheck(AyStar *aystar, OpenListNode *current); 00068 00069 /* 00070 * This function is called to calculate the G-value for AyStar Algorithm. 00071 * return values can be: 00072 * AYSTAR_INVALID_NODE : indicates an item is not valid (e.g.: unwalkable) 00073 * Any value >= 0 : the g-value for this tile 00074 */ 00075 typedef int32 AyStar_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent); 00076 00077 /* 00078 * This function is called to calculate the H-value for AyStar Algorithm. 00079 * Mostly, this must result the distance (Manhattan way) between the 00080 * current point and the end point 00081 * return values can be: 00082 * Any value >= 0 : the h-value for this tile 00083 */ 00084 typedef int32 AyStar_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent); 00085 00086 /* 00087 * This function request the tiles around the current tile and put them in tiles_around 00088 * tiles_around is never resetted, so if you are not using directions, just leave it alone. 00089 * Warning: never add more tiles_around than memory allocated for it. 00090 */ 00091 typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current); 00092 00093 /* 00094 * If the End Node is found, this function is called. 00095 * It can do, for example, calculate the route and put that in an array 00096 */ 00097 typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current); 00098 00099 // For internal use, see aystar.c 00100 typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g); 00101 typedef int AyStar_Main(AyStar *aystar); 00102 typedef int AyStar_Loop(AyStar *aystar); 00103 typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent); 00104 typedef void AyStar_Free(AyStar *aystar); 00105 typedef void AyStar_Clear(AyStar *aystar); 00106 00107 struct AyStar { 00108 /* These fields should be filled before initting the AyStar, but not changed 00109 * afterwards (except for user_data and user_path)! (free and init again to change them) */ 00110 00111 /* These should point to the application specific routines that do the 00112 * actual work */ 00113 AyStar_CalculateG *CalculateG; 00114 AyStar_CalculateH *CalculateH; 00115 AyStar_GetNeighbours *GetNeighbours; 00116 AyStar_EndNodeCheck *EndNodeCheck; 00117 AyStar_FoundEndNode *FoundEndNode; 00118 00119 /* These are completely untouched by AyStar, they can be accesed by 00120 * the application specific routines to input and output data. 00121 * user_path should typically contain data about the resulting path 00122 * afterwards, user_target should typically contain information about 00123 * what where looking for, and user_data can contain just about 00124 * everything */ 00125 void *user_path; 00126 void *user_target; 00127 uint user_data[10]; 00128 00129 /* How many loops are there called before AyStarMain_Main gives 00130 * control back to the caller. 0 = until done */ 00131 byte loops_per_tick; 00132 /* If the g-value goes over this number, it stops searching 00133 * 0 = infinite */ 00134 uint max_path_cost; 00135 /* The maximum amount of nodes that will be expanded, 0 = infinite */ 00136 uint max_search_nodes; 00137 00138 /* These should be filled with the neighbours of a tile by 00139 * GetNeighbours */ 00140 AyStarNode neighbours[12]; 00141 byte num_neighbours; 00142 00143 /* These will contain the methods for manipulating the AyStar. Only 00144 * main() should be called externally */ 00145 AyStar_AddStartNode *addstart; 00146 AyStar_Main *main; 00147 AyStar_Loop *loop; 00148 AyStar_Free *free; 00149 AyStar_Clear *clear; 00150 AyStar_CheckTile *checktile; 00151 00152 /* These will contain the open and closed lists */ 00153 00154 /* The actual closed list */ 00155 Hash ClosedListHash; 00156 /* The open queue */ 00157 Queue OpenListQueue; 00158 /* An extra hash to speed up the process of looking up an element in 00159 * the open list */ 00160 Hash OpenListHash; 00161 }; 00162 00163 00164 void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g); 00165 int AyStarMain_Main(AyStar *aystar); 00166 int AyStarMain_Loop(AyStar *aystar); 00167 int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent); 00168 void AyStarMain_Free(AyStar *aystar); 00169 void AyStarMain_Clear(AyStar *aystar); 00170 00171 /* Initialize an AyStar. You should fill all appropriate fields before 00172 * callling init_AyStar (see the declaration of AyStar for which fields are 00173 * internal */ 00174 void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets); 00175 00176 00177 #endif /* AYSTAR_H */