#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    2
    Rep Power
    0

    For loop and List comprehensions


    Hello everyone.

    I'm trying to debug code that just seems impossible. I have a working example of what the method in my class is suppose to do. Though, upon implementing the working example into my main program, it doesn't work. Here is the code:

    Code:
    class Player(object):
    
    	def __init__(self):
    
    		# Name Attribute of Player Object
    		self.name = "Jake"
    
    		# Equiptment Slots
    		self.slots = {"Head":None,
    			      "Torso":None,
    			      "Legs":None,
    			      "Hand_L":None,
    			      "Hand_R":None,
    			      "Feet":None,
    			      "Neck":None,
    			      "Cape":None,
    			      "Gloves":None}
    
    		# Skill Levels
    		self.strength_level = 1
    		self.speed_level = 1
    		self.defence_level = 1
    
    		# Equiptment Buffs
    		self.equiptment = { "strength" : 0,
    				    "speed" : 0,
    				    "defence" : 0}
    
    		self.update()
    
    	def __str__(self):
    		rep = ""
    		rep += self.name
    		rep += "\n" + ("-"*len(self.name)) + "\n"
    		rep += str([[i, jake.slots[i]] for i in jake.slots]).replace("[","").replace("]","")
    		rep += "\n\nSkills\n"
    		rep += "-"*len("Skills")
    		rep += "\n"
    		rep += "Strenght - " + str(self.strength) + "\nSpeed - " + str(self.speed) + "\nDefence - " + str(self.defence)
    
    		return rep
    
    	def update_equiptment(self):
    		"""
    		Loops through player's slots (head, body, legs, ect)...
    		If that slot contains an item, update equiptment dictionary to reflect item's boost.
    		"""
    
    		for i in self.equiptment:
    			self.equiptment[i] = sum([item.effects[0][1] for item in [self.slots[equiptment] for equiptment in self.slots if self.slots[equiptment]] if item.effects[0][0] == i])
    
    	def update_attributes(self):
    		""" Update attributes based on Levels and Equiptment. """
    
    		# Attribute Expressions
    		self.strength = (self.strength_level * 2) + self.equiptment["strength"]
    		self.speed = (self.speed_level * 2) + self.equiptment["speed"]
    		self.defence = (self.defence_level * 2) + self.equiptment["defence"]
    
    	def update(self):
    		""" Update Both equiptment buffs and attributes based on levels. """
    
    		# update equiptment buff
    		self.update_equiptment()
    
    		#update attributes based on level and equiptment
    		self.update_attributes()
    
    	def equipt(self, item):
    		""" Equipt an item. """
    
    		# Determine what slot the item occupies
    		slot = item.slot
    
    		# Assigns item to slot
    		self.slots[slot] = item
    
    		# update equiptment dictionary to reflect changes made to slots
    		self.update()
    
    	def unequipt(self, slot):
    		""" Unequipt an item. """
    
    		if slot.title() in self.slots:
    			self.slots[slot.title()] = None
    		else:
    			print slot, "is not a slot."
    
    		self.update()
    Code for item class:
    Code:
    class item(object):
    	""" An item """
    
    	def __init__(self, name, slot, effect):
    		self.name = name
    		self.slot = slot
    		self.effects = effect
    
    	def __str__(self):
    		rep = ''
    		rep += self.name
    
    		return rep
    	
    	def __repr__(self):
    		rep = ''
    		rep += self.name
    		
    		return rep
    For a test, I create an item with the name "Wooden Sword", for the slot "Hand_L" , with the effects of [["strength, 5], ["defence", 2]]

    Code:
    ws = item("Wooden Sword", "Hand_L", "[["strength, 5], ["defence",2]]
    
    # create a player object
    jake = Player()
    
    # equipt item
    jake.equipt(ws)
    
    print jake
    
    jake.unequipt("Hand_L")
    
    print jake
    The focus of this script is the update_equiptment method that is only a few lines long.

    Basically, for value of equiptment["strength"] it adds up the value for every strength item equipted. It does the same for speed and defence. This way, the equiptment dictionary represents buffs given by armor and is separate from strength, speed and defence given by leveling the skill.

    To avoid taking up too much more space, I will discuss the specific problem im having with the for loop and list comprehensions.

    I create a list of items equipted by the player.

    Code:
    [self.slots[e] for e in self.slots if self.slots[e]]
    I create a list of effects based on the items in the previous list.

    [item.effects for item in [self.slots[e] for e in self.slots if self.slots[e]]

    At this point, i have a list of effects for each item warn by player. Though the results are shown like this:

    [[['strength', 5], ['speed', 5]]]

    This is where my problem starts. It seems like the above is a list that contains a list, that contains a list with 2 elements "['strength' 5]" and "['speed', 5']". However, if i attempt to do the following:

    Code:
    [item.effects[0] for item in [self.slots[e] for e in self.slots if self.slots[e]]
    The results is:
    [['strength', 5]]

    It gives me the 0th element of [['strength', 5], ['speed' 5]] instead of the 0th element of both items in the sequence [['strength', 5], ['speed' 5]] which would be ["strength", "speed"].

    I don't think i did the best job at describing the problem, so anyone needs clarification on the issue, let me know.

    Thanks in advance.

    Edited for grammar.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2007
    Location
    Joensuu, Finland
    Posts
    431
    Rep Power
    67
    Errrmm... I think you should store the effects as a dictionary instead of as a list:

    Code:
    ws = Item('Wooden Sword', 'Hand_L', {'strength': 5, 'defence': 2})
    This way you would get the names of the effects simply this way:

    Code:
    all_effects = ws.effects.keys()
    This actually returns an iterator in Python 3, so if you really need a list, you have to do list comprehension:

    Code:
    all_effects = [effect for effect in ws.effects.keys()]
    As a sidenote, I’m not sure you should store the slot at all in class Item. An item (like “a wooden sword”) is exactly this item whether it occupies some slot or not. The slot is player-specific, not item-specific, that is.
    My armada: openSUSE 13.1 (home desktop, home laptop), Crunchbang Linux 11 (mini laptop, work laptop), Android 4.2.1 (tablet)
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    2
    Rep Power
    0
    SuperOscar
    Thanks for the suggestion. Ill consider using a dictionary for effects rather than a list. It seems like it would make things much easier.

    As a sidenote, I’m not sure you should store the slot at all in class Item. An item (like “a wooden sword”) is exactly this item whether it occupies some slot or not. The slot is player-specific, not item-specific, that is.
    I'm not entirely sure what you mean.

    The purpose of item having an slot on the in the item class is to specify which slot an item occupies.

    The item class uses Name, Slot and Effects to create a game object, with the name - Name, that occupies the slot - Slots and has the effects of Effects.

    For example:

    Code:
    # item that occupies the player's 'Hand_L' slot
    w_s = Item('Wooden Sword', 'Hand_L', {'strength': 5, 'defence': 2})
    
    # item that occupies the player's 'Hand_R' slot
    w_sh = Item('Wooden Sheild', 'Hand_R', {'defence': 6, 'speed' : -2})
    
    # item that occupies the player's 'Cape' slot
    rc = Item('rogue's cape', 'Cape', {'defence 2'})
  6. #4
  7. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,843
    Rep Power
    480
    We're not confusing slots and __slots__ ?
    [code]Code tags[/code] are essential for python code and Makefiles!
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2007
    Location
    Joensuu, Finland
    Posts
    431
    Rep Power
    67
    Originally Posted by Johneysteel
    I'm not entirely sure what you mean.

    The purpose of item having an slot on the in the item class is to specify which slot an item occupies.
    Yes, I got that, but I think the Item class should not know (or need to know) where it resides. Unlike the other class attributes, the slot doesn’t “define” an item (neither the class nor the instance). It’d be exactly the same item no matter which slot it happens to occupy.

    On the other hand, the Player class should have knowledge of its slots and what, if anything, occupies them, because they are the properties that define the player instance.
    My armada: openSUSE 13.1 (home desktop, home laptop), Crunchbang Linux 11 (mini laptop, work laptop), Android 4.2.1 (tablet)

IMN logo majestic logo threadwatch logo seochat tools logo