CS21 Lab 11: Classes and Objects

This lab is due Saturday, May 2, before midnight

Goals

  • gain experience writing classes

  • gain experience reading and using classes

This week’s lab is to write an in-terminal version of the Neko Atsumi (Kitty Collector) game. It’s just a simple, fun game (also free if you want to try it on your phone) where you buy items (toys and food) to put in your yard, and sometimes cats come visit your yard!

neko atsumi example image

The game is silly and cute, but also an excellent example of classes and objects. In our version of the game we will have 4 different objects (Item, Cat, Store, Yard). We are giving you two of the classes (Store, Yard). Your job is to write the other two classes (Item, Cat), test code for the Store and Yard classes, and some of the functions in the game implementation.

For reference, game play is a simple menu of choices: see the yard, shop for items, see your cat album (where you keep a record of all cats that have visited your yard), and quit. You also start with a certain amount of money (fishes) to shop with. If you have toys and food in your yard, there’s a chance one or more cats will visit your yard. When cats visit and then leave your yard, they leave you a gift (more fishes).

1. the Item class

There are a lot of files in this lab. Don’t worry about all of them now. We’ll edit some and just use the others. If you follow the lab writeup, we’ll guide you through which ones to edit and when. The writeup may seem long, but there are only a few files to edit and run.

Start by editing item.py and writing the Item class. You can write and test this object on it’s own. Items can be either food or toys. Here are the instance variables for an Item object:

  • name: name of the item (ex: "Rubber Ball" or "Frisky Bitz")

  • cost: how much the item costs (ex: 20)

  • itype: the type of the item ("food" or "toy")

And here are the methods you need to write for the Item class:

method description

__init__(self,name,cost,itype)

constructor for Item objects

__str__(self)

should return string representation of object

getName(self)

getter for name of item

getCost(self)

getter for cost of item

getItemType(self)

getter for type of item

setCost(self,cost)

setter for cost of item (if we want to change cost)

isToy(self)

returns True if item is a toy, False if not

isFood(self)

returns True if item is food, False if not

For reference, here is a short example of using the Item class:

   item = Item("Meow Mix",20,"food")
   print(item)
   item.setCost(25)
   print(item)
   print(item.isFood())
At the bottom of the given item.py file we have already provided some test code. We suggest running python3 item.py after you implement each method, even though some of the tests will fail (since you haven’t written all of the methods yet).

For example, after writing the __init__(…​) and __str__(self) methods, you should see something like this (depending on how your str method formats the item data):

$ python3 item.py
         Rubber Ball:  60 fishes (toy)
              Pillow: 120 fishes (toy)
           Fish Bowl:  80 fishes (toy)
                Yarn: 120 fishes (toy)
         Frisky Bitz:  30 fishes (food)
   Two-tier Cat Tree: 200 fishes (toy)
    Deluxe Tuna Bitz:  12 fishes (food)
             Sashimi:  52 fishes (food)
    Fluffy Brown Bed: 160 fishes (toy)
            Bean Bag: 120 fishes (toy)
       Colorful Sock:  20 fishes (toy)
          White Sock:  22 fishes (toy)
           Toy Mouse:  75 fishes (toy)
           Green Box:   5 fishes (toy)
            Keyboard:  95 fishes (toy)
                Tape:  15 fishes (toy)
         Punch Cards:  64 fishes (toy)
        Cheese Bites:  15 fishes (food)
Traceback (most recent call last):
  File "item.py", line 52, in 
    main()
  File "item.py", line 43, in main
    assert(fakeitem.getName()==name)
AttributeError: 'Item' object has no attribute 'getName'

The AttributeError at the end just means we tried to test the getName() method and it failed because you haven’t written it yet. Once you write getName(), that test should pass, and you won’t see an attribute error for getName. Just continue writing methods and running the test code until you don’t see any more errors.

Also note: the utils.py file provides a function called loadItems(filename) that reads in items from the items.txt file. We will use these for the game.

At this point you should have a working Item class. Do not proceed unless your Item class is fully written and tested!

2. the Cat class

Next edit cat.py and write the Cat class. You can write and test this object on it’s own, too. Here are the instance variables for a Cat object:

  • name: name of the cat (ex: "Pumpkin")

  • description: description of the cat (ex: "Orange Tabby")

  • personality: personality of the cat (ex: "Shy")

  • visits: how many times the cat has visited your yard (initially 0 for all cats)

And here are the methods you need to write for the Cat class:

method description

__init__(self,name,description,personality)

constructor for Cat objects

__str__(self)

should return string representation of object

getName(self)

getter for name of cat

getDescription(self)

getter for description of cat

getPersonality(self)

getter for personality of cat

getVisits(self)

getter for visits by cat

getFishes(self)

return random number of fishes (10-50)

visited(self)

add 1 to number of visits by cat

Notice that the self.visits instance variable is not used when creating new Cat objects. All cats automatically start with zero visits.

For reference, here is a short example of using the Cat class:

>>> from cat import *
>>> c = Cat("Pumpkin","Orange Tabby","Shy")
>>> print(c)
Name: Pumpkin
Description: Orange Tabby
Personality: Shy
Visits: 0

>>> c.visited()
>>> print(c.getVisits())
1
>>> print(c)
Name: Pumpkin
Description: Orange Tabby
Personality: Shy
Visits: 1

>>> fishes = c.getFishes()
>>> print(fishes)
13
>>> fishes = c.getFishes()
>>> print(fishes)
29

You can see sample cat data in the cats.txt file, and utils.py has a function to load all cat data and create Cat objects. We will use these in the game.

At the bottom of the given cat.py file we have already provided some test code. We suggest running python3 cat.py after you implement each method, even though some of the tests will fail (since you haven’t written all of the methods yet). Just continue writing methods and running the test code until you don’t see any more errors.

3. the Store class

We’ve already written this class for you, so you don’t have to change anything in the class. Look through the class in the store.py file to understand a little of how it works. You don’t have to understand all of the code in the file, but you should at least read the comments to know what each method does and what it returns (if anything).

To get familiar with the Store objects and methods, you do need to edit main() and add some test code. See and follow the instructions in main() to add the test code. Do not continue with the lab until you have written the test code in main() of store.py!

For reference, here are the Store class methods. You will use them in the game.

method description

__init__(self,items)

constructor for Store objects, given list of Item objects

__str__(self)

should return string representation of object

getNumItems(self)

getter for how many unique items are in the store

getItemCost(self,number)

getter for how much an item costs (item specified by number)

buyItem(self,number)

given item number, "sell" item (return item object)

addItem(self,item)

add given item to store

4. the Yard class

We’ve already written this class for you, too! Like the last class, you also have to write some test code for this one.

Look through the yard.py file to familiarize yourself with the available methods and what they each do. Additionally, read the comment at the top of yard.py to know how Yard objects work in this game. Specifically, you only have so much room in your yard for items, and cats can’t come to your yard unless there is a free item (one not already taken by another cat).

See and follow the instructions in main() to add the test code. Do not continue with the lab until you have written the test code in main() of yard.py!

For reference, here are the Yard class methods. You will use some of them in the game.

method description

__init__(self,nslots)

constructor for Yard objects, given number of slots

__str__(self)

should return string representation of object

addCat(self,cat)

add given cat to the yard, if there’s an available item

addItem(self,item)

add item to yard, if there’s space

addSlot(self)

adds a slot to the yard (expands yard)

empty(self)

return True if yard is empty (no items)

full(self)

return True if no empty slots in yard

getCats(self)

return list of all cats currently in the yard

itemAvailable(self)

return True if an item is available for a cat to play with/eat

numCats(self)

return number of cats currently in the yard

removeCat(self,cat)

removes a specific cat from the yard, give the gift of fishes

removeItem(self,i)

remove a specific item (i), and possibly a cat, from the yard

updateFood(self)

check if food has been eaten, remove if yes (and cat), return fishes

5. write the game functions

In nekoatsume.py we have already written the main() function which includes loading various objects (cats, items, store, yard) and the game loop. Your job is to complete the program by writing the four functions called in the game loop.

You can see full examples of the game here:

Your game does not have to look exactly like our examples, but should be clean and easy to follow.

Here are the requirements for the functions you need to write:

5.1. see yard

Just show all items and cats currently in the yard. Hint: this one is easy…​don’t overthink it! :)

5.2. shop

Show the items in the store and ask the user which item they want to buy. If the user enters a valid item number, check to see if they have enough money (fishes) to buy the item. If they do, buy the item and add it to the yard. If not, let the user know why they can’t buy that item. Either way, this function should return how many fishes the user now has.

In the example output above, if the user enters 0, they don’t want to buy anything at this time.

Here’s an example, and see the outputs above for others.

You've got 199 fishes...
 1. see yard
 2. shop
 3. cat album
 4. quit
Your choice? 2

-------------------- Welcome to the cat store! --------------------

Store Inventory:
 1.        Rubber Ball ( toy) $ 60 fishes
 2.             Pillow ( toy) $120 fishes
 3.          Fish Bowl ( toy) $ 80 fishes
 4.               Yarn ( toy) $120 fishes
 5.        Frisky Bitz (food) $ 30 fishes
 6.  Two-tier Cat Tree ( toy) $200 fishes
 7.   Deluxe Tuna Bitz (food) $ 12 fishes
 8.            Sashimi (food) $ 52 fishes
 9.   Fluffy Brown Bed ( toy) $160 fishes
10.           Bean Bag ( toy) $120 fishes
11.      Colorful Sock ( toy) $ 20 fishes
12.         White Sock ( toy) $ 22 fishes
13.          Toy Mouse ( toy) $ 75 fishes
14.          Green Box ( toy) $  5 fishes
15.           Keyboard ( toy) $ 95 fishes
16.               Tape ( toy) $ 15 fishes
17.        Punch Cards ( toy) $ 64 fishes
18.       Cheese Bites (food) $ 15 fishes

Which item do you want to buy? [0 to cancel] 6
You don't have enough fishes for that! :(
========================================
You've got 199 fishes...
 1. see yard
 2. shop
 3. cat album
 4. quit
Your choice? 2

-------------------- Welcome to the cat store! --------------------

Store Inventory:
 1.        Rubber Ball ( toy) $ 60 fishes
 2.             Pillow ( toy) $120 fishes
 3.          Fish Bowl ( toy) $ 80 fishes
 4.               Yarn ( toy) $120 fishes
 5.        Frisky Bitz (food) $ 30 fishes
 6.  Two-tier Cat Tree ( toy) $200 fishes
 7.   Deluxe Tuna Bitz (food) $ 12 fishes
 8.            Sashimi (food) $ 52 fishes
 9.   Fluffy Brown Bed ( toy) $160 fishes
10.           Bean Bag ( toy) $120 fishes
11.      Colorful Sock ( toy) $ 20 fishes
12.         White Sock ( toy) $ 22 fishes
13.          Toy Mouse ( toy) $ 75 fishes
14.          Green Box ( toy) $  5 fishes
15.           Keyboard ( toy) $ 95 fishes
16.               Tape ( toy) $ 15 fishes
17.        Punch Cards ( toy) $ 64 fishes
18.       Cheese Bites (food) $ 15 fishes

Which item do you want to buy? [0 to cancel] 15
You just bought a Keyboard!

5.3. show cat album

Just show all of the cats that have visited the yard. Here’s an example, and see the outputs above for others.

You've got 199 fishes...
 1. see yard
 2. shop
 3. cat album
 4. quit
Your choice? 3

.................... Cat Album ....................
 1. Sunny (Turkish Calico), visits: 1
 2. Mittens (Black & White), visits: 3
 3. Snowball (Solid White), visits: 1
 4. Bolt (Brown Tabby), visits: 1
...................................................

5.4. update the yard

This function will "decide" when cats come and go, updating the yard accordingly. We are trying to simulate cats being attracted into a yard by food and toys, so we will include these elements in the program:

  1. if there are no items in the yard, no cats will come

  2. if there is food in the yard and a cat eats it, the food is gone and that cat will leave (hopefully to go do his/her business in another yard!)

  3. if there are items in the yard, cats don’t always come right away

  4. if there are cats in the yard playing with toys, they might get bored and leave the yard

Here is one way to structure your update function:

  • if the yard is empty, nothing happens (nothing to update)

  • if there are cats paired with food items, calling the updateFood() yard method should remove the food item and the cat that ate the food (no point sticking around if the food is gone!). Note: this method will return fishes if a cat leaves, so make sure to update the user’s fishes

  • if there are cats in the yard (see the yard methods for this), there should be a random chance one leaves the yard. If a cat does leave it will give the user fishes, so make sure to update the user’s fishes. Note: it doesn’t matter which cat leaves. Just pick one to leave from the list of cats currently in the yard

  • if there is an available item in the yard (ie, there’s an item, and no cats are already playing with it or eating it), there’s a random chance a cat comes into the yard. If a cat does come into the yard, add it to the cat album (if not already in the album) and update the cat’s visited instance variable

All of the above should be done with each update. You are welcome to break the update up into more functions if you want.

The updates require you to use Yard and Cat methods, as well as a function from the random library. If you are stuck on how to implement something, try looking through the Yard and Cat classes for a useful method (or two).

For the "random chances", you are free to pick numbers that make the game interesting. Also, if a cat is coming into the yard, don’t worry about picking a cat that is not already in the yard. We can have magical cat clones in this game — just pick a random cat from the original list of cats and add it to the yard.

Here’s an example of a yard before and after the update function is called. In this example, the two cats eating food both leave, and Tabitha decides to stay and keep playing with the Fish Bowl. Also, no new cats come into the yard this time.

--------------------YARDYARDYARDYARDYARDYARD--------------------
Here's your yard:
  1. Frisky Bitz, AdaLoveyarn
  2. Fish Bowl, Tabitha
  3. Frisky Bitz, Snowball
  4. Cheese Bites
  5.

--------------------YARDYARDYARDYARDYARDYARD--------------------

<<<<< AdaLoveyarn left the yard and gave you 12 fishes!
<<<<< Snowball left the yard and gave you 37 fishes!

========================================
You've got 82 fishes...
 1. see yard
 2. shop
 3. cat album
 4. quit
Your choice? 1

--------------------YARDYARDYARDYARDYARDYARD--------------------
Here's your yard:
  1. Fish Bowl, Tabitha
  2. Cheese Bites
  3.
  4.
  5.

6. enjoy the game! :)

Try running the game. Buy some items and see if any cats come to visit. Test all of the user options and make sure they all work. If you want, add your own cat to the cats.txt file.

7. Extra Challenges

These will not affect your grade or gain you extra points. They are included just as extra challenges, if you are interested (and have already finished the entire game).

  • allow the user to have more items than the yard can hold, and sometimes change the items in the yard (so the cats don’t get bored with the same 5 items)

  • allow the user to expand the yard for a certain number of fishes (ie, add a special store item that increases the number of slots in the yard)

  • add an extra cat instance variable that determines how likely a cat is to enter the yard. For example, for low values the cat would be rare, and come to the yard less than others, but give more fishes to the user if they do come to the yard

  • allow the user to buy more than one of an item at a time:

    Which item do you want to buy? [0 to cancel] 8
    How many would you like? 2
    You just bought 2 Sashimi!

8. Answer the Questionnaire

Please edit the Questions-11.txt file in your cs21/labs/11 directory and answer the questions in that file.

Once you’re done with that, run handin21 again.

Turning in your labs…​.

Remember to run handin21 to turn in your lab files! You may run handin21 as many times as you want. Each time it will turn in any new work. We recommend running handin21 after you complete each program or after you complete significant work on any one program.