#include "crab.h"
#include "tiles.h"
#include "messages.h"

struct player players[NPLAYERS];

int passes, playing, overreason;
int firstplayer;
int allowchallenges = 1;
int firstgame = 1;
int crabref = 1;

main ()
{
	initmessage ();
	newgame ();
	sendall (INIT);

	playing = 0;
	for (;;) {
		while (!playing)
			user ();
		if (!firstgame)
			newgame ();
		playgame ();
		firstgame = 0;
		if (overreason != RESET) {
			adjustscores ();
			sendall (ENDGAME);
		}
		else
			playing = 1;
	}
}

newgame ()
{
	initsock ();
	initboard ();
}

playgame ()
{
	int who;
	
    passes = 0;
    firstplayer = YOU;	/* for now, human goes first */
 
    for (who = 0; who < NPLAYERS; who++) {
		struct player *p = players + who;
		p -> score = 0;
		p -> turnslost = 0;
		initrack (&(p -> rack));
	}
	sendall (BEGINGAME);
    for (who = 0; who < NPLAYERS; who++) {
		struct player *p = players + who;
		fillrack (&(p -> rack));
		send (who, RACK, &(p -> rack));
    }
	play ();
}
	    
play ()
{
	int who;
	for (who = firstplayer; playing; who = OTHERGUY(who)) {
		if (players[who].turnslost)
			players[who].turnslost--;
		else {
			turn (who);
			if (!players[who].rack.total) {
				playing = 0;
				overreason = NOMORETILES;
			}
		}
    }
}

turn (who) int who;
{
    struct move m;
	int movetype;
    struct player  *p = players + who;
    struct tiles   *r = &(p -> rack);
	int nletters;
	int chal;

	send (who, YOURTURN);
	send (OTHERGUY (who), HISTURN);
	movetype = send (who, GETMOVE, &m);
	if (!playing)
		return;
	nletters = strlen (m.tiles);
	
    if (movetype == PLACEWORD) {
		passes = 0;
		chal = send (OTHERGUY (who), TRYMOVE, &m);
		if (!playing)
			return;
		if (allowchallenges && chal)
			if (crabref && legalwords (&m) ||
				!crabref && userref (&m)) {
				sendall (BADCHALLENGE);
				players[OTHERGUY (who)].turnslost++;
			}
			else {
				sendall (GOODCHALLENGE);
				return;
			}
	 /* The move is now made permanent */
		p -> score += score (&m);
		makemove (&m);
		sendall (MOVEMADE, &m);
	}
	else if (movetype == TRADE) {
		passes++;
		if (passes == PASSLIMIT) {
			playing = 0;
			overreason = PASSOUT;
		}
		send (OTHERGUY (who), HETRADES, &nletters);
	}
	removetiles (r, &m);
	fillrack (r);
	if (movetype == TRADE)
	    addtiles (&sock, &m);
	send (who, RACK, r);
}

initmessage ()
{
 	int who;

    for (who = 0; who < NPLAYERS; who++) {
		struct player *p = players + who;
		if (who == ME) {
			int computer ();
			p -> message = &computer;
		}
		else if (who == YOU) {
			int human ();
			p -> message = &human;
		}
	}
}

send (who, mtype, parm)
int who, mtype;
char *parm;
{
	int (*m) () = players[who].message;
	
	return (*m) (mtype, parm);
}

sendall (mtype, parm)
int mtype;
char *parm;
{
	int i;
	
	for (i = 0; i < NPLAYERS; i++)
		send (i, mtype, parm);
}

adjustscores ()
{
	int i, pts;
	
	for (i = 0; i < NPLAYERS; i++) {
		pts = rackpoints (&players[i].rack);
		if (pts)
			players[i].score -= pts;
		else
			players[i].score += rackpoints (&players[OTHERGUY(i)].rack);
	}
}
