Merge pull request #194 from hillexed/master
Weather refactor + Feedback + Literacy
This commit is contained in:
commit
f22af2520a
218
games.py
218
games.py
|
@ -1,6 +1,7 @@
|
||||||
import json, random, os, math, jsonpickle
|
import json, random, os, math, jsonpickle
|
||||||
from enum import Enum
|
|
||||||
import database as db
|
import database as db
|
||||||
|
import weather
|
||||||
|
from gametext import base_string, appearance_outcomes
|
||||||
|
|
||||||
data_dir = "data"
|
data_dir = "data"
|
||||||
games_config_file = os.path.join(data_dir, "games_config.json")
|
games_config_file = os.path.join(data_dir, "games_config.json")
|
||||||
|
@ -28,34 +29,6 @@ def config():
|
||||||
with open(games_config_file) as config_file:
|
with open(games_config_file) as config_file:
|
||||||
return json.load(config_file)
|
return json.load(config_file)
|
||||||
|
|
||||||
def all_weathers():
|
|
||||||
weathers_dic = {
|
|
||||||
"Supernova" : weather("Supernova", "🌟"),
|
|
||||||
"Midnight": weather("Midnight", "🕶"),
|
|
||||||
"Slight Tailwind": weather("Slight Tailwind", "🏌️♀️"),
|
|
||||||
"Heavy Snow": weather("Heavy Snow", "❄"),
|
|
||||||
"Twilight" : weather("Twilight", "👻"),
|
|
||||||
"Thinned Veil" : weather("Thinned Veil", "🌌"),
|
|
||||||
"Heat Wave" : weather("Heat Wave", "🌄"),
|
|
||||||
"Drizzle" : weather("Drizzle", "🌧")
|
|
||||||
}
|
|
||||||
return weathers_dic
|
|
||||||
|
|
||||||
class appearance_outcomes(Enum):
|
|
||||||
strikeoutlooking = "strikes out looking."
|
|
||||||
strikeoutswinging = "strikes out swinging."
|
|
||||||
groundout = "grounds out to"
|
|
||||||
flyout = "flies out to"
|
|
||||||
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."
|
|
||||||
single = "hits a single!"
|
|
||||||
double = "hits a double!"
|
|
||||||
triple = "hits a triple!"
|
|
||||||
homerun = "hits a dinger!"
|
|
||||||
grandslam = "hits a grand slam!"
|
|
||||||
|
|
||||||
|
|
||||||
class player(object):
|
class player(object):
|
||||||
def __init__(self, json_string):
|
def __init__(self, json_string):
|
||||||
|
@ -240,27 +213,30 @@ class game(object):
|
||||||
self.outs = 0
|
self.outs = 0
|
||||||
self.top_of_inning = True
|
self.top_of_inning = True
|
||||||
self.last_update = ({},0) #this is a ({outcome}, runs) tuple
|
self.last_update = ({},0) #this is a ({outcome}, runs) tuple
|
||||||
|
self.play_has_begun = False
|
||||||
self.owner = None
|
self.owner = None
|
||||||
self.ready = False
|
|
||||||
self.victory_lap = False
|
self.victory_lap = False
|
||||||
if length is not None:
|
if length is not None:
|
||||||
self.max_innings = length
|
self.max_innings = length
|
||||||
else:
|
else:
|
||||||
self.max_innings = config()["default_length"]
|
self.max_innings = config()["default_length"]
|
||||||
self.bases = {1 : None, 2 : None, 3 : None}
|
self.bases = {1 : None, 2 : None, 3 : None}
|
||||||
self.weather = weather("Sunny","🌞")
|
self.weather = weather.Weather(self)
|
||||||
|
self.current_batter = None
|
||||||
|
|
||||||
def get_batter(self):
|
def choose_next_batter(self):
|
||||||
if self.top_of_inning:
|
if self.top_of_inning:
|
||||||
bat_team = self.teams["away"]
|
bat_team = self.teams["away"]
|
||||||
counter = self.weather.counter_away
|
|
||||||
else:
|
else:
|
||||||
bat_team = self.teams["home"]
|
bat_team = self.teams["home"]
|
||||||
counter = self.weather.counter_home
|
|
||||||
|
|
||||||
if self.weather.name == "Heavy Snow" and counter == bat_team.lineup_position:
|
self.current_batter = bat_team.lineup[bat_team.lineup_position % len(bat_team.lineup)]
|
||||||
return bat_team.pitcher
|
self.weather.on_choose_next_batter(self)
|
||||||
return bat_team.lineup[bat_team.lineup_position % len(bat_team.lineup)]
|
|
||||||
|
def get_batter(self):
|
||||||
|
if self.current_batter == None:
|
||||||
|
self.choose_next_batter()
|
||||||
|
return self.current_batter
|
||||||
|
|
||||||
def get_pitcher(self):
|
def get_pitcher(self):
|
||||||
if self.top_of_inning:
|
if self.top_of_inning:
|
||||||
|
@ -284,38 +260,34 @@ class game(object):
|
||||||
outcome["batter"] = batter
|
outcome["batter"] = batter
|
||||||
outcome["defender"] = ""
|
outcome["defender"] = ""
|
||||||
|
|
||||||
bat_stat = random_star_gen("batting_stars", batter)
|
player_rolls = {}
|
||||||
pitch_stat = random_star_gen("pitching_stars", pitcher)
|
player_rolls["bat_stat"] = random_star_gen("batting_stars", batter)
|
||||||
if weather.name == "Supernova":
|
player_rolls["pitch_stat"] = random_star_gen("pitching_stars", pitcher)
|
||||||
pitch_stat = pitch_stat * 0.9
|
|
||||||
|
|
||||||
pb_system_stat = (random.gauss(1*math.erf((bat_stat - pitch_stat)*1.5)-1.8,2.2))
|
self.weather.modify_atbat_stats(player_rolls)
|
||||||
hitnum = random.gauss(2*math.erf(bat_stat/4)-1,3)
|
|
||||||
|
|
||||||
if self.weather.name == "Twilight":
|
roll = {}
|
||||||
error_line = - (math.log(defender.stlats["defense_stars"] + 1)/50) + 1
|
roll["pb_system_stat"] = (random.gauss(1*math.erf((player_rolls["bat_stat"] - player_rolls["pitch_stat"])*1.5)-1.8,2.2))
|
||||||
error_roll = random.random()
|
roll["hitnum"] = random.gauss(2*math.erf(player_rolls["bat_stat"]/4)-1,3)
|
||||||
if error_roll > error_line:
|
|
||||||
outcome["error"] = True
|
self.weather.modify_atbat_roll(outcome, roll, defender)
|
||||||
outcome["defender"] = defender
|
|
||||||
pb_system_stat = 0.1
|
|
||||||
|
|
||||||
|
|
||||||
if pb_system_stat <= 0:
|
if roll["pb_system_stat"] <= 0:
|
||||||
outcome["ishit"] = False
|
outcome["ishit"] = False
|
||||||
fc_flag = False
|
fc_flag = False
|
||||||
if hitnum < -1.5:
|
if roll["hitnum"] < -1.5:
|
||||||
outcome["text"] = random.choice([appearance_outcomes.strikeoutlooking, appearance_outcomes.strikeoutswinging])
|
outcome["text"] = random.choice([appearance_outcomes.strikeoutlooking, appearance_outcomes.strikeoutswinging])
|
||||||
elif hitnum < 1:
|
elif roll["hitnum"] < 1:
|
||||||
outcome["text"] = appearance_outcomes.groundout
|
outcome["text"] = appearance_outcomes.groundout
|
||||||
outcome["defender"] = defender
|
outcome["defender"] = defender
|
||||||
elif hitnum < 4:
|
elif roll["hitnum"] < 4:
|
||||||
outcome["text"] = appearance_outcomes.flyout
|
outcome["text"] = appearance_outcomes.flyout
|
||||||
outcome["defender"] = defender
|
outcome["defender"] = defender
|
||||||
else:
|
else:
|
||||||
outcome["text"] = appearance_outcomes.walk
|
outcome["text"] = appearance_outcomes.walk
|
||||||
|
|
||||||
if self.bases[1] is not None and hitnum < -2 and self.outs != 2:
|
if self.bases[1] is not None and roll["hitnum"] < -2 and self.outs != 2:
|
||||||
outcome["text"] = appearance_outcomes.doubleplay
|
outcome["text"] = appearance_outcomes.doubleplay
|
||||||
outcome["defender"] = ""
|
outcome["defender"] = ""
|
||||||
|
|
||||||
|
@ -332,20 +304,20 @@ class game(object):
|
||||||
|
|
||||||
if self.outs < 2 and len(runners) > 1: #fielder's choice replaces not great groundouts if any forceouts are present
|
if self.outs < 2 and len(runners) > 1: #fielder's choice replaces not great groundouts if any forceouts are present
|
||||||
def_stat = random_star_gen("defense_stars", defender)
|
def_stat = random_star_gen("defense_stars", defender)
|
||||||
if -1.5 <= hitnum and hitnum < -0.5: #poorly hit groundouts
|
if -1.5 <= roll["hitnum"] and roll["hitnum"] < -0.5: #poorly hit groundouts
|
||||||
outcome["text"] = appearance_outcomes.fielderschoice
|
outcome["text"] = appearance_outcomes.fielderschoice
|
||||||
outcome["defender"] = ""
|
outcome["defender"] = ""
|
||||||
|
|
||||||
if 2.5 <= hitnum and self.outs < 2: #well hit flyouts can lead to sacrifice flies/advanced runners
|
if 2.5 <= roll["hitnum"] and self.outs < 2: #well hit flyouts can lead to sacrifice flies/advanced runners
|
||||||
if self.bases[2] is not None or self.bases[3] is not None:
|
if self.bases[2] is not None or self.bases[3] is not None:
|
||||||
outcome["advance"] = True
|
outcome["advance"] = True
|
||||||
else:
|
else:
|
||||||
outcome["ishit"] = True
|
outcome["ishit"] = True
|
||||||
if hitnum < 1:
|
if roll["hitnum"] < 1:
|
||||||
outcome["text"] = appearance_outcomes.single
|
outcome["text"] = appearance_outcomes.single
|
||||||
elif hitnum < 2.85 or "error" in outcome.keys():
|
elif roll["hitnum"] < 2.85 or "error" in outcome.keys():
|
||||||
outcome["text"] = appearance_outcomes.double
|
outcome["text"] = appearance_outcomes.double
|
||||||
elif hitnum < 3.1:
|
elif roll["hitnum"] < 3.1:
|
||||||
outcome["text"] = appearance_outcomes.triple
|
outcome["text"] = appearance_outcomes.triple
|
||||||
else:
|
else:
|
||||||
if self.bases[1] is not None and self.bases[2] is not None and self.bases[3] is not None:
|
if self.bases[1] is not None and self.bases[2] is not None and self.bases[3] is not None:
|
||||||
|
@ -362,13 +334,16 @@ class game(object):
|
||||||
if self.bases[base+1] is None: #if there's somewhere to go
|
if self.bases[base+1] is None: #if there's somewhere to go
|
||||||
thieves.append((self.bases[base], base))
|
thieves.append((self.bases[base], base))
|
||||||
for baserunner, start_base in thieves:
|
for baserunner, start_base in thieves:
|
||||||
run_stars = random_star_gen("baserunning_stars", baserunner)*config()["stolen_base_chance_mod"]
|
stats = {
|
||||||
if self.weather.name == "Midnight":
|
"run_stars": random_star_gen("baserunning_stars", baserunner)*config()["stolen_base_chance_mod"],
|
||||||
run_stars = run_stars*2
|
"def_stars": random_star_gen("defense_stars", self.get_pitcher())
|
||||||
def_stars = random_star_gen("defense_stars", self.get_pitcher())
|
}
|
||||||
if run_stars >= (def_stars - 1.5): #if baserunner isn't worse than pitcher
|
|
||||||
|
self.weather.modify_steal_stats(stats)
|
||||||
|
|
||||||
|
if stats["run_stars"] >= (stats["def_stars"] - 1.5): #if baserunner isn't worse than pitcher
|
||||||
roll = random.random()
|
roll = random.random()
|
||||||
if roll >= (-(((run_stars+1)/14)**2)+1): #plug it into desmos or something, you'll see
|
if roll >= (-(((stats["run_stars"]+1)/14)**2)+1): #plug it into desmos or something, you'll see
|
||||||
attempts.append((baserunner, start_base))
|
attempts.append((baserunner, start_base))
|
||||||
|
|
||||||
if len(attempts) == 0:
|
if len(attempts) == 0:
|
||||||
|
@ -533,25 +508,19 @@ class game(object):
|
||||||
def batterup(self):
|
def batterup(self):
|
||||||
scores_to_add = 0
|
scores_to_add = 0
|
||||||
result = self.at_bat()
|
result = self.at_bat()
|
||||||
|
|
||||||
|
self.weather.activate(self, result) # possibly modify result in-place
|
||||||
|
|
||||||
|
if "text_only" in result:
|
||||||
|
return (result, 0)
|
||||||
|
|
||||||
if self.top_of_inning:
|
if self.top_of_inning:
|
||||||
offense_team = self.teams["away"]
|
offense_team = self.teams["away"]
|
||||||
weather_count = self.weather.counter_away
|
|
||||||
defense_team = self.teams["home"]
|
defense_team = self.teams["home"]
|
||||||
else:
|
else:
|
||||||
offense_team = self.teams["home"]
|
offense_team = self.teams["home"]
|
||||||
weather_count = self.weather.counter_home
|
|
||||||
defense_team = self.teams["away"]
|
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"])-5)/6)**2)+1
|
|
||||||
if random.random() > mulligan_roll_target and self.get_batter().stlats["batting_stars"] <= 5:
|
|
||||||
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 = defense_team.lineup.copy()
|
||||||
defenders.append(defense_team.pitcher)
|
defenders.append(defense_team.pitcher)
|
||||||
|
@ -570,8 +539,6 @@ class game(object):
|
||||||
elif result["text"] == appearance_outcomes.homerun or result["text"] == appearance_outcomes.grandslam:
|
elif result["text"] == appearance_outcomes.homerun or result["text"] == appearance_outcomes.grandslam:
|
||||||
self.get_batter().game_stats["total_bases"] += 4
|
self.get_batter().game_stats["total_bases"] += 4
|
||||||
self.get_batter().game_stats["home_runs"] += 1
|
self.get_batter().game_stats["home_runs"] += 1
|
||||||
if self.weather.name == "Thinned Veil":
|
|
||||||
result["veil"] = True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -636,27 +603,10 @@ class game(object):
|
||||||
self.get_batter().game_stats["rbis"] += scores_to_add
|
self.get_batter().game_stats["rbis"] += scores_to_add
|
||||||
self.get_pitcher().game_stats["runs_allowed"] += scores_to_add
|
self.get_pitcher().game_stats["runs_allowed"] += scores_to_add
|
||||||
offense_team.lineup_position += 1 #put next batter up
|
offense_team.lineup_position += 1 #put next batter up
|
||||||
|
self.choose_next_batter()
|
||||||
if self.outs >= 3:
|
if self.outs >= 3:
|
||||||
self.flip_inning()
|
self.flip_inning()
|
||||||
if self.weather.name == "Heat Wave":
|
|
||||||
if self.top_of_inning:
|
|
||||||
self.weather.home_pitcher = self.get_pitcher()
|
|
||||||
if self.inning >= self.weather.counter_home:
|
|
||||||
self.weather.counter_home = self.weather.counter_home - (self.weather.counter_home % 5) + 5 + random.randint(1,4) #rounds down to last 5, adds up to next 5. then adds a random number 2<=x<=5 to determine next pitcher
|
|
||||||
tries = 0
|
|
||||||
while self.get_pitcher() == self.weather.home_pitcher and tries < 3:
|
|
||||||
self.teams["home"].set_pitcher(use_lineup = True)
|
|
||||||
tries += 1
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
self.weather.away_pitcher = self.get_pitcher()
|
|
||||||
if self.inning >= self.weather.counter_away:
|
|
||||||
self.weather.counter_away = self.weather.counter_away - (self.weather.counter_away % 5) + 5 + random.randint(1,4)
|
|
||||||
tries = 0
|
|
||||||
while self.get_pitcher() == self.weather.away_pitcher and tries < 3:
|
|
||||||
self.teams["away"].set_pitcher(use_lineup = True)
|
|
||||||
tries += 1
|
|
||||||
|
|
||||||
|
|
||||||
return (result, scores_to_add) #returns ab information and scores
|
return (result, scores_to_add) #returns ab information and scores
|
||||||
|
@ -665,28 +615,19 @@ class game(object):
|
||||||
for base in self.bases.keys():
|
for base in self.bases.keys():
|
||||||
self.bases[base] = None
|
self.bases[base] = None
|
||||||
self.outs = 0
|
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:
|
self.top_of_inning = 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.weather.on_flip_inning(self)
|
||||||
|
|
||||||
|
self.choose_next_batter()
|
||||||
|
|
||||||
|
if self.top_of_inning:
|
||||||
self.inning += 1
|
self.inning += 1
|
||||||
if self.inning > self.max_innings and self.teams["home"].score != self.teams["away"].score: #game over
|
if self.inning > self.max_innings and self.teams["home"].score != self.teams["away"].score: #game over
|
||||||
self.over = True
|
self.over = True
|
||||||
#do the One Big League stuff here
|
#do the One Big League stuff here
|
||||||
self.top_of_inning = not self.top_of_inning
|
|
||||||
|
|
||||||
if self.weather.name == "Drizzle":
|
|
||||||
if self.top_of_inning:
|
|
||||||
self.bases[2] = self.teams["away"].lineup[(self.teams["away"].lineup_position-1) % len(self.teams["away"].lineup)]
|
|
||||||
else:
|
|
||||||
self.bases[2] = self.teams["home"].lineup[(self.teams["home"].lineup_position-1) % len(self.teams["home"].lineup)]
|
|
||||||
|
|
||||||
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):
|
def end_of_game_report(self):
|
||||||
return {
|
return {
|
||||||
|
@ -708,6 +649,7 @@ class game(object):
|
||||||
|
|
||||||
|
|
||||||
def gamestate_update_full(self):
|
def gamestate_update_full(self):
|
||||||
|
self.play_has_begun = True
|
||||||
attempts = self.thievery_attempts()
|
attempts = self.thievery_attempts()
|
||||||
if attempts == False:
|
if attempts == False:
|
||||||
self.last_update = self.batterup()
|
self.last_update = self.batterup()
|
||||||
|
@ -716,29 +658,10 @@ class game(object):
|
||||||
return self.gamestate_display_full()
|
return self.gamestate_display_full()
|
||||||
|
|
||||||
def gamestate_display_full(self):
|
def gamestate_display_full(self):
|
||||||
if "steals" in self.last_update[0].keys():
|
if not self.over:
|
||||||
return "Still in progress."
|
return "Still in progress."
|
||||||
else:
|
else:
|
||||||
try:
|
return f"""Game over! Final score: **{self.teams['away'].score} - {self.teams['home'].score}**"""
|
||||||
punc = ""
|
|
||||||
if self.last_update[0]["defender"] != "":
|
|
||||||
punc = "."
|
|
||||||
if not self.over:
|
|
||||||
if self.top_of_inning:
|
|
||||||
inningtext = "top"
|
|
||||||
else:
|
|
||||||
inningtext = "bottom"
|
|
||||||
|
|
||||||
updatestring = "this isn't used but i don't want to break anything"
|
|
||||||
|
|
||||||
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}"""
|
|
||||||
except TypeError:
|
|
||||||
return "Game not started."
|
|
||||||
except KeyError:
|
|
||||||
return "Game not started."
|
|
||||||
|
|
||||||
def add_stats(self):
|
def add_stats(self):
|
||||||
players = self.get_stats()
|
players = self.get_stats()
|
||||||
|
@ -868,26 +791,3 @@ def search_team(search_term):
|
||||||
|
|
||||||
teams.append(team_json)
|
teams.append(team_json)
|
||||||
return teams
|
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 "None"
|
|
||||||
|
|
||||||
class weather(object):
|
|
||||||
name = "Sunny"
|
|
||||||
emoji = "🌞"
|
|
||||||
|
|
||||||
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}"
|
|
||||||
|
|
27
gametext.py
Normal file
27
gametext.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class appearance_outcomes(Enum):
|
||||||
|
strikeoutlooking = "strikes out looking."
|
||||||
|
strikeoutswinging = "strikes out swinging."
|
||||||
|
groundout = "grounds out to"
|
||||||
|
flyout = "flies out to"
|
||||||
|
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."
|
||||||
|
single = "hits a single!"
|
||||||
|
double = "hits a double!"
|
||||||
|
triple = "hits a triple!"
|
||||||
|
homerun = "hits a dinger!"
|
||||||
|
grandslam = "hits a grand slam!"
|
||||||
|
|
||||||
|
def base_string(base):
|
||||||
|
if base == 1:
|
||||||
|
return "first"
|
||||||
|
elif base == 2:
|
||||||
|
return "second"
|
||||||
|
elif base == 3:
|
||||||
|
return "third"
|
||||||
|
elif base == 4:
|
||||||
|
return "None"
|
||||||
|
|
|
@ -140,7 +140,7 @@ def update_loop():
|
||||||
state["away_score"] = this_game.teams["away"].score #top_of_inning = True
|
state["away_score"] = this_game.teams["away"].score #top_of_inning = True
|
||||||
state["home_score"] = this_game.teams["home"].score #update_pause = 0
|
state["home_score"] = this_game.teams["home"].score #update_pause = 0
|
||||||
#victory_lap = False
|
#victory_lap = False
|
||||||
if test_string == "Game not started.": #weather_emoji
|
if not this_game.play_has_begun: #weather_emoji
|
||||||
state["update_emoji"] = "🍿" #weather_text
|
state["update_emoji"] = "🍿" #weather_text
|
||||||
state["update_text"] = "Play blall!" #they also need a timestamp
|
state["update_text"] = "Play blall!" #they also need a timestamp
|
||||||
state["start_delay"] -= 1
|
state["start_delay"] -= 1
|
||||||
|
@ -156,9 +156,9 @@ def update_loop():
|
||||||
state["display_inning"] -= 1
|
state["display_inning"] -= 1
|
||||||
state["display_top_of_inning"] = False
|
state["display_top_of_inning"] = False
|
||||||
|
|
||||||
if state["update_pause"] == 1:
|
if state["update_pause"] == 1: #generate the top of the inning message before displaying the at bat result
|
||||||
state["update_emoji"] = "🍿"
|
state["update_emoji"] = "🍿"
|
||||||
if this_game.over:
|
if this_game.over: # game over message
|
||||||
state["display_inning"] -= 1
|
state["display_inning"] -= 1
|
||||||
state["display_top_of_inning"] = False
|
state["display_top_of_inning"] = False
|
||||||
winning_team = this_game.teams['home'].name if this_game.teams['home'].score > this_game.teams['away'].score else this_game.teams['away'].name
|
winning_team = this_game.teams['home'].name if this_game.teams['home'].score > this_game.teams['away'].score else this_game.teams['away'].name
|
||||||
|
@ -170,28 +170,23 @@ def update_loop():
|
||||||
state["update_text"] = f"{winning_team} wins!"
|
state["update_text"] = f"{winning_team} wins!"
|
||||||
state["pitcher"] = "-"
|
state["pitcher"] = "-"
|
||||||
state["batter"] = "-"
|
state["batter"] = "-"
|
||||||
elif this_game.top_of_inning:
|
|
||||||
state["update_text"] = f"Top of {this_game.inning}. {this_game.teams['away'].name} batting!"
|
|
||||||
if this_game.weather.name == "Drizzle":
|
|
||||||
state["update_emoji"] = "🌧"
|
|
||||||
state["update_text"] += f' Due to inclement weather, {this_game.teams["away"].lineup[(this_game.teams["away"].lineup_position-1) % len(this_game.teams["away"].lineup)].name} is placed on second base.'
|
|
||||||
elif this_game.weather.name == "Heat Wave" and hasattr(this_game.weather, "home_pitcher") and this_game.weather.home_pitcher.name != state["pitcher"]:
|
|
||||||
state["update_emoji"] = "🌄"
|
|
||||||
state["update_text"] += f' {this_game.weather.home_pitcher} is exhausted from the heat. {state["pitcher"]} is forced to pitch!'
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if this_game.inning >= this_game.max_innings:
|
if this_game.top_of_inning:
|
||||||
if this_game.teams["home"].score > this_game.teams["away"].score:
|
state["update_text"] = f"Top of {this_game.inning}. {this_game.teams['away'].name} batting!"
|
||||||
this_game.victory_lap = True
|
else:
|
||||||
state["update_text"] = f"Bottom of {this_game.inning}. {this_game.teams['home'].name} batting!"
|
if this_game.inning >= this_game.max_innings:
|
||||||
if this_game.weather.name == "Drizzle":
|
if this_game.teams["home"].score > this_game.teams["away"].score:
|
||||||
state["update_emoji"] = "🌧"
|
this_game.victory_lap = True
|
||||||
state["update_text"] += f' Due to inclement weather, {this_game.teams["home"].lineup[(this_game.teams["home"].lineup_position-1) % len(this_game.teams["home"].lineup)].name} is placed on second base.'
|
state["update_text"] = f"Bottom of {this_game.inning}. {this_game.teams['home'].name} batting!"
|
||||||
elif this_game.weather.name == "Heat Wave" and hasattr(this_game.weather, "away_pitcher") and this_game.weather.away_pitcher.name != state["pitcher"]:
|
|
||||||
state["update_emoji"] = "🌄"
|
this_game.weather.modify_top_of_inning_message(this_game, state)
|
||||||
state["update_text"] += f' {this_game.weather.away_pitcher} is exhausted from the heat. {state["pitcher"]} is forced to pitch!'
|
|
||||||
|
|
||||||
|
elif state["update_pause"] != 1 and this_game.play_has_begun:
|
||||||
|
|
||||||
|
if "weather_message" in this_game.last_update[0].keys():
|
||||||
|
state["update_emoji"] = this_game.weather.emoji
|
||||||
|
|
||||||
elif state["update_pause"] != 1 and test_string != "Game not started.":
|
|
||||||
if "steals" in this_game.last_update[0].keys():
|
if "steals" in this_game.last_update[0].keys():
|
||||||
updatestring = ""
|
updatestring = ""
|
||||||
for attempt in this_game.last_update[0]["steals"]:
|
for attempt in this_game.last_update[0]["steals"]:
|
||||||
|
@ -200,30 +195,17 @@ def update_loop():
|
||||||
state["update_emoji"] = "💎"
|
state["update_emoji"] = "💎"
|
||||||
state["update_text"] = updatestring
|
state["update_text"] = updatestring
|
||||||
|
|
||||||
elif "mulligan" in this_game.last_update[0].keys():
|
elif "text_only" in this_game.last_update[0].keys(): #this handles many weather messages
|
||||||
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"]
|
state["update_text"] = this_game.last_update[0]["text"]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
updatestring = ""
|
updatestring = ""
|
||||||
punc = ""
|
punc = ""
|
||||||
if this_game.last_update[0]["defender"] != "":
|
if this_game.last_update[0]["defender"] != "":
|
||||||
punc = ". "
|
punc = ". "
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if "fc_out" in this_game.last_update[0].keys():
|
if "fc_out" in this_game.last_update[0].keys():
|
||||||
name, base_string = this_game.last_update[0]['fc_out']
|
name, out_at_base_string = this_game.last_update[0]['fc_out']
|
||||||
updatestring = f"{this_game.last_update[0]['batter']} {this_game.last_update[0]['text'].value.format(name, base_string)} {this_game.last_update[0]['defender']}{punc}"
|
updatestring = f"{this_game.last_update[0]['batter']} {this_game.last_update[0]['text'].value.format(name, out_at_base_string)} {this_game.last_update[0]['defender']}{punc}"
|
||||||
else:
|
else:
|
||||||
updatestring = f"{this_game.last_update[0]['batter']} {this_game.last_update[0]['text'].value} {this_game.last_update[0]['defender']}{punc}"
|
updatestring = f"{this_game.last_update[0]['batter']} {this_game.last_update[0]['text'].value} {this_game.last_update[0]['defender']}{punc}"
|
||||||
if this_game.last_update[1] > 0:
|
if this_game.last_update[1] > 0:
|
||||||
|
@ -231,15 +213,8 @@ def update_loop():
|
||||||
|
|
||||||
state["update_emoji"] = "🏏"
|
state["update_emoji"] = "🏏"
|
||||||
state["update_text"] = updatestring
|
state["update_text"] = updatestring
|
||||||
|
|
||||||
if "veil" in this_game.last_update[0].keys():
|
this_game.weather.modify_atbat_message(this_game, state)
|
||||||
state["update_emoji"] = "🌌"
|
|
||||||
state["update_text"] += f" {this_game.last_update[0]['batter']}'s will manifests on {games.base_string(this_game.last_update[1])} base."
|
|
||||||
elif "error" in this_game.last_update[0].keys():
|
|
||||||
state["update_emoji"] = "👻"
|
|
||||||
state["update_text"] = f"{this_game.last_update[0]['batter']}'s hit goes ethereal, and {this_game.last_update[0]['defender']} can't catch it! {this_game.last_update[0]['batter']} reaches base safely."
|
|
||||||
if this_game.last_update[1] > 0:
|
|
||||||
updatestring += f"{this_game.last_update[1]} runs scored!"
|
|
||||||
|
|
||||||
state["bases"] = this_game.named_bases()
|
state["bases"] = this_game.named_bases()
|
||||||
|
|
||||||
|
@ -261,4 +236,4 @@ def update_loop():
|
||||||
state["update_pause"] -= 1
|
state["update_pause"] -= 1
|
||||||
|
|
||||||
socketio.emit("states_update", game_states)
|
socketio.emit("states_update", game_states)
|
||||||
time.sleep(8)
|
time.sleep(8)
|
||||||
|
|
|
@ -5,6 +5,7 @@ from league_storage import league_exists, season_save, season_restart
|
||||||
from the_draft import Draft, DRAFT_ROUNDS
|
from the_draft import Draft, DRAFT_ROUNDS
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
import weather
|
||||||
|
|
||||||
data_dir = "data"
|
data_dir = "data"
|
||||||
config_filename = os.path.join(data_dir, "config.json")
|
config_filename = os.path.join(data_dir, "config.json")
|
||||||
|
@ -189,8 +190,8 @@ class StartGameCommand(Command):
|
||||||
game.teams['home'].set_pitcher(rotation_slot = day)
|
game.teams['home'].set_pitcher(rotation_slot = day)
|
||||||
channel = msg.channel
|
channel = msg.channel
|
||||||
|
|
||||||
if weather_name is not None and weather_name in games.all_weathers().keys():
|
if weather_name is not None and weather_name in weather.all_weathers().keys():
|
||||||
game.weather = games.all_weathers()[weather_name]
|
game.weather = weather.all_weathers()[weather_name](game)
|
||||||
|
|
||||||
|
|
||||||
game_task = asyncio.create_task(watch_game(channel, game, user=msg.author, league=league))
|
game_task = asyncio.create_task(watch_game(channel, game, user=msg.author, league=league))
|
||||||
|
@ -1516,9 +1517,9 @@ async def watch_game(channel, newgame, user = None, league = None):
|
||||||
main_controller.master_games_dic[id] = (newgame, state_init, discrim_string)
|
main_controller.master_games_dic[id] = (newgame, state_init, discrim_string)
|
||||||
|
|
||||||
def prepare_game(newgame, league = None, weather_name = None):
|
def prepare_game(newgame, league = None, weather_name = None):
|
||||||
if weather_name is None and newgame.weather.name == "Sunny": #if no weather name supplied and the game's weather is default, pick random weather
|
if weather_name is None and newgame.weather.name == "Sunny":
|
||||||
weathers = games.all_weathers()
|
weathers = weather.all_weathers()
|
||||||
newgame.weather = weathers[random.choice(list(weathers.keys()))]
|
newgame.weather = weathers[random.choice(list(weathers.keys()))](newgame)
|
||||||
|
|
||||||
state_init = {
|
state_init = {
|
||||||
"away_name" : newgame.teams['away'].name,
|
"away_name" : newgame.teams['away'].name,
|
||||||
|
@ -1538,12 +1539,6 @@ def prepare_game(newgame, league = None, weather_name = None):
|
||||||
else:
|
else:
|
||||||
state_init["is_league"] = True
|
state_init["is_league"] = True
|
||||||
|
|
||||||
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)
|
|
||||||
elif newgame.weather.name == "Heat Wave":
|
|
||||||
newgame.weather.counter_away = random.randint(2,4)
|
|
||||||
newgame.weather.counter_home = random.randint(2,4)
|
|
||||||
return newgame, state_init
|
return newgame, state_init
|
||||||
|
|
||||||
async def start_tournament_round(channel, tourney, seeding = None):
|
async def start_tournament_round(channel, tourney, seeding = None):
|
||||||
|
|
341
weather.py
Normal file
341
weather.py
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
import random
|
||||||
|
import math
|
||||||
|
from gametext import appearance_outcomes, base_string
|
||||||
|
|
||||||
|
class Weather:
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Sunny"
|
||||||
|
self.emoji = "🌞"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.emoji} {self.name}"
|
||||||
|
|
||||||
|
def modify_atbat_stats(self, player_rolls):
|
||||||
|
# Activates before batting
|
||||||
|
pass
|
||||||
|
|
||||||
|
def modify_steal_stats(self, roll):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def modify_atbat_roll(self, outcome, roll, defender):
|
||||||
|
# activates after batter roll
|
||||||
|
pass
|
||||||
|
|
||||||
|
def activate(self, game, result):
|
||||||
|
# activates after the batter calculation. modify result, or just return another thing
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_choose_next_batter(self, game):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_flip_inning(self, game):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def modify_top_of_inning_message(self, game, state):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def modify_atbat_message(self, game, state):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Supernova(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Supernova"
|
||||||
|
self.emoji = "🌟"
|
||||||
|
|
||||||
|
def modify_atbat_stats(self, roll):
|
||||||
|
roll["pitch_stat"] *= 0.9
|
||||||
|
|
||||||
|
class Midnight(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Midnight"
|
||||||
|
self.emoji = "🕶"
|
||||||
|
|
||||||
|
def modify_steal_stats(self, roll):
|
||||||
|
roll["run_stars"] *= 2
|
||||||
|
|
||||||
|
class SlightTailwind(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Slight Tailwind"
|
||||||
|
self.emoji = "🏌️♀️"
|
||||||
|
|
||||||
|
def activate(self, game, result):
|
||||||
|
if game.top_of_inning:
|
||||||
|
offense_team = game.teams["away"]
|
||||||
|
defense_team = game.teams["home"]
|
||||||
|
else:
|
||||||
|
offense_team = game.teams["home"]
|
||||||
|
defense_team = game.teams["away"]
|
||||||
|
|
||||||
|
if "mulligan" not in game.last_update[0].keys() and not result["ishit"] and result["text"] != appearance_outcomes.walk:
|
||||||
|
mulligan_roll_target = -((((game.get_batter().stlats["batting_stars"])-5)/6)**2)+1
|
||||||
|
if random.random() > mulligan_roll_target and game.get_batter().stlats["batting_stars"] <= 5:
|
||||||
|
result.clear()
|
||||||
|
result.update({
|
||||||
|
"text": f"{game.get_batter()} would have gone out, but they took a mulligan!",
|
||||||
|
"text_only": True,
|
||||||
|
"weather_message": True,
|
||||||
|
})
|
||||||
|
|
||||||
|
class HeavySnow(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Heavy Snow"
|
||||||
|
self.emoji = "❄"
|
||||||
|
self.counter_away = random.randint(0,len(game.teams['away'].lineup)-1)
|
||||||
|
self.counter_home = random.randint(0,len(game.teams['home'].lineup)-1)
|
||||||
|
|
||||||
|
self.swapped_batter_data = None
|
||||||
|
|
||||||
|
def activate(self, game, result):
|
||||||
|
if self.swapped_batter_data:
|
||||||
|
original, sub = self.swapped_batter_data
|
||||||
|
self.swapped_batter_data = None
|
||||||
|
result.clear()
|
||||||
|
result.update({
|
||||||
|
"snow_atbat": True,
|
||||||
|
"text": f"{original.name}'s hands are too cold! {sub.name} is forced to bat!",
|
||||||
|
"text_only": True,
|
||||||
|
"weather_message": True,
|
||||||
|
})
|
||||||
|
|
||||||
|
def on_flip_inning(self, game):
|
||||||
|
if game.top_of_inning and self.counter_away < game.teams["away"].lineup_position:
|
||||||
|
self.counter_away = self.pitcher_insert_index(game.teams["away"])
|
||||||
|
|
||||||
|
if not game.top_of_inning and self.counter_home < game.teams["home"].lineup_position:
|
||||||
|
self.counter_home = self.pitcher_insert_index(game.teams["home"])
|
||||||
|
|
||||||
|
def pitcher_insert_index(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 on_choose_next_batter(self, game):
|
||||||
|
if game.top_of_inning:
|
||||||
|
bat_team = game.teams["away"]
|
||||||
|
counter = self.counter_away
|
||||||
|
else:
|
||||||
|
bat_team = game.teams["home"]
|
||||||
|
counter = self.counter_home
|
||||||
|
|
||||||
|
if bat_team.lineup_position == counter:
|
||||||
|
self.swapped_batter_data = (game.current_batter, bat_team.pitcher) # store this to generate the message during activate()
|
||||||
|
game.current_batter = bat_team.pitcher
|
||||||
|
|
||||||
|
class Twilight(Weather):
|
||||||
|
def __init__(self,game):
|
||||||
|
self.name = "Twilight"
|
||||||
|
self.emoji = "👻"
|
||||||
|
|
||||||
|
def modify_atbat_roll(self, outcome, roll, defender):
|
||||||
|
error_line = - (math.log(defender.stlats["defense_stars"] + 1)/50) + 1
|
||||||
|
error_roll = random.random()
|
||||||
|
if error_roll > error_line:
|
||||||
|
outcome["error"] = True
|
||||||
|
outcome["weather_message"] = True
|
||||||
|
outcome["defender"] = defender
|
||||||
|
roll["pb_system_stat"] = 0.1
|
||||||
|
|
||||||
|
def modify_atbat_message(self, this_game, state):
|
||||||
|
result = this_game.last_update[0]
|
||||||
|
if "error" in result.keys():
|
||||||
|
state["update_text"] = f"{result['batter']}'s hit goes ethereal, and {result['defender']} can't catch it! {result['batter']} reaches base safely."
|
||||||
|
if this_game.last_update[1] > 0:
|
||||||
|
state["update_text"] += f" {this_game.last_update[1]} runs scored!"
|
||||||
|
|
||||||
|
class ThinnedVeil(Weather):
|
||||||
|
def __init__(self,game):
|
||||||
|
self.name = "Thinned Veil"
|
||||||
|
self.emoji = "🌌"
|
||||||
|
|
||||||
|
def activate(self, game, result):
|
||||||
|
if result["ishit"]:
|
||||||
|
if result["text"] == appearance_outcomes.homerun or result["text"] == appearance_outcomes.grandslam:
|
||||||
|
result["veil"] = True
|
||||||
|
|
||||||
|
def modify_atbat_message(self, game, state):
|
||||||
|
if "veil" in game.last_update[0].keys():
|
||||||
|
state["update_emoji"] = self.emoji
|
||||||
|
state["update_text"] += f" {game.last_update[0]['batter']}'s will manifests on {base_string(game.last_update[1])} base."
|
||||||
|
|
||||||
|
class HeatWave(Weather):
|
||||||
|
def __init__(self,game):
|
||||||
|
self.name = "Heat Wave"
|
||||||
|
self.emoji = "🌄"
|
||||||
|
|
||||||
|
self.counter_away = random.randint(2,4)
|
||||||
|
self.counter_home = random.randint(2,4)
|
||||||
|
|
||||||
|
self.swapped_pitcher_data = None
|
||||||
|
|
||||||
|
def on_flip_inning(self, game):
|
||||||
|
original_pitcher = game.get_pitcher()
|
||||||
|
if game.top_of_inning:
|
||||||
|
bat_team = game.teams["home"]
|
||||||
|
counter = self.counter_home
|
||||||
|
else:
|
||||||
|
bat_team = game.teams["away"]
|
||||||
|
counter = self.counter_away
|
||||||
|
|
||||||
|
if game.inning == counter:
|
||||||
|
if game.top_of_inning:
|
||||||
|
self.counter_home = self.counter_home - (self.counter_home % 5) + 5 + random.randint(1,4) #rounds down to last 5, adds up to next 5. then adds a random number 2<=x<=5 to determine next pitcher
|
||||||
|
else:
|
||||||
|
self.counter_away = self.counter_away - (self.counter_away % 5) + 5 + random.randint(1,4)
|
||||||
|
|
||||||
|
#swap, accounting for teams where where someone's both batter and pitcher
|
||||||
|
tries = 0
|
||||||
|
while game.get_pitcher() == original_pitcher and tries < 3:
|
||||||
|
bat_team.set_pitcher(use_lineup = True)
|
||||||
|
tries += 1
|
||||||
|
if game.get_pitcher() != original_pitcher:
|
||||||
|
self.swapped_pitcher_data = (original_pitcher, game.get_pitcher())
|
||||||
|
|
||||||
|
def modify_top_of_inning_message(self, game, state):
|
||||||
|
if self.swapped_pitcher_data:
|
||||||
|
original, sub = self.swapped_pitcher_data
|
||||||
|
self.swapped_pitcher_data = None
|
||||||
|
state["update_emoji"] = self.emoji
|
||||||
|
state["update_text"] += f' {original} is exhausted from the heat. {sub} is forced to pitch!'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Drizzle(Weather):
|
||||||
|
def __init__(self,game):
|
||||||
|
self.name = "Drizzle"
|
||||||
|
self.emoji = "🌧"
|
||||||
|
|
||||||
|
def on_flip_inning(self, game):
|
||||||
|
if game.top_of_inning:
|
||||||
|
next_team = "away"
|
||||||
|
else:
|
||||||
|
next_team = "home"
|
||||||
|
|
||||||
|
lineup = game.teams[next_team].lineup
|
||||||
|
game.bases[2] = lineup[(game.teams[next_team].lineup_position-1) % len(lineup)]
|
||||||
|
|
||||||
|
def modify_top_of_inning_message(self, game, state):
|
||||||
|
if game.top_of_inning:
|
||||||
|
next_team = "away"
|
||||||
|
else:
|
||||||
|
next_team = "home"
|
||||||
|
|
||||||
|
placed_player = game.teams[next_team].lineup[(game.teams[next_team].lineup_position-1) % len(game.teams[next_team].lineup)]
|
||||||
|
|
||||||
|
state["update_emoji"] = self.emoji
|
||||||
|
state["update_text"] += f' Due to inclement weather, {placed_player.name} is placed on second base.'
|
||||||
|
|
||||||
|
|
||||||
|
class Sun2(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Sun 2"
|
||||||
|
|
||||||
|
|
||||||
|
def activate(self, game):
|
||||||
|
for teamtype in game.teams:
|
||||||
|
team = game.teams[teamtype]
|
||||||
|
if team.score >= 10:
|
||||||
|
team.score -= 10
|
||||||
|
# no win counting yet :(
|
||||||
|
result.clear()
|
||||||
|
result.update({
|
||||||
|
"text": "The {} collect 10! Sun 2 smiles.".format(team.name),
|
||||||
|
"text_only": True,
|
||||||
|
"weather_message": True
|
||||||
|
})
|
||||||
|
|
||||||
|
class Breezy(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Breezy"
|
||||||
|
self.emoji = "🎐"
|
||||||
|
self.activation_chance = 0.05
|
||||||
|
|
||||||
|
def activate(self, game, result):
|
||||||
|
if random.random() < self.activation_chance:
|
||||||
|
teamtype = random.choice(["away","home"])
|
||||||
|
team = game.teams[teamtype]
|
||||||
|
player = random.choice(team.lineup)
|
||||||
|
old_player_name = player.name
|
||||||
|
if ' ' in player.name:
|
||||||
|
names = player.name.split(" ")
|
||||||
|
first_first_letter = names[0][0]
|
||||||
|
last_first_letter = names[-1][0]
|
||||||
|
names[0] = last_first_letter + names[0][1:]
|
||||||
|
names[-1] = first_first_letter + names[-1][1:]
|
||||||
|
player.name = ' '.join(names)
|
||||||
|
else:
|
||||||
|
#name is one word, so turn 'bartholemew' into 'martholebew'
|
||||||
|
first_letter = player.name[0]
|
||||||
|
last_letter = player.name[-1]
|
||||||
|
player.name = last_letter + player.name[1:-1] + last_letter
|
||||||
|
|
||||||
|
book_adjectives = ["action-packed", "historical", "friendly", "rude", "mystery", "thriller", "horror", "sci-fi", "fantasy", "spooky","romantic"]
|
||||||
|
book_types = ["novel","novella","poem","anthology","fan fiction","tablet","carving", "autobiography"]
|
||||||
|
book = "{} {}".format(random.choice(book_adjectives),random.choice(book_types))
|
||||||
|
|
||||||
|
result.clear()
|
||||||
|
result.update({
|
||||||
|
"text": "{} stopped to read a {} and became Literate! {} is now {}!".format(old_player_name, book, old_player_name, player.name),
|
||||||
|
"text_only": True,
|
||||||
|
"weather_message": True
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class Feedback(Weather):
|
||||||
|
def __init__(self, game):
|
||||||
|
self.name = "Feedback"
|
||||||
|
self.emoji = "🎤"
|
||||||
|
self.activation_chance = 0.02
|
||||||
|
self.swap_batter_vs_pitcher_chance = 0.8
|
||||||
|
|
||||||
|
def activate(self, game, result):
|
||||||
|
if random.random() < self.activation_chance:
|
||||||
|
# feedback time
|
||||||
|
player1 = None
|
||||||
|
player2 = None
|
||||||
|
team1 = game.teams["home"]
|
||||||
|
team2 = game.teams["away"]
|
||||||
|
if random.random() < self.swap_batter_vs_pitcher_chance:
|
||||||
|
# swapping batters
|
||||||
|
# theoretically this could swap players already on base :(
|
||||||
|
team1 = game.teams["home"]
|
||||||
|
team2 = game.teams["away"]
|
||||||
|
homePlayerIndex = random.randint(0,len(team1.lineup)-1)
|
||||||
|
awayPlayerIndex = random.randint(0,len(team2.lineup)-1)
|
||||||
|
|
||||||
|
player1 = team1.lineup[homePlayerIndex]
|
||||||
|
player2 = team2.lineup[awayPlayerIndex]
|
||||||
|
|
||||||
|
team1.lineup[homePlayerIndex] = player2
|
||||||
|
team2.lineup[awayPlayerIndex] = player1
|
||||||
|
else:
|
||||||
|
# swapping pitchers
|
||||||
|
player1 = team1.pitcher
|
||||||
|
player2 = team2.pitcher
|
||||||
|
|
||||||
|
team1.pitcher = player2
|
||||||
|
team2.pitcher = player1
|
||||||
|
|
||||||
|
result.clear()
|
||||||
|
result.update({
|
||||||
|
"text": "{} and {} switched teams in the feedback!".format(player1.name,player2.name),
|
||||||
|
"text_only": True,
|
||||||
|
"weather_message": True,
|
||||||
|
})
|
||||||
|
|
||||||
|
def all_weathers():
|
||||||
|
weathers_dic = {
|
||||||
|
"Supernova" : Supernova,
|
||||||
|
"Midnight": Midnight,
|
||||||
|
"Slight Tailwind": SlightTailwind,
|
||||||
|
"Heavy Snow": HeavySnow,
|
||||||
|
"Twilight" : Twilight,
|
||||||
|
"Thinned Veil" : ThinnedVeil,
|
||||||
|
"Heat Wave" : HeatWave,
|
||||||
|
"Drizzle" : Drizzle,
|
||||||
|
# "Sun 2": Sun2,
|
||||||
|
"Feedback": Feedback,
|
||||||
|
"Breezy": Breezy,
|
||||||
|
}
|
||||||
|
return weathers_dic
|
||||||
|
|
Loading…
Reference in a new issue