#! /bin/sh
#
# THIS WILL UNPACK WITH ERRORS.  SOMEWHERE WE LOST THE TAB CHARS
#
# 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;
~r}i}i}i
        
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&_S
TANDOUT)) {
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 &= ~_STAN
DOUT;
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);
~r
  
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;
{_}i
    
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
