Add comprehensive test suite for game mechanics and level handling

- Introduced `test_final_level_flow.py` to validate final level transitions and game end scenarios.
- Created `test_game_over_flow.py` to ensure game over conditions trigger correctly based on rat counts.
- Implemented `test_keybindings.py` to verify keybinding configurations and their context-specific actions.
- Developed `test_level_editor.py` to assess level editor functionalities and layout computations.
- Added `test_level_io.py` for testing level data serialization and deserialization.
- Established `test_loop_logic_parity.py` to ensure consistent game state across multiple simulation runs.
- Created `test_non_regression.py` to simulate game behavior and capture states for future verification.
- Implemented `test_verify.py` to compare current game states against a golden master for regression detection.
This commit is contained in:
John Doe
2026-05-19 22:18:43 +02:00
parent 486cd6b7c5
commit c7ed24483d
53 changed files with 10169 additions and 3886 deletions
+26 -8
View File
@@ -199,6 +199,26 @@ class KeyBindings:
def __init__(self, game):
self.game = game
self.bindings = {}
# Explicit action mapping for static-friendly dispatch (Nim-ready)
self.action_dispatcher = {
"spawn_rat": self.spawn_rat,
"spawn_new_bomb": self.spawn_new_bomb,
"spawn_new_mine": self.spawn_new_mine,
"spawn_new_nuclear_bomb": self.spawn_new_nuclear_bomb,
"spawn_new_gas": self.spawn_new_gas,
"toggle_audio": self.toggle_audio,
"toggle_pause": self.toggle_pause,
"toggle_full_screen": self.toggle_full_screen,
"quit_game": self.quit_game,
"menu_up": self.game.menu_up,
"menu_down": self.game.menu_down,
"menu_left": self.game.menu_left,
"menu_right": self.game.menu_right,
"reset_game": self.game.reset_game,
"start_scrolling": self.start_scrolling,
"stop_scrolling": self.stop_scrolling,
}
def _binding_sections_for_action(self):
game_end_active, game_end_reason = getattr(self.game, "game_end", (False, None))
@@ -259,16 +279,14 @@ class KeyBindings:
continue
method_name = value.split("|", 1)[0]
# Check both self (KeyBindings) and self.game (MiceMaze)
method = getattr(self, method_name, getattr(self.game, method_name, None))
if callable(method):
if method_name in self.action_dispatcher:
validated[section_name][action] = value
continue
invalid_bindings += 1
print(
f"[input] ignoring binding {section_name}.{action} -> {value}: "
f"missing method {method_name}"
f"missing method {method_name} in dispatcher"
)
if invalid_bindings:
@@ -291,13 +309,13 @@ class KeyBindings:
if "|" in value:
method_name, *args = value.split("|")
method = getattr(self, method_name, getattr(self.game, method_name, None))
if callable(method):
method = self.action_dispatcher.get(method_name)
if method:
method(*args)
return None
method = getattr(self, value, getattr(self.game, value, None))
if callable(method):
method = self.action_dispatcher.get(value)
if method:
method()
return None