TLC - 5 ⛺/Today I Learn

TIL / 3/30 / Python_team_project

Sehe_e 2023. 3. 31. 00:37

문제

 

2023.03.30 - [TLC - 5 ⛺/Today I Learn] - TIL / 3/29 / Python_Cat game PJ

어제자 TIL의 레벨업 시스템의 적용 문제

 

팀원이 이미 캐릭터들 인스턴스를 딕셔너리 형태로 선언해놓은 상태에서 내가 새롭게 선언해야 하는 보스 몬스터의 딕셔너리 형태의 인스턴스 선언에 대한 지식이 없었다.

 


시도

 

레벨업에는 두 가지 방법이 있었다. 

 

1. 캐릭터가 레벨업에 필요한 exp량을 max_exp량에 달성한다면 exp를 초기화, max_exp량을 소량 확장하는 방법.

2. 캐릭터가 레벨업에 필요한 exp량이 max_exp량에 달성한다면 exp를 유지하는 대신 max_exp량을 크게 키워버리는 방법.

 

나는 두 개의 방법 중에 2번을 선택하여 max_exp의 통을 키워주는 함수를 만들었다.

 

레벨업 시 전체 스테이터스를 키워주는 것과 마찬가지로 백분율 단위로 레벨업마다 통이 커지면 될 것 같고, 만약 캐릭터가 한 번의 전투에 얻은 exp량이 레벨업을 두 번 정도 할 수 있는 양이라면 연속으로 가능하도록 반복문을 사용하여 exp보다 커질 때까지 레벨업을 시켜주는 함수를 구현하였다.

# 레벨업마다 max_exp의 값이 오르는 함수입니다.. 80퍼센트씩 오르는 것으로 임의 조정해놨습니다. 경험치 드랍량 보면서 조절해야겠습니다

def sh_max_exp_up(a):
    return int(a * 1.8)

 

def level_up(self, _exp):
        while True:
            if self.exp >= self.max_exp:
                self.level + 1
                print(f'\n{self.name}가 LV.{self.level}로 레벨업했습니다!\n')
                self.max_exp = sh_max_exp_up(self.max_exp)
                self.level_plus1()
            else:
                break
                print(self.max_HP, self.HP, self.max_MP, self.MP,
                	 self.attack, self.defense, self.speed)
        return

근데 여기서 문제점이 1레벨, 2레벨 이렇게 올라가다가 break가 걸려야하는데 max_exp의 통을 넓혀주는 함수가 먹통인건지 아니면 while문의 무엇인가가 잘못되었는지 계속 1레벨과 같은 exp량, max_exp량이 출력되는 무한루프가 출력되었다.

 


 

내가 만들어야 했던 것은 보스몬스터의 스킬과 인스턴스 선언이었다.

class Monster(Object):
    def __init__(self, name, level, HP, MP, attack, defense, speed) -> None:
        super().__init__(name, level, HP, MP, attack, defense, speed)
        weight = round(level / 100, 2)  # 레벨/100배 증가
        self.HP = int(HP * (1 + weight))
        self.max_HP = int(HP * (1 + weight))
        self.MP = int(MP * (1 + weight))
        self.max_MP = int(MP * (1 + weight))
        self.attack = int(attack * (1 + weight))
        self.defense = int(defense * (1 + weight))
        self.speed = int(speed * (1 + weight))

이것이 처음 만들어져있던 몬스터의 클래스였지만 일반몬스터는 스킬이 따로 구현되지 않았기에 skill을 상속받지도 않았다.

 

class Boss(Object):
    def __init__(self, name, level, HP, MP, attack, defense, speed, skill) -> None:
        super().__init__(name, level, HP, MP, attack, defense, speed, skill)
        self.skill = skill

그래서 처음엔 skill을 상속받을 수 있는 부모클래스인 object 클래스를 상속받아 boss 클래스를 새로 만들었지만 생각해보니 팀원이 이미 몬스터 클래스에 몬스터만의 레벨값을 임의로 지정해놓았기에 저것을 두 번 갖다 쓰는건 낭비라고 느껴졌다.

하지만 몬스터 클래스에 보스를 추가하자고 skill을 추가하자니 다른 몬스터들도 다 스킬을 추가해야하니 참 난감했다.

 

인스턴스에서는 개인과제 때 튜플 형식으로 했던 것을 팀원이 딕셔너리 형태로 해놓은 것을 보고 내가 만든 스킬 함수의 매개변수 값은 어디서 지정하는가... 부터 팀원들이 전부 각자 할 일을 하고있는데 일방적으로 도와달라고 할 수도 없어서 팀원들에게 그냥 이거 따라해서 만들면 되냐고 물어보았다.

팀원이 미리 만든 플레이어 파티

 


해결

 

def level_up(self, _exp):
        while True:
            if self.exp >= self.max_exp:
                self.level + 1
                print(f'\n{self.name}가 LV.{self.level}로 레벨업했습니다!\n')
                self.max_exp = sh_max_exp_up(self.max_exp)
                self.level_plus1()
            else:
                break
                print(self.max_HP, self.HP, self.max_MP, self.MP,
                	 self.attack, self.defense, self.speed)
        return

이 레벨업 코드의 문제점은 

1. self.exp = _exp 라고 매개변수에 매개변수를 선언해주지 않았다는 점

2. self.level +=1 이여야 +1이 되면서 self.level값이 갱신될텐데 항상 변수의 갱신을 잊어서 문제였다..

 

고친 후의 코드는 정상적으로 잘 작동하였다.

def level_up(self, _exp):
		self.exp = _exp
        while True:
            if self.exp >= self.max_exp:
                self.level += 1
                print(f'\n{self.name}가 LV.{self.level}로 레벨업했습니다!\n')
                self.max_exp = sh_max_exp_up(self.max_exp)
                self.level_plus1()
            else:
                break
                print(self.max_HP, self.HP, self.max_MP, self.MP,
                	 self.attack, self.defense, self.speed)
        return

> 결과창

더보기
레벨업 테스트용 총스테이터스 출력문. 레벨업함수 모두 다 정상 작동

 


 

이것은 내가 상속에 대한 공부를 덜 한 탓이긴 했다. 팀원 분이 알려주신 해답이였는데 그냥 Monster 클래스를 상속받고 Boss클래스에 skill 매개변수를 추가해도 가능하다고 해주셨다.

class Boss(Monster):
    def __init__(self, name, level, HP, MP, attack, defense, speed, skill) -> None:
        super().__init__(name, level, HP, MP, attack, defense, speed)
        self.skill = skill

__init__에만 추가하며 super()에는 Monster에서 받아온 매개변수만 쓰면 된다고 알려주셨다!

 

그리고 딕셔너리 형태의 인스턴스는 직접 선언하며 팀원들과 코드의 오류를 고치면서 구조를 조금 알게된 것 같다..

#                 LV  HP  MP  ATK  DEF  SPD
bosses = [
    Boss("슈뢰딩거", 15, 2000, 0, 150, 100, 300, "상 자식"),
    Boss("잼민이", 20, 1300, 0, 120, 100, 400, "돌 던지기"),
    Boss("잼순이", 20, 1300, 0, 180, 100, 400, "꼬리 당기기"),
    Boss("제리", 25, 2300, 0, 200, 130, 400, "볼링쇼")
]

bosses_skills = [
    bosses[0].box_shot,
    bosses[1].boss_attack,
    bosses[2].boss_attack,
    bosses[3].jerry_attack
]

처음엔 보스스킬에도 스킬명을 적었지만 그렇게 하는게 아닌지 누군가가 지워주셨다.. 이 부분은 아직도 잘 모르겠다.

 


배운 점

 

딕셔너리 형태로 인스턴스를 선언한다면 키 값이나 리스트의 인덱스 순으로도 매개변수에 값을 전달해줄 수 있다는 것을 오류코드를 고치면서 알게되었다. 첫날에는 팀원이 쓴 코드를 보고 그냥 정말 아무것도 모르겠어서 고치지도 못하겠었는데 이제는 읽을 줄은 알게 된 것 같아서 조금 뿌듯했다. 

레벨업 함수도 평소에는 그냥 당연하듯이 생각했던 시스템인데 깊게 생각해보니 일정량이 가득차면 다음 단계로 넘어가면서 초기화되는 경험치도 있었고, 누적되면서 레벨업에 필요한 경험치량이 늘어나는 시스템도 있었다. 그것을 어떻게 구현해낼지 곰곰히 생각해보니 머릿속에서 식을 어떻게 짜면 될 지 맞춰지는게 떠오르면서 뭔가 나도 해냈다는게 느껴졌던 결과물이였다. 비록 while문과.. 함수 내부에서 이런 저런 잡다한 실수로 시간을 많이 잡아먹긴 했지만 그래도 팀원들과 함께 오류를 고쳐나갔기에 기억에 남을 결과물인 것 같다.