Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
With zip(army_1, army_2) and remove_the_dead property in Army class solution in Clear category for Straight Fight by Phil15
#################### CHANGELOG ####################
# In Army class, new property remove_the_dead
# In Battle class, new staticmethod straight_fight
class Warrior:
"""Define a Warrior, and his general abilities."""
def __init__(self):
self.max_health = 50
self.health = self.max_health
self.attack = 5
@property
def is_alive(self) -> bool:
return self.health > 0
########################### Management of a hit ############################
def hit(self, other, half_damage=False):
"""self hit other (with half damage??), return taken damage by other."""
if self.is_alive:
damage = self.attack
if half_damage: damage //= 2
taken_damage = other.take_a_hit_of(damage)
self.use_vampirism(taken_damage)
return taken_damage
return 0
def take_a_hit_of(self, damage):
"""self take a hit of given damage, return taken damage."""
taken_damage = self.use_defense(damage)
self.health -= taken_damage
return taken_damage
######################## Second hit from a Lancer? #########################
def is_lancer_then_hit(self, other):
"""If self is a lancer, then he hits other with half damage."""
if isinstance(self, Lancer) and other:
self.hit(other, True)
########## Use special attributes: defense, vampirism, heal_power ##########
def use_defense(self, damage):
"""damage -= self.defense (if self has defense attribute)."""
if hasattr(self, 'defense'):
taken_damage = max(0, damage - self.defense)
else:
taken_damage = damage
return taken_damage
def use_vampirism(self, damage):
"""self.health += bonus_vampirism (if self has vampirism attribute)."""
if hasattr(self, 'vampirism'):
bonus_vampirism = int(damage * self.vampirism)
self.health = min(self.max_health, self.health + bonus_vampirism)
def heal(self, unit):
"""unit.health += self.heal_power (if self has heal_power attribute)."""
if hasattr(self, 'heal_power'):
unit.health = min(unit.max_health, unit.health + self.heal_power)
########################### Other types of warriors ############################
class Knight(Warrior):
"""Define a knight, it's a warrior with an increased attack of 7."""
def __init__(self):
self.max_health = 50
self.health = self.max_health
self.attack = 7
class Defender(Warrior):
"""Define a defender, it's a warrior with a defense parameter."""
def __init__(self):
self.max_health = 60
self.health = self.max_health
self.attack = 3
self.defense = 2
class Vampire(Warrior):
"""Define a vampire, capable of vampirism, a way to heal himself."""
def __init__(self):
self.max_health = 40
self.health = self.max_health
self.attack = 4
self.vampirism = 0.5
class Lancer(Warrior):
"""Define a lancer, who can hit two units at the same time, he's vicious!"""
def __init__(self):
self.max_health = 50
self.health = self.max_health
self.attack = 6
class Healer(Warrior):
"""Define a healer, who can heal a neighboring friendly unit when he kills."""
def __init__(self):
self.max_health = 60
self.health = self.max_health
self.attack = 0
self.heal_power = 2
############################## Fight of two units ##############################
def fight(unit_1, unit_2):
"""One-on-one duel"""
while unit_1.is_alive and unit_2.is_alive:
unit_1.hit(unit_2)
unit_2.hit(unit_1)
return unit_1.is_alive
############# An army is a list of warriors, with some properties ##############
class Army(list):
"""Army is a list of units."""
def add_units(self, type_unit, number_units):
"""Add an amount of units of a given type."""
self += [type_unit() for k in range(number_units)]
@property
def is_alive(self) -> bool:
"""Is there anyone in this army?"""
return self != [] # or bool(self)
@property
def first_warrior(self):
"""Return the first warrior of this army."""
return self[0]
@property
def second_warrior(self):
"""Is there a second warrior in this army? Return him."""
try:
return self[1]
except:
return None
@property
def remove_up_to_two_deads(self):
"""Second warrior and first warrior... Are they dead?"""
if self.second_warrior and not self.second_warrior.is_alive:
self.pop(1)
if not self.first_warrior.is_alive:
self.pop(0)
@property
def remove_the_dead(self):
"""Remove all dead warriors from this army."""
i = 0
while i < len(self):
if self[i].is_alive:
i += 1
else:
self.pop(i)
############################### EPIC BATTLES !!! ###############################
class Battle:
"""Define epic battles."""
@staticmethod
def fight(army_1, army_2) -> bool:
"""A fight IN LINE of two armies. Return 'army 1 is alive' boolean."""
while army_1.is_alive and army_2.is_alive:
# This is an adaptation of the fight function (one-on-one duel)
# to manage Lancers and Healers.
unit_1 = army_1.first_warrior
unit_2 = army_2.first_warrior
while unit_1.is_alive and unit_2.is_alive:
# hit/second warrior heal him/second hit if lancer/remove deads
# remark: heal from first hit, not from second hit too.
unit_1.hit(unit_2)
if army_1.second_warrior:
army_1.second_warrior.heal(unit_1)
unit_1.is_lancer_then_hit(army_2.second_warrior)
army_2.remove_up_to_two_deads
# Same thing in the other direction.
unit_2.hit(unit_1)
if army_2.second_warrior:
army_2.second_warrior.heal(unit_2)
unit_2.is_lancer_then_hit(army_1.second_warrior)
army_1.remove_up_to_two_deads
return army_1.is_alive
@staticmethod
def straight_fight(army_1, army_2) -> bool:
"""A fight between survivors of two armies,
without help of healer or lance.
Return 'army 1 is alive' boolean."""
while army_1.is_alive and army_2.is_alive:
for (unit_1, unit_2) in zip(army_1, army_2):
fight(unit_1, unit_2)
army_1.remove_the_dead
army_2.remove_the_dead
return army_1.is_alive
Aug. 10, 2018
Comments: