Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Common fight(), specialized hit() and wounded() solution in Clear category for The Lancers by kkkkk
class Warrior:
"""Base class for fighting unit."""
def __init__(self):
self.health = 50
self.attack = 5
self.is_alive = True
self.next = None
def fight(self, opponent):
"""Return status of fighter after fight to death."""
while self.is_alive and opponent.is_alive:
self.hit(opponent)
if opponent.is_alive:
opponent.hit(self)
return self.is_alive
def hit(self, opponent):
"""Actions taken to wound an opponent."""
opponent.wounded(self.attack)
def wounded(self, attack_amount):
"""Return actual damage and update status when opponent strikes."""
self.health -= attack_amount
self.is_alive = True if self.health > 0 else False
return attack_amount
def __str__(self):
"""Return string representing readable form of this class."""
return (f"alive: {self.is_alive}, health: {self.health}, "
f"attack: {self.attack}\n")
class Knight(Warrior):
"""Specialized fighting unit based on Warrior."""
def __init__(self):
super().__init__()
self.attack = 7
class Vampire(Warrior):
"""Specialized fighting unit that has restorative powers."""
def __init__(self):
super().__init__()
self.health = 40
self.attack = 4
self.vampirism = 50
def hit(self, opponent):
"""Attack opponent, but gain some restorative strength afterwards."""
damage = opponent.wounded(self.attack)
self.health += int(damage * (self.vampirism / 100))
self.is_alive = True if self.health > 0 else False
class Defender(Warrior):
"""Specialized fighting unit based on Warrior; provides extra defense."""
def __init__(self):
super().__init__()
self.health = 60
self.defense = 2
self.attack = 3
def wounded(self, attack_amount):
"""Return actual damage. Update status including defensive ability."""
if attack_amount > self.defense:
self.health -= attack_amount - self.defense
self.is_alive = True if self.health > 0 else False
return attack_amount - self.defense
class Lancer(Warrior):
"""Specialized fighting that wounds two units with the same attack."""
def __init__(self):
super().__init__()
self.health = 50
self.attack = 6
def hit(self, opponent):
"""Attack opponent and half-wound second opponent."""
opponent.wounded(self.attack)
if opponent.next:
opponent.next.wounded(int(self.attack * .5))
class Rookie(Warrior):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.health = 50
self.attack = 1
class Army:
"""Collection of fighting units."""
def __init__(self):
self._army = []
self.is_alive = False
def add_units(self, unit_type, number_of_units):
"""Add fighting units to army.
Units fight in the order they're added.
"""
self.is_alive = True
# Create the list of fighters for this unit by instantiated the
# type of fighter.
fighters = [unit_type() for n in range(number_of_units)]
# Link each fighter to the next fighter in the unit. Note: the
# first fighter will be linked to the last fighter of the last unit.
if self._army:
self._army[-1]['fighters'][-1].next = fighters[0]
for idx in range(len(fighters) - 1):
fighters[idx].next = fighters[idx + 1]
# The last fighter of this unit is not linked to another fighter.
fighters[len(fighters) - 1].next = None
# Add this initialized unit to the list.
self._army.append({
"type": unit_type,
"fighters": fighters,
"unit_alive": True
})
def fighter(self):
"""Return next fighter that's still alive."""
if not self._army or not self.is_alive:
return None
for unit in self._army:
if not unit['unit_alive']:
continue
for fighter in unit['fighters']:
if fighter.is_alive:
return fighter
# No fighter alive in this unit, so this unit is dead.
unit['unit_alive'] = False
# If none of the units have available fighters, this army is dead.
self.is_alive = False
return None
def __str__(self):
"""Return string representing readable form of this class."""
output = "ARMY ===============================================\n"
output += f'is_alive: {self.is_alive}\n'
for unit in self._army:
output += f'----------------------\n'
output += f"type: {unit['type']}, alive: {unit['unit_alive']}\n"
for fighter in unit['fighters']:
output += str(fighter)
return output
class Battle:
"""Coordinates fight between two armies."""
def __init__(self):
self.is_alive = True
def fight(self, army1, army2):
"""Loop until one or the other army is dead."""
fighter1 = army1.fighter()
fighter2 = army2.fighter()
while army1.is_alive and army2.is_alive:
if fighter1.fight(fighter2):
fighter2 = army2.fighter()
else:
fighter1 = army1.fighter()
return True if army1.is_alive else False
def fight(unit_1, unit_2):
return unit_1.fight(unit_2)
Dec. 3, 2019
Comments: