1
0

Merge pull request #9 from KW46/fix-issue-7

Fix issues #6 and #7 (protego working when it should not, stunned_rounds being off by one)
This commit is contained in:
Kwarde 2024-01-16 16:20:34 +01:00 committed by GitHub
commit 8e96f8d1de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 48 deletions

17
game.py
View File

@ -43,7 +43,7 @@ def get_player_spell_from_input(player: Player):
find_what = player_input[5:] find_what = player_input[5:]
spell = find_spell_by_name(find_what)[0] spell = find_spell_by_name(find_what)[0]
if spell == spell_none: if spell is spell_object_none:
print("<!> Spell '{what}' does not exist!".format(what=find_what)) print("<!> Spell '{what}' does not exist!".format(what=find_what))
else: else:
print(spell) print(spell)
@ -124,8 +124,10 @@ try:
player1.active_spell, player1.active_spell_levenshtein_distance = get_player_spell_from_input(player1) player1.active_spell, player1.active_spell_levenshtein_distance = get_player_spell_from_input(player1)
player2.active_spell, player2.active_spell_levenshtein_distance = get_player_spell_from_input(player2) player2.active_spell, player2.active_spell_levenshtein_distance = get_player_spell_from_input(player2)
player1.active_spell = player1.active_spell if (player1.stunned_rounds > 0 and player1.active_spell is not spell_finite_incantatem):
player2.active_spell = player2.active_spell player1.active_spell = spell_object_stunned
if (player2.stunned_rounds > 0 and player2.active_spell is not spell_finite_incantatem):
player2.active_spell = spell_object_stunned
# OUTCOME: SPELLS # OUTCOME: SPELLS
# > Get spell succes # > Get spell succes
@ -173,6 +175,11 @@ try:
player2.active_spell_speed *= 0.67 player2.active_spell_speed *= 0.67
player2.decreased_spell_speed = False player2.decreased_spell_speed = False
if player1.decreased_spell_damage and (player1.active_spell.type == SPELL_TYPE_COMMON or player1.active_spell.type == SPELL_TYPE_POWERFUL):
print("<!> {name} is blinded, spell damage decreased by 33%!".format(name=player1.name))
if player2.decreased_spell_damage and (player2.active_spell.type == SPELL_TYPE_COMMON or player2.active_spell.type == SPELL_TYPE_POWERFUL):
print("<!> {name} is blinded, spell damage decreased by 33%!".format(name=player2.name))
fastest_caster = player1 fastest_caster = player1
slowest_caster = player2 slowest_caster = player2
if player2.active_spell_speed > player1.active_spell_speed: if player2.active_spell_speed > player1.active_spell_speed:
@ -190,9 +197,9 @@ try:
if slowest_caster.health > 0: if slowest_caster.health > 0:
slowest_caster.cast_spell(fastest_caster) slowest_caster.cast_spell(fastest_caster)
fastest_caster.active_spell = spell_none fastest_caster.active_spell = spell_object_none
fastest_caster.active_spell_levenshtein_distance = 0 fastest_caster.active_spell_levenshtein_distance = 0
slowest_caster.active_spell = spell_none slowest_caster.active_spell = spell_object_none
slowest_caster.active_spell_levenshtein_distance = 0 slowest_caster.active_spell_levenshtein_distance = 0
if player1.health == 0: if player1.health == 0:

View File

@ -2,14 +2,17 @@ from wands import Wand
from spells import * from spells import *
MAX_PLAYER_HEALTH = 1000 MAX_PLAYER_HEALTH = 1000
MAX_STUNNED_ROUNDS = 10
class Player: class Player:
def __init__(self, name: str, wand: Wand): def __init__(self, name: str, wand: Wand):
self.name = name self.name = name
self.health = MAX_PLAYER_HEALTH self.health = MAX_PLAYER_HEALTH
self.wand = wand self.wand = wand
self.active_spell = spell_none
self.active_spell_levenshtein_distance = 0 # Penalty => If >0 then damage reduction, 15% per distance self.active_spell = spell_object_none
self.active_spell_succes = False
self.active_spell_levenshtein_distance = 0 # Penalty => If >0 then damage reduction, 15 per distance
self.stunned_rounds = 0 self.stunned_rounds = 0
self.decreased_spell_speed = False self.decreased_spell_speed = False
@ -29,6 +32,11 @@ class Player:
self.health = 0 self.health = 0
return self.health return self.health
def add_stunned_rounds(self, rounds: int):
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):
return 1 * self.wand.succes_rate * spell.succes_rate return 1 * self.wand.succes_rate * spell.succes_rate
@ -53,52 +61,56 @@ class Player:
else: 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!" 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_NONE:
if spell == spell_object_none:
return "{name} must not be feeling well, since they casted a non existing spell. Cast FAILED!".format(name=self.name) return "{name} must not be feeling well, since they casted a non existing spell. Cast FAILED!".format(name=self.name)
elif spell == spell_object_stunned:
return "<!> {name} can't cast anything but {spell} since they are stunned".format(name=self.name, spell=spell_finite_incantatem.name)
else: message = "{name} tried to cast '{spell}' but mispronounced it. Cast FAILED!" else: message = "{name} tried to cast '{spell}' but mispronounced it. Cast FAILED!"
return message.format(name=self.name, spell=spell.name) return message.format(name=self.name, spell=spell.name)
def cast_spell(self, opponent): #: Player ? def cast_spell(self, opponent): #: Player ?
spell_name = self.active_spell.name.lower() spell_name = self.active_spell.name.lower()
if self.active_spell == spell_none: if self.active_spell is spell_object_none:
print("- {name} does nothing".format(name=self.name)) print("- {name} does nothing".format(name=self.name))
return return
if self.stunned_rounds > 0 and self.active_spell != spell_finite_incantatem: if self.stunned_rounds > 0 and self.active_spell is not spell_finite_incantatem:
print("<!> {name} tries to cast a spell but fails because they are stunned!".format(name=self.name)) print("<!> {name} tries to cast a spell but fails because they are stunned!".format(name=self.name))
return return
if self.active_spell.type == SPELL_TYPE_USELESS: if self.active_spell.type == SPELL_TYPE_USELESS:
if self.active_spell == spell_lumos: if self.active_spell is spell_lumos:
if self.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)) 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: 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)) 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 self.lumos = True
elif self.active_spell == spell_nox: elif self.active_spell is spell_nox:
if not self.lumos: if not self.lumos:
print("- {name} shouts: {spell}! Nothing happened".format(name=self.name, spell=spell_name.upper())) print("- {name} shouts: {spell}! Nothing happened".format(name=self.name, spell=spell_name.upper()))
else: else:
print("- {name} shouts {spell}! Their brutal shining light dissapears".format(name=self.name, spell=spell_name.upper())) print("- {name} shouts {spell}! Their brutal shining light dissapears".format(name=self.name, spell=spell_name.upper()))
self.lumos = False self.lumos = False
elif self.active_spell == spell_rennervate: elif self.active_spell is spell_rennervate:
if opponent.stunned_rounds == 0: 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)) 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: else:
print("- {name} casts {spell}! {name_o} is no longer stunned!".format(name=self.name, spell=spell_name, name_o=opponent.name)) 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 opponent.stunned_rounds = 0
elif self.active_spell == spell_igni: elif self.active_spell is 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?") 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: else:
print("<!> [debug]{name} casted SPELL_TYPE_USELESS {spell}. Behaviour unscripted!".format(name=self.name, spell=spell_name)) 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: elif self.active_spell.type == SPELL_TYPE_DEFENSE:
spell_succes = True spell_succes = True
if self.active_spell == spell_finite_incantatem: if self.active_spell is spell_finite_incantatem:
if self.stunned_rounds > 0: if self.stunned_rounds > 0:
if not 10 > random.random() * 100: if not 10 > random.random() * 100:
spell_succes = False spell_succes = False
print("- {name} has no luck. Casting {spell} had no effect".format(name=self.name, spell=spell_name))
else: else:
print("- {name} got lucky! Attempting to cast {spell} broke the silence!".format(name=self.name, spell=spell_name)) print("- {name} got lucky! Attempting to cast {spell} broke the silence!".format(name=self.name, spell=spell_name))
@ -113,55 +125,63 @@ class Player:
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)) 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: elif not spell_succes:
print("- {name}: (nothing, still stunned)".format(name=self.name)) print("- {name}: (nothing, still stunned)".format(name=self.name))
elif self.active_spell == spell_impendimenta: elif self.active_spell is spell_impendimenta:
if opponent.active_spell != spell_protego: if opponent.active_spell is spell_protego and opponent.active_spell_succes:
print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} blocks the attack!".format(name=self.name, name_o=opponent.name, spell=spell_name))
else:
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)) 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 opponent.decreased_spell_speed = True
else: elif self.active_spell is spell_lumos_solem:
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 # 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)) 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 opponent.decreased_spell_damage = True
elif self.active_spell == spell_protego: elif self.active_spell is spell_protego and self.active_spell_succes:
print("- {name} casts {spell}".format(name=self.name, spell=spell_name)) print("- {name} casts {spell}".format(name=self.name, spell=spell_name))
else: else:
print("<!> [debug]{name} casted SPELL_TYPE_DEFENSE {spell}. Behaviour unscripted!".format(name=self.name, spell=spell_name)) 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: elif self.active_spell.type == SPELL_TYPE_UNFORGIVABLE:
if self.active_spell == spell_avada_kedavra: if self.active_spell is 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)) 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 opponent.health = 0
elif self.active_spell == spell_crucio: elif self.active_spell is 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)) 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_rounds += 5 opponent.add_stunned_rounds(5)
elif self.active_spell == spell_imperio: opponent.take_health(self.active_spell.damage)
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)) elif self.active_spell is spell_imperio:
opponent.stunned_rounds = 10 print("- THE NERVE! {name} casts the Imperius curse. \"Why don't you take a nice nap for {max_stunned_rounds} moves, {name_o}?\". {name_o} submits with pleasure".format(name=self.name, name_o=opponent.name, max_stunned_rounds=MAX_STUNNED_ROUNDS))
opponent.add_stunned_rounds(MAX_STUNNED_ROUNDS)
else: else:
if self.active_spell == spell_mimblewimble: if self.active_spell is spell_mimblewimble:
if opponent.active_spell != spell_protego: if opponent.active_spell is spell_protego and opponent.active_spell_succes:
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)) 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: else:
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))
opponent.add_stunned_rounds(-self.active_spell.damage)
elif self.active_spell is spell_silencio:
if opponent.active_spell is spell_protego and opponent.active_spell_succes:
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:
if opponent.stunned_rounds == 0: if opponent.stunned_rounds == 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)) 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_rounds += 3 opponent.add_stunned_rounds(-self.active_spell.damage)
else: 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)) 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: else:
damage_penalty = self.active_spell_levenshtein_distance * 15 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)) 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 self.decreased_spell_damage:
self.decreased_spell_damage = False
damage_modifier = 0.67
else:
damage_modifier = 1
total_damage = self.active_spell.damage * self.wand.damage * damage_modifier - damage_penalty
if total_damage < 0: total_damage = 0 if total_damage < 0: total_damage = 0
if opponent.active_spell == spell_protego: if opponent.active_spell is spell_protego and opponent.active_spell_succes:
print("- {name} casts {spell} on {name_o}. FAILURE! {name_o} blocks the attack!".format(name=self.name, spell=spell_name, name_o=opponent.name)) 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: 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)) print("- {name} casts {spell} on {name_o} causing {dmg} damage!".format(name=self.name, spell=spell_name, name_o=opponent.name, dmg=total_damage))

View File

@ -1,6 +1,7 @@
import random import random
from Levenshtein import distance from Levenshtein import distance
SPELL_TYPE_NONE = -1
SPELL_TYPE_USELESS = 0 SPELL_TYPE_USELESS = 0
SPELL_TYPE_DEFENSE = 1 SPELL_TYPE_DEFENSE = 1
SPELL_TYPE_COMMON = 2 SPELL_TYPE_COMMON = 2
@ -89,8 +90,9 @@ spell_avada_kedavra = Spell("Avada Kedavra", 999, 999, 2, "Instantl
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_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_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 # Internal usage
spell_none = Spell(__INVALID_SPELL, 0, 0, 0, "(internal) invalid spell", SPELL_TYPE_USELESS) spell_object_none = Spell(__INVALID_SPELL, 0, 0, 0, "(internal) invalid spell", SPELL_TYPE_NONE)
spell_object_stunned = Spell(__INVALID_SPELL, 0, 0, 0, "(internal) object when stunned", SPELL_TYPE_NONE)
## ##
## Standalone spell functions ## Standalone spell functions
@ -107,7 +109,7 @@ def find_spell_by_name(input: str): # Returns a list with: [spell_object, levens
dist = distance(i.name.title(), input.title()) dist = distance(i.name.title(), input.title())
if dist < MAX_LEVENSHTEIN_DISTANCE: if dist < MAX_LEVENSHTEIN_DISTANCE:
return [i, dist] return [i, dist]
return [spell_none, 0] return [spell_object_none, 0]
def print_spells(): def print_spells():
header_spells_useless = "== USELESS SPELLS ==" header_spells_useless = "== USELESS SPELLS =="
@ -117,7 +119,7 @@ def print_spells():
header_spells_unforgivable = "== UNFORGIVABLE CURSES ==" header_spells_unforgivable = "== UNFORGIVABLE CURSES =="
for i in Spell.spellList: for i in Spell.spellList:
if i.type == SPELL_TYPE_UNFORGIVABLE or i.type == SPELL_TYPE_USELESS: if i.type == SPELL_TYPE_UNFORGIVABLE or i.type == SPELL_TYPE_USELESS or i.type == SPELL_TYPE_NONE:
continue continue
if i.type == SPELL_TYPE_USELESS and header_spells_useless: if i.type == SPELL_TYPE_USELESS and header_spells_useless:

View File

@ -39,7 +39,7 @@ class Wand:
def __repr__(self): def __repr__(self):
return"\t{id}: {wood} wand with core: {core}\n\t\t-- SPEED: {info_speed}\tDAMAGE: {info_dmg}\tSUCCES RATE: {info_srate}".format( return"\t{id}: {wood} wand with core: {core}\n\t\t-- SPEED: {info_speed}\tDAMAGE: {info_dmg}\tSUCCES RATE: {info_srate}".format(
id=self.id, wood=self.get_wand_wood(), core=self.get_wand_core(), info_srate=round(self.succes_rate, 2), info_speed=self.speed, info_dmg=self.damage id=self.id, 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):