#include <stdio.h>
#include <stdlib.h>
#include "splib.h"
#ifndef TRUE
#define TRUE (0==0)
#define FALSE (!TRUE)
#endif
int printed = 0;
NODE *dict;
INDEX nedges;
char *die5[25] = {
"hiprry",
"ceipst",
"aafirs",
"adennn",
"ddlonr",
"ooottu",
"aaafrs",
"ceiilt",
"ccnstw",
"fiprsy",
"aeegmu",
"dhlnor",
"gorrvw",
"dhhlor",
"aaeeee",
"ensssu",
"ceilpt",
"emottt",
"aeeeem",
"eiiitt",
"afirsy",
"dhhnot",
"aegmnn",
"nootuw",
"bjkQxz"
};
char *die4[16] = {
"eegnaa",
"soiset",
"abbooj",
"ldexir",
"wrethv",
"wtoota",
"muQhni",
"wegnhe",
"tstidy",
"verldy",
"ienues",
"zhrlnn",
"fskfap",
"rettyl",
"iotmcu",
"ahspoc"
};
#define swap(a, b, c) {c = a; a = b; b = c;}
int irand(int max)
{
/* return an integer between 0 and i-1 */
int i = rand();
if (i < 0) i = -i;
i = i % max;
if (i >= max) i = 0;
return(i);
}
int check_word(char *s)
{
return(dawg_check(dict, s));
}
int check_stem(char *s)
{
return(dawg_prefix(dict, s));
}
void output_word(char *s, int len)
{
if (len >= 3) printf("%s\n", s);
printed += 1;
}
void boggle(int bogsize, int x, int y, char *stem, int stemlen, int board[5][5], int used[5][5])
{
int dx, dy, len;
/* pruning illegal moves would be more efficient outside the procedure call,
but not as elegant */
if (x < 0 || x >= bogsize) return;
if (y < 0 || y >= bogsize) return;
if (used[x][y]) return;
if (board[x][y] == 'Q') {
/* Easy hack for 'qu' tile */
/* Note it wouldn't be much of a hack to *also* invoke the
next step to search for those words with 'q' which *aren't*
followed by a 'u'. However I don't think they're allowed
in boggle... */
stem[stemlen] = 'q';
stem[stemlen+1] = 'u';
len = 2;
} else {
stem[stemlen] = board[x][y];
len = 1;
}
stem[stemlen+len] = '\0';
if (check_word(stem)) { /* Got one */
output_word(stem, stemlen+len);
}
if (!check_stem(stem)) {
return; /* Prune search - can't find any with this prefix */
}
used[x][y] = TRUE;
for (dy = -1; dy <= 1; dy++) {
for (dx = -1; dx <= 1; dx++) {
/* The 'if' is optional - would be trimmed inside by used[][]==TRUE */
if (dx != 0 || dy != 0) {
boggle(bogsize, x+dx, y+dy, stem, stemlen+len, board, used);
}
}
}
stem[stemlen] = '\0';
used[x][y] = FALSE;
return;
}
int skip_spaces(void)
{
int c;
for (;;) {
c = fgetc(stdin);
if (c != ' ') return(c);
}
}
int get_tile(void)
{
int c = skip_spaces();
if (c == 'q') {
c = fgetc(stdin);
if (c != 'u') {
fprintf(stderr, "Data file error: 'q' not followed by 'u'\n");
exit(2);
}
return('Q');
} else return(c);
}
void drain_line(void)
{
int c = skip_spaces();
if (c == '\n') return;
fprintf(stderr, "Data file error: spurious character '%c'\n", c);
exit(3);
}
int main(int argc, char **argv) {
int juggle[25];
int board[5][5];
int used[5][5];
char word[51];
int bogsize = 4;
int x, y, i, tmp;
int use_stdin = FALSE;
int use_argv4 = FALSE;
if (!dawg_init("words", &dict, &nedges)) {
fprintf(stderr, "Cannot open words.dwg\n");
exit(1);
}
if (argc >= 2) {
if (strcmp(argv[1], "-5") == 0) {
bogsize = 5;
argv += 1; argc -= 1;
}
}
if (argc == 2) {
/* filename param */
if (strcmp(argv[1], "-") == 0) {
/* Use stdin */
use_stdin = TRUE;
} else {
/* use file at argv[1] - not yet implemented */
}
} else if (argc == 5) {
/* four four-letter words on command line - use those instead of stdin */
use_argv4 = TRUE;
/* bsd compatibility mode, for use with ../gboggle */
}
for (i = 0; i < bogsize*bogsize; i++) {
juggle[i] = i;
}
srand(14); /* 14 gives us a Q for testing, on mine at least */
/* Standard card-shuffling algorithm */
for (i = 0; i < bogsize*bogsize; i++) {
if ((irand(2)&1) != 0) swap(juggle[i], juggle[bogsize*bogsize-1], tmp);
/* bugfix 16Jun00: had juggle[15] above */
}
for (y = 0; y < bogsize; y++) {
for (x = 0; x < bogsize; x++) {
if (bogsize == 4) {
board[x][y] = die4[juggle[y*bogsize+x]][irand(6)];
} else {
board[x][y] = die5[juggle[y*bogsize+x]][irand(6)];
}
used[x][y] = FALSE;
}
}
if (use_stdin) {
for (y = 0; y < bogsize; y++) {
for (x = 0; x < bogsize; x++) {
board[x][y] = get_tile();
}
drain_line();
}
} else if (use_argv4) {
int ap, c;
for (ap = 1; ap <= 4; ap++) {
for (x = 0; x < bogsize; x++) {
c = argv[ap][x];
if (c == 'q') c = 'Q';
board[x][4-ap] = c;
}
}
} else {
for (y = 0; y < bogsize; y++) {
for (x = 0; x < bogsize; x++) {
printf(" %c", board[x][y]);
}
printf("\n");
}
}
word[0] = '\0';
for (y = 0; y < bogsize; y++) {
for (x = 0; x < bogsize; x++) {
boggle(bogsize, x, y, word, 0, board, used);
}
}
if (use_argv4) fprintf(stderr, "gtboggle: %s %s %s %s %d\n", argv[1], argv[2], argv[3], argv[4], printed);
exit(0);
}