Due at 11:59pm on 07/16/2015.

Starter Files

Download lab08.zip. Inside the archive, you will find starter files for the questions in this lab, along with a copy of the OK autograder.

Submission

By the end of this lab, you should have submitted the lab with python3 ok --submit. You may submit more than once before the deadline; only the final submission will be graded.

To receive credit for this lab, you must complete the following:

  • Unlock Question 1 (What would Python print?)
  • Complete Questions 2 in data.py
  • Complete Questions 3, 4, and 5 in classses.py

In this lab, you will use Object-oriented programming (OOP) — a style of programming that allows you to think of code in terms of "objects" — to build a text-based adventure game!

Prologue

It's the day of the CS 61A potluck, and Robert needs to buy food for the potluck. It would be really convenient if he could drive a car; after all, there's a lot of food to carry!

In car.py, you'll find a class called Car. Remember that a class is a blueprint for how to create objects of that type; in this case, the Car class tells us how to to create create Car objects.

Let's build Robert a car. Don't worry, you won't need to do any physical work, the constructor will do it for you. A class's constructor is a function that builds an instance of the class. In Python, the constructor is called the __init__. There must be two underscores on each side of init. The Car class's constructor looks like this:

def __init__(self, model_type):
    self.wheels = Car.num_wheels
    self.color = "No color yet. You need to paint me."
    self.model = model_type

Let's make our car. First, open up the Python interpreter and load car.py:

python3 -i car.py

Robert would like to drive a Tesla. Try constructing an instance of the Car class with the following::

roberts_car = Car("Tesla")

An object is an instance of a class. In this case,roberts_car is an instance of the Car class.

That's cool and all, but what color is my car?

We'll use an attribute of the class. An attribute is a quality of the object: cars have wheels and color, so we have given our Car class self.wheels and self.color attributes. We can access attributes using dot notation. What does the following print in the interpreter?

roberts_car.color

Look's like we need to paint it.

Let's use the paint method. Methods are functions that are bound to an object. Think of methods as "verbs" of the class. Cars can drive so we have given our Car class the method drive. Try out the following in the interpreter:

roberts_car.paint("Black")
roberts_car.color

Awesome! But why don't I need to input two arguments? The car constructor should take in self and model, but I only passed in model, and it worked. Why?

In Python, the dot notation implicitly passes in roberts_car as self. When a method is called, self is bound to an instance of the class.

Question 1: What would Python print?

Use OK to test your knowledge with the following What would Python print questions:

python3 ok -q car -u
>>> roberts_car = Car("Tesla")
>>> roberts_car.model
______
'Tesla'
>>> Car.headlights
______
2
>>> roberts_car.headlights
______
2
>>> Car.headlights = 3 >>> roberts_car.headlights
______
3
>>> roberts_car.headlights = 2 >>> Car.headlights
______
3
>>> roberts_car.wheels = 2
>>> roberts_car.wheels
______
2
>>> Car.num_wheels
______
4
>>> roberts_car.drive()
______
'Tesla cannot drive!'

Variables

Before you enter Soda! You must take this chart with you...

With OOP be aware of three types of variables:

Notice: Local variables has two examples

Instance Attributes Class Attributes Local Variable
Traits - Will be accessible after method calls.
- Each instance of a class keeps its own version of the instance attribute
- Will be accessible after method calls.
- All instances of a class will share the same class attributes.
- Will not be accessible after method or function calls.
- Just like the variables in normal functions.
Examples
>>> car1 = Car('red')
>>> car2 = Car('blue')
>>> car1.color
'red'
>>> car2.color
'blue'
>>> car1.color = 'yellow'
>>> car1.color
'yellow'
>>> car2.color
'blue' 
>>> car1 = Car('red')
>>> car2 = Car('blue')
>>> car1.num_wheels
4
>>> car2.num_wheels
4
>>> Car.num_wheels = 2
>>> car1.num_wheels
2
>>> car2.num_wheels
2
def __init__(self, model_type):
    self.wheels = Car.num_wheels
    self.color = "No color yet.
    You need to paint me."
    self.model = model_type

def method(self):
    x = 5
Explanations We construct two Car instances. Each has its own self.color instance attribute/variable. One is 'red', and the other is 'blue'. num_wheels is a class attribute of the Car class. model_type is a local variable. It is not accessible outside of the __init__ method. In contrast, self.model is an instance variable that is accessible everywhere. x is also a local variable.

Note: Access class attributes by <class name>.<attribute>, such as Car.num_wheels, or by <instance>.<attribute>, such as car1.num_wheels.

Adventure Game!

In this lab, you will implement a text adventure game. To start the game, type

python3 adventure.py

The ZIP archive provided at the start of lab contains all the starter code. All of your changes will be made to classes.py, although you have to create yourself as a player in data.py before implementing anything else.

  • classes.py: Implementation for classes used in the game
  • data.py: All of the objects used in the game
  • adventure.py: Interpreter of the game

Question 2: Who am I?

It is time for you to enter a world of adventure! First, you need to create yourself as a Player object in data.py. Take a look at the Player class in classes.py and create a Player object at the bottom of data.py.

The Player constructor takes two arguments:

  • name should be your preferred name (as a string)
  • the starting place

Your Player should start at sather_gate.

# Player:
# The Player should start at sather_gate.
me = None
me = Player('Sally', sather_gate)

Question 3: Where do I go?

Once you've created your player, you can start the adventure game:

python3 adventure.py

You will see the following output:

Welcome to the adventure game!

It's a bright sunny day.
You are a cute little squirrel named [your name],
wandering around Berkeley campus looking for food.

Let's go to FSM (Free Speech Movement Cafe)
and see what we can find there!

There are 6 possible commands:
    talk to [character]
    help
    take [thing]
    go to [direction]
    look
    check backpack

adventure>

First, we need to be able to go to places. If you try the go command, you'll notice it doesn't do anything.

In classes.py, implement the go_to method in the Player class. go_to takes in a direction that you want to go to.

Hint: The exit_to method in Place will return the corresponding Place object if direction is among your available exits. Otherwise, exit_to will return the current Place. Take a look at the doctest for more details.

def go_to(self, direction):
    """Go to direction if it's among the exits of player's current place.
    >>> sather_gate = Place('Sather Gate', 'You are at Sather Gate', [], [])
    >>> gbc = Place('GBC', 'You are at Golden Bear Cafe', [], [])
    >>> sather_gate.add_exits([gbc])
    >>> gbc.add_exits([sather_gate])
    >>> me = Player('player', sather_gate)
    >>> me.go_to('GBC')
    You are at Golden Bear Cafe
    >>> me.place.name
    'GBC'
    >>> me.go_to('GBC')
    Can't go to GBC from GBC.
    Try looking around to see where to go.
    >>> me.go_to('Sather Gate')
    You are at Sather Gate
    """
"*** YOUR CODE HERE ***"
self.place = self.place.exit_to(direction)

Use OK to test your code:

python3 ok -q go_to

Question 4: How do I talk?

Now you can go wherever you want! Try going to Wheeler Hall. There, you'll find Derrick. Try talking to him with the talk to command. This also doesn't work :(

Next, implement the talk_to method in Player. talk_to takes in the name of a Character object, and prints out the Character's response. Take a look at the doctest for more details.

Hint: talk_to takes in an argument person, which is a string. The characters instance attribute in self.place is a dictionary mapping Character names (strings) to Character objects.

Once you've got the Character object, what method in the Character class will make them talk?

def go_to(self, direction):
    """Go to direction if it's among the exits of player's current place.
    >>> sather_gate = Place('Sather Gate', 'You are at Sather Gate', [], [])
    >>> gbc = Place('GBC', 'You are at Golden Bear Cafe', [], [])
    >>> sather_gate.add_exits([gbc])
    >>> gbc.add_exits([sather_gate])
    >>> me = Player('player', sather_gate)
    >>> me.go_to('GBC')
    You are at Golden Bear Cafe
    >>> me.place.name
    'GBC'
    >>> me.go_to('GBC')
    Can't go to GBC from GBC.
    Try looking around to see where to go.
    >>> me.go_to('Sather Gate')
    You are at Sather Gate
    """
"*** YOUR CODE HERE ***"
self.place = self.place.exit_to(direction)

Use OK to test your code:

python3 ok -q talk_to

Question 5: How do I take items?

Now you can talk to people in adventure world! To make it even better, let's implement the take method in the Player class. take takes in a Thing object and puts it into your backpack. Currently, you don't have a backpack, so let's create an instance variable backpack and initialize it to an empty list.

After you've done initialized your empty backpack, take a look at the doctests for take and implement the method.

Hint: the things instance attribute in the Place class is a dictionary that maps Thing names (strings) to Thing objects.

The take method in the Place class will also come in handy.

def take(self, thing):
    """Take a thing if thing is at player's current place
    >>> hotdog = Thing('Hotdog', 'A hot looking hotdog')
    >>> gbc = Place('GBC', 'You are at Golden Bear Cafe', [], [hotdog])
    >>> me = Player('Player', gbc)
    >>> me.backpack
    []
    >>> me.take(hotdog)
    Thing should be a string.
    >>> me.take('dog')
    dog is not here.
    >>> me.take('Hotdog')
    Player takes the Hotdog
    >>> me.take('Hotdog')
    Hotdog is not here.
    >>> type(me.backpack[0])
    <class '__main__.Thing'>
    """
    if type(thing) != str:
        print('Thing should be a string.')
return None # Replace this line
elif thing not in self.place.things: print(thing, 'is not here.') else: taken = self.place.take(thing) print(self.name, 'takes the', taken.name) self.backpack.append(taken)

Use OK to test your code:

python3 ok -q take

Question 6: Win the game!

Good job! Now you can explore around campus and try to win the game. Talk to the people at different places in order to get hints. Can you save the day and make it to the 61A potluck in time?

Enjoy!