📄 bnserver.c
字号:
/* * Batalla Naval (c) 1995,1996,1997 Ricardo Quesada * (rquesada@dc.uba.ar) * * Servidor para Linux * version: 0.60 * * Modificaciones para adaptar cliente Win16 por: * Horacio Pe馻 ( horape@balug.org.ar ) * *//* INCLUDES */#include <ncurses.h> /* new on v0.41 */#include <sys/types.h>#include <sys/socket.h>#include <sys/resource.h>#include <unistd.h>#include <netinet/in.h>#include <stdio.h>#include <syslog.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <stdarg.h> /* new on v0.41 */#include "../share/protocol.h" /* definicion del protocolo */#ifdef WDEBUG#include <sys/stat.h>#include <fcntl.h>#endif/* DEFINES */#define BN_SVER "0.60"#define BNVERH 0#define BNVERL 60#define MAXPLAYER 5/* VARIABLES GLOBALES y STRUCT y TYPEDEF y ... */WINDOW *windows[MAXPLAYER];WINDOW *titles[MAXPLAYER];WINDOW *title;typedef struct tabla_typ { int x,y; char p[10][10];} tabla,*tabla_ptr;struct datos { char server_name[50]; /* server name */ int port; /* donde va el port */ int debug; /* debug mode */ int nro_tot[MAXPLAYER]; /* 1 int por jugador */ int nro_fd[MAXPLAYER]; /* 1 file descriptor por jugador */ int hits[MAXPLAYER]; /* how many hits has a player received */ tabla table[MAXPLAYER]; char names[MAXPLAYER][MAXNAMELEN]; /* other players's name new on v0.36 */} usuario,*usuario_ptr;fd_set test_set, ready_set; /* here is new on v0.35 */int temp; /* variable temporal */char tempbuf[MSGMAXLEN]; /* varible general *//***************************************************************************** * FUNCIONES *****************************************************************************//***************************************************************************** * funciones TCP/IP ***************************************************************************/void bnwrite(int fde,char *buf,char tip0,char tip1,char tip2,char jugyo ) { int i; struct protocolo proto; proto.bnptip0=tip0; proto.bnptip1=tip1; proto.bnptip2=tip2; proto.jugador=jugyo; for(i=0;i<MSGMAXLEN;i++) proto.bnpmsg[i]=buf[i]; strcpy(proto.bnphead,BNPHEAD); proto.bnpver=BNPVER; write(fde,&proto,MAXLEN);}/* manda el mensaje msg a todos los que cumplan nro_tot>=yes menos a no */void broadcast(char *msg,char tip0,int yes, int no,char tip1,char tip2,char jugyo) { /* new on v0.34 */ char msgnew[MSGMAXLEN]; int i; for(i=0;i<MSGMAXLEN;i++) msgnew[i]=msg[i]; for(i=0;i<MAXPLAYER;i++) { if(i!=no) { if(usuario.nro_tot[i]>=yes) { bnwrite(usuario.nro_fd[i],msg,tip0,tip1,tip2,jugyo); } } }}/***************************************************************************** * CHEQUEO DE ALGORITOMO ****************************************************************************//* points to next pos.return TRUE . FALSE in case there are no more ships *//* this rutine uses global x,y */int nextbarco(int num_jug) { if(usuario.table[num_jug].x==9) { usuario.table[num_jug].x=0; usuario.table[num_jug].y++; } else usuario.table[num_jug].x++; if( usuario.table[num_jug].y==10 ) return FALSE; else return TRUE;} /* return TRUE if in (x,y) hay barco. else FALSE *//* this rutine uses local x,y */int haybarco( int x, int y,int num_jug) { if( (x < 0) || ( x > 9 ) || (y < 0) || (y >9 ) ) return FALSE; if( usuario.table[num_jug].p[x][y]>=BARCO ) /* new on v0.45 */ return TRUE; if( usuario.table[num_jug].p[x][y]<=NOBARCO ) return FALSE; return FALSE;}/* return TRUE if table is OK .else return FALSE */int algoritmo(int num_jug) { int i,xx,yy,barcos,subarco; int barquitos[4]; for(i=0;i<4;i++) barquitos[i]=0; /* global x,y */ usuario.table[num_jug].x=0; usuario.table[num_jug].y=0; barcos=0; for(;;) { if(haybarco(usuario.table[num_jug].x,usuario.table[num_jug].y,num_jug)==FALSE) { if(nextbarco(num_jug)==FALSE) { if( (barquitos[3]==1) && (barquitos[2]==2) && (barquitos[1]==3) && (barquitos[0]==4) ) { return TRUE; /* tabla bien puesta */ } else { return FALSE; } } } else { if( haybarco(usuario.table[num_jug].x,usuario.table[num_jug].y,num_jug)==TRUE ) { if( (haybarco(usuario.table[num_jug].x,usuario.table[num_jug].y-1,num_jug)==FALSE) && (haybarco(usuario.table[num_jug].x-1,usuario.table[num_jug].y,num_jug)==FALSE) ) { subarco=1; barcos++; xx=usuario.table[num_jug].x;yy=usuario.table[num_jug].y; for(;;) { if( (haybarco(usuario.table[num_jug].x-1,usuario.table[num_jug].y+1,num_jug)==TRUE) || (haybarco(usuario.table[num_jug].x+1,usuario.table[num_jug].y+1,num_jug)==TRUE) ) { return FALSE; } if( (haybarco(usuario.table[num_jug].x+1,usuario.table[num_jug].y,num_jug)==FALSE) && (haybarco(usuario.table[num_jug].x,usuario.table[num_jug].y+1,num_jug)==FALSE) ) { usuario.table[num_jug].x=xx; usuario.table[num_jug].y=yy; /* restauro pos */ barquitos[subarco-1]++; /* update cantidad de tama;os de barcos */ break; } else if( haybarco(usuario.table[num_jug].x+1,usuario.table[num_jug].y,num_jug) == TRUE ) { subarco++; barcos++; usuario.table[num_jug].x++; } else if( haybarco(usuario.table[num_jug].x,usuario.table[num_jug].y+1,num_jug) == TRUE ) { usuario.table[num_jug].y++; barcos++; subarco++; } if( subarco > 4) { return FALSE; } } /* for(;;) */ } /* if(haybarco(x,y-1)==FALSE) */ } /* if(haybarco(x,y)==TRUE) */ if(nextbarco(num_jug)==FALSE) { if( (barquitos[3]==1) && (barquitos[2]==2) && (barquitos[1]==3) && (barquitos[0]==4) ) { return TRUE; /* tabla bien puesta */ } else { return FALSE; } } /* if nextbarco()==FALSE) */ } /* else */ } /* for(;;) */} /* void algoritomo() *//*************************************************************************** * FUNCIONES RELACIONADAS CON LAS TABLAS y WPRINTD ***************************************************************************/void wprintd(WINDOW *win, char *fmt,...) { va_list ap; va_start(ap,fmt); if(usuario.debug==TRUE) { vwprintw(win,fmt,ap); wrefresh(win); } va_end(ap);}/* write to board */int wtable( int jug,struct protocolo *proto ) { int i,x,y; x=0;y=0; for(i=0;i<100;i++) { usuario.table[jug].p[x][y]=proto->bnpmsg[i]; x++; if(x>=10) { x=0; y++; } } return( algoritmo(jug));}/* read from board */void rtable( char outbuf[],int jug,char sup) { int i,x,y; x=0;y=0; for(i=0;i<100;i++) { if(sup==BNSUP) outbuf[i]=usuario.table[jug].p[x][y]; else { if(usuario.table[jug].p[x][y]==1) outbuf[i]=0; else outbuf[i]=usuario.table[jug].p[x][y]; } x++; if(x>=10) { x=0; y++; } }}/* clean board */void ctable( int jug) { int i,x,y; x=0;y=0; for(i=0;i<100;i++) { usuario.table[jug].p[x][y]=0; x++; if(x>=10) { x=0; y++; } }}/* tablero de un muerto */void mtable( int jug ) { int i,x,y; x=0;y=0; for(i=0;i<100;i++) { if(usuario.table[jug].p[x][y]==NOBARCO) usuario.table[jug].p[x][y]=AGUA; x++; if(x>=10) { x=0; y++; } }}/***************************************************************************** * EL BARCO ESTA HUNDIDO ? y todo tipo de funciones *****************************************************************************/int quebarco( int i,int x, int y) { if( (x < 0) || ( x > 9 ) || (y < 0) || (y >9 ) ) return 0; return( usuario.table[i].p[x][y]);}/* 1 funciones recursiva para chequear si esta hundido */void goudlr( int i,int x,int y,int xx,int yy) { if (quebarco(i,x,y)==2) goudlr(i,x+xx,y+yy,xx,yy); else if(quebarco(i,x,y)==1) temp+=1;}/* 1 funcion recursiva para pintar al barco hundido */void pgoudlr( int i,int x,int y,int xx,int yy) { if(quebarco(i,x,y)==2) { usuario.table[i].p[x][y]=HUNDIDO; /* 3 means hundido (sunk) */ tempbuf[0]=(char)x; tempbuf[1]=(char)y; tempbuf[2]=HUNDIDO; /* hundido */ bnwrite(usuario.nro_fd[i],tempbuf,BNHIT,0,0,i+1); pgoudlr(i,x+xx,y+yy,xx,yy); }}/* i assume that quebarco(i,x,y)==2 o 1 */int eshundido(int i,int x,int y) { int xx,yy; /* direccion a buscar */ if(quebarco(i,x,y) <= 0) /* IDIOTA, COMO VA A SER HUNDIDO */ return FALSE; if(quebarco(i,x,y)==3) /* estaba hundido de antes idiota */ return TRUE; usuario.table[i].p[x][y]=2; /* tocado por ahora*/ temp=0; xx=-1;yy=0;goudlr(i,x,y,xx,yy); xx=0;yy=-1;goudlr(i,x,y,xx,yy); xx=1;yy=0;goudlr(i,x,y,xx,yy); xx=0;yy=1;goudlr(i,x,y,xx,yy); if(temp==0) { xx=-1;yy=0;pgoudlr(i,x,y,xx,yy); xx=0;yy=-1;pgoudlr(i,x,y-1,xx,yy); xx=1;yy=0;pgoudlr(i,x+1,y,xx,yy); xx=0;yy=1;pgoudlr(i,x,y+1,xx,yy); usuario.hits[i]++; if(usuario.hits[i]==10) { bnwrite(usuario.nro_fd[i],tempbuf,BNLOS,0,0,i+1); usuario.nro_tot[i]=PERDIO; /* nuevo en 0.48 */ /* usuario.hits[i]=0; */ /* comentado en la 0.48 */ /* usuario.names[i][0]=0; */ /* ctable(i);*/ mtable(i); sprintf(tempbuf,"Player %i is dead.",i+1); /* new on v0.32 */ broadcast(tempbuf,BNEXT,1,i,i+1,1,0); /* informs that i is dead */ wprintd(windows[i],"\nPlayer was killed"); wprintd(windows[i],"\n- - - - -"); /* * no hace falte volver a poner el nombre */ /* wprintd(titles[i],"\nPlayer %i, name:'%s'",i+1,usuario.names[i]); */ } return TRUE; } return FALSE;}/***************************************************************************** * funciones CONTROL DE CHILD Y JUEGO ***************************************************************************//* * Funcion bnexit() introducida en v0.50 * ya que no voy a repetir el codigo * Porque se puede salir de dos manera */void bnexit( int num_jug, int modo_quit ){ char outbuf[MSGMAXLEN]; int i; /* * Si el tipo que abandona es el que tiene el turno tiene * que pasar al siguiente */ if(usuario.nro_tot[num_jug]==4) { for(i=num_jug;i<MAXPLAYER;i++) { if(usuario.nro_tot[i]==3) break; } if(i==MAXPLAYER) { for(i=0;i<MAXPLAYER;i++) { if(usuario.nro_tot[i]==3) break; } } if(i!=MAXPLAYER) { usuario.nro_tot[i]=4; bnwrite(usuario.nro_fd[i],outbuf,BNTRN,0,0,i+1); wprintd(windows[i],"\nIt is my turn"); sleep(1); } } usuario.nro_tot[num_jug]=0; usuario.hits[num_jug]=0; ctable(num_jug); usuario.nro_fd[num_jug]=0; usuario.names[num_jug][0]=0; if(modo_quit==0) { sprintf(outbuf,"Player %i quits the game.",num_jug+1); wprintd(windows[num_jug],"\nQuitting the game..."); } else if(modo_quit==1) { sprintf(outbuf,"Player %i aborts the game.",num_jug+1); wprintd(windows[num_jug],"\nAborting the game..."); } broadcast(outbuf,BNEXT,3,num_jug,num_jug+1,0,0); wprintd(windows[num_jug],"\n- - - - -");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -