xref: /csrg-svn/old/boggle/boggle.c (revision 9895)
1*9895Ssam #ifndef lint
2*9895Ssam static char sccsid[] = "@(#)boggle.c	4.1 12/24/82";
3*9895Ssam #endif
4*9895Ssam 
5*9895Ssam #include <ctype.h>
6*9895Ssam #include <errno.h>
7*9895Ssam #include <setjmp.h>
8*9895Ssam #include <sgtty.h>
9*9895Ssam #include <signal.h>
10*9895Ssam #include <stdio.h>
11*9895Ssam 
12*9895Ssam /* basic parameters */
13*9895Ssam #define N 4
14*9895Ssam #define SSIZE 200
15*9895Ssam #define MAXWORDS 1000
16*9895Ssam #define CWIDTH 10
17*9895Ssam #define LWIDTH 80
18*9895Ssam 
19*9895Ssam /* parameters defined in terms of above */
20*9895Ssam #define BSIZE (N*N)
21*9895Ssam #define row(x) (x/N)
22*9895Ssam #define col(x) (x%N)
23*9895Ssam 
24*9895Ssam /* word being searched for */
25*9895Ssam int wlength;
26*9895Ssam int numsame;
27*9895Ssam char wbuff [BSIZE+1];
28*9895Ssam 
29*9895Ssam /* tty and process control */
30*9895Ssam extern int errno;
31*9895Ssam int status;
32*9895Ssam int pipefd[2];
33*9895Ssam int super = 0;
34*9895Ssam int delct = 1;
35*9895Ssam int zero = 0;
36*9895Ssam int master = 1;
37*9895Ssam int column;
38*9895Ssam int *timept;
39*9895Ssam int timeint[] = {60,60,50,7,1,1,1,0};
40*9895Ssam long timein;
41*9895Ssam extern long int time();
42*9895Ssam struct sgttyb origttyb, tempttyb;
43*9895Ssam int ctlecho = 0;
44*9895Ssam int lctlech = LCTLECH;
45*9895Ssam jmp_buf env;
46*9895Ssam 
47*9895Ssam /* monitoring variables */
48*9895Ssam int games;
49*9895Ssam int logfile = -1;
50*9895Ssam long logloc;
51*9895Ssam char logbuff[100] = {"inst\t"};
52*9895Ssam extern char *ctime(), *getlogin();
53*9895Ssam extern long lseek();
54*9895Ssam 
55*9895Ssam /* dictionary interface */
56*9895Ssam char defname[] = "/usr/games/bogdict";
57*9895Ssam char *dictname = &defname[0];
58*9895Ssam FILE *dict;
59*9895Ssam 
60*9895Ssam /* structures for doing matching */
61*9895Ssam struct frame {
62*9895Ssam 	struct frame *parent;
63*9895Ssam 	int place;
64*9895Ssam };
65*9895Ssam struct frame stack [SSIZE];
66*9895Ssam struct frame *level [BSIZE+1];
67*9895Ssam 
68*9895Ssam /* the board and subsidiary structures */
69*9895Ssam char present [BSIZE+1];
70*9895Ssam char board [BSIZE];
71*9895Ssam char olink [BSIZE];
72*9895Ssam char adj [BSIZE+1][BSIZE];
73*9895Ssam char occurs [26];
74*9895Ssam 
75*9895Ssam /* the boggle cubes */
76*9895Ssam char *cube [BSIZE] = {
77*9895Ssam 	"forixb", "moqabj", "gurilw", "setupl",
78*9895Ssam 	"cmpdae", "acitao", "slcrae", "romash",
79*9895Ssam 	"nodesw", "hefiye", "onudtk", "tevign",
80*9895Ssam 	"anedvz", "pinesh", "abilyt", "gkyleu"
81*9895Ssam };
82*9895Ssam 
83*9895Ssam 
84*9895Ssam /* storage for words found */
85*9895Ssam int ubotch, ustart, wcount;
86*9895Ssam char *word [MAXWORDS];
87*9895Ssam char *freesp;
88*9895Ssam char space[10000];
89*9895Ssam 
90*9895Ssam endline ()
91*9895Ssam {
92*9895Ssam 	if (column != 0) {
93*9895Ssam 		putchar('\n');
94*9895Ssam 		column = 0;
95*9895Ssam 	}
96*9895Ssam }
97*9895Ssam 
98*9895Ssam timeout ()
99*9895Ssam {
100*9895Ssam 	if (*timept > 0) {
101*9895Ssam 		signal (SIGALRM, timeout);
102*9895Ssam 		alarm(*timept++);
103*9895Ssam 	}
104*9895Ssam 	putchar('\007');
105*9895Ssam }
106*9895Ssam 
107*9895Ssam interrupt ()
108*9895Ssam {
109*9895Ssam 	signal(SIGINT, interrupt);
110*9895Ssam 	if (delct++ >= 1)
111*9895Ssam 		longjmp(env, 1);
112*9895Ssam 	timept = &zero;
113*9895Ssam }
114*9895Ssam 
115*9895Ssam goodbye (stat)
116*9895Ssam int stat;
117*9895Ssam {
118*9895Ssam 	if (master != 0) {
119*9895Ssam 		wait(&status);
120*9895Ssam 		if ( ctlecho & LCTLECH ) {
121*9895Ssam 			ioctl( fileno(stdin), TIOCLBIS, &lctlech );
122*9895Ssam 		}
123*9895Ssam 		stty(fileno(stdin), &origttyb);
124*9895Ssam 	}
125*9895Ssam 	exit(stat);
126*9895Ssam }
127*9895Ssam 
128*9895Ssam clearscreen ()
129*9895Ssam {
130*9895Ssam 	stty (fileno(stdin), &tempttyb);
131*9895Ssam 	printf("\n\033\f\r");
132*9895Ssam }
133*9895Ssam 
134*9895Ssam compare (a, b)
135*9895Ssam char **a, **b;
136*9895Ssam {
137*9895Ssam 	return(wordcomp(*a, *b));
138*9895Ssam }
139*9895Ssam 
140*9895Ssam wordcomp (p, q)
141*9895Ssam register char *p, *q;
142*9895Ssam {
143*9895Ssam 	if (*p=='0' && *q!='0')
144*9895Ssam 		return(-1);
145*9895Ssam 	if (*p!='0' && *q=='0')
146*9895Ssam 		return(1);
147*9895Ssam 	while (*++p == *++q && isalpha(*p)) ;
148*9895Ssam 	if (!isalpha(*p))
149*9895Ssam 		return(-isalpha(*q));
150*9895Ssam 	if (!isalpha(*q))
151*9895Ssam 		return(1);
152*9895Ssam 	return(*p-*q);
153*9895Ssam }
154*9895Ssam 
155*9895Ssam printinst ()
156*9895Ssam {
157*9895Ssam 	stty (fileno(stdin), &tempttyb);
158*9895Ssam 	printf("instructions?");
159*9895Ssam 	if (getchar() == 'y') {
160*9895Ssam 		clearscreen();
161*9895Ssam 		printf("     The object of Boggle (TM  Parker  Bros.)  is  to  find,  within  3\n");
162*9895Ssam 		printf("minutes,  as many words as possible in a 4 by 4 grid of letters.  Words\n");
163*9895Ssam 		printf("may be formed from any sequence of 3 or more adjacent  letters  in  the\n");
164*9895Ssam 		printf("grid.   The  letters  may join horizontally, vertically, or diagonally.\n");
165*9895Ssam 		printf("However, no position in the grid may be used more than once within  any\n");
166*9895Ssam 		printf("one  word.   In  competitive  play amongst humans, each player is given\n");
167*9895Ssam 		printf("credit for those of his words which no other player has found.\n");
168*9895Ssam 		printf("     This program is intended  for  people  wishing  to  sharpen  their\n");
169*9895Ssam 		printf("skills  at  Boggle.   If  you  invoke the program with 4 arguments of 4\n");
170*9895Ssam 		printf("letters each, (e.g. \"boggle appl epie moth erhd\") the program forms the\n");
171*9895Ssam 		printf("obvious  Boggle grid and lists all the words from /usr/dict/words found\n");
172*9895Ssam 		printf("therein.  If you invoke the program without arguments, it will generate\n");
173*9895Ssam 		printf("a  board  for you, let you enter words for 3 minutes, and then tell you\n");
174*9895Ssam 		printf("how well you did relative to /usr/dict/words.\n");
175*9895Ssam 		printf("     In interactive play, enter your words separated by  spaces,  tabs,\n");
176*9895Ssam 		printf("or  newlines.   A  bell will ring when there is 2:00, 1:00, 0:10, 0:02,\n");
177*9895Ssam 		printf("0:01, and 0:00 time left.  You may complete any word started before the\n");
178*9895Ssam 		printf("expiration  of  time.   You  can surrender before time is up by hitting\n");
179*9895Ssam 		printf("'break'.  While entering words, your erase character is only  effective\n");
180*9895Ssam 		printf("within the current word and your line kill character is ignored.\n");
181*9895Ssam 		printf("     Advanced players may wish to invoke the program with 1 or 2 +'s as\n");
182*9895Ssam 		printf("the  first argument.  The first + removes the restriction that postions\n");
183*9895Ssam 		printf("can only be used once in each word.  The second + causes a position  to\n");
184*9895Ssam 		printf("be  considered  adjacent  to itself as well as its (up to) 8 neighbors.\n");
185*9895Ssam 		printf("Hit any key to begin.\n");
186*9895Ssam 		stty (fileno(stdin), &tempttyb);
187*9895Ssam 		getchar();
188*9895Ssam 	}
189*9895Ssam 	stty (fileno(stdin), &tempttyb);
190*9895Ssam }
191*9895Ssam 
192*9895Ssam setup ()
193*9895Ssam {
194*9895Ssam 	register int i, j;
195*9895Ssam 	int rd, cd, k;
196*9895Ssam 	for (i=0; i<BSIZE; i++) {
197*9895Ssam 		adj[i][i] = super>=2 ? 1 : 0;
198*9895Ssam 		adj[BSIZE][i] = 1;
199*9895Ssam 		for (j=0; j<i; j++) {
200*9895Ssam 			rd = row(i)-row(j);
201*9895Ssam 			cd = col(i)-col(j);
202*9895Ssam 			k = 0;
203*9895Ssam 			switch (rd) {
204*9895Ssam 			case -1:
205*9895Ssam 			case 1:
206*9895Ssam 				if (-1<=cd && cd<=1)
207*9895Ssam 					k = 1;
208*9895Ssam 				break;
209*9895Ssam 			case 0:
210*9895Ssam 				if (cd==-1 || cd==1)
211*9895Ssam 					k = 1;
212*9895Ssam 				break;
213*9895Ssam 			}
214*9895Ssam 			adj[i][j] = adj[j][i] = k;
215*9895Ssam 		}
216*9895Ssam 	}
217*9895Ssam 	stack[0].parent = &stack[0];
218*9895Ssam 	stack[0].place = BSIZE;
219*9895Ssam 	level[0] = &stack[0];
220*9895Ssam 	level[1] = &stack[1];
221*9895Ssam }
222*9895Ssam 
223*9895Ssam makelists ()
224*9895Ssam {
225*9895Ssam 	register int i, c;
226*9895Ssam 	for (i=0; i<26; i++)
227*9895Ssam 		occurs[i] = BSIZE;
228*9895Ssam 	for (i=0; i<BSIZE; i++) {
229*9895Ssam 		c = board[i];
230*9895Ssam 		olink[i] = occurs[c-'a'];
231*9895Ssam 		occurs[c-'a'] = i;
232*9895Ssam 	}
233*9895Ssam }
234*9895Ssam 
235*9895Ssam genboard ()
236*9895Ssam {
237*9895Ssam 	register int i, j;
238*9895Ssam 	for (i=0; i<BSIZE; i++)
239*9895Ssam 		board[i] = 0;
240*9895Ssam 	for (i=0; i<BSIZE; i++) {
241*9895Ssam 		j = rand()%BSIZE;
242*9895Ssam 		while (board[j] != 0)
243*9895Ssam 			j = (j+1)%BSIZE;
244*9895Ssam 		board[j] = cube[i][rand()%6];
245*9895Ssam 	}
246*9895Ssam }
247*9895Ssam 
248*9895Ssam printboard ()
249*9895Ssam {
250*9895Ssam 	register int i, j;
251*9895Ssam 	for (i=0; i<N; i++) {
252*9895Ssam 		printf("\t\t\t\t\b\b");
253*9895Ssam 		for (j=0; j<N; j++) {
254*9895Ssam 			putchar ((putchar(board[i*N+j]) == 'q') ? 'u' : ' ');
255*9895Ssam 			putchar(' ');
256*9895Ssam 		}
257*9895Ssam 		putchar('\n');
258*9895Ssam 	}
259*9895Ssam 	putchar('\n');
260*9895Ssam }
261*9895Ssam 
262*9895Ssam getdword ()
263*9895Ssam {
264*9895Ssam 	/* input:  numsame = # chars same as last word   */
265*9895Ssam 	/* output: numsame = # same chars for next word  */
266*9895Ssam 	/*        word in wbuff[0]...wbuff[wlength-1]    */
267*9895Ssam 	register int c;
268*9895Ssam 	register char *p;
269*9895Ssam 	if (numsame == EOF)
270*9895Ssam 		return (0);
271*9895Ssam 	p = &wbuff[numsame]+1;
272*9895Ssam 	while ((*p++ = c = getc(dict)) != EOF && isalpha(c)) ;
273*9895Ssam 	numsame = c;
274*9895Ssam 	wlength = p - &wbuff[2];
275*9895Ssam 	return (1);
276*9895Ssam }
277*9895Ssam 
278*9895Ssam getuword ()
279*9895Ssam {
280*9895Ssam 	int c;
281*9895Ssam 	register char *p, *q, *r;
282*9895Ssam 	numsame = 0;
283*9895Ssam 	while (*timept>0 && (isspace(c=getchar()) || c==EOF));
284*9895Ssam 	if (*timept == 0)
285*9895Ssam 		return(0);
286*9895Ssam 	word[wcount++] = freesp;
287*9895Ssam 	*freesp++ = '0';
288*9895Ssam 	r = &wbuff[1];
289*9895Ssam 	q = p = freesp;
290*9895Ssam 	*p++ = c;
291*9895Ssam 	while (!isspace(c = getchar())) {
292*9895Ssam 		if (c == EOF)
293*9895Ssam 			continue;
294*9895Ssam 		if (c == origttyb.sg_erase) {
295*9895Ssam 			if (p > q)
296*9895Ssam 				p--;
297*9895Ssam 			continue;
298*9895Ssam 		}
299*9895Ssam 		*p++ = c;
300*9895Ssam 	}
301*9895Ssam 	freesp = p;
302*9895Ssam 	for (p=q; p<freesp && r<&wbuff[BSIZE]; )
303*9895Ssam 		if (islower(c = *p++) && (*r++ = *q++ = c) == 'q' && *p == 'u')
304*9895Ssam 			p++;
305*9895Ssam 	*(freesp = q) = '0';
306*9895Ssam 	wlength = r-&wbuff[1];
307*9895Ssam 	return(1);
308*9895Ssam }
309*9895Ssam 
310*9895Ssam aputuword (ways)
311*9895Ssam int ways;
312*9895Ssam {
313*9895Ssam 	*word[wcount-1] = ways>=10 ? '*' : '0'+ways;
314*9895Ssam }
315*9895Ssam 
316*9895Ssam aputword (ways)
317*9895Ssam int ways;
318*9895Ssam {
319*9895Ssam 	/* store (wbuff, ways) in next slot in space */
320*9895Ssam 	register int i;
321*9895Ssam 	*freesp++ = ways>=10 ? '*' : '0'+ways;
322*9895Ssam 	for (i=1; i<= wlength; i++)
323*9895Ssam 		*freesp++ = wbuff[i];
324*9895Ssam 	word[++wcount] = freesp;
325*9895Ssam }
326*9895Ssam 
327*9895Ssam tputword (ways)
328*9895Ssam int ways;
329*9895Ssam {
330*9895Ssam 	/* print (wbuff, ways) on terminal */
331*9895Ssam 	wbuff[wlength+1] = '0';
332*9895Ssam 	wbuff[0] = ways>=10 ? '*' : '0'+ways;
333*9895Ssam 	outword(&wbuff[0]);
334*9895Ssam }
335*9895Ssam 
336*9895Ssam outword (p)
337*9895Ssam register char *p;
338*9895Ssam {
339*9895Ssam 	register int newcol;
340*9895Ssam 	register char *q;
341*9895Ssam 	for (q=p+1; isalpha(*q); ) {
342*9895Ssam 		putchar(*q);
343*9895Ssam 		if (*q++ == 'q') {
344*9895Ssam 			putchar('u');
345*9895Ssam 			column++;
346*9895Ssam 		}
347*9895Ssam 	}
348*9895Ssam 	column += q-p-1;
349*9895Ssam 	if (column > LWIDTH-CWIDTH) {
350*9895Ssam 		putchar('\n');
351*9895Ssam 		column = 0;
352*9895Ssam 		return;
353*9895Ssam 	}
354*9895Ssam 	newcol = ((column+CWIDTH)/CWIDTH)*CWIDTH;
355*9895Ssam 	while (((column+8)/8)*8 <= newcol) {
356*9895Ssam 		putchar('\t');
357*9895Ssam 		column = ((column+8)/8)*8;
358*9895Ssam 	}
359*9895Ssam 	while (column < newcol) {
360*9895Ssam 		putchar(' ');
361*9895Ssam 		column++;
362*9895Ssam 	}
363*9895Ssam }
364*9895Ssam 
365*9895Ssam printdiff ()
366*9895Ssam {
367*9895Ssam 	register int c, d, u;
368*9895Ssam 	char both, donly, uonly;
369*9895Ssam 	word[wcount] = freesp;
370*9895Ssam 	*freesp = '0';
371*9895Ssam 	both = donly = uonly = column = d = 0;
372*9895Ssam 	u = ustart;
373*9895Ssam 	while (d < ubotch) {
374*9895Ssam 		c = u<wcount ? wordcomp (word[d], word[u]) : -1;
375*9895Ssam 		if (c == 0) {
376*9895Ssam 			/* dict and user found same word */
377*9895Ssam 			if (both == 0) {
378*9895Ssam 				both = 1;
379*9895Ssam 				printf("\t\t\t   we both found:\n");
380*9895Ssam 			}
381*9895Ssam 			outword(word[d]);
382*9895Ssam 			word[d++] = NULL;
383*9895Ssam 			word[u++] = NULL;
384*9895Ssam 		} else if (c < 0) {
385*9895Ssam 			/* dict found it, user didn't */
386*9895Ssam 			donly = 1;
387*9895Ssam 			d++;
388*9895Ssam 		} else {
389*9895Ssam 			/* user found it, dict didn't */
390*9895Ssam 			uonly = 1;
391*9895Ssam 			u++;
392*9895Ssam 		}
393*9895Ssam 	}
394*9895Ssam 	endline();
395*9895Ssam 	if (donly) {
396*9895Ssam 		printf("\n\t\t\tI alone found these:\n");
397*9895Ssam 		for (d=0; d<ubotch; d++)
398*9895Ssam 			if (word[d] != NULL)
399*9895Ssam 				outword(word[d]);
400*9895Ssam 		endline();
401*9895Ssam 	}
402*9895Ssam 	if (uonly) {
403*9895Ssam 		printf("\n\t\t\tyou alone found these:\n");
404*9895Ssam 		for (u=ustart; u<wcount; u++)
405*9895Ssam 			if (word[u] != NULL)
406*9895Ssam 				outword(word[u]);
407*9895Ssam 		endline();
408*9895Ssam 	}
409*9895Ssam 	if (ubotch < ustart) {
410*9895Ssam 		printf("\n\t\t\t  you botched these:\n");
411*9895Ssam 		for (u=ubotch; u<ustart; u++)
412*9895Ssam 			outword(word[u]);
413*9895Ssam 		endline();
414*9895Ssam 	}
415*9895Ssam }
416*9895Ssam 
417*9895Ssam numways (leaf, last)
418*9895Ssam register struct frame *leaf;
419*9895Ssam struct frame *last;
420*9895Ssam {
421*9895Ssam 	int count;
422*9895Ssam 	register char *p;
423*9895Ssam 	register struct frame *node;
424*9895Ssam 	if (super > 0)
425*9895Ssam 		return(last-leaf);
426*9895Ssam 	count = 0;
427*9895Ssam 	present[BSIZE] = 1;
428*9895Ssam 	while (leaf < last) {
429*9895Ssam 		for (p = &present[0]; p < &present[BSIZE]; *p++ = 0);
430*9895Ssam 		for (node = leaf; present[node->place]++ == 0; node = node->parent);
431*9895Ssam 		if (node == &stack[0])
432*9895Ssam 			count++;
433*9895Ssam 		leaf++;
434*9895Ssam 	}
435*9895Ssam 	return(count);
436*9895Ssam }
437*9895Ssam 
438*9895Ssam evalboard (getword, putword)
439*9895Ssam int (*getword)(), (*putword)();
440*9895Ssam {
441*9895Ssam 	register struct frame *top;
442*9895Ssam 	register int l, q;
443*9895Ssam 	int fo, found;
444*9895Ssam 	struct frame *parent, *lastparent;
445*9895Ssam 	char *padj;
446*9895Ssam 
447*9895Ssam 	numsame = found = 0;
448*9895Ssam 	makelists ();
449*9895Ssam 
450*9895Ssam 	while (1) {
451*9895Ssam 		l = numsame;
452*9895Ssam 		if (!(*getword) ())
453*9895Ssam 			break;
454*9895Ssam 		top = level[l+1];
455*9895Ssam 
456*9895Ssam 		while (1) {
457*9895Ssam 			level[l+1] = lastparent = top;
458*9895Ssam 			/* wbuff[1]...wbuff[l] have been matched */
459*9895Ssam 			/* level[0],...,level[l] of tree built */
460*9895Ssam 			if (l == wlength) {
461*9895Ssam 				if (wlength >= 3 && (q = numways(level[l], top)) != 0) {
462*9895Ssam 					(*putword) (q);
463*9895Ssam 					found++;
464*9895Ssam 				}
465*9895Ssam 				l = BSIZE+1;
466*9895Ssam 				break;
467*9895Ssam 			}
468*9895Ssam 			if ((fo = occurs[wbuff[++l]-'a']) == BSIZE)
469*9895Ssam 				break;
470*9895Ssam 			/* wbuff[1]...wbuff[l-1] have been matched */
471*9895Ssam 			/* level[0],...,level[l-1] of tree built */
472*9895Ssam 			for (parent=level[l-1]; parent<lastparent; parent++) {
473*9895Ssam 				padj = &adj[parent->place][0];
474*9895Ssam 				for (q=fo; q!=BSIZE; q=olink[q])
475*9895Ssam 					if (padj[q]) {
476*9895Ssam 						top->parent = parent;
477*9895Ssam 						top->place = q;
478*9895Ssam 						if (++top >= &stack[SSIZE]) {
479*9895Ssam 							printf("stack overflow\n");
480*9895Ssam 							goodbye(1);
481*9895Ssam 						}
482*9895Ssam 					}
483*9895Ssam 			}
484*9895Ssam 			/* were any nodes added? */
485*9895Ssam 			if (top == lastparent)
486*9895Ssam 				break;
487*9895Ssam 		}
488*9895Ssam 
489*9895Ssam 		/* advance until first l characters of next word are different */
490*9895Ssam 		while (numsame >= l && (*getword)()) ;
491*9895Ssam 	}
492*9895Ssam 	return(found);
493*9895Ssam }
494*9895Ssam 
495*9895Ssam main (argc, argv)
496*9895Ssam int argc;
497*9895Ssam char **argv;
498*9895Ssam {
499*9895Ssam 	char *q;
500*9895Ssam 	register char *p;
501*9895Ssam 	register int i, c;
502*9895Ssam 
503*9895Ssam 	gtty (fileno(stdin), &origttyb);
504*9895Ssam 	setbuf(stdin, NULL);
505*9895Ssam 	tempttyb = origttyb;
506*9895Ssam 	if (setjmp(env) != 0)
507*9895Ssam 		goodbye(0);
508*9895Ssam 	signal (SIGINT, interrupt);
509*9895Ssam 	timein = time(0L);
510*9895Ssam 	if (argv[0][0] != 'a' && (logfile = open("/usr/games/boglog", 1)) >= 0) {
511*9895Ssam 		p = &logbuff[5];
512*9895Ssam 		q = getlogin();
513*9895Ssam 		while (*p++ = *q++);
514*9895Ssam 		p[-1] = '\t';
515*9895Ssam 		q = ctime(&timein);
516*9895Ssam 		while (*p++ = *q++);
517*9895Ssam 		logloc = lseek(logfile, 0L, 2);
518*9895Ssam 		write(logfile, &logbuff[0], p-&logbuff[1]);
519*9895Ssam 	}
520*9895Ssam 	if ((dict = fopen(dictname, "r")) == NULL) {
521*9895Ssam 		printf("can't open %s\n", dictname);
522*9895Ssam 		goodbye (2);
523*9895Ssam 	}
524*9895Ssam 	while ( argc > 1 && ( argv[1][0] == '+' || argv[1][0] == '-' ) ) {
525*9895Ssam 		if (argv[1][0]=='+') {
526*9895Ssam 			while(*(argv[1]++) == '+')
527*9895Ssam 				super++;
528*9895Ssam 			argc--;
529*9895Ssam 			argv++;
530*9895Ssam 		}
531*9895Ssam 		if ( argv[1][0] == '-' ) {
532*9895Ssam 			timeint[0] = 60 * ( atol( &argv[1][1] ) - 2 );
533*9895Ssam 			if ( timeint[0] <= 0 ) {
534*9895Ssam 				timeint[0] = 60;
535*9895Ssam 			}
536*9895Ssam 			argc--;
537*9895Ssam 			argv++;
538*9895Ssam 		}
539*9895Ssam 	}
540*9895Ssam 	setup ();
541*9895Ssam 	switch (argc) {
542*9895Ssam 	default:  punt:
543*9895Ssam 		printf("usage: boggle [+[+]] [row1 row2 row3 row4]\n");
544*9895Ssam 		goodbye (3);
545*9895Ssam 	case 5:
546*9895Ssam 		for (i=0; i<BSIZE; i++) {
547*9895Ssam 			board[i] = c = argv[row(i)+1][col(i)];
548*9895Ssam 			if (!islower(c)) {
549*9895Ssam 				printf("bad board\n");
550*9895Ssam 				goto punt;
551*9895Ssam 			}
552*9895Ssam 		}
553*9895Ssam 		printboard();
554*9895Ssam 		column = 0;
555*9895Ssam 		evalboard(getdword, tputword);
556*9895Ssam 		endline();
557*9895Ssam 		if (logfile >= 0) {
558*9895Ssam 			strncpy(&logbuff[0], "eval", 4);
559*9895Ssam 			lseek(logfile, logloc, 0);
560*9895Ssam 			write(logfile, &logbuff[0], 4);
561*9895Ssam 		}
562*9895Ssam 		goodbye(0);
563*9895Ssam 	case 1:
564*9895Ssam 		tempttyb.sg_flags |= CBREAK;
565*9895Ssam 		if ( ioctl( fileno(stdin), TIOCLGET, &ctlecho ) == 0 ) {
566*9895Ssam 			if ( ctlecho & LCTLECH ) {
567*9895Ssam 				ioctl( fileno(stdin), TIOCLBIC, &lctlech );
568*9895Ssam 			}
569*9895Ssam 		}
570*9895Ssam 		printinst();
571*9895Ssam 		srand((int) timein);
572*9895Ssam 		while (setjmp(env) == 0) {
573*9895Ssam 			errno = 0;
574*9895Ssam 			if (pipe(&pipefd[0]) != 0) {
575*9895Ssam 				printf("can't create pipe\n");
576*9895Ssam 				goodbye(4);
577*9895Ssam 			}
578*9895Ssam 			genboard();
579*9895Ssam 			delct = wcount = 0;
580*9895Ssam 			word[0] = freesp = &space[0];
581*9895Ssam 			if ((master = fork()) == 0) {
582*9895Ssam 				close(pipefd[0]);
583*9895Ssam 				clearscreen();
584*9895Ssam 				printboard();
585*9895Ssam 				signal(SIGALRM, timeout);
586*9895Ssam 				timept = &timeint[0];
587*9895Ssam 				alarm(*timept++);
588*9895Ssam 				evalboard(getuword, aputuword);
589*9895Ssam 				clearscreen();
590*9895Ssam 				qsort(&word[0], wcount, sizeof (int), compare);
591*9895Ssam 				for (i=0; i<wcount; i++)
592*9895Ssam 					if (i==0 || wordcomp(word[i], word[i-1])!=0) {
593*9895Ssam 						p = word[i];
594*9895Ssam 						while (isalpha(*++p)) ;
595*9895Ssam 						write (pipefd[1], word[i], p-word[i]);
596*9895Ssam 					}
597*9895Ssam 				close(pipefd[1]);
598*9895Ssam 				goodbye(0);
599*9895Ssam 			}
600*9895Ssam 			close(pipefd[1]);
601*9895Ssam 			rewind(dict);
602*9895Ssam 			getc(dict);
603*9895Ssam 			evalboard(getdword, aputword);
604*9895Ssam 			p = freesp;
605*9895Ssam 			while ((i = read(pipefd[0], freesp, 512)) != 0) {
606*9895Ssam 				if (i < 0)
607*9895Ssam 					if (errno != EINTR)
608*9895Ssam 						break;
609*9895Ssam 					else
610*9895Ssam 						i = 0;
611*9895Ssam 				freesp += i;
612*9895Ssam 			}
613*9895Ssam 			close(pipefd[0]);
614*9895Ssam 			ustart = ubotch = wcount;
615*9895Ssam 			while (p < freesp) {
616*9895Ssam 				word[wcount++] = p;
617*9895Ssam 				if (*p == '0')
618*9895Ssam 					ustart = wcount;
619*9895Ssam 				while (isalpha(*++p));
620*9895Ssam 			}
621*9895Ssam 			wait(&status);
622*9895Ssam 			if (status != 0)
623*9895Ssam 				goodbye (5);
624*9895Ssam 			delct = 1;
625*9895Ssam 			printdiff();
626*9895Ssam 			printboard();
627*9895Ssam 			games++;
628*9895Ssam 			if (logfile >= 0) {
629*9895Ssam 				sprintf(&logbuff[0], "%4d", games);
630*9895Ssam 				lseek(logfile, logloc, 0);
631*9895Ssam 				write(logfile, &logbuff[0], 4);
632*9895Ssam 			}
633*9895Ssam 			stty (fileno(stdin), &tempttyb);
634*9895Ssam 			printf("\nanother game?");
635*9895Ssam 			if (getchar() != 'y') {
636*9895Ssam 				putchar('\n');
637*9895Ssam 				break;
638*9895Ssam 			}
639*9895Ssam 			stty (fileno(stdin), &tempttyb);
640*9895Ssam 		}
641*9895Ssam 		goodbye(0);
642*9895Ssam 	}
643*9895Ssam }
644