I have bug! in ex45.py

what is problem?


I think you can figure this out on your own. Hints:

  1. The error tells you that in line 18 of managerGame.py current_scene is None. You need to find out why. Print, print, print…
  2. I can see the error somewhere in your screenshots, so you don’t need to search any other files.

Happy debugging. :wink: Ask again if you feel that you’re completely stuck. :slight_smile:


I didn’t figure it out ? i don’t know the enter () where come from

Your map maps strings to scenes. You query the next scene with the key that the enter method of the previous scene returns. So all the enter methods must return strings, not scenes. But your weapon scene returns scenes in most cases.

1 Like

so you tell me I can’t add find enter because I use function direct in managerGame.py
and this is way def enter null, i must go to map to make def enter work ? am I right?

No. This is the problem with object oriented programming: it generates a lot of confusing indirection…

Your bug surfaces somewhere in the engine code where you move to the next scene. So let’s see how that works:

  1. Your engine has-a Map which is basically a thin wrapper around a dictionary that maps string keys to Scene objects, like "death" -> Death(). The engine calls Map.next_scene(key) to get the next scene.
  2. Every Scene has-a enter method. When the Engine has obtained the next scene from the Map it calls that method on the scene to run it.
  3. When a scene is finished, its enter method returns the key of the next scene to the Engine.
  4. The Engine uses that key to fetch the next scene from the Map. Go back to 1.

Now let’s look at the error message:
current_scene.enter(): 'NoneType' object has no attribute 'enter'

This means that at this point (line 18 in managerGame.py) you are calling enter on an object that doesn’t have that method.

Okay, which is the object? current_scene. You expect current_scene to be a Scene object, but the message says it’s None (NoneType), and None doesn’t have enter.

Why is it None? You need to go, find out where current_scene gets its current value. That’s in the line above:
current_scene = self.scene_map.next_scene(next_scene_name)

We’ve seen that current_scene ends up being None and that the map is just a dictionary. Whenever you get None from a dictionary it’s usually a sign that the requested key doesn’t exist. So we need to look at the key: next_scene_name.

Where does next_scene_name get its value? The line above:
next_scene_name = current_scene.enter()

We know that enter should return strings, but it seems this one returns something, maybe a string, maybe something else that’s not a valid key for the map. Let’s look at the offending scene. From your screenshots it’s Weapon.

And here we see what’s going on: In the if block at the end of Weapon.enter() you return Sword() and Gun() and so on, but it must be "sword" and "gun", respectively. You need to return the exact keys that are used in the map, not the values. Otherwise the map says "sorry, I don’t have a key Sword()", and returns None.

Does this make sense?

What you would usually do is print out current_scene and next_scene_name to see what the values are and then compare to what you expect.

1 Like

yes make sense, and this what I understand
I run map and add sense (romeDevel) to map then map call (Engine) so go to it and run (__init__)
and then back to map and run (a_amp.play) then go to (Engine) and run def (play) inside def play var (current_scene) = romeDevel..opening_scene() =>back to map to run this def ,and
this opening_scene()=>call def next_scene() and next_scene() get key from dict , and dict return it if exist , and before to go to var ( next_scene_name) if user solve the romeDevel will return him to weapon and this scene go to var ( next_scene_name)

and so on

Yeah that sounds about right.
Just nitpicking: when you say “run this def”, the correct word for “def” would be “function”. “def” is a shorthand for “define [a function]” in Python. I had to read your post twice to get what you were saying. :wink: