import random
# --- 데이터: 타구 묘사 및 수비 위치 ---
OUT_DESCRIPTIONS = {'GB': [("유격수 땅볼 아웃", 'SS'),("2루수 땅볼 아웃", '2B'),("3루수 땅볼 아웃", '3B'),("투수 앞 땅볼", 'P'),("1루수 땅볼 아웃", '1B')],'FB': [("좌익수 뜬공 아웃", 'LF'),("중견수 뜬공 아웃", 'CF'),("우익수 뜬공 아웃", 'RF'),("내야 뜬공 아웃", '2B')]}
SINGLE_DESCRIPTIONS = ["중견수 앞 안타", "우익수 방향 안타", "좌익수 앞에 떨어지는 1루타"]
DOUBLE_DESCRIPTIONS = ["좌중간을 가르는 2루타", "우측 펜스를 직격하는 2루타"]
TRIPLE_DESCRIPTIONS = ["우중간 깊숙한 3루타"]
HOMERUN_DESCRIPTIONS = ["좌측 담장을 넘기는 홈런!", "가운데 담장을 넘기는 대형 홈런!"]
# --- 클래스 정의 ---
class Player:
def __init__(self, name, hand, stats, zones, fielding_pos):
self.name = name; self.batting_hand = hand; self.stats = stats
self.hot_zone = zones['hot']; self.cold_zone = zones['cold']
self.fielding_pos = fielding_pos; self.fielding_rating = stats.get('fielding', 50)
class Pitcher:
def __init__(self, name, hand, role, stats, pitches):
self.name = name; self.throwing_hand = hand; self.role = role
self.base_stats = stats; self.stats = stats.copy()
self.pitches = pitches; self.pitch_count = 0
self.max_stamina = stats.get('stamina', 50)
self.current_stamina_pct = 100.0
self.fielding_rating = stats.get('fielding', 50)
self._pitch_list = list(pitches.keys()); self._usage_weights = [p['usage'] for p in pitches.values()]
def select_pitch(self, target_location):
selected_pitch_name = random.choices(self._pitch_list, weights=self._usage_weights, k=1)[0]
pitch_info = self.pitches[selected_pitch_name]
deviation = max(0, 10 - int((self.stats['location'] - 20) / 10))
actual_location = target_location + random.randint(-deviation, deviation)
return selected_pitch_name, pitch_info, actual_location
def update_stamina(self):
fatigue_rate = 1.5 - ((self.max_stamina - 40) * 0.01)
self.current_stamina_pct -= fatigue_rate
penalty = 0
if self.current_stamina_pct < 40: penalty = (40 - self.current_stamina_pct) / 4
if self.current_stamina_pct < 15:
print(f"!! {self.name} 투수, 지친 기색이 역력합니다! (스태미나: {self.current_stamina_pct:.1f}%) !!")
penalty += (15 - self.current_stamina_pct) / 1.5
self.stats['location'] = max(20, self.base_stats['location'] - penalty)
self.stats['stuff'] = max(20, self.base_stats['stuff'] - penalty)
self.stats['movement'] = max(20, self.base_stats['movement'] - penalty)
class Team:
def __init__(self, name, batters, starting_pitcher, bullpen):
self.name = name; self.batters = batters; self.score = 0
self.starting_pitcher = starting_pitcher; self.bullpen = bullpen[:] # 리스트 복사본 사용
self.current_pitcher = starting_pitcher
self.current_batter_index = 0
self.defensive_lineup = {player.fielding_pos: player for player in self.batters}
self.defensive_lineup['P'] = self.current_pitcher
self.hits = 0
self.errors_committed = 0
def get_next_batter(self):
batter = self.batters[self.current_batter_index]
self.current_batter_index = (self.current_batter_index + 1) % len(self.batters); return batter
def change_pitcher(self, new_pitcher):
print(f"\n>>>> 투수 교체: {self.current_pitcher.name} 내려가고, {new_pitcher.name} 올라옵니다! <<<<")
self.current_pitcher = new_pitcher
self.defensive_lineup['P'] = new_pitcher
if new_pitcher in self.bullpen:
self.bullpen.remove(new_pitcher)
EMERGENCY_PITCHER_TEMPLATE = Pitcher("비상 등판 야수", 'R', 'GARBAGE', {'stamina': 20, 'command': 20, 'location': 20, 'stuff': 20, 'movement': 20, 'fielding': 40},
{'직구': {'grade': 20, 'usage': 100, 'velocity': 120, 'whiff_bonus': 0, 'gb_fb_bonus': 0}})
class Game:
def __init__(self, team1, team2):
self.teams = [team1, team2]; self.inning = 1; self.outs = 0; self.bases = [None, None, None]
self.inning_scores = {team1.name: [0] * 9, team2.name: [0] * 9} # 9이닝 점수판
def display_status(self):
runner_info = f"주자: 1루({self.bases[0].name if self.bases[0] else 'X'}) 2루({self.bases[1].name if self.bases[1] else 'X'}) 3루({self.bases[2].name if self.bases[2] else 'X'})"
score_info = f"스코어: {self.teams[0].name} {self.teams[0].score} : {self.teams[1].score} {self.teams[1].name}"
out_info = f"아웃: {self.outs}"
print(f"[{runner_info}] | [{score_info}] | [{out_info}]")
print("-" * 80)
# Game 클래스 내부에 있는 advance_runners 메소드를 아래 코드로 교체하세요.
# Game 클래스 내부에 있는 advance_runners 메소드를 아래 코드로 교체하세요.
def advance_runners(self, batter, hit_type, attacking_team, is_error=False):
if is_error:
runs_scored_on_error = 0
if self.bases[2] is not None: runs_scored_on_error += 1; self.bases[2] = None
if self.bases[1] is not None: runs_scored_on_error += 1; self.bases[1] = None
if runs_scored_on_error > 0:
attacking_team.score += runs_scored_on_error
# Ensure correct dictionary and list access
if self.inning <= 9: self.inning_scores[attacking_team.name][self.inning - 1] += runs_scored_on_error
print(f"*** 실책으로 {runs_scored_on_error}점 득점! ***")
# 실책 진루
if self.bases[0] is not None: self.bases[1] = self.bases[0]
self.bases[0] = batter
return
scored_runners = []
if hit_type in ["Single", "Double", "Triple", "Homerun"]:
attacking_team.hits += 1
# --- 진루 로직 ---
if hit_type == "Single":
if self.bases[2] is not None: scored_runners.append(self.bases[2]); self.bases[2] = None
if self.bases[1] is not None: scored_runners.append(self.bases[1]); self.bases[1] = None # 단타에 2루 주자 홈인
if self.bases[0] is not None:
if random.random() < 0.4: self.bases[2] = self.bases[0] # 1루 -> 3루
else: self.bases[1] = self.bases[0] # 1루 -> 2루
self.bases[0] = None
self.bases[0] = batter # 타자 -> 1루
elif hit_type in ["Double", "Triple", "Homerun"]:
advances = {"Double": 2, "Triple": 3, "Homerun": 4}[hit_type]
for i in range(2, -1, -1): # 3루부터
if self.bases[i] is not None:
new_base = i + advances
if new_base >= 3: scored_runners.append(self.bases[i]) # 득점
else: self.bases[new_base] = self.bases[i] # 진루
self.bases[i] = None # 원래 있던 루 비움
if advances >= 4: scored_runners.append(batter) # 홈런 타자 득점
else: self.bases[advances - 1] = batter # 타자 진루
elif hit_type == "Walk":
if self.bases[0] is not None and self.bases[1] is not None and self.bases[2] is not None: # 만루
scored_runners.append(self.bases[2]); self.bases[2] = self.bases[1]; self.bases[1] = self.bases[0] # 밀어내기
elif self.bases[0] is not None and self.bases[1] is not None: # 1, 2루
self.bases[2] = self.bases[1]; self.bases[1] = self.bases[0]
elif self.bases[0] is not None: # 1루
self.bases[1] = self.bases[0]
self.bases[0] = batter # 타자 -> 1루
# --- 진루 로직 끝 ---
# 득점 처리 및 점수판 업데이트
if scored_runners:
runs_this_play = len(scored_runners)
attacking_team.score += runs_this_play
# Ensure correct dictionary and list access
if self.inning <= 9:
# Make sure attacking_team.name is a valid key and self.inning-1 is a valid index
try:
self.inning_scores[attacking_team.name][self.inning - 1] += runs_this_play
except KeyError:
print(f"!!! ERROR: Team name '{attacking_team.name}' not found in inning_scores !!!")
except IndexError:
print(f"!!! ERROR: Inning index {self.inning - 1} out of range !!!")
print(f"*** {runs_this_play}점 득점! ***")
def simulate_at_bat(self, batter, pitcher):
strikes, balls = 0, 0
temp_batter_stats = batter.stats.copy()
if batter.batting_hand == pitcher.throwing_hand:
print(f"(상성 불리! {pitcher.throwing_hand}투수 vs {batter.batting_hand}타자)")
for key in ['contact', 'power', 'gap_power', 'eye']: temp_batter_stats[key] = max(20, temp_batter_stats[key] - 5)
print(f"\n--- 마운드: {pitcher.name}({pitcher.current_stamina_pct:.1f}%) vs 타석: {batter.name} ---")
while strikes < 3 and balls < 4:
pitcher.pitch_count += 1; pitcher.update_stamina()
target_location = 5 if random.random() > (pitcher.stats['command'] - 20) / 60.0 else random.choice([1,3,7,9])
pitch_name, pitch_info, actual_location = pitcher.select_pitch(target_location)
velocity = pitch_info['velocity'] + random.randint(-2, 2)
print(f"투구: {pitch_name}({velocity}km/h) to Zone {actual_location} | 카운트: {balls}-{strikes} | 총 투구수: {pitcher.pitch_count}")
current_batter_stats = temp_batter_stats.copy()
if actual_location in batter.hot_zone: print("타자의 Hot Zone으로 공이!"); [current_batter_stats.update({k:v+10}) for k,v in current_batter_stats.items() if k in ['contact', 'power']]
elif actual_location in batter.cold_zone: print("타자의 Cold Zone... 공략당합니다!"); [current_batter_stats.update({k:max(20, v-10)}) for k,v in current_batter_stats.items() if k in ['contact', 'power']]
control_vs_eye = (pitcher.stats['location'] + pitch_info['grade'])/2 - current_batter_stats['eye']
if random.random() < (0.45 - (control_vs_eye * 0.008)): balls += 1; print("판정: 볼!"); continue
stuff_vs_contact = (pitcher.stats['stuff'] - (current_batter_stats['contact'] + current_batter_stats['avoid_k'])/2) + pitch_info['whiff_bonus']
if random.random() < (0.3 + (stuff_vs_contact * 0.006)): strikes += 1; print("결과: 헛스윙 스트라이크!"); continue
foul_chance = 0.45 + (current_batter_stats['avoid_k'] - 50) * 0.003
if strikes == 2: foul_chance += (current_batter_stats['avoid_k'] - 50) * 0.0015
if random.random() < foul_chance:
if strikes < 2: strikes += 1
print("결과: 파울!"); continue
print("결과: 타격! 인플레이!"); return self.determine_hit_type(batter, pitcher, pitch_info)
if strikes == 3: return "Strikeout", ("삼진 아웃!", None)
if balls == 4: return "Walk", ("볼넷 출루!", None)
def determine_hit_type(self, batter, pitcher, pitch_info):
gb_chance = 0.5 + pitch_info['gb_fb_bonus'] / 100.0
power_vs_movement = batter.stats['power'] - pitcher.stats['movement']
if random.random() < (((power_vs_movement + 60) ** 2) / 75000.0): return "Homerun", (random.choice(HOMERUN_DESCRIPTIONS), None)
gap_vs_movement = batter.stats['gap_power'] - pitcher.stats['movement']
if random.random() < (((gap_vs_movement + 60) ** 2) / 55000.0):
if random.random() < 0.8: return "Double", (random.choice(DOUBLE_DESCRIPTIONS), None)
else: return "Triple", (random.choice(TRIPLE_DESCRIPTIONS), None)
if random.random() < ((batter.stats['contact'] - pitcher.stats['stuff'] * 0.6) / 110.0): return "Single", (random.choice(SINGLE_DESCRIPTIONS), None)
if random.random() < gb_chance: desc, pos = random.choice(OUT_DESCRIPTIONS['GB']); return "Out", (desc, pos)
else: desc, pos = random.choice(OUT_DESCRIPTIONS['FB']); return "Out", (desc, pos)
def check_for_pitcher_change(self, defending_team, attacking_team):
pitcher = defending_team.current_pitcher
if pitcher.role == 'GARBAGE': return
change_reason = None
if pitcher.role == 'SP' and pitcher.pitch_count > 105: change_reason = "선발 투구수 105구 초과"
elif pitcher.current_stamina_pct < 10: change_reason = "스태미나 완전 고갈"
score_diff = defending_team.score - attacking_team.score
is_late_inning = self.inning >= 7
runners_in_scoring_pos = self.bases[1] or self.bases[2]
if is_late_inning and runners_in_scoring_pos and -1 <= score_diff <= 3 and pitcher.current_stamina_pct < 40:
change_reason = "경기 후반 승부처"
if not change_reason: return
print(f"\n--- 감독 결정: {change_reason}으로 투수 교체를 고려합니다. ---")
if defending_team.bullpen:
new_pitcher = None
if self.inning >= 9 and 0 < score_diff <= 3: new_pitcher = next((p for p in defending_team.bullpen if p.role == 'CP'), None)
elif self.inning >= 8 and 0 < score_diff <= 3: new_pitcher = next((p for p in defending_team.bullpen if p.role == 'SU'), None)
if not new_pitcher: new_pitcher = next((p for p in defending_team.bullpen if p.role == 'MRP'), defending_team.bullpen[0])
defending_team.change_pitcher(new_pitcher)
else:
print("!!! 불펜에 남은 투수가 없습니다! 비상 상황입니다! !!!")
emergency_pitcher_instance = Pitcher(EMERGENCY_PITCHER_TEMPLATE.name, EMERGENCY_PITCHER_TEMPLATE.throwing_hand, EMERGENCY_PITCHER_TEMPLATE.role, EMERGENCY_PITCHER_TEMPLATE.base_stats, EMERGENCY_PITCHER_TEMPLATE.pitches)
defending_team.change_pitcher(emergency_pitcher_instance)
def play_half_inning(self, attacking_team_idx):
defending_team_idx = 1 - attacking_team_idx; attacking_team = self.teams[attacking_team_idx]; defending_team = self.teams[defending_team_idx]
self.outs = 0; self.bases = [None, None, None]
while self.outs < 3:
self.check_for_pitcher_change(defending_team, attacking_team)
batter = attacking_team.get_next_batter()
outcome, (description, position) = self.simulate_at_bat(batter, defending_team.current_pitcher)
# !!!!! BUG FIX: 삼진(Strikeout)도 아웃으로 처리 !!!!!
if outcome == "Strikeout":
print(f"▶ {description}!")
self.outs += 1
elif outcome == "Out":
fielder = defending_team.defensive_lineup.get(position)
if fielder is None: # DH 등이 수비 위치로 지정된 경우 대비
print(f"!!! DEBUG: Fielder not found for position {position}. Assigning to SS. !!!")
fielder = defending_team.defensive_lineup.get('SS', defending_team.batters[0])
error_chance = 0.1 - (fielder.fielding_rating - 50) * 0.0015
if random.random() < error_chance:
print(f"▶ {description}... 이럴수가! {fielder.name}의 실책입니다!")
defending_team.errors_committed += 1
self.advance_runners(batter, "Single", attacking_team, is_error=True)
else:
print(f"▶ {description}!")
self.outs += 1
else: # 안타, 홈런, 볼넷 등
print(f"▶ {description}!")
self.advance_runners(batter, outcome, attacking_team)
# 아웃카운트가 3 미만일 때만 다음 타석 진행 전 상태 표시
if self.outs < 3:
self.display_status()
# 3 아웃 시에는 이닝 종료 메시지 후 상태 표시 (run_game에서 처리)
def run_game(self):
print(f"--- {self.teams[0].name} vs {self.teams[1].name} 경기 시작 ---"); self.display_status()
for inning in range(1, 10):
self.inning = inning
print(f"\n{'='*30} {self.inning}회초 공격 ({self.teams[0].name}) {'='*30}"); self.play_half_inning(0)
print(f"--- {self.inning}회초 종료 ---"); self.display_status()
if self.inning == 9 and self.teams[0].score < self.teams[1].score: break
print(f"\n{'='*30} {self.inning}회말 공격 ({self.teams[1].name}) {'='*30}"); self.play_half_inning(1)
print(f"--- {self.inning}회말 종료 ---"); self.display_status()
print("\n" + "="*30 + " 경기 종료 " + "="*30)
# !!!!! 기존 display_status() 대신 스코어보드 함수 호출 !!!!!
self.display_final_scoreboard()
def display_final_scoreboard(self):
"""경기 종료 후 최종 스코어보드를 출력"""
team1 = self.teams[0]
team2 = self.teams[1]
# 헤더 출력 (1~9회 + R, H, E)
header = "Team | 1 2 3 4 5 6 7 8 9 | R H E"
separator = "-" * len(header)
print("\n" + separator)
print(header)
print(separator)
# 팀별 점수, 안타, 실책 출력
def format_scores(team_name, scores, total_runs, hits, errors):
# 팀 이름은 최대 9글자까지 표시
name_str = f"{team_name[:9]:<9}"
# 이닝별 점수 문자열 만들기
score_str = " ".join(f"{s:<2}" for s in scores)
# 최종 결과 문자열 만들기 (R, H, E)
result_str = f"| {total_runs:<2} {hits:<2} {errors:<2}"
return f"{name_str} | {score_str} {result_str}"
print(format_scores(team1.name, self.inning_scores[team1.name], team1.score, team1.hits, team1.errors_committed))
print(format_scores(team2.name, self.inning_scores[team2.name], team2.score, team2.hits, team2.errors_committed))
print(separator + "\n")
def main():
# --- 2025 LG 트윈스 로스터 ---
lg_batters = [
Player("홍창기", 'L', {'contact': 70, 'power': 45, 'gap_power': 55, 'eye': 80, 'avoid_k': 75, 'fielding': 60}, {'hot': [1,7], 'cold': [5]}, 'RF'),
Player("박해민", 'L', {'contact': 60, 'power': 35, 'gap_power': 45, 'eye': 55, 'avoid_k': 70, 'fielding': 80}, {'hot': [1], 'cold': [9]}, 'CF'),
Player("김현수", 'L', {'contact': 75, 'power': 60, 'gap_power': 65, 'eye': 70, 'avoid_k': 80, 'fielding': 45}, {'hot': [5,6], 'cold': [1]}, 'LF'),
Player("오스틴", 'R', {'contact': 65, 'power': 70, 'gap_power': 70, 'eye': 60, 'avoid_k': 50, 'fielding': 55}, {'hot': [4,5], 'cold': [7]}, '1B'),
Player("오지환", 'L', {'contact': 55, 'power': 60, 'gap_power': 60, 'eye': 60, 'avoid_k': 45, 'fielding': 70}, {'hot': [6], 'cold': [1]}, 'SS'),
Player("문보경", 'L', {'contact': 65, 'power': 55, 'gap_power': 65, 'eye': 65, 'avoid_k': 70, 'fielding': 60}, {'hot': [8], 'cold': [2]}, '3B'),
Player("박동원", 'R', {'contact': 45, 'power': 70, 'gap_power': 55, 'eye': 45, 'avoid_k': 35, 'fielding': 50}, {'hot': [4], 'cold': [7,9]}, 'C'),
Player("신민재", 'L', {'contact': 55, 'power': 25, 'gap_power': 35, 'eye': 50, 'avoid_k': 65, 'fielding': 65}, {'hot': [1], 'cold': [5]}, '2B'),
Player("구본혁", 'R', {'contact': 45, 'power': 40, 'gap_power': 40, 'eye': 55, 'avoid_k': 60, 'fielding': 60}, {'hot': [8], 'cold': [3]}, 'DH'),
]
lg_sp = Pitcher("켈리", 'R', 'SP', {'stamina': 70, 'command': 65, 'location': 60, 'stuff': 65, 'movement': 60, 'fielding': 55},
{'포심': {'grade': 65, 'usage': 30, 'velocity': 148, 'whiff_bonus': 5, 'gb_fb_bonus': 0},
'커터': {'grade': 70, 'usage': 25, 'velocity': 142, 'whiff_bonus': 8, 'gb_fb_bonus': 5},
'커브': {'grade': 60, 'usage': 20, 'velocity': 125, 'whiff_bonus': 10, 'gb_fb_bonus': -5},
'체인지업': {'grade': 75, 'usage': 25, 'velocity': 133, 'whiff_bonus': 15, 'gb_fb_bonus': 10}})
lg_bullpen = [
Pitcher("함덕주", 'L', 'MRP', {'stamina': 40, 'command': 65, 'location': 60, 'stuff': 70, 'movement': 65, 'fielding': 50},
{'포심': {'grade': 65, 'usage': 40, 'velocity': 145, 'whiff_bonus': 8, 'gb_fb_bonus': 5},
'슬라이더': {'grade': 75, 'usage': 60, 'velocity': 133, 'whiff_bonus': 18, 'gb_fb_bonus': -10}}),
Pitcher("유영찬", 'R', 'SU', {'stamina': 45, 'command': 60, 'location': 55, 'stuff': 75, 'movement': 60, 'fielding': 50},
{'포심': {'grade': 70, 'usage': 60, 'velocity': 152, 'whiff_bonus': 10, 'gb_fb_bonus': 0},
'포크볼': {'grade': 65, 'usage': 40, 'velocity': 138, 'whiff_bonus': 15, 'gb_fb_bonus': 10}}),
Pitcher("고우석", 'R', 'CP', {'stamina': 35, 'command': 55, 'location': 50, 'stuff': 80, 'movement': 55, 'fielding': 50},
{'포심': {'grade': 80, 'usage': 70, 'velocity': 155, 'whiff_bonus': 15, 'gb_fb_bonus': -5},
'슬라이더': {'grade': 65, 'usage': 30, 'velocity': 140, 'whiff_bonus': 12, 'gb_fb_bonus': 0}}),
]
# --- 2025 한화 이글스 로스터 ---
hanwha_batters = [
Player("정은원", 'L', {'contact': 65, 'power': 45, 'gap_power': 55, 'eye': 75, 'avoid_k': 70, 'fielding': 65}, {'hot': [7], 'cold': [3]}, '2B'),
Player("최인호", 'L', {'contact': 60, 'power': 50, 'gap_power': 60, 'eye': 60, 'avoid_k': 65, 'fielding': 50}, {'hot': [8], 'cold': [1]}, 'LF'),
Player("노시환", 'R', {'contact': 55, 'power': 80, 'gap_power': 70, 'eye': 60, 'avoid_k': 40, 'fielding': 55}, {'hot': [4,1], 'cold': [9]}, '3B'),
Player("채은성", 'R', {'contact': 65, 'power': 65, 'gap_power': 65, 'eye': 55, 'avoid_k': 65, 'fielding': 50}, {'hot': [5,6], 'cold': [7]}, '1B'),
Player("안치홍", 'R', {'contact': 70, 'power': 55, 'gap_power': 65, 'eye': 65, 'avoid_k': 75, 'fielding': 60}, {'hot': [4,7], 'cold': [1]}, 'DH'),
Player("김태연", 'R', {'contact': 50, 'power': 60, 'gap_power': 55, 'eye': 50, 'avoid_k': 50, 'fielding': 45}, {'hot': [4], 'cold': [8]}, 'RF'),
Player("최재훈", 'R', {'contact': 60, 'power': 30, 'gap_power': 40, 'eye': 70, 'avoid_k': 80, 'fielding': 65}, {'hot': [7,8], 'cold': [2]}, 'C'),
Player("이도윤", 'R', {'contact': 55, 'power': 35, 'gap_power': 45, 'eye': 50, 'avoid_k': 60, 'fielding': 75}, {'hot': [9], 'cold': [1]}, 'SS'),
Player("이진영", 'L', {'contact': 50, 'power': 45, 'gap_power': 50, 'eye': 55, 'avoid_k': 55, 'fielding': 70}, {'hot': [2], 'cold': [8]}, 'CF'),
]
hanwha_sp = Pitcher("류현진", 'L', 'SP', {'stamina': 75, 'command': 80, 'location': 80, 'stuff': 65, 'movement': 70, 'fielding': 70},
{'포심': {'grade': 65, 'usage': 30, 'velocity': 145, 'whiff_bonus': 5, 'gb_fb_bonus': 5},
'커터': {'grade': 70, 'usage': 25, 'velocity': 140, 'whiff_bonus': 8, 'gb_fb_bonus': 10},
'커브': {'grade': 65, 'usage': 20, 'velocity': 120, 'whiff_bonus': 12, 'gb_fb_bonus': -10},
'체인지업': {'grade': 80, 'usage': 25, 'velocity': 130, 'whiff_bonus': 20, 'gb_fb_bonus': 15}})
hanwha_bullpen = [
Pitcher("주현상", 'R', 'MRP', {'stamina': 40, 'command': 65, 'location': 60, 'stuff': 65, 'movement': 75, 'fielding': 60},
{'투심': {'grade': 70, 'usage': 70, 'velocity': 146, 'whiff_bonus': 5, 'gb_fb_bonus': 20},
'슬라이더': {'grade': 60, 'usage': 30, 'velocity': 135, 'whiff_bonus': 10, 'gb_fb_bonus': 0}}),
Pitcher("박상원", 'R', 'SU', {'stamina': 40, 'command': 60, 'location': 55, 'stuff': 70, 'movement': 60, 'fielding': 50},
{'포심': {'grade': 70, 'usage': 50, 'velocity': 150, 'whiff_bonus': 12, 'gb_fb_bonus': -5},
'슬라이더': {'grade': 65, 'usage': 50, 'velocity': 138, 'whiff_bonus': 15, 'gb_fb_bonus': -10}}),
Pitcher("문동주", 'R', 'CP', {'stamina': 50, 'command': 55, 'location': 50, 'stuff': 80, 'movement': 65, 'fielding': 55},
{'포심': {'grade': 80, 'usage': 80, 'velocity': 158, 'whiff_bonus': 18, 'gb_fb_bonus': 0},
'커브': {'grade': 65, 'usage': 20, 'velocity': 130, 'whiff_bonus': 10, 'gb_fb_bonus': -5}}),
]
# Team 생성 시 bullpen 리스트 복사본 전달
lg_team = Team("LG 트윈스", lg_batters, lg_sp, lg_bullpen[:])
hanwha_team = Team("한화 이글스", hanwha_batters, hanwha_sp, hanwha_bullpen[:])
game = Game(lg_team, hanwha_team)
game.run_game()
input("\n경기가 모두 종료되었습니다. Enter 키를 누르면 창이 닫힙니다...")
if __name__ == "__main__":
main()
To embed this project on your website, copy the following code and paste it into your website's HTML: