On Tue, 27 Mar 2007, Don Dailey wrote:
Would it be possible to publish a little library for others in C?
I will have a place on the main page to download goodies like this.
Here is the code I am currently using.
Christoph
/* ----------------------------------------------------------------------
*
* cgos.c -> client.c
*
* 2006-09-05 Christoph C. Birk ([EMAIL PROTECTED])
* CGOS (cgos.boardspace.net 6867) interface
* 2007-03-26 modified for new CGOS
*
* CGOS(pseudo-server) <-> Client <-> Engine(server)
*
* ---------------------------------------------------------------------- */
/*
* the engine calls 'cgos_run()' in a loop like this:
do {
i = cgos_run(goban,host,port,myName,myPassword);
if (i) sleep(30);
} while (i != 0);
*/
/* ---------------------------------------------------------------------- */
#ifdef NDEBUG /* release version */
#define DEBUG 0
#else
#ifndef DEBUG
#define DEBUG 1 /* debug level */
#endif
#endif
#define USE_CGOS3 /* use new CGOS protocol */
/* INCLUDEs ------------------------------------------------------------- */
#include <stdlib.h> /* atof() */
#include <stdio.h> /* sprintf() */
#include <string.h> /* strlen(),memset() */
#include <time.h> /* time() */
#include <unistd.h> /* close() */
#include <fcntl.h> /* fcntl() */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netdb.h> /* getprotobyname() */
#if 1 // my stuff
#include "gutils.h"
#include "evaluate.h"
#endif
/* DEFINEs -------------------------------------------------------------- */
#define PING_TIME 20 /* old CGOS only */
#define TOKSEP " \t"
/* EXTERNs -------------------------------------------------------------- */
extern int nsims;
/* function prototype(s) */
extern move_t genmove_1 (Goban*,int);
/* STATICs -------------------------------------------------------------- */
static int cgos_sock=-1;
/* function prototype(s) */
static int cgos_connect (const char*,u_short,const char*,const char*);
static void cgos_disconnect (void);
static int cgos_receive (char*,int);
static int cgos_send (const char*);
static int read_byte (int,char*,int);
/* ---------------------------------------------------------------------- */
int cgos_run(Goban* goban,const char* host,u_short port,
const char* name,const char* pass)
{
int i,r;
time_t next_ping,last_game,max_time=600;
char buffer[1024],*p;
r = cgos_connect(host,port,name,pass); if (r < 0) return(-1);
last_game = time(NULL);
next_ping = last_game + PING_TIME;
do {
r = cgos_receive(buffer,2000); if (r < 0) break;
if (r == 0) {
#ifndef USE_CGOS3
if (next_ping) { /* send ping ? */
if (time(NULL) > next_ping) {
cgos_send("ping");
next_ping = time(NULL)+PING_TIME;
}
}
#endif
} else
if (!strncmp(buffer,"newgame",7)) { int d; float k,t; /* old CGOS */
if (sscanf(buffer,"newgame %d %f %f\n",&d,&k,&t) == 3) {
komi = k;
time_left = t;
max_time = (int)t;
}
#if 1 // todo issue GTP commands here
goban_init(goban);
goban_show(goban,buffer);
#endif
last_game = time(NULL);
next_ping = 0;
} else
if (!strncmp(buffer,"setup",5)) { int id,d,t0; float k; /* new CGOS */
if (sscanf(buffer,"setup %d %d %f %d",&id,&d,&k,&t0) == 4) {
time_left = (float)t0/1000.0f; max_time = (int)time_left;
}
#if 1 // todo issue GTP commands here
goban_init(goban);
goban_show(goban,buffer);
#endif
last_game = time(NULL);
} else
if (!strncmp(buffer,"genmove",7)) { move_t move; /* genmove b 108584 */
#ifdef USE_CGOS3
for (i=1,p=strtok(buffer,TOKSEP); i<3; i++) p=strtok(NULL,TOKSEP);
if (p) {
time_left = (float)atof(p)/1000.0f;
#if (DEBUG > 0)
fprintf(stderr,"time_left= %.1f\n",time_left);
#endif
}
#endif
#if 1 // todo issue GTP commands here
move = genmove_1(goban,nsims);
goban_play_move(goban,move);
goban_show(goban,move_string(move));
#endif
cgos_send(move_string(move));
} else
if (!strncmp(buffer,"play",4)) { /* play w B8 93827 */
for (i=1,p=strtok(buffer,TOKSEP); i<3; i++) p=strtok(NULL,TOKSEP);
if (p) {
#if 1 // todo issue GTP command here
goban_play_move(goban,str2move(p));
goban_show(goban,p);
#endif
} else {
fprintf(stderr,"%s: unrecognized move\n",__FILE__);
}
} else
if (!strncmp(buffer,"time",4)) { /* old CGOS only */
for (i=1,p=strtok(buffer,TOKSEP); i<3; i++) p=strtok(NULL,TOKSEP);
if (p) {
time_left = (float)atof(p);
#if (DEBUG > 0)
fprintf(stderr,"time_left= %.1f\n",time_left);
#endif
}
} else
// todo 'gameover 2007-03-26 W+38.5 ' with USE_CGOS3
if (!strncmp(buffer,"gameover",8)) { float score;
#if 1 // todo GTP commmand here
score = score_board(goban->board,NULL,NULL);
fprintf(stderr,"my_score= %.1f\n",score);
#endif
sprintf(buffer,"/tmp/%s.terminate",name); /* exit program? */
if (!unlink(buffer)) { r = 0; break; }
next_ping = time(NULL) + PING_TIME;
#ifdef USE_CGOS3
cgos_send("ready"); /* stay for another game */
#else
cgos_send("ok"); /* stay for another game */
#endif
} else
if (!strncmp(buffer,"info",4)) { char *p; /* new CGOS only */
if ((p=strstr(buffer,"next round:")) != NULL) { int m,s;
if (sscanf(p,"next round: %d:%d",&m,&s) == 2) {
last_game = time(NULL) + m*60 + s;
}
}
} else {
fprintf(stderr,"unknown command from CGOS '%s'\n",buffer);
}
/* exit when no game is played for too long */
} while (time(NULL) < last_game+3*max_time);
cgos_disconnect();
return(r);
}
/* ---------------------------------------------------------------------- */
static int cgos_connect(const char* host,u_short port,
const char* name,const char* pass)
{
int r;
char buffer[1024];
struct hostent *hostp;
struct protoent *proto;
struct sockaddr_in saddr;
#if (DEBUG > 0)
fprintf(stderr,"cgos_connect(%s:%d,%s,%s)\n",host,port,name,pass);
#endif
hostp = gethostbyname(host); /* get host IP address */
if (hostp == NULL) return(-1);
proto = getprotobyname("tcp"); /* get protocol by name */
if (proto == NULL) return(-1);
memset((void*)&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons((u_short)port);
memcpy(&saddr.sin_addr,hostp->h_addr_list[0],hostp->h_length);
cgos_sock = socket(AF_INET,SOCK_STREAM,proto->p_proto);
if (cgos_sock < 0) return(-1);
(void)fcntl(cgos_sock,F_SETFD,FD_CLOEXEC); /* close connection on exec() */
r = connect(cgos_sock,(struct sockaddr *)&saddr,sizeof(saddr));
if (r == -1) {
(void)close(cgos_sock);
return(-1);
}
r = cgos_receive(buffer,5000); /* protocol */
#ifdef USE_CGOS3
if (r > 0) {
if (strcmp(buffer,"protocol")) r = -1;
else cgos_send("e1 myCtest");
}
if (r > 0) r = cgos_receive(buffer,5000); /* username */
#endif
if (r > 0) {
if (strcmp(buffer,"username")) r = -1;
else cgos_send(name);
}
if (r > 0) r = cgos_receive(buffer,5000); /* password */
if (r > 0) {
if (strcmp(buffer,"password")) r = -1;
else cgos_send(pass);
}
#ifndef USE_CGOS3
if (r > 0) r = cgos_receive(buffer,5000); /* successfull.. */
if (r > 0) {
if (strncmp(buffer,"succe",5)) r = -1;
}
#endif
if (r <= 0) { cgos_disconnect(); return(-1); }
return(0);
}
/* ---------------------------------------------------------------------- */
static void cgos_disconnect(void)
{
#if (DEBUG > 0)
fprintf(stderr,"cgos_disconnect(%d)\n",cgos_sock);
#endif
if (cgos_sock > 0) { close(cgos_sock); cgos_sock = -1; }
}
/* ---------------------------------------------------------------------- */
static int cgos_receive(char* answer,int timeout)
{
int i,r;
char c=0;
char buffer[1024];
*answer = '\0'; /* preset 'answer' */
r = read_byte(cgos_sock,&c,timeout);
if (r <= 0) return(r);
buffer[0] = c; i = 1;
do {
if (read_byte(cgos_sock,&c,timeout+5000) <= 0) break;
if (c == 0x0d) continue; /* <CR> */
if (c == 0x0a) break; /* <LF> */
buffer[i] = c; i++;
} while (i < sizeof(buffer)-1);
buffer[i]= '\0';
#if (DEBUG > 0)
fprintf(stderr,"CGOS-> '%s'\n",buffer);
#endif
strcpy(answer,buffer);
return (i);
}
/* ---------------------------------------------------------------------- */
static int read_byte(int sock,char* c,int timeout) /* timeout (ms) */
{
int r;
fd_set rfd;
struct timeval tout;
do { /* wait for byte */
FD_ZERO(&rfd);
FD_SET(sock,&rfd);
tout.tv_sec = timeout/1000; tout.tv_usec = (timeout*1000) % 1000000;
r = select(sock+1,&rfd,NULL,NULL,&tout);
if (FD_ISSET(sock,&rfd)) break;
} while (r > 0);
if (r <= 0) return(r);
r = recv(sock,c,1,0); /* read byte */
if (r <= 0) return(-1);
return(r);
}
/* ---------------------------------------------------------------------- */
static int cgos_send(const char *text)
{
char message[1024];
#if (DEBUG > 0)
fprintf(stderr,"cgos_send(%s)\n",text);
#endif
sprintf(message,"%s\n",text);
if (send(cgos_sock,message,strlen(message),0) == -1) return(-1);
return(0);
}
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
_______________________________________________
computer-go mailing list
[email protected]
http://www.computer-go.org/mailman/listinfo/computer-go/