Ex43.py: AttributeError: 'NoneType' object has no attribute 'enter'

Hi, I’m stuck on exercise 43.
I get this:
Traceback (most recent call last):
File “ex43.py”, line 256, in
a_game.play()
File “ex43.py”, line 24, in play
next_scene_name = current_scene.enter()
AttributeError: ‘NoneType’ object has no attribute ‘enter’
I’ve searched online for 2 hours now and I can’t find what is wrong with my version of the exercise. https://paste.pythondiscord.com/kinoxuqudu.py

Thanks in advance for your help!

OK, I learned from my mistake.

a_map = Map(‘central_corridor’) was missing an underscore in the central corridor. A simple typo

All the best,

S

2 Likes

Nice, yeah any time you have NoneType look at the return values, and any time you have a ValueError look at spelling mistakes.

did the same thing…

I have the same type of error but I do not seem to have a spelling mistake (or im just dissy from looking at the code too long.)

Can anyone find what I am doing wrong?

from sys import exit
from random import randint
from textwrap import dedent

class Scene(object):

	health = 10

	def enter(self):
		print("This scene is not yet configured.")
		print("Subclass it and implement enter()")
		exit(1)

class Engine(object):

	 def __init__(self, scene_map):
		 self.scene_map = scene_map

	 def play(self):
		 current_scene = self.scene_map.opening_scene()
		 last_scene = self.scene_map.next_scene('finished')

		 while current_scene != last_scene:
			 next_scene_name = current_scene.enter()
			 current_scene = self.scene_map.next_scene(next_scene_name)

			 #be sure to print out the last scene
		 current_scene.enter()
class Death(Scene):

	rip = ["son of a gun",
			"Bruh?"
			"What are you doing?!?"
			"No more slacking. Period."
			"........"]
	def enter(self):
		print(rip.randint(1,5))

class CentralCorridor(Scene):

	def enter(self):
		print("""
		You are dropped on a space pirate ship in 3th quadrant of blorgon.
		You know what to do. Find the exit and pew pew the bad guys.


		There is a door with alien guards protecting it right in front of you.
		Do you shoot or are you scared?""")
		action = (input(" >"))

		health = 10

		while action == "shoot" and health >= 0:
			accuracy = randint(1, 6)
			alienacc = randint(1, 4)
			if accuracy > alienacc:
				print("Fine marksmanship. Quick, head to the laserweapon armory!!")
				return 'LaserWeaponArmory'
			elif accuracy < alienacc:
				health -= alienacc
				print(f"""They hit you back and wounded you for {alienacc} livepoints.
				this leaves you with {health} livepoints""")

		else:
			print("There is time and place for everything. But not now!")
			return 'central_corridor'

class LaserWeaponArmory(Scene):

	def enter(self):
		print("""Ok great. You are in the laserweaponarmory.
		You get 10 guesses to unlock the masterchest.
		Good luck.""")

		code = f"{randint(1,9)}{randint(1,9)}{randint(1,9)}"

		guess = input("> ")
		guesses = 0

		while guess != code and guesses < 10:
			print("Wrong!")
			guesses += 1
			guess = input("> ")

		if guess == code:
			print("Good work. You retrieve the laserblaster and head to the bridge.")
			return'the_bridge'
		else:
			print("Guesses are up. You are getting ambushed by aliens!")
			return 'death'
class TheBridge(Scene):

	def enter(self):
		print("""You cross the bridge and find yourself swarmed by aliendefenders.
				 What do you do?
				 Jump of the bridge?
				 Take them all down?
				 Give up?""")
		action = input("Jump\nFight\nGive up\n>")

		if action == "Jump":
			print("smart choice. you jumped into the escape pod below you.")
			return 'EscapePod'
		elif action == "Fight":
			print("You die an honorable man atleast.")
			return 'Death'
		elif action == "Give up":
			print("coward.")
			return 'Death'
		else:
			print("No time for this nonsense.")
			return 'Death'

class EscapePod(Scene):

	def enter(self):
		print("""The escape pod has no keys in it.
		You have to cut one of the 5 wires to make the pod work.
		Which one do you cut?""")

		goodwire = randint(1,5)

		choice = input("> ")

		if choice == goodwire:

			return 'finished'

		elif choice != goodwire:
			print("RIP")
			return 'Death'

class Finished(Scene):

	def enter(self):
		print("You won! Good job.")
		return 'finished'

class Map(object):

	scenes = {
		'central_corridor': CentralCorridor(),
		'laser_weapon_armory': LaserWeaponArmory(),
		'the_bridge': TheBridge(),
		'escape_pod': EscapePod(),
		'death': Death(),
		'finished': Finished(),
}

	def __init__(self, start_scene):
		self.start_scene = start_scene

	def next_scene(self, scene_name):
		val = Map.scenes.get(scene_name)
		return val
	def opening_scene(self):
		return self.next_scene(self.start_scene)

a_map = Map('central_corridor')
a_game = Engine(a_map)
a_game.play()

Can you please edit your post and wrap your code in code tags?

[code]
# your code
[/code]

It’s just silly to try and read through the mess that the automatic formatting creates…

You do return different keys though, sometimes “Death”, sometimes “death”. Also, make sure all branches of your control structures have a return.

In your next_scene function do this at the top:

print("next_scene>>>", scene_name)

You’ve probably named something wrong, like Death instead of death, so when you try to get the Map.scenes it returns None. You should then add print statements like this on every place that has a variable for this until you figure out how you’re getting a None value.

The reason this is happening can be seen if you try this:

x = None
x.enter()

You’re calling .enter() on something that’s None.

Ok thanks guys. I fixed it. Guess I was staring at my code too long. Another question has risen though.

Why doesn’t this work:

	rip = ["son of a gun",
			"Bruh?"
			"What are you doing?!?"
			"No more slacking. Period."
			"........"]
	def enter(self):
		print(rip.randint(1,5))
                exit(1)

as opposed to this:

                 quips = [
"You died. You kinda suck at this.",
"Your Mom would be proud...if she were smarter.",
"Such a luser.",
"I have a small puppy that's better at this.",
"You're worse than your Dad's jokes."


       def enter(self):
              print(Death.quips[randint(0, len(self.quips)-1)])
              exit(1)

NameError: name ‘rip’ is not defined

This is the error message when I run the former but that is the one that I could come up with, with my knowledge so far. The other one is way over my head.

Thanks in advance!

Will do from now on!

To add to this.

When the death scene occurs in the wire scene it only prints the first item of the list, but when I die in the escape pod scene it prints all the other ones.

Has anyone else had this problem?

Another question I had was:

When I run this code:

a_map = Map('central_corridor')

Does it put the equivalent of central_corridor’s key as parameter on all the second arguments after self in the code below?

	def __init__(self, start_scene):
		self.start_scene = start_scene

	def next_scene(self, scene_name):
		val = Map.scenes.get(scene_name)
		return val
	def opening_scene(self):
		return self.next_scene(self.start_scene)

On top of this:

How is it that if i make the variable ‘health’ in the scene class that i get the following error:

Traceback (most recent call last):
File “C:\Users\user\pythonlearn\ex43.py”, line 166, in
a_game.play()
File “C:\Users\user\pythonlearn\ex43.py”, line 24, in play
next_scene_name = current_scene.enter()
File “C:\Users\user\pythonlearn\ex43.py”, line 55, in enter
while action == “shoot” and health >= 0:
UnboundLocalError: local variable ‘health’ referenced before assignment.

But when I put it in the class which I am actually running it does work. I thought the daughter class was supposed to “Inherit” everything from the mother class.

Much thanks!

One thing is you are forgetting the commas on the list:

	rip = ["son of a gun",
			"Bruh?",
			"What are you doing?!?",
			"No more slacking. Period.",
			"........"]

Next, when you have a class, and you define a variable inside the class, then that variable is for the class like this:

MyClass.rip

See how you did it with:

Death.quips

Also, I think you might be typing a lot of code and then running it once and trying to fix it. Try writing only a little bit of code, running it and getting that working, then writing some more. You’ll find errors quicker and code faster and more accurately.

Thank you. I will try to work in smaller bits. One last question about this exercise and then i’ll stop bugging.

I get the following error when I run my code:

File “C:\Users\user\pythonlearn\ex43.py”, line 5, in
class Scene(object):
File “C:\Users\user\pythonlearn\ex43.py”, line 12, in Scene
health == 10
NameError: name ‘health’ is not defined

The powershell tells me that I have not yet defined “health”. But that is exactly what I am trying to do within this class:

class Scene(object):

	def enter(self):
		print("This scene is not yet configured.")
		print("Subclass it and implement enter()")
		exit(1)

	health == 10

Is it not possible do define a variable within a class?

health == 10

But this is not an assignment. There’s a difference between = (assignment) and == (testing for equality).

From this and your previous posts I think you should work a bit on paying more attention to syntactical details. There are lots of small subtleties with the special characters in programming, and you need to get used to getting them right.

1 Like

Yep, @florian is on point as usual.