OOP how to get the script (a game) to run - python

I'm trying to get my head around OOP using Python. Working through a tutorial I've been instructed to make a game. Earlier in the tutorial I made a game just using functions but now I have to use classes and objects.
Once I have my objects though I'm unsure how the get things moving. Here's the gist of it:
class Scene(object):
def enter(self):
pass
class Scene1(Scene):
def enter(self):
print "Some text describing the scene bla bla"
def someFunction that requires raw_input and a correct answer
return 'Scene2'
class Scene2(Scene):
def enter(self):
print "Some text describing the scene bla bla"
def someFunction that requires raw_input and a correct answer
return 'Scene3'
class Scene3(Scene):
def enter(self):
print "Some text describing the scene bla bla"
def someFunction that requires raw_input and a correct answer
return 'finished'
There is more to the game than that, but I've just slimmed it right down to the part I'm having trouble with.
The tutorial author hints to use another object to run the game, an "engine" that would start with scene1 and run through each scene till 'finished' is returned. He does have an example but it was for a more complex game so I've tried to ignore it. I think he wants us to use a while loop though.
But while what? What logic could I use to run the game? I'm a learner as you may be able to tell. Do I have all of the objects that I need? What would be the best way to "run" the game?

Create a Class that holds all scenes. The run() method loops through all scenes and execute the enter() method, which will output both: the print and the return string.
class Engine:
def __init__(self):
self.scenes = [Scene1(),Scene2(),Scene3()]
def run(self):
for s in self.scenes:
print s.enter()
Engine().run()
Output:
Some text describing the scene bla bla
Scene2
Some text describing the scene bla bla
Scene3
Some text describing the scene bla bla
finished
Update to comment: do it more dynamically:
class Scene1(Scene):
def enter(self):
print "Some text describing the scene bla bla"
raw = raw_input("Guess the number")
if raw != "42":
return 'Scene1'
return 'Scene2'
class Engine:
def __init__(self):
self.scenes = {'Scene1':Scene1(),'Scene2':Scene2(),'Scene3':Scene3()}
def run(self):
next = 'Scene1'
while True:
if next == 'finished':
break;
next = self.scenes.get(next).enter()
Engine().run()

the arguments about this being a good canidate for oop not withstanding
class Scene1:
def enter(self):
print "a scene"
raw_input("Hit Enter To Go To Next Scene")
return "Scene2"
class Scene2:
def enter(self):
print "a different scene"
raw_input("Hit Enter To Go Back:")
return "Scene1"
class Engine:
def __init__(self,sceneDict,startKey=1):
self._scenes = sceneDict
self._current = self._scenes[startKey]
def run(self):
while True:
next_scene_key = self._current.enter()
self._current = self._scenes[next_scene_key]
Engine({"Scene1":Scene1(),"Scene2":Scene2()},"Scene1").run()
is one example of many ways to accomplish this

First of all, if you see a lot of repeated code in an OOP-project, you most probably are working against OOP and not with it.
Don't make a new class for each scene, but one object (of scene) for each.
This is a very simple example of how to implement your "engine" (last 4 lines):
#! /usr/bin/python3
class Scene:
def __init__(self, name, welcome, question, answer):
self.name = name
self.welcome = welcome
self.question = question
self.answer = answer
self.connected = []
def connect(self, otherScene):
self.connected.append(otherScene)
def enter(self):
print(self.welcome)
while (input(self.question + ' ') != self.answer): pass #raw_input in py2
if not self.connected: return
print('\nWhither goest thou?')
for i, scene in enumerate(self.connected):
print('{}: {}'.format(i, scene.name))
while True:
try:
i = int(input('? '))
return self.connected[i]
except ValueError:
print('I understand thee not.')
except IndexError:
print('I understand thee not.')
#creating the scenes
house = Scene('A house',
'Thou art standing in front of a house. The landlord talketh to thee.',
'What is the top speed of an uncharged swallow?',
'42')
bridge = Scene('A bridge',
'Thou seest a bridge guarded by a knight clothèd in black.',
'What is the capital of England?',
'London')
swamp = Scene('A swamp',
'Thou enterst a foul morast and a witch eyeballth thee.',
'What is the capital of Azerbaijan?',
'Baku')
castle = Scene('A castle',
'The castle! A fair maiden greeteth thee.',
'What is my name?',
'Peach')
#connecting the scenes
house.connect(bridge)
house.connect(swamp)
bridge.connect(castle)
swamp.connect(castle)
#the game engine
nextScene = house
while nextScene:
nextScene = nextScene.enter()
print('Fin')

Related

Need to have a string contain code

So I'm trying to make a simple text based game from scratch, and I'm running into a problem right away. I'm trying to create a class for events that will happen in-game to make writing the code easier. Here's what I mean:
class event(object):
def __init__(self, text, trigger1, trigger2, outcome1, outcome2):
print(text)
time.sleep(1)
choice= input("What will you do?")
if choice == trigger1:
(Somehow execute outcome 1)
if choice == trigger2:
(Somehow execute outcome 2)
but I don't know how to make the outcomes contain code that I will write later, so any help would be appreciated!
The pythonic way is to use a dictionary with function objects:
def outcome1():
print("Outcome 1")
def outcome2():
print("Outcome 2")
def event(text, triggers):
print(text)
time.sleep(1)
choice= input("What will you do?")
triggers[choice]()
event("You can got west or east.", {
"go west": outcome1,
"go east": outcome2,
})
I do hope I'm understanding your question appropriately, so feel free to correct me if this isn't on target.
When you create a new instance of the class Event (and it's convention to capitalize the first character of classes). Assign a function to the value of outcome1 and outcome2, which will be executed according to their respective triggers.
def outcomeFunction1():
#Whatever you'd like to do for first outcome
print("Hello")
def outcomeFunction2():
#Whatever you'd like to do for second outcome
print("Bye")
Event('text', 'trigger1', 'trigger2', outcomeFunction1(), outcomeFunction2())
In your class definition write:
if choice == trigger1:
outcome1
elif choice == trigger2:
outcome2
Hope this helps!
Why is this in init? Are you really going to create new instance on every new event? To your question, if I got your question correctly, then this is code you may want to have.
def outcome1(text):
print("outcome1: %s" % text)
def outcome2(text):
print ("outcome2: %s" % text)
trigger_map = {
trigger1 : outcome1,
trigger2 : outcome2,
}
class event(object):
def __init__(self, trigger_map):
sefl._tmap = trigger_map
def onEvent (self, text):
print(text)
time.sleep(1)
choice= input("What will you do?")
return self._tmap [choice] (text)
Sorry if I misunderstood your question, but here I go...
The answer here depends on whether you want to have to make a new instance for every event. If you do, the code might look something like this (and as Jeremy E. pointed out, it's a good idea to capitalize the first character of classes):
class Event:
def __init__(self, text, question, trigger1, trigger2, outcome1, outcome2):
self.text, self.question = text, question
self.trigger1, self.trigger2 = trigger1, trigger2
self.outcome1, self.outcome2 = outcome1, outcome2
def get_choice(self):
print(self.text)
self.choice = input(self.question)
def execute(self):
if self.choice == self.trigger1:
exec(self.outcome1)
if self.choice == self.trigger2:
exec(self.outcome2)
I used the exec function to execute the outcomes. I moved some of the code to different functions, leaving the __init__ function to save the variables for the other functions. Then, you can make an instance for each event, like this:
room = Event("You are in a room with exits to the north and east.", "Where will you go?", "north", "east", "print('You went north.')", "print('You went east.'")
Notice I also added a question parameter, as to not force the What will you do? question on every event.
Now, if you wanted to only need one instance of the Event class, the code is a bit different:
class Event:
def make_event(self, text, question, trigger1, trigger2, outcome1, outcome2):
print(text)
choice = input(question)
if choice == trigger1:
exec(outcome1)
if choice == trigger2:
exec(outcome2)
You can see that the code is much shorter. To create an event with this, you would do something like this (with the same example as before):
event = Event() # This is only needed once, at the start of the program
event.make_event("You are in a room with exits to the north and east.", "Where will you go?", "north", "east", "print('You went north.')", "print('You went east.')")
EDIT: You may want to remove the class definition entirely, leaving just the make_event function I wrote for you above.
You can choose between either of these class examples, or use their ideas to make a customized one. I hope I answered your question.

I cannot figure out why I am getting AttributeError

Dear StackOverflow Angels,
I am really stuck with this problem. I am coding a game and am receiving this error message:
File "VillageGame.py", line 120, in <module>
launch.play()
File "VillageGame.py", line 84, in play
returned_scene = future_scene.enter()
AttributeError: 'NoneType' object has no attribute 'enter'
Here is the code referenced by the error message:
class Room(object):
def __init__(self):
pass
def enter(self):
pass
class Road(Room):
def __init__(self):
pass
def enter(self):
pass
def walk(self):
print "It is afternoon and you stand by the road of Red Village. It is a small, run-down place"
print "with a few shops and houses. A few residents walk about. It is a quiet place. You need"
print "to steal gold to feed yourself and pay your rent. This evening you need to steal 800 gold"
print "to pay your rent and bills. There are houses and businesses in the area. But plan carefully,"
print "the police here are armed and the locals are suspicious of odd outsiders like yourself. But"
print "you can fight, which should help. In front of you is a food shop, a weapons shop,"
print "a medicine shop, a bank and an inn. Where would you like to go first?"
return 'road'
def run(self):
pass
class Engine(object):
def __init__(self, game_map):
self.game_map = game_map
def play(self):
future_scene = self.game_map.launch_scene()
last_scene = self.game_map.next_scene('finished')
while future_scene != last_scene:
returned_scene = future_scene.enter()
future_scene = self.game_map.next_scene(returned_scene)
# make sure you run the last scene
future_scene.enter()
class Map(object):
rooms = {
'road' : Road(),
'food_shop' : FoodShop(),
'weapons_shop' : WeaponsShop(),
'medicine_shop' : MedicineShop(),
'bank' : Bank(),
'inn' : Inn(),
'death' : Death(),
'finished' : Finished()
}
def __init__(self, start_scene):
self.start_scene = start_scene
def next_scene(self, returned_scene):
val = Map.rooms.get(returned_scene)
return val
def launch_scene(self):
return self.next_scene(self.start_scene)
firstscene = Map('road')
launch = Engine(firstscene)
launch.play()
Apologies if this seems like a code dump, but I don't know what parts are relevant to the error message and what parts are not linked to it - because I am quite new to this you see.
If anyone has any insight into what code I could cut out of this message, I Would appreciate that too. It would help me to keep future questions shorter.
The problem is Map('road') returns None. I think what you're trying to do is this.
map = Map('road')
firstscene = map.launch_scene()
launch = Engine(firstscene)
launch.play()
But even that is not quite right. The line below doesn't instantiate a map.
val = Map.rooms.get(returned_scene)
If you want to call a function of the Map class from within that class, use the self keyword such as self.rooms.get(returned_scene).
This line returned_scene = future_scene.enter() expects a return value but you haven't implemented anything in the methoddef enter(self) (you're just pass-ing it, and so it returns a None object.

LPTHW ex. 45, how to return functions from a class in another module?

Trying to make my own RPG character generator for ex 45 in Zed Shaw's LPTHW. Part of the assignment is to make a new class for each 'room' of the program, like WelcomeScreen or ChooseMutations.
Here is the main program.
import rooms
class Program(object):
def __init__(self, start):
self.start = start
def run(self):
next_room_name = self.start
while True:
room = getattr(self, next_room_name)
next_room_name = room()
x = rooms.WelcomeRoom()
Program(x.hello_user())
And here is the rooms file its trying to pull stuff from.
class WelcomeRoom(object):
def __init__(self):
pass
def hello_user(self):
print '*' * 79
print '\n'
print '\t\tWelcome to the'
print '\t\tMetamorphosis Alpha Character & Random Encounter Generator'
print '\t\tProgrammed poorly by Raymond Weiss'
print '\n'
print '*' * 79
raw_input('Please press enter to continue')
return 'get_name'
def get_name(self):
name = raw_input('Hello, whats your name?',
'\n',
':> ')
But when I run the main program in python, it just logs out instead of returning the function get_name() from rooms. Output posted below.
Raymond-Weisss-MacBook-Pro:macgre Raylug$ python macgre.py
*******************************************************************************
Welcome to the
Metamorphosis Alpha Character & Random Encounter Generator
Programmed poorly by Raymond Weiss
*******************************************************************************
Please press enter to continue
Raymond-Weisss-MacBook-Pro:macgre Raylug$
I apologize in advance if my question title isn't exactly what im trying to ask, as a newbie its sometimes hard not knowing what exactly to ask.
You're returning a string, not a function (or function result). You probably want something like:
def hello_user(self):
return self.get_name
or
def hello_user(self):
return self.get_name()
Based on your program, I think you probably want the second one. The difference is that the first one returns the get_name function, whereas the second one returns the results of the get_name function.

Python - Classes and OOP Basics

I do not fully understand classes. I have read the python documentation and several other tutorials. I get the basic gist of it but don't understand the nuance. For instance in my code here:
class whiteroom():
""" Pick a door: red, blue, green, or black. """
do = raw_input("> ")
if "red" in do:
print "You entered the red room."
elif "blue" in do:
print "You entered the blue room."
elif "green" in do:
print "You entered the green room."
elif "black" in do:
print "You entered the black room."
else:
print "You sit patiently but slowly begin to stave. You're running out of time."
return whiteroom()
game = whiteroom()
game
(original codepad)
I would like to return the class whiteroom. Which is, either not possible, or not being done correctly. If you could clear up how to return a class or how to "link" two classes together so that whiteroom repeats on the else and the other rooms (which would be classes) are returned when called that would be awesome.
Also I'm super shaky on __init__ and am still not really sure what its purpose is. Everyone keeps telling me that it "initializes", which I'm sure it does, but that doesn't seem to be helping my brain out.
Functions are very different from classes. It looks like you took a function and just changed the def to class. I guess that mostly works in your case, but it's not how classes are supposed to go.
Classes contain functions (methods) and data. For example, you have a ball:
class Ball(object):
# __init__ is a special method called whenever you try to make
# an instance of a class. As you heard, it initializes the object.
# Here, we'll initialize some of the data.
def __init__(self):
# Let's add some data to the [instance of the] class.
self.position = (100, 100)
self.velocity = (0, 0)
# We can also add our own functions. When our ball bounces,
# its vertical velocity will be negated. (no gravity here!)
def bounce(self):
self.velocity = (self.velocity[0], -self.velocity[1])
Now we have a Ball class. How can we use it?
>>> ball1 = Ball()
>>> ball1
<Ball object at ...>
It doesn't look very useful. The data is where it could be useful:
>>> ball1.position
(100, 100)
>>> ball1.velocity
(0, 0)
>>> ball1.position = (200, 100)
>>> ball1.position
(200, 100)
Alright, cool, but what's the advantage over a global variable? If you have another Ball instance, it will remain independent:
>>> ball2 = Ball()
>>> ball2.velocity = (5, 10)
>>> ball2.position
(100, 100)
>>> ball2.velocity
(5, 10)
And ball1 remains independent:
>>> ball1.velocity
(0, 0)
Now what about that bounce method (function in a class) we defined?
>>> ball2.bounce()
>>> ball2.velocity
(5, -10)
The bounce method caused it to modify the velocity data of itself. Again, ball1 was not touched:
>>> ball1.velocity
Application
A ball is neat and all, but most people aren't simulating that. You're making a game. Let's think of what kinds of things we have:
A room is the most obvious thing we could have.
So let's make a room. Rooms have names, so we'll have some data to store that:
class Room(object):
# Note that we're taking an argument besides self, here.
def __init__(self, name):
self.name = name # Set the room's name to the name we got.
And let's make an instance of it:
>>> white_room = Room("White Room")
>>> white_room.name
'White Room'
Spiffy. This turns out not to be all that useful if you want different rooms to have different functionality, though, so let's make a subclass. A subclass inherits all functionality from its superclass, but you can add more functionality or override the superclass's functionality.
Let's think about what we want to do with rooms:
We want to interact with rooms.
And how do we do that?
The user types in a line of text that gets responded to.
How it's responded do depends on the room, so let's make the room handle that with a method called interact:
class WhiteRoom(Room): # A white room is a kind of room.
def __init__(self):
# All white rooms have names of 'White Room'.
self.name = 'White Room'
def interact(self, line):
if 'test' in line:
print "'Test' to you, too!"
Now let's try interacting with it:
>>> white_room = WhiteRoom() # WhiteRoom's __init__ doesn't take an argument (even though its superclass's __init__ does; we overrode the superclass's __init__)
>>> white_room.interact('test')
'Test' to you, too!
Your original example featured moving between rooms. Let's use a global variable called current_room to track which room we're in.1 Let's also make a red room.
1. There's better options besides global variables here, but I'm going to use one for simplicity.
class RedRoom(Room): # A red room is also a kind of room.
def __init__(self):
self.name = 'Red Room'
def interact(self, line):
global current_room, white_room
if 'white' in line:
# We could create a new WhiteRoom, but then it
# would lose its data (if it had any) after moving
# out of it and into it again.
current_room = white_room
Now let's try that:
>>> red_room = RedRoom()
>>> current_room = red_room
>>> current_room.name
'Red Room'
>>> current_room.interact('go to white room')
>>> current_room.name
'White Room'
Exercise for the reader: Add code to WhiteRoom's interact that allows you to go back to the red room.
Now that we have everything working, let's put it all together. With our new name data on all rooms, we can also show the current room in the prompt!
def play_game():
global current_room
while True:
line = raw_input(current_room.name + '> ')
current_room.interact(line)
You might also want to make a function to reset the game:
def reset_game():
global current_room, white_room, red_room
white_room = WhiteRoom()
red_room = RedRoom()
current_room = white_room
Put all of the class definitions and these functions into a file and you can play it at the prompt like this (assuming they're in mygame.py):
>>> import mygame
>>> mygame.reset_game()
>>> mygame.play_game()
White Room> test
'Test' to you, too!
White Room> go to red room
Red Room> go to white room
White Room>
To be able to play the game just by running the Python script, you can add this at the bottom:
def main():
reset_game()
play_game()
if __name__ == '__main__': # If we're running as a script...
main()
And that's a basic introduction to classes and how to apply it to your situation.
I'm sure you've heard all this before, but I'll give it a go.
Classes are a way to group up a bunch of function and variables into a single object. When you get all the way down to it, this is simply a way of organizing everything into groups that make sense. There are benefits down the road for making things easier to understand, debug, extend, or maintain, but basically its just a way to make something more defined in your mental model.
Your code looks like you are trying to write your entire program inside an 'object' (really, you just have an incorrectly written function).
Consider this instead.
Think of your mental model of rooms which have doors to them and whiteboards in them. Doors have a color. Also, whiteboards can have some text written on them. We'll leave it there to be simple.
To me, this suggests 3 different objects -- a door object that has a string for color, a whiteboard object that has a string for the text, and a room object that has a door and a whiteboard.
Consider the following code:
class Door(object):
def __init__(self, color):
self.color = color
class Whiteboard(object):
def __init__(self, default_text=''):
self.text = ''
self.write_text(default_text)
def write_text(self, text):
self.text += text
def erase(self):
self.text = ''
class Room(object):
def __init__(self, doorcolor, whiteboardtext=''):
self.whiteboard = Whiteboard(whiteboardtext)
self.door = Door(doorcolor)
# make a room with a red door and no text on the whiteboard
room1 = Room('red')
# make a room with a blue door and 'yeah, whiteboard' on the whiteboard
room2 = Room('blue', 'yeah, whiteboard')
# make a room with a green door
room3 = Room('green')
# now I can play around with my 'rooms' and they keep track of everything internally
print 'room 1 door color: ' + room1.door.color
print 'room 2 door color: ' + room2.door.color
# all my rooms have a door and a whiteboard, but each one is different and self contained. For example
# if I write on room 1's whiteboard, it doesn't change anything about room 3s
print 'room1 whiteboard: ' + room1.whiteboard.text
print 'room2 whiteboard: ' + room2.whiteboard.text
print 'room3 whiteboard: ' + room3.whiteboard.text
print '-- changeing room 1 whiteboard text --'
room1.whiteboard.write_text('oop is really helpful')
print 'room1 whiteboard: ' + room1.whiteboard.text
print 'room2 whiteboard: ' + room2.whiteboard.text
print 'room3 whiteboard: ' + room3.whiteboard.text
The init function is what gets called when you 'initialize' a new instance of your class. In the example I am making 3 Room objects which each create a Door and Whiteboard object internally. The parameters I pass into the constructor Room(parameter1, parameter2) get passed to the init functions - you can see I'm using this to set the door color and optionally some text on the whiteboard. Also notice that the variables that 'belong' to the objects are referenced with self - this reference is what gets passed in as the first parameter to all class functions (and becomes more important later when you are extending classes and other more advanced things).
You're really far off.
Sorry to say it, but this is just barely salvageable.
From what I can tell you want something like a room class, for instance:
class Room(object):
''' A generic room '''
def __init__(self):
self.choices = None
self.enter()
def enter(self):
''' Enter the room, to be filled out in subclass '''
pass
def print_choices(self):
'''You are stuck bro'''
print "You are stuck bro"
Then you can make a specific room like the whiteroom like so:
class Whiteroom(Room):
''' A white room '''
def __init__(self):
self.choices = ["red", "blue", "green", "black"]
self.enter()
def enter(self):
print "You sit patiently, but slowly begin to starve. You're running out of time."
def print_choices(self):
print "You can choose from the following rooms:"
print self.choices
class Blackroom(Room):
''' A black room '''
def enter(self):
print "It's really dark in here. You're out of time."
class Redroom(Room):
''' A red room '''
def __init__(self):
self.choices = ["black", "blue", "green", "white"]
self.enter()
def enter(self):
print "It's getting hot in here. So take off all your clothes."
def print_choices(self):
print "You can choose from the following rooms:"
print self.choices
class Blueroom(Room):
''' A blue room '''
def __init__(self):
self.choices = ["black", "red", "green", "white"]
self.enter()
def enter(self):
print "It's nice and cool in here. Stay awhile if you want."
def print_choices(self):
print "You can choose from the following rooms:"
print self.choices
class Greenroom(Room):
''' A green room '''
def __init__(self):
self.choices = ["black", "red", "blue", "white"]
self.enter()
def enter(self):
print "You won."
Then you'd have do this to run the game:
print "Type 'quit' to quit"
print "Type 'choices' to see what your choices are"
current_room = Whiteroom()
done = False
while (not done):
entry = raw_input("> ")
if entry == "quit":
done = True
if "choices" in entry:
current_room.print_choices()
if current_room.choices:
if entry in current_room.choices:
if "white" in entry:
current_room = Whiteroom()
if "black" in entry:
current_room = Blackroom()
if "red" in entry:
current_room = Redroom()
if "green" in entry:
current_room = Greenroom()
done = True
if "blue" in entry:
current_room = Blueroom()
That's my best attempt at turning your snippet into an actual game, using classes.
In OOP you have types and objects. Types are abstractions (I would call it idea of) and concrete objects. When you define a class via the syntax class Idea: you identify a type and you can give that type attributes and abilities.
For example:
class Idea:
populare = None
#staticmethod
def change_the_world(atrribute):
return f'a new {attribute} world'
Why is it great and not just a coding style? Just because, in our complex world there are many ideas and even more of the idea of those ideas and so it appears in complex applications. You can have the idea itself as a basement, a mix of other ideas, as a layer in multiple levels of ideas or a hybrid of all that.
As an example:
class Idea:
populare = None
#staticmethod
def change_the_world(atrribute):
return f'a new {attribute} world'
class Freedom(Idea):
populare = True
#classmethod
def desire(cls):
return cls.change_the_world('free')
How powerful this is? You will notice when you think about built-in-types and what all you have done or could do with them. How easy it gets to implement design pattern and to built a whole world that manifests your point of view. But enough of types, there are a concrete objects. They are manifested types with individual identities, so called Entity's.
As example:
class Color:
def __init__(self, name, value):
self.name = None
self.value = None
def less_red(self):
red_portion = self.value[0]
new_value = red_portion-1
self.value = (new_value, self.value[1], self.value[2])
return self.value
my_red = Color('My Red', (255, 0, 0))
Entities can be imagine as manifested idea, that can be identified by themselves. That why the we usually write self as the first parameter in the __init__ it is a hint that this pointer is a reference to itself, not the class but the entity you just initialized.
class Circle():
pi = 3.14
def __init__(self,radius=1):
self.radius = radius
self.area = radius*radius*self.pi
def get_circrumference(self):
return self.radius* self.pi*2
result:
Circle(23)
my_circle = Circle(30)
my_circle.pi =
3.14
my_circle.radius =
30
my_circle.get_circrumference() =
118.4
my_circle.area =
2826.0
help(Circle) =
Help on class Circle in module main:
class Circle(builtins.object)
| Circle(radius=1)
|
| Methods defined here:
|
| init(self, radius=1)
| Initialize self. See help(type(self)) for accurate signature.
|
| get_circrumference(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| dict
| dictionary for instance variables (if defined)
|
| weakref
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| pi = 3.14
Here's a simple implementation of cartesian points using class:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, move_x, move_y):
self.x += move_x
self.y += move_y
def scale(self, factor):
self.x *= factor
self.y *= factor
def mod(self):
return (self.x ** 2 + self.y ** 2) ** (1 / 2)
A = Point(3, 4)
print(A.x, A.y) -> 3 4
print(A.mod()) -> 5
A.move(2, 8) #(5, 12)
A.scale(2) #(10, 26)

How can I use a returned value to open up another instance of a class in Python?

I am on exercise 43 doing some self-directed work in Learn Python The Hard Way. And I have designed the framework of a game spread out over two python files. The point of the exercise is that each "room" in the game has a different class. I have tried a number of things, but I cannot figure out how to use the returned value from their initial choice to advance the user to the proper "room", which is contained within a class. Any hints or help would be greatly appreciated.
Apologies for the poor code, I'm just starting out in python, but at my wit's end on this.
Here is the ex43_engine.py code which I run to start the game.
from ex43_map import *
import ex43_map
import inspect
#Not sure if this part is neccessary, generated list of all the classes (rooms) I imported from ex43_map.py, as I thought they might be needed to form a "map"
class_list = []
for name, obj in inspect.getmembers(ex43_map):
if inspect.isclass(obj):
class_list.append(name)
class Engine(object):
def __init__(self, room):
self.room = room
def play(self):
# starts the process, this might need to go inside the loop below
next = self.room
start.transportation_choice()
while True:
print "\n-------------"
# I have tried numerous things here to make it work...nothing has
start = StartRoom()
car = CarRoom()
bus = BusRoom()
train = TrainRoom()
airplane = AirplaneRoom()
terminal = TerminalRoom()
a_game = Engine("transportation_choice")
a_game.play()
And here is the ex43_map.py code
from sys import exit
from random import randint
class StartRoom(object):
def __init__(self):
pass
def transportation_choice(self):
print "\nIt's 6 pm and you have just found out that you need to get to Chicago by tomorrow morning for a meeting"
print "How will you choose to get there?\n"
print "Choices: car, bus, train, airplane"
choice = raw_input("> ")
if choice == "car":
return 'CarRoom'
elif choice == "bus":
return 'BusRoom'
elif choice == "train":
return 'TrainRoom'
elif choice == "airplane":
return 'AirplaneRoom'
else:
print "Sorry but '%s' wasn't a choice." % choice
return 'StartRoom'
class CarRoom(object):
def __init__(self):
print "Welcome to the CarRoom"
class BusRoom(object):
def __init__(self):
print "Welcome to the BusRoom"
class TrainRoom(object):
def __init__(self):
print "Welcome to the TrainRoom"
class AirplaneRoom(object):
def __init__(self):
print "Welcome to the AirplaneRoom"
class TerminalRoom(object):
def __init__(self):
self.quips = [
"Oh so sorry you died, you are pretty bad at this.",
"Too bad, you're dead buddy.",
"The end is here.",
"No more playing for you, you're dead."
]
def death(self):
print self.quips[randint(0, len(self.quips)-1)] # randomly selects one of the quips from 0 to # of items in the list and prints it
exit(1)
Instead of returning a string try returning an object, ie
if choice == "car":
return CarRoom()
It might be a good idea to make a Room class, and derive your other rooms from it.
The Room base class can then have a class variable which automatically keeps track of all instantiated rooms.
I haven't thoroughly tested the following, but hopefully it will give you some ideas:
# getters.py
try:
getStr = raw_input # Python 2.x
except NameError:
getStr = input # Python 3.x
getStr.type = str
def typeGetter(dataType):
def getter(msg):
while True:
try:
return dataType(getStr(msg))
except ValueError:
pass
getter.type = dataType
return getter
getInt = typeGetter(int)
getFloat = typeGetter(float)
getBool = typeGetter(bool)
def getOneOf(*args, **kwargs):
"""Get input until it matches an item in args, then return the item
#param *args: items to match against
#param getter: function, input-getter of desired type (defaults to getStr)
#param prompt: string, input prompt (defaults to '> ')
Type of items should match type of getter
"""
argSet = set(args)
getter = kwargs.get('getter', getStr)
prompt = kwargs.get('prompt', '> ')
print('[{0}]'.format(', '.join(args)))
while True:
res = getter(prompt)
if res in argset:
return res
.
# ex43_rooms.py
import textwrap
import random
import getters
class Room(object):
# list of instantiated rooms by name
ROOMS = {}
#classmethod
def getroom(cls, name):
"""Return room instance
If named room does not exist, throws KeyError
"""
return cls.ROOMS[name]
def __init__(self, name):
super(Room,self).__init__()
self.name = name
Room.ROOMS[name] = self
def run(self):
"""Enter the room - what happens?
Abstract base method (subclasses must override)
#retval Room instance to continue or None to quit
"""
raise NotImplementedError()
def __str__(self):
return self.name
def __repr__(self):
return '{0}({1})'.format(self.__class__.__name__, self.name)
class StartRoom(Room):
def __init__(self, name):
super(StartRoom,self).__init__(name)
def run(self):
print textwrap.dedent("""
It's 6 pm and you have just found out that you need to get to Chicago
by tomorrow morning for a meeting! How will you get there?
""")
inp = getters.getOneOf('car','bus','train','airplane')
return Room.getroom(inp)
class CarRoom(Room):
def __init__(self,name):
super(CarRoom,self).__init__(name)
class BusRoom(Room):
def __init__(self,name):
super(BusRoom,self).__init__(name)
class TrainRoom(Room):
def __init__(self,name):
super(TrainRoom,self).__init__(name)
class PlaneRoom(Room):
def __init__(self,name):
super(PlaneRoom,self).__init__(name)
class TerminalRoom(Room):
def __init__(self,name):
super(TerminalRoom,self).__init__(name)
def run(self):
print(random.choice((
"Oh so sorry you died, you are pretty bad at this.",
"Too bad, you're dead buddy.",
"The end is here.",
"No more playing for you, you're dead."
)))
return None
# create rooms (which registers them with Room)
StartRoom('start')
CarRoom('car')
BusRoom('bus')
TrainRoom('train')
PlaneRoom('airplane')
TerminalRoom('terminal')
.
# ex43.py
from ex43_rooms import Room
def main():
here = Room.getroom('start')
while here:
here = here.run()
if __name__=="__main__":
main()

Categories

Resources