Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
iter and filter solution in Clear category for Straight Fight by ayubutrym
# Taken from mission The Healers
# Taken from mission The Lancers
class Warrior:
_MAX_HEALTH = 50
def __init__(self, health=_MAX_HEALTH, attack=5, defense=0):
self.health = health
self.attack = attack
self.defense = defense
self._behind = None
@property
def is_alive(self):
return self.health > 0
def damage_to(self, other):
damage = max(0, self.attack - other.defense)
if isinstance(self._behind, Healer):
self._behind.heal(self)
return damage
def set_behind(self, other):
self._behind = other
def clear_behind(self):
self._behind = None
def hit_by(self, other):
damage = other.damage_to(self)
self.health -= damage
if isinstance(other, Lancer) and self._behind is not None:
self._behind.health -= max(0, 0.5*damage - self._behind.defense)
return self
class Knight(Warrior):
def __init__(self):
super().__init__(attack=7)
class Defender(Warrior):
_MAX_HEALTH = 60
def __init__(self):
super().__init__(health=self._MAX_HEALTH, attack=3, defense=2)
class Vampire(Warrior):
_MAX_HEALTH = 40
def __init__(self):
super().__init__(health=self._MAX_HEALTH, attack=4)
self.vampirism = 0.5
def damage_to(self, other):
damage = super().damage_to(other)
self.health += self.vampirism * damage
return damage
class Lancer(Warrior):
def __init__(self):
super().__init__(attack=6)
class Healer(Warrior):
_MAX_HEALTH = 60
def __init__(self):
super().__init__(health=self._MAX_HEALTH, attack=0)
def heal(self, patient):
patient.health = min(patient.health + 2, patient._MAX_HEALTH)
def fight(unit1, unit2):
attacker, defender = unit1, unit2
while attacker.is_alive:
attacker, defender = defender.hit_by(attacker), attacker
return unit1.is_alive
class Army:
def __init__(self):
self._troops = []
def __iter__(self):
return filter(lambda w: w.is_alive, self._troops)
def add_units(self, unit_type, number):
for _ in range(number):
self._troops.append(unit_type())
def remove_dead(self):
if any(not warrior.is_alive for warrior in self._troops):
self._troops = [*self]
return self
def __bool__(self):
return any(self)
def get_fighter(self):
while self._troops and not self._troops[-1].is_alive:
self._troops.pop() # remove dead from the end
return self._troops[-1] if self._troops else None
def get_second_fighter(self):
i = len(self._troops) - 2
while i >= 0:
if self._troops[i].is_alive:
return self._troops[i]
else:
i -= 1
return None
class Battle:
def fight(self, attacker_army, defender_army):
while attacker_army:
attacker = attacker_army.get_fighter()
defender = defender_army.get_fighter()
if defender is None:
return True
if isinstance(attacker, Lancer):
defender.set_behind(defender_army.get_second_fighter())
if isinstance(defender, Lancer):
attacker.set_behind(attacker_army.get_second_fighter())
fight(attacker, defender)
attacker.clear_behind()
defender.clear_behind()
return False
def straight_fight(self, army1, army2):
if not army2: return True
if not army1: return False
for fighter1, fighter2 in zip(army1, army2):
fight(fighter1, fighter2)
return self.straight_fight(army1.remove_dead(), army2.remove_dead())
if __name__ == '__main__':
#fight tests
chuck = Warrior()
bruce = Warrior()
carl = Knight()
dave = Warrior()
mark = Warrior()
bob = Defender()
mike = Knight()
rog = Warrior()
lancelot = Defender()
eric = Vampire()
adam = Vampire()
richard = Defender()
ogre = Warrior()
freelancer = Lancer()
vampire = Vampire()
priest = Healer()
assert fight(chuck, bruce) == True
assert fight(dave, carl) == False
assert chuck.is_alive == True
assert bruce.is_alive == False
assert carl.is_alive == True
assert dave.is_alive == False
assert fight(carl, mark) == False
assert carl.is_alive == False
assert fight(bob, mike) == False
assert fight(lancelot, rog) == True
assert fight(eric, richard) == False
assert fight(ogre, adam) == True
assert fight(freelancer, vampire) == True
assert freelancer.is_alive == True
assert freelancer.health == 14
priest.heal(freelancer)
assert freelancer.health == 16
#battle tests
my_army = Army()
my_army.add_units(Defender, 2)
my_army.add_units(Healer, 1)
my_army.add_units(Vampire, 2)
my_army.add_units(Lancer, 2)
my_army.add_units(Healer, 1)
my_army.add_units(Warrior, 1)
enemy_army = Army()
enemy_army.add_units(Warrior, 2)
enemy_army.add_units(Lancer, 4)
enemy_army.add_units(Healer, 1)
enemy_army.add_units(Defender, 2)
enemy_army.add_units(Vampire, 3)
enemy_army.add_units(Healer, 1)
army_3 = Army()
army_3.add_units(Warrior, 1)
army_3.add_units(Lancer, 1)
army_3.add_units(Healer, 1)
army_3.add_units(Defender, 2)
army_4 = Army()
army_4.add_units(Vampire, 3)
army_4.add_units(Warrior, 1)
army_4.add_units(Healer, 1)
army_4.add_units(Lancer, 2)
army_5 = Army()
army_5.add_units(Warrior, 10)
army_6 = Army()
army_6.add_units(Warrior, 6)
army_6.add_units(Lancer, 5)
battle = Battle()
assert battle.fight(my_army, enemy_army) == False
assert battle.fight(army_3, army_4) == True
assert battle.straight_fight(army_5, army_6) == False
print("Coding complete? Let's try tests!")
July 31, 2019
Comments: