Skip to content

Instantly share code, notes, and snippets.

@decagondev
Created August 1, 2025 18:26
Show Gist options
  • Save decagondev/aebb05c66d5ded42bad65a7d194e6f93 to your computer and use it in GitHub Desktop.
Save decagondev/aebb05c66d5ded42bad65a7d194e6f93 to your computer and use it in GitHub Desktop.

Bandersnatch Game Plan

This document outlines the plan for adding a browser-based text adventure game to the BandersnatchStarter project (https://github.com/BloomTech-Labs/BandersnatchStarter). The game will be a dungeon crawler with minimal graphics, integrated into the existing Flask application. It will use a Player class for stats and state, a MongoDB collection for rooms, randomly spawned monsters from the existing database as enemies, a text-based input/output system, and simple battle mechanics (fight or run). The game will be implemented in a game.py file and integrated into the Flask app.

Objective

Create a text-based adventure game where players navigate dungeon rooms, encounter monsters, and engage in simple battles. Each room will display a text description and a static image, with player input driving navigation and combat. The game will leverage the existing MongoDB database for monster data and extend it with a rooms collection, integrating seamlessly with the Flask app’s structure.

Audience

  • Data Science Beginners: Familiar with Python notebooks, pandas, and basic scikit-learn, but new to Flask and web apps.
  • JavaScript Engineers: Familiar with Node.js/Express and MongoDB, but new to Python/Flask. The plan uses terminology and analogies to bridge both audiences.

Game Features

  1. Player Class:

    • Stores player stats (e.g., health, attack, defense) and state (e.g., current room, inventory).
    • Analogous to a Python class for data science users (like a data structure in a notebook) or a JavaScript class in a Node.js app.
    • Persisted in MongoDB or session storage for continuity.
  2. Room Collection:

    • A MongoDB collection storing dungeon rooms with fields like description, image URL, and possible exits (e.g., north, south).
    • Similar to a MongoDB collection in a Node.js app or a dataset in a pandas DataFrame.
  3. Monster Encounters:

    • Randomly spawn monsters from the existing MongoDB monster collection as enemies in rooms.
    • Use monster attributes (e.g., power) for combat, like querying a DataFrame or MongoDB collection.
  4. Text-Based Input/Output:

    • Players input commands (e.g., "go north", "fight", "run") via a web form.
    • Output is text descriptions of rooms, encounters, and battle results, displayed in HTML.
    • Similar to a notebook cell outputting text or a JavaScript app rendering dynamic content.
  5. Minimal Graphics:

    • Each room displays a static image (e.g., hosted in static/ or an external URL) alongside text.
    • Like embedding an image in a notebook or serving static assets in Express.
  6. Battle Mechanics:

    • Simple turn-based combat: player chooses to fight (compare stats with monster) or run (random success chance).
    • Similar to a notebook script comparing values or a JavaScript game loop with random logic.

Integration with BandersnatchStarter

The game will integrate with the existing Flask app, MongoDB database, and project structure:

  • Flask Routes: Add new routes in app/main.py for game pages (e.g., /game, /game/action).
  • MongoDB: Extend the database with a rooms collection and reuse the monsters collection.
  • Templates: Create HTML/Jinja2 templates for game UI, like existing templates in templates/.
  • Static Assets: Store room images in static/images/, like CSS files in the current setup.
  • Game Logic: Implement in a new game.py file in the app/ directory, imported into main.py.

Project Structure Changes

File/Folder Purpose Notes
app/game.py New file for game logic (Player class, room management, battle mechanics). Like a Node.js controller or a notebook with game functions.
app/main.py Add routes for game (e.g., /game, /game/action). Extend existing Flask routes, like Express endpoints.
templates/game.html HTML template for game UI (text display, input form, room image). Jinja2 template, like EJS in Node.js.
static/images/ Store room images (e.g., room1.jpg). Like public/ in Express, served statically.
data/rooms.py (optional) Script to seed MongoDB rooms collection. Like a Mongoose seed script or notebook data loader.

Implementation Plan

1. Player Class (app/game.py)

  • Purpose: Manage player stats (health, attack, defense) and state (current room, inventory).
  • Implementation:
    • Define a Player class with attributes (e.g., health, current_room_id).
    • Store player state in Flask session or MongoDB for persistence.
    • Methods: move(room_id), fight(monster), run().
  • Hints:
    • Data science users: Think of the class as a structured DataFrame row.
    • JS users: Like a JavaScript class with properties and methods.
  • Resources:

2. Room Collection

  • Purpose: Store dungeon rooms in MongoDB with fields: id, description, image_url, exits (e.g., {'north': 'room2', 'south': 'room1'}).
  • Implementation:
    • Create a rooms collection in MongoDB.
    • Seed with 5–10 rooms (e.g., via a script in data/rooms.py).
    • Query rooms in game.py to get descriptions and exits.
  • Hints:
    • Data science users: Like a DataFrame of room data, queried with pymongo.
    • JS users: Like a MongoDB collection with Mongoose, but using pymongo.
  • Resources:

3. Monster Encounters

  • Purpose: Randomly select monsters from the existing monsters collection for encounters.
  • Implementation:
    • In game.py, query monsters collection randomly (e.g., db.monsters.aggregate([{'$sample': {'size': 1}}])).
    • Use monster attributes (e.g., power) for combat.
  • Hints:
    • Data science users: Like sampling a DataFrame with df.sample().
    • JS users: Like Model.find().limit(1) in Mongoose.
  • Resources:

4. Text-Based Input/Output

  • Purpose: Handle player commands (e.g., "go north", "fight") and display game state.
  • Implementation:
    • Create a /game route to render game.html with room description, image, and form.
    • Create a /game/action route to process POST requests with player input.
    • Parse input (e.g., split into command and argument) and update game state.
  • Hints:
    • Data science users: Like processing user input in a notebook loop.
    • JS users: Like handling form submissions in Express with req.body.
  • Resources:

5. Minimal Graphics

  • Purpose: Display a static image per room alongside text.
  • Implementation:
    • Store images in static/images/ (e.g., room1.jpg).
    • In game.html, use Jinja2 to render <img src="{{ url_for('static', filename='images/room1.jpg') }}">.
    • Store image URLs in the rooms collection.
  • Hints:
    • Data science users: Like displaying an image in a notebook with IPython.display.
    • JS users: Like serving static files in Express and rendering in EJS.
  • Resources:

6. Battle Mechanics

  • Purpose: Allow players to fight or run during monster encounters.
  • Implementation:
    • In game.py, implement Player.fight(monster) (compare stats, e.g., player.attack vs. monster.power) and Player.run() (random success chance, e.g., random.random() > 0.5).
    • Update player health or state based on outcomes.
    • Display results in game.html (e.g., "You defeated the Bandersnatch!" or "You ran away!").
  • Hints:
    • Data science users: Like a notebook function comparing values with random outcomes.
    • JS users: Like a game loop with Math.random() for probability.
  • Resources:

Integration Steps

  1. Create game.py:

    • Define Player class and game logic functions.
    • Include methods for room navigation, monster encounters, and battles.
    • Import pymongo for MongoDB queries and random for encounter logic.
  2. Update app/main.py:

    • Add routes: /game (GET) to display the game UI, /game/action (POST) to handle input.
    • Import game.py functions to manage game state.
  3. Create templates/game.html:

    • Display room description, image, exits, and a form for input (e.g., <input type="text" name="command">).
    • Use Jinja2 to render dynamic content (e.g., {{ room.description }}).
  4. Seed Rooms:

    • Create a script (e.g., data/rooms.py) to insert 5–10 rooms into MongoDB.
    • Example room: {'id': 'room1', 'description': 'A dark cave...', 'image_url': 'images/room1.jpg', 'exits': {'north': 'room2'}}.
  5. Add Static Images:

    • Place room images in static/images/.
    • Ensure image_url in the rooms collection points to these files.
  6. Test Locally:

    • Run the app (python -m app.main or ./run.sh) and test at http://127.0.0.1:5000/game.
    • Debug like a Node.js app (check terminal logs) or notebook (test functions incrementally).
  7. Deploy to Render.com:

    • Update requirements.txt if new libraries are added (e.g., python-dotenv).
    • Ensure static/images/ is included in the Git repository.
    • Update Render’s start command (gunicorn app.main:APP) and DB_URL environment variable.

Technical Considerations

  • Dependencies: Add python-dotenv (for .env) and ensure pymongo, flask are in requirements.txt.
  • MongoDB: Reuse the existing DB_URL from .env for the rooms collection.
  • Session Management: Use Flask’s session to store temporary player state, like req.session in Express.
  • Error Handling: Validate player input (e.g., valid commands) and handle MongoDB query errors, like try/catch in JS.
  • Performance: Limit room and monster queries to small datasets for fast response times, like optimizing Mongoose queries.

Resources for Implementation

Success Criteria

  • Players can navigate rooms via text commands (e.g., "go north").
  • Rooms display a description and image in the browser.
  • Random monster encounters occur, with fight/run options.
  • Battle outcomes update player health and display results.
  • The game integrates with the existing Flask app and MongoDB database.
  • The app runs locally and deploys to Render.com without errors.

Stretch Goals

  • Add inventory system (e.g., items in Player class, stored in MongoDB).
  • Implement multiple enemy types with varied stats.
  • Add ASCII art in text output for flair, like a console game.
  • Allow saving/loading player progress in MongoDB.
  • These align with the README’s stretch goals (e.g., database reset) and are approachable for both audiences.

Notes for Developers

  • Data Science Users: Treat game.py like a notebook: break logic into functions (e.g., move, fight), test incrementally, and use pandas for data manipulation if needed.
  • JS Engineers: Think of game.py as a Node.js module, Flask routes as Express endpoints, and Jinja2 as EJS. Debug like a web app with browser dev tools and terminal logs.
  • Start small: implement one room, one monster encounter, and one battle before scaling up.
  • Use the existing project structure (app/, templates/, static/) to keep integration clean.

This plan sets the stage for implementing the game in game.py, ensuring it fits the BandersnatchStarter project and is accessible for both audiences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment