From c91ab77b6f5763a1fc6f1cd3bf9781d4480b7723 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Sun, 27 Dec 2020 02:06:43 -0500 Subject: [PATCH] sim overhaul: more baserunner motion, less double plays, better fielders' choice text --- games.py | 82 +++++++++++++++++++++++++++++++++++++------------ the_prestige.py | 8 +++-- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/games.py b/games.py index 81ea9cb..32f2923 100644 --- a/games.py +++ b/games.py @@ -26,7 +26,7 @@ class appearance_outcomes(Enum): strikeoutswinging = "strikes out swinging." groundout = "grounds out to" flyout = "flies out to" - fielderschoice = "reaches on fielder's choice." + fielderschoice = "reaches on fielder's choice. {} is out at {} base." #requires .format(player, base_string) doubleplay = "grounds into a double play!" sacrifice = "hits a sacrifice fly towards" walk = "draws a walk." @@ -182,21 +182,29 @@ class game(object): else: outcome["text"] = appearance_outcomes.walk - if self.bases[1] is not None and hitnum < -1.3 and self.outs != 2: + if self.bases[1] is not None and hitnum < -2 and self.outs != 2: outcome["text"] = appearance_outcomes.doubleplay outcome["defender"] = "" - for base in self.bases.values(): - if base is not None: - fc_flag = True + #for base in self.bases.values(): + #if base is not None: + #fc_flag = True - if fc_flag and self.outs < 2: - if 0 <= hitnum and hitnum < 1.5: + runners = [(0,self.get_batter())] + for base in range(1,4): + if self.bases[base] == None: + break + runners.append((base, self.bases[base])) + outcome["runners"] = runners #list of consecutive baserunners: (base number, player object) + + if self.outs < 2 and len(runners) > 1: #fielder's choice replaces not great groundouts if any forceouts are present + if -1.5 <= hitnum and hitnum < 0.5: #poorly hit groundouts outcome["text"] = appearance_outcomes.fielderschoice outcome["defender"] = "" - elif 2.5 <= hitnum: - if self.bases[2] is not None or self.bases[3] is not None: - outcome["advance"] = True + + if 2.5 <= hitnum: #well hit flyouts can lead to sacrifice flies/advanced runners + if self.bases[2] is not None or self.bases[3] is not None: + outcome["advance"] = True else: outcome["ishit"] = True if hitnum < 1: @@ -237,15 +245,34 @@ class game(object): return runs elif outcome["text"] == appearance_outcomes.fielderschoice: - for base in range(3, 0, -1): - if self.bases[base] is not None: - self.fc_out = self.bases[base] - for movebase in range(base,1,-1): - self.bases[movebase] = self.bases[movebase-1] - break - self.bases[1] = self.get_batter() + furthest_base, runner = outcome["runners"].pop() #get furthest baserunner + self.bases[furthest_base] = None + outcome["fc_out"] = (runner.name, base_string(furthest_base+1)) #runner thrown out + for index in range(0,len(outcome["runners"])): + base, this_runner = outcome["runners"].pop() + self.bases[base+1] = this_runner #includes batter, at base 0 + if self.bases[3] is not None and furthest_base == 1: #fielders' choice with runners on the corners + self.bases[3] = None + return 1 return 0 + elif outcome["text"] == appearance_outcomes.groundout or outcome["text"] == appearance_outcomes.doubleplay: + runs = 0 + if self.bases[3] is not None: + runs += 1 + self.bases[3] = None + if self.bases[2] is not None: + run_roll = random.gauss(math.erf(random_star_gen("baserunning_stars", self.bases[2])-def_stat)-.5,1.5) + if run_roll > 0: + self.bases[3] = self.bases[2] + self.bases[2] = None + if self.bases[1] is not None: #double plays set this to None before this call + run_roll = random.gauss(math.erf(random_star_gen("baserunning_stars", self.bases[1])-def_stat)-.5,1.5) + if run_roll > 1: + self.bases[2] = self.bases[1] + self.bases[1] = None + return runs + elif outcome["ishit"]: runs = 0 if outcome["text"] == appearance_outcomes.single: @@ -353,7 +380,9 @@ class game(object): elif result["text"] == appearance_outcomes.doubleplay: self.get_pitcher().game_stats["outs_pitched"] += 2 self.outs += 2 - self.bases[1] = None + self.bases[1] = None + scores_to_add += self.baserunner_check(defender, result) + self.get_batter().game_stats["rbis"] -= scores_to_add #remove the fake rbi from the player in advance elif result["text"] == appearance_outcomes.fielderschoice: self.get_pitcher().game_stats["outs_pitched"] += 1 @@ -373,6 +402,11 @@ class game(object): self.get_batter().game_stats["strikeouts_taken"] += 1 self.get_pitcher().game_stats["strikeouts_given"] += 1 + elif result["text"] == appearance_outcomes.groundout: + self.get_pitcher().game_stats["outs_pitched"] += 1 + self.outs += 1 + scores_to_add += self.baserunner_check(defender, result) + else: self.get_pitcher().game_stats["outs_pitched"] += 1 self.outs += 1 @@ -500,4 +534,14 @@ def search_team(search_term): for team_pickle in db.search_teams(search_term): this_team = jsonpickle.decode(team_pickle[0], keys=True, classes=team) teams.append(this_team) - return teams \ No newline at end of file + return teams + +def base_string(base): + if base == 1: + return "first" + elif base == 2: + return "second" + elif base == 3: + return "third" + elif base == 4: + return "fourth" \ No newline at end of file diff --git a/the_prestige.py b/the_prestige.py index db16682..20cad60 100644 --- a/the_prestige.py +++ b/the_prestige.py @@ -453,7 +453,11 @@ async def watch_game(channel, game): if newgame.last_update[0]["defender"] != "": punc = ". " - updatestring = f"{newgame.last_update[0]['batter']} {newgame.last_update[0]['text'].value} {newgame.last_update[0]['defender']}{punc}" + if "fc_out" in newgame.last_update[0].keys(): + name, base_string = newgame.last_update[0]['fc_out'] + updatestring = f"{newgame.last_update[0]['batter']} {newgame.last_update[0]['text'].value.format(name, base_string)} {newgame.last_update[0]['defender']}{punc}" + else: + updatestring = f"{newgame.last_update[0]['batter']} {newgame.last_update[0]['text'].value} {newgame.last_update[0]['defender']}{punc}" if newgame.last_update[1] > 0: updatestring += f"{newgame.last_update[1]} runs scored!" @@ -486,7 +490,7 @@ async def watch_game(channel, game): newgame.gamestate_update_full() pause -= 1 - await asyncio.sleep(6) + await asyncio.sleep(2) title_string = f"{newgame.teams['away'].name} at {newgame.teams['home'].name} ended after {newgame.inning-1} innings" if (newgame.inning - 1) > newgame.max_innings: #if extra innings