2021-03-03 22:46:15 +00:00
import random , math , roman
2021-02-21 23:15:23 +00:00
from gametext import appearance_outcomes , base_string
2021-02-21 08:03:25 +00:00
class Weather :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Sunny "
2021-02-21 23:45:37 +00:00
self . emoji = " 🌞 "
2021-02-21 08:03:25 +00:00
def __str__ ( self ) :
return f " { self . emoji } { self . name } "
2021-02-21 23:15:23 +00:00
def modify_atbat_stats ( self , player_rolls ) :
# Activates before batting
2021-02-21 08:03:25 +00:00
pass
2021-02-21 23:15:23 +00:00
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
2021-02-21 08:03:25 +00:00
pass
def on_choose_next_batter ( self , game ) :
pass
2021-02-21 23:15:23 +00:00
def on_flip_inning ( self , game ) :
2021-02-21 18:02:47 +00:00
pass
2021-02-21 23:15:23 +00:00
def modify_top_of_inning_message ( self , game , state ) :
2021-02-21 18:02:47 +00:00
pass
2021-02-21 23:15:23 +00:00
def modify_atbat_message ( self , game , state ) :
2021-02-21 18:02:47 +00:00
pass
2021-03-03 22:32:35 +00:00
def modify_gamestate ( self , game , state ) :
pass
2021-03-03 23:26:21 +00:00
def modify_game_end_message ( self , game , state ) :
pass
2021-02-21 23:15:23 +00:00
2021-02-21 23:45:37 +00:00
class Supernova ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Supernova "
2021-02-21 23:45:37 +00:00
self . emoji = " 🌟 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 1 , 2 )
2021-02-21 08:03:25 +00:00
2021-02-21 18:02:47 +00:00
def modify_atbat_stats ( self , roll ) :
2021-02-24 02:33:50 +00:00
roll [ " pitch_stat " ] * = 0.8
2021-02-21 08:03:25 +00:00
2021-02-21 23:45:37 +00:00
class Midnight ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Midnight "
2021-02-21 23:45:37 +00:00
self . emoji = " 🕶 "
2021-03-04 20:34:30 +00:00
self . duration = 1
2021-02-21 18:02:47 +00:00
def modify_steal_stats ( self , roll ) :
roll [ " run_stars " ] * = 2
2021-02-21 08:03:25 +00:00
class SlightTailwind ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Slight Tailwind "
2021-02-21 23:45:37 +00:00
self . emoji = " 🏌️♀️ "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 2 , 4 )
2021-02-21 18:02:47 +00:00
2021-02-21 08:03:25 +00:00
def activate ( self , game , result ) :
if " mulligan " not in game . last_update [ 0 ] . keys ( ) and not result [ " ishit " ] and result [ " text " ] != appearance_outcomes . walk :
2021-02-22 00:37:53 +00:00
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 :
2021-02-21 23:15:23 +00:00
result . clear ( )
result . update ( {
2021-02-22 00:37:53 +00:00
" text " : f " { game . get_batter ( ) } would have gone out, but they took a mulligan! " ,
2021-02-24 02:33:50 +00:00
" mulligan " : True ,
2021-02-21 23:15:23 +00:00
" text_only " : True ,
" weather_message " : True ,
} )
2021-02-21 08:03:25 +00:00
2021-02-25 22:13:14 +00:00
class Starlight ( Weather ) :
def __init__ ( self , game ) :
self . name = " Starlight "
self . emoji = " 🌃 "
2021-03-04 20:34:30 +00:00
self . duration = 2
2021-02-25 22:13:14 +00:00
def activate ( self , game , result ) :
if ( result [ " text " ] == appearance_outcomes . homerun or result [ " text " ] == appearance_outcomes . grandslam ) :
result [ " weather_message " ] = True
dinger_roll = random . random ( )
if " dragon " in game . get_batter ( ) . name . lower ( ) :
result [ " dragin_the_park " ] = True
elif dinger_roll < 0.941 :
result . clear ( )
result . update ( {
" text " : f " { game . get_batter ( ) } hits a dinger, but the stars do not approve! The ball pulls foul. " ,
2021-02-28 18:37:43 +00:00
" text_only " : True ,
" weather_message " : True
2021-02-25 22:13:14 +00:00
} )
else :
result [ " in_the_park " ] = True
def modify_atbat_message ( self , game , state ) :
result = game . last_update [ 0 ]
if " in_the_park " in result . keys ( ) :
state [ " update_text " ] = f " The stars are pleased with { result [ ' batter ' ] } , and allow a dinger! { game . last_update [ 1 ] } runs scored! "
elif " dragin_the_park " in result . keys ( ) :
state [ " update_text " ] = f " The stars enjoy watching dragons play baseball, and allow { result [ ' batter ' ] } to hit a dinger! { game . last_update [ 1 ] } runs scored! "
2021-03-04 20:16:03 +00:00
class Blizzard ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-03-04 20:16:03 +00:00
self . name = " Blizzard "
2021-02-21 23:45:37 +00:00
self . emoji = " ❄ "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 3 , 6 )
2021-02-21 18:02:47 +00:00
self . counter_away = random . randint ( 0 , len ( game . teams [ ' away ' ] . lineup ) - 1 )
self . counter_home = random . randint ( 0 , len ( game . teams [ ' home ' ] . lineup ) - 1 )
2021-02-21 08:03:25 +00:00
2021-02-21 23:15:23 +00:00
self . swapped_batter_data = None
2021-02-21 08:03:25 +00:00
2021-02-21 23:15:23 +00:00
def activate ( self , game , result ) :
if self . swapped_batter_data :
original , sub = self . swapped_batter_data
self . swapped_batter_data = None
2021-02-21 08:03:25 +00:00
result . clear ( )
result . update ( {
2021-02-21 19:56:27 +00:00
" snow_atbat " : True ,
2021-02-21 23:15:23 +00:00
" text " : f " { original . name } ' s hands are too cold! { sub . name } is forced to bat! " ,
2021-02-21 08:03:25 +00:00
" text_only " : True ,
2021-02-21 19:12:34 +00:00
" weather_message " : True ,
2021-02-21 08:03:25 +00:00
} )
def on_flip_inning ( self , game ) :
if game . top_of_inning and self . counter_away < game . teams [ " away " ] . lineup_position :
2021-02-21 23:15:23 +00:00
self . counter_away = self . pitcher_insert_index ( game . teams [ " away " ] )
2021-02-21 08:03:25 +00:00
if not game . top_of_inning and self . counter_home < game . teams [ " home " ] . lineup_position :
2021-02-21 23:15:23 +00:00
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
2021-02-21 08:03:25 +00:00
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
2021-02-21 23:15:23 +00:00
if bat_team . lineup_position == counter :
self . swapped_batter_data = ( game . current_batter , bat_team . pitcher ) # store this to generate the message during activate()
2021-02-21 08:03:25 +00:00
game . current_batter = bat_team . pitcher
class Twilight ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Twilight "
2021-02-21 23:45:37 +00:00
self . emoji = " 👻 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 2 , 3 )
2021-02-21 18:02:47 +00:00
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
2021-02-21 19:12:34 +00:00
outcome [ " weather_message " ] = True
2021-02-21 18:02:47 +00:00
outcome [ " defender " ] = defender
roll [ " pb_system_stat " ] = 0.1
2021-02-21 23:15:23 +00:00
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 :
2021-02-21 23:45:37 +00:00
state [ " update_text " ] + = f " { this_game . last_update [ 1 ] } runs scored! "
2021-02-21 23:15:23 +00:00
2021-02-21 08:03:25 +00:00
class ThinnedVeil ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Thinned Veil "
2021-02-21 23:45:37 +00:00
self . emoji = " 🌌 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 2 , 4 )
2021-02-21 08:03:25 +00:00
def activate ( self , game , result ) :
if result [ " ishit " ] :
if result [ " text " ] == appearance_outcomes . homerun or result [ " text " ] == appearance_outcomes . grandslam :
result [ " veil " ] = True
2021-02-21 23:15:23 +00:00
def modify_atbat_message ( self , game , state ) :
if " veil " in game . last_update [ 0 ] . keys ( ) :
state [ " update_emoji " ] = self . emoji
2021-02-24 22:06:17 +00:00
state [ " update_text " ] + = f " { game . last_update [ 0 ] [ ' batter ' ] } ' s will manifests on { base_string ( game . last_update [ 1 ] ) } base. "
2021-02-21 08:03:25 +00:00
class HeatWave ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Heat Wave "
2021-02-21 23:45:37 +00:00
self . emoji = " 🌄 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 3 , 6 )
2021-02-21 08:03:25 +00:00
2021-02-21 23:15:23 +00:00
self . counter_away = random . randint ( 2 , 4 )
self . counter_home = random . randint ( 2 , 4 )
self . swapped_pitcher_data = None
2021-02-21 08:03:25 +00:00
def on_flip_inning ( self , game ) :
2021-02-21 23:15:23 +00:00
original_pitcher = game . get_pitcher ( )
2021-02-21 08:03:25 +00:00
if game . top_of_inning :
bat_team = game . teams [ " home " ]
counter = self . counter_home
2021-02-21 18:02:47 +00:00
else :
bat_team = game . teams [ " away " ]
counter = self . counter_away
2021-02-21 08:03:25 +00:00
2021-02-21 23:15:23 +00:00
if game . inning == counter :
2021-02-21 08:03:25 +00:00
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 )
2021-02-21 23:15:23 +00:00
#swap, accounting for teams where where someone's both batter and pitcher
2021-02-21 08:03:25 +00:00
tries = 0
2021-02-21 23:15:23 +00:00
while game . get_pitcher ( ) == original_pitcher and tries < 3 :
2021-02-21 08:03:25 +00:00
bat_team . set_pitcher ( use_lineup = True )
tries + = 1
2021-02-21 23:15:23 +00:00
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
2021-02-24 22:06:17 +00:00
state [ " update_text " ] + = f ' { original } is exhausted from the heat. { sub } is forced to pitch! '
2021-02-21 23:15:23 +00:00
2021-02-21 08:03:25 +00:00
class Drizzle ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-21 08:03:25 +00:00
self . name = " Drizzle "
self . emoji = " 🌧 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 2 , 3 )
2021-02-21 08:03:25 +00:00
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 ) ]
2021-02-21 23:15:23 +00:00
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
2021-02-21 23:45:37 +00:00
state [ " update_text " ] + = f ' Due to inclement weather, { placed_player . name } is placed on second base. '
2021-02-21 23:15:23 +00:00
2021-02-22 00:50:28 +00:00
class Breezy ( Weather ) :
2021-02-21 18:02:47 +00:00
def __init__ ( self , game ) :
2021-02-22 00:50:28 +00:00
self . name = " Breezy "
self . emoji = " 🎐 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 1 , 4 )
2021-02-24 03:14:47 +00:00
self . activation_chance = 0.08
2021-02-21 18:02:47 +00:00
2021-02-21 19:12:34 +00:00
def activate ( self , game , result ) :
2021-02-21 08:03:25 +00:00
if random . random ( ) < self . activation_chance :
teamtype = random . choice ( [ " away " , " home " ] )
team = game . teams [ teamtype ]
player = random . choice ( team . lineup )
2021-02-24 03:16:24 +00:00
player . stlats [ " batting_stars " ] = player . stlats [ " pitching_stars " ]
player . stlats [ " pitching_stars " ] = player . stlats [ " baserunning_stars " ]
2021-02-21 08:03:25 +00:00
old_player_name = player . name
2021-02-24 18:22:48 +00:00
if not hasattr ( player , " stat_name " ) :
player . stat_name = old_player_name
2021-02-21 08:03:25 +00:00
if ' ' in player . name :
names = player . name . split ( " " )
first_first_letter = names [ 0 ] [ 0 ]
last_first_letter = names [ - 1 ] [ 0 ]
2021-02-21 19:12:34 +00:00
names [ 0 ] = last_first_letter + names [ 0 ] [ 1 : ]
names [ - 1 ] = first_first_letter + names [ - 1 ] [ 1 : ]
2021-02-21 08:03:25 +00:00
player . name = ' ' . join ( names )
else :
2021-02-24 03:14:47 +00:00
#name is one word, so turn 'bartholemew' into 'martholemeb'
2021-02-21 08:03:25 +00:00
first_letter = player . name [ 0 ]
last_letter = player . name [ - 1 ]
2021-02-24 03:14:47 +00:00
player . name = last_letter + player . name [ 1 : - 1 ] + first_letter
2021-02-21 19:12:34 +00:00
2021-02-23 00:25:12 +00:00
book_adjectives = [ " action-packed " , " historical " , " mystery " , " thriller " , " horror " , " sci-fi " , " fantasy " , " spooky " , " romantic " ]
book_types = [ " novel " , " novella " , " poem " , " anthology " , " fan fiction " , " autobiography " ]
2021-02-21 19:12:34 +00:00
book = " {} {} " . format ( random . choice ( book_adjectives ) , random . choice ( book_types ) )
2021-02-21 08:03:25 +00:00
result . clear ( )
result . update ( {
2021-02-23 00:25:12 +00:00
" text " : " {} stopped to enjoy a {} in the nice breeze! {} is now {} ! " . format ( old_player_name , book , old_player_name , player . name ) ,
2021-02-21 08:03:25 +00:00
" text_only " : True ,
2021-02-21 19:12:34 +00:00
" weather_message " : True
2021-02-21 08:03:25 +00:00
} )
2021-02-26 00:27:11 +00:00
class MeteorShower ( Weather ) :
def __init__ ( self , game ) :
self . name = " Meteor Shower "
self . emoji = " 🌠 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 3 , 6 )
2021-02-26 00:30:36 +00:00
self . activation_chance = 0.13
2021-02-26 00:27:11 +00:00
def activate ( self , game , result ) :
if random . random ( ) < self . activation_chance and game . occupied_bases ( ) != { } :
base , runner = random . choice ( list ( game . occupied_bases ( ) . items ( ) ) )
runner = game . bases [ base ]
game . bases [ base ] = None
if game . top_of_inning :
bat_team = game . teams [ " away " ]
else :
bat_team = game . teams [ " home " ]
bat_team . score + = 1
result . clear ( )
result . update ( {
2021-02-28 19:16:36 +00:00
" text " : f " { runner . name } wished upon one of the shooting stars, and was warped to None base!! 1 runs scored! " ,
2021-02-26 00:27:11 +00:00
" text_only " : True ,
" weather_message " : True
} )
2021-03-01 00:20:40 +00:00
class Hurricane ( Weather ) :
def __init__ ( self , game ) :
self . name = " Hurricane "
self . emoji = " 🌀 "
2021-03-04 20:34:30 +00:00
self . duration = 1
2021-03-01 00:20:40 +00:00
self . swaplength = random . randint ( 2 , 4 )
self . swapped = False
def on_flip_inning ( self , game ) :
if game . top_of_inning and ( game . inning % self . swaplength ) == 0 :
self . swaplength = random . randint ( 2 , 4 )
self . swapped = True
def modify_top_of_inning_message ( self , game , state ) :
if self . swapped :
game . teams [ " home " ] . score , game . teams [ " away " ] . score = ( game . teams [ " away " ] . score , game . teams [ " home " ] . score ) #swap scores
state [ " away_score " ] , state [ " home_score " ] = ( game . teams [ " away " ] . score , game . teams [ " home " ] . score )
state [ " update_emoji " ] = self . emoji
state [ " update_text " ] + = " The hurricane rages on, flipping the scoreboard! "
self . swapped = False
class Tornado ( Weather ) :
def __init__ ( self , game ) :
self . name = " Tornado "
self . emoji = " 🌪 "
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 1 , 2 )
2021-03-02 00:38:38 +00:00
self . activation_chance = 0.33
2021-03-01 00:20:40 +00:00
self . counter = 0
def activate ( self , game , result ) :
if self . counter == 0 and random . random ( ) < self . activation_chance and game . occupied_bases ( ) != { } :
runners = list ( game . bases . values ( ) )
current_runners = runners . copy ( )
self . counter = 5
while runners == current_runners and self . counter > 0 :
random . shuffle ( runners )
self . counter - = 1
for index in range ( 1 , 4 ) :
game . bases [ index ] = runners [ index - 1 ]
result . clear ( )
result . update ( {
" text " : f " The tornado sweeps across the field and pushes { ' the runners ' if len ( game . occupied_bases ( ) . values ( ) ) > 1 else list ( game . occupied_bases ( ) . values ( ) ) [ 0 ] . name } to a different base! " ,
" text_only " : True ,
" weather_message " : True
} )
self . counter = 2
elif self . counter > 0 :
self . counter - = 1
2021-02-26 00:27:11 +00:00
2021-03-03 22:32:35 +00:00
class Downpour ( Weather ) :
def __init__ ( self , game ) :
self . target = game . max_innings
2021-03-03 22:46:15 +00:00
self . name = f " Torrential Downpour: { roman . roman_convert ( str ( self . target ) ) } "
self . emoji = ' ⛈ '
2021-03-04 20:34:30 +00:00
self . duration = random . randint ( 2 , 5 )
2021-03-03 22:46:15 +00:00
2021-03-03 22:32:35 +00:00
def on_flip_inning ( self , game ) :
high_score = game . teams [ " home " ] . score if game . teams [ " home " ] . score > game . teams [ " away " ] . score else game . teams [ " away " ] . score
if high_score > = self . target and game . teams [ " home " ] . score != game . teams [ " away " ] . score :
2021-03-03 22:46:15 +00:00
game . max_innings = game . inning
2021-03-03 22:32:35 +00:00
else :
game . max_innings = game . inning + 1
def modify_gamestate ( self , game , state ) :
state [ " max_innings " ] = " ∞ "
2021-03-03 23:26:21 +00:00
def modify_top_of_inning_message ( self , game , state ) :
state [ " update_emoji " ] = self . emoji
state [ " update_text " ] = " The gods are not yet pleased. Play continues through the storm. "
def modify_game_end_message ( self , game , state ) :
state [ " update_emoji " ] = self . emoji
state [ " update_text " ] = f " { self . target } runs are reached, pleasing the gods. The storm clears. "
2021-03-03 22:32:35 +00:00
2021-02-21 08:03:25 +00:00
def all_weathers ( ) :
weathers_dic = {
2021-02-21 23:45:37 +00:00
" Supernova " : Supernova ,
" Midnight " : Midnight ,
" Slight Tailwind " : SlightTailwind ,
2021-03-04 20:16:03 +00:00
" Blizzard " : Blizzard ,
2021-02-22 00:37:53 +00:00
" Twilight " : Twilight ,
2021-02-21 23:15:23 +00:00
" Thinned Veil " : ThinnedVeil ,
" Heat Wave " : HeatWave ,
" Drizzle " : Drizzle ,
2021-02-25 22:13:14 +00:00
" Breezy " : Breezy ,
2021-02-26 00:27:11 +00:00
" Starlight " : Starlight ,
2021-03-01 00:20:40 +00:00
" Meteor Shower " : MeteorShower ,
" Hurricane " : Hurricane ,
2021-03-03 22:32:35 +00:00
" Tornado " : Tornado ,
" Torrential Downpour " : Downpour
2021-02-21 08:03:25 +00:00
}
return weathers_dic
2021-03-04 20:16:03 +00:00
class WeatherChains ( ) :
2021-03-04 20:34:30 +00:00
light = [ SlightTailwind , Twilight , Breezy , Drizzle ] #basic starting points for weather, good comfortable spots to return to
magic = [ Twilight , ThinnedVeil , MeteorShower , Starlight ] #weathers involving breaking the fabric of spacetime
sudden = [ Tornado , Hurricane , Twilight , Starlight , Midnight , Supernova ] #weathers that always happen and leave over 1-3 games
disaster = [ Hurricane , Tornado , Downpour , Blizzard ] #storms
aftermath = [ Midnight , Starlight , MeteorShower ] #calm epilogues