import random
# 가챠 아이템 정의
FIVE_STAR_COMBATANTS = ["루크", "칼리페", "마그나", "린", "오를레아", "메이린", "베로니카", "레노아", "휴고", "카일론"]
FIVE_STAR_PICKUP_COMBATANTS = ["하루"]
FOUR_STAR_COMBATANTS = ["니아", "셀레나", "트리사", "아미르", "루카스", "마리벨", "카시우스", "오웬", "레이"]
FOUR_STAR_PICKUP_COMBATANTS = ["미카", "베릴"]
FOUR_STAR_PARTNERS = ["아르웬", "알리사", "아카드", "빌헬미나", "로자리아", "엘로이즈", "리토치카", "캐로티", "레이첼", "릴리안", "데이지"]
THREE_STAR_PARTNERS = ["나키아", "사테라", "라이델", "더글라스", "유리", "이본느"]
class GachaSimulator:
def __init__(self):
self.pity_count = 0 # 5성이 안 나온 횟수
self.guarantee_pickup = False # 다음 5성이 픽업 확정인지
self.pull_history = [] # 모든 뽑기 기록 저장
self.character_count = {} # 캐릭터별 뽑은 횟수
def get_five_star_rate(self):
"""현재 pity_count에 따른 5성 확률 계산"""
if self.pity_count < 58:
return 1.0
elif self.pity_count < 70:
# 58회부터 4.5%씩 증가
increase = (self.pity_count - 57) * 4.5
return 1.0 + increase
else: # 70회 (pity_count == 70)
return 100.0
def pull_once(self):
"""가챠 1회 뽑기"""
self.pity_count += 1
five_star_rate = self.get_five_star_rate()
roll = random.random() * 100
# 5성 전투원 판정
if roll < five_star_rate:
self.pity_count = 0
# 70회 확정 또는 140회 확정 판정
if self.guarantee_pickup:
# 픽업 확정
result = random.choice(FIVE_STAR_PICKUP_COMBATANTS)
self.guarantee_pickup = False
rarity = "5성 픽업 전투원"
else:
# 일반 5성 50%, 픽업 5성 50%
if random.random() < 0.5:
result = random.choice(FIVE_STAR_COMBATANTS)
self.guarantee_pickup = True # 다음은 픽업 확정
rarity = "5성 전투원"
else:
result = random.choice(FIVE_STAR_PICKUP_COMBATANTS)
self.guarantee_pickup = False # 픽업 나왔으므로 초기화
rarity = "5성 픽업 전투원"
# 4성 판정 (6%)
elif roll < 7.0: # 1% + 6% = 7%
# 4성 전투원, 4성 픽업 전투원, 4성 파트너를 균등하게
category = random.choice(['combatant', 'pickup_combatant', 'partner'])
if category == 'combatant':
result = random.choice(FOUR_STAR_COMBATANTS)
rarity = "4성 전투원"
elif category == 'pickup_combatant':
result = random.choice(FOUR_STAR_PICKUP_COMBATANTS)
rarity = "4성 픽업 전투원"
else:
result = random.choice(FOUR_STAR_PARTNERS)
rarity = "4성 파트너"
# 3성 파트너 (93%)
else:
result = random.choice(THREE_STAR_PARTNERS)
rarity = "3성 파트너"
# 뽑기 기록 저장
self.pull_history.append({
'character': result,
'rarity': rarity,
'pity_count': self.pity_count
})
# 캐릭터별 카운트 증가
if result in self.character_count:
self.character_count[result] += 1
else:
self.character_count[result] = 1
return result, rarity
def pull_multiple(self, count):
"""여러 번 뽑기"""
results = []
for i in range(count):
item, rarity = self.pull_once()
results.append({
'pull_number': i + 1,
'item': item,
'rarity': rarity,
'pity_after': self.pity_count
})
return results
def simulate_until_pickup_count(self, target_count=6, max_pulls=10000):
"""5성 픽업을 특정 개수만큼 뽑을 때까지 시뮬레이션"""
pickup_count = 0
total_pulls = 0
pickup_history = []
while pickup_count < target_count and total_pulls < max_pulls:
item, rarity = self.pull_once()
total_pulls += 1
if rarity == "5성 픽업 전투원":
pickup_count += 1
pickup_history.append({
'count': pickup_count,
'item': item,
'total_pulls': total_pulls
})
return total_pulls, pickup_history
def get_character_statistics(self):
"""캐릭터별 통계 반환"""
return self.character_count
def print_statistics(self):
"""캐릭터별 통계를 보기 좋게 출력"""
print("\n" + "=" * 50)
print("[캐릭터별 뽑기 통계]")
print("=" * 50)
# 등급별로 분류
five_star = {}
five_star_pickup = {}
four_star = {}
four_star_pickup = {}
four_star_partner = {}
three_star = {}
for char, count in self.character_count.items():
if char in FIVE_STAR_COMBATANTS:
five_star[char] = count
elif char in FIVE_STAR_PICKUP_COMBATANTS:
five_star_pickup[char] = count
elif char in FOUR_STAR_COMBATANTS:
four_star[char] = count
elif char in FOUR_STAR_PICKUP_COMBATANTS:
four_star_pickup[char] = count
elif char in FOUR_STAR_PARTNERS:
four_star_partner[char] = count
elif char in THREE_STAR_PARTNERS:
three_star[char] = count
# 5성 전투원
if five_star:
print("\n[5성 전투원]")
for char, count in sorted(five_star.items(), key=lambda x: x[1], reverse=True):
print(f" {char}: {count}번")
# 5성 픽업 전투원
if five_star_pickup:
print("\n[5성 픽업 전투원]")
for char, count in sorted(five_star_pickup.items(), key=lambda x: x[1], reverse=True):
print(f" {char}: {count}번")
# 4성 전투원
if four_star:
print("\n[4성 전투원]")
for char, count in sorted(four_star.items(), key=lambda x: x[1], reverse=True):
print(f" {char}: {count}번")
# 4성 픽업 전투원
if four_star_pickup:
print("\n[4성 픽업 전투원]")
for char, count in sorted(four_star_pickup.items(), key=lambda x: x[1], reverse=True):
print(f" {char}: {count}번")
# 4성 파트너
if four_star_partner:
print("\n[4성 파트너]")
for char, count in sorted(four_star_partner.items(), key=lambda x: x[1], reverse=True):
print(f" {char}: {count}번")
# 3성 파트너
if three_star:
print("\n[3성 파트너]")
for char, count in sorted(three_star.items(), key=lambda x: x[1], reverse=True):
print(f" {char}: {count}번")
# 총 통계
print("\n" + "=" * 50)
print(f"총 뽑기 횟수: {len(self.pull_history)}회")
print(f"획득한 캐릭터 종류: {len(self.character_count)}종")
# ===== 사용 예시 ===== # ===== 사용 예시 ===== # ===== 사용 예시 ===== # ===== 사용 예시 ===== # ===== 사용 예시 =====
num = 5000 # 시뮬레이션 반복 횟수
target_pickup = 11 # 목표 픽업 개수
print("=" * 50)
print("가챠 시뮬레이터 (4성픽업 미적용)")
print("=" * 50)
# 5성 픽업 목표 개수만큼 뽑기까지 num번 시뮬레이션
print(f"\n[5성 픽업 {target_pickup}번 획득 시뮬레이션 - {num}회 반복]")
print("시뮬레이션 진행 중...")
all_pulls = []
for i in range(num):
gacha = GachaSimulator()
total_pulls, history = gacha.simulate_until_pickup_count(target_count=target_pickup)
all_pulls.append(total_pulls)
# 통계 계산
avg_pulls = sum(all_pulls) / len(all_pulls)
min_pulls = min(all_pulls)
max_pulls = max(all_pulls)
print("\n" + "=" * 50)
print("[통계 결과]")
print("=" * 50)
print(f"평균 총 뽑기 횟수: {avg_pulls:.2f}회")
print(f"최소 뽑기 횟수: {min_pulls}회")
print(f"최대 뽑기 횟수: {max_pulls}회")
print(f"평균 픽업 1개당: {avg_pulls/target_pickup:.2f}회")
# 샘플 1개 상세 보기
print("\n" + "=" * 50)
print("[샘플 시뮬레이션 상세]")
print("=" * 50)
gacha_sample = GachaSimulator()
total_pulls, history = gacha_sample.simulate_until_pickup_count(target_count=target_pickup)
print(f"총 {total_pulls}회 뽑기로 5성 픽업 {target_pickup}개 획득\n")
for h in history:
print(f"{h['count']}번째 픽업: {h['item']} (누적 {h['total_pulls']}회)")
# 캐릭터별 통계 출력
gacha_sample.print_statistics()
To embed this project on your website, copy the following code and paste it into your website's HTML: