def unnamed_monster(level: int, iterations: int) -> Monster: result = T.cast(Monster, random.choice(MONSTERS)) for _ in range(iterations): alternative = T.cast(Monster, random.choice(MONSTERS)) if abs(level - alternative.level) < abs(level - result.level): result = alternative return result
def pick_equipment( source: T.List[EquipmentPreset], goal: int ) -> EquipmentPreset: result = T.cast(EquipmentPreset, random.choice(source)) for _ in range(5): alternative = T.cast(EquipmentPreset, random.choice(source)) if abs(goal - alternative.quality) < abs(goal - result.quality): result = alternative return result
def generate_name() -> str: parts = [ "br|cr|dr|fr|gr|j|kr|l|m|n|pr||||r|sh|tr|v|wh|x|y|z".split("|"), "a|a|e|e|i|i|o|o|u|u|ae|ie|oo|ou".split("|"), "b|ck|d|g|k|m|n|p|t|v|x|z".split("|"), ] result = "" for i in range(6): result += random.choice(parts[i % 3]) return result.title()
def win_equipment(self) -> None: choice = random.choice(list(EquipmentType)) stuff: T.List[EquipmentPreset] better: T.List[Modifier] worse: T.List[Modifier] if choice == EquipmentType.weapon: stuff = WEAPONS better = OFFENSE_ATTRIB worse = OFFENSE_BAD else: stuff = SHIELDS if choice == EquipmentType.shield else ARMORS better = DEFENSE_ATTRIB worse = DEFENSE_BAD equipment = pick_equipment(stuff, self.level) name = equipment.name plus = self.level - equipment.quality if plus < 0: modifier_pool = worse else: modifier_pool = better count = 0 while count < 2 and plus: modifier = random.choice(modifier_pool) if modifier.name in name: break # no repeats if abs(plus) < abs(modifier.quality): break # too much name = modifier.name + " " + name plus -= modifier.quality count += 1 if plus < 0: name = f"{plus} {name}" if plus > 0: name = f"+{plus} {name}" logger.info("Gained %s %s", name, choice.value) self.equipment.put(choice, name)
def complete_quest(self) -> None: self.player.quest_book.quest_bar.reset(50 + random.below_low(1000)) if self.player.quest_book.current_quest: logger.info( "Quest completed: %s", self.player.quest_book.current_quest ) random.choice( [ self.player.win_spell, self.player.win_equipment, self.player.win_stat, self.player.win_item, ] )() self.player.quest_book.monster = None caption = "" choice = random.below(5) if choice == 0: self.player.quest_book.monster = unnamed_monster( self.player.level, iterations=3 ) caption = "Exterminate " + definite( self.player.quest_book.monster.name, 2 ) elif choice == 1: caption = "Seek " + definite(interesting_item(), 1) elif choice == 2: caption = "Deliver this " + boring_item() elif choice == 3: caption = "Fetch me " + indefinite(boring_item(), 1) elif choice == 4: monster = unnamed_monster(self.player.level, iterations=1) caption = "Placate " + definite(monster.name, 2) else: raise AssertionError self.player.quest_book.add_quest(caption) self.player.quest_book.emit("start_quest", caption)
def win_stat(self) -> bool: chosen_stat: T.Optional[StatType] = None if random.odds(1, 2): chosen_stat = random.choice(list(StatType)) else: # favor the best stat so it will tend to clump t = sum(value ** 2 for _stat, value in self.stats) t = random.below(t) chosen_stat = None for stat, value in self.stats: chosen_stat = stat t -= value ** 2 if t < 0: break assert chosen_stat is not None self.stats.increment(chosen_stat) if chosen_stat == StatType.strength: self.inventory.set_capacity(10 + self.stats[StatType.strength]) return True
def monster_task( player_level: int, quest_monster: T.Optional[Monster] ) -> KillTask: level = player_level for _ in range(level): if random.odds(2, 5): level += random.below(2) * 2 - 1 if level < 1: level = 1 is_definite = False monster: T.Optional[Monster] = None if random.odds(1, 25): # use an NPC every once in a while race = random.choice(RACES) if random.odds(1, 2): result = "passing " + race.name + " " + random.choice(CLASSES).name else: result = ( random.choice_low(TITLES) + " " + generate_name() + " the " + race.name ) is_definite = True lev = level elif quest_monster and random.odds(1, 4): # use the quest monster monster = quest_monster result = monster.name lev = monster.level else: # pick the monster out of so many random ones closest to the level we want monster = unnamed_monster(level, iterations=5) result = monster.name lev = monster.level qty = 1 if level - lev > 10: # lev is too low. multiply qty = (level + random.below(max(lev, 1))) // max(lev, 1) if qty < 1: qty = 1 level //= qty if level - lev <= -10: result = "imaginary " + result elif level - lev < -5: i = 10 + level - lev i = 5 - random.below(i + 1) result = sick(i, young(lev - level - i, result)) elif level - lev < 0 and random.below(2) == 1: result = sick(level - lev, result) elif level - lev < 0: result = young(level - lev, result) elif level - lev >= 10: result = "messianic " + result elif level - lev > 5: i = 10 - (level - lev) i = 5 - random.below(i + 1) result = big(i, special(level - lev - i, result)) elif level - lev > 0 and random.below(2) == 1: result = big(level - lev, result) elif level - lev > 0: result = special(level - lev, result) lev = level level = lev * qty if not is_definite: result = indefinite(result, qty) duration = (2 * 3 * level * 1000) // player_level return KillTask(f"Executing {result}", duration, monster=monster)
def impressive_guy() -> str: return T.cast(str, random.choice(IMPRESSIVE_TITLES)) + ( " of the " + T.cast(Race, random.choice(RACES)).name if random.below(2) else " of " + generate_name() )
def boring_item() -> str: return T.cast(str, random.choice(BORING_ITEMS))
def interesting_item() -> str: return ( T.cast(str, random.choice(ITEM_ATTRIB)) + " " + T.cast(str, random.choice(SPECIALS)) )
def special_item() -> str: return interesting_item() + " of " + T.cast(str, random.choice(ITEM_OFS))
def terminate_message(player_name: str) -> str: adjective = random.choice(["faithful", "noble", "loyal", "brave"]) return f"Terminate {adjective} {player_name}?"