5
\$\begingroup\$

I'm learning Python as my first language and this is my first OOP project. What improvements can I make on my code for style, best practices, better logic, and to make it more efficient?

from __future__ import print_function
import random


class Chest(object):

    possible_contents = ['Key', 'Horn', 'Brandy']

    def __init__(self):
        self.chest_inventory = Inventory()

    def __str__(self):
        return "{0}".format(self.chest_inventory)

    def __del__(self):
        pass

    def add_contents(self):
        random_item = [random.choice(Chest.possible_contents)]
        self.chest_inventory.add_inven_contents(random_item)


class Player(object):

    def __init__(self):
        self.inventory = Inventory()

    def take(self, item):
        item_list = item.inventory_list
        self.inventory.add_inven_contents(item_list)
        print("You aquire {0}".format(item_list))
        item.empty()

class Inventory(object):

    def __init__(self):
        self.inventory_list = []

    def __str__(self):
        return "{0}".format(self.inventory_list)

    def __iter__(self):
        return iter(self.inventory_list)

    def __del__(self):
        pass

    def add_inven_contents(self, item):
        for each in item:
            self.inventory_list.extend([each])

    def empty(self):
        self.inventory_list = []


class Get_Choice(object):

    def __init__(self, room_info):
        self.info = room_info

    def receive_input(self):
        options = self.info.options
        choice = None
        bad_input_message = 0

        while choice not in xrange(1, (len(self.info.options) + 1)):
            if bad_input_message == 1:
                print("Incorrect input, try again.")
            for each in options:
                list_index = options.index(each) + 1
                print("{0}. {1}".format(list_index, each))
            choice = raw_input("Enter a number> ")
            bad_input_message = 1
            if choice.isdigit():
                choice = int(choice)
            else:
                pass

        return choice

class Room(object):

    def __init__(self):
        self.optionchoice = Get_Choice(self)
        self.firstrun = 0

    def print_scene(self):
        if self.firstrun == 0:
            print(self.__str__())


class Entrance(Room):

  def __init__(self):
        super(Entrance, self).__init__()      
        self.entrance_chest = Chest()
        self.options = [
            "Climb the ladder",  
            "Go through door",
            "Check the chest",
            ]

  def __str__(self):
    self.firstrun = 1
    return (
        "After a day of travel, you find and abandoned outpost. "
        "You decide to spend the night there. "
        "You enter the output. "
        "You see another door, a ladder, and a chest."
        )

  def run(self):
    self.entrance_chest.add_contents()
    chest_inven = self.entrance_chest.chest_inventory
    while True:
        choosenoption = self.optionchoice.receive_input()
        if choosenoption == 1:
            chest_inven.empty()
            return 'ladder'
        elif choosenoption == 2:
            chest_inven.empty()
            print("You mysteriously find yourself back in the same room.")
            return 'entrance'
        elif choosenoption == 3:
            if chest_inven.inventory_list != []:
                player1.take(chest_inven)
            else:
                print("It is empty")


class LadderRoom(Room):

    def __init__(self):
        super(LadderRoom, self).__init__()
        self.options = [
            "Try to open door",
            "Go back down ladder",
            ]

    def __str__(self):
        self.firstrun = 1
        return (
            "You enter a small room "
            "and there is a large door with a keyhole"
            )

    def run(self):
        end_text = (
            "You open the door with the key you found. "
            "Inside is a pile of gold. You win!"
            )
        while True:
            choosenoption = self.optionchoice.receive_input()
            if choosenoption == 1:
                if 'Key' in player1.inventory:
                    print(end_text)
                    return 'end'
                else:
                    print("The door is locked, you can't get in.")
            elif choosenoption == 2:
                print("As expected, you find yourself back at the entrance.")
                return 'entrance'


class Engine(object):

    def __init__(self):
        self.status = 'entrance'
        self.room0 = Entrance()
        self.room1 = LadderRoom()

    def play(self):
        while self.status != 'end':
            if self.status == 'entrance':
                self.room0.print_scene()
                self.status = self.room0.run()
            elif self.status == 'ladder':
                self.room1.print_scene()
                self.status = self.room1.run()
        raise SystemExit

player1 = Player()
engine1 = Engine()
engine1.play()
\$\endgroup\$
1
\$\begingroup\$

I would keep the class for the Inventory simpler:

class Inventory(list):

    def __del__(self):
        pass # this avoids an Inventory gets deleted, is it really necessary?

    def add_inven_contents(self, items): # as you're adding multiple items, name it items 
        self.extend(items) # extend takes an iterable

If you don't mind calling inventory.extend instead of inventory.add_inven_contents you can drop this method

This will allow to call some additional methods on Inventory, which isn't a problem in my opinion

\$\endgroup\$
  • \$\begingroup\$ Nice! That simplifies things a lot! Thank you! \$\endgroup\$ – tre Feb 3 '17 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.