147854Sbostic /*-
2*60755Sbostic * Copyright (c) 1982, 1993
3*60755Sbostic * The Regents of the University of California. All rights reserved.
447854Sbostic *
547854Sbostic * %sccs.include.proprietary.c%
621499Smckusick */
721499Smckusick
89895Ssam #ifndef lint
9*60755Sbostic static char copyright[] =
10*60755Sbostic "@(#) Copyright (c) 1982, 1993\n\
11*60755Sbostic The Regents of the University of California. All rights reserved.\n";
1247854Sbostic #endif /* not lint */
139895Ssam
1421499Smckusick #ifndef lint
15*60755Sbostic static char sccsid[] = "@(#)boggle.c 8.1 (Berkeley) 05/31/93";
1647854Sbostic #endif /* not lint */
1721499Smckusick
1859781Storek #include <sys/types.h>
1959781Storek #include <sys/wait.h>
209895Ssam #include <ctype.h>
219895Ssam #include <errno.h>
2259781Storek #include <fcntl.h>
239895Ssam #include <setjmp.h>
249895Ssam #include <sgtty.h>
259895Ssam #include <signal.h>
269895Ssam #include <stdio.h>
2759781Storek #include <stdlib.h>
2859781Storek #include <string.h>
2959781Storek #include <time.h>
3059781Storek #include <unistd.h>
3141169Sbostic #include "pathnames.h"
329895Ssam
339895Ssam /* basic parameters */
349895Ssam #define N 4
359895Ssam #define SSIZE 200
369895Ssam #define MAXWORDS 1000
379895Ssam #define CWIDTH 10
389895Ssam #define LWIDTH 80
399895Ssam
409895Ssam /* parameters defined in terms of above */
419895Ssam #define BSIZE (N*N)
429895Ssam #define row(x) (x/N)
439895Ssam #define col(x) (x%N)
449895Ssam
459895Ssam /* word being searched for */
469895Ssam int wlength;
479895Ssam int numsame;
489895Ssam char wbuff [BSIZE+1];
499895Ssam
509895Ssam /* tty and process control */
519895Ssam extern int errno;
529895Ssam int status;
539895Ssam int pipefd[2];
549895Ssam int super = 0;
559895Ssam int delct = 1;
569895Ssam int zero = 0;
579895Ssam int master = 1;
589895Ssam int column;
599895Ssam int *timept;
609895Ssam int timeint[] = {60,60,50,7,1,1,1,0};
6159781Storek time_t timein;
629895Ssam struct sgttyb origttyb, tempttyb;
639895Ssam int ctlecho = 0;
649895Ssam int lctlech = LCTLECH;
659895Ssam jmp_buf env;
669895Ssam
679895Ssam /* monitoring variables */
689895Ssam int games;
699895Ssam int logfile = -1;
7059781Storek off_t logloc;
719895Ssam char logbuff[100] = {"inst\t"};
729895Ssam
739895Ssam /* dictionary interface */
749895Ssam FILE *dict;
759895Ssam
769895Ssam /* structures for doing matching */
779895Ssam struct frame {
789895Ssam struct frame *parent;
799895Ssam int place;
809895Ssam };
8159781Storek struct frame stack[SSIZE];
8259781Storek struct frame *level[BSIZE+1];
839895Ssam
849895Ssam /* the board and subsidiary structures */
8559781Storek char present[BSIZE+1];
8659781Storek char board[BSIZE];
8759781Storek char olink[BSIZE];
8859781Storek char adj[BSIZE+1][BSIZE];
8959781Storek char occurs[26];
909895Ssam
919895Ssam /* the boggle cubes */
9259781Storek char *cube[BSIZE] = {
939895Ssam "forixb", "moqabj", "gurilw", "setupl",
949895Ssam "cmpdae", "acitao", "slcrae", "romash",
959895Ssam "nodesw", "hefiye", "onudtk", "tevign",
969895Ssam "anedvz", "pinesh", "abilyt", "gkyleu"
979895Ssam };
989895Ssam
999895Ssam
1009895Ssam /* storage for words found */
1019895Ssam int ubotch, ustart, wcount;
10259781Storek char *word[MAXWORDS];
1039895Ssam char *freesp;
1049895Ssam char space[10000];
1059895Ssam
10659781Storek void aputuword __P((int));
10759781Storek void aputword __P((int));
10859781Storek void clearscreen __P((void));
10959781Storek int compare __P((const void *, const void *));
11059781Storek void endline __P((void));
11159781Storek int evalboard __P((int (*)(void), void (*)(int)));
11259781Storek void genboard __P((void));
11359781Storek int getdword __P((void));
11459781Storek int getuword __P((void));
11559781Storek __dead void goodbye __P((int));
11659781Storek void interrupt __P((int));
11759781Storek void makelists __P((void));
11859781Storek int numways __P((struct frame *, struct frame *));
11959781Storek void outword __P((char *));
12059781Storek void printboard __P((void));
12159781Storek void printdiff __P((void));
12259781Storek void printinst __P((void));
12359781Storek void setup __P((void));
12459781Storek void timeout __P((int));
12559781Storek void tputword __P((int));
12659781Storek int wordcomp __P((char *, char *));
12759781Storek
12859781Storek
12959781Storek void
endline()13059781Storek endline()
1319895Ssam {
1329895Ssam if (column != 0) {
1339895Ssam putchar('\n');
1349895Ssam column = 0;
1359895Ssam }
1369895Ssam }
1379895Ssam
13846734Sbostic void
timeout(sig)13959781Storek timeout(sig)
14059781Storek int sig;
1419895Ssam {
1429895Ssam if (*timept > 0) {
14359781Storek signal(SIGALRM, timeout);
1449895Ssam alarm(*timept++);
1459895Ssam }
1469895Ssam putchar('\007');
1479895Ssam }
1489895Ssam
14946734Sbostic void
interrupt(sig)15059781Storek interrupt(sig)
15159781Storek int sig;
1529895Ssam {
15359781Storek
1549895Ssam signal(SIGINT, interrupt);
1559895Ssam if (delct++ >= 1)
1569895Ssam longjmp(env, 1);
1579895Ssam timept = &zero;
1589895Ssam }
1599895Ssam
16059781Storek __dead void
goodbye(stat)16159781Storek goodbye(stat)
16259781Storek int stat;
1639895Ssam {
1649895Ssam if (master != 0) {
1659895Ssam wait(&status);
16659781Storek if (ctlecho & LCTLECH)
16759781Storek ioctl(fileno(stdin), TIOCLBIS, &lctlech);
1689895Ssam stty(fileno(stdin), &origttyb);
1699895Ssam }
1709895Ssam exit(stat);
1719895Ssam }
1729895Ssam
17359781Storek void
clearscreen()17459781Storek clearscreen()
1759895Ssam {
17659781Storek stty(fileno(stdin), &tempttyb);
1779895Ssam printf("\n\033\f\r");
1789895Ssam }
1799895Ssam
18059781Storek int
compare(a,b)18159781Storek compare(a, b)
18259781Storek const void *a, *b;
1839895Ssam {
18459781Storek
18559781Storek return(wordcomp(*(char **)a, *(char **)b));
1869895Ssam }
1879895Ssam
18859781Storek int
wordcomp(p,q)18959781Storek wordcomp(p, q)
19059781Storek register char *p, *q;
1919895Ssam {
1929895Ssam if (*p=='0' && *q!='0')
1939895Ssam return(-1);
1949895Ssam if (*p!='0' && *q=='0')
1959895Ssam return(1);
1969895Ssam while (*++p == *++q && isalpha(*p)) ;
1979895Ssam if (!isalpha(*p))
1989895Ssam return(-isalpha(*q));
1999895Ssam if (!isalpha(*q))
2009895Ssam return(1);
2019895Ssam return(*p-*q);
2029895Ssam }
2039895Ssam
20459781Storek void
printinst()20559781Storek printinst()
2069895Ssam {
20759781Storek stty(fileno(stdin), &tempttyb);
2089895Ssam printf("instructions?");
2099895Ssam if (getchar() == 'y') {
2109895Ssam clearscreen();
2119895Ssam printf(" The object of Boggle (TM Parker Bros.) is to find, within 3\n");
2129895Ssam printf("minutes, as many words as possible in a 4 by 4 grid of letters. Words\n");
2139895Ssam printf("may be formed from any sequence of 3 or more adjacent letters in the\n");
2149895Ssam printf("grid. The letters may join horizontally, vertically, or diagonally.\n");
2159895Ssam printf("However, no position in the grid may be used more than once within any\n");
2169895Ssam printf("one word. In competitive play amongst humans, each player is given\n");
2179895Ssam printf("credit for those of his words which no other player has found.\n");
2189895Ssam printf(" This program is intended for people wishing to sharpen their\n");
2199895Ssam printf("skills at Boggle. If you invoke the program with 4 arguments of 4\n");
2209895Ssam printf("letters each, (e.g. \"boggle appl epie moth erhd\") the program forms the\n");
2219895Ssam printf("obvious Boggle grid and lists all the words from /usr/dict/words found\n");
2229895Ssam printf("therein. If you invoke the program without arguments, it will generate\n");
2239895Ssam printf("a board for you, let you enter words for 3 minutes, and then tell you\n");
2249895Ssam printf("how well you did relative to /usr/dict/words.\n");
2259895Ssam printf(" In interactive play, enter your words separated by spaces, tabs,\n");
2269895Ssam printf("or newlines. A bell will ring when there is 2:00, 1:00, 0:10, 0:02,\n");
2279895Ssam printf("0:01, and 0:00 time left. You may complete any word started before the\n");
2289895Ssam printf("expiration of time. You can surrender before time is up by hitting\n");
2299895Ssam printf("'break'. While entering words, your erase character is only effective\n");
2309895Ssam printf("within the current word and your line kill character is ignored.\n");
2319895Ssam printf(" Advanced players may wish to invoke the program with 1 or 2 +'s as\n");
23220195Smckusick printf("the first argument. The first + removes the restriction that positions\n");
2339895Ssam printf("can only be used once in each word. The second + causes a position to\n");
2349895Ssam printf("be considered adjacent to itself as well as its (up to) 8 neighbors.\n");
2359895Ssam printf("Hit any key to begin.\n");
23659781Storek stty(fileno(stdin), &tempttyb);
2379895Ssam getchar();
2389895Ssam }
23959781Storek stty(fileno(stdin), &tempttyb);
2409895Ssam }
2419895Ssam
24259781Storek void
setup()24359781Storek setup()
2449895Ssam {
2459895Ssam register int i, j;
2469895Ssam int rd, cd, k;
2479895Ssam for (i=0; i<BSIZE; i++) {
2489895Ssam adj[i][i] = super>=2 ? 1 : 0;
2499895Ssam adj[BSIZE][i] = 1;
2509895Ssam for (j=0; j<i; j++) {
2519895Ssam rd = row(i)-row(j);
2529895Ssam cd = col(i)-col(j);
2539895Ssam k = 0;
2549895Ssam switch (rd) {
2559895Ssam case -1:
2569895Ssam case 1:
2579895Ssam if (-1<=cd && cd<=1)
2589895Ssam k = 1;
2599895Ssam break;
2609895Ssam case 0:
2619895Ssam if (cd==-1 || cd==1)
2629895Ssam k = 1;
2639895Ssam break;
2649895Ssam }
2659895Ssam adj[i][j] = adj[j][i] = k;
2669895Ssam }
2679895Ssam }
2689895Ssam stack[0].parent = &stack[0];
2699895Ssam stack[0].place = BSIZE;
2709895Ssam level[0] = &stack[0];
2719895Ssam level[1] = &stack[1];
2729895Ssam }
2739895Ssam
27459781Storek void
makelists()27559781Storek makelists()
2769895Ssam {
2779895Ssam register int i, c;
2789895Ssam for (i=0; i<26; i++)
2799895Ssam occurs[i] = BSIZE;
2809895Ssam for (i=0; i<BSIZE; i++) {
2819895Ssam c = board[i];
2829895Ssam olink[i] = occurs[c-'a'];
2839895Ssam occurs[c-'a'] = i;
2849895Ssam }
2859895Ssam }
2869895Ssam
28759781Storek void
genboard()28859781Storek genboard()
2899895Ssam {
2909895Ssam register int i, j;
2919895Ssam for (i=0; i<BSIZE; i++)
2929895Ssam board[i] = 0;
2939895Ssam for (i=0; i<BSIZE; i++) {
2949895Ssam j = rand()%BSIZE;
2959895Ssam while (board[j] != 0)
2969895Ssam j = (j+1)%BSIZE;
2979895Ssam board[j] = cube[i][rand()%6];
2989895Ssam }
2999895Ssam }
3009895Ssam
30159781Storek void
printboard()30259781Storek printboard()
3039895Ssam {
3049895Ssam register int i, j;
3059895Ssam for (i=0; i<N; i++) {
3069895Ssam printf("\t\t\t\t\b\b");
3079895Ssam for (j=0; j<N; j++) {
3089895Ssam putchar ((putchar(board[i*N+j]) == 'q') ? 'u' : ' ');
3099895Ssam putchar(' ');
3109895Ssam }
3119895Ssam putchar('\n');
3129895Ssam }
3139895Ssam putchar('\n');
3149895Ssam }
3159895Ssam
31659781Storek int
getdword()31759781Storek getdword()
3189895Ssam {
3199895Ssam /* input: numsame = # chars same as last word */
3209895Ssam /* output: numsame = # same chars for next word */
3219895Ssam /* word in wbuff[0]...wbuff[wlength-1] */
3229895Ssam register int c;
3239895Ssam register char *p;
3249895Ssam if (numsame == EOF)
3259895Ssam return (0);
3269895Ssam p = &wbuff[numsame]+1;
3279895Ssam while ((*p++ = c = getc(dict)) != EOF && isalpha(c)) ;
3289895Ssam numsame = c;
3299895Ssam wlength = p - &wbuff[2];
3309895Ssam return (1);
3319895Ssam }
3329895Ssam
33359781Storek int
getuword()33459781Storek getuword()
3359895Ssam {
3369895Ssam int c;
3379895Ssam register char *p, *q, *r;
3389895Ssam numsame = 0;
3399895Ssam while (*timept>0 && (isspace(c=getchar()) || c==EOF));
3409895Ssam if (*timept == 0)
3419895Ssam return(0);
3429895Ssam word[wcount++] = freesp;
3439895Ssam *freesp++ = '0';
3449895Ssam r = &wbuff[1];
3459895Ssam q = p = freesp;
3469895Ssam *p++ = c;
3479895Ssam while (!isspace(c = getchar())) {
3489895Ssam if (c == EOF)
3499895Ssam continue;
3509895Ssam if (c == origttyb.sg_erase) {
3519895Ssam if (p > q)
3529895Ssam p--;
3539895Ssam continue;
3549895Ssam }
3559895Ssam *p++ = c;
3569895Ssam }
3579895Ssam freesp = p;
3589895Ssam for (p=q; p<freesp && r<&wbuff[BSIZE]; )
3599895Ssam if (islower(c = *p++) && (*r++ = *q++ = c) == 'q' && *p == 'u')
3609895Ssam p++;
3619895Ssam *(freesp = q) = '0';
3629895Ssam wlength = r-&wbuff[1];
3639895Ssam return(1);
3649895Ssam }
3659895Ssam
36659781Storek void
aputuword(ways)36759781Storek aputuword(ways)
36859781Storek int ways;
3699895Ssam {
3709895Ssam *word[wcount-1] = ways>=10 ? '*' : '0'+ways;
3719895Ssam }
3729895Ssam
37359781Storek void
aputword(ways)37459781Storek aputword(ways)
37559781Storek int ways;
3769895Ssam {
3779895Ssam /* store (wbuff, ways) in next slot in space */
3789895Ssam register int i;
3799895Ssam *freesp++ = ways>=10 ? '*' : '0'+ways;
3809895Ssam for (i=1; i<= wlength; i++)
3819895Ssam *freesp++ = wbuff[i];
3829895Ssam word[++wcount] = freesp;
3839895Ssam }
3849895Ssam
38559781Storek void
tputword(ways)38659781Storek tputword(ways)
38759781Storek int ways;
3889895Ssam {
3899895Ssam /* print (wbuff, ways) on terminal */
3909895Ssam wbuff[wlength+1] = '0';
3919895Ssam wbuff[0] = ways>=10 ? '*' : '0'+ways;
3929895Ssam outword(&wbuff[0]);
3939895Ssam }
3949895Ssam
39559781Storek void
outword(p)39659781Storek outword(p)
39759781Storek register char *p;
3989895Ssam {
3999895Ssam register int newcol;
4009895Ssam register char *q;
4019895Ssam for (q=p+1; isalpha(*q); ) {
4029895Ssam putchar(*q);
4039895Ssam if (*q++ == 'q') {
4049895Ssam putchar('u');
4059895Ssam column++;
4069895Ssam }
4079895Ssam }
4089895Ssam column += q-p-1;
4099895Ssam if (column > LWIDTH-CWIDTH) {
4109895Ssam putchar('\n');
4119895Ssam column = 0;
4129895Ssam return;
4139895Ssam }
4149895Ssam newcol = ((column+CWIDTH)/CWIDTH)*CWIDTH;
4159895Ssam while (((column+8)/8)*8 <= newcol) {
4169895Ssam putchar('\t');
4179895Ssam column = ((column+8)/8)*8;
4189895Ssam }
4199895Ssam while (column < newcol) {
4209895Ssam putchar(' ');
4219895Ssam column++;
4229895Ssam }
4239895Ssam }
4249895Ssam
42559781Storek void
printdiff()42659781Storek printdiff()
4279895Ssam {
4289895Ssam register int c, d, u;
4299895Ssam char both, donly, uonly;
4309895Ssam word[wcount] = freesp;
4319895Ssam *freesp = '0';
4329895Ssam both = donly = uonly = column = d = 0;
4339895Ssam u = ustart;
4349895Ssam while (d < ubotch) {
4359895Ssam c = u<wcount ? wordcomp (word[d], word[u]) : -1;
4369895Ssam if (c == 0) {
4379895Ssam /* dict and user found same word */
4389895Ssam if (both == 0) {
4399895Ssam both = 1;
4409895Ssam printf("\t\t\t we both found:\n");
4419895Ssam }
4429895Ssam outword(word[d]);
4439895Ssam word[d++] = NULL;
4449895Ssam word[u++] = NULL;
4459895Ssam } else if (c < 0) {
4469895Ssam /* dict found it, user didn't */
4479895Ssam donly = 1;
4489895Ssam d++;
4499895Ssam } else {
4509895Ssam /* user found it, dict didn't */
4519895Ssam uonly = 1;
4529895Ssam u++;
4539895Ssam }
4549895Ssam }
4559895Ssam endline();
4569895Ssam if (donly) {
4579895Ssam printf("\n\t\t\tI alone found these:\n");
4589895Ssam for (d=0; d<ubotch; d++)
4599895Ssam if (word[d] != NULL)
4609895Ssam outword(word[d]);
4619895Ssam endline();
4629895Ssam }
4639895Ssam if (uonly) {
4649895Ssam printf("\n\t\t\tyou alone found these:\n");
4659895Ssam for (u=ustart; u<wcount; u++)
4669895Ssam if (word[u] != NULL)
4679895Ssam outword(word[u]);
4689895Ssam endline();
4699895Ssam }
4709895Ssam if (ubotch < ustart) {
4719895Ssam printf("\n\t\t\t you botched these:\n");
4729895Ssam for (u=ubotch; u<ustart; u++)
4739895Ssam outword(word[u]);
4749895Ssam endline();
4759895Ssam }
4769895Ssam }
4779895Ssam
47859781Storek int
numways(leaf,last)47959781Storek numways(leaf, last)
48059781Storek register struct frame *leaf;
48159781Storek struct frame *last;
4829895Ssam {
4839895Ssam int count;
4849895Ssam register char *p;
4859895Ssam register struct frame *node;
4869895Ssam if (super > 0)
4879895Ssam return(last-leaf);
4889895Ssam count = 0;
4899895Ssam present[BSIZE] = 1;
4909895Ssam while (leaf < last) {
4919895Ssam for (p = &present[0]; p < &present[BSIZE]; *p++ = 0);
4929895Ssam for (node = leaf; present[node->place]++ == 0; node = node->parent);
4939895Ssam if (node == &stack[0])
4949895Ssam count++;
4959895Ssam leaf++;
4969895Ssam }
4979895Ssam return(count);
4989895Ssam }
4999895Ssam
50059781Storek int
5019895Ssam evalboard (getword, putword)
50259781Storek int (*getword) __P((void));
50359781Storek void (*putword) __P((int));
5049895Ssam {
5059895Ssam register struct frame *top;
5069895Ssam register int l, q;
5079895Ssam int fo, found;
5089895Ssam struct frame *parent, *lastparent;
5099895Ssam char *padj;
5109895Ssam
5119895Ssam numsame = found = 0;
5129895Ssam makelists ();
5139895Ssam
5149895Ssam while (1) {
5159895Ssam l = numsame;
5169895Ssam if (!(*getword) ())
5179895Ssam break;
5189895Ssam top = level[l+1];
5199895Ssam
5209895Ssam while (1) {
5219895Ssam level[l+1] = lastparent = top;
5229895Ssam /* wbuff[1]...wbuff[l] have been matched */
5239895Ssam /* level[0],...,level[l] of tree built */
5249895Ssam if (l == wlength) {
5259895Ssam if (wlength >= 3 && (q = numways(level[l], top)) != 0) {
5269895Ssam (*putword) (q);
5279895Ssam found++;
5289895Ssam }
5299895Ssam l = BSIZE+1;
5309895Ssam break;
5319895Ssam }
5329895Ssam if ((fo = occurs[wbuff[++l]-'a']) == BSIZE)
5339895Ssam break;
5349895Ssam /* wbuff[1]...wbuff[l-1] have been matched */
5359895Ssam /* level[0],...,level[l-1] of tree built */
5369895Ssam for (parent=level[l-1]; parent<lastparent; parent++) {
5379895Ssam padj = &adj[parent->place][0];
5389895Ssam for (q=fo; q!=BSIZE; q=olink[q])
5399895Ssam if (padj[q]) {
5409895Ssam top->parent = parent;
5419895Ssam top->place = q;
5429895Ssam if (++top >= &stack[SSIZE]) {
5439895Ssam printf("stack overflow\n");
5449895Ssam goodbye(1);
5459895Ssam }
5469895Ssam }
5479895Ssam }
5489895Ssam /* were any nodes added? */
5499895Ssam if (top == lastparent)
5509895Ssam break;
5519895Ssam }
5529895Ssam
5539895Ssam /* advance until first l characters of next word are different */
5549895Ssam while (numsame >= l && (*getword)()) ;
5559895Ssam }
5569895Ssam return(found);
5579895Ssam }
5589895Ssam
55959781Storek int
main(argc,argv)56059781Storek main(argc, argv)
56159781Storek int argc;
56259781Storek char **argv;
5639895Ssam {
5649895Ssam char *q;
5659895Ssam register char *p;
5669895Ssam register int i, c;
5679895Ssam
56859781Storek gtty(fileno(stdin), &origttyb);
5699895Ssam setbuf(stdin, NULL);
5709895Ssam tempttyb = origttyb;
5719895Ssam if (setjmp(env) != 0)
5729895Ssam goodbye(0);
57359781Storek signal(SIGINT, interrupt);
57446734Sbostic timein = time((time_t *)NULL);
57559781Storek if (argv[0][0] != 'a' &&
57659781Storek (logfile = open(_PATH_BOGLOG, O_WRONLY, 0)) >= 0) {
5779895Ssam p = &logbuff[5];
5789895Ssam q = getlogin();
57959781Storek while ((*p++ = *q++) != 0);
5809895Ssam p[-1] = '\t';
5819895Ssam q = ctime(&timein);
58259781Storek while ((*p++ = *q++) != 0);
5839895Ssam logloc = lseek(logfile, 0L, 2);
5849895Ssam write(logfile, &logbuff[0], p-&logbuff[1]);
5859895Ssam }
58641169Sbostic if ((dict = fopen(_PATH_DICTIONARY, "r")) == NULL) {
58741169Sbostic printf("can't open %s\n", _PATH_DICTIONARY);
5889895Ssam goodbye (2);
5899895Ssam }
5909895Ssam while ( argc > 1 && ( argv[1][0] == '+' || argv[1][0] == '-' ) ) {
5919895Ssam if (argv[1][0]=='+') {
5929895Ssam while(*(argv[1]++) == '+')
5939895Ssam super++;
5949895Ssam argc--;
5959895Ssam argv++;
5969895Ssam }
5979895Ssam if ( argv[1][0] == '-' ) {
5989895Ssam timeint[0] = 60 * ( atol( &argv[1][1] ) - 2 );
5999895Ssam if ( timeint[0] <= 0 ) {
6009895Ssam timeint[0] = 60;
6019895Ssam }
6029895Ssam argc--;
6039895Ssam argv++;
6049895Ssam }
6059895Ssam }
6069895Ssam setup ();
6079895Ssam switch (argc) {
6089895Ssam default: punt:
6099895Ssam printf("usage: boggle [+[+]] [row1 row2 row3 row4]\n");
6109895Ssam goodbye (3);
6119895Ssam case 5:
6129895Ssam for (i=0; i<BSIZE; i++) {
6139895Ssam board[i] = c = argv[row(i)+1][col(i)];
6149895Ssam if (!islower(c)) {
6159895Ssam printf("bad board\n");
6169895Ssam goto punt;
6179895Ssam }
6189895Ssam }
6199895Ssam printboard();
6209895Ssam column = 0;
6219895Ssam evalboard(getdword, tputword);
6229895Ssam endline();
6239895Ssam if (logfile >= 0) {
6249895Ssam strncpy(&logbuff[0], "eval", 4);
6259895Ssam lseek(logfile, logloc, 0);
6269895Ssam write(logfile, &logbuff[0], 4);
6279895Ssam }
6289895Ssam goodbye(0);
6299895Ssam case 1:
6309895Ssam tempttyb.sg_flags |= CBREAK;
6319895Ssam if ( ioctl( fileno(stdin), TIOCLGET, &ctlecho ) == 0 ) {
6329895Ssam if ( ctlecho & LCTLECH ) {
6339895Ssam ioctl( fileno(stdin), TIOCLBIC, &lctlech );
6349895Ssam }
6359895Ssam }
6369895Ssam printinst();
6379895Ssam srand((int) timein);
6389895Ssam while (setjmp(env) == 0) {
6399895Ssam errno = 0;
6409895Ssam if (pipe(&pipefd[0]) != 0) {
6419895Ssam printf("can't create pipe\n");
6429895Ssam goodbye(4);
6439895Ssam }
6449895Ssam genboard();
6459895Ssam delct = wcount = 0;
6469895Ssam word[0] = freesp = &space[0];
6479895Ssam if ((master = fork()) == 0) {
6489895Ssam close(pipefd[0]);
6499895Ssam clearscreen();
6509895Ssam printboard();
6519895Ssam signal(SIGALRM, timeout);
6529895Ssam timept = &timeint[0];
6539895Ssam alarm(*timept++);
6549895Ssam evalboard(getuword, aputuword);
6559895Ssam clearscreen();
65659781Storek qsort(&word[0], wcount, sizeof(int), compare);
6579895Ssam for (i=0; i<wcount; i++)
6589895Ssam if (i==0 || wordcomp(word[i], word[i-1])!=0) {
6599895Ssam p = word[i];
6609895Ssam while (isalpha(*++p)) ;
6619895Ssam write (pipefd[1], word[i], p-word[i]);
6629895Ssam }
6639895Ssam close(pipefd[1]);
6649895Ssam goodbye(0);
6659895Ssam }
6669895Ssam close(pipefd[1]);
6679895Ssam rewind(dict);
6689895Ssam getc(dict);
6699895Ssam evalboard(getdword, aputword);
6709895Ssam p = freesp;
6719895Ssam while ((i = read(pipefd[0], freesp, 512)) != 0) {
6729895Ssam if (i < 0)
6739895Ssam if (errno != EINTR)
6749895Ssam break;
6759895Ssam else
6769895Ssam i = 0;
6779895Ssam freesp += i;
6789895Ssam }
6799895Ssam close(pipefd[0]);
6809895Ssam ustart = ubotch = wcount;
6819895Ssam while (p < freesp) {
6829895Ssam word[wcount++] = p;
6839895Ssam if (*p == '0')
6849895Ssam ustart = wcount;
6859895Ssam while (isalpha(*++p));
6869895Ssam }
6879895Ssam wait(&status);
6889895Ssam if (status != 0)
6899895Ssam goodbye (5);
6909895Ssam delct = 1;
6919895Ssam printdiff();
6929895Ssam printboard();
6939895Ssam games++;
6949895Ssam if (logfile >= 0) {
69532490Sbostic (void)sprintf(&logbuff[0], "%4d", games);
6969895Ssam lseek(logfile, logloc, 0);
6979895Ssam write(logfile, &logbuff[0], 4);
6989895Ssam }
6999895Ssam stty (fileno(stdin), &tempttyb);
7009895Ssam printf("\nanother game?");
7019895Ssam if (getchar() != 'y') {
7029895Ssam putchar('\n');
7039895Ssam break;
7049895Ssam }
7059895Ssam stty (fileno(stdin), &tempttyb);
7069895Ssam }
7079895Ssam goodbye(0);
7089895Ssam }
7099895Ssam }
710