wm: glendy

ref: e19630c0ef62e3e66cc17a438704df07cb2161ce
dir: /netclient.c/

View raw version
#ifdef unix
#include "unix.h"
#else
#include <u.h>
#include <libc.h>
#include <draw.h>
#endif
#include "engine.h"
#include "netclient.h"
#include "util.h"

int waitbit = 1; /* 0 is go, 1 is wait */
int networked = 0; /* 0 is local, 1 is networked */
int pside; /* Trapper, Glenda */

int srvfd;

char *pnick;
int pside;
int pgame;
int popts;

static char*
himsg(char *name, int game, int side, int opts)
{
	char *msg;
	
	dprint("himsg(%s, %d, %d, %d)\n", name, game, side, opts);
	if(side > PRandom)
		return nil;
	
	msg = (char*)emalloc(32);
	sprint(msg, "%s %d %d %d\n", name, game, side, opts);
	return msg;
}

static char*
movemsg(int dir)
{
	char *d, *msg;
	
	d = dirtostr(dir);
	if(d == nil)
		return nil;
	
	msg = (char*)emalloc(8);
	sprint(msg, "m %s\n", d);
	return msg;
}

static char*
putmsg(int x, int y)
{
	char *msg;
	dprint("putmsg(%d, %d)\n", x, y);
	if(x > SzX || x < 0 || y > SzY || y < 0)
		return nil;
	
	msg = (char*)emalloc(10);
	sprint(msg, "p %d %d\n", x, y);
	return msg;
}

int
nethi(Game *game, char *name, int gameset, int side, int opts)
{	
	int len;
	char *msg;

	msg = himsg(name, gameset, side, opts);
	if(msg == nil)
		return Err;
	
	len = strlen(msg);
	if(write(srvfd, msg, len) < len)
		sysfatal("nethi(): half written?");

	/* otherwise client wont read socket to confirm */
	waitbit = 1;
	free(msg);
	game->state = STATE_INIT;
	return Ok;
}

int
netmove(int dir)
{
	int len;
	char *msg;

	msg = movemsg(dir);

	if(msg == nil)
		return Err;
	
	len = strlen(msg);
	if(write(srvfd, msg, len) < len)
		sysfatal("netmove(): half written?");
	
	free(msg);
	return Ok;
}

int
netput(int x, int y)
{
	int len;
	char *msg;

	msg = putmsg(x, y);
	
	if(msg == nil)
		return Err;
	
	len = strlen(msg);
	if(write(srvfd, msg, len) < len)
			sysfatal("netput(): half written?: %r");

	free(msg);
	return Ok;
}

static void
netproc(Game *game, Netmsg *msg, char *in)
{
	int i, dir;
	char *tmp, *xpos, *ypos;
	char **tokens = (char**)emalloc(64 * sizeof(char*));
	Point p;
	
	msg->omsg = strdup(in);
	dprint("msg->omsg: %s\n", msg->omsg);
	
	tokens[0] = strtok(in, " ");
	for(i = 1 ; tokens[i-1] != nil ; i++)
	{
		tokens[i] = strtok(nil, " ");
		fprint(2, "token[%d] = %s\n", i, tokens[i]);
	}
	
	msg->ntoken = i;
	msg->tokens = tokens;
	msg->err = Ok;

	if(tokens[0] == nil)
		msg->err = Err;
	else if(!strcmp(tokens[0], "CONN"))
	{
		switch(*tokens[1])
		{
			case '0':
				pside = PTrapper;
				break;
			case '1':
				pside = PGlenda;
				break;
			default:
				sysfatal("invalid conn");
		}
	}
	else if(!strcmp(tokens[0], "UGUD"))
		fprint(srvfd, "y\n");

	else if(!strcmp(tokens[0], "WAIT"))
		waitbit = 1;

	else if(!strcmp(tokens[0], "INIT"))
	{
		waitbit = 0;
		game->state = STATE_INIT;
		while(game->state == STATE_INIT)
		{
			tmp = netread();
			/* lots of assuming goes here,
			 * messages are in the form of:
			 * {w,g} xx yy\n
			 */
			strtok(tmp, " ");
			switch(*tmp)
			{
				case 'w':
					xpos = strtok(nil, " ");
					ypos = strtok(nil, " ");
					if(xpos == nil || ypos == nil)
						sysfatal("netproc(): w xpos or ypos is nil?\n");
					p.x = atoi(xpos);
					p.y = atoi(ypos);
					
					game->grid[p.x][p.y] = PIECE_WALL;
					break;
				case 'g':
					xpos = strtok(nil, " ");
					ypos = strtok(nil, " ");
					if(xpos == nil || ypos == nil)
						dprint("netproc(): g xpos or ypos is nil?\n");
					
					p.x = atoi(xpos);
					p.y = atoi(ypos);
					
					game->grid[p.x][p.y] = PIECE_GLENDA;
					break;
				default:
					if(!strcmp("SENT", tmp))
						game->state = STATE_START;
					else
						dprint("netproc(): Init: unknown command: %s\n", tmp);
				
			}
		}
	}
	else if(!strcmp(tokens[0], "SENT"))
		/* sent is handled in INIT */
		dprint("SENT without INIT?\n");
	
	else if(!strcmp(tokens[0], "TURN"))
		waitbit = 0;

	else if(!strcmp(tokens[0], "SYNC"))
	{
		if(game->state == STATE_START)
			game->state = STATE_PLAYING;
		if(msg->ntoken < 2)
			sysfatal("netproc(): not enough toknes?");
		
		if(atoi(msg->tokens[1]) % 2 == 0)
		{
			/* trapper's turn is done */
			if(msg->ntoken != 4)
				sysfatal("netproc(): not enough tokens to SYNC trapper's move");
			
			p = parseput(tokens[2], tokens[3]);
			doput(game, p);
		}
		else
		{
			/* glenda's turn is done */
			if(msg->ntoken != 3)
				sysfatal("netproc(): not enough tokens to SYNC glenda's move");
			dir = strtodir(tokens[2]);
			domove(game, dir);
		}
	}
	else if(!strcmp(tokens[0], "WON"))
	{
		msg->err = STATE_WON;
	}
	else if(!strcmp(tokens[0], "LOST"))
	{
		msg->err = STATE_LOST;
	}
	else 
		sysfatal("netproc(): unkown message: 0x%x %s", *tokens[0], tokens[0]);
}

char*
netread(void)
{
	char *s = malloc(1024);
	int n = 0;
	
	memset(s, 0, 1024);
	while(read(srvfd, s+n, 1) == 1 && n < 1023)
	{
		if(s[n] == '\n' || s[n] == '\0')
		{
			s[n] = '\0';
			break;
		}
		n++;
	}
	return s;
}

void
netinit(Game *game)
{
	Netmsg *msg;
	char *s;

	msg = (Netmsg*)emalloc(sizeof(Netmsg));

	game->state = STATE_CONNECT;
	nethi(game, pnick, 0, pside, 0);
	
	for(;;)
	{
		s = netread();
		netproc(game, msg, s);

		dprint("msg->tokens[0]: %s\n", msg->tokens[0]);
		if(msg->tokens[0] != nil && !strcmp(msg->tokens[0], "INIT"))
			break;
		
		free(s);
	}
	free(s);
}

Netmsg*
netmain(Game *game)
{
	Netmsg *msg;
	char *s;
	msg = (Netmsg*)emalloc(sizeof(Netmsg));
	
	s = netread();
	netproc(game, msg, s);
	free(s);
	return msg;
}