src/hcode/btech/autopilot.h

Go to the documentation of this file.
00001 
00002 /*
00003  * $Id: autopilot.h,v 1.4 2005/08/03 21:40:54 av1-op Exp $
00004  *
00005  * Author: Markus Stenberg <fingon@iki.fi>
00006  *
00007  *  Copyright (c) 1996 Markus Stenberg
00008  *  Copyright (c) 1998-2002 Thomas Wouters
00009  *  Copyright (c) 2000-2002 Cord Awtry
00010  *       All rights reserved
00011  *
00012  * Created: Wed Oct 30 20:43:42 1996 fingon
00013  * Last modified: Sat Jun  6 19:56:42 1998 fingon
00014  *
00015  */
00016 
00017 #ifndef AUTOPILOT_H
00018 #define AUTOPILOT_H
00019 
00020 #include "mech.events.h"
00021 #include "dllist.h"
00022 
00023 #define AUTOPILOT_MEMORY        100     /* Number of command slots available to AI */
00024 #define AUTOPILOT_MAX_ARGS      5       /* Max number of arguments for a given AI Command
00025                                            Includes the command as the first argument */
00026 
00027 /* The various flags for the AI */
00028 #define AUTOPILOT_AUTOGUN           1       /* Is autogun enabled, ie: shoot what AI wants to */
00029 #define AUTOPILOT_GUNZOMBIE         2
00030 #define AUTOPILOT_PILZOMBIE         4
00031 #define AUTOPILOT_ROAM              8       /* Are we roaming around */
00032 #define AUTOPILOT_LSENS             16      /* Should change sensors or user set them */
00033 #define AUTOPILOT_CHASETARG         32      /* Should chase the target */
00034 #define AUTOPILOT_WAS_CHASE_ON      64      /* Was chasetarg on, for use with movement stuff */
00035 #define AUTOPILOT_SWARMCHARGE       128 
00036 #define AUTOPILOT_ASSIGNED_TARGET   256     /* We given a specific target ? */
00037 
00038 /* Various delays for the autopilot */
00039 #define AUTOPILOT_NC_DELAY              1       /* Generic command wait time before executing */
00040 
00041 #define AUTOPILOT_GOTO_TICK             3       /* How often to check any GOTO event */
00042 #define AUTOPILOT_LEAVE_TICK            5       /* How often to check if we've left 
00043                                                    the bay/hangar */
00044 #define AUTOPILOT_WAITFOE_TICK          4
00045 #define AUTOPILOT_PURSUE_TICK           3
00046 
00047 #define AUTOPILOT_FOLLOW_TICK           3
00048 #define AUTOPILOT_FOLLOW_UPDATE_TICK    10  /* When should we update the target hex */
00049 
00050 #define AUTOPILOT_CHASETARG_UPDATE_TICK 30  /* When should we update chasetarg */
00051 
00052 #define AUTOPILOT_STARTUP_TICK  STARTUP_TIME + AUTOPILOT_NC_DELAY   /* Delay for startup */
00053 
00054 /* Defines for the autogun/autosensor stuff */
00055 #define AUTO_GUN_TICK                   1       /* Every second */
00056 #define AUTO_GUN_MAX_HEAT               6.0     /* Last heat we let heat go to */
00057 #define AUTO_GUN_MAX_TARGETS            100     /* Don't really use this one */
00058 #define AUTO_GUN_MAX_RANGE              30      /* Max range to look for targets */
00059 #define AUTO_GUN_UPDATE_TICK            30      /* When to look for a new target */
00060 #define AUTO_GUN_IDLE_TICK              10      /* How often to call autogun when in idle mode */
00061 #define AUTO_GUN_PHYSICAL_RANGE_MIN     3.0     /* Min range at which to physically attack 
00062                                                    other targets if our main target is beyond
00063                                                    this distance */
00064 #define AUTO_PROFILE_TICK               180     /* How often to update the weapon profile 
00065                                                    of the AI */
00066 #define AUTO_PROFILE_MAX_SIZE           30      /* Size of the profile array */
00067 #define AUTO_SENSOR_TICK                30      /* Every 30 seconds or so */
00068 
00069 #define Gunning(a)              ((a)->flags & AUTOPILOT_AUTOGUN)
00070 #define StartGun(a)             (a)->flags |= AUTOPILOT_AUTOGUN
00071 #define StopGun(a)              (a)->flags &= ~(AUTOPILOT_AUTOGUN|AUTOPILOT_GUNZOMBIE)
00072 
00073 /* Do we have an assigned target */
00074 #define AssignedTarget(a)       ((a)->flags & AUTOPILOT_ASSIGNED_TARGET)
00075 #define AssignTarget(a)         (a)->flags |= AUTOPILOT_ASSIGNED_TARGET
00076 #define UnassignTarget(a)       (a)->flags &= ~(AUTOPILOT_ASSIGNED_TARGET)
00077 
00078 /* Chase Target stuff for use with auto_set_chasetarget_mode */
00079 #define AUTO_CHASETARGET_ON             1       /* Turns it on and resets the values */
00080 #define AUTO_CHASETARGET_OFF            2       /* Turns it off */
00081 #define AUTO_CHASETARGET_REMEMBER       3       /* Turns it on only if the AI remembers it 
00082                                                    being on */
00083 #define AUTO_CHASETARGET_SAVE           4       /* Turns it off and saves that it was on */
00084 
00085 /* Is chasetarget mode on */
00086 #define ChasingTarget(a)        ((a)->flags & AUTOPILOT_CHASETARG)
00087 #define StartChasingTarget(a)   (a)->flags |= AUTOPILOT_CHASETARG
00088 #define StopChasingTarget(a)    (a)->flags &= ~(AUTOPILOT_CHASETARG)
00089 
00090 /* Was chasetarget mode on ? */
00091 #define WasChasingTarget(a)         ((a)->flags & AUTOPILOT_WAS_CHASE_ON)
00092 #define RememberChasingTarget(a)    (a)->flags |= AUTOPILOT_WAS_CHASE_ON
00093 #define ForgetChasingTarget(a)      (a)->flags &= ~(AUTOPILOT_WAS_CHASE_ON) 
00094 
00095 /* Roam Stuff */
00096 /* Types of ROAMing */
00097 #define AUTO_ROAM_MAP                   1       /* Roaming the whole map */
00098 #define AUTO_ROAM_SPOT                  2       /* Roaming a single area */
00099 
00100 /* Tick values etc.. */
00101 #define AUTO_ROAM_TICK                  3       /* How often to update */
00102 #define AUTO_ROAM_NEW_HEX_TICK          100     /* How often to pick a new hex */
00103 #define AUTO_ROAM_MAX_RADIUS            30      /* Max distance a person can make AI
00104                                                    radius roam */
00105 #define AUTO_ROAM_MAX_MAP_DISTANCE      50      /* Max distance an AI will try to roam
00106                                                    at a given time if its roaming the
00107                                                    whole map */
00108 #define AUTO_ROAM_MAX_ITERATIONS        3       /* Max number of times AI will look
00109                                                    for a new roam hex */
00110 
00112 #define AUTO_GOET               15
00113 #define AUTO_GOTT               240
00114 
00115 #define DoStartGun(a) \
00116     do { \
00117         StartGun(a); \
00118         a->flags &= ~AUTOPILOT_GUNZOMBIE; \
00119     } while (0)
00120 
00121 #define DoStopGun(a)       StopGun(a) 
00122 
00123 #define Zombify(a) \
00124     do { a->flags |= AUTOPILOT_GUNZOMBIE; StopGun(a); } while (0)
00125 
00126 #define PilZombify(a) \
00127     do { a->flags |= AUTOPILOT_PILZOMBIE; } while (0)
00128 
00129 #define UnZombify(a) \
00130     do { if (a->flags & AUTOPILOT_GUNZOMBIE) { StartGun(a);\
00131         a->flags &= ~AUTOPILOT_GUNZOMBIE; } } while (0)
00132 
00133 #define UnZombifyAuto(a) \
00134     do { if (Gunning(a)) UnZombify(a); if (a->flags & AUTOPILOT_PILZOMBIE) { \
00135         a->flags &= ~AUTOPILOT_PILZOMBIE ;\
00136         AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event, 1, 0); } } while (0)
00137 
00138 #define UnZombifyMech(mech) \
00139     do { AUTO *au; if (MechAuto(mech) > 0 && \
00140         (au=FindObjectsData(MechAuto(mech)))) UnZombifyAuto(au); } while (0)
00141 
00144 #define GVAL(a,b) \
00145     (((a->program_counter + (b)) < a->first_free) ? \
00146     a->commands[(a->program_counter+(b))] : -1)
00147 
00148 #define CCLEN(a) \
00149        (1 + acom[a->commands[a->program_counter]].argcount)
00150 
00151 #define PG(a) \
00152        a->program_counter
00153 
00154 /* Command Macros */
00155 
00156 /* Basic checks for the autopilot */
00157 #define AUTO_CHECKS(a) \
00158     if (Location(a->mynum) != a->mymechnum) return; \
00159     if (Destroyed(mech)) return;
00160 
00161 /* Shortcut to the auto_com_event function */
00162 #define AUTO_COM(a,n) \
00163         AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event, (n), 0);
00164 
00166 #define ADVANCE_PG(a) \
00167         PG(a) += CCLEN(a); REDO(a,AUTOPILOT_NC_DELAY)
00168 
00169 /* Force the unit to start up */
00170 #define AUTO_PSTART(a,mech) \
00171         if (!Started(mech)) { auto_command_startup(a, mech); return; }
00172 
00173 /* Force the unit to startup as well as try to stand */
00174 #define AUTO_GSTART(a,mech) \
00175     AUTO_PSTART(a,mech); \
00176     if (MechType(mech) == CLASS_MECH && Fallen(mech) && \
00177             !(CountDestroyedLegs(mech) > 0)) { \
00178         if (!Standing(mech)) mech_stand(a->mynum, mech, ""); \
00179         AUTO_COM(a, AUTOPILOT_NC_DELAY); return; \
00180     }; \
00181     if (MechType(mech) == CLASS_VTOL && Landed(mech) && \
00182             !SectIsDestroyed(mech, ROTOR)) { \
00183         if (!TakingOff(mech)) aero_takeoff(a->mynum, mech, ""); \
00184         AUTO_COM(a, AUTOPILOT_NC_DELAY); return; \
00185     }
00186 
00187 /* Macros for quick access to bitfield code */
00188 #define HexOffSet(x, y) (x * MAPY + y)
00189 #define HexOffSetNode(node) (HexOffSet(node->x, node->y))
00190 
00191 #define WhichByte(hex_offset) ((hex_offset) >> 3)
00192 #define WhichBit(hex_offset) ((hex_offset) & 7)
00193 
00194 #define CheckHexBit(array, offset) (array[WhichByte(offset)] & (1 << WhichBit(offset)) ? 1 : 0)
00195 #define SetHexBit(array, offset) do { array[offset >> 3] = \
00196         array[offset >> 3] | (1 << (offset & 7)); } while (0)
00197 #define ClearHexBit(array, offset) do { array[offset >> 3] = \
00198         array[offset >> 3] & ~(1 << (offset & 7)); } while (0)
00199 
00200 #ifdef DEBUG_AUTOGUN
00201     #define print_autogun_log(autopilot, args...) \
00202     do { \
00203         fprintf(stderr, "AI: %d AUTOGUN ", autopilot->mynum); \
00204         fprintf(stderr, args); \
00205         fprintf(stderr, "\n"); \
00206     } while(0)
00207 #else
00208     #define print_autogun_log(autopilot, args...)
00209 #endif
00210 
00211 /*
00212  * Profile node structure
00213  */
00214 typedef struct profile_node_t {
00215     int damage;
00216     int heat;
00217     rbtree weaplist;
00218 } profile_node;
00219 
00220 /*
00221  * The Autopilot Structure
00222  */
00223 typedef struct {
00224     dbref mynum;                    /* The AI's dbref number */
00225     MECH *mymech;                   /* The AI's unit */
00226     int mapindex;                   /* The map the AI is currently on */
00227     dbref mymechnum;                /* the dbref of the AI's mech */
00228     unsigned short speed;           /* % of speed (1-100) that the AI should drive at */
00229     int ofsx, ofsy;                 /* ? */
00230 
00231     unsigned char verbose_level;    /* How talkative should the AI be */
00232 
00233     dbref target;                   /* The AI's current target */
00234     int target_score;               /* Current score of the AI's target */
00235     int target_threshold;           /* Threshold at which to change to another target */
00236     int target_update_tick;         /* What autogun tick we currently at and should we update */
00237 
00238     dbref chase_target;             /* Current target we are chasing */
00239     int chasetarg_update_tick;      /* When should we update chasetarg */
00240 
00241     int follow_update_tick;         /* When should we update follow */
00242 
00243     /* Special AI flags */
00244     unsigned short flags;
00245 
00246     /* The autopilot's command list */
00247     dllist *commands;
00248 
00249     /* AI A* pathfinding stuff */
00250     dllist *astar_path;
00251 
00252     /* The AI's Weaplist for use with autogun */
00253     dllist *weaplist;
00254 
00255     /* Range Profile Array - for use with autogun */
00256     rbtree profile[AUTO_PROFILE_MAX_SIZE];
00257 
00258     /* Max Range of AI's mech's weapons */
00259     int mech_max_range;
00260 
00261     /* Roam Stuff */
00262     unsigned char roam_type;            /* What type of ROAM are we doing */
00263     int roam_update_tick;               /* When should we update roam info */
00264     short roam_target_hex_x;            /* Target Hex - X Coord */
00265     short roam_target_hex_y;            /* Target Hex - Y Coord */
00266     short roam_anchor_hex_x;            /* Anchor Hex - X Coord */
00267     short roam_anchor_hex_y;            /* Anchor Hex - Y Coord */
00268     short roam_anchor_distance;         /* Distance (in hexes) allowed from anchor hex */
00269 
00271     /* Temporary AI-pathfind data variables */
00272     int ahead_ok;
00273     int auto_cmode;     /* 0 = Flee ; 1 = Close ; 2 = Maintain distances if possible */
00274     int auto_cdist;     /* Distance we're trying to maintain */
00275     int auto_goweight;
00276     int auto_fweight;
00277     int auto_nervous;
00278 
00279     int b_msc, w_msc, b_bsc, w_bsc, b_dan, w_dan, last_upd;
00280 
00281 } AUTO;
00282 
00283 /* command_node struct to store AI 
00284  * commands for the AI command list */
00285 typedef struct command_node_t {
00286     char *args[AUTOPILOT_MAX_ARGS];         /* Store arguements - At most will ever have 5 */
00287     unsigned char argcount;                 /* Number of arguments */
00288     int command_enum;                       /* The ENUM value for the command */
00289     int (*ai_command_function)(AUTO *);     /* Function Pointer */
00290 } command_node;
00291 
00292 /* A structure to store info about the various AI commands */
00293 typedef struct {
00294     char *name;
00295     int argcount;
00296     int command_enum;
00297     int (*ai_command_function)(AUTO *);
00298 } ACOM;
00299 
00300 /* astar node Structure for the A star pathfinding */
00301 typedef struct astar_node_t {
00302     short x;
00303     short y;
00304     short x_parent;
00305     short y_parent;
00306     int g_score;
00307     int h_score;
00308     int f_score;
00309     int hexoffset;
00310 } astar_node;
00311 
00312 /* Weaplist node for storing info about weapons on the mech */
00313 typedef struct weapon_node_t {
00314     short weapon_number;
00315     short weapon_db_number;
00316     short section;
00317     short critical;
00318     int range_scores[AUTO_PROFILE_MAX_SIZE];
00319 } weapon_node;
00320 
00321 /* Target node for storing target data */
00322 typedef struct target_node_t {
00323     int target_score;
00324     dbref target_dbref;
00325 } target_node;
00326 
00327 /* Quick flags for use with the various autopilot
00328  * commands.  Check the ACOM array in autopilot_commands.c */
00329 enum {
00330     GOAL_CHASETARGET,   /* An extension of follow for chasetarget */
00331     GOAL_DUMBFOLLOW,
00332     GOAL_DUMBGOTO,
00333     GOAL_ENTERBASE,     /* Revamp of enterbase so it keeps trying */
00334     GOAL_FOLLOW,        /* Uses the new Astar system */
00335     GOAL_GOTO,          /* Uses the new Astar system */ 
00336     GOAL_LEAVEBASE,
00337     GOAL_OLDGOTO,       /* Old implementation of goto */
00338     GOAL_ROAM,          /* New version using Astar */
00339     GOAL_WAIT,          /* unimplemented */
00340 
00341     COMMAND_ATTACKLEG,  /* unimplemented */
00342     COMMAND_AUTOGUN,    /* New version that has 3 options 'on', 'off' and 'target dbref' */
00343     COMMAND_CHASEMODE,  /* unimplemented */
00344     COMMAND_CMODE,      /* unimplemented */
00345     COMMAND_DROPOFF, 
00346     COMMAND_EMBARK,
00347     COMMAND_ENTERBAY,   /* unimplemented */
00348     COMMAND_JUMP,       /* unimplemented */
00349     COMMAND_LOAD,       /* unimplemented */
00350     COMMAND_PICKUP,
00351     COMMAND_REPORT,     /* unimplemented */
00352     COMMAND_ROAMMODE,   /* unimplemented */
00353     COMMAND_SHUTDOWN,
00354     COMMAND_SPEED,
00355     COMMAND_STARTUP,
00356     COMMAND_STOPGUN,    /* unimplemented */
00357     COMMAND_SWARM,      /* unimplemented */
00358     COMMAND_SWARMMODE,  /* unimplemented */
00359     COMMAND_UDISEMBARK,
00360     COMMAND_UNLOAD,     /* unimplemented */
00361     AUTO_NUM_COMMANDS
00362 };
00363 
00364 /* Function Prototypes will go here */
00365 
00366 /* From autopilot_core.c */
00367 void auto_destroy_command_node(command_node *node);
00368 void auto_save_commands(FILE *file, AUTO *autopilot);
00369 void auto_load_commands(FILE *file, AUTO *autopilot);
00370 void auto_delcommand(dbref player, void *data, char *buffer);
00371 void auto_addcommand(dbref player, void *data, char *buffer);
00372 void auto_listcommands(dbref player, void *data, char *buffer);
00373 void auto_eventstats(dbref player, void *data, char *buffer);
00374 void auto_set_comtitle(AUTO *autopilot, MECH * mech);
00375 void auto_init(AUTO *autopilot, MECH *mech);
00376 void auto_engage(dbref player, void *data, char *buffer);
00377 void auto_disengage(dbref player, void *data, char *buffer);
00378 void auto_goto_next_command(AUTO *autopilot, int time);
00379 char *auto_get_command_arg(AUTO *autopilot, int command_number, int arg_number);
00380 int auto_get_command_enum(AUTO *autopilot, int command_number);
00381 void auto_newautopilot(dbref key, void **data, int selector);
00382 
00383 /* From autopilot_commands.c */
00384 void auto_cal_mapindex(MECH *mech);
00385 void auto_set_chasetarget_mode(AUTO *autopilot, int mode);
00386 void auto_command_startup(AUTO *autopilot, MECH *mech);
00387 void auto_command_shutdown(AUTO *autopilot, MECH *mech);
00388 void auto_command_pickup(AUTO *autopilot, MECH *mech);
00389 void auto_command_dropoff(MECH *mech);
00390 void auto_command_speed(AUTO *autopilot);
00391 void auto_com_event(MUXEVENT *muxevent);
00392 void auto_astar_goto_event(MUXEVENT *muxevent);
00393 void auto_astar_follow_event(MUXEVENT *muxevent);
00394 void auto_dumbgoto_event(MUXEVENT *muxevent);
00395 void auto_dumbfollow_event(MUXEVENT *muxevent);
00396 void auto_leave_event(MUXEVENT *muxevent);
00397 void auto_enter_event(MUXEVENT *muxevent);
00398 void auto_command_roam(AUTO *autopilot, MECH *mech);
00399 void auto_astar_roam_event(MUXEVENT *muxevent);
00400 
00401 /* From autopilot_ai.c */
00402 int auto_astar_generate_path(AUTO *autopilot, MECH *mech, short end_x, short end_y);
00403 void auto_destroy_astar_path(AUTO *autopilot);
00404 
00405 /* From autopilot_autogun.c */
00406 int SearchLightInRange(MECH *mech, MAP *map);
00407 int PrefVisSens(MECH *mech, MAP *map, int slite, MECH *target);
00408 void auto_sensor_event(AUTO * muxevent);
00409 void auto_gun_event(AUTO * AUTOPILOT);
00410 void auto_destroy_weaplist(AUTO *autopilot);
00411 void auto_update_profile_event(AUTO * autopilot);
00412 
00413 /* From autopilot_radio.c */
00414 void auto_reply_event(MUXEVENT *muxevent);
00415 void auto_reply(MECH *mech, char *buf);
00416 void auto_parse_command(AUTO *autopilot, MECH *mech, int chn, char *buffer);
00417 
00418 void auto_radio_command_autogun(AUTO *autopilot, MECH *mech,
00419         char **args, int argc, char *mesg);
00420 void auto_radio_command_chasetarg(AUTO *autopilot, MECH *mech, 
00421         char **args, int argc, char *mesg);
00422 void auto_radio_command_dfollow(AUTO *autopilot, MECH *mech, 
00423         char **args, int argc, char *mesg);
00424 void auto_radio_command_dgoto(AUTO *autopilot, MECH *mech, 
00425         char **args, int argc, char *mesg);
00426 void auto_radio_command_dropoff(AUTO *autopilot, MECH *mech, 
00427         char **args, int argc, char *mesg);
00428 void auto_radio_command_embark(AUTO *autopilot, MECH *mech,
00429         char **args, int argc, char *mesg);
00430 void auto_radio_command_enterbase(AUTO *autopilot, MECH *mech,
00431         char **args, int argc, char *mesg);
00432 void auto_radio_command_follow(AUTO *autopilot, MECH *mech,
00433         char **args, int argc, char *mesg);
00434 void auto_radio_command_goto(AUTO *autopilot, MECH *mech, 
00435         char **args, int argc, char *mesg);
00436 void auto_radio_command_heading(AUTO *autopilot, MECH *mech, 
00437         char **args, int argc, char *mesg);
00438 void auto_radio_command_help(AUTO *autopilot, MECH *mech, 
00439         char **args, int argc, char *mesg);
00440 void auto_radio_command_hide(AUTO *autopilot, MECH *mech,
00441         char **args, int argc, char *mesg);
00442 void auto_radio_command_jumpjet(AUTO *autopilot, MECH *mech,
00443         char **args, int argc, char *mesg);
00444 void auto_radio_command_leavebase(AUTO *autopilot, MECH *mech,
00445         char **args, int argc, char *mesg);
00446 void auto_radio_command_ogoto(AUTO *autopilot, MECH *mech, 
00447         char **args, int argc, char *mesg);
00448 void auto_radio_command_pickup(AUTO *autopilot, MECH *mech, 
00449         char **args, int argc, char *mesg);
00450 void auto_radio_command_position(AUTO *autopilot, MECH *mech,
00451         char **args, int argc, char *mesg);
00452 void auto_radio_command_prone(AUTO *autopilot, MECH *mech,
00453         char **args, int argc, char *mesg);
00454 void auto_radio_command_report(AUTO *autopilot, MECH *mech, 
00455         char **args, int argc, char *mesg);
00456 void auto_radio_command_reset(AUTO *autopilot, MECH *mech,
00457         char **args, int argc, char *mesg);
00458 void auto_radio_command_sensor(AUTO *autopilot, MECH *mech,
00459         char **args, int argc, char *mesg);
00460 void auto_radio_command_shutdown(AUTO *autopilot, MECH *mech, 
00461         char **args, int argc, char *mesg);
00462 void auto_radio_command_speed(AUTO *autopilot, MECH *mech,
00463         char **args, int argc, char *mesg);
00464 void auto_radio_command_stand(AUTO *autopilot, MECH *mech,
00465         char **args, int argc, char *mesg);
00466 void auto_radio_command_startup(AUTO *autopilot, MECH *mech, 
00467         char **args, int argc, char *mesg);
00468 void auto_radio_command_stop(AUTO *autopilot, MECH *mech, 
00469         char **args, int argc, char *mesg);
00470 void auto_radio_command_sweight(AUTO *autopilot, MECH *mech,
00471         char **args, int argc, char *mesg);
00472 void auto_radio_command_target(AUTO *autopilot, MECH *mech,
00473         char **args, int argc, char *mesg);
00474 
00475 #include "p.autopilot.h"
00476 #include "p.ai.h"
00477 #include "p.autopilot_command.h"
00478 #include "p.autopilot_commands.h"
00479 #include "p.autogun.h"
00480 
00481 #endif                  /* AUTOPILOT_H */

Generated on Mon May 28 04:25:20 2007 for BattletechMUX by  doxygen 1.4.7