Logo Search packages:      
Sourcecode: teg version File versions  Download package

helper.c

/*    $Id: helper.c,v 1.9 2002/09/13 00:58:48 riq Exp $     */
/* Tenes Empanadas Graciela
 *
 * Copyright (C) 2000 Ricardo Quesada
 *
 * Author: Ricardo Calixto Quesada <rquesada@core-sdi.com>
 *
 * 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; only version 2 of the License
 *
 * 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.
 */
/*
 * helper functions used by play*
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>

#include "server.h"
#include "fow.h"
#include "my_inet_ntop.h"

static char colors[TEG_MAX_PLAYERS];

#ifdef MACOSX
      #define socklen_t int
#endif

/* initialize the colors */
void color_init()
{
      memset( colors, 0, sizeof(colors));
}

/* frees on color */
void color_del( int i )
{
      colors[i]=0;
}

/* sets and set if the color is free */
BOOLEAN color_libre( int *color )
{
      int i;
      if( (*color) < 0 || (*color) > (TEG_MAX_PLAYERS-1) )
            return FALSE;
      if( colors[*color]==0 ) {
            colors[*color]=1;
            return TRUE;
      }
      /* tries to find a free color */
      for(i=0;i<TEG_MAX_PLAYERS;i++) {
            if( colors[i]==0 ) {
                  colors[i]=1;
                  *color = i;
                  return TRUE;
            }
      }
      return FALSE;
}

/* tells which colors are availables */
TEG_STATUS colores_libres( char *c )
{
      int i;
      for(i=0;i<TEG_MAX_PLAYERS;i++) {
            c[i] = colors[i];
      }
      return TEG_STATUS_SUCCESS;
}

/* order-insert a char in a array */
void ins_orden( char d, char *array, int len )
{
      int i,j;

      for( i=0;i < len ; i++ ) {
            if( d > array[i] )
                  break;
      }
      if(array[i] == 0) {
            array[i] = d;
            return;
      }
      j=i;
      for( i=len-1; i>j; i--)
            array[i] = array[i-1];
      array[j]=d;
}

/* Validates the total number of armies placed */
TEG_STATUS aux_token_fichas( int fd, char *str, int maximo, unsigned long conts )
{
      PARSER p;
      DELIM igualador={ ':', ':', ':' };
      DELIM separador={ ',', ',', ',' };
      PSPLAYER j;
      int fichas,country,cant,real;
      char *copia;
      int cptr[CONT_CANT];                /**< continent ptr */
      
      if( player_whoisfd(fd, &j) != TEG_STATUS_SUCCESS )
            goto error;

      if( g_game.turno != j )
            goto error;

      if( strlen(str)==0 )
            goto error;

      copia = str;

      p.igualador = &igualador;
      p.separador = &separador;
      p.data = str;

      memset( cptr, 0, sizeof(cptr));
      fichas=0;
      real=0;

do_real:
      do {
            if( parser_call( &p )) {

                  country = atoi( p.token );          
                  cant = atoi( p.value );       

                  if( country<0 || country >= COUNTRIES_CANT || cant<0 ||
                        cant+fichas > maximo || g_countries[country].numjug != j->numjug ) {
                        goto error;
                  }

                  /* cuando real==1 se asignas los ejercitos, sino hace el test */
                  if(real) {
                        g_countries[country].ejercitos += cant;
                        j->tot_armies += cant;
                  }

                  if( conts )
                        cptr[ g_countries[country].continente ] += cant;

                  fichas += cant;
            } else {
                  goto error;
            }

      } while( p.hay_otro );

      if( fichas != maximo ) {
            goto error;
      }

      /* Did I have to place armies in continents ? */
      if( conts ) {
            unsigned long conts_tmp = conts;
            int i;

            for(i=0;i<CONT_CANT;i++) {
                  if( conts_tmp & 1 ) {
                        if( cptr[i] < g_conts[i].fichas_x_cont ) {
                              goto error;
                        }
                  }
                  conts_tmp >>= 1;
            }
      }

      if(real==0) {
            fichas=0;
            real=1;
            memset( cptr, 0, CONT_CANT);
            p.data = copia;
            goto do_real;
      }

      return TEG_STATUS_SUCCESS;
error:
      return TEG_STATUS_PARSEERROR;
}


/* simulates the attack between 2 countries telling the result of the dices */
TEG_STATUS aux_token_attack( int src, int dst, int *src_lost, int *dst_lost, char *dados_src, char *dados_dst )
{
      int i,tmp;
      char src_d[4];
      char dst_d[4];

      memset( src_d,0,sizeof(src_d));
      memset( dst_d,0,sizeof(dst_d));

      (*dst_lost) = 0;
      (*src_lost) = 0;

      if( dst > 3 ) dst =3 ;
      src--;
      if( src > 3 ) src = 3;

      for(i=0;i<src;i++) {
            tmp = RANDOM_MAX(1,6);
            ins_orden( (char) tmp, src_d, 3 );
      }

      for(i=0;i<dst;i++) {
            tmp = RANDOM_MAX(1,6);
            ins_orden( (char) tmp, dst_d, 3 );
      }

      for(i=0; i< 3 && src_d[i]!=0 && dst_d[i]!=0; i++ ) {
            if(src_d[i] > dst_d[i])
                  (*dst_lost)++;
            else
                  (*src_lost)++;
      }
      memcpy( dados_src, src_d, 3);
      memcpy( dados_dst, dst_d, 3);

      return TEG_STATUS_SUCCESS;
}

/* generates the status in a given array */
TEG_STATUS aux_token_stasta(char *strout, size_t len )
{
      int n;
      char strtmp[ PLAYERNAME_MAX_LEN + 200];

      PLIST_ENTRY l = g_list_player.Flink;
      PSPLAYER j;

      strout[0]=0;

      n=0;
      while( !IsListEmpty( &g_list_player ) && (l != &g_list_player) ) {
            j = (PSPLAYER) l;

            if( j->is_player ) {
                  int color = (j->color==-1) ? TEG_MAX_PLAYERS : j->color;
                  if(n==0) {
                        snprintf(strtmp,sizeof(strtmp)-1,"%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s"
                                    ,j->name
                                    ,color
                                    ,j->player_stats.score
                                    ,j->numjug
                                    ,j->estado
                                    ,(! g_game.fog_of_war) ? j->tot_countries : -1
                                    ,(! g_game.fog_of_war) ? j->tot_armies : -1
                                    ,j->tot_cards
                                    ,(g_game.empieza_turno && (g_game.empieza_turno->numjug==j->numjug))
                                    ,j->human
                                    ,j->addr );
                        n=1;
                  } else 
                        snprintf(strtmp,sizeof(strtmp)-1,"/%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s"
                                    ,j->name
                                    ,color
                                    ,j->player_stats.score
                                    ,j->numjug
                                    ,j->estado
                                    ,(! g_game.fog_of_war) ? j->tot_countries : -1
                                    ,(! g_game.fog_of_war) ? j->tot_armies : -1
                                    ,j->tot_cards
                                    ,(g_game.empieza_turno && (g_game.empieza_turno->numjug==j->numjug))
                                    ,j->human
                                    ,j->addr );

                  strtmp[ sizeof(strtmp) -1 ] = 0;

                  strncat( strout, strtmp, len - strlen(strout) );
            }

            l = l->Flink;
      }
      return TEG_STATUS_SUCCESS;
}


/* find by random a country */
PCOUNTRY get_random_country( get_random_func func )
{
      int i;

again:
      i = RANDOM_MAX(0,COUNTRIES_CANT-1);
      if( func(i) )
            return &g_countries[i];
      else {
            int r = RANDOM_MAX(0,2);
            switch(r) {
                  /* search going down */
                  case 0:
                        for(;i>=0;i--) {
                              if( func(i) )
                                    return &g_countries[i];
                        }
                        for(i=COUNTRIES_CANT-1;i>=0;i--) {
                              if( func(i) )
                                    return &g_countries[i];
                        }
                        PDEBUG("uncountryelibre(down): Abnormal error\n");
                        break;
                  /* search going up */
                  case 1:
                        for(;i<COUNTRIES_CANT;i++) {
                              if( func(i))
                                    return &g_countries[i];
                        }
                        for(i=0;i<COUNTRIES_CANT;i++) {
                              if( func(i))
                                    return &g_countries[i];
                        }
                        PDEBUG("uncountrylibre(up):Abnormal error\n");
                        break;
                  /* search again */
                  case 2:
                  default:
                        goto again;
            }
      }

      /* to prevent warnings at compile time */
      return &g_countries[0];
}

/* Sends the player the total number of armies it must place, and the continents he has conquered */
TEG_STATUS aux_token_fichasc( PSPLAYER pJ )
{
      unsigned long conts=0;
      int armies;
      int x_canje=0;

      assert( pJ );

      if( pJ->fichasc_armies ) {
            conts = pJ->fichasc_conts;
            armies = pJ->fichasc_armies;
      } else {
            if( player_listar_conts( pJ, &conts ) != TEG_STATUS_SUCCESS )
                  return TEG_STATUS_UNEXPECTED;
            armies = player_fichasc_cant( pJ );

            pJ->fichasc_conts = conts;
            pJ->fichasc_armies = armies;
      }

      if( pJ->hizo_canje )
            x_canje = cuantos_x_canje( pJ->tot_exchanges );

      pJ->estado = PLAYER_STATUS_FICHASC;
      netall_printf( TOKEN_FICHASC"=%d,%d,%d\n",pJ->numjug,conts,armies + x_canje );

      return TEG_STATUS_SUCCESS;
}


/* give the 'token fichas' to the next player */
TEG_STATUS fichas_next( void )
{
      turno_2nextplayer( &g_game.turno );
      if(  turno_is_round_complete() ) {
            /* ya di la vuelta */
            g_game.turno->estado = PLAYER_STATUS_FICHAS2;
            netall_printf( TOKEN_FICHAS2"=%d,%d\n",g_game.turno->numjug,g_game.fichas2);

      } else {
            /* paso el estado fichas al siguiente */
            g_game.turno->estado = PLAYER_STATUS_FICHAS;
            netall_printf( TOKEN_FICHAS"=%d,%d\n",g_game.turno->numjug,g_game.fichas);
      }
      return TEG_STATUS_SUCCESS;
}

/* give the 'token fichas 2' to the next player */
TEG_STATUS fichas2_next( void )
{
      turno_2nextplayer( &g_game.turno );
      if(  turno_is_round_complete() ) {
            /* ya di la vuelta, enconces a empezar a jugar  */
            g_game.turno->estado = PLAYER_STATUS_ATAQUE;
            netall_printf( TOKEN_TURNO"=%d\n",g_game.turno->numjug);

      } else {
            /* paso el estado fichas2 al siguiente */
            g_game.turno->estado = PLAYER_STATUS_FICHAS2;
            netall_printf( TOKEN_FICHAS2"=%d,%d\n",g_game.turno->numjug,g_game.fichas2);
      }
      return TEG_STATUS_SUCCESS;
}

/* give the 'token fichas c' to the next player */
TEG_STATUS fichasc_next( void )
{
      turno_2nextplayer( &g_game.turno );

      if(  turno_is_round_complete() ) {
            /* ya di la vuelta */
            g_game.turno->estado = PLAYER_STATUS_ATAQUE;
            netall_printf( TOKEN_TURNO"=%d\n",g_game.turno->numjug);

      } else {
            aux_token_fichasc( g_game.turno );
      }
      return TEG_STATUS_SUCCESS;
}

/* find the internet address of a player */
TEG_STATUS aux_find_inaddr( PSPLAYER pJ )
{
      struct sockaddr *sa;
      socklen_t slen = 128;

      assert(pJ);

      strncpy(pJ->addr, _("Unknown"), sizeof(pJ->addr)-1);

#ifdef WITH_GGZ
      if(g_server.with_ggz) {
            strncpy(pJ->addr, _("GGZ Client"), sizeof(pJ->addr)-1);
            return TEG_STATUS_SUCCESS;
      }
#endif /* WITH_GGZ */

      if( pJ->fd <= 0)
            return TEG_STATUS_ERROR;

      if( (sa=malloc(slen)) == NULL )
            return TEG_STATUS_ERROR;

      if( getpeername( pJ->fd, sa, &slen ) == -1) {
            con_text_out(M_ERR,"Error in getpeername()\n");
            pJ->addr[sizeof(pJ->addr)-1]=0;

            free(sa);
            return TEG_STATUS_ERROR;
      }

      switch(sa->sa_family) {
      case AF_INET: {
            struct sockaddr_in *sin = (struct sockaddr_in*) sa;
            my_inet_ntop( AF_INET, &sin->sin_addr,pJ->addr, sizeof(pJ->addr)-1);
            break;
            }
      case AF_INET6: {
            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*) sa;
            my_inet_ntop( AF_INET6, &sin6->sin6_addr,pJ->addr, sizeof(pJ->addr)-1);
            break;
            }
      case AF_UNIX:
            strncpy(pJ->addr,"127.0.0.1",sizeof(pJ->addr)-1);
            break;
#if 0
             {
            struct sockaddr_un *unp = (struct sockaddr_un *) sa;
            if(unp->sun_path[0]==0)
                  strncpy(pJ->addr,_("Unknown"),sizeof(pJ->addr)-1);
            else
                  snprintf(pJ->addr, sizeof(pJ->addr)-1, "%s", unp->sun_path);
            break;
            }
#endif
      default:
            break;
      }

      pJ->addr[sizeof(pJ->addr)-1]=0;

      strip_invalid(pJ->addr);

      free(sa);

      return TEG_STATUS_SUCCESS;
}

TEG_STATUS aux_token_countries( PSPLAYER pJ, char *buf, int buflen )
{
      PLIST_ENTRY pL;
      PCOUNTRY country;
      int i,n=0;
      char strtmp[2048];

      assert(buf);

      memset(buf,0,buflen);

      /* special case where I want to send all countries that he CAN'T see */
      if( g_game.fog_of_war && pJ->numjug == -1 ) {
            for(i=0;i<COUNTRIES_CANT;i++)
            {
                  if( ! fow_can_player_see_country( g_game.player_fow, &g_countries[i] ) ) {
                        if(n==0) {
                              snprintf(strtmp,sizeof(strtmp)-1,"%i:%d",i,-1);
                              n=1;
                        } else 
                              snprintf(strtmp,sizeof(strtmp)-1,",%i:%d",i,-1);
                  
                        strtmp[ sizeof(strtmp) -1 ] = 0;

                        strncat(buf,strtmp,buflen);
                  }
            }
            return TEG_STATUS_SUCCESS;
      }

      /* the other case */
      pL = pJ->countries.Flink;
      while( !IsListEmpty( &pJ->countries) && (pL != &pJ->countries) ) {
            country = (PCOUNTRY) pL;

            if( 
                  ( ! g_game.fog_of_war ) ||
                  ( g_game.fog_of_war && fow_can_player_see_country( g_game.player_fow, country ) ) )
            {

                  if(n==0) {
                        snprintf(strtmp,sizeof(strtmp)-1,"%i:%d",country->id,country->ejercitos);
                        n=1;
                  } else 
                        snprintf(strtmp,sizeof(strtmp)-1,",%i:%d",country->id,country->ejercitos);

                  strtmp[ sizeof(strtmp) -1 ] = 0;

                  strncat(buf,strtmp,buflen);
            }

            pL = LIST_NEXT(pL);
      }
      buf[buflen]=0;

      return TEG_STATUS_SUCCESS;
}

TEG_STATUS launch_robot( int *robot_socket, char *mode )
{
      pid_t pid;
      char *args[5];

      int sockets[2];

      // sockets[0] is the client side of the robot
      // sockets[1] is the server side
      int r = socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets );
      if( r != 0 )
            return TEG_STATUS_ERROR;

      // launch the server connected
      if ( (pid = fork()) < 0) {
            perror("tegserver: launch_bot() ");
            return TEG_STATUS_ERROR;
      } else if (pid == 0) {

            close( sockets[1] );
            args[0] = BINDIR"/tegrobot";
            args[1] = mode;
            args[2] = NULL;

            if ( dup2(  sockets[0], 3 ) == -1 )
                  return TEG_STATUS_ERROR;
      
            con_text_out(M_ERR, _("Launching robot with options: %s %s\n"),args[0],args[1]);
            if( execv(args[0], args) < 0) {
                  fprintf(stderr,"Launching robot failed. Does the file `%s' exists ?",args[0]);
                  perror("exe:");
            }
            exit(1);
      } else {

            close( sockets[0] );
      }

      // return the robot fd
      *robot_socket = sockets[1];

      return TEG_STATUS_SUCCESS;
}

Generated by  Doxygen 1.6.0   Back to index