Subversion Repositories Kolibri OS

Rev

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