Summary
Add a Codex screen that records living entities the player has encountered and can be opened via a configurable keybinding.
Background
Roam has no persistent record of what the player has discovered. A Codex gives players a sense of progression and a reference for entity types they have encountered. The initial scope covers living entities only (Chicken, Bear) with the data model designed to accommodate additional entity types in future. The keybinding should be managed through KeyBindings (src/config/keyBindings.py) so it is remappable via the Controls screen like all other actions. Note: if PR #344 is merged before this, any new logging calls should use getLogger from src/gameLogging/logger.py.
Requirements
Codex Data
- Create
src/codex/codex.py with a Codex class registered as a @component in the DI container (src/appContainer.py)
- The class maintains a
set of discovered entity class names (e.g. "Bear", "Chicken") and exposes:
discover(entityClassName: str) — adds the class name to the discovered set
hasDiscovered(entityClassName: str) -> bool
getDiscoveredEntities() -> list[str] — sorted alphabetically
- Persist the discovered set to
{pathToSaveDirectory}/codex.json using a new schemas/codex.json JSON schema; save on discovery and load on world screen initialization alongside stats and tick count
- Add a
CodexJsonReaderWriter (src/codex/codexJsonReaderWriter.py) following the same pattern as StatsJsonReaderWriter
Discovery Trigger
- In
WorldScreen (src/screen/worldScreen.py), resolve Codex from the DI container
- After any room transition or room draw, iterate
currentRoom.getLivingEntities() and call codex.discover(entity.__class__.__name__) for each living entity in the room
- On first discovery of a new entity type, display a brief status message via
status.set(...), e.g. "New codex entry: Bear"
Keybinding
- Add a
codex action to KeyBindings.DEFAULT_BINDINGS in src/config/keyBindings.py with a default of pygame.K_l
- Handle the key in
WorldScreen.handleKeyDownEvent() to switch to ScreenType.CODEX_SCREEN
- Add
CODEX_SCREEN to ScreenType (src/screen/screenType.py)
- Handle the new screen type in
Roam.run() (src/roam.py)
Codex Screen
- Create
src/screen/codexScreen.py with a CodexScreen class decorated with @component
- Display a scrollable list of discovered living entities, one per row, showing:
- The entity's display name (e.g.
"Bear", "Chicken")
- A scaled version of the entity's texture (loaded via
DrawableEntity.getImage())
- A placeholder row (e.g.
"???"), dimmed, for known but not-yet-discovered entity types — hardcode the full list of living entity types for now (Bear, Chicken)
- Support mouse wheel scrolling, consistent with
ControlsScreen and SaveSelectionScreen
- Include a Back button at the bottom that returns to the world screen (or options screen if opened from there)
- Layout and styling should be consistent with
ControlsScreen
README
- Add
L (Codex) to the Controls table in README.md
Acceptance Criteria
Summary
Add a Codex screen that records living entities the player has encountered and can be opened via a configurable keybinding.
Background
Roam has no persistent record of what the player has discovered. A Codex gives players a sense of progression and a reference for entity types they have encountered. The initial scope covers living entities only (
Chicken,Bear) with the data model designed to accommodate additional entity types in future. The keybinding should be managed throughKeyBindings(src/config/keyBindings.py) so it is remappable via the Controls screen like all other actions. Note: if PR #344 is merged before this, any new logging calls should usegetLoggerfromsrc/gameLogging/logger.py.Requirements
Codex Data
src/codex/codex.pywith aCodexclass registered as a@componentin the DI container (src/appContainer.py)setof discovered entity class names (e.g."Bear","Chicken") and exposes:discover(entityClassName: str)— adds the class name to the discovered sethasDiscovered(entityClassName: str) -> boolgetDiscoveredEntities() -> list[str]— sorted alphabetically{pathToSaveDirectory}/codex.jsonusing a newschemas/codex.jsonJSON schema; save on discovery and load on world screen initialization alongside stats and tick countCodexJsonReaderWriter(src/codex/codexJsonReaderWriter.py) following the same pattern asStatsJsonReaderWriterDiscovery Trigger
WorldScreen(src/screen/worldScreen.py), resolveCodexfrom the DI containercurrentRoom.getLivingEntities()and callcodex.discover(entity.__class__.__name__)for each living entity in the roomstatus.set(...), e.g."New codex entry: Bear"Keybinding
codexaction toKeyBindings.DEFAULT_BINDINGSinsrc/config/keyBindings.pywith a default ofpygame.K_lWorldScreen.handleKeyDownEvent()to switch toScreenType.CODEX_SCREENCODEX_SCREENtoScreenType(src/screen/screenType.py)Roam.run()(src/roam.py)Codex Screen
src/screen/codexScreen.pywith aCodexScreenclass decorated with@component"Bear","Chicken")DrawableEntity.getImage())"???"), dimmed, for known but not-yet-discovered entity types — hardcode the full list of living entity types for now (Bear,Chicken)ControlsScreenandSaveSelectionScreenControlsScreenREADME
L(Codex) to the Controls table inREADME.mdAcceptance Criteria
BearorChickenadds it to the Codex and shows a status message on first discoveryLkey (remappable via the Controls screen)???codex.jsonCodex.discover(), persistence round-trip, and theCodexScreenpanel bounds