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 "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_REVERSI*/    { 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 /* 0..64 - Ok  0xFF - not empty*/
  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 /******************** Module Information structure ******************/
 432 
 433 ModuleInfo _module_info =
 434 {
 435     MODULEINFO_V1_MAGICNUM,
 436     sizeof(ModuleInfo),
 437     SIMPLE_MODULE_VERSION,              // Module version
 438 
 439     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,                       // Requirements of CHDK version
 440     ANY_PLATFORM_ALLOWED,               // Specify platform dependency
 441 
 442     -LANG_MENU_GAMES_REVERSI,   // Module name
 443     MTYPE_GAME,
 444 
 445     &_librun.base,
 446 
 447     ANY_VERSION,                // CONF version
 448     CAM_SCREEN_VERSION,         // CAM SCREEN version
 449     ANY_VERSION,                // CAM SENSOR version
 450     ANY_VERSION,                // CAM INFO version
 451 
 452     0,
 453 };
 454 

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