mirror of
https://codeberg.org/hkzlab/TK2048.git
synced 2025-12-25 18:12:15 +11:00
Use signed arithmetics for game logic
This commit is contained in:
parent
5348adcd72
commit
f5cfc0f5da
1 changed files with 149 additions and 149 deletions
298
src/game_logic.c
298
src/game_logic.c
|
|
@ -1,149 +1,149 @@
|
|||
#include "game_logic.h"
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
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 <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue