
/* RCS Info: $Revision: 1.2 $ on $Date: 89/03/15 16:33:18 $
 *           $Source: /yew3/faustus/src/scrabble/RCS/tty.c,v $
 * Copyright (c) 1989 Wayne A. Christopher, U. C. Berkeley CS Dept
 *      faustus@renoir.berkeley.edu, ucbvax!faustus
 * Permission is granted to modify and re-distribute this code in any manner
 * as long as this notice is preserved.  All standard disclaimers apply.
 *
 */

#include "scrabble.h"
#include <curses.h>
#undef bool

static WINDOW *boardwin, *scores, *summary, *dialog;
#ifdef notdef
static WINDOW *title;
#endif

static char lbchar[] = " `\"(<";
static char rbchar[] = " '\")>";

static int messline = 0;

#define bpos(px, py, x, y)     (px) = 3 * (x) + 4; (py) = (y) + 1;
#define MESS_SIZE              5
#define beep()                 putc('\007', stderr); fflush(stderr);

static char *help[] = {
"Scrabble Version 1.0, by Wayne Christopher (faustus@renoir.Berkeley.EDU)    ",
"                                                                            ",
"    The rules of the game are the same as those of the board game, and will ",
"    not be described here.  The screen is divided up into a board area,     ",
"    which the player can move around in, a status and score window to the   ",
"    right, and a message window at the bottom.  A star appears by the name  ",
"    of the player whose turn it is, and if this is not a machine player the ",
"    commands below may be given.  The commands H, V, Q, and T terminate the ",
"    player's turn, assuming the word is valid.                              ",
"                                                                            ",
"Available commands are:                                                     ",
"    h, j, k, l : Move the cursor around the board.                          ",
"    H          : Create a horizontal word at the cursor position.           ",
"    V          : Create a vertical word at the cursor position.             ",
"    T          : Trade in a number of tiles for new tiles.                  ",
"    S          : Save the game into a file.                                 ",
"    R          : Restore a game from a file (loses the current game).       ",
"    A          : Ask for advice from the computer.                          ",
"    Q          : Quit the game.                                             ",
"    ^L         : Redraw the screen.                                         ",
"    ?          : Print this help message.                                   "
} ;

void
tty_init(board_t *board, player_t *players[], int numplayers)
{
       int i, j;
       int x, y;

       initscr();
       noecho();
       crmode();

#ifdef notdef
       title = newwin(2, 80, 0, 0);
#endif
       boardwin = newwin(17, 51, 0, 0);
       scores = newwin(9, 29, 3, 51);
       summary = newwin(3, 29, 14, 51);
       dialog = newwin(0, 80, 18, 0);

#ifdef notdef
       /* Draw the title... */
       wmove(title, 0, 7);
       wprintw(title, "Scrabble %s, by %s (%s)", VERSION, AUTHOR, ADDRESS);
#endif

       /* Draw the board...  top and bottom... */
       for (i = 0; i < 15; i++) {
               wmove(boardwin, 0, 3 * i + 4);
               wprintw(boardwin, "%-2d", i);
               wmove(boardwin, 16, 3 * i + 4);
               wprintw(boardwin, "%-2d", i);
       }

       /* Left and right... */
       for (i = 0; i < 15; i++) {
               wmove(boardwin, 1 + i, 0);
               wprintw(boardwin, "%2d", i);
               wmove(boardwin, 1 + i, 49);
               wprintw(boardwin, "%-2d", i);
       }
       for (i = 0; i < 15; i++)
               for (j = 0; j < 15; j++) {
                       bpos(x, y, i, j);
                       wmove(boardwin, y, x - 1);
                       waddch(boardwin, lbchar[board->bonus[j][i]]);
                       wmove(boardwin, y, x);
                       waddch(boardwin, '.');
                       wmove(boardwin, y, x + 1);
                       waddch(boardwin, rbchar[board->bonus[j][i]]);
               }
       
       /* Draw the scores display... */
       wmove(scores, 0, 0);
       wprintw(scores, "      Scrabble %s", VERSION);
       wmove(scores, 1, 0);
       wprintw(scores, "   by %s", AUTHOR);

       wmove(scores, 3, 0);
       wprintw(scores, "   Name  Score   Letters");
       for (i = 0; i < numplayers; i++)
               tty_drawplayer(players[i], i, (i == 0) ? true : false);

       /* Draw the summary window. */
       tty_drawsummary(board, 0);

       /* The dialog window is blank. */

       wrefresh(boardwin);

       return;
}

void
tty_message(char *message)
{
       /* Print the message and clear the line below it. */
       messline = (messline + 1) % MESS_SIZE;
       if (messline < MESS_SIZE - 1) {
               wmove(dialog, messline + 1, 0);
               wclrtoeol(dialog);
       }
       wmove(dialog, messline, 0);
       wclrtoeol(dialog);
       wprintw(dialog, "%s", message);

       wrefresh(dialog);

       return;
}

char *
tty_question(char *message)
{
       static char buf[BSIZE];

       tty_message(message);
       wmove(dialog, messline, strlen(message) + 1);
       wrefresh(dialog);
       echo();
       nocrmode();
       wgetstr(dialog, buf);
       crmode();
       noecho();

       return (buf);
}

bool
tty_confirm(char *message)
{
       char c;

       tty_message(message);
       wmove(dialog, messline, strlen(message) + 1);
       wrefresh(dialog);
       c = wgetch(dialog);

       if ((c == 'y') || (c == 'Y'))
               return (true);
       else
               return (false);
}

/* Let the player move to a place in the board, type 'h' or 'v', then enter
 * a word.  Other commands are 'T', 'S', 'R', 'Q', and '?'.
 */

command_t
tty_command(board_t *board, player_t *player, move_t *mv)
{
       int x = 7, y = 7;
       int px, py;
       bool horiz = false, done = false;
       char *word, buf[BSIZE];
       char c;
       int i;

       for (;;) {
               bpos(px, py, x, y);
               wmove(boardwin, py, px);
               wrefresh(boardwin);
               c = wgetch(boardwin);
               switch (c) {
                   case '\014':
                       tty_update();
                       break;

                   case 'h':
                       if (x > 0)
                               x--;
                       else {
                               beep();
                       }
                       break;

                   case 'j':
                       if (y < SIZE - 1)
                               y++;
                       else {
                               beep();
                       }
                       break;

                   case 'k':
                       if (y > 0)
                               y--;
                       else {
                               beep();
                       }
                       break;

                   case 'l':
                       if (x < SIZE - 1)
                               x++;
                       else {
                               beep();
                       }
                       break;

                   case 'H':
                       horiz = true;
                       done = true;
                       break;

                   case 'V':
                       horiz = false;
                       done = true;
                       break;

                   case 'T':
                        return (TRADEIN);

                   case 'S':
                       return (SAVE);

                   case 'R':
                       return (RESTORE);

                   case 'A':
                       return (ADVICE);

                   case 'Q':
                       if (tty_confirm("Really quit?"))
                               return (QUIT);
                       else
                               break;

                   case '?':
                       return (HELP);

                   default:
                       beep();
                       break;
               }

               if (done)
                       break;
       }

       if (horiz)
               sprintf(buf, "Horiz word at (%d, %d):", x, y);
       else
               sprintf(buf, "Vert word at (%d, %d):", x, y);

       word = tty_question(buf);

       if (strlen(word) > SIZE)
               word[SIZE] = '\0';

       mv->word = strsav(word);
       mv->x = x;
       mv->y = y;
       mv->length = strlen(word);
       mv->horiz = horiz;
       mv->points = 0;

       for (i = 0; i < SIZE; i++)
               mv->wild[i] = false;

       for (i = 0; i < mv->length; i++) {
               if (!isalpha(mv->word[i])) {
                       tty_message("Invalid word.");
                       return (NOTHING);
               } else if (isupper(mv->word[i])) {
                       mv->word[i] = tolower(mv->word[i]);
               }
       }

       return (MOVE);
}

void
tty_drawplayer(player_t *player, int pos, bool up)
{
       int i;

       wmove(scores, pos + 5, 0);
       wprintw(scores, " %c %-6.6s %3d ", up ? '*' : ' ', player->name,
                       player->score);
       for (i = 0; i < player->numworking; i++)
               wprintw(scores, " %c", player->working[i]);
       wclrtoeol(scores);
       wmove(scores, pos + 5, 0);
       wrefresh(scores);

       return;
}

void
tty_drawsummary(board_t *board, int turn)
{
       wmove(summary, 0, 0);
       wprintw(summary, "     Game turn:  %d   ", turn);
       wmove(summary, 1, 0);
       wprintw(summary, "    Tiles left:  %d   ", board->numleft);
       wrefresh(summary);

       return;
}

void
tty_drawmove(board_t *board, move_t *mv, player_t *player)
{
       int i, x, y;
       char c;
       char buf[BSIZE];

       for (i = 0; i < mv->length; i++) {
               c = mv->word[i];
               if (!mv->wild[i])
                       c = toupper(c);
               if (mv->horiz) {
                       bpos(x, y, mv->x + i, mv->y);
               } else {
                       bpos(x, y, mv->x, mv->y + i);
               }

assert((x >= 0) && (x < 51) && (y >= 0) && (y < 17));

               wmove(boardwin, y, x);
               waddch(boardwin, c);
       }
       wrefresh(boardwin);
       sprintf(buf, "%s: \"%s\" at (%d, %d), %s, %d points.", player->name,
                       mv->word, mv->x, mv->y, mv->horiz ? "horiz" : "vert",
                       mv->points);
       tty_message(buf);

       return;
}

void
tty_givehelp()
{
       WINDOW *hwin = newwin(24, 80, 0, 0);
       int i;

       wclear(hwin);
       overwrite(hwin, stdscr);
       wrefresh(hwin);
       wrefresh(stdscr);

       for (i = 0; i < sizeof (help) / sizeof (help[0]); i++) {
               wmove(hwin, i, 0);
               wprintw(hwin, "%s", help[i]);
       }

       wmove(hwin, i + 1, 0);
       wprintw(hwin, "Hit return to continue...");
       wrefresh(hwin);
       (void) wgetch(hwin);

       wclear(hwin);
       wrefresh(hwin);

       delwin(hwin);

       touchwin(boardwin);
       touchwin(scores);
       touchwin(summary);
       touchwin(dialog);

       tty_update();

       return;
}

void
tty_update()
{
       wrefresh(boardwin);
       wrefresh(scores);
       wrefresh(summary);
       wrefresh(dialog);

       return;
}

void
tty_cleanup()
{
       move(23, 0);
       clrtoeol();
       refresh();
       endwin();
       return;
}

