From c5f61b178c9c0716b7903424654e60cd0ff8846c Mon Sep 17 00:00:00 2001 From: Kwarde Date: Mon, 15 Jan 2024 17:20:03 +0100 Subject: [PATCH] Finish cast_spell(), few tweaks done --- game.py | 22 +++++++--- player.py | 125 +++++++++++++++++++++++++++++++++++++++++++++++++----- spells.py | 24 +++++------ 3 files changed, 144 insertions(+), 27 deletions(-) diff --git a/game.py b/game.py index f14019f..a053ce3 100644 --- a/game.py +++ b/game.py @@ -1,5 +1,4 @@ from player import * -from spells import * from wands import * ## @@ -155,10 +154,10 @@ try: if not player1.active_spell_succes and not player2.active_spell_succes: continue if not player1.active_spell_succes and player2.active_spell_succes: - player2.cast_spell(player2.active_spell, player1) + player2.cast_spell(player1) continue elif player1.active_spell_succes and not player2.active_spell_succes: - player1.cast_spell(player1.active_spell, player2) + player1.cast_spell(player2) continue # > Determine fastest spell @@ -187,8 +186,21 @@ try: )) # CAST SPELLS - fastest_caster.cast_spell(fastest_caster.active_spell, slowest_caster) - slowest_caster.cast_spell(slowest_caster.active_spell, fastest_caster) + fastest_caster.cast_spell(slowest_caster) + if slowest_caster.health > 0: + slowest_caster.cast_spell(fastest_caster) + + fastest_caster.active_spell = spell_none + fastest_caster.active_spell_levenshtein_distance = 0 + slowest_caster.active_spell = spell_none + slowest_caster.active_spell_levenshtein_distance = 0 + + if player1.health == 0: + print("END! {name} has been defeated. Congratulations {name2}!".format(name=player1.name, name2=player2.name)) + game_running = False + elif player2.health == 0: + print("END! {name} has been defeated. Congratulations {name2}!".format(name=player2.name, name2=player1.name)) + game_running = False except KeyboardInterrupt: print() diff --git a/player.py b/player.py index 78a49a5..f6eed52 100644 --- a/player.py +++ b/player.py @@ -1,5 +1,5 @@ from wands import Wand -from spells import Spell, SPELL_TYPE_USELESS, SPELL_TYPE_UNFORGIVABLE, spell_none +from spells import * MAX_PLAYER_HEALTH = 500 @@ -9,6 +9,7 @@ class Player: self.health = MAX_PLAYER_HEALTH self.wand = wand self.active_spell = spell_none + self.active_spell_levenshtein_distance = 0 # Penalty => If >0 then damage reduction, 15% per distance self.stunned_rounds = 0 self.decreased_spell_speed = False @@ -36,9 +37,9 @@ class Player: effect_slowed = "Slowed" effect_blinded = "Blinded" - if (self.decreased_spell_speed): + if self.decreased_spell_speed: output = effect_slowed - if (self.decreased_spell_damage): + if self.decreased_spell_damage: if not output: output = effect_blinded else: output += ", " + effect_blinded @@ -47,17 +48,121 @@ class Player: return output def cast_spell_result(self, spell: Spell, succes: bool): - if (succes): + if succes: message = "{name} casted '{spell}' with succes" else: - if (spell.type == SPELL_TYPE_UNFORGIVABLE): + if spell.type == SPELL_TYPE_UNFORGIVABLE: message = "{name} tried to cast '{spell}' but didn't truly mean it. Cast FAILED!" - elif (spell.type == SPELL_TYPE_USELESS): + elif spell.type == SPELL_TYPE_USELESS: return "{name} must not be feeling well, since they casted a non existing spell. Cast FAILED!".format(name=self.name) else: message = "{name} tried to cast '{spell}' but mispronounced it. Cast FAILED!" return message.format(name=self.name, spell=spell.name) - def cast_spell(self, spell: Spell, opponent): #: Player ? - # Below is pretty much a placeholder and will be implemented after placing all cast_spell()s in game.py - print("> {} hits {} and does {} damage!".format(self.name, opponent.name, spell.damage)) - opponent.health -= spell.damage \ No newline at end of file + def cast_spell(self, opponent): #: Player ? + spell_name = self.active_spell.name.lower() + + if self.active_spell == spell_none: + print("- {name} does nothing".format(name=self.name)) + return + + if self.stunned_rounds > 0 and self.active_spell != spell_finite_incantatem: + print(" {name} tries to cast a spell but fails because they are stunned!".format(name=self.name)) + return + + if self.active_spell.type == SPELL_TYPE_USELESS: + if self.active_spell == spell_lumos: + if self.lumos: + print("- {name} casts {spell} with no effect: {name} already has a brutal shining light at the tip of their wand!".format(name=self.name, spell=spell_name)) + else: + print("- {name} casts {spell}! Look at that brutal shining light at the tip of their wand. Absolutely gorgeous!".format(name=self.name, spell=spell_name)) + self.lumos = True + elif self.active_spell == spell_nox: + if not self.lumos: + print("- {name} shouts: {spell}! Nothing happened".format(name=self.name, spell=spell_name.upper())) + else: + print("- {name} shouts {spell}! Their brutal shining light dissapears".format(name=self.name, spell=spell_name.upper())) + self.lumos = False + elif self.active_spell == spell_rennervate: + if opponent.stunned_rounds == 0: + print("- {name} casts {spell} with no effect, because {name_o} is not currently stunned!".format(name=self.name, spell=spell_name, name_o=opponent.name)) + else: + print("- {name} casts {spell}! {name_o} is no longer stunned!".format(name=self.name, spell=spell_name, name_o=opponent.name)) + opponent.stunned_rounds = 0 + elif self.active_spell == spell_igni: + print("- Geralt casts Igni. Wait. Geralt? White Wolf? The butcher of Blaviken? What is he doing here? Is he even here? What is going on?") + else: + print(" [debug]{name} casted SPELL_TYPE_USELESS {spell}. Behaviour unscripted!".format(name=self.name, spell=spell_name)) + + elif self.active_spell.type == SPELL_TYPE_DEFENSE: + spell_succes = True + if self.active_spell == spell_finite_incantatem: + if self.stunned_rounds > 0: + if not 10 > random.random() * 100: + spell_succes = False + else: + print("- {name} got lucky! Attempting to cast {spell} broke the silence!".format(name=self.name, spell=spell_name)) + + if spell_succes and (self.decreased_spell_damage or self.decreased_spell_speed): + print("- {name} casts {spell} and removes queued effects!".format(name=self.name, spell=spell_name)) + self.decreased_spell_damage = False + self.decreased_spell_speed = False + elif spell_succes and not self.decreased_spell_damage and not self.decreased_spell_speed: + if self.stunned_rounds > 0: + self.stunned_rounds = 0 + else: + print("- {name} casts {spell}. {name_o} is looking confused. What spell did {name} try to cancel?".format(name=self.name, spell=spell_name, name_o=opponent.name)) + elif not spell_succes: + print("- {name}: (nothing, still stunned)".format(name=self.name)) + elif self.active_spell == spell_impendimenta: + if opponent.active_spell != spell_protego: + print("- {name} casts {spell} on {name_o}. {name_o} is slowed and their next offensive move will have a 33% slower spell speed!".format(name=self.name, name_o=opponent.name, spell=spell_name)) + opponent.decreased_spell_speed = True + else: + print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} blocks the attack!".format(name=self.name, name_o=opponent.name, spell=spell_name)) + elif self.active_spell == spell_lumos_solem: + # Light still goes through the shield, therefor always succeed blinding attempts + print("- {name} casts {spell} on {name_o}. {name_o} is blinded and their next offensive move will have 33% less damage!".format(name=self.name, name_o=opponent.name, spell=spell_name)) + opponent.decreased_spell_damage = True + elif self.active_spell == spell_protego: + print("- {name} casts {spell}".format(name=self.name, spell=spell_name)) + else: + print(" [debug]{name} casted SPELL_TYPE_DEFENSE {spell}. Behaviour unscripted!".format(name=self.name, spell=spell_name)) + + elif self.active_spell.type == SPELL_TYPE_UNFORGIVABLE: + if self.active_spell == spell_avada_kedavra: + print("- THE NERVE! {name} casts the killing curse! See you in the after life {name_o}!".format(name=self.name, name_o=opponent.name)) + opponent.health = 0 + elif self.active_spell == spell_crucio: + print("- THE NERVE! {name} casts the torture curse. {name_o} is greatly hurt and falls to the ground. They are stunned for 5 (more) moves".format(name=self.name, name_o=opponent.name)) + opponent.stunned_moves += 5 + elif self.active_spell == spell_imperio: + print("- THE NERVE! {name} casts the Imperius curse. \"Why don't you take a nice nap for 10 moves, {name_o}?\". {name_o} submits with pleasure".format(name=self.name, name_o=opponent.name)) + opponent.stunned_moves = 10 + + else: + if self.active_spell == spell_mimblewimble: + if opponent.active_spell != spell_protego: + print("- {name} casts {spell} on {name_o}. {name_o}'s tongue is tied in a knot. That's annoying! {name_o} is silenced for 1 (more) move".format(name=self.name, spell=spell_name, name_o=opponent.name)) + else: + print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} blocks the attack!".format(name=self.name, spell=spell_name, name_o=opponent.name)) + elif self.active_spell == spell_silencio: + if opponent.active_spell != spell_protego: + if opponent.stunned_moves == 0: + print("- {name} casts {spell} on {name_o}. SUCCES! {name_o} is silenced for 3 (more) moves".format(name=self.name, spell=spell_name, name_o=opponent.name)) + opponent.stunned_moves += 3 + else: + print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} is already silenced!".format(name=self.name, spell=spell_name, name_o=opponent.name)) + else: + print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} blocks the attack!".format(name=self.name, spell=spell_name, name_o=opponent.name)) + else: + damage_penalty = self.active_spell_levenshtein_distance * 15 + if damage_penalty != 0: print(" {name} was unclear in their pronunciation and receives a damage penalty of {damage_penalty}".format(name=self.name, damage_penalty=damage_penalty)) + + total_damage = self.active_spell.damage * self.wand.damage - damage_penalty + if total_damage < 0: total_damage = 0 + + if opponent.active_spell == spell_protego: + print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} blocks the attack!".format(name=self.name, spell=spell_name, name_o=opponent.name)) + else: + print("- {name} casts {spell} on {name_o} causing {dmg} damage!".format(name=self.name, spell=spell_name, name_o=opponent.name, dmg=total_damage)) + opponent.take_health(total_damage) \ No newline at end of file diff --git a/spells.py b/spells.py index ac07563..366b42f 100644 --- a/spells.py +++ b/spells.py @@ -68,26 +68,26 @@ spell_igni = Spell("Igno", 100, 000, 100, "Damages # Defensive spell. Each cast from this category has a 5% chance of completely restoring health or 25% chance to heal 5% of maximum health spell_finite_incantatem = Spell("Finite Incantatem", 100, 000, 45, "Cancel all effects casted upon you. If you are stunned/silenced, there's a 10% chance this spell might work", SPELL_TYPE_DEFENSE) -spell_impendimenta = Spell("Impendimenta", 100, 000, 60, "Slows your opponent. EFFECT: Decrease opponent's spell speed by 33% in their next offensive move", SPELL_TYPE_DEFENSE) -spell_lumos_solem = Spell("Lumos Solem", 100, 000, 60, "Blinds your opponent. EFFECT: Decrease opponent's spell damage by 33% in their next offensive move", SPELL_TYPE_DEFENSE) -spell_protego = Spell("Protego", 100, 000, 95, "Create a shield that blocks most attacks", SPELL_TYPE_DEFENSE) +spell_impendimenta = Spell("Impendimenta", 94, 000, 60, "Slows your opponent. EFFECT: Decrease opponent's spell speed by 33% in their next offensive move", SPELL_TYPE_DEFENSE) +spell_lumos_solem = Spell("Lumos Solem", 94, 000, 60, "Blinds your opponent. EFFECT: Decrease opponent's spell damage by 33% in their next offensive move", SPELL_TYPE_DEFENSE) +spell_protego = Spell("Protego", 100, 000, 80, "Create a shield that blocks most attacks", SPELL_TYPE_DEFENSE) # Common combat spells. High chance of succes, deals some damage -spell_reducto = Spell("Reducto", 75, 150, 75, "Blast an object near your opponent") +spell_reducto = Spell("Reducto", 75, 150, 85, "Blast an object near your opponent") spell_rictusempra = Spell("Rictusempra", 85, 90, 90, "Causes your opponent to curl up in laughter, tiring them out") spell_stupefy = Spell("Stupefy", 95, 75, 95, "Knock over your opponent") # Powerful combat spells. Medium chance of succes, deals more damage or stuns opponents -spelll_bombarda = Spell("Bombarda", 50, 180, 65, "Creates an explosion near your opponent", SPELL_TYPE_POWERFUL) -spell_confringo = Spell("Confringo", 50, 200, 55, "Creates an explosion directly at your opponent", SPELL_TYPE_POWERFUL) -spell_mimblewimble = Spell("Mimblewimble", 50, -1, 45, "Ties a knot in your opponents tongue, causing them to be unable to cast a spell for 1 move", SPELL_TYPE_POWERFUL) -spell_sectusempra = Spell("Sectusempra", 90, 400, 40, "Slices your opponent", SPELL_TYPE_POWERFUL) -spell_silencio = Spell("Silencio", 35, -3, 20, "Silences your opponent, causing them unable to cast spells for 3 moves", SPELL_TYPE_POWERFUL) +spell_bombarda = Spell("Bombarda", 50, 180, 75, "Creates an explosion near your opponent", SPELL_TYPE_POWERFUL) +spell_confringo = Spell("Confringo", 50, 200, 70, "Creates an explosion directly at your opponent", SPELL_TYPE_POWERFUL) +spell_mimblewimble = Spell("Mimblewimble", 50, -1, 70, "Ties a knot in your opponents tongue, causing them to be unable to cast a spell for 1 (more) move", SPELL_TYPE_POWERFUL) +spell_sectumsempra = Spell("Sectumsempra", 90, 400, 35, "Slices your opponent", SPELL_TYPE_POWERFUL) +spell_silencio = Spell("Silencio", 35, -3, 55, "Silences your opponent, causing them unable to cast spells for 3 moves. Only works if opponent is not stunned yet", SPELL_TYPE_POWERFUL) # Unforgivable spells. Very low chance of success, instantly kills or deals alot of damage/stun amount -spell_avada_kedavra = Spell("Avada Kedavra", 100, 999, 2, "Instantly end your opponent", SPELL_TYPE_UNFORGIVABLE) -spell_crucio = Spell("Crucio", 100, 500, 5, "Cause excruciating pain to your opponent, causing alot of damage and making them unable to cast spells for 5 moves", SPELL_TYPE_UNFORGIVABLE) -spell_imperio = Spell("Imperio", 100, -1, 3, "Muddle with your opponent's mind, convincing them to stop casting spells for 10 moves", SPELL_TYPE_UNFORGIVABLE) +spell_avada_kedavra = Spell("Avada Kedavra", 999, 999, 2, "Instantly end your opponent", SPELL_TYPE_UNFORGIVABLE) +spell_crucio = Spell("Crucio", 999, 500, 5, "Cause excruciating pain to your opponent, causing alot of damage and making them unable to cast spells for 5 moves", SPELL_TYPE_UNFORGIVABLE) +spell_imperio = Spell("Imperio", 999, -1, 3, "Muddle with your opponent's mind, convincing them to stop casting spells for 10 moves", SPELL_TYPE_UNFORGIVABLE) # spell_none, used as a fallback if an invalid spell was casted spell_none = Spell(__INVALID_SPELL, 0, 0, 0, "(internal) invalid spell", SPELL_TYPE_USELESS)