Skip to content

Instantly share code, notes, and snippets.

@otykhonruk
Last active November 23, 2023 12:31
Show Gist options
  • Save otykhonruk/4840b6d7f263a55f9ce46f893169cf4a to your computer and use it in GitHub Desktop.
Save otykhonruk/4840b6d7f263a55f9ce46f893169cf4a to your computer and use it in GitHub Desktop.
A simple game logic example which demonstrates basic OOP techniques in Python.
__pycache__
*~
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)
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