generated from GarandPLG/rust-flake-template
Introduce AGENTS.md as an entry point for agents, add CODE_MAP.md with a module overview and diagrams, and create PROGRESS.md to log work progress. Update flake.lock to reflect dependency revisions.
116 lines
9.0 KiB
Markdown
116 lines
9.0 KiB
Markdown
# Mapa kodu i przepływu
|
||
|
||
Migawka: 2026-10-18. Projekt `war_in_tunnels` 0.1.0 to prototyp terminalowego RTS. Działają menu, prezentacja planszy, nawigacja, zaznaczanie ścieżki i obsługa audio; pełna symulacja nie jest podłączona do zegara.
|
||
|
||
## Moduły i odpowiedzialność
|
||
|
||
Wszystkie ścieżki poniżej są względem katalogu głównego repozytorium.
|
||
|
||
| Obszar | Pliki | Odpowiedzialność |
|
||
|---|---|---|
|
||
| Start | `src/main.rs`, `src/lib.rs` | CLI, kanały, wątki, terminal, eksporty biblioteki |
|
||
| Parametry | `src/cli.rs`, `src/logs.rs` | Clap, walidacja zakresów, opcjonalny logger |
|
||
| Pętla aplikacji | `src/app/app.rs` | `App`, inicjalizacja stanów przy pierwszym rysowaniu, wejście, resize, update |
|
||
| Zbiór stanów | `src/app/state.rs`, `src/app/states/` | `GameStates`, menu, potyczka, ustawienia, perki, umiejętności |
|
||
| Routing widoku | `src/app/view.rs`, `src/app/views/` | `View`, implementacja `Widget for &mut App`, layouty i ekrany |
|
||
| Wejście | `src/app/keybind.rs`, `src/app/keybindings/` | Routing według widoku, `KEYBINDINGS`, `Action`, `Group`, mapowanie zdarzeń |
|
||
| Plansza | `src/app/states/skirmish_states/board.rs` | Tworzenie mapy, kamera, zoom, focus, zaznaczenia, zlecanie i szkic wykonywania zadań |
|
||
| Współrzędne | `focused_cell.rs`, `offset.rs`, `marked_cells.rs`, `zoom_level.rs` w `skirmish_states/` | Granice kursora i przewijania, ścieżka zaznaczenia, rozmiar komórek |
|
||
| Obiekty gry | `skirmish_states/structures/`, `units/`, `tasks/` | Traity `Structure`, `Unit`, `Task` i delegujące enumy `Structures`, `Units`, `Tasks` |
|
||
| Widgety | `src/app/widgets/` | Plansza, komórka, panel boczny i legenda klawiszy |
|
||
| Pomocniczy layout | `src/app/helpers/` | Obszar komórek, tytuły bloków i tekst opcji menu |
|
||
| Wątki | `src/app/threads/{events,tick,audio}.rs` | Crossterm, zegar 33 ms, Rodio i komendy audio |
|
||
| Środowisko | `Cargo.toml`, `flake.nix`, `default.nix`, `flake.lock` | Zależności, toolchain Fenix, ALSA, pakowanie przez Naersk lub buildRustPackage |
|
||
| Zasoby | `soundtracks/default/`, `ui_draft/` | Dwa pliki OGG i tekstowe szkice ekranów |
|
||
|
||
Ścieżki skrócone `skirmish_states/` oznaczają `src/app/states/skirmish_states/`. Nie ma osobnego silnika gry, bazy danych ani warstwy sieciowej. Zależności Cargo: Ratatui/Crossterm, Clap, Rodio, log/simplelog i once_cell.
|
||
|
||
## Uruchomienie i pętla
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
CLI[Cli::parse / get_args] --> MAIN[main]
|
||
MAIN --> INPUT[Wątek handle_ct_events]
|
||
MAIN --> TICK[Wątek handle_tick_event: 33 ms]
|
||
MAIN --> AUDIO[Wątek handle_audio, jeśli włączony]
|
||
MAIN --> INIT[ratatui::init / App::new]
|
||
INIT --> LOOP[App::run]
|
||
INPUT -->|kanały key i resize| LOOP
|
||
TICK -->|kanał tick| LOOP
|
||
LOOP --> DRAW[terminal.draw / App::draw]
|
||
DRAW --> STATES[GameStates::new przy pierwszym rozmiarze okna]
|
||
LOOP --> KEYS[handle_keybindings]
|
||
KEYS -->|AudioCmd| AUDIO
|
||
LOOP --> UPDATE[App::update / SkirmishState::tick_update]
|
||
LOOP --> SLEEP[sleep 10 ms]
|
||
SLEEP --> LOOP
|
||
LOOP -->|exit lub błąd| RESTORE[ratatui::restore]
|
||
```
|
||
|
||
Kanały to standardowe `std::sync::mpsc`. Stan gry mutuje główny wątek. Każdy obrót pętli najpierw rysuje, następnie próbuje odebrać po jednym zdarzeniu z każdego kanału. Aktualizacja potyczki odbywa się niezależnie od wybranego ekranu. `tick_update` obecnie tylko zwiększa `turn_counter`; `self.board.advance_turn()` jest zakomentowane.
|
||
|
||
`GameStates::new` tworzy wszystkie stany jednocześnie. `SettingsState` przechowuje parametry z CLI; samo istnienie parametrów ekonomii, XP i trybu gry nie oznacza zaimplementowanych mechanik. `View` zawiera MainMenu, Skirmish, PerkDecks i SkillsConfig. Dwa ostatnie używają `default_view` z napisem „Work in progress”; ustawienia nie mają osobnego wariantu `View`.
|
||
|
||
## Renderowanie i dane
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
APP[App + GameStates] --> ROUTE[View::render]
|
||
ROUTE --> MENU[main_menu_view]
|
||
ROUTE --> SK[skirmish_view i layouty]
|
||
ROUTE --> WIP[default_view]
|
||
SK --> BOARD[BoardWidget]
|
||
SK --> SIDE[SidePanelWidget]
|
||
SK --> HELP[KeybindingsWidget]
|
||
BOARD --> CELL[CellWidget]
|
||
CELL --> STRUCT[Structures / Structure]
|
||
CELL --> UNIT[Option Units / Unit]
|
||
UNIT --> TASK[VecDeque Tasks / Task]
|
||
```
|
||
|
||
`BoardState.cells: Vec<Vec<CellWidget>>` łączy model i prezentację: komórka zawiera strukturę, opcjonalną jednostkę, pozycję i flagi UI. `BoardWidget` wybiera widoczne komórki przez offsety i layout; `CellWidget` odpowiada za ich tekst i styl. Panel boczny prezentuje dane zaznaczenia. Zoom wpływa na wielkość komórek i liczbę widocznych wierszy/kolumn; resize i przełączanie panelu zmieniają granice offsetów.
|
||
|
||
Mapa powstaje deterministycznie: kamień, baza gracza w `(map_height / 2, 2)`, baza przeciwnika w `(map_height / 2, map_width - 3)`, sąsiadujące złoża i po jednym górniku w bazie. CLI domyślnie wybiera mapę 42 × 11; dopuszczalne zakresy to szerokość 36–108 i wysokość 11–39. Dostępne struktury to Base, Ore, Stone, Tunnel; jedyna jednostka to Miner, jedyne zadanie to Digging.
|
||
|
||
## Klawisze i zlecanie kopania
|
||
|
||
1. `handle_ct_events` odbiera zdarzenie Crossterm i przekazuje je kanałem do `App`.
|
||
2. `handle_keybindings` wybiera obsługę menu, potyczki albo domyślną.
|
||
3. `event_to_action` porównuje kod, rodzaj i modyfikatory z `KEYBINDINGS`, następnie obsługuje znak wildcard.
|
||
4. Akcje wspólne realizują wyjście, powrót do menu i komendy audio.
|
||
5. W potyczce ruch zmienia focus i ewentualnie kamerę; zoom przelicza rozmiary; Tab przełącza panel.
|
||
6. Spacja przełącza zaznaczanie. `start_marking_cells` zapamiętuje jednostkę z komórki początkowej; ruch dopisuje współrzędne do kolejki. Backspace cofa ścieżkę, Delete ją anuluje.
|
||
7. `end_marking_cells(false)` pomija pierwsze pole, tworzy `DiggingTask` z pozostałej ścieżki i siły kopania oraz przekazuje zadanie jednostce.
|
||
|
||
Projektowane wykonanie: `advance_turn` skanuje komórki, wyjmuje jednostkę przez `take()`, obsługuje pierwsze zadanie i przenosi jednostkę na cel, zastępując strukturę tunelem. Ten przepływ istnieje w kodzie, ale nie jest obecnie wywoływany przez tick.
|
||
|
||
## Audio i pakowanie
|
||
|
||
Główny wątek wysyła `AudioCmd`; osobny wątek obsługuje głośność, mute, część i soundtrack. Cache wykorzystuje `Lazy`, `RwLock`, `Arc` i bajty OGG. Calm ładuje `calm.ogg`; Buildup, Assault i Outro korzystają obecnie z `test.ogg`. Błędy urządzenia, odczytu i dekodowania mogą zakończyć wątek przez `expect`.
|
||
|
||
`flake.nix` dostarcza devShell dla `x86_64-linux`, domyślny pakiet z `default.nix` i pakiet `.#develop` budowany przez Naersk. Obie ścieżki pakowania kopiują soundtracki do `$out/bin` i zmieniają nazwę binarki na `war-in-tunnels`. `default.nix` ma stały `cargoHash`; po zmianie zależności wymaga osobnej weryfikacji. Samo `cargo test` nie sprawdza pakowania.
|
||
|
||
## Punkty wymagające uwagi przed dalszą implementacją
|
||
|
||
To obserwacje statyczne, nie lista napraw wykonanych w tej sesji:
|
||
|
||
- **Symulacja wyłączona:** `SkirmishState::tick_update` nie wywołuje `advance_turn`.
|
||
- **Postęp zadania:** `DiggingTask::progress` oblicza nową wartość i ją odrzuca (`let _ = ...`); nie aktualizuje pola `progress`.
|
||
- **Ruch w szkicu symulacji:** `advance_turn` pobiera cel bez warunku osiągnięcia postępu, nie aktualizuje współrzędnych jednostki i nie usuwa zakończonego zadania z kolejki. Jednostka przeniesiona na późniejszą komórkę może zostać obsłużona ponownie w tym samym skanowaniu. Zapis celu może nadpisać inną jednostkę i strukturę. Przed aktywacją potrzebne są reguły kolizji i testy pojedynczej tury.
|
||
- **Zaznaczenie:** jednostka startowa jest zapamiętywana oddzielnie; przy uruchomieniu ruchu trzeba sprawdzić ważność jej pozycji i zachowanie dla pustej komórki oraz jednostki przeciwnika.
|
||
- **Audio:** pętla `handle_audio` wymaga sprawdzenia zużycia CPU przy braku komend; testy Cargo nie weryfikują urządzenia ani odtwarzania.
|
||
- **Granice UI:** małe terminale, resize i trzy poziomy zoomu wymagają interaktywnego sprawdzenia. Indeksowanie planszy zakłada poprawne współrzędne.
|
||
- **Pokrycie:** brak testów jednostkowych/integracyjnych i konfiguracji CI w analizowanym drzewie. Clippy zgłasza 54 ostrzeżenia; nie uruchamiać automatycznych poprawek poza zakresem zadania.
|
||
|
||
## Gdzie zacząć konkretną zmianę
|
||
|
||
| Zadanie | Główne miejsca i powiązania |
|
||
|---|---|
|
||
| Nowa akcja | `keybindings/keybindings.rs` → handler widoku → lista akcji w `views/` |
|
||
| Mechanika kopania | `tasks/digging.rs` → `units/` → `board.rs::advance_turn` → `skirmish.rs::tick_update` |
|
||
| Nowy obiekt | Trait i enum w `structures/` lub `units/`, eksporty `mod.rs`, tworzenie mapy, komórka i panel |
|
||
| Kamera i zoom | `board.rs`, `focused_cell.rs`, `offset.rs`, `zoom_level.rs`, `helpers/cells_area.rs`, layout i widget planszy |
|
||
| Nowy ekran | `View`, `GameStates`, `states/`, `views/`, routing klawiszy i menu |
|
||
| Parametr CLI | `cli.rs`, walidacja, `GameStates::new`, faktyczny konsument i README |
|
||
| Audio lub dystrybucja | `threads/audio.rs`, `main.rs`, zasoby, `flake.nix`, `default.nix` |
|