From fa109442c215641927af947839ad370dde6fbdb3 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 26 Dec 2024 07:04:00 -0600 Subject: [PATCH] Added range embeds to uncapped hits Update gbA with runner on 3rd --- command_logic/logic_gameplay.py | 420 ++++++++++++++++++++++++++------ 1 file changed, 350 insertions(+), 70 deletions(-) diff --git a/command_logic/logic_gameplay.py b/command_logic/logic_gameplay.py index 57fe820..3089e26 100644 --- a/command_logic/logic_gameplay.py +++ b/command_logic/logic_gameplay.py @@ -1,5 +1,6 @@ import asyncio +import copy import logging import discord from discord import SelectOption @@ -10,7 +11,7 @@ from sqlalchemy import delete from typing import Literal from api_calls import db_delete, db_get, db_post -from dice import d_twenty_roll, frame_plate_check, sa_fielding_roll +from dice import DTwentyRoll, d_twenty_roll, frame_plate_check, sa_fielding_roll from exceptions import * from helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel from in_game.game_helpers import legal_check @@ -35,6 +36,13 @@ AT_BASE = { 3: 'at third', 4: 'at home' } +RANGE_CHECKS = { + 1: 3, + 2: 7, + 3: 11, + 4: 15, + 5: 19 +} async def get_scorebug_embed(session: Session, this_game: Game, full_length: bool = True, classic: bool = True) -> discord.Embed: @@ -1303,17 +1311,247 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact this_game = this_play.game outfielder = await show_outfield_cards(session, interaction, this_play) logger.info(f'throw from {outfielder.player.name_with_desc}') + + this_roll = d_twenty_roll(this_play.batter.team, this_play.game) + block_roll = d_twenty_roll(this_play.catcher.team, this_play.game) + def_team = this_play.pitcher.team runner_bc = get_batter_card(this_lineup=lead_runner) of_rating = await get_position(session, this_card=outfielder.card, position=outfielder.position) - defense_embed = def_team.embed - defense_embed.description = f'{outfielder.player.name}\'s Throw' - trail_bc = get_batter_card(this_lineup=trail_runner) - logger.info(f'trail runner batting card: {trail_bc}') + c_rating = await get_position(session, this_play.catcher.card, position='C') + runner_embed = this_play.batter.team.embed + runner_embed.add_field(name=f'{outfielder.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}') + safe_range = None + + def_alignment = this_play.managerai.defense_alignment(session, this_play.game) + lead_bc = get_batter_card(this_lineup=lead_runner) + logger.info(f'lead runner batting card: {lead_bc}') + + lead_safe_range = lead_bc.running + of_rating.arm + logger.info(f'lead_safe_range: {lead_safe_range}') + + # Build lead runner embed + lead_runner_embed = copy.deepcopy(runner_embed) + lead_runner_embed.title = f'{lead_runner.player.name} To {"Home" if lead_base == 4 else "Third"}' + lead_runner_embed.description = f'{outfielder.team.abbrev} {outfielder.position} {outfielder.player.name}\'s Throw' + lead_runner_embed.add_field(name=f'Runner Speed', value=lead_runner.card.batterscouting.battingcard.running) + + if this_play.starting_outs == 2: + logger.info(f'Adding 2 for 2 outs') + lead_safe_range += 2 + lead_runner_embed.add_field(name='2-Out Mod', value=f'+2') + + if lead_base == 3 and outfielder.position != 'CF': + of_mod = -2 if outfielder.position == 'LF' else 2 + logger.info(f'{outfielder.position} to 3B mod: {of_mod}') + + lead_safe_range += of_mod + lead_runner_embed.add_field(name=f'{outfielder.position} Mod', value=f'{"+" if of_mod > 0 else ""}{of_mod}') + logger.info(f'lead_runner_embed: {lead_runner_embed}') + + # Build trail runner embed + trail_runner_embed = copy.deepcopy(runner_embed) + trail_bc = get_batter_card(this_lineup=trail_runner) + trail_runner_embed.title = f'{trail_runner.player.name} To {"Third" if trail_base == 3 else "Second"}' + trail_runner_embed.description = f'{outfielder.team.abbrev} {outfielder.position} {outfielder.player.name}\'s Throw' + + trail_runner_embed.add_field(name=f'Runner Speed', value=trail_bc.running) + logger.info(f'trail runner batting card: {trail_bc}') + + trail_safe_range = trail_bc.running - 5 + of_rating.arm + logger.info(f'trail_safe_range: {trail_safe_range}') + + if trail_base == 3 and outfielder.position != 'CF': + of_mod = 2 if outfielder.position == 'LF' else -2 + logger.info(f'{outfielder.position} to 3B mod: {of_mod}') + + trail_safe_range += of_mod + trail_runner_embed.add_field(name=f'{outfielder.position} Mod', value=f'{"+" if of_mod > 0 else ""}{of_mod}', inline=False) + + trail_runner_embed.add_field(name='Trail Runner', value='-5') + + def at_home_strings(safe_range: int): + safe_string = f'1{" - " if safe_range > 1 else ""}' + if safe_range > 1: + if safe_range <= 20: + safe_string += f'{safe_range - 1}' + else: + safe_string += f'20' + + if safe_range == 20: + out_string = 'None' + catcher_string = '20' + elif safe_range > 20: + out_string = 'None' + catcher_string = 'None' + elif safe_range == 19: + out_string = 'None' + catcher_string = '19 - 20' + elif safe_range == 18: + out_string = f'20' + catcher_string = '18 - 19' + else: + out_string = f'{safe_range + 2} - 20' + catcher_string = f'{safe_range} - {safe_range + 1}' + logger.info(f'safe: {safe_string} / catcher: {catcher_string} / out: {out_string}') + + return {'safe': safe_string, 'catcher': catcher_string, 'out': out_string} + + def at_third_strings(safe_range: int): + safe_string = f'1{" - " if safe_range > 1 else ""}' + if safe_range > 1: + if safe_range <= 20: + safe_string += f'{safe_range}' + else: + safe_string += f'20' + + if safe_range > 19: + out_string = '20' + else: + out_string = f'{safe_range + 1} - 20' + logger.info(f'safe: {safe_string} / out: {out_string}') + + return {'safe': safe_string, 'out': out_string} + + async def out_at_home(safe_range: int): + if this_roll.d_twenty in [safe_range, safe_range + 1]: + logger.info(f'Roll of {this_roll.d_twenty} is a catcher check with safe range of {safe_range}') + + is_block_plate = await ask_confirm( + interaction, + question=f'Looks like **{this_play.catcher.player.name}** has a chance to block the plate! Is that correct?', + label_type='yes', + delete_question=False + ) + + if is_block_plate: + logger.info(f'Looks like a block the plate check') + await interaction.channel.send(content=None, embeds=block_roll.embeds) + + if block_roll.d_twenty > RANGE_CHECKS[c_rating]: + logger.info(f'Roll of {this_roll.d_twenty} is OUT {AT_BASE[4]}') + runner_thrown_out = True + q_text = f'Looks like **{lead_runner.player.name}** is OUT {AT_BASE[4]}!' + else: + logger.info(f'Roll of {this_roll.d_twenty} is SAFE {AT_BASE[4]}') + runner_thrown_out = False + q_text = f'Looks like **{lead_runner.player.name}** is SAFE {AT_BASE[4]}!' + else: + runner_thrown_out = await ask_confirm( + interaction=interaction, + question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[4]}?', + label_type='yes', + ) + else: + logger.info(f'Roll of {this_roll.d_twenty} has a clear result with safe range of {safe_range}') + if this_roll.d_twenty > safe_range: + logger.info(f'Roll of {this_roll.d_twenty} is OUT {AT_BASE[4]}') + runner_thrown_out = True + q_text = f'Looks like **{lead_runner.player.name}** is OUT {AT_BASE[4]}!' + else: + logger.info(f'Roll of {this_roll.d_twenty} is SAFE {AT_BASE[4]}') + runner_thrown_out = False + q_text = f'Looks like **{lead_runner.player.name}** is SAFE {AT_BASE[4]}!' + + is_correct = await ask_confirm( + interaction, + question=f'{q_text} Is that correct?', + label_type='yes', + delete_question=False + ) + + if not is_correct: + logger.warning(f'{interaction.user.name} says call is incorrect; runner is {"not " if runner_thrown_out else ""}thrown out') + runner_thrown_out = not runner_thrown_out + + return runner_thrown_out + + async def out_at_base(safe_range: int, this_runner: Lineup, this_base: int): + if this_roll.d_twenty > safe_range: + logger.info(f'Roll of {this_roll.d_twenty} is OUT {AT_BASE[this_base]}') + runner_thrown_out = True + q_text = f'Looks like **{this_runner.player.name}** is OUT {AT_BASE[this_base]}!' + else: + logger.info(f'Roll of {this_roll.d_twenty} is SAFE {AT_BASE[this_base]}') + runner_thrown_out = False + q_text = f'Looks like **{this_runner.player.name}** is SAFE {AT_BASE[this_base]}!' + + is_correct = await ask_confirm( + interaction, + question=f'{q_text} Is that correct?', + label_type='yes', + delete_question=False + ) + + if not is_correct: + logger.warning(f'{interaction.user.name} says call is incorrect; runner is {"not " if runner_thrown_out else ""}thrown out') + runner_thrown_out = not runner_thrown_out + + return runner_thrown_out # Either there is no AI team or the AI is pitching if not this_game.ai_team or not this_play.ai_is_batting: + # Build lead runner embed + # Check for lead runner hold + if (lead_runner == this_play.on_second and def_alignment.hold_second) or (lead_runner == this_play.on_first and def_alignment.hold_first): + lead_safe_range -= 1 + logger.info(f'Lead runner was held, -1 to safe range: {lead_safe_range}') + lead_runner_embed.add_field(name='Runner Held', value='-1') + else: + logger.info(f'Lead runner was not held, +1 to safe range: {lead_safe_range}') + lead_safe_range += 1 + lead_runner_embed.add_field(name='Runner Not Held', value='+1') + + lead_runner_embed.add_field(name='', value='', inline=False) + + if lead_base == 4: + logger.info(f'lead base is 4, building strings') + lead_strings = at_home_strings(lead_safe_range) + + lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe']) + lead_runner_embed.add_field(name='Catcher Check', value=lead_strings['catcher']) + lead_runner_embed.add_field(name='Out Range', value=lead_strings['out']) + + else: + logger.info(f'lead base is 3, building strings') + lead_strings = at_third_strings(lead_safe_range) + + lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe']) + lead_runner_embed.add_field(name='Out Range', value=lead_strings['out']) + + # Build trail runner embed + if (trail_runner == this_play.on_first and def_alignment.hold_first): + trail_safe_range -= 1 + logger.info(f'Trail runner was held, -1 to safe range: {trail_safe_range}') + trail_runner_embed.add_field(name='Runner Held', value='-1') + elif (trail_runner == this_play.on_first and not def_alignment.hold_first): + trail_safe_range += 1 + logger.info(f'Trail runner was not held, +1 to safe range: {trail_safe_range}') + trail_runner_embed.add_field(name='Runner Not Held', value='+1') + else: + logger.info('Trail runner was not from first base, no hold modifier') + + trail_runner_embed.add_field(name='', value='', inline=False) + + logger.info(f'Building strings for trail runner') + safe_string = f'1{" - " if trail_safe_range > 1 else ""}' + if trail_safe_range > 1: + if trail_safe_range < 20: + safe_string += f'{trail_safe_range}' + else: + logger.info(f'capping safe range at 19') + trail_safe_range = 19 + safe_string += f'19' + + out_string = f'{trail_safe_range + 1} - 20' + logger.info(f'safe: {safe_string} / out: {out_string}') + + trail_runner_embed.add_field(name='Safe Range', value=safe_string) + trail_runner_embed.add_field(name='Out Range', value=out_string) + + await interaction.channel.send(embeds=[lead_runner_embed, trail_runner_embed]) + is_lead_running = await ask_confirm( interaction=interaction, question=f'Is **{lead_runner.player.name}** being sent {TO_BASE[lead_base]}?', @@ -1322,7 +1560,6 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact if is_lead_running: throw_resp = None - def_alignment = this_play.managerai.defense_alignment(session, this_play.game) if this_game.ai_team: throw_resp = this_play.managerai.throw_at_uncapped(session, this_game) @@ -1341,7 +1578,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact return this_play else: - await interaction.channel.send(content=f'{outfielder.player.name} is throwing {TO_BASE[lead_base]}!') + await interaction.channel.send(content=f'**{outfielder.player.name}** is throwing {TO_BASE[lead_base]}!') else: throw_for_lead = await ask_confirm( @@ -1358,7 +1595,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact this_play.on_second_final = 4 log_run_scored(session, lead_runner, this_play) return this_play - + # Human runner is advancing, defense is throwing trail_advancing = await ask_confirm( interaction=interaction, @@ -1366,24 +1603,13 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact label_type='yes' ) - lead_bc = get_batter_card(this_lineup=lead_runner) - logger.info(f'lead runner batting card: {lead_bc}') - - lead_safe_range = lead_bc.running + of_rating.arm + 1 - if lead_runner == this_play.on_second: - lead_safe_range -= 2 if def_alignment.hold_second else 0 - elif lead_runner == this_play.on_first: - lead_safe_range -= 2 if def_alignment.hold_first else 0 - logger.info(f'lead_safe_range: {lead_safe_range}') - # Trail runner is advancing if trail_advancing: - trail_safe = trail_bc.running - 5 + of_rating.arm - logger.info(f'trail_safe: {trail_safe}') + throw_lead = False if this_game.ai_team: - if throw_resp.at_trail_runner and trail_safe <= throw_resp.trail_max_safe and trail_safe <= throw_resp.trail_max_safe_delta - lead_safe_range: + if throw_resp.at_trail_runner and trail_safe_range <= throw_resp.trail_max_safe and trail_safe_range <= throw_resp.trail_max_safe_delta - lead_safe_range: logger.info(f'defense throwing at trail runner {AT_BASE[trail_base]}') await interaction.channel.send(f'**{outfielder.player.name}** will throw {TO_BASE[trail_base]}!') throw_lead = False @@ -1404,10 +1630,12 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact # Throw is going to lead runner if throw_lead: + logger.info(f'Throw is going to lead base') try: await question.delete() except (discord.NotFound, UnboundLocalError): pass + if this_play.on_first == trail_runner: this_play.on_first_final += 1 elif this_play.batter == trail_runner: @@ -1422,16 +1650,12 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact except (discord.NotFound, UnboundLocalError): pass - runner_thrown_out = await ask_confirm( - interaction=interaction, - question=f'**{trail_runner.player.name}**\'s safe range is 1 -> {trail_safe} - were they thrown out {AT_BASE[trail_base]}?', - label_type='yes', - custom_confirm_label=f'Out {AT_BASE[trail_base]}', - custom_cancel_label=f'Safe {AT_BASE[trail_base]}' - ) + await interaction.channel.send(content=None, embeds=this_roll.embeds) + runner_thrown_out = await out_at_base(trail_safe_range, trail_runner, trail_base) # Trail runner is thrown out if runner_thrown_out: + logger.info(f'logging one one additional out for trail runner') # Log out on play this_play.outs += 1 @@ -1442,7 +1666,9 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact this_play.batter_final = None # Advance lead runner extra base + logger.info(f'advancing lead runner') if this_play.on_second == lead_runner: + logger.info(f'run scored from second') this_play.rbi += 1 this_play.on_second_final = 4 log_run_scored(session, lead_runner, this_play) @@ -1450,19 +1676,15 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact elif this_play.on_first == lead_runner: this_play.on_first_final += 1 if this_play.on_first_final > 3: + logger.info(f'run scored from first') this_play.rbi += 1 log_run_scored(session, lead_runner, this_play) return this_play # Ball is going to lead base, ask if safe - runner_thrown_out = await ask_confirm( - interaction=interaction, - question=f'**{lead_runner.player.name}**\'s safe range is 1 -> {lead_safe_range} - were they thrown out {AT_BASE[lead_base]}?', - label_type='yes', - custom_confirm_label=f'Out {AT_BASE[lead_base]}', - custom_cancel_label=f'Safe {AT_BASE[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, lead_runner, lead_base) # Lead runner is thrown out if runner_thrown_out: @@ -1489,28 +1711,60 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact elif this_play.ai_is_batting: run_resp = this_play.managerai.uncapped_advance(session, this_game, lead_base, trail_base) - runner_held = await ask_confirm( + lead_runner_held = await ask_confirm( interaction=interaction, - question=f'Was **{lead_runner.player.name}** held before the pitch?', + question=f'Was **{lead_runner.player.name}** held at {"second" if lead_runner == this_play.on_second else "first"} before the pitch?', label_type='yes' ) - safe_range = runner_bc.running + of_rating.arm - 1 - if runner_held: - safe_range -= 1 + if lead_runner_held: + lead_safe_range -= 1 + lead_runner_embed.add_field(name='Runner Held', value='-1') + logger.info(f'runner was held, -1 to lead safe range: {lead_safe_range}') else: - safe_range += 1 - - if this_play.starting_outs == 2: - safe_range += 2 + lead_safe_range += 1 + lead_runner_embed.add_field(name='Runner Not Held', value='+1') + logger.info(f'runner was not held, +1 to lead safe range: {lead_safe_range}') - if lead_base == 3: - if outfielder.position == 'RF': - safe_range += 2 - elif outfielder.position == 'LF': - safe_range -= 2 - - if safe_range > run_resp.min_safe: + if lead_safe_range > run_resp.min_safe: + logger.info(f'AI is not advancing with lead runner') return this_play + + logger.info(f'Building embeds') + + lead_runner_embed.add_field(name='', value='', inline=False) + + if lead_base == 4: + logger.info(f'lead base is 4, building strings') + lead_strings = at_home_strings(lead_safe_range) + + lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe']) + lead_runner_embed.add_field(name='Catcher Check', value=lead_strings['catcher']) + lead_runner_embed.add_field(name='Out Range', value=lead_strings['out']) + + else: + logger.info(f'lead base is 3, building strings') + lead_strings = at_third_strings(lead_safe_range) + + lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe']) + lead_runner_embed.add_field(name='Out Range', value=lead_strings['out']) + + if trail_runner == this_play.on_first: + trail_runner_held = await ask_confirm( + interaction=interaction, + question=f'Was **{trail_runner.player.name}** held at first before the pitch?', + label_type='yes' + ) + logger.info(f'Trail runner held: {trail_runner_held}') + if trail_runner_held: + trail_runner_embed.add_field(name='Runner Held', value=f'-1') + trail_safe_range -= 1 + logger.info(f'Trail runner held, -1 to safe range: {trail_safe_range}') + else: + trail_runner_embed.add_field(name='Runner Not Held', value='+1') + trail_safe_range += 1 + logger.info(f'Trail runner not held, +1 to safe range: {trail_safe_range}') + + await interaction.channel.send(embeds=[lead_runner_embed, trail_runner_embed]) is_defense_throwing = await ask_confirm( interaction=interaction, @@ -1533,7 +1787,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact # Human throw is not being cut off if run_resp.send_trail: await interaction.channel.send( - f'**{trail_runner.player.name}** is advancing {TO_BASE[trail_base]} as the trail runner with a safe range of 1->{trail_bc.running - 5 + of_rating.arm}!', + f'**{trail_runner.player.name}** is advancing {TO_BASE[trail_base]} as the trail runner!', ) is_throwing_lead = await ask_confirm( interaction=interaction, @@ -1554,23 +1808,22 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact # Throw is going to trail runner else: - is_trail_out = await ask_confirm( - interaction=interaction, - question=f'Was **{trail_runner.player.name}** thrown out {AT_BASE[trail_base]}?', - label_type='yes' - ) + runner_thrown_out = await out_at_base(trail_safe_range, trail_runner, trail_base) - if is_trail_out: + if runner_thrown_out: + logger.info(f'Runner was thrown out') # Log out on play this_play.outs += 1 # Remove trail runner + logger.info(f'Remove trail runner') if this_play.on_first == trail_runner: this_play.on_first_final = None else: this_play.batter_final = None # Advance lead runner extra base + logger.info(f'Advance lead runner extra base') if this_play.on_second == lead_runner: this_play.rbi += 1 this_play.on_second_final = 4 @@ -1588,23 +1841,25 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact await interaction.channel.send(content=f'**{trail_runner.player.name}** is NOT trailing to {TO_BASE[trail_base]}.') # Ball is going to lead base, ask if safe - is_lead_out = await ask_confirm( + logger.info(f'Throw is going to lead base') + 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', ) # Lead runner is thrown out - if is_lead_out: + if runner_thrown_out: logger.info(f'Lead runner is thrown out.') this_play.outs += 1 if this_play.on_second == lead_runner: logger.info(f'setting lead runner on_second_final') - this_play.on_second_final = None if is_lead_out else lead_base + this_play.on_second_final = None if runner_thrown_out else lead_base elif this_play.on_first == lead_runner: logger.info(f'setting lead runner on_first') - this_play.on_first_final = None if is_lead_out else lead_base + this_play.on_first_final = None if runner_thrown_out else lead_base else: log_exception(LineupsMissingException, f'Could not find lead runner to set final destination') @@ -2393,8 +2648,6 @@ def undo_play(session: Session, this_play: Play): logger.warning(f'Deleting lineup IDs: {new_player_ids}') session.exec(delete(Lineup).where(Lineup.id.in_(new_player_ids))) - # TODO: check for runners that scored in previous play, find their last AB, and set run and e_run to 0 - session.commit() try: @@ -2901,6 +3154,7 @@ async def manual_end_game(session: Session, interaction: discord.Interaction, th async def groundballs(session: Session, interaction: discord.Interaction, this_play: Play, groundball_letter: Literal['a', 'b', 'c']): if this_play.on_base_code == 2 and groundball_letter in ['a', 'b']: + logger.info(f'Groundball {groundball_letter} with runner on second') to_right_side = await ask_confirm( interaction, question=f'Was that ball hit to either 1B or 2B?', @@ -2909,12 +3163,38 @@ async def groundballs(session: Session, interaction: discord.Interaction, this_p this_play = gb_result_6(session, this_play, to_right_side) elif this_play.on_base_code in [3, 6] and groundball_letter in ['a', 'b']: - to_mif = await ask_confirm( - interaction, - question=f'Was that ball hit to either 2B or SS?', - label_type='yes' - ) - this_play = gb_result_5(session, this_play, to_mif) + logger.info(f'Groundball {groundball_letter} with runner on third') + def_alignment = this_play.managerai.defense_alignment(session, this_play.game) + + if this_play.game.ai_team is not None and this_play.pitcher.team.is_ai and def_alignment.infield_in: + logger.info(f'AI on defense, hit to MIF, playing in') + this_play = gb_result_7(session, this_play) + + else: + logger.info(f'Checking if hit to MIF') + to_mif = await ask_confirm( + interaction, + question=f'Was that ball hit to either 2B or SS?', + label_type='yes' + ) + + if not to_mif: + logger.info(f'Not to a MIF, gb 7') + this_play = gb_result_7(session, this_play) + + else: + logger.info(f'AI batting, hit to MIF') + mif_playing_in = await ask_confirm( + interaction, + question=f'Were they playing in?', + label_type='yes', + ) + if mif_playing_in: + logger.info(f'playing in, gb 7') + this_play = gb_result_7(session, this_play) + else: + logger.info(f'playing back, gb 5') + this_play = gb_result_5(session, this_play, to_mif) else: this_play = await gb_letter(session, interaction, this_play, groundball_letter.upper(), 'None', False)