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)30 int 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()44 void 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)66 float letter_prob(char c)
67 {
68 	return (float)lfreq[c&255]/freq_total;
69 }
70 
letter_score(char c)71 int 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)78 char 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)106 int letter_valid(char c)
107 {
108 	return lfreq[c&255]!=0;
109 }
110