This is an abbreviated version of the book Make Your Own Python Text Adventure.
All games take place in some sort of world. The world can be as simple as a chess board or as complex as the Mass Effect universe and provides the foundation for the game as a whole. All elements of a game reside in the world and some elements interact with the world. In this post, you’ll learn how to add items and enemies to your world.
The coordinate plane
A text adventure usually involves a player moving through the world one section per turn. We can think of each section as a tile on an x-y grid. Note: in most game programming the x-y coordinate plane is different from the one you learned in algebra. In the game world, (0,0) is in the top left corner, x increases to the right, and y increases to the bottom.
Creating tiles
Start by creating a module tiles.py with this class:
import items, enemies
class MapTile:
def __init__(self, x, y):
self.x = x
self.y = y
The import
keyword means “give this module access the ‘items’ module and ‘enemies’ module. We need this because we will want to put these elements inside some of our rooms.
The MapTile
class is going to provide a template for all of the tiles in our world, which means we need to define the methods that all tiles will need. First, we’ll want to display some text to the user when they enter the tile that describes the world. We also expect that some actions may take place when the player enters the tile, and that those actions change the state of the player (e.g., they pick something up, they win the game, something attacks them, etc.). Let’s add those methods now.
def intro_text(self):
raise NotImplementedError()
def modify_player(self, player):
raise NotImplementedError()
We haven’t talked about the code for the player yet, but that’s OK. The player
parameter will serve as a placeholder. As you might guess, these methods aren’t going to do much in their current state. In fact, they will actually cause the program to crash! This might seem silly, but this behavior is to help us as programmers.
When thinking about our world, we don’t want to have tiles that do nothing. We may want tiles of water, tiles in a spaceship corridor, tiles with other characters, or tiles with treasure, but not empty tiles. So this MapTile
class is actually just a template that all other tiles will expand on.
In the last post we learned about base classes. MapTile
is actually a specific flavor of a base class. We call it an abstract base class because we don’t want to create any instances of it. In our game, we will only create specific types of tiles. We will never create a MapTile
directly, instead we will create subclasses. The code raise NotImplementedError()
will warn us if we accidentally create a MapTile
directly.
Now on to our first tile subclass!
class StartingRoom(MapTile):
def intro_text(self):
return """
You find yourself if a cave with a flickering torch on the wall.
You can make out four paths, each equally as dark and foreboding.
"""
def modify_player(self, player):
#Room has no action on player
pass
This class extends MapTile
to make a more specific type of tile. We override the intro_text
and modify_player
methods to implement the specific behavior that this tile should have. A method is overridden when a subclass has the same method name as a superclass. Because it’s the starting room, I didn’t want anything to happen to the player. The pass
keyword simply tells Python to not do anything. You might wonder why the method is even in this class if it doesn’t do anything. The reason is because if we don’t override modify_player
, the superclass’s modify_player
will execute and if that happens the program will crash because of raise NotImplementedError()
.
Next, let’s add a class for the tile where a player will find a new item.
class LootRoom(MapTile):
def __init__(self, x, y, item):
self.item = item
super().__init__(x, y)
def add_loot(self, player):
player.inventory.append(self.item)
def modify_player(self, player):
self.add_loot(player)
Remember, we haven’t created player
yet, but we can guess that the player will have an inventory.
Let’s define one more type of room: a room in which the player encounters an enemy.
class EnemyRoom(MapTile):
def __init__(self, x, y, enemy):
self.enemy = enemy
super().__init__(x, y)
def modify_player(self, the_player):
if self.enemy.is_alive():
the_player.hp = the_player.hp - self.enemy.damage
print("Enemy does {} damage. You have {} HP remaining.".format(self.enemy.damage, the_player.hp))
This constructor should look familiar to you now. It’s very similar to the LootRoom
constructor, but instead of an item, we are working with an enemy.
The logic for this room is a bit different. I didn’t want enemies to respawn. So if the player already visited this room and killed the enemy, they should not engage battle again. Assuming the enemy is alive, they attack the player and do damage to the player’s hit points.
Now that we have some basic types of tiles defined, we can make some even more specific versions. Here are some that I created:
class EmptyCavePath(MapTile):
def intro_text(self):
return """
Another unremarkable part of the cave. You must forge onwards.
"""
def modify_player(self, player):
#Room has no action on player
pass
class GiantSpiderRoom(EnemyRoom):
def __init__(self, x, y):
super().__init__(x, y, enemies.GiantSpider())
def intro_text(self):
if self.enemy.is_alive():
return """
A giant spider jumps down from its web in front of you!
"""
else:
return """
The corpse of a dead spider rots on the ground.
"""
class FindDaggerRoom(LootRoom):
def __init__(self, x, y):
super().__init__(x, y, items.Dagger())
def intro_text(self):
return """
Your notice something shiny in the corner.
It's a dagger! You pick it up.
"""
If you remember, I also created an Ogre
enemy and Gold
item. You may choose to create corresponding rooms too.
Creating the world
We’re going to close out this post by actually creating a world based on the tiles we’ve defined. This delves into some advanced features so it’s OK if you don’t follow everything. I’ll explain everything briefly here, but I encourage you to read up on anything you’re interested in learning more about.
Create a new module in the same directory called world.py
. Next, make a folder called “resources” that is in the same directory as the “adventuretotrial” directory and create map.txt
inside. We’re going to build the world in this external file and load it into the game programatically.
I like to use a spreadsheet program and then copy the text into the map file, but you can just edit the file directly too. The goal is to lay out a grid of tiles whose names match the class names and are separated by tabs. Here’s an example in a spreadsheet:
Remember, your map should not include MapTile, LootRoom, or EnemyRoom! Those are base classes that should not be created directly.
In the world
module, add the following dictionary and method to parse the file you created.
_world = {}
starting_position = (0, 0)
def load_tiles():
"""Parses a file that describes the world space into the _world object"""
with open('resources/map.txt', 'r') as f:
rows = f.readlines()
x_max = len(rows[0].split('\t')) # Assumes all rows contain the same number of tabs
for y in range(len(rows)):
cols = rows[y].split('\t')
for x in range(x_max):
tile_name = cols[x].replace('\n', '') # Windows users may need to replace '\r\n'
if tile_name == 'StartingRoom':
global starting_position
starting_position = (x, y)
_world[(x, y)] = None if tile_name == '' else getattr(__import__('tiles'), tile_name)(x, y)
The parsing method goes through each line of the file and splits the line into cells. Using a double for
loop is a common way of working with grids. The x
and y
variables keep track of the coordinates. When we find the Starting Room, that position is saved because we will use it later. We use the global
keyword to let us access the starting_position
variable that lives outside of this method. The last line is the most interesting, but it’s fine if you don’t fully understand it.
The variable _world
is a dictionary that maps a coordinate pair to a tile. So the code _world[(x, y)]
creates the key (i.e. the coordinate pair) of the dictionary. If the cell is an empty string, we don’t want to store a tile in it’s place which is why we have the code None if tile_name == ''
. However, if the cell does contain a name, we want to actually create a tile of that type. The getattr
method is built into Python and lets us reflect into the tile module and find the class whose name matches tile_name
. Finally the (x, y)
passes the coordinates to the constructor of the tile.
Looking for an easier approach to building your world? Check out Chapter 13 of Make Your Own Python Text Adventure.
Essentially what we’re doing is using some advanced features in Python as an alternative to something like this:
tile_map = [[FindGoldRoom(),GiantSpiderRoom(),None,None,None],
[None,StartingRoom(),EmptyCave(),EmptyCave(),None]
]
That’s hard to read and maintain. Using a text file makes changing our world easy. It’s also a lot simpler to visualize the world space.
Keep in mind that the only reason we are able to do this is because all of our tile classes derive from the same base class with a common constructor that accepts the parameters x and y.
Let’s add one more method to the world module that will make working with the tiles a little easier:
def tile_exists(x, y):
return _world.get((x, y))
Congratulations for making it this far! If you’d like to see how to make the game easier or more difficult with different enemy types, see Chapter 12 of Make Your Own Python Text Adventure.
Click here for Part 3 of the abridged tutorial.
Thank you for this tutorial. I am getting an error on the line: tile_name = cols[x].replace(‘\n’, ”), the error is Index Error: List index is out of range. I’m pretty sure it replaces line breaks (\n) with empties (”) in the cols list and assigns it to a new varrible: title_name. I cant seem to get it to work for me. I’ve copied and pasted your github code to be sure its not a something I overlooked. What version of python are you using?
My guess is that your text file containing the rooms does not have the same number of tabs in each rows. The error you are getting is because
x
is larger than the number of columns in the current row. A few lines abovex_max
is set to the number of columns in the first row.This assumes that all rows are “padded” with tabs to make sure they are the same length.This code should work on Python 3.4.x.
i’m having the same problem, i don’t know if i’m doing something wrong.
Thank you, I have it working now.
Im getting an error on “_world[(x, y)] = None if title_name == ” els getattr(_import_(‘titles’) . . . “. It’s tellimg me name ‘_import_ isn’t defined??
You have made several typos. Please make sure you are entering the code exactly as it appears. Happy coding!
Hello Phillip,
I’ve got some problems with enemyroom. When I create tile enemyroom, it look like this:
world = {(2,5): tiles.Enemyroom(2,5, enemy.Cerberus(1)
That’s how it should look like but when I write “enemy.” ,window should appear with names of superclassess, but instead in this window hp, attack and other stuff like this is written. So I am trying to write enemy.Cerberus, but error appears- “unresolved reference enemy”
What should I do? I don’t understand what’s happening. I am just trying to call enemy just like an item, but it gives me error.
Thanks for this tutorial, but I am getting an error, despite the fact that I have copied and pasted it. The section of code is:
tile_name = cols[x].replace(‘\n’, ”)
_world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
When I run it, I get the error (‘module’ object has no attribute ‘ ‘). Any thoughts on how to fix this? I have tried replacing ‘\n’ with ‘\r\n’, because I am running Windows, but I still got the same error. Any help will be greatly appreciated.
Well, that suggests that
cols[x]
does not exist, so you are just getting an empty string. Naturally, that empty string is not found in the possible names. I would verify that your tile map is correct and make sure you understand the assumptions the code makes about that map. Happy coding!It worked! Thank you very much for your fast and helpful reply. This is a really great tutorial.
im still getting this error and i dont know what else I can do
my code:
I’ve had to make several changes to the code.
Hi
I can’t import either of the items.py or enemies.py modules. When I type ‘import items, enemies’, I receive the following error: Traceback (most recent call last): File “”, line 1, in <modules import items ImportError: No module named 'items'. I have tried several things to fix this, like adding the _init_.py file to all folders in the path, saved tiles.py in its own subfolder, and only trying to import one module at a time. I have checked the code in the modules I created previous to tiles.py, and they are all ok. Any ideas about what else I could try? Thanks for any help in advance!
At this point in the tutorial there’s nothing really to run. But if you are trying to run something, try taking a look at the instructions in Part 4. You need to make sure you are executing the code from the correct directory and (possibly) that your PYTHONPATH is set properly.
Hi.
This guide as been a huge help I have only come a across one bug in my coding that I cant figure out why it is creating problems. it tells me I have invalid syntax and it highlights the import in the
world[(x, y)] = None if tile_name == '' else getattr(import ('tiles'), tile name)(x, y)
statement I don’t know why. can you think of why it would be doing this?
You have a few typos. Here’s that line in my code:
thank you very much it is now running without a hitch, and once again great tutorial keep up the awesome work
I am getting this error when I try to load my game:
Traceback (most recent call last):
File “C:\Users\Ryan\PycharmProjects\Final Project – Coffee Shop\game.py”, line 27, in
play()
File “C:\Users\Ryan\PycharmProjects\Final Project – Coffee Shop\game.py”, line 12, in play
room.modify_player(player)
AttributeError: ‘NoneType’ object has no attribute ‘modify_player’
Any idea why that is happening?
This means that no room was found at the given coordinates, so Python returned
None
. Make sure to review the assumptions about the map file above. If all else fails, use the file included in the GitHub project, and then make modifications to it. Happy coding!File “C:/Users/Drew/Desktop/Intro Game Dev Project 1\world.py”, line 21, in load_tiles
_world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
ImportError: No module named tiles
What is the reason for this error? I checked to make sure things aren’t mistyped
How are you trying to run the application?
Yes, this is an error i received in the shell when attempting to run the program.
nevermind i figured the problem out. my tiles.py got removed from the folder.
Ok, so whenever I type “import items, enemies”, it says unresolved import and unused import for both names. Any ideas on how to fix this?
It sounds like you might be using an IDE in which case you may need to tweak the PYTHONPATH settings for the project.
when I run the program it says File “C:\Users\ncssurfabc\Desktop\adventure\game.py”, line 1, in
import world
File “C:\Users\ncssurfabc\Desktop\adventure\world.py”, line 18, in
tile_map = [[FindDaggerRoom(),GiantSpiderRoom(),None,None,None],
NameError: name ‘FindDaggerRoom’ is not defined
Did you create the
FindDaggerRoom
class? Maybe there is a typo?Hey Phillip, I’ve been getting an attribute error on line 27,
_world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
It says that the module ’tiles’ has no attribute (random mess in quotes).
Would you happen to know what I should be looking at?
There’s a difference between
'('module' object has no attribute '')
and'('module' object has no attribute 'OgreRoom')
. The former has been discussed previously in the comments above. If you’re getting the second error, then it is probably because Python cannot find all of your code at runtime. Make sure you are in the correct directory when you run the code and that you are running it from a terminal/command line. If all else fails, you may need to adjust your PYTHONPATH, but that’s probably the solution to another more systemic problem.When creating the world, how would you create a room so that if the player had a certain item (ex: the dagger), they would be able to pass, and if not, the room would be impossible to go through, so you couldn’t get to the next room without this item?
I would probably implement that in the
available_actions()
method on thePlayer
class. You would need to do a check to see if the adjacent room is of type XYZ and check the player’s inventory to see if they have the required item. If either of those conditions is false, remove the action from the list of available actions.Thanks, your idea worked perfectly! Only I’ve come across yet another error. I’ve decided to modify the entire game to create a Pokemon-type adventure. Everything works fine, only with Pikachu (a weapon), it says that it’s missing the statement “collected = 0”. And the command is clearly there. I’ve tried deleting and retyping this part of the code, and it’s still not cooperating. Suggestions?
Why did you use triple quotes to return the description of the starting room? I’m not sure why it seems to work…
Triple-quotes allow for multi-line strings. You don’t have to use them, but they can make code that prints out strings cleaner.
Hey!
First of all I’d like to thank you for your great guide. I had no idea how to get a game loop going and this really helped me out a lot.
However, I’m running into an error that already has been answered by you, though I don’t quite follow your explanation. (the error was a little different too)
” _world[(x, y)] = None if tile_name == “” else getattr(__import__(“tiles”), tile_name)(x, y)
AttributeError: module ’tiles’ has no attribute ‘ ”
is the error I encounter.
I’m genuinely clueless, I’m very sorry
EDIT:
AttributeError: module ’tiles’ has no attribute ‘StartingRoom
sorry I quoted the error wrongly.
I’m running it from command line and pythonpath has to be okay since any other python script runs smoothly from commandline.
what am I missing?
It looks like you’re having the same problem as Alfred was above. I would suggest adding a
print(cols[x])
so you can actually see the value oftile_name
. At some point, you’ll see thattile_name
does not have a value. This should give you a hint as to where the problem is in your map file because you’ll see where the code fails.Thanks a lot, for some reason cols[x] prints empty a few empty lines even though I replace line breaks with ”
I tripple checked the map.txt and there is no whitespace, only linebreaks, text and tabs.
the rest of the print looks normal
Thanks for your continued support for this tutorial! It’s been really fun and informative as a novice programmer. I’ve solved a few things from your responses above but now I’m running into this error:
I’m really at a loss as to what it’s referencing. Any thoughts?
It most likely means there is a problem with the
__init__
method of the tile you are trying to create. To figure out the problem tile, try printing outtile_name
,x
, andy
. When you know the tile causing the problem, make sure it’s initializer is correct. If you’re still stuck, compare your code with the code in the GitHub repo and that should pinpoint the error.Hello
I have been using this tutorial heavily and I have to say it explains quite a lot. However, I get this error every time I attempt to run it
_world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
AttributeError: ‘module’ object has no attribute ‘End_game’
I have not used End_game anywhere and I am incredibly confused.
Thanks for the tutorial
That probably means you named a tile “End_game”, does that sound right?
I’m having a problem running the GiantSpiderRoom class on Python 3.5.2. I keep getting the error:
” File “/home/adventuretutorial/tiles.py”, line 81, in __init__
super().__init__(x, y, enemies.GiantSpider())
TypeError: super() takes at least 1 argument (0 given)”
My code is this:
“class GiantSpiderRoom(EnemyRoom):
def __init__(self, x, y):
super().__init__(x, y, enemies.GiantSpider())”
I’ve looked at your previous answer to this problem, but it was for Python 2.x, not 3.x, so I’m very confused.
I’ve even gone through your code and copy-pasted your GIantSpiderRoom class into my script and I receive the same error.
Nevermind, I started this project on WIndows 8.1, but became so frustrated with Windows Command Line that I dual booted my laptop with Ubuntu 16.04 and the default call of “python” is for python 2.7.11, not python 3.x.
I’ve been having some problems with the map.txt, actually. I’ve created a 13×13 map using LibreOffice, but no matter what I do, it says:
” File “/home/adventuretutorial/world.py”, line 12, in load_tiles
tile_name = cols[x].replace(‘\n’, ”)
IndexError: list index out of range”
I understand that this means that what I actually created did not have the same number of rows in each column, but I cannot figure out what is wrong. I copied and pasted your map.txt in place of mine and the code still gave me the same error. (I also copied and pasted your world.py script to see if mine was the problem, but I received the same error again.
I downloaded your GitHub file and have modified it to include everything I wanted, like healing items and more weapons and enemies, but whenever I try to modify your map.txt file, I receive this same error. Is there another way to creating a large map?
Try printing
x_max
andx
to help debug. You will probably see thatx_max
is something like 12 when you expect 13. You don’t have to use LibreOffice. Just open the file in a text editor and turn on “show whitespace characters”.Take a look at the first comment string on this post. That may also help you out.
Thank you! This really helped.
Hi Phillip,
Excellent tutorial for a beginner like myself – I’ve really enjoyed it, so thank you!
I’m running this in Python 2.7 on Ubuntu, and I’ve changed the super() calls to suit, but I’m getting an error, and not sure if it is because of my version, or I’m doing something wrong. Could you help?
_world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
TypeError: GiantSpiderRoom() takes exactly 1 argument (2 given)
Here is the tile code:
def GiantSpiderRoom(EnemyRoom):
def __init__(self, x, y):
super(GiantSpiderRoom, self).__init__(x, y, enemies.GiantSpider())
This tutorial is written for Python 3, not 2. I believe some people in the comments may have posted some code changes that make it compatible with Python 2, but I highly recommend using Python 3 in general.
I have everything in place but when I run game.py, only the ViewInventory action is utilized. I don’t think any of the adjacent rooms are being noticed.
I tried modifying world.py to fix it and I still get the same issue. The game runs, but I can only view my inventory.
You might try debugging by printing out information. In
load_tiles()
, you can doprint("X: " + str(x) + " Y: " + str(y))
andprint(_world[(x, y)])
to see all the rooms being added. Then you can try addingprint
statements to theadjacent_moves
method of thePlayer
class. If all else fails, compare your code and map to what I have up at GitHub.Hello Phillip!
I’m in Chapter 13 of your book, Expanding the World. I have isolated my problem down to this block of code:
When I run my game.py, I get the error:
AttributeError: ‘NoneType’ object has no attribute ‘intro_text’
I have erased the entire chapter’s code and re-entered it, so I know it’s all entered correctly. However I must be missing something. My assumption is that the rows are not correctly appending to the world_map list, so when my game tries to access the intro_text for the selected tile it returns ‘None’ as the tile type. This is totally a guess, however.
The actual error is at this point:
and when I added print(room) below room = world.tile I got ‘None’ and then the error again, so I’m not getting a value for my tile_at function D:
And I’d like to say that your book is fantastic! I’ve only ever made choose-your-own-adventure games with tons and tons of if and elif statements, so this tutorial has been invaluable in making a more involved game. Thank you so much!
I’m so sorry, I hate that you can’t edit comments on this. Found one error:
I changed this:
dsl_cells = dsl_row.split()
to this:
dsl_cells = dsl_row.split("|")
but I still get the same error, unfortunately. From game.py I tried print(world.world_map) and got an empty list, so the items “ST” and “VT” etc. aren’t being added to the world_map list for some reason :S
Hi Allie,
You’re on the right track here! The error you are getting is because nothing is loaded into the map. When the game tries to find the starting tile, nothing is there, so Python uses
None
, which of course does not have anintro_text
method.The trick is going to be figuring out what’s wrong with your DSL. I would add
print
statements to theparse_world_dsl()
method. If you need to, do it after each line of code. Make sure yourtile_type_dict
is also correct. If all else fails, you can do an online diff between my code and yours.Happy coding!
Hey Phillip!
Thank you so much for answering. I ended up getting it, I needed to add world.parse_world_dsl() above player = Player() in game.py 😀
Thanks for your help!
Just bought the book and I’m in the world building section. Which is more “pythonic” using the excel spreadsheet to make the world or the DSL method?
Both methods use a DSL, so it’s more a question of putting the layout as a string directly in the code or storing it in a file. I don’t think either method is more pythonic than the other. However, I personally prefer to store it in a file. Especially if you had a game with a large world and/or multiple levels, trying to put all of that directly in code would get annoying. However, reading from a file adds some complexity that I wanted to avoid when writing the book so I went with the simpler method.
Thanks for answering my questions! This book is awesome and been a great resource for understanding classes and python in general in a fun way.
Hey Phillip,
First of this is a great resource for beginners like me, so thank you!
Second, if I wanted to input the coordinates of the rooms directly into my tiles, how would I do it? Currently this is an example of my code:
Notice how I input the coordinates into the super().__int__ of the subclass itself. But this doesn’t seem to be working. for example when I use:
to pull up the room at any particular coordinate I get None.
Please help!
Well if you aren’t using the map method of creating the tiles, you need something else to put the tiles into the
__world
variable. Something like:But this is really not a great idea and will give you a lot of headaches. If you don’t want to use the map file, at least something like this is still preferable:
Can you help? The section on making the map is rather vague, and I have no money to buy the book.
I’ve made the map to the best of my ability, and I keep getting an error:
I really have no idea what to do at this point. I apologize if someone has asked this before, but I really can’t find anything that will help.
This has been asked and answered above (check the comments). You likely have whitespace in your map file that is throwing things off.
Phillip,
Bought your book.
Really enjoyed it.
Looking to expand my game a bit more than I have and make enemy tiles respawn.
Not sure how I would do it though.
First I would create a
respawn
method in theEnemy
class to set the HP back to 100.Next, I would create a new method called
pre_check
and put it intoMapTile
with apass
body. Then call that method in theplay
method ingame.py
. Finally, override thepre_check
method inEnemyTile
and do something like this:Hope that helps and happy programming!
Wouldn’t this just give the same enemy that was generated originally 100 HP again?
Trying to also make the specific tile re spawn a random enemy when it does.
Sure, that’s actually easier. Move the code that creates an enemy into a new method like
def create_enemy(self)
. Then call thecreate_enemy
method in both theinit
andpre_check
methods.when I run the code I keep getting the error File “C:\Users\ncssurfabc\Desktop\adventure\world.py”, line 16, in load_tiles
_world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
AttributeError: module ’tiles’ has no attribute ‘ def play():’
and I looked over my code and cannot find the problem _world[(x, y)] = None if tile_name == ” else getattr(__import__(’tiles’), tile_name)(x, y)
Go back and review your code against the code in the tutorial. You can also view all the code on GitHub. I can’t tell specicially without seeing your code, but there’s no reason that the
tiles
module should be trying to load something calleddef play()
. It’s also suspicious that there is a space beforedef
.game.py
print(room.intro_text())
‘NoneType’ object has no attribute ‘intro_text’
What is happening?
Take a look at my response above.
I’m running into this error:
Only thing i can think of is in my player class i have functions ex: maxHpCalc() that use player.attributes in their value. without them the functions would fail so i’m not sure if that’s the issue or something else entirely.
You’ve got a typo: there is a difference between
player()
andPlayer()
. When you create the player object, you have to capitalize it so it refers back to thePlayer
class. Hope that helps!all my python files start with capitals ex: Player.py my classes and all my functions are player() all starting with lowercase letter.
I would recommend not doing that since it’s not the standard way to write Python. If you still want to, then you will need to change the name of your variable to something other than
player
such asthe_player = player()
.i will give that a shot an see if it gets me past the error. thanks
so i’m having issues with things like
the
Player.thePlayer.moveSouth
is all correct and works works. but i’m confused what i should actually be putting in most of these. for instance.————————-
Should i be putting them in like this:
pythonModule.class.function
? i have everything imported so i’m not understanding why i should have to put in both in the moveSouth function, but once i did it worked.also i started mine like this instead of play()
———————–
i kept running into player not defined once i was already in the play() so i just made it global.. once my pickRace() returns the race i pick. player.moveSouth should be the same thing as typing magmar.moveSouth Correct? so i’m not seeing why i should have to put in pyfile then my class to access these things. any help on what’s going on?
Whether or not you have to use the
module.Class.method
syntax when creating a player action depends on your imports. In the tutorial, I use thefrom module import Class
syntax to import the player. So you would probably dofrom Player import thePlayer
(again, that naming style is not standard Python and may be adding to your confusion).I don’t fully understand your last question, but when you are referring to a method, you should refer to its definition in a class, not an instance of the class. In my code,
Player.move_south
refers to the definition of themove_south
method in thePlayer
class. If I were to do something likethe_player_instance.move_south
it would not work for the reason you stated:the_player_instance
is not defined.so i HAD Main.py which had the main1() and pickRaise() and raiseStat() along with some elif input == “stats”, “look %s” % player.name which prints all stats, and updated them when they were raised. look name printed out hp, max hp mp and such and updated them with my maxHPCalc(). everything in it worked perfectly. then i moved the main1() before play so i could pick a race before entering into the game. makes perfect sense. but once i did that. my pickRaise i had to put Main.pickRace() and Main.raiseStat(). then when i return my pick race (player = Main.pickRace() ) it tells me magmar isn’t defined.
option = input(“—>”)
if option == “magmar”:
print(“\n you have chosen %s” %option)
time.sleep(1)
return magmar(playerName)
i haven’t changed any of this coding in my pickrace() or raiseStat() functions but since moving the Main1() now everything is broken. in Game.py i did use the regular import Player, import Main which are the py files. instead of from Player import thePlayer
should i be using from Main import pickRace, raiseStat instead of importing the whole python file?
————————-
once i create an instance of my race. player = magmar() i can then access that instance with things like print(player.hp) which should print out the current hp of the magmar instance i created which is equal to player? which was the move_south question from before.
so i changed my imports from import Main to from Main import pickRace, raiseStat which got my past having to put Main.pickRace()
then i get you have chosen magmar
Traceback (most recent call last):
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Game.py”, line 48, in
main1()
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Game.py”, line 46, in main1
play()
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Game.py”, line 19, in play
room = World.tileExists(player.locationX, player.locationY)
NameError: name ‘player’ is not defined
so then i readded global player in the main1() and then i get past that to loading the available rooms and get:
you have chosen magmar
As you enter the plane you shiver with anticipation of the coming adventure!
Choose an action:
Traceback (most recent call last):
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Game.py”, line 48, in
main1()
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Game.py”, line 46, in main1
play()
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Game.py”, line 27, in play
availableActions = room.availableActions()
File “C:\Users\reede_000\Desktop\gameCode\gamefile\MapTile.py”, line 44, in availableActions
moves = self.adjacentMoves()
File “C:\Users\reede_000\Desktop\gameCode\gamefile\MapTile.py”, line 30, in adjacentMoves
moves.append(Actions.moveSouth())
File “C:\Users\reede_000\Desktop\gameCode\gamefile\Actions.py”, line 36, in __init__
super().__init__(method = player.moveSouth, name=’Move south’, hotkey=’s’)
NameError: name ‘player’ is not defined
not sure why player.location would work and player.METHOD doesn’t.
So I’m working with this on the IDE called Cloud9, and I was wondering how to make a spreadsheet in there. Could you walk me through that? I’m working on this for a final project in my IT class and we need to be done in two weeks
I have finished the project but it says that intro_text is not defined, what should I do
I really love this tutorial. It’s great for a beginner like me. After running this in python shell within command prompt and debugging many of my typos i’m stuck.
Any help would be greatly appreciated.
It has to do with how (and from where) you are running the game. Take a look at part 4, where I discuss ho to launch the game.
I found a bug when I tried to run it, but I could not find any errors from that.
Double check all your enemy tiles. Make sure that you have something like
super().__init__(x, y, enemies.GiantSpider())
in all of them. This error is because you are trying to create an enemy tile without passing in an actual enemy, hence the message “required positional argument: enemy”.THE CODE USED:
ERROR RECEIVED:
Hi loving this tutorial so far I really like how it can be expanded on. I have made a couple of mistakes which i have managed to resolve on my own but this one has me stumped I know I’ve done something stupid but I can’t figure out where I have gone wrong any help would be appreciated.
Many Thanks,
K
So the code you copied (correctly) tries to pass
(x, y)
into the object that it is creating. But the error means that the object being created doesn’t accept(x, y)
. I would take a look at your tiles.py file and make sure all the tile types you created correctly extended fromMapTile
, e.g.LeaveCaveRoom(MapTile)
. If you still can’t find the error, add print statements inside ofload_tiles
to print out the values of x and y so you can determine which tile, specifically, it is failing on.Thank you so much for you fast response and you was completely correct i missed the MapTile off the Puzzle Room I had added silly mistake! 🙂
Hi, I’m completely new to python and relatively new to programming. I’ve been using your tutorial to understand python. I’ve come to an error with world.py.
What I’ve been doing is just changing some names to make it easier for me to understand (basically just some translations into Spanish. I’ve come across with the following error when trying to load the map tiles:
And I’m completely clueless about why that is happening. What should I be looking for?
This error means that the “thing” found in your map at that location has an incorrect
init
method. You’ll need to first find out where the problem is. I recommend printing out x and y so can see where the error occurs. Then look at your code for that tile. Make sure it correctly loads from the baseMapTile
as inStartingRoom(MapTile)
and also double-check yourMapTile init
looks likedef __init__(self, x, y)
. If you still can’t figure it out, post a link to your code and I can take a look.Thanks for helping me wthh this one! I totally failed. Here’s the link to pastebin with my world.py file (I miss-named the file in the link): https://pastebin.com/JWVPUZ21
BTW, if I want to print the name of the tile by calling load_tiles() in world.py, is it even posible or should I make another fuction for that?
The error is probably in tiles.py, did you check there?
Try this to print the name of the tile:
Hi, can you post the whole game as one flow of code please, I’m doing a project and this would really help me out. Once I get the code I can make mods and add various things…
Thanks Spencer
The full project is available in GitHub, it is linked to in the post.
I’m getting “NameError: name ‘Player’ is not defined. No clue what that’s about. This after debugging other things like the tabs parsing and all. I found also that using asterisks instead of empty cells was better for formatting the map and avoiding the row length errors.
Can’t say for certain without seeing the code, but you are probably missing an
import
.So, my code looks like this:
which is exactly the same as yours, but I continue to get the error code below.
How are you trying to run your application? Have you gotten to Part 4 yet?
Yes, I have.
I’m trying to run it through my command prompt, and have used the cd command to get to my directory where everything is. Then I use the START command to run the program.
You should be running
python adventuretutorial/game.py
. If that still does not work, put your code on GitHub and I will take a closer look.So, I literally type in the console python adventuretutorial/game.py ?
Other than that, here’s the link to the GitHub
https://github.com/linkcool200/MyTextGame
So, I went into my console, and went to where the folder is, and then typed ‘python AdventureTutorial/game.py’
But nothing happens, should I be using the path to get there or the cd command?
I notice that each time I enter the FIND 5 GOLD room I get 5 gold, even though I’ve gone inside 20 times. I now have 20x 5 gold from the same room
Hi i’m trying to create a game based on legends of my country and get this error of wich can’t solve, i already read all the comments above and there’s some that are similar to my problem but i can’t get any solution for this.
Thanks for the tutorial i got a lot of fun creating the game and learning at the same time.
Here’s the error that i get in WindowsPowerShell:
Traceback (most recent call last):
PS C:\Users\…\python\ejercicios\leyendas del sur de chile> python game.py
Traceback (most recent call last):
File “game.py”, line 26, in
play()
File “game.py”, line 5, in play
world.load_tiles()
File “C:\Users\…\python\ejercicios\leyendas del sur de chile\world.py”, line 16, in load_tiles
_world[(x, y)] = None if tile_name == ‘ ‘ else getattr(__import__(’tiles’), tile_name)(x, y)
AttributeError: ‘module’ object has no attribute ”
It means there is extra or invalid whitespace in your map file. Make sure you don’t have any extra spaces, line breaks, etc. Sometimes it helps to use a text editor like Notepad++ so you see all the whitespace characters.
Is there a place where I can find the whole code?
It is available on Github.
I have tried everything but I can’t get this to work:
Traceback (most recent call last):
File “C:\Users\chr05012\OneDrive – Vestfold og Telemark fylkeskommune\Skrivebord\Python\AdventureGameTutorial\game.py”, line 1, in
import world
File “C:\Users\chr05012\OneDrive – Vestfold og Telemark fylkeskommune\Skrivebord\Python\AdventureGameTutorial\world.py”, line 6
with open(‘C:\Users\chr05012\OneDrive – Vestfold og Telemark fylkeskommune\Skrivebord\Python\AdventureGameTutorial\map.txt’, ‘r’) as f:
^
SyntaxError: (unicode error) ‘unicodeescape’ codec can’t decode bytes in position 2-3: truncated \UXXXXXXXX escape
>>>
Nevermind, I saw your github and realized my mistake