root/modules/games/gui_sokoban.c

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

DEFINITIONS

This source file includes following definitions.
  1. sokoban_undo_add
  2. sokoban_undo
  3. sokoban_redo
  4. sokoban_undo_reset
  5. sokoban_set_level
  6. sokoban_finished
  7. sokoban_next_level
  8. sokoban_move
  9. sokoban_draw_box
  10. gui_sokoban_init
  11. gui_sokoban_kbd_process
  12. gui_sokoban_draw
  13. gui_module_menu_kbd_process
  14. _run
  15. _module_loader
  16. _module_unloader
  17. _module_can_unload
  18. _module_exit_alt

   1 #include "camera_info.h"
   2 #include "stdlib.h"
   3 #include "keyboard.h"
   4 #include "modes.h"
   5 #include "lang.h"
   6 #include "conf.h"
   7 #include "gui.h"
   8 #include "gui_draw.h"
   9 #include "gui_lang.h"
  10 #include "gui_batt.h"
  11 #include "gui_mbox.h"
  12 
  13 #include "module_def.h"
  14 #include "simple_module.h"
  15 
  16 //-------------------------------------------------------------------
  17 
  18 typedef struct
  19 {
  20     int sokoban_level;
  21 } SokobanConf;
  22 
  23 SokobanConf sconf;
  24 
  25 static ConfInfo conf_info[] = {
  26     CONF_INFO( 1, sconf.sokoban_level,          CONF_DEF_VALUE, i:0),
  27     {0,0,0,0,{0}}
  28 };
  29 
  30 void gui_module_menu_kbd_process();
  31 int gui_sokoban_kbd_process();
  32 void gui_sokoban_draw();
  33 
  34 gui_handler GUI_MODE_SOKOBAN = 
  35     /*GUI_MODE_SOKOBAN*/    { GUI_MODE_MODULE, gui_sokoban_draw, gui_sokoban_kbd_process, gui_module_menu_kbd_process, 0, GUI_MODE_FLAG_NODRAWRESTORE };
  36 
  37 //-------------------------------------------------------------------
  38 #define FIELD_WIDTH             15
  39 #define FIELD_HEIGHT            15
  40 
  41 #define WALL_COLOR_1            COLOR_GREY
  42 #define WALL_COLOR_2            COLOR_BLACK
  43 #define BOX_COLOR_1             COLOR_RED
  44 #define BOX_COLOR_2             COLOR_BLACK
  45 #define BOX_COLOR_3             COLOR_YELLOW
  46 #define PLACE_COLOR_1           COLOR_BLUE
  47 #define PLACE_COLOR_2           COLOR_BLACK
  48 #define PLAYER_COLOR_1          COLOR_GREEN
  49 #define PLAYER_COLOR_2          COLOR_BLACK
  50 
  51 #define MARKER_WALL             '#'
  52 #define MARKER_BOX              '$'
  53 #define MARKER_PLACE            '.'
  54 #define MARKER_BOX_PLACE        '*'
  55 #define MARKER_PLAYER           '@'
  56 #define MARKER_PLAYER_PLACE     '+'
  57 #define MARKER_EMPTY            '_' // was space
  58 #define MARKER_LINE_END        '\n' // was |
  59 #define MARKER_LEVEL_END        '!'
  60 
  61 #define LEVEL_CHARS "#$.*@+_"
  62 
  63 #define UNDO_SIZE               1000
  64 
  65 //-------------------------------------------------------------------
  66 static const char *level_file_name="A/CHDK/GAMES/SOKOBAN.LEV";
  67 #define MAX_LEVELS 200
  68 static unsigned short level_start_list[MAX_LEVELS];
  69 static unsigned char level_length_list[MAX_LEVELS];
  70 static unsigned num_levels;
  71 
  72 static int need_redraw;
  73 static int need_redraw_all;
  74 static int  moves;
  75 static char field[FIELD_HEIGHT][FIELD_WIDTH];
  76 
  77 static int cell_size;
  78 static int xPl, yPl;
  79 
  80 static int undo[UNDO_SIZE/10];
  81 static int undo_begin, undo_end, undo_curr;
  82 
  83 //-------------------------------------------------------------------
  84 static void sokoban_undo_add(int dx, int dy, int box) {
  85     int offs, bits, value;
  86 
  87     value = ((box)?1:0)<<2;
  88     if (dx) {
  89         value |= ((dx<0)?1:0)<<1;
  90     } else {
  91         value |= (((dy<0)?1:0)<<1)|1;
  92     }
  93     
  94     offs = undo_curr/10;
  95     bits = (undo_curr%10)*3;
  96     undo[offs] &= ~(7<<bits);
  97     undo[offs] |= (value&7)<<bits;
  98 
  99     if (++undo_curr==UNDO_SIZE) undo_curr=0;
 100     if (undo_curr==undo_begin) {
 101         if (++undo_begin==UNDO_SIZE) undo_begin=0;
 102     }
 103     undo_end=undo_curr;
 104 } 
 105 
 106 //-------------------------------------------------------------------
 107 static void sokoban_undo() {
 108     int dx=0, dy=0, value;
 109     
 110     if (undo_curr!=undo_begin) {
 111         if (undo_curr==0) undo_curr=UNDO_SIZE;
 112         --undo_curr;
 113         
 114         value = (undo[undo_curr/10]>>((undo_curr%10)*3))&7;
 115         if (value&1) dy=1; else dx=1;
 116         if (value&2) {dy=-dy; dx=-dx;}
 117 
 118         field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLAYER_PLACE)?MARKER_PLACE:MARKER_EMPTY;
 119         if (value&4) {
 120             field[yPl+dy][xPl+dx]=(field[yPl+dy][xPl+dx]==MARKER_BOX_PLACE)?MARKER_PLACE:MARKER_EMPTY;
 121             field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLACE)?MARKER_BOX_PLACE:MARKER_BOX;
 122         }
 123         xPl-=dx; yPl-=dy;
 124         field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLACE)?MARKER_PLAYER_PLACE:MARKER_PLAYER;
 125         --moves;
 126     }
 127 }
 128 
 129 //-------------------------------------------------------------------
 130 static void sokoban_redo() {
 131     int dx=0, dy=0, value;
 132     
 133     if (undo_curr!=undo_end) {
 134         value = (undo[undo_curr/10]>>((undo_curr%10)*3))&7;
 135         if (value&1) dy=1; else dx=1;
 136         if (value&2) {dy=-dy; dx=-dx;}
 137 
 138         field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLAYER_PLACE)?MARKER_PLACE:MARKER_EMPTY;
 139         xPl+=dx; yPl+=dy;
 140         if (value&4) {
 141             field[yPl][xPl]=(field[yPl][xPl]==MARKER_BOX_PLACE)?MARKER_PLACE:MARKER_EMPTY;
 142             field[yPl+dy][xPl+dx]=(field[yPl+dy][xPl+dx]==MARKER_PLACE)?MARKER_BOX_PLACE:MARKER_BOX;
 143         }
 144         field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLACE)?MARKER_PLAYER_PLACE:MARKER_PLAYER;
 145         ++moves;
 146 
 147         ++undo_curr;
 148         if (undo_curr==UNDO_SIZE) undo_curr=0;
 149     }
 150 }
 151 
 152 //-------------------------------------------------------------------
 153 static void sokoban_undo_reset() {
 154     undo_begin=undo_end=undo_curr=0;
 155 }
 156 
 157 //-------------------------------------------------------------------
 158 static void sokoban_set_level(int lvl) {
 159     int x=0, y, w=0, h=0;
 160     const char *p;
 161     char *buf;
 162     FILE *fd;    
 163     int start,len;
 164 
 165     len=level_length_list[lvl];
 166     start=level_start_list[lvl];
 167     fd=fopen(level_file_name,"rb");
 168     if(!fd) {
 169         num_levels=0;
 170         return;
 171     }
 172 
 173     buf=malloc(len+1);
 174     if(!buf) {
 175         fclose(fd);
 176         return;
 177     }
 178 
 179     if(fseek(fd,start,SEEK_SET) != 0) {
 180         fclose(fd);
 181         free(buf);
 182         return;
 183     }
 184     fread(buf,1,len,fd);
 185     buf[len]=0;
 186     fclose(fd);
 187 
 188     p=buf;
 189 
 190     // determine dimensions
 191     while (*p) {
 192       if (*p==MARKER_LINE_END) {
 193           ++h;
 194           if (x>w) w=x;
 195           x=0;
 196       } else {
 197           ++x;
 198       }
 199       ++p;
 200     }
 201     if (x>w) w=x;
 202     h-=1; //the last line didn't previously have an end marker
 203 
 204     // clear field
 205     for (y=0; y<FIELD_HEIGHT; ++y)
 206         for (x=0; x<FIELD_WIDTH; ++x)
 207             field[y][x]=MARKER_EMPTY;
 208     
 209     // place maze at the center
 210     p=buf;
 211     for (y=(FIELD_HEIGHT-h)/2; y<FIELD_HEIGHT; ++y, ++p) {
 212         for (x=(FIELD_WIDTH-w)/2; x<FIELD_WIDTH && *p && *p!=MARKER_LINE_END; ++x, ++p) {
 213             field[y][x]=*p;
 214             if (field[y][x] == MARKER_PLAYER || field[y][x] == MARKER_PLAYER_PLACE) {
 215               xPl = x; yPl = y;
 216             }
 217         }
 218         if (!*p || (*p == MARKER_LINE_END && !*(p+1))) break;
 219     }
 220     
 221     free(buf);
 222     sconf.sokoban_level = lvl;
 223     moves = 0;
 224     sokoban_undo_reset();
 225 }
 226 
 227 //-------------------------------------------------------------------
 228 static int sokoban_finished() {
 229     int x, y;
 230 
 231     for (y=0; y<FIELD_HEIGHT; ++y)
 232         for (x=0; x<FIELD_WIDTH; ++x)
 233             if (field[y][x]==MARKER_BOX) 
 234                 return 0;
 235     return 1;
 236 }
 237 
 238 //-------------------------------------------------------------------
 239 static void sokoban_next_level() {
 240     if (++sconf.sokoban_level >= num_levels) sconf.sokoban_level = 0;
 241     sokoban_set_level(sconf.sokoban_level);
 242     need_redraw_all = 1;
 243 }
 244 
 245 //-------------------------------------------------------------------
 246 static int sokoban_move(int dx, int dy) {
 247     switch (field[yPl+dy][xPl+dx]) {
 248         case MARKER_WALL:
 249             return 0;
 250             break;
 251         case MARKER_BOX:
 252         case MARKER_BOX_PLACE:
 253             if (field[yPl+dy*2][xPl+dx*2]==MARKER_WALL || field[yPl+dy*2][xPl+dx*2]==MARKER_BOX || field[yPl+dy*2][xPl+dx*2]==MARKER_BOX_PLACE)
 254                 return 0;
 255             break;
 256         case MARKER_PLACE:
 257         case MARKER_EMPTY:
 258             break;
 259     }
 260     field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLAYER_PLACE)?MARKER_PLACE:MARKER_EMPTY;
 261     xPl+=dx; yPl+=dy;
 262     if (field[yPl][xPl]==MARKER_BOX || field[yPl][xPl]==MARKER_BOX_PLACE) {
 263         field[yPl][xPl]=(field[yPl][xPl]==MARKER_BOX_PLACE)?MARKER_PLACE:MARKER_EMPTY;
 264         field[yPl+dy][xPl+dx]=(field[yPl+dy][xPl+dx]==MARKER_PLACE)?MARKER_BOX_PLACE:MARKER_BOX;
 265         sokoban_undo_add(dx, dy, 1);
 266     } else {
 267         sokoban_undo_add(dx, dy, 0);
 268     }
 269     field[yPl][xPl]=(field[yPl][xPl]==MARKER_PLACE)?MARKER_PLAYER_PLACE:MARKER_PLAYER;
 270     return 1;
 271 }
 272 
 273 //-------------------------------------------------------------------
 274 static void sokoban_draw_box(int x, int y, twoColors cl) {
 275     draw_rectangle(camera_screen.disp_left+x*cell_size, y*cell_size, camera_screen.disp_left+x*cell_size+cell_size-1, y*cell_size+cell_size-1, cl, RECT_BORDER1|DRAW_FILLED);
 276     draw_line(camera_screen.disp_left+x*cell_size+2, y*cell_size, camera_screen.disp_left+x*cell_size+2, y*cell_size+cell_size-1, FG_COLOR(cl));
 277     draw_line(camera_screen.disp_left+x*cell_size+cell_size-1-2, y*cell_size, camera_screen.disp_left+x*cell_size+cell_size-1-2, y*cell_size+cell_size-1, FG_COLOR(cl));
 278     draw_line(camera_screen.disp_left+x*cell_size+2, y*cell_size+2, camera_screen.disp_left+x*cell_size+cell_size-1-2, y*cell_size+2, FG_COLOR(cl));
 279     draw_line(camera_screen.disp_left+x*cell_size+2, y*cell_size+cell_size-1-2, camera_screen.disp_left+x*cell_size+cell_size-1-2, y*cell_size+cell_size-1-2, FG_COLOR(cl));
 280 }
 281 
 282 //-------------------------------------------------------------------
 283 int gui_sokoban_init() {
 284     /* first time through, load the file and make an index
 285      if would could tell when the user left sokoban, 
 286      we could avoid this and malloc all the data structures
 287      unfortunately, gui_mode gets set all over the place */
 288     if(!num_levels) {
 289         char *buf,*p;
 290         FILE *fd;    
 291         struct stat st;
 292 
 293         if (stat((char *)level_file_name,&st) != 0 || st.st_size==0) 
 294             return 0;
 295 
 296         fd=fopen(level_file_name,"rb");
 297         if(!fd) 
 298             return 0;
 299 
 300         buf=malloc(st.st_size+1);
 301         if(!buf) {
 302             fclose(fd);
 303             return 0;
 304         }
 305 
 306         fread(buf,1,st.st_size,fd);
 307         buf[st.st_size]=0;
 308         fclose(fd);
 309         p = buf;
 310         do {
 311             // skip to the first level char
 312             p = strpbrk(p,LEVEL_CHARS);
 313             // found a level char, store the start
 314             if (p) {
 315                 unsigned pos = p - buf;
 316                 if ( pos > 65535 ) {
 317                     break;
 318                 }
 319                 level_start_list[num_levels] = (unsigned short)pos;
 320                 p=strchr(p,MARKER_LEVEL_END);
 321                 // found the end char, store the end
 322                 if(p) {
 323                     unsigned len = p - (buf + level_start_list[num_levels]);
 324                     // bail on invalid level
 325                     if ( len > 255 ) {
 326                         break;
 327                     }
 328                     level_length_list[num_levels] = (unsigned char)len;
 329                     ++num_levels;
 330                 }
 331             }
 332         } while(p && num_levels < MAX_LEVELS);
 333         free(buf);
 334     }
 335     if(!num_levels) {
 336         return 0;
 337     }
 338     else if(sconf.sokoban_level >= num_levels) {
 339         sconf.sokoban_level = 0;
 340     }
 341     if (camera_screen.height*3 > camera_screen.width*2) {
 342         // worst case scenario (640x480)
 343         cell_size = 8*camera_screen.height/(9*FIELD_HEIGHT);
 344     }
 345     else {
 346         cell_size = camera_screen.height/FIELD_HEIGHT;
 347     }
 348     sokoban_set_level(sconf.sokoban_level);
 349         // if the file is no longer readable, set_level will set this
 350     if(!num_levels) {
 351         return 0;
 352     }
 353     need_redraw_all = 1;
 354 
 355     gui_set_mode(&GUI_MODE_SOKOBAN);
 356     return 1;
 357 }
 358 
 359 //-------------------------------------------------------------------
 360 int gui_sokoban_kbd_process() {
 361     switch (kbd_get_autoclicked_key()) {
 362         case KEY_UP:
 363             moves+=sokoban_move(0, -1);
 364             need_redraw = 1;
 365             break;
 366         case KEY_DOWN:
 367             moves+=sokoban_move(0, +1);
 368             need_redraw = 1;
 369             break;
 370         case KEY_LEFT:
 371             moves+=sokoban_move(-1, 0);
 372             need_redraw = 1;
 373             break;
 374         case KEY_RIGHT:
 375             moves+=sokoban_move(+1, 0);
 376             need_redraw = 1;
 377             break;
 378         case KEY_SET:
 379             if (moves == 0) {
 380                 sokoban_next_level();
 381             }
 382             break;
 383         case KEY_ZOOM_OUT:
 384             sokoban_undo();
 385             need_redraw = 1;
 386             break;
 387         case KEY_ZOOM_IN:
 388             sokoban_redo();
 389             need_redraw = 1;
 390             break;
 391         case KEY_ERASE:
 392         case KEY_DISPLAY:
 393             sokoban_set_level(sconf.sokoban_level);
 394             need_redraw_all = 1;
 395             break;
 396     }
 397     return 0;
 398 }
 399 
 400 //-------------------------------------------------------------------
 401 void gui_sokoban_draw() {
 402     int y, x;
 403     static char str[16];
 404 
 405     if (need_redraw_all) {
 406         draw_rectangle(camera_screen.disp_left, 0, camera_screen.disp_right, camera_screen.height-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
 407         need_redraw_all = 0;
 408         need_redraw = 1;
 409     }
 410 
 411     if (need_redraw) {
 412         need_redraw = 0;
 413         for (y=0; y<FIELD_HEIGHT; ++y) {
 414             for (x=0; x<FIELD_WIDTH; ++x) {
 415                 switch (field[y][x]) {
 416                     case MARKER_WALL:
 417                         draw_rectangle(camera_screen.disp_left+x*cell_size, y*cell_size, camera_screen.disp_left+x*cell_size+cell_size-1, y*cell_size+cell_size-1, MAKE_COLOR(WALL_COLOR_1, WALL_COLOR_2), RECT_BORDER1|DRAW_FILLED);
 418                         break;
 419                     case MARKER_BOX:
 420                         sokoban_draw_box(x, y, MAKE_COLOR(BOX_COLOR_1, BOX_COLOR_2));
 421                         break;
 422                     case MARKER_PLACE:
 423                         draw_rectangle(camera_screen.disp_left+x*cell_size, y*cell_size, camera_screen.disp_left+x*cell_size+cell_size-1, y*cell_size+cell_size-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
 424                         draw_rectangle(camera_screen.disp_left+x*cell_size+4, y*cell_size+4, camera_screen.disp_left+x*cell_size+cell_size-1-4, y*cell_size+cell_size-1-4, MAKE_COLOR(PLACE_COLOR_1, PLACE_COLOR_2), RECT_BORDER1|DRAW_FILLED);
 425                         break;
 426                     case MARKER_BOX_PLACE:
 427                         sokoban_draw_box(x, y, MAKE_COLOR(BOX_COLOR_3, BOX_COLOR_2));
 428                         break;
 429                     case MARKER_PLAYER:
 430                     case MARKER_PLAYER_PLACE:
 431                         draw_rectangle(camera_screen.disp_left+x*cell_size, y*cell_size, camera_screen.disp_left+x*cell_size+cell_size-1, y*cell_size+cell_size-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
 432                         draw_ellipse(camera_screen.disp_left+x*cell_size+(cell_size>>1)-1, y*cell_size+(cell_size>>1)-1, (cell_size>>1)-3, (cell_size>>1)-3, PLAYER_COLOR_1, DRAW_FILLED);
 433                         break;
 434                     case MARKER_EMPTY:
 435                     default:
 436                         draw_rectangle(camera_screen.disp_left+x*cell_size, y*cell_size, camera_screen.disp_left+x*cell_size+cell_size-1, y*cell_size+cell_size-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
 437                         break;
 438                 }
 439             }
 440         }
 441 
 442         draw_line(camera_screen.disp_left+cell_size*FIELD_WIDTH, 0, camera_screen.disp_left+cell_size*FIELD_WIDTH, camera_screen.height-1, COLOR_WHITE);
 443         draw_line(camera_screen.disp_left+cell_size*FIELD_WIDTH+1, 0, camera_screen.disp_left+cell_size*FIELD_WIDTH+1, camera_screen.height-1, COLOR_BLACK);
 444 
 445         sprintf(str, "%s: %-6d", lang_str(LANG_SOKOBAN_TEXT_LEVEL), sconf.sokoban_level+1);
 446         draw_string(camera_screen.disp_left+cell_size*FIELD_WIDTH+2, 8, str, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE));
 447         sprintf(str, "%s: %-6d", lang_str(LANG_SOKOBAN_TEXT_MOVES), moves);
 448         draw_string(camera_screen.disp_left+cell_size*FIELD_WIDTH+2, 8+FONT_HEIGHT, str, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE));
 449 
 450         if (sokoban_finished()) {
 451             gui_mbox_init(LANG_SOKOBAN_MSG_FINISH_TITLE, LANG_SOKOBAN_MSG_FINISH_TEXT, MBOX_TEXT_CENTER, NULL);
 452             sokoban_next_level();
 453         }
 454     }
 455 
 456     sprintf(str, "Batt:%3d%%", get_batt_perc());
 457     draw_string_justified(camera_screen.disp_left, camera_screen.height-FONT_HEIGHT,
 458                           str, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE), 0, camera_screen.disp_width-FONT_WIDTH, TEXT_RIGHT);
 459 }
 460 
 461 
 462 static int running = 0;
 463 
 464 void gui_module_menu_kbd_process()
 465 {
 466     running = 0;
 467         gui_default_kbd_process_menu_btn();
 468 }
 469 
 470 // =========  MODULE INIT =================
 471 
 472 /***************** BEGIN OF AUXILARY PART *********************
 473   ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
 474  **************************************************************/
 475 
 476 int _run()
 477 {
 478     if (!camera_info.state.mode_play)
 479     {
 480         gui_mbox_init(LANG_MSG_INFO_TITLE, LANG_MSG_SWITCH_TO_PLAY_MODE, MBOX_FUNC_RESTORE|MBOX_TEXT_CENTER, 0);
 481     }
 482     else
 483     {
 484         running = 1;
 485         gui_sokoban_init();
 486     }
 487 
 488     return 0;
 489 }
 490 
 491 //---------------------------------------------------------
 492 // PURPOSE:   Perform on-load initialisation
 493 // RETURN VALUE: 1 error, 0 ok
 494 //---------------------------------------------------------
 495 int _module_loader( unsigned int* chdk_export_list )
 496 {
 497     sconf.sokoban_level = 0;
 498     config_restore(&conf_info[0], "A/CHDK/MODULES/CFG/sokoban.cfg", 0);
 499     return 0;
 500 }
 501 
 502 //---------------------------------------------------------
 503 // PURPOSE: Finalize module operations (close allocs, etc)
 504 // RETURN VALUE: 0-ok, 1-fail
 505 //---------------------------------------------------------
 506 int _module_unloader()
 507 {
 508     config_save(&conf_info[0], "A/CHDK/MODULES/CFG/sokoban.cfg", 99000);
 509     return 0;
 510 }
 511 
 512 int _module_can_unload()
 513 {
 514     return running == 0;
 515 }
 516 
 517 int _module_exit_alt()
 518 {
 519     running = 0;
 520     return 0;
 521 }
 522 
 523 /******************** Module Information structure ******************/
 524 
 525 libsimple_sym _librun =
 526 {
 527     {
 528          0, _module_unloader, _module_can_unload, _module_exit_alt, _run
 529     }
 530 };
 531 
 532 ModuleInfo _module_info =
 533 {
 534     MODULEINFO_V1_MAGICNUM,
 535     sizeof(ModuleInfo),
 536     SIMPLE_MODULE_VERSION,              // Module version
 537 
 538     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,                       // Requirements of CHDK version
 539     ANY_PLATFORM_ALLOWED,               // Specify platform dependency
 540 
 541     -LANG_MENU_GAMES_SOKOBAN,   // Module name
 542     MTYPE_GAME,
 543 
 544     &_librun.base,
 545 
 546     ANY_VERSION,                // CONF version
 547     CAM_SCREEN_VERSION,         // CAM SCREEN version
 548     ANY_VERSION,                // CAM SENSOR version
 549     ANY_VERSION,                // CAM INFO version
 550 };
 551 
 552 /*************** END OF AUXILARY PART *******************/

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