btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: autopilot_command.c,v 1.4 2005/08/10 14:09:34 av1-op Exp $
 *
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1997 Markus Stenberg
 *  Copyright (c) 1998-2002 Thomas Wouters
 *  Copyright (c) 2000-2002 Cord Awtry
 *       All rights reserved
 *
 * Created: Tue Sep 23 20:33:33 1997 fingon
 * Last modified: Sat Jun  6 21:47:38 1998 fingon
 *
 */

/* Most of the BattleSheep(tm) code is here.. */

#include <math.h>
#include "mech.h"
#include "autopilot.h"
#include "spath.h"
#include "mech.notify.h"
#include "p.mech.utils.h"
#include "p.mech.sensor.h"
#include "p.mech.los.h"
#include "p.mech.startup.h"
#include "p.mech.maps.h"
#include "p.ds.bay.h"
#include "p.mech.maps.h"
#include "p.bsuit.h"
#include "p.glue.h"

void sendchannelstuff(MECH * mech, int freq, char *msg);

/*! \todo {Should really do away with this some how but i'm being lazy right now} */
#define Clear(a) \
    auto_disengage(a->mynum, a, ""); \
    auto_delcommand(a->mynum, a, "-1"); \
    if (a->target >= -1) { \
        if (AssignedTarget(a) && a->target != -1) { \
            snprintf(buffer, SBUF_SIZE, "autogun target %d", a->target); \
        } else { \
            snprintf(buffer, SBUF_SIZE, "autogun on"); \
        } \
        auto_addcommand(a->mynum, autopilot, buffer); \
    } \

#define BACMD(name) char * name (AUTO *autopilot, MECH *mech, char **args, int argc, int chn)
#define ACMD(name) static BACMD(name)

/* 
 * Master list of AI - radio commands
 */
struct {
    char *sho;
    char *name;
    int args;
    int silent;
    void (*fun)(AUTO *autopilot, MECH *mech, char **args, int argc, char *mesg);
} auto_cmds[] = {
    {
    "auto", "autogun", 1, 0, auto_radio_command_autogun}, {
#if 0
    "att", "attackleg", 1, 0, auto_attackleg}, {
    "chanf", "chanfreq", 2, 0, auto_setchanfreq}, {
    "chanm", "chanmode", 2, 0, auto_setchanmode}, {
#endif
    "chase", "chasetarg", 1, 0, auto_radio_command_chasetarg}, {
#if 0
    "cm", "cmode", 2, 0, auto_cmode}, {
#endif
    "dfo", "dfollow", 1, 0, auto_radio_command_dfollow}, {
    "dgo", "dgoto", 2, 0, auto_radio_command_dgoto}, {
#if 0
    "dr", "drally", 2, 0, auto_drally}, {
    "dr", "drally", 3, 0, auto_drally}, {
#endif
    "drop", "dropoff", 0, 0, auto_radio_command_dropoff}, {
    "emb", "embark", 1, 0, auto_radio_command_embark}, {
    "en", "enterbase", 0, 0, auto_radio_command_enterbase}, {
    "en", "enterbase", 1, 0, auto_radio_command_enterbase}, {
#if 0
    "en", "enterbay", 0, 0, auto_enterbay}, {
    "en", "enterbay", 1, 0, auto_enterbay}, {
#endif
    "fo", "follow", 1, 0, auto_radio_command_follow}, {
#if 0
    "fr", "freq", 1, 0, auto_freq}, {
#endif
    "go", "goto", 2, 0, auto_radio_command_goto}, {
    "he", "heading", 1, 0, auto_radio_command_heading}, {
    "he", "help", 0, 1, auto_radio_command_help}, {
    "hi", "hide", 0, 0, auto_radio_command_hide}, {
    "jump", "jumpjet", 1, 0, auto_radio_command_jumpjet}, {
    "jump", "jumpjet", 2, 0, auto_radio_command_jumpjet}, {
    "le", "leavebase", 1, 0, auto_radio_command_leavebase}, {
#if 0
    "nog", "nogun", 0, 0, auto_nogun}, {
    "not", "notarget", 0, 0, auto_notarget}, {
#endif
    "ogo", "ogoto", 2, 0, auto_radio_command_ogoto}, {
    "pick", "pickup", 1, 0, auto_radio_command_pickup}, {
    "pos", "position", 2, 0, auto_radio_command_position}, {
    "pr", "prone", 0, 0, auto_radio_command_prone}, {
#if 0
    "ra", "rally", 2, 0, auto_rally}, {
    "ra", "rally", 3, 0, auto_rally}, {
#endif
    "re", "report", 0, 1, auto_radio_command_report}, {
    "reset", "reset", 0, 0, auto_radio_command_reset}, {
#if 0
    "roam", "roammode", 1, 0, auto_roammode }, {
#endif
    "se", "sensor", 2, 0, auto_radio_command_sensor}, {
    "se", "sensor", 0, 0, auto_radio_command_sensor}, {
    "sh", "shutdown", 0, 0, auto_radio_command_shutdown}, {
    "sp", "speed", 1, 0, auto_radio_command_speed}, {
    "st", "stand", 0, 0, auto_radio_command_stand}, {
    "st", "startup", 0, 0, auto_radio_command_startup}, {
    "st", "startup", 1, 0, auto_radio_command_startup}, {
    "st", "stop", 0, 0, auto_radio_command_stop}, {
    "sw", "sweight", 2, 1, auto_radio_command_sweight}, {
#if 0
    "swa", "swarm", 1, 0, auto_swarm}, {
    "swarmc", "swarmcharge", 1, 0, auto_swarmcharge }, {
    "swarmm", "swarmmode", 1, 0, auto_swarmmode }, {
#endif
    "ta", "target", 1, 0, auto_radio_command_target}, {
#if 0
    "ta", "target", 2, 0, auto_target}, {
#endif
    NULL, NULL, 0, 0, NULL}
};

/*
 * The autogun radio interface
 */
void auto_radio_command_autogun(AUTO *autopilot, MECH *mech, 
        char **args, int argc, char *mesg) {

    if (strcmp(args[1], "on") == 0) {

        autopilot->target = -1;
        autopilot->target_score = 0;
        autopilot->target_update_tick = AUTO_GUN_UPDATE_TICK;

        /* Reset the Assigned target flag */
        if (AssignedTarget(autopilot)) {
            UnassignTarget(autopilot);
        }

        if (Gunning(autopilot)) {
            DoStopGun(autopilot);
        }
        DoStartGun(autopilot);

        snprintf(mesg, LBUF_SIZE, "shooting at whatever I want");
        return;

    } else if (strcmp(args[1], "off") == 0) {

        /* Reset the AI */
        autopilot->target = -2;
        autopilot->target_score = 0;
        autopilot->target_update_tick = 0;

        /* Reset this flag since we don't want to be shooting anything */
        if (AssignedTarget(autopilot)) {
            UnassignTarget(autopilot);
        }

        if (Gunning(autopilot))
            DoStopGun(autopilot);

        snprintf(mesg, LBUF_SIZE, "powering down weapons");
        return;

    }
    snprintf(mesg, LBUF_SIZE, "!Invalid Input for autogun:"
            " use 'on' or 'off'");

}

/*
 * Tell the AI to chase whatever its targeting
 */
void auto_radio_command_chasetarg(AUTO *autopilot, MECH *mech, 
        char **args, int argc, char *mesg) {

    if (strcmp(args[1], "on") == 0) {

        auto_set_chasetarget_mode(autopilot, AUTO_CHASETARGET_ON);
        snprintf(mesg, LBUF_SIZE, "Chase Target Mode is Activated");
        return;

    } else if (strcmp(args[1], "off") == 0) {

        auto_set_chasetarget_mode(autopilot, AUTO_CHASETARGET_OFF);
        snprintf(mesg, LBUF_SIZE, "Chase Target Mode is Deactivated");
        return;
    }
    snprintf(mesg, LBUF_SIZE, "!Invalid Input for chasetarg: use 'on' or 'off'");

}

/*
 * Radio command to force AI to [dumbly] follow a given target
 */
void auto_radio_command_dfollow(AUTO *autopilot, MECH *mech, 
        char **args, int argc, char *mesg) {

    dbref targetref;
    char buffer[SBUF_SIZE];

    targetref = FindTargetDBREFFromMapNumber(mech, args[1]);
    if (targetref <= 0) {
        snprintf(mesg, LBUF_SIZE, "!Invalid target to follow");
        return;
    }

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "dumbfollow %d", targetref);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "following %s [dumbly] (%d degrees, %d away)",
            args[1], autopilot->ofsx, autopilot->ofsy);
}

/*
 * Radio command to force AI to [dumbly] goto a given hex
 */
void auto_radio_command_dgoto(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {
    
    int x, y;
    char buffer[SBUF_SIZE];

    if (Readnum(x, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!First number not an integer");
        return;
    }
    if (Readnum(y, args[2])) {
        snprintf(mesg, LBUF_SIZE, "!First number not an integer");
        return;
    }

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "dumbgoto %d %d", x, y);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "going [dumbly] to %d,%d", x, y);

}

/*
 * Radio command to force AI to drop whatever its carrying
 */
void auto_radio_command_dropoff(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[SBUF_SIZE];

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "dropoff");
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "dropping off");

}

/*
 * Radio command to force AI to embark a carrier
 */
void auto_radio_command_embark(AUTO* autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    dbref targetref;
    char buffer[SBUF_SIZE];

    targetref = FindTargetDBREFFromMapNumber(mech, args[1]);
    if (targetref <= 0) {
        snprintf(mesg, LBUF_SIZE, "!Invalid target to embark");
        return;
    }

    Clear(autopilot);
    snprintf(buffer, SBUF_SIZE, "embark %d", targetref);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "embarking %s", args[1]);
    return;

}

/*
 * Radio command to force AI to enterbase
 */
void auto_radio_command_enterbase(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[SBUF_SIZE];

    if (argc - 1) {
        snprintf(buffer, SBUF_SIZE, "enterbase %s", args[1]);
        snprintf(mesg, LBUF_SIZE, "entering base (%s side)",
                args[1]);
    } else {
        strncpy(buffer, "enterbase n", SBUF_SIZE);
        snprintf(mesg, LBUF_SIZE, "entering base");
    }

    Clear(autopilot);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");

}

/*
 * New smart follow system based on A*'s goto
 */
void auto_radio_command_follow(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[SBUF_SIZE];
    dbref targetref;

    targetref = FindTargetDBREFFromMapNumber(mech, args[1]);
    if (targetref <= 0) {
        snprintf(mesg, LBUF_SIZE, "!Invalid target to follow");
        return;
    }

    Clear(autopilot);
  
    snprintf(buffer, SBUF_SIZE, "follow %d", targetref);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "following %s (%d degrees, %d away)", args[1], 
            autopilot->ofsx, autopilot->ofsy);

}

/*
 * Smart goto system based on Astar path finding
 */
void auto_radio_command_goto(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {
    
    int x, y;
    char buffer[SBUF_SIZE];

    if (Readnum(x, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!First number not integer");
        return;
    }
    if (Readnum(y, args[2])) {
        snprintf(mesg, LBUF_SIZE, "!Second number not integer");
        return;
    }

    if (MechX(mech) == x && MechY(mech) == y) {
        snprintf(mesg, LBUF_SIZE, "!Already in that hex");
        return;
    }

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "goto %d %d", x, y);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "going to %d,%d", x, y);

}

/*
 * Radio command to alter an AI's heading
 */
void auto_radio_command_heading(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    int heading;
    char buffer[SBUF_SIZE];

    if (Readnum(heading, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!Number not integer");
        return;
    }

    Clear(autopilot);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(buffer, SBUF_SIZE, "%d", heading);
    mech_heading(autopilot->mynum, mech, buffer);
    strcpy(buffer, "0");
    mech_speed(autopilot->mynum, mech, buffer);
    snprintf(buffer, LBUF_SIZE, "stopped and heading changed to %d", heading);

}

/*
 * Help message, lists the various commands for the AI
 */
void auto_radio_command_help(AUTO *autopilot, MECH *mech, 
        char **args, int argc, char *mesg) {

    int i;

    /*! \todo {Add a short form of this command} */

    snprintf(mesg, LBUF_SIZE, "The following commands are possible:");

    for (i = 0; auto_cmds[i].name; i++) {
        if (i > 0 && !strcmp(auto_cmds[i].name, auto_cmds[i-1].name))
            continue;
        strncat(mesg, " ", LBUF_SIZE);
        strncat(mesg, auto_cmds[i].name, LBUF_SIZE);
    }

    auto_reply(mech, mesg);

}

/*
 * Radio command to force AI to try and hide itself
 */
void auto_radio_command_hide(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    if ((HasCamo(mech)) ? 
            0 : MechType(mech) != CLASS_BSUIT && MechType(mech) != CLASS_MW) {
        snprintf(mesg, LBUF_SIZE, "!Last I checked I was kind of big for that");
        return;
    }

    if (!(MechRTerrain(mech) == HEAVY_FOREST ||
            MechRTerrain(mech) == LIGHT_FOREST ||
            MechRTerrain(mech) == ROUGH ||
            MechRTerrain(mech) == MOUNTAINS ||
            (MechType(mech) == CLASS_BSUIT ?  MechRTerrain(mech) == BUILDING : 0))) {
        snprintf(mesg, LBUF_SIZE, "!Invalid Terrain");
        return;
    }

    bsuit_hide(autopilot->mynum, mech, "");
    snprintf(mesg, LBUF_SIZE, "Begining to hide");

}

/*
 * Radio command to force AI to jump either on a target or 
 * in a given direction range
 */
void auto_radio_command_jumpjet(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {
    
    dbref target;
    char buffer[SBUF_SIZE];
    int bear, rng;

    if (!abs(MechJumpSpeed(mech))) {
        snprintf(mesg, LBUF_SIZE, "!I don't do hiphop and jump around");
        return;
    }

    if ((argc - 1) == 1) {
        if ((target = FindTargetDBREFFromMapNumber(mech, args[1])) <= 0) {
            snprintf(mesg, LBUF_SIZE, "!Unable to see such a target");
            return;
        }
        strcpy(buffer, args[1]);
        mech_jump(autopilot->mynum, mech, buffer);
        snprintf(mesg, LBUF_SIZE, "jumping on [%s]", args[1]);
        return;
    } else {
        if (Readnum(bear, args[1])) {
            snprintf(mesg, LBUF_SIZE, "!Invalid bearing");
            return;
        }
        if (Readnum(rng, args[2])) {
            snprintf(mesg, LBUF_SIZE, "!Invalid range");
            return;
        }
        snprintf(buffer, SBUF_SIZE, "%s %s", args[1], args[2]);
        mech_jump(autopilot->mynum, mech, buffer);
        snprintf(mesg, LBUF_SIZE, "jump %s degrees %s hexes", args[1], args[2]);
        return;
    }
}

/*
 * Radio command to force AI to leavebase
 */
void auto_radio_command_leavebase(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[SBUF_SIZE];
    int direction;

    if (Readnum(direction, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!Invalid value for direction");
        return;
    }

    /* Make sure chasetarget doesn't interfere with this */
    if (ChasingTarget(autopilot)) {
        StopChasingTarget(autopilot);
    }

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "leavebase %d", direction);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, ""); 
    snprintf(mesg, LBUF_SIZE, "leaving base at %d heading", direction);

}

/*
 * Old goto system - will phase out
 */
void auto_radio_command_ogoto(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {
    
    int x, y;
    char buffer[SBUF_SIZE];

    if (Readnum(x, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!First number not integer");
        return;
    }
    if (Readnum(y, args[2])) {
        snprintf(mesg, LBUF_SIZE, "!Second number not integer");
        return;
    }

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "oldgoto %d %d", x, y);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "going [old version] to %d,%d", x, y);

}

/*
 * Radio command to force AI to pickup a target
 */
void auto_radio_command_pickup(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    dbref targetref;
    char buffer[SBUF_SIZE];

    targetref = FindTargetDBREFFromMapNumber(mech, args[1]);
    if (targetref <= 0) {
        snprintf(mesg, LBUF_SIZE, "!Invalid target to pickup");
        return;
    }

    /* Make sure chasetarget doesn't interfere with this */
    if (ChasingTarget(autopilot)) {
        StopChasingTarget(autopilot);
    }

    Clear(autopilot);

    snprintf(buffer, SBUF_SIZE, "pickup %d", targetref);
    auto_addcommand(autopilot->mynum, autopilot, buffer);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "picking up %s", args[1]);

}

/*
 * Radio command to make AI take up a given position (dir & range) from
 * their current target (hex or unit)
 */
void auto_radio_command_position(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    int x, y;

    /*! \todo {Add in some checks for validity of the arguments} */

    if (Readnum(x, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!Invalid first int");
        return;
    }
    if (Readnum(y, args[2])) {
        snprintf(mesg, LBUF_SIZE, "!Invalide second int");
        return;
    }

    autopilot->ofsx = x;
    autopilot->ofsy = y;
    snprintf(mesg, LBUF_SIZE, "following %d degrees, %d away", x, y);

}

/*
 * Radio command to force AI to go prone
 */
void auto_radio_command_prone(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    mech_drop(autopilot->mynum, mech, "");
    snprintf(mesg, LBUF_SIZE, "hitting the deck");

}

/*
 * Radio command so the AI can report its status
 */
/*! \todo {Add something that tells more info then this} */
void auto_radio_command_report(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[MBUF_SIZE];
    MECH *target;

    /* Is the AI moving or something */
    if (Jumping(mech))
        strcpy(buffer, "Jumping");
    else if (Fallen(mech))
        strcpy(buffer, "Prone");
    else if (IsRunning(MechSpeed(mech), MMaxSpeed(mech)))
        strcpy(buffer, "Running");
    else if (MechSpeed(mech) > 1.0)
        strcpy(buffer, "Walking");
    else
        strcpy(buffer, "Standing");

    snprintf(mesg, LBUF_SIZE, "%s at %d, %d", buffer, MechX(mech), MechY(mech));

    /* Which way is the AI going */
    if (MechSpeed(mech) > 1.0) {
        snprintf(buffer, MBUF_SIZE, ", headed %d speed %.2f",
                MechFacing(mech), MechSpeed(mech));
        strncat(mesg, buffer, LBUF_SIZE);
    } else {
        snprintf(buffer, MBUF_SIZE, ", headed %d",
                MechFacing(mech));
        strncat(mesg, buffer, LBUF_SIZE);
    }

    /* Is the AI targeting something */
    if (MechTarget(mech) != -1) {
        target = getMech(MechTarget(mech));

        if (target) {
            snprintf(buffer, MBUF_SIZE, ", targeting %s %s",
                    GetMechToMechID(mech, target),
                    InLineOfSight(mech, target, MechX(target),
                        MechY(target), FaMechRange(mech, target)) ?
                    "" : "(not in LOS)");
            strncat(mesg, buffer, LBUF_SIZE);
        }
    }
    
    /* Send the mesg to the reply system, this is a silent command */
    auto_reply(mech, mesg);

}

/*
 * Radio command to reset the AI's internal flags what not
 */
void auto_radio_command_reset(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[SBUF_SIZE];

    auto_disengage(autopilot->mynum, autopilot, "");
    auto_delcommand(autopilot->mynum, autopilot, "-1");
    auto_init(autopilot, mech);
    auto_engage(autopilot->mynum, autopilot, "");
    snprintf(mesg, LBUF_SIZE, "all internal events and flags reset!");

}

/*
 * Radio command to alter or let the AI alter
 * its sensors
 */
void auto_radio_command_sensor(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buf[SBUF_SIZE];

    if (argc) {

        /* Make sure no sensor event running */
        muxevent_remove_type_data(EVENT_AUTO_SENSOR, autopilot);

        /* Set the user specified sensors */
        snprintf(buf, SBUF_SIZE, "%s %s", args[1], args[2]);
        mech_sensor(autopilot->mynum, mech, buf);
        autopilot->flags |= AUTOPILOT_LSENS;
        snprintf(mesg, LBUF_SIZE, "updated my sensors");
        return;

    }

    /* Let AI decide */
    autopilot->flags &= ~AUTOPILOT_LSENS;
    UpdateAutoSensor(autopilot, 0);
    snprintf(mesg, LBUF_SIZE, "using my own judgement with sensors");
    return;

}

/*
 * Radio command to force AI to shutdown
 */
void auto_radio_command_shutdown(AUTO *autopilot, MECH *mech, 
        char **args, int argc, char *mesg) {

    mech_shutdown(autopilot->mynum, mech, "");
    snprintf(mesg, LBUF_SIZE, "shutting down");

}

/*
 * Radio command to alter the speed of an AI (% of speed)
 */
void auto_radio_command_speed(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    int speed = 100;

    if (Readnum(speed, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!Invalid value - not a number");
        return;
    }

    if (speed < 1 || speed > 100) {
        snprintf(mesg, LBUF_SIZE, "!Invalid speed");
        return;
    }

    autopilot->speed = speed;
    snprintf(mesg, LBUF_SIZE, "setting speed to %d %%", speed);

}

/*
 * Radio Command to force AI to stand
 */
void auto_radio_command_stand(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    mech_stand(autopilot->mynum, mech, "");
    snprintf(mesg, LBUF_SIZE, "standing up");

}

/*
 * Radio command to force AI to startup
 */
void auto_radio_command_startup(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    if (argc > 1) {
        if (!strncasecmp(args[1], "override", strlen(args[1]))) {
            mech_startup(autopilot->mynum, mech, "override");
            snprintf(mesg, LBUF_SIZE, "emergency override startup triggered");
            return;
        }
    }

    mech_startup(autopilot->mynum, mech, "");
    snprintf(mesg, LBUF_SIZE, "starting up");

}

/*
 * Radio command to stop the AI
 */
void auto_radio_command_stop(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    char buffer[SBUF_SIZE];

    strcpy(buffer, "0");

    /* Turn chasetarget off */
    auto_set_chasetarget_mode(autopilot, AUTO_CHASETARGET_OFF);

    Clear(autopilot);

    auto_engage(autopilot->mynum, autopilot, "");
    mech_speed(autopilot->mynum, mech, buffer);
    snprintf(mesg, LBUF_SIZE, "halting");

}

/*
 * Command for the old goto, will phase it out
 */
void auto_radio_command_sweight(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    int x, y;

    if (Readnum(x, args[1])) {
        snprintf(mesg, LBUF_SIZE, "!Invalid first int");
        return;
    }
    if (Readnum(y, args[2])) {
        snprintf(mesg, LBUF_SIZE, "!Invalide second int");
        return;
    }
    x = MAX(1, x);
    y = MAX(1, y);
    autopilot->auto_goweight = x;
    autopilot->auto_fweight = y;
    snprintf(mesg, LBUF_SIZE, "sweight'ed to %d:%d. (go:fight)", x, y);
    return;

}

/*
 * Tell the AI to target a specific unit
 */
void auto_radio_command_target(AUTO *autopilot, MECH *mech,
        char **args, int argc, char *mesg) {

    dbref targetref;

    if (!strcmp(args[1], "-")) {
       
        /* Basicly doing the same as 'autogun on' */
        autopilot->target = -1;
        autopilot->target_score = 0;
        autopilot->target_update_tick = AUTO_GUN_UPDATE_TICK;

        if (AssignedTarget(autopilot)) {
            UnassignTarget(autopilot);
        }

        if (Gunning(autopilot)) {
            DoStopGun(autopilot);
        }
        DoStartGun(autopilot);

        snprintf(mesg, LBUF_SIZE, "shooting at whatever I want");
        return;

    } else {

        targetref = FindTargetDBREFFromMapNumber(mech, args[1]);
        if (targetref <= 0) {
            snprintf(mesg, LBUF_SIZE, "!Unable to see such a target");
            return;
        }

    }

    autopilot->target = targetref;
    autopilot->target_score = 0;
    autopilot->target_update_tick = 0;

    /* Let the AI know its an assigned target */
    if(!AssignedTarget(autopilot)) {
        AssignTarget(autopilot);
    }
    
    if (Gunning(autopilot)) {
        DoStopGun(autopilot);
    }
    DoStartGun(autopilot);

    snprintf(mesg, LBUF_SIZE, "aiming for [%s] (and ignoring everyone else)",
            args[1]);

}

#if 0
ACMD(auto_swarm)
{
    dbref targetref;

    if (!mech || MechType(mech) != CLASS_BSUIT)
    return "!Not a bsuit";
    targetref = FindTargetDBREFFromMapNumber(mech, args[0]);
    if (targetref <= 0)
        return "!Invalid target to swarm"; 
    Clear(a);
    auto_addcommand(a->mynum, a, tprintf("swarm %d", targetref));
    auto_engage(a->mynum, a, "");
    return tprintf("swarming %s.", args[0]); 
}
#endif
#if 0
ACMD(auto_attackleg)
{
    dbref targetref;

    if (!mech || MechType(mech) != CLASS_BSUIT)
    return "!Not a bsuit";
    targetref = FindTargetDBREFFromMapNumber(mech, args[0]);
    if (targetref <= 0)
        return "!Invalid target to attackleg"; 
    Clear(a);
    auto_addcommand(a->mynum, a, tprintf("attackleg %d", targetref));
    auto_engage(a->mynum, a, "");
    return tprintf("attacklegging %s.", args[0]); 
}
#endif
#if 0
ACMD(auto_notarget)
{
    a->targ = -1;
    if (Gunning(a)) {
        DoStopGun(a);
        DoStartGun(a);
    }
    return "shooting at anything that moves";
}
#endif
#if 0
ACMD(auto_nogun)
{
    a->targ = -2;
    if (Gunning(a))
        DoStopGun(a);
    return "powering down weapons";
}
#endif
#if 0
ACMD(auto_rally)
{
    char xb[6], yb[6];
    int x, y, h;

    if (Readnum(x, args[0]))
        return "!Invalid X coord";
    if (Readnum(y, args[1]))
        return "!Invalid Y coord";
    if (argc < 3)
        h = MechFacing(mech);
    else if (Readnum(h, args[2]))
        return "!Invalid heading";
    /* Base things on the <h = heading> */
    x = x + a->ofsy * cos(TWOPIOVER360 * (270 + (a->ofsx + h)));
    y = y + a->ofsy * sin(TWOPIOVER360 * (270 + (a->ofsx + h)));
    sprintf(xb, "%d", x);
    sprintf(yb, "%d", y);
    args[0] = xb;
    args[1] = yb;
    return auto_goto(a, mech, args, 2, chn);
}
#endif
#if 0
ACMD(auto_drally)
{
    char xb[6], yb[6];
    int x, y, h;

    if (Readnum(x, args[0]))
        return "!Invalid X coord";
    if (Readnum(y, args[1]))
        return "!Invalid Y coord";
    if (argc < 3)
        h = MechFacing(mech);
    else if (Readnum(h, args[2]))
        return "!Invalid heading";
    /* Base things on the <h = heading> */
    x = x + a->ofsy * cos(TWOPIOVER360 * (270 + (a->ofsx + h)));
    y = y + a->ofsy * sin(TWOPIOVER360 * (270 + (a->ofsx + h)));
    sprintf(xb, "%d", x);
    sprintf(yb, "%d", y);
    args[0] = xb;
    args[1] = yb;
    return auto_dgoto(a, mech, args, 2, chn);
}
#endif
#if 0
ACMD(auto_roammode)
{
    if (strcmp(args[0], "on") == 0) {
    Clear(a);
    auto_addcommand(a->mynum, a, tprintf("roammode 1"));
    auto_engage(a->mynum, a, "");
        return "Roam mode is ON";
        } else if (strcmp(args[0], "off") == 0) {
    Clear(a);
    auto_addcommand(a->mynum, a, tprintf("roammode 0"));
    auto_engage(a->mynum, a, "");
        return "Roam mode is OFF";
        }
    return "!Invalid input use on or off";
}
#endif
#if 0
ACMD(auto_swarmmode)
{
    if (MechType(mech) != CLASS_BSUIT)
    return "!I am not a battlesuit";

    if (strcmp(args[0], "on") == 0) {
        a->flags |= AUTOPILOT_SWARMCHARGE;
        return "Swarm Mode is ON";
        } else if (strcmp(args[0], "off") == 0) {
        a->flags &= ~AUTOPILOT_SWARMCHARGE;
        return "Swarm Mode is OFF";
        }
    return "!Invalid input use on or off";
}
#endif
#if 0
ACMD(auto_swarmcharge)
{
    dbref targetref;

    if (MechType(mech) != CLASS_BSUIT)
    return "!I am not a battlesuit";

    if (strcmp(args[0], "cancel") == 0) {
    a->flags &= ~AUTOPILOT_SWARMCHARGE;
    return "Canceling swarm charge";
    }

    targetref = FindTargetDBREFFromMapNumber(mech, args[0]);
    if (targetref <= 0)
        return "!Invalid target to swarmcharge";
    Clear(a);
    auto_addcommand(a->mynum, a, tprintf("dumbfollow %d", targetref));
    auto_engage(a->mynum, a, "");
    a->flags |= AUTOPILOT_SWARMCHARGE; 
    return tprintf("swarmcharging %s (%d degrees, %d away)", args[0],
        a->ofsx, a->ofsy);
}
#endif
#if 0
ACMD(auto_freq)
{
    int freq;

    if (Readnum(freq, args[0]))
        return "!Invalid freq";
    mech_set_channelfreq(a->mynum, mech, tprintf("a=%s", args[0]));
    return "channel changed";
}
#endif
#if 0
ACMD(auto_setchanfreq)
{
    mech_set_channelfreq(a->mynum, mech, tprintf("%s=%s", args[0],
        args[1]));
    return tprintf("set channelfreq %s=%s", args[0], args[1]);
}
#endif
#if 0
ACMD(auto_setchanmode)
{
    mech_set_channelmode(a->mynum, mech, tprintf("%s=%s", args[0],
        args[1]));
    return tprintf("set channelmode %s=%s", args[0], args[1]);
}
#endif
#if 0
ACMD(auto_enterbay)
{
    mech_enterbay(a->mynum, mech, argc ? tprintf("%s",
            args[0]) : tprintf(""));
    return argc ? tprintf("entering bay (of %s)",
            args[0]) : "entering bay";
}
#endif
#if 0
ACMD(auto_cmode)
{
    int mod, ran;
    static char buf[MBUF_SIZE];

    if (Readnum(mod, args[0]))
        return "!Invalid mode [0-2]";
    if (mod < 0 || mod > 2)
        return "!Invalid mode [0-2]";
    if (Readnum(ran, args[1]))
        return "!Invalid range [0-999]";
    if (ran < 0 || ran > 999)
        return "!Invalid range [0-999]";
    a->auto_cdist = ran;
    a->auto_cmode = mod;
    switch (mod) {
    case 0:
        sprintf(buf, "fleeing, at least to range %d {from all foes}", ran);
        break;
    case 1:
        sprintf(buf, "trying to maintain range %d {from all foes}", ran);
        break;
    case 2:
        sprintf(buf, "charging to range %d {from all foes}", ran);
        break;
    }
    return buf;
}
#endif

/*
 * Event to get AI to radio a message
 */
void auto_reply_event(MUXEVENT *muxevent) {

    MECH *mech = (MECH *) muxevent->data;
    char *buf = (char *) muxevent->data2;
    MAP *map;

    /* Make sure its a mech */
    if (!IsMech(mech->mynum)) {
        free(buf);
        return;
    }

    /* If valid object */
    if (mech)
        if ((map = (getMap(mech->mapindex))))
            sendchannelstuff(mech, 0, buf);

    free(buf);
}

/*
 * Force the AI to reply over radio
 */
void auto_reply(MECH *mech, char *buf) {

    char *reply;

    /* No zero freq messages */
    if (!mech->freq[0])
        return;

    /* Make sure there is an autopilot */
    if (MechAuto(mech) <= 0)
        return;

    /* Make sure valid objects */
    if (!(FindObjectsData(MechAuto(mech))) || 
            !Good_obj(MechAuto(mech)) || 
            Location(MechAuto(mech)) != mech->mynum) {
        MechAuto(mech) = -1;
        return;
    }

    /* Copy the buffer */
    reply = strdup(buf); 

    if (reply) {
        MECHEVENT(mech, EVENT_AUTO_REPLY, auto_reply_event, Number(1, 2), reply);
    } else {
        SendAI("Interal AI Error: Attempting to radio reply but unable to copy string");
    }

}

/*
 * Parse an AI radio command
 */
void auto_parse_command(AUTO *autopilot, MECH *mech, int chn, char *buffer) {
    
    int argc, cmd;
    char *args[2];
    char *command_args[AUTOPILOT_MAX_ARGS];
    char mech_id[3];
    char message[LBUF_SIZE];
    char reply[LBUF_SIZE];
    int i;

    /* Basic checks */
    if (!autopilot || !mech)
        return;
    if (Destroyed(mech))
        return;

    /* Get the args - just need the first one */
    if (proper_explodearguments(buffer, args, 2) < 2) {
        /* free args */
        for(i = 0; i < 2; i++) {
            if(args[i]) free(args[i]);
        }
        return;
    }

    /* Check to see if the command was given to this AI */
    if (strcmp(args[0], "all")) {
        mech_id[0] = MechID(mech)[0];
        mech_id[1] = MechID(mech)[1];
        mech_id[2] = '\0';

        if (strcasecmp(mech_id, args[0])) {
            /* free args */
            for(i = 0; i < 2; i++) {
                if(args[i]) free(args[i]);
            }
            return;
        }

    }

    /* Parse the command */
    cmd = -1;
    argc = proper_explodearguments(args[1], command_args, AUTOPILOT_MAX_ARGS);

    /* Loop through the various possible commands looking for ours */
    for (i = 0; auto_cmds[i].sho; i++) {
        if (!strncmp(auto_cmds[i].sho, command_args[0], strlen(auto_cmds[i].sho)))
            if (!strncmp(auto_cmds[i].name, command_args[0], strlen(command_args[0]))) {
                if (argc == (auto_cmds[i].args + 1)) {
                    cmd = i;
                    break;
                }
            }
    }

    /* Did we find a command */
    if (cmd < 0) {

        snprintf(message, LBUF_SIZE, "Unable to comprehend the command.");
        auto_reply(mech, message); 

        /* free args */
        for(i = 0; i < 2; i++) {
            if(args[i]) free(args[i]);
        }
        for (i = 0; i < AUTOPILOT_MAX_ARGS; i++) {
            if (command_args[i]) free(command_args[i]);
        }
        return;

    }

    /* Zero the buffer */
    memset(message, 0, sizeof(message));
    memset(reply, 0, sizeof(reply));

    /* Call the radio command function */
    (*(auto_cmds[cmd].fun)) (autopilot, mech, command_args, argc, message);

    /* If its a silent command there is no reply */
    if (auto_cmds[cmd].silent) {

        /* Free args and exit */
        for(i = 0; i < 2; i++) {
            if(args[i]) free(args[i]);
        }
        for (i = 0; i < AUTOPILOT_MAX_ARGS; i++) {
            if (command_args[i]) free(command_args[i]);
        }
        return;

    }

    /* Check to see if a message was returned */
    if (*message) {

        /* Check if there was an error message
         * otherwise add a front and back to the message */
        if (message[0] == '!') {
            snprintf(reply, LBUF_SIZE, "ERROR: %s!", message + 1);
        } else {

            switch (Number(0, 20)) {
                case 0:
                case 1:
                case 2:
                case 4:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Affirmative, ",
                            message, ".");
                    break;
                case 5:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Nod, ",
                            message, ".");
                    break;
                case 6:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Fine, ",
                            message, ".");
                    break;
                case 7:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Aye aye, Captain, ",
                            message, "!");
                    break;
                case 8:
                case 9:
                case 10:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Da, boss, ",
                            message, "!");
                    break;
                case 11:
                case 12:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Ok, ",
                            message, ".");
                    break;
                case 13:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Okay, okay, ",
                            message, ", happy now?");
                    break;
                case 14:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Okidoki, ",
                            message, "!");
                    break;
                case 15:
                case 16:
                case 17:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Aye, ",
                            message, ".");
                    break;
                default:
                    snprintf(reply, LBUF_SIZE, "%s%s%s", "Roger, Roger, ",
                            message, ".");
                    break;
            } /* End of switch */

        } 

        auto_reply(mech, reply);

    } else if (!auto_cmds[cmd].silent) {

        /* Command isn't silent but it didn't return a message */
        snprintf(reply, LBUF_SIZE, "Ok.");
        auto_reply(mech, reply);

    }

    /* free args */
    for(i = 0; i < 2; i++) {
        if(args[i]) free(args[i]);
    }
    for (i = 0; i < AUTOPILOT_MAX_ARGS; i++) {
        if (command_args[i]) free(command_args[i]);
    }

}