This source file includes following definitions.
- NotPlayer
- GetNum
- DrawCell
- Place
- ComputerPlace
- CanPlace
- Result
- DrawMainWindow
- InitMainWindow
- NewGame
- Clk
- Timer
- redraw
- basic_module_init
- gui_reversi_kbd_process
- gui_reversi_touch_handler
- gui_reversi_draw
1 #include "camera_info.h"
2 #include "keyboard.h"
3 #include "clock.h"
4 #include "lang.h"
5 #include "gui.h"
6 #include "gui_draw.h"
7 #include "gui_lang.h"
8 #include "gui_batt.h"
9 #include "gui_mbox.h"
10 #include "modes.h"
11
12 #include "module_def.h"
13
14 void gui_game_menu_kbd_process();
15 int gui_reversi_kbd_process();
16 void gui_reversi_draw();
17 static int gui_reversi_touch_handler(int,int);
18
19 gui_handler GUI_MODE_REVERSI =
20 { GUI_MODE_MODULE, gui_reversi_draw, gui_reversi_kbd_process,
21 gui_game_menu_kbd_process, gui_reversi_touch_handler, GUI_MODE_FLAG_NODRAWRESTORE };
22
23
24 #define FIELD_EMPTY 0
25 #define FIELD_PLAYER1 1
26 #define FIELD_PLAYER2 2
27 #define COMPUTER_ONLY 3
28
29 #define FIELD_COLOR_WHITE COLOR_GREEN
30 #define FIELD_COLOR_BLACK COLOR_GREEN_DK
31 #define SELECTED_COLOR COLOR_RED
32
33
34 typedef unsigned char uchar;
35 typedef unsigned int uint;
36
37
38 static uchar Field[8][8];
39 static uchar CurrPlayer, Computer, InGame, NumPl1, NumPl2;
40
41 static unsigned short field_size, field_x, field_y, cell_size;
42
43 static uchar xPos, yPos, OldxPos, OldyPos;
44 static volatile uchar need_redraw = 0, need_redraw_all = 0, MFlag = 0;
45
46 static char buf[128];
47
48
49 static void redraw();
50
51
52 static uchar NotPlayer(uchar Pl) {
53 return (Pl ^ COMPUTER_ONLY);
54 }
55
56
57 static inline void GetNum() {
58 uchar x, y;
59 NumPl1 = NumPl2 = 0;
60
61 for (x=0; x<8; ++x)
62 for (y=0; y<8; ++y) {
63 if (Field[x][y]==FIELD_PLAYER1) ++NumPl1;
64 if (Field[x][y]==FIELD_PLAYER2) ++NumPl2;
65 }
66 }
67
68
69 static void DrawCell(uchar x, uchar y) {
70 draw_rectangle(field_x+cell_size*x, field_y+cell_size*y,
71 field_x+cell_size*(x+1), field_y+cell_size*(y+1),
72 (x==xPos && y==yPos)?MAKE_COLOR(SELECTED_COLOR, COLOR_RED):((x+y)&1)?MAKE_COLOR(FIELD_COLOR_WHITE, COLOR_WHITE)
73 :MAKE_COLOR(FIELD_COLOR_BLACK, COLOR_WHITE), RECT_BORDER0|DRAW_FILLED);
74 switch (Field[x][y]) {
75 case FIELD_EMPTY:
76 break;
77 case FIELD_PLAYER1:
78 draw_ellipse(field_x+cell_size*x+(cell_size>>1), field_y+cell_size*y+(cell_size>>1),
79 (cell_size>>1)-4, (cell_size>>1)-4, COLOR_WHITE, DRAW_FILLED);
80 break;
81 case FIELD_PLAYER2:
82 draw_ellipse(field_x+cell_size*x+(cell_size>>1), field_y+cell_size*y+(cell_size>>1),
83 (cell_size>>1)-4, (cell_size>>1)-4, COLOR_BLACK, DRAW_FILLED);
84 break;
85 }
86 }
87
88
89 static uchar Place(uchar x, uchar y, uchar Player, uchar Placed) {
90
91 int I, J, x1, y1;
92 uchar Eated, E;
93
94 if (Field[x][y]!=FIELD_EMPTY) {
95 return 0xFF;
96 } else {
97 Eated = 0;
98 for (I=-1; I<=1; I++) {
99 for (J=-1; J<=1; J++) {
100 E = 0;
101 x1 = x + I;
102 y1 = y + J;
103 while (((x1>=0) && (x1<8) && (y1>=0) && (y1<8)) && (Field[x1][y1]!=FIELD_EMPTY) && (Field[x1][y1]!=Player)) {
104 E++;
105 x1 = x1 + I;
106 y1 = y1 + J;
107 }
108 if ((Placed) && ((x1>=0) && (x1<8) && (y1>=0) && (y1<8)) && (Field[x1][y1]!=FIELD_EMPTY) && (E>0)) {
109 Field[x][y] = Player;
110 DrawCell(x, y);
111 x1 = x + I;
112 y1 = y + J;
113 while (((x1>=0) && (x1<8) && (y1>=0) && (y1<8)) && (Field[x1][y1]!=FIELD_EMPTY) && (Field[x1][y1]!=Player)) {
114 Field[x1][y1] = Player;
115 DrawCell(x1, y1);
116 x1 = x1 + I;
117 y1 = y1 + J;
118 }
119 }
120 if (((x1>=0) && (x1<8) && (y1>=0) && (y1<8)) && (Field[x1][y1]!=FIELD_EMPTY))
121 Eated += E;
122 }
123 }
124 return Eated;
125 }
126 }
127
128
129 static void ComputerPlace(uchar Player) {
130
131 static const uchar PlaceTable[8][8] ={{ 11, 78, 62, 65, 65, 62, 78, 11},
132 { 78, 94, 74, 73, 73, 74, 94, 78},
133 { 62, 74, 63, 64, 64, 63, 74, 62},
134 { 65, 73, 64, 11, 11, 64, 73, 65},
135 { 65, 73, 64, 11, 11, 64, 73, 65},
136 { 62, 74, 63, 64, 64, 63, 74, 62},
137 { 78, 94, 74, 73, 73, 74, 94, 78},
138 { 11, 78, 62, 65, 65, 62, 78, 11}};
139
140 uchar PlX[61];
141 uchar PlY[61];
142 static uchar DynTable[8][8];
143 uchar NPl = 0, I, J, MaxE = 0, E, MinPr = 100;
144
145 srand(get_tick_count());
146
147 for (I=0; I<8; I++)
148 for (J=0; J<8; J++)
149 DynTable[I][J] = PlaceTable[I][J] + (rand()%3) - 1;
150
151 for (I=0; I<8; I++) {
152 for (J=0; J<8; J++) {
153 E = Place(I, J, Player, 0);
154 if ((MinPr>DynTable[I][J]) && (E<0xFF) && (E>0)) {
155 MinPr = DynTable[I][J];
156 NPl = 0;
157 MaxE = 0;
158 }
159 if ((E<0xFF) && (MinPr==DynTable[I][J])) {
160 if (E>MaxE) {
161 MaxE = E;
162 NPl = 1;
163 PlX[1] = I;
164 PlY[1] = J;
165 } else {
166 if (E==MaxE) {
167 NPl++;
168 PlX[NPl] = I;
169 PlY[NPl] = J;
170 }
171 }
172 }
173 }
174 }
175
176 MaxE = MinPr = 0;
177
178 for(I=0; I<8; I+=7) {
179 for(J=0; J<8; J+=7) {
180 E = Place(I, J, Player, 0);
181 if ((E<0xFF) && (E>0)) {MaxE = E; MinPr = (I<<4) + J + 1;}
182 }
183 }
184
185 E = (rand()%NPl) + 1;
186 if(MinPr) Place(MinPr>>4, (MinPr&0x0F)-1, Player, 1);
187 else Place(PlX[E], PlY[E], Player, 1);
188
189 return;
190 }
191
192
193 static uchar CanPlace(uchar Player) {
194 uchar I, J, E = 0, E1;
195
196 for (I=0; I<8; I++) {
197 for (J=0; J<8; J++) {
198 E1 = Place(I, J, Player, 0);
199 if (E1<0xFF) E+=E1;
200 }
201 }
202 return (E>0);
203 }
204
205
206 static void Result() {
207 if (NumPl1>NumPl2)
208 gui_mbox_init(LANG_REVERSI_MSG_RESULTS_TITLE, LANG_REVERSI_MSG_RESULTS_WON, MBOX_TEXT_CENTER, NULL);
209 else if (NumPl1<NumPl2)
210 gui_mbox_init(LANG_REVERSI_MSG_RESULTS_TITLE, LANG_REVERSI_MSG_RESULTS_LOST, MBOX_TEXT_CENTER, NULL);
211 else
212 gui_mbox_init(LANG_REVERSI_MSG_RESULTS_TITLE, LANG_REVERSI_MSG_RESULTS_DRAW, MBOX_TEXT_CENTER, NULL);
213 redraw();
214 need_redraw_all = 1;
215 }
216
217
218 static void DrawMainWindow() {
219 uchar x, y;
220
221 draw_rectangle(camera_screen.disp_left+field_size+field_x, FONT_HEIGHT*5, camera_screen.disp_right,
222 camera_screen.height-FONT_HEIGHT*4-1, MAKE_COLOR(COLOR_BLUE, COLOR_BLUE), RECT_BORDER0|DRAW_FILLED);
223 for (y=0; y<8; ++y) {
224 for (x=0; x<8; ++x) {
225 DrawCell(x, y);
226 }
227 }
228 }
229
230
231 static void InitMainWindow() {
232 InGame = 0;
233 draw_rectangle(camera_screen.disp_left, 0, camera_screen.disp_right,
234 camera_screen.height-1, MAKE_COLOR(COLOR_BLUE, COLOR_BLUE), RECT_BORDER0|DRAW_FILLED);
235 field_size = camera_screen.height & 0xFFF8;
236 field_x = camera_screen.disp_left;
237 field_y = camera_screen.height-field_size;
238 cell_size = field_size >> 3;
239 }
240
241
242 static void NewGame() {
243 memset(Field, FIELD_EMPTY, sizeof(Field));
244 Field[3][3] = Field[4][4] = FIELD_PLAYER1;
245 Field[3][4] = Field[4][3] = FIELD_PLAYER2;
246 CurrPlayer = FIELD_PLAYER1;
247 Computer = FIELD_PLAYER2;
248 NumPl1 = NumPl2 = 2;
249 xPos = yPos = OldxPos = OldyPos = 3;
250 InGame = 1;
251 need_redraw_all = 1;
252 }
253
254
255 static void Clk(uchar x, uchar y) {
256 uchar Placed;
257
258 if ((CurrPlayer==Computer) || (! InGame) || (Computer==COMPUTER_ONLY))
259 ;
260 else {
261 Placed = Place(x, y ,CurrPlayer, 0);
262 if (Placed==0) {
263 gui_mbox_init(LANG_REVERSI_MSG_WRONG_TITLE, LANG_REVERSI_MSG_WRONG_TEXT_1, MBOX_TEXT_CENTER, NULL);
264 need_redraw_all = 1;
265 } else if (Placed==0xFF) {
266 gui_mbox_init(LANG_REVERSI_MSG_WRONG_TITLE, LANG_REVERSI_MSG_WRONG_TEXT_2, MBOX_TEXT_CENTER, NULL);
267 need_redraw_all = 1;
268 } else {
269 Placed = Place(x, y, CurrPlayer, 1);
270 CurrPlayer = NotPlayer(CurrPlayer);
271 GetNum();
272 need_redraw = 1;
273 if (!CanPlace(FIELD_PLAYER1) && !CanPlace(FIELD_PLAYER2)) {
274 InGame = 0;
275 Result();
276 }
277 if (InGame && !CanPlace(CurrPlayer)) {
278 CurrPlayer = NotPlayer(CurrPlayer);
279 need_redraw = 1;
280 }
281 }
282 }
283 }
284
285
286 static void Timer() {
287 if ((InGame) & (CurrPlayer==Computer || Computer==COMPUTER_ONLY)) {
288 if (CanPlace(CurrPlayer)) {
289 ComputerPlace(CurrPlayer);
290 GetNum();
291 need_redraw = 1;
292 }
293 CurrPlayer = NotPlayer(CurrPlayer);
294 if (!CanPlace(FIELD_PLAYER1) && !CanPlace(FIELD_PLAYER2)) {
295 InGame = 0;
296 Result();
297 }
298 if (InGame && !CanPlace(CurrPlayer)) {
299 CurrPlayer = NotPlayer(CurrPlayer);
300 need_redraw = 1;
301 }
302 }
303 }
304
305
306 static void redraw() {
307 uint x, y, mid;
308 char *plm1, *plm2;
309
310 if (InGame) {
311 if (CurrPlayer==FIELD_PLAYER1) {
312 plm1 = "\x10";
313 plm2 = " ";
314 }
315 else {
316 plm1 = " ";
317 plm2 = "\x10";
318 }
319 }
320 else {
321 plm1 = plm2 = " ";
322 }
323
324 draw_rectangle(field_x+cell_size*xPos, field_y+cell_size*yPos, field_x+cell_size*(xPos+1),
325 field_y+cell_size*(yPos+1), MAKE_COLOR(COLOR_RED,COLOR_RED), RECT_BORDER1);
326 x = camera_screen.disp_left+field_size, y = 40;
327 mid = ((camera_screen.width-field_size) >> 2);
328 x += mid;
329 draw_string(x, y-10, "REVERSI", MAKE_COLOR(COLOR_BLUE, COLOR_WHITE));
330 sprintf(buf, " %d ", NumPl1);
331 draw_string(x+FONT_WIDTH*(7-strlen(buf))/2, y+FONT_HEIGHT*2, buf, MAKE_COLOR(COLOR_BLUE, COLOR_WHITE));
332 draw_string(x, y+FONT_HEIGHT*2, plm1, MAKE_COLOR(COLOR_BLUE, COLOR_WHITE));
333 draw_ellipse(x+FONT_WIDTH*1.5+(cell_size>>1), y+FONT_HEIGHT*3+(cell_size>>1),
334 (cell_size>>1)-4, (cell_size>>1)-4, COLOR_WHITE, DRAW_FILLED);
335 sprintf(buf, " %d ", NumPl2);
336 draw_string(x+FONT_WIDTH*(7-strlen(buf))/2, y+FONT_HEIGHT*6, buf, MAKE_COLOR(COLOR_BLUE, COLOR_WHITE));
337 draw_string(x, y+FONT_HEIGHT*6, plm2, MAKE_COLOR(COLOR_BLUE, COLOR_WHITE));
338 draw_ellipse(x+FONT_WIDTH*1.5+(cell_size>>1), y+FONT_HEIGHT*7+(cell_size>>1),
339 (cell_size>>1)-4, (cell_size>>1)-4, COLOR_BLACK, DRAW_FILLED);
340 }
341
342
343 int basic_module_init() {
344 gui_set_mode(&GUI_MODE_REVERSI);
345 InitMainWindow();
346 NewGame();
347 need_redraw_all = 1;
348 return 1;
349 }
350
351
352 int gui_reversi_kbd_process() {
353 switch (kbd_get_autoclicked_key()) {
354 case KEY_UP:
355 yPos = (yPos-1)&7;
356 MFlag = 1;
357 break;
358 case KEY_DOWN:
359 yPos = (yPos+1)&7;
360 MFlag = 1;
361 break;
362 case KEY_LEFT:
363 xPos = (xPos-1)&7;
364 MFlag = 1;
365 break;
366 case KEY_RIGHT:
367 xPos = (xPos+1)&7;
368 MFlag = 1;
369 break;
370 case KEY_SET:
371 if (InGame)
372 Clk(xPos, yPos);
373 else
374 NewGame();
375 need_redraw = 1;
376 break;
377 case KEY_ERASE:
378 case KEY_DISPLAY:
379 if (InGame)
380 Computer=COMPUTER_ONLY;
381 else
382 NewGame();
383 need_redraw = 1;
384 break;
385 }
386 return 0;
387 }
388
389
390 static int gui_reversi_touch_handler(int sx, int sy) {
391 if ((sx >= field_x) && (sx < field_x+cell_size*8) && (sy >= field_y) && (sy < field_x+cell_size*8))
392 {
393 sx = (sx - field_x) / cell_size;
394 sy = (sy - field_y) / cell_size;
395 if ((sx != xPos) || (sy != yPos))
396 {
397 xPos = sx;
398 yPos = sy;
399 need_redraw = 1;
400 }
401 return KEY_SET;
402 }
403 return 0;
404 }
405
406
407 void gui_reversi_draw() {
408 if (MFlag) {
409 MFlag = 0;
410 DrawCell(OldxPos, OldyPos);
411 DrawCell(xPos, yPos);
412 OldxPos = xPos, OldyPos = yPos;
413 }
414 if (need_redraw_all) {
415 need_redraw_all = 0;
416 DrawMainWindow();
417 need_redraw = 1;
418 }
419 if (need_redraw) {
420 need_redraw = 0;
421 redraw();
422 }
423 sprintf(buf, "Batt:%3d%%", get_batt_perc());
424 draw_string_justified(camera_screen.disp_left, camera_screen.height-FONT_HEIGHT,
425 buf, MAKE_COLOR(COLOR_BLUE, COLOR_WHITE), 0, camera_screen.disp_width, TEXT_RIGHT);
426 Timer();
427 }
428
429 #include "simple_game.c"
430
431
432
433 ModuleInfo _module_info =
434 {
435 MODULEINFO_V1_MAGICNUM,
436 sizeof(ModuleInfo),
437 SIMPLE_MODULE_VERSION,
438
439 ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,
440 ANY_PLATFORM_ALLOWED,
441
442 -LANG_MENU_GAMES_REVERSI,
443 MTYPE_GAME,
444
445 &_librun.base,
446
447 ANY_VERSION,
448 CAM_SCREEN_VERSION,
449 ANY_VERSION,
450 ANY_VERSION,
451
452 0,
453 };
454