Pokémon Text Adventure is a short text adventure about encountering and battling wild Pokémon.
Like the start of any Pokémon game, the player is able to choose a starter Pokémon. They can choose between Bulbasaur, Charmander, or Squirtle. However, the Pokémon Professor won’t let the player venture out on their own until they’ve raised their level 5 starter to level 10. They must roam the grassy fields outside of town and battle wild Pokémon in order to strengthen their starter. Only then can they truly begin their Pokémon journey.
- An overworld rendered using text characters
- Overworld screen is top-down and player can move around freely like in actual Pokémon
- A Pokémon inspired battle system with leveling progression and random encounters
- C# Command Console
- Individual (100 Hours)
The Pokémon name and all elements thereof are registered trademarks of The Pokémon Company, a subsidiary of Nintendo Co., Ltd. This was a student project for the Guildhall at SMU. I do not own anything related to the Pokémon name. I’m only using it as a part of this project which is purely for academic and non-profit reasons.
All music is from Pokémon Red/Blue. Composer: Junichi Masuda
I coded Pokémon Text Adventure entirely in C#, using Microsoft Visual Studio as an editor. One of my biggest accomplishments was being able to draw everything using text characters. Having things render to the screen allowed me to create a top-down overworld that the player can freely move around in. This overworld, plus a battle system, leveling progression, and random encounters helped make the text adventure feel more like actual Pokémon.
I wanted my text adventure to feel as much like Pokémon as possible while still remaining simple enough for me to implement on my own. The text adventure’s story closely mimics the beginning of a Pokémon game in that the player battles wild Pokémon outside their home town. Other elements such as music from Pokémon Red/Blue and being able to raise a starter helped make the experience feel more authentic. I feel that I was successful in capturing the core of Pokémon with my text adventure.
With traditional text adventures, players usually only have text that describes things to them and when it comes to movement, players simply type in the direction they want to go. I thought it’d be a fun challenge to have a world the player can move around in and actually see. Adding this feature made my text adventure unique and reinforced my other goal of making a simplified version of Pokémon. I’m really glad I was able to meet this challenge.
I designed Pokémon Text Adventure’s overworld structure like that of the original Legend of Zelda. The overworld is a series of screen-sized areas and the player transitions between areas by moving to the edge of the screen. Below are two maps: a map of all the areas and a map showing which Pokémon exist in those areas.
The overworld only contains two objects: walls and grass. Walls are barriers the player cannot move past. They serve to confine the player within the world and to form various structures that make the overworld layout more interesting. Grass acts just like tall grass from Pokémon games. When the player walks through grass, they have a chance of encountering wild Pokémon. I wanted the text adventure to be short, so I made the overworld small. However, though it is small, it still has multiple areas for the player to visit.
I based the Pokémon locations around the battle system’s support for type advantages. The player can choose a starter of Grass, Fire, or Water type. As such, I wanted the player to have a good chance to encounter wild Pokémon they have an advantage over regardless of which starter they chose. That is why each area has one Pokémon of each type.
I based the levels of wild Pokémon on the player’s starting location. Since the player begins the game in the bottom-middle area, I wanted that area and those that surround it to have low level Pokémon. The areas further away have higher level Pokémon. I did this so the player does not initially encounter Pokémon that are too strong for them to defeat. This was my way of avoiding player frustration.
I spit the text adventure’s code is into three separate scripts. TextAdventure.cs does the bulk of the work. It is responsible for rendering everything, handling player input, managing the battle system, and tracking player progression. Pokémon.cs defines what a Pokémon is. It specifies a Pokémon’s stats, how they battle, and how they level up. Finally, Area.cs creates the overworld, which is composed of screen-sized areas. This script states how these areas are connected, which Pokémon the player can find in each area, and what level those Pokémon are.
TextAdventure.cs is the general manger for the text adventure and is where program execution begins. As such, it is responsible for initializing all variables and tracking player progression. TextAdventure.cs uses the other two scripts to define the world that it manages.
This script’s core is a main gameplay loop, which checks the state the text adventure is in. This is important as the text adventure behaves differently depending on its state. For example, when the text adventure is in the Overworld state, it renders the overworld, handles player movement, and monitors whether the player has initiated a Pokémon battle.
The gameplay loop accomplishes its goals by calling major functions, which then call smaller helper functions. The functions the gameplay loop calls depends on the state. Additionally, the state changes when the player performs certain actions or when certain events occur.
Pokémon.cs outlines a Pokémon‘s stats, how it battles, and how it levels up. This script defines nine Pokémon species, three of which are starters the player can choose from as their companion. The other six are wild Pokémon the player encounters in the overworld. Each Pokémon has a dictionary, which specifies all its stats for whatever level the Pokémon is. TextAdventure.cs accesses these dictionaries to manage Pokémon battles and to display stats to the player.
Besides accessing stats, TextAdventure.cs also calls multiple functions inside of Pokémon.cs. The three most important of these functions are the ones that calculate damage, experience, and level-up eligibility for Pokémon battles.
During a battle, TextAdventure.cs uses a function in Pokémon.cs to calculate damage for the battling Pokémon until one of them loses all their HP and faints. If the player won, TextAdventure.cs then uses Pokémon.cs to calculate how much experience their Pokémon should receive. Finally, if the experience the player’s Pokémon receives pushes its total experience over a certain threshold, TextAdventure.cs calls a function in Pokémon.cs that levels-up the Pokémon.
Area.cs defines the text adventure’s overworld. The overworld is a collection of areas with connections between them, similar to a graph of nodes. For any given area, this script defines the areas it has connections to. The script calls these connections Neighbors. When the player moves between areas in the overworld, TextAdventure.cs uses Area.cs to find the appropriate Neighbor, sets it as the current area, and transitions the player to it.
All the areas in Area.cs contain a string of characters that represents their layout. TextAdventure.cs reads in these strings in order to initialize the overworld before the player begins the game. Additionally, each area has a list of Pokémon that exist within it. Area.cs specifies these Pokémon and their levels. When the player initiates a Pokémon battle, TextAdventure.cs grabs a random Pokémon from the current area’s list and sets it as the wild Pokémon for the player to battle.
The battle system borrows many standard elements from the Pokémon battle system. The player battles wild Pokémon with their own starter Pokémon. The player enters battle by walking in tall grass until a wild Pokémon appears. During battle, both Pokémon take turns attacking each other until one of them faints. If the player wins, their starter gains experience. With enough experience, the starter levels up and its stats increase.
If you look at the Rules section, you’ll see the procedures that govern how battles take place. I felt this set of rules was large enough to encompass the majority of Pokémon’s battle system and small enough to remain simplistic. I purposefully left out elements like items, multiple moves, and capturing Pokémon to keep things simple. Pokémon Text Adventure is not a faithful recreation of Pokémon, but rather a simple Pokémon tech demo. I wanted the battle system to reflect this.
- Type Advantages: GRASS beats WATER, WATER beats FIRE, FIRE beats GRASS
- In battle, a Pokémon with a type advantage over the other will do 2x damage. If the Pokémon has a type disadvantage, they do 0.5 damage. Finally, two Pokémon of the same type do normal damage to each other.
- After every battle, your Pokémon is automatically healed.
- If your Pokémon faints, the battle ends and your Pokémon is still automatically healed.
- Each Pokémon has three stats: Attack (Atk), Defense (Def), and Speed (Spd)
- The Atk stat is how much damage a Pokémon does. The attacker’s Atk stat minus the target’s Def stat determines the actual damage the target takes.
- The Spd stat determines which Pokémon attacks first in battle. The Pokémon with the higher Spd stat attacks first.
At first, I didn’t think what I wanted to do was going to work. I had never heard of a text adventure where the player could move around the screen in real time. I also didn’t know how I was going to do things like collision detection in the overworld. I’m really glad I was successful and I’m proud of the work I did.
If I were going to go back and do this project from scratch, I would split TextAdventure.cs into smaller separate scripts. I divided logic with things like the Pokémon.cs and Area.cs, but I could have done more. For example, all the rendering logic should have had its own script. It would have been much cleaner and I could have reused the rendering script in future projects.
Besides each starter having a different type, they were pretty much the same. I tried to differentiate them a little by having one with higher attack, one with higher defense, and one with higher speed. However, these distinctions weren’t strong enough to make a real difference. In general, I could have done a better job differentiating the wild Pokémon too. I know meaningful choices are important in games, especially RPGs. If I did this project again, I would do better to facilitate meaningful choices.
I learned to do so many cool things with nothing but text. Being limited to only text forced me to get creative and gave me the chance to push what I could do with it. I also found that making a text adventure was a great programming exercise. Since there aren’t things like 3D or physics to consider, all my focus was on logic. Making a text adventure was programming logic in one of its simplest and purest forms.
RPGs are one of my favorite game genres. With this project, I learned how they work on at least a simple level. I made a battle system, managed player progression, and even had random encounters. I think my choice to do Pokémon was a smart one, because it was simple enough to mimic and I learned a lot about how Pokémon works programming wise.