[comp.sources.games] v11i001: kriss - kriss-kross puzzle solver for X-Windows, Part01/01

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