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