# Mice! Mice! is a strategic game where players must kill rats with bombs before they reproduce and become too numerous. The game is a clone of the classic game Rats! for Windows 95. ## Compatibility *Developed and tested with Python 3.11+* ## Features - **Maze Generation**: Randomly generated mazes using Depth First Search (DFS) algorithm - **Multiple Unit Types**: Rats, bombs, mines, gas, and collectible points with unique behaviors - **User Profile System**: Track scores, achievements, and game statistics - **Graphics**: Custom graphics for maze tiles, units, and effects - **Sound Effects**: Audio feedback for various game events - **Scoring**: Points system with leaderboards and profile integration - **Dual Rendering Engines**: Support for both SDL2 and Pygame ## Rendering Engine Options The game now supports **two rendering backends** with identical interfaces: ### 1. SDL2 Backend (`engine/sdl2_layer.py`) - **Original implementation** using PySDL2 - Hardware-accelerated rendering via SDL2 - Optimized for performance on Linux systems - Direct access to low-level graphics features ### 2. Pygame Backend (`engine/pygame_layer.py`) ⭐ **NEW** - **Drop-in replacement** for SDL2 backend - More portable and easier to set up - Better cross-platform support (Windows, macOS, Linux) - Simplified dependency management - Identical API - no game code changes needed ### Switching Between Rendering Engines To switch from SDL2 to Pygame, simply change the import in `rats.py`: ```python # Using SDL2 (original) from engine import maze, controls, graphics, sdl2_layer as engine, unit_manager, scoring # Using Pygame (new) from engine import maze, controls, graphics, pygame_layer as engine, unit_manager, scoring ``` That's it! No other code changes are required thanks to the compatible interface design. ## Browser / Pyodide Support (experimental) - The project includes an experimental browser build that runs the game in WebAssembly using Pyodide and a bundled pygame-ce build. This supports running the game inside modern browsers (desktop only) and is intended for demos and lightweight testing. - Key points: - `index.html` contains the Pyodide bootstrap, asset loader and a JS-driven game loop that calls into the Python game tick function so the UI stays responsive. - The browser integration includes a small profile sync mechanism so profiles saved by the Python code (inside Pyodide's virtual FS) are synchronized back to browser `localStorage`. - A tiny utility `tools/create_favicon.py` generates `favicon.ico` from the game's `assets` if you want a browser favicon for local hosting. Use the browser demo for quick sharing and testing, but prefer the native Python + SDL2/pygame backends for actual play and development. ## Cleanup notes This repository contains some auxiliary files used during development and for old/demo flows. If you want me to remove unused items, I can safely delete them in a single branch/commit after you confirm. Suggested candidates are listed in the developer checklist below. ### Developer cleanup checklist (proposed deletions) These files look like auxiliary or duplicate/demo artifacts and can be removed to reduce noise. I'll only delete them if you confirm. - `BROWSER_GAME_README.md` — duplicate/demo readme for browser build - `BROWSER_SETUP_QUICK_START.md` — quick-start for browser demo - `PYGAME_BACKEND_GUIDE.md` — documentation duplicate - `pyodide-guide.html` — local demo HTML (we already ship `index.html`) - `browser-game-setup.sh` and `play.sh` — demo scripts not used in CI - `assets/asset-manifest.json`, `assets/sound-manifest.json` — generated manifests (can be regenerated) - `engine/pygame_layer.py` and `engine/sdl2_layer.py` — ensure you want to keep one backend; if you prefer only SDL2 or only Pygame, remove the other If you'd like me to proceed, reply with "delete these files" and I will create a branch, remove them, and push the change. ## Engine Architecture The Mice! game engine is built on a modular architecture designed for flexibility and maintainability. The engine follows a component-based design pattern where different systems handle specific aspects of the game. ### Core Engine Components #### 1. **Rendering System** (`engine/sdl2_layer.py` or `engine/pygame_layer.py`) - **GameWindow Class**: Central rendering manager - **Features**: - Hardware-accelerated rendering - Texture management and caching - Sprite rendering with transparency support - Text rendering with custom fonts - Resolution-independent scaling - Fullscreen/windowed mode switching - Dynamic blood splatter effects - White flash screen effects - **Implementation**: - Double buffering for smooth animation - Texture atlas for optimized memory usage - Viewport transformations for different screen resolutions - Alpha blending for transparency effects #### 2. **Input System** (`engine/controls.py`) - **KeyBindings Class**: Handles all user input - **Features**: - Keyboard input mapping and handling - Joystick/gamepad support - Configurable key bindings via YAML/JSON - Context-sensitive input (menu vs. gameplay) - **Implementation**: - Event-driven input processing - Support for multiple input devices simultaneously - Dynamic key binding system with action mapping #### 3. **Map System** (`engine/maze.py`) - **Map Class**: Manages the game world structure - **Features**: - Maze data loading from JSON - Collision detection system - Tile-based world representation - Pathfinding support for AI units - **Implementation**: - Grid-based coordinate system - Efficient collision detection - Support for walls and floor tiles - Integration with procedural maze generation #### 4. **Audio System** - **Sound Management**: Handles all audio playback - **Features**: - Sound effect playback with multiple channels - Background music support - Volume control - Per-channel audio mixing - **Implementation**: - SDL2 backend: Native SDL2 audio system - Pygame backend: pygame.mixer module - Support for WAV format audio files - Multiple simultaneous sound channels (base, effects, music) #### 5. **Unit Management System** (`engine/unit_manager.py`) - **UnitManager Class**: Manages all game entities - **Features**: - Dynamic unit spawning and removal - Position tracking for collision detection - Resource management (ammo, items) - **Implementation**: - UUID-based unique identifiers - Efficient lookup structures - Automatic cleanup on unit death #### 6. **User Profile System** (`engine/user_profile_integration.py`) - **UserProfileIntegration Class**: Manages player profiles - **Features**: - Multiple user profile support - Score tracking and leaderboards - Game statistics (games played, wins, best score) - Device-specific profiles - Global leaderboard integration ### Game Loop Architecture The main game loop follows the standard pattern: 1. **Input Processing**: Capture and process user input 2. **Update Phase**: Update game state, unit logic, and physics 3. **Render Phase**: Draw all game objects to the screen 4. **Timing Control**: Maintain consistent frame rate (target 60 FPS) ``` Input → Update → Render → Present → Repeat ``` ## Units Implementation The game uses an object-oriented approach for all game entities. Each unit type inherits from a base unit class and implements specific behaviors. ### Base Unit Architecture (`units/unit.py`) All units share common properties and methods defined in the abstract `Unit` class: **Common Attributes**: - `id` (UUID): Unique identifier for each unit - `position` (tuple): Current (x, y) grid coordinates - `position_before` (tuple): Previous position for smooth movement - `age` (int): Time alive in game ticks - `speed` (float): Movement speed multiplier - `partial_move` (float): Sub-cell movement progress (0.0 to 1.0) - `bbox` (tuple): Bounding box for collision detection - `stop` (int): Remaining ticks of immobilization **Abstract Methods** (must be implemented by subclasses): - `move()`: Update unit position and state each frame - `draw()`: Render the unit on screen **Concrete Methods**: - `collisions()`: Handle interactions with other units - `die(score=None)`: Remove unit from game and handle cleanup ### Unit Types Implementation #### 1. **Rat Units** (`units/rat.py`) **Base Rat Class**: - **AI Behavior**: Pathfinding with direction memory to avoid backtracking - **Movement**: Smooth interpolated movement between grid cells - **Lifecycle**: Age-based behavior changes (baby → adult → elder) - **Gas Vulnerability**: Can be killed by poison gas **Male Rat Class**: - **Reproduction**: Seeks female rats for mating - **Fighting**: Territorial combat with other males - **Adult Threshold**: Becomes fertile after 200 game ticks **Female Rat Class**: - **Pregnancy System**: 500-tick gestation period - **Offspring Generation**: Spawns baby rats at intervals - **Maternal Behavior**: Protects territory from threats **Implementation Details**: ```python class Rat(Unit): def move(self): self.age += 1 if self.gassed > 35: self.choked() # Death by gas if self.age == AGE_THRESHOLD: self.speed *= SPEED_REDUCTION # Slow down with age self.partial_move += self.speed if self.partial_move >= 1: self.position = self.find_next_position() self.partial_move = 0 ``` #### 2. **Bomb Units** (`units/bomb.py`) **Timer Bomb Class**: - **Countdown System**: Visual timer (4 stages) before explosion - **Chain Reactions**: Triggers nearby bombs - **Directional Blast**: Explodes in 4 cardinal directions until hitting walls **Nuclear Bomb Class**: - **Instant Kill**: Destroys all rats on the map - **White Flash Effect**: Screen flash on detonation - **Single Use**: Limited to 1 per game **Explosion Class**: - **Temporary Effect**: Short-lived visual and damage entity - **Kill Radius**: Destroys all rats in the same cell - **Score Bonus**: Awards points for each rat killed **Implementation Details**: ```python class Timer(Bomb): def move(self): self.age += 1 if self.age > 160: # 160 ticks = explosion self.die(unit=self, score=10) def die(self, unit=None, score=None): # Create explosion and propagate in 4 directions for direction in ["N", "S", "E", "W"]: # Spread until wall while not self.game.map.is_wall(x, y): self.game.spawn_unit(Explosion, (x, y)) ``` #### 3. **Mine Units** (`units/mine.py`) **Mine Class**: - **Arming Delay**: Becomes active after placement delay - **Contact Trigger**: Detonates when rat steps on it - **Gas Release**: Creates poison gas clouds on detonation - **Limited Supply**: Max 4 mines at a time #### 4. **Gas Units** (`units/gas.py`) **Gas Cloud Class**: - **Lingering Effect**: Stays in place for duration - **Poison Damage**: Accumulates damage on rats over time - **Chaining**: Can spawn additional gas clouds - **Visual Effect**: Semi-transparent gas sprite #### 5. **Point Units** (`units/points.py`) **Point Class**: - **Collection Mechanics**: Auto-collected by player cursor - **Value System**: Different point values (5, 10, 25, 50, 100) - **Timed Existence**: Disappears after ~5 seconds - **Score Tracking**: Updates player score on collection ### Unit Interaction System Units interact through a centralized collision and event system: #### Collision Detection - **Spatial Hashing**: Grid-based lookup for nearby units - **Bounding Box**: Precise pixel-perfect collision detection - **Overlap Tolerance**: Small margin to prevent jittering - **Bi-directional**: Both units check for collisions #### Event System - **Death Events**: Spawn points, trigger explosions, update score - **Reproduction Events**: Create new rat units - **Explosion Events**: Chain reactions, area damage - **Collection Events**: Point pickup, ammo refill #### AI Communication - **Position Tracking**: `unit_positions` dictionary for fast lookup - **Shared Pathfinding**: Avoid blocked cells - **Danger Awareness**: Rats flee from explosions ## Technical Details ### Language & Core Libraries - **Python**: 3.11+ (recommended) - **Rendering**: - `pysdl2` - SDL2 bindings for graphics (original backend) - `pygame` - Pygame library for graphics (new backend) - **Image Processing**: `Pillow` - For image loading and manipulation - **Configuration**: `pyaml` - YAML config file parsing - **Standard Library**: `uuid`, `random`, `os`, `json` ### Performance Optimizations - **Spatial Partitioning**: Grid-based collision detection reduces O(n²) to O(n) - **Texture Caching**: Pre-loaded assets prevent repeated disk I/O - **Background Rendering**: Static maze rendered once, cached as texture - **Delta Time**: Frame-rate independent updates using `partial_move` - **Efficient Drawing**: Only draw units in visible viewport area ### Memory Management - **Automatic Cleanup**: Dead units removed from `units` dictionary - **Surface Reuse**: Blood stains combined into background texture - **Lazy Loading**: Assets loaded on demand - **Reference Counting**: Python GC handles most cleanup ### Architecture Patterns - **Multiple Inheritance**: Game class combines Controls, Graphics, UnitManager, Scoring - **Abstract Base Classes**: `Unit` defines interface for all game entities - **Factory Pattern**: `spawn_unit()` method for dynamic unit creation - **Observer Pattern**: Event-driven input system with callbacks - **Strategy Pattern**: Different AI behaviors for rat types ## Environment Variables Configure the game behavior using environment variables: - `SDL_VIDEODRIVER`: Video driver selection (x11, wayland, etc.) - `RESOLUTION`: Screen resolution in format `WIDTHxHEIGHT` (default: 640x480) - `FULLSCREEN`: Enable fullscreen mode (true/false) - `SOUND_ENABLED`: Enable/disable sound effects (true/false) Example: ```bash RESOLUTION=1920x1080 FULLSCREEN=true python rats.py ``` ## Installation ### Prerequisites - Python 3.11 or higher - pip package manager ### Step-by-Step Installation 1. **Clone the repository**: ```bash git clone https://github.com/yourusername/mice-maze-game.git cd mice-maze-game ``` 2. **Create a virtual environment** (recommended): ```bash python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate ``` 3. **Install dependencies**: For **Pygame backend** (recommended for beginners): ```bash pip install pygame Pillow pyaml ``` For **SDL2 backend** (advanced users): ```bash pip install pysdl2 Pillow pyaml ``` Or install all dependencies: ```bash pip install -r requirements.txt ``` 4. **Run the game**: ```bash python rats.py ``` ### Platform-Specific Notes #### Linux - SDL2 backend requires `libsdl2-dev` package - Install via: `sudo apt-get install libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev` #### macOS - Install SDL2 via Homebrew: `brew install sdl2 sdl2_ttf sdl2_mixer` - Pygame backend works out of the box #### Windows - Pygame backend recommended (easiest setup) - SDL2 backend requires manual SDL2 DLL installation ## Project Structure ``` mice/ ├── engine/ # Core engine components │ ├── controls.py # Input handling system │ ├── graphics.py # Graphics and rendering helpers │ ├── maze.py # Map and collision system │ ├── sdl2_layer.py # SDL2 rendering backend │ ├── pygame_layer.py # Pygame rendering backend ⭐ NEW │ ├── unit_manager.py # Entity spawning and management │ ├── scoring.py # Score tracking system │ ├── user_profile_integration.py # User profile system │ └── score_api_client.py # API client for global leaderboard ├── units/ # Game entity implementations │ ├── __init__.py # Unit package exports │ ├── unit.py # Abstract base class for all units │ ├── rat.py # Rat AI and behavior (Male/Female) │ ├── bomb.py # Bombs, timers, and explosions │ ├── mine.py # Mine traps │ ├── gas.py # Poison gas clouds │ └── points.py # Collectible point items ├── profile_manager/ # Profile management system │ ├── profile_manager.py # Profile CRUD operations │ ├── profile_data.py # Profile data models │ ├── ui_components.py # UI helpers │ └── screens/ # Profile management screens │ ├── screen_manager.py # Screen navigation │ ├── main_menu_screen.py │ ├── profile_list_screen.py │ ├── create_profile_screen.py │ ├── edit_profile_screen.py │ ├── profile_stats_screen.py │ └── leaderboard_screen.py ├── assets/ # Game resources │ ├── Rat/ # Sprite images │ │ ├── BMP_*.png # Various game sprites │ └── decterm.ttf # Font file ├── sound/ # Audio files │ ├── converted/ # Converted audio format │ └── *.WAV # Sound effects ├── conf/ # Configuration files │ ├── keybindings.yaml # Key mapping configuration │ ├── keybindings_*.yaml # Device-specific bindings │ └── keybindings.json # JSON format bindings ├── tools/ # Utility scripts │ ├── convert_audio.py # Audio format converter │ ├── resize_assets.py # Image resizing tool │ └── colorize_assets.py # Asset colorization ├── rats.py # Main game entry point ├── maze.json # Maze layout data ├── user_profiles.json # User profile storage ├── requirements.txt # Python dependencies ├── README.md # This documentation ├── README_PROFILE_MANAGER.md # Profile system documentation └── UNIT_ARCHITECTURE_GUIDE.md # Unit system guide ``` ## Game Files Details ### Core Game Files - **`rats.py`**: Main game controller, entry point, and game loop - **`maze.json`**: Maze layout definition (grid of walls and paths) - **`key.py`**: Additional key handling utilities ### Engine Modules - **`engine/controls.py`**: Input abstraction with configurable bindings - **`engine/graphics.py`**: Graphics helpers (asset loading, background generation) - **`engine/maze.py`**: World representation with collision detection - **`engine/sdl2_layer.py`**: Low-level SDL2 graphics interface - **`engine/pygame_layer.py`**: Pygame graphics interface (new) - **`engine/unit_manager.py`**: Unit spawning and lifecycle management - **`engine/scoring.py`**: Score calculation and persistence ### Unit Implementations - **`units/unit.py`**: Abstract base class defining unit interface - **`units/rat.py`**: Rat AI with pathfinding and reproduction - **`units/bomb.py`**: Explosive units with timer and blast mechanics - **`units/mine.py`**: Trap units with proximity trigger - **`units/gas.py`**: Poison gas clouds with area effect - **`units/points.py`**: Collectible scoring items ### Data Files - **`user_profiles.json`**: Persistent user profile data - **`scores.txt`**: Traditional high score storage (legacy) - **`maze.json`**: Level layout definition ### Configuration - **`conf/keybindings.yaml`**: Key mapping for different game states - **Device-specific configs**: Optimized bindings for different devices ## How to Play ### Objective Eliminate all rats before they reproduce and overwhelm the maze. Collect points by killing rats with bombs, mines, and gas. ### Controls #### Default Keyboard Controls - **Arrow Keys**: Move cursor - **Space**: Place bomb at cursor position - **M**: Place mine at cursor position - **G**: Release poison gas at cursor position - **N**: Deploy nuclear bomb (one-time use) - **P**: Pause game - **F**: Toggle fullscreen - **S**: Toggle sound - **ESC**: Quit game #### Gamepad Support - **D-Pad**: Move cursor - **Button A**: Place bomb - **Button B**: Place mine - **Button X**: Release gas - **Start**: Pause game *Controls can be customized via configuration files in `conf/`* ### Gameplay Tips 1. **Early Game**: Focus on preventing rat reproduction by targeting adults 2. **Bomb Placement**: Use walls to direct explosion paths 3. **Mine Strategy**: Place mines in narrow corridors where rats pass frequently 4. **Gas Tactics**: Gas lingers and accumulates damage - use in rat-dense areas 5. **Nuclear Option**: Save the nuclear bomb for when rats exceed ~150 6. **Resource Management**: Ammo refills randomly - don't waste bombs early 7. **Scoring**: Chain kills and quick clears give bonus points ### Win Condition Clear all rats from the maze without letting their population exceed 200. ### Lose Condition Rat population exceeds 200 - they've overrun the maze. ## Profile System Mice! includes a comprehensive user profile system to track your progress: ### Features - **Multiple Profiles**: Create profiles for different players - **Statistics Tracking**: Games played, wins, losses, best score - **Device Support**: Profile data syncs across devices - **Leaderboards**: Compare scores globally and locally - **Achievements**: Track milestones and accomplishments ### Profile Management Access the profile manager before starting the game: ```bash python profile_manager/profile_manager.py ``` Or manage profiles from within the game main menu. ## Development ### Adding New Units 1. Create a new class in `units/` inheriting from `Unit` 2. Implement required methods: `move()`, `draw()` 3. Optionally override: `collisions()`, `die()` 4. Register in `units/__init__.py` 5. Add spawning logic in `unit_manager.py` Example: ```python from units.unit import Unit class MyUnit(Unit): def move(self): # Update logic here pass def draw(self): # Rendering logic here image = self.game.assets["MY_SPRITE"] self.game.render_engine.draw_image(x, y, image, tag="unit") ``` ### Switching Rendering Backends Edit the import in `rats.py`: ```python # For SDL2 from engine import sdl2_layer as engine # For Pygame from engine import pygame_layer as engine ``` ### Creating Custom Mazes Edit `maze.json` - it's a 2D grid where: - `0` = path/floor - `1` = wall Example: ```json { "maze": [ [1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1] ] } ``` ## Troubleshooting ### Common Issues **Issue**: Game window doesn't appear - **Solution**: Check `RESOLUTION` environment variable, try `640x480` **Issue**: No sound - **Solution**: Verify `SOUND_ENABLED` not set to false, check audio files in `sound/` **Issue**: SDL2 import errors - **Solution**: Switch to Pygame backend or install SDL2 libraries **Issue**: Slow performance - **Solution**: Reduce resolution, close other applications, update graphics drivers **Issue**: Profile data not saving - **Solution**: Check file permissions for `user_profiles.json` ## Contributing Contributions are welcome! Please: 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## License This project is a fan remake of the classic "Rats!" game from Windows 95. ## Credits - **Original Game**: Rats! for Windows 95 - **Developer**: Matteo (because he was bored) - **Engine**: Custom Python engine with SDL2/Pygame backends - **Contributors**: See GitHub contributors page ## Changelog ### Version 2.0 (Current) - ⭐ Added Pygame rendering backend - ⭐ Dual backend support (SDL2 + Pygame) - ⭐ Complete API compatibility between backends - Improved documentation - Enhanced README with technical details ### Version 1.0 - Initial release - SDL2 rendering engine - User profile system - Multiple unit types - Configurable controls - Leaderboard system ## Technical Details - **Language**: Python 3.11 - **Libraries**: - `sdl2` for graphics and window management - `Pillow` for image processing - `uuid` for unique unit identification - `subprocess` for playing sound effects - `tkinter` for maze generation visualization - **Performance Optimizations**: - Spatial partitioning for collision detection - Texture atlasing for reduced memory usage - Object pooling for frequently created/destroyed units - Delta time-based updates for frame rate independence - **Memory Management**: - Automatic cleanup of dead units - Texture caching and reuse - Efficient data structures for large numbers of units ## Environment Variables - `SDL_VIDEODRIVER`: Set the video driver (x11, wayland, etc.) - `RESOLUTION`: Set the screen resolution (format: WIDTHxHEIGHT) - `FULLSCREEN`: Enable/disable fullscreen mode (true/false) - `SOUND_ENABLED`: Enable/disable sound effects (true/false) ## Installation 1. **Clone the repository**: ```bash git clone https://github.com/yourusername/mice-maze-game.git cd mice-maze-game ``` 2. **Create a virtual environment**: ```bash python3 -m venv venv source venv/bin/activate ``` 3. **Install the dependencies**: ```bash pip install -r requirements.txt ``` 4. **Run the game**: ```bash python rats.py ``` ## Project Structure ``` mice/ ├── engine/ # Core engine components │ ├── controls.py # Input handling system │ ├── maze.py # Map and collision system │ └── sdl2.py # Rendering and window management ├── units/ # Game entity implementations │ ├── bomb.py # Bomb and explosion logic │ ├── rat.py # Rat AI and behavior │ └── points.py # Collectible points ├── assets/ # Game resources │ ├── images/ # Sprites and textures │ └── fonts/ # Text rendering fonts ├── sound/ # Audio files ├── maze.py # Maze generation algorithms ├── rats.py # Main game entry point ├── requirements.txt # Python dependencies ├── .env # Environment configuration └── README.md # This documentation ``` ## Game Files Details - `maze.py`: Contains the `MazeGenerator` class implementing DFS algorithm for procedural maze generation - `rats.py`: Main game controller, initializes engine systems and manages game state - `engine/controls.py`: Input abstraction layer with configurable key bindings - `engine/maze.py`: World representation with collision detection and pathfinding support - `engine/sdl2.py`: Low-level graphics interface wrapping SDL2 functionality - `units/bomb.py`: Explosive units with timer mechanics and blast radius calculations - `units/rat.py`: AI-driven entities with reproduction, pathfinding, and survival behaviors - `units/points.py`: Collectible scoring items with visual feedback systems - `assets/`: Game resources including sprites, textures, and fonts - `sound/`: Audio assets for game events and feedback - `scores.txt`: Persistent high score storage - `.env`: Runtime configuration and environment settings - `.gitignore`: Version control exclusion rules