Ex. 45 - Make Your Own Game

Hi all,

So, I’ve spent a little over a week on my game. It’s essentially a text-based dungeon crawler, where the player is given the option to play as one of three archetypes (rather than classes, so there aren’t any conflicts with python keywords). The user can choose to play as a barbarian, a ranger, or a wizard. They’re all extremely watered-down versions of the classes you can choose from in DnD.

Combat Sequence:

Map & Engine:

Archetype (where the player chooses their archetype and gains access to their abilities):

Enemies (enemy archetypes and abilities):

As of right now, I’ve been able to get the game working if I play as a wizard; if I choose any of the other classes, however, I encounter a problem. If I attempt to play the game as a wizard, once I go into my first combat sequence and attempt to use one of the ranger’s abilities, it returns this error message:

Traceback (most recent call last):
  File ".\map_engine.py", line 413, in <module>
    game_engine.play(combat_mechanics, arch_map)
  File ".\map_engine.py", line 34, in play
    next_room_name = current_room.enter()
  File ".\map_engine.py", line 155, in enter
    combat_mechanics.combat(kobold_grunt)
  File "C:\Users\nickm\documents\python\my_game\combat_sequence.py", line 117, in combat
    self.arch_map.raw_damage_staff(self.arch_map, enemy_arch, enemy_choice, block_amt, stun)
AttributeError: 'Ranger' object has no attribute 'raw_damage_staff'

For some reason, it thinks I’m wanting to call on one of the Wizard’s class methods; however, I attempted to automate the process to where the combat_sequence.py script knows what archetype you picked, then only allows the user to select from a specific list of moves. I know for sure I should only have access to the Ranger’s move set thanks to printing; when I print the instance variable self.arch_map, it returns this:

<archetype.Ranger object at 0x032B1190>

So, where am I going wrong? (Also, I’ve provided my other scripts for context, if needed. Just run map_engine.py from the command line.)

On a side note, if you go through the archetype.py module, you’ll notice some of the abilities are blank. I’m having a tough time implementing abilities that have a duration. In the case of the Ranger class method poision_shot, I only want it to last three turns. I was thinking of defining a local variable within the method (turn = 0), then, if the player does choose the poison shot attack, add and return 1 to the true variable. After the enemy took their turn, I was going to create an if-statement saying that if turn == 1, add and return 1 (with the enemy taking some damage). I was then going to have another if-statement (though I don’t know where to place this one…) saying that if turn == 3, then the poison would subside. Any thoughts?

I understand many users may not invest as much effort in this exercise, and I don’t want to spend too much time here when I could move on and begin learning new things. At the same time, I don’t want to just quit working on this game with 85% (hopefully I don’t find out I have to do a lot of reconstruction) or so of the program done. I definitely don’t want to miss out on that satisfaction. For now, I’ll move on to the next exercise, and maybe come back to it intermittently.

Thanks!

Hi there,
I see you are pretty dedicated and the game looks interesting.
It would be very useful for you to subscribe to Learn Code The Hard Way experimental course.
We are an entire group and you could get more detailed help from Zed.
You could also have access to the lab (a gitlab playground where our group submits code.)
That would be a good idea because you could show us all your game, we could play it and test it.
There are even weekly seminars dedicated to refactoring code.
So you could submit your game and Zed would analyze it and refactor it live showing you what could be improved.
Drop him a private message on here and he can help you with the subscription process.
I am very excited about it this is why I feel like telling everyone.
I made huge progress, it’s very motivating.

Yes, I did! It sounds like an amazing offer. I get paid this week. Once that happens, I’ve told Zed I’m more than likely going to join.

2 Likes

Coolness! See you in the private part of the forum then!

1 Like

My 2p worth… you revisit the game model a few more times in the book, during testing activities and online version, so bear that on mind.

However I rushed this bit and I’m actually going back over and completely remaking my game so it about full use of what I’ve learned over the actual game content. So getting into the complexity now isn’t a bad thing at all.

And as @io_io says, LCLive is awesome!

Yeah, that’s kind of what I figured. I wouldn’t mind seeing it turn into a side project once I learn more. I’ll take the feedback I get and improve it later.

And yes, I’ll see you all there soon. ^.^

1 Like

When you get that attribute error it’s like getting a NameError: it means you spelled something wrong. Looking at your code, I see a lot of raw_damage functions but not raw_damage_staff.

There is a raw_damage_staff function, but it’s under the Wizard class in the archetype.py module. Only if you choose a wizard as your archetype at the beginning of the program should it let you use that ability. I’m not noticing any discrepancies between the two modules, either, in the case of the ranger’s functions. I also know that we’re working with a ranger object because of what the print statement returns. Could it be because of how similarly the methods are named?

Ah, I missed that. But, remember that you still have an error saying that method is missing. That means one of two things:

  1. You spelled it wrong.
  2. You are calling it on the wrong class of object.

Print out the object that you’re trying to call this on to see what type it is. You can also do this:

At the top put import pdb, then right before this error put pdb.set_trace(). Then you’ll get a python shell and you can type python code to see what that is. You can do this:

obj.__dict__
obj.__class__

You should then see what it is, and you can also try different function calls on it. (Keep in mind I’m using obj where you should use the variable name that you have.)

Alright, I’ll try that and report back here.

Alternatively, I’m on exercise 46 (The Project Skeleton). Do we have an exercise for pytest, since nose is deprecated? Or should I just research that on my own (I have a basic knowledge of it)? Sorry for the additional question - just didn’t want to bother making another post.

Thanks again.

Pytest is actually a lot easier. You write the test almost like you would with nose, except you just use the normal assert feature of python:

assert that == False, “What?! That’s not false?”

That’s it. Then you run the tests with pytest and it should pick them up and run them, with a lot better output.

1 Like

At first glance, I’d have to agree with pytest being a lot easier. There isn’t any boilerplate and you just run it from the command line.