개인 프로젝트/게임 만들기

[메이플스토리] 스타포스 시뮬레이터 코드

Jinomad 2020. 10. 9. 22:38

 

전에 만들었던 스타포스 시뮬레이터의 코드 

GUI조차 없는 허접한 시뮬이었지만 나름 스스로만든 첫작품

 

import random
import math
import os


class ItemSample:
    # 입력받을 정보
    # Item_Kind = 0 # 아이템 종류 : 일반템(Nomal), 타일런트(Tyrant)
    Item_Level = 0  # 아이템 레벨 : 1 ~ 200 사이의 정수
    Star_Catch_Percent = 0  # 스타캐치 확률 : 0 ~ 5 %
    Star_Catch_Kind = 0  # 스타캐치 종류 : 1. 미적용, 2. 합적용, 3.곱적용
    Start_Star = 0  # 시작 별 개수 : 0 ~ 24 사이의 정수
    Goal_Star = 0  # 목표 별 개수 :  1 ~ 25 사이, Start_Star 보다 큰 정수
    Even_Kind = 0  # 이벤트 종류 : 1.비용 30% 할인, 2. 100% 이벤트(5,10,15), 3. 10성 이하 1+1, 4. 미적용
    Destroyed_Defence = 0  # 파괴방지 : 1. 12~17성, 2. 15~17성, 3. 미적용
    Mvp_Class = 0  # MVP 등급 : 1. 다이아 레드, 2. 골드, 3. 실버, 4. 브론즈 혜택없음
    Pc_Discount = False  # PC방 할인 : 1. 적용, 2. 미적용
    # 결과 혹은 결과에 필요한 정보
    Total_Cost = 0  # 강화에 들어간 총 메소 비용
    Destroyed = False  # 장비가 파괴되었는지 확인
    Total_try = 0  # 총 강화 횟수
    Now_Star = 0  # 현재 스타포스

    def __init__(self, item_level, star_catch_percent, star_catch_kind, start_star,
               goal_star, even_kind, destroyed_defence, mvp_class, pc_discount):
        self.Item_Level = item_level
        self.Star_Catch_Percent = star_catch_percent
        self.Star_Catch_Kind = star_catch_kind
        self.Start_Star = start_star
        self.Now_Star = start_star
        self.Goal_Star = goal_star
        self.Even_Kind = even_kind
        self.Destroyed_Defence = destroyed_defence
        self.Mvp_Class = mvp_class
        self.Pc_Discount = pc_discount

    def reinforce(self): # 강화 시도
        self.Total_try += 1
        self.Total_Cost += self.cost()
        rand_num = random.randint(1, 1000)  # 1천개의 확률
        event = self.Now_Star == 5 or self.Now_Star == 10 or self.Now_Star == 15
        if self.Even_Kind == 2 and event: # 5, 10, 15성 강화 시 100% 이벤트
            suc_percent = 1000
            dis_percent = 0
        else:
            suc_percent = self.suc_percentage()
            if self.Destroyed_Defence == 1 and 12 <= self.Now_Star <= 17:
                dis_percent = 0
            elif self.Destroyed_Defence == 2 and 15 <= self.Now_Star <= 17:
                dis_percent = 0
            else:
                dis_percent = self.dis_percentage() + suc_percent

        if 1 <= rand_num <= suc_percent:  # 성공 했는지 확인
            if self.Even_Kind == 3 and self.Now_Star <= 10:  # 10성 이하 강화 성공 시 1 + 1 이벤트
                self.Now_Star += 2
            else:
                self.Now_Star += 1  # 스타포스 + 1
        elif suc_percent < rand_num <= dis_percent:  # 파괴 되었는지 확인
            self.Destroyed = True
        else:  # 그 외에는 실패 (0 ~ 10성, 15성, 20성 : 유지, 나머지 : 하락)
            self.fail()

    def fail(self):
        if 0 <= self.Now_Star <= 10 or self.Now_Star == 15 or self.Now_Star == 20:
            pass
        else:
            self.Now_Star -= 1

    def suc_percentage(self):  # 강화 확률 (스타캐치, 이벤트 적용 시)
        suc_percent = 0
        star_per = 0
        if self.Star_Catch_Kind == 1:
            self.Star_Catch_Percent = 0
        if 0 <= self.Now_Star <= 2:
            suc_percent = 95 - (5 * self.Now_Star)
        elif 3 <= self.Now_Star <= 14:
            suc_percent = 100 - (5 * self.Now_Star)
        elif 15 <= self.Now_Star <= 21:
            suc_percent = 30
        elif self.Now_Star == 22:
            suc_percent = 3
        elif self.Now_Star == 23:
            suc_percent = 2
        elif self.Now_Star == 24:
            suc_percent = 1
        if star_per != 0:
            star_per = self.Star_Catch_Percent * 10
        if self.Star_Catch_Kind == 1:  # 합적용
            suc_percent = suc_percent * 10 + int(star_per)
        elif self.Star_Catch_Kind == 2:  # 곱적용
            suc_percent = suc_percent * 10 + (suc_percent * math.floor(star_per) / 100)
        else:
            suc_percent = suc_percent * 10
        return int(suc_percent)

    def dis_percentage(self):  # 장비가 파괴될 확률
        dis_percent = 0
        if 0 <= self.Now_Star <= 11:
            pass
        elif self.Now_Star == 12:
            dis_percent = 6
        elif self.Now_Star == 13:
            dis_percent = 13
        elif self.Now_Star == 14:
            dis_percent = 14
        elif 15 <= self.Now_Star <= 17:
            dis_percent = 21
        elif 18 <= self.Now_Star <= 19:
            dis_percent = 28
        elif 20 <= self.Now_Star <= 21:
            dis_percent = 70
        elif self.Now_Star == 22:
            dis_percent = 194
        elif self.Now_Star == 23:
            dis_percent = 294
        elif self.Now_Star == 24:
            dis_percent = 396
        return dis_percent

    def cost(self):  # 해당 강화에 들어가는 비용
        meso = 0
        sail_percent = 0
        if self.Pc_Discount == 1:
            sail_percent += 5
        if self.Mvp_Class == 1:
            sail_percent += 10
        elif self.Mvp_Class == 2:
            sail_percent += 5
        elif self.Mvp_Class == 3:
            sail_percent += 3
        if 0 <= self.Now_Star <= 9:
            meso = 1000 + (self.Item_Level ** 3) * (self.Now_Star + 1) // 25
        elif 10 <= self.Now_Star <= 14:
            meso = 1000 + (self.Item_Level ** 3) * ((self.Now_Star + 1) ** 2.7) // 400
        elif 15 <= self.Now_Star <= 24:
            meso = 1000 + (self.Item_Level ** 3) * ((self.Now_Star + 1) ** 2.7) // 200
        round(meso, -2)
        tmp_meso = meso
        meso = int(meso - (meso * sail_percent / 100))
        if self.Even_Kind == 1:
            meso = int(meso - (meso * 0.3))
        if self.Destroyed_Defence == 1 and 12 <= self.Now_Star <= 17 and self.Even_Kind != 2:
            meso += tmp_meso
        elif self.Destroyed_Defence == 2 and 15 <= self.Now_Star <= 17 and self.Even_Kind != 2:
            meso += tmp_meso
        return int(meso)

    def integrated(self):  # 실제 강화 진행하는 함수 ( 목표 수치까지 강화하되 장비 파괴시 종료)
        while self.Goal_Star != self.Now_Star:
            self.reinforce()
            if self.Destroyed:
                break

    # 정보 반환 함수
    def info_cost(self):
        return self.Total_Cost

    def info_try(self):
        return self.Total_try

    def info_suc(self):
        return not self.Destroyed


def simulator():
    total_meso = 0
    total_try = 0
    total_suc = 0
    best_result = []  # [파괴 횟수, 소모 비용]
    worst_result = []
    print("= = = 메이플 스타포스 시뮬레이터 = = =")
    # print("아이템의 종류를 선택하세요. \n 1. 일반템 \t 2. 타일런트")
    # item_kind = input("입력 : ")
    print("표본 개수를 입력하세요.")
    num_samples = int(input("입력 : "))
    print("아이템 레벨을 입력하세요.")
    item_level = int(input("입력 : "))
    print("시작 강화 수치를 설정하세요.")
    start_star = int(input("입력 : "))
    print("목표 강화 수치를 설정하세요.")
    goal_star = int(input("입력 : "))
    print("스타캐치, 이벤트, 할인, 파괴방지를 적용하시겠습니까? \n 1. 적용\t2. 미적용")
    select = int(input("입력: "))
    if select == 1:
        print("스타캐치 적용 방식을 정하세요. \n 1. 합적용 \t 2. 곱적용\t 3. 미적용")
        star_catch_kind = int(input("입력 : "))
        if star_catch_kind == 1 or star_catch_kind == 2:
            print("스타캐치 확률을 입력하세요. \n * 0 ~ 5%(소수점 첫째짜리까지 입력 가능 * ")
            star_catch_percent = float(input("입력 : "))
        else:
            star_catch_percent = 0
        print("이벤트 종류를 설정하세요. \n 1. 비용 30% 세일\t2. 100% 이벤트(5,10,15)\t3. 10성 이하 1+1\t4. 미적용")
        even_kind = int(input("입력 : "))
        print("파괴방지를 설정하세요. \n 1. 12 ~ 17성\t2. 15 ~ 17성\t3. 미적용")
        destroyed_defence = int(input("입력 : "))
        print("MVP 등급을 설정하세요. \n 1. 다이아, 레드\t2. 골드\t3. 실버\t4. 브론즈(해당 없음)")
        mvp_class = int(input("입력 : "))
        print("PC방 할인을 설정하세요. \n 1. 적용\t2. 미적용")
        pc_discount = int(input("입력 : "))
    else:
        star_catch_percent = 0
        star_catch_kind = 3
        even_kind = 4
        destroyed_defence = 3
        mvp_class = 4
        pc_discount = 2

    for _ in range(num_samples):
        sample = ItemSample(item_level, star_catch_percent, star_catch_kind, start_star,
                            goal_star, even_kind, destroyed_defence, mvp_class, pc_discount)
        sample.integrated()
        total_meso += sample.info_cost()
        total_try += sample.info_try()
        if sample.info_suc():
            total_suc += 1

    print("표본의 개수 :", num_samples)
    print("총 시도 횟수 :", total_try)
    print("총 소모한 메소 :", format(total_meso, ','), '메소')
    print("성공한 장비의 개수 :", total_suc)
    print("장비 1 개 성공 확률 :", total_suc / num_samples * 100, '%')
    if total_suc != 0:
        one_meso = total_meso // total_suc
    else:
        one_meso = 0
    print("장비 1개 성공시 기댓값 :", format(total_meso // total_suc, ','), '메소')
    os.system('pause')

simulator()