billr@saab.CNA.TEK.COM (Bill Randle) (07/27/90)
Submitted-by: Brien Wheeler <wheeler@fermi.ces.cwru.edu>
Posting-number: Volume 11, Issue 1
Archive-name: kriss/Part01
[I haven't tried this one. Even though it's an X-only game,
it doesn't have all the accessory files required by
comp.sources.x, so I'm posting it here. -br]
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 1)."
# Contents: README MANIFEST kriss.c kriss.man
# Wrapped by billr@saab on Thu Jul 26 15:27:33 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(549 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XKriss solves puzzles that are generically known as kriss-kross puzzles.
XGiven a board layout and a list of words, kriss will fit all the words
Xinto the puzzle board. Kriss uses the X Windowing System to display the
Xboard. The list of words should be in the 'words' file upon startup.
X
XAfter starting up, kriss will display either the board read from the
X'board' file, or a blank board. See the man page for more details.
X
X Brien L. Wheeler
X Department of Computer Engineering and Science
X Case Western Reserve University
END_OF_FILE
if test 549 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(238 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X-----------------------------------------------------------
X MANIFEST 1 This shipping list
X README 1
X kriss.c 1
X kriss.man 1
END_OF_FILE
if test 238 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'kriss.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kriss.c'\"
else
echo shar: Extracting \"'kriss.c'\" \(28120 characters\)
sed "s/^X//" >'kriss.c' <<'END_OF_FILE'
X/*
X * (C) 1990 Brien L. Wheeler
X *
X * This software may be freely distributed as long as this notice
X * remains on it and unchanged. It shall in no case be sold singly
X * or as part of a package, without written permission of the author.
X *
X * Version: 2.0 Date: July 16 1990
X */
X
X/* History:
X * Version 1.0 :
X * Basic solving of puzzle
X * Command line options
X *
X * Version 2.0 :
X * Starting word
X * Instructions window
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <X11/Xlib.h>
X
X#define MAXWLEN 15
X
X#define MINROWS 20
X#define MINCOLS 20
X
X#define MAXROWS 50
X#define MAXCOLS 50
X
X#define SWIDTH 15
X#define SHEIGHT 15
X
X#define HORZ 1
X#define VERT 2
X
X#define LARGE 32767
X
X#define FONT "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1"
X
X#define min(x,y) ((x<y)?x:y)
X#define max(x,y) ((x>y)?x:y)
X
Xtypedef struct wlist {
X char *word;
X int used;
X struct wlist *next;
X } WList, *PtrWList;
X
Xtypedef struct wllist {
X struct wlist *wlist;
X struct wllist *next;
X } WLList, *PtrWLList;
X
Xtypedef struct splist {
X int verhor;
X int r;
X int c;
X int used;
X struct splist *next;
X } SpList, *PtrSpList;
X
Xint display=1;
Xint pause=0;
Xint fast=0;
Xint rows;
Xint cols;
Xint nword;
Xint stage=1;
Xint textx=0;
Xint texty=0;
Xint nwlen[MAXWLEN+1];
XPtrWList words[MAXWLEN+1];
XPtrSpList space[MAXWLEN+1];
Xchar board[MAXROWS][MAXCOLS];
X
XDisplay *dpy;
XWindow pwin;
XWindow win;
XWindow win2;
XGC gc;
XGC rgc;
XXFontStruct *font;
X
Xchar *malloc();
Xchar *getenv();
Xchar *index();
X
Xvoid
XInitialize()
X{
X int i;
X int j;
X
X nword = 0;
X
X for (i=0; i<=MAXWLEN; i++) {
X nwlen[i] = 0;
X words[i] = NULL;
X space[i] = NULL;
X }
X
X for (i=0; i<MAXROWS; i++)
X for (j=0; j<MAXCOLS; j++)
X board[i][j] = (char) -1;
X
X return;
X}
X
X
Xvoid
XInputWords()
X{
X FILE *infil;
X char buf[80];
X int error=0;
X PtrWList tmp;
X int len;
X
X infil = fopen("words","r");
X if (infil == NULL) {
X fprintf(stderr,"\n\nCouldn't open 'words' file.\n\n");
X exit(-1);
X }
X
X fscanf(infil,"%s",buf);
X while (!feof(infil)) {
X len = strlen(buf);
X if (len == 1) {
X fprintf(stderr,"Error: One-character word found in 'words'\n\n");
X exit(-1);
X }
X if (len > MAXWLEN) {
X fprintf(stderr,"Error: %s greater than %d characters.\n",
X buf,MAXWLEN);
X error++;
X }
X else if (len != 0) {
X tmp = (PtrWList) malloc(sizeof(WList));
X tmp->word = malloc(len + 1);
X strcpy(tmp->word,buf);
X tmp->used = 0;
X tmp->next = words[len];
X words[len] = tmp;
X nwlen[len]++;
X }
X fscanf(infil,"%s",buf);
X }
X fclose(infil);
X
X if (error) {
X fprintf(stderr,"\n\nErrors in 'words' file.\n\n");
X exit(-1);
X }
X
X return;
X}
X
Xvoid
XPrintString(str)
Xchar *str;
X{
X static int maxasc=0;
X static int maxdes=0;
X int again;
X int asc;
X int des;
X int dir;
X int w;
X char *buf;
X char *c;
X char *r;
X XCharStruct dum;
X
X c = buf = malloc(strlen(str)+1);
X strcpy(buf,str);
X
X w = SWIDTH * cols - 9;
X
X while (XTextWidth(font,c,strlen(c)) > (w - textx)) {
X r = c + (strlen(str)-1)*sizeof(char);
X do {
X again = 0;
X while ((r > c) && (!isspace(*r) || isspace(*(r-sizeof(char)))))
X r--;
X if (XTextWidth(font,c,(r-c)/sizeof(char)+1) > (w - textx)) {
X r--;
X again = 1;
X }
X } while (again);
X if (r == c) {
X if (textx == 0) {
X if (texty == 0) {
X XTextExtents(font, c, strlen(c), &dir, &asc, &des, &dum);
X texty = asc + des + 2;
X }
X XDrawImageString(dpy,win2,gc,textx,texty,c,strlen(c));
X textx = 0;
X XTextExtents(font, c, strlen(c), &dir, &asc, &des, &dum);
X maxasc = max(maxasc,asc);
X maxdes = max(maxdes,des);
X texty += maxasc + maxdes;
X maxasc = maxdes = 0;
X free(buf);
X return;
X }
X else {
X textx = 0;
X texty += maxasc + maxdes;
X maxasc = maxdes = 0;
X }
X }
X else {
X *r = '\0';
X if (texty == 0) {
X XTextExtents(font, c, strlen(c), &dir, &asc, &des, &dum);
X texty = asc + des + 2;
X }
X XDrawImageString(dpy,win2,gc,textx,texty,c,strlen(c));
X textx = 0;
X XTextExtents(font, c, strlen(c), &dir, &asc, &des, &dum);
X maxasc = max(maxasc,asc);
X maxdes = max(maxdes,des);
X texty += maxasc + maxdes;
X maxasc = maxdes = 0;
X c = r + sizeof(char);
X while (isspace(*c))
X c++;
X }
X }
X
X if (*c) {
X if (texty == 0) {
X XTextExtents(font, c, strlen(c), &dir, &asc, &des, &dum);
X texty = asc + des + 2;
X }
X XDrawImageString(dpy,win2,gc,textx,texty,c,strlen(c));
X textx += XTextWidth(font,c,strlen(c));
X XTextExtents(font,c,strlen(c),&dir,&asc,&des,&dum);
X maxasc = max(maxasc,asc);
X maxdes = max(maxdes,des);
X }
X
X free(buf);
X return;
X}
X
Xvoid
XInstructions()
X{
X textx = texty = 0;
X XClearWindow(dpy,win2);
X
X switch (stage) {
X case 1:
X PrintString("Use Button1 to create spaces on the board. ");
X PrintString("Use Button2 to erase spaces from the board. ");
X PrintString("Click Button3 when done.");
X break;
X
X case 2:
X PrintString("Use Button1 or Button2 to designate the space ");
X PrintString("for the starting word.");
X PrintString("Click Button3 if there is no starting word.");
X break;
X
X case 3:
X PrintString("Use Button1 and Button2 to move backward and ");
X PrintString("forward through the list of words. Use Button3 ");
X PrintString("to solve the puzzle using the initial word shown.");
X break;
X
X case 4:
X PrintString("Solving.");
X break;
X
X case 5:
X PrintString("Solution.");
X }
X}
X
Xvoid
XInitWindow()
X{
X int scr;
X int w;
X int h;
X
X dpy = XOpenDisplay(getenv("DISPLAY"));
X
X if (dpy == NULL) {
X fprintf(stderr,"\n\nCouldn't open display.\n\n");
X exit(-1);
X }
X
X scr = DefaultScreen(dpy);
X
X w = SWIDTH * cols + 1;
X h = SHEIGHT * rows + 1;
X
X pwin = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),
X 0,0,w,h+100,0,BlackPixel(dpy,scr),WhitePixel(dpy,scr));
X
X win = XCreateSimpleWindow(dpy,pwin,0,0,w,h,0,BlackPixel(dpy,scr),
X BlackPixel(dpy,scr));
X
X win2 = XCreateSimpleWindow(dpy,pwin,0,h,w,100,0,BlackPixel(dpy,scr),
X WhitePixel(dpy,scr));
X
X gc = XCreateGC(dpy,win,0,0);
X XSetForeground(dpy,gc,BlackPixel(dpy,scr));
X XSetBackground(dpy,gc,WhitePixel(dpy,scr));
X
X rgc = XCreateGC(dpy,win,0,0);
X XSetForeground(dpy,rgc,WhitePixel(dpy,scr));
X XSetBackground(dpy,rgc,BlackPixel(dpy,scr));
X
X font = XLoadQueryFont(dpy,FONT);
X XSetFont(dpy,gc,font->fid);
X
X XSelectInput(dpy,win,ExposureMask | ButtonPressMask | ButtonReleaseMask);
X
X XSelectInput(dpy,win2,ExposureMask | KeyPressMask);
X
X XStoreName(dpy,pwin,"XKrissKross");
X XSetIconName(dpy,pwin,"Kross");
X
X XMapWindow(dpy,pwin);
X XMapSubwindows(dpy,pwin);
X
X return;
X}
X
Xvoid
XOutlineSpace(r,c)
Xint r;
Xint c;
X{
X int ulx;
X int uly;
X
X ulx = c * SWIDTH + 1;
X uly = r * SHEIGHT + 1;
X
X XDrawLine(dpy,win,rgc,ulx,uly,ulx+SWIDTH-2,uly);
X XDrawLine(dpy,win,rgc,ulx,uly,ulx,uly+SHEIGHT-2);
X XDrawLine(dpy,win,rgc,ulx+SWIDTH-2,uly,ulx+SWIDTH-2,uly+SHEIGHT-2);
X XDrawLine(dpy,win,rgc,ulx,uly+SHEIGHT-2,ulx+SWIDTH-2,uly+SHEIGHT-2);
X
X return;
X}
X
Xvoid
XFillSpace(r,c)
Xint r;
Xint c;
X{
X int ulx;
X int uly;
X
X ulx = c * SWIDTH + 1;
X uly = r * SHEIGHT + 1;
X
X XClearArea(dpy,win,ulx,uly,SWIDTH-1,SHEIGHT-1,False);
X
X return;
X}
X
Xvoid
XClearSpace(r,c)
Xint r;
Xint c;
X{
X int ulx;
X int uly;
X
X ulx = c * SWIDTH + 1;
X uly = r * SHEIGHT + 1;
X
X XFillRectangle(dpy,win,rgc,ulx,uly,SWIDTH-1,SHEIGHT-1);
X
X return;
X}
X
Xvoid
XLetterSpace(r,c,ch)
Xint r;
Xint c;
Xchar ch;
X{
X int ulx;
X int uly;
X char c2;
X
X ulx = c * SWIDTH + 1;
X uly = r * SHEIGHT + 1;
X
X c2 = toupper(ch);
X
X XDrawImageString(dpy,win,gc,ulx+3,uly+SHEIGHT-4,&c2,1);
X
X return;
X}
X
Xvoid
XRedrawBoard(outline)
XBool outline;
X{
X int i;
X int j;
X int done;
X XEvent xev;
X
X XClearWindow(dpy,win);
X
X for (i=0; i<rows; i++)
X for (j=0; j<cols; j++)
X switch ((int) board[i][j]) {
X case -1 :
X if (outline == True)
X OutlineSpace(i,j);
X break;
X case 0 :
X ClearSpace(i,j);
X break;
X default :
X ClearSpace(i,j);
X LetterSpace(i,j,board[i][j]);
X }
X
X Instructions();
X
X done = 0;
X while (XPending(dpy) && !done) {
X XPeekEvent(dpy,&xev);
X if (xev.type == Expose)
X XNextEvent(dpy,&xev);
X else
X done++;
X }
X
X return;
X}
X
Xvoid
XGetXY(xbev,r,c)
XXButtonEvent *xbev;
Xint *r;
Xint *c;
X{
X *c = xbev->x / SWIDTH;
X *r = xbev->y / SHEIGHT;
X return;
X}
X
X
Xvoid
XCreateSpace(xbev)
XXButtonEvent *xbev;
X{
X int done=0;
X int i;
X int r1;
X int r2;
X int c1;
X int c2;
X XEvent xev;
X XButtonEvent *xbev2;
X
X while (!done) {
X XNextEvent(dpy,&xev);
X
X if (xev.type == ButtonRelease) {
X done++;
X xbev2 = (XButtonEvent *) &xev;
X }
X }
X
X GetXY(xbev,&r1,&c1);
X GetXY(xbev2,&r2,&c2);
X
X if (r1 == r2)
X for (i=min(c1,c2); i<=max(c1,c2); i++) {
X ClearSpace(r1,i);
X board[r1][i] = (char) 0;
X }
X else if (c1 == c2)
X for (i=min(r1,r2); i<=max(r1,r2); i++) {
X ClearSpace(i,c1);
X board[i][c1] = (char) 0;
X }
X
X return;
X}
X
Xvoid
XDeleteSpace(xbev)
XXButtonEvent *xbev;
X{
X int done=0;
X int i;
X int r1;
X int r2;
X int c1;
X int c2;
X XEvent xev;
X XButtonEvent *xbev2;
X
X while (!done) {
X XNextEvent(dpy,&xev);
X
X if (xev.type == ButtonRelease) {
X done++;
X xbev2 = (XButtonEvent *) &xev;
X }
X }
X
X GetXY(xbev,&r1,&c1);
X GetXY(xbev2,&r2,&c2);
X
X if (r1 == r2)
X for (i=min(c1,c2); i<=max(c1,c2); i++) {
X FillSpace(r1,i);
X OutlineSpace(r1,i);
X board[r1][i] = (char) -1;
X }
X else if (c1 == c2)
X for (i=min(r1,r2); i<=max(r1,r2); i++) {
X FillSpace(i,c1);
X OutlineSpace(i,c1);
X board[i][c1] = (char) -1;
X }
X
X return;
X}
X
Xvoid
XInputBoard()
X{
X int done=0;
X XEvent xev;
X XButtonEvent *xbev;
X
X while (!done) {
X while (!XPending(dpy));
X
X XNextEvent(dpy,&xev);
X if (xev.type == Expose)
X RedrawBoard(True);
X
X if (xev.type == ButtonPress) {
X xbev = (XButtonEvent *) &xev;
X switch(xbev->button) {
X case Button1 :
X CreateSpace(xbev);
X break;
X case Button2 :
X DeleteSpace(xbev);
X break;
X case Button3 :
X done++;
X }
X }
X }
X
X return;
X}
X
X
Xvoid
XFreeSpLists()
X{
X int i;
X PtrSpList SpL;
X PtrSpList tmp;
X
X for (i=0; i<=MAXWLEN; i++) {
X SpL = space[i];
X space[i] = NULL;
X while (SpL != NULL) {
X tmp = SpL;
X SpL = SpL->next;
X free(tmp);
X }
X }
X
X return;
X}
X
Xint
XCheckBoard()
X{
X int i;
X int j;
X int beg;
X int error=0;
X int nw[MAXWLEN+1];
X PtrSpList SpL;
X
X for (i=0; i<=MAXWLEN; i++)
X nw[i] = 0;
X
X for (i=0; i<rows; i++)
X for (j=0; j<cols; j++)
X if (board[i][j] == (char) 0) {
X beg = j;
X while ((board[i][j] == (char) 0) && (j < cols))
X j++;
X if ((j-beg) > MAXWLEN) {
X fprintf(stderr,"Error: Word on board too long. (%d,%d)H\n",
X i,beg);
X error++;
X }
X else if ((j-beg) > 1) {
X SpL = (PtrSpList) malloc(sizeof(SpList));
X SpL->verhor = HORZ;
X SpL->r = i;
X SpL->c = beg;
X SpL->used = 0;
X SpL->next = space[j-beg];
X space[j-beg] = SpL;
X nw[j-beg]++;
X }
X }
X
X for (j=0; j<cols; j++)
X for (i=0; i<rows; i++)
X if (board[i][j] == (char) 0) {
X beg = i;
X while ((board[i][j] == (char) 0) && (i < rows))
X i++;
X if ((i-beg) > MAXWLEN) {
X fprintf(stderr,"Error: Word on board too long. (%d,%d)V\n",
X beg,j);
X error++;
X }
X else if ((i-beg) > 1) {
X SpL = (PtrSpList) malloc(sizeof(SpList));
X SpL->verhor = VERT;
X SpL->r = beg;
X SpL->c = j;
X SpL->used = 0;
X SpL->next = space[i-beg];
X space[i-beg] = SpL;
X nw[i-beg]++;
X }
X }
X
X if (error) {
X FreeSpLists();
X return(1);
X }
X
X for (i=0; i<=MAXWLEN; i++)
X if (nwlen[i] != nw[i]) {
X fprintf(stderr,"Error on board: Len: %2d List: %2d Board %2d\n",
X i,nwlen[i],nw[i]);
X error++;
X }
X
X if (error) {
X FreeSpLists();
X return(1);
X }
X
X return(0);
X}
X
Xint
XMatch(w,sp)
XPtrWList w;
XPtrSpList sp;
X{
X int i;
X int row=0;
X int col=0;
X
X if (sp->verhor == HORZ)
X col++;
X else
X row++;
X
X for (i=0; i<strlen(w->word); i++)
X if ((board[sp->r+i*row][sp->c+i*col] != (char) 0) &&
X (board[sp->r+i*row][sp->c+i*col] != w->word[i]))
X return(0);
X
X return(1);
X}
X
XPtrWLList
XCreateMatchList(sp,i)
XPtrSpList sp;
Xint i;
X{
X PtrWList w;
X PtrWLList ret=NULL;
X PtrWLList tmp2;
X
X for (w=words[i]; w!=NULL; w=w->next)
X if (!(w->used) && Match(w,sp)) {
X tmp2 = (PtrWLList) malloc(sizeof(WLList));
X tmp2->wlist = w;
X tmp2->next = ret;
X ret = tmp2;
X }
X
X return(ret);
X}
X
Xint
XFindLowestMatch(posl,sp)
XPtrWLList *posl;
XPtrSpList *sp;
X{
X int minn=LARGE;
X int mini;
X int i;
X int n;
X PtrWList w;
X PtrSpList SpL;
X PtrSpList minsp;
X
X for (i=0; i<=MAXWLEN; i++) {
X for (SpL=space[i]; SpL!=NULL; SpL=SpL->next)
X if (!(SpL->used)) {
X n = 0;
X for (w=words[i]; w!=NULL; w=w->next)
X if ((!w->used) && Match(w,SpL))
X n++;
X if (n == 0)
X return(0);
X if (n < minn) {
X minn = n;
X minsp = SpL;
X mini = i;
X }
X }
X }
X
X if (minn == LARGE)
X return(-1);
X
X *sp = minsp;
X *posl = CreateMatchList(minsp,mini);
X
X return(minn);
X}
X
Xvoid
XFreeWLList(WLL)
XPtrWLList WLL;
X{
X PtrWLList tmp;
X
X while (WLL != NULL) {
X tmp = WLL;
X WLL = WLL->next;
X free(tmp);
X }
X
X return;
X}
X
Xvoid
XClickToEnd()
X{
X
X int done=0;
X XEvent xev;
X
X while (!done) {
X XNextEvent(dpy,&xev);
X
X if (xev.type == Expose)
X RedrawBoard(False);
X
X if (xev.type == ButtonPress)
X done++;
X }
X}
X
Xint
XSolvePuzzle()
X{
X int place=0;
X int i;
X int row=0;
X int col=0;
X int n;
X int done=0;
X PtrWLList pos;
X PtrWLList WL;
X PtrSpList sp;
X XEvent xev;
X
X while (XPending(dpy)) {
X XNextEvent(dpy,&xev);
X switch(xev.type) {
X case Expose :
X RedrawBoard(False);
X break;
X case ButtonPress :
X if (display)
X while (!done) {
X while (!XPending(dpy));
X XNextEvent(dpy,&xev);
X if (xev.type == ButtonRelease)
X done++;
X }
X }
X }
X
X if ((n = FindLowestMatch(&pos,&sp)) == 0)
X return(0);
X
X if (n == -1)
X return(1);
X
X sp->used = 1;
X if (sp->verhor == HORZ)
X col++;
X else
X row++;
X for (WL=pos; WL!=NULL; WL=WL->next) {
X WL->wlist->used = 1;
X for (i=0; i<strlen(WL->wlist->word); i++)
X if (board[sp->r+i*row][sp->c+i*col] == (char) 0) {
X if (display) {
X LetterSpace(sp->r+i*row,sp->c+i*col,WL->wlist->word[i]);
X if (fast)
X XSync(dpy,0);
X }
X board[sp->r+i*row][sp->c+i*col] = WL->wlist->word[i];
X place |= 0x1 << i;
X }
X if (display && !fast)
X XSync(dpy,0);
X if (pause)
X ClickToEnd();
X if (SolvePuzzle()) {
X if (n > 1)
X FreeWLList(pos);
X return(1);
X }
X WL->wlist->used = 0;
X for (i=0; i<strlen(WL->wlist->word); i++)
X if (place & (0x1 << i)) {
X if (display) {
X ClearSpace(sp->r+i*row,sp->c+i*col);
X if (fast)
X XSync(dpy,0);
X }
X board[sp->r+i*row][sp->c+i*col] = (char) 0;
X }
X if (display && !fast)
X XSync(dpy,0);
X if (pause)
X ClickToEnd();
X }
X sp->used = 0;
X if (n > 1)
X FreeWLList(pos);
X
X return(0);
X}
X
Xvoid
XWriteBoardToFile()
X{
X FILE *outfil;
X int i;
X int j;
X
X outfil = fopen("board","w");
X if (outfil == NULL) {
X fprintf(stderr,"Can't open 'board' file.\n\n");
X exit(-1);
X }
X
X fprintf(outfil,"%d\n%d\n",rows,cols);
X
X for (i=0; i<rows; i++) {
X for(j=0; j<cols; j++)
X if (board[i][j] == (char) -1)
X fputc('0',outfil);
X else
X fputc('1',outfil);
X fputc('\n',outfil);
X }
X
X fclose(outfil);
X fprintf(stderr,"'board' file written.\n");
X
X return;
X}
X
Xvoid
XReadBoardFromFile()
X{
X FILE *infil;
X int i;
X int j;
X char c;
X
X infil = fopen("board","r");
X if (infil == NULL) {
X fprintf(stderr,"Can't open 'board' file.\n\n");
X exit(-1);
X }
X
X fscanf(infil,"%d\n",&rows);
X fscanf(infil,"%d\n",&cols);
X
X if ((rows < MINROWS) || (rows > MAXROWS) || (cols < MINCOLS) ||
X (cols > MAXCOLS)) {
X fprintf(stderr,"Error in range: Rows: %d Cols: %d\n",rows,cols);
X fprintf(stderr,"Rows must be between %d and %d.\n",MINROWS,MAXROWS);
X fprintf(stderr,"Cols must be between %d and %d.\n",MINCOLS,MAXCOLS);
X exit(-1);
X }
X
X for (i=0; i<rows; i++) {
X for (j=0; j<cols; j++) {
X c = fgetc(infil);
X if (c == '1')
X board[i][j] = (char) 0;
X else
X board[i][j] = (char) -1;
X }
X fscanf(infil,"\n");
X }
X
X fclose(infil);
X
X return;
X}
X
Xvoid
XGetSizeOfBoard(arg)
Xchar *arg;
X{
X sscanf(arg,"%d",&rows);
X sscanf(index(arg,'x')+1,"%d",&cols);
X
X if ((rows < MINROWS) || (rows > MAXROWS) || (cols < MINCOLS) ||
X (cols > MAXCOLS)) {
X fprintf(stderr,"Error in range: Rows: %d Cols: %d\n",rows,cols);
X fprintf(stderr,"Rows must be between %d and %d.\n",MINROWS,MAXROWS);
X fprintf(stderr,"Cols must be between %d and %d.\n",MINCOLS,MAXCOLS);
X exit(-1);
X }
X
X return;
X}
X
Xvoid
XWriteSolutionToFile()
X{
X FILE *outfil;
X int i;
X int j;
X
X outfil = fopen("solution","w");
X if (outfil == NULL) {
X fprintf(stderr,"Error in opening 'solution' file.\n");
X return;
X }
X
X for (i=0; i<rows; i++) {
X for (j=0; j<cols; j++)
X if (board[i][j] == (char) -1)
X fputc(' ',outfil);
X else
X fputc(toupper(board[i][j]),outfil);
X fputc('\n',outfil);
X }
X
X fclose(outfil);
X
X return;
X}
X
Xvoid
XDisplaySolution()
X{
X int i;
X int j;
X
X for (i=0; i<rows; i++)
X for (j=0; j<cols; j++)
X if (board[i][j] != (char) -1)
X LetterSpace(i,j,board[i][j]);
X
X XSync(dpy,0);
X
X return;
X}
X
XPtrSpList
XFindSpace(r1,c1,r2,c2,len)
Xint r1;
Xint c1;
Xint r2;
Xint c2;
Xint *len;
X{
X PtrSpList sp;
X
X if (r1 == r2) {
X *len = c2 - c1 + 1;
X if (*len > MAXWLEN)
X return(NULL);
X for (sp=space[*len]; sp!=NULL; sp=sp->next)
X if ((sp->verhor == HORZ) && (sp->r == r1) && (sp->c == c1))
X return(sp);
X return(NULL);
X }
X else if (c1 == c2) {
X *len = r2 - r1 + 1;
X if (*len > MAXWLEN)
X return(NULL);
X for (sp=space[*len]; sp!=NULL; sp=sp->next)
X if ((sp->verhor == VERT) && (sp->r == r1) && (sp->c == c1))
X return(sp);
X return(NULL);
X }
X
X return(NULL);
X}
X
Xint
XGetButton()
X{
X XEvent xev;
X XButtonEvent *xbev;
X
X while (1) {
X XNextEvent(dpy,&xev);
X if (xev.type == Expose)
X RedrawBoard(False);
X if (xev.type == ButtonPress) {
X XNextEvent(dpy,&xev);
X xbev = (XButtonEvent *) &xev;
X return(xbev->button);
X }
X }
X}
X
Xvoid
XFillInWord(sp,len)
XPtrSpList sp;
Xint len;
X{
X PtrWList w;
X PtrWList tmpw;
X int r;
X int c;
X int but;
X int dr;
X int dc;
X int i;
X
X stage = 3;
X Instructions();
X
X for (w=words[len]; w->next!=NULL; w=w->next);
X
X dr = dc = 0;
X if (sp->verhor == VERT)
X dr = 1;
X else
X dc = 1;
X
X while (1) {
X r = sp->r;
X c = sp->c;
X for (i=0; i<len; i++) {
X LetterSpace(r,c,w->word[i]);
X r += dr;
X c += dc;
X }
X XSync(dpy,0);
X
X but = GetButton();
X switch (but) {
X case 1:
X if (w->next != NULL) {
X tmpw = w->next;
X r = sp->r;
X c = sp->c;
X for (i=0; i<len; i++) {
X ClearSpace(r,c);
X LetterSpace(r,c,tmpw->word[i]);
X r += dr;
X c += dc;
X }
X XSync(dpy,0);
X w = tmpw;
X }
X break;
X case 2:
X if (w != words[len]) {
X for (tmpw=words[len]; tmpw!=NULL; tmpw=tmpw->next)
X if (tmpw->next == w)
X break;
X r = sp->r;
X c = sp->c;
X for (i=0; i<len; i++) {
X ClearSpace(r,c);
X LetterSpace(r,c,tmpw->word[i]);
X r += dr;
X c += dc;
X }
X XSync(dpy,0);
X w = tmpw;
X }
X break;
X case 3:
X w->used = 1;
X sp->used = 1;
X r = sp->r;
X c = sp->c;
X for (i=0; i<len; i++) {
X board[r][c] = w->word[i];
X r += dr;
X c += dc;
X }
X return;
X }
X }
X}
X
Xvoid
XGetStartingWord()
X{
X XEvent xev;
X XButtonEvent *xbev;
X PtrSpList sp;
X int len;
X int done=0;
X int done2=0;
X int r1;
X int r2;
X int c1;
X int c2;
X
X stage = 2;
X Instructions();
X
X while (!done) {
X XNextEvent(dpy,&xev);
X
X if (xev.type == Expose)
X RedrawBoard(False);
X
X if (xev.type == ButtonPress) {
X done = 1;
X xbev = (XButtonEvent *) &xev;
X switch (xbev->button) {
X case Button1:
X case Button2:
X GetXY(xbev,&r1,&c1);
X while (!done2) {
X XNextEvent(dpy,&xev);
X if (xev.type == Expose)
X RedrawBoard(False);
X if (xev.type == ButtonRelease) {
X done2 = 1;
X xbev = (XButtonEvent *) &xev;
X GetXY(xbev,&r2,&c2);
X }
X }
X sp = FindSpace(r1,c1,r2,c2,&len);
X if (sp == NULL)
X done = 0;
X else
X FillInWord(sp,len);
X break;
X case Button3:
X XNextEvent(dpy,&xev);
X return;
X }
X }
X }
X return;
X}
X
Xint
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X int error;
X int flag=0;
X int i;
X int ok;
X
X Initialize();
X
X for (i=1; i<argc; i++) {
X ok = 0;
X if ((!strcmp(argv[i],"-b") || index(argv[i],'x')) && flag) {
X fprintf(stderr,"Only one of -b or ROWSxCOLS can be used.\n\n");
X exit(-1);
X }
X if (!strcmp(argv[i],"-b") && !flag) {
X ReadBoardFromFile();
X flag = 1;
X ok++;
X }
X if (index(argv[i],'x') && !flag) {
X GetSizeOfBoard(argv[i]);
X flag = 2;
X ok++;
X }
X if (!strcmp(argv[i],"-d")) {
X display = 0;
X ok++;
X }
X if (!strcmp(argv[i],"-p")) {
X pause = 1;
X ok++;
X }
X if (!strcmp(argv[i],"-f")) {
X fast = 1;
X ok++;
X }
X if (!ok)
X fprintf(stderr,"Unknown option: '%s' -- Ignored.\n",argv[i]);
X }
X
X if (flag == 0) {
X printf("Rows? ");
X scanf("%d",&rows);
X printf("Cols? ");
X scanf("%d",&cols);
X if ((rows < MINROWS) || (rows > MAXROWS) || (cols < MINCOLS) ||
X (cols > MAXCOLS)) {
X fprintf(stderr,"Error in range: Rows: %d Cols: %d\n",rows,cols);
X fprintf(stderr,"Rows must be between %d and %d.\n",MINROWS,MAXROWS);
X fprintf(stderr,"Cols must be between %d and %d.\n",MINCOLS,MAXCOLS);
X exit(-1);
X }
X }
X
X InputWords();
X
X InitWindow();
X
X do {
X InputBoard();
X error = CheckBoard();
X if (error)
X printf("-------------------------------------------------\n");
X } while (error);
X
X RedrawBoard(False);
X
X GetStartingWord();
X
X stage = 4;
X Instructions();
X
X if (SolvePuzzle()) {
X stage = 5;
X Instructions();
X WriteBoardToFile();
X if (!display)
X DisplaySolution();
X WriteSolutionToFile();
X ClickToEnd();
X }
X else {
X fprintf(stderr,"\n\nCould not solve puzzle.\n\n");
X if (flag != 1)
X WriteBoardToFile();
X exit(-1);
X }
X
X exit(0);
X}
X
END_OF_FILE
if test 28120 -ne `wc -c <'kriss.c'`; then
echo shar: \"'kriss.c'\" unpacked with wrong size!
fi
# end of 'kriss.c'
fi
if test -f 'kriss.man' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kriss.man'\"
else
echo shar: Extracting \"'kriss.man'\" \(3015 characters\)
sed "s/^X//" >'kriss.man' <<'END_OF_FILE'
X.TH kriss 6X11
X.SH NAME
Xkriss \- kriss-kross puzzle solver
X.SH SYNTAX
X.B kriss
X[ { \-b | ROWSxCOLS } -d -f -p ]
X.SH DESCRIPTION
X.PP
X\fIkriss\fP
Xsolves puzzles that are generically known as kriss-kross puzzles. Given
Xa board layout and a list of words, \fIkriss\fP will fit all the words into
Xthe puzzle board. \fIkriss\fP uses the X Windowing System to display the
Xboard. The list of words should be in the 'words' file upon startup.
X.PP
XAfter starting up, \fIkriss\fP will display either the board read from the
X\'board\' file, or a blank board. At this time the board can be modified.
XTo create spaces, click and hold the first button on the starting space,
Xthen move the pointer to the ending space and release the button.
X\fIkriss\fP will ignore any spaces not drawn on a vertical or horizontal line.
XSpaces can be removed the same way by using the second button of the
Xmouse. When you are done with the board, click the third button on the
Xmouse.
X.PP
XYou can now enter an optional starting word, if the puzzle contains one.
XUsing Button1 or Button2, you may specify the space in which to place the
Xstarting word. If no starting word is given, click Button3 at this time.
XAfter identifying the space in which to start, you must select the word
Xto place in that space. \fIkriss\fP will place the first n-letter word
Xin the designated space. You may use Button1 and Button2 to move backward
Xand forward through the list of n-letter words, and Button3 to select the
Xcurrent word.
X.PP
XWhen \fIkriss\fP is done solving the puzzle, click any button on the
Xmouse to quit. \fIkriss\fP will save both the board layout and solution
Xto files.
X.SH OPTIONS
X.PP
X -b Read the board layout from a 'board' file.
X
X.PP
X ROWSxCOLS Use ROWS and COLS as the size of the board.
X
X.PP
X -d Display only the final solution.
X
X.PP
X -f Use with fast X Servers.
X
X.PP
X -p Pause every time a word is placed or erased.
X Continue by clicking any button on the
X mouse.
X.PP
XGiven neither the -b nor the ROWSxCOLS option, \fIkriss\fP will prompt for
Xthe size of the board, and then start with a blank board of that size.
XWith pause mode off, pressing a button on the mouse will pause the program
Xuntil the button is released.
X
X
X.SH 'board' FILE
X.PP
XThe format of the board file is:
X
X ROWS
X COLS
X row 1 (is COLS 0 and 1's, 1 denoting a space,
X row 2 0 denoting a blank square)
X .
X .
X row ROWS
X
Xlike this:
X
X 5
X 5
X 10000
X 10000
X 11111
X 10000
X 10000
X
XThe above 'board' file will give a 5x5 board with one each vertical
Xand horizontal 5-letter word.
X.SH FILES
X board The physical layout of the board.
X words The list of words.
X solution The puzzle solution(written by \fIkriss\fP).
X
X.SH AUTHOR
X Brien L. Wheeler
X Department of Computer Engineering and Science
X Case Western Reserve University
X
X
END_OF_FILE
if test 3015 -ne `wc -c <'kriss.man'`; then
echo shar: \"'kriss.man'\" unpacked with wrong size!
fi
# end of 'kriss.man'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have the archive.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0