Skip to content

feat: Add Codex screen for recording discovered living entities#349

Merged
dmccoystephenson merged 4 commits into
mainfrom
copilot/add-codex-screen-for-living-entities
Apr 20, 2026
Merged

feat: Add Codex screen for recording discovered living entities#349
dmccoystephenson merged 4 commits into
mainfrom
copilot/add-codex-screen-for-living-entities

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 20, 2026

Adds a Codex that tracks which living entity types (Bear, Chicken) the player has encountered, with persistence across save/load and a dedicated screen accessible via configurable keybinding and the options menu.

Codex data model

  • src/codex/codex.py@component class maintaining a set of discovered entity class names with discover(), hasDiscovered(), getDiscoveredEntities() (sorted)
  • src/codex/codex.py also centralizes ALL_LIVING_ENTITY_TYPES and ENTITY_IMAGE_PATHS as the single source of truth for the entity roster
  • src/codex/codexJsonReaderWriter.py — JSON persistence following the Stats pattern, with graceful error handling for corrupted save files
  • schemas/codex.json — validation schema

Discovery trigger

  • WorldScreen resolves Codex via DI, calls discoverLivingEntitiesInRoom() after room transitions and on initialization
  • First discovery of a new type shows "New codex entry: Bear" via status.set() and saves immediately

Keybinding & navigation

  • codex action added to KeyBindings.DEFAULT_BINDINGS (default pygame.K_l) with label for Controls screen remapping
  • CODEX_SCREEN added to ScreenType, handled in WorldScreen.handleKeyDownEvent() and Roam.run()
  • Codex is also reachable via a "Codex" button in the options menu
  • Context-aware back navigation: returns to Options when opened from the menu, or to the World when opened via keybinding

Codex screen

  • src/screen/codexScreen.py@component screen consistent with ControlsScreen layout: scrollable entity list with textures for discovered entries, "???" dimmed for undiscovered, Back button, mouse wheel scrolling
  • Entity names are left-aligned after sprites to prevent overlap at any window size
  • Font and image objects are cached to avoid per-frame recreation overhead

Persistence integration

  • Codex loaded in WorldScreen.initialize() alongside stats/tick/inventory
  • Codex saved in saveSynchronous() on world exit

Tests

  • 19 new tests: Codex data model, persistence round-trip, schema validation, CodexScreen behavior, scroll bounds, and return-screen routing

Copilot AI linked an issue Apr 20, 2026 that may be closed by this pull request
6 tasks
- Create src/codex/codex.py with Codex class (@component)
- Create src/codex/codexJsonReaderWriter.py for persistence
- Create schemas/codex.json JSON schema
- Create src/screen/codexScreen.py with scrollable entity list
- Add CODEX_SCREEN to ScreenType
- Add 'codex' keybinding (L) to KeyBindings
- Integrate discovery in WorldScreen (room transitions, initialization)
- Handle codex screen in Roam.run()
- Save/load codex alongside stats and tick count
- Add L (Codex) to README Controls table
- Add 18 new tests for Codex and CodexScreen
- Update CHANGELOG.md

Agent-Logs-Url: https://github.com/Preponderous-Software/roam/sessions/3d54f664-2b84-4573-8909-b57272f8c9dc

Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
Copilot AI changed the title [WIP] Add Codex screen for recording encountered living entities feat: Add Codex screen for recording discovered living entities Apr 20, 2026
Copilot AI requested a review from dmccoystephenson April 20, 2026 02:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Codex” feature that records which living entity types the player has encountered, persists that data in saves, and provides a dedicated Codex UI screen accessible via a configurable keybinding.

Changes:

  • Introduces Codex model + JSON persistence + schema validation for save/load.
  • Adds CodexScreen UI and wires it into the screen routing / keybinding system.
  • Hooks entity discovery into WorldScreen (initialization + room transitions) and persists codex state on exit / first discovery.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/codex/codex.py New DI-registered Codex model tracking discovered entity types.
src/codex/codexJsonReaderWriter.py Adds codex save/load JSON persistence with schema validation.
schemas/codex.json New JSON schema for codex save data.
src/screen/codexScreen.py New Codex UI screen with scrollable list and entity textures.
src/screen/screenType.py Adds CODEX_SCREEN screen type constant.
src/screen/worldScreen.py Discovers living entities on init/room change; loads/saves codex with the save set.
src/roam.py Resolves and routes to CodexScreen based on ScreenType.CODEX_SCREEN.
src/config/keyBindings.py Adds codex action default binding (K_l) and label for remapping UI.
tests/codex/test_codex.py Unit tests for Codex behavior and persistence round-trip.
tests/codex/test_codexScreen.py Unit tests for CodexScreen basic behavior and scrolling.
README.md Documents the new default Codex keybinding.
CHANGELOG.md Records the new Codex feature and adds a learning-log entry.
src/codex/__init__.py Package init file for the new codex module.

Comment thread src/screen/codexScreen.py Outdated
Comment on lines +9 to +16
# All known living entity types for the codex display.
ALL_LIVING_ENTITY_TYPES = ["Bear", "Chicken"]

# Maps entity class names to their asset image paths.
ENTITY_IMAGE_PATHS = {
"Bear": "assets/images/bear.png",
"Chicken": "assets/images/chicken.png",
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ALL_LIVING_ENTITY_TYPES / ENTITY_IMAGE_PATHS are hardcoded in the screen, so adding a new living entity type requires updating multiple places and the codex UI can easily fall out of sync with the actual entity roster. Consider centralizing the roster (e.g., in codex module) or deriving it from an existing registry used for living entities so there’s a single source of truth.

Copilot uses AI. Check for mistakes.
Comment thread src/codex/codexJsonReaderWriter.py
Comment thread src/codex/codexJsonReaderWriter.py Outdated
Comment on lines +37 to +43
with open(path) as f:
data = json.load(f)

with open("schemas/codex.json") as f:
schema = json.load(f)
jsonschema.validate(data, schema)

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load() performs schema validation without handling validation errors. A corrupted/edited codex.json will currently raise and prevent the world from loading. Consider catching jsonschema.exceptions.ValidationError / json.JSONDecodeError, logging the problem, and returning None (or an empty list) so the game can still start.

Copilot uses AI. Check for mistakes.
Comment thread tests/codex/test_codexScreen.py Outdated
@@ -0,0 +1,79 @@
import pygame
import pytest
from unittest.mock import MagicMock, patch
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import: patch is imported but never referenced. Removing it keeps the test module clean and avoids lint/static-analysis noise.

Suggested change
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock

Copilot uses AI. Check for mistakes.
Comment thread src/screen/codexScreen.py
Comment thread src/screen/codexScreen.py Outdated
imageX = x * 0.25
nameX = x * 0.25 + 45

visibleRows = int((y - startY - 80) / rowHeight)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

visibleRows can become 0 (or negative) if the window height is small, which makes maxOffset/scrollInfo calculations inconsistent (e.g., showing ranges like 3-2 of 2). Guard by ensuring visibleRows is at least 1, or skip rendering/clamping logic when there’s no vertical space to show rows.

Suggested change
visibleRows = int((y - startY - 80) / rowHeight)
visibleRows = max(1, int((y - startY - 80) / rowHeight))

Copilot uses AI. Check for mistakes.
@dmccoystephenson
Copy link
Copy Markdown
Member

@copilot You are a coding agent tasked with resolving all open comments and review threads
on this pull request. Work through every comment systematically and apply the
appropriate code changes.


Instructions

1. Discover all comments

  • Read every review thread, inline comment, and general PR comment
  • Include comments from: Copilot, human reviewers, and any other bots
  • Do not skip comments marked as suggestions — apply them if they make sense

2. For each comment, do the following:

  • Understand what is being requested or flagged
  • Locate the relevant file(s) and line(s)
  • Apply the fix directly in code
  • If a Copilot suggestion diff is provided, apply it (or an equivalent fix)
  • If the comment is ambiguous, use your best judgment and reply in the PR thread or review comment explaining what you did; only add a code comment when explicitly requested or when future maintainers would benefit from it
  • After addressing a comment, reply to the thread summarising what you did and mark it as resolved if your environment supports it

3. Types of issues to handle:

  • Code quality / style issues (naming, formatting, readability)
  • Logic bugs or edge cases flagged by reviewers
  • Security concerns (e.g. input validation, secrets, injection risks)
  • Performance suggestions
  • Missing or incomplete error handling
  • Test coverage gaps
  • Documentation / comment improvements
  • Dependency or import issues

4. Do NOT:

  • Dismiss or ignore any comment without acting on it — note that "acting" can also mean replying to the thread with a rationale (e.g., won't fix, already addressed elsewhere) and leaving the code unchanged when appropriate
  • Leave TODO comments as a substitute for fixing the issue
  • Break existing tests while addressing comments
  • Change functionality beyond the scope of what the comment asks for

After making changes

  • Ensure all existing tests still pass
  • Add or update tests if a comment explicitly asks for them, or if a bug fix warrants it
  • Double-check that every open thread has been addressed, replied to, and resolved

Context

  • This PR may contain Copilot-generated review comments — treat these with the same priority as human comments
  • If two comments conflict with each other, prefer the human reviewer's intent and document the conflict and resolution in the PR conversation or commit message, not in a code comment
  • Commit changes in logical groups if there are many unrelated fixes

…ing, fix imports

- Move ALL_LIVING_ENTITY_TYPES and ENTITY_IMAGE_PATHS from codexScreen.py
  to codex.py as the single source of truth
- Add error handling for jsonschema validation in CodexJsonReaderWriter:
  save() catches ValidationError and logs instead of crashing;
  load() catches ValidationError/JSONDecodeError and returns None
- Replace blanket Exception catch in _getEntityImage() with specific
  (pygame.error, FileNotFoundError) and log via getLogger()
- Guard visibleRows with max(1, ...) to prevent layout issues on small windows
- Remove unused 'patch' import from test_codexScreen.py

Agent-Logs-Url: https://github.com/Preponderous-Software/roam/sessions/5762f4f8-0ed1-412f-bb57-d80c3429e98c

Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 20, 2026

@copilot You are a coding agent tasked with resolving all open comments and review threads
on this pull request. Work through every comment systematically and apply the
appropriate code changes....

All 6 review comments addressed in f094246:

  1. Centralized entity roster — Moved ALL_LIVING_ENTITY_TYPES and ENTITY_IMAGE_PATHS from codexScreen.py to codex.py as the single source of truth. Screen imports from the codex module.
  2. Save error handlingsave() now catches ValidationError and logs instead of crashing, matching the inventoryJsonReaderWriter pattern.
  3. Load error handlingload() now catches json.JSONDecodeError and ValidationError, logs the error, and returns None so a corrupted file won't prevent the game from starting.
  4. Removed unused import — Removed patch from test_codexScreen.py.
  5. Specific exception handling — Replaced blanket Exception in _getEntityImage() with (pygame.error, FileNotFoundError) and added logging via getLogger().
  6. Guard visibleRows — Changed to max(1, int(...)) to prevent zero/negative row counts on small windows.

All 381 tests pass.

@dmccoystephenson
Copy link
Copy Markdown
Member

@copilot The Codex should be reachable via the options menu. Additionally, please ensure that the entity names and entity sprites don't overlap in the Codex screen.

…ligned text

- Add "Codex" button to OptionsScreen between Controls and Back
- CodexScreen now tracks returnScreen: navigates back to Options when
  opened from Options, back to World when opened via keybinding
- Fix sprite/text overlap by left-aligning entity names after the image
  using _drawTextLeftAligned() instead of centered drawText()
- Cache font objects to avoid repeated creation per frame
- Add test_set_return_screen test for the new routing behavior

Agent-Logs-Url: https://github.com/Preponderous-Software/roam/sessions/f211acb6-dde9-481b-9b4f-ffda21865e99

Co-authored-by: dmccoystephenson <21204351+dmccoystephenson@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 20, 2026

@copilot The Codex should be reachable via the options menu. Additionally, please ensure that the entity names and entity sprites don't overlap in the Codex screen.

Both changes addressed in b59acc2:

Options menu access — Added a "Codex" button to the options menu (between Controls and Back). Navigation is context-aware: pressing Back/Escape returns to Options when opened from the menu, or to the World when opened via the L keybinding.

Sprite/text overlap fix — Entity names are now left-aligned starting 16px after the right edge of the sprite image, using a new _drawTextLeftAligned() method instead of the center-aligned drawText(). This prevents text from overlapping sprites regardless of name length.

@dmccoystephenson dmccoystephenson marked this pull request as ready for review April 20, 2026 03:45
@dmccoystephenson dmccoystephenson merged commit f7f3a36 into main Apr 20, 2026
@dmccoystephenson dmccoystephenson deleted the copilot/add-codex-screen-for-living-entities branch April 20, 2026 03:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex

3 participants