In the c_step function, the function place_tile_at_random_cell is called after move, but before update_stats_and_get_heuristic_rewards. This is a problem because place_tile_at_random_cell relies on game->empty_count, which is not updated after a move merges some tiles, only in update_stats_and_get_heuristic_rewards.
|
void c_step(Game* game) { |
|
float reward = 0.0f; |
|
float score_add = 0.0f; |
|
unsigned char prev_max_tile = game->max_tile; |
|
bool did_move = move(game, game->actions[0] + 1, &reward, &score_add); |
|
game->tick++; |
|
|
|
if (did_move) { |
|
game->moves_made++; |
|
place_tile_at_random_cell(game, get_new_tile()); |
|
game->score += score_add; |
|
|
|
// Add heuristic rewards/penalties and update grid stats |
|
reward += update_stats_and_get_heuristic_rewards(game); |
|
reward *= game->reward_scaler; |
|
static inline void place_tile_at_random_cell(Game* game, unsigned char tile) { |
|
if (game->empty_count == 0) return; |
|
|
|
int target = rand() % game->empty_count; |
|
int pos = 0; |
|
for (int i = 0; i < SIZE; i++) { |
|
for (int j = 0; j < SIZE; j++) { |
|
if (game->grid[i][j] == EMPTY) { |
|
if (pos == target) { |
|
game->grid[i][j] = tile; |
|
game->empty_count--; |
|
return; |
|
} |
|
pos++; |
|
} |
|
} |
|
} |
|
} |
In update_stats_and_get_heuristic_rewards:
|
game->empty_count = empty_count; |
The consequences are:
- When the grid was full before a valid move, the move will necessarily have merged some tiles, but
place_tile_at_random_cell still sees that game->empty_count is 0 and returns immediately. Therefore the game does not spawn a tile for that move.
- When the grid was not full before a move merged more tiles,
place_tile_at_random_cell will see a smaller value of game->empty_count than the actual empty count, and thus will never spawn a tile in the last empty cell(s).
In the
c_stepfunction, the functionplace_tile_at_random_cellis called aftermove, but beforeupdate_stats_and_get_heuristic_rewards. This is a problem becauseplace_tile_at_random_cellrelies ongame->empty_count, which is not updated after a move merges some tiles, only inupdate_stats_and_get_heuristic_rewards.PufferLib/pufferlib/ocean/g2048/g2048.h
Lines 558 to 572 in 5cbaf88
PufferLib/pufferlib/ocean/g2048/g2048.h
Lines 204 to 221 in 5cbaf88
In
update_stats_and_get_heuristic_rewards:PufferLib/pufferlib/ocean/g2048/g2048.h
Line 481 in 5cbaf88
The consequences are:
place_tile_at_random_cellstill sees thatgame->empty_countis 0 and returns immediately. Therefore the game does not spawn a tile for that move.place_tile_at_random_cellwill see a smaller value ofgame->empty_countthan the actual empty count, and thus will never spawn a tile in the last empty cell(s).