#include "graphics.h"
#include "globals.h"

#define CMDHELP 1
#define KEYHELP 2
#define TILEHELP 3
 
position (y, x) int y, x;
{
    move (Ypos (y), Xpos (x));
}

mark (y, x, s) int y, x; char *s;
{
    position (y, x);
    addstr (s);
}

removeletter ()
{
    int     y,
            x;
    getyx (stdscr, y, x);
    y = y - BOARDLINE;
    x = (x - BOARDCOL) >> 1;
    addch (BOARDCHAR (y, x));
}

placeletter (c) char c;
{
    addch ((c & 077) + '@');
}

/* Clear line l of the screen */
clearline (l) int   l;
{
    move (l, 0);
    clrtoeol ();
}

/* Print string s centered on line l */
centerprint (l, s) int  l;
char   *s; {
    clearline (l);
    mvaddstr (l, (COLS - strlen (s)) / 2, s);
}

/* Draw a horizontal line on screen row y from xmin to xmax.
   Use '-' in the middle of the line and '+' at the ends. */

horiz (y, xmin, xmax) int   y, xmin, xmax;
{
    int     x;
    standout ();
    for (x = xmin; x <= xmax; x++)
	mvaddch (y, x, (x == xmin || x == xmax) ? '+' : '-');
    standend ();
}

/* Draw a vertical line on screen column x from ymin to ymax.
   Use '|' in the middle of the lines and '+' at the ends. */
vert (x, ymin, ymax) int    x, ymin, ymax;
{
    int     y;
    standout ();
    for (y = ymin; y <= ymax; y++)
	mvaddch (y, x, (y == ymin || y == ymax) ? '+' : '|');
    standend ();
}

showset (line, set) unsigned line, set;
{
    char    c = 'a' - 1;
    clearline (line);
    move (line, 10);
    while (set) {
	if (set & 1)
	    addch (c);
	set >>= 1;
	c++;
    }
}

posit (fill, r, c) char fill[17][17]; unsigned r, c;
{
    if (fill == afill)
	position (r, c);
    else
	position (c, r);
}

beep ()
{
    putchar ('\007');
}

errortell (s) char *s;
{
    centerprint (ERRORLINE, s);
}

tell (s) char *s;
{
    centerprint (MSGLINE, s);
}

static int helpline;
static int whichhelp = 0;

picture ()
{
    centerprint (BOARDLINE - 1, "CRAB 1.3 - Jacoppel Enterprises");
 /* Draw a box around the board */
    horiz (Ypos (0), Xpos (0), Xpos (LEN + 1));
    horiz (Ypos (LEN + 1), Xpos (0), Xpos (LEN + 1));
    vert (Xpos (0), Ypos (0), Ypos (LEN + 1));
    vert (Xpos (LEN + 1), Ypos (0), Ypos (LEN + 1));
    whichhelp = 0;
    givehelp ();
}


starthelp ()
{
    helpline = HELPWLINE;
}

helps (r, s) char *r, *s;
{
    move (helpline, HELPWCOL);
    clrtoeol ();
    addstr (r);
    mvaddstr (helpline++, HELPWCOL2, s);
}

helpc (c, s) char c, *s;
{
    move (helpline, HELPWCOL);
    clrtoeol ();
    addch (c);
    mvaddstr (helpline++, HELPWCOL2, s);
}

helpt (s) char *s;
{
    move (helpline++, HELPWCOL2 - 3);
    clrtoeol ();
    standout ();
    addstr (s);
    standend ();
    addch (' ');
    clrtoeol ();
}

helpx ()
{
    move (helpline++, HELPWCOL);
    clrtoeol ();
}

endhelp ()
{
    int     dummy;
    getyx (stdscr, helpline, dummy);
    helpline++;
    while (helpline < LINES)
	helpx ();
}

givehelp ()
{
    int     i;
    starthelp ();
    switch (++whichhelp) {
	default: 
	    whichhelp = CMDHELP;
	case CMDHELP: 
	    helpt (" Commands ");
	    helpx ();
	    helps ("0-9", "Move Cursor");
	    helps ("a-z", "Place Letter");
	    helpc ('#', "Place Blank");
	    helps ("space", "Remove Tile");
	    helpx ();
	    helpc ('.', "Make Move");
	    helpc (':', "Make Bogus Move");
	    helpc ('-', "Exchange Tiles");
	    helpc ('=', "Pass");
	    helpc ('+', "Quit Game");
	    helpc ('~', "Suggest Move");
	    helpx ();
	    helpc ('?', "Get More Help");
	    break;
	case KEYHELP: 
	    helpt ("    Key   ");
	    helpx ();
	    helps ("A-Z", "Normal Tile");
	    helps ("a-z", "Blank on Board");
	    helpc ('#', "Blank in Rack");
	    helpc (TILEBACK, "Back of Tile");
	    helpx ();
	    helpc (LETx2, "Double Letter");
	    helpc (LETx3, "Triple Letter");
	    helpc (WORDx2, "Double Word");
	    helpc (WORDx3, "Triple Word");
	    break;
	case TILEHELP: 
	    helpt ("   Tiles  ");
	    helpx ();
	    helps ("Value", " #Unaccounted");
	    helpx ();
	    for (i = 1; i < 28; ++i)
		showtilecount (i);
	    break;
    }
    endhelp ();
}

#define HELPMID		((HELPWCOL + COLS) / 2)

showtilecount (k) int k;
{
    int     x,
            y;
    if (whichhelp != TILEHELP)
	return;
    if (k < 14) {
	move (HELPWLINE + 3 + k, HELPWCOL);
	prtile (k);
	getyx (stdscr, y, x);
	while (x++ < HELPMID)
	    addch (' ');
    }
    else
	if (k < 27) {
	    move (HELPWLINE - 10 + k, HELPMID);
	    clrtoeol ();
	    prtile (k);
	}
	else {
	    move (HELPWLINE + 17, HELPWCOL);
	    clrtoeol ();
	    printw ("    Blank[0] %d", rack[k] + sock[k]);
	}
}

prtile (k) int k;
{
    register    value = lettervalue[k];
    register    unaccounted = rack[k] + sock[k];
    if (unaccounted > 9 || value > 9)
	printw ("%c[%d] %d", '@' + k, value, unaccounted);
    else
	printw ("%c[%d]  %d", '@' + k, value, unaccounted);
}

thinking (amI)
{
    mvprintw (MYLINE - 1, RACKCOL, amI ? "THINKING" : "        ");
}

showsock ()
{
    int     i;
    mvprintw (SOCKLINE - 1, SOCKCOL, " Tiles Remaining: %2d", socksize);
    for (i = socksize; i >= 0; i--) {
	sockposition (i);
	if (inch () == TILEBACK)
	    break;
	addch (TILEBACK);
    }

    for (i = socksize; i < 100; i++) {
	sockposition (i);
	if (inch () == ' ')
	    break;
	addch (' ');
    }
}

sockposition (i) int i;
{
    move (SOCKLINE + i % 5, SOCKCOL + i / 5 + (i / 5 > 9));
}

showstuff ()
{
    int     i,
            j;

    showsock ();

    mvprintw (MYLINE, RACKCOL, "CRAB's score: %3d", myscore);
    showrack (MYLINE + 1, rack, FALSE);

    mvprintw (YOURLINE, RACKCOL, "Your score: %3d", yourscore);
    showrack (YOURLINE + 1, yourrack, TRUE);
}

showrack (y, rak, visible) int y, visible; char *rak;
#define V(x) (visible ? (x) : TILEBACK)
{
    int     i,
            j;
    move (y, RACKCOL);
    for (i = 1; i < 27; i++)
	for (j = 0; j < rak[i]; j++) {
	    addch (V (i | '@'));
	    addch (' ');
	}
    for (j = 0; j < rak[27]; j++) {
	addch (V ('#'));
	addch (' ');
    }
    getyx (stdscr, i, j);
    while (j++ < RACKCOL + 15)
	addch (' ');
}
	
int showpoints (y, rak) int y; char *rak;
{
    int     i,
            j;
    move (y, RACKCOL);
    for (i = 1; i < 28; i++)
	for (j = 0; j < rak[i]; j++)
	    printw ("%d ", lettervalue[i]);
    getyx (stdscr, i, j);
    while (j < RACKCOL + 15) {
	addch (' ');
	j++;
    }
    printw ("= %2d", pointrack (rak));
}

int pointrack (rak) char *rak;
{
    int     i,
            tot = 0;
    for (i = 1; i < 28; i++)
	tot += rak[i] * lettervalue[i];
    return (tot);
}

endgame ()
{
    int     mytot,
            yourtot;
    thinking (0);
    yourtot = pointrack (yourrack);
    mytot = pointrack (rack);
    myscore -= mytot;
    yourscore -= yourtot;
    if (anyrackempty) {
	myscore += yourtot;
	yourscore += mytot;
    }
    showstuff ();
    showrack (MYLINE + 1, rack, TRUE);
    showpoints (MYLINE + 2, rack);
    showpoints (YOURLINE + 2, yourrack);
    if (myscore > yourscore)
	tell ("The game is over.  CRAB wins.");
    else
	if (yourscore > myscore)
	    tell ("The game is over.  You win.");
	else
	    tell ("The game is a draw.");
}

quit ()
{
    char    c;
    beep ();
    errortell ("Play again?");
    refresh ();
    while ((c = getch ()) != 'n' && c != 'y')
	beep ();
    if (c == 'y') restart ();
 /* Quit - Move cursor to bottom of screen and fix up funny terminal modes
    we set */
    move (LINES - 1, 0);
    refresh ();
    noraw ();
    echo ();
    endwin ();
    exit ();
}
