Subversion Repositories Kolibri OS

Rev

Rev 5231 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "board.h"
  2.  
  3. rect base_cell = {0};
  4. tile null_tile = {0};
  5.  
  6.  
  7. struct {
  8.     rect    draw;                       // background rect
  9.     rect    cell_map[BOARD_MAP_SIZE];   // background cells array
  10.     tile    tile_map[BOARD_MAP_SIZE];   // tiles array
  11.     __u16   empty_index[BOARD_MAP_SIZE];// empty cells indexes
  12.     __u16   empty_count;                // empty cells count
  13.     __u32   score;
  14. } board = {0};
  15.  
  16. // Get tile index for row and column
  17. __u16 board_index(__u16 row, __u16 column) {
  18.     return column + row * BOARD_COUNT;
  19. }
  20.  
  21. // Get tile position (as point with eow and column) for index
  22. point board_position(__u16 index) {
  23.     point p = {
  24.         .x = index % BOARD_COUNT,
  25.         .y = index / BOARD_COUNT
  26.     };
  27.     return p;
  28. }
  29.  
  30. // Calculate cell rect for row and column
  31. rect position2cell(point p) {
  32.     rect c = {0};
  33.     c.width = base_cell.width;
  34.     c.height = base_cell.height;
  35.     c.x = board.draw.x + BOARD_SPACING + p.x * (c.width + BOARD_SPACING);
  36.     c.y = board.draw.y + BOARD_SPACING + p.y * (c.height + BOARD_SPACING);
  37.     return c;
  38. }
  39.  
  40. // Update information about empty cells
  41. void board_update_empty_info();
  42.  
  43. // Represent tile array as pointers array
  44. void board_to_tempboard(tile* temp[]);
  45.  
  46. // Fill tile array with tiles from pointers array
  47. void board_from_tempboard(tile* temp[], __u8 forward);
  48.  
  49. // Move tile inside a pointer array
  50. void tempboard_move_tile(tile* temp[], __u16 from, __u16 to);
  51.  
  52. // Merge tiles inside a pointer array
  53. void tempboard_merge_tile(tile* temp[], __u16 from, __u16 to);
  54.  
  55. // Random number generator
  56. __u32 random_u32(__u32 max);
  57.  
  58. void board_init(rect* r)
  59. {
  60.     // seed for random number generator
  61.     srand(__menuet__getsystemclock());
  62.  
  63.     board.score = 0;
  64.     board.draw = *r;
  65.  
  66.     __u16 cell_size = (r->width - BOARD_SPACING * (BOARD_COUNT + 1)) / BOARD_COUNT;
  67.     base_cell.width = cell_size;
  68.     base_cell.height = cell_size;
  69.  
  70.     null_tile.value = 0;
  71.     null_tile.animate = false;
  72.     null_tile.ani_step = ANIM_STEP;
  73.     null_tile.merged = false;
  74.  
  75.     __u16 i = 0;
  76.     for (i = 0; i < BOARD_MAP_SIZE; i++)
  77.     {
  78.         board.cell_map[i] = position2cell(board_position(i));
  79.         board.tile_map[i] = null_tile;
  80.     }
  81.  
  82.     i = 0;
  83.     for (i = 0; i < START_COUNT; i++)
  84.     {
  85.         board_add_random_tile();
  86.     }
  87.  
  88.     board_redraw();
  89. }
  90.  
  91. void board_redraw()
  92. {
  93.     __u16 i = 0;
  94.     __u8 animate = false;
  95.     __u8 last_animate = false;
  96.     do
  97.     {
  98.         vsync();
  99.         rect_draw(&board.draw,BOARD_BG_COLOR);
  100.  
  101.         for (i = 0; i < BOARD_MAP_SIZE; i++)
  102.         {
  103.             rect_draw(&board.cell_map[i],CELL_COLOR);
  104.         }
  105.  
  106.         animate = false;
  107.         last_animate = false;
  108.         for (i = 0; i < BOARD_MAP_SIZE; i++)
  109.         {
  110.             tile* t = &board.tile_map[i];
  111.             last_animate = tile_draw(t);
  112.             if (last_animate)
  113.             {
  114.                 animate = last_animate;
  115.             }
  116.         }
  117.  
  118.         if (animate)
  119.         {
  120.             __menuet__delay100(ANIM_DELAY);
  121.         }
  122.     }
  123.     while (animate);
  124. }
  125.  
  126. __u8 board_up()
  127. {
  128.     __u8 moved = false;
  129.  
  130.     __u16 row = 0;
  131.     __u16 column = 0;
  132.     __u16 ind = 0;
  133.     __u16 preind = 0;
  134.     tile* indtile = 0;
  135.     tile* pretile = 0;
  136.  
  137.     tile* temp_board[BOARD_MAP_SIZE] = {0};
  138.     board_to_tempboard(temp_board);
  139.  
  140.     for (column = 0; column < BOARD_COUNT; column++)
  141.     {
  142.         for (row = 0; row < BOARD_COUNT; row++)
  143.         {
  144.             if (row > 0)
  145.             {
  146.                 ind = board_index(row,column);
  147.                 indtile = temp_board[ind];
  148.                 if (indtile)
  149.                 {
  150.                     preind = board_index(row - 1,column);
  151.                     pretile = temp_board[preind];
  152.                     if (!pretile)
  153.                     {
  154.                         moved = true;
  155.                         tempboard_move_tile(temp_board,ind,preind);
  156.                         row = 0;
  157.                     }
  158.                     else if (tile_mergeable(indtile,pretile))
  159.                     {
  160.                         moved = true;
  161.                         board.score += indtile->value * 2;
  162.                         tempboard_merge_tile(temp_board,ind,preind);
  163.                         row = 0;
  164.                     }
  165.                 }
  166.             }
  167.         }
  168.     }
  169.  
  170.     board_from_tempboard(temp_board,true);
  171.  
  172.     return moved;
  173. }
  174.  
  175. __u8 board_down()
  176. {
  177.     __u8 moved = false;
  178.  
  179.     __u16 row = 0;
  180.     __u16 column = 0;
  181.     __u16 ind = 0;
  182.     __u16 preind = 0;
  183.     tile* indtile = 0;
  184.     tile* pretile = 0;
  185.  
  186.     tile* temp_board[BOARD_MAP_SIZE] = {0};
  187.     board_to_tempboard(temp_board);
  188.  
  189.     for (column = 0; column < BOARD_COUNT; column++)
  190.     {
  191.         row = BOARD_COUNT;
  192.         while (row--)
  193.         {
  194.             if ((BOARD_COUNT - row) > 1)
  195.             {
  196.                 ind = board_index(row,column);
  197.                 indtile = temp_board[ind];
  198.                 if (indtile)
  199.                 {
  200.                     preind = board_index(row + 1,column);
  201.                     pretile = temp_board[preind];
  202.                     if (!pretile)
  203.                     {
  204.                         moved = true;
  205.                         tempboard_move_tile(temp_board,ind,preind);
  206.                         row = BOARD_COUNT;
  207.                     }
  208.                     else if (tile_mergeable(indtile,pretile))
  209.                     {
  210.                         moved = true;
  211.                         board.score += indtile->value * 2;
  212.                         tempboard_merge_tile(temp_board,ind,preind);
  213.                         row = BOARD_COUNT;
  214.                     }
  215.                 }
  216.             }
  217.         }
  218.     }
  219.  
  220.     board_from_tempboard(temp_board,false);
  221.  
  222.     return moved;
  223. }
  224.  
  225. __u8 board_left()
  226. {
  227.     __u8 moved = false;
  228.  
  229.     __u16 row = 0;
  230.     __u16 column = 0;
  231.     __u16 ind = 0;
  232.     __u16 preind = 0;
  233.     tile* indtile = 0;
  234.     tile* pretile = 0;
  235.  
  236.     tile* temp_board[BOARD_MAP_SIZE] = {0};
  237.     board_to_tempboard(temp_board);
  238.  
  239.     for (row = 0; row < BOARD_COUNT; row++)
  240.     {
  241.         for (column = 0; column < BOARD_COUNT; column++)
  242.         {
  243.             if (column > 0)
  244.             {
  245.                 ind = board_index(row,column);
  246.                 indtile = temp_board[ind];
  247.                 if (indtile)
  248.                 {
  249.                     preind = board_index(row,column - 1);
  250.                     pretile = temp_board[preind];
  251.                     if (!pretile)
  252.                     {
  253.                         moved = true;
  254.                         tempboard_move_tile(temp_board,ind,preind);
  255.                         column = 0;
  256.                     }
  257.                     else if (tile_mergeable(indtile,pretile))
  258.                     {
  259.                         moved = true;
  260.                         board.score += indtile->value * 2;
  261.                         tempboard_merge_tile(temp_board,ind,preind);
  262.                         column = 0;
  263.                     }
  264.                 }
  265.             }
  266.         }
  267.     }
  268.  
  269.     board_from_tempboard(temp_board,true);
  270.  
  271.     return moved;
  272. }
  273.  
  274. __u8 board_right()
  275. {
  276.     __u8 moved = false;
  277.  
  278.     __u16 row = 0;
  279.     __u16 column = 0;
  280.     __u16 ind = 0;
  281.     __u16 preind = 0;
  282.     tile* indtile = 0;
  283.     tile* pretile = 0;
  284.  
  285.     tile* temp_board[BOARD_MAP_SIZE] = {0};
  286.     board_to_tempboard(temp_board);
  287.  
  288.     for (row = 0; row < BOARD_COUNT; row++)
  289.     {
  290.         column = BOARD_COUNT;
  291.         while (column--)
  292.         {
  293.             if ((BOARD_COUNT - column) > 1)
  294.             {
  295.                 ind = board_index(row,column);
  296.                 indtile = temp_board[ind];
  297.                 if (indtile)
  298.                 {
  299.                     preind = board_index(row,column + 1);
  300.                     pretile = temp_board[preind];
  301.                     if (!pretile)
  302.                     {
  303.                         moved = true;
  304.                         tempboard_move_tile(temp_board,ind,preind);
  305.                         column = BOARD_COUNT;
  306.                     }
  307.                     else if (tile_mergeable(indtile,pretile))
  308.                     {
  309.                         moved = true;
  310.                         board.score += indtile->value * 2;
  311.                         tempboard_merge_tile(temp_board,ind,preind);
  312.                         column = BOARD_COUNT;
  313.                     }
  314.                 }
  315.             }
  316.         }
  317.     }
  318.  
  319.     board_from_tempboard(temp_board,false);
  320.  
  321.     return moved;
  322. }
  323.  
  324. __u8 board_add_random_tile()
  325. {
  326.     board_update_empty_info();
  327.     if (board.empty_count)
  328.     {
  329.         __u16 rnd_av = random_u32(board.empty_count);
  330.         rnd_av = board.empty_index[rnd_av];
  331.  
  332.         tile* av_tile = &board.tile_map[rnd_av];
  333.         av_tile->value = (random_u32(10) < 9) ? 2 : 4;
  334.  
  335.         av_tile->animate = true;
  336.         av_tile->ani_step = 5;
  337.         av_tile->transition = position2cell(board_position(rnd_av));
  338.         av_tile->cell.x = av_tile->transition.x + base_cell.width / 2;
  339.         av_tile->cell.y = av_tile->transition.y + base_cell.height / 2;
  340.         av_tile->cell.width = 0;
  341.         av_tile->cell.height = 0;
  342.     }
  343.     return board.empty_count;
  344. }
  345.  
  346. __u8 board_has_moves()
  347. {
  348.     __u16 ind = 0;
  349.     __u16 next = 0;
  350.     __u16 step = 0;
  351.     __u16 pos = 0;
  352.     for (step = 0; step < BOARD_COUNT; step++)
  353.     {
  354.         for (pos = 0; pos < BOARD_COUNT; pos++)
  355.         {
  356.             // check horizontal
  357.             ind = board_index(step,pos);
  358.             next = board_index(step,pos + 1);
  359.  
  360.             if (!board.tile_map[ind].value ||
  361.                     (((pos + 1) < BOARD_COUNT) &&
  362.                      (!board.tile_map[next].value ||
  363.                       (board.tile_map[ind].value == board.tile_map[next].value)
  364.                       )
  365.                      )
  366.                     )
  367.                 return true;
  368.  
  369.             // check vertical
  370.             ind = board_index(pos,step);
  371.             next = board_index(pos + 1,step);
  372.  
  373.             if (!board.tile_map[ind].value ||
  374.                     (((pos + 1) < BOARD_COUNT) &&
  375.                      (!board.tile_map[next].value ||
  376.                       (board.tile_map[ind].value == board.tile_map[next].value)
  377.                       )
  378.                      )
  379.                     )
  380.                 return true;
  381.         }
  382.     }
  383.     return false;
  384. }
  385.  
  386. __u32 board_score()
  387. {
  388.     return board.score;
  389. }
  390.  
  391. void board_update_empty_info()
  392. {
  393.     board.empty_count = 0;
  394.  
  395.     __u16 i = 0;
  396.     for (i = 0; i < BOARD_MAP_SIZE; i++)
  397.     {
  398.         if (!board.tile_map[i].value)
  399.         {
  400.             board.empty_index[board.empty_count] = i;
  401.             board.empty_count++;
  402.         }
  403.     }
  404. }
  405.  
  406. void board_to_tempboard(tile* temp[])
  407. {
  408.     __u16 ind = 0;
  409.     for (ind = 0; ind < BOARD_MAP_SIZE; ind++)
  410.     {
  411.         tile* bt = &board.tile_map[ind];
  412.         if (bt->value)
  413.         {
  414.             temp[ind] = bt;
  415.         }
  416.     }
  417. }
  418.  
  419. void board_from_tempboard(tile *temp[], __u8 forward)
  420. {
  421.     __u16 ind = 0;
  422.     if (forward)
  423.     {
  424.         for (ind = 0; ind < BOARD_MAP_SIZE; ind++)
  425.         {
  426.             tile* bt = &board.tile_map[ind];
  427.             tile* tt = temp[ind];
  428.             if (tt)
  429.             {
  430.                 *bt = *tt;
  431.                 bt->transition = position2cell(board_position(ind));
  432.             }
  433.             else
  434.             {
  435.                 *bt = null_tile;
  436.             }
  437.         }
  438.     }
  439.     else
  440.     {
  441.         ind = BOARD_MAP_SIZE;
  442.         while (ind--)
  443.         {
  444.             tile* bt = &board.tile_map[ind];
  445.             tile* tt = temp[ind];
  446.             if (tt)
  447.             {
  448.                 *bt = *tt;
  449.                 bt->transition = position2cell(board_position(ind));
  450.             }
  451.             else
  452.             {
  453.                 *bt = null_tile;
  454.             }
  455.         }
  456.     }
  457. }
  458.  
  459. void tempboard_move_tile(tile* temp[], __u16 from, __u16 to)
  460. {
  461.     temp[to] = temp[from];
  462.     temp[to]->animate = true;
  463.     temp[from] = 0;
  464. }
  465.  
  466. void tempboard_merge_tile(tile* temp[], __u16 from, __u16 to)
  467. {
  468.     temp[from]->merged = true;
  469.     temp[from]->merged_rect = temp[to]->cell;
  470.     tempboard_move_tile(temp,from,to);
  471. }
  472.  
  473. __u32 random_u32(__u32 max)
  474. {
  475.     return ((rand() * 1.0) / RAND_MAX) * max;
  476. }
  477.