#! /usr/bun/python3 """spell.py""" import random def random_chance(chance): maximum = 1 / chance draw = random.randint(1, maximum) return (draw == 1) class Spelling_Player: """A base player that can be used as an abstract class for other players.""" LEVEL = 16 def __init__(self): self.hp = 100 self.status = 0 self.name = "" self.max_letters = Spelling_Player.LEVEL self.casted = {} class Letter: """A single letter of a spell.""" VALUES = {"a" : 16, "e" : 8, "i" : 12, "o" : 6, "u" : 4} STATUSES = {"h" : 1, "j" : 2, "l" : 4, "m" : 8, "n" : 16, "q" : 32, "r" : 64, "w" : 128} def __init__(self, character = ""): self.character = character if(self.character in Letter.VALUES.keys()): self.value = Letter.VALUES[self.character] else: self.value = 0 if(self.character in Letter.STATUSES.keys()): self.status = Letter.STATUSES[self.character] else: self.status = 0 def __str__(self): return str(self.character) class Spell: """A spell.""" #constants: VOWELS = "aeiouy" UNPAIREDS = "hjlmnqrw" XBUFFS = "bd" IBUFFS = "gvz" XNERFS = "fks" INERFS = "pt" SPECIALS = "cx" def __init__(self, word = ""): valid = False for i in Spell.VOWELS: if(i in word): valid = True break if(not valid): raise ValueError("No vowels are present.") self.word = [] for i in word: if(i == "y"): i = random.choice("aeiou") #if the next letter is "y", change it to any other vowel elif(self.is_special(i)): i = random.choice(Spell.UNPAIREDS + Spell.XBUFFS + Spell.IBUFFS + Spell.XNERFS + Spell.INERFS) #unpaireds, buffs, & nerfs else: pass self.word.append(Letter(i)) if(len(self.word) >= 16): break self.values = {"a" : 0, "e" : 0, "i" : 0, "o" : 0, "u" : 0} self.xnerfs = {"a" : 1, "e" : 1, "i" : 1, "o" : 1, "u" : 1} self.inerfs = {"a" : 0, "e" : 0, "i" : 0, "o" : 0, "u" : 0} self.stats = 0 self.last_vowel = None self.vowel_coef = 1 self.total_damage = 0 self.absorb = 0 def is_vowel(self, char): return (char in Spell.VOWELS) def is_unpaired(self, char): return (char in Spell.UNPAIREDS) def is_xbuff(self, char): return (char in Spell.XBUFFS) def is_ibuff(self, char): return (char in Spell.IBUFFS) def is_xnerf(self, char): return (char in Spell.XNERFS) def is_inerf(self, char): return (char in Spell.INERFS) def is_special(self, char): return (char in Spell.SPECIALS) def parse(self): """Initial parser""" next_syl = [] for next_letter in self.word: if(self.is_vowel(next_letter.character)): if(self.last_vowel): self.syl(next_syl) next_syl = [] self.last_vowel = next_letter.character next_syl.append(next_letter) self.syl(next_syl) #remember not to let the last syllable drop off the Earth! def syl(self, syllable): """Process a single syllable. In this game, a syllable contains exactly one vowel, all consonants adjacent to && after it (until the next vowel), and, if it's the first one, all consonants in front as well.""" vowel = None xvalue = 1 ivalue = 0 xnerf = 1 inerf = 0 status = 0 for next_letter in syllable: if(self.is_vowel(next_letter.character)): #vowels vowel = next_letter.character xvalue *= max(int((next_letter.value / self.vowel_coef) + 0.5), 1) ivalue *= next_letter.value inerf *= int(next_letter.value / 2) self.vowel_coef *= 2 elif(self.is_unpaired(next_letter.character)): #unpairedes if(random_chance(1 / 8)): status = status | next_letter.status elif(self.is_xbuff(next_letter.character)): #xbuffs xvalue *= 2 elif(self.is_ibuff(next_letter.character)): #ibuffs if(vowel): ivalue += Letter.VALUES[vowel] else: ivalue += 1 elif(self.is_xnerf(next_letter.character)): #xnerfs xnerf *= 2 elif(self.is_inerf(next_letter.character)): #inerfs if(vowel): inerf += int(Letter.VALUES[vowel] / 2) else: inerf += 1 else: continue self.values[vowel] += (xvalue + ivalue) self.xnerfs[vowel] *= xnerf self.inerfs[vowel] += inerf self.stats = self.stats | status def parse_nerfs(self, opponent): #opponent is the other guy's spell for k in opponent.xnerfs.keys(): if(self.values[k] > 0): self.values[k] = int(max((self.values[k] - opponent.inerfs[k]), 1)) #incremental nerfs are applied self.values[k] = int(max((self.values[k] / opponent.xnerfs[k]) + 0.5, 1)) #multiplicative nerfs are applied (is "multiplicative" a word?) def parse_atk(self): self.total_damage = self.values["a"] def parse_ret_def(self, opponent): opponent.absorb = min(self.total_damage, opponent.values["u"]) self.total_damage = max(self.total_damage - opponent.values["u"], 0) def parse_def(self, opponent): #print(self.total_damage) total = min(self.total_damage, opponent.values["i"]) self.total_damage -= total #total damage is decremented by the opponent's defense opponent.values["i"] -= total #print(self.total_damage) def parse_defatk_def(self, opponent): defense = min(opponent.values["e"], self.total_damage) #do defatk defense first opponent.values["e"] -= defense self.total_damage -= defense def parse_defatk_atk(self, opponent): self.total_damage += self.values["e"] total = min(self.total_damage, opponent.values["i"]) self.total_damage -= total opponent.values["i"] -= total def parse_ret_atk(self, opponent): self.total_damage += self.absorb self.total_damage -= opponent.values["i"] if(self.total_damage < 0): self.total_damage = 0 def affect(self, opponent, caster): #opponent is the other guy's spell, caster is the player who cast the spell caster.hp -= opponent.total_damage if(caster.hp <= 0): caster.hp = 0 return caster.hp += self.values["o"] if(caster.hp > 100): caster.hp = 100 caster.status = opponent.stats def compare_spells(spell1, spell2): spell1.parse() spell2.parse() spell1.parse_nerfs(spell2) spell2.parse_nerfs(spell1) spell1.parse_atk() spell2.parse_atk() spell1.parse_ret_def(spell2) spell2.parse_ret_def(spell1) spell1.parse_def(spell2) spell2.parse_def(spell1) spell1.parse_defatk_def(spell2) spell2.parse_defatk_def(spell1) spell1.parse_defatk_atk(spell2) spell2.parse_defatk_atk(spell1) spell1.parse_ret_atk(spell2) spell2.parse_ret_atk(spell1) return spell1, spell2 if(__name__ == "__main__"): print("""spell.py Contents: random_chance(chance) class Spelling_Player class Letter class Spell compare_spells(spell1, spell2)""")