from math import ceil ARMOR = 0 DAMAGE = 1 RANGE = 2 TYPES = (ARMOR, DAMAGE, RANGE) STATS = [# hp, dmg, range, cost (8, 2, 0, 1.00), # armor (6, 6, 1, 1.75), # damage (4, 4, 2, 2.50)] # range def getCostFromHP(army_hp): return sum(STATS[t][3] * (army_hp[t] / float(STATS[t][0])) for t in TYPES) def getDamage(att_hp, distance): """Compute total damage done by attacker.""" dmg = 0 for t in TYPES: units = ceil(att_hp[t] / float(STATS[t][0])) if STATS[t][2] >= distance: dmg += units * STATS[t][1] return dmg def applyDamage(def_hp, dmg): """Apply dmg to defender's units.""" for t in TYPES: if def_hp[t] >= dmg: def_hp[t] -= dmg break else: dmg -= def_hp[t] def_hp[t] = 0 def simulate(a_units, b_units): """ Simulates battle between two armys and returns the score. Accepts army in this format: [armored, damage, ranged] """ turn = 0 a_hp = [STATS[t][0] * a_units[t] for t in TYPES] b_hp = [STATS[t][0] * b_units[t] for t in TYPES] a_cost = sum(STATS[t][3] * a_units[t] for t in TYPES) b_cost = sum(STATS[t][3] * b_units[t] for t in TYPES) while any(a_hp) and any(b_hp): a_dmg = getDamage(a_hp, 2 - turn) b_dmg = getDamage(b_hp, 2 - turn) applyDamage(a_hp, b_dmg) applyDamage(b_hp, a_dmg) turn += 1 if any(b_hp): # if b won... return - getCostFromHP(b_hp) / float(b_cost) else: return getCostFromHP(a_hp) / float(a_cost)