From db52625899e670f9ea0c9271a9329d65058c9b1c Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 6 Feb 2025 10:00:56 -0600 Subject: [PATCH] Day 1 Gauntlet Updates Baserunner advancement bug fixes Pitcher sub bug fixes --- command_logic/logic_gameplay.py | 157 ++++++++++++++++++++++++++------ gauntlets.py | 16 ++-- in_game/gameplay_models.py | 20 ++-- in_game/gameplay_queries.py | 6 +- 4 files changed, 155 insertions(+), 44 deletions(-) diff --git a/command_logic/logic_gameplay.py b/command_logic/logic_gameplay.py index bada062..f7ceaf6 100644 --- a/command_logic/logic_gameplay.py +++ b/command_logic/logic_gameplay.py @@ -13,6 +13,7 @@ from typing import Literal from api_calls import db_delete, db_get, db_post from dice import DTwentyRoll, d_twenty_roll, frame_plate_check, sa_fielding_roll from exceptions import * +from gauntlets import post_result from helpers import COLORS, DEFENSE_LITERAL, SBA_COLOR, get_channel, team_role from in_game.ai_manager import get_starting_lineup from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check @@ -225,7 +226,7 @@ async def get_scorebug_embed(session: Session, this_game: Game, full_length: boo else: log_exception(PositionNotFoundException, f'No catcher rating found for {curr_play.catcher.card.player.name}') - cat_string = f'{curr_play.catcher.player.name_card_link('batter')}\nArm: {"+" if pitchingcard.hold > 0 else ""}{catcher_rating.arm}, PB: {catcher_rating.pb}, OT: {catcher_rating.overthrow}' + cat_string = f'{curr_play.catcher.player.name_card_link('batter')}\nArm: {"+" if catcher_rating.arm > 0 else ""}{catcher_rating.arm}, PB: {catcher_rating.pb}, OT: {catcher_rating.overthrow}' embed.add_field(name='Catcher', value=cat_string) if curr_play.ai_is_batting and curr_play.on_base_code > 0: @@ -512,6 +513,33 @@ def complete_play(session:Session, this_play: Play): new_batter_team = this_play.game.away_team if nih == 'top' else this_play.game.home_team new_pitcher_team = this_play.game.away_team if nih == 'bot' else this_play.game.home_team inning = this_play.inning_num if nih == 'bot' else this_play.inning_num + 1 + + logger.info(f'Calculate runs scored') + for this_runner, runner_dest in [ + (this_play.batter, this_play.batter_final), (this_play.on_first, this_play.on_first_final), (this_play.on_second, this_play.on_second_final), (this_play.on_third, this_play.on_third_final) + ]: + if runner_dest is not None: + if runner_dest == 1: + logger.info(f'{this_runner} advances to first') + if on_first is not None: + log_exception(ValueError, f'Cannot place {this_runner.player.name} on first; {on_first.player.name} is already placed there') + if not switch_sides: + on_first = this_runner + elif runner_dest == 2: + logger.info(f'{this_runner} advances to second') + if on_second is not None: + log_exception(ValueError, f'Cannot place {this_runner.player.name} on second; {on_second.player.name} is already placed there') + if not switch_sides: + on_second = this_runner + elif runner_dest == 3: + logger.info(f'{this_runner} advances to third') + if on_third is not None: + log_exception(ValueError, f'Cannot place {this_runner.player.name} on third; {on_third.player.name} is already placed there') + if not switch_sides: + on_third = this_runner + elif runner_dest == 4: + logger.info(f'{this_runner} advances to home') + runs_scored += 1 else: switch_sides = False @@ -519,45 +547,54 @@ def complete_play(session:Session, this_play: Play): nih = this_play.inning_half new_batter_team = this_play.batter.team new_pitcher_team = this_play.pitcher.team - inning = this_play.inning_num + inning = this_play.inning_num + logger.info(f'Calculate runs scored') for this_runner, runner_dest in [ (this_play.batter, this_play.batter_final), (this_play.on_first, this_play.on_first_final), (this_play.on_second, this_play.on_second_final), (this_play.on_third, this_play.on_third_final) ]: if runner_dest is not None: if runner_dest == 1: + logger.info(f'{this_runner} advances to first') if on_first is not None: log_exception(ValueError, f'Cannot place {this_runner.player.name} on first; {on_first.player.name} is already placed there') - on_first = this_runner + if not switch_sides: + on_first = this_runner elif runner_dest == 2: + logger.info(f'{this_runner} advances to second') if on_second is not None: log_exception(ValueError, f'Cannot place {this_runner.player.name} on second; {on_second.player.name} is already placed there') - on_second = this_runner + if not switch_sides: + on_second = this_runner elif runner_dest == 3: + logger.info(f'{this_runner} advances to third') if on_third is not None: log_exception(ValueError, f'Cannot place {this_runner.player.name} on third; {on_third.player.name} is already placed there') - on_third = this_runner + if not switch_sides: + on_third = this_runner elif runner_dest == 4: + logger.info(f'{this_runner} advances to home') runs_scored += 1 - if this_play.inning_half == 'top': - away_score = this_play.away_score + runs_scored - home_score = this_play.home_score - - logger.info(f'Check for go-ahead run') - if runs_scored > 0 and this_play.away_score <= this_play.home_score and away_score > home_score: - this_play.is_go_ahead = True - - else: - away_score = this_play.away_score - home_score = this_play.home_score + runs_scored - - logger.info(f'Check for go-ahead run') - if runs_scored > 0 and this_play.home_score <= this_play.away_score and home_score > away_score: - this_play.is_go_ahead = True - obc = get_obc(on_first, on_second, on_third) + + if this_play.inning_half == 'top': + away_score = this_play.away_score + runs_scored + home_score = this_play.home_score + + logger.info(f'Check for go-ahead run') + if runs_scored > 0 and this_play.away_score <= this_play.home_score and away_score > home_score: + this_play.is_go_ahead = True + + else: + away_score = this_play.away_score + home_score = this_play.home_score + runs_scored + + logger.info(f'Check for go-ahead run') + if runs_scored > 0 and this_play.home_score <= this_play.away_score and home_score > away_score: + this_play.is_go_ahead = True + logger.info(f'Calculating re24') this_play.re24 = get_re24(this_play, runs_scored, new_obc=obc, new_starting_outs=nso) @@ -2001,11 +2038,11 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact logger.info(f'Throw is going to lead base') await interaction.channel.send(content=None, embeds=this_roll.embeds) runner_thrown_out = await out_at_home(lead_safe_range) if lead_base == 4 else await out_at_base(lead_safe_range, trail_runner, trail_base) - runner_thrown_out = await ask_confirm( - interaction=interaction, - question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[lead_base]}?', - label_type='yes', - ) + # runner_thrown_out = await ask_confirm( + # interaction=interaction, + # question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[lead_base]}?', + # label_type='yes', + # ) # Lead runner is thrown out if runner_thrown_out: @@ -3212,6 +3249,17 @@ async def complete_game(session: Session, interaction: discord.Interaction, this losing_team=losing_team, this_game=this_game ) + if 'gauntlet' in this_game.game_type: + logger.info(f'Posting gauntlet results') + await post_result( + run_id=int(this_game.game_type.split('-')[3]), + is_win=winning_team.gmid == interaction.user.id, + this_team=this_game.human_team, + bot=None, + channel=interaction.channel, + responders=[interaction.user] + ) + except Exception as e: await roll_back(db_game['id'], plays=True, decisions=True) log_exception(e, msg='Error while posting game rewards') @@ -3449,7 +3497,7 @@ async def groundballs(session: Session, interaction: discord.Interaction, this_p logger.info(f'Batter out, runners hold') this_play = gb_result_1(session, this_play) - elif this_play.on_base_code in [4, 5, 7] and groundball_letter == 'a': + elif this_play.on_base_code in [5, 7] and groundball_letter == 'a': logger.info(f'Groundball {groundball_letter} with runners on including third') if this_play.game.ai_team is not None and this_play.pitcher.team.is_ai: @@ -3479,8 +3527,61 @@ async def groundballs(session: Session, interaction: discord.Interaction, this_p logger.info(f'playing back, gb 2') this_play = gb_result_2(session, this_play) + elif this_play.on_base_code in [5, 7] and groundball_letter == 'b': + logger.info(f'Groundball {groundball_letter} with runners on including third') + + if this_play.game.ai_team is not None and this_play.pitcher.team.is_ai: + def_alignment = this_play.managerai.defense_alignment(session, this_play.game) + logger.info(f'def_alignment: {def_alignment}') + + to_mif = await ask_confirm( + interaction, + question='Was that hit to 2B/SS?', + label_type='yes' + ) + + if def_alignment.infield_in or not to_mif and def_alignment.corners_in: + playing_in = True + + else: + playing_in = await ask_confirm( + interaction, + question='Was the defender playing in?', + label_type='yes' + ) + + if playing_in and this_play.on_base_code == 7: + logger.info(f'playing in, gb 11') + this_play = gb_result_11(session, this_play) + + elif playing_in: + logger.info(f'playing in, gb 9') + this_play = gb_result_9(session, this_play) + + else: + logger.info(f'playing back, gb 4') + this_play = gb_result_4(session, this_play) + else: - this_play = await gb_letter(session, interaction, this_play, groundball_letter.upper(), 'None', False) + if this_play.on_base_code in [3, 5, 6, 7]: + def_align = this_play.managerai.defense_alignment(session, this_play.game) + if def_align.infield_in: + playing_in = True + else: + to_mif = await ask_confirm( + interaction, + question='Was that ball hit to 2B/SS?', + label_type='yes' + ) + + if not to_mif and def_align.corners_in: + playing_in = True + else: + playing_in = False + else: + playing_in = False + + this_play = await gb_letter(session, interaction, this_play, groundball_letter.upper(), 'None', playing_in) session.add(this_play) session.commit() diff --git a/gauntlets.py b/gauntlets.py index f36149f..f5916ae 100644 --- a/gauntlets.py +++ b/gauntlets.py @@ -1771,7 +1771,7 @@ async def get_embed(this_run=None, this_event=None, this_team=None): return embed -async def end_run(this_run, this_event, this_team, force_end: bool = False): +async def end_run(this_run, this_event, this_team: Team, force_end: bool = False): l_message = f'Tough loss. That brings your {this_event["name"]} record to ' \ f'**{this_run["wins"]}-{this_run["losses"]}**. ' if this_run['losses'] == 2 or force_end: @@ -1781,15 +1781,15 @@ async def end_run(this_run, this_event, this_team, force_end: bool = False): object_id=this_run['id'], params=[('ended', True)] ) - c_query = await db_post(f'cards/wipe-team/{this_team["id"]}') + c_query = await db_post(f'cards/wipe-team/{this_team.id}') return l_message -async def evolve_pokemon(this_team, channel, responders): +async def evolve_pokemon(this_team: Team, channel, responders): c_query = await db_get( 'cards', - params=[('team_id', this_team['id']), ('order_by', 'new'), ('limit', 26)] + params=[('team_id', this_team.id), ('order_by', 'new'), ('limit', 26)] ) evolvable_mons = [x for x in c_query['cards'] if x['player']['cardset']['id'] in [23] and x['player']['fangr_id'] is not None and len(x['player']['fangr_id']) > 3] @@ -1809,10 +1809,10 @@ async def evolve_pokemon(this_team, channel, responders): await channel.send('All of your Pokemon are fully evolved!') -async def post_result(run_id: int, is_win: bool, this_team, bot, channel, responders: list[discord.User] = None): +async def post_result(run_id: int, is_win: bool, this_team: Team, bot, channel, responders: list[discord.User] = None): this_run = await db_get('gauntletruns', object_id=run_id) this_event = await db_get('events', object_id=this_run['gauntlet']['id']) - t_query = await db_get('teams', params=[('abbrev', f'{this_team["abbrev"].replace("Gauntlet-","")}')]) + t_query = await db_get('teams', params=[('abbrev', f'{this_team.abbrev.replace("Gauntlet-","")}')]) main_team = t_query['teams'][0] if is_win: @@ -1889,13 +1889,13 @@ async def post_result(run_id: int, is_win: bool, this_team, bot, channel, respon await send_to_channel( bot, 'pd-network-news', - content=f'{choas_role.mention}\n\nThe **{this_team["lname"]}** have completed the ' + content=f'{choas_role.mention}\n\nThe **{this_team.lname}** have completed the ' f'**{this_event["name"]} Gauntlet** with a record of {this_run["wins"]}-' f'{this_run["losses"]}!' ) final_message = f'That\'s number 10! Way to go - you have completed the **{this_event["name"]} Gauntlet** ' \ f'with a record of {this_run["wins"]}-{this_run["losses"]}! ' - c_query = await db_post(f'cards/wipe-team/{this_team["id"]}') + c_query = await db_post(f'cards/wipe-team/{this_team.id}') else: final_message = f'Big win there! Your {this_event["name"]} record is now **{this_run["wins"]}-' \ f'{this_run["losses"]}**. ' diff --git a/in_game/gameplay_models.py b/in_game/gameplay_models.py index 0b5f0b2..18e3acc 100644 --- a/in_game/gameplay_models.py +++ b/in_game/gameplay_models.py @@ -691,15 +691,19 @@ class ManagerAi(ManagerAiBase, table=True): logger.info(f'Starter is cooking with {allowed_runners} runners allowed - staying in') return False - elif run_diff > 5 or (run_diff > 2 and self.ahead_aggression > 5) and (allowed_runners < run_diff or this_play.on_base_code <= 3): + elif this_pitcher.is_fatigued and this_play.on_base_code > 1: + logger.info(f'Starter is fatigued') + return True + + elif (run_diff > 5 or (run_diff > 2 and self.ahead_aggression > 5)) and (allowed_runners < run_diff or this_play.on_base_code <= 3): logger.info(f'AI team has big lead of {run_diff} - staying in') return False - elif run_diff > 2 or (run_diff >= 0 and self.ahead_aggression > 5) and (allowed_runners < run_diff or this_play.on_base_code <= 1): + elif (run_diff > 2 or (run_diff >= 0 and self.ahead_aggression > 5)) and (allowed_runners < run_diff or this_play.on_base_code <= 1): logger.info(f'AI team has lead of {run_diff} - staying in') return False - elif run_diff >= 0 or (run_diff >= -2 and self.behind_aggression > 5) and (allowed_runners < 5 and this_play.on_base_code <= run_diff): + elif (run_diff >= 0 or (run_diff >= -2 and self.behind_aggression > 5)) and (allowed_runners < 5 and this_play.on_base_code <= run_diff): logger.info(f'AI team in close game with run diff of {run_diff} - staying in') return False @@ -722,16 +726,20 @@ class ManagerAi(ManagerAiBase, table=True): if outs >= pitcher_pow * 3 + 3: logger.info(f'Only allow POW + 1 IP - pull reliever') return True + + elif this_pitcher.is_fatigued and this_play.is_new_inning: + logger.info(f'Reliever is fatigued to start the inning - pull reliever') + return True - elif run_diff > 5 or (run_diff > 2 and self.ahead_aggression > 5) and (this_play.starting_outs == 2 or allowed_runners <= run_diff or this_play.on_base_code <= 3 or this_play.starting_outs == 2): + elif (run_diff > 5 or (run_diff > 2 and self.ahead_aggression > 5)) and (this_play.starting_outs == 2 or allowed_runners <= run_diff or this_play.on_base_code <= 3 or this_play.starting_outs == 2): logger.info(f'AI team has big lead of {run_diff} - staying in') return False - elif run_diff > 2 or (run_diff >= 0 and self.ahead_aggression > 5) and (allowed_runners < run_diff or this_play.on_base_code <= 1 or this_play.starting_outs == 2): + elif (run_diff > 2 or (run_diff >= 0 and self.ahead_aggression > 5)) and (allowed_runners < run_diff or this_play.on_base_code <= 1 or this_play.starting_outs == 2): logger.info(f'AI team has lead of {run_diff} - staying in') return False - elif run_diff >= 0 or (run_diff >= -2 and self.behind_aggression > 5) and (allowed_runners < 5 or this_play.on_base_code <= run_diff or this_play.starting_outs == 2): + elif (run_diff >= 0 or (run_diff >= -2 and self.behind_aggression > 5)) and (allowed_runners < 5 or this_play.on_base_code <= run_diff or this_play.starting_outs == 2): logger.info(f'AI team in close game with run diff of {run_diff} - staying in') return False diff --git a/in_game/gameplay_queries.py b/in_game/gameplay_queries.py index 1bc6a6d..1ab8fb0 100644 --- a/in_game/gameplay_queries.py +++ b/in_game/gameplay_queries.py @@ -670,6 +670,8 @@ def get_db_ready_decisions(session: Session, this_game: Game, db_game_id: int) - } final_inning = session.exec(select(func.max(Play.inning_num)).where(Play.game == this_game)).one() + away_starter = session.exec(select(Lineup).where(Lineup.game == this_game, Lineup.team == this_game.away_team, Lineup.position == 'P', Lineup.after_play == 0)).one() + away_pitcher = away_starter # Get starting pitchers and update this as a pointer for the play crawl for play in session.exec(select(Play).where(Play.game == this_game)).all(): @@ -758,11 +760,11 @@ def get_db_ready_decisions(session: Session, this_game: Game, db_game_id: int) - count += 1 if winner is None: - logger.info(f'Game {this_game.id} | Setting winner to {winner} by default on play #{play.play_num}') winner = home_pitcher if play.inning_half == 'bot' else away_pitcher + logger.info(f'Game {this_game.id} | Setting winner to {winner} by default on play #{play.play_num}') if loser is None: - logger.info(f'Game {this_game.id} | Setting loser to {loser} by default on play #{play.play_num}') + logger.info(f'Game {this_game.id} | Setting loser to {play.pitcher} by default on play #{play.play_num}') loser = play.pitcher if play.is_tied and runs_scored == 0: