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

#include "ckuser.h"

static struct tiles rack;
static struct move bestmove, mv;
static int bestscore;

computer (code, parm)
int code;
char *parm;
{
	switch (code) {
		case GETMOVE:
			return computermove ((struct move *) parm);
		case DOYOUCHALLENGE:
			return computerchallenge ((struct move *) parm);
		case BADCHALLENGE:
			break;
		case GOODCHALLENGE:
			break;
		case HETRADES:
			break;
		case RACK:
			computerrack ((struct tiles *) parm);
			break;
		case INIT:
			break;
		case BEGINGAME:
			break;
		case ENDGAME:
			break;
		default:
			break;
	}
}

computermove (m) struct move *m;
{
    bestscore = -1;

    genmoves ();
    
    if (bestscore > 0) {
	*m = bestmove;
	return PLACEWORD;
    }
    else {
	*(m -> tiles) = EMPTY;
	return TRADE;
    }
}

computerchallenge (m, who) struct move *m; int who;
{
    return !legalwords (m);
}

computerrack (r) struct tiles *r;
{
	rack = *r;
}

static eval (m) struct move *m;
{
    register s = score (m);

    if (s > bestscore) {
	bestscore = s;
	bestmove = *m;
    }
}

static int anchor, stopsquare;
static char *word;

genmoves ()
{
    stopsquare = 0;
    word = mv.tiles;

    for (anchor = 0; anchor < NPOS; anchor++)
	if (isadjacent (anchor)) {
	    if (board[anchor - 1])
		extend (root, mv.position = stopsquare + 1);
	    else {
		mv.position = anchor;
		prefix (root);
	    }
	    stopsquare = anchor;
	}
	else if (!COLUMN (anchor))
	    stopsquare = anchor;
}

prefix (loc) register long loc;
{
    register long  *l;

    extend (unterm (loc), anchor);
    --mv.position;
    if (mv.position != stopsquare && ptr (loc)) {
	l = dawg + ptr (loc);
	do {
	    register    d, c = chr (*l);
		CKUSER;
	    if (rack.count[c])
		rack.count[d = c]--;
	    else if (rack.count[BLANK]) {
		c |= BLANKBIT;
		rack.count[d = BLANK]--;
	    }
	    else
		continue;
	    *word++ = c;
	    prefix (*l);
	    --word;
	    rack.count[d]++;
	} while (!last (*l++));
    }
    mv.position++;
}
 
extend (loc, p) register long loc; register p;
{
    register long  *l;

	CKUSER;
    if (board[p]) {
	if (ptr (loc)) {
	    l = dawg + ptr (loc);
	    do
		if (chr (*l) == chr (board[p]))
		    extend (*l, p + 1);
	    while (!last (*l++));
	}
    }
    else {
	if (term (loc) && word != mv.tiles) {
	    *word = '\0';
	    eval (&mv);
	}
	if (ptr (loc)) {
	    l = dawg + ptr (loc);
	    do {
		register d, c = chr (*l);
		if (MEMBER (check_set[p], c)) {
		    if (rack.count[c])
			rack.count[d = c]--;
		    else if (rack.count[BLANK]) {
			c |= BLANKBIT;
			rack.count[d = BLANK]--;
		    }
		    else
		        continue;
		    *word++ = c;
		    extend (*l, p + 1);
		    --word;
		    rack.count[d]++;
		}
	    } while (!last (*l++));
	}
    }
}
