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)