Eris

From ASSS Wiki
Jump to: navigation, search

Eris's bot

Eris, a sysop of Alpha for the longest time, created his own bot core. His was the second bot created for SubSpace, the first being PriitK's bot system which has never been released to anyone.

Eris's bots were originally used in Alpha for fun little projects for himself, but then were extended and handed out to a few other programmers. The most famous bots that used Eris's core were the Pro League bots, which up until 2004 were still running the same software for the most part.

His bot core couldn't do much, as it was very basic, but what it could do, it did well. The core was very stable and ran without errors, and for the most part, was even able to handle some bot code crashes with exception handling. This lead to lazier programming, which showed with some bots being very unstable.

bot.h

// Header for implementing behaviors
// Very early draft 1/24/00 by eris

// I am certain this will change, so don't go nuts writing behaviors
// but the basic layout should remain similar...

// This header should not be modified, as its used in the bot core as well

// Things in particular you shouldn't add because they'll be added to the
// bot core:

// Commands: I plan to parse commands in the core so every behavior won't
// repeat the same work. This will also include some sort of help system.

// BotOp: The BotOp password, etc. will be handled in the core.

// Info: *info will be handled by the core (at the behavior's request) so
// the data is easily managed and multiple behaviors don't *info the same
// person over and over... (unless they need an updated lag report or
// something)

// Ignoring: I will provide an ignore feature the behaviors can call. It
// will have 2 modes, loose and strict. Loose is just ignore by name, while
// strict will ignore by name, IP, and machine ID.


// -- snip -- Code starts here

#ifndef BOT_H
#define BOT_H

// this is the only function a behavior has to implement:
// extern "C" __declspec (dllexport) void CALLBACK BOT_Cmd(BOTCMD *bc);


#define MAXUSERS 500
#define MAXBEHAVIORS 50

typedef struct {
  // This data should always be accurate
  char   Name[32];
  char   Squad[32];      //nyi
  int    Wins;           //nyi
  int    Losses;         //nyi
  int    Points;         //nyi
  int    Rating;         //nyi

  char   Lastship;       // 1-8 for ships, 0 for spec - Only valid on
                         // BOTCMD_ShipChange
  char   Shiptype;       // 1-8 for ships, 0 for spec
  
  // This data is updated only periodically when requested
  // and should only be used in response to MSG_SPECINFO
  short  Bounty;         //nyi
  int    XCoord;         //nyi
  int    YCoord;         //nyi
  char   ShipDirection;  //nyi
  short  Energy;         //nyi
  char   Flags;          //nyi
  char   HasBall;        //nyi

  // This data is updated only periodically when requested and should be used
  // only in response to MSG_USERINFO. Some of the info like IP and MID
  // will remain constant if looked at even once, so IsKnown is set to true
  // if we have this info...
  char   IsKnown;        //nyi
  int    MID;            //nyi
  short  LastFreq;       // Only valid on BOTCMD_FreqChange
  short  Freq;
  char   IP[16];         //nyi
  short  AvePing,CurPing,MinPing,MaxPing;  //nyi
  short  S2CPloss,C2SPloss; //nyi
  // *todo* There's plenty of other info in a *info we can grab

  // This field is updated whenever this structure is sent to a behavior
  // and is read and stored upon return. It is the only data field that
  // is not read only. A behavior may ignore this, or use it however it
  // wants to store data.
  void*  Ptr;

  // This data is for internal use and should not be messed with at all.
  char   IsValid;
  short  UID;
  char   SpecCnt;                  //nyi
//char   SpecList[MAXBEHAVIORS];   //nyi
  char   InfoCnt;                  //nyi
//char   InfoList[MAXBEHAVIORS];   //nyi
  int    PtrList[MAXBEHAVIORS];    //nyi
  char   IsBotOp;                  //nyi
  short  IgnoreTime;               // in minutes      // nyi
  int    IgnoredAt;                //nyi

} USER_DATA;



typedef struct {
  int   Msg;           // One of the #define BOTMSG_

///// used for BOTMSG_Line ////////////////////////////////////////////////////
  short uid;           // user ID if its a private message
  short LineType;      // Line Type
  char  *Line;         // pointer to text
  char  Sound;         // 0 for no sound, otherwise sound #

///// used for BOTMSG_Register ////////////////////////////////////////////////
  char *Cmd;           // String of command including !
  char OpOnly;         // Is the command for ops only?
  char *HelpFile;      // Help Filename for this command
  int  CmdID;          // CmdID - The bot core doesn't care about this,
                       // the behavior should use it to uniquely identify
                       // this command.

} BOTMSG;

typedef struct {
  int Cmd;  // One of the #define BOTCMD_

///// used for BOTCMD_Init ////////////////////////////////////////////////////
  HWND hwnd;   // Window handle to send messages
  char BehaviorID;  // Your Behavior's ID, save this, you need to send it
                    // with every BOT_MSG

///// used for all commands that have user data (except kills) ////////////////


  // This is read only with the single exception of Ptr, which
  // is a Ptr to info for this user for this behavior. Ptr is
  // maintained independantly for each behavior and may contain
  // anything the behavior wants    
  USER_DATA *UserData;

///// used for BOTCMD_Kill ////////////////////////////////////////////////////
  USER_DATA *Killed;
  USER_DATA *Killer;
  short     Bounty;

///// used for BOTCMD_Line ////////////////////////////////////////////////////
  char  *Line;
  short LineType;   // see #define LINETYPE_

///// used for BOTCMD_Cmd /////////////////////////////////////////////////////
  char *CmdStr;  // the text of the command - should use CmdID, its faster
  char *Params;  // parameters of the command
  int  CmdID;    // the command ID the behavior registered for this command

///// used for all commands except BOTCMD_Init ////////////////////////////////

  USER_DATA *UserList;   // This is the list of all users.
                         // Its an array of USER_DATA of size MAXUSERS.
                         // Only records with UserList[i].IsValid==TRUE
                         // are valid users. ALL THIS DATA IS READ ONLY
                         // AND ONLY ACCURATE FOR THIS MESSAGE. COPY
                         // ANYTHING YOU NEED LONG TERM.



} BOTCMD;


// To send messages to the bot, use SendMessage with a message of WM_BOT,
// wparam set to your BotID, and lparam set to the pointer to the message.
// DO NOT USE POSTMESSAGE. The message structure is copied and may be
// reused after SendMessage has completed

#define WM_BOT            0x423
#define BOTMSG_Line       0  // Send a message
#define BOTMSG_Register   1  // Register a command
#define BOTMSG_LineSound  2  // Send a message with a sound

#define BOTCMD_Init       0
#define BOTCMD_Entered    1
#define BOTCMD_Left       2
#define BOTCMD_Kill       3
#define BOTCMD_Line       4
#define BOTCMD_Shutdown   5
#define BOTCMD_Command    6
#define BOTCMD_Arena      7  // changing arenas, forget everything you know
                             // Arena name is in "Line" and is "" for pub
#define BOTCMD_Tick       8  // called every 50ms or so
#define BOTCMD_Shipchange 9
#define BOTCMD_FreqChange 10

// *todo* chat, squad, rederror
#define LINETYPE_Pub         2
#define LINETYPE_Macro       1
#define LINETYPE_Team        3
#define LINETYPE_AnyTeam     4
#define LINETYPE_Private     5
#define LINETYPE_CrossZone   7  // does not have user data
#define LINETYPE_Arena       0  // does not have user data
#define LINETYPE_Chat        9  // does not have user data
#define LINETYPE_SysopMsg    8  // does not have user data

#endif

example.cpp

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <windowsx.h>
#include <winuser.h>
#include "bot.h"

// this is a simple example for the PB guys
// please understand this is very prealpha right now :)

// These 2 variables are passed to the behavior from the bot in the
// BOTCMD_Init, which is always the first command a behavior will get.

HWND hwnd;  // handle of the main bot window. This is used when
            // SendMessage is called to pass a message to the bot.

int ID;     // This is your assigned behavior ID, you need to pass
            // this when sending the bot core messages


void SendPriv(int uid, char *str);
void SendPub(char *str);

// this is the function the bot calls for every event
extern "C" __declspec (dllexport) void CALLBACK BOT_Cmd(BOTCMD *bc) {
  BOTMSG bm;
  char str[500];
  static int enabled;

  switch (bc->Cmd) {
    case BOTCMD_Init: 
      // always include these 2 lines, you need this data for sending
      // messages back to the bot
      hwnd=bc->hwnd;
      ID=bc->BehaviorID;

      // this is how you register a bot command, set OpOnly to 0 if the
      // command is public, else 1. CmdID should be unique for
      // every command you register (unless you want 2 commands to
      // do the same thing).

      bm.Msg=BOTMSG_Register;
      strcpy(str,"!enable");
      bm.CmdID=1;
      bm.Cmd=str;
      bm.OpOnly=1;
      bm.HelpFile=NULL;
      SendMessage(hwnd,WM_BOT,ID,(int)(&bm));

      bm.Msg=BOTMSG_Register;
      strcpy(str,"!disable");
      bm.CmdID=2;
      bm.Cmd=str;
      bm.OpOnly=1;
      bm.HelpFile=NULL;
      SendMessage(hwnd,WM_BOT,ID,(int)(&bm));

      // that was also an example of how to send the bot a message
      // NEVER use PostMessage to send a message to the bot

      enabled=0;

      break;
    case BOTCMD_Command:
      // this processes !commands you have registered
      if (bc->CmdID==1) { // !enable
        enabled=1;
      } else if (bc->CmdID==2) { // !disable
        enabled=0;
      }
      break;
    case BOTCMD_Entered:
      if (enabled)
        SendPriv(bc->UserData->UID,"Welcome to Powerball!");
      break;
    case BOTCMD_Line:
      if (enabled)
        if (bc->LineType==LINETYPE_Pub)
          if (!strcmp(bc->Line,"Powerball"))
            SendPub("rules!");
      break;
  }
}


void SendPub(char *str) {
  BOTMSG bm;

  bm.Msg=BOTMSG_Line;
  bm.uid=0;
  bm.Line=str;
  bm.LineType=LINETYPE_Pub;
  SendMessage(hwnd,WM_BOT,ID,(int)(&bm));
}


void SendPriv(int uid, char *str) {
  BOTMSG bm;

  bm.Msg=BOTMSG_Line;
  bm.uid=uid;
  bm.Line=str;
  bm.LineType=LINETYPE_Private;
  SendMessage(hwnd,WM_BOT,ID,(int)(&bm));
}

Undoc.h

#ifndef UNDOC_H
#define UNDOC_H

// undocumented bot commands

#define BOTMSG_Arena -1  // changes arenas to the arena in BOTMSG.Line

#endif