Alright so I have a dict with keys that point to an array of 5 values. These 5 values I pass to a class to sort out and feed me info etc.
Main
So, this works, but my querstion is is there a better way of exytracting the array to pass to the 'weapon' class, or do i just need to 'wepstats[0],wepstats[1]' etc? Or is there a better way of going about this? I'm all ears as Im only learning to do this stuff.
class Main():
def weaponDamage(self):
#print 15 * 2.22
wdb = WeaponDB()
wepstats = wdb.getWeaponStats('Sword')
wep = Weapon(wepstats[0],wepstats[1],wepstats[2],wepstats[3],wepstats[4])
wep2 = Weapon("Sword", 5, 55, 1.55, 2.1)
print wep
print wep2
s = sayThings()
greet = s.Say()
self.crit = wep.getDamageCrtRND()
self.scrit = wep.getDamageSCrtRND()
self.avg = wep.getDamageAvg()
self.high = wep.getDamageHigh()
self.low = wep.getDamageLow()
self.mod = wep.getDamageMod()
self.norm = wep.getDamageNrmRND()
self.name = wep.getWeaponName()
print greet
print "-----------"
print "Name: " + self.name
print "-----------"
print "High: %s" % self.high
print "Low : %s" % self.low
print "Avg : %s" % self.avg
print "Crit: %s" % self.crit
print "--------------------"
Dict
EDIT: Should I be making a DB of items in this manner in the first place? Is there a more logic method of doing this?
class WeaponDB():
"""Here be thine weapons of thy holy might"""
def __init__(self):
self.script = {
'None': "Error: No Weapon stats to get selected.",
'Sword': ("Sword", 5, 55, 1.55, 2.1),
}
def getWeaponStats(self, key = 'None'):
try:
return self.script[key]
except KeyError:
return self.script['None']
Class useing the values as parameters
class Weapon():
def __init__(self, name = "Stick", high = 1, low = 0, critMod = 1, scritMod = 2):
self.rng = randNum()
self.name = name
self.high = high
self.low = low
self.critMod = critMod
self.scritMod = scritMod
def getWeaponName(self):
return self.name
def getDamageHigh(self):
return self.high
def getDamageLow(self):
return self.low
def getDamageMod(self):
return self.critMod
def getDamageSMod(self):
return self.scritMod
etc...
If I understand well you can do something like this:
class Weapon:
def __init__( self, name = 'Stick', high = 1, low = 0 ):
self.name = name
self.high = high
self.low = low
wepstats = ( 'Sword', 5, 55 )
sword = Weapon( *wepstats )
Then if you check your attributes you get:
>>> sword.name
'Sword'
>>> sword.high
5
>>> sword.low
55
Using *wepstats you pass the entire tuple as arguments for your constructor.
Related
I've spent an hour or two collectively now trying to figure this problem out but I'm not getting any results. In my program when a defending animal is "killed" it should be deleted from it's registry, but no matter what I do I can't seem to get that to happen. In this instance if I were to initiate a hunter and a buffalo then attack() the buffalo with the hunter the buffalo should be killed and removed from it's classes registry but I can't get python to select that specific buffalo from the registry.
Any help is appreciated.
class IterRegistry(type):
def __iter__(cls):
return iter(cls._registry)
class Buffalo(object):
__metaclass__ = IterRegistry
_registry = []
hp = 1
price = 150
attacks = 0
regeneration = 2
def __init__(self, name):
self._registry.append(self)
self.name = name
def createBuffalo():
for i in range(len(Buffalo._registry),len(Buffalo._registry)+1):
varname = ("b" + str(i))
globals()[varname] = Buffalo("b" + str(i))
class Wolf:
__metaclass__ = IterRegistry
_registry = []
hp = 1
price = 0
attacks = 2
regeneration = 1.5
def __init__(self, name):
self._registry.append(self)
self.name = name
def createWolf():
for i in range(len(Wolf._registry),len(Wolf._registry)+1):
varname = ("w" + str(i))
globals()[varname] = Wolf("w" + str(i))
class Hunter:
__metaclass__ = IterRegistry
_registry = []
hp = 2
price = 0
attacks = 1
regeneration = 0
balance = 0
def __init__(self, name):
self._registry.append(self)
self.name = name
def createHunter():
for i in range(len(Hunter._registry),len(Hunter._registry)+1):
varname = ("h" + str(i))
globals()[varname] = Hunter("h" + str(i))
def attack(attacker, target):
if attacker.attacks >= 1:
target.hp -= 1
if target.hp == 0:
if type(attacker) == Hunter:
attacker.balance += 150
print(target)
if type(target) == Wolf:
del Wolf._registry[[n for n in Wolf._registry if n == target]]
if type(target) == Hunter:
del Hunter._registry[[n for n in Hunter._registry if n == target]]
if type(target) == Buffalo:
del Buffalo._registry[[n for n in Hunter._registry if n == target]]
One more note, the reason I have double brackets is because it was incorrect syntax with single brackets but the syntax was fine with doubles.
If you need any more code, ask in a comment below (I have not included all of it but it should be enough).
The issue you're trying to solve is caused by trying to use a list as an index to be removed from your list
[n for n in Wolf._registry if n == target]
All you're trying to get out of this list comprehension is the target, so just use that.
Wolf._registry.remove(target)
Is there a way I could implement user input to create a new entry in this class I defined?
class Pulsar:
'Collective base of all Pulsars'
pulsarCount = 0
def __init__(self, name, distance):
self.name = name
self.distance = distance
Pulsar.pulsarCount += 1
def displayCount(self):
print( "Total Pulsars %d" % Pulsar.pulsarCount)
def displayPulsar(self):
print( "Name : ", self.name, ", Distance: ", self.distance)
"This creates the first object"
pulsar1 = Pulsar("B1944+17", "979 Lightyears")
"This creates the second pulsar in the class"
pulsar2 = Pulsar("J2129-5721", "1305 Lightyears")
pulsar1.displayPulsar()
pulsar2.displayPulsar()
print( "Total Pulsars %d" % Pulsar.pulsarCount)
I'm hoping for the user to be able to input their own name/distance and have it append to my current defined variables.
Depending on what you're doing with the Pulsar objects, a class may be overkill.
class Pulsar:
def __repr__(self) -> str:
return f'Pulsar({self.name!r}, {self.distance!r})'
def __init__(self, distance: str, name: str) -> None:
self.name: str = name
self.distance: str = distance
num_pulsars_input = int(input('How many pulsars do you wish to create: '))
pulsar_list = []
for _ in range(num_pulsars_input):
curr_p_name = input('Enter pulsar name: ')
curr_p_dist = input('Enter pulsar distance: ')
curr_p = Pulsar(curr_p_name, curr_p_dist)
pulsar_list.append(curr_p)
print(pulsar_list)
class Pulsar:
'Collective base of all Pulsars'
pulsarCount = 0
def __init__(self, name, distance):
self.name = name
self.distance = distance
Pulsar.pulsarCount += 1
def displayCount(self):
print( "Total Pulsars %d" % Pulsar.pulsarCount)
def displayPulsar(self):
print( "Name : ", self.name, ", Distance: ", self.distance)
"This creates the first object"
pulsar1 = Pulsar("B1944+17", "979 Lightyears")
"This creates the second pulsar in the class"
pulsar2 = Pulsar("J2129-5721", "1305 Lightyears")
pulsar1.displayPulsar()
pulsar2.displayPulsar()
print( "Total Pulsars %d" % Pulsar.pulsarCount)
# New code
users_name = input('Your name: ')
distance = input('The distance: ')
pulsar1.name = users_name
pulsar1.distance = distance
# Then you can wrap this in a function if you want
I am in designing one "jigsaw puzzle" like tool to manage different water pipe like parts combination for fun.
I have different single parts type with different purpose(cooler, heater, purifier...)
Those parts with different interfaces size can be connected with each other (1/4 inch. 1/6 inch ....)
I want those parts can be stored in database and can be combined into a total new parts combination(randomly or purposely), but still can be considering as a function-able part.
Here is the initial thinking
class MetaInfo():
def __init__(self, name, intype,outtype,shape,serialno):
this.name = name
this.intype = intype
this.outtype = outtype
this.shape = shape
this.sn = serialno
def parts():
def __init__(self, meta):
this.meta = meta
def linkwith(self, part):
if part.meta.shape == this.meta.shape:
# make it simple, logical here is just same shape can be connected each other
return ??? # a new parts combination
else:
raise Error
m1 = MetaInfo("cooler", "hotwater", "coldwater", "1/4 inch round", "SN:11111" )
m2 = MetaInfo("heater", "coldwater", "hotwater", "1/4 inch round", "SN:22222" )
m3 = MetaInfo("purifier", "coldwater", "hotwater", "1/6 inch round", "SN:33333" )
a = parts(m1)
b = parts(m2)
c = parts(m3)
Here is what I need your help:
how to save m1, m2, m3 as a list which can persistent in a human readable database, next time only change that database itself I can add meta?
how to chain different parts as a new combination? Such as
e = a.linkwith(b)
d = c.linkwith(a)
and store it in that database as well?
can I make a long chain, make a new parts instance , such as
f = c.linkwith(a,b,d,e)
and findout easily which part is incapable to link in this chain, here part c with different size?
Many thanks.
I got bored. It's very rough but it works. If you take this far enough, you will want to use a database; but I understand wanting to use a human readable format.
from copy import copy
import csv
class Part_Base(object):
pass
class MultiPart_Base(list):
pass
class part_meta(type):
part_names = {}
parts = []
def __init__(cls, cls_name, cls_bases, cls_dict):
super(part_meta, cls).__init__(cls_name, cls_bases, cls_dict)
if(not Part_Base in cls_bases):
part_meta.part_names[cls_name] = cls
def __call__(self, *args, **kwargs):
name = kwargs.get("name", "")
if(part_meta.part_names.has_key(name) and not (self is part_meta.part_names[name])):
obj = part_meta.part_names[name].__call__(*args, **kwargs)
else:
obj = None
if(not part_meta.part_names.has_key(self.__name__)):
new_class = part_meta(name, (Generic_Part,), {})
globals()[name] = new_class
obj = new_class(*args, **kwargs)
else:
obj = super(part_meta, self).__call__(*args, **kwargs)
if not obj in part_meta.parts:
part_meta.parts.append(obj)
return obj
#classmethod
def save(cls):
all_fields = list(reduce(lambda x, y: x | set(y.fields), cls.parts, set([])))
with open("parts.csv", "w") as file_h:
writer = csv.DictWriter\
(
file_h,
all_fields,
restval = "",
extrasaction = "ignore",
dialect = "excel",
lineterminator = "\n",
)
writer.writeheader()
for part in cls.parts:
writer.writerow({field : getattr(part, field) for field in part.fields})
#classmethod
def load(cls):
with open("parts.csv", "r") as file_h:
reader = csv.DictReader(file_h)
for row in reader:
Part(**row)
class Part(Part_Base):
__metaclass__ = part_meta
fields = []
def __init__(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value)
self.fields += kwargs.keys()
def __repr__(self):
return "<%s>" % self.description
#property
def description(self):
return "%s: %s %s %s %s" % (self.name, self.intype, self.outtype, self.shape, self.serialno)
def linkwith(self, *parts):
return Generic_MultiPart(self, *parts)
class Generic_Part(Part):
def __init__(self, **kwargs):
kwargs["name"] = self.__class__.__name__
super(Generic_Part, self).__init__(**kwargs)
class Generic_MultiPart(MultiPart_Base):
def __init__(self, *parts):
super(Generic_MultiPart, self).__init__()
if len(parts) >= 2:
self.shape = parts[0].shape
self.linkwith(*parts)
else:
raise ValueError("Not enough parts")
def __repr__(self):
return "<MultiPart: %s>" % super(Generic_MultiPart, self).__repr__()
def linkwith(self, *parts):
for part in parts:
if part.shape == self.shape:
if isinstance(part, Part):
self.append(part)
elif isinstance(part, MultiPart_Base):
self.extend(part)
else:
raise ValueError("Incompatible parts")
return self
class cooler(Generic_Part):
intype = "hotwater"
outtype = "coldwater"
fields = ["intype", "outtype"]
class heater(Generic_Part):
intype = "coldwater"
outtype = "hotwater"
fields = ["intype", "outtype"]
def make_some_parts():
some_parts = \
[
# This is actually a cooler object
# The metaclass uses the cooler class from above
# to create the object
Part
(
name = "cooler",
shape = "1/4 inch round",
serialno = "SN:11111"
),
# Using the heater class directly
heater
(
shape = "1/4 inch round",
serialno = "SN:22222"
),
Part
(
name = "purifier",
intype = "coldwater",
outtype = "hotwater",
shape = "1/6 inch round",
serialno = "SN:33333"
),
Part
(
name = "carbon_filter",
intype = "coldwater",
outtype = "coldwater",
shape = "1/4 inch round",
serialno = "SN:33333"
)
]
useless_part = some_parts[0].linkwith(some_parts[1])
print useless_part
filter_part = copy(useless_part).linkwith(some_parts[3])
print filter_part
part_meta.save()
def load_some_parts():
part_meta.load()
print part_meta.parts
You can manually edit parts.csv (in Excel or other) and it will make the parts described.
The save/restore functionality hasn't been extended to MultiParts; you can do that.
Writing code in Python for an Astar program to find the shortest path between cities. Getting the above error, and I'm at a complete loss. Pulling between a few .py files, here are the relevant sections:
from asdriver.py - added full asdriver
import adata # Map data
import astar # A* class
import sys
# Default start, goal cities
defaultcities = ('Yakima, WA', 'Tampa, FL')
def printnode(n):
print n.toString()
adata.input()
startcity = raw_input("Start city [{0}]: ".format(defaultcities[0])).strip()
if startcity == '': startcity = defaultcities[0]
if startcity not in adata.cities:
print "City not recognized"
sys.exit(0)
goalcity = raw_input("Goal city [{0}]: ".format(defaultcities[1])).strip()
if goalcity == '': goalcity = defaultcities[1]
if goalcity not in adata.cities:
print "City not recognized"
sys.exit(0)
dbg = raw_input("Debug Options: [none]").strip()
findpath = astar.AS(startcity, goalcity, printnode)
ans = findpath.astar_run(printnode, dbg)
if not ans:
print "No answer"
else:
print "Final Path:"
print ans.toString()
From astar.py
import adata
class AS:
def __init__(self, startcity, goalcity, tracefunc):
self.startcity = startcity
self.goalcity = goalcity
self.tracefunc = tracefunc
self.openlist = [Node([startcity])]
self.closedlist = []
def heuristic(self, printnode, start, end):
raise NotImplementedError
def astar_run(self, startcity, endcity, dbg = ""):
while self.openlist:
citystep = min(self.openlist, key = lambda o:o.g + o.h)
if citystep == self.goalcity:
path = []
while citystep.parent:
path.append(citystep)
citystep = citystep.parent
path.append(citystep)
return path[::-1]
self.openlist.remove(citystep)
self.closedlist.append(citystep)
for printnode in self.openlist: #was self.tracefunc
if printnode in self.closedset:
continue
elif printnode in self.openset:
newG = citystep.g + citystep.cost(printnode)
if printnode.g > newG:
printnode.g = newG
printnode.parent = citystep
else:
printnode.g = citystep.g + citystep.cost(printnode)
printnode.h = self.heuristic(printnode, start, end)
printnode.parent = citystep
self.openset.add(printnode)
return self
class Node:
def __init__(self, path=[], f=0, g=0, h=0):
self.path = path[:]
self.f = f
self.g = g
self.h = h
self.parent = None
def toString(self):
s = 'f=%d g=%d h=%d ' % (self.f, self.g, self.h)
for city in self.path:
s = s + ' ' + city
return s
def cost(self):
raise NotImplementedError
'
Complete beginner, so any help would be appreciated.
Thanks in advance!!!
Your def astar_run() method returns self (see last line of your method), or it returns a list by slicing the path[::-1], neither has a toString() method so you are getting this exception. If you want to print the representation of your class then it is normal to declare this method __repr__() and then you can just print ans. If you want to be able to convert to a string then the method is usually called __str__().
What do you expect to be return from astar_run()? It is usually poor practice to return two different types from the same function.
I'm trying to have a class (dprObject) that is a container for several dprVariables
each variable has a list with integers (for now)
but when I change something to one variable, it changes to all the other variables
in this case, the output I get is
score: 5, 6, 3, 4,
position: 5, 6, 3, 4,
but I want to see
score: 5, 6,
position: 3, 4,
#!/usr/bin/python3
import pprint
def main():
d = dprObject() #new dpr object
score = dprVariable(d, "score") #new dpr variable
score.set(5) #set value
score.set(6)
position = dprVariable(d, "position")
position.set(3)
position.set(4)
print(d)
print("done")
class dprObject:
var = []
t = 0
def __init__(self):
pass
def __str__(self):
toReturn = ""
for v in self.var:
toReturn += v.toString()
return toReturn
def tick(self):
self.t += 1
def addVariable(self,v):
self.var.append(v)
class dprVariable:
name = ""
value = None
val = []
def __init__(self,d,name):
self.name = name
d.addVariable(self)
def __str__(self):
return self.toString()
def toString(self):
toReturn = self.name + ": "
for v in self.val:
toReturn += str(v) + ", "
return toReturn
def set (self, value):
self.value = value
self.val.append(value)
#class DprValue:
if __name__ == "__main__":
main()
any help would be appreciated
thanks
This code:
class dprVariable:
...
val = []
makes val a class variable, shared between all instances of dprVariable. To have one val per instance, you need to do this:
class dprVariable:
def __init__(self, ...):
self.val = []
(dprObject has the same problem.)