This source file includes following definitions.
- db_random
- db_hang_forall
- db_randomsym
- db_hang
- db_hangman
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <sys/param.h>
30
31 #include <uvm/uvm_extern.h>
32
33 #include <machine/db_machdep.h>
34
35 #include <ddb/db_sym.h>
36 #include <ddb/db_extern.h>
37 #include <ddb/db_output.h>
38
39 #include <dev/cons.h>
40 #include <dev/rndvar.h>
41
42 #define ABC_ISCLR(c) sabc->abc[(c)-'a']==0
43 #define ABC_ISWRONG(c) sabc->abc[(c)-'a']=='_'
44 #define ABC_SETWRONG(c) (sabc->abc[(c)-'a']='_')
45 #define ABC_SETRIGHT(c) (sabc->abc[(c)-'a']='+')
46 #define ABC_CLR() memset(sabc->abc,0,sizeof sabc->abc)
47 struct _abc {
48 char abc[26+2];
49 };
50
51 #define TOLOWER(c) ((c)|0x20)
52 #define ISLOWALPHA(c) ('a'<=(c) && (c)<='z')
53 #define ISALPHA(c) ISLOWALPHA(TOLOWER(c))
54
55 void db_hang(int, char *, struct _abc *);
56
57 u_long db_plays, db_guesses;
58
59 static const char hangpic[]=
60 "\n88888\r\n"
61 "9 7 6\r\n"
62 "97 5\r\n"
63 "9 423\r\n"
64 "9 2\r\n"
65 "9 1 0\r\n"
66 "9\r\n"
67 "9 ";
68 static const char substchar[]="\\/|\\/O|/-|";
69
70 static size_t
71 db_random(size_t mod)
72 {
73 if (cold)
74 return (random() % mod);
75 return (arc4random() % mod);
76 }
77
78 struct db_hang_forall_arg {
79 int cnt;
80 db_sym_t sym;
81 };
82
83
84
85
86 static void db_hang_forall(db_symtab_t *, db_sym_t, char *, char *, int,
87 void *);
88
89 static void
90 db_hang_forall(db_symtab_t *stab, db_sym_t sym, char *name, char *suff, int pre,
91 void *varg)
92 {
93 struct db_hang_forall_arg *arg = (struct db_hang_forall_arg *)varg;
94
95 if (arg->cnt-- == 0)
96 arg->sym = sym;
97 }
98
99 static __inline char *
100 db_randomsym(size_t *lenp)
101 {
102 extern db_symtab_t db_symtabs[];
103 db_symtab_t *stab;
104 int nsymtabs, nsyms;
105 char *p, *q;
106 struct db_hang_forall_arg dfa;
107
108 for (nsymtabs = 0; db_symtabs[nsymtabs].name != NULL; nsymtabs++)
109 ;
110
111 if (nsymtabs == 0)
112 return (NULL);
113
114 stab = &db_symtabs[db_random(nsymtabs)];
115
116 dfa.cnt = 0;
117 X_db_forall(stab, db_hang_forall, &dfa);
118 nsyms = -dfa.cnt;
119
120 if (nsyms == 0)
121 return (NULL);
122
123 dfa.cnt = db_random(nsyms);
124 X_db_forall(stab, db_hang_forall, &dfa);
125
126 q = db_qualify(dfa.sym, stab->name);
127
128
129 if (nsymtabs < 3)
130 while (*q++ != ':');
131
132
133 for ((*lenp) = 0, p = q; *p; p++)
134 if (ISALPHA(*p))
135 (*lenp)++;
136
137 return (q);
138 }
139
140 void
141 db_hang(int tries, char *word, struct _abc *sabc)
142 {
143 const char *p;
144 int i;
145 int c;
146 #ifdef ABC_BITMASK
147 int m;
148 #endif
149
150 for (p = hangpic; *p; p++)
151 cnputc((*p >= '0' && *p <= '9') ? ((tries <= (*p) - '0') ?
152 substchar[(*p) - '0'] : ' ') : *p);
153
154 for (p = word; *p; p++) {
155 c = TOLOWER(*p);
156 cnputc(ISLOWALPHA(c) && ABC_ISCLR(c) ? '-' : *p);
157 }
158
159 #ifdef ABC_WRONGSTR
160 db_printf(" (%s)\r", ABC_WRONGSTR);
161 #else
162 db_printf(" (");
163
164 #ifdef ABC_BITMASK
165 m = sabc->wrong;
166 for (i = 'a'; i <= 'z'; ++i, m >>= 1)
167 if (m&1)
168 cnputc(i);
169 #else
170 for (i = 'a'; i <= 'z'; ++i)
171 if (ABC_ISWRONG(i))
172 cnputc(i);
173 #endif
174
175 db_printf(")\r");
176 #endif
177 }
178
179 void
180 db_hangman(db_expr_t addr, int haddr, db_expr_t count, char *modif)
181 {
182 char *word;
183 size_t tries;
184 size_t len;
185 struct _abc sabc[1];
186 int skill;
187
188 if (modif[0] != 's' || (skill = modif[1] - '0') > 9U)
189 skill = 3;
190 word = NULL;
191 tries = 0;
192 for (;;) {
193
194 if (word == NULL) {
195 ABC_CLR();
196
197 tries = skill + 1;
198 word = db_randomsym(&len);
199 if (word == NULL)
200 break;
201
202 db_plays++;
203 }
204
205 {
206 int c;
207
208 db_hang(tries, word, sabc);
209 c = cngetc();
210 c = TOLOWER(c);
211
212 if (ISLOWALPHA(c) && ABC_ISCLR(c)) {
213 char *p;
214 size_t n;
215
216
217 for (n = 0, p = word; *p ; p++)
218 if (TOLOWER(*p) == c)
219 n++;
220
221 if (n) {
222 ABC_SETRIGHT(c);
223 len -= n;
224 } else {
225 ABC_SETWRONG(c);
226 tries--;
227 }
228 }
229 }
230
231 if (tries && len)
232 continue;
233
234 if (!tries && skill > 2) {
235 char *p = word;
236 for (; *p; p++)
237 if (ISALPHA(*p))
238 ABC_SETRIGHT(TOLOWER(*p));
239 }
240 if (tries)
241 db_guesses++;
242 db_hang(tries, word, sabc);
243 db_printf("\nScore: %lu/%lu\n", db_plays, db_guesses);
244 word = NULL;
245 if (tries)
246 break;
247 }
248 }