1

I'm studying LPTHW and stuck on making my own game.

class Engine(object):

    location_dict = {
        'main_corridor': MainCorridor(),
    }

    def goto(self, location):
        return Engine.location_dict.get(location).start()

    def test(self):
        print "Calling Engine() from MainCorridor()"    


class MainCorridor(object):

    def __init__(self):
        self.engine = Engine()

    def start(self):
        self.engine.test()



game = Engine()
game.goto('main_corridor')

Can anyone advice on me on how to approach this? greatly appreciated thank you

Here is the error message:

Traceback (most recent call last):
    File "ex45_game.py", line 1, in <module>
        class Engine(object):
    File "ex45_game.py", line 4, in Engine
        'main_corridor': MainCorridor()
NameError: name 'MainCorridor' is not defined
yuze
  • 11
  • 2
  • 2
    a slightly convoluted design, in my humble opinion. You got an answer below. By the way, you might want to use `self.location_dict.get(location).start()` instead of going through `Engine.`, if you really need this intricate back-n-forward calling – Pynchia May 19 '15 at 12:07

2 Answers2

2

I recently did the lpthw tutorial. What Zed does is create a third class that maps out the levels in the game, that way they can be instantiated after the rest of the classes are defined. That should fix the 'not defined' error.

But another issue is you are creating an engine object at the end:

game = Engine()

Then when you initialize the MainCorridor class you create a separate engine object:

class MainCorridor(object):

    def __init__(self):
        self.engine = Engine()

A solution is to create the engine class in the MainCorridor class only:

class Engine(object):

    def test(self):
        print "Calling Engine() from MainCorridor()"    


class MainCorridor(object):

    def __init__(self):
        self.engine = Engine()

    def start(self):
        self.engine.test()


class Map(object):

    location_dict = {
        'main_corridor': MainCorridor(),
    }

    def goto(self, location):
        map = self.get_location(location)
        return map.start()

    def get_location(self, location):
        return self.location_dict[location]


game = Map()
game.goto('main_corridor')

But this way, each location instance you put in the location_dict will have its own unique Engine object.

What you could do to give every location the single Engine object is pass 'self' from engine into the map class, and have the map class instantiate location_dict by passing the same engine object to each location in the list:

class Engine(object):

    def __init__(self):
        self.map = Map(self)

    def test(self):
        print "Calling Engine() from MainCorridor()"    


class MainCorridor(object):

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

    def start(self):
        self.engine.test()


class Map(object):

    def __init__(self, engine):
        self.location_dict = {
            'main_corridor': MainCorridor(engine),
        }

    def goto(self, location):
        map = self.get_location(location)
        return map.start()

    def get_location(self, location):
        return self.location_dict[location]


game = Engine()
game.map.goto('main_corridor')
Dracunos
  • 79
  • 10
0

You're getting this error because location_dict is a class variable. You're attempting to assign a MainCorridor object to location_dict when you're defining location_dict, but this is before you've defined MainCorridor, so you get the error you're receiving because it doesn't exist yet. You won't get this if you define location_dict on the instance rather than the class (see below).

class Engine(object):
    def goto(self, location):
        return Engine.location_dict.get(location).start()
    def test(self):
        print "Calling Engine() from MainCorridor()"
    def __init__(self):
        self.location_dict = {'main_corridor': MainCorridor(),}


class MainCorridor(object):
    def __init__(self):
        self.engine = Engine()
    def start(self):
        self.engine.test()

On the other hand, because of the back-and-forth you do between the objects, I got a RuntimeError: maximum recursion depth exceeded when I ran the code with these modifications. This happens when you create an instance of Engine. Note that as you create your Engine, it creates a MainCorridor and puts it into the dict. But when you create a MainCorridor, it creates an Engine, which creates a MainCorridor and puts it into the dict. But when you create a MainCorridor...

Deacon
  • 3,615
  • 2
  • 31
  • 52
  • 1
    Since you spotted the cyclical instantiation error why do you provide it as an answer? This is plain wrong. – rantanplan May 19 '15 at 12:47
  • 1
    You have most definitely taught me new things here - so thanks for that! But as you have witnessed yourself, errors still arise. the topic deals with inheritance vs. composition and it's very tricky to implement so far. – yuze May 19 '15 at 12:54
  • @rantanplan - Since it's "Learn Python the Hard Way," I'm explaining the error that tripped the OP up, and then identifying the next issue that he's going to experience to give him a pointer in the right direction. Since he's doing this as a learning exercise (and is obviously trying to understand what's going on), it's part of the exercise to fix it. What would've been wrong would be to go on and fix it for him, negating the learning experience. OTOH, if he'd said "this is a piece of production code..." then I would've resolved the cyclical instantiation issue or not posted. – Deacon May 19 '15 at 12:58
  • 1
    @yuze see this http://stackoverflow.com/questions/23245149/how-to-use-a-method-in-ayou-class-from-another-class-that-inherits-from-yet-another/23245820#23245820 seems similar to your question – rantanplan May 19 '15 at 12:58
  • 1
    Doug, you just copy-pasted his code with just a slight alteration and then you have a full paragraph explaining your observation that "hey this is wrong it seems". He may be reading LPTHW but this is stack overflow and this answer is not helpful. – rantanplan May 19 '15 at 13:01