1
0

Add type annotations for class variables and function return types

This commit is contained in:
Kwarde 2024-01-19 07:41:38 +01:00
parent d19c467a7c
commit e76d315832
5 changed files with 54 additions and 55 deletions

View File

@ -2,13 +2,12 @@ from game import intro_message_welcome, intro_get_username, intro_print_wands, i
from game import round_get_player_spells, round_set_player_spells_succes, round_get_player_spells_speed, round_cast_spells, start_round
from player import Player
current_round = 0
current_round: int = 0
intro_message_welcome()
player1 = Player(None, None)
player2 = Player(None, None)
player1.name = intro_get_username(1)
player2.name = intro_get_username(2)

26
game.py
View File

@ -1,7 +1,7 @@
import random
from player import Player
from wands import wands
from spells import spells, random_combat_spell, print_spells, find_spell_by_name
from spells import Spell, spells, random_combat_spell, print_spells, find_spell_by_name
from spells import _INVALID_SPELL, SPELL_TYPE_COMMON, SPELL_TYPE_POWERFUL
from game_config import MIN_USERNAME_LEN, MAX_PLAYER_HEALTH
@ -17,7 +17,7 @@ INPUT_MESSAGES = (
##
## Intro functions
##
def intro_message_welcome():
def intro_message_welcome() -> None:
print()
print("Welcome! You're about to perform a wizard duel!")
print("After joining in, you have to select a wand. Your wand will affect the power of your spells. Spells have three atrributes that modify the power of spells:")
@ -26,14 +26,14 @@ def intro_message_welcome():
print("3- SPEED: If both players succesfully cast a spell, the spell with the greatest speed will succeed and the other one will not")
print()
def intro_message_duel_start():
def intro_message_duel_start() -> None:
print("<!> If you need a list of available spells, enter: help (this will not take away a move)")
print("<!> If you need information of a specific spell, enter: help SPELL_NAME")
print("<!> You can press enter (without typing a spell) to cast a random basic combat spell")
print()
print("Alright! Time to duel!")
def intro_get_username(playerid: int):
def intro_get_username(playerid: int) -> str:
while True:
user_input = input("Player {id} - What's your name? ".format(id=playerid))
@ -43,11 +43,11 @@ def intro_get_username(playerid: int):
return user_input
def intro_print_wands():
def intro_print_wands() -> None:
for i in wands.items():
print("{wand_id}:{wand_desc}".format(wand_id=i[0], wand_desc=i[1]))
def intro_get_wand(player: Player):
def intro_get_wand(player: Player) -> Spell:
while (True):
try:
user_input = int(input("What wand do you want {name}? (Enter one of the numbers): ".format(name=player.name)))
@ -62,7 +62,7 @@ def intro_get_wand(player: Player):
##
## Game round functions
##
def start_round(round: int, player1: Player, player2: Player):
def start_round(round: int, player1: Player, player2: Player) -> None:
if (player1.stunned_rounds > 0): player1.stunned_rounds -= 1
if (player2.stunned_rounds > 0): player2.stunned_rounds -= 1
@ -77,10 +77,10 @@ def start_round(round: int, player1: Player, player2: Player):
)
)
def print_turn_message(player: Player):
def print_turn_message(player: Player) -> None:
return random.choice(INPUT_MESSAGES).format(name=player.name)
def get_player_spell_from_input(player: Player):
def get_player_spell_from_input(player: Player) -> tuple:
while True:
player_input = input(print_turn_message(player))
@ -100,7 +100,7 @@ def get_player_spell_from_input(player: Player):
else:
return find_spell_by_name(player_input)
def round_get_player_spells(player1: Player, player2: Player):
def round_get_player_spells(player1: Player, player2: Player) -> None:
spell, dist = get_player_spell_from_input(player1)
player1.active_spell = spells.get(spell[0])
player1.active_spell_levenshtein_distance = dist
@ -114,7 +114,7 @@ def round_get_player_spells(player1: Player, player2: Player):
if (player2.stunned_rounds > 0 and player2.active_spell is not spells["Finite Incantatem"]):
player2.active_spell = None
def round_set_player_spells_succes(player1: Player, player2: Player):
def round_set_player_spells_succes(player1: Player, player2: Player) -> None:
player1.active_spell_succes = player1.get_spell_succes_rate(player1.active_spell) > random.random() * 100
player2.active_spell_succes = player2.get_spell_succes_rate(player2.active_spell) > random.random() * 100
print(player1.cast_spell_result(player1.active_spell, player1.active_spell_succes))
@ -134,7 +134,7 @@ def round_set_player_spells_succes(player1: Player, player2: Player):
player2.give_health(MAX_PLAYER_HEALTH)
print("<!> {name} casted {spell} outstanding! {name} now has full health!".format(name=player2.name, spell=player2.active_spell.get_spell_name(), hp=MAX_PLAYER_HEALTH*0.05))
def round_get_player_spells_speed(player1: Player, player2: Player):
def round_get_player_spells_speed(player1: Player, player2: Player) -> tuple:
player1.active_spell_speed = player1.active_spell.speed * player1.wand.speed
player2.active_spell_speed = player2.active_spell.speed * player2.wand.speed
@ -166,7 +166,7 @@ def round_get_player_spells_speed(player1: Player, player2: Player):
return (fastest_caster, slowest_caster)
def round_cast_spells(player1: Player, player2: Player):
def round_cast_spells(player1: Player, player2: Player) -> None:
player1.cast_spell(player2)
if player2.health > 0:
player2.cast_spell(player1)

View File

@ -5,44 +5,44 @@ from spells import Spell, spells, _INVALID_SPELL
from game_config import MAX_PLAYER_HEALTH, MAX_STUNNED_ROUNDS
class Player:
def __init__(self, name: str, wand: Wand):
self.name = name
self.health = MAX_PLAYER_HEALTH
self.wand = wand
def __init__(self, name: str, wand: Wand) -> None:
self.name: str = name
self.health: float = MAX_PLAYER_HEALTH
self.wand: Wand = wand
self.active_spell = spells[_INVALID_SPELL]
self.active_spell_succes = False
self.active_spell_levenshtein_distance = 0 # Penalty => If >0 then damage reduction, 15 per distance
self.active_spell: Spell = spells[_INVALID_SPELL]
self.active_spell_succes: bool = False
self.active_spell_levenshtein_distance: int = 0 # Penalty => If >0 then damage reduction, 15 per distance
self.stunned_rounds = 0
self.decreased_spell_speed = False
self.decreased_spell_damage = False
self.stunned_rounds: int = 0
self.decreased_spell_speed: bool = False
self.decreased_spell_damage: bool = False
self.lumos = False
self.lumos: bool = False
def give_health(self, health: int):
def give_health(self, health: int) -> float:
self.health += health
if self.health > MAX_PLAYER_HEALTH:
self.health = MAX_PLAYER_HEALTH
return self.health
def take_health(self, health: int):
def take_health(self, health: int) -> float:
self.health -= health
if self.health < 0:
self.health = 0
return self.health
def add_stunned_rounds(self, rounds: int):
def add_stunned_rounds(self, rounds: int) -> None:
self.stunned_rounds += rounds + 1
if (self.stunned_rounds > MAX_STUNNED_ROUNDS + 1):
self.stunned_rounds = MAX_STUNNED_ROUNDS
def get_spell_succes_rate(self, spell: Spell):
def get_spell_succes_rate(self, spell: Spell) -> float:
if spell == None:
return 0
return 1 * self.wand.succes_rate * spell.succes_rate
def get_queued_effects(self):
def get_queued_effects(self) -> str:
output = ""
effect_slowed = "Slowed"
effect_blinded = "Blinded"
@ -57,7 +57,7 @@ class Player:
if not output: output = "None"
return output
def cast_spell_result(self, spell: Spell, succes: bool):
def cast_spell_result(self, spell: Spell, succes: bool) -> str:
if spell == None:
return "<!> {name} can't cast anything but Finite Incantatem since they are stunned".format(name=self.name)
@ -72,7 +72,7 @@ class Player:
else: message = "{name} tried to cast '{spell}' but mispronounced it. Cast FAILED!"
return message.format(name=self.name, spell=spell.get_spell_name())
def cast_spell(self, opponent): #: Player ?
def cast_spell(self, opponent) -> None:
spell_name = self.active_spell.get_spell_name()
if self.active_spell is None:

View File

@ -31,23 +31,23 @@ class Spell:
- SPELL_TYPE_POWER: Powerful combat spell - deals alot of damage or takes away a few moves from opponent
- SPELL_TYPE_UNFORGIVABLE: deals alot of damage or takes away alot of moves from opponent
"""
def __init__(self, speed: int, damage: int, succes_rate: int, description: str, type: int = SPELL_TYPE_COMMON):
self.speed = speed
self.damage = damage
self.succes_rate = succes_rate
self.description = description
self.type = type
def __init__(self, speed: int, damage: int, succes_rate: int, description: str, type: int = SPELL_TYPE_COMMON) -> None:
self.speed: int = speed
self.damage: int = damage
self.succes_rate: int = succes_rate
self.description: str = description
self.type: int = type
def __repr__(self):
def __repr__(self) -> str:
return "\n\t{desc}\n\tSUCCES RATE: {srate}%\tSPEED: {speed}\tDAMAGE: {dmg}".format(type=type, desc=self.description, srate=self.succes_rate, speed=self.speed, dmg=self.damage)
def chance_heal_partly_succes(self):
def chance_heal_partly_succes(self) -> bool:
return self.type == SPELL_TYPE_DEFENSE and CHANCE_HEAL_PARTLY > random.random() * 100
def chance_heal_fully_succes(self):
def chance_heal_fully_succes(self) -> bool:
return self.type == SPELL_TYPE_DEFENSE and CHANCE_HEAL_FULLY > random.random() * 100
def get_spell_name(self):
def get_spell_name(self) -> str:
return str(list(i for i in spells if spells[i] == self)).strip("[]'")
##
@ -95,10 +95,10 @@ if DEBUG_MODE:
##
## Standalone spell functions
##
def random_combat_spell():
def random_combat_spell() -> tuple:
return random.choice([i for i in spells.items() if i[1].type == SPELL_TYPE_COMMON]) # note: returns tuple ('spell_name', spell_obj)
def find_spell_by_name(input: str): # Returns a multidimensional tuple: ( ('spell_name', spell_object), levenshtein_distance )
def find_spell_by_name(input: str) -> tuple: # Returns a multidimensional tuple: ( ('spell_name', spell_object), levenshtein_distance )
ret = (input, spells.get(input.title(), spells[_INVALID_SPELL]))
dist = 0
if ret[1] == spells[_INVALID_SPELL]:
@ -111,7 +111,7 @@ def find_spell_by_name(input: str): # Returns a multidimensional tuple: ( ('spel
break
return (ret, dist)
def print_spells():
def print_spells() -> None:
header_spells_useless = "== USELESS SPELLS =="
header_spells_defensive = "== DEFENSIVE SPELLS =="
header_spells_common = "== COMMON COMBAT SPELLS =="

View File

@ -7,13 +7,13 @@ WAND_WOOD_ELDER = 1 #Speed -4%
WAND_WOOD_APPLE = 2 #Damage -5%
class Wand:
def __init__(self, wand_core: int, wand_wood: int):
self.core = wand_core
self.wood = wand_wood
def __init__(self, wand_core: int, wand_wood: int) -> None:
self.core: int = wand_core
self.wood: int = wand_wood
self.succes_rate = 1
self.speed = 1
self.damage = 1
self.succes_rate: float = 1
self.speed: float = 1
self.damage: float = 1
if self.core == WAND_CORE_UNICORN:
self.succes_rate *= 1.03
@ -29,18 +29,18 @@ class Wand:
elif self.wood == WAND_WOOD_APPLE:
self.damage *= 0.95
def __repr__(self):
def __repr__(self) -> str:
return"\t{wood} wand with core: {core}\n\t\t-- SPEED: {info_speed}\tDAMAGE: {info_dmg}\tSUCCES RATE: {info_srate}".format(
wood=self.get_wand_wood(), core=self.get_wand_core(), info_srate=round(self.succes_rate, 2), info_speed=self.speed, info_dmg=round(self.damage, 2)
)
def get_wand_core(self):
def get_wand_core(self) -> str:
if self.core == WAND_CORE_UNICORN: return "Unicorn hair"
elif self.core == WAND_CORE_PHOENIX: return "Phoenix feather"
elif self.core == WAND_CORE_DRAGON: return "Dragon heartstring"
else: return "Muggle's electric wire"
def get_wand_wood(self):
def get_wand_wood(self) -> str:
if self.wood == WAND_WOOD_ASH: return "Ash"
elif self.wood == WAND_WOOD_ELDER: return "Elder"
elif self.wood == WAND_WOOD_APPLE: return "Apple"