boggle(6), from 44lite
This commit is contained in:
parent
107c0a28c5
commit
86ef266907
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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
|
|
@ -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 *));
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/11/93
|
||||
|
||||
PROG= mkdict
|
||||
CFLAGS+=-I${.CURDIR}/../boggle
|
||||
NOMAN=noman
|
||||
|
||||
install:
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/11/93
|
||||
|
||||
PROG= mkindex
|
||||
CFLAGS+=-I${.CURDIR}/../boggle
|
||||
NOMAN=noman
|
||||
|
||||
install:
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue