-
Notifications
You must be signed in to change notification settings - Fork 2
Improved Game State #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This is a QoL improvement especially when manually inspecting the game state sanitized as JSON with depth >=7. Most of the time, the UI-related keys are not relevant and can be safely ignored.
- Update imports from src.balatrobot to balatrobot package structure - Replace GameState references with G model throughout test files - Update test class documentation and comments to reflect new naming
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR significantly enhances the game state representation by improving data structure matching between Lua and Python, expanding game state information, and updating test files to align with the new schema. The changes support more comprehensive game state tracking as referenced in issue #23.
- Complete restructuring of game state models to match Lua types exactly
- Expanded game state extraction with detailed field documentation
- Updated test files to use new data structures and handle highlighted card differences
Reviewed Changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/runs/one_ante_no_shop_1.jsonl | Updated test data with expanded game state structure and detailed card information |
| tests/lua/test_runs.py | Added hack to handle highlighted card differences between logged and replayed states |
| tests/lua/test_api_functions.py | Updated to access cards through new nested structure (hand.cards vs hand) |
| tests/balatrobot/test_models.py | Changed import paths and model names (GameState → G) |
| tests/balatrobot/test_exceptions.py | Updated import paths for relocated modules |
| tests/balatrobot/test_client.py | Updated model references and import paths throughout |
| src/lua/utils.lua | Significantly expanded game state extraction with comprehensive field documentation |
| src/lua/types.lua | Complete rewrite of type definitions to match new game state structure |
| src/lua/api.lua | Added type annotations for better code clarity |
| src/balatrobot/models.py | Complete restructuring to match Lua types with hierarchical game state models |
| src/balatrobot/init.py | Updated exports (GameState → G) |
| docs/balatrobot-api.md | Updated documentation to reflect new model structure |
| # HACK: Remove highlighted field from cards before comparison | ||
| # The logger hook, log the game state after the card selection, | ||
| # so in the replay we have the highlighted cards, while the game_state | ||
| # before the action has the non-highlighted cards. | ||
| if "hand" in actual_game_state and "cards" in actual_game_state["hand"]: | ||
| for card in actual_game_state["hand"]["cards"]: | ||
| card.pop("highlighted", None) | ||
| if ( | ||
| "hand" in expected_game_state | ||
| and "cards" in expected_game_state["hand"] | ||
| ): | ||
| for card in expected_game_state["hand"]["cards"]: | ||
| card.pop("highlighted", None) |
Copilot
AI
Jul 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hack indicates a design issue where logged state differs from replayed state. Consider logging the game state before card selection instead of after, or implement a proper normalization function rather than this inline hack.
| # HACK: Remove highlighted field from cards before comparison | |
| # The logger hook, log the game state after the card selection, | |
| # so in the replay we have the highlighted cards, while the game_state | |
| # before the action has the non-highlighted cards. | |
| if "hand" in actual_game_state and "cards" in actual_game_state["hand"]: | |
| for card in actual_game_state["hand"]["cards"]: | |
| card.pop("highlighted", None) | |
| if ( | |
| "hand" in expected_game_state | |
| and "cards" in expected_game_state["hand"] | |
| ): | |
| for card in expected_game_state["hand"]["cards"]: | |
| card.pop("highlighted", None) | |
| # Normalize game states before comparison | |
| actual_game_state = normalize_game_state(actual_game_state) | |
| expected_game_state = normalize_game_state(expected_game_state) |
src/lua/utils.lua
Outdated
| -- TODO: continue from here (in the select blind state), maybe try to skip a blind | ||
| -- |
Copilot
AI
Jul 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove TODO comment as it appears to be leftover development notes and doesn't provide actionable information for the current implementation.
| -- TODO: continue from here (in the select blind state), maybe try to skip a blind | |
| -- | |
| -- Skip keys that start with capital letters (UI-related) | ||
| -- Skip predefined fields to avoid circular references and large data | ||
| if not (type(key) == "string" and string.sub(key, 1, 1):match("[A-Z]")) and not skip_fields[key] then |
Copilot
AI
Jul 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The logic for skipping capital letter keys is hardcoded and may be too broad. Consider using a more specific whitelist or blacklist approach to avoid accidentally filtering legitimate game state fields.
| -- Skip keys that start with capital letters (UI-related) | |
| -- Skip predefined fields to avoid circular references and large data | |
| if not (type(key) == "string" and string.sub(key, 1, 1):match("[A-Z]")) and not skip_fields[key] then | |
| -- Skip UI-related keys based on a specific blacklist | |
| -- Skip predefined fields to avoid circular references and large data | |
| local ui_skip_fields = { | |
| UIElement = true, | |
| UIButton = true, | |
| UILabel = true, | |
| UIPanel = true, | |
| } | |
| if not ui_skip_fields[key] and not skip_fields[key] then |
|
@stirby , so far I've implemented these new fields. G.jokers will be added later after other shop actions implementation so we can reach a game state with bought jolly programmatically. |
Related to #23