Monstoryum is a classic text RPG adventure game. It is programmed in Python to be played in a terminal.
The player begins the game locked in a jail cell and is immediately attacked by a monster. The player must complete challenges in different spaces, encountering various monsters en route, in order to escape. It is deployed in a mock terminal.
MonStoryum was developed to showcase the Python skills of the website developer.
The target audience for MonStoryum:
- The game is aimed at all fans of classic RPG games
User goals are:
- Have fun
- Be immersed in the story
- Complete challenges, learn strategies to beat the game
- Replay the game after playing all the way through
MonStoryum fills these needs by:
- Providing a challenging game
- Providing detailed descriptions of all rooms, monsters and items
- Providing a variety of challenges for the player to complete in each room
- Providing an extra, optional, challenge for the player before completing the game
The Business Goals of MonStoryum are:
- Provide a fun game to engage visitors to the website
- Showcase the skills of the website owner
- As a user, I expect the game commands to be clear
- I expect feedback on any input I enter
- I expect to be able to check the status and inventory of my character
- I expect to be able to compare my results with other players at the end of the game
-
The concept for the game was to have a linear set of rooms, with the option to only go forwards or backwards, in order to keep the scope manageable.
-
I initially created the classes that I would need to create the game content.
-
Since item objects are also attributes of other classes, I had to make the item class first.
-
Monsters and features are attributes of the room class, so needed to be created next.
-
Once these classes had been created, the rooms could be created and populated.
-
The Player and Dragon classes were added as extensions of the Monster class. The Player class adds methods relating to the inventory and status actions. The Dragon class adds a talk method, which calls the hangman game.
-
The hangman game was made as an independent game, for testing purposes and then imported to the main game.
-
Due to the size of the program, the code was refactored into modules:
- run.py calls the create game and enter room functions to start the game
- create_game.py imports all of the classes and creates object instances that are needed for the game, monsters, items, features, rooms. As the Player class is an extension of the Monster class, it is also created here, and the player is prompted to enter a name
- play_turn.py contains all of the functions that run once the game has started, with the exception of the endgame functions and clear_console function
- endgame.py contains the functions that end the game, and updates the Google Sheet containing the Hall of Fame data
- clear.py contains a function to clear the console
- hangman.py contains the hangman mini-game within the game
- The other modules (item.py, monster.py, feature.py, room.py) contain the classes used for the game
The start screen prompts the player to choose a name before starting the game
- The examine room screen appears at the beginning of the game, when a player enters a room, or when the player types 'examine room'
- It contains a description of the room, along with all of the items, features and monsters in the room
- When the room has been visited, a shorter description appears
-
The status tables show important information about the player
-
Which weapon the player has equipped
-
Which armor the player has equipped
-
The current and maximum HP of the player
-
The Inventory table shows which items the player is carrying, along with important information about the item
-
The items are grouped by category
- Weapons
- Armor
- Potions
- Keys
-
Target select allows players to choose a target by entering a number from a list
-
Target select is shown when
- The player does not specify a target
- There is more than one instance of the same monster
-
Examine select allows players to choose an item/monster/feature by entering a number from a list
-
Examine select is shown when there is more than one instance of the item/monster/feature
-
The Hall of Fame is shown at the end of the game, either when the player dies, or wins the game
-
The player results are stored in Google Sheets using the gspread API
-
The table shows which room the player reached, which monster they were killed by or if they escaped and won the game
-
The gold medallion can bet obtained by killing the dragon before leaving the dungeon and is an extra challenge for those who have already beaten the game
- random
- randomising initial game variables
- randomising attack hits and damage
- math
- rounding up randomly generated numbers to whole numbers
- time
- delay between attacks
- delaying console clear to allow time to read messages
- os
- clear the console on all operating systems
- operator
- sort the Hall of Fame by column
- rich
- coloured text output
- identify objects the player can interact with
- highlight important information
- prettytable
- print out information in tables
- Inventory, status, Hall of Fame
- gspread
- required for the gspread API
- Gspread
- Store player results in the Hall of Fame
- Github
- Storing code remotely
- Gitpod
- IDE for project development
- Heroku
- Deployment
- Google Sheets
- Storing the Hall of Fame data
- Google Cloud
- Managing the gspread API
-
autopep8 was used to automatically format the code
-
most of the remaining errors were lines that were too long, which had to be changed manually
-
The following warnings from Pylint remain
-
Rich redefines the print function, which was used for colour in the game
-
The formatting warnings relate to the argument of a table in prettytable, using and f string caused the data to display incorrectly, therefore I did not change it to an f string
-
The unused arguments were needed for Monster methods which were redefined for subclassses, so that I could call the method with all Monster objects without an error
-
-
One error from Flake8 remained regardless of the indentation I used
-
Inputs were tested at each stage of developent, they would be too lengthy to put into a table
-
The program was tested with repeated runthroughs after completion
There are no unfixed bugs that I am aware of.
The endgame functions originally called the main function to restart the game and break out of the start_turn loop.
However after refactoring the code to modules, these caused an import recursion error. Therefore I refactored to code to exit the loop when the game had finished. This caused several bugs, where the game would continue the loop when it ended, or text was printed that should not appear on the screen. I had to fix these by introducing extra variables and condition checks to exit the loop when the game ended.
I also refactored recursive function calls to while loops.
Because the Enter_room function calls the start_turn function, which in turn calls the enter_room function when the player chooses to enter a new room, there is still a recursion loop in the code. This could be refactored by putting the enter_room function in while loop, and returning the room number from the start_turn function instead of calling the enter_room function again. However due to time constraints I fixed this in an inelegant way by recursively exiting the function at the end_game.
-
add a room map, that updtes when the player explores
-
add a seconds room index, so that the player has a choice of directions and the game is not linear
-
add friendly monster mechanics
Note: in order to deploy the game, you will need a copy of the creds.json file, which is not included in the github repository for security reasons.
-
Open a terminal in the folder you want to clone the project to.
-
In the terminal type:
git clone https://github.com/alexrobincrabbe/Monstoryum
-
Change to the repository folder:
cd .\Boopball\
-
Install requirements:
pip install -r requirements.txt
-
Run the game:
pip install -r requirements.txt
-
Open a terminal in the folder you want to clone the project to.
-
In the terminal type:
git clone https://github.com/alexrobincrabbe/Boopball
-
Change to the repository folder:
cd .\Boopball\
-
Remove the origin:
git remote rm origin"
-
On Github, create a new repository with a name of your choosing.
-
Add your Github repository to the origin:
git remote add origin <url of your repository>
-
Push the files to your repository:
git push --set-upstream origin main
-
You will need a Heroku account and to log into it
-
Click on New --> Create new app
-
Choose an app name, and your region --> click create app
-
Click on the setting tab
-
Add buildpack Python
-
Add buildpack NodeJs
-
Click on Reveal Config Vars
-
Enter key "PORT" and value "8000"
-
Enter key "CREDS" and value will be the content of the creds.json file
-
Click on the deploy tab
-
Click on connect to github
-
Enter the path to your github repository
-
Click on deploy branch
Thanks to Leda for helping with the room descriptions