Skip to content

Rinrino/filler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rust Docker License: MIT

🤖 Filler AI: Advanced Rust Bot & Analysis Suite

An algorithmic AI bot developed for the 01Founders Rust curriculum. This project features a high-performance bot with a dynamic state-machine strategy and a custom SDL2 visualizer with built-in fairness auditing.

📖 Project Overview

Filler is a competitive game where two bots fight for territory on a grid (the Anfield).

  • The Rule: Each new piece must overlap exactly one cell of your existing territory.

  • The Victory: The player who occupies the most surface area when no more moves are possible wins.

🧠 Bot Strategy: Dynamic State Analysis

My AI utilizes a Dynamic State Machine that adapts its scoring weights based on the current proximity to the opponent and available mobility.

1. State-Based Heuristics

The bot detects the game phase in state.rs and adjusts its "Brain" in strategy.rs:

  • Expansion Phase: Focuses on perimeter growth to secure a large bounding box.

  • Engagement Phase: Scales a mobility_factor based on how many moves the opponent has. If the opponent is more mobile, the bot shifts to Aggressive Blocking.

  • Combat Phase: Focuses exclusively on Frontier Control, identifying cells that directly block the opponent's access to external space.

2. Advanced Frontier Detection

Instead of a simple heatmap, the bot uses Graph Theory to evaluate the map:

  • Frontier Analysis: Uses a BFS "Flood Fill" to identify "External Empty Space" reachable from the borders. Only cells touching this "Air" are high-priority targets.
  • Trap Recognition: Identifies "Trapped" regions (cells surrounded on 3+ sides) to avoid wasting moves in territory that is already effectively secured.

🎨 Visualizer & Audit Suite

The visualizer (built with SDL2) serves as both a playback tool and a statistical referee.

✨ Key Features:

  • Interactive Playback
    Use Space to pause, Left/Right arrows to step through moves, and Up/Down to adjust playback speed.

  • Scientific Audit
    Upon match completion, the terminal outputs an Early Game Fairness Analysis.
    It calculates the total "cell area" offered to each player up to the first pass to determine whether a win was due to strategy or "luck of the draw".

  • Real-time Pass Tracking
    Visual markers (STUCK) appear the moment a player is unable to place a piece, clearly highlighting the "bonus turns" taken by the winner.

  • Dynamic Scaling
    Automatically resizes the UI to fit any Anfield size, from $10 \times 10$ to $100 \times 100$.

  • Zero-Cost Diagnostics: Uses a custom debug_log! macro that yields 0ms overhead during competition.

🎬 Visualization

AI Gameplay Demo
🎮 Interactive Visualizer Controls
Rinbo AI expanding on Map00
Key Action
SpacePause / Resume
Left / RightStep Turn
Up / DownSpeed +/-
RRestart
Audit Analysis Report
📊 Game Analysis Report
Scientific fairness breakdown
• Active Phase: Both players moving.
• Resource Gap: Balanced if the gap is < 1.5 units.
• Winner's Lap: Solo turns at end.

📂 Project Structure (AI Machine and Visualizer)

filler/
├── docker_image/            # Docker setup: game_engine, robots, maps
├── solution/                # AI logic program (Rinbo)
│   ├── src/
│   │   ├── main.rs          # Entry point
│   │   ├── game/            # Game modules
│   │   │   ├── mod.rs       # Re-exports the modules
│   │   │   ├── anfield.rs   # Parsing & grid representation
│   │   │   ├── piece.rs     # Piece parsing and shape utils
│   │   │   ├── strategy.rs  # Core move decision logic
│   │   │   ├── token.rs     # Player token management
│   │   │   └── state.rs     # GameState to control the strategy
│   ├── Cargo.toml
│   └── Cargo.lock
│
└── viz/              # visualizer program
    ├── assets/       # font for text
    ├── src/
    |   ├── game/     # Game modules (anfield, piece, etc.)
    |   ├── parser/   # STDIN stream parsing
    |   ├── draw/     # SDL2 rendering logic
    |   ├── analyze/  # Game analysis & fairness logic
    │   ├── main.rs   # Entry point for visualizer
    ├── Cargo.toml
    └── Cargo.lock

🚀 Getting Started

1️⃣ Prerequisites (Host Machine)

  • Docker (Desktop or CLI)

  • Rust toolchain: Rustup

  • For the Visualizer, install SDL2 development libraries:

    • 🐧 Linux (Debian/Ubuntu): sudo apt install libsdl2-dev libsdl2-ttf-dev
    • 🍎 macOS: brew install sdl2 sdl2_ttf
    • 🪟 Windows: Follow Rust-SDL2 Windows guide or use vcpkg.

2️⃣ Project Setup

1. Clone the repository:

git clone https://github.com/Rinrino/filler.git
cd filler

2. Download & Prepare Docker Assets:

  • Download the official assets: filler.zip

  • Unzip it → you should now have a docker_image/ folder.

  • Prepare binaries (inside docker_image/):

cd docker_image

# For standard Linux/x86_64 users:
rm -f m1_game_engine m1_robots          # Remove Apple Silicon files
mv linux_game_engine game_engine
mv linux_robots robots
chmod +x game_engine robots/*
cd ..

Apple M1/M2 users: rename the m1_* files instead (e.g. mv m1_game_engine game_engine).

3. Update / use this Dockerfile:

FROM rust:1.78-slim-bookworm

COPY ./maps /filler/maps
COPY ./robots /filler/robots
COPY ./game_engine /filler/game_engine

RUN chmod +x /filler/game_engine && chmod +x /filler/robots/\*

WORKDIR /filler

ENTRYPOINT ["/bin/bash"]

4. Build the image:

docker build -t rinbo ./docker_image

3️⃣ Running the AI (Inside Container)

1. Launch & Mount:

docker run -v "$(pwd)/solution":/filler/solution -it rinbo

2. Compile Rinbo:

cd /filler/solution && cargo build --release

3. Run a Match:

# Navigate back to the engine directory
cd /filler

# High Performance Mode (Recommended for tournaments)
./game_engine -f maps/map01 -p1 robots/bender -p2 ./solution/target/release/rinbo

# Debug Mode (Generates 'rinbo_debug.log')
RINBO_DEBUG=1 ./game_engine -f maps/map01 -p1 robots/bender -p2 ./solution/target/release/rinbo

Player Role Selection

  • To play as Player 1 (@):
./game_engine -f maps/map01 -p1 ./solution/target/release/rinbo -p2 robots/terminator
  • To play as Player 2 ($):
./game_engine -f maps/map01 -p1 robots/bender -p2 ./solution/target/release/rinbo

When finished: type exit

4️⃣ Feed Output to Visualizer (Host Machine)

Option 1. Live Stream (Recommended) Run this from the project root. This uses your host's local binaries to pipe data into the UI:

./docker_image/game_engine -f ./docker_image/maps/map01 -p1 ./docker_image/robots/terminator -p2 ./solution/target/release/rinbo | cargo run --release --manifest-path viz/Cargo.toml

Option 2: Playback from Log If you want to save a match and watch it later:

# 1. Generate the log
./docker_image/game_engine -f ./docker_image/maps/map01 -p1 ./solution/target/release/rinbo -p2 ./docker_image/robots/terminator > output.log

# 2. Open in visualizer
cargo run --release --manifest-path viz/Cargo.toml < output.log

🛠️ Technical Critique: The "Bounding Box" Bug

During development, a significant architectural limitation was identified in the game_engine piece generation.

The Conflict:

  • Engine Logic: The engine generates pieces within a rectangular bounding box that often includes several rows/columns of "empty" padding (.) at the top or left.
  • Protocol Requirement: The bot must return the $(X, Y)$ coordinate for the top-left corner of the provided box.
  • Validation Rule: The engine strictly requires $X \ge 0$ and $Y \ge 0$.

The Impact: "The Dead Zone"

If a piece has "padding" (empty dots) on its top or left side, it becomes mathematically impossible to place the actual shape against the top or left edges of the Anfield.

  • Example: To place a shape at Row 0, using a box with 1 row of top-padding, the bot would need to return Y = -1.
  • Because the engine rejects negative coordinates, these moves are lost,creating "dead zones" on the map.

✨ My Solution: filler-game-engine

I developed a custom, high-performance remake of the engine in Rust that implements a trim_and_build algorithm. This strips all external padding from pieces before transmission, ensuring 100% of the Anfield grid is playable and fair.

⚖️ License

This project is licensed under the MIT License - see the LICENSE file for details.

👩🏻‍💻 Author

About

🤖 High-performance Filler AI developed in Rust. Features a dynamic state-machine strategy (BFS Frontier Analysis) and a custom SDL2 visualizer with built-in statistical fairness auditing.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages