Intial commit

This commit is contained in:
2026-08-27 22:16:23 +03:00
commit a5963c9ed6
12 changed files with 3178 additions and 0 deletions
+1929
View File
File diff suppressed because it is too large Load Diff
+240
View File
@@ -0,0 +1,240 @@
# AGENTS.md
## Purpose
This repository contains firmware and a web application for an ESP32-C6 Mini built with Visual Studio Code and PlatformIO.
These instructions are intended for Codex and other coding agents working in this repository. Prefer small, reviewable changes and keep the firmware suitable for a resource-constrained embedded device.
## Sources and instruction scope
- Treat every file under `sources/` as read-only reference material.
- Do not edit, rename, move, or delete files under `sources/`.
- Files under `sources/` may be replaced when the ChatGPT project is synchronized.
- A more deeply nested `AGENTS.md`, if present, takes precedence for files in its directory tree.
- Read `MVP.md` before making architectural or gameplay changes.
- Once present, treat `platformio.ini` as the source of truth for the PlatformIO environments, board identifier, framework, build flags, dependency versions, flash layout, and upload settings.
- Do not assume that every board sold as “ESP32-C6 Mini” has the same flash size, pinout, LED polarity, or PlatformIO board identifier.
## Expected project layout
Use the conventional PlatformIO layout unless the existing project deliberately uses another structure:
```text
.
├── platformio.ini # PlatformIO environments and dependencies
├── include/ # Public project headers
├── src/ # Firmware sources and main.cpp
├── lib/ # Project-specific reusable libraries
├── data/ # LittleFS web assets
├── test/ # PlatformIO unit tests
├── scripts/ # Build and validation helpers
├── MVP.md # Product and architecture requirements
└── AGENTS.md # Repository instructions
```
Do not edit generated content under `.pio/`. Do not commit build products, serial logs, local secrets, or editor-specific temporary files.
## Working method
Before editing:
1. Read the relevant requirements and existing implementation.
2. Inspect `platformio.ini` and use an existing environment instead of inventing one.
3. Search for repository conventions, existing abstractions, and tests.
4. Identify whether the change affects firmware, browser assets, the API contract, stored data, or hardware configuration.
While editing:
- Make the smallest coherent change that satisfies the request.
- Preserve unrelated user changes and avoid broad formatting rewrites.
- Keep hardware-specific values in configuration rather than scattering them through the code.
- Update documentation and tests when behavior or public interfaces change.
- Do not add a dependency when a small, clear implementation using the existing stack is sufficient.
- Pin third-party PlatformIO dependencies to known compatible versions in `platformio.ini`.
- Never patch dependency sources inside `.pio/libdeps`.
After editing:
1. Run the narrowest relevant tests.
2. Build every affected PlatformIO environment.
3. Check compiler output for new warnings, memory pressure, and image-size regressions.
4. Summarize what changed, what was verified, and anything that still requires physical hardware.
## PlatformIO commands
Use the repository's actual environment names. List environments or inspect `platformio.ini` before supplying `-e <environment>`.
Common non-destructive checks:
```sh
pio run
pio run -e <environment>
pio test
pio test -e <test-environment>
pio run -t size
```
Use project-provided formatting, linting, or validation scripts when available. Do not invent a formatting command without checking the repository configuration.
The following operations affect connected hardware and must only be performed when the user asks for them or clearly authorizes hardware interaction:
```sh
pio run -e <environment> -t upload
pio run -e <environment> -t uploadfs
pio device monitor
pio run -t erase
```
Treat flash erase as destructive. Confirm the target device and environment before uploading or erasing. Never leave a serial monitor running indefinitely.
## Firmware design rules
### Architecture
- Keep domain logic independent from Arduino callbacks and transport code where practical.
- Separate Wi-Fi, HTTP/WebSocket transport, session handling, persistence, device control, and application logic.
- Route all state-changing requests through a single validated application layer.
- Keep the ESP32 authoritative. Browser-side validation improves usability but must not enforce the only copy of a rule.
- Use explicit state machines for multi-step workflows rather than loosely related Boolean flags.
- Keep public headers small and avoid unnecessary global state.
### Memory and performance
- Prefer fixed-size arrays, fixed-width integer types, bounded buffers, and predictable ownership.
- Avoid unbounded `String` concatenation, repeated heap allocation, large temporary JSON documents, and unnecessary copies.
- Set explicit limits for sessions, WebSocket clients, request bodies, queue sizes, names, and messages.
- Parse all external input with bounds checks.
- Stream or serve files from LittleFS instead of embedding large duplicate assets in RAM.
- Measure rather than guess when changing task stacks, JSON capacity, filesystem partitions, or connection limits.
- Check final flash and RAM usage after meaningful changes.
### Timing and responsiveness
- Avoid long blocking calls and long `delay()` operations.
- Use `millis()`-based scheduling, timers, queues, or tasks for delayed work.
- Keep HTTP, WebSocket, timer, and interrupt callbacks short.
- Never perform filesystem writes, large serialization, or expensive game logic in an interrupt service routine.
- Ensure the main loop and network stack remain responsive under reconnects and multiple clients.
- Add timeouts to network and peripheral operations.
### Concurrency
- Document which task or callback owns mutable state.
- Protect state shared between callbacks or FreeRTOS tasks with an appropriate mutex, queue, or critical section.
- Do not hold locks while sending network data or performing slow I/O.
- Prefer taking a bounded snapshot before serializing state for clients.
- Make repeated requests idempotent where retries are expected.
### C++ conventions
- Follow the C++ standard and warning flags configured by the project.
- Use `enum class`, `constexpr`, `const`, fixed-width integers, and RAII where supported.
- Prefer clear value types and explicit ownership over raw heap allocation.
- Check return values from Wi-Fi, filesystem, JSON, and server operations.
- Avoid macros except for compile-time configuration, platform compatibility, or logging wrappers.
- Keep functions focused and name units in identifiers when values represent milliseconds, bytes, volts, or similar quantities.
- Do not enable exceptions or RTTI unless the project already uses and budgets for them.
### Logging and errors
- Use consistent log levels and concise messages.
- Never log Wi-Fi passwords, session tokens, private payloads, or other credentials.
- Avoid high-frequency logs in normal operation.
- Return stable machine-readable error codes from APIs and separate them from Russian user-facing messages.
- Fail safely: reject invalid commands without partially modifying application state.
## Wi-Fi and configuration
- The ESP32-C6 Mini operates as a station on the home Wi-Fi network unless requirements say otherwise.
- Keep SSIDs, passwords, tokens, certificates, and private endpoints out of tracked source files.
- Store local secrets in a gitignored file or inject them through build-time configuration.
- Provide a tracked example file with placeholder values when setup would otherwise be unclear.
- Never replace real credentials or erase device configuration unless explicitly requested.
- Reconnect with bounded exponential backoff; do not block the application indefinitely while Wi-Fi is unavailable.
- The application must handle a changing DHCP address. mDNS may be added as a convenience but must not be the only documented access method unless verified on the target network.
## Web server and browser application
- Store required HTML, CSS, and JavaScript locally in `data/` so the application does not depend on internet access or a CDN.
- Prefer framework-free browser code for small interfaces. Justify large client dependencies by a concrete requirement.
- Keep the HTTP API versionable and document changes to request and response schemas.
- Validate authentication token, role, current state, game ID, coordinates, lengths, and content type on the server.
- Generate role-specific responses. Never send hidden or privileged state and rely on CSS or JavaScript to conceal it.
- Escape user-provided text before rendering it in HTML.
- Use WebSocket for immediate updates and provide the HTTP polling fallback required by `MVP.md`.
- Implement reconnect backoff, heartbeat handling, state versioning, and full resynchronization after missed events.
- Avoid broadcasting one privileged payload to all clients; construct a safe view for each role.
- Set appropriate cache headers. Do not cache personalized API responses.
- Compress static assets during the build when supported, but keep the uncompressed sources maintainable.
- Design touch interactions for phones and tablets. Do not rely on hover or color alone.
## Filesystem and persistence
- Treat LittleFS layout and the flash partition table as part of the product configuration.
- Check mount failures and report them clearly; do not silently format a filesystem unless the product explicitly requires that behavior.
- Use atomic replace patterns for important persisted files where possible.
- Minimize flash writes and avoid writing frequently changing counters on every event.
- The MVP keeps active game state and statistics in RAM and resets them after reboot, as specified in `MVP.md`.
## Testing expectations
### Host or native tests
Keep pure application logic buildable without ESP32 hardware where practical. Unit-test at least:
- state transitions;
- bounds and malformed input;
- game or domain rules;
- random-generation invariants;
- serialization and role-specific data filtering;
- retry and idempotency behavior;
- bot or automation logic.
Use a deterministic random seed in tests and do not use the production seed as an assertion target.
### Device tests
Features involving Wi-Fi, LittleFS, WebSocket, timing, heap behavior, or peripherals require a final device check. When hardware is available, verify:
- cold boot and reconnect behavior;
- static asset loading from LittleFS;
- multiple simultaneous clients;
- WebSocket loss and HTTP fallback;
- repeated workflows without heap degradation;
- flash/RAM usage and watchdog stability;
- operation on the exact ESP32-C6 Mini variant.
Do not claim device verification when only a local build or host test was performed.
## Security and robustness
- Treat every HTTP, WebSocket, serial, and persisted value as untrusted input.
- Reject oversized, malformed, stale, unauthorized, and out-of-state requests.
- Use cryptographically strong random session tokens when the platform API provides suitable entropy.
- Do not put credentials in browser assets, logs, examples, tests, or error responses.
- Avoid undefined behavior, unchecked indexing, integer overflow, and unsafe string functions.
- Add rate or queue limits where one client could exhaust device memory or monopolize processing.
- A home network is not a security boundary. Document any deliberately simplified MVP security assumptions.
## Documentation
- Keep setup steps reproducible for a new developer using VS Code and PlatformIO.
- Document the exact board variant, USB/serial behavior, flash size, PlatformIO environment, filesystem upload step, and access URL once known.
- Update `MVP.md` only when product scope or agreed behavior changes.
- Update API documentation whenever routes, messages, events, error codes, or authorization rules change.
- Record hardware-only verification steps rather than implying they were automated.
## Definition of done
A change is complete when all applicable conditions are met:
- The requested behavior is implemented with no unrelated changes.
- Affected PlatformIO environments build successfully.
- Relevant automated tests pass.
- No new compiler warnings or exposed secrets are introduced.
- Input bounds, failure paths, reconnects, and role permissions are handled.
- Flash and RAM impact are acceptable for the target ESP32-C6 Mini.
- Web assets work without an external internet dependency.
- Documentation and examples reflect the new behavior.
- Any remaining physical-device checks are explicitly listed in the handoff.
+3
View File
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(battleship)
+286
View File
@@ -0,0 +1,286 @@
# ESP32 Battleship Implementation Plan
## Purpose of the initial milestones
Before implementing the complete game, experimentally verify that the specific ESP32-C6 Mini board:
- can be flashed and run reliably with the selected PlatformIO and Arduino stack;
- can connect to the home Wi-Fi network;
- can store and serve the web interface from LittleFS;
- can support HTTP, WebSocket, and HTTP polling fallback;
- has enough flash, RAM, and processing capacity for one game, two players, and up to eight spectators;
- can provide role-specific state without exposing hidden game data.
Full MVP implementation may begin only after Milestone 004 is completed with a documented **Go** decision.
## Codex execution rules
This file is an ordered execution queue for Codex.
1. Work on milestones strictly in numerical order.
2. In one task, execute only the first milestone whose status is `READY`.
3. Do not start the next milestone during the same task unless the user explicitly requests it.
4. A milestone may become `READY` only after all milestones listed under `Depends on` are `DONE`.
5. Before implementation, change the selected milestone status from `READY` to `IN PROGRESS`.
6. Do not mark a milestone `DONE` until every acceptance criterion has objective evidence.
7. If a criterion cannot be met, set the status to `BLOCKED` and record the reason, evidence, and proposed next action in that milestone's execution record.
8. If implementation changes the plan, preserve the intent and acceptance criteria of already completed milestones.
9. Add future milestones only at the end of this file. Do not insert or renumber milestones after work has started.
10. Never edit files under `sources/`; they are read-only reference material.
11. Never store Wi-Fi credentials or other secrets in tracked project files.
Allowed statuses:
- `BLOCKED` — work cannot proceed until a recorded issue is resolved;
- `READY` — all dependencies are complete and the milestone may be executed;
- `IN PROGRESS` — this is the milestone currently being executed;
- `DONE` — all acceptance criteria have passed and evidence is recorded.
At most one milestone may have the status `IN PROGRESS`.
## Execution record format
When completing or blocking a milestone, append an execution record inside that milestone using this format:
```text
Execution record
- Date:
- Board model and revision:
- Toolchain and library versions:
- Result: PASS | FAIL | BLOCKED
- Evidence:
- Measurements:
- Issues or deviations:
- Next action:
```
Evidence should include the exact test scenario, relevant logs, reset reasons, resource measurements, and paths to created project files. A statement such as “works in general” is not sufficient.
---
## Milestone 000 — Identify the board and lock the technical baseline
**Status:** `BLOCKED`
**Depends on:** none
### Objective
Remove the uncertainty hidden by the generic name “ESP32-C6 Mini” and establish a reproducible build configuration.
### Work
- Record the manufacturer, exact board model, and revision from the physical markings and authoritative documentation.
- Record the ESP32-C6 module variant, flash size, presence and size of PSRAM, USB connection type, and built-in LED.
- Locate the schematic or pinout and identify pins used by USB, UART, flash, and the built-in LED.
- Select the exact PlatformIO `board` identifier. If no exact profile exists, select the closest ESP32-C6 profile and explicitly configure flash and partition parameters.
- Pin the PlatformIO, Espressif 32 platform, and Arduino Core versions.
- Define an initial partition layout that provides space for both the application and LittleFS.
- Create a short board passport containing a photo of the markings, documentation links, and confirmed specifications.
### Deliverables
- A board passport in the project documentation.
- An initial `platformio.ini` with pinned versions.
- A documented memory map and selected partition layout.
### Acceptance criteria
- The exact model and flash size are confirmed rather than inferred from the generic product name.
- The build configuration does not depend on floating package versions.
- The partition layout includes both an application partition and LittleFS.
- Every unknown board parameter is either resolved or recorded as a specific risk to test in Milestone 001.
### Blocking conditions
- The flash size or a safe flashing configuration cannot be determined.
- The available toolchain has no usable ESP32-C6 support for this board.
### Completion action
If all criteria pass, set this milestone to `DONE`, append its execution record, and change Milestone 001 from `BLOCKED` to `READY`.
Execution record
- Date: 2026-08-27
- Board model and revision: Unknown; no physical markings or board photograph were supplied.
- Toolchain and library versions: PlatformIO Core 6.1.19; locally installed `platformio/espressif32` 7.0.1; ESP-IDF 6.0.1; Arduino Core not installed.
- Result: BLOCKED
- Evidence: `docs/BOARD_PASSPORT.md`; no `sources/` directory or board image exists; no `/dev/ttyACM*`, `/dev/ttyUSB*`, `/dev/serial/by-id`, or `/dev/serial/by-path` device is exposed; the local `esp32-c6-devkitm-1` profile declares 4 MB while `sdkconfig.esp32-c6-devkitm-1` declares 2 MB and a single-app partition table without LittleFS.
- Measurements: No hardware measurements possible. Repository metadata reports conflicting 4 MB and 2 MB flash configurations.
- Issues or deviations: Exact manufacturer/model/revision, module, flash, PSRAM, USB implementation, LED, and board pinout cannot be confirmed. A safe flash/partition configuration and pinned Arduino baseline therefore cannot be selected. No firmware or hardware configuration was changed.
- Next action: Supply clear photographs of both board sides and the matching manufacturer documentation, and expose the board for an `esptool.py flash_id` check. Then reconcile the flash size, select a LittleFS-capable partition CSV, pin the compatible PlatformIO platform and Arduino Core, and rerun Milestone 000. Milestone 001 remains `BLOCKED`.
---
## Milestone 001 — Prove build, flashing, and stable basic operation
**Status:** `BLOCKED`
**Depends on:** Milestone 000
### Objective
Prove that the configuration selected in Milestone 000 works reliably on the physical board.
### Work
- Create a minimal firmware project with serial logging and reports for chip information, flash size, reset reason, and available heap.
- Flash the board and test startup after a manual reset, a full power cycle, and several repeated flashing cycles.
- Test the built-in LED if present and confirm that its pin does not conflict with USB or flash operation.
- Add uptime and periodic free-heap reporting.
- Run the firmware continuously for at least two hours without Wi-Fi and record every reset reason.
### Required measurements
- Firmware size and flash usage.
- Free heap immediately after startup and minimum free heap during the run.
- Boot and reset reasons.
- Any errors, watchdog resets, or unexpected restarts.
### Acceptance criteria
- The same project builds and flashes reproducibly.
- The board starts correctly after reset and full power loss.
- The two-hour run completes without a hang, watchdog reset, or unexpected restart.
- Free heap does not show a persistent downward trend.
- The detected flash size matches the configuration established in Milestone 000.
### Failure path
- First verify the board profile, USB mode, flash frequency, and partition layout.
- If Arduino Core is unstable on this board, repeat only this bring-up test with ESP-IDF before rejecting the board.
### Completion action
If all criteria pass, set this milestone to `DONE`, append its execution record, and change Milestone 002 from `BLOCKED` to `READY`.
---
## Milestone 002 — Prove the Wi-Fi, LittleFS, and HTTP vertical slice
**Status:** `BLOCKED`
**Depends on:** Milestone 001
### Objective
Prove the MVP's basic delivery path: home Wi-Fi, LittleFS, and HTTP served directly by the ESP32.
### Work
- Connect the board to a predefined home Wi-Fi network in station mode.
- Keep Wi-Fi credentials in a local configuration file excluded from version control.
- Implement automatic reconnection after a temporary Wi-Fi outage without a manual reset.
- Mount LittleFS and upload test `index.html`, CSS, and JavaScript files.
- Implement `GET /`, static asset delivery, and `GET /api/health`.
- Return uptime, Wi-Fi state, RSSI, free heap, minimum free heap, and build version from `/api/health`, without exposing secrets.
- Open the page from at least one phone and one tablet or second client device on the same network.
- Verify MIME types, gzip delivery for static assets, and appropriate cache headers.
### Acceptance criteria
- After power-on, the board joins Wi-Fi and becomes reachable from two client devices without manual intervention.
- The page and all assets load locally without a CDN or internet access.
- After the router or Wi-Fi connection is interrupted and restored, the board becomes reachable again without reflashing or a user-triggered reset.
- `/api/health` remains responsive during repeated page reloads.
- A LittleFS mount failure is visible in the serial log and does not cause an endless reboot loop.
- Measured firmware, filesystem, and heap usage are recorded.
### Blocking conditions
- Wi-Fi or HTTP repeatedly hangs and cannot recover in software.
- The filesystem cannot hold the minimum interface while retaining safe space for firmware growth.
### Completion action
If all criteria pass, set this milestone to `DONE`, append its execution record, and change Milestone 003 from `BLOCKED` to `READY`.
---
## Milestone 003 — Prove real-time transport, fallback, and state isolation
**Status:** `BLOCKED`
**Depends on:** Milestone 002
### Objective
Prove that the selected server stack works on ESP32-C6 and validate WebSocket delivery, HTTP fallback, versioning, and role-specific state before implementing game logic.
### Work
- Select and pin an HTTP/WebSocket library version compatible with the pinned Arduino Core and ESP32-C6.
- Implement a test state containing a monotonically increasing `version`, public data, and simulated hidden data.
- Add WebSocket endpoint `/ws`, role-specific state snapshots, and `GET /api/state?version=N`.
- In the test page, retry WebSocket after 1, 2, 5, and 10 seconds and poll HTTP every 2 seconds while WebSocket is unavailable.
- Connect two player clients and at least two spectator clients simultaneously.
- Deliberately interrupt WebSocket, verify the transition to HTTP polling, and then restore WebSocket.
- Inspect player and spectator traffic to confirm that simulated hidden data is absent.
- Limit incoming message size and reject malformed JSON without crashing or leaking memory.
### Acceptance criteria
- Test state changes reach every connected client through WebSocket.
- While WebSocket is unavailable, clients receive current state through HTTP within approximately one polling interval.
- After WebSocket recovers, polling stops and each client receives the current `version` without losing state.
- Hidden data is absent from HTTP responses, WebSocket messages, and client-side source files.
- Malformed and oversized messages are rejected while the server remains responsive.
- A 30-minute run with four clients completes without hangs, restarts, or a persistent downward trend in free heap.
### Fallback path
If the asynchronous server library is unstable with the pinned Arduino Core, repeat only this vertical slice with ESP-IDF and `esp_http_server`. Keep the protocol and acceptance criteria unchanged.
### Completion action
If all criteria pass, set this milestone to `DONE`, append its execution record, and change Milestone 004 from `BLOCKED` to `READY`.
---
## Milestone 004 — Prove MVP capacity and make the Go/No-Go decision
**Status:** `BLOCKED`
**Depends on:** Milestone 003
### Objective
Test the expected worst-case MVP workload before investing in the complete game engine and user interface.
### Work
- Create a compact mock state for one game: two 10 × 10 boards, 20 ships, two player sessions, eight spectator sessions, statistics, and protocol metadata.
- Generate separate safe views for player 1, player 2, and spectators without keeping a complete JSON copy for every client at the same time.
- Connect two client devices and eight spectator connections. A local load script may simulate some spectator connections.
- Simulate a game start and at least 200 state changes with WebSocket broadcasts and HTTP polling from a subset of clients.
- Run at least 20 consecutive simulated games without rebooting the board.
- Record firmware and LittleFS sizes, current and minimum free heap, maximum JSON message size, state generation and delivery time, reconnection count, and reset reasons.
- Test recovery after Wi-Fi loss, client reconnections, and a sequence of malformed requests.
- Document a **Go**, **Go with constraints**, or **No-Go** decision.
### Resource budgets
Before running the capacity test, define numerical limits based on the board specifications and evidence from Milestones 000003 for:
- maximum firmware and static asset size;
- minimum acceptable free-heap reserve;
- maximum HTTP or WebSocket message size;
- maximum API response and update-delivery time;
- acceptable error and restart count.
Do not adjust a threshold after seeing the result unless the execution record contains an explicit justification.
### Acceptance criteria
- Two players and eight spectators simultaneously receive the state intended for their roles.
- No client receives hidden opponent cells before the simulated game ends.
- Twenty simulated games complete without a hang, watchdog reset, or manual restart.
- After the tests, measured flash and heap reserves remain sufficient for `GameEngine`, `FleetGenerator`, `BotPlayer`, and the complete interface.
- Minimum free heap does not show a persistent game-to-game decline.
- State delivery recovers after Wi-Fi and WebSocket interruptions without rebooting the board.
### Decision rules
- **Go:** all acceptance criteria pass with sufficient measured resource reserves. Full game-engine implementation may begin.
- **Go with constraints:** the MVP is feasible only after reducing a nonessential target such as the spectator limit or interface size. Update `MVP.md` explicitly before further implementation.
- **No-Go for the current stack:** the board works, but the Arduino/server stack is unstable. Evaluate the ESP-IDF fallback.
- **No-Go for the board:** the fallback stack also fails the stability or resource criteria. Select a different board before implementing the complete game.
### Completion action
Set this milestone to `DONE` only for a documented **Go** decision. For any other decision, set it to `BLOCKED` and record the required scope or platform decision. Append every future milestone after this section without renumbering Milestones 000004.
+70
View File
@@ -0,0 +1,70 @@
# Board passport
## Identification status
The target board has not been identified. No photograph of the physical
markings is available in the repository, no `sources/` directory is present,
and no serial device is exposed to the build environment. Consequently, the
manufacturer, exact board model and revision, module variant, flash size,
PSRAM, USB connection, built-in LED, and board-specific pinout cannot be
confirmed without guessing.
Required evidence to unblock Milestone 000:
- clear photographs of both sides of the board, including all PCB and module
markings;
- the manufacturer's product page, schematic, and pinout matching those
markings;
- the flash/module ordering code, or an `esptool.py flash_id` report from the
connected board.
## Current repository baseline (not hardware confirmation)
| Item | Observed value | Status |
|---|---|---|
| PlatformIO Core | 6.1.19 | Installed locally |
| PlatformIO platform | `platformio/espressif32` 7.0.1 | Installed locally; `platformio.ini` is not version-pinned |
| Framework | ESP-IDF 6.0.1 | Current project setting conflicts with the Arduino-first MVP baseline |
| Arduino Core | Not installed | Cannot be pinned and verified against this board yet |
| PlatformIO board | `esp32-c6-devkitm-1` | Unverified candidate, not evidence of the physical model |
| Board-profile flash size | 4 MB | Unverified; profile metadata only |
| Generated SDK flash size | 2 MB | Conflicts with the board profile |
| Generated partition table | Single application, no LittleFS | Does not meet Milestone 000 |
The current configuration is not a safe flashing baseline. It must not be used
to upload firmware until the physical flash size and board identity are
confirmed.
## Candidate reference only
If the physical markings prove that the board is an Espressif
ESP32-C6-DevKitM-1, the matching authoritative references are:
- [ESP32-C6-DevKitM-1 user guide](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitm-1/user_guide.html)
- [ESP32-C6-DevKitM-1 schematic](https://docs.espressif.com/projects/esp-dev-kits/en/latest/_static/esp32-c6-devkitm-1/schematics/esp32-c6-devkitm-1-schematics.pdf)
- [ESP32-C6-MINI-1 datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6-mini-1_mini-1u_datasheet_en.pdf)
For that board only, Espressif documents an ESP32-C6-MINI-1(U) module with
4 MB in-package SPI flash, no PSRAM, a USB-C connector connected through a
USB-to-UART bridge, UART0 on GPIO16/GPIO17, native USB D-/D+ on GPIO12/GPIO13,
and an addressable RGB LED on GPIO8. These values are deliberately not adopted
as the target specifications until the markings match.
## Memory map and partition status
No partition CSV has been selected because the physical flash capacity is
unknown. The eventual layout must reserve, at minimum, NVS, PHY initialization,
one application partition, and one LittleFS data partition, with offsets and
sizes validated against the confirmed flash capacity. Selecting a 4 MB layout
now could make flashing unsafe on a smaller device.
## Risks carried to the next action
- A generic “ESP32-C6 Mini” may not match Espressif's DevKitM-1 pinout, LED
polarity/type, USB bridge, or flash capacity.
- GPIO8, GPIO12, GPIO13, GPIO16, and GPIO17 must not be assigned from the
candidate documentation until the exact board is confirmed.
- Official `platformio/espressif32` 7.0.1 exposes the C6 DevKitM profile only
for ESP-IDF and its bundled Arduino Core 2.0.17 does not support ESP32-C6.
An exact Arduino-compatible PlatformIO platform/Core pairing must be chosen
and pinned after the board is identified, then proven by Milestone 001.
+535
View File
@@ -0,0 +1,535 @@
# MVP: «Морской бой» на ESP32-C6 Mini
## 1. Назначение
Создать первую рабочую версию игры «Морской бой», полностью обслуживаемую одной платой ESP32-C6 Mini. Контроллер подключается к домашней Wi-Fi-сети, раздаёт веб-интерфейс и хранит всю игровую логику и текущее состояние в оперативной памяти.
Играть можно с телефонов и планшетов в двух режимах:
1. игрок против игрока с двух разных устройств;
2. игрок против ESP32.
К активной партии могут подключаться зрители. Одновременно ESP32 обслуживает только одну партию.
## 2. Цели MVP
- Полностью провести партию от входа игроков до определения победителя.
- Поддержать режимы «игрок против игрока» и «игрок против ESP32».
- Обеспечить синхронное обновление интерфейсов через WebSocket.
- Использовать HTTP-опрос как автоматический резервный механизм при недоступности WebSocket.
- Не передавать игрокам и зрителям скрытое расположение неповреждённых кораблей соперника.
- Поддержать зрителей, повторную игру и статистику в пределах текущего запуска ESP32.
- Сделать русскоязычный адаптивный интерфейс прежде всего для телефонов и планшетов.
## 3. Что не входит в MVP
- Несколько одновременных игровых комнат.
- Игра через интернет без доступа к домашней сети.
- Регистрация, пароли и полноценные учётные записи.
- Сохранение партии и статистики после перезагрузки ESP32.
- Ручная расстановка кораблей.
- Чат, звук, таймер хода, рейтинги и история матчей.
- Отдельная точка доступа Wi-Fi, создаваемая ESP32.
- Гарантированная поддержка настольных компьютеров как целевой платформы.
## 4. Принятые правила
### 4.1. Поле и флот
- Размер поля: 10 × 10 клеток.
- Столбцы обозначаются буквами А–К без буквы Ё, строки — числами 1–10.
- Классический флот каждого участника:
- 1 корабль длиной 4 клетки;
- 2 корабля длиной 3 клетки;
- 3 корабля длиной 2 клетки;
- 4 корабля длиной 1 клетку.
- Корабли располагаются только горизонтально или вертикально.
- Корабли не могут соприкасаться ни сторонами, ни углами.
- Расстановка создаётся сервером автоматически и случайно перед каждой партией.
### 4.2. Ходы
- Первый ход случайно назначается сервером после начала партии.
- Игрок выбирает одну ещё не обстрелянную клетку поля соперника.
- При попадании игрок сохраняет ход и стреляет снова.
- При промахе ход переходит сопернику.
- Потопленным считается корабль, у которого поражены все клетки.
- После потопления сервер автоматически отмечает окружающие корабль клетки как гарантированные промахи.
- Побеждает участник, первым уничтоживший все 10 кораблей соперника.
- Повторный выстрел по уже обработанной клетке отклоняется сервером и не меняет ход.
Эти правила фиксируются для MVP и должны одинаково применяться к человеку и встроенному сопернику.
## 5. Роли
### Игрок 1
- Вводит отображаемое имя.
- Выбирает режим игры.
- Запускает партию, когда второй участник готов или выбран режим против ESP32.
- Видит полностью своё поле и только результаты выстрелов на поле соперника.
### Игрок 2
- Доступен только в режиме «игрок против игрока».
- Вводит отображаемое имя и занимает свободное место второго игрока.
- Имеет тот же объём игровой информации, что и первый игрок.
### Зритель
- Вводит отображаемое имя и подключается без права выполнять игровые действия.
- Видит имена игроков, текущий ход, статистику и результаты уже выполненных выстрелов на обоих полях.
- Не видит неповреждённые корабли ни одного игрока во время партии.
- После завершения партии видит полностью раскрытые поля.
### ESP32-соперник
- Отображается под именем «ESP32».
- Ходит автоматически после небольшой задержки интерфейса, например 500–900 мс.
- Использует серверную стратегию и не раскрывает своё поле клиенту.
## 6. Идентификация и сессии
- При первом открытии пользователь вводит имя длиной 1–20 символов.
- Сервер очищает имя от управляющих символов и HTML-разметки.
- После входа сервер выдаёт случайный непрозрачный `sessionToken` и назначает роль.
- Браузер хранит токен и имя в `localStorage`.
- При кратковременной потере связи пользователь может вернуться в прежнюю роль по токену, пока ESP32 не перезагружена и место не освобождено.
- Одинаковые отображаемые имена допустимы: сервер различает клиентов по токену.
- Если оба игровых места заняты, новый пользователь может подключиться только зрителем.
- Рекомендуемый лимит MVP: до 2 игроков и 8 одновременно подключённых зрителей. Значение должно быть конфигурируемым.
- После перезагрузки ESP32 все токены, партия и статистика сбрасываются.
Полноценная авторизация не требуется: приложение предназначено для доверенной домашней сети. Токен нужен для сохранения роли и предотвращения случайной отправки хода чужим браузером.
## 7. Пользовательские сценарии
### 7.1. Игрок против игрока
1. Первый пользователь открывает адрес ESP32, вводит имя и становится игроком 1.
2. Он выбирает режим «Два игрока».
3. Второй пользователь открывает тот же адрес, вводит имя и занимает место игрока 2.
4. Сервер сообщает обоим игрокам, что партия готова к запуску.
5. Игрок 1 нажимает «Начать игру».
6. Сервер автоматически и независимо расставляет оба флота, выбирает первого игрока и рассылает разрешённое состояние всем клиентам.
7. Игроки по очереди стреляют до победы одного из них.
8. На экране результата показываются победитель, итоговая статистика и кнопка «Сыграть ещё».
### 7.2. Игрок против ESP32
1. Пользователь входит как игрок 1 и выбирает режим «Против ESP32».
2. Место второго участника автоматически занимает ESP32.
3. Игрок запускает партию.
4. Сервер расставляет оба флота и выбирает первого участника.
5. Во время хода ESP32 сервер сам выполняет один или несколько выстрелов с учётом правила продолжения хода после попадания.
6. После завершения доступна повторная игра.
### 7.3. Зритель
1. Пользователь выбирает «Наблюдать» или автоматически получает роль зрителя, если игровые места заняты.
2. Сервер отправляет ему публичное представление текущей партии.
3. Зритель получает обновления в реальном времени, но сервер отклоняет любые команды выстрела, старта или повторной игры.
### 7.4. Повторная игра
- После завершения любой игрок может предложить повторную игру.
- В режиме двух игроков новый матч начинается после подтверждения обоих игроков.
- В режиме против ESP32 достаточно подтверждения человека.
- Для нового матча сервер создаёт новые случайные расстановки и заново выбирает первого участника.
- Имена, роли и накопленная статистика текущего запуска сохраняются.
## 8. Состояния игры
```text
LOBBY -> PREPARING -> IN_PROGRESS -> FINISHED -> REMATCH_WAIT
^ |
+------------------------------------------------+
```
- `LOBBY`: выбор режима и ожидание участников.
- `PREPARING`: генерация и проверка расстановок.
- `IN_PROGRESS`: активная партия.
- `FINISHED`: победитель определён, поля раскрыты.
- `REMATCH_WAIT`: ожидание подтверждений повторной игры.
Каждое изменение состояния увеличивает монотонный номер `version`. Клиенты используют его для обнаружения пропущенных событий и резервного HTTP-опроса.
## 9. Интерфейс
### 9.1. Экраны
1. **Подключение** — имя, кнопки «Играть» и «Наблюдать», сообщение о доступности мест.
2. **Лобби** — участники, выбор режима игроком 1, состояние готовности и запуск.
3. **Игра** — собственное поле, поле выстрелов, имя текущего игрока, статус последнего выстрела и краткая статистика.
4. **Наблюдение** — два публичных поля и ход партии без элементов управления.
5. **Результат** — победитель, раскрытые поля, статистика матча и повторная игра.
### 9.2. Адаптивность
- На телефоне поля показываются по одному с переключателем «Моё поле / Поле соперника».
- На планшете при достаточной ширине поля показываются рядом.
- Размер игрового поля подстраивается под ширину экрана, клетки остаются квадратными.
- Основные кнопки имеют крупную сенсорную область.
- Нельзя полагаться только на цвет: попадание, промах и корабль дополнительно различаются символом или формой.
- Перед отправкой выстрела выбранная клетка визуально подтверждается. Для уменьшения ошибочных касаний допустим режим «выбрать клетку → нажать “Огонь”».
- Интерфейс и все сообщения — только на русском языке.
### 9.3. Обозначения клеток
- вода — пустая синяя клетка;
- собственный корабль — контрастная заливка;
- промах — точка;
- попадание — крест;
- потопленный корабль — кресты с отдельным оформлением контура;
- выбранная цель — заметная рамка до подтверждения выстрела.
## 10. Предлагаемая техническая реализация
### 10.1. Базовый стек
- **Среда:** Visual Studio Code + PlatformIO.
- **Целевая плата:** ESP32-C6 Mini.
- **Платформа:** Espressif 32. Точный идентификатор `board` в `platformio.ini` выбирается по производителю и маркировке конкретной ESP32-C6 Mini; если готового описания платы нет, используется совместимая конфигурация ESP32-C6 с явно заданными параметрами flash и разделов памяти.
- **Фреймворк:** Arduino для ESP32 как наиболее быстрый путь к MVP в PlatformIO.
- **Сеть:** штатный `WiFi` в режиме клиента домашней сети.
- **Файловая система:** LittleFS для HTML, CSS и JavaScript.
- **HTTP и WebSocket:** асинхронный веб-сервер с поддержкой ESP32-C6; конкретную совместимую библиотеку следует закрепить по версии в `platformio.ini`.
- **JSON:** ArduinoJson либо небольшой собственный сериализатор с контролируемыми буферами.
- **Фронтенд:** нативные HTML, CSS и JavaScript без обязательного фреймворка.
Vanilla JavaScript рекомендуется для MVP, потому что игровому интерфейсу не нужен крупный UI-фреймворк. Это уменьшает размер файлов, потребление памяти и зависимость от доступа в интернет. Все необходимые ресурсы должны храниться на ESP32; CDN не должен быть обязательным для запуска игры.
Если выбранная асинхронная библиотека окажется нестабильной на конкретной версии Arduino Core для ESP32-C6, запасной вариант — PlatformIO с ESP-IDF и встроенным `esp_http_server`, который поддерживает WebSocket. Игровая модель и протокол при этом останутся теми же.
### 10.2. Компоненты прошивки
- `WiFiManager` — подключение к заранее заданной домашней сети и отображение состояния связи.
- `WebServer` — статические файлы, HTTP API и WebSocket.
- `SessionManager` — токены, имена, роли, подключения и переподключения.
- `GameEngine` — правила, очередь хода, выстрелы, победа и повторная игра.
- `FleetGenerator` — случайная корректная расстановка флота.
- `BotPlayer` — выбор цели ESP32.
- `StatePresenter` — формирует отдельное безопасное представление состояния для каждого игрока и зрителей.
- `Statistics` — статистика матча и накопительные показатели до перезагрузки.
Сетевая обработка не должна напрямую изменять массивы поля. Любая команда сначала проходит проверку сессии, роли, фазы, номера партии и очереди хода, после чего передаётся в `GameEngine`.
## 11. Модель данных
Пример внутренних структур на уровне концепции:
```cpp
enum class Cell : uint8_t { Water, Ship, Miss, Hit };
enum class Phase : uint8_t { Lobby, Preparing, InProgress, Finished, RematchWait };
enum class Mode : uint8_t { HumanVsHuman, HumanVsBot };
enum class Role : uint8_t { Player1, Player2, Spectator };
struct Ship {
uint8_t x;
uint8_t y;
uint8_t length;
bool horizontal;
uint8_t hits;
};
struct Board {
Cell cells[10][10];
Ship ships[10];
uint8_t shipsAlive;
};
```
Для каждой партии сервер хранит:
- уникальный `gameId`;
- фазу и режим;
- два внутренних поля;
- текущего участника;
- победителя;
- номер версии состояния;
- подтверждения повторной игры;
- статистику обоих участников;
- последнее публичное событие.
Координаты внутри прошивки и протокола рекомендуется хранить числами `x` и `y` от 0 до 9. Буквенные обозначения формирует интерфейс.
## 12. Скрытие информации
Сервер не должен отправлять единый полный объект партии всем клиентам.
- Игрок получает своё полное поле и только известные клетки поля соперника.
- Зритель получает только известные клетки обоих полей.
- Внутренняя расстановка ESP32 никогда не попадает в браузер до завершения партии.
- После `FINISHED` сервер может включить в представление полные поля обоих участников.
- Все игровые проверки выполняются на ESP32. Клиентская проверка нужна только для удобства интерфейса и не считается защитой.
## 13. HTTP API
Предлагаемый минимальный набор:
| Метод | Путь | Назначение |
|---|---|---|
| `GET` | `/` | Основная страница |
| `GET` | `/assets/*` | CSS, JavaScript и локальные ресурсы |
| `GET` | `/api/info` | Состояние устройства и доступность мест без скрытых данных |
| `POST` | `/api/session/join` | Вход по имени и желаемой роли |
| `POST` | `/api/session/resume` | Восстановление роли по токену |
| `POST` | `/api/game/config` | Выбор режима игроком 1 |
| `POST` | `/api/game/start` | Запуск готовой партии |
| `POST` | `/api/game/shot` | Выстрел по координатам |
| `POST` | `/api/game/rematch` | Подтверждение повторной игры |
| `GET` | `/api/state?version=N` | Снимок разрешённого состояния и резервный опрос |
| `GET` | `/api/health` | Проверка доступности сервера |
Все изменяющие запросы содержат токен сессии и `gameId`. Сервер возвращает JSON с полями `ok`, `code`, `message` и при необходимости новой `version`.
Основные коды ошибок:
- `INVALID_NAME`;
- `NO_PLAYER_SLOT`;
- `UNAUTHORIZED`;
- `FORBIDDEN_ROLE`;
- `WRONG_PHASE`;
- `NOT_YOUR_TURN`;
- `CELL_ALREADY_SHOT`;
- `STALE_GAME`;
- `SERVER_BUSY`.
## 14. WebSocket и резервный опрос
- Точка подключения: `/ws`.
- После открытия клиент передаёт токен сессии и последнюю известную `version`.
- Сервер подтверждает сессию и отправляет персонализированный снимок состояния.
- После каждого принятого действия сервер увеличивает `version` и рассылает новые безопасные представления всем подключённым клиентам.
Рекомендуемые серверные события:
- `state` — полный разрешённый снимок;
- `player_joined` и `player_left`;
- `game_started`;
- `shot_result`;
- `turn_changed`;
- `ship_sunk`;
- `game_finished`;
- `rematch_status`;
- `error`;
- `ping`/`pong`.
Клиентская стратегия соединения:
1. открыть WebSocket;
2. при обрыве выполнить повторные подключения с растущей задержкой, например 1, 2, 5 и 10 секунд;
3. пока WebSocket недоступен, запрашивать `/api/state` каждые 2 секунды;
4. после восстановления WebSocket прекратить опрос;
5. если полученная версия не следует за текущей, запросить полный снимок.
HTTP остаётся каналом для команд и резервной синхронизации, а WebSocket используется для немедленной доставки изменений. Такой подход проще отлаживать и позволяет выполнить ход даже во время кратковременного восстановления WebSocket.
## 15. Алгоритмы
### 15.1. Автоматическая расстановка
1. Очистить поле.
2. Перемешать порядок кораблей или обрабатывать их от длинных к коротким.
3. Случайно выбрать ориентацию и начальную клетку.
4. Проверить границы поля.
5. Проверить клетки корабля и все соседние клетки вокруг него.
6. Разместить корабль либо повторить попытку.
7. Если лимит попыток исчерпан, очистить поле и запустить генерацию заново.
8. Перед стартом проверить количество и длины кораблей, отсутствие касаний и выходов за границы.
### 15.2. Соперник ESP32
Для MVP предлагается стратегия `hunt/target`:
- в режиме поиска выбирать случайную необстрелянную клетку, предпочтительно по шахматному шаблону;
- после попадания добавлять соседние клетки по вертикали и горизонтали в очередь целей;
- после второго попадания определять ориентацию корабля и продолжать стрелять вдоль неё;
- после потопления удалять из кандидатов клетки вокруг корабля и возвращаться в режим поиска;
- никогда не использовать скрытое знание о расположении кораблей человека при выборе выстрела.
Стратегия достаточно понятна и интереснее чистого случайного выбора, но остаётся небольшой по объёму кода и памяти.
## 16. Статистика
Для каждого участника в текущем матче показываются:
- количество выстрелов;
- попадания;
- промахи;
- точность в процентах;
- число потопленных кораблей;
- результат матча.
До перезагрузки ESP32 дополнительно накапливаются:
- сыгранные партии;
- победы и поражения;
- общие выстрелы и попадания;
- общая точность.
Статистика обновляется только сервером. Для зрителя доступна симметричная статистика обоих игроков. При повторной игре статистика матча обнуляется, накопительная — сохраняется.
## 17. Обработка отключений и ошибок
- При отключении игрока активная партия не завершается сразу; его место и состояние сохраняются в памяти ESP32.
- Интерфейс остальных клиентов показывает статус «Игрок переподключается».
- После возвращения с тем же токеном игрок получает актуальный снимок и продолжает партию.
- Для MVP партия может ожидать отключившегося игрока неограниченно; игрок 1 может вернуть систему в лобби отдельной командой подтверждения.
- Отключение зрителя не влияет на игру.
- Потеря WebSocket автоматически включает HTTP-опрос.
- Потеря Wi-Fi или перезапуск ESP32 завершает текущую партию. После восстановления пользователи входят заново.
- При переполнении лимита подключений новый зритель получает понятное сообщение, а действующая партия продолжается.
## 18. Предлагаемая структура проекта
```text
esp32-battleship/
├── platformio.ini
├── include/
│ ├── AppConfig.h
│ ├── GameTypes.h
│ ├── GameEngine.h
│ ├── FleetGenerator.h
│ ├── BotPlayer.h
│ ├── SessionManager.h
│ ├── StatePresenter.h
│ └── Statistics.h
├── src/
│ ├── main.cpp
│ ├── GameEngine.cpp
│ ├── FleetGenerator.cpp
│ ├── BotPlayer.cpp
│ ├── SessionManager.cpp
│ ├── StatePresenter.cpp
│ └── WebApi.cpp
├── data/
│ ├── index.html
│ └── assets/
│ ├── app.css
│ └── app.js
└── test/
├── test_fleet_generator/
├── test_game_engine/
└── test_bot_player/
```
Wi-Fi-данные не следует фиксировать в публичном репозитории. Для MVP их можно вынести в локальный файл конфигурации, исключённый из Git. В дальнейшем можно добавить страницу первичной настройки сети.
## 19. Ограничения для ESP32-C6 Mini
До начала реализации необходимо зафиксировать точного производителя/модель платы, объём flash и наличие встроенного светодиода. Название «ESP32-C6 Mini» используется несколькими платами, поэтому эти параметры нельзя надёжно определить только по общему названию. Игровая архитектура от них не зависит, но они влияют на `platformio.ini`, таблицу разделов и назначение выводов.
- Хранить игровые поля в компактных фиксированных массивах, а не в динамических коллекциях.
- Не создавать отдельную полную JSON-копию состояния для каждого клиента одновременно.
- Ограничить размер входящих HTTP- и WebSocket-сообщений.
- Не загружать изображения и крупные внешние библиотеки без необходимости.
- Сжимать статические файлы (`gzip`) при сборке и отдавать их с правильными заголовками.
- Настроить кэширование CSS и JavaScript, но не кэшировать персонализированное API-состояние.
- Не выполнять длительные циклы генерации, хода бота или рассылки внутри критического сетевого обработчика.
- Добавить периодическую очистку истёкших зрительских сессий.
## 20. Этапы реализации
### Этап 1. Каркас устройства
- Создать PlatformIO-проект и конфигурацию конкретной ESP32-C6 Mini.
- Подключить ESP32 к домашней сети.
- Настроить LittleFS и выдачу тестовой страницы.
- Добавить `/api/health` и журналирование через Serial.
### Этап 2. Игровое ядро
- Реализовать структуры поля и кораблей.
- Реализовать и протестировать генератор флота.
- Реализовать выстрел, попадание, промах, потопление, смену хода и победу.
- Реализовать статистику матча.
### Этап 3. Сессии и API
- Реализовать вход по имени, роли и токены.
- Добавить лобби и запуск партии.
- Добавить персонализированные представления состояния.
- Реализовать HTTP-команды и проверки доступа.
### Этап 4. Синхронизация
- Подключить WebSocket.
- Добавить версионирование состояния и рассылку событий.
- Реализовать переподключение и HTTP fallback.
### Этап 5. Веб-интерфейс
- Реализовать экраны подключения, лобби, игры и результата.
- Добавить адаптивные поля для телефона и планшета.
- Добавить режим зрителя и понятные сообщения об ошибках.
### Этап 6. Бот и повторная игра
- Реализовать стратегию `hunt/target`.
- Добавить задержку и визуализацию хода ESP32.
- Добавить подтверждение повторной игры и накопительную статистику.
### Этап 7. Проверка на устройстве
- Проверить два телефона и несколько зрителей одновременно.
- Проверить переподключение, потерю WebSocket и переход на опрос.
- Проверить расход памяти и устойчивость нескольких последовательных партий.
- Оптимизировать и сжать статические ресурсы.
## 21. Тестирование
### Автоматические тесты логики
- Генератор создаёт ровно 10 кораблей нужных размеров.
- Ни один корабль не выходит за поле и не касается другого.
- Выстрел по воде создаёт промах и меняет ход.
- Попадание сохраняет ход.
- Повторный выстрел отклоняется без изменения состояния.
- Потопление корректно отмечает корабль и соседние клетки.
- Уничтожение последнего корабля завершает партию.
- Бот никогда не стреляет дважды в одну клетку.
- Представление игрока и зрителя не содержит скрытых кораблей.
### Ручные сценарии
- Полная партия «игрок против игрока» с двух устройств.
- Полная партия против ESP32.
- Подключение и отключение нескольких зрителей во время партии.
- Обновление страницы игроком и восстановление по токену.
- Отключение WebSocket с продолжением через HTTP-опрос.
- Повторная игра в обоих режимах.
- Перезапуск ESP32 с ожидаемым сбросом партии.
- Проверка интерфейса на узком телефоне и планшете в обеих ориентациях.
## 22. Критерии готовности MVP
MVP считается готовым, когда:
1. ESP32-C6 Mini стабильно подключается к заданной домашней Wi-Fi-сети и открывает русскоязычный интерфейс.
2. Два пользователя могут войти по именам и полностью сыграть одну партию с разных устройств.
3. Один пользователь может полностью сыграть партию против ESP32.
4. Все расстановки соответствуют классическому набору и запрету касаний.
5. Сервер отклоняет недопустимые и несвоевременные выстрелы.
6. Скрытые корабли не присутствуют в сетевых ответах для соперника или зрителя.
7. Минимум два зрителя могут наблюдать партию без влияния на неё; целевая конфигурация поддерживает до восьми.
8. Изменения обычно появляются через WebSocket, а при его отключении интерфейс автоматически продолжает обновляться через HTTP.
9. Обновление страницы восстанавливает роль и актуальное состояние, если ESP32 не перезагружалась.
10. После окончания отображаются победитель и корректная статистика.
11. Повторная игра создаёт новые расстановки и сохраняет накопительную статистику до перезагрузки.
12. Интерфейс остаётся удобным на телефоне и планшете.
13. Не менее 20 последовательных тестовых партий проходят без зависания, заметной утечки памяти или необходимости перезапуска устройства.
## 23. Возможные расширения после MVP
- Настройка Wi-Fi через временную точку доступа и captive portal.
- Сохранение статистики в NVS.
- Несколько комнат и больше одновременных игроков.
- PIN-код партии и управление зрительским доступом.
- Ручная расстановка кораблей.
- Выбор варианта правил, включая строго один выстрел за ход.
- Таймер хода, чат, звук и анимации.
- Уровни сложности ESP32.
- Локальное имя устройства через mDNS, например `battleship.local`.
- OTA-обновление прошивки и веб-ресурсов.
- Режим собственной точки доступа для игры без домашнего роутера.
+37
View File
@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
+46
View File
@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
+14
View File
@@ -0,0 +1,14 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32-c6-devkitm-1]
platform = espressif32
board = esp32-c6-devkitm-1
framework = espidf
+6
View File
@@ -0,0 +1,6 @@
# This file was automatically generated for projects
# without default 'CMakeLists.txt' file.
FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
idf_component_register(SRCS ${app_sources})
+1
View File
@@ -0,0 +1 @@
void app_main() {}
+11
View File
@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html