147854Sbostic /*- 247854Sbostic * Copyright (c) 1982 The Regents of the University of California. 347854Sbostic * All rights reserved. 447854Sbostic * 547854Sbostic * %sccs.include.proprietary.c% 621499Smckusick */ 721499Smckusick 89895Ssam #ifndef lint 921499Smckusick char copyright[] = 1047854Sbostic "@(#) Copyright (c) 1982 The Regents of the University of California.\n\ 1121499Smckusick All rights reserved.\n"; 1247854Sbostic #endif /* not lint */ 139895Ssam 1421499Smckusick #ifndef lint 15*59781Storek static char sccsid[] = "@(#)boggle.c 5.7 (Berkeley) 05/07/93"; 1647854Sbostic #endif /* not lint */ 1721499Smckusick 18*59781Storek #include <sys/types.h> 19*59781Storek #include <sys/wait.h> 209895Ssam #include <ctype.h> 219895Ssam #include <errno.h> 22*59781Storek #include <fcntl.h> 239895Ssam #include <setjmp.h> 249895Ssam #include <sgtty.h> 259895Ssam #include <signal.h> 269895Ssam #include <stdio.h> 27*59781Storek #include <stdlib.h> 28*59781Storek #include <string.h> 29*59781Storek #include <time.h> 30*59781Storek #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}; 61*59781Storek 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; 70*59781Storek 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 }; 81*59781Storek struct frame stack[SSIZE]; 82*59781Storek struct frame *level[BSIZE+1]; 839895Ssam 849895Ssam /* the board and subsidiary structures */ 85*59781Storek char present[BSIZE+1]; 86*59781Storek char board[BSIZE]; 87*59781Storek char olink[BSIZE]; 88*59781Storek char adj[BSIZE+1][BSIZE]; 89*59781Storek char occurs[26]; 909895Ssam 919895Ssam /* the boggle cubes */ 92*59781Storek 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; 102*59781Storek char *word[MAXWORDS]; 1039895Ssam char *freesp; 1049895Ssam char space[10000]; 1059895Ssam 106*59781Storek void aputuword __P((int)); 107*59781Storek void aputword __P((int)); 108*59781Storek void clearscreen __P((void)); 109*59781Storek int compare __P((const void *, const void *)); 110*59781Storek void endline __P((void)); 111*59781Storek int evalboard __P((int (*)(void), void (*)(int))); 112*59781Storek void genboard __P((void)); 113*59781Storek int getdword __P((void)); 114*59781Storek int getuword __P((void)); 115*59781Storek __dead void goodbye __P((int)); 116*59781Storek void interrupt __P((int)); 117*59781Storek void makelists __P((void)); 118*59781Storek int numways __P((struct frame *, struct frame *)); 119*59781Storek void outword __P((char *)); 120*59781Storek void printboard __P((void)); 121*59781Storek void printdiff __P((void)); 122*59781Storek void printinst __P((void)); 123*59781Storek void setup __P((void)); 124*59781Storek void timeout __P((int)); 125*59781Storek void tputword __P((int)); 126*59781Storek int wordcomp __P((char *, char *)); 127*59781Storek 128*59781Storek 129*59781Storek void 130*59781Storek endline() 1319895Ssam { 1329895Ssam if (column != 0) { 1339895Ssam putchar('\n'); 1349895Ssam column = 0; 1359895Ssam } 1369895Ssam } 1379895Ssam 13846734Sbostic void 139*59781Storek timeout(sig) 140*59781Storek int sig; 1419895Ssam { 1429895Ssam if (*timept > 0) { 143*59781Storek signal(SIGALRM, timeout); 1449895Ssam alarm(*timept++); 1459895Ssam } 1469895Ssam putchar('\007'); 1479895Ssam } 1489895Ssam 14946734Sbostic void 150*59781Storek interrupt(sig) 151*59781Storek int sig; 1529895Ssam { 153*59781Storek 1549895Ssam signal(SIGINT, interrupt); 1559895Ssam if (delct++ >= 1) 1569895Ssam longjmp(env, 1); 1579895Ssam timept = &zero; 1589895Ssam } 1599895Ssam 160*59781Storek __dead void 161*59781Storek goodbye(stat) 162*59781Storek int stat; 1639895Ssam { 1649895Ssam if (master != 0) { 1659895Ssam wait(&status); 166*59781Storek if (ctlecho & LCTLECH) 167*59781Storek ioctl(fileno(stdin), TIOCLBIS, &lctlech); 1689895Ssam stty(fileno(stdin), &origttyb); 1699895Ssam } 1709895Ssam exit(stat); 1719895Ssam } 1729895Ssam 173*59781Storek void 174*59781Storek clearscreen() 1759895Ssam { 176*59781Storek stty(fileno(stdin), &tempttyb); 1779895Ssam printf("\n\033\f\r"); 1789895Ssam } 1799895Ssam 180*59781Storek int 181*59781Storek compare(a, b) 182*59781Storek const void *a, *b; 1839895Ssam { 184*59781Storek 185*59781Storek return(wordcomp(*(char **)a, *(char **)b)); 1869895Ssam } 1879895Ssam 188*59781Storek int 189*59781Storek wordcomp(p, q) 190*59781Storek 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 204*59781Storek void 205*59781Storek printinst() 2069895Ssam { 207*59781Storek 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"); 236*59781Storek stty(fileno(stdin), &tempttyb); 2379895Ssam getchar(); 2389895Ssam } 239*59781Storek stty(fileno(stdin), &tempttyb); 2409895Ssam } 2419895Ssam 242*59781Storek void 243*59781Storek 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 274*59781Storek void 275*59781Storek 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 287*59781Storek void 288*59781Storek 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 301*59781Storek void 302*59781Storek 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 316*59781Storek int 317*59781Storek 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 333*59781Storek int 334*59781Storek 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 366*59781Storek void 367*59781Storek aputuword(ways) 368*59781Storek int ways; 3699895Ssam { 3709895Ssam *word[wcount-1] = ways>=10 ? '*' : '0'+ways; 3719895Ssam } 3729895Ssam 373*59781Storek void 374*59781Storek aputword(ways) 375*59781Storek 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 385*59781Storek void 386*59781Storek tputword(ways) 387*59781Storek 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 395*59781Storek void 396*59781Storek outword(p) 397*59781Storek 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 425*59781Storek void 426*59781Storek 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 478*59781Storek int 479*59781Storek numways(leaf, last) 480*59781Storek register struct frame *leaf; 481*59781Storek 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 500*59781Storek int 5019895Ssam evalboard (getword, putword) 502*59781Storek int (*getword) __P((void)); 503*59781Storek 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 559*59781Storek int 560*59781Storek main(argc, argv) 561*59781Storek int argc; 562*59781Storek char **argv; 5639895Ssam { 5649895Ssam char *q; 5659895Ssam register char *p; 5669895Ssam register int i, c; 5679895Ssam 568*59781Storek gtty(fileno(stdin), &origttyb); 5699895Ssam setbuf(stdin, NULL); 5709895Ssam tempttyb = origttyb; 5719895Ssam if (setjmp(env) != 0) 5729895Ssam goodbye(0); 573*59781Storek signal(SIGINT, interrupt); 57446734Sbostic timein = time((time_t *)NULL); 575*59781Storek if (argv[0][0] != 'a' && 576*59781Storek (logfile = open(_PATH_BOGLOG, O_WRONLY, 0)) >= 0) { 5779895Ssam p = &logbuff[5]; 5789895Ssam q = getlogin(); 579*59781Storek while ((*p++ = *q++) != 0); 5809895Ssam p[-1] = '\t'; 5819895Ssam q = ctime(&timein); 582*59781Storek 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(); 656*59781Storek 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