src/hcode/btech/autopilot_core.c

Go to the documentation of this file.
00001 /*
00002  * Author: Markus Stenberg <fingon@iki.fi>
00003  *
00004  *  Copyright (c) 1996 Markus Stenberg
00005  *  Copyright (c) 1998-2002 Thomas Wouters
00006  *  Copyright (c) 2000-2002 Cord Awtry
00007  *       All rights reserved
00008  *
00009  */
00010 
00011 #include "mech.h"
00012 #include "mech.events.h"
00013 #include "autopilot.h"
00014 #include "coolmenu.h"
00015 #include "mycool.h"
00016 #include "p.mech.utils.h"
00017 
00018 extern ACOM acom[AUTO_NUM_COMMANDS + 1];
00019 extern char *muxevent_names[];
00020 
00021 #define AI_COMMAND_DLLIST_START     51  /* Tag for start of saved command list */
00022 #define AI_COMMAND_DLLIST_END       63  /* Tag for end of saved command list */
00023 
00024 #define outbyte(a) tmpb=(a); fwrite(&tmpb, 1, 1, file);
00025 
00026 #define CHESA(a,b,c,d) if ((tmpb=fwrite(a,b,c,d)) != c) \
00027     { fprintf (stderr, "Error writing dllist\n"); \
00028       fflush(stderr); exit(1); }
00029 
00030 #define CHELO(a,b,c,d) if ((tmpb=fread(a,b,c,d)) != c) \
00031     { fprintf (stderr, "Error loading dllist\n"); \
00032       fflush(stderr); exit(1); }
00033 
00034 /*
00035  * Creates a new command_node for the AI's
00036  * command list
00037  */
00038 static command_node *auto_create_command_node()
00039 {
00040 
00041         command_node *temp;
00042 
00043         temp = malloc(sizeof(command_node));
00044         if(temp == NULL)
00045                 return NULL;
00046 
00047         memset(temp, 0, sizeof(command_node));
00048         temp->ai_command_function = NULL;
00049 
00050         return temp;
00051 
00052 }
00053 
00054 /*
00055  * Destroys a command_node
00056  */
00057 void auto_destroy_command_node(command_node * node)
00058 {
00059 
00060         int i;
00061 
00062         /* Free the args */
00063         for(i = 0; i < AUTOPILOT_MAX_ARGS; i++) {
00064                 if(node->args[i]) {
00065                         free(node->args[i]);
00066                         node->args[i] = NULL;
00067                 }
00068         }
00069 
00070         /* Free the node */
00071         free(node);
00072 
00073         return;
00074 
00075 }
00076 
00077 /*
00078  * Writes a command_node to the file specified by f. Used to
00079  * save AI command list to the hcode.db file
00080  */
00081 static void auto_write_command_node(FILE * file, command_node * node)
00082 {
00083 
00084         unsigned char size;                     /* Number of Arguments to save */
00085         char buf[MBUF_SIZE];            /* Buffer to write the strings */
00086         int i;                                          /* Counter */
00087         unsigned short tmpb;            /* Store the number of bytes written */
00088 
00089         /* Zero the Buffer */
00090         memset(buf, '\0', sizeof(buf));
00091 
00092         /* Write the Number of Arguments we're storing */
00093         size = node->argcount;
00094         CHESA(&size, 1, sizeof(size), file);
00095 
00096         /* Loop through the args and write them */
00097         for(i = 0; i <= size; i++) {
00098                 strncpy(buf, node->args[i], MBUF_SIZE);
00099                 CHESA(&buf, 1, sizeof(buf), file);
00100         }
00101 
00102         return;
00103 
00104 }
00105 
00106 /*
00107  * Reads the data for a command_node from a file. Used
00108  * to load the AI command list from hcode.db
00109  */
00110 static command_node *auto_read_command_node(FILE * file)
00111 {
00112 
00113         unsigned char size;                     /* Number of Arguments to read */
00114         char buf[MBUF_SIZE];            /* Buffer to store the strings */
00115         int i;                                          /* Counter */
00116         unsigned short tmpb;            /* Store the number of bytes read */
00117 
00118         command_node *temp_command_node;
00119 
00120         /* Allocate a command node */
00121         temp_command_node = auto_create_command_node();
00122 
00123         /* Zero the Buffer */
00124         memset(buf, '\0', sizeof(buf));
00125 
00126         /* Read the Number of Arguments we're storing */
00127         CHELO(&size, 1, sizeof(size), file);
00128         temp_command_node->argcount = size;
00129 
00130         /* Loop through the arguments and store them */
00131         for(i = 0; i <= size; i++) {
00132 
00133                 CHELO(&buf, 1, sizeof(buf), file);
00134                 temp_command_node->args[i] = strndup(buf, MBUF_SIZE);
00135 
00136         }
00137 
00138         /* Make sure there is a command */
00139         if(!temp_command_node->args[0]) {
00140                 fprintf(stderr, "Error loading command node from file - "
00141                                 "no command found\n");
00142                 exit(1);
00143         }
00144 
00145         /* Get the command_enum and the command_function */
00146         for(i = 0; acom[i].name; i++) {
00147                 if((!strncmp(temp_command_node->args[0], acom[i].name,
00148                                          strlen(temp_command_node->args[0]))) &&
00149                    (!strncmp(acom[i].name, temp_command_node->args[0],
00150                                          strlen(acom[i].name))))
00151                         break;
00152         }
00153 
00154         if(!acom[i].name) {
00155                 fprintf(stderr, "Error loading command node from file - "
00156                                 "Invalid Command\n");
00157                 exit(1);
00158         }
00159 
00160         temp_command_node->command_enum = acom[i].command_enum;
00161         temp_command_node->ai_command_function = acom[i].ai_command_function;
00162 
00163         return temp_command_node;
00164 
00165 }
00166 
00167 /* 
00168  * Saves the current command list from the AI to
00169  * a file.  Called by SaveSpecialObjects from
00170  * glue.c
00171  */
00172 void auto_save_commands(FILE * file, AUTO * autopilot)
00173 {
00174 
00175         int i;                                          /* Our Counter */
00176         unsigned char tmpb;                     /* Our temp int we use when writing */
00177         unsigned int size;                      /* The size of our command list */
00178 
00179         command_node *temp_command_node;
00180 
00181         /* Print the Start Code */
00182         outbyte(AI_COMMAND_DLLIST_START);
00183 
00184         /* Write the size of our list */
00185         size = dllist_size(autopilot->commands);
00186         CHESA(&size, sizeof(size), 1, file);
00187 
00188         /* Check the size of the list, if there are commands save them */
00189         if(dllist_size(autopilot->commands) > 0) {
00190 
00191                 /* Ok there stuff here so lets write it */
00192                 for(i = 1; i <= dllist_size(autopilot->commands); i++) {
00193                         temp_command_node =
00194                                 (command_node *) dllist_get_node(autopilot->commands, i);
00195                         auto_write_command_node(file, temp_command_node);
00196                 }
00197 
00198         }
00199 
00200         /* Print the Stop Code */
00201         outbyte(AI_COMMAND_DLLIST_END);
00202 
00203         return;
00204 
00205 }
00206 
00207 /*
00208  * Loads an AI's saved command list from
00209  * a file.  Called by load_xcode in glue.c
00210  */
00211 void auto_load_commands(FILE * file, AUTO * autopilot)
00212 {
00213 
00214         int i;                                          /* Our Counter */
00215         unsigned char tmpb;                     /* Our temp int we use when reading */
00216         unsigned int size;                      /* The size of our command list */
00217 
00218         dllist_node *temp_dllist_node;
00219         command_node *temp_command_node;
00220 
00221         /* Alloc a dllist to the AI for commands */
00222         autopilot->commands = dllist_create_list();
00223 
00224         /* If we can't even read the file don't bother
00225          * with the rest */
00226         if(feof(file))
00227                 return;
00228 
00229         /* Loop for the beginning tag */
00230         fread(&tmpb, 1, 1, file);
00231         if(tmpb != AI_COMMAND_DLLIST_START) {
00232                 fprintf(stderr, "Unable to locate START for reading data"
00233                                 " for AI #%d\n", autopilot->mynum);
00234                 fflush(stderr);
00235                 exit(1);
00236         }
00237 
00238         /* Read in size of dllist */
00239         CHELO(&size, sizeof(size), 1, file);
00240 
00241         /* if size is bigger then zero means we have to read
00242          * in some command nodes */
00243         if(size > 0) {
00244 
00245                 /* Loop through the list and add the nodes */
00246                 for(i = 1; i <= size; i++) {
00247 
00248                         temp_command_node = auto_read_command_node(file);
00249                         temp_dllist_node = dllist_create_node(temp_command_node);
00250                         dllist_insert_end(autopilot->commands, temp_dllist_node);
00251 
00252                 }
00253 
00254         }
00255 
00256         /* Look for the end tag */
00257         fread(&tmpb, 1, 1, file);
00258         if(tmpb != AI_COMMAND_DLLIST_END) {
00259                 fprintf(stderr, "Unable to locate END for reading data"
00260                                 " for AI #%d\n", autopilot->mynum);
00261                 fflush(stderr);
00262                 exit(1);
00263         }
00264 
00265         return;
00266 
00267 }
00268 
00269 /* 
00270    The Autopilot command interface
00271 
00272    addcommand <name> [args]
00273    delcommand <num>
00274    listcommands
00275    engage
00276    disengage
00277    jump
00278 
00279  */
00280 
00281 /*
00282  * The commands that are on the XCODE Object along
00283  * with some helper commands for modifying the state
00284  * of the AI
00285  */
00286 
00288 int auto_valid_progline(AUTO * a, int p)
00289 {
00290         int i;
00291 #if 0
00292         for(i = 0; i < a->first_free; i += (acom[a->commands[i]].argcount + 1))
00293                 if(i == p)
00294                         return 1;
00295 #endif
00296         return 0;
00297 }
00298 
00299 /*
00300  * Internal function to return a string that
00301  * displays a command from a command_node
00302  */
00304 static char *auto_show_command(command_node * node)
00305 {
00306 
00307         static char buf[MBUF_SIZE];
00308         int i;
00309 
00310         snprintf(buf, MBUF_SIZE, "%-10s", node->args[0]);
00311 
00312         /* Loop through the args and print the commands */
00313         for(i = 1; i < AUTOPILOT_MAX_ARGS; i++)
00314                 if(node->args[i]) {
00315                         strncat(buf, " ", MBUF_SIZE);
00316                         strncat(buf, node->args[i], MBUF_SIZE);
00317                 }
00318 
00319         return buf;
00320 
00321 }
00322 
00323 /*
00324  * Removes a command from the AI's command list
00325  */
00326 void auto_delcommand(dbref player, void *data, char *buffer)
00327 {
00328 
00329         int p, i;
00330         AUTO *autopilot = (AUTO *) data;
00331         int remove_all_commands = 0;
00332         command_node *temp_command_node;
00333         char error_buf[MBUF_SIZE];
00334 
00335         /* Make sure they specified an argument */
00336         if(!*buffer) {
00337                 notify(player, "No argument used : Usage delcommand [num]\n");
00338                 notify_printf(player, "Must be within the range"
00339                                           " 1 to %d or -1 for all\n",
00340                                           dllist_size(autopilot->commands));
00341                 return;
00342         }
00343 
00344         /* Make sure its a number */
00345         if(Readnum(p, buffer)) {
00346                 notify_printf(player, "Invalid Argument : Must be within the range"
00347                                           " 1 to %d or -1 for all\n",
00348                                           dllist_size(autopilot->commands));
00349                 return;
00350         }
00351 
00352         /* Check if its a valid command position
00353          * If its -1 means remove all */
00354         if(p == -1) {
00355                 remove_all_commands = 1;
00356         } else if((p > dllist_size(autopilot->commands)) || (p < 1)) {
00357                 notify_printf(player, "Invalid Argument : Must be within the range"
00358                                           " 1 to %d or -1 for all\n",
00359                                           dllist_size(autopilot->commands));
00360                 return;
00361         }
00362 
00366         /* Now remove the node(s) */
00367         if(!remove_all_commands) {
00368 
00369                 /* Remove the node at pos */
00370                 temp_command_node =
00371                         (command_node *) dllist_remove_node_at_pos(autopilot->commands,
00372                                                                                                            p);
00373 
00374                 if(!temp_command_node) {
00375                         snprintf(error_buf, MBUF_SIZE,
00376                                          "Internal AI Error: Trying to remove"
00377                                          " Command #%d from AI #%d but the command node doesn't exist\n",
00378                                          p, autopilot->mynum);
00379                         SendAI(error_buf);
00380                 }
00381 
00382                 /* Destroy the command_node */
00383                 auto_destroy_command_node(temp_command_node);
00384 
00385                 notify_printf(player, "Command #%d Successfully Removed\n", p);
00386 
00387         } else {
00388 
00389                 /* Remove ALL the commands */
00390                 while (dllist_size(autopilot->commands)) {
00391 
00392                         /* Remove the first node on the list and get the data
00393                          * from it */
00394                         temp_command_node =
00395                                 (command_node *) dllist_remove(autopilot->commands,
00396                                                                                            dllist_head(autopilot->
00397                                                                                                                    commands));
00398 
00399                         /* Make sure the command node exists */
00400                         if(!temp_command_node) {
00401 
00402                                 snprintf(error_buf, MBUF_SIZE,
00403                                                  "Internal AI Error: Trying to remove"
00404                                                  " the first command from AI #%d but the command node doesn't exist\n",
00405                                                  autopilot->mynum);
00406                                 SendAI(error_buf);
00407 
00408                         } else {
00409 
00410                                 /* Destroy the command node */
00411                                 auto_destroy_command_node(temp_command_node);
00412 
00413                         }
00414 
00415                 }
00416 
00417                 notify(player, "All the commands have been removed.\n");
00418 
00419         }
00420 
00421 }
00422 
00423 /*
00424  * Jump to a specific command location in the AI's
00425  * command list
00426  */
00427 void auto_jump(dbref player, void *data, char *buffer)
00428 {
00429         int p;
00430         AUTO *a = (AUTO *) data;
00431 
00432         notify(player, "jump has been temporarly disabled till I can figure out"
00433                    " how I want to change it - Dany");
00434 #if 0
00435         skipws(buffer);
00436         DOCHECK(!*buffer, "Argument expected!");
00437         DOCHECK(Readnum(p, buffer), "Invalid argument - single number expected.");
00438         /* Find out if it's valid position */
00439         DOCHECK(!auto_valid_progline(a, p),
00440                         "Invalid : Argument out of range, or argument, not command.");
00441         PG(a) = p;
00442         notify_printf(player, "Program Counter set to #%d.", p);
00443 #endif
00444 }
00445 
00446 /*
00447  * Adds a command to the AI Command List
00448  */
00449 void auto_addcommand(dbref player, void *data, char *buffer)
00450 {
00451 
00452         AUTO *autopilot = (AUTO *) data;
00453         char *args[AUTOPILOT_MAX_ARGS]; /* args[0] is the command the rest are 
00454                                                                            args for the command */
00455         char *command;                          /* temp string to get the name of the command */
00456         int argc;
00457         int i, j;
00458 
00459         command_node *temp_command_node;
00460         dllist_node *temp_dllist_node;
00461 
00462         /* Clear the Args */
00463         memset(args, 0, sizeof(char *) * AUTOPILOT_MAX_ARGS);
00464 
00465         command = first_parseattribute(buffer);
00466 
00467         /* Look at the buffer and try and get the command */
00468         for(i = 0; acom[i].name; i++) {
00469                 if((!strncmp(command, acom[i].name, strlen(command))) &&
00470                    (!strncmp(acom[i].name, command, strlen(acom[i].name))))
00471                         break;
00472         }
00473 
00474         /* Free the command string we dont need it anymore */
00475         free(command);
00476 
00477         /* Make sure its a valid command */
00478         DOCHECK(!acom[i].name, "Invalid Command!");
00479 
00480         /* Get the arguments for the command */
00481         if(acom[i].argcount > 0) {
00482 
00483                 /* Parse the buffer for commands
00484                  * Its argcount + 1 because we are parsing the command + its
00485                  * arguments */
00486                 argc = proper_explodearguments(buffer, args, acom[i].argcount + 1);
00487 
00488                 if(argc != acom[i].argcount + 1) {
00489 
00490                         /* Free the args before we quit */
00491                         for(j = 0; j < AUTOPILOT_MAX_ARGS; j++) {
00492                                 if(args[j])
00493                                         free(args[j]);
00494                         }
00495                         notify(player, "Not the proper number of arguments!");
00496                         return;
00497 
00498                 }
00499 
00500         } else {
00501 
00502                 /* Copy the command to the first arg */
00503                 args[0] = strdup(acom[i].name);
00504 
00505         }
00506 
00507         /* Build the command node */
00508         temp_command_node = auto_create_command_node();
00509 
00510         for(j = 0; j < AUTOPILOT_MAX_ARGS; j++) {
00511                 if(args[j])
00512                         temp_command_node->args[j] = args[j];
00513         }
00514 
00515         temp_command_node->argcount = acom[i].argcount;
00516         temp_command_node->command_enum = acom[i].command_enum;
00517         temp_command_node->ai_command_function = acom[i].ai_command_function;
00518 
00519         /* Add the command to the list */
00520         temp_dllist_node = dllist_create_node(temp_command_node);
00521         dllist_insert_end(autopilot->commands, temp_dllist_node);
00522 
00523         /* Let the player know it worked */
00524         notify_printf(player, "Command Added: %s",
00525                                   auto_show_command(temp_command_node));
00526 
00527 }
00528 
00529 /*
00530  * Lists the various settings and commands currently on the AI
00531  */
00532 void auto_listcommands(dbref player, void *data, char *buffer)
00533 {
00534 
00535         AUTO *autopilot = (AUTO *) data;
00536         coolmenu *c = NULL;
00537         char buf[MBUF_SIZE];
00538         int i, count = 0;
00539 
00540         addline();
00541 
00542         snprintf(buf, MBUF_SIZE, "Autopilot data for %s", Name(autopilot->mynum));
00543         vsi(buf);
00544 
00545         snprintf(buf, MBUF_SIZE, "Controling unit %s",
00546                          Name(Location(autopilot->mynum)));
00547         vsi(buf);
00548 
00549         addline();
00550 
00551         snprintf(buf, MBUF_SIZE, "MyRef: #%d  MechRef: #%d  MapIndex: #%d  "
00552                          "FSpeed: %d %% (Flag:%d)", autopilot->mynum,
00553                          autopilot->mymechnum, autopilot->mapindex, autopilot->speed,
00554                          autopilot->flags);
00555         vsi(buf);
00556 
00557         addline();
00558 
00559         if(dllist_size(autopilot->commands)) {
00560 
00561                 for(i = 1; i <= dllist_size(autopilot->commands); i++) {
00562                         snprintf(buf, MBUF_SIZE, "#%-3d %s", i,
00563                                          auto_show_command((command_node *)
00564                                                                            dllist_get_node(autopilot->commands,
00565                                                                                                            i)));
00566                         vsi(buf);
00567                 }
00568 
00569         } else {
00570                 vsi("No commands have been queued to date.");
00571         }
00572 
00573         addline();
00574         ShowCoolMenu(player, c);
00575         KillCoolMenu(c);
00576 }
00577 
00578 void auto_eventstats(dbref player, void *data, char *buffer)
00579 {
00580 
00581         AUTO *autopilot = (AUTO *) data;
00582         int i, j, total;
00583 
00584         notify(player, "Events by type: ");
00585         notify(player, "-------------------------------");
00586 
00587         total = 0;
00588 
00589         for(i = FIRST_AUTO_EVENT; i <= LAST_AUTO_EVENT; i++) {
00590 
00591                 if((j = muxevent_count_type_data(i, (void *) autopilot))) {
00592                         notify_printf(player, "%-20s%d", muxevent_names[i], j);
00593                         total += j;
00594                 }
00595 
00596         }
00597 
00598         if(total) {
00599                 notify(player, "-------------------------------");
00600                 notify_printf(player, "%d total", total);
00601         }
00602 
00603 }
00604 
00605 /*
00606  * Turn the autopilot on
00607  */
00608 static int auto_pilot_on(AUTO * autopilot)
00609 {
00610 
00611         int i, j, count = 0;
00612 
00613         for(i = FIRST_AUTO_EVENT; i <= LAST_AUTO_EVENT; i++)
00614                 if((j = muxevent_count_type_data(i, (void *) autopilot)))
00615                         count += j;
00616 
00617         if(!count) {
00618                 return autopilot->flags & (AUTOPILOT_AUTOGUN | AUTOPILOT_GUNZOMBIE |
00619                                                                    AUTOPILOT_PILZOMBIE);
00620         }
00621 
00622         return count;
00623 
00624 }
00625 
00626 /*
00627  * Stop whatever the autopilot is doing
00628  */
00629 extern void auto_stop_pilot(AUTO * autopilot)
00630 {
00631 
00632         int i;
00633 
00634         autopilot->flags &= ~(AUTOPILOT_AUTOGUN | AUTOPILOT_GUNZOMBIE
00635                                                   | AUTOPILOT_PILZOMBIE);
00636 
00637         for(i = FIRST_AUTO_EVENT; i <= LAST_AUTO_EVENT; i++)
00638                 muxevent_remove_type_data(i, (void *) autopilot);
00639 
00640 }
00641 
00642 /*
00643  * Set the comtitle for the autopilot's unit
00644  */
00645 void auto_set_comtitle(AUTO * autopilot, MECH * mech)
00646 {
00647 
00648         char buf[LBUF_SIZE];
00649 
00650         snprintf(buf, LBUF_SIZE, "a=%s/%s", MechType_Ref(mech), MechIDS(mech, 1));
00651         mech_set_channeltitle(autopilot->mynum, mech, buf);
00652 
00653 }
00654 
00655 /*
00656  * Set default parameters for the AI
00657  */
00659 void auto_init(AUTO * autopilot, MECH * mech)
00660 {
00661 
00662         autopilot->ofsx = 0;            /* Positional - angle */
00663         autopilot->ofsy = 0;            /* Positional - distance */
00664         autopilot->auto_cmode = 1;      /* CHARGE! */
00665         autopilot->auto_cdist = 2;      /* Attempt to avoid kicking distance */
00666         autopilot->auto_nervous = 0;
00667         autopilot->auto_goweight = 44;  /* We're mainly concentrating on fighting */
00668         autopilot->auto_fweight = 55;
00669         autopilot->speed = 100;         /* Reset to full speed */
00670         autopilot->flags = 0;
00671 
00672         /* Target Stuff */
00673         autopilot->target = -2;
00674         autopilot->target_score = 0;
00675         autopilot->target_threshold = 50;
00676         autopilot->target_update_tick = AUTO_GUN_UPDATE_TICK;
00677 
00678         /* Follow & Chase target stuff */
00679         autopilot->chase_target = -10;
00680         autopilot->chasetarg_update_tick = AUTOPILOT_CHASETARG_UPDATE_TICK;
00681         autopilot->follow_update_tick = AUTOPILOT_FOLLOW_UPDATE_TICK;
00682 
00683 }
00684 
00685 /*
00686  * Setup all the flags and variables to current, then
00687  * start the AI's first command.
00688  */
00689 void auto_engage(dbref player, void *data, char *buffer)
00690 {
00691 
00692         AUTO *autopilot = (AUTO *) data;
00693         MECH *mech;
00694 
00695         autopilot->mymech = mech =
00696                 getMech((autopilot->mymechnum = Location(autopilot->mynum)));
00697         DOCHECK(!autopilot, "Internal error! - Bad AI object!");
00698         DOCHECK(!mech, "Error: The autopilot isn't inside a 'mech!");
00699         DOCHECK(auto_pilot_on(autopilot),
00700                         "The autopilot's already online! You have to disengage it first.");
00701 
00702         if(MechAuto(mech) <= 0)
00703                 auto_init(autopilot, mech);
00704         MechAuto(mech) = autopilot->mynum;
00705 
00706         if(MechAuto(mech) > 0)
00707                 auto_set_comtitle(autopilot, mech);
00708 
00709         autopilot->mapindex = mech->mapindex;
00710 
00711         notify(player, "Engaging autopilot...");
00712         AUTOEVENT(autopilot, EVENT_AUTOCOM, auto_com_event, AUTOPILOT_NC_DELAY,
00713                           0);
00714 
00715         return;
00716 
00717 }
00718 
00719 /*
00720  * Turn off the autopilot
00721  */
00722 void auto_disengage(dbref player, void *data, char *buffer)
00723 {
00724 
00725         AUTO *autopilot = (AUTO *) data;
00726 
00727         DOCHECK(!auto_pilot_on(autopilot),
00728                         "The autopilot's already offline! You have to engage it first.");
00729 
00730         auto_stop_pilot(autopilot);
00731         notify(player, "Autopilot has been disengaged.");
00732 
00733         return;
00734 
00735 }
00736 
00737 /*
00738  * Remove the first command_node in the list and go to the next
00739  */
00740 void auto_goto_next_command(AUTO * autopilot, int time)
00741 {
00742 
00743         command_node *temp_command_node;
00744         char error_buf[MBUF_SIZE];
00745 
00746         if(dllist_size(autopilot->commands) < 0) {
00747                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to remove"
00748                                  " the first command from AI #%d but the command list is empty\n",
00749                                  autopilot->mynum);
00750                 SendAI(error_buf);
00751                 return;
00752         }
00753 
00754         temp_command_node = (command_node *) dllist_remove(autopilot->commands,
00755                                                                                                            dllist_head(autopilot->
00756                                                                                                                                    commands));
00757 
00758         if(!temp_command_node) {
00759                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to remove"
00760                                  " the first command from AI #%d but the command node doesn't exist\n",
00761                                  autopilot->mynum);
00762                 SendAI(error_buf);
00763                 return;
00764         }
00765 
00766         auto_destroy_command_node(temp_command_node);
00767 
00768         /* Fire off the AUTO_COM event */
00769         AUTO_COM(autopilot, time);
00770 
00771 }
00772 
00773 /*
00774  * Get the argument for a given command position and argument number
00775  * Remember to free the string that this returns after use 
00776  */
00777 char *auto_get_command_arg(AUTO * autopilot, int command_number,
00778                                                    int arg_number)
00779 {
00780 
00781         char *argument;
00782         command_node *temp_command_node;
00783         char error_buf[MBUF_SIZE];
00784 
00785         if(command_number > dllist_size(autopilot->commands)) {
00786                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to "
00787                                  "access Command #%d for AI #%d but it doesn't exist",
00788                                  command_number, autopilot->mynum);
00789                 SendAI(error_buf);
00790                 return NULL;
00791         }
00792 
00793         if(arg_number >= AUTOPILOT_MAX_ARGS) {
00794                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to "
00795                                  "access Arg #%d for AI #%d Command #%d but its greater"
00796                                  " then AUTOPILOT_MAX_ARGS (%d)",
00797                                  arg_number, autopilot->mynum, command_number,
00798                                  AUTOPILOT_MAX_ARGS);
00799                 SendAI(error_buf);
00800                 return NULL;
00801         }
00802 
00803         temp_command_node = (command_node *) dllist_get_node(autopilot->commands,
00804                                                                                                                  command_number);
00805 
00808         if(!temp_command_node->args[arg_number]) {
00809                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to "
00810                                  "access Arg #%d for AI #%d Command #%d but it doesn't exist",
00811                                  autopilot->mynum, arg_number, command_number);
00812                 SendAI(error_buf);
00813                 return NULL;
00814         }
00815 
00816         argument = strndup(temp_command_node->args[arg_number], MBUF_SIZE);
00817 
00818         return argument;
00819 
00820 }
00821 
00822 /*
00823  * Returns the command_enum value for the given command
00824  * from the AI command list
00825  */
00826 int auto_get_command_enum(AUTO * autopilot, int command_number)
00827 {
00828 
00829         int command_enum;
00830         command_node *temp_command_node;
00831         char error_buf[MBUF_SIZE];
00832 
00833         /* Make sure there are commands */
00834         if(dllist_size(autopilot->commands) <= 0) {
00835                 return -1;
00836         }
00837 
00838         if(command_number <= 0) {
00839                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to "
00840                                  "access a command (%d) for AI #%d that can't be on a list",
00841                                  command_number, autopilot->mynum);
00842                 SendAI(error_buf);
00843                 return -1;
00844         }
00845 
00846         /* Make sure the command is on the list */
00847         if(command_number > dllist_size(autopilot->commands)) {
00848                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Trying to "
00849                                  "access Command #%d for AI #%d but it doesn't exist",
00850                                  autopilot->mynum, command_number);
00851                 SendAI(error_buf);
00852                 return -1;
00853         }
00854 
00855         temp_command_node = (command_node *) dllist_get_node(autopilot->commands,
00856                                                                                                                  command_number);
00857 
00860         command_enum = temp_command_node->command_enum;
00861 
00862         /* If its a bad enum value we have a problem */
00863         if((command_enum >= AUTO_NUM_COMMANDS) || (command_enum < 0)) {
00864                 snprintf(error_buf, MBUF_SIZE, "Internal AI Error: Command ENUM for"
00865                                  " AI #%d Command Number #%d doesn't exist\n",
00866                                  autopilot->mynum, command_number);
00867                 SendAI(error_buf);
00868                 return -1;
00869         }
00870 
00871         return command_enum;
00872 
00873 }
00874 
00875 #define SPECIAL_FREE 0
00876 #define SPECIAL_ALLOC 1
00877 
00878 /*
00879  * Called when either creating a new autopilot - SPECIAL_ALLOC
00880  * or when destroying an autopilot - SPECIAL_FREE
00881  */
00882 void auto_newautopilot(dbref key, void **data, int selector)
00883 {
00884 
00885         AUTO *autopilot = *data;
00886         MECH *mech;
00887         command_node *temp;
00888         int i;
00889 
00890         switch (selector) {
00891         case SPECIAL_ALLOC:
00892 
00893                 /* Allocate the command list */
00894                 autopilot->commands = dllist_create_list();
00895 
00896                 /* Make sure certain things are set NULL */
00897                 autopilot->astar_path = NULL;
00898                 autopilot->weaplist = NULL;
00899 
00900                 for(i = 0; i < AUTO_PROFILE_MAX_SIZE; i++) {
00901                         autopilot->profile[i] = NULL;
00902                 }
00903 
00904                 /* And some things not set null */
00905                 autopilot->speed = 100;
00906 
00907                 break;
00908 
00909         case SPECIAL_FREE:
00910 
00911                 /* Make sure the AI is stopped */
00912                 auto_stop_pilot(autopilot);
00913 
00914                 /* Go through the list and remove any leftover nodes */
00915                 while (dllist_size(autopilot->commands)) {
00916 
00917                         /* Remove the first node on the list and get the data
00918                          * from it */
00919                         temp = (command_node *) dllist_remove(autopilot->commands,
00920                                                                                                   dllist_head(autopilot->
00921                                                                                                                           commands));
00922 
00923                         /* Destroy the command node */
00924                         auto_destroy_command_node(temp);
00925 
00926                 }
00927 
00928                 /* Destroy the list */
00929                 dllist_destroy_list(autopilot->commands);
00930                 autopilot->commands = NULL;
00931 
00932                 /* Destroy any astar path list thats on the AI */
00933                 auto_destroy_astar_path(autopilot);
00934 
00935                 /* Destroy profile array */
00936                 for(i = 0; i < AUTO_PROFILE_MAX_SIZE; i++) {
00937                         if(autopilot->profile[i]) {
00938                                 rb_destroy(autopilot->profile[i]);
00939                         }
00940                         autopilot->profile[i] = NULL;
00941                 }
00942 
00943                 /* Destroy weaponlist */
00944                 auto_destroy_weaplist(autopilot);
00945 
00946                 /* Finally reset the AI value on its unit if
00947                  * it needs to */
00948                 if((mech = getMech(autopilot->mymechnum))) {
00949 
00950                         /* Just incase another AI has taken over */
00951                         if(MechAuto(mech) == autopilot->mynum) {
00952                                 MechAuto(mech) = -1;
00953                         }
00954 
00955                 }
00956 
00957                 break;
00958 
00959         }
00960 
00961 }
00962 
00963 // XXX: put in a header file
00964 extern unsigned int global_tick;
00965 
00966 void auto_heartbeat(AUTO *autopilot) {
00967     if(!autopilot->mymech) return;
00968     auto_sensor_event(autopilot);
00969     if(autopilot->weaplist == NULL || global_tick % AUTO_PROFILE_TICK == 0)  
00970         auto_update_profile_event(autopilot);
00971     auto_gun_event(autopilot);
00972 }

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