#include <stdio.h>
#include "graphics.h"
#include "trie.h"
#include "globals.h"

char tellbuf[80];

void fillsock(void)
{
    register int    i;
    for (i = 0, socksize = 0; i < 28; i++) {
	socksize += (sock[i] = letterquantity[i]);
	yourrack[i] = rack[i] = 0;
    }
}

void drawtile (int k, char r[28]);

void drawtiles (char r[28])
{
    register int    i,
                    j,
                    k,
                    c;
    for (i = 1, c = 7; i < 28; i++)
	c -= r[i];
    if (c == 7 && socksize == 0)
	anyrackempty = 1;
    if (socksize < c)
	c = socksize;
    for (i = 0; i < c; i++) {
	j = rand () % socksize;
	k = 0;
	while (j >= 0)
	    j -= sock[++k];
	drawtile (k, r);
    }
}

void drawtile (int k, char r[28])
{
    r[k]++;
    sock[k]--;
    socksize--;
    showtilecount (k);
}

void makemove (struct goodmove *m, bool rr, int bits)
{
    register unsigned   r,
                        c;
    register char  *w;
    char    (*xfill)[17];
    r = m -> r;
    c = m -> c;
    if (m -> fill == afill)
	xfill = dfill;
    else
	xfill = afill;
    for (w = m -> word, c--; *w; c--)
	if (!m -> fill[r][c]) {
	    m -> fill[r][c] = xfill[c][r] = ((*w) & 077) | bits;
	    posit (m -> fill, r, c);
	    if (rr) {
/*
		standout ();
		placeletter (*w);
		standend ();
*/
	    }
	    else
		placeletter (*w);
	    showtilecount ((*w & BLANKBIT) ? BLANK : chr (*w));
	    w++;
	}
}

void zapmove(void)
{
    register unsigned int c;
    for (c = 1; c < 16; c++) {
/*
	posit (bestmove.fill, bestmove.r, c);
	addch (127 & inch ());
*/
    }
}

int suggestmove (void)
{
    char   *w;
    int     i,
            j;
    char    saverack[28];

    bestmove.value = -1000;
    for (i = 0; i < 28; ++i)
	saverack[i] = rack[i];
    for (i = 0; i < 28; ++i)
	rack[i] = yourrack[i];
    if (afill[8][8]) {
	putp (acheck, afill, atrans);
	putp (dcheck, dfill, dtrans);
    }
    else
	firstmove ();
    if (bestmove.value > -1000) {
	for (w = bestmove.word; *w; w++)
	    if (BLANKBIT & (*w))
		rack[BLANK]--;
	    else
		rack[chr (*w)]--;
	computechecks (dfill, acheck, atrans);
	computechecks (afill, dcheck, dtrans);
	makemove (&bestmove, TRUE, NEWBIT);

	sprintf (tellbuf, "(for %d points)", bestmove.score);
	tell (tellbuf);
    for (i = 0; i < 28; ++i)
	yourrack[i] = rack[i];
    for (i = 0; i < 28; ++i)
	rack[i] = saverack[i];
    return(TRUE);
    }
    else {
	tell ("I can't think of any moves for you!");
    for (i = 0; i < 28; ++i)
	yourrack[i] = rack[i];
    for (i = 0; i < 28; ++i)
	rack[i] = saverack[i];
        return(FALSE);
    }
}

void computermove(void)
{
    char   *w;
    computechecks (dfill, acheck, atrans);
    computechecks (afill, dcheck, dtrans);
    bestmove.value = -1000;
    if (afill[8][8]) {
	putp (acheck, afill, atrans);
	putp (dcheck, dfill, dtrans);
    }
    else
	firstmove ();
    if (bestmove.value > -1000) {
	for (w = bestmove.word; *w; w++)
	    if (BLANKBIT & (*w))
		rack[BLANK]--;
	    else
		rack[chr (*w)]--;
	makemove (&bestmove, TRUE, 0);
	consecutivepasses = 0;
	drawtiles (rack);
	myscore += bestmove.score;
	sprintf (tellbuf, "I get %d points.", bestmove.score);
	tell (tellbuf);
    }
    else {
	tell ("I can't think of a good move -- your turn.");
	consecutivepasses++;
    }
    computechecks (dfill, acheck, atrans);
    computechecks (afill, dcheck, dtrans);
}

int humanmove (char bogus)
{
    int     minr = 16,
            maxr = 0,
            minc = 16,
            maxc = 0;
    int     xscore = 0,
            fscore = 0,
            factor = 1,
            t,
            l;
    int     r,
            c,
            count;
    char    new,
            (*fill)[17], (*xfill)[17];
    int     (*trans)[17];
    for (r = 1; r < 16; r++)
	for (c = 1; c < 16; c++)
	    if (afill[r][c] & NEWBIT) {
		if (r < minr)
		    minr = r;
		if (r > maxr)
		    maxr = r;
		if (c < minc)
		    minc = c;
		if (c > maxc)
		    maxc = c;
	    }
    if (afill[8][8] == 0) {
	fprintf(stderr, "The first move must cover the center square\n");
	return (0);
    }
    if (minr != maxr && minc != maxc) {
	fprintf(stderr,
		maxr > 0 ? "Your word must be all in the same row or column.\n"
		: "Use = if you want to pass without playing a word.\n");
	return (0);
    }
    if (minr == maxr && (maxc > minc || afill[maxr][maxc - 1] || afill[maxr][maxc + 1])) {
	fill = afill;
	xfill = dfill;
	trans = atrans;
    }
    else {
	fill = dfill;
	xfill = afill;
	trans = dtrans;
	minc = minr;
	minr = maxc;
	maxc = maxr;
	maxr = minr;
    }
    r = minr;
    for (c = minc; c <= maxc; c++)
	if (!fill[r][c]) {
	    fprintf(stderr, "Your word must be contiguous at %c%d.\n",
              c+'A'-1, r);
	    return (0);
	}
    t = (fill[8][8] & NEWBIT) | fill[r][minc - 1] | fill[r][maxc + 1];
    for (c = minc; c <= maxc; c++)
	t |= fill[r - 1][c] | fill[r + 1][c];
    if (!t) {
	fprintf(stderr, "Your word must be adjacent to one already on the board.\n");
	return (0);
    }
    while (fill[r][c])
	c++;
    if ((!bogus) && !checkmove (fill, r, c - 1)) {
        /*fprintf(stderr, "bogus or didn't check\n");*/
	/*return (0);*/
    }
    bestmove.r = r;
    bestmove.c = c;
    bestmove.fill = fill;
    for (count = 0, c--; new = fill[r][c]; c--)
	if (NEWBIT & new) {
	    l = lettermult[r][c] * lettervalue[new & 077];
	    t = trans[r][c];
	    if (t >= 0)
		xscore += (t + l) * wordmult[r][c];
	    fscore += l;
	    factor *= wordmult[r][c];
	    fill[r][c] = 0;
	    xfill[c][r] = 0;
	    bestmove.word[count++] = new;
	}
	else
	    fscore += lettervalue[new];
    bestmove.word[count] = 0;
    bestmove.score = fscore * factor + xscore + 50 * (count == 7);
    makemove (&bestmove, FALSE, 0);
    consecutivepasses = 0;
    zapmove ();
    yourscore += bestmove.score;
    fprintf (stderr, "You get %d points.\n", bestmove.score);
    return (1);
}

unsigned long checkword (unsigned long t, char *s)
{
    register unsigned long *p;
    if (!*s)
	return (t);
    if (!ptr (t))
	return (0);
    p = dawg + ptr (t);
    do {
	if (chr (*p) == chr (*s))
	    return (checkword (*p, s + 1));
    }
    while (!last (*p++));
    return (0);
}

int checkmove (char (*fill)[17], unsigned int r, unsigned int c)
{
    unsigned long (*check)[17];
    if (fill == afill)
	check = acheck;
    else
	check = dcheck;
    for (; fill[r][c]; c--)
	if ((fill[r][c] & NEWBIT) && !((1 << chr (fill[r][c])) & check[r][c])) {
	    errortell ("One of your cross words isn't!");
	    return (0);
	}
    if (!term (checkword (root, fill[r] + c + 1))) {
	errortell ("Your word is bogus.");
	return (0);
    }
    return (1);
}

int exchange(void)
{
    register unsigned   r,
                        c,
                        count = 0;
    for (r = 1; r < 16; r++)
	for (c = 1; c < 16; c++)
	    if (afill[r][c] & NEWBIT)
		count++;
    if (count == 0) {
	tell ("Put the tiles you want to trade in anywhere on the board, then press -.");
	return (0);
    }
    if (count > socksize) {
	errortell ("You're trying to trade in more tiles than there are left!");
	return (0);
    }
    drawtiles (yourrack);
    for (r = 1; r < 16; r++)
	for (c = 1; c < 16; c++)
	    if (afill[r][c] & NEWBIT) {
		char    let = afill[r][c] & BLANKBIT ? BLANK
						     : chr (afill[r][c]);
		sock[let]++;
		socksize++;
		showtilecount (let);
		position (r, c);
		removeletter ();
		afill[r][c] = dfill[c][r] = 0;
	    }
    return (1);
}