home *** CD-ROM | disk | FTP | other *** search
/ Boldly Go Collection / version40.iso / TS / 17A / ANGRY.ZIP / ANGRY.C next >
C/C++ Source or Header  |  1992-07-30  |  19KB  |  788 lines

  1. /* Angry! The cross word builder */
  2. /* written by Andrew Tridgell (23rd July 1992) */  
  3. /* Copyright (C) Andrew Tridgell 1992 */
  4.  
  5. /* 
  6. Permission is given for the use or copying of this program for
  7. non-commercial purposes. If you wish to use it for commercial purposes
  8. then please contact the author:
  9.  
  10. Andrew Tridgell
  11. Computer Sciences Laboratory
  12. Australian National University
  13. GPO BOX 4
  14. Canberra, 2601, Australia
  15.  
  16. E-Mail: Andrew.Tridgell@anu.edu.au
  17. */
  18.  
  19.  
  20. #define VERSION "1.0"
  21.   
  22. #include <stdio.h>  
  23. #include <alloc.h>
  24. #include <stdlib.h>  
  25. #include <time.h>  
  26.  
  27. enum _Direction{ACROSS,DOWN}; 
  28. typedef enum _Direction Direction; 
  29. typedef int BOOL; 
  30.  
  31.  
  32. /* this structure holds the word list */
  33. typedef struct
  34. {
  35.   char *word;
  36.   int i,j;
  37.   Direction d;
  38.   BOOL used;
  39. } list_struct;
  40.  
  41.  
  42.  
  43. #define True 1 
  44. #define False 0 
  45. #define CONST const 
  46. #define LONG_STRING_LENGTH 1000
  47. #define MAX_TRY depth 
  48. #define MAX_FAILURES 20 
  49.  
  50. /* define how words will be scored */
  51. #define SC_END 30 
  52. #define SC_MID 35 
  53. #define SC_NOEDGE 9 
  54. #define SC_DIR 1 
  55.  
  56. /* min score for a word with some crossings */
  57. #define SC_MIN_CROSSING (SC_NOEDGE + SC_DIR + 1)
  58.  
  59. /* these bits implement the "rotating line" */
  60. char circle[4] = "\\|/-"; 
  61. char lastc = 0; 
  62. #define CIRCLE {printf("%c\r",circle[(lastc=((lastc+1)%4))]);fflush(stdout);}
  63.  
  64.  
  65. char *strtidy(); 
  66. void read_a_line(); 
  67. char *my_fgets(); 
  68.  
  69.  
  70. #ifndef __MSDOS__ 
  71. #define randomize() srand(time(NULL)) 
  72. #define BLACKSQUARE 32 
  73. #define kbhit() False 
  74. #else 
  75. #define BLACKSQUARE 219 
  76. #endif 
  77.  
  78.  
  79.  
  80. /* GLOBAL VARIABLES */
  81. int xsize=0;  
  82. int ysize=0;  
  83. int depth=1; 
  84. BOOL final_try=False; 
  85. char **grid; 
  86.  
  87.  
  88.  
  89. /******************************************************************* 
  90. create a 2D matrix of any type. The return must be cast correctly. 
  91. ********************************************************************/ 
  92. void **any_matrix2D(int el_size,int dim1,int dim2) 
  93. int dimension=2; 
  94. int *dims=NULL; 
  95. void **mat; 
  96. int i,j,size,ptr_size,ppos,prod; 
  97. int padding; 
  98. void *next_ptr; 
  99.   
  100. /* first gather the arguments */  
  101.   
  102. if (dimension <= 0) return(NULL);  
  103. if (el_size <= 0) return(NULL);  
  104.   
  105. dims = (int *)malloc(dimension * sizeof(int));  
  106. if (dims == NULL) return(NULL);  
  107. dims[0] = dim1;
  108. dims[1] = dim2;
  109.   
  110. /* now we've disected the arguments we can go about the real business of  
  111. creating the matrix */  
  112.   
  113. /* calculate how much space all the pointers will take up */  
  114. ptr_size = 0;  
  115. for (i=0;i<(dimension-1);i++)  
  116.     {  
  117.     prod=sizeof(void *);  
  118.     for (j=0;j<=i;j++) prod *= dims[j];  
  119.     ptr_size += prod;  
  120.     }  
  121.   
  122. /* padding overcomes potential alignment errors */  
  123. padding = (el_size - (ptr_size % el_size)) % el_size;  
  124.   
  125. /* now calculate the total memory taken by the array */  
  126. {  
  127. prod=el_size;  
  128. for (i=0;i<dimension;i++) prod *= dims[i];  
  129. size = prod + ptr_size + padding;  
  130. }  
  131.   
  132. /* allocate the matrix memory */  
  133. mat = (void **)malloc(size);  
  134.   
  135. if (mat == NULL)  
  136.     {  
  137.     fprintf(stdout,"Error allocating %d dim matrix of size %d\n",dimension,size);  
  138.     free(dims);  
  139.     return(NULL);  
  140.     }  
  141.   
  142. /* now fill in the pointer values */  
  143. next_ptr = (void *)&mat[dims[0]];  
  144. ppos = 0;  
  145. prod = 1;  
  146. for (i=0;i<(dimension-1);i++)  
  147. {  
  148. int skip;  
  149. if (i == dimension-2)   
  150.   {  
  151.     skip = el_size*dims[i+1];  
  152.     next_ptr = (void *)(((char *)next_ptr) + padding); /* add in the padding */  
  153.   }  
  154. else  
  155.   skip = sizeof(void *)*dims[i+1];  
  156.   
  157. for (j=0;j<(dims[i]*prod);j++)  
  158.   {  
  159.     mat[ppos++] = next_ptr;  
  160.     next_ptr = (void *)(((char *)next_ptr) + skip);  
  161.   }  
  162. prod *= dims[i];  
  163. }  
  164.   
  165. free(dims);  
  166. return((void *)mat);  
  167. }  
  168.   
  169.   
  170. /*******************************************************************  
  171. return a random number  
  172. ********************************************************************/  
  173. int random_num(void)  
  174. {  
  175. return(rand());  
  176. }  
  177.   
  178.   
  179. /*******************************************************************  
  180. this returns the number of lines in a text file  
  181. ********************************************************************/  
  182. int num_text_lines(CONST char *fname)  
  183. {  
  184. FILE *file;  
  185. int count = 0;  
  186. char buf[2000];  
  187.   
  188. file = fopen(fname,"r");  
  189. if (!file)  
  190.   return(0);  
  191.   
  192. while (!feof(file))  
  193.   {  
  194.     read_a_line(buf,2000,file);  
  195.     if (*buf) count++;  
  196.   }  
  197.   
  198. fclose(file);  
  199. return(count);  
  200. }  
  201.   
  202. /*******************************************************************  
  203. read a line from a file. If the line is of 0 length then read another  
  204. ********************************************************************/  
  205. void read_a_line(char *buf,int maxlen,FILE *file)  
  206. {  
  207. my_fgets(buf,maxlen,file);  
  208. if (strlen(buf) == 0)  
  209.     my_fgets(buf,maxlen,file);  
  210. }  
  211.   
  212. /*******************************************************************  
  213. like fgets but remove trailing CR or LF  
  214. ********************************************************************/  
  215. char *my_fgets(char *s,int n,FILE *stream)  
  216. {  
  217. char *ret;  
  218.   
  219. ret = fgets(s,n,stream);  
  220. if (ret == NULL)   
  221.   {  
  222.     *s = 0;  
  223.     return(NULL);  
  224.   }  
  225.   
  226. return(strtidy(s,"\n\r "));  
  227. }  
  228.   
  229. /*******************************************************************  
  230. remove specified chars from front and back of a string   
  231. ********************************************************************/  
  232. char *strtidy(char *str,CONST char *chars)  
  233. {  
  234. int len=strlen(str);  
  235. while ((len > 0) && (strchr(chars,*str) != NULL))  
  236.     {  
  237.     memcpy(str,&str[1],len);  
  238.     len--;  
  239.     }  
  240. while ((len > 0) && (strchr(chars,str[len-1]) != NULL))  
  241.     {  
  242.     str[len-1]=0;  
  243.     len--;  
  244.     }  
  245. return(str);  
  246. }  
  247.   
  248.   
  249.   
  250.   
  251. /*******************************************************************  
  252. load a list of words  
  253. ********************************************************************/  
  254. list_struct *LoadWordList(char *fname,int *num)  
  255. {  
  256. FILE *file;  
  257. int i;  
  258. char line[LONG_STRING_LENGTH];  
  259. list_struct *list;  
  260. *num = num_text_lines(fname);  
  261. if (*num < 1)  
  262.   return(NULL);  
  263.   
  264. list = (list_struct *)malloc(sizeof(list_struct)*(*num));  
  265. if (!list) return(NULL);
  266.  
  267. file = fopen(fname,"r");  
  268. for (i=0;i<(*num);i++)  
  269.   {  
  270.     read_a_line(line,LONG_STRING_LENGTH,file);  
  271.     list[i].word = (char *)malloc(sizeof(char)*(strlen(line)+1));
  272.     if (!list[i].word) return(NULL);
  273.     strcpy(list[i].word,line);  
  274.     list[i].used = False;
  275.   }  
  276. fclose(file);  
  277.   
  278. return(list);  
  279. }  
  280.   
  281. /*******************************************************************  
  282. place a word on the grid
  283. ********************************************************************/  
  284. void PlaceWord(char *word,int i,int j,Direction dir)  
  285. {  
  286. int k;  
  287. int len=strlen(word);  
  288. CIRCLE
  289. if (dir == ACROSS)  
  290.   {  
  291.     for (k=0;k<len;k++)  
  292.       grid[i+k][j] = word[k];  
  293.   }  
  294. else  
  295.   {  
  296.     for (k=0;k<len;k++)  
  297.       grid[i][j+k] = word[k];  
  298.   }  
  299. }  
  300.  
  301.  
  302. /*******************************************************************  
  303. un_place a word  
  304. ********************************************************************/  
  305. void UnPlaceWord(char *word,int i,int j,Direction dir)  
  306. {  
  307. int k;  
  308. int len=strlen(word);
  309. BOOL minus,plus;  
  310. if (dir == ACROSS)  
  311.   {  
  312.     minus = (j!=0);
  313.     plus = (j!=(ysize-1));
  314.     for (k=0;k<len;k++)  
  315.       if (!(minus && grid[i+k][j-1]) && !(plus && grid[i+k][j+1]))
  316.     grid[i+k][j] = 0;  
  317.   }  
  318. else  
  319.   {  
  320.     minus = (i!=0);
  321.     plus = (i!=(xsize-1));
  322.     for (k=0;k<len;k++)  
  323.       if (!(minus && grid[i-1][j+k]) && !(plus && grid[i+1][j+k]))
  324.     grid[i][j+k] = 0;  
  325.   }  
  326. }  
  327.  
  328.  
  329. /*******************************************************************  
  330. work out how many cross overs there are for a word
  331. ********************************************************************/  
  332. int Crossings(char *word,int i,int j,Direction dir)  
  333. {  
  334. int k;  
  335. int len=strlen(word);
  336. int res=0;
  337. BOOL minus,plus;  
  338. if (dir == ACROSS)  
  339.   {  
  340.     minus = (j!=0);
  341.     plus = (j!=(ysize-1));
  342.     for (k=0;k<len;k++)  
  343.       if ((minus && grid[i+k][j-1]) || (plus && grid[i+k][j+1]))
  344.     res++;
  345.   }  
  346. else  
  347.   {  
  348.     minus = (i!=0);
  349.     plus = (i!=(xsize-1));
  350.     for (k=0;k<len;k++)  
  351.       if ((minus && grid[i-1][j+k]) || (plus && grid[i+1][j+k]))
  352.     res++;
  353.   }  
  354. return(res);
  355. }  
  356.  
  357.  
  358. /*******************************************************************  
  359. determine if a position is taken - just checks for overlaps
  360. ********************************************************************/  
  361. BOOL Taken(list_struct *list,int num,char *word,int i,int j,Direction dir)  
  362. {
  363.   int len=strlen(word);
  364.   int n;
  365.   if (dir == ACROSS)
  366.     for (n=0;n<num;n++)
  367.       if (list[n].used && (list[n].d == dir) && (list[n].j == j))
  368.     {
  369.       int l2=strlen(list[n].word);
  370.       int e1 = i+len-1;
  371.       int e2 = list[n].i+l2-1;
  372.       if (!((i>e2) || (list[n].i>e1))) return(True);
  373.     }
  374.  
  375.   if (dir == DOWN)
  376.     for (n=0;n<num;n++)
  377.       if (list[n].used && (list[n].d == dir) && (list[n].i == i))
  378.     {
  379.       int l2=strlen(list[n].word);
  380.       int e1 = j+len-1;
  381.       int e2 = list[n].j+l2-1;
  382.       if (!((j>e2) || (list[n].j>e1))) return(True);
  383.     }
  384.  
  385. return(False);
  386. }
  387.  
  388.   
  389. /*******************************************************************  
  390. determine if a word is legal in a position  
  391. ********************************************************************/  
  392. BOOL Legal(char *word,int i,int j,Direction dir)  
  393. {  
  394. int len=strlen(word);  
  395. BOOL plus,minus;
  396. if (dir == ACROSS)  
  397.   {  
  398.     int k;  
  399.     if (i+len > xsize) return(False);  
  400.     if ((i != 0) && grid[i-1][j]) return(False);  
  401.     if (((i+len) != xsize) && grid[i+len][j]) return(False);  
  402.     minus = (j!=0);
  403.     plus = (j!=(ysize-1));
  404.     for (k=0;k<len;k++)  
  405.       {  
  406.     if (grid[i+k][j] && (grid[i+k][j] != word[k])) return(False);  
  407.     if ((j != 0) && grid[i+k][j-1] && !grid[i+k][j]) return(False);  
  408.     if ((j != (ysize-1)) && grid[i+k][j+1] && !grid[i+k][j]) return(False);  
  409.     if (grid[i+k][j] && !((plus && grid[i+k][j+1]) || (minus && grid[i+k][j-1])))
  410.       return(False);
  411.       }  
  412.   }  
  413. else  
  414.   {  
  415.     int k;  
  416.     if (j+len > ysize) return(False);  
  417.     if ((j != 0) && grid[i][j-1]) return(False);  
  418.     if (((j+len) != ysize) && grid[i][j+len]) return(False);  
  419.     minus = (i!=0);
  420.     plus = (i!=(xsize-1));
  421.     for (k=0;k<len;k++)  
  422.       {  
  423.     if (grid[i][j+k] && (grid[i][j+k] != word[k])) return(False);  
  424.     if ((i != 0) && grid[i-1][j+k] && !grid[i][j+k]) return(False);  
  425.     if ((i != (xsize-1)) && grid[i+1][j+k] && !grid[i][j+k]) return(False);  
  426.     if (grid[i][j+k] && !((plus && grid[i][j+k]) || (minus && grid[i-1][j+k])))
  427.       return(False);
  428.       }  
  429.   }  
  430. return(True);  
  431. }  
  432.   
  433. /*******************************************************************  
  434. score a word in a position  
  435. ********************************************************************/  
  436. int Score(char *word,int i,int j,Direction dir)  
  437. {  
  438. int len=strlen(word);  
  439. int score=0;  
  440. if (dir == ACROSS)  
  441.   {  
  442.     int k;  
  443.     for (k=0;k<len;k++)  
  444.       if (grid[i+k][j])
  445.     {  
  446.       if ((k == 0) || (k == (len-1)))   
  447.         score += SC_END;  
  448.       else  
  449.         score += SC_MID;  
  450.     }  
  451.     if ((j != 0) && (j != (ysize-1))) score += SC_NOEDGE;  
  452.   }  
  453. else  
  454.   {  
  455.     int k;  
  456.     for (k=0;k<len;k++)  
  457.       if (grid[i][j+k])
  458.     {  
  459.       if ((k == 0) || (k == (len-1)))   
  460.         score += SC_END;  
  461.       else  
  462.         score += SC_MID;  
  463.     }  
  464.     if ((i != 0) && (i != (xsize-1))) score += SC_NOEDGE;  
  465.   }  
  466. return(score);  
  467. }  
  468.   
  469. Direction last_dir=ACROSS;  
  470.   
  471.   
  472. /*******************************************************************  
  473. find the best position for a word  
  474. ********************************************************************/  
  475. BOOL BestPosition(char *word,int *besti,int *bestj,Direction *dir)  
  476. {  
  477. int best;  
  478. register int i,j;  
  479. Direction d;  
  480. int s;  
  481. int len = strlen(word);  
  482. best = -1;  
  483.  
  484.   
  485. d = ACROSS;  
  486. for (i=0;i<=(xsize-len);i++)  
  487.   for (j=0;j<ysize;j++)  
  488.       if (Legal(word,i,j,d))  
  489.     {  
  490.       s = Score(word,i,j,d);  
  491.       if (last_dir != d) s += SC_DIR;  
  492.       if (s > best || ((s == best) && ((random_num()%(xsize*ysize/4))!=0)))  
  493.         {  
  494.           best = s;  
  495.           *besti = i;  
  496.           *bestj = j;  
  497.           *dir = d;  
  498.         }  
  499.     }  
  500.   
  501. d = DOWN;  
  502. for (i=0;i<xsize;i++)  
  503.   for (j=0;j<=(ysize-len);j++)  
  504.       if (Legal(word,i,j,d))  
  505.     {  
  506.       s = Score(word,i,j,d);  
  507.       if (last_dir != d) s += SC_DIR;  
  508.       if (s > best || ((s == best) && ((random_num()%(xsize*ysize/4))!=0)))  
  509.         {  
  510.           best = s;  
  511.           *besti = i;  
  512.           *bestj = j;  
  513.           *dir = d;  
  514.         }  
  515.     }  
  516.   
  517. return(best >= 0);  
  518. }  
  519.   
  520. /*******************************************************************  
  521. zero a crossword  
  522. ********************************************************************/  
  523. void ZeroCrossword(list_struct *list,int num)  
  524. {  
  525. int i,j;  
  526. for (i=0;i<xsize;i++)  
  527.   for (j=0;j<ysize;j++)  
  528.     grid[i][j] = 0;  
  529. for (i=0;i<num;i++)
  530.   list[i].used = False;
  531. }  
  532.   
  533.   
  534.   
  535. /*******************************************************************  
  536. build a crossword  
  537. ********************************************************************/  
  538. int BuildCrossword(list_struct *list,int num,int min_score)  
  539. {  
  540. int i,j,n;  
  541. Direction d;  
  542. int remaining=0;  
  543. int failures=0; 
  544. int *scores = (int *)malloc(sizeof(int)*num);  
  545.  
  546. for (n=0;n<num;n++)
  547.   if (!list[n].used) remaining++;
  548.   
  549. while (remaining > 0)  
  550.   {  
  551.     int n1,tried;  
  552.     int choose;  
  553.     int numbest=0,bestscore=-1;  
  554.     int k;  
  555.  
  556.  
  557.     for (i=0;i<num;i++)  
  558.       scores[i] = -1;  
  559.  
  560.     tried=0;  
  561.  
  562.     n1 = random_num() % num;  
  563.  
  564.     for (n=n1;(n<num) && (tried++ < MAX_TRY) && !kbhit();n++)  
  565.       if (!list[n].used && BestPosition(list[n].word,&i,&j,&d))  
  566.     {
  567.       scores[n] = Score(list[n].word,i,j,d);  
  568.       if (scores[n] == bestscore) numbest++;  
  569.       if (scores[n] > bestscore)  
  570.         {  
  571.           bestscore = scores[n];  
  572.           numbest = 1;  
  573.         } 
  574.     } 
  575.  
  576.     for (n=0;(n<n1) && (tried++ < MAX_TRY) && !kbhit();n++)  
  577.       if (!list[n].used && BestPosition(list[n].word,&i,&j,&d))  
  578.     {
  579.       scores[n] = Score(list[n].word,i,j,d);  
  580.       if (scores[n] == bestscore) numbest++;  
  581.       if (scores[n] > bestscore)  
  582.         {  
  583.           bestscore = scores[n];  
  584.           numbest = 1;  
  585.         } 
  586.     } 
  587.  
  588.     if (kbhit()) return(0);  
  589.  
  590.     if (bestscore < min_score) 
  591.       { 
  592.     failures++; 
  593.     if (failures > MAX_FAILURES) 
  594.       {  
  595.         free(scores);  
  596.         return(num-remaining);  
  597.       }  
  598.     continue; 
  599.       } 
  600.     else 
  601.       failures=0; 
  602.     k = random_num() % numbest;  
  603.     numbest=0;  
  604.     for (n=0;n<num;n++)  
  605.       if (scores[n] == bestscore)  
  606.     {  
  607.       if (numbest == k) choose=n;  
  608.       numbest++;  
  609.     }  
  610.     BestPosition(list[choose].word,&i,&j,&d);  
  611.     PlaceWord(list[choose].word,i,j,d);
  612.     
  613.     list[choose].used = True;  
  614.     list[choose].i = i;
  615.     list[choose].j = j;
  616.     list[choose].d = d;
  617.  
  618.     remaining--;  
  619.   }  
  620. free(scores);  
  621. return(num-remaining);  
  622. }
  623.  
  624.  
  625. /*******************************************************************  
  626. try every word - place any with score greater than min_score
  627. ********************************************************************/  
  628. int TryAllWords(list_struct *list,int num,int min_score)  
  629. {  
  630.   int i,j,n;  
  631.   Direction d;  
  632.   int res=0;
  633.  
  634.   for (n=0;n<num && !kbhit();n++)  
  635.     if (!list[n].used && BestPosition(list[n].word,&i,&j,&d) &&
  636.     (Score(list[n].word,i,j,d) >= min_score))
  637.       {
  638.     PlaceWord(list[n].word,i,j,d);
  639.     
  640.     list[n].used = True;  
  641.     list[n].i = i;
  642.     list[n].j = j;
  643.     list[n].d = d;
  644.     res++;
  645.       }
  646.  
  647. return(res);  
  648. }
  649.  
  650.  
  651. /*******************************************************************  
  652. remove all words below a specified score
  653. ********************************************************************/  
  654. int RemoveLowCrossings(list_struct *list,int num,int min_cross)  
  655. {  
  656. int n;  
  657. int removed=0;
  658.  
  659. for (n=0;(n<num);n++)  
  660.   if (list[n].used && (Crossings(list[n].word,list[n].i,list[n].j,list[n].d) < min_cross))
  661.     {
  662.       UnPlaceWord(list[n].word,list[n].i,list[n].j,list[n].d);
  663.       list[n].used = False;
  664.       removed++;
  665.     }
  666. return(removed);
  667. }  
  668.  
  669.   
  670. /*******************************************************************  
  671. display the crossword  
  672. ********************************************************************/  
  673. void DisplayCrossword(FILE *f)  
  674. {  
  675. int i,j;  
  676. for (j=0;j<ysize;j++)  
  677.   {  
  678.     for (i=0;i<xsize;i++)  
  679.       {  
  680.     if (grid[i][j])  
  681.       fputc(grid[i][j],f);  
  682.     else  
  683.       fputc(BLACKSQUARE,f);  
  684.       }  
  685.     fputc('\n',f);  
  686.   }  
  687. putchar('\n');  
  688. }  
  689.   
  690.   
  691. /*******************************************************************  
  692. save the crossword in a pzl file  
  693. ********************************************************************/  
  694. void SavePuzzle(char *fname)  
  695. {  
  696. FILE *f = fopen(fname,"w");  
  697. int i,j;  
  698. if (!f) return;  
  699.   
  700. fprintf(f,"%cXWORD0%s%c%c%2d%2d",42,"Angry",3,3,xsize,ysize);  
  701.   
  702. for (j=0;j<ysize;j++)  
  703.     for (i=0;i<xsize;i++)  
  704.       fprintf(f,"%c %c",(grid[i][j]?grid[i][j]:'1'),3);  
  705.   
  706. fclose(f);  
  707. }  
  708.   
  709.   
  710. /*******************************************************************  
  711. the main program
  712. ********************************************************************/  
  713. int main(int argc,char *argv[])  
  714. {  
  715. char *wordfile;
  716. list_struct *wordlist;
  717. int num_words;
  718.  
  719. int best=-1;  
  720.   
  721. randomize();
  722. if (argc < 4)  
  723.   {  
  724.     printf("angry: Xsize Ysize WordFile [depth]\n");  
  725.     return(0);  
  726.   }  
  727.  
  728. xsize = atoi(argv[1]);  
  729. ysize = atoi(argv[2]);  
  730. wordfile = argv[3];  
  731.  
  732. if (argc > 4) 
  733.   depth = atoi(argv[4]); 
  734. if (depth > 10) final_try = True;
  735.   
  736. grid = (char **)any_matrix2D(sizeof(char),xsize,ysize);  
  737.  
  738. if (!grid)  
  739.   {  
  740.     printf("failed to allocate memory for the crossword\n");
  741.     return(0);  
  742.   }  
  743.   
  744. wordlist = LoadWordList(wordfile,&num_words);  
  745. if (!wordlist)
  746.   {
  747.     printf("Failed to read list of words from %s\n",wordfile);
  748.     return(0);
  749.   }
  750.  
  751.  
  752. printf("Welcome to Angry - the Cross Word builder! (version %s)\n",VERSION);  
  753. printf("please be patient.....\n\n");  
  754.   
  755. while (True && !kbhit())
  756.   {  
  757.   int n;  
  758.   ZeroCrossword(wordlist,num_words);  
  759.   printf("*\r");
  760.   n = BuildCrossword(wordlist,num_words,0);  
  761.   n -= RemoveLowCrossings(wordlist,num_words,1);
  762.   n = BuildCrossword(wordlist,num_words,SC_MIN_CROSSING);
  763.   n -= RemoveLowCrossings(wordlist,num_words,1);
  764.   if (final_try)
  765.   n += TryAllWords(wordlist,num_words,SC_MIN_CROSSING);
  766.   if (n > best)  
  767.     {  
  768.       best = n;  
  769.       printf("placed %d words\n",best);  
  770.       {  
  771.     FILE *f = fopen("best.doc","w");  
  772.     if (f)
  773.       {
  774.         fprintf(f,"placed %d words\n\n",best);  
  775.         DisplayCrossword(f);  
  776.         fclose(f);
  777.       }
  778.     DisplayCrossword(stdout);  
  779.     SavePuzzle("best.pzl");  
  780.       }  
  781.     }  
  782.   fflush(stdout);  
  783. }  
  784. return(0);  
  785. }  
  786.  
  787.