Last active
November 23, 2023 12:31
-
-
Save otykhonruk/4840b6d7f263a55f9ce46f893169cf4a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A simple game logic example which demonstrates basic OOP techniques in Python. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__pycache__ | |
*~ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from model import Battle | |
from model import Tribe | |
def simulate_battle(total_members, style_battle): | |
tribe1 = Tribe.generate_random(total_members) | |
tribe2 = Tribe.generate_random(total_members) | |
battle = style_battle(tribe_1, tribe_2) | |
print("\nTribe 1:") | |
print(tribe1) | |
print("\nTribe 2:") | |
print(tribe2) | |
round_number = 1 | |
while tribe_1.has_members() and tribe_2.has_members(): | |
print(f"\nRound {round_number}:") | |
battle.battle(tribe1, tribe2) | |
print("\nTribe 1:") | |
print(tribe_1) | |
print("\nTribe 2:") | |
print(tribe_2) | |
round_number += 1 | |
def choose_battle_style(battle_styles=Battle.__subclasses__()): | |
battle_style_choices = ', '.join(f"{i} - {bs.__name__}" | |
for i, bs in enumerate(battle_styles, 1)) | |
style_choice = int(input(f"\nChoose the battle style ({battle_style_choices}): ")) | |
return battle_styles[style_choice - 1] | |
if __name__ == '__main__': | |
total_members = int(input("Enter the total number of members for Tribe: ")) | |
battle_style = choose_battle_style() | |
result = simulate_battle(total_members, battle_style) | |
print(result) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import choice, randint | |
class TribeMember: | |
def __init__(self, name, health, attack, defence): | |
self.name = name | |
self.health = health | |
self.attack = attack | |
self.defence = defence | |
@classmethod | |
def random(cls, name): | |
params = [randint(*range_) for range_ in | |
[cls.health_range, cls.attack_range, cls.defence_range]] | |
return cls(name, *params) | |
# def attack_enemy(self, enemy): | |
# damage = max(0, self.attack - enemy.defence) | |
# enemy.health -= damage | |
# if enemy.health <= 0: | |
# return True # Enemy defeated | |
# return False | |
@property | |
def is_alive(self): | |
return self.health > 0 | |
def __str__(self): | |
return f"Attacker - {self.name}, (Health: {self.health}, Attack: {self.attack}, Defence: {self.defence})" | |
class Warrior(TribeMember): | |
health_range = (80, 100) | |
attack_range = (7, 10) | |
defence_range = (5, 8) | |
class Archer(TribeMember): | |
health_range = (60, 80) | |
attack_range = (8, 12) | |
defence_range = (3, 6) | |
class Hunter(TribeMember): | |
health_range = (70, 90) | |
attack_range = (6, 9) | |
defence_range = (4, 7) | |
class Tribe(list): | |
def __str__(self): | |
return '\n'.join(map(str, self)) | |
@staticmethod | |
def generate_random(total_members, roles=TribeMember.__subclasses__()): | |
if total_members < 5: | |
raise ValueError("A tribe must have at least 5 members.") | |
tribe = Tribe() | |
for i in range(total_members): | |
role = choice(roles) | |
name = f"{role.__name__}_{i}" | |
tribe.append(role.random(name)) | |
return tribe | |
def has_members(self): | |
return any(member.is_alive for member in self) | |
def total_health(self): | |
return sum(member.health for member in self if member.is_alive) | |
def remove_defeated_members(self): | |
self[:] = [member for member in self if member.is_alive] | |
class Battle: | |
def __init__(self, tribe1, tribe2): | |
self.tribe1 = tribe1 | |
self.tribe2 = tribe2 | |
def _attack(self, attacker, target): | |
damage = max(0, attacker.attack - target.defence) | |
target.health -= min(damage, target.health) | |
print(f"{attacker.name} deals {damage} damage to {target.name}") | |
if target.health == 0: | |
print(f"{target.name} has been defeated!") | |
def _battle(self, participant1, participant2): | |
print(f"\n{participant1.name} attacks {participant2.name}:") | |
self._attack(participant1, participant2) | |
self.tribe1.remove_defeated_members() | |
if participant2.is_alive: | |
print(f"\n{participant2.name} counterattacks {participant1.name}:") | |
self._attack(participant2, participant1) | |
self.tribe2.remove_defeated_members() | |
def check_victory(self): | |
tribe1_no_members = not self.tribe1.has_members() | |
tribe2_no_members = not self.tribe2.has_members() | |
if tribe1_no_members and tribe2_no_members: | |
return "\nThe battle ended: both tribes are left without warriors." | |
elif tribe1_no_members: | |
return f"\nTribe 2 wins!" | |
elif tribe2_no_members: | |
return f"\nTribe 1 wins!" | |
def battle(self, tribe1, tribe2): | |
NotImplemented | |
class SequentialBattle(Battle): | |
def battle(self, tribe1, tribe2): | |
for participant1, participant2 in zip(tribe1, tribe2): | |
if not tribe2.has_members(): | |
break | |
if tribe1.has_members() and tribe2.has_members(): | |
self._battle(participant1, participant2) | |
# Check for the winner after each round | |
victory_result = self.check_victory() | |
if victory_result: | |
return victory_result | |
class LimitedStrikesBattle(Battle): | |
def battle(self, tribe1, tribe2): | |
max_strikes_per_tribe = int(input("Enter the number of attacks each tribe should make --> ")) | |
for participant1 in tribe1: | |
participant2 = choice(tribe2) | |
if tribe1.has_members() and tribe2.has_members(): | |
self._battle(participant1, participant2) | |
# Check for the winner after each round | |
victory_result = self.check_victory() | |
if victory_result: | |
return victory_result | |
# Calculate total remaining health for each tribe | |
total_health_tribe1 = tribe1.total_health() | |
total_health_tribe2 = tribe2.total_health() | |
# Check for the winner based on total remaining health | |
if total_health_tribe1 > total_health_tribe2: | |
return f"Tribe 1 wins with a total remaining health of {total_health_tribe1}!" | |
elif total_health_tribe2 > total_health_tribe1: | |
return f"Tribe 2 wins with a total remaining health of {total_health_tribe2}!" | |
else: | |
return "The battle ended in a draw: both tribes have the same total remaining health." | |
class RandomBattle(Battle): | |
def battle(self, tribe1, tribe2): | |
for participant1 in tribe1: | |
if not tribe2.has_members(): | |
break | |
participant2 = choice(tribe2) | |
if tribe1.has_members() and tribe2.has_members(): | |
self._battle(participant1, participant2) | |
# Check for the winner after each round | |
victory_result = self.check_victory() | |
if victory_result: | |
return victory_result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment