diff --git a/src/game_logic.c b/src/game_logic.c index aa19674..22867b5 100644 --- a/src/game_logic.c +++ b/src/game_logic.c @@ -1,149 +1,149 @@ -#include "game_logic.h" - -#include "utility.h" - -#include - -static uint8_t game_grid_alpha[GRID_SIDE * GRID_SIDE]; -static uint8_t game_grid_beta[GRID_SIDE * GRID_SIDE]; - -static uint8_t *front_grid = game_grid_alpha; -static uint8_t *back_grid = game_grid_beta; - -void swap_grids(void); - -void swap_grids(void) { - uint8_t *temp = front_grid; - - front_grid = back_grid; - back_grid = temp; -} - -uint8_t reset_game(void) { - uint8_t score = 0; - - // Clear the back and front grid - memset(back_grid, 0, GRID_SIDE * GRID_SIDE); - memset(front_grid, 0, GRID_SIDE * GRID_SIDE); - - // Then add two random tiles - score += (1 << front_grid[add_random_tile() - 1]); - score += (1 << front_grid[add_random_tile() - 1]); - - return score; -} - -uint8_t *get_front_grid(void) { - return front_grid; -} - -uint8_t add_random_tile(void) { - uint16_t rand = lfsr_update(); - uint8_t tile_val = (rand & 0x000F) > 0x0D ? 2 : 1; // ~90% chance of a tile of type 1 (a "2"), 10% of a type 2 (a "4") - - uint8_t free_tiles = 0; - uint8_t chosen_tile; - - for (uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) { - if (!front_grid[offset]) free_tiles++; - } - - if(!free_tiles) return 0; - chosen_tile = (rand >> 8) % free_tiles; - - for (uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) { - if (!front_grid[offset] && !(chosen_tile--)) { - front_grid[offset] = tile_val; - return offset + 1; - } - } - - return 0; // Return 0 if we were not able to place the tile, else we return (offset + 1) to indicate where the tile was placed -} - -int8_t step_game(uint8_t dir) { - int8_t done = 0; - uint8_t start_offset; - int8_t column_step; - int8_t row_step; - - /* - * UP: scans TOP to BOTTOM, RIGHT to LEFT - * DOWN: scans BOTTOM to TOP, RIGHT to LEFT - * LEFT: scans LEFT to RIGHT, TOP to BOTTOM - * RIGHT: scans RIGHT to LEFT, TOP to BOTTOM - */ - - switch(dir) { - case GAME_STEP_UP: - start_offset = GRID_SIDE - 1; - column_step = GRID_SIDE; - row_step = -1; - break; - case GAME_STEP_DOWN: - start_offset = (GRID_SIDE * GRID_SIDE) - 1; - column_step = -GRID_SIDE; - row_step = -1; - break; - case GAME_STEP_LEFT: - start_offset = 0; - column_step = 1; - row_step = GRID_SIDE; - break; - case GAME_STEP_RIGHT: - start_offset = GRID_SIDE - 1; - column_step = -1; - row_step = GRID_SIDE; - break; - }; - - // Clear the back grid - memset(back_grid, 0, GRID_SIDE * GRID_SIDE); - - for (uint8_t row = 0; row < GRID_SIDE; row++) { - for(uint8_t col = 0; col < GRID_SIDE; col++) { - uint8_t current_offset = start_offset + (col * column_step) + (row * row_step); - uint8_t sub_col; - - // Search for the first non-zero value in the front grid and copy it in the current place of the back grid (zeroing it in the front) - for(sub_col = col; sub_col < GRID_SIDE; sub_col++) { - uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step); - if(front_grid[sub_col_offset]) { - back_grid[current_offset] = front_grid[sub_col_offset]; - front_grid[sub_col_offset] = 0; - - break; - } - } - - // The value is still 0, we found nothing. On to the next row! - if (!back_grid[current_offset]) break; - - // Now search if there is an identical value following this one, so we can merge them - for(; sub_col < GRID_SIDE; sub_col++) { - uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step); - if(front_grid[sub_col_offset] == back_grid[current_offset]) { - back_grid[current_offset]++; // Merge them (by increasing the value of the current square and removing the merged one) - front_grid[sub_col_offset] = 0; - - done += back_grid[current_offset] == 11 ? 1 : 0; - break; - } else if (front_grid[sub_col_offset]) break; - } - } - } - - swap_grids(); - - return done; -} - -uint16_t calculate_score(void) { - uint16_t score = 0; - - for(uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) { - if(front_grid[offset]) score += ((uint16_t)1 << front_grid[offset]); - } - - return score; -} +#include "game_logic.h" + +#include "utility.h" + +#include + +static uint8_t game_grid_alpha[GRID_SIDE * GRID_SIDE]; +static uint8_t game_grid_beta[GRID_SIDE * GRID_SIDE]; + +static uint8_t *front_grid = game_grid_alpha; +static uint8_t *back_grid = game_grid_beta; + +void swap_grids(void); + +void swap_grids(void) { + uint8_t *temp = front_grid; + + front_grid = back_grid; + back_grid = temp; +} + +uint8_t reset_game(void) { + uint8_t score = 0; + + // Clear the back and front grid + memset(back_grid, 0, GRID_SIDE * GRID_SIDE); + memset(front_grid, 0, GRID_SIDE * GRID_SIDE); + + // Then add two random tiles + score += (1 << front_grid[add_random_tile() - 1]); + score += (1 << front_grid[add_random_tile() - 1]); + + return score; +} + +uint8_t *get_front_grid(void) { + return front_grid; +} + +uint8_t add_random_tile(void) { + uint16_t rand = lfsr_update(); + uint8_t tile_val = (rand & 0x000F) > 0x0D ? 2 : 1; // ~90% chance of a tile of type 1 (a "2"), 10% of a type 2 (a "4") + + uint8_t free_tiles = 0; + uint8_t chosen_tile; + + for (int8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) { + if (!front_grid[offset]) free_tiles++; + } + + if(!free_tiles) return 0; + chosen_tile = (rand >> 8) % free_tiles; + + for (int8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) { + if (!front_grid[offset] && !(chosen_tile--)) { + front_grid[offset] = tile_val; + return offset + 1; + } + } + + return 0; // Return 0 if we were not able to place the tile, else we return (offset + 1) to indicate where the tile was placed +} + +int8_t step_game(uint8_t dir) { + int8_t done = 0; + int8_t start_offset; + int8_t column_step; + int8_t row_step; + + /* + * UP: scans TOP to BOTTOM, RIGHT to LEFT + * DOWN: scans BOTTOM to TOP, RIGHT to LEFT + * LEFT: scans LEFT to RIGHT, TOP to BOTTOM + * RIGHT: scans RIGHT to LEFT, TOP to BOTTOM + */ + + switch(dir) { + case GAME_STEP_UP: + start_offset = GRID_SIDE - 1; + column_step = GRID_SIDE; + row_step = -1; + break; + case GAME_STEP_DOWN: + start_offset = (GRID_SIDE * GRID_SIDE) - 1; + column_step = -GRID_SIDE; + row_step = -1; + break; + case GAME_STEP_LEFT: + start_offset = 0; + column_step = 1; + row_step = GRID_SIDE; + break; + case GAME_STEP_RIGHT: + start_offset = GRID_SIDE - 1; + column_step = -1; + row_step = GRID_SIDE; + break; + }; + + // Clear the back grid + memset(back_grid, 0, GRID_SIDE * GRID_SIDE); + + for (int8_t row = 0; row < GRID_SIDE; row++) { + for(int8_t col = 0; col < GRID_SIDE; col++) { + uint8_t current_offset = start_offset + (col * column_step) + (row * row_step); + uint8_t sub_col; + + // Search for the first non-zero value in the front grid and copy it in the current place of the back grid (zeroing it in the front) + for(sub_col = col; sub_col < GRID_SIDE; sub_col++) { + uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step); + if(front_grid[sub_col_offset]) { + back_grid[current_offset] = front_grid[sub_col_offset]; + front_grid[sub_col_offset] = 0; + + break; + } + } + + // The value is still 0, we found nothing. On to the next row! + if (!back_grid[current_offset]) break; + + // Now search if there is an identical value following this one, so we can merge them + for(; sub_col < GRID_SIDE; sub_col++) { + uint8_t sub_col_offset = start_offset + (sub_col * column_step) + (row * row_step); + if(front_grid[sub_col_offset] == back_grid[current_offset]) { + back_grid[current_offset]++; // Merge them (by increasing the value of the current square and removing the merged one) + front_grid[sub_col_offset] = 0; + + done += back_grid[current_offset] == 11 ? 1 : 0; + break; + } else if (front_grid[sub_col_offset]) break; + } + } + } + + swap_grids(); + + return done; +} + +uint16_t calculate_score(void) { + uint16_t score = 0; + + for(uint8_t offset = 0; offset < GRID_SIDE * GRID_SIDE; offset++) { + if(front_grid[offset]) score += ((uint16_t)1 << front_grid[offset]); + } + + return score; +}