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