boggle(6), from 44lite

This commit is contained in:
jtc 1994-10-21 20:52:51 +00:00
parent 107c0a28c5
commit 86ef266907
17 changed files with 2628 additions and 0 deletions

15
games/boggle/Makefile Normal file
View File

@ -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 <bsd.subdir.mk>

65
games/boggle/README Normal file
View File

@ -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

View File

@ -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 <bsd.prog.mk>

671
games/boggle/boggle/bog.c Normal file
View File

@ -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 <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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 <setjmp.h>
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 <space> to begin...");
while (inputch() != ' ');
for (done = 0; !done;) {
newgame(bspec);
bspec = NULL; /* reset for subsequent games */
playgame();
prompt("Type <space> 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);
}

85
games/boggle/boggle/bog.h Normal file
View File

@ -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;
};

View File

@ -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

View File

@ -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 *));

101
games/boggle/boggle/help.c Normal file
View File

@ -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 <curses.h>
#include <stdio.h>
#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 <space> 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);
}

View File

@ -0,0 +1,92 @@
Commands:
Enter word: <return> or <linefeed> or <space>
Delete previous character: <delete> or <backspace>
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: <space> 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:
<esc>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.

676
games/boggle/boggle/mach.c Normal file
View File

@ -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 <ctype.h>
#include <curses.h>
#include <fcntl.h>
#include <sgtty.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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': /* <del> */
case '\010': /* <bs> */
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("<PAUSE>");
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': /* <del> */
case '\010': /* <bs> */
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();
}

View File

@ -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 <curses.h>
#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);
}

118
games/boggle/boggle/timer.c Normal file
View File

@ -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 <sys/param.h>
#include <sys/time.h>
#include <curses.h>
#include <setjmp.h>
#include <stdio.h>
#include <unistd.h>
#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);
}

216
games/boggle/boggle/word.c Normal file
View File

@ -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 <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -0,0 +1,9 @@
# @(#)Makefile 8.1 (Berkeley) 6/11/93
PROG= mkdict
CFLAGS+=-I${.CURDIR}/../boggle
NOMAN=noman
install:
.include <bsd.prog.mk>

View File

@ -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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -0,0 +1,9 @@
# @(#)Makefile 8.1 (Berkeley) 6/11/93
PROG= mkindex
CFLAGS+=-I${.CURDIR}/../boggle
NOMAN=noman
install:
.include <bsd.prog.mk>

View File

@ -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 <stdio.h>
#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);
}