feat(game): implement authoritative movement and visibility core
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
idf_component_register(
|
||||
SRCS "main.c"
|
||||
REQUIRES esp_event esp_netif esp_timer heap maze32_config maze32_maze maze32_network maze32_platform maze32_web
|
||||
REQUIRES esp_event esp_netif esp_timer heap maze32_config maze32_game maze32_maze maze32_network maze32_platform maze32_web
|
||||
)
|
||||
|
||||
+111
@@ -14,6 +14,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "maze32_config_store.h"
|
||||
#include "maze32_game.h"
|
||||
#include "maze32_health.h"
|
||||
#include "maze32_maze.h"
|
||||
#include "maze32_network.h"
|
||||
@@ -25,6 +26,109 @@ static httpd_handle_t web_server;
|
||||
static maze32_network_t network;
|
||||
static maze32_gateway_t gateway;
|
||||
|
||||
#ifdef MAZE32_MILESTONE_006_DEVICE_TEST
|
||||
static maze32_maze_t game_test_maze;
|
||||
static maze32_maze_workspace_t game_test_workspace;
|
||||
static maze32_game_t device_test_game;
|
||||
static maze32_view_t device_test_view;
|
||||
static char device_test_payload[MAZE32_GAME_VIEW_CHUNK_BYTES];
|
||||
|
||||
static maze32_game_direction_t first_open_direction(const maze32_maze_t* maze, maze32_cell_t cell) {
|
||||
static const maze32_game_direction_t DIRECTIONS[] = {
|
||||
MAZE32_GAME_DIRECTION_NORTH,
|
||||
MAZE32_GAME_DIRECTION_EAST,
|
||||
MAZE32_GAME_DIRECTION_SOUTH,
|
||||
MAZE32_GAME_DIRECTION_WEST,
|
||||
};
|
||||
static const maze32_passage_t PASSAGES[] = {
|
||||
MAZE32_PASSAGE_NORTH,
|
||||
MAZE32_PASSAGE_EAST,
|
||||
MAZE32_PASSAGE_SOUTH,
|
||||
MAZE32_PASSAGE_WEST,
|
||||
};
|
||||
for (size_t index = 0U; index < sizeof(DIRECTIONS) / sizeof(DIRECTIONS[0]); ++index) {
|
||||
if (maze32_maze_has_passage(maze, cell, PASSAGES[index])) {
|
||||
return DIRECTIONS[index];
|
||||
}
|
||||
}
|
||||
return (maze32_game_direction_t)UINT8_MAX;
|
||||
}
|
||||
|
||||
static esp_err_t run_game_device_test(void) {
|
||||
maze32_maze_config_t maze_config = maze32_maze_default_config();
|
||||
maze32_maze_report_t maze_report;
|
||||
if (maze32_maze_generate(&game_test_maze, &game_test_workspace, &maze_config,
|
||||
UINT32_C(0x5a320006), &maze_report) != MAZE32_MAZE_OK) {
|
||||
ESP_LOGE(TAG, "M006 physical game test could not generate its maze");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
maze32_game_config_t game_config = maze32_game_default_config();
|
||||
size_t free_before = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int64_t started_us = esp_timer_get_time();
|
||||
if (maze32_game_init(&device_test_game, &game_test_maze, &game_config) !=
|
||||
MAZE32_GAME_RESULT_ACCEPTED) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
maze32_game_set_phase(&device_test_game, MAZE32_GAME_PHASE_ACTIVE);
|
||||
maze32_game_direction_t direction =
|
||||
first_open_direction(&game_test_maze, device_test_game.players[0].position);
|
||||
uint32_t command_sequence = 0U;
|
||||
if (direction > MAZE32_GAME_DIRECTION_WEST ||
|
||||
maze32_game_enqueue_move(&device_test_game, MAZE32_GAME_ROLE_PLAYER_ONE, direction, 0U,
|
||||
&command_sequence) != MAZE32_GAME_RESULT_ACCEPTED) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
maze32_game_command_result_t command_result = maze32_game_process_next(&device_test_game);
|
||||
if (command_result.result != MAZE32_GAME_RESULT_ACCEPTED ||
|
||||
command_result.state_sequence != 1U ||
|
||||
maze32_game_project_view(&device_test_game, MAZE32_GAME_ROLE_PLAYER_ONE, 3U,
|
||||
&device_test_view) != MAZE32_GAME_RESULT_ACCEPTED) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
uint16_t player_cells = device_test_view.cell_count;
|
||||
uint8_t player_objects = device_test_view.object_count;
|
||||
size_t player_chunks = maze32_game_view_chunk_count(&device_test_view);
|
||||
size_t payload_bytes = 0U;
|
||||
if (maze32_game_serialize_view_chunk(&device_test_view, 0U, device_test_payload,
|
||||
sizeof(device_test_payload),
|
||||
&payload_bytes) != MAZE32_GAME_RESULT_ACCEPTED) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (maze32_game_project_view(&device_test_game, MAZE32_GAME_ROLE_OBSERVER, 0U,
|
||||
&device_test_view) != MAZE32_GAME_RESULT_ACCEPTED) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
uint64_t elapsed_us = (uint64_t)(esp_timer_get_time() - started_us);
|
||||
size_t free_after = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t fixed_bytes =
|
||||
sizeof(device_test_game) + sizeof(device_test_view) + sizeof(device_test_payload);
|
||||
ESP_LOGI(TAG, "M006 command: command=%" PRIu32 ", state=%" PRIu32 ", result=%s, position=%u,%u",
|
||||
command_sequence, command_result.state_sequence,
|
||||
maze32_game_result_name(command_result.result), device_test_game.players[0].position.x,
|
||||
device_test_game.players[0].position.y);
|
||||
ESP_LOGI(TAG,
|
||||
"M006 views: player_cells=%u, player_objects=%u, player_chunks=%u, "
|
||||
"observer_cells=%u, observer_objects=%u, observer_chunks=%u, first_chunk=%u bytes",
|
||||
player_cells, player_objects, (unsigned int)player_chunks, device_test_view.cell_count,
|
||||
device_test_view.object_count,
|
||||
(unsigned int)maze32_game_view_chunk_count(&device_test_view),
|
||||
(unsigned int)payload_bytes);
|
||||
ESP_LOGI(TAG, "M006 budget: fixed=%u/%u bytes, runtime=%" PRIu64 "/%u ms, heap_delta=%d",
|
||||
(unsigned int)fixed_bytes, (unsigned int)MAZE32_GAME_RAM_BUDGET_BYTES,
|
||||
elapsed_us / 1000U, (unsigned int)MAZE32_GAME_RUNTIME_BUDGET_MS,
|
||||
(int)(free_before - free_after));
|
||||
if (device_test_view.cell_count != MAZE32_MAZE_DEFAULT_WIDTH * MAZE32_MAZE_DEFAULT_HEIGHT ||
|
||||
fixed_bytes > MAZE32_GAME_RAM_BUDGET_BYTES ||
|
||||
elapsed_us > (uint64_t)MAZE32_GAME_RUNTIME_BUDGET_MS * 1000U || free_before != free_after) {
|
||||
ESP_LOGE(TAG, "M006 physical game test failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "M006 physical game test: PASS");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAZE32_MILESTONE_005_DEVICE_TEST
|
||||
static maze32_maze_t device_test_maze;
|
||||
static maze32_maze_workspace_t device_test_workspace;
|
||||
@@ -159,6 +263,13 @@ void app_main(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MAZE32_MILESTONE_006_DEVICE_TEST
|
||||
if (run_game_device_test() != ESP_OK) {
|
||||
maze32_health_set(&health, MAZE32_HEALTH_ERROR, (int)ESP_FAIL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1500));
|
||||
ESP_LOGI(TAG, "maze32 firmware version %s starting", application->version);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user