-3

I was trying to pass the value from getattr to another class Map(), but it still tell me that there is no this argument in the class Engine. The thing is that how do I pass the attribute to the class Map? It keep looking the attribute in the class Engine().

class Engine(object):

    def __init__(self,start):
        self.map = start
        self.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."            
        ]

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

    def play(self):
        next = self.map

        while True:
            print ("\n------------------")
            # Trying to get attribute of object and pass to class Map.
            Map = getattr(self, next)
            next = Map()


class Map():

    def __init__(self, next):
        self.map = next

    def central_corridor(self):
        print ("The Gothons of planet Percal #25 have invaded your ship and destryoed")
        if action == "shoot!":
           print ("Quick on the draw you yank out your blaster and fire)
           return 'death'
        elif action == 'tell a joke':
           print ("Lucky for you they made you learn Gothon insults in the academy")    
           return 'Go to bridge'

    def go_to_bridge(self):
        print ("You burst onto the Bridge with the neutron destruct bomb")
a_game = Engine("central_corridor")

a_game.play()

Traceback

Traceback (most recent call last): File"c:\Learn_Python_In_the_hard_way\SourceCode\E42_Class_Execrise.py", line 175, in <module> a_game.play() File "c:\Learn_Python_In_the_hard_way\SourceCode\E42_Class_Execrise.py", line 27, in play Map = getattr(self, next) AttributeError: 'Engine' object has no attribute 'central_corridor'

smci
  • 32,567
  • 20
  • 113
  • 146
jashdf
  • 85
  • 5
  • What is the full traceback of the error you are getting? I'm guessing it has something to do with `next = Map()` where you try to initialise a `Map` with no arguments but a `next` argument is required. – FHTMitchell Aug 03 '18 at 09:26
  • Where do you see a `getattr()` call in your code ? If you expect any help, please post a proper MCVE and the full error message AND traceback. – bruno desthuilliers Aug 03 '18 at 09:45
  • sorry I put my another version here. I updated once again. – jashdf Aug 05 '18 at 05:52
  • You have a lot of errors in your code, you did not close string here: print ("Quick on the draw you yank out your blaster and fire), play method is badly written, you should rethink your code a bit. – BJT Aug 05 '18 at 07:20
  • Ok you need to decide where you store the player's location (presumably as a state variable in Map, not Engine). 1) `Engine` class does not need to know where the player is, only if they're alive or dead (what they're carrying, what their energy level is, score etc.). So trying to initialize things with `Engine("central_corridor")` makes no sense. `Engine` class should not need to know *how* to initialize an instance of `Map`. 2) So how can you write `Map` class such that it initializes its location by itself to "central_corridor"? 2b) Location should be stored as a data member, not a method – smci Aug 05 '18 at 07:44
  • Also, if you want to ask for general comments on non-working code (like this), better to use [CodeReview.SE](https://codereview.stackexchange.com/) – smci Aug 06 '18 at 19:29
  • And have a look at other people's code in the tag [tag:adventure] – smci Aug 07 '18 at 07:35

1 Answers1

0

Here is what you need to fix about the decomposition:

  • You should be storing the player's location as a state variable in Map, not in Engine. Actually you should rename Map to Location, since it does more than just record where they are, it knows which actions are legal and processes them, then updates to new location.
  • Engine class does not need to know where the player is, only if they're alive or dead (what they're carrying, what their energy level is, score etc.).
  • So trying to initialize Engine("central_corridor") makes no sense. (Btw, "central_corridor" is a string, Map.central_corridor is a method, but doing that would still be terrible decomposition, you would be coupling Engine to Map for no reason)
  • Engine class should not need to know how to initialize an instance of Map
  • So how can you write Map class such that it initializes its location by itself to "central_corridor"?

    • Location should be stored as a data member (methods in Map should set or get self.location = "central corridor", "bridge"), not as methods Map.central_corridor(), Map.go_to_bridge(). Certainly if you do that, you need one method for every legal source-destination pair of locations, that will be unnecessary unless the adventure is pretty linear.
  • so your current idea to store location as a method name from Map, then have Engine.play() loop through those locations (method names) is not great.

  • Engine.play is just causing you a headache in needlessly passing control flow from Map <-> Engine and legally passing locations
  • also where does action come from? you're missing a method to ask the player for actions, and reject and loop unless it recognizes a legal action at that location.
  • and consider how Map class is supposed to pass the state (alive/dead) back to Engine. As a string? As a boolean? Or could you just return None to indicate the player has died?
  • so what would the solution look like?
    • rename Map to Location
    • Location would have a member where (or state or whatever you want to call it)
    • Engine or Engine.__init__ would only need to define self.location = Location(). No passing in initial state.
  • Location class should have one big method turn() which inspects the current value of self.location, prints whatever corresponding description text, calls a method to get player action (probably want to pass it a list of legal actions as strings), then processes the chosen action for that location and determines the next action and the next player state (alive/dead).
smci
  • 32,567
  • 20
  • 113
  • 146
  • Thanks smci. I rebuilt the program as you said. And clearly I found that I am totally not understand the 'class' function and the question is so stupid. But again, thanks very much to point out my problem. I should read more the docs. – jashdf Aug 19 '18 at 08:46
  • But do check out [CodeReview.SE](https://codereview.stackexchange.com/) for general code reviews – smci Aug 19 '18 at 18:19