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.
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.
- 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.
-
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.
-
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.
-
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.
-
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.
-
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.
- Each room displays a static image (e.g., hosted in
-
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.
The game will integrate with the existing Flask app, MongoDB database, and project structure:
- Flask Routes: Add new routes in
app/main.pyfor game pages (e.g.,/game,/game/action). - MongoDB: Extend the database with a
roomscollection and reuse themonsterscollection. - 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.pyfile in theapp/directory, imported intomain.py.
| 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. |
- Purpose: Manage player stats (health, attack, defense) and state (current room, inventory).
- Implementation:
- Define a
Playerclass 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().
- Define a
- Hints:
- Data science users: Think of the class as a structured DataFrame row.
- JS users: Like a JavaScript class with properties and methods.
- Resources:
- Purpose: Store dungeon rooms in MongoDB with fields:
id,description,image_url,exits(e.g.,{'north': 'room2', 'south': 'room1'}). - Implementation:
- Create a
roomscollection in MongoDB. - Seed with 5–10 rooms (e.g., via a script in
data/rooms.py). - Query rooms in
game.pyto get descriptions and exits.
- Create a
- Hints:
- Data science users: Like a DataFrame of room data, queried with
pymongo. - JS users: Like a MongoDB collection with Mongoose, but using
pymongo.
- Data science users: Like a DataFrame of room data, queried with
- Resources:
- Purpose: Randomly select monsters from the existing
monsterscollection for encounters. - Implementation:
- In
game.py, querymonsterscollection randomly (e.g.,db.monsters.aggregate([{'$sample': {'size': 1}}])). - Use monster attributes (e.g.,
power) for combat.
- In
- Hints:
- Data science users: Like sampling a DataFrame with
df.sample(). - JS users: Like
Model.find().limit(1)in Mongoose.
- Data science users: Like sampling a DataFrame with
- Resources:
- Purpose: Handle player commands (e.g., "go north", "fight") and display game state.
- Implementation:
- Create a
/gameroute to rendergame.htmlwith room description, image, and form. - Create a
/game/actionroute to process POST requests with player input. - Parse input (e.g., split into command and argument) and update game state.
- Create a
- Hints:
- Data science users: Like processing user input in a notebook loop.
- JS users: Like handling form submissions in Express with
req.body.
- Resources:
- 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
roomscollection.
- Store images in
- 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.
- Data science users: Like displaying an image in a notebook with
- Resources:
- Purpose: Allow players to fight or run during monster encounters.
- Implementation:
- In
game.py, implementPlayer.fight(monster)(compare stats, e.g.,player.attackvs.monster.power) andPlayer.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!").
- In
- 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:
-
Create
game.py:- Define
Playerclass and game logic functions. - Include methods for room navigation, monster encounters, and battles.
- Import
pymongofor MongoDB queries andrandomfor encounter logic.
- Define
-
Update
app/main.py:- Add routes:
/game(GET) to display the game UI,/game/action(POST) to handle input. - Import
game.pyfunctions to manage game state.
- Add routes:
-
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 }}).
- Display room description, image, exits, and a form for input (e.g.,
-
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'}}.
- Create a script (e.g.,
-
Add Static Images:
- Place room images in
static/images/. - Ensure
image_urlin theroomscollection points to these files.
- Place room images in
-
Test Locally:
- Run the app (
python -m app.mainor./run.sh) and test athttp://127.0.0.1:5000/game. - Debug like a Node.js app (check terminal logs) or notebook (test functions incrementally).
- Run the app (
-
Deploy to Render.com:
- Update
requirements.txtif 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) andDB_URLenvironment variable.
- Update
- Dependencies: Add
python-dotenv(for.env) and ensurepymongo,flaskare inrequirements.txt. - MongoDB: Reuse the existing
DB_URLfrom.envfor theroomscollection. - Session Management: Use Flask’s
sessionto store temporary player state, likereq.sessionin 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.
- Flask for Game Routes: Flask Tutorial (covers routes and templates).
- PyMongo for Rooms/Monsters: PyMongo Docs (MongoDB queries in Python).
- Jinja2 for UI: Jinja2 Docs (dynamic HTML rendering).
- Python Classes for Player: Python Classes Tutorial (class basics).
- Random Logic for Battles: Python Random Module (random number generation).
- Static Files for Images: Flask Static Files (serving images).
- 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.
- Add inventory system (e.g., items in
Playerclass, 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.
- Data Science Users: Treat
game.pylike 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.pyas 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.