def execute(self): """ Equips player with item in inventory. """ #Create variables inventory = self._player.getInventory() equipped = self._player.getEquipped() equippable = ItemSet() #Create list of equippable items for item in inventory: if (isinstance(item, Weapon) or isinstance(item, Armor) or isinstance(item, Charm)) and item not in equipped: equippable.addItem(item) #If no equippable items if equippable.count() == 0: print "No equippable items in inventory." return #User prompt print "%s may equip:" % self._player.getName() for item in equippable: print "\t%s" % item.getName() print "" itemToEquip = raw_input("Which item do you want to equip? ") #Attempt to equip item item = inventory.getItemByName(itemToEquip) if item: statement = self._player.equip(item) print statement else: print "Item not in inventory."
def execute(self): """ Uses potion in inventory to heal player. """ #Check that potions in inventory inventory = self._player.getInventory() potions = ItemSet() for item in inventory: if isinstance(item, Potion): potions.addItem(item) if potions.count() == 0: print "%s has no potions." % self._player.getName() return #User prompt print "%s currently has:" % self._player.getName() for potion in potions: print "\t%s with %s healing power." % (potion.getName(), potion.getHealing()) print "" choice = None while True: choice = raw_input("Which potion would you like to use? ") if potions.containsItemWithName(choice): break else: print "%s does not have that potion." % self._player.getName() print "" #Healing mechanics potionChoice = potions.getItemByName(choice) healing = potionChoice.getHealing() preHealedHealth = self._player.getHp() self._player.heal(healing) postHealedHealth = self._player.getHp() healed = postHealedHealth - preHealedHealth inventory.removeItem(potionChoice) print "%s was healed by %s! %s's health is now %s." \ % (self._player.getName(), healed, self._player.getName(), self._player.getHp())
def getItems(region, numItems, quality): """ Generates random items for shop. @param region: The region the shop is in. @param numItems: The number of items to generate @param quality: Integer from 0-20 that determines quality of items generated. @return: A list of randomly generated item objects. """ items = ItemSet() for item in range(numItems): #Generate random number used in determining item type randType = random.random() #Randomize quality quality = qualityRandomizer(quality) #Generate items and append to items list if randType < constants.ShopFactoryConstants.WEAPON_UPPER_LIMIT: item = genWeapon(quality, region) items.addItem(item) elif randType < constants.ShopFactoryConstants.ARMOR_UPPER_LIMIT: item = genArmor(quality, region) items.addItem(item) elif randType < constants.ShopFactoryConstants.POTION_UPPER_LIMIT: item = genPotion(quality, region) items.addItem(item) else: #Only shops advanced in the game generate uniques if (constants.ShopFactoryConstants.UNIQUE_QUALITY_REQ <= quality and lowLevelFindableUniques): item = random.choice(lowLevelFindableUniques) items.addItem(item) #Low-level shops generate additional potions else: item = genPotion(quality, region) items.addItem(item) return items
def getItems(region, numItems, quality): """ Generates random items for shop. @param region: The region the shop is in. @param numItems: The number of items to generate @param quality: Integer from 0-20 that determines quality of items generated. @return: A list of randomly generated item objects. """ items = ItemSet() for item in range(numItems): #Generate random number used in determining item type randType = random.random() #Randomize quality quality = qualityRandomizer(quality) #Generate items and append to items list if randType < constants.ShopFactoryConstants.WEAPON_UPPER_LIMIT: item = genWeapon(quality, region) items.addItem(item) elif randType < constants.ShopFactoryConstants.ARMOR_UPPER_LIMIT: item = genArmor(quality, region) items.addItem(item) else: item = genPotion(quality, region) items.addItem(item) return items
class ItemSetTest(unittest.TestCase): """ Tests ItemSet class. """ INITIAL_COUNT = 3 INITIAL_WEIGHT = 4 def setUp(self): from items.item import Item from items.item_set import ItemSet sword = Item("sword", "made by elves", 2) helmet = Item("helmet", "made by men", 1) potion = Item("potion", "restores health", 1) self._itemList = [sword, helmet, potion] self._items = ItemSet([sword, helmet, potion]) def tearDown(self): self._itemList = self._items = None def testInitItemSet(self): errorMsg = "ItemSet object has more objects than it was given " \ "during initialization." self.assertEqual(len(self._items._items), ItemSetTest.INITIAL_COUNT, errorMsg) errorMsg = "ItemSet object does not include all objects given " \ "during initialization." for item in self._itemList: self.assertTrue(item in self._items._items, errorMsg) def testCountItems(self): expectedCount = ItemSetTest.INITIAL_COUNT actualCount = self._items.count() errorMsg = "Actual count and expected count different for ItemSet object." self.assertEqual(expectedCount, actualCount, errorMsg) def testAddRemoveContainsItems(self): from items.item import Item antidote = Item("antidote", "cures poison", 1) #Verify item not included in collection errorMsg = "ItemSet.containsItem() claimed to contain item not present." self.assertFalse(self._items.containsItem(antidote), errorMsg) #Add item self._items.addItem(antidote) errorMsg = "ItemSet.containsItem() failed to identify existing item." self.assertTrue(self._items.containsItem(antidote), errorMsg) #Remove item self._items.removeItem(antidote) errorMsg = "ItemSet.containsItem() claimed to contain item not present." self.assertFalse(self._items.containsItem(antidote), errorMsg) def testItemsWeight(self): from items.item import Item errorMsg = "Initial weight of ItemSet object incorrect." expectedWeight = ItemSetTest.INITIAL_WEIGHT actualWeight = self._items.weight() self.assertEqual(expectedWeight, actualWeight, errorMsg) heavyRock = Item("heavy rock", "weighs a ton", 2000) #Add item self._items.addItem(heavyRock) errorMsg = "ItemSet.weight() reported incorrect weight." expectedWeight += 2000 actualWeight = self._items.weight() self.assertEqual(expectedWeight, actualWeight, errorMsg) #Remove item self._items.removeItem(heavyRock) expectedWeight -= 2000 actualWeight = self._items.weight() self.assertEqual(expectedWeight, actualWeight, errorMsg) def testItemSetIter(self): #Verify iterator returns by ItemSet object visits the exact #collection of objects added to ItemSet #(Implicitly) use iterator in for loop for item in self._items: #Verify item returned is recognized errorMsg = "ItemSet iterator returned unrecognized object." self.assertTrue(item in self._itemList, errorMsg) #Remove item from original list of items self._itemList.remove(item) #Assert all items are accounted for errorMsg = "ItemSet object contained Item not added during initialization." self.assertEqual(len(self._itemList), 0, errorMsg)
class Space(object): """ A given location on the map. Connects with other spaces to form larger geographic areas. """ def __init__(self, name, description, region, battleProbability = 0, battleBonusDifficulty = 0, items = None, city = None, uniquePlace = None): """ Initialize a Space object. @param name: Name of space. @param description: Description of space. @param battleProbability: Probability between [0, 1] that a random battle will occur between successive game command executions. @param battleBonusDifficulty: Probability between [0, 1] that is used to determine battle bonus difficulty. This stat results in a percentage increase over default monster stats and number for any given space. For instance, if bonus difficulty is set to .5, space will spawn 50% more monsters with 150% base stats. @keyword items: (Optional) Items found in the space. May be a reference to a single item or an ItemSet. @keyword city: (Optional) City objects in space. May be a reference to an individual object or a list. @keyword uniquePlace: (Optional) Reference to unique places in space. May be a reference to an individual object or a list. """ self._exits = {Direction.NORTH : None, Direction.SOUTH : None, Direction.EAST : None, Direction.WEST : None} self._name = name self._description = description self._region = region self._battleProbability = battleProbability self._battleBonusDifficulty = battleBonusDifficulty self._items = ItemSet() self._city = city self._uniquePlace = uniquePlace def getName(self): """ Returns the name of the space. @return: Name of the space. """ return self._name def getDescription(self): """ Returns description of space. @return: Description of space. """ return self._description def getRegion(self): """ Returns the region of the space. @return: The region of space. """ return self._region def getItems(self): """ Returns a string of times. @return: Items in Space (as ItemSet). """ return self._items def addItem(self, item): """ Adds an item to the space. @param item: Item to add. """ #Special prompt for theOneRing if item == theOneRing and self._name != "Orodruin": print "\nYou see some strange men walk by." return if isinstance(item, Item): self._items.addItem(item) elif isinstance(item, list): self._items.addItems(item) else: errorMsg = "space.AddItem() was given invalid item type." raise AssertionError(errorMsg) def removeItem(self, item): """ Removes an item from the space. @param item: Item to remove. """ self._items.removeItem(item) def containsItem(self, item): """ Determines if space contains an item. @param item: Item object to search for. @return: True if item is contained in Space, False otherwise. """ return self._items.containsItem(item) def containsItemString(self, string): """ Determines if space contains an item. @param string: The name-string of the target item. @return: True if item is contained in space, False otherwise. """ return self._items.containsItemWithName(string) def getCity(self): """ Returns city object/objects. @return: Reference to cit(ies). May refer to a single city or list of cities. """ return self._city def getUniquePlace(self): """ Returns uniquePlace object(s). @return: Reference to unique place(s). May be reference to a single unique place or a list of unique places. """ return self._uniquePlace def getBattleProbability(self): """ Returns probability of a random battle. @return: The probability that a random battle occurs. """ return self._battleProbability def getBattleBonusDifficulty(self): """ Returns bonus difficulty attribute of space. @return: The difficulty parameter of space. """ return self._battleBonusDifficulty def createExit(self, direction, space, outgoingOnly = False): """ Create an exit to another space. By default, the method creates the appropriate exit in the second space. (This can be suppressed, however, using I{outgoingOnly}). Spaces can have multiple spaces per direction. @param direction: Direction of exit. @param space: Adjacent space. @keyword outgoingOnly: By default, this method creates the appropriate exit in the second space. Set I{outgoingOnly} to False to suppress this behaviour. """ #Make sure a valid direction has been specified if not self._isExit(direction): errorMsg = "Direction not valid: %s" % direction raise AssertionError(errorMsg) #Set exit to other space - if a space already exists if self._exits[direction]: currentSpace = self._exits[direction] #If multiple spaces already exist in that direction if isinstance(self._exits[direction], list): currentSpace.append(space) #If a single space exists in that direction else: self._exits[direction] = [currentSpace, space] #If no space already exists else: self._exits[direction] = space #Create exit from other space to this space if not outgoingOnly: oppositeDirection = self._oppositeDirection(direction) #outgoingOnly = True as to not create an infinite loop space.createExit(oppositeDirection, self, outgoingOnly = True) def clearExit(self, direction, outgoingOnly, space = None): """ Removes an exit to another space. By default, the method removes the appropriate exit from the second space. (This can be suppressed, however, using I{outgoingOnly}). @param direction: Direction of exit. @keyword outgoingOnly: By default, this method removes the appropriate exit from the second space. Set I{outgoingOnly} to False to suppress this behavior. """ #Make sure a valid direction has been specified if not self._isExit(direction): errorMsg = "Direction not valid: %s" % direction raise AssertionError(errorMsg) #If exit has not been set, there is nothing to do if self._exits[direction] == None: return #Create a temporary copy of adjacent space adjSpace = self._exits[direction] if isinstance(self._exits[direction], list): self._exits[direction].remove(space) else: self._exits[direction] = None if not outgoingOnly: oppositeDirection = self._oppositeDirection(direction) adjSpace.clearExit(oppositeDirection, True, space = self) def getExit(self, direction): """ Returns a reference to an adjacent space. Returns None if no space exists in given direction. @param direction: Direction of adjacent space. Must be one of the directions defined in constants.Direction. @return: Reference to space in given direction. (Returns None if no exit is defined for given direction). """ space = self._exits[direction] return space def getExits(self): """ Returns dictionary of direction-space pairs. @return: Dictionary of direction-space pairs. """ return self._exits def _isExit(self, exit): """ Makes sure that a string represents a valid exit. @param direction: Name of exit. @return: True if valid exit, False otherwise. """ availableExits = self._exits.keys() if exit not in availableExits: return False return True def _oppositeDirection(self, direction): """ Returns the opposite direction. (e.g. North is opposite of South) @param direction: A direction (from constants.Direction) @return: Opposite direction (from constants.Direction) """ if direction == Direction.NORTH: return Direction.SOUTH elif direction == Direction.SOUTH: return Direction.NORTH elif direction == Direction.EAST: return Direction.WEST elif direction == Direction.WEST: return Direction.EAST else: raise AssertionError("Not a valid direction: %s" % direction)
class Player(object): """ Represents the (human) player. """ def __init__(self, name, location): """ Initializes the player. @param name: The name of the player (e.g. "Frodo"). @param location: The location of player. """ self._name = name self._location = location self._money = constants.STARTING_MONEY #Initialize player inventory and equipment self._inventory = ItemSet() self._equipped = ItemSet() #Initialize player stats self._experience = constants.STARTING_EXPERIENCE self._level = constants.STARTING_LEVEL self._hp = self._level * constants.HP_STAT self._maxHp = self._level * constants.HP_STAT self._attack = self._level * constants.ATTACK_STAT #Initialize items bonuses self._weaponAttack = 0 self._totalAttack = self._attack + self._weaponAttack self._armorDefense = 0 def getName(self): """ Returns player name. @return: The name of the player. """ return self._name def attack(self, target): """ Allows player to attack target. @param target: The target player is to attack. """ self._totalAttack = self._attack + self._weaponAttack target.takeAttack(self._totalAttack) def getAttack(self): """ Gets a player's total attack power (including items). @return: Sum of player attack and weapon attack. """ return self._totalAtack def takeAttack(self, attack): """ Allows player to receive an attack. @param attack: The attack player is to receive. """ self._hp = max(self._hp - max(attack - self._armorDefense, 0), 0) def getExperience(self): """ Return's player experience. @return: Returns player experience. """ return self._experience def increaseExperience(self, newExperience): """ Allows player to receive additional experience. @param newExperience: The experience player is to receive. """ self._experience += newExperience def getLevel(self): """ Return's player level. @return: Player level. """ return self._level def _updateLevel(self): """ Levels up player and updates player stats. """ #Checks to see if player has leveled up if self._level == constants.MAX_LEVEL: return if self._level != floor(self._experience / 20) + 1: self._level = floor(self._experience / 20) + 1 #Player has leveled up. Updates player level and stats. print "%s leveled up! %s is now level %s" \ % (self._name, self._name, self._level) self._maxHp = self._level * constants.HP_STAT self._attack = self._level * constants.ATTACK_STAT self._totalAttack = self._attack + self._weaponAttack def getHp(self): """ Returns player hp. @return: Player hp. """ return self._hp def getMaxHp(self): """ Returns player maximum hp. @return: Player maximum hp. """ return self._maxHp def heal(self, amount): """ Allows player to heal up to maximum starting hp. @param amount: The amount of hp to be healed. """ #If amount that player may be healed is less than amount possible if self._maxHp - self._hp < amount: amountHealed = maxHp - self._hp #If amount that player may be healed is equal to or more than amount possible else: amountHealed = amount self._hp += amountHealed print "%s got healed by %s! %s's health is now at %s" % ( self._name, amountHealed, self._name, self._hp) def equip(self, item): """ Allows a character to equip an item in inventory. Note: An item *must* be in the player's inventory before it can be equipped. The item must also be a piece of Armor or a Weapon. @param item: The item to be equipped. """ #TODO: Need to revisit the logic of this method. # The method should take advantage of the unequip() method # now that it exists. # # After that change, review the overall logic # to make sure it makes sense. #Check to see if item may be equipped if not (item in self._inventory) \ or not (isinstance(item, Armor) or isinstance(item, Weapon)) \ or item in self._equipped: print "" print "Cannot equip %s." % item.getName() return #Unequip currently equipped armor/weapon if necessary if isinstance(item, Armor): self._armor = item self._armorDefense = self._armor.getDefense() elif isinstance(item, Weapon): self._weapon = item self._weaponAttack = self._weapon.getAttack() for currentItem in self._equipped: if isinstance(item, Weapon) and isinstance(currentItem, Weapon): self.unequip(currentItem) elif isinstance(item, Armor) and isinstance(currentItem, Armor): self.unequip(currentItem) #Update player to reflect equipment if isinstance(item, Armor): self._armor = item self._armorDefense = self._armor.getDefense() elif isinstance(item, Weapon): self._weapon = item self._weaponAttack = self._weapon.getAttack() self._equipped.addItem(item) print "%s equipped %s." % (self._name, item.getName()) def unequip(self, item): """ Allows a character to unequip a currently equipped item. @param item: The item to be unequipped. """ print "" if item in self._equipped: self._equipped.removeItem(item) #Update player to reflect equipment if isinstance(item, Weapon): self._weapon = None self._weaponAttack = 0 if isinstance(item, Armor): self._armor = None self._armorDefense = 0 print "%s unequipped %s." % (self._name, item.getName()) else: print "Cannot unequip %s." % item.getName() def getWeapon(self): """ Returns play weapon. @return: Player's current weapon. """ return self._weapon def getArmor(self): """ Returns player armor. @return: Player's current armor. """ return self._armor def getEquipped(self): """ Returns the player's currently equipped equipment. @return: Player's current gear. """ return self._equipped def addToInventory(self, item): """ Adds an item to inventory. @param item: The item to be added to inventory. """ if (isinstance(item, Item) and (item not in self._inventory)): print "Added %s to inventory." % item.getName() self._inventory.addItem(item) else: print "Cannot add %s to inventory." % item def removeFromInventory(self, item): """ Removes an item from inventory. If item is currently equipped, unequips item. @param item: The item to be removed. """ if item in self._inventory: if item in self._equipped: self.unequip(item) self._inventory.removeItem(item) def getInventory(self): """ Returns the player's inventory. @return: Player's inventory. """ return self._inventory def getMoney(self): """ Returns player's money. @return: Player's money. """ return self._money def increaseMoney(self, amount): """ Increases player money. """ if amount <= 0: errorMsg = "Method increaseMoney() was given a negative value" raise AssertionError(errorMsg) self._money += amount def decreaseMoney(self, amount): """ Decreases player money. """ if amount <= 0: errorMsg = "Method decreaseMoney() was given a negative value" raise AssertionError(errorMsg) self._money -= amount def canMoveNorth(self): """ Determines if player can move north. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.NORTH) if exit: return True return False def canMoveSouth(self): """ Determines if player can move south. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.SOUTH) if exit: return True return False def canMoveEast(self): """ Determines if player can move east. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.EAST) if exit: return True return False def canMoveWest(self): """ Determines if player can move west. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.WEST) if exit: return True return False def moveNorth(self): """ Moves player north one space. """ northSpace = self._location.getExit(constants.Direction.NORTH) #If north space does not exist, do nothing if not northSpace: return #...otherwise, move to new space self._location = northSpace def moveSouth(self): """ Moves player south one space. """ southSpace = self._location.getExit(constants.Direction.SOUTH) #If south space does not exist, do nothing if not southSpace: return #...otherwise, move to new space self._location = southSpace def moveEast(self): """ Moves player east one space. """ eastSpace = self._location.getExit(constants.Direction.EAST) #If east space does not exist, do nothing if not eastSpace: return #...otherwise, move to new space self._location = eastSpace def moveWest(self): """ Moves player west one space. """ westSpace = self._location.getExit(constants.Direction.WEST) #If west space does not exist, do nothing if not westSpace: return #...otherwise, move to new space self._location = westSpace def getLocation(self): """ Returns player's current location (i.e. space). @return: Player's current location. """ return self._location
class Space(object): """ A given location on the map. Connects with other spaces to form larger geographic areas. """ def __init__(self, name, description, items = None, city = None, uniquePlaces = None): """ Initialize a Space object. @param name: Name of space. @param description: Description of space. @keyword items: (Optional) Items found in the space. May be a reference to a single item or an ItemSet. @keyword city: (Optional) Reference to unique place(s). May be a reference to an object or a list. @keyword uniquePlaces: (Optional) Reerence to city/cities. May be a reference to an object or a list. """ self._exits = { Direction.NORTH : None, Direction.SOUTH : None, Direction.EAST : None, Direction.WEST : None } self._name = name self._description = description #TODO: Need to add items passed into method; items is currently ignored. # Will need to check if items refers to single object or to an ItemSet. # If it points to an ItemSet, you can just set self._items to that ItemSet. # (self._items = items) self._items = ItemSet() self._city = city self._uniquePlaces = uniquePlaces def getName(self): """ Returns the name of the room. @return: Name of the room. """ return self._name def getDescription(self): """ Returns description of the room. @return: Description of room. """ return self._description def getItems(self): """ Returns a string of times. @return: Items in Space (as ItemSet). """ return self._items def addItem(self, item): """ Adds an item to the room. @param item: Item to add. """ self._items.addItem(item) def removeItem(self, item): """ Removes an item from the room. @param item: Item to remove. """ self._items.removeItem(item) def containsItem(self, item): """ Determines if room contains an item. @param item: Item object to search for. @return: True if item is contained in Space, False otherwise. """ return self._items.containsItem(item) def containsItemString(self, string): """ Determines if room contains an item. @param item: The string associated with the name of the item that we are looking for. @return: True if item is contained in Space, False otherwise. """ #TODO: Use ItemSet's containsItemWithName() instead here. for item in self._items: if item.getName() == string: return True return False def getCity(self): """ Returns city object. @return: Reference to cit(ies). May be reference to single city or list of cities. """ return self._city def getUniquePlace(self): """ Returns uniquePlace object(s). @return: Reference to unique place(s). May be reference to single unique place or list of unique places. """ return self._uniquePlaces def createExit(self, direction, space, outgoingOnly = False): """ Create an exit to another space. By default, the method creates the appropriate exit in the second space. (This can be suppressed, however, using I{outgoingOnly}). @param direction: Direction of exit. @param space: Adjacent space. @keyword outgoingOnly: By default, this method creates the appropriate exit in the second space. Set I{outgoingOnly} to False to supress this behavior. """ #Make sure a valid direction has been specified if not self._isExit(direction): errorMsg = "Direction not valid: %s" % direction raise AssertionError(errorMsg) #Set exit to other space self._exits[direction] = space #Create exit from other space to this space if not outgoingOnly: oppositeDirection = self._oppositeDirection(direction) space._exits[oppositeDirection] = self def clearExit(self, direction, outgoingOnly): """ Removes an exit to another space. By default, the method removes the appropriate exit from the second space. (This can be suppressed, however, using I{outgoingOnly}). @param direction: Direction of exit. @keyword outgoingOnly: By default, this method removes the appropriate exit from the second space. Set I{outgoingOnly} to False to suppress this behavior. """ #Make sure a valid direction has been specified if not self._isExit(direction): errorMsg = "Direction not valid: %s" % direction raise AssertionError(errorMsg) #If exit has not been set, there is nothing to do if self._exits[direction] == None: return #Create a temporary copy of adjacent space adjSpace = self._exits[direction] #Clear exit from this space self._exits[direction] = None #Clear exit from other space to this space if not outgoingOnly: oppositeDirection = self._oppositeDirection(direction) adjSpace._exits[oppositeDirection] = None def getExit(self, direction): """ Returns a reference to an adjacent space. Returns None if no space exists in given direction. @param direction: Direction of adjacent space. Must be one of the directions defined in constants.Direction. @return: Reference to space in given direction. (Returns None if no exit is defined for given direction). """ space = self._exits[direction] return space def _isExit(self, exit): """ Makes sure that a string represents a valid exit. @param direction: Name of exit. @return: True if valid exit, False otherwise. """ availableExits = self._exits.keys() if exit not in availableExits: return False return True def _oppositeDirection(self, direction): """ Returns the opposite direction. (e.g. North is opposite of South) @param direction: A direction (from constants.Direction) @return: Opposite direction (from constants.Direction) """ if direction == Direction.NORTH: return Direction.SOUTH elif direction == Direction.SOUTH: return Direction.NORTH elif direction == Direction.EAST: return Direction.WEST elif direciton == Direction.WEST: return Direction.EAST else: raise AssertionError("Not a valid direction: %s" % direction)
class Player(object): """ Represents the (human) player. """ def __init__(self, name, location): """ Initializes the player. @param name: The name of the player (e.g. "Frodo"). @param location: The location of player. """ self._name = name self._location = location self._money = constants.STARTING_MONEY #Initialize player inventory and equipment self._inventory = ItemSet() self._equipped = ItemSet() #Initialize player stats self._experience = constants.STARTING_EXPERIENCE self._level = constants.STARTING_LEVEL self._hp = self._level * constants.HP_STAT self._maxHp = self._level * constants.HP_STAT self._attack = self._level * constants.ATTACK_STAT #Initialize items bonuses self._weaponAttack = 0 self._totalAttack = self._attack + self._weaponAttack self._armorDefense = 0 def getName(self): """ Returns player name. @return: The name of the player. """ return self._name def attack(self, target): """ Allows player to attack target. @param target: The target player is to attack. """ self._totalAttack = self._attack + self._weaponAttack target.takeAttack(self._totalAttack) def getAttack(self): """ Gets a player's total attack power (including items). @return: Sum of player attack and weapon attack. """ return self._totalAtack def takeAttack(self, attack): """ Allows player to receive an attack. @param attack: The attack player is to receive. """ self._hp = max(self._hp - max(attack - self._armorDefense, 0), 0) def getExperience(self): """ Return's player experience. @return: Returns player experience. """ return self._experience def increaseExperience(self, newExperience): """ Allows player to receive additional experience. @param newExperience: The experience player is to receive. """ self._experience += newExperience def getLevel(self): """ Return's player level. @return: Player level. """ return self._level def _updateLevel(self): """ Levels up player and updates player stats. """ #Checks to see if player has leveled up if self._level == constants.MAX_LEVEL: return if self._level != floor(self._experience/20) + 1: self._level = floor(self._experience/20) + 1 #Player has leveled up. Updates player level and stats. print "%s leveled up! %s is now level %s" \ % (self._name, self._name, self._level) self._maxHp = self._level * constants.HP_STAT self._attack = self._level * constants.ATTACK_STAT self._totalAttack = self._attack + self._weaponAttack def getHp(self): """ Returns player hp. @return: Player hp. """ return self._hp def getMaxHp(self): """ Returns player maximum hp. @return: Player maximum hp. """ return self._maxHp def heal(self, amount): """ Allows player to heal up to maximum starting hp. @param amount: The amount of hp to be healed. """ #If amount that player may be healed is less than amount possible if self._maxHp - self._hp < amount: amountHealed = self._maxHp - self._hp #If amount that player may be healed is equal to or more than amount possible else: amountHealed = amount self._hp += amountHealed print "%s got healed by %s! %s's health is now at %s" % (self._name, amountHealed, self._name, self._hp) def equip(self, item): """ Allows a character to equip an item in inventory. Note: An item *must* be in the player's inventory before it can be equipped. The item must also be a piece of Armor or a Weapon. @param item: The item to be equipped. """ #TODO: Need to revisit the logic of this method. # The method should take advantage of the unequip() method # now that it exists. # # After that change, review the overall logic # to make sure it makes sense. #Check to see if item may be equipped if not (item in self._inventory) \ or not (isinstance(item, Armor) or isinstance(item, Weapon)) \ or item in self._equipped: print "" print "Cannot equip %s." %item.getName() return #Unequip currently equipped armor/weapon if necessary if isinstance(item, Armor): self._armor = item self._armorDefense = self._armor.getDefense() elif isinstance(item, Weapon): self._weapon = item self._weaponAttack = self._weapon.getAttack() for currentItem in self._equipped: if isinstance(item, Weapon) and isinstance(currentItem, Weapon): self.unequip(currentItem) elif isinstance(item, Armor) and isinstance(currentItem, Armor): self.unequip(currentItem) #Update player to reflect equipment if isinstance(item, Armor): self._armor = item self._armorDefense = self._armor.getDefense() elif isinstance(item, Weapon): self._weapon = item self._weaponAttack = self._weapon.getAttack() self._equipped.addItem(item) print "%s equipped %s." %(self._name, item.getName()) def unequip(self, item): """ Allows a character to unequip a currently equipped item. @param item: The item to be unequipped. """ print "" if item in self._equipped: self._equipped.removeItem(item) #Update player to reflect equipment if isinstance(item, Weapon): self._weapon = None self._weaponAttack = 0 if isinstance(item, Armor): self._armor = None self._armorDefense = 0 print "%s unequipped %s." % (self._name, item.getName()) else: print "Cannot unequip %s." % item.getName() def getWeapon(self): """ Returns play weapon. @return: Player's current weapon. """ return self._weapon def getArmor(self): """ Returns player armor. @return: Player's current armor. """ return self._armor def getEquipped(self): """ Returns the player's currently equipped equipment. @return: Player's current gear. """ return self._equipped def addToInventory(self, item): """ Adds an item to inventory. @param item: The item to be added to inventory. """ if (isinstance(item, Item) and (item not in self._inventory)): print "Added %s to inventory." % item.getName() self._inventory.addItem(item) else: print "Cannot add %s to inventory." % item def removeFromInventory(self, item): """ Removes an item from inventory. If item is currently equipped, unequips item. @param item: The item to be removed. """ if item in self._inventory: if item in self._equipped: self.unequip(item) self._inventory.removeItem(item) def getInventory(self): """ Returns the player's inventory. @return: Player's inventory. """ return self._inventory def getMoney(self): """ Returns player's money. @return: Player's money. """ return self._money def increaseMoney(self, amount): """ Increases player money. """ if amount <= 0: errorMsg = "Method increaseMoney() was given a negative value" raise AssertionError(errorMsg) self._money += amount def decreaseMoney(self, amount): """ Decreases player money. """ if amount <= 0: errorMsg = "Method decreaseMoney() was given a negative value" raise AssertionError(errorMsg) self._money -= amount def canMoveNorth(self): """ Determines if player can move north. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.NORTH) if exit: return True return False def canMoveSouth(self): """ Determines if player can move south. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.SOUTH) if exit: return True return False def canMoveEast(self): """ Determines if player can move east. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.EAST) if exit: return True return False def canMoveWest(self): """ Determines if player can move west. @return: True if possible, false otherwise. """ exit = self._location.getExit(constants.Direction.WEST) if exit: return True return False def moveNorth(self): """ Moves player north one space. """ northSpace = self._location.getExit(constants.Direction.NORTH) #If north space does not exist, do nothing if not northSpace: return #...otherwise, move to new space self._location = northSpace def moveSouth(self): """ Moves player south one space. """ southSpace = self._location.getExit(constants.Direction.SOUTH) #If south space does not exist, do nothing if not southSpace: return #...otherwise, move to new space self._location = southSpace def moveEast(self): """ Moves player east one space. """ eastSpace = self._location.getExit(constants.Direction.EAST) #If east space does not exist, do nothing if not eastSpace: return #...otherwise, move to new space self._location = eastSpace def moveWest(self): """ Moves player west one space. """ westSpace = self._location.getExit(constants.Direction.WEST) #If west space does not exist, do nothing if not westSpace: return #...otherwise, move to new space self._location = westSpace def getLocation(self): """ Returns player's current location (i.e. space). @return: Player's current location. """ return self._location
class Player(object): """ Represents the (human) player. """ def __init__(self, name, location): """ Initializes the player. @param name: The name of the player (e.g. "Frodo"). @param location: The location of player. When initialized, given space "shire." """ self._name = name self._location = location #Initialize player stats self._money = constants.PlayerInitialization.MONEY self._experience = constants.PlayerInitialization.EXPERIENCE self._level = constants.PlayerInitialization.LEVEL self._hp = constants.PlayerInitialization.MAX_HP self._maxHp = constants.PlayerInitialization.MAX_HP self._attack = constants.PlayerInitialization.ATTACK self._weightLimit = constants.PlayerInitialization.WEIGHT_LIMIT #Initialize player inventory and equipment self._inventory = ItemSet() self._equipped = ItemSet() #Initialize item-based bonuses self._weaponAttack = constants.PlayerInitialization.WEAPON_ATTACK self._armorDefense = constants.PlayerInitialization.ARMOR_DEFENSE self._charmAttack = constants.PlayerInitialization.CHARM_ATTACK self._charmDefense = constants.PlayerInitialization.CHARM_DEFENSE self._charmHp = constants.PlayerInitialization.CHARM_HP #Update player stats for item-based bonuses self._totalAttack = (self._attack + self._weaponAttack + self._charmAttack) self._totalDefense = self._armorDefense + self._charmDefense self._totalMaxHp = self._maxHp + self._charmHp def getName(self): """ Returns player name. @return: The name of the player. """ return self._name def attack(self, target): """ Allows player to attack target. @param target: The target player is to attack. """ target.takeAttack(self._totalAttack) def getAttack(self): """ Gets a player's total attack power (excluding items). @return: Base player attack. """ return self._attack def getTotalAttack(self): """ Gets player's total attack power (including items). @return: Total player attack value. """ return self._totalAttack def takeAttack(self, attack): """ Allows player to receive an attack. @param attack: The attack player is to receive. """ self._hp = max(self._hp - max(attack - self._totalDefense, 0), 0) def getTotalDefense(self): """ Returns player's total defense. @return: Player's total defense stat. """ return self._totalDefense def getCharmAttack(self): """ Returns player's charm attack. @return: Player's charm attack stat. """ return self._charmAttack def getCharmDefense(self): """ Returns player's charm defense. @return: Player's charm defense stat. """ return self._charmDefense def getCharmHp(self): """ Returns player's charm hp. @return: Player's charm hp stat. """ return self._charmHp def getWeightLimit(self): """ Returns player's weight limit. @return: Player weight limit. """ return self._weightLimit def getExperience(self): """ Return's player experience. @return: Returns player experience. """ return self._experience def increaseExperience(self, newExperience): """ Allows player to receive additional experience. Runs _updateLevel() upon receiving additional experience. @param newExperience: The experience player is to receive. """ self._experience += newExperience self._updateLevel() def getLevel(self): """ Return's player level. @return: Player level. """ return self._level def _updateLevel(self): """ Levels up player and updates player stats. This method creates a list of levels for which player experiences qualifies. Player level is the highest level for which player experience qualifies. After level-up is determined, player stats are updated. """ #Checks to see if player is max level if self._level == constants.MAX_LEVEL: return #Check to see if player has leveled up currentLevel = self._level potentialLevels = [] #Create list of levels for which player experience qualifies for level in constants.LEVEL_EXP_REQUIREMENT: if self._experience >= constants.LEVEL_EXP_REQUIREMENT[level]: potentialLevels.append(level) #Player level is the highest of the qualified levels potentialNewLevel = max(potentialLevels) #If player has leveled up if currentLevel != potentialNewLevel: numberLevelUp = potentialNewLevel - currentLevel self._level = potentialNewLevel print "\n%s leveled up! %s is now level %s!" \ % (self._name, self._name, self._level) #Updates player level and stats for level in range(numberLevelUp): self._maxHp = floor(self._maxHp * constants.HP_STAT) self._totalMaxHp = self._maxHp + self._charmHp self._attack = floor(self._attack * constants.ATTACK_STAT) self._totalAttack = (self._attack + self._weaponAttack + self._charmAttack) self._weightLimit = floor(self._weightLimit * constants.WEIGHT_LIMIT_STAT) def getHp(self): """ Returns player hp. @return: Player hp. """ return self._hp def getMaxHp(self): """ Returns player maximum hp. @return: Player maximum hp. """ return self._maxHp def getTotalMaxHp(self): """ Returns player maximum hp, including charms. @return: Player maximum hp. """ return self._totalMaxHp def heal(self, amount): """ Allows player to heal up to totalMaxHp. @param amount: The amount of hp to be healed. """ #If amount that player may be healed is less than amount possible if self._totalMaxHp - self._hp < amount: amountHealed = self._totalMaxHp - self._hp #If amount that player may be healed is greater than or equal to the #amount possible else: amountHealed = amount self._hp += amountHealed def equip(self, item): """ Allows a character to equip an item. Preconditions: -Item in inventory. -Item is instance of Armor, Weapon, or Charm. -Item is not currently in self._equipped. @param item: The item to be equipped. """ #Check to see that preconditions are met if item not in self._inventory: statement = "%s not currently in inventory." % item.getName() return statement if not (isinstance(item, Armor) or isinstance(item, Weapon) or isinstance(item, Charm)): statement = "Item must be a weapon, armor, or charm." return statement if item in self._equipped: statement = "%s already equipped." % item.getName() return statement #Unequip currently equipped armor/weapon if necessary for currentItem in self._equipped: if isinstance(item, Weapon) and isinstance(currentItem, Weapon): self.unequip(currentItem) elif isinstance(item, Armor) and isinstance(currentItem, Armor): self.unequip(currentItem) #Equip new item self._equipped.addItem(item) if isinstance(item, Weapon): self._weaponAttack = item.getAttack() self._totalAttack = (self._attack + self._weaponAttack + self._charmAttack) elif isinstance(item, Armor): self._armorDefense = item.getDefense() self._totalDefense = self._armorDefense + self._charmDefense elif isinstance(item, Charm): self._charmAttack += item.getAttack() self._charmDefense += item.getDefense() self._charmHp += item.getHp() self._totalAttack = (self._attack + self._weaponAttack + self._charmAttack) self._totalDefense = self._armorDefense + self._charmDefense self._totalMaxHp = self._maxHp + self._charmHp statement = "%s equipped %s." %(self._name, item.getName()) #Sort self._equipped sortItems(self._equipped) return statement def unequip(self, item): """ Allows a character to unequip a currently equipped item. @param item: The item to be unequipped. """ #Precondition - that item is currently equipped. if item not in self._equipped: statement = "%s not in equipped items." % item.getName() return statement #Unequip item and update player stats self._equipped.removeItem(item) if isinstance(item, Weapon): self._weaponAttack = 0 self._totalAttack = (self._attack + self._weaponAttack + self._charmAttack) if isinstance(item, Armor): self._armorDefense = 0 self._totalDefense = self._armorDefense + self._charmDefense if isinstance(item, Charm): charmAttack = item.getAttack() charmDefense = item.getDefense() charmHp = item.getHp() self._charmAttack -= charmAttack self._charmDefense -= charmDefense self._charmHp -= charmHp self._totalAttack = (self._attack + self._weaponAttack + self._charmAttack) self._totalDefense = self._armorDefense + self._charmDefense self._totalMaxHp = self._maxHp + self._charmHp #Update player Hp for charms self._updateHpForCharms() #Sort self._equipped sortItems(self._equipped) statement = "%s unequipped %s." % (self._name, item.getName()) return statement def _updateHpForCharms(self): """ For unequiping charms, player HP needs to be updated to reflect new totalMaxHp. """ currentHp = self._hp if self._totalMaxHp < currentHp: self._hp = self._totalMaxHp def getEquipped(self): """ Returns the player's currently equipped equipment. @return: Player's current gear. """ sortItems(self._equipped) return self._equipped def addToInventory(self, item): """ Adds an item to inventory. @param item: The item to be added to inventory. @return: True if execution suceeds, False otherwise. """ inventory = self._inventory #If user input is not an item if not isinstance(item, Item): errorMsg = "Not an item." raise AssertionError(errorMsg) #Check inventory weight restriction itemWeight = item.getWeight() inventoryWeight = inventory.getWeight() if itemWeight + inventoryWeight > self._weightLimit: print "You are overburdened." return False #Successful execution inventory.addItem(item) sortItems(inventory) print "Added %s to inventory." % item.getName() return True def removeFromInventory(self, item): """ Removes an item from inventory. If item is currently equipped, unequips item. @param item: The item to be removed. """ #Item must be in inventory if not item in self._inventory: return #Unequip if necessary if item in self._equipped: self.unequip(item) self._inventory.removeItem(item) sortItems(self._inventory) def getInventory(self): """ Returns the player's inventory. @return: Player's inventory. """ sortItems(self._inventory) return self._inventory def getMoney(self): """ Returns player's money. @return: Player's money. """ return self._money def increaseMoney(self, amount): """ Increases player money. """ if amount < 0: errorMsg = "Method increaseMoney() was given a negative value." raise AssertionError(errorMsg) self._money += amount def decreaseMoney(self, amount): """ Decreases player money. """ if amount < 0: errorMsg = "Method decreaseMoney() was given a negative value." raise AssertionError(errorMsg) self._money -= amount def canMoveNorth(self): """ Determines if player can move north. @return: True if possible, False otherwise. """ exit = self._location.getExit(constants.Direction.NORTH) if exit: return True return False def canMoveSouth(self): """ Determines if player can move south. @return: True if possible, False otherwise. """ exit = self._location.getExit(constants.Direction.SOUTH) if exit: return True return False def canMoveEast(self): """ Determines if player can move east. @return: True if possible, False otherwise. """ exit = self._location.getExit(constants.Direction.EAST) if exit: return True return False def canMoveWest(self): """ Determines if player can move west. @return: True if possible, False otherwise. """ exit = self._location.getExit(constants.Direction.WEST) if exit: return True return False def moveNorth(self): """ Moves player north one space. """ northSpace = self._location.getExit(constants.Direction.NORTH) #If north space does not exist, do nothing if not northSpace: return #...Otherwise, move to new space if not isinstance(northSpace, list): self._location = northSpace else: self._moveList(northSpace) def moveSouth(self): """ Moves player south one space. """ southSpace = self._location.getExit(constants.Direction.SOUTH) #If south space does not exist, do nothing if not southSpace: return #...Otherwise, move to new space if not isinstance(southSpace, list): self._location = southSpace else: self._moveList(southSpace) def moveEast(self): """ Moves player east one space. """ eastSpace = self._location.getExit(constants.Direction.EAST) #If east space does not exist, do nothing if not eastSpace: return #...Otherwise, move to new space if not isinstance(eastSpace, list): self._location = eastSpace else: self._moveList(eastSpace) def moveWest(self): """ Moves player west one space. """ westSpace = self._location.getExit(constants.Direction.WEST) #If west space does not exist, do nothing if not westSpace: return #...Otherwise, move to new space if not isinstance(westSpace, list): self._location = westSpace else: self._moveList(westSpace) def _moveList(self, spaces): """ Helper method for the four movement commands. Processes cases when there are multiple spaces available for a single direction. """ acceptableChoices = {} choice = None #Solicit user input print "You may move to the following:" for space in spaces: print "\t-%s" % space.getName() acceptableChoices[space] = space.getName() print "" while choice not in acceptableChoices.values(): choice = raw_input("Where would you like to go? ") #Move to new space for pair in acceptableChoices.items(): if choice in pair: space = pair[0] break self._location = space def getLocation(self): """ Returns player's current location. @return: Player current location. """ return self._location