jako jo jo

This commit is contained in:
tovjemam 2023-11-22 22:05:31 +01:00
commit 7037378cbe
6 changed files with 470 additions and 0 deletions

111
character.py Normal file
View File

@ -0,0 +1,111 @@
from weapon import *
class Character:
"""
Character reprezentuje postavu v RPG hre
@Author: zbyv
@Date: 15.11.2023
"""
HAND_LEFT = 0
"""
Leva ruka postavy
"""
HAND_RIGHT = 1
"""
Prava ruka postavy
"""
def __init__(self, name: str, strength: int, agility: int, vitality: int) -> None:
"""
Args:
name: Nazev postavy
strength: Utocna sila postavy
agility: Hbitost postavy
vitality: Zdravi postavi
"""
self.__name: str = name
self.__strength: int = strength
self.__agility: int = agility
self.__vitality: int = vitality
self.__weapons: list[Weapon|None] = [None, None]
def attack(self) -> int:
"""
Zjisti utocnou silu postavy
Returns:
Utocna sila postavy
"""
ret = self.__strength
for weapon in self.__weapons:
if weapon:
ret += weapon.attack
return ret
def __defense(self) -> int:
defense = self.__agility
for weapon in self.__weapons:
if weapon:
defense += weapon.defense
return defense
def defend(self, attack: int) -> int:
"""
Vystavi postavu utoku
Args:
attack: Utocna sila nepritele
Returns:
Zdravi ztracene pri utoku
"""
loss = attack - self.__defense()
if loss < 0:
return 0
loss = min(self.__vitality, loss)
self.__vitality -= loss
return loss
def is_alive(self) -> bool:
"""
Zjisti, jestli je postava nazivu
Returns:
True pokud (zdravi > 0), jinak False
"""
return self.__vitality > 0
def take_weapon(self, weapon: Weapon|None, hand: int) -> bool:
"""
Vlozi postave do ruky zbran, pokud v teto ruce doposud zadnou zbran nema
Args:
weapon: Zbran, ktera bude vlozena postave do ruky
hand: Ruka, do ktere postave bude zbran vlozena
Returns:
True pokud si postava zbran vzala, jinak False
"""
if not self.__weapons[hand]:
self.__weapons[hand] = weapon
return True
else:
return False
def __str__(self) -> str:
return f"{self.__name} [{self.__vitality}] ({self.attack()}/{self.__defense()})"

98
rpg.py Normal file
View File

@ -0,0 +1,98 @@
from character import *
class RPG:
"""
Hlavni trida RPG hry
@Author: zbyv
@Date: 15.11.2023
"""
def __init__(self) -> None:
pass
def input_character(self) -> Character:
"""
Vytvori postavu na zaklade udaju nactenych ze standartniho vstupu
Returns:
vytvorena postava
"""
return Character(input("Jmeno postavy: "), int(input("Sila: ")), int(input("Hbitost: ")), int(input("Zdravi: ")))
def input_weapon(self) -> Weapon|None:
"""
Vytvori zbran na zaklade udaju nactenych ze standartniho vstupu
Returns:
vytvorena zbran, nebo None, pokud byl nazev zbrane prazdny
"""
name = input("Nazev zbrane: ")
if name == "":
return None
return Weapon(name, int(input("Utok: ")), int(input("Obrana: ")))
def equip_character(self, character: Character, left: Weapon|None, right: Weapon|None) -> None:
"""
Vyzbroji postavu zadanymi zbranemi, avsak stavajici zbrane nebudou nahrazeny.
Args:
character: Postava pro vyzbrojeni
left: Zbran do leve ruky
right: Zbran do prave ruky
"""
character.take_weapon(left, Character.HAND_LEFT)
character.take_weapon(right, Character.HAND_RIGHT)
@staticmethod
def __process_attack(attacker: Character, defender: Character) -> bool:
dmg = defender.defend(attacker.attack())
print(f"utoci {attacker} a dava {dmg} zraneni")
return not defender.is_alive()
def fight(self, character1: Character, character2: Character) -> Character:
"""
Spusti souboj mezi postavami
Args:
character1: postava souboje, ktera utoci jako prvni
character2: postava souboje, ktera brani jako prvni
Returns:
postava, ktera souboj vyhrala
"""
while True:
if RPG.__process_attack(character1, character2):
return character1
if RPG.__process_attack(character2, character1):
return character2
def run(self) -> None:
"""
Spusti hru
"""
character1 = self.input_character()
self.equip_character(character1, self.input_weapon(), self.input_weapon())
character2 = self.input_character()
self.equip_character(character2, self.input_weapon(), self.input_weapon())
winner = self.fight(character1, character2)
print(f"Vitez: {winner}")
def main() -> None:
rpg = RPG()
rpg.run()
if __name__ == "__main__":
main()

90
tests/character_test.py Normal file
View File

@ -0,0 +1,90 @@
import random
import unittest
from character import Character
from weapon import Weapon
class CharacterTest(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
self.strength = random.randrange(1,50)
self.attackL = random.randrange(1,50)
self.attackR = random.randrange(1,50)
self.agility = random.randrange(1,50)
self.defenseL = random.randrange(1,50)
self.defenseR = random.randrange(1,50)
self.vitality = random.randrange(1,50)
def assertCharacter(self, char:Character, name:str, vitality:int, attack:int, defense:int, msg:str):
text = f"{name} [{vitality}] ({attack}/{defense})"
self.assertEqual(text, char.__str__(), msg)
def test_init(self):
name = "Postava"
text = f"{name} [{self.vitality}] ({self.strength}/{self.agility})"
char = Character(name,self.strength,self.agility,self.vitality)
self.assertCharacter(char, name, self.vitality, self.strength, self.agility,"|Postava o sobe nepodava spravne informace.")
def test_take_weapon(self):
name = "vezmiZbran"
left = Weapon("LEVA", self.attackL, self.defenseL)
right = Weapon("PRAVA", self.attackR, self.defenseR)
char = Character(name, self.strength, self.agility, self.vitality)
self.assertTrue(char.take_weapon(left,Character.HAND_LEFT),"|Postava tvrdi, ze si nemuze vzit zbran do prazdne leve ruky")
self.assertCharacter(char,name,self.vitality,self.strength + self.attackL, self.agility + self.defenseL, "|Postava o sobe nepodava spravne informace")
self.assertFalse(char.take_weapon(left,Character.HAND_LEFT),"|Postava tvrdi, ze si muze vzit zbran do plne leve ruky")
self.assertCharacter(char,name,self.vitality,self.strength + self.attackL, self.agility + self.defenseL, "|Postava o sobe nepodava spravne informace")
self.assertTrue(char.take_weapon(right,Character.HAND_RIGHT),"|Postava tvrdi, ze si nemuze vzit zbran do prazdne prave ruky")
self.assertCharacter(char,name,self.vitality,self.strength + self.attackR + self.attackL, self.agility + self.defenseR + self.defenseL, "|Postava o sobe nepodava spravne informace")
char = Character(name, self.strength, self.agility, self.vitality)
self.assertTrue(char.take_weapon(right,Character.HAND_RIGHT),"|Postava tvrdi, ze si nemuze vzit zbran do prazdne prave ruky")
self.assertCharacter(char,name,self.vitality,self.strength + self.attackR, self.agility + self.defenseR, "|Postava o sobe nepodava spravne informace")
self.assertFalse(char.take_weapon(right,Character.HAND_RIGHT),"|Postava tvrdi, ze si muze vzit zbran do plne prave ruky")
self.assertTrue(char.take_weapon(left,Character.HAND_LEFT), "|Postava tvrdi, ze si nemuze vzit zbran do prazdne leve ruky")
def test_defend(self):
name = "branSe"
attack = random.randint(1,10)
left = Weapon("LEVA", 0, self.defenseL)
right = Weapon("PRAVA", 0, self.defenseR)
char = Character(name, 0, self.agility, self.vitality)
char.take_weapon(left,Character.HAND_LEFT)
char.take_weapon(right, Character.HAND_RIGHT)
self.assertTrue(0==char.defend(self.agility+self.defenseL+self.defenseR-1), "|Postava tvrdi, ze utrpela zraneni, i kdyz je utok mensi nez obrana")
self.assertCharacter(char, name, self.vitality,0,self.agility+self.defenseL+self.defenseR,"|Postava o sobe nepodava spravne informace")
self.assertTrue(0==char.defend(self.agility+self.defenseL+self.defenseR), "|Postava tvrdi, ze utrpela zraneni, i kdyz je utok mensi nez obrana")
self.assertCharacter(char, name, self.vitality,0,self.agility+self.defenseL+self.defenseR,"|Postava o sobe nepodava spravne informace")
self.assertTrue(attack==char.defend(self.agility+self.defenseL+self.defenseR+attack), "|Postava tvrdi, ze utrpela jine zraneni, nez mela")
self.assertCharacter(char, name, self.vitality-attack,0,self.agility+self.defenseL+self.defenseR,"|Postava o sobe nepodava spravne informace")
def test_attack(self):
name = "zautoc"
left = Weapon("LEVA", self.attackL, 0)
right = Weapon("PRAVA", self.attackR, 0)
char = Character(name, self.strength, 0, self.vitality)
char.take_weapon(left,Character.HAND_LEFT)
char.take_weapon(right, Character.HAND_RIGHT)
self.assertTrue(self.strength + self.attackL + self.attackR == char.attack(), "|Postava tvrdi, ze utoci jinou silou, nez jaky je jeji utok.")
self.assertCharacter(char, name, self.vitality, self.strength + self.attackL + self.attackR, 0, "|Postava o sobe nepodava spravne informace")
def test_is_alive(self):
name = "jeZiva"
char = Character(name, 0,0,self.vitality)
self.assertTrue(char.is_alive(), "|Postava zemrela pri narozeni")
char.defend(self.vitality)
self.assertFalse(char.is_alive(), "|Postava nezemrela pri brutalnim utoku")

118
tests/rpg_test.py Normal file
View File

@ -0,0 +1,118 @@
import random
import unittest
import builtins
import typing
from typing import Any
from character import Character
from weapon import Weapon
from rpg import RPG
class RPGTest(unittest.TestCase):
class InputShim:
"""
Třída pro nahrazení standardní funkce input pro vstup dat
"""
__idx:int = 0
__lines:list[str] = []
@staticmethod
def set_input_data(lines:list[str]):
RPGTest.InputShim.__idx = 0
RPGTest.InputShim.__lines = lines
builtins.input = typing.cast(Any, RPGTest.InputShim.__next)
@staticmethod
def get_latest_input() -> str|None:
if RPGTest.InputShim.__idx==0:
return None
else:
return RPGTest.InputShim.__lines[RPGTest.InputShim.__idx-1]
@staticmethod
def __next(prompt:str=""):
assert RPGTest.InputShim.__idx<len(RPGTest.InputShim.__lines), "| nejsou zadany dalsi hodnoty na vstupu"
result = RPGTest.InputShim.__lines[RPGTest.InputShim.__idx] # + "\n"
RPGTest.InputShim.__idx += 1
return result
"""
class PrintShim:
@staticmethod
def set_output_data():
builtins.print =
"""
def assertCharacter(self, char:Character, name:str, vitality:int, attack:int, defense:int, msg:str):
text = f"{name} [{vitality}] ({attack}/{defense})"
self.assertEqual(text, char.__str__(), msg)
def assertWeapon(self, weapon:Weapon, name:str, attack:int, defense: int, msg:str):
text = f"{name} [{attack}/{defense}]"
self.assertEqual(text, weapon.__str__(), msg)
def test_input_character(self):
strength = random.randrange(1,50)
agility = random.randrange(1,50)
vitality = random.randrange(1,50)
name = "nactiPostavu"
RPGTest.InputShim.set_input_data([name,strength,agility,vitality])
rpg = RPG()
char = rpg.input_character()
self.assertCharacter(char, name, vitality, strength, agility, "|Nactena postava tvrdi, ze ma jine vlastnosti, nez by mela mit.")
def test_input_weapon(self):
defense = random.randrange(1,50)
attack = random.randrange(1,50)
name = "nactiZbran"
RPGTest.InputShim.set_input_data([name,attack,defense])
rpg = RPG()
weapon = rpg.input_weapon()
self.assertWeapon(weapon,name,attack,defense,"|Nactena zbran tvrdi, ze ma jine vlastnosti, nez by mela mit.")
RPGTest.InputShim.set_input_data([""])
rpg = RPG()
weapon = rpg.input_weapon()
self.assertIsNone(weapon, "|Nemela se nacist zadna zbran")
def test_equip_character(self):
strength = random.randrange(1,50)
attackL = random.randrange(1,50)
attackR = random.randrange(1,50)
agility = random.randrange(1,50)
defenseL = random.randrange(1,50)
defenseR = random.randrange(1,50)
vitality = random.randrange(1,50)
name = "vyzbrojPostavu"
char = Character(name,strength,agility,vitality)
left = Weapon("leva",attackL,defenseL)
right = Weapon("prava",attackR,defenseR)
rpg = RPG()
rpg.equip_character(char,None,right)
self.assertCharacter(char,name,vitality,strength+attackR, agility + defenseR,"|Vyzbrojeni postavy se nepovedlo, cekal jsem jiny utok.")
rpg.equip_character(char,left,None)
self.assertCharacter(char,name,vitality,strength+attackR+attackL, agility + defenseR+defenseL,"|Vyzbrojeni postavy se nepovedlo, cekal jsem jiny utok.")
def test_fight(self):
char1=Character("Golias",3,0,10)
char2=Character("David",1,1,20)
c1s = char1.__str__()
c2s = char2.__str__()
rpg = RPG()
winner = rpg.fight(char1, char2)
self.assertEqual(winner, char1, f"|{c1s} zautocil na {c2s} a mel vyhrat")
char1=Character("Golias",3,0,10)
char2=Character("David",1,1,20)
c1s = char1.__str__()
c2s = char2.__str__()
rpg = RPG()
winner = rpg.fight(char2, char1)
self.assertEqual(winner, char2, f"|{c2s} zautocil na {c1s} a mel vyhrat")

17
tests/weapon_test.py Normal file
View File

@ -0,0 +1,17 @@
import random
import unittest
from weapon import Weapon
class WeaponTest(unittest.TestCase):
def assertWeapon(self, weapon:Weapon, name:str, attack:int, defense: int, msg:str):
text = f"{name} [{attack}/{defense}]"
self.assertEqual(text, weapon.__str__(), msg)
def test_weapon(self):
attack = random.randrange(100)
defense = random.randrange(100)
weapon = Weapon("Zbran", attack, defense)
self.assertEqual(defense, weapon.defense, "|Vytvorena zbran ma jinou obranu, nez s jakou byla vytvorena.")
self.assertEqual(attack, weapon.attack, "|Vytvorena zbran ma jiny utok, nez s jakym byla vytvorena.")
self.assertWeapon(weapon,"Zbran",attack,defense, "|Vytvorena zbran se lisi od zadani")

36
weapon.py Normal file
View File

@ -0,0 +1,36 @@
class Weapon:
"""
Weapon reprezentuje zbran, kterou muze Character drzet ve svych rukou
@Author: zbyv
@Date: 15.11.2023
"""
def __init__(self, name: str, attack: int, defense: int) -> None:
"""
Args:
name: Nazev zbrane
attack: Utocna sila zbrane
defense: Obranna sila zbrane
"""
self.__name = name
self.__attack = attack
self.__defense = defense
@property
def attack(self) -> int:
"""
Utocna sila zbrane
"""
return self.__attack
@property
def defense(self) -> int:
"""
Obranna sila zbrane
"""
return self.__defense
def __str__(self) -> str:
return f"{self.__name} [{self.__attack}/{self.__defense}]"