Wednesday, October 9, 2013

Easybot Source

http://web.archive.org/web/20040914010300/http://pages.videotron.com/sst/



Starship Traders Resource Site

Your source for TLR and TLF





/*******************************************************************************
*
* easybot V1.0 Utilising the sst structure and modified readnet routine from
*               Kat's sst client.  The free LCC compiler is used for compiling
*               source on windows machine, while gcc is used on linux platform.
*               This is a demonstration program for making a client connection.
*
* Copyright (C) 2005 Brian Estabrooks
*
* Comments can be sent to: sstdevelopment@videotron.ca
*
* Visit my Starship Traders Resource Site for updates and source code
* at http://pages.videtron.com/sst
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License. Full license
* can be found in gpl.txt
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Portions of code based on Kirellii.c
* (Adapted/Modified by David Johnson)
*
* Kirellii.c, copyright 2003, David Johnson
* this software is released under the terms
* of the GPL v.2.  See http://www.gnu.org/
* for details and a copy of the license.
*
* Which is based on:
* sst graphical client, vsn 0.12 (5/31/2001)
* --- sst.c, copyright 2001, Ray Yeargin ---
* this software is released under the terms
* of the GPL v.2.  See http://www.gnu.org/
* for details and a copy of the license.
*
*******************************************************************************/

#ifdef _WIN32

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <winsock2.h>

WSADATA *WsaData;

/* closesocket() is required to close a socket in windows */

#define close(x) (closesocket((x)))

#else

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

/* Linked on linux using: gcc -Wall -o easybot easybot.c */

#endif

/*****************************************************************************/
int socfd;

void myInit(void);

void readnet(void);
void get_buff(void);

void sendcommand(char *string);
void sendstring(char *string);
void sendnumber(unsigned long number);

int login(char *name, char *pass);
void logout(void);

#define TIMEOUT 630

/******************************************************************************
* Kat's defines
******************************************************************************/

#define TEST_IP "192.168.0.18"
#define TEST_PORT 4022         /* starshiptraders.com port 1222 4022 */
#define DEST_PORT_COC 1222 /* Continuum of Chaos Game old SST port */

//#define DEST_IP "199.44.248.254"

#define DEST_IP "69.55.229.31" // ioresort.com
#define DEST_PORT_TLF 1866     // ioresort.com port The Last Frontier Game
#define DEST_PORT_TLR  666 // ioresort.com port The Last Resort Game

/******************************************************************************
* Kat's globals
******************************************************************************/

unsigned char inbuf[65536];

/******************************************************************************
* Bot globals
******************************************************************************/

char lineout[100];

FILE *lp; // pointer to the log file if used

int hotkeys=1,exitgame=0;

// *****************************************************************************
struct sectorlayout
{
  unsigned char head; // 239,240,...
  unsigned char headx; //
  unsigned char heady; //
  unsigned char headz; //
  struct flaglayout1 // miscellaneous flags to be renamed, used as needed
  {
      //ooops... 0, every eighth bit after must be unused to avoid tripping trailer byte!
      unsigned int unused1:1; //avoid tripping trailer byte check

      unsigned int statmod:1;
      unsigned int scooper:1;
      unsigned int plfinder:1;
      unsigned int supercomp:1;
      unsigned int scoutl:1;
      unsigned int scanner:1;
      unsigned int orbiter:1;

      unsigned int unused9:1;

      unsigned int navmod:1;
      unsigned int tractor:1;
      unsigned int hdlauncher:1;
      unsigned int f13:1;
      unsigned int yesno:1;
      unsigned int inteam:1;
      unsigned int incomm:1;

      unsigned int inpref:1;

      unsigned int onplanet:1;
      unsigned int inhwdepot:1;
      unsigned int ingreenport:1;
      unsigned int inrockmine:1;
      unsigned int intradingpost:1;
      unsigned int autopilot:1;
      unsigned int fixed:1;

      unsigned int inmessage:1;

      unsigned int nudgewarp:1;
      unsigned int inmenu:1;
      unsigned int inatakmenu:1;
      unsigned int inbunker:1;
      unsigned int inradio:1;
      unsigned int radio:1;
      unsigned int news:1;
      } flags;
  unsigned char type; // sector type... 0,1,3 ... 1=Nebula, 3=Black Hole x-3=Starbase #
  unsigned char porttype; // 0,1,2,3,4  (0 for none, 1 for rockmine, 2 for greenport, 3 for hardware, 4 for tradingpost?)
  unsigned char bcode; // 0,253,254
  unsigned char fcode; // 0,253,254

  unsigned char galnumb; // 1-255
  unsigned char debris; // 0-255
  unsigned char worm; // count ... read # times worm struct in loop:
  unsigned char planet; // 1==planet here

  //unsigned char fownername[25]; // 0 or 1 of these
  unsigned char shiptype; //0-18
  unsigned char shields;  //shields, 0-10
  unsigned char ccs;      //combat computers, 0-10
  unsigned char boosters; //0-25

  unsigned char hdevices; //0-25
  unsigned char ssttlr; //0-1... 0=Space, 1=TLR World
  unsigned char sparec2;
  unsigned char sparec3;

  unsigned int  myfighters; // fighters with ship

  unsigned short mynumber; // player number of player
  unsigned short spares0; // spare short int

  unsigned char sparec0[12]; // more spares...

  unsigned char portletter[6];//a-z, A-Z, $, ^, *, blank
  unsigned char sparec4[2];// spare chars
  unsigned char sign[20]; // empty or sector beacon
  signed short portprod[3]; // commodity productivities of port
  unsigned short ship; // count ... read # times ship struct in loop:
  signed short planprod[3]; // commodity productivities of planet
  unsigned short sauthor; // owner of graffiti -- for kill purposes
  unsigned short fowner; // owner of fighters/starbase in sector
  unsigned short spares; // spare short int
  unsigned long warp[6]; // hard warps 1-6 to other sectors
  unsigned long fighters; // number of fighters deployed in sector
  unsigned long number; // sector number
  unsigned long anti; // antimatter left
  unsigned long cash; // cash on hand
  unsigned char iron; // iron in holds
  unsigned char alc; // alcohol in holds
  unsigned char eqp; // hardware / equipment in holds
  unsigned char holds; // spare short int
}
sstsector; // 136 bytes long

// *****************************************************************************
struct shiplayout // loaded by loop of reads
{
  unsigned short size;
  unsigned short number;
  unsigned short holds;
  unsigned char ccs;
  unsigned char shields;
}
sstship[256];
// 8 (56?) bytes long (14K total?) ... eventually, this needs to occur more
// since up to 1600 ships(!) can be in a single sector

// *****************************************************************************
struct sstwormlayout // loaded by loop of reads
{
  unsigned long destin;
  unsigned long origin;
  unsigned long type;
}
sstworm[28];
// 12 bytes long
//  (eventually, this won't be an array, but will be looped through

// *****************************************************************************
void myInit()
{
  struct sockaddr_in dest_addr;

#ifdef _WIN32
  unsigned long data=1; // Value other than 0 will set socket to non-blocking
#endif

  if(socfd) close(socfd);

  printf("\nConnecting...\n");
  socfd=socket(AF_INET, SOCK_STREAM, 0);

#ifndef _WIN32
  fcntl(socfd, F_SETFL, O_NONBLOCK);
#else
  ioctlsocket(socfd, FIONBIO, &data); // Changes socket to non-blocking
#endif

  dest_addr.sin_family= AF_INET;
  dest_addr.sin_port= htons(DEST_PORT_TLR);

#ifdef TEST
  dest_addr.sin_addr.s_addr= inet_addr(TEST_IP);
#else
  dest_addr.sin_addr.s_addr= inet_addr(DEST_IP);
#endif

  memset(&(dest_addr.sin_zero),'\0',8);
  connect(socfd,(struct sockaddr *)&dest_addr,sizeof(struct sockaddr));
}

#ifdef _WIN32
/*<---------------------------------------------------------------------->*/
/* --- The following code comes from g:\lcc\lib\wizard\tcpini.tpl. */
// WSADATA *InitWS2(void)
// Routine Description:
//
// Calls WSAStartup, makes sure we have a good version of WinSock2
//
//
// Return Value:
//  A pointer to a WSADATA structure - WinSock 2 DLL successfully started up
//  NULL - Error starting up WinSock 2 DLL.
//
WSADATA *InitWS2(void)
{
  int           Error;              // catches return value of WSAStartup
  WORD           VersionRequested;   // passed to WSAStartup
  static WSADATA WsaData;            // receives data from WSAStartup
  BOOL           ReturnValue = TRUE; // return value flag

  // Start WinSock 2.  If it fails, we don't need to call
  // WSACleanup().
  VersionRequested = MAKEWORD(2, 0);
  Error = WSAStartup(VersionRequested, &WsaData);
  if (Error) {
      fprintf(stderr,"Could not find high enough version of WinSock");
      ReturnValue = FALSE;
  } else {

      // Now confirm that the WinSock 2 DLL supports the exact version
      // we want. If not, make sure to call WSACleanup().
      if (LOBYTE(WsaData.wVersion) != 2) {
        fprintf(stderr,"Could not find the correct version of WinSock");
        WSACleanup();
        ReturnValue = FALSE;
      }
  }
  if (ReturnValue)
      return &WsaData;
  return(NULL);

} // InitWS2()
#endif

// *****************************************************************************
void readnet()
{
  static int nlen=0;
  int bytesin=0,blen=0,ilen=0,slen=0,stop=0,termflag=241;
  time_t stime,etime;

  while(1) {
    stime = time(NULL);
    do {
      bytesin=recv(socfd,&inbuf[slen],65534-slen,0);
      if(bytesin>0) {
        slen+=bytesin;
        termflag=(int)inbuf[slen -1];
      }
      if(slen>=65534) {
        printf("readnet:Buffer overflow occured...\n");
        break;
      }
      etime = time(NULL) - stime;
      if(etime > TIMEOUT) {
        printf(" Timeout has occurred\n");
        exitgame = 1;
        stop = 1;
        break;
      }
    }
    while (termflag!=241);

    // This will log everything to a file
    if(lp && (slen-blen)) fwrite(&inbuf[blen],sizeof (char),slen-blen,lp);
    blen = slen;
    inbuf[slen]=0;

    if(slen) {
      while(ilen<slen) {
        while(inbuf[ilen] && inbuf[ilen]!=13 && nlen<98 &&
              inbuf[ilen]!=240 && inbuf[ilen]!=239) { // escape codes here...
          if (inbuf[ilen]==8) { // Backspace code

            ilen++;
            if (nlen>0) nlen--;
          } else if (inbuf[ilen]<239 && inbuf[ilen]>31) // escape code lower limit and control codes

            lineout[nlen++]=inbuf[ilen++];
          else
            ilen++;
        }
        lineout[nlen] = '\0';
        if(inbuf[ilen]==240) { //sstsector struct follows.
          if ((slen-ilen) < 136) {
            printf(" Read error: sstsector struct(%d) \x7",slen-ilen);
            break;
          }
          memcpy(&sstsector,&inbuf[ilen],sizeof(sstsector));
          ilen+=sizeof(sstsector);
          if(sstsector.ship) {
            if((slen-ilen) < (8*sstsector.ship)) break;
            memcpy(&sstship[0],&inbuf[ilen],8*sstsector.ship);
            ilen+=8*sstsector.ship;
          }
          if(sstsector.worm) {
            if((slen-ilen) < (12*sstsector.worm)) break;
            memcpy(&sstworm[0],&inbuf[ilen],12*sstsector.worm);
            ilen+=12*sstsector.worm;
          }
          stop = 1;
        } else if (inbuf[ilen]==239) { // nonsector struct follows...
          if ((slen-ilen) < 8) break;
          memcpy(&sstsector,&inbuf[ilen],sizeof(sstsector.flags)+4);
          ilen+=sizeof(sstsector.flags)+4;
          stop = 1;
        } else {
          if (inbuf[ilen]==0 || inbuf[ilen]==13) ilen++;
          //if (inbuf[ilen]==13)
          nlen = 0;
          //printf("%s\n",lineout);
        }
      }
    }
    if(stop || exitgame || slen >=65534) break;
    termflag = 0;
  }
}

// *****************************************************************************
void get_buff() //this will keep reading until something is read

{
  do {
    readnet();
  }
  while(!(strlen(inbuf)));
}

/******************************************************************************
* It's very important to send only one command at a time to server otherwise
* the bot will get stuck waiting in the get_buff or you will not be testing
* for the correct prompt when checking the lineout string.  When you return
* from this function, lineout should contain the prompt for current condition
* of bot on the server.  If hotkeys is not enabled, append return to execute
* command.  Be sure to set hotkeys variable to 0, if you have hotkeys turned
* off for your ship.  The default for new ships in the game is hotkeys on, so
* hotkeys is set to 1 in this code.
*
******************************************************************************/
void sendcommand(char *string)
{
  char command[128];
  int len;

  if(hotkeys) {
    len = strlen(string);
    send(socfd,string,len,0);
  } else {
    sprintf(command,"%s\r",string);
    len = strlen(command);
    send(socfd,command,len,0);
  }
  get_buff();
}

// *****************************************************************************
void sendstring(char *string)
{
  char command[128];
  int len;

  sprintf(command,"%s\r",string);
  len = strlen(command);
  send(socfd,command,len,0);
  get_buff();
}

// *****************************************************************************
void sendnumber(unsigned long number)
{
  char command[128];
  int len;

  sprintf(command,"%lu\r",number);
  len = strlen(command);
  send(socfd,command,len,0);
  get_buff();
}

/******************************************************************************
* login returns -1 if error, 0 if everything is ok
******************************************************************************/
int login(char *name, char *pass)
{
  myInit();
  get_buff();

  exitgame = 0;
  printf("Logging in...\n");
  sendstring(name);
  // Please enter your password:
  if(strncmp(lineout,"Please",6) == 0) {
    sendstring(pass);
    if(strncmp(lineout,"Please",6) == 0) {
      printf("Invalid password entered for: %s\n",name);
      return -1;
    }
  } else {
    // BART is not in my files -- are you a new user?  (Y/N) [N]
    printf("%.*s\n\n",strlen(lineout)-34,lineout);
    return -1;
  }

  // Handle events (required if you don't enter messages upon login)
  while(strncmp(lineout,"Press (Enter) to continue:",26) == 0)
    sendstring("");

  if(strncmp(lineout,"(Conf",5) == 0) { // In comm menu?
    sendcommand("G"); // Enter game
  }

  // Handle events (required if you enter messages upon login)
  while(strncmp(lineout,"Press (Enter) to continue:",26) == 0)
    sendstring("");

  return 0;
}

// *****************************************************************************
void logout()
{
  printf("Logging out...\n");
  if(hotkeys) sendcommand("QY"); /* Exception to single command sent */

  close(socfd); /* Just closing the socket will also work for logging out */
}

// *****************************************************************************
int main(int argc,char *argv[])
{
  char logname[30];

  if(argc < 3) {
    printf("\nUsage : %s name password\n",argv[0]);
    return 1;
  }

#ifdef _WIN32
  WsaData = InitWS2();
  if(WsaData == NULL)
    return 0;
#endif

  sprintf(logname,"%s.000",argv[1]);
  lp = fopen(logname,"wb");

  login(argv[1],argv[2]);

  logout();

  if(lp) fclose(lp);

#ifdef _WIN32
  WSACleanup();
#endif

  return 0;

No comments:

Post a Comment