root/modules/games/gui_reversi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. NotPlayer
  2. GetNum
  3. DrawCell
  4. Place
  5. ComputerPlace
  6. CanPlace
  7. Result
  8. DrawMainWindow
  9. InitMainWindow
  10. NewGame
  11. Clk
  12. Timer
  13. redraw
  14. basic_module_init
  15. gui_reversi_kbd_process
  16. gui_reversi_touch_handler
  17. gui_reversi_draw

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

/* [<][>][^][v][top][bottom][index][help] */