Refactor new game checks
Trail batter-runner on uncapped hits
This commit is contained in:
parent
a4bce3cbce
commit
3db25b177a
157
cogs/gameplay.py
157
cogs/gameplay.py
@ -11,7 +11,7 @@ import pygsheets
|
||||
from sqlmodel import or_
|
||||
|
||||
from api_calls import db_get
|
||||
from command_logic.logic_gameplay import advance_runners, bunts, chaos, complete_game, doubles, flyballs, frame_checks, get_full_roster_from_sheets, get_lineups_from_sheets, checks_log_interaction, complete_play, get_scorebug_embed, groundballs, hit_by_pitch, homeruns, is_game_over, lineouts, manual_end_game, popouts, read_lineup, show_defense_cards, singles, starting_pitcher_dropdown_view, steals, strikeouts, sub_batter_dropdown_view, triples, undo_play, update_game_settings, walks, xchecks, activate_last_play
|
||||
from command_logic.logic_gameplay import advance_runners, bunts, chaos, complete_game, doubles, flyballs, frame_checks, get_full_roster_from_sheets, get_lineups_from_sheets, checks_log_interaction, complete_play, get_scorebug_embed, groundballs, hit_by_pitch, homeruns, is_game_over, lineouts, manual_end_game, new_game_conflicts, popouts, read_lineup, show_defense_cards, singles, starting_pitcher_dropdown_view, steals, strikeouts, sub_batter_dropdown_view, triples, undo_play, update_game_settings, walks, xchecks, activate_last_play
|
||||
from dice import ab_roll
|
||||
from exceptions import GameNotFoundException, GoogleSheetsException, TeamNotFoundException, PlayNotFoundException, GameException, log_exception
|
||||
import gauntlets
|
||||
@ -166,30 +166,20 @@ class Gameplay(commands.Cog):
|
||||
await interaction.response.defer()
|
||||
|
||||
with Session(engine) as session:
|
||||
conflict = get_channel_game_or_none(session, interaction.channel_id)
|
||||
if conflict is not None:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Ope. There is already a game going on in this channel. Please wait for it to complete '
|
||||
f'before starting a new one.'
|
||||
)
|
||||
return
|
||||
|
||||
if interaction.channel.category is None or interaction.channel.category.name != PUBLIC_FIELDS_CATEGORY_NAME:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Why don\'t you head down to one of the Public Fields that way other humans can help if anything pops up?'
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
await new_game_conflicts(session, interaction)
|
||||
except GameException as e:
|
||||
return
|
||||
|
||||
away_team = await get_team_or_none(session, team_abbrev=away_team_abbrev)
|
||||
except LookupError as e:
|
||||
if away_team is None:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Hm. I\'m not sure who **{away_team_abbrev}** is - check on that and try again!'
|
||||
)
|
||||
return
|
||||
try:
|
||||
|
||||
home_team = await get_team_or_none(session, team_abbrev=home_team_abbrev)
|
||||
except LookupError as e:
|
||||
if home_team is None:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Hm. I\'m not sure who **{home_team_abbrev}** is - check on that and try again!'
|
||||
)
|
||||
@ -332,35 +322,29 @@ class Gameplay(commands.Cog):
|
||||
await interaction.response.defer()
|
||||
|
||||
with Session(engine) as session:
|
||||
conflict = get_channel_game_or_none(session, interaction.channel_id)
|
||||
if conflict is not None:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Ope. There is already a game going on in this channel. Please wait for it to complete '
|
||||
f'before starting a new one.'
|
||||
)
|
||||
return
|
||||
|
||||
if interaction.channel.category is None or interaction.channel.category.name != PUBLIC_FIELDS_CATEGORY_NAME:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Why don\'t you head down to one of the Public Fields that way other humans can help if anything pops up?'
|
||||
)
|
||||
try:
|
||||
await new_game_conflicts(session, interaction)
|
||||
except GameException as e:
|
||||
return
|
||||
|
||||
main_team = await get_team_or_none(
|
||||
session,
|
||||
gm_id=interaction.user.id
|
||||
gm_id=interaction.user.id,
|
||||
main_team=True
|
||||
)
|
||||
human_team = await get_team_or_none(
|
||||
session,
|
||||
gm_id=interaction.user.id,
|
||||
gauntlet_team=True
|
||||
)
|
||||
|
||||
if not main_team:
|
||||
await interaction.edit_original_response(
|
||||
content=f'I don\'t see a team for you, yet. You can sign up with the `/newteam` command!'
|
||||
)
|
||||
return
|
||||
|
||||
this_team = await get_team_or_none(
|
||||
session,
|
||||
team_abbrev=f'Gauntlet-{main_team.abbrev}'
|
||||
)
|
||||
if not this_team:
|
||||
if not human_team:
|
||||
await interaction.edit_original_response(
|
||||
content=f'I don\'t see an active run for you. You can get started with the `/gauntlets start` command!'
|
||||
)
|
||||
@ -377,7 +361,7 @@ class Gameplay(commands.Cog):
|
||||
this_event = e_query['events'][0]
|
||||
r_query = await db_get(
|
||||
'gauntletruns',
|
||||
params=[('team_id', this_team['id']), ('gauntlet_id', this_event['id']), ('is_active', True)]
|
||||
params=[('team_id', human_team['id']), ('gauntlet_id', this_event['id']), ('is_active', True)]
|
||||
)
|
||||
|
||||
if r_query['count'] == 0:
|
||||
@ -392,7 +376,7 @@ class Gameplay(commands.Cog):
|
||||
else:
|
||||
r_query = await db_get(
|
||||
'gauntletruns',
|
||||
params=[('team_id', this_team['id']), ('is_active', True)]
|
||||
params=[('team_id', human_team.id), ('is_active', True)]
|
||||
)
|
||||
|
||||
if r_query['count'] == 0:
|
||||
@ -406,22 +390,34 @@ class Gameplay(commands.Cog):
|
||||
this_event = r_query['runs'][0]['gauntlet']
|
||||
|
||||
# If not new or after draft, create new AI game
|
||||
is_home = gauntlets.is_home_team(this_team, this_event, this_run)
|
||||
opponent = await gauntlets.get_opponent(this_team, this_event, this_run)
|
||||
if opponent is None:
|
||||
is_home = gauntlets.is_home_team(human_team, this_event, this_run)
|
||||
ai_team = await gauntlets.get_opponent(session, human_team, this_event, this_run)
|
||||
if ai_team is None:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Yike. I\'m not sure who your next opponent is. Plz ping the shit out of Cal!'
|
||||
)
|
||||
return
|
||||
else:
|
||||
logger.info(f'opponent: {opponent}')
|
||||
logger.info(f'opponent: {ai_team}')
|
||||
|
||||
ai_role = await team_role(interaction, ai_team)
|
||||
human_role = await team_role(interaction, human_team)
|
||||
away_role = ai_role if is_home else human_role
|
||||
home_role = human_role if is_home else ai_role
|
||||
|
||||
conflict_games = get_active_games_by_team(session, team=human_team)
|
||||
if len(conflict_games) > 0:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Ope. The {human_team.sname} are already playing over in {interaction.guild.get_channel(conflict_games[0].channel_id).mention}'
|
||||
)
|
||||
return
|
||||
|
||||
current = await db_get('current')
|
||||
game_code = gauntlets.get_game_code(this_team, this_event, this_run)
|
||||
game_code = gauntlets.get_game_code(human_team, this_event, this_run)
|
||||
|
||||
this_game = Game(
|
||||
away_team_id=opponent.id if is_home else this_team.id,
|
||||
home_team_id=this_team.id if is_home else opponent.id,
|
||||
away_team_id=ai_team.id if is_home else human_team.id,
|
||||
home_team_id=human_team.id if is_home else ai_team.id,
|
||||
channel_id=interaction.channel_id,
|
||||
season=current['season'],
|
||||
week=current['week'],
|
||||
@ -430,14 +426,79 @@ class Gameplay(commands.Cog):
|
||||
game_type=game_code
|
||||
)
|
||||
logger.info(
|
||||
f'Game {this_game.id} between {this_team.abbrev} and {opponent.abbrev} is posted!'
|
||||
f'Game {this_game.id} between {human_team.abbrev} and {ai_team.abbrev} is initializing!'
|
||||
)
|
||||
|
||||
# Get AI SP
|
||||
await interaction.edit_original_response(
|
||||
content=f'{ai_team.gmname} is looking for a Starting Pitcher...'
|
||||
)
|
||||
ai_sp_lineup = await get_starting_pitcher(
|
||||
session,
|
||||
ai_team,
|
||||
this_game,
|
||||
is_home=True if not is_home else False,
|
||||
league_name=game_code
|
||||
)
|
||||
logger.info(f'Chosen SP in Game {this_game.id}: {ai_sp_lineup.player.name_with_desc}')
|
||||
await interaction.edit_original_response(
|
||||
content=f'The {ai_team.sname} are starting **{ai_sp_lineup.player.name_with_desc}**:\n\n{ai_sp_lineup.player.pitcher_card_url}'
|
||||
)
|
||||
|
||||
# Get AI Lineup
|
||||
final_message = await interaction.channel.send(
|
||||
content=f'{ai_team.gmname} is filling out the {ai_team.sname} lineup card...'
|
||||
)
|
||||
logger.info(f'Pulling lineup in Game {this_game.id}')
|
||||
batter_lineups = await get_starting_lineup(
|
||||
session,
|
||||
team=ai_team,
|
||||
game=this_game,
|
||||
league_name=game_code,
|
||||
sp_name=ai_sp_lineup.player.name
|
||||
)
|
||||
t_role = await team_role(interaction, main_team)
|
||||
|
||||
await interaction.edit_original_response(
|
||||
content=f'Creating this game for {t_role.mention}:\n{this_game}'
|
||||
)
|
||||
|
||||
# Check for last game settings
|
||||
logger.info(f'Checking human team\'s automation preferences...')
|
||||
g_query = session.exec(select(Game).where(or_(Game.home_team == human_team, Game.away_team == human_team)).order_by(Game.id.desc()).limit(1)).all()
|
||||
|
||||
if len(g_query) > 0:
|
||||
last_game = g_query[0]
|
||||
this_game.auto_roll = last_game.auto_roll
|
||||
this_game.roll_buttons = last_game.roll_buttons
|
||||
logger.info(f'Setting auto_roll to {last_game.auto_roll} and roll_buttons to {last_game.roll_buttons}')
|
||||
|
||||
# Commit game and lineups
|
||||
session.add(this_game)
|
||||
session.commit()
|
||||
|
||||
await final_message.edit(content=f'The {ai_team.sname} lineup is in, pulling in scouting data...')
|
||||
for batter in batter_lineups:
|
||||
if batter.position != 'DH':
|
||||
await get_position(session, batter.card, batter.position)
|
||||
|
||||
embed = await get_scorebug_embed(session, this_game)
|
||||
embed.clear_fields()
|
||||
embed.add_field(
|
||||
name=f'{ai_team.abbrev} Lineup',
|
||||
value=this_game.team_lineup(session, ai_team)
|
||||
)
|
||||
|
||||
# Get pitchers from rosterlinks
|
||||
done = await get_full_roster_from_sheets(session, interaction, self.sheets, this_game, human_team, 1)
|
||||
if done:
|
||||
sp_view = starting_pitcher_dropdown_view(session, this_game, human_team)
|
||||
await interaction.channel.send(content=f'### {human_team.lname} Starting Pitcher', view=sp_view)
|
||||
|
||||
await final_message.edit(
|
||||
content=f'{away_role.mention} @ {home_role.mention} is set!',
|
||||
embed=embed
|
||||
)
|
||||
|
||||
# TODO: add new-game exhibition, unlimited, and ranked
|
||||
|
||||
@commands.command(name='force-endgame', help='Mod: Force a game to end without stats')
|
||||
@ -527,7 +588,7 @@ class Gameplay(commands.Cog):
|
||||
return
|
||||
|
||||
this_play = this_game.current_play_or_none(session)
|
||||
await self.post_play(session, interaction, this_play)
|
||||
await self.post_play(session, interaction, this_play, full_length=include_lineups)
|
||||
|
||||
@app_commands.command(name='settings-ingame', description='Change in-game settings')
|
||||
@app_commands.describe(
|
||||
|
||||
@ -14,7 +14,7 @@ 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 helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel
|
||||
from in_game.game_helpers import legal_check
|
||||
from in_game.game_helpers import PUBLIC_FIELDS_CATEGORY_NAME, legal_check
|
||||
from in_game.gameplay_models import BattingCard, Game, Lineup, PositionRating, RosterLink, Team, Play
|
||||
from in_game.gameplay_queries import get_available_batters, get_batter_card, get_batting_statline, get_pitching_statline, get_position, get_available_pitchers, get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, get_game_lineups, get_last_team_play, get_one_lineup, get_player_id_from_dict, get_player_name_from_dict, get_player_or_none, get_sorted_lineups, get_team_or_none, get_players_last_pa, post_game_rewards
|
||||
from in_game.managerai_responses import DefenseResponse
|
||||
@ -968,9 +968,10 @@ async def flyballs(session: Session, interaction: discord.Interaction, this_play
|
||||
ranges_embed = this_of.team.embed
|
||||
ranges_embed.title = f'Tag Play'
|
||||
ranges_embed.description = f'{this_of.team.abbrev} {this_of.position} {this_of.card.player.name}\'s Throw vs {runner.name}'
|
||||
ranges_embed.add_field(name=f'{this_of.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}')
|
||||
ranges_embed.add_field(name=f'Runner Speed', value=runner_lineup.card.batterscouting.battingcard.running)
|
||||
ranges_embed.add_field(name=f'{this_of.position} Mod', value=f'{of_mod}', inline=False)
|
||||
ranges_embed.add_field(name=f'{this_of.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}')
|
||||
ranges_embed.add_field(name=f'{this_of.position} Mod', value=f'{of_mod}')
|
||||
ranges_embed.add_field(name='', value='', inline=False)
|
||||
ranges_embed.add_field(name='Safe Range', value=safe_string)
|
||||
ranges_embed.add_field(name='Hold Range', value=hold_string)
|
||||
ranges_embed.add_field(name='Out Range', value=out_string)
|
||||
@ -1320,7 +1321,6 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
of_rating = await get_position(session, this_card=outfielder.card, position=outfielder.position)
|
||||
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
|
||||
|
||||
@ -1336,6 +1336,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
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)
|
||||
lead_runner_embed.add_field(name=f'{outfielder.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}')
|
||||
|
||||
if this_play.starting_outs == 2:
|
||||
logger.info(f'Adding 2 for 2 outs')
|
||||
@ -1353,11 +1354,13 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
# Build trail runner embed
|
||||
trail_runner_embed = copy.deepcopy(runner_embed)
|
||||
trail_bc = get_batter_card(this_lineup=trail_runner)
|
||||
logger.info(f'trail runner batting card: {trail_bc}')
|
||||
|
||||
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_runner_embed.add_field(name=f'{outfielder.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}')
|
||||
|
||||
trail_safe_range = trail_bc.running - 5 + of_rating.arm
|
||||
logger.info(f'trail_safe_range: {trail_safe_range}')
|
||||
@ -1680,6 +1683,10 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
this_play.rbi += 1
|
||||
log_run_scored(session, lead_runner, this_play)
|
||||
|
||||
if trail_runner != this_play.batter:
|
||||
logger.info(f'Trail runner is not batter, advancing batter')
|
||||
this_play.batter_final += 1
|
||||
|
||||
return this_play
|
||||
|
||||
# Ball is going to lead base, ask if safe
|
||||
@ -1835,6 +1842,10 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
this_play.rbi += 1
|
||||
log_run_scored(session, lead_runner, this_play)
|
||||
|
||||
if trail_runner != this_play.batter:
|
||||
logger.info(f'Trail runner is not batter, advancing batter')
|
||||
this_play.batter_final += 1
|
||||
|
||||
return this_play
|
||||
|
||||
else:
|
||||
@ -3500,3 +3511,19 @@ def gb_result_13(session: Session, this_play: Play):
|
||||
this_play = gb_result_2(session, this_play)
|
||||
|
||||
return this_play
|
||||
|
||||
|
||||
async def new_game_conflicts(session: Session, interaction: discord.Interaction):
|
||||
conflict = get_channel_game_or_none(session, interaction.channel_id)
|
||||
if conflict is not None:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Ope. There is already a game going on in this channel. Please wait for it to complete '
|
||||
f'before starting a new one.'
|
||||
)
|
||||
log_exception(GameException, f'{interaction.user} attempted to start a new game in {interaction.channel.name}, but there is another active game')
|
||||
|
||||
if interaction.channel.category is None or interaction.channel.category.name != PUBLIC_FIELDS_CATEGORY_NAME:
|
||||
await interaction.edit_original_response(
|
||||
content=f'Why don\'t you head down to one of the Public Fields that way other humans can help if anything pops up?'
|
||||
)
|
||||
log_exception(GameException, f'{interaction.user} attempted to start a new game in {interaction.channel.name} so they were redirected to {PUBLIC_FIELDS_CATEGORY_NAME}')
|
||||
|
||||
@ -81,3 +81,7 @@ class InvalidResultException(GameException):
|
||||
|
||||
class ButtonOptionNotChosen(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MissingRoleException(GameException):
|
||||
pass
|
||||
|
||||
@ -215,7 +215,6 @@ async def get_opponent(session: Session, this_team, this_event, this_run) -> Tea
|
||||
t_id = 25
|
||||
else:
|
||||
raise KeyError(f'Hmm...I do not know who you should be playing right now.')
|
||||
return await db_get('teams', object_id=t_id, none_okay=False)
|
||||
elif this_event['id'] == 7:
|
||||
if gp == 0:
|
||||
t_id = 10
|
||||
@ -244,6 +243,8 @@ async def get_opponent(session: Session, this_team, this_event, this_run) -> Tea
|
||||
else:
|
||||
return None
|
||||
|
||||
this_team = await get_team_or_none(session, team_id=t_id)
|
||||
logger.info(f'Gauntlet opponent: {this_team}')
|
||||
return await get_team_or_none(session, t_id)
|
||||
|
||||
|
||||
|
||||
@ -317,6 +317,7 @@ async def get_starting_lineup(session: Session, team: Team, game: Game, league_n
|
||||
async def get_starting_pitcher(
|
||||
session: Session, this_team: Team, this_game: Game, is_home: bool, league_name: str) -> Lineup:
|
||||
d_100 = random.randint(1, 100)
|
||||
logger.info(f'Getting a {league_name} starting pitcher for the {this_team.lname}; d100: {d_100}')
|
||||
if is_home:
|
||||
if d_100 <= 30:
|
||||
sp_rank = 1
|
||||
@ -339,6 +340,7 @@ async def get_starting_pitcher(
|
||||
sp_rank = 4
|
||||
else:
|
||||
sp_rank = 5
|
||||
logger.info(f'chosen rank: {sp_rank}')
|
||||
|
||||
sp_query = await db_get(
|
||||
f'teams/{this_team.id}/sp/{league_name}?sp_rank={sp_rank}{this_game.cardset_param_string}'
|
||||
|
||||
@ -60,7 +60,7 @@ def get_active_games_by_team(session: Session, team: Team) -> list[Game]:
|
||||
|
||||
|
||||
async def get_team_or_none(
|
||||
session: Session, team_id: int | None = None, gm_id: int | None = None, team_abbrev: str | None = None, skip_cache: bool = False, main_team: bool = None, gauntlet_team: bool = None) -> Team | None:
|
||||
session: Session, team_id: int | None = None, gm_id: int | None = None, team_abbrev: str | None = None, skip_cache: bool = False, main_team: bool = None, gauntlet_team: bool = None, include_packs: bool = False) -> Team | None:
|
||||
logger.info(f'Getting team or none / team_id: {team_id} / gm_id: {gm_id} / team_abbrev: {team_abbrev} / skip_cache: {skip_cache} / main_team: {main_team} / gauntlet_team: {gauntlet_team}')
|
||||
if gm_id is not None:
|
||||
if main_team is None and gauntlet_team is None:
|
||||
@ -106,18 +106,18 @@ async def get_team_or_none(
|
||||
return db_team
|
||||
|
||||
if team_id is not None:
|
||||
t_query = await db_get('teams', object_id=team_id, params=[('inc_packs', False)])
|
||||
t_query = await db_get('teams', object_id=team_id, params=[('inc_packs', include_packs)])
|
||||
if t_query is not None:
|
||||
return cache_team(t_query)
|
||||
|
||||
elif gm_id is not None:
|
||||
t_query = await db_get('teams', params=[('gm_id', gm_id)])
|
||||
t_query = await db_get('teams', params=[('gm_id', gm_id), ('inc_packs', include_packs)])
|
||||
if t_query['count'] != 0:
|
||||
for team in [x for x in t_query['teams'] if 'gauntlet' not in x['abbrev'].lower()]:
|
||||
return cache_team(team)
|
||||
|
||||
elif team_abbrev is not None:
|
||||
t_query = await db_get('teams', params=[('abbrev', team_abbrev)])
|
||||
t_query = await db_get('teams', params=[('abbrev', team_abbrev), ('inc_packs', include_packs)])
|
||||
if t_query['count'] != 0:
|
||||
if 'gauntlet' in team_abbrev.lower():
|
||||
return cache_team(t_query['teams'][0])
|
||||
|
||||
Loading…
Reference in New Issue
Block a user