1 /* Copyright 1998,2001 Mark Pulford 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. Read the file COPYING found in this archive for details, or 4 * visit http://www.gnu.org/copyleft/gpl.html 5 */ 6 7 #include <config.h> 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <unistd.h> 13 #include <time.h> 14 #include <assert.h> 15 16 #include "lang.h" 17 #include "dict.h" 18 #include "iface.h" 19 #include "lexter.h" 20 21 static int lfreq[256]; 22 static int freq_total; 23 static int lscore[256]; 24 25 /* Cannot trust RAND_MAX with random(). Some systems define it for a 26 * 15bit rand() function */ 27 #define RMAX 2147483647 28 29 /* Return a random number in [0,n-1] */ rnd(int n)30int rnd(int n) 31 { 32 static int noseed = 1; 33 double i = n; 34 35 if(noseed) { 36 srandom(getpid()+time(NULL)); 37 noseed = 0; 38 } 39 40 return (int) (i * random() / (RMAX+1.0)); 41 } 42 43 /* update frequency/letter score tables */ letter_update_freq()44void letter_update_freq() 45 { 46 int i; 47 int max; 48 49 if(!dict_get_freq(lfreq)) 50 abort(); 51 52 freq_total = 0; 53 max = 0; 54 /* Calculate sum for proportional random letter */ 55 for(i=0; i<256; i++) { 56 freq_total += lfreq[i]; 57 if(lfreq[i]>max) 58 max = lfreq[i]; 59 } 60 61 /* Calculate score */ 62 for(i=0; i<256; i++) 63 lscore[i] = ((max - lfreq[i])*100)/max; 64 } 65 letter_prob(char c)66float letter_prob(char c) 67 { 68 return (float)lfreq[c&255]/freq_total; 69 } 70 letter_score(char c)71int letter_score(char c) 72 { 73 assert(letter_valid(c)); 74 return lscore[c&255] + LETTER_BONUS; 75 } 76 77 /* bchance is % chance of a blank character */ letter_generate(int bchance)78char letter_generate(int bchance) 79 { 80 int lsum=0, i, r; 81 82 if(rnd(100)<bchance) 83 return ' '; 84 85 r = rnd(freq_total); 86 87 lsum = 0; 88 for(i=0; i<256; i++) { 89 lsum += lfreq[i]; 90 if(r<lsum) 91 break; 92 } 93 94 /* Assuming i<256. This must be true since 95 * - at the end of the loop lsum == freq_total 96 * - r < freq_total 97 * - therefore it will always "break" out of the loop */ 98 /* If this fails then random() probably returned higher than RMAX */ 99 assert(i<256); 100 101 return i; 102 } 103 104 /* Returns: 1 valid letter found in dictionary 105 * 0 letter not found in dictionary */ letter_valid(char c)106int letter_valid(char c) 107 { 108 return lfreq[c&255]!=0; 109 } 110