games@tekred.CNA.TEK.COM (04/07/89)
Submitted-by: "Wayne A. Christopher" <faustus@dogwood.Berkeley.EDU> Posting-number: Volume 6, Issue 46 Archive-name: scrabble/Part01 [This game needs an ANSI C compatable compiler such as gcc (or Turbo C if you try and port it to a PC), since function prototyping is used. Not having a copy of gcc around and not wanting to convert the source, I haven't tested this. -br] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 2)." # Contents: README MANIFEST Makefile date.h dict.c move.c refresh.c # scrabble.c scrabble.h tty.c # Wrapped by billr@saab on Thu Apr 6 12:40:38 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(1811 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X X Scrabble 1.0, by Wayne Christopher (faustus@yew.Berkeley.EDU) X XThis program plays the board game Scrabble. It uses curses, but it Xshould be easy for somebody to add X10 or X11 support (if anybody does, Xplease tell me). X XIt plays a pretty strong game, usually getting scores between 350 and X400. The major problem is its dictionary -- I have a file that Xcontains most of /usr/dict/words along with plurals, but there are lots Xof word modifications it doesn't know about (-ing, -ed, ...). There Xare also "plurals" for adjectives, which are usually wrong. I'm not Xincluding this file because it's too large, but if you pipe X/usr/dict/words through the plural program (also in this directory) and Xmerge the output with /usr/dict/words, and then take out things like XRoman numerals and any other non-words you find, you should have a Xpretty good word list. The program will remember when you tell it Xabout a word it doesn't know, or tell it it's using a bad word (if you Xgive the -c option), and update the dictionary file so it can learn Xfrom experience. If anybody knows of a good wordlist, with all the Xvarious forms of words, or for that matter a wordlist with parts of Xspeech, please tell me about it. X XTo install it, update the DICT_DEF definition at the top of the XMakefile to indicate where you have installed the dictionary (it's ok Xto make it /usr/dict/words). You need an ANSI C compiler -- I've only Xused gcc. The file refresh.c, which is part of curses, is included Xbecause I had problems when I compiled the program with gcc against the Xstandard Sun libcurses.a -- I think it has something to do with the Xfact that refresh.c uses register function arguments. In any case, it Xwent away when I gcc'ed refresh.c also. On another machine you could Xprobably take this file out of the Makefile. X END_OF_FILE if test 1811 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(672 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X MANIFEST 1 This shipping list X Makefile 1 X README 1 X board.c 2 X curses.ext 2 X date.h 1 X dict.c 1 X move.c 1 X player.c 2 X plural.c 2 X refresh.c 1 X savegame.c 2 X scrabble.c 1 X scrabble.h 1 X tty.c 1 X user.c 2 X util.c 2 X util.h 2 END_OF_FILE if test 672 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(4846 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X X# RCS Info: $Revision: 1.2 $ on $Date: 89/03/15 11:16:17 $ X# $Source: /yew3/faustus/src/scrabble/RCS/Makefile,v $ X# Copyright (c) 1987 Wayne A. Christopher, U. C. Berkeley CAD Group X# X# Program Makefile X# X# This makefile has the standard options "clean", "require", and "install". X# Also available are "lint", "depend", "tags", "opt", "debug", and "prof". X# "opt" causes the program to be compiled optimized, "debug" with -g, and X# "prof" with -pg. As an added bonus, the Makefile remembers the last of X# these options given. X Xwhat: all X X#---- Tool specific stuff ---- X XDICT_DEF = -DDICT_FILE=\"dictionary\" X XPROGRAM = scrabble X XSRC = \ X board.c \ X dict.c \ X move.c \ X player.c \ X savegame.c \ X scrabble.c \ X tty.c \ X user.c \ X util.c refresh.c X XOBJ = \ X board.o \ X dict.o \ X move.o \ X player.o \ X savegame.o \ X scrabble.o \ X tty.o \ X user.o \ X util.o refresh.o X XHDR = \ X scrabble.h \ X util.h X XSUPPORT = plural X XSABER_HDR = scrabble.h X XREQUIRE = X XSPEC_OPT_LIBS = X XSPEC_DEBUG_LIBS = X XSPEC_PROF_LIBS = X XSPEC_LINT_LIBS = X XSPEC_INCLUDE = -I. -I../include X XSPEC_DEFINES = $(DICT_DEF) X XMAN_SECTION = 1 X XDOC = X XMISC = X XCC = gcc -W -fwritable-strings X XOPT_LIBS = $(SPEC_OPT_LIBS) X XDEBUG_LIBS = $(SPEC_DEBUG_LIBS) X XPROF_LIBS = $(SPEC_PROF_LIBS) X XOPT_LDFLAGS = -lcurses -ltermlib -lX -lm -O X XDEBUG_LDFLAGS = -lcurses -ltermlib -lX -lm -g X XPROF_LDFLAGS = -lcurses -ltermlib -lX_p -lm_p -pg X XMAN_PAGE = $(PROGRAM).$(MAN_SECTION) X X#---- State ---- X XCFLAGS=-O -g XLIBS=$(OPT_LIBS) XLDFLAGS=$(OPT_LDFLAGS) X X#---- Generic stuff ---- X X# EXTDEFINES are things that come from a higher-level Makefile X XEXTDEFINES = X XDEFINES = $(EXT_DEFINES) $(SPEC_DEFINES) X XINCLUDE = $(SPEC_INCLUDE) X XLINT_LIBS = $(SPEC_LINT_LIB) X XLINT_FLAGS = -DLINT -u -z -lc X X.c.o: $*.c X $(CC) $(DEFINES) $(INCLUDE) $(CFLAGS) -c $*.c X Xall: date.h $(PROGRAM) $(SUPPORT) .saberinit X @echo "All done." X X$(PROGRAM): $(OBJ) $(LIBS) X rm -f $(PROGRAM) X $(CC) -o $(PROGRAM) $(OBJ) $(LIBS) $(LDFLAGS) X X$(SUPPORT): $(SUPPORT).o X rm -f $(SUPPORT) X $(CC) -o $(SUPPORT) $(SUPPORT).o $(LIBS) $(LDFLAGS) X Xdate.h: /tmp X @echo \#define DATE \"`date`\" > date.h X @echo \#define HOST \"`hostname`\" >> date.h X @echo \#define USER \"`whoami`\" >> date.h X X#---- Stuff that changes our state ---- X Xopt: X @-if egrep -s '^CFLAGS=-O' Makefile ; then \ X echo already -O ... ; \ X else echo converting from $(CFLAGS) to -O ; \ X sed -e 's/^CFLAGS=.*$$/CFLAGS=-O/' \ X -e 's/^LIBS=.*$$/LIBS=\$$\(OPT_LIBS\)/' \ X -e 's/^LDFLAGS=.*$$/LDFLAGS=\$$\(OPT_LDFLAGS\)/' \ X < Makefile > mktemp ; \ X mv mktemp Makefile ; \ X rm *.o ; \ X fi X @make $(MFLAGS) X Xdebug: X @-if egrep -s '^CFLAGS=-g' Makefile ; then \ X echo already -g ... ; \ X else echo converting from $(CFLAGS) to -g ; \ X sed -e 's/^CFLAGS=.*$$/CFLAGS=-g/' \ X -e 's/^LIBS=.*$$/LIBS=\$$\(DEBUG_LIBS\)/' \ X -e 's/^LDFLAGS=.*$$/LDFLAGS=\$$\(DEBUG_LDFLAGS\)/' \ X < Makefile > mktemp ; \ X mv mktemp Makefile ; \ X rm *.o ; \ X fi X @make $(MFLAGS) X Xprof: X @-if egrep -s '^CFLAGS=-pg' Makefile ; then \ X echo already -pg -O ... ; \ X else echo converting from $(CFLAGS) to -pg -O ; \ X sed -e 's/^CFLAGS=.*$$/CFLAGS=-pg -O/' \ X -e 's/^LIBS=.*$$/LIBS=\$$\(PROF_LIBS\)/' \ X -e 's/^LDFLAGS=.*$$/LDFLAGS=\$$\(PROF_LDFLAGS\)/' \ X < Makefile > mktemp ; \ X mv mktemp Makefile ; \ X rm *.o ; \ X fi X @make $(MFLAGS) X Xcheckin: X ci $(SRC) $(HDR) $(MAN_PAGE) Makefile $(DOC) $(MISC) </dev/null X rcs -U $(SRC) $(HDR) $(MAN_PAGE) Makefile $(DOC) $(MISC) X Xcheckout: X co $(SRC) $(HDR) $(MAN_PAGE) $(DOC) $(MISC) </dev/null X X#---- Stuff for lint ---- X Xlint: $(SRC) $(HDR) X lint $(LINT_FLAGS) $(DEFINES) $(INCLUDE) $(SRC) $(LINT_LIBS) X X#---- Stuff for "make install" ---- X X#install: $(INSTALLED) $(MAN_INSTALLED) X# X#$(INSTALLED): $(TARGET) X# cp $(TARGET) $(INSTALLED) X# strip $(TARGET) $(INSTALLED) X# X#$(MAN_INSTALLED): $(MAN_PAGE) X# cp $(MAN_PAGE) $(MAN_INSTALLED) X X#---- Misc junk ---- X Xdist: X rdist -Rich $(SRC) $(SUPPSRC) $(HDR) $(MAN_PAGE) $(DOC) \ X $(MISC) Makefile $(DIST) X Xprint: X psgrind -2r -Plps $(HDR) $(SRC) $(SUPPSRC) X Xrequire: X @echo $(REQUIRE) X Xclean: X rm -f $(TARGET) $(SUPPORT) $(OBJ) $(SUPPOBJ) tags *.out foo tmp X Xtags: $(SRC) $(HDR) $(SUPPSRC) X ctags -w -t $(SRC) $(HDR) $(SUPPSRC) > /dev/null 2>&1 X Xdepend: $(SRC) $(SUPPSRC) X cc -M $(DEFINES) $(INCLUDE) $(CFLAGS) $(SRC) $(SUPPSRC) > makedep X echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep X echo '$$r makedep' >>eddep X echo 'w' >>eddep X ed - Makefile < eddep X rm eddep makedep X echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile X echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile X echo '# see make depend above' >> Makefile X X.saberinit: Makefile X @echo load $(SRC) $(LIBS) $(LDFLAGS) > .saberinit X X#----------------------------------------------------------------- X# DO NOT DELETE THIS LINE -- make depend uses it X# DEPENDENCIES MUST END AT END OF FILE X END_OF_FILE if test 4846 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'date.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'date.h'\" else echo shar: Extracting \"'date.h'\" \(84 characters\) sed "s/^X//" >'date.h' <<'END_OF_FILE' X#define DATE "Thu Apr 6 12:36:51 PDT 1989" X#define HOST "saab" X#define USER "billr" END_OF_FILE if test 84 -ne `wc -c <'date.h'`; then echo shar: \"'date.h'\" unpacked with wrong size! fi # end of 'date.h' fi if test -f 'dict.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dict.c'\" else echo shar: Extracting \"'dict.c'\" \(5716 characters\) sed "s/^X//" >'dict.c' <<'END_OF_FILE' X X/* RCS Info: $Revision: 1.2 $ on $Date: 89/03/15 11:16:27 $ X * $Source: /yew3/faustus/src/scrabble/RCS/dict.c,v $ X * Copyright (c) 1989 Wayne A. Christopher, U. C. Berkeley CS Dept X * faustus@renoir.berkeley.edu, ucbvax!faustus X * Permission is granted to modify and re-distribute this code in any manner X * as long as this notice is preserved. All standard disclaimers apply. X * X */ X X#include "scrabble.h" X Xstatic int dicthash(char *word, int tabsize); Xstatic void getem(word_t **wordp, char *lbuf, int place, char *opt, X int numopt, int len); X Xstatic dict_t *dictionary; X Xvoid Xreaddict(char *file) X{ X FILE *fp; X char buf[BSIZE], *e; X word_t *ww; X int i, j, k, n, t; X X if (!(fp = fopen(file, "r"))) { X perror(file); X exit(0); X } X fprintf(stderr, "Reading \"%s\" ", file); X fflush(stderr); X X dictionary = (dict_t *) util_malloc(sizeof (dict_t)); X for (i = 0; i < MAX_LENGTH; i++) X for (j = 0; j < HASH_SIZE; j++) X dictionary->buckets[i][j] = NULL; X dictionary->size = 0; X X while (fgets(buf, BSIZE, fp)) { X if (isupper(buf[0]) || !buf[2]) X continue; X X for (e = buf; *e; e++) X ; X *--e = '\0'; X addword(buf); X X#ifdef notdef X /* Add the plural... */ X s = e - 1; X if (index("sxz", *s)) { X *++s = 'e'; X *++s = 's'; X *++s = '\0'; X } else { X *++s = 's'; X *++s = '\0'; X } X addword(buf); X *e = '\0'; X#endif X } X X fprintf(stderr, " %d words.\n", dictionary->size); X X if (debug) { X fprintf(stderr, "Stats:\n"); X for (i = 0; i < MAX_LENGTH; i++) { X fprintf(stderr, "\t%d:", i + 1); X n = t = 0; X for (j = 0; j < HASH_SIZE; j++) { X for (ww = dictionary->buckets[i][j], k = 0; ww; X ww = ww->next) X k++; X /* fprintf(stderr, " %d", k); */ X if (k) X n++; X t += k; X } X fprintf(stderr, " %d / %d full, %d total\n", X n, HASH_SIZE, t); X } X } X X fclose(fp); X X return; X} X Xvoid Xwritedict(char *file) X{ X int i, j, k = 0; X word_t *word; X FILE *fp; X char buf[BSIZE]; X X if (!(fp = fopen(file, "w"))) { X perror(file); X return; X } X X for (i = 0; i < MAX_LENGTH; i++) X for (j = 0; j < HASH_SIZE; j++) X for (word = dictionary->buckets[i][j]; word; X word = word->next) { X fprintf(fp, "%s\n", word->word); X k++; X } X X fclose(fp); X X sprintf(buf, "Wrote %d words to %s.", k, file); X user_message(buf); X X return; X} X Xvoid Xaddword(char *word) X{ X int key = dicthash(word, HASH_SIZE); X int len = strlen(word); X word_t *ww; X X if ((key == -1) || (len > SIZE)) X return; X X ww = (word_t *) util_malloc(sizeof (word_t)); X X ww->word = strsav(word); X ww->length = len; X ww->next = dictionary->buckets[len - 1][key]; X dictionary->buckets[len - 1][key] = ww; X X dictionary->size++; X X if (dictionary->size % 1000 == 0) { X fprintf(stderr, "."); X fflush(stderr); X } X X return; X} X Xvoid Xremword(char *word) X{ X int key = dicthash(word, HASH_SIZE); X int len = strlen(word); X word_t *ww, *lw = NULL; X X for (ww = dictionary->buckets[len - 1][key]; ww; ww = ww->next) { X if (eq(ww->word, word)) X break; X lw = ww; X } X X assert(ww); X X if (lw) X lw->next = ww->next; X else X dictionary->buckets[len - 1][key] = ww->next; X X dictionary->size--; X X return; X} X Xbool Xisaword(char *poss) X{ X word_t *word; X int len = strlen(poss); X int key = dicthash(poss, HASH_SIZE); X X if (key == -1) X return (false); X X for (word = dictionary->buckets[len - 1][key]; word; word = word->next) X if (eq(word->word, poss)) X return (true); X X return (false); X} X X/* Return a list of the buckets containing all the words we could make with X * the given letters and are of the given length. Look at all the combinations X * that include all the required ones and enough optional ones to make X * up the length. X */ X Xword_t * Xgetpossibles(char *opt, int numopt, char *req, int numreq, int len) X{ X char lbuf[SIZE]; X int i; X word_t *word = NULL; X int wc1 = -1, wc2 = -1; X X for (i = 0; i < numreq; i++) X lbuf[i] = req[i]; X X if (numreq + numopt < len) X return (NULL); X X for (i = 0; i < numopt; i++) X if (opt[i] == WILD) { X if (wc1 == -1) X wc1 = i; X else X wc2 = i; X } X X if (wc1 > -1) { X for (opt[wc1] = 'a'; opt[wc1] <= 'z'; opt[wc1]++) { X if (wc2 > -1) { X for (opt[wc2] = 'a'; opt[wc2] <= 'z'; X opt[wc2]++) X getem(&word, lbuf, numreq, opt, numopt, X len); X opt[wc2] = WILD; X } else X getem(&word, lbuf, numreq, opt, numopt, len); X } X opt[wc1] = WILD; X } else X getem(&word, lbuf, numreq, opt, numopt, len); X X return (word); X} X Xstatic void Xgetem(word_t **wordp, char *lbuf, int place, char *opt, int numopt, int len) X{ X int key; X word_t *set, *ww; X Xassert(numopt >= 0); X X if ((numopt == len - place) || (place == len)) { X while (place < len) X lbuf[place++] = *opt++; X lbuf[len] = '\0'; X key = dicthash(lbuf, HASH_SIZE); X set = dictionary->buckets[len - 1][key]; X if (set) { X for (ww = *wordp; ww; ww = ww->next_set) X if (ww == set) X break; X if (ww) X return; X X set->next_set = *wordp; X *wordp = set; X#ifdef notdef X if (debug) { X fprintf(stderr, "\t\t"); X for (ww = set; ww; ww = ww->next) X fprintf(stderr, " %s", ww->word); X fprintf(stderr, "\n"); X } X#endif X } X } else { X lbuf[place] = *opt; X getem(wordp, lbuf, place + 1, opt + 1, numopt - 1, len); X getem(wordp, lbuf, place, opt + 1, numopt - 1, len); X } X X return; X} X X#define NLETTERS 28 /* So it's a multiple of 4. */ X X/* A return value of -1 denotes that this is a bad word. */ X Xstatic int Xdicthash(char *word, int tabsize) X{ X int i; X unsigned long result = 0; X unsigned long letters[NLETTERS]; X char *s; X X for (i = 0; i < NLETTERS; i++) X letters[i] = 0; X X for (s = word; *s; s++) { X if (!isalpha(*s)) X return (-1); X letters[isupper(*s) ? (*s - 'A') : (*s - 'a')]++; X } X X for (i = 0; i < NLETTERS; i++) X result ^= letters[i] << i; X X return (result % tabsize); X} X END_OF_FILE if test 5716 -ne `wc -c <'dict.c'`; then echo shar: \"'dict.c'\" unpacked with wrong size! fi # end of 'dict.c' fi if test -f 'move.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'move.c'\" else echo shar: Extracting \"'move.c'\" \(9358 characters\) sed "s/^X//" >'move.c' <<'END_OF_FILE' X X/* RCS Info: $Revision: 1.2 $ on $Date: 89/03/15 11:16:30 $ X * $Source: /yew3/faustus/src/scrabble/RCS/move.c,v $ X * Copyright (c) 1989 Wayne A. Christopher, U. C. Berkeley CS Dept X * faustus@renoir.berkeley.edu, ucbvax!faustus X * Permission is granted to modify and re-distribute this code in any manner X * as long as this notice is preserved. All standard disclaimers apply. X * X */ X X#include "scrabble.h" X Xstatic void dopos(board_t *board, player_t *player, int x, int y, X bool horiz, move_t *best); Xstatic int wordpoints(board_t *board, int x, int y, bool horiz, int len, X char *word, char subc, int wx, int wy, bool allbonuses, X bool *wilds); Xstatic bool validword(board_t *board, int x, int y, int len, char subc, X bool horiz, bool machine, bool check); Xstatic bool validlocation(board_t *board, int x, int y, bool horiz, int len); X Xvoid Xbestmove(board_t *board, player_t *player, move_t *best) X{ X int x, y; X move_t try; X X best->points = -1; X X for (x = 0; x < SIZE; x++) X for (y = 0; y < SIZE; y++) { X dopos(board, player, x, y, true, &try); X if (try.points > best->points) X *best = try; X dopos(board, player, x, y, false, &try); X if (try.points > best->points) X *best = try; X } X X return; X} X X#ifdef notdef X Xvoid Xprintmove(int which, move_t *move, FILE *fp) X{ X fprintf(fp, "Player %d: \"%s\", %s at (%d, %d) for %d points.\n", X which, move->word, move->horiz ? "horiz" : "vert", X move->x, move->y, move->points); X X return; X} X X#endif X Xstatic void Xdopos(board_t *board, player_t *player, int x, int y, bool horiz, move_t *best) X{ X char opt[SIZE]; X char req[SIZE]; X int numopt, numreq; X word_t *words, *set, *word; X int i, j, len; X char c; X move_t try; X X best->points = -1; X X try.x = x; X try.y = y; X try.horiz = horiz; X X for (len = 1; horiz ? (x + len <= SIZE) : (y + len <= SIZE); len++) { X try.length = len; X X /* First make sure this is a place we can put a word. */ X if (!validlocation(board, x, y, horiz, len)) X continue; X X#ifdef notdef X if (debug) X fprintf(stderr, "\t(%d, %d), %s, len %d ---\n", X x, y, horiz ? "horiz" : "vert", len); X#endif X X /* Make the letter set. */ X for (i = 0, numopt = 0; i < player->numworking; i++) X opt[i] = player->working[i]; X numopt = player->numworking; X X for (j = 0, numreq = 0; j < len; j++) { X c = boardletter(board, x, y, horiz, j); X if (something(c)) X req[numreq++] = c; X } X if (((horiz ? x : y) + len < SIZE) && something(boardletter X (board, x, y, horiz, len))) X continue; X if (((horiz ? x : y) > 0) && something(boardletter X (board, x, y, horiz, - 1))) X continue; X X if (numreq + numopt < len) X break; X X#ifdef notdef X if (debug) { X fprintf(stderr, "\tReq:"); X for (i = 0; i < numreq; i++) X fprintf(stderr, " %c", req[i]); X fprintf(stderr, "\n\tOpt:"); X for (i = 0; i < numopt; i++) X fprintf(stderr, " %c", opt[i]); X fprintf(stderr, "\n"); X } X#endif X X words = getpossibles(opt, numopt, req, numreq, len); X X for (set = words; set; set = set->next_set) X for (word = set; word; word = word->next) { X try.word = word->word; X for (i = 0; i < SIZE; i++) X try.wild[i] = false; X trymove(&try, board, player, false); X if (try.points > best->points) X *best = try; X } X } X X return; X} X Xstatic bool Xvalidlocation(board_t *board, int x, int y, bool horiz, int len) X{ X int i; X X if (board->virgin) { X if (((y == SIZE / 2) && (x <= SIZE / 2) && X (x + len - 1 >= SIZE / 2)) || X ((x == SIZE / 2) && (y <= SIZE / 2) && X (y + len - 1 >= SIZE / 2))) X return (true); X else X return (false); X } X X for (i = 0; i < len; i++) X if (horiz) { X if (something(boardletter(board, x, y, horiz, i)) || X ((y > 0) && something(boardletter X (board, x, y - 1, horiz, i))) || X ((y < SIZE - 1) && something(boardletter X (board, x, y + 1, horiz, i)))) X return (true); X } else { X if (something(boardletter(board, x, y, horiz, i)) || X ((x > 0) && something(boardletter X (board, x - 1, y, horiz, i))) || X ((x < SIZE - 1) && something(boardletter X (board, x + 1, y, horiz, i)))) X return (true); X } X X return (false); X} X X/* This routine returns the value of a move, or -1 if the move would X * be invalid. X */ X Xvoid Xtrymove(move_t *move, board_t *board, player_t *player, bool check) X{ X bool used[WORK_SIZE]; X int numused = 0; X int i, j, x, y; X int len; X char c; X char buf[BSIZE]; X X/*printf("try %s at %d, %d, %d\n", move->word, move->x, move->y, move->horiz);*/ X X if (check) { X sprintf(buf, "Is \"%s\" a word?", move->word); X if (!user_confirm(buf)) { X remword(move->word); X move->points = -1; X return; X } X } X X for (i = 0; i < WORK_SIZE; i++) { X used[i] = false; X if (iswild(player->working[i])) X player->working[i] = WILD; X } X X /* First do the validity checks. */ X for (i = 0; i < move->length; i++) { X c = boardletter(board, move->x, move->y, move->horiz, i); X if (iswild(c)) X c = maketame(c); X if (something(c)) { X if (move->word[i] != c) { X move->points = -1; X return; X } X } else { X for (j = 0; j < player->numworking; j++) X if ((move->word[i] == player->working[j]) && X !used[j]) { X used[j] = true; X numused++; X break; X } X if (j == player->numworking) { X for (j = 0; j < player->numworking; j++) X if ((player->working[j] == WILD) && X !used[j]) { X move->wild[i] = true; X used[j] = true; X numused++; X break; X } X if (j == player->numworking) { X move->points = -1; X return; X } X } X } X } X X#ifdef notdef X if (debug) X fprintf(stderr, "\t(%d, %d) %s: %s", move->x, move->y, X move->horiz ? "horiz" : "vert", move->word); X#endif X X if (!numused) { X move->points = -1; X return; X } X X /* Add up the value of this word. */ X move->points = wordpoints(board, move->x, move->y, move->horiz, X move->length, move->word, '\0', 0, 0, true, X move->wild); X X if (numused == WORK_SIZE) X move->points += ALL_BONUS; X X if (move->horiz) X for (i = 0; i < move->length; i++) { X x = move->x + i; X if (something(board->letters[x][move->y])) X continue; X for (y = move->y; (y > 0) && something(board-> X letters[x][y - 1]); y--) X ; X for (len = 1, j = y; (j < SIZE - 1) && X (something(board->letters[x][j + 1]) || X (j + 1 == move->y)); len++, j++) X ; X if (len == 1) X continue; X if (validword(board, x, y, len, move->word[i], false, X player->machine, check)) X move->points += wordpoints(board, x, y, false, X len, (char *) NULL, X move->word[i], x, y, X false, (bool *) NULL); X else { X move->points = -1; X#ifdef notdef X if (debug) X fprintf(stderr, "=-1\n"); X#endif X return; X } X } X else X for (i = 0; i < move->length; i++) { X y = move->y + i; X if (something(board->letters[move->x][y])) X continue; X for (x = move->x; (x > 0) && something(board-> X letters[x - 1][y]); x--) X ; X for (len = 1, j = x; (j < SIZE - 1) && X (something(board->letters[j + 1][y]) || X (j + 1 == move->x)); len++, j++) X ; X if (len == 1) X continue; X if (validword(board, x, y, len, move->word[i], true, X player->machine, check)) X move->points += wordpoints(board, x, y, true, X len, (char *) NULL, X move->word[i], x, y, X false, (bool *) NULL); X else { X move->points = -1; X#ifdef notdef X if (debug) X fprintf(stderr, "=-1\n"); X#endif X return; X } X } X X#ifdef notdef X if (debug) X fprintf(stderr, "\n"); X#endif X X return; X} X Xstatic bool Xvalidword(board_t *board, int x, int y, int len, char subc, bool horiz, X bool machine, bool check) X{ X char buf[BSIZE], qbuf[BSIZE], c; X int i; X X for (i = 0; i < len; i++) { X c = boardletter(board, x, y, horiz, i); X if (something(c)) X buf[i] = c; X else X buf[i] = subc; X if (iswild(buf[i])) X buf[i] = maketame(buf[i]); X } X buf[i] = '\0'; X X#ifdef notdef X if (debug) X fprintf(stderr, " %s", buf); X#endif X X if (check) { X sprintf(qbuf, "Is \"%s\" a word?", buf); X if (user_confirm(qbuf)) { X return (true); X } else { X remword(buf); X return (false); X } X } else if (isaword(buf)) { X return (true); X } else if (!machine) { X sprintf(qbuf, "I don't think \"%s\" is a word. Do you?", buf); X if (user_confirm(qbuf)) { X addword(buf); X return (true); X } else X return (false); X } else { X return (false); X } X} X Xstatic int Xwordpoints(board_t *board, int x, int y, bool horiz, int len, char *word, X char subc, int wx, int wy, bool allbonuses, bool *wilds) X{ X int value = 0; X int mult = 1; X int i; X bonus_t b; X char c; X X if ((horiz ? x : y) + len > SIZE) X return (-1); X X for (i = 0; i < len; i++) { X if (allbonuses || (horiz && (x + i == wx)) || X (!horiz && (y + i == wy))) X b = boardbonus(board, x, y, horiz, i); X else X b = NONE; X X c = boardletter(board, x, y, horiz, i); X X if (!something(c)) { X if (word) X c = word[i]; X else X c = subc; X assert(c); X } else X b = NONE; X X if (wilds && wilds[i]) X c = makewild(c); X X switch (b) { X case NONE: X value += letterpoints(c); X break; X X case DOUBLE_LETTER: X value += letterpoints(c) * 2; X break; X X case TRIPLE_LETTER: X value += letterpoints(c) * 3; X break; X X case DOUBLE_WORD: X value += letterpoints(c); X mult *= 2; X break; X X case TRIPLE_WORD: X value += letterpoints(c); X mult *= 3; X break; X } X } X X value *= mult; X X#ifdef notdef X if (debug) X fprintf(stderr, "=%d", value); X#endif X X return (value); X} X END_OF_FILE if test 9358 -ne `wc -c <'move.c'`; then echo shar: \"'move.c'\" unpacked with wrong size! fi # end of 'move.c' fi if test -f 'refresh.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'refresh.c'\" else echo shar: Extracting \"'refresh.c'\" \(6569 characters\) sed "s/^X//" >'refresh.c' <<'END_OF_FILE' X/* X * Copyright (c) 1981 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)refresh.c 5.2 (Berkeley) 6/8/88"; X#endif /* not lint */ X X/* X * make the current screen look like "win" over the area coverd by X * win. X */ X X# include "curses.ext" X X# ifdef DEBUG X# define STATIC X# else X# define STATIC static X# endif X XSTATIC short ly, lx; X XSTATIC bool curwin; X XWINDOW *_win = NULL; X Xwrefresh(win) Xreg WINDOW *win; X{ X reg short wy; X reg int retval; X reg WINDOW *orig; X X /* X * make sure were in visual state X */ X if (_endwin) { X _puts(VS); X _puts(TI); X _endwin = FALSE; X } X X /* X * initialize loop parameters X */ X X ly = curscr->_cury; X lx = curscr->_curx; X wy = 0; X _win = win; X curwin = (win == curscr); X X if (win->_clear || curscr->_clear || curwin) { X if ((win->_flags & _FULLWIN) || curscr->_clear) { X _puts(CL); X ly = 0; X lx = 0; X if (!curwin) { X curscr->_clear = FALSE; X curscr->_cury = 0; X curscr->_curx = 0; X werase(curscr); X } X touchwin(win); X } X win->_clear = FALSE; X } X if (!CA) { X if (win->_curx != 0) X _putchar('\n'); X if (!curwin) X werase(curscr); X } X# ifdef DEBUG X fprintf(outf, "REFRESH(%0.2o): curwin = %d\n", win, curwin); X fprintf(outf, "REFRESH:\n\tfirstch\tlastch\n"); X# endif X for (wy = 0; wy < win->_maxy; wy++) { X# ifdef DEBUG X fprintf(outf, "%d\t%d\t%d\n", wy, win->_firstch[wy], X win->_lastch[wy]); X# endif X if (win->_firstch[wy] != _NOCHANGE) X if (makech(win, wy) == ERR) X return ERR; X else { X if (win->_firstch[wy] >= win->_ch_off) X win->_firstch[wy] = win->_maxx + X win->_ch_off; X if (win->_lastch[wy] < win->_maxx + X win->_ch_off) X win->_lastch[wy] = win->_ch_off; X if (win->_lastch[wy] < win->_firstch[wy]) X win->_firstch[wy] = _NOCHANGE; X } X# ifdef DEBUG X fprintf(outf, "\t%d\t%d\n", win->_firstch[wy], X win->_lastch[wy]); X# endif X } X X if (win == curscr) X domvcur(ly, lx, win->_cury, win->_curx); X else { X if (win->_leave) { X curscr->_cury = ly; X curscr->_curx = lx; X ly -= win->_begy; X lx -= win->_begx; X if (ly >= 0 && ly < win->_maxy && lx >= 0 && X lx < win->_maxx) { X win->_cury = ly; X win->_curx = lx; X } X else X win->_cury = win->_curx = 0; X } X else { X domvcur(ly, lx, win->_cury + win->_begy, X win->_curx + win->_begx); X curscr->_cury = win->_cury + win->_begy; X curscr->_curx = win->_curx + win->_begx; X } X } X retval = OK; Xret: X _win = NULL; X fflush(stdout); X return retval; X} X X/* X * make a change on the screen X */ XSTATIC Xmakech(win, wy) Xreg WINDOW *win; Xshort wy; X{ X reg char *nsp, *csp, *ce; X reg short wx, lch, y; X reg int nlsp, clsp; /* last space in lines */ X X wx = win->_firstch[wy] - win->_ch_off; X if (wx >= win->_maxx) X return OK; X else if (wx < 0) X wx = 0; X lch = win->_lastch[wy] - win->_ch_off; X if (lch < 0) X return OK; X else if (lch >= win->_maxx) X lch = win->_maxx - 1;; X y = wy + win->_begy; X X if (curwin) X csp = " "; X else X csp = &curscr->_y[wy + win->_begy][wx + win->_begx]; X X nsp = &win->_y[wy][wx]; X if (CE && !curwin) { X for (ce = &win->_y[wy][win->_maxx - 1]; *ce == ' '; ce--) X if (ce <= win->_y[wy]) X break; X nlsp = ce - win->_y[wy]; X } X X if (!curwin) X ce = CE; X else X ce = NULL; X X while (wx <= lch) { X if (*nsp != *csp) { X domvcur(ly, lx, y, wx + win->_begx); X# ifdef DEBUG X fprintf(outf, "MAKECH: 1: wx = %d, lx = %d\n", wx, lx); X# endif X ly = y; X lx = wx + win->_begx; X while (*nsp != *csp && wx <= lch) { X if (ce != NULL && wx >= nlsp && *nsp == ' ') { X /* X * check for clear to end-of-line X */ X ce = &curscr->_y[ly][COLS - 1]; X while (*ce == ' ') X if (ce-- <= csp) X break; X clsp = ce - curscr->_y[ly] - win->_begx; X# ifdef DEBUG X fprintf(outf, "MAKECH: clsp = %d, nlsp = %d\n", clsp, nlsp); X# endif X if (clsp - nlsp >= strlen(CE) X && clsp < win->_maxx) { X# ifdef DEBUG X fprintf(outf, "MAKECH: using CE\n"); X# endif X _puts(CE); X lx = wx + win->_begx; X while (wx++ <= clsp) X *csp++ = ' '; X return OK; X } X ce = NULL; X } X /* X * enter/exit standout mode as appropriate X */ X if (SO && (*nsp&_STANDOUT) != (curscr->_flags&_STANDOUT)) { X if (*nsp & _STANDOUT) { X _puts(SO); X curscr->_flags |= _STANDOUT; X } X else { X _puts(SE); X curscr->_flags &= ~_STANDOUT; X } X } X wx++; X if (wx >= win->_maxx && wy == win->_maxy - 1) X if (win->_scroll) { X if ((curscr->_flags&_STANDOUT) && X (win->_flags & _ENDLINE)) X if (!MS) { X _puts(SE); X curscr->_flags &= ~_STANDOUT; X } X if (!curwin) X _putchar((*csp = *nsp) & 0177); X else X _putchar(*nsp & 0177); X if (win->_flags&_FULLWIN && !curwin) X scroll(curscr); X ly = win->_begy+win->_cury; X lx = win->_begx+win->_curx; X return OK; X } X else if (win->_flags&_SCROLLWIN) { X lx = --wx; X return ERR; X } X if (!curwin) X _putchar((*csp++ = *nsp) & 0177); X else X _putchar(*nsp & 0177); X# ifdef FULLDEBUG X fprintf(outf, X "MAKECH:putchar(%c)\n", *nsp & 0177); X# endif X if (UC && (*nsp & _STANDOUT)) { X _putchar('\b'); X _puts(UC); X } X nsp++; X } X# ifdef DEBUG X fprintf(outf, "MAKECH: 2: wx = %d, lx = %d\n", wx, lx); X# endif X if (lx == wx + win->_begx) /* if no change */ X break; X lx = wx + win->_begx; X if (lx >= COLS && AM) { X lx = 0; X ly++; X /* X * xn glitch: chomps a newline after auto-wrap. X * we just feed it now and forget about it. X */ X if (XN) { X _putchar('\n'); X _putchar('\r'); X } X } X } X else if (wx <= lch) X while (*nsp == *csp && wx <= lch) { X nsp++; X if (!curwin) X csp++; X ++wx; X } X else X break; X# ifdef DEBUG X fprintf(outf, "MAKECH: 3: wx = %d, lx = %d\n", wx, lx); X# endif X } X return OK; X} X X/* X * perform a mvcur, leaving standout mode if necessary X */ XSTATIC Xdomvcur(oy, ox, ny, nx) Xint oy, ox, ny, nx; { X X if (curscr->_flags & _STANDOUT && !MS) { X _puts(SE); X curscr->_flags &= ~_STANDOUT; X } X mvcur(oy, ox, ny, nx); X} END_OF_FILE if test 6569 -ne `wc -c <'refresh.c'`; then echo shar: \"'refresh.c'\" unpacked with wrong size! fi # end of 'refresh.c' fi if test -f 'scrabble.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'scrabble.c'\" else echo shar: Extracting \"'scrabble.c'\" \(6426 characters\) sed "s/^X//" >'scrabble.c' <<'END_OF_FILE' X X/* RCS Info: $Revision: 1.3 $ on $Date: 89/03/15 16:33:15 $ X * $Source: /yew3/faustus/src/scrabble/RCS/scrabble.c,v $ X * Copyright (c) 1989 Wayne A. Christopher, U. C. Berkeley CS Dept X * faustus@renoir.berkeley.edu, ucbvax!faustus X * Permission is granted to modify and re-distribute this code in any manner X * as long as this notice is preserved. All standard disclaimers apply. X * X */ X X#include "scrabble.h" X#include "date.h" X#include <signal.h> X Xbool debug = false; Xbool userpick = false; Xbool confirm = false; X Xstatic bool domove(board_t *board, player_t **players, int which); Xstatic void sighandler(); X Xstatic char *dictfile = DICT_FILE; X Xint Xmain(int ac, char **av) X{ X board_t *board; X player_t *players[MAX_PLAYERS]; X bool machine[MAX_PLAYERS]; X int numplayers = 2; X int whosup = 0; X int turn = 1; X char buf[BSIZE]; X char *savedfile = NULL; X FILE *sfp = NULL; X int i, j, k; X X /* X printf("\tScrabble 1.0, by Wayne Christopher\n"); X printf("Compiled %s by %s@%s\n\n", DATE, USER, HOST); X */ X X srandom(time(0)); X X for (i = 0; i < MAX_PLAYERS; i++) X machine[i] = false; X X for (ac--, av++; ac && (**av == '-'); ac--, av++) { X if (eq(*av, "-d")) { X debug = true; X } else if (eq(*av, "-p")) { X userpick = true; X } else if (eq(*av, "-c")) { X confirm = true; X } else if (eq(*av, "-n")) { X numplayers = atoi(*++av); X ac--; X } else if (eq(*av, "-w")) { X dictfile = *++av; X ac--; X } else if (eq(*av, "-m")) { X machine[atoi(*++av)] = true; X ac--; X } else { X goto usage; X } X } X if (ac > 0) X savedfile = *av; X X if (savedfile) { X if (!(sfp = fopen(savedfile, "r"))) { X perror(savedfile); X savedfile = NULL; X } else { X unlink(savedfile); X } X } X X /* Read the words. */ X readdict(dictfile); X X /* Create the board. */ X if (savedfile) { X board = restoregame(sfp, &numplayers, &whosup, &turn); X if (!board) { X savedfile = NULL; X board = makeboard(); X } X } else { X board = makeboard(); X } X X /* Create the players. */ X for (i = 0; i < numplayers; i++) X if (savedfile) { X players[i] = restoreplayer(sfp); X } else { X players[i] = makeplayer(board, i); X players[i]->machine = machine[i]; X if (machine[i]) X sprintf(buf, "Mach %d", i); X else { X printf("Enter name of player %d: ", i); X fgets(buf, BSIZE, stdin); X buf[strlen(buf) - 1] = '\0'; X if (!*buf) X sprintf(buf, "Dude %d", i); X } X players[i]->name = strsav(buf); X } X X if (sfp) X fclose(sfp); X X user_init(DEV_TTY, board, players, numplayers); X X signal(SIGINT, sighandler); X X /* Now take turns. */ X for (;;) { X user_drawsummary(board, turn); X while (whosup < numplayers) X if (!domove(board, players, whosup) || X !players[whosup]->numworking) X goto endgame; X else X whosup++; X turn++; X whosup = 0; X } X Xendgame: X if (players[whosup]->numworking > 0) X whosup = -1; X for (i = 0; i < numplayers; i++) { X if (i == whosup) X continue; X for (j = 0, k = 0; j < players[i]->numworking; j++) { Xassert(players[i]->working[j]); X k += letterpoints(players[i]->working[j]); X } X sprintf(buf, "%s has %d points left.", players[i]->name, X players[i]->score); X user_message(buf); X players[i]->score -= k; X if (whosup >= 0) X players[whosup]->score += k; X X user_drawplayer(players[i], i, false); X } X if (whosup >= 0) X user_drawplayer(players[whosup], whosup, true); X X whosup = 0; X for (i = 1; i < numplayers; i++) X if (players[i]->score > players[whosup]->score) X whosup = i; X X sprintf(buf, "%s wins with %d points. Hit return to exit...", X players[whosup]->name, players[whosup]->score); X (void) user_confirm(buf); X X if (user_confirm("Save updated dictionary?")) X writedict(dictfile); X X user_cleanup(); X exit(0); X Xusage: X fprintf(stderr, "Usage: scrabble [ options ] [ saved-game ]\n"); X fprintf(stderr, "\tOptions are: -d Debug mode\n"); X fprintf(stderr, "\t -p Allow user to pick tiles\n"); X fprintf(stderr, "\t -c Confirm all words used\n"); X fprintf(stderr, "\t -n num Allow nnum players\n"); X fprintf(stderr, "\t -m pnum Player pnum is the machine\n"); X fprintf(stderr, "\t -w words Use words for the dictfile\n"); X X exit(1); X} X Xstatic bool Xdomove(board_t *board, player_t **players, int which) X{ X move_t move; X char buf[BSIZE]; X command_t com; X X#ifdef notdef X if (debug) X fprintf(stderr, "Moving for player %d...\n", which); X#endif X X user_drawplayer(players[which], which, true); X X if (players[which]->numworking == 0) X return (false); X X if (players[which]->machine) { X do { X bestmove(board, players[which], &move); X if (confirm) X trymove(&move, board, players[which], true); X } while (confirm && (move.points < 0)); X X if (move.points < 0) X return (false); X X user_drawmove(board, &move, players[which]); X playermove(board, players[which], &move); X boardmove(board, &move); X user_drawplayer(players[which], which, false); X } else { X for (;;) { X com = user_command(board, players[which], &move); X switch (com) { X case NOTHING: X continue; X X case MOVE: X trymove(&move, board, players[which], false); X X if (!isaword(move.word)) { X sprintf(buf, X "I don't think \"%s\" is a word. Do you?", X move.word); X if (user_confirm(buf)) { X addword(move.word); X } else X continue; X } X X if (move.points < 0) { X user_message("You can't do that."); X continue; X } X X user_drawmove(board, &move, players[which]); X playermove(board, players[which], &move); X boardmove(board, &move); X user_drawplayer(players[which], which, false); X break; X X case ADVICE: X players[which]->machine = true; X bestmove(board, players[which], &move); X players[which]->machine = false; X sprintf(buf, X "I'd suggest \"%s\" at (%d, %d) %s for %d points.", X move.word, move.x, move.y, X move.horiz ? "horiz" : "vert", X move.points); X user_message(buf); X continue; X X case TRADEIN: X user_message("Sorry, can't do that yet."); X continue; X X case SAVE: X user_message("Sorry, can't do that yet."); X continue; X X case RESTORE: X user_message("Sorry, can't do that yet."); X continue; X X case HELP: X user_givehelp(); X continue; X X case QUIT: X if (user_confirm("Save updated dictionary?")) X writedict(dictfile); X user_cleanup(); X exit(0); X } X X break; X } X } X X return (true); X} X Xstatic void Xsighandler() X{ X user_cleanup(); X exit(0); X} X END_OF_FILE if test 6426 -ne `wc -c <'scrabble.c'`; then echo shar: \"'scrabble.c'\" unpacked with wrong size! fi # end of 'scrabble.c' fi if test -f 'scrabble.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'scrabble.h'\" else echo shar: Extracting \"'scrabble.h'\" \(5035 characters\) sed "s/^X//" >'scrabble.h' <<'END_OF_FILE' X X/* RCS Info: $Revision: 1.2 $ on $Date: 89/03/15 11:16:37 $ X * $Source: /yew3/faustus/src/scrabble/RCS/scrabble.h,v $ X * Copyright (c) 1989 Wayne A. Christopher, U. C. Berkeley CS Dept X * faustus@renoir.berkeley.edu, ucbvax!faustus X * Permission is granted to modify and re-distribute this code in any manner X * as long as this notice is preserved. All standard disclaimers apply. X * X */ X X#include "util.h" X X#define AUTHOR "Wayne Christopher" X#define ADDRESS "faustus@yew.Berkeley.EDU" X#define VERSION "1.0" X X#define SIZE 15 X#define WORK_SIZE 7 X#define POOL_SIZE 100 X#define ALL_BONUS 50 X#define NUM_LETTERS 27 /* Plus wildcard. */ X#define MAX_PLAYERS 4 X X#ifndef DICT_FILE X#define DICT_FILE "/usr/dict/words" X#endif X X#define HASH_SIZE 5003 X#define MAX_LENGTH 15 X#define WILD '*' X#define ZIP ' ' X Xtypedef struct board_s board_t; Xtypedef struct player_s player_t; Xtypedef struct move_s move_t; Xtypedef struct dict_s dict_t; Xtypedef struct word_s word_t; Xtypedef enum bonus_e bonus_t; Xtypedef enum command_e command_t; Xtypedef enum devtype_e devtype_t; X Xenum bonus_e { X NONE = 0, X DOUBLE_LETTER = 1, X TRIPLE_LETTER = 2, X DOUBLE_WORD = 3, X TRIPLE_WORD = 4 X} ; X Xenum command_e { X NOTHING = 0, X MOVE = 1, X TRADEIN = 2, X SAVE = 3, X RESTORE = 4, X HELP = 5, X ADVICE = 6, X QUIT = 7 X} ; X Xenum devtype_e { X DEV_TTY = 0, X DEV_X10 = 1, X DEV_X11 = 2 X} ; X Xstruct board_s { X char letters[SIZE][SIZE]; X bonus_t bonus[SIZE][SIZE]; X char pool[POOL_SIZE]; X int numleft; X bool virgin; X} ; X Xstruct player_s { X char working[WORK_SIZE]; X int numworking; X int score; X bool machine; X char *name; X} ; X Xstruct move_s { X char *word; X bool wild[SIZE]; X int x, y; X int length; X bool horiz; X int points; X} ; X X/* The dictionary structure is a hash table, where the hash function is X * calculated from the number of times each letter appears in the word. X */ X Xstruct dict_s { X word_t *buckets[MAX_LENGTH][HASH_SIZE]; X int size; X} ; X Xstruct word_s { X char *word; X int length; X word_t *next; X word_t *next_set; X} ; X X#define boardletter(board, x, y, hf, pos) \ X ((hf) ? (board)->letters[(x) + (pos)][(y)] : \ X (board)->letters[(x)][(y) + (pos)]) X#define boardbonus(board, x, y, hf, pos) \ X ((hf) ? (board)->bonus[(x) + (pos)][(y)] : \ X (board)->bonus[(x)][(y) + (pos)]) X#define something(c) ((c) != ZIP) X#define letterpoints(c) ((iswild(c) || ((c) == WILD)) ? 0 : \ X letterpoint_values[(c) - 'a']) X#define iswild(c) (isupper(c)) X#define maketame(c) ((c) - 'A' + 'a') X#define makewild(c) ((c) - 'a' + 'A') X X/* scrabble.c */ X Xextern int main(int ac, char **av); Xextern dict_t *dictionaries; Xextern bool debug; Xextern bool userpick; X X/* board.c */ X Xextern board_t *makeboard(); Xextern void boardmove(board_t *board, move_t *move); Xextern char pickletter(board_t *board); Xextern int letterpoint_values[]; X X/* extern void printboard(board_t *board, FILE *fp); */ X X/* move.c */ X Xextern void bestmove(board_t *board, player_t *player, move_t *best); Xextern void trymove(move_t *move, board_t *board, player_t *player, bool check); X X/* extern void printmove(int which, move_t *move, FILE *fp); */ X X/* dict.c */ X Xextern void readdict(char *file); Xextern word_t *getpossibles(char *req, int numreq, char *opt, int numopt, X int len); Xextern bool isaword(char *poss); Xextern void addword(char *word); Xextern void remword(char *word); Xextern void writedict(char *file); X X/* player.c */ X Xextern player_t *makeplayer(board_t *board, int num); Xextern void playermove(board_t *board, player_t *player, move_t *move); X X/* extern void printplayer(player_t *player, int num, FILE *fp); */ X X/* savegame.c */ X Xextern board_t *restoregame(FILE *fp, int *nump, int *whosup, int *turn); Xextern player_t *restoreplayer(FILE *fp); Xextern void savegame(FILE *fp, int nump, int whosup, int turn); Xextern void saveplayer(FILE *fp); X X/* user.c */ X Xextern void user_init(devtype_t type, board_t *board, player_t *players[], X int numplayers); Xextern void user_message(char *message); Xextern char *user_question(char *message); Xextern bool user_confirm(char *message); Xextern command_t user_command(board_t *board, player_t *player, move_t *move); Xextern void user_drawplayer(player_t *player, int pos, bool up); Xextern void user_drawsummary(board_t *board, int turn); Xextern void user_drawmove(board_t *board, move_t *move, player_t *player); Xextern void user_givehelp(); Xextern void user_update(); Xextern void user_cleanup(); X X/* extern bool readmove(board_t *board, player_t *player, move_t *move); */ X X/* tty.c */ X Xextern void tty_init(board_t *board, player_t *players[], int numplayers); Xextern void tty_message(char *message); Xextern char *tty_question(char *message); Xextern bool tty_confirm(char *message); Xextern command_t tty_command(board_t *board, player_t *player, move_t *mv); Xextern void tty_drawplayer(player_t *player, int pos, bool up); Xextern void tty_drawsummary(board_t *board, int turn); Xextern void tty_drawmove(board_t *board, move_t *mv, player_t *player); Xextern void tty_givehelp(); Xextern void tty_update(); Xextern void tty_cleanup(); X END_OF_FILE if test 5035 -ne `wc -c <'scrabble.h'`; then echo shar: \"'scrabble.h'\" unpacked with wrong size! fi # end of 'scrabble.h' fi if test -f 'tty.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tty.c'\" else echo shar: Extracting \"'tty.c'\" \(8653 characters\) sed "s/^X//" >'tty.c' <<'END_OF_FILE' X X/* RCS Info: $Revision: 1.2 $ on $Date: 89/03/15 16:33:18 $ X * $Source: /yew3/faustus/src/scrabble/RCS/tty.c,v $ X * Copyright (c) 1989 Wayne A. Christopher, U. C. Berkeley CS Dept X * faustus@renoir.berkeley.edu, ucbvax!faustus X * Permission is granted to modify and re-distribute this code in any manner X * as long as this notice is preserved. All standard disclaimers apply. X * X */ X X#include "scrabble.h" X#include <curses.h> X#undef bool X Xstatic WINDOW *boardwin, *scores, *summary, *dialog; X#ifdef notdef Xstatic WINDOW *title; X#endif X Xstatic char lbchar[] = " `\"(<"; Xstatic char rbchar[] = " '\")>"; X Xstatic int messline = 0; X X#define bpos(px, py, x, y) (px) = 3 * (x) + 4; (py) = (y) + 1; X#define MESS_SIZE 5 X#define beep() putc('\007', stderr); fflush(stderr); X Xstatic char *help[] = { X"Scrabble Version 1.0, by Wayne Christopher (faustus@renoir.Berkeley.EDU) ", X" ", X" The rules of the game are the same as those of the board game, and will ", X" not be described here. The screen is divided up into a board area, ", X" which the player can move around in, a status and score window to the ", X" right, and a message window at the bottom. A star appears by the name ", X" of the player whose turn it is, and if this is not a machine player the ", X" commands below may be given. The commands H, V, Q, and T terminate the ", X" player's turn, assuming the word is valid. ", X" ", X"Available commands are: ", X" h, j, k, l : Move the cursor around the board. ", X" H : Create a horizontal word at the cursor position. ", X" V : Create a vertical word at the cursor position. ", X" T : Trade in a number of tiles for new tiles. ", X" S : Save the game into a file. ", X" R : Restore a game from a file (loses the current game). ", X" A : Ask for advice from the computer. ", X" Q : Quit the game. ", X" ^L : Redraw the screen. ", X" ? : Print this help message. " X} ; X Xvoid Xtty_init(board_t *board, player_t *players[], int numplayers) X{ X int i, j; X int x, y; X X initscr(); X noecho(); X crmode(); X X#ifdef notdef X title = newwin(2, 80, 0, 0); X#endif X boardwin = newwin(17, 51, 0, 0); X scores = newwin(9, 29, 3, 51); X summary = newwin(3, 29, 14, 51); X dialog = newwin(0, 80, 18, 0); X X#ifdef notdef X /* Draw the title... */ X wmove(title, 0, 7); X wprintw(title, "Scrabble %s, by %s (%s)", VERSION, AUTHOR, ADDRESS); X#endif X X /* Draw the board... top and bottom... */ X for (i = 0; i < 15; i++) { X wmove(boardwin, 0, 3 * i + 4); X wprintw(boardwin, "%-2d", i); X wmove(boardwin, 16, 3 * i + 4); X wprintw(boardwin, "%-2d", i); X } X X /* Left and right... */ X for (i = 0; i < 15; i++) { X wmove(boardwin, 1 + i, 0); X wprintw(boardwin, "%2d", i); X wmove(boardwin, 1 + i, 49); X wprintw(boardwin, "%-2d", i); X } X for (i = 0; i < 15; i++) X for (j = 0; j < 15; j++) { X bpos(x, y, i, j); X wmove(boardwin, y, x - 1); X waddch(boardwin, lbchar[board->bonus[j][i]]); X wmove(boardwin, y, x); X waddch(boardwin, '.'); X wmove(boardwin, y, x + 1); X waddch(boardwin, rbchar[board->bonus[j][i]]); X } X X /* Draw the scores display... */ X wmove(scores, 0, 0); X wprintw(scores, " Scrabble %s", VERSION); X wmove(scores, 1, 0); X wprintw(scores, " by %s", AUTHOR); X X wmove(scores, 3, 0); X wprintw(scores, " Name Score Letters"); X for (i = 0; i < numplayers; i++) X tty_drawplayer(players[i], i, (i == 0) ? true : false); X X /* Draw the summary window. */ X tty_drawsummary(board, 0); X X /* The dialog window is blank. */ X X wrefresh(boardwin); X X return; X} X Xvoid Xtty_message(char *message) X{ X /* Print the message and clear the line below it. */ X messline = (messline + 1) % MESS_SIZE; X if (messline < MESS_SIZE - 1) { X wmove(dialog, messline + 1, 0); X wclrtoeol(dialog); X } X wmove(dialog, messline, 0); X wclrtoeol(dialog); X wprintw(dialog, "%s", message); X X wrefresh(dialog); X X return; X} X Xchar * Xtty_question(char *message) X{ X static char buf[BSIZE]; X X tty_message(message); X wmove(dialog, messline, strlen(message) + 1); X wrefresh(dialog); X echo(); X nocrmode(); X wgetstr(dialog, buf); X crmode(); X noecho(); X X return (buf); X} X Xbool Xtty_confirm(char *message) X{ X char c; X X tty_message(message); X wmove(dialog, messline, strlen(message) + 1); X wrefresh(dialog); X c = wgetch(dialog); X X if ((c == 'y') || (c == 'Y')) X return (true); X else X return (false); X} X X/* Let the player move to a place in the board, type 'h' or 'v', then enter X * a word. Other commands are 'T', 'S', 'R', 'Q', and '?'. X */ X Xcommand_t Xtty_command(board_t *board, player_t *player, move_t *mv) X{ X int x = 7, y = 7; X int px, py; X bool horiz = false, done = false; X char *word, buf[BSIZE]; X char c; X int i; X X for (;;) { X bpos(px, py, x, y); X wmove(boardwin, py, px); X wrefresh(boardwin); X c = wgetch(boardwin); X switch (c) { X case '\014': X tty_update(); X break; X X case 'h': X if (x > 0) X x--; X else { X beep(); X } X break; X X case 'j': X if (y < SIZE - 1) X y++; X else { X beep(); X } X break; X X case 'k': X if (y > 0) X y--; X else { X beep(); X } X break; X X case 'l': X if (x < SIZE - 1) X x++; X else { X beep(); X } X break; X X case 'H': X horiz = true; X done = true; X break; X X case 'V': X horiz = false; X done = true; X break; X X case 'T': X return (TRADEIN); X X case 'S': X return (SAVE); X X case 'R': X return (RESTORE); X X case 'A': X return (ADVICE); X X case 'Q': X if (tty_confirm("Really quit?")) X return (QUIT); X else X break; X X case '?': X return (HELP); X X default: X beep(); X break; X } X X if (done) X break; X } X X if (horiz) X sprintf(buf, "Horiz word at (%d, %d):", x, y); X else X sprintf(buf, "Vert word at (%d, %d):", x, y); X X word = tty_question(buf); X X if (strlen(word) > SIZE) X word[SIZE] = '\0'; X X mv->word = strsav(word); X mv->x = x; X mv->y = y; X mv->length = strlen(word); X mv->horiz = horiz; X mv->points = 0; X X for (i = 0; i < SIZE; i++) X mv->wild[i] = false; X X for (i = 0; i < mv->length; i++) { X if (!isalpha(mv->word[i])) { X tty_message("Invalid word."); X return (NOTHING); X } else if (isupper(mv->word[i])) { X mv->word[i] = tolower(mv->word[i]); X } X } X X return (MOVE); X} X Xvoid Xtty_drawplayer(player_t *player, int pos, bool up) X{ X int i; X X wmove(scores, pos + 5, 0); X wprintw(scores, " %c %-6.6s %3d ", up ? '*' : ' ', player->name, X player->score); X for (i = 0; i < player->numworking; i++) X wprintw(scores, " %c", player->working[i]); X wclrtoeol(scores); X wmove(scores, pos + 5, 0); X wrefresh(scores); X X return; X} X Xvoid Xtty_drawsummary(board_t *board, int turn) X{ X wmove(summary, 0, 0); X wprintw(summary, " Game turn: %d ", turn); X wmove(summary, 1, 0); X wprintw(summary, " Tiles left: %d ", board->numleft); X wrefresh(summary); X X return; X} X Xvoid Xtty_drawmove(board_t *board, move_t *mv, player_t *player) X{ X int i, x, y; X char c; X char buf[BSIZE]; X X for (i = 0; i < mv->length; i++) { X c = mv->word[i]; X if (!mv->wild[i]) X c = toupper(c); X if (mv->horiz) { X bpos(x, y, mv->x + i, mv->y); X } else { X bpos(x, y, mv->x, mv->y + i); X } X Xassert((x >= 0) && (x < 51) && (y >= 0) && (y < 17)); X X wmove(boardwin, y, x); X waddch(boardwin, c); X } X wrefresh(boardwin); X sprintf(buf, "%s: \"%s\" at (%d, %d), %s, %d points.", player->name, X mv->word, mv->x, mv->y, mv->horiz ? "horiz" : "vert", X mv->points); X tty_message(buf); X X return; X} X Xvoid Xtty_givehelp() X{ X WINDOW *hwin = newwin(24, 80, 0, 0); X int i; X X wclear(hwin); X overwrite(hwin, stdscr); X wrefresh(hwin); X wrefresh(stdscr); X X for (i = 0; i < sizeof (help) / sizeof (help[0]); i++) { X wmove(hwin, i, 0); X wprintw(hwin, "%s", help[i]); X } X X wmove(hwin, i + 1, 0); X wprintw(hwin, "Hit return to continue..."); X wrefresh(hwin); X (void) wgetch(hwin); X X wclear(hwin); X wrefresh(hwin); X X delwin(hwin); X X touchwin(boardwin); X touchwin(scores); X touchwin(summary); X touchwin(dialog); X X tty_update(); X X return; X} X Xvoid Xtty_update() X{ X wrefresh(boardwin); X wrefresh(scores); X wrefresh(summary); X wrefresh(dialog); X X return; X} X Xvoid Xtty_cleanup() X{ X move(23, 0); X clrtoeol(); X refresh(); X endwin(); X return; X} X END_OF_FILE if test 8653 -ne `wc -c <'tty.c'`; then echo shar: \"'tty.c'\" unpacked with wrong size! fi # end of 'tty.c' fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0