Update
Someone is probably going to drop the hammer on me for posting this way but there’s not enough room in comments to cover this and they specifically tell you not to answer your own question with a follow-up, so here goes…
I’ve created the dice class like you guys were talking about.
class dice():
def __init__(self, sides, number):
self.sides = sides
self.number = number
def roll(self):
return random.randint(1, self.sides)
The number argument isn’t doing anything though.
def att():
d = dice(20, 2)
base = d.roll()
if base == 1:
print 'Miss!'
elif base == 20:
crit = d.roll()
if crit < 10:
print 'Hit!'
else:
print 'Critical hit!\n'
effect = super_crit()
else:
print base
The only way I’m getting more than one die is if I do something like this:
def initiative():
d = dice(10, 1)
ini = d.roll(), d.roll()
print ini
I’ve also tried:
def initiative():
d = dice(10, 2)
d.sides = 10
d.number = 2
ini = d.roll()
print ini
That looks redundant to me but I get a Type Error: for having too few arguments without dice(10, 2). No matter which method I use, I get the same result – one die. Am I missing something?
Original post
I’m learning how to use classes in Python 2.7 and as an exercise I’m writing a combat module for a text-based RPG. It uses the old school dice roll method to determine outcomes and effects. A roll determines a hit or miss. If a natural 20 is rolled, another roll determines if it was a critical hit. If critical hit = TRUE, another die is rolled to determined which body part is effected. Each body part is paired with a number 1-12 in a dictionary. There are three possible output messages depending on the affected part. My problem is that the entire list of values is returned instead of a specific part. What am I doing wrong here?
Yes, I know this is super nerdy. Yes, I know the output is lame, but it’s all place holder.
import sys, random
#dice generator
class dice():
def d4(self):
number = random.randint(1, 4)
return number
def d6(self):
number = random.randint(1, 6)
return number
def d10(self):
number = random.randint(0, 9)
return number
def d12(self):
number = random.randint(1, 12)
return number
def d20(self):
number = random.randint(1, 20)
return number
def d100(self):
number = random.randint(0, 99)
return number
#critical hit effect generator
class super_crit(dice):
def __init__(self):
roll = dice()
loc = roll.d12()
hit_loc = {1 : 'Head',
2 : 'Left Arm',
3 : 'Right Arm',
4 : 'Left Leg',
5 : 'Right Leg',
6 : 'Left Hand',
7 : 'Right Hand',
8 : 'Left Foot',
9 : 'Right Foot',
10 : 'Chest',
11 : 'Stomach',
12 : 'Body'}
part = hit_loc.values()
for w in part:
if loc <= 9:
print w, "has been severed!"
elif loc == 10:
print "You sink your blade into his", w, "and pierce the heart!"
elif loc == 11:
print "You slash him across the", w, "and eviscerate him!"
elif loc == 12:
print "You shred the enemy's", w, "to ribbons!"
class attackRoll(dice):
pass
#Attack function
def att():
roll = attackRoll()
base = roll.d20()
if base == 1:
print 'Miss!'
elif base == 20:
crit = roll.d20()
if crit < 10:
print 'Hit!'
else:
effect = super_crit()
else:
print base
def main():
att()
if __name__ == '__main__':
main()
You loop over all the values of the dict:
Perhaps you meant to pick the one that is affected instead?
In other words, you do not need a loop here at all.
Note that, whenever you find yourself using a sequential series of numbers as keys to a dictionary, you may as well make it a list instead:
except now the indexes run from 0 to 11, so use
loc - 1to find the right body part: