From 59d081ebf54dd031de27738cf8fa17341ee4cbf0 Mon Sep 17 00:00:00 2001 From: jtc Date: Fri, 21 Oct 1994 20:52:51 +0000 Subject: boggle(6), from 44lite --- boggle/Makefile | 15 ++ boggle/README | 65 +++++ boggle/boggle/Makefile | 15 ++ boggle/boggle/bog.c | 671 ++++++++++++++++++++++++++++++++++++++++++++++ boggle/boggle/bog.h | 85 ++++++ boggle/boggle/boggle.6 | 114 ++++++++ boggle/boggle/extern.h | 71 +++++ boggle/boggle/help.c | 101 +++++++ boggle/boggle/helpfile | 92 +++++++ boggle/boggle/mach.c | 676 +++++++++++++++++++++++++++++++++++++++++++++++ boggle/boggle/prtable.c | 127 +++++++++ boggle/boggle/timer.c | 118 +++++++++ boggle/boggle/word.c | 216 +++++++++++++++ boggle/mkdict/Makefile | 9 + boggle/mkdict/mkdict.c | 124 +++++++++ boggle/mkindex/Makefile | 9 + boggle/mkindex/mkindex.c | 120 +++++++++ 17 files changed, 2628 insertions(+) create mode 100644 boggle/Makefile create mode 100644 boggle/README create mode 100644 boggle/boggle/Makefile create mode 100644 boggle/boggle/bog.c create mode 100644 boggle/boggle/bog.h create mode 100644 boggle/boggle/boggle.6 create mode 100644 boggle/boggle/extern.h create mode 100644 boggle/boggle/help.c create mode 100644 boggle/boggle/helpfile create mode 100644 boggle/boggle/mach.c create mode 100644 boggle/boggle/prtable.c create mode 100644 boggle/boggle/timer.c create mode 100644 boggle/boggle/word.c create mode 100644 boggle/mkdict/Makefile create mode 100644 boggle/mkdict/mkdict.c create mode 100644 boggle/mkindex/Makefile create mode 100644 boggle/mkindex/mkindex.c (limited to 'boggle') diff --git a/boggle/Makefile b/boggle/Makefile new file mode 100644 index 00000000..ed47dcb3 --- /dev/null +++ b/boggle/Makefile @@ -0,0 +1,15 @@ +# @(#)Makefile 8.1 (Berkeley) 6/11/93 + +SUBDIR= boggle mkdict mkindex + +beforeinstall: + mkdict/obj/mkdict < /usr/share/dict/words > \ + ${DESTDIR}/usr/share/games/boggle/dictionary + mkindex/obj/mkindex < ${DESTDIR}/usr/share/games/boggle/dictionary > \ + ${DESTDIR}/usr/share/games/boggle/dictindex + chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/share/games/boggle/dictionary + chmod 444 ${DESTDIR}/usr/share/games/boggle/dictionary + chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/share/games/boggle/dictindex + chmod 444 ${DESTDIR}/usr/share/games/boggle/dictindex + +.include diff --git a/boggle/README b/boggle/README new file mode 100644 index 00000000..ac87da00 --- /dev/null +++ b/boggle/README @@ -0,0 +1,65 @@ + +Bog is a fairly portable simulation of Parker Brother's game of Boggle and +is similar to the 4.[23] BSD "boggle" and Sun's "boggletool". +Bog has not been derived from any proprietary code. +It has been tested on the Sun 3 under SunOS 3.2 and on the Atari 1040ST (MWC). + +What You Need + +You will need curses/termcap and a large word list. +The minix word list or /usr/dict/words will do nicely. +The word list must already be sorted (you can use "sort -c" to check). + +Contents + + README - this file + Makefile + bog.man - half-hearted man page (use the game's help command) + bog.h - configuration and header info + bog.c - machine independent game code + word.c - machine independent word list routines + help.c - (curses) help routine + mach.c - (curses) display code + prtable.c - ditto + timer.c - machine dependent (os) input polling + mkdict.c - convert a word list to a bog dictionary + mkindex.c - create an index file for the bog dictionary + showdict.c - print a bog dictionary to stdout + +Portability + +- I've tried to make bog.c (the program logic) independent of the I/O. + My plan was to make it straightforward to adapt the game to run under a + windowing system (eg., Suntools, GEM). I have no plan to actually do this. + I've stuck to a small subset of the curses routines. +- The program runs with the input in raw mode. +- If you want the running timer you must #define TIMER in bog.h + and insert the input polling code in timer.c for your system. There is + already code there for BSD, SYSV, and ATARI. + +Setup + +1. Check bog.h and Makefile and edit to fit your environment +2. "make all" + This will make all the binaries and create the dictionary and index files +3. Move "dict", "dict.ind", and "helpfile" to where you specified in bog.h +4. Play away + +Distribution + +You may use this software for your enjoyment and you may share it with others. +You may not sell this software or use it for any commercial purposes +whatsoever. All modified versions of the software that you redistribute must +clearly indicate your changes. + +If you come across any bugs or make any changes you'd like to share please +send mail to me rather than posting to the net. + +Enjoy. [But beware: boggle can be addictive!] + +----- +Barry Brachman | UUCP: {alberta,uw-beaver,uunet}! +Dept. of Computer Science| ubc-vision!ubc-csgrads!brachman +Univ. of British Columbia| Internet: brachman@cs.ubc.ca +Vancouver, B.C. V6T 1W5 | brachman%ubc.csnet@csnet-relay.arpa +(604) 228-5010 | brachman@ubc.csnet diff --git a/boggle/boggle/Makefile b/boggle/boggle/Makefile new file mode 100644 index 00000000..03466cb2 --- /dev/null +++ b/boggle/boggle/Makefile @@ -0,0 +1,15 @@ +# @(#)Makefile 8.1 (Berkeley) 6/11/93 + +PROG= boggle +SRCS= bog.c help.c mach.c prtable.c timer.c word.c +DPADD= ${LIBCURSES} ${LIBTERM} +LDADD= -lcurses -ltermlib +HIDEGAME=hidegame +MAN6= boggle.0 + +beforeinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/helpfile \ + ${DESTDIR}/usr/share/games/boggle/helpfile + +.include "../../Makefile.inc" +.include diff --git a/boggle/boggle/bog.c b/boggle/boggle/bog.c new file mode 100644 index 00000000..fa76bd0c --- /dev/null +++ b/boggle/boggle/bog.c @@ -0,0 +1,671 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)bog.c 8.1 (Berkeley) 6/11/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include "bog.h" +#include "extern.h" + +static int compar __P((const void *, const void *)); + +struct dictindex dictindex[26]; + +/* + * Cube position numbering: + * + * 0 1 2 3 + * 4 5 6 7 + * 8 9 A B + * C D E F + */ +static int adjacency[16][16] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + { 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 0 */ + { 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 1 */ + { 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 2 */ + { 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 3 */ + { 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* 4 */ + { 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, /* 5 */ + { 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 }, /* 6 */ + { 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, /* 7 */ + { 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 }, /* 8 */ + { 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0 }, /* 9 */ + { 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1 }, /* A */ + { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1 }, /* B */ + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* C */ + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0 }, /* D */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1 }, /* E */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 } /* F */ +}; + +static int letter_map[26][16]; + +char board[17]; +int wordpath[MAXWORDLEN + 1]; +int wordlen; /* Length of last word returned by nextword() */ +int usedbits; + +char *pword[MAXPWORDS], pwords[MAXPSPACE], *pwordsp; +int npwords; + +char *mword[MAXMWORDS], mwords[MAXMSPACE], *mwordsp; +int nmwords; + +int ngames = 0; +int tnmwords = 0, tnpwords = 0; + +#include +jmp_buf env; + +long start_t; + +static FILE *dictfp; + +int batch; +int debug; +int minlength; +int reuse; +int tlimit; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + long seed; + int ch, done, i, selfuse, sflag; + char *bspec, *p; + + batch = debug = reuse = selfuse = sflag = 0; + bspec = NULL; + minlength = 3; + tlimit = 180; /* 3 minutes is standard */ + + while ((ch = getopt(argc, argv, "bds:t:w:")) != EOF) + switch(ch) { + case 'b': + batch = 1; + break; + case 'd': + debug = 1; + break; + case 's': + sflag = 1; + seed = atol(optarg); + break; + case 't': + if ((tlimit = atoi(optarg)) < 1) + errx(1, "bad time limit"); + break; + case 'w': + if ((minlength = atoi(optarg)) < 3) + errx(1, "min word length must be > 2"); + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (strcmp(argv[0], "+") == 0) + reuse = 1; + else if (strcmp(argv[0], "++") == 0) + selfuse = 1; + else if (islower(argv[0][0])) { + if (strlen(argv[0]) != 16) { + usage(); + + /* This board is assumed to be valid... */ + bspec = argv[0]; + } else + usage(); + } + + if (batch && bspec == NULL) + errx(1, "must give both -b and a board setup"); + + if (selfuse) + for (i = 0; i < 16; i++) + adjacency[i][i] = 1; + + if (batch) { + newgame(bspec); + while ((p = batchword(stdin)) != NULL) + (void) printf("%s\n", p); + exit (0); + } + setup(sflag, seed); + prompt("Loading the dictionary..."); + if ((dictfp = opendict(DICT)) == NULL) { + warn("%s", DICT); + cleanup(); + exit(1); + } +#ifdef LOADDICT + if (loaddict(dictfp) < 0) { + warnx("can't load %s", DICT); + cleanup(); + exit(1); + } + (void)fclose(dictfp); + dictfp = NULL; +#endif + if (loadindex(DICTINDEX) < 0) { + warnx("can't load %s", DICTINDEX); + cleanup(); + exit(1); + } + + prompt("Type to begin..."); + while (inputch() != ' '); + + for (done = 0; !done;) { + newgame(bspec); + bspec = NULL; /* reset for subsequent games */ + playgame(); + prompt("Type to continue, any cap to quit..."); + delay(50); /* wait for user to quit typing */ + flushin(stdin); + for (;;) { + ch = inputch(); + if (ch == '\033') + findword(); + else if (ch == '\014' || ch == '\022') /* ^l or ^r */ + redraw(); + else { + if (isupper(ch)) { + done = 1; + break; + } + if (ch == ' ') + break; + } + } + } + cleanup(); + exit (0); +} + +/* + * Read a line from the given stream and check if it is legal + * Return a pointer to a legal word or a null pointer when EOF is reached + */ +char * +batchword(fp) + FILE *fp; +{ + register int *p, *q; + register char *w; + + q = &wordpath[MAXWORDLEN + 1]; + p = wordpath; + while (p < q) + *p++ = -1; + while ((w = nextword(fp)) != NULL) { + if (wordlen < minlength) + continue; + p = wordpath; + while (p < q && *p != -1) + *p++ = -1; + usedbits = 0; + if (checkword(w, -1, wordpath) != -1) + return (w); + } + return (NULL); +} + +/* + * Play a single game + * Reset the word lists from last game + * Keep track of the running stats + */ +void +playgame() +{ + /* Can't use register variables if setjmp() is used! */ + int i, *p, *q; + long t; + char buf[MAXWORDLEN + 1]; + + ngames++; + npwords = 0; + pwordsp = pwords; + nmwords = 0; + mwordsp = mwords; + + time(&start_t); + + q = &wordpath[MAXWORDLEN + 1]; + p = wordpath; + while (p < q) + *p++ = -1; + showboard(board); + startwords(); + if (setjmp(env)) { + badword(); + goto timesup; + } + + while (1) { + if (getline(buf) == NULL) { + if (feof(stdin)) + clearerr(stdin); + break; + } + time(&t); + if (t - start_t >= tlimit) { + badword(); + break; + } + if (buf[0] == '\0') { + int remaining; + + remaining = tlimit - (int) (t - start_t); + (void)snprintf(buf, sizeof(buf), + "%d:%02d", remaining / 60, remaining % 60); + showstr(buf, 1); + continue; + } + if (strlen(buf) < minlength) { + badword(); + continue; + } + + p = wordpath; + while (p < q && *p != -1) + *p++ = -1; + usedbits = 0; + + if (checkword(buf, -1, wordpath) < 0) + badword(); + else { + if (debug) { + (void) printf("["); + for (i = 0; wordpath[i] != -1; i++) + (void) printf(" %d", wordpath[i]); + (void) printf(" ]\n"); + } + for (i = 0; i < npwords; i++) { + if (strcmp(pword[i], buf) == 0) + break; + } + if (i != npwords) { /* already used the word */ + badword(); + showword(i); + } + else if (!validword(buf)) + badword(); + else { + int len; + + len = strlen(buf) + 1; + if (npwords == MAXPWORDS - 1 || + pwordsp + len >= &pwords[MAXPSPACE]) { + warnx("Too many words!"); + cleanup(); + exit(1); + } + pword[npwords++] = pwordsp; + (void) strcpy(pwordsp, buf); + pwordsp += len; + addword(buf); + } + } + } + +timesup: ; + + /* + * Sort the player's words and terminate the list with a null + * entry to help out checkdict() + */ + qsort(pword, npwords, sizeof(pword[0]), compar); + pword[npwords] = NULL; + + /* + * These words don't need to be sorted since the dictionary is sorted + */ + checkdict(); + + tnmwords += nmwords; + tnpwords += npwords; + + results(); +} + +/* + * Check if the given word is present on the board, with the constraint + * that the first letter of the word is adjacent to square 'prev' + * Keep track of the current path of squares for the word + * A 'q' must be followed by a 'u' + * Words must end with a null + * Return 1 on success, -1 on failure + */ +int +checkword(word, prev, path) + char *word; + int prev, *path; +{ + register char *p, *q; + register int i, *lm; + + if (debug) { + (void) printf("checkword(%s, %d, [", word, prev); + for (i = 0; wordpath[i] != -1; i++) + (void) printf(" %d", wordpath[i]); + (void) printf(" ]\n"); + } + + if (*word == '\0') + return (1); + + lm = letter_map[*word - 'a']; + + if (prev == -1) { + char subword[MAXWORDLEN + 1]; + + /* + * Check for letters not appearing in the cube to eliminate some + * recursive calls + * Fold 'qu' into 'q' + */ + p = word; + q = subword; + while (*p != '\0') { + if (*letter_map[*p - 'a'] == -1) + return (-1); + *q++ = *p; + if (*p++ == 'q') { + if (*p++ != 'u') + return (-1); + } + } + *q = '\0'; + while (*lm != -1) { + *path = *lm; + usedbits |= (1 << *lm); + if (checkword(subword + 1, *lm, path + 1) > 0) + return (1); + usedbits &= ~(1 << *lm); + lm++; + } + return (-1); + } + + /* + * A cube is only adjacent to itself in the adjacency matrix if selfuse + * was set, so a cube can't be used twice in succession if only the + * reuse flag is set + */ + for (i = 0; lm[i] != -1; i++) { + if (adjacency[prev][lm[i]]) { + int used; + + used = 1 << lm[i]; + /* + * If necessary, check if the square has already + * been used. + */ + if (!reuse && (usedbits & used)) + continue; + *path = lm[i]; + usedbits |= used; + if (checkword(word + 1, lm[i], path + 1) > 0) + return (1); + usedbits &= ~used; + } + } + *path = -1; /* in case of a backtrack */ + return (-1); +} + +/* + * A word is invalid if it is not in the dictionary + * At this point it is already known that the word can be formed from + * the current board + */ +int +validword(word) + char *word; +{ + register int j; + register char *q, *w; + + j = word[0] - 'a'; + if (dictseek(dictfp, dictindex[j].start, 0) < 0) { + (void) fprintf(stderr, "Seek error\n"); + cleanup(); + exit(1); + } + + while ((w = nextword(dictfp)) != NULL) { + int ch; + + if (*w != word[0]) /* end of words starting with word[0] */ + break; + q = word; + while ((ch = *w++) == *q++ && ch != '\0') + ; + if (*(w - 1) == '\0' && *(q - 1) == '\0') + return (1); + } + if (dictfp != NULL && feof(dictfp)) /* Special case for z's */ + clearerr(dictfp); + return (0); +} + +/* + * Check each word in the dictionary against the board + * Delete words from the machine list that the player has found + * Assume both the dictionary and the player's words are already sorted + */ +void +checkdict() +{ + register char *p, **pw, *w; + register int i; + int prevch, previndex, *pi, *qi, st; + + mwordsp = mwords; + nmwords = 0; + pw = pword; + prevch ='a'; + qi = &wordpath[MAXWORDLEN + 1]; + + (void) dictseek(dictfp, 0L, 0); + while ((w = nextword(dictfp)) != NULL) { + if (wordlen < minlength) + continue; + if (*w != prevch) { + /* + * If we've moved on to a word with a different first + * letter then we can speed things up by skipping all + * words starting with a letter that doesn't appear in + * the cube. + */ + i = (int) (*w - 'a'); + while (i < 26 && letter_map[i][0] == -1) + i++; + if (i == 26) + break; + previndex = prevch - 'a'; + prevch = i + 'a'; + /* + * Fall through if the word's first letter appears in + * the cube (i.e., if we can't skip ahead), otherwise + * seek to the beginning of words in the dictionary + * starting with the next letter (alphabetically) + * appearing in the cube and then read the first word. + */ + if (i != previndex + 1) { + if (dictseek(dictfp, + dictindex[i].start, 0) < 0) { + warnx("seek error in checkdict()"); + cleanup(); + exit(1); + } + continue; + } + } + + pi = wordpath; + while (pi < qi && *pi != -1) + *pi++ = -1; + usedbits = 0; + if (checkword(w, -1, wordpath) == -1) + continue; + + st = 1; + while (*pw != NULL && (st = strcmp(*pw, w)) < 0) + pw++; + if (st == 0) /* found it */ + continue; + if (nmwords == MAXMWORDS || + mwordsp + wordlen + 1 >= &mwords[MAXMSPACE]) { + warnx("too many words!"); + cleanup(); + exit(1); + } + mword[nmwords++] = mwordsp; + p = w; + while (*mwordsp++ = *p++); + } +} + +/* + * Crank up a new game + * If the argument is non-null then it is assumed to be a legal board spec + * in ascending cube order, oth. make a random board + */ +void +newgame(b) + char *b; +{ + register int i, p, q; + char *tmp; + int *lm[26]; + static char *cubes[16] = { + "ednosw", "aaciot", "acelrs", "ehinps", + "eefhiy", "elpstu", "acdemp", "gilruw", + "egkluy", "ahmors", "abilty", "adenvz", + "bfiorx", "dknotu", "abjmoq", "egintv" + }; + + if (b == NULL) { + /* + * Shake the cubes and make the board + */ + i = 0; + while (i < 100) { + p = (int) (random() % 16); + q = (int) (random() % 16); + if (p != q) { + tmp = cubes[p]; + cubes[p] = cubes[q]; + cubes[q] = tmp; + i++; + } + /* else try again */ + } + + for (i = 0; i < 16; i++) + board[i] = cubes[i][random() % 6]; + } + else { + for (i = 0; i < 16; i++) + board[i] = b[i]; + } + board[16] = '\0'; + + /* + * Set up the map from letter to location(s) + * Each list is terminated by a -1 entry + */ + for (i = 0; i < 26; i++) { + lm[i] = letter_map[i]; + *lm[i] = -1; + } + + for (i = 0; i < 16; i++) { + register int j; + + j = (int) (board[i] - 'a'); + *lm[j] = i; + *(++lm[j]) = -1; + } + + if (debug) { + for (i = 0; i < 26; i++) { + int ch, j; + + (void) printf("%c:", 'a' + i); + for (j = 0; (ch = letter_map[i][j]) != -1; j++) + (void) printf(" %d", ch); + (void) printf("\n"); + } + } + +} + +int +compar(p, q) + const void *p, *q; +{ + return (strcmp(*(char **)p, *(char **)q)); +} + +void +usage() +{ + (void) fprintf(stderr, + "usage: bog [-bd] [-s#] [-t#] [-w#] [+[+]] [boardspec]\n"); + exit(1); +} diff --git a/boggle/boggle/bog.h b/boggle/boggle/bog.h new file mode 100644 index 00000000..a25f1d75 --- /dev/null +++ b/boggle/boggle/bog.h @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bog.h 8.1 (Berkeley) 6/11/93 + */ + +#define LOADDICT 1 /* Load the dictionary for speed */ + +/* + * Locations for the dictionary (generated by mkdict), + * index (generated by mkindex), and helpfile + */ +#define DICT "/usr/share/games/boggle/dictionary" +#define DICTINDEX "/usr/share/games/boggle/dictindex" +#define HELPFILE "/usr/share/games/boggle/helpfile" + +/* + * The theoretical maximum for MAXWORDLEN is ('a' - 1) == 96 + */ +#define MAXWORDLEN 40 /* Maximum word length */ +#define MAXPWORDS 200 /* Maximum number of player's words */ +#define MAXMWORDS 200 /* Maximum number of machine's words */ +#define MAXPSPACE 2000 /* Space for player's words */ +#define MAXMSPACE 4000 /* Space for machines's words */ + +#define MAXCOLS 20 + +/* + * The following determine the screen layout + */ +#define PROMPT_COL 20 +#define PROMPT_LINE 2 + +#define BOARD_COL 0 +#define BOARD_LINE 0 + +#define SCORE_COL 20 +#define SCORE_LINE 0 + +#define LIST_COL 0 +#define LIST_LINE 10 + +#define TIMER_COL 20 +#define TIMER_LINE 2 + +/* + * Internal dictionary index + * Initialized from the file created by mkindex + */ +struct dictindex { + long start; + long length; +}; diff --git a/boggle/boggle/boggle.6 b/boggle/boggle/boggle.6 new file mode 100644 index 00000000..2b9f3053 --- /dev/null +++ b/boggle/boggle/boggle.6 @@ -0,0 +1,114 @@ +.\" Copyright (c) 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Barry Brachman. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)boggle.6 8.1 (Berkeley) 6/11/93 +.\" +.TH BOGGLE 6 "June 11, 1993" +.UC +.SH NAME +boggle \- word search game +.SH SYNOPSIS +boggle [-bd] [-s seed] [-t time] [-w length] [+[+]] [boardspec] +.SH DESCRIPTION +The object of +.I boggle +is to find as many words as possible on the Boggle board within the three +minute time limit. +A Boggle board is a four by four arrangement of Boggle cubes, each side of +each cube displaying a letter of the alphabet or `qu'. +Words are formed by finding a sequence of cubes (letters) that are in the +game's dictionary. +The (N+1)th cube in the word must be horizontally, +vertically, or diagonally adjacent to the Nth cube. +Cubes cannot be reused. +Words consist solely of lower case letters and must be at least 3 letters long. +.PP +Command line flags can be given to change the rules of the game. +The +.B + +flag allows a cube to be used multiple times, but not in succession. +The +.B ++ +flag allows the same cubes to be considered adjacent to itself. +.B +A seed other than the time of day is specified by +.B -s#, +where +.B # +is the seed. +The time limit can be changed from the default 3 minutes by using the flag +.B -t#, +where +.B # +is the duration (in seconds) of each game. +The minimum word length can be changed from 3 letters by specifying +.B -w#, +where +.B # +is the minimum number of letters to use. +.PP +A starting board position can be specified on the command line by +listing the board left to right and top to bottom. +.PP +The +.B -b +flag puts +.I boggle +in batch mode. +A +.B boardspec +must also be given. +The dictionary is read from stdin and a list of words appearing in +.B boardspec +is printed to stdout. +.PP +Help is available during play by typing `?'. +More detailed information on the game is given there. +.SH BUGS +If there are a great many words in the cube the final display of the words +may scroll off of the screen. (On a 25 line screen about 130 words can be +displayed.) +.sp 2 +No word can contain a 'q' that is not immediately followed by a 'u'. +.sp 2 +When using the '+' or '++' options the display of words found in the board +doesn't indicate reused cubes. +.SH AUTHOR +Boggle is a trademark of Parker Brothers. +.br +Barry Brachman +.br +Dept. of Computer Science +.br +University of British Columbia diff --git a/boggle/boggle/extern.h b/boggle/boggle/extern.h new file mode 100644 index 00000000..9761c4f6 --- /dev/null +++ b/boggle/boggle/extern.h @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/11/93 + */ + +void addword __P((char *)); +void badword __P((void)); +char *batchword __P((FILE *)); +void checkdict __P((void)); +int checkword __P((char *, int, int *)); +void cleanup __P((void)); +void delay __P((int)); +long dictseek __P((FILE *, long, int)); +void findword __P((void)); +void flushin __P((FILE *)); +char *getline __P((char *)); +void getword __P((char *)); +int help __P((void)); +int inputch __P((void)); +int loaddict __P((FILE *)); +int loadindex __P((char *)); +void newgame __P((char *)); +char *nextword __P((FILE *)); +FILE *opendict __P((char *)); +void playgame __P((void)); +void prompt __P((char *)); +void prtable __P((char *[], + int, int, int, void (*)(char *[], int), int (*)(char *[], int))); +void putstr __P((char *)); +void redraw __P((void)); +void results __P((void)); +int setup __P((int, long)); +void showboard __P((char *)); +void showstr __P((char *, int)); +void showword __P((int)); +void starttime __P((void)); +void startwords __P((void)); +void stoptime __P((void)); +int timerch __P((void)); +void usage __P((void)); +int validword __P((char *)); diff --git a/boggle/boggle/help.c b/boggle/boggle/help.c new file mode 100644 index 00000000..684c0ff6 --- /dev/null +++ b/boggle/boggle/help.c @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)help.c 8.1 (Berkeley) 6/11/93"; +#endif /* not lint */ + +#include +#include + +#include "bog.h" +#include "extern.h" + +int +help() +{ + extern int nlines; + int eof, i; + FILE *fp; + WINDOW *win; + char buf[BUFSIZ]; + + if ((fp = fopen(HELPFILE, "r")) == NULL) + return(-1); + win = newwin(0, 0, 0, 0); + clearok(win, 1); + + eof = 0; + if (ungetc(getc(fp), fp) == EOF) { + wprintw(win, "There doesn't seem to be any help."); + eof = 1; /* Nothing there... */ + } + + while (!eof) { + for (i = 0; i < nlines - 3; i++) { + if (fgets(buf, sizeof(buf), fp) == (char *) NULL) { + eof = 1; + break; + } + if (buf[0] == '.' && buf[1] == '\n') + break; + wprintw(win, "%s", buf); + } + if (eof || ungetc(getc(fp), fp) == EOF) { + eof = 1; + break; + } + wmove(win, nlines - 1, 0); + wprintw(win, + "Type to continue, anything else to quit..."); + wrefresh(win); + if ((inputch() & 0177) != ' ') + break; + wclear(win); + } + + fclose(fp); + if (eof) { + wmove(win, nlines - 1, 0); + wprintw(win, "Hit any key to continue..."); + wrefresh(win); + inputch(); + } + delwin(win); + clearok(stdscr, 1); + refresh(); + return(0); +} diff --git a/boggle/boggle/helpfile b/boggle/boggle/helpfile new file mode 100644 index 00000000..c511efe7 --- /dev/null +++ b/boggle/boggle/helpfile @@ -0,0 +1,92 @@ + +Commands: + +Enter word: or or +Delete previous character: or +Delete line: <^u> or <^w> +Redraw screen: <^l> or <^r> +Pause game: <^s> +Resume game: <^q> or <^s> +Suspend game (BSD only): <^z> +Give up on current cube: <^d> +Show remaining time: first thing on a line +Show help: ? (Suspends timer until done) +Exit game: <^c> + +(^u means "control u", etc.) + +[Note for users of versions of this program that do not display a timer: +The first word entered after the timer has run out causes a list of all the +words you found, the words you missed, and your running statistics to be +displayed.] + +Any time you are prompted while the board is displayed you can type: + word +to see where "word" is on the board. + +Usage: + bog [-b] [-d] [-s#] [-t#] [-w#] [+[+]] [boardspec] + + -b: batch mode (boardspec must be present); dictionary read from stdin + -d: debug mode + -s#: use # as the random number seed + -t#: time limit is # seconds instead of default 180 + -w#: minimum word length is # letters instead of default 3 + +: can reuse a cube, but not twice in succession + ++: can reuse cubes arbitrarily + boardspec: the first board to use (use 'q' for 'qu'); e.g.: + bog nolezeebnqieegei +. + Default Rules + +A Boggle board is a four by four arrangement of Boggle cubes. +You have 3 minutes to find as many words as possible in the Boggle board. +Words are formed by finding a sequence of cubes (letters) that are in the +game's dictionary. The (N+1)th cube in the word must be horizontally, +vertically, or diagonally adjacent to the Nth cube. Cubes cannot be reused. +Words consist solely of lower case letters and must be at least 3 letters long. +. + Options + +Command line flags can be given to change the rules of the game. +The '+' flag allows a cube to be used multiple times, but not in succession. +The '++' flag makes each cube adjacent to itself. +The time limit can be changed from the default 3 minutes by using the flag +'-t#', where # is the duration (in seconds) of each game. +The minimum word length can be changed from 3 letters by specifying 'w#', +where # is the minimum number of letters to use. +. + Bugs and Limitations + +The following bugs and problems are known to exist: + +- If there are a great many words in the cube the final display of the words + may scroll off of the screen. (On a 25 line screen about 130 words can be + displayed.) + +- Computing the complete word list can be too slow on small machines. + +- No word can contain a 'q' that is not immediately followed by a 'u'. + +- When using the '+' or '++' options the display of words found in the board + doesn't indicate reused cubes. +. + About This Program + +Permission is given to freely copy and distribute this software providing: + +1) You do not sell it, +2) You do not use it for commercial advantage, +3) If you pass the program on you must make the source code available, and +4) This notice must accompany the distribution + +Please notify the author of any bugs or if you have any suggestions. + +Copyright (c) 1988 +Barry Brachman | UUCP: {alberta,uw-beaver,uunet}! +Dept. of Computer Science| ubc-vision!ubc-csgrads!brachman +Univ. of British Columbia| Internet: brachman@cs.ubc.ca +Vancouver, B.C. V6T 1W5 | brachman%ubc.csnet@csnet-relay.arpa +(604) 228-5010 | brachman@ubc.csnet + +Boggle is a trademark of Parker Brothers. diff --git a/boggle/boggle/mach.c b/boggle/boggle/mach.c new file mode 100644 index 00000000..a7b42010 --- /dev/null +++ b/boggle/boggle/mach.c @@ -0,0 +1,676 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)mach.c 8.1 (Berkeley) 6/11/93"; +#endif /* not lint */ + +/* + * Terminal interface + * + * Input is raw and unechoed + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bog.h" +#include "extern.h" + +static int ccol, crow, maxw; +static int colstarts[MAXCOLS], ncolstarts; +static int lastline; +int ncols, nlines; + +extern char *pword[], *mword[]; +extern int ngames, nmwords, npwords, tnmwords, tnpwords; + +static void cont_catcher __P((int)); +static int prwidth __P((char *[], int)); +static void prword __P((char *[], int)); +static void stop_catcher __P((int)); +static void tty_cleanup __P((void)); +static int tty_setup __P((void)); +static void tty_showboard __P((char *)); +static void winch_catcher __P((int)); + +/* + * Do system dependent initialization + * This is called once, when the program starts + */ +int +setup(sflag, seed) + int sflag; + long seed; +{ + extern int debug; + + if (tty_setup() < 0) + return(-1); + + if (!sflag) + time(&seed); + srandom(seed); + if (debug) + (void) printf("seed = %ld\n", seed); + return(0); +} + +/* + * Do system dependent clean up + * This is called once, just before the program terminates + */ +void +cleanup() +{ + tty_cleanup(); +} + +/* + * Display the player's word list, the list of words not found, and the running + * stats + */ +void +results() +{ + int col, row; + int denom1, denom2; + + move(LIST_LINE, LIST_COL); + clrtobot(); + printw("Words you found (%d):", npwords); + refresh(); + move(LIST_LINE + 1, LIST_COL); + prtable(pword, npwords, 0, ncols, prword, prwidth); + + getyx(stdscr, row, col); + move(row + 1, col); + printw("Words you missed (%d):", nmwords); + refresh(); + move(row + 2, col); + prtable(mword, nmwords, 0, ncols, prword, prwidth); + + denom1 = npwords + nmwords; + denom2 = tnpwords + tnmwords; + + move(SCORE_LINE, SCORE_COL); + printw("Percentage: %0.2f%% (%0.2f%% over %d game%s)\n", + denom1 ? (100.0 * npwords) / (double) (npwords + nmwords) : 0.0, + denom2 ? (100.0 * tnpwords) / (double) (tnpwords + tnmwords) : 0.0, + ngames, ngames > 1 ? "s" : ""); +} + +static void +prword(base, indx) + char *base[]; + int indx; +{ + printw("%s", base[indx]); +} + +static int +prwidth(base, indx) + char *base[]; + int indx; +{ + return (strlen(base[indx])); +} + +/* + * Main input routine + * + * - doesn't accept words longer than MAXWORDLEN or containing caps + */ +char * +getline(q) + char *q; +{ + register int ch, done; + register char *p; + int row, col; + + p = q; + done = 0; + while (!done) { + ch = timerch(); + switch (ch) { + case '\n': + case '\r': + case ' ': + done = 1; + break; + case '\033': + findword(); + break; + case '\177': /* */ + case '\010': /* */ + if (p == q) + break; + p--; + getyx(stdscr, row, col); + move(row, col - 1); + clrtoeol(); + refresh(); + break; + case '\025': /* <^u> */ + case '\027': /* <^w> */ + if (p == q) + break; + getyx(stdscr, row, col); + move(row, col - (int) (p - q)); + p = q; + clrtoeol(); + refresh(); + break; +#ifdef SIGTSTP + case '\032': /* <^z> */ + stop_catcher(0); + break; +#endif + case '\023': /* <^s> */ + stoptime(); + printw(""); + refresh(); + while ((ch = inputch()) != '\021' && ch != '\023') + ; + move(crow, ccol); + clrtoeol(); + refresh(); + starttime(); + break; + case '\003': /* <^c> */ + cleanup(); + exit(0); + /*NOTREACHED*/ + case '\004': /* <^d> */ + done = 1; + ch = EOF; + break; + case '\014': /* <^l> */ + case '\022': /* <^r> */ + redraw(); + break; + case '?': + stoptime(); + if (help() < 0) + showstr("Can't open help file", 1); + starttime(); + break; + default: + if (!islower(ch)) + break; + if ((int) (p - q) == MAXWORDLEN) { + p = q; + badword(); + break; + } + *p++ = ch; + addch(ch); + refresh(); + break; + } + } + *p = '\0'; + if (ch == EOF) + return((char *) NULL); + return(q); +} + +int +inputch() +{ + return (getch() & 0177); +} + +void +redraw() +{ + clearok(stdscr, 1); + refresh(); +} + +void +flushin(fp) + FILE *fp; +{ + int arg; + + arg = FREAD; + (void)ioctl(fileno(fp), TIOCFLUSH, &arg); +} + +static int gone; + +/* + * Stop the game timer + */ +void +stoptime() +{ + extern long start_t; + long t; + + (void)time(&t); + gone = (int) (t - start_t); +} + +/* + * Restart the game timer + */ +void +starttime() +{ + extern long start_t; + long t; + + (void)time(&t); + start_t = t - (long) gone; +} + +/* + * Initialize for the display of the player's words as they are typed + * This display starts at (LIST_LINE, LIST_COL) and goes "down" until the last + * line. After the last line a new column is started at LIST_LINE + * Keep track of each column position for showword() + * There is no check for exceeding COLS + */ +void +startwords() +{ + crow = LIST_LINE; + ccol = LIST_COL; + maxw = 0; + ncolstarts = 1; + colstarts[0] = LIST_COL; + move(LIST_LINE, LIST_COL); + refresh(); +} + +/* + * Add a word to the list and start a new column if necessary + * The maximum width of the current column is maintained so we know where + * to start the next column + */ +void +addword(w) + char *w; +{ + int n; + + if (crow == lastline) { + crow = LIST_LINE; + ccol += (maxw + 5); + colstarts[ncolstarts++] = ccol; + maxw = 0; + move(crow, ccol); + } + else { + move(++crow, ccol); + if ((n = strlen(w)) > maxw) + maxw = n; + } + refresh(); +} + +/* + * The current word is unacceptable so erase it + */ +void +badword() +{ + + move(crow, ccol); + clrtoeol(); + refresh(); +} + +/* + * Highlight the nth word in the list (starting with word 0) + * No check for wild arg + */ +void +showword(n) + int n; +{ + int col, row; + + row = LIST_LINE + n % (lastline - LIST_LINE + 1); + col = colstarts[n / (lastline - LIST_LINE + 1)]; + move(row, col); + standout(); + printw("%s", pword[n]); + standend(); + move(crow, ccol); + refresh(); + delay(15); + move(row, col); + printw("%s", pword[n]); + move(crow, ccol); + refresh(); +} + +/* + * Get a word from the user and check if it is in either of the two + * word lists + * If it's found, show the word on the board for a short time and then + * erase the word + * + * Note: this function knows about the format of the board + */ +void +findword() +{ + int c, col, found, i, r, row; + char buf[MAXWORDLEN + 1]; + extern char board[]; + extern int usedbits, wordpath[]; + extern char *mword[], *pword[]; + extern int nmwords, npwords; + + getyx(stdscr, r, c); + getword(buf); + found = 0; + for (i = 0; i < npwords; i++) { + if (strcmp(buf, pword[i]) == 0) { + found = 1; + break; + } + } + if (!found) { + for (i = 0; i < nmwords; i++) { + if (strcmp(buf, mword[i]) == 0) { + found = 1; + break; + } + } + } + for (i = 0; i < MAXWORDLEN; i++) + wordpath[i] = -1; + usedbits = 0; + if (!found || checkword(buf, -1, wordpath) == -1) { + move(r, c); + clrtoeol(); + addstr("[???]"); + refresh(); + delay(10); + move(r, c); + clrtoeol(); + refresh(); + return; + } + + standout(); + for (i = 0; wordpath[i] != -1; i++) { + row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1; + col = BOARD_COL + (wordpath[i] % 4) * 4 + 2; + move(row, col); + if (board[wordpath[i]] == 'q') + printw("Qu"); + else + printw("%c", toupper(board[wordpath[i]])); + move(r, c); + refresh(); + delay(5); + } + + standend(); + + for (i = 0; wordpath[i] != -1; i++) { + row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1; + col = BOARD_COL + (wordpath[i] % 4) * 4 + 2; + move(row, col); + if (board[wordpath[i]] == 'q') + printw("Qu"); + else + printw("%c", toupper(board[wordpath[i]])); + } + move(r, c); + clrtoeol(); + refresh(); +} + +/* + * Display a string at the current cursor position for the given number of secs + */ +void +showstr(str, delaysecs) + char *str; + int delaysecs; +{ + addstr(str); + refresh(); + delay(delaysecs * 10); + move(crow, ccol); + clrtoeol(); + refresh(); +} + +void +putstr(s) + char *s; +{ + addstr(s); +} + +/* + * Get a valid word and put it in the buffer + */ +void +getword(q) + char *q; +{ + int ch, col, done, i, row; + char *p; + + done = 0; + i = 0; + p = q; + addch('['); + refresh(); + while (!done && i < MAXWORDLEN - 1) { + ch = getch() & 0177; + switch (ch) { + case '\177': /* */ + case '\010': /* */ + if (p == q) + break; + p--; + getyx(stdscr, row, col); + move(row, col - 1); + clrtoeol(); + break; + case '\025': /* <^u> */ + case '\027': /* <^w> */ + if (p == q) + break; + getyx(stdscr, row, col); + move(row, col - (int) (p - q)); + p = q; + clrtoeol(); + break; + case ' ': + case '\n': + case '\r': + done = 1; + break; + case '\014': /* <^l> */ + case '\022': /* <^r> */ + clearok(stdscr, 1); + refresh(); + break; + default: + if (islower(ch)) { + *p++ = ch; + addch(ch); + i++; + } + break; + } + refresh(); + } + *p = '\0'; + addch(']'); + refresh(); +} + +void +showboard(b) + char *b; +{ + tty_showboard(b); +} + +void +prompt(mesg) + char *mesg; +{ + move(PROMPT_LINE, PROMPT_COL); + printw("%s", mesg); + move(PROMPT_LINE + 1, PROMPT_COL); + refresh(); +} + +static int +tty_setup() +{ + initscr(); + raw(); + noecho(); + + /* + * Does curses look at the winsize structure? + * Should handle SIGWINCH ... + */ + nlines = LINES; + lastline = nlines - 1; + ncols = COLS; + + (void) signal(SIGTSTP, stop_catcher); + (void) signal(SIGCONT, cont_catcher); + (void) signal(SIGWINCH, winch_catcher); + return(0); +} + +static void +stop_catcher(signo) + int signo; +{ + stoptime(); + noraw(); + echo(); + move(nlines - 1, 0); + refresh(); + + (void) signal(SIGTSTP, SIG_DFL); + (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP-1))); + (void) kill(0, SIGTSTP); + (void) signal(SIGTSTP, stop_catcher); +} + +static void +cont_catcher(signo) + int signo; +{ + (void) signal(SIGCONT, cont_catcher); + noecho(); + raw(); + clearok(stdscr, 1); + move(crow, ccol); + refresh(); + starttime(); +} + +/* + * The signal is caught but nothing is done about it... + * It would mean reformatting the entire display + */ +static void +winch_catcher(signo) + int signo; +{ + struct winsize win; + + (void) signal(SIGWINCH, winch_catcher); + (void) ioctl(fileno(stdout), TIOCGWINSZ, &win); + /* + LINES = win.ws_row; + COLS = win.ws_col; + */ +} + +static void +tty_cleanup() +{ + move(nlines - 1, 0); + refresh(); + noraw(); + echo(); + endwin(); +} + +static void +tty_showboard(b) + char *b; +{ + register int i; + int line; + + clear(); + move(BOARD_LINE, BOARD_COL); + line = BOARD_LINE; + printw("+---+---+---+---+"); + move(++line, BOARD_COL); + for (i = 0; i < 16; i++) { + if (b[i] == 'q') + printw("| Qu"); + else + printw("| %c ", toupper(b[i])); + if ((i + 1) % 4 == 0) { + printw("|"); + move(++line, BOARD_COL); + printw("+---+---+---+---+"); + move(++line, BOARD_COL); + } + } + move(SCORE_LINE, SCORE_COL); + printw("Type '?' for help"); + refresh(); +} diff --git a/boggle/boggle/prtable.c b/boggle/boggle/prtable.c new file mode 100644 index 00000000..a61c05fa --- /dev/null +++ b/boggle/boggle/prtable.c @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)prtable.c 8.1 (Berkeley) 6/11/93 + */ + +#include + +#include "extern.h" + +#define NCOLS 5 + +static int get_maxlen __P((char *[], int, int (*)(char **, int))); + +/* + * Routine to print a table + * Modified from 'ls.c' mods (BJB/83) + * Arguments: + * base - address of first entry + * num - number of entries + * d_cols - number of columns to use if > 0, "best" size if == 0 + * width - max line width if not zero + * prentry - address of the routine to call to print the string + * length - address of the routine to call to determine the length + * of string to be printed + * + * prtable and length are called with the the address of the base and + * an index + */ +void +prtable(base, num, d_cols, width, prentry, length) + char *base[]; + int num, d_cols, width; + void (*prentry) __P((char *[], int)); + int (*length) __P((char *[], int)); +{ + register int c, j; + register int a, b, cols, loc, maxlen, nrows, z; + int col, row; + + if (num == 0) + return; + maxlen = get_maxlen(base, num, length) + 1; + if (d_cols > 0) + cols = d_cols; + else + cols = width / maxlen; + if (cols == 0) + cols = NCOLS; + nrows = (num - 1) / cols + 1; + for (a = 1; a <= nrows; a++) { + b = c = z = loc = 0; + for (j = 0; j < num; j++) { + c++; + if (c >= a + b) + break; + } + while (j < num) { + (*prentry)(base, j); + loc += (*length)(base, j); + z++; + b += nrows; + for (j++; j < num; j++) { + c++; + if (c >= a + b) + break; + } + if (j < num) { + while (loc < z * maxlen) { + addch(' '); + loc++; + } + } + } + getyx(stdscr, row, col); + move(row + 1, 0); + } + refresh(); +} + +static int +get_maxlen(base, num, length) + char *base[]; + int num; + int (*length) __P((char **, int)); +{ + register int i, len, max; + + max = (*length)(base, 0); + for (i = 0; i < num; i++) { + if ((len = (*length)(base, i)) > max) + max = len; + } + return(max); +} diff --git a/boggle/boggle/timer.c b/boggle/boggle/timer.c new file mode 100644 index 00000000..573ec3c2 --- /dev/null +++ b/boggle/boggle/timer.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)timer.c 8.2 (Berkeley) 2/22/94"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include + +#include "bog.h" +#include "extern.h" + +static int waitch __P((long)); + +/* + * Update the display of the remaining time while waiting for a character + * If time runs out do a longjmp() to the game controlling routine, returning + * non-zero; oth. return the character + * Leave the cursor where it was initially + */ +int +timerch() +{ + extern int tlimit; + extern long start_t; + extern jmp_buf env; + long prevt, t; + int col, remaining, row; + + getyx(stdscr, row, col); + prevt = 0L; + for (;;) { + if (waitch(1000L) == 1) + break; + time(&t); + if (t == prevt) + continue; + prevt = t; + remaining = tlimit - (int) (t - start_t); + if (remaining < 0) { + longjmp(env, 1); + /*NOTREACHED*/ + } + move(TIMER_LINE, TIMER_COL); + printw("%d:%02d", remaining / 60, remaining % 60); + move(row, col); + refresh(); + } + return (getch() & 0177); +} + +/* + * Wait up to 'delay' microseconds for input to appear + * Returns 1 if input is ready, 0 oth. + */ +static int +waitch(delay) + long delay; +{ + fd_set fdbits; + struct timeval duration; + + duration.tv_sec = 0; + duration.tv_usec = delay; + FD_ZERO(&fdbits); + FD_SET(STDIN_FILENO, &fdbits); + return (select(32, &fdbits, NULL, NULL, &duration)); +} + +void +delay(tenths) + int tenths; +{ + struct timeval duration; + + duration.tv_usec = (tenths % 10 ) * 100000L; + duration.tv_sec = (long) (tenths / 10); + select(32, 0, 0, 0, &duration); +} diff --git a/boggle/boggle/word.c b/boggle/boggle/word.c new file mode 100644 index 00000000..0427dab0 --- /dev/null +++ b/boggle/boggle/word.c @@ -0,0 +1,216 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)word.c 8.1 (Berkeley) 6/11/93"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include + +#include "bog.h" +#include "extern.h" + +static char *dictspace, *dictend; +static char *sp; + +static int first = 1, lastch = 0; + +/* + * Return the next word in the compressed dictionary in 'buffer' or + * NULL on end-of-file + */ +char * +nextword(fp) + FILE *fp; +{ + extern int wordlen; + register int ch, pcount; + register char *p; + static char buf[MAXWORDLEN + 1]; + + if (fp == NULL) { + if (sp == dictend) + return (NULL); + + p = buf + (int) *sp++; + + /* + * The dictionary ends with a null byte + */ + while (*sp >= 'a') + if ((*p++ = *sp++) == 'q') + *p++ = 'u'; + } else { + if (first) { + if ((pcount = getc(fp)) == EOF) + return (NULL); + first = 0; + } else if ((pcount = lastch) == EOF) + return (NULL); + + p = buf + pcount; + + while ((ch = getc(fp)) != EOF && ch >= 'a') + if ((*p++ = ch) == 'q') + *p++ = 'u'; + lastch = ch; + } + wordlen = (int) (p - buf); + *p = '\0'; + return (buf); +} + +/* + * Reset the state of nextword() and do the fseek() + */ +long +dictseek(fp, offset, ptrname) + FILE *fp; + long offset; + int ptrname; +{ + if (fp == NULL) { + if ((sp = dictspace + offset) >= dictend) + return (-1); + return (0); + } + + first = 1; + return (fseek(fp, offset, ptrname)); +} + +FILE * +opendict(dict) + char *dict; +{ + FILE *fp; + + if ((fp = fopen(dict, "r")) == NULL) + return (NULL); + return (fp); +} + +/* + * Load the given dictionary and initialize the pointers + */ +int +loaddict(fp) + FILE *fp; +{ + struct stat statb; + long n; + int st; + char *p; + + if (fstat(fileno(fp), &statb) < 0) { + (void)fclose(fp); + return (-1); + } + + /* + * An extra character (a sentinel) is allocated and set to null + * to improve the expansion loop in nextword(). + */ + if ((dictspace = malloc(statb.st_size + 1)) == NULL) { + (void)fclose(fp); + return (-1); + } + n = (long)statb.st_size; + sp = dictspace; + dictend = dictspace + n; + + p = dictspace; + st = -1; + while (n > 0 && (st = fread(p, 1, BUFSIZ, fp)) > 0) { + p += st; + n -= st; + } + if (st < 0) { + (void)fclose(fp); + (void)fprintf(stderr, "Error reading dictionary\n"); + return (-1); + } + *p = '\0'; + return (0); +} + +/* + * Dependent on the exact format of the index file: + * Starting offset field begins in column 1 and length field in column 9 + * Taking the easy way out, the input buffer is made "large" and a check + * is made for lines that are too long + */ +int +loadindex(indexfile) + char *indexfile; +{ + register int i, j; + char buf[BUFSIZ]; + FILE *fp; + extern struct dictindex dictindex[]; + + if ((fp = fopen(indexfile, "r")) == NULL) { + (void) fprintf(stderr, "Can't open '%s'\n", indexfile); + return (-1); + } + i = 0; + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (strchr(buf, '\n') == NULL) { + (void)fprintf(stderr, + "A line in the index file is too long\n"); + return(-1); + } + j = *buf - 'a'; + if (i != j) { + (void) fprintf(stderr, "Bad index order\n"); + return(-1); + } + dictindex[j].start = atol(buf + 1); + dictindex[j].length = atol(buf + 9) - dictindex[j].start; + i++; + } + if (i != 26) { + (void) fprintf(stderr, "Bad index length\n"); + return(-1); + } + (void) fclose(fp); + return(0); +} diff --git a/boggle/mkdict/Makefile b/boggle/mkdict/Makefile new file mode 100644 index 00000000..83a323a1 --- /dev/null +++ b/boggle/mkdict/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/11/93 + +PROG= mkdict +CFLAGS+=-I${.CURDIR}/../boggle +NOMAN=noman + +install: + +.include diff --git a/boggle/mkdict/mkdict.c b/boggle/mkdict/mkdict.c new file mode 100644 index 00000000..2bec6a88 --- /dev/null +++ b/boggle/mkdict/mkdict.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkdict.c 8.1 (Berkeley) 6/11/93"; +#endif /* not lint */ + +/* + * Filter out words that: + * 1) Are not completely made up of lower case letters + * 2) Contain a 'q' not immediately followed by a 'u' + * 3) Are less that 3 characters long + * 4) Are greater than MAXWORDLEN characters long + */ + +#include +#include +#include +#include + +#include "bog.h" + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register char *p, *q; + register int ch, common, n, nwords; + int current, len, prev, qcount; + char buf[2][MAXWORDLEN + 1]; + + prev = 0; + current = 1; + buf[prev][0] = '\0'; + if (argc == 2) + n = atoi(argv[1]); + + for (nwords = 1; + fgets(buf[current], MAXWORDLEN + 1, stdin) != NULL; ++nwords) { + if ((p = index(buf[current], '\n')) == NULL) { + fprintf(stderr, + "mkdict: word too long: %s\n", buf[current]); + while ((ch = getc(stdin)) != EOF && ch != '\n') + ; + if (ch == EOF) + break; + continue; + } + len = 0; + for (p = buf[current]; *p != '\n'; p++) { + if (!islower(*p)) + break; + if (*p == 'q') { + q = p + 1; + if (*q != 'u') + break; + else { + while (*q = *(q + 1)) + q++; + } + len++; + } + len++; + } + if (*p != '\n' || len < 3 || len > MAXWORDLEN) + continue; + if (argc == 2 && nwords % n) + continue; + + *p = '\0'; + p = buf[current]; + q = buf[prev]; + qcount = 0; + while ((ch = *p++) == *q++ && ch != '\0') + if (ch == 'q') + qcount++; + common = p - buf[current] - 1; + printf("%c%s", common + qcount, p - 1); + prev = !prev; + current = !current; + } + fprintf(stderr, "%d words\n", nwords); + exit(0); +} diff --git a/boggle/mkindex/Makefile b/boggle/mkindex/Makefile new file mode 100644 index 00000000..0b8a02f4 --- /dev/null +++ b/boggle/mkindex/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/11/93 + +PROG= mkindex +CFLAGS+=-I${.CURDIR}/../boggle +NOMAN=noman + +install: + +.include diff --git a/boggle/mkindex/mkindex.c b/boggle/mkindex/mkindex.c new file mode 100644 index 00000000..eae6c565 --- /dev/null +++ b/boggle/mkindex/mkindex.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Barry Brachman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkindex.c 8.1 (Berkeley) 6/11/93"; +#endif /* not lint */ + +#include + +#include "bog.h" + +char *nextword __P((FILE *, char *, int *, int *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int clen, rlen, prev; + long off, start; + char buf[MAXWORDLEN + 1]; + + prev = '\0'; + off = start = 0L; + while (nextword(stdin, buf, &clen, &rlen) != NULL) { + if (*buf != prev) { + if (prev != '\0') + printf("%c %6ld %6ld\n", prev, start, off - 1); + prev = *buf; + start = off; + } + off += clen + 1; + } + printf("%c %6ld %6ld\n", prev, start, off - 1); + exit(0); +} + +/* + * Return the next word in the compressed dictionary in 'buffer' or + * NULL on end-of-file + * Also set clen to the length of the compressed word (for mkindex) and + * rlen to the strlen() of the real word + */ +char * +nextword(fp, buffer, clen, rlen) + FILE *fp; + char *buffer; + int *clen, *rlen; +{ + register int ch, pcount; + register char *p, *q; + static char buf[MAXWORDLEN + 1]; + static int first = 1; + static int lastch = 0; + + if (first) { + if ((pcount = getc(fp)) == EOF) + return (NULL); + first = 0; + } + else if ((pcount = lastch) == EOF) + return (NULL); + + p = buf + (*clen = pcount); + + while ((ch = getc(fp)) != EOF && ch >= 'a') + *p++ = ch; + lastch = ch; + *p = '\0'; + + *rlen = (int) (p - buf); + *clen = *rlen - *clen; + + p = buf; + q = buffer; + while ((*q++ = *p) != '\0') { + if (*p++ == 'q') + *q++ = 'u'; + } + return (buffer); +} -- cgit v1.2.3-56-ge451