From 00e4426e56fac4c87e21c6570c8745caeba50e87 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sat, 2 Jan 2021 04:02:57 -0500 Subject: [PATCH 1/2] added moveplayer, removeplayer, and addplayer for roster management --- games.py | 51 +++++++++++++++++++------- the_prestige.py | 95 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 128 insertions(+), 18 deletions(-) diff --git a/games.py b/games.py index a077faf..f2b0368 100644 --- a/games.py +++ b/games.py @@ -107,20 +107,45 @@ class team(object): self.score = 0 self.slogan = None + def find_player(self, name): + for index in range(0,len(self.lineup)): + if self.lineup[index].name == name: + return (self.lineup[index], index, self.lineup) + for index in range(0,len(self.rotation)): + if self.rotation[index].name == name: + return (self.rotation[index], index, self.rotation) + else: + return (None, None, None) + def swap_player(self, name): - if len(self.lineup) > 1: - for index in range(0,len(self.lineup)): - if self.lineup[index].name == name: - if self.add_pitcher(self.lineup[index]): - self.lineup.pop(index) - return True - if len(self.rotation) > 1: - for index in range(0,len(self.rotation)): - if self.rotation[index].name == name: - if self.add_lineup(self.rotation[index])[0]: - self.rotation.pop(index) - return True + this_player, index, roster = self.find_player(name) + if this_player is not None and len(roster) > 1: + if roster == self.lineup: + if self.add_pitcher(this_player): + roster.pop(index) + return True + else: + if self.add_lineup(this_player)[0]: + self.rotation.pop(index) + return True return False + + def delete_player(self, name): + this_player, index, roster = self.find_player(name) + if this_player is not None and len(roster) > 1: + roster.pop(index) + return True + else: + return False + + def slide_player(self, name, new_spot): + this_player, index, roster = self.find_player(name) + if this_player is not None and new_spot < len(roster): + roster.pop(index) + roster.insert(new_spot-1, this_player) + return True + else: + return False def add_lineup(self, new_player): if len(self.lineup) < 20: @@ -735,7 +760,7 @@ def search_team(search_term): return None teams.append(team_json) - return teams + return teams def base_string(base): if base == 1: diff --git a/the_prestige.py b/the_prestige.py index 239595b..cfce42d 100644 --- a/the_prestige.py +++ b/the_prestige.py @@ -295,8 +295,8 @@ class CreditCommand(Command): await msg.channel.send("Our avatar was graciously provided to us, with permission, by @HetreaSky on Twitter.") class SwapPlayerCommand(Command): - name = "swap" - template = """m;swap + name = "swapsection" + template = """m;swapsection [team name] [player name]""" description = "Swaps a player from lineup to rotation, or from rotation to lineup. Requires team ownership." @@ -308,16 +308,98 @@ class SwapPlayerCommand(Command): if team is None: await msg.channel.send("Can't find that team, boss. Typo?") return - elif owner_id != msg.author.id or msg.author.id not in config()["owners"]: + elif owner_id != msg.author.id and msg.author.id not in config()["owners"]: await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.") return elif not team.swap_player(player_name): - await msg.channel.send("Either we can't find that player, or they're your last member of that side of the roster. Can't field an empty lineup, chief.") + await msg.channel.send("Either we can't find that player, you've got no space on the other side, or they're your last member of that side of the roster. Can't field an empty lineup, and we *do* have rules, chief.") return else: await msg.channel.send(embed=build_team_embed(team)) games.update_team(team) - await msg.channel.send("Paperwork signed, stamped, and copied.") + await msg.channel.send("Paperwork signed, stamped, copied, and faxed up to the goddess. Xie's pretty quick with this stuff.") + +class MovePlayerCommand(Command): + name = "move" + template = """m;move + [team name] + [player name] + [new lineup/rotation position number] (indexed with 1 being the top)""" + description = "Moves a player in your lineup or rotation. Requires team ownership." + + async def execute(self, msg, command): + team_name = command.split("\n")[1].strip() + player_name = command.split("\n")[2].strip() + team, owner_id = games.get_team_and_owner(team_name) + try: + new_pos = int(command.split("\n")[3].strip()) + except ValueError: + await msg.channel.send("Hey, quit being cheeky. We're just trying to help. Third line has to be a natural number, boss.") + return + if owner_id != msg.author.id and msg.author.id not in config()["owners"]: + await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.") + return + elif not team.slide_player(player_name, new_pos): + await msg.channel.send("You either gave us a number that was bigger than your current roster, or we couldn't find the player on the team. Try again.") + return + else: + await msg.channel.send(embed=build_team_embed(team)) + games.update_team(team) + await msg.channel.send("Paperwork signed, stamped, copied, and faxed up to the goddess. Xie's pretty quick with this stuff.") + +class AddPlayerCommand(Command): + name = "addplayer" + template = """m;addplayer pitcher (or m;addplayer batter) + [team name] + [player name]""" + description = "Recruits a new player to your team, as either a pitcher or a batter. Requires team ownership." + + async def execute(self, msg, command): + team_name = command.split("\n")[1].strip() + player_name = command.split("\n")[2].strip() + team, owner_id = games.get_team_and_owner(team_name) + if owner_id != msg.author.id and msg.author.id not in config()["owners"]: + await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.") + return + + new_player = games.player(ono.get_stats(player_name)) + + if "batter" in command.split("\n")[0]: + if not team.add_lineup(new_player)[0]: + await msg.channel.send("Too many batters 🎶") + return + elif "pitcher" in command.split("\n")[0]: + if not team.add_pitcher(new_player): + await msg.channel.send("8 pitchers is quite enough, we think.") + return + + await msg.channel.send(embed=build_team_embed(team)) + games.update_team(team) + await msg.channel.send("Paperwork signed, stamped, copied, and faxed up to the goddess. Xie's pretty quick with this stuff.") + +class DeletePlayerCommand(Command): + name = "removeplayer" + template = """m;removeplayer + [team name] + [player name]""" + + async def execute(self, msg, command): + team_name = command.split("\n")[1].strip() + player_name = command.split("\n")[2].strip() + team, owner_id = games.get_team_and_owner(team_name) + if owner_id != msg.author.id and msg.author.id not in config()["owners"]: + await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.") + return + + if not team.delete_player(player_name): + await msg.channel.send("We've got bad news: that player isn't on your team. The good news is that... that player isn't on your team?") + return + + else: + await msg.channel.send(embed=build_team_embed(team)) + games.update_team(team) + await msg.channel.send("Paperwork signed, stamped, copied, and faxed up to the goddess. Xie's pretty quick with this stuff.") + class HelpCommand(Command): name = "help" @@ -386,6 +468,9 @@ commands = [ SaveTeamCommand(), ImportCommand(), SwapPlayerCommand(), + MovePlayerCommand(), + AddPlayerCommand(), + DeletePlayerCommand(), DeleteTeamCommand(), ShowTeamCommand(), ShowAllTeamsCommand(), From e2eb77b1efd8bd0695398ac9cfae1619233b9d3c Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sat, 2 Jan 2021 05:42:14 -0500 Subject: [PATCH 2/2] fully implemented heavy snow and slight tailwind weathers. removed supernova from the pool --- games.py | 67 ++++++++++++++++++++++++++-------------------- main_controller.py | 13 +++++++++ the_prestige.py | 3 +++ 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/games.py b/games.py index f2b0368..b8dafb0 100644 --- a/games.py +++ b/games.py @@ -24,22 +24,13 @@ def config(): return json.load(config_file) def all_weathers(): - if not os.path.exists("weather_config.json"): - #generate default config - super_weather_json = jsonpickle.encode(weather("Supernova", "🌟")) - mid_weather_json = jsonpickle.encode(weather("Midnight", "🕶")) - config_dic = { - "Supernova" : super_weather_json, - "Midnight": mid_weather_json - } - with open("weather_config.json", "w") as config_file: - json.dump(config_dic, config_file, indent=4) - with open("weather_config.json") as config_file: - weather_dic = {} - for weather_json in json.load(config_file).values(): - this_weather = jsonpickle.decode(weather_json, classes=weather) - weather_dic[this_weather.name] = this_weather - return weather_dic + weathers_dic = { + #"Supernova" : weather("Supernova", "🌟"), + "Midnight": weather("Midnight", "🕶"), + "Slight Tailwind": weather("Slight Tailwind", "🏌️‍♀️"), + "Heavy Snow": weather("Heavy Snow", "❄") + } + return weathers_dic class appearance_outcomes(Enum): @@ -222,8 +213,13 @@ class game(object): def get_batter(self): if self.top_of_inning: bat_team = self.teams["away"] + counter = self.weather.counter_away else: bat_team = self.teams["home"] + counter = self.weather.counter_home + + if self.weather.name == "Heavy Snow" and counter == bat_team.lineup_position: + return bat_team.pitcher return bat_team.lineup[bat_team.lineup_position % len(bat_team.lineup)] def get_pitcher(self): @@ -484,14 +480,26 @@ class game(object): def batterup(self): scores_to_add = 0 result = self.at_bat() - self.get_batter() if self.top_of_inning: offense_team = self.teams["away"] + weather_count = self.weather.counter_away defense_team = self.teams["home"] else: offense_team = self.teams["home"] + weather_count = self.weather.counter_home defense_team = self.teams["away"] + if self.weather.name == "Slight Tailwind" and "mulligan" not in self.last_update[0].keys() and not result["ishit"] and result["text"] != appearance_outcomes.walk: + mulligan_roll_target = -((((self.get_batter().stlats["batting_stars"])-7)/7)**2)+1 + if random.random() > mulligan_roll_target: + result["mulligan"] = True + return (result, 0) + + if self.weather.name == "Heavy Snow" and weather_count == offense_team.lineup_position and "snow_atbat" not in self.last_update[0].keys(): + result["snow_atbat"] = True + result["text"] = f"{offense_team.lineup[offense_team.lineup_position % len(offense_team.lineup)].name}'s hands are too cold! {self.get_batter().name} is forced to bat!" + return (result, 0) + defenders = defense_team.lineup.copy() defenders.append(defense_team.pitcher) defender = random.choice(defenders) #pitcher can field outs now :3 @@ -581,12 +589,21 @@ class game(object): for base in self.bases.keys(): self.bases[base] = None self.outs = 0 + if self.top_of_inning and self.weather.name == "Heavy Snow" and self.weather.counter_away < self.teams["away"].lineup_position: + self.weather.counter_away = self.pitcher_insert(self.teams["away"]) + if not self.top_of_inning: + if self.weather.name == "Heavy Snow" and self.weather.counter_home < self.teams["home"].lineup_position: + self.weather.counter_home = self.pitcher_insert(self.teams["home"]) self.inning += 1 if self.inning > self.max_innings and self.teams["home"].score != self.teams["away"].score: #game over self.over = True self.top_of_inning = not self.top_of_inning + def pitcher_insert(self, this_team): + rounds = math.ceil(this_team.lineup_position / len(this_team.lineup)) + position = random.randint(0, len(this_team.lineup)-1) + return rounds * len(this_team.lineup) + position def end_of_game_report(self): return { @@ -629,19 +646,9 @@ class game(object): else: inningtext = "bottom" - updatestring = f"{self.last_update[0]['batter']} {self.last_update[0]['text'].value} {self.last_update[0]['defender']}{punc}\n" + updatestring = "this isn't used but i don't want to break anything" - if self.last_update[1] > 0: - updatestring += f"{self.last_update[1]} runs scored!" - - return f"""Last update: {updatestring} - - Score: {self.teams['away'].score} - {self.teams['home'].score}. - Current inning: {inningtext} of {self.inning}. {self.outs} outs. - Pitcher: {self.get_pitcher().name} - Batter: {self.get_batter().name} - Bases: 3: {str(self.bases[3])} 2: {str(self.bases[2])} 1: {str(self.bases[1])} - """ + return "this isn't used but i don't want to break anything" else: return f"""Game over! Final score: **{self.teams['away'].score} - {self.teams['home'].score}** Last update: {self.last_update[0]['batter']} {self.last_update[0]['text'].value} {self.last_update[0]['defender']}{punc}""" @@ -779,6 +786,8 @@ class weather(object): def __init__(self, new_name, new_emoji): self.name = new_name self.emoji = new_emoji + self.counter_away = 0 + self.counter_home = 0 def __str__(self): return f"{self.emoji} {self.name}" \ No newline at end of file diff --git a/main_controller.py b/main_controller.py index 01d35a5..3bf30f3 100644 --- a/main_controller.py +++ b/main_controller.py @@ -88,6 +88,19 @@ def update_loop(): state["update_emoji"] = "💎" state["update_text"] = updatestring + elif "mulligan" in this_game.last_update[0].keys(): + updatestring = "" + punc = "" + if this_game.last_update[0]["defender"] != "": + punc = ", " + + state["update_emoji"] = "🏌️‍♀️" + state["update_text"] = f"{this_game.last_update[0]['batter']} would have gone out, but they took a mulligan!" + + elif "snow_atbat" in this_game.last_update[0].keys(): + state["update_emoji"] = "❄" + state["update_text"] = this_game.last_update[0]["text"] + else: updatestring = "" punc = "" diff --git a/the_prestige.py b/the_prestige.py index 988bb8d..df06614 100644 --- a/the_prestige.py +++ b/the_prestige.py @@ -720,6 +720,9 @@ async def watch_game(channel, newgame, user = None, league = None): "start_delay" : 5, "end_delay" : 10 } + if newgame.weather.name == "Heavy Snow": + newgame.weather.counter_away = random.randint(0,len(newgame.teams['away'].lineup)-1) + newgame.weather.counter_home = random.randint(0,len(newgame.teams['home'].lineup)-1) if league is not None: discrim_string = league