class Weapon(object): def __init__(self, dmg: int, action_pts: int, range_: int, ammo: Union[int, float]) -> None: self._dmg = PositiveStat(dmg) self._action = PositiveStat(action_pts) self._range = PositiveStat(range_) self._ammo = PositiveStat(ammo) @property def dmg(self): return self._dmg.max @property def action_pts(self): return self._action.max @property def range(self): return self._range.max @property def ammo(self): return self._ammo.current @property def max_ammo(self): return self._ammo.max def use_weapon(self): if self.ammo <= 0: raise OutOfAmmo() self._ammo.modify_current(-1) return self.dmg def refill_ammo(self): self._ammo.reset() def is_melee_weapon(self): return isinstance(self, MeleeWeapon)
class Soldier(object): def __init__(self, action_pts: int = 3, health: Union[float, int] = 100, heal_pct: float = 5.0): self._strategy = StupidStrategy() self._action_pts = PositiveStat(action_pts) self._health = PositiveStat(health) self._healing_pct = heal_pct self._weapon = FIST @property def strategy(self): return self._strategy def get_perimeter_size(self) -> int: return self._weapon.range def get_sight_range(self) -> int: return 10 def get_action_points(self) -> int: return self._action_pts.current def can_act(self, action_pts) -> bool: return action_pts <= self._action_pts.current and not self.is_dead() def move(self, mv_pts): if mv_pts < 0: raise ValueError('mv_pts can\'t be less than zero') if self.can_act(mv_pts): self._action_pts.modify_current(-mv_pts) def reset_move_points(self): self._action_pts.reset() def get_health(self) -> int: return self._health.current def get_weapon(self) -> Weapon: return self._weapon def equip_weapon(self, weapon: Weapon): self._weapon = weapon def attack(self, opponent): action_pts = self._weapon.action_pts if not self.can_act(action_pts): return None self._action_pts.modify_current(-action_pts) try: dmg = self._weapon.use_weapon() opponent.receive_dmg(dmg) except OutOfAmmo: self._weapon.refill_ammo() def is_dead(self) -> bool: return self._health.current <= 0 def receive_dmg(self, dmg: int): if dmg < 0: raise ValueError('damage can\'t be less than zero') self._health.modify_current(-dmg) def heal(self, health_pts: int): """cannot heal past max""" if health_pts < 0: raise ValueError('health_pts can\'t be less than zero') if self.is_dead(): return None self._health.modify_current(health_pts) def rest(self): """heal and reset_move""" heal_points = int(round(self._health.max * self._healing_pct / 100.)) self.heal(heal_points) self.reset_move_points()