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;