3
\$\begingroup\$

I am trying to make a text-based RPG in Python and Pygame. I need a way to manage my inventory slots. Currently, I have no way to find out what is currently equipped. I can only overwrite it, even though I can display the current armor value and what it would be.

Here is the code for the only item I have "finished," a leather tunic:

leatherTunicItem = False
if leatherTunicItem == True and itemSlotArmorChest == False:
    itemSlotArmorChest = True
    chestArmorValue = 2
    print("The leather tunic is now equipped")
elif leatherTunicItem == True and itemSlotArmorChest == True:
    print("Your armor value is currently: ", totalArmorValue, "Equipping a Leather Tunic will make this value: ", totalArmorValue - chestArmorValue + 2)
    print("Would you still like to equip this item? (Yes or No)")
    lti = input("")
    if lti == "y" or lti == "Y" or lti == "yes" or lti == "Yes":
        itemSlotArmorChest = True
        chestArmorValue = 2
        print("Your armor value is now ", totalArmorValue)
    else:
        print("This Leather Tunic will be discarded.")
        leatherTunicItem = False

I have the whole Pastebin code here.

Note: the inventory is all that I am working on for now.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The code that you have posted makes no sense. If leatherTunicItem = False, then none of the rest of the code can possibly have any effect, because both the if and the elif blocks require it to be True. So what code is there to review? \$\endgroup\$ Nov 15 '18 at 1:20
5
\$\begingroup\$

Some considerations on your current code:

  1. Don't use == True. You either want to check the truth value of the object, in which case simply drop the == True, or you want to check for identity, in which case you should use is True(even though it's really rare to see is True/False. You usually check for is None).
  2. Instead of lti == "y" or lti == "Y" or ... you can simply convert lti to lowercase and check for y. Something like lti.lower()[:1] == "y". This will include also things like yabbadu. An other option is to use in: lti.lower() in {"y", "yes"} accepts y and yes in any case(so also yEs is accepted.
  3. You should follow the PEP8 when writing. It's the standard coding-style for python. Using it will allow all python programmers to read your code more easily. To follow this style you should use lower_case_with_underscore for functions/variables, FullCamelCase for classes.
  4. Regarding the full code from pastebin: it is not well organized. Things like equipping an armor should be managed by a function or by some class and they shouldn't depend on the armor kind. It's probably a good example where using classes make sense. You should have an Armor class that provides the basic implementation of an armor and the various subclasses TunicArmor etc. that provide different armor points etc. Note that inheritance is not the only way to do it.

In the end the code would look like:

leather_tunic_item = False
if leather_tunic_item and not item_slot_armor_chest:
    item_slot_armor_chest = True
    chest_armor_value = 2
    print("The leather tunic is now equipped")
elif leather_tunic_item:  #no need: and item_slot_armor_chest.
    print("Your armor value is currently: ", total_armor_value, "Equipping a Leather Tunic will make this value: ", total_armor_value - chest_armor_value + 2)
    print("Would you still like to equip this item? (Yes or No)")
    lti = input("")
    if lti.lower() in {"y", "yes"}:
        item_slot_armor_chest = True
        chest_armor_value = 2
        print("Your armor value is now ", total_armor_value)
    else:
        print("This Leather Tunic will be discarded.")
        leather_tunic_item = False

A sample implementation of what I meant in the last point might be this:

class ArmorPiece:
    def __init__(self, name, points):
        self.name = name
        self.points = points


class NullPiece:
    """An armor piece that is used to represent a missing armor piece."""
    def __init__(self):
        super(NullPiece, self).__init__("", 0)


class Armor:
    def __init__(self, head=None, chest=None, legs=None):
        self.head = head if head is not None else NullPiece()
        self.chest = chest if chest is not None else NullPiece()
        self.legs = legs if legs is not None else NullPiece()

    def defense_points(self):
        return self.head.points + self.chest.points + self.legs.points


class Tunic(ArmorPiece):
    def __init__(self):
        super(Tunic, self).__init__("tunic", 2)

After this, if you want to replace the chest piece you could do:

def change_chest(armor, new_chest):
    if isinstance(armor.chest, NullPiece):
        # The player is not wearing a chest armor piece
        armor.chest = new_chest
        print("The {.name} is now equipped.".format(new_chest))
    else:
        # The player is wearing something else.
        print("Your armor value is currently: ", armor.defense_points(), "Equipping a {.name} will make this value: ".format(new_chest), armor.defense_points() - armor.chest.points + new_chest.points)
        print("Would you still like to equip this item? (Yes or No)")
        lti = input("")
        if lti.lower() in {"y", "yes"}:
            armor.chest = new_chest
            print("Your armor value is now: ", armor.defense_points())
        else:
            print("This {.name} will be discarded".format(new_chest))

You could make this function a method of Armor if you want, even though I like to separate the logic of the program from the input/output code. Your code will be more flexible.

Note that in the formatting strings the {.name} parts are replaced with the attribute name of the object passed to format. Doing "{.name}".format(new_chest) is the same as "{}".format(new_chest.name).

You should probably read a bit of the documentation about string formatting.


If you are not comfortable with classes you can simplify the code using some dictionaries. something like:

armor = {
    "head": {"name": "", "points": 0},
    "chest": {"name": "", "points": 0},
    "legs": {"name": "", "points": 0},
}

def defense_points(armor):
    return sum(value["points"] for key, value in armor.items())

To change the head armor simply do:

armor["head"] = {"name": "tunic", "points": 2}

The code to handle this would be pretty similar to the above, but replacing attribute access with item access(e.g. new_chest.name -> new_chest["name"]).

\$\endgroup\$
7
  • \$\begingroup\$ Thanks @Bakuriu, that helps a lot! what i was looking for, though, was how to detect what was currently equipped, print that, so "You will replace "THIS" with a Leather Tunic, your armor walue will be x". If you add that, i will accept this answer. \$\endgroup\$
    – Pip
    Jun 26 '13 at 15:19
  • \$\begingroup\$ @PythonInProgress Well, by what I see you don't keep track of the name of the items. In your code there's only a leather_tunic_item which is either True or False. You probably want to keep track of the names of the items too. I'll update my answer(soon) with an example on how you could do this using classes. \$\endgroup\$
    – Bakuriu
    Jun 26 '13 at 15:24
  • \$\begingroup\$ Is is ok to use this code? If you say yes I will note you in the credits. :D \$\endgroup\$
    – Pip
    Jun 26 '13 at 17:54
  • \$\begingroup\$ @PythonInProgress Sure, but before using it be sure to understand it, otherwise it may hinder you later, when you have to modify it to implement new things in your game. \$\endgroup\$
    – Bakuriu
    Jun 26 '13 at 18:07
  • \$\begingroup\$ Want to join me in chat? \$\endgroup\$
    – Pip
    Jun 26 '13 at 18:11

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