diff options
Diffstat (limited to 'apps/plugins/othelo.c')
-rw-r--r-- | apps/plugins/othelo.c | 1545 |
1 files changed, 0 insertions, 1545 deletions
diff --git a/apps/plugins/othelo.c b/apps/plugins/othelo.c deleted file mode 100644 index 7f0502794b..0000000000 --- a/apps/plugins/othelo.c +++ /dev/null | |||
@@ -1,1545 +0,0 @@ | |||
1 | /* | ||
2 | Designed, Written, AI Bots, the lot ...BlueChip =8ĒD# | ||
3 | |||
4 | Thanks espcially to | ||
5 | DevZer0, LinusN, Zagor, scott666 | ||
6 | for their help with understanding Rockbox & the SDK | ||
7 | |||
8 | Please note that the code formatting is not that which was | ||
9 | produced originally, but has been updated by whoever | ||
10 | ported it to the plugin system. | ||
11 | I am sure it was done with good reason, so I have not | ||
12 | redone it! | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * Version Date Who Comment | ||
17 | * -------- -------- ---- ------------------------------------------------ | ||
18 | * 1.4 20030729 BC Ensure game terminates even if dreamer disabled | ||
19 | * 1.3 20030729 BC Fixed display bug introduced by port to plugin | ||
20 | * Updated documentation | ||
21 | * 1.2 2003 Ported to new plugin system | ||
22 | * 1.1 20030625 BC Flash board when invalid move to used aquare | ||
23 | * Fixed "pause computer" for real harware! | ||
24 | * Added USB_CONNECTED support | ||
25 | * Ensure correct fonts on the way in and out | ||
26 | * 1.0 20030622 BC Release | ||
27 | * | ||
28 | * | ||
29 | * Todo: | ||
30 | * # More AI :) | ||
31 | * # Reintroduce suspend feature under plugin system | ||
32 | */ | ||
33 | |||
34 | /* Plugin header */ | ||
35 | #include "plugin.h" | ||
36 | |||
37 | #ifdef HAVE_LCD_BITMAP | ||
38 | |||
39 | static struct plugin_api* rb; | ||
40 | |||
41 | /***************************************************************************/ | ||
42 | /***************************************************************************/ | ||
43 | /* OTHFONT.H */ | ||
44 | /***************************************************************************/ | ||
45 | /***************************************************************************/ | ||
46 | |||
47 | /* Don't reorder this array - you have been warned! */ | ||
48 | enum othfontc { | ||
49 | of_plx, | ||
50 | of_plo, | ||
51 | of_poss, | ||
52 | of_choice, | ||
53 | of_sp, | ||
54 | of_h, | ||
55 | of_c, | ||
56 | of_0, | ||
57 | of_1, | ||
58 | of_2, | ||
59 | of_3, | ||
60 | of_4, | ||
61 | of_5, | ||
62 | of_6, | ||
63 | of_7, | ||
64 | of_8, | ||
65 | of_9, | ||
66 | of_colon, | ||
67 | of_dash, | ||
68 | of_ptr, | ||
69 | of_p, | ||
70 | of_l, | ||
71 | of_a, | ||
72 | of_y, | ||
73 | of_q, | ||
74 | of_u, | ||
75 | of_i, | ||
76 | of_t, | ||
77 | of_eos | ||
78 | }; | ||
79 | |||
80 | static unsigned char othfont[of_eos][6] = { | ||
81 | /* +------+ | ||
82 | * | ## | | ||
83 | * | #### | | ||
84 | * |######| | ||
85 | * |######| | ||
86 | * | #### | | ||
87 | * | ## | | ||
88 | * +------+ | ||
89 | */ | ||
90 | {0x0C, 0x1E, 0x3F, 0x3F, 0x1E, 0x0C}, | ||
91 | /* +------+ | ||
92 | * | ## | | ||
93 | * | #### | | ||
94 | * |## ##| | ||
95 | * |## ##| | ||
96 | * | #### | | ||
97 | * | ## | | ||
98 | * +------+ | ||
99 | */ | ||
100 | {0x0C, 0x1E, 0x33, 0x33, 0x1E, 0x0C}, | ||
101 | /* +------+ | ||
102 | * | | | ||
103 | * | | | ||
104 | * | ## | | ||
105 | * | ## | | ||
106 | * | | | ||
107 | * | | | ||
108 | * +------+ | ||
109 | */ | ||
110 | {0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00}, | ||
111 | /* +------+ | ||
112 | * | | | ||
113 | * | # # | | ||
114 | * | ## | | ||
115 | * | ## | | ||
116 | * | # # | | ||
117 | * | | | ||
118 | * +------+ | ||
119 | */ | ||
120 | {0x00, 0x12, 0x0C, 0x0C, 0x12, 0x00}, | ||
121 | /* +------+ | ||
122 | * | | | ||
123 | * | | | ||
124 | * | | | ||
125 | * | | | ||
126 | * | | | ||
127 | * | | | ||
128 | * +------+ | ||
129 | */ | ||
130 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
131 | /* +------+ | ||
132 | * | # # | 0001 0010 12 | ||
133 | * | # # | 0001 0010 12 | ||
134 | * | #### | 0001 1110 1E | ||
135 | * | # # | 0001 0010 12 | ||
136 | * | # # | 0001 0010 12 | ||
137 | * | # # | 0001 0010 12 | ||
138 | * +------+ | ||
139 | */ | ||
140 | {0x12,0x12,0x1E,0x12,0x12,0x12}, | ||
141 | /* +------+ | ||
142 | * | ## | 0000 1100 0C | ||
143 | * | # # | 0001 0010 12 | ||
144 | * |# | 0010 0000 20 | ||
145 | * |# | 0010 0000 20 | ||
146 | * | # # | 0001 0010 12 | ||
147 | * | ## | 0000 1100 0C | ||
148 | * +------+ | ||
149 | */ | ||
150 | {0x0C,0x12,0x20,0x20,0x12,0x0C}, | ||
151 | /* +------+ | ||
152 | * | ## | 0000 1100 0C | ||
153 | * | # # | 0001 0010 12 | ||
154 | * | # ## | 0001 0110 16 | ||
155 | * | ## # | 0001 1010 1A | ||
156 | * | # # | 0001 0010 12 | ||
157 | * | ## | 0000 1100 0C | ||
158 | * +------+ | ||
159 | */ | ||
160 | {0x0C,0x12,0x16,0x1A,0x12,0x0C}, | ||
161 | /* +------+ | ||
162 | * | # | 0000 0100 04 | ||
163 | * | ## | 0000 1100 0C | ||
164 | * | # | 0000 0100 04 | ||
165 | * | # | 0000 0100 04 | ||
166 | * | # | 0000 0100 04 | ||
167 | * | ### | 0000 1110 0E | ||
168 | * +------+ | ||
169 | */ | ||
170 | {0x04,0x0C,0x04,0x04,0x04,0x0E}, | ||
171 | /* +------+ | ||
172 | * | ## | 0000 1100 0C | ||
173 | * | # # | 0001 0010 12 | ||
174 | * | # | 0000 0010 02 | ||
175 | * | ## | 0000 1100 0C | ||
176 | * | # | 0001 0000 10 | ||
177 | * | #### | 0001 1110 1E | ||
178 | * +------+ | ||
179 | */ | ||
180 | {0x0C,0x12,0x02,0x0C,0x10,0x1E}, | ||
181 | /* +------+ | ||
182 | * | ### | 0001 1100 1C | ||
183 | * | # | 0000 0010 02 | ||
184 | * | ## | 0000 1100 0C | ||
185 | * | # | 0000 0010 02 | ||
186 | * | # | 0000 0010 02 | ||
187 | * | ### | 0001 1100 1C | ||
188 | * +------+ | ||
189 | */ | ||
190 | {0x1C,0x02,0x0C,0x02,0x02,0x1C}, | ||
191 | /* +------+ | ||
192 | * | # | 0001 0000 10 | ||
193 | * | # | 0001 0000 10 | ||
194 | * | # # | 0001 0100 14 | ||
195 | * | # # | 0001 0100 14 | ||
196 | * | #### | 0001 1110 1E | ||
197 | * | # | 0000 0100 04 | ||
198 | * +------+ | ||
199 | */ | ||
200 | {0x10,0x10,0x14,0x14,0x1E,0x04}, | ||
201 | /* +------+ | ||
202 | * | #### | 0001 1110 1E | ||
203 | * | # | 0001 0000 10 | ||
204 | * | ### | 0001 1100 1C | ||
205 | * | # | 0000 0010 02 | ||
206 | * | # # | 0001 0010 12 | ||
207 | * | ## | 0000 1100 0C | ||
208 | * +------+ | ||
209 | */ | ||
210 | {0x1E,0x10,0x1C,0x02,0x12,0x0C}, | ||
211 | /* +------+ | ||
212 | * | ### | 0000 1110 0E | ||
213 | * | # | 0001 0000 10 | ||
214 | * | ### | 0001 1100 1C | ||
215 | * | # # | 0001 0010 12 | ||
216 | * | # # | 0001 0010 12 | ||
217 | * | ## | 0000 1100 0C | ||
218 | * +------+ | ||
219 | */ | ||
220 | {0x0E,0x10,0x1C,0x12,0x12,0x0C}, | ||
221 | /* +------+ | ||
222 | * | #### | 0001 1110 1E | ||
223 | * | # | 0000 0010 02 | ||
224 | * | # | 0000 0100 04 | ||
225 | * | # | 0000 0100 04 | ||
226 | * | # | 0000 1000 08 | ||
227 | * | # | 0000 1000 08 | ||
228 | * +------+ | ||
229 | */ | ||
230 | {0x1E,0x02,0x04,0x04,0x08,0x08}, | ||
231 | /* +------+ | ||
232 | * | ## | 0000 1100 0C | ||
233 | * | # # | 0001 0010 12 | ||
234 | * | ## | 0000 1100 0C | ||
235 | * | # # | 0001 0010 12 | ||
236 | * | # # | 0001 0010 12 | ||
237 | * | ## | 0000 1100 0C | ||
238 | * +------+ | ||
239 | */ | ||
240 | {0x0C,0x12,0x0C,0x12,0x12,0x0C}, | ||
241 | /* +------+ | ||
242 | * | ## | 0000 1100 0C | ||
243 | * | # # | 0001 0010 12 | ||
244 | * | # # | 0001 0010 12 | ||
245 | * | ### | 0000 1110 0E | ||
246 | * | # | 0000 0010 02 | ||
247 | * | ## | 0000 1100 0C | ||
248 | * +------+ | ||
249 | */ | ||
250 | {0x0C,0x12,0x12,0x0E,0x02,0x0C}, | ||
251 | /* +------+ | ||
252 | * | | 0000 0000 00 | ||
253 | * | ## | 0000 1100 0C | ||
254 | * | ## | 0000 1100 0C | ||
255 | * | | 0000 0000 00 | ||
256 | * | ## | 0000 1100 0C | ||
257 | * | ## | 0000 1100 0C | ||
258 | * +------+ | ||
259 | */ | ||
260 | {0x00,0x0C,0x0C,0x00,0x0C,0x0C}, | ||
261 | /* +------+ | ||
262 | * | | 0000 0000 00 | ||
263 | * | | 0000 0000 00 | ||
264 | * | #### | 0001 1110 1E | ||
265 | * | #### | 0001 1110 1E | ||
266 | * | | 0000 0000 00 | ||
267 | * | | 0000 0000 00 | ||
268 | * +------+ | ||
269 | */ | ||
270 | {0x00,0x00,0x1E,0x1E,0x00,0x00}, | ||
271 | /* +------+ | ||
272 | * | | 0000 0000 00 | ||
273 | * | # | 0000 0100 04 | ||
274 | * | ## | 0000 0110 06 | ||
275 | * |######| 0011 1111 3F | ||
276 | * | ## | 0000 0110 06 | ||
277 | * | # | 0000 0100 04 | ||
278 | * +------+ | ||
279 | */ | ||
280 | {0x00,0x04,0x06,0x3F,0x06,0x04}, | ||
281 | /* | ||
282 | * ÚÄÄÄÄÄÄŋ ÚÄÄÄÄÄÄŋ ÚÄÄÄÄÄÄŋ ÚÄÄÄÄÄÄŋ | ||
283 | * ŗ.###..ŗ.ŗ#.....ŗ.ŗ.###..ŗ.ŗ#...#.ŗ xx01 1100 | xx10 0000 | xx01 1100 | xx10 0010 | 1C 20 1C 22 | ||
284 | * ŗ#...#.ŗ.ŗ#.....ŗ.ŗ#...#.ŗ.ŗ#...#.ŗ xx10 0010 | xx10 0000 | xx10 0010 | xx10 0010 | 22 20 22 22 | ||
285 | * ŗ#...#.ŗ.ŗ#.....ŗ.ŗ#...#.ŗ.ŗ.###..ŗ xx10 0010 | xx10 0000 | xx10 0010 | xx01 1100 | 22 20 22 1C | ||
286 | * ŗ####..ŗ.ŗ#.....ŗ.ŗ#####.ŗ.ŗ..#...ŗ xx11 1100 | xx10 0000 | xx11 1110 | xx00 1000 | 3C 20 3E 08 | ||
287 | * ŗ#.....ŗ.ŗ#...#.ŗ.ŗ#...#.ŗ.ŗ..#...ŗ xx10 0000 | xx10 0010 | xx10 0010 | xx00 1000 | 20 22 22 08 | ||
288 | * ŗ#.....ŗ.ŗ.###..ŗ.ŗ#...#.ŗ.ŗ..#...ŗ xx10 0000 | xx01 1100 | xx10 0010 | xx00 1000 | 20 1C 22 08 | ||
289 | * ĀÄÄÄÄÄÄŲ ĀÄÄÄÄÄÄŲ ĀÄÄÄÄÄÄŲ ĀÄÄÄÄÄÄŲ | ||
290 | */ | ||
291 | {0x1C,0x22,0x22,0x3C,0x20,0x20}, | ||
292 | {0x20,0x20,0x20,0x20,0x22,0x1C}, | ||
293 | {0x1C,0x22,0x22,0x3E,0x22,0x22}, | ||
294 | {0x22,0x22,0x1C,0x08,0x08,0x08}, | ||
295 | /* ÚÄÄÄÄÄÄŋ ÚÄÄÄÄÄÄŋ ÚÄÄÄÄÄÄŋ ÚÄÄÄÄÄÄŋ | ||
296 | * ŗ.###..ŗ.ŗ#...#.ŗ.ŗ#####.ŗ.ŗ#####.ŗ xx01 1100 | xx10 0010 | xx11 1110 | xx11 1110 | 1C 22 3E 3E | ||
297 | * ŗ#...#.ŗ.ŗ#...#.ŗ.ŗ..#...ŗ.ŗ..#...ŗ xx10 0010 | xx10 0010 | xx00 1000 | xx00 1000 | 22 22 08 08 | ||
298 | * ŗ#...#.ŗ.ŗ#...#.ŗ.ŗ..#...ŗ.ŗ..#...ŗ xx10 0010 | xx10 0010 | xx00 1000 | xx00 1000 | 22 22 08 08 | ||
299 | * ŗ#...#.ŗ.ŗ#...#.ŗ.ŗ..#...ŗ.ŗ..#...ŗ xx10 0010 | xx10 0010 | xx00 1000 | xx00 1000 | 22 22 08 08 | ||
300 | * ŗ#..##.ŗ.ŗ#...#.ŗ.ŗ..#...ŗ.ŗ..#...ŗ xx10 0110 | xx10 0010 | xx00 1000 | xx00 1000 | 22 22 08 08 | ||
301 | * ŗ.#####ŗ.ŗ.###..ŗ.ŗ#####.ŗ.ŗ..#...ŗ xx01 1111 | xx01 1100 | xx11 1110 | xx00 1000 | 1F 1C 3E 08 | ||
302 | * ĀÄÄÄÄÄÄŲ ĀÄÄÄÄÄÄŲ ĀÄÄÄÄÄÄŲ ĀÄÄÄÄÄÄŲ | ||
303 | */ | ||
304 | {0x1C,0x22,0x22,0x22,0x22,0x1F}, | ||
305 | {0x22,0x22,0x22,0x22,0x22,0x1C}, | ||
306 | {0x3E,0x08,0x08,0x08,0x08,0x3E}, | ||
307 | {0x3E,0x08,0x08,0x08,0x08,0x08} | ||
308 | |||
309 | }; | ||
310 | |||
311 | |||
312 | /***************************************************************************/ | ||
313 | /***************************************************************************/ | ||
314 | /* OTHLOGO.H */ | ||
315 | /***************************************************************************/ | ||
316 | /***************************************************************************/ | ||
317 | |||
318 | /* | ||
319 | |||
320 | ######### # # ### ## ## ### | ||
321 | #### # # # # # # # # # # | ||
322 | ## # ### ### # # # # # | ||
323 | ## # # # # # ### # ## | ||
324 | ## # # # # # # # # # | ||
325 | # # ### ## # # ### | ||
326 | # | ||
327 | # ### # # ### ##### ### # # ### | ||
328 | # # # # # # # # # # # | ||
329 | # ## ### ## # ### # # # ## | ||
330 | # # # # # # # # # # | ||
331 | # # # # # # # # # # | ||
332 | #### ### # ### # ### # # ### | ||
333 | |||
334 | |||
335 | |||
336 | ##################################### | ||
337 | ##################################### | ||
338 | |||
339 | |||
340 | ## ##### # # #### # ## | ||
341 | #### # # # # # #### | ||
342 | ###### # #### ### # ## ## | ||
343 | ###### # # # # # ## ## | ||
344 | #### # # # # # #### | ||
345 | ## # # # #### #### ## | ||
346 | |||
347 | |||
348 | ##################################### | ||
349 | ##################################### | ||
350 | |||
351 | X=42, Y=30 | ||
352 | ####|####|# # | # |### | ##| #|# |### | | | FF A2 E3 18 E0 00 | ||
353 | ####| |# # | # |# #| # |# # | # #| | | | F0 A2 94 A5 00 00 | ||
354 | ## | |# #|## |### | # |# # | # #| | | | C0 9C E4 A5 00 00 | ||
355 | ## | | |# |# #| # |# ##|# #| ##| | | C0 08 94 B9 30 00 | ||
356 | ## | | |# |# #| # |# # |# #| #| | | C0 08 94 A9 10 00 | ||
357 | # | | |# |### | ##| # | # |### | | | 80 08 E3 24 E0 00 | ||
358 | # | | | | | | | | | | | 80 00 00 00 00 00 | ||
359 | # | ##|# # | # | ###| ###|## |### | # #| #|## | 83 A2 77 CE 51 C0 | ||
360 | # | # | # | # |# | #| #| |# # |# # | | 84 22 81 10 AA 00 | ||
361 | # | ##| #|## | ## | #| #|## |# # |# #|# | 83 1C 61 1C A9 80 | ||
362 | # | |# |# | #| #| #| |# # |# | # | 80 88 11 10 A8 40 | ||
363 | # #| |# |# | #| #| #| |# |# | # | 90 88 11 10 88 40 | ||
364 | ####| ###| |# |### | #| |### |# |# ##|# | F7 08 E1 0E 8B 80 | ||
365 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
366 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
367 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
368 | ##|####|####|####|####|####|####|####|####|### | | 3F FF FF FF FE 00 | ||
369 | ##|####|####|####|####|####|####|####|####|### | | 3F FF FF FF FE 00 | ||
370 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
371 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
372 | | ##| #|####| # |# ##|## #| | ## | | | 03 1F 4B D0 60 00 | ||
373 | | ###|# | # | # |# # | #| |####| | | 07 84 4A 10 F0 00 | ||
374 | |####|## | # | ###|# ##|# #| #|# #|# | | 0F C4 7B 91 98 00 | ||
375 | |####|## | # | # |# # | #| #|# #|# | | 0F C4 4A 11 98 00 | ||
376 | | ###|# | # | # |# # | #| |####| | | 07 84 4A 10 F0 00 | ||
377 | | ##| | # | # |# ##|## #|### | ## | | | 03 04 4B DE 60 00 | ||
378 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
379 | | | | | | | | | | | | 00 00 00 00 00 00 | ||
380 | ##|####|####|####|####|####|####|####|####|### | | 3F FF FF FF FE 00 | ||
381 | ##|####|####|####|####|####|####|####|####|### | | 3F FF FF FF FE 00 | ||
382 | */ | ||
383 | |||
384 | /* | ||
385 | * bpl = BYTES per line | ||
386 | * ppl = PIXELS per line | ||
387 | * l = total lines | ||
388 | */ | ||
389 | #define logo_bpl 6 | ||
390 | #define logo_ppl 42 | ||
391 | #define logo_l 32 | ||
392 | |||
393 | static unsigned char logo[] = { | ||
394 | 0xFF,0xA2,0xE3,0x18,0xE0,0x00, | ||
395 | 0xF0,0xA2,0x94,0xA5,0x00,0x00, | ||
396 | 0xC0,0x9C,0xE4,0xA5,0x00,0x00, | ||
397 | 0xC0,0x08,0x94,0xB9,0x30,0x00, | ||
398 | 0xC0,0x08,0x94,0xA9,0x10,0x00, | ||
399 | 0x80,0x08,0xE3,0x24,0xE0,0x00, | ||
400 | 0x80,0x00,0x00,0x00,0x00,0x00, | ||
401 | 0x83,0xA2,0x77,0xCE,0x51,0xC0, | ||
402 | 0x84,0x22,0x81,0x10,0xAA,0x00, | ||
403 | 0x83,0x1C,0x61,0x1C,0xA9,0x80, | ||
404 | 0x80,0x88,0x11,0x10,0xA8,0x40, | ||
405 | 0x90,0x88,0x11,0x10,0x88,0x40, | ||
406 | 0xF7,0x08,0xE1,0x0E,0x8B,0x80, | ||
407 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
408 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
409 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
410 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
411 | 0x3F,0xFF,0xFF,0xFF,0xFE,0x00, | ||
412 | 0x3F,0xFF,0xFF,0xFF,0xFE,0x00, | ||
413 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
414 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
415 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
416 | 0x03,0x1F,0x4B,0xD0,0x60,0x00, | ||
417 | 0x07,0x84,0x4A,0x10,0xF0,0x00, | ||
418 | 0x0F,0xC4,0x7B,0x91,0x98,0x00, | ||
419 | 0x0F,0xC4,0x4A,0x11,0x98,0x00, | ||
420 | 0x07,0x84,0x4A,0x10,0xF0,0x00, | ||
421 | 0x03,0x04,0x4B,0xDE,0x60,0x00, | ||
422 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
423 | 0x00,0x00,0x00,0x00,0x00,0x00, | ||
424 | 0x3F,0xFF,0xFF,0xFF,0xFE,0x00, | ||
425 | 0x3F,0xFF,0xFF,0xFF,0xFE,0x00 | ||
426 | }; | ||
427 | |||
428 | static void showlogo(int x, int y, bool on) | ||
429 | { | ||
430 | int px,py; /* pixel x & y */ | ||
431 | |||
432 | if (on) | ||
433 | { | ||
434 | for (py=0; py<logo_l; py++) | ||
435 | for (px=0; px<logo_ppl; px++) | ||
436 | if ( ((logo[(py*logo_bpl)+(px/8)] >>(7-(px%8))) &1) ) | ||
437 | rb->lcd_drawpixel(x+px, y+py); | ||
438 | else | ||
439 | rb->lcd_clearpixel(x+px, y+py); | ||
440 | rb->lcd_update_rect(x,y, logo_ppl, logo_l); | ||
441 | } | ||
442 | else | ||
443 | rb->lcd_clearrect(x,y, logo_ppl, logo_l); | ||
444 | |||
445 | return; | ||
446 | |||
447 | } | ||
448 | |||
449 | |||
450 | /***************************************************************************/ | ||
451 | /***************************************************************************/ | ||
452 | /* OTHELO.H */ | ||
453 | /***************************************************************************/ | ||
454 | /***************************************************************************/ | ||
455 | |||
456 | |||
457 | /* the following #define had to be taken from Button.c | ||
458 | 'cos it is not defined in the header!! */ | ||
459 | /* how long until repeat kicks in */ | ||
460 | #define REPEAT_START 6 | ||
461 | |||
462 | /* player types */ | ||
463 | #define HUMAN false | ||
464 | #define AIBOT true | ||
465 | |||
466 | /* for domove() */ | ||
467 | #define CHECK false | ||
468 | #define MAKE true | ||
469 | |||
470 | /* screen coords - top left x&y */ | ||
471 | /* game over */ | ||
472 | #define go_tlx 71 | ||
473 | #define go_tly 17 | ||
474 | /* WiNS */ | ||
475 | #define win_tlx 63 | ||
476 | #define win_tly 1 | ||
477 | /* DRaW */ | ||
478 | #define draw_tlx 59 | ||
479 | #define draw_tly 1 | ||
480 | /* scores */ | ||
481 | #define sc_tlx 65 | ||
482 | #define sc_tly 39 | ||
483 | /* logo */ | ||
484 | #define logo_tlx 65 | ||
485 | #define logo_tly 2 | ||
486 | |||
487 | /* board sqaures - | ||
488 | * there are a number of routines that expect these values asis | ||
489 | * do not try to play with these, you will likely kill the program | ||
490 | */ | ||
491 | #define PLAYERX 0 | ||
492 | #define PLAYERO 1 | ||
493 | #define POSS 2 | ||
494 | #define CHOICE 3 | ||
495 | #define EMPTY 4 | ||
496 | #define BORDER 5 | ||
497 | |||
498 | /* Who gets first turn */ | ||
499 | #define FIRST PLAYERX | ||
500 | #define DF_PLX HUMAN | ||
501 | #define DF_AIX NONE | ||
502 | #define DF_PLO AIBOT | ||
503 | #define DF_AIO WEAK | ||
504 | |||
505 | /* Oponent skill level / help level | ||
506 | * -------- --------------------------------------------------- | ||
507 | * NONE no ai / no help | ||
508 | * WEAK random valid move / show all possible | ||
509 | * AVERAGE most pieces (random) / all + most pieces | ||
510 | * SMART most pieces (weighted/random) / all + weighted | ||
511 | * EXPERT | ||
512 | * GURU | ||
513 | */ | ||
514 | #define NONE 0 | ||
515 | #define WEAK 1 | ||
516 | #define AVERAGE 2 | ||
517 | #define SMART 3 | ||
518 | #define EXPERT 4 | ||
519 | #define GURU 5 | ||
520 | #define BEST 3 /* the best ai alogrithm currently available */ | ||
521 | |||
522 | /* these are for code clarity, do not change them! */ | ||
523 | #define LEFT 0x08 | ||
524 | #define RIGHT 0x04 | ||
525 | #define UP 0x02 | ||
526 | #define DOWN 0x01 | ||
527 | |||
528 | /* This represents the maximum number of possible moves | ||
529 | * I have no idea what the real maximum is, buts tests | ||
530 | * suggest about 10 | ||
531 | */ | ||
532 | #define MAXPOSS 20 | ||
533 | |||
534 | struct move | ||
535 | { | ||
536 | int x; | ||
537 | int y; | ||
538 | int taken; | ||
539 | int rank; | ||
540 | bool player; | ||
541 | }; | ||
542 | |||
543 | |||
544 | /*=================================================================== | ||
545 | * local global variables | ||
546 | * THIS IS THE DATA THAT NEEDS TO BE SAVED TO ALLOW THE GAME | ||
547 | * TO CONTINUE ...THE CONTINUE FEATURE DOES NOT WORK UNDER THE | ||
548 | * NEW PLUGIN SYSTEM! | ||
549 | *==================================================================*/ | ||
550 | |||
551 | /* score */ | ||
552 | static struct | ||
553 | { | ||
554 | int x; | ||
555 | int o; | ||
556 | } score; | ||
557 | |||
558 | /* 8x8 with borders */ | ||
559 | static unsigned char board[10][10]; | ||
560 | |||
561 | /* player=HUMAN|AIBOT */ | ||
562 | static bool player[2] = {DF_PLX, DF_PLO}; | ||
563 | |||
564 | /* AI = WEAK|AVERAGE|SMART|EXPERT|GURU | ||
565 | Help=NONE|WEAK|AVERAGE|SMART|EXPERT|GURU */ | ||
566 | static unsigned char ai_help[2] = {DF_AIX, DF_AIO}; | ||
567 | |||
568 | /* is a game under way */ | ||
569 | static bool playing = false; | ||
570 | |||
571 | /* who's turn is it? */ | ||
572 | static bool turn = FIRST; | ||
573 | |||
574 | /******************************************************************** | ||
575 | * strlen ofr use with othello print system | ||
576 | ********************************************************************/ | ||
577 | static int othstrlen(char* s) | ||
578 | { | ||
579 | int i; | ||
580 | |||
581 | for(i=0; s[i]!=of_eos; i++); | ||
582 | |||
583 | return(i); | ||
584 | |||
585 | } | ||
586 | |||
587 | /******************************************************************** | ||
588 | * print othello char upd=true will issue update_lcd() | ||
589 | ********************************************************************/ | ||
590 | static void othprint(unsigned char x, unsigned char y, char ch, bool upd) | ||
591 | { | ||
592 | int px,py; /* pixel coords 1..6 */ | ||
593 | |||
594 | for (py=0; py<6; py++) | ||
595 | for (px=0; px<6; px++) | ||
596 | if ((othfont[(unsigned char)ch][py] >>(5-px)) &1) | ||
597 | rb->lcd_drawpixel(x+px, y+py); | ||
598 | else | ||
599 | rb->lcd_clearpixel(x+px, y+py); | ||
600 | |||
601 | if (upd) | ||
602 | rb->lcd_update_rect(x,y, 6,6); | ||
603 | |||
604 | return; | ||
605 | |||
606 | } | ||
607 | |||
608 | |||
609 | /******************************************************************** | ||
610 | * print othello string upd=true will issue update_lcd() | ||
611 | ********************************************************************/ | ||
612 | static void othprints(unsigned char x, unsigned char y, char* s, bool upd) | ||
613 | { | ||
614 | int i; | ||
615 | int l; /* length of string */ | ||
616 | |||
617 | l = othstrlen(s); | ||
618 | |||
619 | for (i=0; i<l; i++) | ||
620 | othprint(x+i*6,y, s[i], false); | ||
621 | |||
622 | if (upd) | ||
623 | rb->lcd_update_rect(x,y, l*6,6); | ||
624 | |||
625 | return; | ||
626 | |||
627 | } | ||
628 | |||
629 | |||
630 | /******************************************************************** | ||
631 | * display game over visuals | ||
632 | ********************************************************************/ | ||
633 | static void show_endgame(unsigned char scx, unsigned char sco) | ||
634 | { | ||
635 | /* end of game messages */ | ||
636 | showlogo(logo_tlx,logo_tly, false); | ||
637 | |||
638 | /* game over */ | ||
639 | rb->lcd_putsxy(go_tlx+1,go_tly+1, "Game"); | ||
640 | rb->lcd_putsxy(go_tlx+1,go_tly+11, "oveR"); | ||
641 | rb->lcd_invertrect(go_tlx,go_tly, 27,20); | ||
642 | |||
643 | if (scx==sco) | ||
644 | { | ||
645 | /* draw */ | ||
646 | rb->lcd_putsxy(draw_tlx+13,draw_tly+4, "DraW"); | ||
647 | othprint(draw_tlx+5,draw_tly+5, of_plx, true); | ||
648 | othprint(draw_tlx+40,draw_tly+5, of_plo, true); | ||
649 | rb->lcd_drawrect(draw_tlx+2,draw_tly+2, 47,11); | ||
650 | rb->lcd_drawrect(draw_tlx,draw_tly, 51,15); | ||
651 | } | ||
652 | else | ||
653 | { | ||
654 | /* win */ | ||
655 | rb->lcd_putsxy(win_tlx+14,win_tly+4, "WiNS"); | ||
656 | if (sco>scx) | ||
657 | othprint(win_tlx+5,win_tly+5, of_plo, true); | ||
658 | else | ||
659 | othprint(win_tlx+5,win_tly+5, of_plx, true); | ||
660 | rb->lcd_drawrect(win_tlx+2,win_tly+2, 39,11); | ||
661 | rb->lcd_drawrect(win_tlx,win_tly, 43,15); | ||
662 | } | ||
663 | |||
664 | rb->lcd_update(); | ||
665 | |||
666 | return; | ||
667 | |||
668 | } | ||
669 | |||
670 | |||
671 | /******************************************************************** | ||
672 | * display othello grid | ||
673 | * currenly hard coded to the top left corner of the screen | ||
674 | ********************************************************************/ | ||
675 | static void show_grid(void) | ||
676 | { | ||
677 | int x,y; | ||
678 | |||
679 | rb->lcd_clearrect(0,0, (8*7)+1,(8*7)+1); | ||
680 | rb->lcd_drawrect(0,0, (8*7)+1,(8*7)+1); | ||
681 | for (x=7; x<((7*7)+1); x+=7) | ||
682 | { | ||
683 | rb->lcd_drawline(1,x, 2,x); | ||
684 | rb->lcd_drawline(x,1, x,2); | ||
685 | rb->lcd_drawline(x,(8*7)-1, x,(8*7)-2); | ||
686 | rb->lcd_drawline((8*7)-1,x, (8*7)-2,x); | ||
687 | for (y=7; y<((7*7)+1); y+=7) | ||
688 | { | ||
689 | rb->lcd_drawline(x-2,y, x+2,y); | ||
690 | rb->lcd_drawline(x,y-2, x,y+2); | ||
691 | } | ||
692 | } | ||
693 | rb->lcd_update_rect(0,0, (8*7)+1,(8*7)+1); | ||
694 | |||
695 | return; | ||
696 | |||
697 | } | ||
698 | |||
699 | |||
700 | /******************************************************************** | ||
701 | * flash the board - used for invalid move! | ||
702 | ********************************************************************/ | ||
703 | static void flashboard(void) | ||
704 | { | ||
705 | rb->lcd_invertrect(0,0, (8*7)+1,(8*7)+1); | ||
706 | rb->lcd_update_rect(0,0, (8*7)+1,(8*7)+1); | ||
707 | rb->sleep(HZ/10); | ||
708 | rb->lcd_invertrect(0,0, (8*7)+1,(8*7)+1); | ||
709 | rb->lcd_update_rect(0,0, (8*7)+1,(8*7)+1); | ||
710 | |||
711 | return; | ||
712 | |||
713 | } | ||
714 | |||
715 | |||
716 | /******************************************************************** | ||
717 | * show player skill levels | ||
718 | ********************************************************************/ | ||
719 | static void show_players(void) | ||
720 | { | ||
721 | static char scs[] = { | ||
722 | of_plx, of_colon, of_h, of_dash, of_0, of_eos, /* 0 */ | ||
723 | of_plo, of_colon, of_h, of_dash, of_0, of_eos /* 6 */ | ||
724 | }; | ||
725 | |||
726 | if (player[PLAYERX]==AIBOT) | ||
727 | scs[2] = of_c; | ||
728 | else | ||
729 | scs[2] = of_h; | ||
730 | scs[4] = ai_help[PLAYERX] +of_0; | ||
731 | |||
732 | if (player[PLAYERO]==AIBOT) | ||
733 | scs[8] = of_c; | ||
734 | else | ||
735 | scs[8] = of_h; | ||
736 | scs[10] = ai_help[PLAYERO] +of_0; | ||
737 | |||
738 | othprints( 2,58, &scs[0], true); | ||
739 | othprints(40,58, &scs[6], true); | ||
740 | |||
741 | return; | ||
742 | |||
743 | } | ||
744 | |||
745 | |||
746 | /******************************************************************** | ||
747 | * show f3 function | ||
748 | ********************************************************************/ | ||
749 | static void show_f3(bool playing) | ||
750 | { | ||
751 | static char scs[10] = {of_p, of_l, of_a, of_y, of_eos, | ||
752 | of_q, of_u, of_i, of_t, of_eos }; | ||
753 | |||
754 | if (playing) | ||
755 | othprints(80,58, &scs[5], true); | ||
756 | else | ||
757 | othprints(80,58, &scs[0], true); | ||
758 | |||
759 | return; | ||
760 | |||
761 | } | ||
762 | |||
763 | |||
764 | /******************************************************************** | ||
765 | * update board tiles | ||
766 | ********************************************************************/ | ||
767 | static void show_board(void) | ||
768 | { | ||
769 | unsigned char x,y; | ||
770 | |||
771 | for (y=1; y<=8; y++) | ||
772 | for (x=1; x<=8; x++) | ||
773 | othprint(((x-1)*7)+1, ((y-1)*7)+1, board[y][x], false); | ||
774 | rb->lcd_update_rect(0,0, (8*7)+1,(8*7)+1); | ||
775 | |||
776 | return; | ||
777 | |||
778 | } | ||
779 | |||
780 | |||
781 | /******************************************************************** | ||
782 | * display scores player "turn" will get the arrow | ||
783 | ********************************************************************/ | ||
784 | static void show_score(bool turn) | ||
785 | { | ||
786 | static char scs[] = {of_ptr, of_eos, /* 0 */ | ||
787 | of_sp, of_eos, /* 2 */ | ||
788 | of_plx, of_colon, of_eos, /* 4 */ | ||
789 | of_plo, of_colon, of_eos, /* 7 */ | ||
790 | of_sp, of_sp, of_eos, /* 10 score.x */ | ||
791 | of_sp, of_sp, of_eos, /* 13 score.o */ | ||
792 | }; | ||
793 | |||
794 | rb->snprintf(&scs[10], 3, "%d", score.x); | ||
795 | scs[10] = scs[10] -'0' +of_0; | ||
796 | if (scs[11]=='\0') | ||
797 | scs[11] = of_sp; | ||
798 | else | ||
799 | scs[11] = scs[11] -'0' +of_0; | ||
800 | scs[12] = of_eos; | ||
801 | |||
802 | rb->snprintf(&scs[13], 3, "%d", score.o); | ||
803 | scs[13] = scs[13] -'0' +of_0; | ||
804 | if (scs[14]=='\0') | ||
805 | scs[14] = of_sp; | ||
806 | else | ||
807 | scs[14] = scs[14] -'0' +of_0; | ||
808 | scs[15] = of_eos; | ||
809 | |||
810 | /* turn arrow */ | ||
811 | if (turn==PLAYERX) | ||
812 | { | ||
813 | othprints(sc_tlx,sc_tly, &scs[0], false); | ||
814 | othprints(sc_tlx,sc_tly+8, &scs[2], false); | ||
815 | } | ||
816 | else | ||
817 | { | ||
818 | othprints(sc_tlx,sc_tly, &scs[2], false); | ||
819 | othprints(sc_tlx,sc_tly+8, &scs[0], false); | ||
820 | } | ||
821 | |||
822 | /* names */ | ||
823 | othprints(sc_tlx+10,sc_tly, &scs[4], false); | ||
824 | othprints(sc_tlx+10,sc_tly+8, &scs[7], false); | ||
825 | |||
826 | /* scores */ | ||
827 | othprints(sc_tlx+26,sc_tly, &scs[10], false); | ||
828 | othprints(sc_tlx+26,sc_tly+8, &scs[13], false); | ||
829 | |||
830 | rb->lcd_update_rect(sc_tlx,sc_tly, 40,14); | ||
831 | |||
832 | return; | ||
833 | } | ||
834 | |||
835 | |||
836 | /******************************************************************** | ||
837 | * cls() | ||
838 | ********************************************************************/ | ||
839 | static void initscreen(void) | ||
840 | { | ||
841 | rb->lcd_setfont(FONT_SYSFIXED); | ||
842 | rb->lcd_clear_display(); | ||
843 | rb->lcd_update(); | ||
844 | |||
845 | return; | ||
846 | } | ||
847 | |||
848 | |||
849 | /******************************************************************** | ||
850 | * Check is the specified move is valid | ||
851 | * if type=MOVE - the board will be updated. | ||
852 | * this is the recursive bit - it is called by domove() | ||
853 | * checkmove only checks the move in ONE direction | ||
854 | ********************************************************************/ | ||
855 | static int checkmove(unsigned char x, unsigned char y, bool pl, | ||
856 | unsigned char dir, bool type) | ||
857 | { | ||
858 | int i; | ||
859 | unsigned char t; | ||
860 | |||
861 | x -= ( ((dir&LEFT )==LEFT ) ?1:0); | ||
862 | x += ( ((dir&RIGHT)==RIGHT) ?1:0); | ||
863 | y -= ( ((dir&UP )==UP ) ?1:0); | ||
864 | y += ( ((dir&DOWN )==DOWN ) ?1:0); | ||
865 | |||
866 | t = board[y][x]; | ||
867 | |||
868 | /* found your piece */ | ||
869 | if ( t == ((pl==PLAYERX)?PLAYERX:PLAYERO) ) | ||
870 | return(1); | ||
871 | |||
872 | /* found an empty sqaure or board edge */ | ||
873 | if (t>PLAYERO) | ||
874 | return(0); | ||
875 | |||
876 | /* must have found opponent piece */ | ||
877 | if ((i = checkmove(x,y, pl, dir, type))) | ||
878 | { | ||
879 | if (type==MAKE) | ||
880 | board[y][x] = pl; | ||
881 | return(i+1); | ||
882 | } | ||
883 | else | ||
884 | return(0); | ||
885 | } | ||
886 | |||
887 | |||
888 | /******************************************************************** | ||
889 | * this is the control loop for checkmove() | ||
890 | * checkmove()it is called with all eight possible directoins | ||
891 | * the move.taken is defined before it returns | ||
892 | * 0 taken is an invalid move | ||
893 | ********************************************************************/ | ||
894 | static void domove(struct move* move, bool type) | ||
895 | { | ||
896 | int i; | ||
897 | unsigned char dir; | ||
898 | |||
899 | move->taken = 0; | ||
900 | for (dir=DOWN; dir<=(LEFT|UP); dir++) | ||
901 | { | ||
902 | if ( (dir&(UP|DOWN)) ==(UP|DOWN) ) | ||
903 | continue; | ||
904 | if ((i = checkmove(move->x, move->y, move->player, dir, type))) | ||
905 | move->taken += i-1; | ||
906 | } | ||
907 | |||
908 | return; | ||
909 | } | ||
910 | |||
911 | |||
912 | /******************************************************************** | ||
913 | * initialise a new game board and draw it on the screen | ||
914 | ********************************************************************/ | ||
915 | static void initboard(void) | ||
916 | { | ||
917 | unsigned char x,y; | ||
918 | |||
919 | for (y=0; y<10; y++) | ||
920 | for (x=0; x<10; x++) | ||
921 | if ( (y%9)==0 || (x%9)==0) | ||
922 | board[y][x] = BORDER; | ||
923 | else | ||
924 | board[y][x] = EMPTY; | ||
925 | |||
926 | board[4][4] = PLAYERX; | ||
927 | board[5][5] = PLAYERX; | ||
928 | board[4][5] = PLAYERO; | ||
929 | board[5][4] = PLAYERO; | ||
930 | |||
931 | score.x = 2; | ||
932 | score.o = 2; | ||
933 | |||
934 | show_grid(); | ||
935 | show_board(); | ||
936 | show_score(FIRST); | ||
937 | |||
938 | return; | ||
939 | } | ||
940 | |||
941 | |||
942 | /******************************************************************** | ||
943 | * remove "possible" markers from the board | ||
944 | ********************************************************************/ | ||
945 | static void clearposs(void) | ||
946 | { | ||
947 | int x, y; | ||
948 | |||
949 | for (y=1; y<=8; y++) | ||
950 | for (x=1; x<=8; x++) | ||
951 | if (board[y][x]>=POSS) | ||
952 | board[y][x]=EMPTY; | ||
953 | |||
954 | return; | ||
955 | } | ||
956 | |||
957 | |||
958 | /******************************************************************** | ||
959 | * build a list of all possible moves | ||
960 | ********************************************************************/ | ||
961 | static int getplist(struct move* plist, unsigned char pl) | ||
962 | { | ||
963 | int x, y; | ||
964 | unsigned char pcnt = 0; | ||
965 | |||
966 | /* this significantly reduces the amount of pointer maths */ | ||
967 | struct move pmove; | ||
968 | |||
969 | /* clear previous possibilities */ | ||
970 | clearposs(); | ||
971 | |||
972 | for (y=1; y<=8; y++) | ||
973 | for (x=1; x<=8; x++) | ||
974 | { | ||
975 | /* only empty sqaures */ | ||
976 | if (board[y][x]!=EMPTY) | ||
977 | continue; | ||
978 | /* try move */ | ||
979 | pmove.x = x; | ||
980 | pmove.y = y; | ||
981 | pmove.player = pl; | ||
982 | domove(&pmove, CHECK); | ||
983 | /* if valid - add to list */ | ||
984 | if (pmove.taken) | ||
985 | rb->memcpy(&plist[pcnt++], &pmove, sizeof(struct move)); | ||
986 | } | ||
987 | |||
988 | return(pcnt); | ||
989 | |||
990 | } | ||
991 | |||
992 | |||
993 | /******************************************************************** | ||
994 | * qsort | ||
995 | ********************************************************************/ | ||
996 | static int plist_bytaken(const void* m1, const void* m2) | ||
997 | { | ||
998 | /* highest is best */ | ||
999 | return( ((struct move*)m2)->taken - ((struct move*)m1)->taken ); | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /******************************************************************** | ||
1004 | * qsort | ||
1005 | ********************************************************************/ | ||
1006 | static int plist_byrank(const void* m1, const void* m2) | ||
1007 | { | ||
1008 | /* lowest is best */ | ||
1009 | return( ((struct move*)m1)->rank - ((struct move*)m2)->rank ); | ||
1010 | } | ||
1011 | |||
1012 | |||
1013 | /******************************************************************** | ||
1014 | * | ||
1015 | CORNERS (1) | ||
1016 | x......x 1,1(01) 1,8(08) | ||
1017 | ........ | ||
1018 | ........ | ||
1019 | ........ | ||
1020 | ........ | ||
1021 | ........ | ||
1022 | ........ | ||
1023 | x......x 8,1(08) 8,8(64) | ||
1024 | |||
1025 | |||
1026 | BLUFF (2) | ||
1027 | ..x..x.. 1,3(03) 1,6(06) | ||
1028 | ........ | ||
1029 | x.x..x.x 3,1(03) 3,3(09) 3,6(18) 3,8(24) | ||
1030 | ........ | ||
1031 | ........ | ||
1032 | x.x..x.x 6,1(06) 6,3(18) 6,6(36) 6,8(48) | ||
1033 | ........ | ||
1034 | ..x..x.. 8,3(24) 8,6(48) 8,8(64) | ||
1035 | |||
1036 | |||
1037 | EDGE (3) | ||
1038 | ...xx... 1,4(00) 1,5(00) | ||
1039 | ........ | ||
1040 | ........ | ||
1041 | x......x 4,1(00) 4,8(00) | ||
1042 | x......x 5,1(00) 5,8(00) | ||
1043 | ........ | ||
1044 | ........ | ||
1045 | ...xx... 8,4(00) 8,5(00) | ||
1046 | |||
1047 | |||
1048 | BAD (5) - some of these are edge pieces | ||
1049 | .x....x. 1,2(02) 1,7(07) | ||
1050 | xx....xx 2,1(02) 2,2(04) 2,7(14) 2,8(16) | ||
1051 | ........ | ||
1052 | ........ | ||
1053 | ........ | ||
1054 | ........ | ||
1055 | xx....xx 7,1(07) 7,2(14) 7,7(49) 7,8(56) | ||
1056 | .x....x. 8,2(16) 8,7(56) | ||
1057 | |||
1058 | |||
1059 | OTHER (4) | ||
1060 | |||
1061 | * this is called my reduceplist, if the "smart" AIBOT is playing | ||
1062 | * board sqaures are weighted as above | ||
1063 | * | ||
1064 | ********************************************************************/ | ||
1065 | static void smartranking(struct move* plist, unsigned char pcnt) | ||
1066 | { | ||
1067 | |||
1068 | #define corner \ | ||
1069 | ( ((y==1)||(y==8)) && ((x==1)||(x==8)) ) | ||
1070 | |||
1071 | #define bluff \ | ||
1072 | ( ((y==1)||(y==3)||(y==6)||(y==8)) && \ | ||
1073 | ((x==1)||(x==3)||(x==6)||(x==8)) ) | ||
1074 | |||
1075 | #define edge \ | ||
1076 | ( ( ((y==1)||(y==8)) && ((x==4)||(x==5)) ) || \ | ||
1077 | ( ((y==4)||(y==5)) && ((x==1)||(x==8)) ) ) | ||
1078 | |||
1079 | int i; | ||
1080 | register unsigned char mul; | ||
1081 | register unsigned char x, y; | ||
1082 | |||
1083 | for (i=0; i<pcnt; i++) | ||
1084 | { | ||
1085 | x = plist[i].x; | ||
1086 | y = plist[i].y; | ||
1087 | mul = x *y; | ||
1088 | |||
1089 | /* preferred squares */ | ||
1090 | if (corner) { plist[i].rank = 1; continue; } | ||
1091 | else if (bluff) { plist[i].rank = 2; continue; } | ||
1092 | else if (edge) { plist[i].rank = 3; continue; } | ||
1093 | |||
1094 | /* uninteresting square */ | ||
1095 | plist[i].rank = 4; | ||
1096 | |||
1097 | /* avoid "bad" sqaures */ | ||
1098 | if ( (mul==02)||(mul==04)|| | ||
1099 | (mul==07)||(mul==14)||(mul==16)|| | ||
1100 | (mul==49)||(mul==56) ) | ||
1101 | plist[i].rank = 5; | ||
1102 | } | ||
1103 | |||
1104 | return; | ||
1105 | |||
1106 | #undef corner | ||
1107 | #undef bluff | ||
1108 | #undef edge | ||
1109 | |||
1110 | } | ||
1111 | |||
1112 | |||
1113 | /******************************************************************** | ||
1114 | * called by pressing f1 or f2 to change player modes | ||
1115 | ********************************************************************/ | ||
1116 | static void changeplayer(bool pl) | ||
1117 | { | ||
1118 | ai_help[pl]++; | ||
1119 | if (ai_help[pl]>BEST) | ||
1120 | { | ||
1121 | player[pl] = (player[pl]==HUMAN)?AIBOT:HUMAN; | ||
1122 | if (player[pl]==HUMAN) | ||
1123 | ai_help[pl] = NONE; | ||
1124 | else | ||
1125 | ai_help[pl] = WEAK; | ||
1126 | } | ||
1127 | show_players(); | ||
1128 | |||
1129 | return; | ||
1130 | } | ||
1131 | |||
1132 | |||
1133 | /******************************************************************** | ||
1134 | * this proc reduces the list of possible moves to a short list of | ||
1135 | * preferred moves, dependand on the player AI | ||
1136 | ********************************************************************/ | ||
1137 | static unsigned char reduceplist(struct move* plist, unsigned char pcnt, unsigned char ai_help) | ||
1138 | { | ||
1139 | |||
1140 | int i; | ||
1141 | |||
1142 | switch(ai_help) | ||
1143 | { | ||
1144 | /* ------------------------------------------------- */ | ||
1145 | /* weak does not modify the possible's list */ | ||
1146 | /* | ||
1147 | case WEAK: | ||
1148 | break; | ||
1149 | */ | ||
1150 | /* ------------------------------------------------- */ | ||
1151 | case GURU: | ||
1152 | break; | ||
1153 | /* ------------------------------------------------- */ | ||
1154 | case EXPERT: | ||
1155 | break; | ||
1156 | /* ------------------------------------------------- */ | ||
1157 | /* this player will favour certain known moves */ | ||
1158 | case SMART: | ||
1159 | if (pcnt>1) | ||
1160 | { | ||
1161 | smartranking(plist, pcnt); | ||
1162 | rb->qsort(plist, pcnt, sizeof(struct move), plist_byrank); | ||
1163 | for (i=1; i<pcnt; i++) | ||
1164 | if (plist[i].rank!=plist[i-1].rank) | ||
1165 | break; | ||
1166 | pcnt = i; | ||
1167 | } | ||
1168 | /* FALL THROUGH */ | ||
1169 | /* ------------------------------------------------- */ | ||
1170 | /* reduce possibilites to "most pieces taken" */ | ||
1171 | case AVERAGE: | ||
1172 | if (pcnt>1) | ||
1173 | { | ||
1174 | rb->qsort(plist, pcnt, sizeof(struct move), plist_bytaken); | ||
1175 | for (i=1; i<pcnt; i++) | ||
1176 | if (plist[i].taken!=plist[i-1].taken) | ||
1177 | break; | ||
1178 | pcnt = i; | ||
1179 | } | ||
1180 | break; | ||
1181 | /* ------------------------------------------------- */ | ||
1182 | default: | ||
1183 | // you should never get here! | ||
1184 | break; | ||
1185 | } | ||
1186 | |||
1187 | return(pcnt); | ||
1188 | |||
1189 | } | ||
1190 | |||
1191 | |||
1192 | /******************************************************************** | ||
1193 | * calc all moves with wieghting and report back to the user/aibot | ||
1194 | ********************************************************************/ | ||
1195 | static bool calcposs(struct move* plist, unsigned char* pcnt, bool turn) | ||
1196 | { | ||
1197 | int i; | ||
1198 | |||
1199 | /* get list of all possible moves */ | ||
1200 | (*pcnt) = getplist(plist, turn); | ||
1201 | |||
1202 | /* no moves? trigger Game Over */ | ||
1203 | if (!(*pcnt)) | ||
1204 | return(true); | ||
1205 | |||
1206 | /* only evaluate moves for AIBOTs or HUMAN+HELP */ | ||
1207 | if ( (player[turn]==AIBOT) || (ai_help[turn]) ) | ||
1208 | { | ||
1209 | /* mark all possible moves on board */ | ||
1210 | for (i=0; i<(*pcnt); i++) | ||
1211 | board[plist[i].y][plist[i].x] = POSS; | ||
1212 | |||
1213 | /* use ai to reduce list */ | ||
1214 | (*pcnt) = reduceplist(plist, (*pcnt), ai_help[turn]); | ||
1215 | |||
1216 | /* higlight preferred moves */ | ||
1217 | if (ai_help[turn]>WEAK) | ||
1218 | for (i=0; i<(*pcnt); i++) | ||
1219 | board[plist[i].y][plist[i].x] = CHOICE; | ||
1220 | } | ||
1221 | else /* no ai/help required */ | ||
1222 | { | ||
1223 | /* create dummy plist entry for default cursor position */ | ||
1224 | plist[0].x = 4; | ||
1225 | plist[0].y = 4; | ||
1226 | } | ||
1227 | |||
1228 | return(false); /* do not cause Game Over */ | ||
1229 | } | ||
1230 | |||
1231 | |||
1232 | /******************************************************************** | ||
1233 | * cursor highlight | ||
1234 | ********************************************************************/ | ||
1235 | static void hilite(struct move* move, bool on) | ||
1236 | { | ||
1237 | int x = (move->x-1)*7; | ||
1238 | int y = (move->y-1)*7; | ||
1239 | |||
1240 | rb->lcd_invertrect(x+1,y+1, 6,6); | ||
1241 | if (on) | ||
1242 | rb->lcd_drawrect(x,y, 8,8); | ||
1243 | else | ||
1244 | { | ||
1245 | if (x) | ||
1246 | rb->lcd_clearline(x,y+3, x,y+4); | ||
1247 | if (y) | ||
1248 | rb->lcd_clearline(x+3,y, x+4,y); | ||
1249 | if (x!=7*7) | ||
1250 | rb->lcd_clearline(x+7,y+3, x+7,y+4); | ||
1251 | if (y!=7*7) | ||
1252 | rb->lcd_clearline(x+3,y+7, x+4,y+7); | ||
1253 | } | ||
1254 | rb->lcd_update_rect(x,y, 8,8); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | /******************************************************************** | ||
1259 | * main othelo keyboard handler | ||
1260 | * returns the key that it terminated with | ||
1261 | ********************************************************************/ | ||
1262 | static int getmove(struct move* move, struct move* plist, unsigned char* pcnt, bool turn) | ||
1263 | { | ||
1264 | int key; | ||
1265 | bool waiting = true; | ||
1266 | |||
1267 | /* get next move */ | ||
1268 | do | ||
1269 | { | ||
1270 | hilite(move, true); | ||
1271 | key = rb->button_get(true); | ||
1272 | hilite(move, false); | ||
1273 | |||
1274 | switch(key) | ||
1275 | { | ||
1276 | case BUTTON_ON: | ||
1277 | case BUTTON_OFF: | ||
1278 | case BUTTON_F3: | ||
1279 | waiting = false; | ||
1280 | break; | ||
1281 | case BUTTON_UP: | ||
1282 | case BUTTON_UP | BUTTON_REPEAT: | ||
1283 | if (move->y>1) move->y--; | ||
1284 | break; | ||
1285 | case BUTTON_DOWN: | ||
1286 | case BUTTON_DOWN | BUTTON_REPEAT: | ||
1287 | if (move->y<8) move->y++; | ||
1288 | break; | ||
1289 | case BUTTON_LEFT: | ||
1290 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
1291 | if (move->x>1) move->x--; | ||
1292 | break; | ||
1293 | case BUTTON_RIGHT: | ||
1294 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
1295 | if (move->x<8) move->x++; | ||
1296 | break; | ||
1297 | case BUTTON_PLAY: | ||
1298 | if (board[move->y][move->x]>=POSS) | ||
1299 | waiting = false; | ||
1300 | else | ||
1301 | flashboard(); | ||
1302 | break; | ||
1303 | case BUTTON_F1: | ||
1304 | case BUTTON_F2: | ||
1305 | { | ||
1306 | bool pl; | ||
1307 | |||
1308 | pl = (key==BUTTON_F1)?PLAYERX:PLAYERO; | ||
1309 | |||
1310 | changeplayer(pl); | ||
1311 | /* update board if *current* player options changed */ | ||
1312 | if (move->player==pl) | ||
1313 | { | ||
1314 | clearposs(); | ||
1315 | calcposs(plist, pcnt, turn); | ||
1316 | show_board(); | ||
1317 | } | ||
1318 | break; | ||
1319 | } | ||
1320 | default: | ||
1321 | break; | ||
1322 | } | ||
1323 | } while (waiting); | ||
1324 | |||
1325 | return(key); | ||
1326 | } | ||
1327 | |||
1328 | |||
1329 | /******************************************************************** | ||
1330 | * main control loop | ||
1331 | ********************************************************************/ | ||
1332 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | ||
1333 | { | ||
1334 | #define STILL_PLAYING (!gameover && !quit) | ||
1335 | |||
1336 | #define default_players \ | ||
1337 | player[PLAYERX] = DF_PLX; \ | ||
1338 | ai_help[PLAYERX] = DF_AIX; \ | ||
1339 | player[PLAYERO] = DF_PLO; \ | ||
1340 | ai_help[PLAYERO] = DF_AIO; | ||
1341 | |||
1342 | int key; | ||
1343 | |||
1344 | unsigned char pcnt; | ||
1345 | struct move plist[MAXPOSS]; | ||
1346 | |||
1347 | bool gameover; | ||
1348 | bool quit; | ||
1349 | |||
1350 | struct move move; | ||
1351 | |||
1352 | TEST_PLUGIN_API(api); | ||
1353 | (void)parameter; | ||
1354 | rb = api; | ||
1355 | |||
1356 | quit = false; | ||
1357 | |||
1358 | do /* while !quit */ | ||
1359 | { | ||
1360 | initscreen(); | ||
1361 | showlogo(logo_tlx,logo_tly, true); | ||
1362 | show_players(); | ||
1363 | show_f3(true); | ||
1364 | |||
1365 | if (!playing) | ||
1366 | { | ||
1367 | initboard(); | ||
1368 | playing = true; | ||
1369 | turn = FIRST; | ||
1370 | } | ||
1371 | else | ||
1372 | { | ||
1373 | show_grid(); | ||
1374 | show_board(); | ||
1375 | show_score(turn); | ||
1376 | } | ||
1377 | |||
1378 | gameover = false; | ||
1379 | |||
1380 | do /* while !gameover && !quit */ | ||
1381 | { | ||
1382 | /* who's move is it? */ | ||
1383 | move.player = turn; | ||
1384 | |||
1385 | /* perform ai/help routine */ | ||
1386 | if ((gameover = calcposs(plist, &pcnt, turn))) continue; | ||
1387 | |||
1388 | /* player now gets to take a turn */ | ||
1389 | if (player[turn]==AIBOT) | ||
1390 | { | ||
1391 | int timeout; | ||
1392 | bool held = false; | ||
1393 | |||
1394 | unsigned char t; | ||
1395 | /* select a random move from the possibles list */ | ||
1396 | /* this block of code corrupts pcnt */ | ||
1397 | if (pcnt>1) | ||
1398 | t = rb->rand() % pcnt; | ||
1399 | else | ||
1400 | t = 0; | ||
1401 | move.x = plist[t].x; | ||
1402 | move.y = plist[t].y; | ||
1403 | /* move selected will always be valid! */ | ||
1404 | domove(&move, CHECK); | ||
1405 | |||
1406 | /* bots run faster when no humans are playing */ | ||
1407 | if ((player[PLAYERX]==AIBOT) && (player[PLAYERO]==AIBOT)) | ||
1408 | timeout = *rb->current_tick +((HZ*6)/10); | ||
1409 | else | ||
1410 | timeout = *rb->current_tick +((HZ*(REPEAT_START+1))/10); | ||
1411 | while (TIME_BEFORE(*rb->current_tick, timeout)) | ||
1412 | { | ||
1413 | key = rb->button_get(false); | ||
1414 | switch (key) | ||
1415 | { | ||
1416 | case SYS_USB_CONNECTED: | ||
1417 | rb->usb_screen(); | ||
1418 | return PLUGIN_USB_CONNECTED; | ||
1419 | /* hold play to freeze board */ | ||
1420 | case BUTTON_PLAY: | ||
1421 | case BUTTON_PLAY|BUTTON_REPEAT: | ||
1422 | timeout = *rb->current_tick +HZ; | ||
1423 | held = true; | ||
1424 | break; | ||
1425 | case BUTTON_PLAY|BUTTON_REL: | ||
1426 | if (held) | ||
1427 | timeout = *rb->current_tick-1; | ||
1428 | continue; | ||
1429 | case BUTTON_F3: | ||
1430 | gameover = true; | ||
1431 | break; | ||
1432 | case BUTTON_OFF: | ||
1433 | default_players; | ||
1434 | playing = false; | ||
1435 | /* Fall through to BUTTON_ON */ | ||
1436 | case BUTTON_ON: | ||
1437 | return PLUGIN_OK; | ||
1438 | default: | ||
1439 | break; | ||
1440 | } | ||
1441 | } /*endwhile*/; | ||
1442 | } | ||
1443 | else /* player is human */ | ||
1444 | { | ||
1445 | /* only display poss on screen if help is enabled */ | ||
1446 | if (ai_help[turn]) show_board(); | ||
1447 | move.x = plist[0].x; | ||
1448 | move.y = plist[0].y; | ||
1449 | while(true) | ||
1450 | { | ||
1451 | key = getmove(&move, plist, &pcnt, turn); | ||
1452 | switch(key) | ||
1453 | { | ||
1454 | case SYS_USB_CONNECTED: | ||
1455 | rb->usb_screen(); | ||
1456 | return PLUGIN_USB_CONNECTED; | ||
1457 | case BUTTON_OFF: | ||
1458 | playing = false; | ||
1459 | default_players; | ||
1460 | case BUTTON_ON: | ||
1461 | rb->lcd_setfont(FONT_UI); | ||
1462 | return PLUGIN_OK; | ||
1463 | case BUTTON_F3: | ||
1464 | gameover = true; | ||
1465 | default: | ||
1466 | break; | ||
1467 | } | ||
1468 | if (key==BUTTON_F3) | ||
1469 | break; | ||
1470 | |||
1471 | /* check move is valid & retrieve "pieces taken" */ | ||
1472 | domove(&move, CHECK); | ||
1473 | if (move.taken==0) | ||
1474 | flashboard(); | ||
1475 | else | ||
1476 | break; | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | /* player may have hit restart instead of moving */ | ||
1481 | if (STILL_PLAYING) | ||
1482 | { | ||
1483 | /* MAKE MOVE */ | ||
1484 | /* add new piece */ | ||
1485 | board[move.y][move.x] = move.player; | ||
1486 | /* flip opponent pieces */ | ||
1487 | domove(&move, MAKE); | ||
1488 | /* update board */ | ||
1489 | clearposs(); | ||
1490 | show_board(); | ||
1491 | /* update score */ | ||
1492 | if (turn==PLAYERX) | ||
1493 | { | ||
1494 | score.x += move.taken+1; | ||
1495 | score.o -= move.taken; | ||
1496 | } | ||
1497 | if (turn==PLAYERO) | ||
1498 | { | ||
1499 | score.o += move.taken+1; | ||
1500 | score.x -= move.taken; | ||
1501 | } | ||
1502 | /* next player please */ | ||
1503 | turn = (turn==PLAYERX)?PLAYERO:PLAYERX; | ||
1504 | show_score(turn); | ||
1505 | } | ||
1506 | |||
1507 | } while(STILL_PLAYING); | ||
1508 | |||
1509 | clearposs(); | ||
1510 | show_board(); | ||
1511 | show_f3(false); | ||
1512 | show_endgame(score.x, score.o); | ||
1513 | playing = false; | ||
1514 | |||
1515 | do | ||
1516 | { | ||
1517 | if ((key = rb->button_get(true)) ==BUTTON_F3) | ||
1518 | break; | ||
1519 | switch(key) | ||
1520 | { | ||
1521 | case SYS_USB_CONNECTED: | ||
1522 | rb->usb_screen(); | ||
1523 | return PLUGIN_USB_CONNECTED; | ||
1524 | case BUTTON_OFF: | ||
1525 | default_players; | ||
1526 | case BUTTON_ON: | ||
1527 | quit = true; | ||
1528 | break; | ||
1529 | case BUTTON_F1: | ||
1530 | changeplayer(PLAYERX); | ||
1531 | break; | ||
1532 | case BUTTON_F2: | ||
1533 | changeplayer(PLAYERO); | ||
1534 | break; | ||
1535 | default: | ||
1536 | break; | ||
1537 | } | ||
1538 | } while(!quit); | ||
1539 | |||
1540 | }while(!quit); | ||
1541 | |||
1542 | return PLUGIN_OK; | ||
1543 | |||
1544 | } | ||
1545 | #endif | ||