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
computer-go@computer-go.org
http://www.computer-go.org/mailman/listinfo/computer-go/

Reply via email to