Short (Non-Explanatory) Summary of Code
I just started learning Python a month or 2 ago, and this (small) 955 line mess is what I've worked on since summer started in June. I am basing it on Dungeons and Dragons, and so far, the coding has gone relatively smooth. I used Enthought Canopy to code this, as it allows me to call anything in the code using the input/output box.
So far, I have:
- A class for NPCs/enemies with methods covering most of the basics.
- An item class with its own child classes for weapons, armour, and bags.
- A skill class for attack moves and such.
- An effect class, which is just for dealing damage and healing so far.
- An effect-over-time class, which handles the basic damage/heal each turn.
- A (currently) empty treasure generator, which I'm planning to link to a
.txt
file.
Explanation of Code
- An underscore (
_
) before a variable/method name signifies that it is 'raw'. It's not meant to be accessed by itself or is the backbone of a similarly named method. eg:_inven
andinven()
,_drop()
anddrop()
. Note that some 'raw' variables and methods do not yet have a non-underscored method. - Similar brackets, eg:
((
,))
,[[
,{{
, etc. have a space between them to make it easier (for me) to read. Empty lines are added at the ends of
if
,elif
, andelse
statements. ie:if statement: #do something elif otherStatement: if moreStatment: #do moreSomething else: #do somethingElse else: #do otherSomething
- I also randomly add an empty line whenever it makes it easier (for me) to read.
What to Do
I will accept any and all criticism given to me provided it isn't a blatant stab at my lack of skill. Please include at least 1 Must Change and/or Recommended Change. These can be structure formatting, renaming variables, confused queries of what a method does, etc. I will only accept praise if you hide it within a criticism.
The Code
'''
To Do List:
* Add _drop() and drop() methods to NPC (in-progress on doc)
- Convert to suitable format for Bag
* Create file for treasure
- Adapt getTreasure() to access file (in-progress)
* Add Trap
* Add talk() method to NPC
* Create GUI (Later)
'''
import math
import random
#import tkinter
class NPC:
def __init__(self, name='Shrouded Figure', agil=0.0, char=0.0, endur=0.0, stren=0.0, tough=0.0, will=0.0, wis=0.0, luck=0.0, focus=0.0, magpot=0.0, level=None, gold=0, skills={}, inven={}, equipment={}):
#Name
self.name = name
#Attributes
self._attributes = {
'agility' : agil,
'charisma' : char,
'endurance' : endur,
'strength' : stren,
'toughness' : tough,
'willpower' : will,
'wisdom' : wis,
'luck' : luck,
'focus' : focus,
'magic potential' : magpot
}
#Random attribute generator
for attrib in self._attributes:
if type(self._attributes[attrib]) == list:
self._attributes[attrib] = float(random.randint(self._attributes[attrib][0], self._attributes[attrib][1]) )
if type(level) == int:
for n in range(level):
self._attributes[random.choice(list(self._attributes) )] += 1.0
#Stats
self._stats = {
'speed' : math.ceil( ( ( (self._attributes['agility'] + ( (self._attributes['agility'] * self._attributes['endurance']) ** 0.5)/3 + self._attributes['endurance']/2) + 1) * (self._attributes['willpower'] + 1) ) ** 0.5),
'health' : math.ceil( ( ( self._attributes['toughness']**2 - self._attributes['toughness'])/2 + self._attributes['endurance']/5 + 1) * (self._attributes['willpower']/10 + 1) + 24),
'accuracy' : math.ceil( (40*(1 - 0.9**self._attributes['focus']) + 30*(1 - 0.9**self._attributes['luck']) + 20*(1 - 0.9**self._attributes['willpower']) + 10) * 10) / 10,
'stamina' : math.ceil( (self._attributes['endurance'] - 1/(self._attributes['willpower'] + 1) + 1) + (self._attributes['willpower'] - 1/(self._attributes['endurance'] + 1) + 1)/2 + 5),
'power' : math.ceil( (self._attributes['strength'] + self._attributes['willpower']/2 + (self._attributes['strength']*self._attributes['willpower'] + self._attributes['endurance']/3)/(self._attributes['strength'] + self._attributes['willpower'] + 1) + 1 + self._attributes['endurance']/5) * 10) / 10,
'recovery' : math.ceil( (self._attributes['magic potential']/5 + self._attributes['endurance'] + self._attributes['toughness']/3 + 1 + ( (self._attributes['magic potential'] * self._attributes['endurance'] * self._attributes['toughness']) ** 0.5) / 4) / 1.5),
'awareness' : math.ceil( ( ( ( (self._attributes['luck']/5 + self._attributes['focus'] + self._attributes['willpower']/3) ** 1.5) + 1.25) / 5) * 10) / 10,
'sneaking' : math.ceil( ( ( (self._attributes['luck'] + self._attributes['focus']/2 + self._attributes['agility']/3 + 1) ** 0.75) * (self._attributes['focus']/2 + 1) / 4) * 10) / 10,
'dodging' : math.ceil( (50*(1 - 0.9**self._attributes['agility']) + 30*(1 - 0.9**self._attributes['willpower']) + 20*(1 - 0.9**self._attributes['luck']) ) * 10) / 10,
'shielding' : math.ceil( (self._attributes['toughness']/2 + self._attributes['willpower']/3 + self._attributes['strength']) * self._attributes['strength']/4),
'mPower' : math.ceil( ( ( (self._attributes['magic potential'] + self._attributes['strength']/2 + self._attributes['willpower']/5) * self._attributes['magic potential']/4) ** (1/3) ) * 10) / 10,
'mReserves' : math.ceil(self._attributes['magic potential'] + (self._attributes['magic potential'] * self._attributes['endurance'])**0.5 + (self._attributes['endurance']/2)**1.25),
'mSkill' : math.ceil( (self._attributes['magic potential'] + self._attributes['wisdom']/2 + (self._attributes['magic potential']*(self._attributes['wisdom'] + 1) ) ) ** 0.5),
'mConcentration' : math.ceil( (50*(1 - 0.9**self._attributes['magic potential']) + 30*(1 - 0.9**self._attributes['focus']) + 10*(1 - 0.9**self._attributes['willpower']) + 10*(1 - 0.9**self._attributes['luck']) ) * 10) / 10,
'looting' : math.ceil(0.9 * (1 - 0.8**self._attributes['luck'])/0.2 * 20) + 10,
'capacity' : math.ceil( ( (self._attributes['endurance']/3 + self._attributes['strength'] + 1) * (self._attributes['willpower']/4 + 1) ) + 9)
}
'''Unused stats'''
#'knowledge' : math.ceil( ( ( (self._attributes['charisma']/7 + self._attributes['wisdom'] + self._attributes['magic potential']/11) * (self._attributes['charisma']/5 + self._attributes['wisdom'] + 1) + 1) ** 0.75) * 10) / 10
#'trading' : math.ceil( (self._attributes['charisma']**2 + self._attributes['wisdom'] + self._attributes['luck']*(self._attributes['luck'] - 1) + 1) ** 0.25)
#Starting stats
self.hp = self._stats['health']
self.sp = self._stats['stamina']
self.mp = self._stats['mReserves']
#Skillset
self._skills = skills
#Gold
self.gold = gold
#Inventory
self._inven = inven
#Equipment
self._equipment = equipment
#Adjust equality factor
def __eq__(self, other):
return self.__dict__ == other.__dict__
#Adjust string value
def __str__(self):
returnStr = 'NPC(name=\'' + self.name + '\''
if self._attributes['agility'] != 0.0:
returnStr += ', agil=' + str(self._attributes['agility'])
if self._attributes['endurance'] != 0.0:
returnStr += ', endur=' + str(self._attributes['endurance'])
if self._attributes['charisma'] != 0.0:
returnStr += ', char=' + str(self._attributes['charisma'])
if self._attributes['toughness'] != 0.0:
returnStr += ', tough=' + str(self._attributes['toughness'])
if self._attributes['strength'] != 0.0:
returnStr += ', stren=' + str(self._attributes['strength'])
if self._attributes['wisdom'] != 0.0:
returnStr += ', wis=' + str(self._attributes['wisdom'])
if self._attributes['willpower'] != 0.0:
returnStr += ', will=' + str(self._attributes['willpower'])
if self._attributes['luck'] != 0.0:
returnStr += ', luck=' + str(self._attributes['luck'])
if self._attributes['focus'] != 0.0:
returnStr += ', focus=' + str(self._attributes['focus'])
if self._attributes['magic potential'] != 0.0:
returnStr += ', magpot=' + str(self._attributes['magic potential'])
if self.gold > 0:
returnStr += ', gold=' + str(self.gold)
if len(self._skills) > 0:
returnStr += ', skills={' + str(self._skills)
#Used for multiple items
m = 0
for skill in self._skills:
if m > 0:
returnStr += ', '
returnStr += '\'' + skill + '\':' + str(self._skills[skill])
m += 1
returnStr += '}'
if len(self._inven) > 0:
returnStr += ', inven={' + str(self._inven)
#Used for multiple items
m = 0
for item in self._inven:
if m > 0:
returnStr += ', '
returnStr += '\'' + item + '\':' + str(self._inven[item])
m += 1
returnStr += '}'
if len(self._equipment) > 0:
returnStr += ', equipment={'
#Used for multiple items
m = 0
for item in self._equipment:
if m > 0:
returnStr += ', '
returnStr += '\'' + item + '\':' + str(self._equipment[item])
m += 1
returnStr += '}'
returnStr += ')'
return returnStr
#Display info
def show(self):
print(self.name)
print('HP: ' + str(self.hp) + '/' + str(self._stats['health']) )
print('SP: ' + str(self.sp) + '/' + str(self._stats['stamina']) )
print('MP: ' + str(self.mp) + '/' + str(self._stats['mReserves']) )
print('')
#Activate end-of-turn effects
def endTurn(self):
DOT.cycleDOT(target=self)
self.hp = min(self.hp + self._stats['recovery'], self._stats['health'])
self.sp = min(self.hp + self._stats['recovery'], self._stats['stamina'])
self.mp = min(self.hp + self._stats['recovery'], self._stats['mReserves'])
self.display()
#Get loot from NPC
def getLoot(self, user):
loot = {}
#Generate loot from inventory
for item in self._inven:
#Check for stackable item
if type(self._inven[item]) == int:
#Apply looting chances to individual items in stack
for n in range(self._inven[item]):
rand = random.randint(1, 100)
if rand <= user._stats['looting']:
#Check for/add missing item
if item not in loot:
loot[item] = 0
loot[item] += 1
else:
rand = random.randint(1, 100)
if rand <= user._stats['looting']:
loot[item] = self._inven[item]
#Generate loot from equipment
for item in self._equipment:
rand = random.randint(1, 100)
if rand <= user._stats['looting']:
loot[self._equipment[item].name] = self._equipment[item]
#Generate loot from gold
randG = random.randint(0, self.gold**2)
randG = randG * (user._stats['looting']/100)
randG = math.ceil(math.sqrt(randG) )
loot['Gold'] = randG
#Generate loot from levels (not affected by looting)
randXp = 0
for attrib in self._attributes:
randXp += math.ceil(self._attributes[attrib] ** 1.5)
loot['XP'] = randXp
return loot
#Get dmg of NPC
def getDmg(self, mult=1, mod=0):
#Check for weapon
if 'weapon' in self._equipment:
#Differentiate between int and list dmg ranges
if type(self._equipment['weapon'].dmgRange) == int:
dmg = math.ceil(mult * self._equipment['weapon'].dmgRange) + mod
elif type(self._equipment['weapon'].dmgRange) == list:
dmg = math.ceil(mult * random.randint(self._equipment['weapon'].dmgRange[0], self._equipment['weapon'].dmgRange[1]) ) + mod
else:
dmg = math.ceil(mod + mult)
#Keep dmg above or equal to 0
dmg = max(0, dmg)
return dmg
#Get defence of NPC
def getDef(self):
defence = 0
if 'head' in self._equipment:
defence += self._equipment['head'].defence
if 'body' in self._equipment:
defence += self._equipment['body'].defence
if 'hands' in self._equipment:
defence += self._equipment['hands'].defence
if 'legs' in self._equipment:
defence += self._equipment['legs'].defence
if 'feet' in self._equipment:
defence += self._equipment['feet'].defence
return defence
#Add item(s) to inventory
def give(self, items):
#Check if items is a dict
if type(items) == dict:
for item in items:
#Item variable
_item = items[item]
#Name editor
nameEdit = ''
#Re-iterate search algorithm until resolved
while True:
#Check if item is a list w/ an Item instance
if type(_item) == list and isinstance(_item[1], Item):
#Check if item w/ same name is in inven
if (item + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[item + nameEdit]) == list and isinstance(self._inven[item + nameEdit][1], Item):
#Check if item and inven item are the same
if _item[1] == self._inven[item + nameEdit][1]:
self._inven[item + nameEdit][0] += _item[0]
break
else:
#Misfire, add *
nameEdit += '*'
#Check if inven item is an int
elif type(self._inven[_item[1].name + nameEdit]) == int:
#Misfire, add *
nameEdit += '*'
#Check if item and inven item are the same
elif item[1] == self._inven[item[1].name + nameEdit]:
self._inven[item + nameEdit] = [_item[0] + 1, _item[1] ]
break
else:
#Add new item
self._inven[item + nameEdit] = _item
break
#Check if item in an int
elif type(_item) == int:
#Check if item is in inven
if (item + nameEdit) in self._inven:
#Check if inven item is int
if type(self._inven[item + nameEdit]) == int:
self._inven[item + nameEdit] += _item
break
else:
#Misfire, add *
nameEdit += '*'
else:
#Add new item
self._inven[item + nameEdit] = _item
break
#Check if item is an Item instance
elif isinstance(_item, Item):
#Check if item w/ same name is in inven
if (item + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[item + nameEdit]) == list and isinstance(self._inven[item + nameEdit][1], Item):
#Check if item and inven item are the same
if _item == self._inven[item + nameEdit][1]:
self._inven[item + nameEdit][0] += 1
break
else:
#Misfire, add *
nameEdit += '*'
#Check if inven item is Item instance and the same as item
elif isinstance(self._inven[item + nameEdit], Item) and self._inven[item + nameEdit] == _item:
self._inven[item + nameEdit] = [2, _item]
break
else:
#Misfire, add *
nameEdit += '*'
else:
#Add new item
self._inven[item + nameEdit] = _item
break
else:
print('Item type(?) not available: ' + str(type(_item) ) )
break
#Check if items is a list w/ Item instance
elif type(items) == list and isinstance(items[1], Item):
#Name editor
nameEdit =''
#Item variable
_item = items[1]
while True:
#Check if item w/ same name is in inven
if (_item.name + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[_item.name + nameEdit]) == list and isinstance(self._inven[_item.name + nameEdit][1], Item):
#Check if item and inven item are the same
if _item[1] == self._inven[_item.name + nameEdit][1]:
self._inven[_item.name + nameEdit][0] += items[0]
break
else:
#Misfire, add *
nameEdit += '*'
#Check if item and inven item are the same
elif _item == self._inven[_item.name + nameEdit]:
self._inven[_item.name + nameEdit] = [items[0] + 1, _item]
break
else:
#Misfire, add *
nameEdit += '*'
else:
#Add new item
self._inven[_item.name + nameEdit] = items
break
#Check if items is an Item instance
elif isinstance(items, Item):
#Name editor
nameEdit = ''
#Re-iterate search algorithm until resolved
while True:
#Check if item w/ same name is in inven
if (items.name + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[items.name + nameEdit]) == list and isinstance(self._inven[items.name + nameEdit][1], Item):
#Check if item and inven item are the same
if items == self._inven[items.name + nameEdit][1]:
self._inven[items.name + nameEdit][0] += 1
break
else:
#Misfire, add *
nameEdit += '*'
#Check if inven item is Item instance and the same as item
elif isinstance(self._inven[items.name + nameEdit], Item) and self._inven[items.name + nameEdit] == items:
self._inven[items.name + nameEdit] = [2, items]
break
else:
#Misfire, add *
nameEdit += '*'
else:
#Add new item
self._inven[items.name + nameEdit] = items
break
else:
print('Items type(?) not available: ' + str(type(items) ) )
if len(self._inven) > self._stats['capacity']:
print(self.name + '\'s inventory is overflowing: ' + str(len(self._inven) ) + '/' + str(self._stats['capacity']) )
#Change stats of NPC
def editStat(self, stat, newAmount):
self._stats[stat] = newAmount
if stat == 'health':
self.hp = newAmount
elif stat == 'stamina':
self.sp = newAmount
elif stat == 'mReserves':
self.mp = newAmount
print(self.name + '\'s ' + stat + " is now " + str(newAmount) )
print('')
def recalc(self, reset=False):
self._stats = {
'speed' : math.ceil( ( ( (self._attributes['agility'] + ( (self._attributes['agility'] * self._attributes['endurance']) ** 0.5)/3 + self._attributes['endurance']/2) + 1) * (self._attributes['willpower'] + 1) ) ** 0.5),
'health' : math.ceil( ( ( self._attributes['toughness']**2 - self._attributes['toughness'])/2 + self._attributes['endurance']/5 + 1) * (self._attributes['willpower']/10 + 1) + 24),
'accuracy' : math.ceil( (40*(1 - 0.9**self._attributes['focus']) + 30*(1 - 0.9**self._attributes['luck']) + 20*(1 - 0.9**self._attributes['willpower']) + 10) * 10) / 10,
'stamina' : math.ceil( (self._attributes['endurance'] - 1/(self._attributes['willpower'] + 1) + 1) + (self._attributes['willpower'] - 1/(self._attributes['endurance'] + 1) + 1)/2 + 5),
'power' : math.ceil( (self._attributes['strength'] + self._attributes['willpower']/2 + (self._attributes['strength']*self._attributes['willpower'] + self._attributes['endurance']/3)/(self._attributes['strength'] + self._attributes['willpower'] + 1) + 1 + self._attributes['endurance']/5) * 10) / 10,
'recovery' : math.ceil( (self._attributes['magic potential']/5 + self._attributes['endurance'] + self._attributes['toughness']/3 + 1 + ( (self._attributes['magic potential'] * self._attributes['endurance'] * self._attributes['toughness']) ** 0.5) / 4) / 1.5),
'awareness' : math.ceil( ( ( ( (self._attributes['luck']/5 + self._attributes['focus'] + self._attributes['willpower']/3) ** 1.5) + 1.25) / 5) * 10) / 10,
'sneaking' : math.ceil( ( ( (self._attributes['luck'] + self._attributes['focus']/2 + self._attributes['agility']/3 + 1) ** 0.75) * (self._attributes['focus']/2 + 1) / 4) * 10) / 10,
'dodging' : math.ceil( (50*(1 - 0.9**self._attributes['agility']) + 30*(1 - 0.9**self._attributes['willpower']) + 20*(1 - 0.9**self._attributes['luck']) ) * 10) / 10,
'shielding' : math.ceil( (self._attributes['toughness']/2 + self._attributes['willpower']/3 + self._attributes['strength']) * self._attributes['strength']/4),
'mPower' : math.ceil( ( ( (self._attributes['magic potential'] + self._attributes['strength']/2 + self._attributes['willpower']/5) * self._attributes['magic potential']/4) ** (1/3) ) * 10) / 10,
'mReserves' : math.ceil(self._attributes['magic potential'] + (self._attributes['magic potential'] * self._attributes['endurance'])**0.5 + (self._attributes['endurance']/2)**1.25),
'mSkill' : math.ceil( (self._attributes['magic potential'] + self._attributes['wisdom']/2 + (self._attributes['magic potential']*(self._attributes['wisdom'] + 1) ) ) ** 0.5),
'mConcentration' : math.ceil( (50*(1 - 0.9**self._attributes['magic potential']) + 30*(1 - 0.9**self._attributes['focus']) + 10*(1 - 0.9**self._attributes['willpower']) + 10*(1 - 0.9**self._attributes['luck']) ) * 10) / 10,
'looting' : math.ceil(0.9 * (1 - 0.8**self._attributes['luck'])/0.2 * 20) + 10,
'capacity' : math.ceil( ( (self._attributes['endurance']/3 + self._attributes['strength'] + 1) * (self._attributes['willpower']/4 + 1) ) + 9)
}
if reset:
#Starting stats
self.hp = self._stats['health']
self.sp = self._stats['stamina']
self.mp = self._stats['mReserves']
else:
self.hp = min(self.hp, self._stats['health'])
self.sp = min(self.sp, self._stats['stamina'])
self.mp = min(self.mp, self._stats['mReserves'])
def _levelUp(self,attrib,value=1):
self._attributes[attrib] +=value
self.recalc()
def inven(self):
if len(self._inven) > 0:
print(self.name + '\'s inventory:')
m = 0
for item in self._inven:
m += 1
if isinstance(self._inven[item], Bag):
print(str(m) + '/' + str(self._stats['capacity']) + '\t' + item + ':')
n = 0
for _item in self._inven[item]._inven:
n += 1
if type(self._inven[item]._inven[_item]) == list:
print('\t' + str(n) + '/' + str(self._inven[item].capacity) + '\t' + _item + ': ' + str(self._inven[item]._inven[_item][0]) + ' x ' + str(self._inven[item]._inven[_item][1]) )
else:
print('\t' + str(n) + '/' + str(self._inven[item].capacity) + '\t' + _item + ': ' + str(self._inven[item]._inven[_item]) )
elif type(self._inven[item]) == list:
print(str(m) + '/' + str(self._stats['capacity']) + '\t' + item + ': ' + str(self._inven[item][0]) + ' x ' + str(self._inven[item][1]) )
else:
print(str(m) + '/' + str(self._stats['capacity']) + '\t' + item + ': ' + str(self._inven[item]) )
else:
print(self.name + '\'s inventory is empty.')
#Items
class Item:
def __init__(self, name, desc=''):
self.name = name
self.desc = desc
def __str__(self):
returnStr = 'Item(\'' + self.name + '\''
if len(self.desc) > 0:
returnStr += ', desc=\'' + self.desc + '\''
returnStr += ')'
return returnStr
def __eq__(self, other):
return self.__dict__ == other.__dict__
#Weapons
class Weapon(Item):
def __init__(self, name, kind, dmgRange, minPower=0, mods={}):
self.name = name
self.kind = kind
self.dmgRange = dmgRange
self.minPower = minPower
#Currently unused
self.mods = mods
#Show weapon info
def show(self):
print(self.name)
print(self.kind)
#Differentiate between int/list
if type(self.dmgRange) == list:
print('Dmg: ' + str(self.dmgRange[0]) + '-' + str(self.dmgRange[1]) )
else:
print('Dmg: ' + str(self.dmgRange) )
if self.minPower > 0:
print('Minimum Power: ' + str(self.minPower) )
def __str__(self):
returnStr = 'Weapon(\'' + self.name + '\', \'' + self.kind + '\', ' + str(self.dmgRange)
if self.minPower > 0:
returnStr += ', minPower=' + str(self.minPower)
if len(self.mods) > 0:
returnStr += ', mods=' + str(self.mods)
returnStr += ')'
return returnStr
#Armour
class Armour(Item):
def __init__(self, name, place, defence=0, minPower=0, mods={}):
self.name = name
self.place = place
self.defence = defence
self.minPower = minPower
#Currently unused
self.mods = mods
#Show armour info
def show(self):
print(self.name)
print(self.place)
print('Defence: ' + str(self.defence) )
print('Minimum Power: ' + str(self.minPower) )
def __str__(self):
returnStr = 'Armour(\'' + self.name + '\', \'' + self.place + '\''
if self.defence > 0:
returnStr += ', defence=' + str(self.defence)
if self.minPower > 0:
returnStr += ', minPower=' + str(self.minPower)
if len(self.mods) > 0:
returnStr += ', mods=' + str(self.mods)
returnStr += ')'
return returnStr
class Bag(Item):
def __init__(self, name, capacity, inven={}):
self.name = name
self.capacity = capacity
self._inven = inven
def __str__(self):
returnStr = 'Bag(\'' + self.name + '\', ' + str(self.capacity)
if len(self._inven) > 0:
returnStr += ', inven={' + str(self._inven)
#Used for multiple items
m = 0
for item in self._inven:
if m > 0:
returnStr += ', '
returnStr += '\'' + item + '\':' + str(self._inven[item])
m += 1
returnStr += '}'
returnStr += ')'
return returnStr
def inven(self):
if len(self._inven) > 0:
print(self.name + ':')
m = 0
for item in self._inven:
m += 1
if type(self._inven[item]) == list:
print(str(m) + '/' + str(self.capacity) + '\t' + item + ': ' + str(self._inven[item][0]) + ' x ' + str(self._inven[item][1]) )
else:
print(str(m) + '/' + str(self.capacity) + '\t' + item + ': ' + str(self._inven[item]) )
else:
print(self.name + ' is empty.')
def add(self,items):
#Rejected items
rejects = {}
#Check if items is a dict
if type(items) == dict:
for item in items:
if len(self._inven) < self.capacity:
#Item variable
_item = items[item]
#Name editor
nameEdit = ''
#Re-iterate search algorithm until resolved
while True:
#Check if item is a list w/ an Item instance that is not a Bag
if type(_item) == list and isinstance(_item[1], Item) and not isinstance(_item[1],Bag):
#Check if item w/ same name is in inven
if (item + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[item + nameEdit]) == list and isinstance(self._inven[item + nameEdit][1], Item):
#Check if item and inven item are the same
if _item[1] == self._inven[item + nameEdit][1]:
self._inven[item + nameEdit][0] += _item[0]
break
else:
#Misfire, add *
nameEdit += '*'
#Check if inven item is an int
elif type(self._inven[_item[1].name + nameEdit]) == int:
#Misfire, add *
nameEdit += '*'
#Check if item and inven item are the same
elif item[1] == self._inven[item[1].name + nameEdit]:
self._inven[item + nameEdit] = [_item[0] + 1, _item[1] ]
break
else:
#Add new item
self._inven[item + nameEdit] = _item
break
#Check if item in an int
elif type(_item) == int:
#Check if item is in inven
if (item + nameEdit) in self._inven:
#Check if inven item is int
if type(self._inven[item + nameEdit]) == int:
self._inven[item + nameEdit] += _item
break
else:
#Misfire, add *
nameEdit += '*'
else:
#Add new item
self._inven[item + nameEdit] = _item
break
#Check if item is an Item instance that is not a Bag
elif isinstance(_item, Item) and not isinstance(_item,Bag):
#Check if item w/ same name is in inven
if (item + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[item + nameEdit]) == list and isinstance(self._inven[item + nameEdit][1], Item):
#Check if item and inven item are the same
if _item == self._inven[item + nameEdit][1]:
self._inven[item + nameEdit][0] += 1
break
else:
#Misfire, add *
nameEdit += '*'
#Check if inven item is Item instance and the same as item
elif isinstance(self._inven[item + nameEdit], Item) and self._inven[item + nameEdit] == _item:
self._inven[item + nameEdit] = [2, _item]
break
else:
#Misfire, add *
nameEdit += '*'
else:
#Add new item
self._inven[item + nameEdit] = _item
break
else:
print('Item type(?) not available: ' + str(type(_item) ) )
rejects[str(items)] = items
break
else:
rejects[item] = items[item]
#Check if items is a list w/ Item instance that is not a Bag
elif type(items) == list and isinstance(items[1], Item) and not isinstance(items[1],Bag):
#Name editor
nameEdit =''
#Item variable
_item = items[1]
while True:
#Check if item w/ same name is in inven
if (_item.name + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[_item.name + nameEdit]) == list and isinstance(self._inven[_item.name + nameEdit][1], Item):
#Check if item and inven item are the same
if _item[1] == self._inven[_item.name + nameEdit][1]:
self._inven[_item.name + nameEdit][0] += items[0]
break
else:
#Misfire, add *
nameEdit += '*'
#Check if item and inven item are the same
elif _item == self._inven[_item.name + nameEdit]:
self._inven[_item.name + nameEdit] = [items[0] + 1, _item]
break
else:
#Misfire, add *
nameEdit += '*'
elif len(self._inven) < self.capacity:
#Add new item
self._inven[_item.name + nameEdit] = items
break
else:
rejects[items[1].name] = items
break
#Check if items is an Item instance that is not a Bag
elif isinstance(items, Item) and not isinstance(items,Bag):
#Name editor
nameEdit = ''
#Re-iterate search algorithm until resolved
while True:
#Check if item w/ same name is in inven
if (items.name + nameEdit) in self._inven:
#Check if inven item is a list w/ in Item instance
if type(self._inven[items.name + nameEdit]) == list and isinstance(self._inven[items.name + nameEdit][1], Item):
#Check if item and inven item are the same
if items == self._inven[items.name + nameEdit][1]:
self._inven[items.name + nameEdit][0] += 1
break
else:
#Misfire, add *
nameEdit += '*'
#Check if inven item is Item instance and the same as item
elif isinstance(self._inven[items.name + nameEdit], Item) and self._inven[items.name + nameEdit] == items:
self._inven[items.name + nameEdit] = [2, items]
break
else:
#Misfire, add *
nameEdit += '*'
elif len(self._inven) < self.capacity:
#Add new item
self._inven[items.name + nameEdit] = items
break
else:
rejects[items.name] = items
break
else:
print('Items type(?) not available: ' + str(type(items) ) )
rejects[str(items)] = items
if len(rejects) > 0:
print(self.name + ' is too full, or cannot accept certain items. ' + str(len(rejects) ) + ' items were rejected.')
return rejects
#Skills
class Skill:
def __init__(self, name, effects, desc=''):
self.name = name
self.effects = effects
self.desc = desc
def useSkill(self, user, Target):
print(user.name + ' used ' + self.name + ' on ' + Target.name)
if type(self.effects) == list:
for effect in self.effects:
eval(effect)
else:
eval(self.effects)
def __str__(self):
returnStr = 'Skill(\'' + self.name + '\', '
if type(self.effects) == list:
returnStr = returnStr + '['
m = 0
for effect in self.effects:
if m > 0:
returnStr += ','
returnStr += '\'' + effect + '\''
m += 1
returnStr += ']'
return returnStr
#Effects
class Effects:
#Dmg target
def dealDmg(target, dmg):
print(target.name + ' received ' + str(dmg) + ' damage')
target.hp -= dmg
print(target.name + " " + str(target.hp) + "/" + str(target._stats['health']) )
print('')
#Heal target
def heal(target, health):
print(target.name + ' received ' + str(health) + ' health')
target.hp = min(target.hp + health, target._stats['health'])
print(target.name + " " + str(target.hp) + "/" + str(target._stats['health']) )
print('')
#Deal dmg/heal over x turns
class DealOverTime:
def __init__(self):
self.DOTeffects = []
#add DOT
def addDOT(self, target, dmg, turns):
self.DOTeffects.append([target, dmg, turns])
#Activate any/all stored DOTs
def cycleDOT(self, target=None):
for dot in self.DOTeffects:
#Check if target is in stored DOTs
if target == None or dot[0] == target:
#Check if turns remain
if dot[2] > 0:
#Differentiate between dmg/heal
if dot[1] > 0:
Effects.dealDmg(dot[0], dot[1])
elif dot[1] < 0:
Effects.heal(dot[0], -dot[1])
#Reduce turn counter
dot[2] -= 1
#Remove DOT w/ 0 remaining turns
if dot[2] == 0:
self.DOTeffects.remove(dot)
#Generate treasure
def getTreasure(size):
pass
#Initialize new DOT storage
DOT = DealOverTime()
#Test stuff
dummy = NPC("Training Dummy", tough=100)
dummy.show()
-
3\$\begingroup\$ maybe write a library for this program, and break this program into multiple modules... I have never realized 955 lines can be so hard to read for another person. \$\endgroup\$hamster on wheels– hamster on wheels2017年07月26日 03:52:31 +00:00Commented Jul 26, 2017 at 3:52
-
\$\begingroup\$ Those nested ifs with gazillion levels is a horror for readers. Break that into multiple functions please ... my head was spinning when I saw that. \$\endgroup\$hamster on wheels– hamster on wheels2017年07月26日 03:54:58 +00:00Commented Jul 26, 2017 at 3:54
-
1\$\begingroup\$ Separate calculation (math) and the interface (printing) might be a good idea. When the proof reader/translator tries to work on the text messages, it is not fun if they are all scattered over everywhere in the code. \$\endgroup\$hamster on wheels– hamster on wheels2017年07月26日 03:58:43 +00:00Commented Jul 26, 2017 at 3:58
-
\$\begingroup\$ @rxu Thanks for all these tips. Please compile them into a review, with some basic solutions, and I'll get right on them. \$\endgroup\$The Eye– The Eye2017年07月27日 00:30:29 +00:00Commented Jul 27, 2017 at 0:30
-
1\$\begingroup\$ With @hamsteronwheels point about a library I would probably put NPC in a file on its own to be imported and then leave the rest there \$\endgroup\$13ros27– 13ros272017年12月16日 17:24:31 +00:00Commented Dec 16, 2017 at 17:24
1 Answer 1
Sorry to be the person who does this (I always have this happen when someone reviews my code) but PEP8. The lines between the statements are good but please try and keep your line length under 80 characters. For instance, your init
line of NPC
is at least three times the recommended line length in PEP8 and later on in init
the sums reach even longer. I am not sure what to do for the initialisation apart from maybe have the values set in a few functions you call one after the other (although this seems unnecessary) however the sums should either be separated so that you do some sums on the variable then some more on the next line or just have some line breaks because it helps with readability no end.
Another thing to do with PEP8 is that it may help to add docstrings to the start of your classes and possibly functions as well just explaining briefly what it does (trust me, if you have nothing like that then you will come back to your code a year later and have no idea what the different bits do). It also makes later development a lot easier. Also, with most of your classes you have a comment just before them detailing what they do and it is more pythonesque to put them as the first thing in the class and it also means you can poll the class for it.
I can kind of understand why you have a commented out import tkinter
because you plan to add a GUI later but it just seems unnecessary at this stage.
Explore related questions
See similar questions with these tags.