Add simple example game - Dungeon Postman#59
Conversation
📝 WalkthroughWalkthroughAdds a standalone Dungeon Postman example: procedural dungeon generation, torch-based FOV with revealed/visible tiles, key/exit progression, goblin monsters with three-tier AI, toast HUD, run-state overlays, and a main loop with WASM support. ChangesDungeon Postman Game Example
Sequence DiagramsequenceDiagram
participant Player
participant Engine as GameLoop
participant Map as Dungeon+FOV
participant Monsters
participant Renderer
Player->>Engine: Move input (arrow/WASD/numpad)
Engine->>Map: Validate move (bounds/walls)
alt Key pickup
Map->>Engine: collect key
end
alt Exit reached
Map->>Engine: LevelClear or GameClear
end
Engine->>Map: Recompute FOV
Map->>Engine: visible/revealed update
alt Monster timer elapsed
Engine->>Monsters: tick
Monsters->>Map: check visibility to player
alt Player visible
Monsters->>Monsters: A* pathfind & chase
else Memory exists
Monsters->>Monsters: move toward last-known
else Wander
Monsters->>Monsters: random neighbor
end
alt collision
Monsters->>Engine: set Lost state
end
end
Engine->>Renderer: render tiles, monsters, key, player, toasts, HUD
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bracket-terminal/examples/dungeon_postman.rs (1)
1-788: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy liftAdd tests for the new gameplay logic.
This introduces substantial behavior (map generation, movement, AI transitions, win/lose states), but no tests are included in the changed Rust module set. Please add focused tests for core transitions (e.g., locked exit behavior, key pickup, collision loss, AI state transitions).
As per coding guidelines, "Add tests for new functionality in the relevant module; for split domains, prefer colocatedtests.rs".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bracket-terminal/examples/dungeon_postman.rs` around lines 1 - 788, Add unit tests colocated with this module (e.g., a tests.rs under cfg(test)) that exercise the new gameplay transitions: create a deterministically initialised State via State::build(level) (or a helper that sets player_pos/monsters/map directly), then assert behavior of State::try_move_player for the locked exit (player cannot enter Exit without has_key), key pickup (stepping onto key_pos sets has_key and clears key_pos and updates key_status_line/log), collision loss (place a Monster at player_pos and call move_monsters or inspect run_state/log), and AI transitions (toggle map.visible and last_known_pos and call move_monsters to assert alerted/last_known_pos changes and that appropriate transitions trigger). Reference State::build, State::try_move_player, State::move_monsters, State::push_toast/toasts, and RunState to locate logic; keep tests focused, deterministic, and colocated per guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bracket-terminal/examples/dungeon_postman.rs`:
- Around line 706-734: The code marks player_moved true on any movement key
press even if movement was blocked; modify try_move_player to return a bool
(true when the player actually moved) and change each call site in the key match
to set player_moved = self.try_move_player(dx, dy) (or player_moved |=
self.try_move_player(...)) so update_fov(), push_toast(TOAST_FOV, ...), and
fov_toast_cooldown logic only run when actual movement occurred; also update any
other callers of try_move_player to handle the new boolean return.
- Around line 347-384: try_move_player currently lets the player step onto a
tile occupied by a monster and relies on move_monsters() to handle combat later;
update try_move_player to check for a monster at new_pos immediately (e.g.
inspect self.monsters for an entry with pos == new_pos) and handle the collision
synchronously by setting self.run_state to the appropriate defeat state (e.g.
RunState::GameOver or RunState::PlayerDead), updating self.log with a defeat
message, and reverting player_pos if needed; this ensures immediate, consistent
collision semantics between try_move_player, player_pos, monsters, run_state,
and log.
---
Outside diff comments:
In `@bracket-terminal/examples/dungeon_postman.rs`:
- Around line 1-788: Add unit tests colocated with this module (e.g., a tests.rs
under cfg(test)) that exercise the new gameplay transitions: create a
deterministically initialised State via State::build(level) (or a helper that
sets player_pos/monsters/map directly), then assert behavior of
State::try_move_player for the locked exit (player cannot enter Exit without
has_key), key pickup (stepping onto key_pos sets has_key and clears key_pos and
updates key_status_line/log), collision loss (place a Monster at player_pos and
call move_monsters or inspect run_state/log), and AI transitions (toggle
map.visible and last_known_pos and call move_monsters to assert
alerted/last_known_pos changes and that appropriate transitions trigger).
Reference State::build, State::try_move_player, State::move_monsters,
State::push_toast/toasts, and RunState to locate logic; keep tests focused,
deterministic, and colocated per guidelines.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 65a6d80b-5199-41ae-be28-cd3a556691cb
📒 Files selected for processing (1)
bracket-terminal/examples/dungeon_postman.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Format all Rust code usingcargo fmt --all
Fix allcargo clippywarnings — the CI enforces-D warnings
Add tests for new functionality in the relevant module; for split domains, prefer colocatedtests.rs
Files:
bracket-terminal/examples/dungeon_postman.rs
|
@utilForever 혹시 저한테 coderabbitai bot의 리뷰가 보이지 않는게 정상일까요? |
|
@coderabbitai Can you review it? |
|
Tip For best results, initiate chat on the files or code changes.
[review] |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
bracket-terminal/examples/dungeon_postman.rs (1)
746-751: ⚡ Quick winPreserve timer overflow to keep monster cadence stable under frame spikes.
At Lines 746-751, resetting
self.monster_timerto0.0drops residual elapsed time. This can make monster movement slower/inconsistent whenframe_time_msis large.Suggested change
- if self.monster_timer >= monster_interval && self.run_state == RunState::Running { - self.monster_timer = 0.0; - self.move_monsters(); - } + while self.monster_timer >= monster_interval && self.run_state == RunState::Running { + self.monster_timer -= monster_interval; + self.move_monsters(); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bracket-terminal/examples/dungeon_postman.rs` around lines 746 - 751, The timer reset drops leftover frame time causing inconsistent monster cadence; instead of setting self.monster_timer = 0.0 in the block that checks self.monster_timer >= monster_interval and self.run_state == RunState::Running, preserve overflow by subtracting monster_interval from self.monster_timer (or use a while loop that repeatedly subtracts monster_interval and calls self.move_monsters() to handle multiple intervals in one large frame) so residual elapsed time is kept and monster movement cadence remains stable; changes should be applied around the self.monster_timer, monster_interval, RunState::Running and self.move_monsters() logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bracket-terminal/examples/dungeon_postman.rs`:
- Around line 224-795: Add a colocated test module (#[cfg(test)] mod tests) in
this file (or a new tests.rs next to it) and add focused unit tests that
exercise deterministic rules by constructing or mutating State instances and
calling the exposed methods: 1) test blocked movement: set up a State/map where
the target tile is TileType::Wall and assert State::try_move_player returns
false and player_pos is unchanged; 2) test key pickup and exit gating: place
key_pos on an adjacent tile, step onto it and assert has_key becomes true and
key_pos becomes None, then place Exit on an adjacent tile and assert stepping
onto it without key leaves run_state as Running and player_pos reset, but
stepping with has_key transitions run_state to RunState::LevelClear or
RunState::GameClear depending on level; 3) test monster interactions and loss:
create a State with a monster positioned on the destination tile (or move a
monster onto player_pos), call try_move_player or move_monsters as appropriate
and assert run_state becomes RunState::Lost and log updated; for move_monsters
tests set map.visible / last_known_pos to force alert/search paths and assert
monsters[].alerted and last_known_pos update accordingly. Construct State via
State::build(1) then mutate fields (map, player_pos, key_pos, monsters,
map.visible) so tests remain deterministic and avoid UI; use asserts on
RunState, has_key, player_pos, monsters and key_pos to validate behavior.
---
Nitpick comments:
In `@bracket-terminal/examples/dungeon_postman.rs`:
- Around line 746-751: The timer reset drops leftover frame time causing
inconsistent monster cadence; instead of setting self.monster_timer = 0.0 in the
block that checks self.monster_timer >= monster_interval and self.run_state ==
RunState::Running, preserve overflow by subtracting monster_interval from
self.monster_timer (or use a while loop that repeatedly subtracts
monster_interval and calls self.move_monsters() to handle multiple intervals in
one large frame) so residual elapsed time is kept and monster movement cadence
remains stable; changes should be applied around the self.monster_timer,
monster_interval, RunState::Running and self.move_monsters() logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5bcddbda-12d4-45d3-8b00-f5ffc4980f6e
📒 Files selected for processing (1)
bracket-terminal/examples/dungeon_postman.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Format all Rust code usingcargo fmt --all
Fix allcargo clippywarnings — the CI enforces-D warnings
Add tests for new functionality in the relevant module; for split domains, prefer colocatedtests.rs
Files:
bracket-terminal/examples/dungeon_postman.rs
utilForever
left a comment
There was a problem hiding this comment.
코드 리뷰가 많이 늦어져 죄송합니다. 확인 부탁드립니다.
utilForever
left a comment
There was a problem hiding this comment.
LGTM now. Thanks for your work! 🎉
What
Add dungeon_postman example: a 5-level roguelike that showcases bracket-lib's RNG, FOV, and A* pathfinding APIs in an interactive game context.
Why
The existing examples demonstrate individual APIs in isolation. dungeon_postman provides a cohesive, game-sized example that shows how bracket_random, bracket_pathfinding, and bracket_terminal compose together — giving new users a realistic reference for building their own games.
Closes #25.
Checklist
Required
cargo check --allpassescargo fmt --all -- --checkpassescargo clippy --workspace --all-targets -- -D warnings -A clippy::multiple-crate-versionspassescargo test --allpassesCloses #123)Functional Validation
Configuration & Docs
README.md,ARCHITECTURE.md, or relevant manual pages, if applicable; not applicable)If Applicable
cargo auditlocally if needed; not needed for workflow-only change)Validation Notes
git diff --checkpasses..github/workflows/rust.ymland.github/workflows/sonarcloud.ymlwere parsed successfully as YAML.Summary by CodeRabbit