/*
* $Id: autopilot.h,v 1.4 2005/08/03 21:40:54 av1-op Exp $
*
* Author: Markus Stenberg <fingon@iki.fi>
*
* Copyright (c) 1996 Markus Stenberg
* Copyright (c) 1998-2002 Thomas Wouters
* Copyright (c) 2000-2002 Cord Awtry
* All rights reserved
*
* Created: Wed Oct 30 20:43:42 1996 fingon
* Last modified: Sat Jun 6 19:56:42 1998 fingon
*
*/
#ifndef AUTOPILOT_H
#define AUTOPILOT_H
#include "mech.events.h"
#include "dllist.h"
#define AUTOPILOT_MEMORY 100 /* Number of command slots available to AI */
#define AUTOPILOT_MAX_ARGS 5 /* Max number of arguments for a given AI Command
Includes the command as the first argument */
/* The various flags for the AI */
#define AUTOPILOT_AUTOGUN 1 /* Is autogun enabled, ie: shoot what AI wants to */
#define AUTOPILOT_GUNZOMBIE 2
#define AUTOPILOT_PILZOMBIE 4
#define AUTOPILOT_ROAMMODE 8 /* Are we roaming around */
#define AUTOPILOT_LSENS 16 /* Should change sensors or user set them */
#define AUTOPILOT_CHASETARG 32 /* Should chase the target */
#define AUTOPILOT_WAS_CHASE_ON 64 /* Was chasetarg on, for use with movement stuff */
#define AUTOPILOT_SWARMCHARGE 128
#define AUTOPILOT_ASSIGNED_TARGET 256 /* We given a specific target ? */
/* Various delays for the autopilot */
#define AUTOPILOT_NC_DELAY 1 /* Generic command wait time before executing */
#define AUTOPILOT_GOTO_TICK 3 /* How often to check any GOTO event */
#define AUTOPILOT_LEAVE_TICK 5 /* How often to check if we've left
the bay/hangar */
#define AUTOPILOT_WAITFOE_TICK 4
#define AUTOPILOT_PURSUE_TICK 3
#define AUTOPILOT_FOLLOW_TICK 3
#define AUTOPILOT_FOLLOW_UPDATE_TICK 30 /* When should we update the target hex */
#define AUTOPILOT_CHASETARG_UPDATE_TICK 30 /* When should we update chasetarg */
#define AUTOPILOT_STARTUP_TICK STARTUP_TIME + AUTOPILOT_NC_DELAY /* Delay for startup */
/* Defines for the autogun/autosensor stuff */
#define AUTO_GUN_TICK 1 /* Every second */
#define AUTO_GUN_MAX_HEAT 6.0 /* Last heat we let heat go to */
#define AUTO_GUN_MAX_TARGETS 100 /* Don't really use this one */
#define AUTO_GUN_MAX_RANGE 30 /* Max range to look for targets */
#define AUTO_GUN_UPDATE_TICK 30 /* When to look for a new target */
#define AUTO_GUN_PHYSICAL_RANGE_MIN 3.0 /* Min range at which to physically attack
other targets if our main target is beyond
this distance */
#define AUTO_PROFILE_TICK 180 /* How often to update the weapon profile
of the AI */
#define AUTO_PROFILE_MAX_SIZE 30 /* Size of the profile array */
#define AUTO_SENSOR_TICK 30 /* Every 30 seconds or so */
/* Chase Target stuff for use with auto_set_chasetarget_mode */
#define AUTO_CHASETARGET_ON 1 /* Turns it on and resets the values */
#define AUTO_CHASETARGET_OFF 2 /* Turns it off */
#define AUTO_CHASETARGET_REMEMBER 3 /* Turns it on only if the AI remembers it
being on */
#define AUTO_CHASETARGET_SAVE 4 /* Turns it off and saves that it was on */
/*! \todo {Not sure what these are look into it} */
#define AUTO_GOET 15
#define AUTO_GOTT 240
#define Gunning(a) ((a)->flags & AUTOPILOT_AUTOGUN)
#define StartGun(a) (a)->flags |= AUTOPILOT_AUTOGUN
#define StopGun(a) (a)->flags &= ~(AUTOPILOT_AUTOGUN|AUTOPILOT_GUNZOMBIE)
/* Do we have an assigned target */
#define AssignedTarget(a) ((a)->flags & AUTOPILOT_ASSIGNED_TARGET)
#define AssignTarget(a) (a)->flags |= AUTOPILOT_ASSIGNED_TARGET
#define UnassignTarget(a) (a)->flags &= ~(AUTOPILOT_ASSIGNED_TARGET)
/* Is chasetarget mode on */
#define ChasingTarget(a) ((a)->flags & AUTOPILOT_CHASETARG)
#define StartChasingTarget(a) (a)->flags |= AUTOPILOT_CHASETARG
#define StopChasingTarget(a) (a)->flags &= ~(AUTOPILOT_CHASETARG)
/* Was chasetarget mode on ? */
#define WasChasingTarget(a) ((a)->flags & AUTOPILOT_WAS_CHASE_ON)
#define RememberChasingTarget(a) (a)->flags |= AUTOPILOT_WAS_CHASE_ON
#define ForgetChasingTarget(a) (a)->flags &= ~(AUTOPILOT_WAS_CHASE_ON)
#define UpdateAutoSensor(a, flag) \
AUTOEVENT(a, EVENT_AUTO_SENSOR, auto_sensor_event, 1, flag)
#define TrulyStartGun(a) \
do { \
AUTOEVENT(a, EVENT_AUTO_PROFILE, auto_update_profile_event, 1, 0); \
AUTOEVENT(a, EVENT_AUTOGUN, auto_gun_event, 1, 0); \
AUTOEVENT(a, EVENT_AUTO_SENSOR, auto_sensor_event, 1, 0); \
} while (0)
#define DoStartGun(a) \
do { \
StartGun(a); \
TrulyStartGun(a); \
a->flags &= ~AUTOPILOT_GUNZOMBIE; \
} while (0)
#define TrulyStopGun(a) \
do { \
muxevent_remove_type_data(EVENT_AUTO_PROFILE, a); \
muxevent_remove_type_data(EVENT_AUTOGUN, a); \
muxevent_remove_type_data(EVENT_AUTO_SENSOR, a); \
} while (0)
#define DoStopGun(a) \
do { StopGun(a); TrulyStopGun(a); } while (0)
#define Zombify(a) \
do { a->flags |= AUTOPILOT_GUNZOMBIE; TrulyStopGun(a); } while (0)
#define PilZombify(a) \
do { a->flags |= AUTOPILOT_PILZOMBIE; } while (0)
#define UnZombify(a) \
do { if (a->flags & AUTOPILOT_GUNZOMBIE) { TrulyStartGun(a);\
a->flags &= ~AUTOPILOT_GUNZOMBIE; } } while (0)
#define UnZombifyAuto(a) \
do { if (Gunning(a)) UnZombify(a); if (a->flags & AUTOPILOT_PILZOMBIE) { \
a->flags &= ~AUTOPILOT_PILZOMBIE ;\
AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event, 1, 0); } } while (0)
#define UnZombifyMech(mech) \
do { AUTO *au; if (MechAuto(mech) > 0 && \
(au=FindObjectsData(MechAuto(mech)))) UnZombifyAuto(au); } while (0)
/*! \todo {Get rid of these} */
#define GVAL(a,b) \
(((a->program_counter + (b)) < a->first_free) ? \
a->commands[(a->program_counter+(b))] : -1)
#define CCLEN(a) \
(1 + acom[a->commands[a->program_counter]].argcount)
#define PG(a) \
a->program_counter
/* Command Macros */
/* Basic checks for the autopilot */
#define AUTO_CHECKS(a) \
if (Location(a->mynum) != a->mymechnum) return; \
if (Destroyed(mech)) return;
/* Shortcut to the auto_com_event function */
#define AUTO_COM(a,n) \
AUTOEVENT(a, EVENT_AUTOCOM, auto_com_event, (n), 0);
/*! \todo {Get rid of this once we're done} */
#define ADVANCE_PG(a) \
PG(a) += CCLEN(a); REDO(a,AUTOPILOT_NC_DELAY)
/* Force the unit to start up */
#define AUTO_PSTART(a,mech) \
if (!Started(mech)) { auto_command_startup(a, mech); return; }
/* Force the unit to startup as well as try to stand */
#define AUTO_GSTART(a,mech) \
AUTO_PSTART(a,mech); \
if (MechType(mech) == CLASS_MECH && Fallen(mech) && \
!(CountDestroyedLegs(mech) > 0)) { \
if (!Standing(mech)) mech_stand(a->mynum, mech, ""); \
AUTO_COM(a, AUTOPILOT_NC_DELAY); return; \
}; \
if (MechType(mech) == CLASS_VTOL && Landed(mech) && \
!SectIsDestroyed(mech, ROTOR)) { \
if (!TakingOff(mech)) aero_takeoff(a->mynum, mech, ""); \
AUTO_COM(a, AUTOPILOT_NC_DELAY); return; \
}
/* Macros for quick access to bitfield code */
#define HexOffSet(x, y) (x * MAPY + y)
#define HexOffSetNode(node) (HexOffSet(node->x, node->y))
#define WhichByte(hex_offset) ((hex_offset) >> 3)
#define WhichBit(hex_offset) ((hex_offset) & 7)
#define CheckHexBit(array, offset) (array[WhichByte(offset)] & (1 << WhichBit(offset)) ? 1 : 0)
#define SetHexBit(array, offset) (array[offset >> 3] = \
array[offset >> 3] | (1 << (offset & 7)))
#define ClearHexBit(array, offset) (array[offset >> 3] = \
array[offset >> 3] & ~(1 << (offset & 7)))
#ifdef DEBUG_AUTOGUN
#define print_autogun_log(autopilot, args...) \
do { \
fprintf(stderr, "AI: %d AUTOGUN ", autopilot->mynum); \
fprintf(stderr, args); \
fprintf(stderr, "\n"); \
} while(0)
#else
#define print_autogun_log(autopilot, args...)
#endif
/*
* Profile node structure
*/
typedef struct profile_node_t {
int damage;
int heat;
rbtree *weaplist;
} profile_node;
/*
* The Autopilot Structure
*/
typedef struct {
dbref mynum; /* The AI's dbref number */
MECH *mymech; /* The AI's unit */
int mapindex; /* The map the AI is currently on */
dbref mymechnum; /* the dbref of the AI's mech */
unsigned short speed; /* % of speed (1-100) that the AI should drive at */
int ofsx, ofsy; /* ? */
unsigned char verbose_level; /* How talkative should the AI be */
dbref target; /* The AI's current target */
int target_score; /* Current score of the AI's target */
int target_threshold; /* Threshold at which to change to another target */
int target_update_tick; /* What autogun tick we currently at and should we update */
dbref chase_target; /* Current target we are chasing */
int chasetarg_update_tick; /* When should we update chasetarg */
int follow_update_tick; /* When should we update follow */
/* Special AI flags */
unsigned short flags;
/* The autopilot's command list */
dllist *commands;
/* AI A* pathfinding stuff */
dllist *astar_path;
/* The AI's Weaplist for use with autogun */
dllist *weaplist;
/* Range Profile Array - for use with autogun */
rbtree *profile[AUTO_PROFILE_MAX_SIZE];
/* Max Range of AI's mech's weapons */
int mech_max_range;
/*! \todo {Figure out if we need to keep these variables} */
/* Temporary AI-pathfind data variables */
int ahead_ok;
int auto_cmode; /* 0 = Flee ; 1 = Close ; 2 = Maintain distances if possible */
int auto_cdist; /* Distance we're trying to maintain */
int auto_goweight;
int auto_fweight;
int auto_nervous;
int b_msc, w_msc, b_bsc, w_bsc, b_dan, w_dan, last_upd;
} AUTO;
/* command_node struct to store AI
* commands for the AI command list */
typedef struct command_node_t {
char *args[AUTOPILOT_MAX_ARGS]; /* Store arguements - At most will ever have 5 */
unsigned char argcount; /* Number of arguments */
int command_enum; /* The ENUM value for the command */
int (*ai_command_function)(AUTO *); /* Function Pointer */
} command_node;
/* A structure to store info about the various AI commands */
typedef struct {
char *name;
int argcount;
int command_enum;
int (*ai_command_function)(AUTO *);
} ACOM;
/* astar node Structure for the A star pathfinding */
typedef struct astar_node_t {
short x;
short y;
short x_parent;
short y_parent;
int g_score;
int h_score;
int f_score;
int hexoffset;
} astar_node;
/* Weaplist node for storing info about weapons on the mech */
typedef struct weapon_node_t {
short weapon_number;
short weapon_db_number;
short section;
short critical;
int range_scores[AUTO_PROFILE_MAX_SIZE];
} weapon_node;
/* Target node for storing target data */
typedef struct target_node_t {
int target_score;
dbref target_dbref;
} target_node;
/* Quick flags for use with the various autopilot
* commands. Check the ACOM array in autopilot_commands.c */
enum {
GOAL_CHASETARGET, /* An extension of follow for chasetarget */
GOAL_DUMBFOLLOW,
GOAL_DUMBGOTO,
GOAL_ENTERBASE, /* Revamp of enterbase so it keeps trying */
GOAL_FOLLOW, /* Uses the new Astar system */
GOAL_GOTO, /* Uses the new Astar system */
GOAL_LEAVEBASE,
GOAL_OLDGOTO, /* Old implementation of goto */
GOAL_ROAM, /* unimplemented */
GOAL_WAIT, /* unimplemented */
COMMAND_ATTACKLEG, /* unimplemented */
COMMAND_AUTOGUN, /* New version that has 3 options 'on', 'off' and 'target dbref' */
COMMAND_CHASEMODE, /* unimplemented */
COMMAND_CMODE, /* unimplemented */
COMMAND_DROPOFF,
COMMAND_EMBARK,
COMMAND_ENTERBAY, /* unimplemented */
COMMAND_JUMP, /* unimplemented */
COMMAND_LOAD, /* unimplemented */
COMMAND_PICKUP,
COMMAND_REPORT, /* unimplemented */
COMMAND_ROAMMODE, /* unimplemented */
COMMAND_SHUTDOWN,
COMMAND_SPEED,
COMMAND_STARTUP,
COMMAND_STOPGUN, /* unimplemented */
COMMAND_SWARM, /* unimplemented */
COMMAND_SWARMMODE, /* unimplemented */
COMMAND_UDISEMBARK,
COMMAND_UNLOAD, /* unimplemented */
AUTO_NUM_COMMANDS
};
/* Function Prototypes will go here */
/* From autopilot_core.c */
void auto_destroy_command_node(command_node *node);
void auto_save_commands(FILE *file, AUTO *autopilot);
void auto_load_commands(FILE *file, AUTO *autopilot);
void auto_delcommand(dbref player, void *data, char *buffer);
void auto_addcommand(dbref player, void *data, char *buffer);
void auto_listcommands(dbref player, void *data, char *buffer);
void auto_eventstats(dbref player, void *data, char *buffer);
void auto_set_comtitle(AUTO *autopilot, MECH * mech);
void auto_init(AUTO *autopilot, MECH *mech);
void auto_engage(dbref player, void *data, char *buffer);
void auto_disengage(dbref player, void *data, char *buffer);
void auto_goto_next_command(AUTO *autopilot, int time);
char *auto_get_command_arg(AUTO *autopilot, int command_number, int arg_number);
int auto_get_command_enum(AUTO *autopilot, int command_number);
void auto_newautopilot(dbref key, void **data, int selector);
/* From autopilot_commands.c */
void auto_cal_mapindex(MECH *mech);
void auto_set_chasetarget_mode(AUTO *autopilot, int mode);
void auto_command_startup(AUTO *autopilot, MECH *mech);
void auto_command_shutdown(AUTO *autopilot, MECH *mech);
void auto_command_pickup(AUTO *autopilot, MECH *mech);
void auto_command_dropoff(MECH *mech);
void auto_command_speed(AUTO *autopilot);
void auto_com_event(MUXEVENT *muxevent);
void auto_astar_goto_event(MUXEVENT *muxevent);
void auto_astar_follow_event(MUXEVENT *muxevent);
void auto_dumbgoto_event(MUXEVENT *muxevent);
void auto_dumbfollow_event(MUXEVENT *muxevent);
void auto_leave_event(MUXEVENT *muxevent);
void auto_enter_event(MUXEVENT *muxevent);
/* From autopilot_ai.c */
int auto_astar_generate_path(AUTO *autopilot, MECH *mech, short end_x, short end_y);
void auto_destroy_astar_path(AUTO *autopilot);
/* From autopilot_autogun.c */
int SearchLightInRange(MECH *mech, MAP *map);
int PrefVisSens(MECH *mech, MAP *map, int slite, MECH *target);
void auto_sensor_event(MUXEVENT *muxevent);
void auto_gun_event(MUXEVENT *muxevent);
void auto_destroy_weaplist(AUTO *autopilot);
void auto_update_profile_event(MUXEVENT *muxevent);
/* From autopilot_radio.c */
void auto_reply_event(MUXEVENT *muxevent);
void auto_reply(MECH *mech, char *buf);
void auto_parse_command(AUTO *autopilot, MECH *mech, int chn, char *buffer);
void auto_radio_command_autogun(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_chasetarg(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_dfollow(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_dgoto(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_dropoff(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_embark(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_enterbase(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_follow(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_goto(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_heading(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_help(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_hide(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_jumpjet(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_leavebase(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_ogoto(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_pickup(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_position(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_prone(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_report(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_reset(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_sensor(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_shutdown(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_speed(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_stand(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_startup(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_stop(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_sweight(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
void auto_radio_command_target(AUTO *autopilot, MECH *mech,
char **args, int argc, char *mesg);
#include "p.autopilot.h"
#include "p.ai.h"
#include "p.autopilot_command.h"
#include "p.autopilot_commands.h"
#include "p.autogun.h"
#endif /* AUTOPILOT_H */