# aystar.h

Go to the documentation of this file.

    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 */