def sievea(function): for unit in attack.availunits: eval(function + '(unit)') def sieved(function): for unit in defend.availunits: eval(function + '(unit)') def sieveaoverd(function): for aunit in attack.availunits: for dunit in defend.availunits: eval(function + '(aunit,dunit)') def sievedovera(function): for dunit in defend.availunits: for aunit in attack.availunits: eval(function + '(dunit,aunit)') class defenses: def __init__(self): self.trap = 0 class forcesetup: def __init__(self,archlvl,hbr,comp,miltrad,ironw,med,heroatt,amt): self.archlvl = archlvl self.hbr = hbr self.comp = comp self.miltrad = miltrad self.ironw = ironw self.med = med self.heroatt = heroatt self.amt = amt self.workers = {'amt':amt[0],'life':100,'attack':5,'defense':10,'speed':180,'range':10,'name':"worker",'type':"infantry"} self.warriors = {'amt':amt[1],'life':200,'attack':50,'defense':50,'speed':200,'range':20,'name':"warrior",'type':"infantry"} self.scouts = {'amt':amt[2],'life':100,'attack':20,'defense':20,'speed':3000,'range':20,'name':"scout",'type':"infantry"} self.pikemen = {'amt':amt[3],'life':300,'attack':150,'defense':150,'speed':300,'range':50,'name':"pikeman",'type':"infantry"} self.swordsmen = {'amt':amt[4],'life':350,'attack':100,'defense':250,'speed':275,'range':30,'name':"swordsman",'type':"infantry"} self.archers = {'amt':amt[5],'life':250,'attack':120,'defense':50,'speed':250,'range':1200,'name':"archer",'type':"infantry"} self.cavalry = {'amt':amt[6],'life':500,'attack':250,'defense':180,'speed':1000,'range':100,'name':"cavalry",'type':"cavalry"} self.cataphracts = {'amt':amt[7],'life':1000,'attack':350,'defense':350,'speed':750,'range':80,'name':"cataphract",'type':"cavalry"} self.transporters = {'amt':amt[8],'life':700,'attack':10,'defense':60,'speed':150,'range':10,'name':"transporter",'type':"machine"} self.ballistae = {'amt':amt[9],'life':320,'attack':450,'defense':160,'speed':100,'range':1400,'name':"ballista",'type':"machine"} self.batteringrams = {'amt':amt[10],'life':5000,'attack':250,'defense':160,'speed':120,'range':600,'name':"batteringram",'type':"machine"} self.catapults = {'amt':amt[11],'life':480,'attack':600,'defense':200,'speed':80,'range':1500,'name':"catapult",'type':"machine"} self.archertowers = {'amt':amt[12],'life':2000,'attack':300,'defense':360,'speed':0.0000000001,'range':1300,'name':"archertower",'type':"fortification"} self.availunits = [self.workers, self.warriors, self.scouts, self.pikemen, self.swordsmen, self.archers, self.cavalry, self.cataphracts, self.transporters, self.ballistae, self.batteringrams, self.catapults, self.archertowers] def nonzero(self): if self.availunits.__contains__(self.workers): self.availunits.remove(self.workers) if self.warriors['amt'] == 0 and self.availunits.__contains__(self.warriors): self.availunits.remove(self.warriors) if self.availunits.__contains__(self.scouts): self.availunits.remove(self.scouts) if self.pikemen['amt'] == 0 and self.availunits.__contains__(self.pikemen): self.availunits.remove(self.pikemen) if self.swordsmen['amt'] == 0 and self.availunits.__contains__(self.swordsmen): self.availunits.remove(self.swordsmen) if self.archers['amt'] == 0 and self.availunits.__contains__(self.archers): self.availunits.remove(self.archers) if self.cavalry['amt'] == 0 and self.availunits.__contains__(self.cavalry): self.availunits.remove(self.cavalry) if self.cataphracts['amt'] == 0 and self.availunits.__contains__(self.cataphracts): self.availunits.remove(self.cataphracts) if self.availunits.__contains__(self.transporters): self.availunits.remove(self.transporters) if self.ballistae['amt'] == 0 and self.availunits.__contains__(self.ballistae): self.availunits.remove(self.ballistae) if self.batteringrams['amt'] == 0 and self.availunits.__contains__(self.batteringrams): self.availunits.remove(self.batteringrams) if self.catapults['amt'] == 0 and self.availunits.__contains__(self.catapults): self.availunits.remove(self.catapults) if self.archertowers['amt'] == 0 and self.availunits.__contains__(self.archertowers): self.availunits.remove(self.archertowers) def modify(self,unit): #REAL NUMBER ASSUMPTION!!!! if unit['range'] >= 1000: unit['range'] = unit['range'] * (1 + .05 * self.archlvl) unit['defense'] *= (1 + .05 * self.ironw) unit['attack'] *= (1 + .05 * self.miltrad + .01 * self.heroatt) unit['life'] *= (1 + .05 * self.med) if unit['type'] == "infantry": unit['speed'] = unit['speed'] * (1 + .10 * self.comp) elif unit['type'] == "cavalry" or unit['type'] == "machine": unit['speed'] = unit['speed'] * (1 + .05 * self.hbr) def heldback(self): if (not self.availunits and self.scouts['amt']) or (not self.availunits and self.transporters['amt']) or (not self.availunits and self.workers['amt']): if self.scouts['amt']: self.availunits.append(self.scouts) if self.transporters['amt']: self.availunits.append(self.transporters) if self.workers['amt']: self.availunits.append(self.workers) class initpos: def __init__(self): self.longestrange = 0 def calcposs(self): if not defense.trap: sievea('ip.attacklongestrange') sieved('ip.defendlongestrange') sievea('ip.aposs') sieved('ip.dposs') else: self.longestrange = 5000 sievea('ip.aposs') sieved('ip.dposs') def attacklongestrange(self,unit): if unit['range'] > self.longestrange: self.longestrange = unit['range'] def defendlongestrange(self,unit): if unit['range'] > self.longestrange: self.longestrange = unit['range'] def aposs(self,unit): unit['poss'] = self.longestrange def dposs(self,unit): unit['poss'] = 0 class targeting: #test 1k arch vs. 1 ballista. expected rounds = 2 #test 1k arch vs. 1 cavalry & 1 ballista. expected rounds = 3 #test 1k arch vs. 1 catapult. expected rounds = 3 #test 1k arch vs. 500 ballistae & 10 catapult. expected result: catapults untouched. rounds unknown. #test 1k arch vs. 10 ballistae & 200 catapults. expected result: ballistae untouched. rounds unknown. #test 1k arch vs. 5k warriors & 200 arch. expected result, attack threating units(i.e. archers) first. rounds unknown. def reset(self,unit): unit['target'] = 0 unit['dead'] = 0 unit['tempspeed'] = unit['speed'] def target(self,unit,oppunit): if unit['range'] < abs(unit['poss'] - oppunit['poss']): pass else: oppvalue = (abs(unit['poss'] - oppunit['poss']) - oppunit['range']) / oppunit['speed'] if unit['target']: curoppvalue = (abs(unit['poss'] - unit['target']['poss']) - unit['target']['range']) / unit['target']['speed'] if oppvalue < curoppvalue: unit['target'] = oppunit else: unit['target'] = oppunit class battles: def combat(self,unit): if unit['target']: oppunit = unit['target'] rangemod = 1 if (unit['range'] / 2 < abs(unit['poss'] - oppunit['poss'])) and unit['range'] >= 1000: rangemod = .5 elif (abs(unit['poss'] - oppunit['poss']) == 0) and unit['range'] >= 1000: rangemod = .25 else: rangemod = 1 modifier = 1 if unit['name'] == "worker": modifier = .96 elif unit['name'] == "scout": modifier = .97 elif unit['name'] == "pikeman" and oppunit['name'] == "cavalry": modifier = 1.8 elif unit['name'] == "pikeman" and oppunit['name'] == "cataphract": modifier = 1.8 elif unit['name'] == "swordsman" and oppunit['name'] == "pikeman": modifier = 1.1 elif unit['name'] == "cavalry" and oppunit['name'] == "archer": modifier = 1.2 elif unit['name'] == "cataphract" and oppunit['name'] == "archer": modifier = 1.2 else: modifier = 1 oppunit['dead'] = int((unit['amt'] * unit['attack'] * modifier * rangemod * (1 - oppunit['defense']/1000)) / oppunit['life']) + 1 + oppunit['dead'] def deaths(self,unit): if unit['dead'] > 0: unit['amt'] = unit['amt'] - unit['dead'] if unit['amt'] < 0: unit['amt'] = 0 class movements: def attackmoving(self,unit,oppunit): if unit['target'] == 0 and unit['amt'] > 0: distance = abs(unit['poss'] - oppunit['poss']) if distance < unit['speed'] and unit['tempspeed'] > distance: unit['tempspeed'] = distance def defendmoving(self,unit,oppunit): if unit['target'] == 0 and unit['amt'] > 0: distance = abs(unit['poss'] - oppunit['poss']) if unit['tempspeed'] > distance: unit['tempspeed'] = distance def attmove(self,unit): if unit['target'] == 0 and unit['amt'] > 0: unit['poss'] = unit['poss'] - unit['tempspeed'] def defmove(self,unit): if unit['target'] == 0 and unit['amt'] > 0: unit['poss'] = unit['poss'] + unit['tempspeed'] class resolutions: def resolve(self,attack,defend): attack.nonzero() defend.nonzero() attack.heldback() defend.heldback() def setup(skills,amt): fs = forcesetup(skills[0],skills[1],skills[2],skills[3],skills[4],skills[5],skills[6],amt) return fs def simulation(askills,aamt,dskills,damt): global attack global defend global defense global ip global tar global battle global movement global resolution attack = setup(askills,aamt) defend = setup(dskills,damt) defense = defenses() ip = initpos() tar = targeting() battle = battles() movement = movements() resolution = resolutions() sievea('attack.modify') sieved('defend.modify') ip.calcposs() resolution.resolve(attack,defend) rounds = 0 while rounds < 100 and attack.availunits and defend.availunits: sievea('tar.reset') sieved('tar.reset') sieveaoverd('tar.target') sievedovera('tar.target') sievea('battle.combat') sieved('battle.combat') sievea('battle.deaths') sieved('battle.deaths') sieveaoverd('movement.attackmoving') sievea('movement.attmove') sievedovera('movement.defendmoving') sieved('movement.defmove') resolution.resolve(attack,defend) rounds += 1 remainattack = [attack.workers['amt'], attack.warriors['amt'], attack.scouts['amt'], attack.pikemen['amt'], attack.swordsmen['amt'], attack.archers['amt'], attack.cavalry['amt'], attack.cataphracts['amt'], attack.transporters['amt'], attack.ballistae['amt'], attack.batteringrams['amt'], attack.catapults['amt']] remaindefend = [defend.workers['amt'], defend.warriors['amt'], defend.scouts['amt'], defend.pikemen['amt'], defend.swordsmen['amt'], defend.archers['amt'], defend.cavalry['amt'], defend.cataphracts['amt'], defend.transporters['amt'], defend.ballistae['amt'], defend.batteringrams['amt'], defend.catapults['amt'], defend.archertowers['amt']] remaining = [remainattack,remaindefend,rounds] return remaining