개발 일지


7일차 개발이다.

 

목표


user class에서 공격, 스킬, 아이템 사용 구현, 로그 파일 입출력, 테스트 추가, 전투 로직 구현

 

 

개발 이슈


 

Pycharm 키보드 작성 중에 타이핑이 고정폭으로 계속 입력이 되는 이슈가 있었다. 프로젝트를 껐다 켜도 동일한 증상이 있었다. 파이참을 껐다 키니 문제가 사라졌다.

 

GUI에 물려서 사용할 함수를 하나로 압축했다. 전일 짜놓았던 코드이다.

    def run_character_select_option(self, index_: int, option_: str, target=None):
        if target == "victory":
            return

        if not isinstance(index_, int) and index_ not in range(0, 5):
            raise ValueError("index는 0~4 의 int형 인덱스가 들어와야합니다.")
        option_list = ["공격", "스킬", "아이템", "도망가기"]
        if option_ not in option_list:
            raise ValueError(f"option 값으로 {option_list}가 들어와야합니다.")

        if option_ == '공격' or option_ == '스킬':
            if target is None or not isinstance(target, Monster):
                raise ValueError("공격이나 스킬 사용 시엔 Guardian 인스턴스가 들어와야합니다.")

        if option_ == '아이템':
            if target is None or not isinstance(target, Item):
                raise ValueError("아이템 사용 시엔 Item 인스턴스가 들어와야합니다.")

        selected_guardian = self.guardians[index_]
        selected_guardian: Guardian

        if option_ == '공격':
            selected_guardian.guardian_basic_attack(target)
        elif option_ == '스킬':
            selected_guardian.guardian_skill_attack(target)
        elif option_ == '아이템':
            selected_guardian.use_item(target)
        elif option_ == '도망가기':
            selected_guardian.try_run()

리팩토링과 기능을 추가하여 다음과 같이 만들었다.

    def _assert_run_character_options(self, using_guardian_index: int, option_: str,
                                      selected_item=None, action_target_index=None):
        if not isinstance(using_guardian_index, int) and using_guardian_index not in range(0, 5):
            raise ValueError("index는 0~4 의 int형 인덱스가 들어와야합니다.")

        unable_guardian_index = []
        for i, guardian in enumerate(self.guardians):
            if guardian.battle_enable_state is False:
                unable_guardian_index.append(i)

        if using_guardian_index in unable_guardian_index:
            raise ValueError("해당 캐릭터는 행동 불능 상태입니다.")

        option_list = ["공격", "스킬", "아이템 사용", '아이템 버리기', '장비 장착', '장비 해제', "도망가기"]
        if option_ not in option_list:
            raise ValueError(f"option 값으로 {option_list}가 들어와야합니다.")

        if option_ == '공격' or option_ == '스킬':
            if not -10 <= action_target_index < 5:
                raise ValueError("인덱스를 입력해주세요.")

        if option_ == '아이템':
            if selected_item is not None and not (
                    isinstance(selected_item, Item) or selected_item in [x.item_name for x in self.consume_inventory]
                    or (isinstance(selected_item, int) and selected_item in range(len(self.equip_inventory)))):
                raise ValueError("아이템 사용 시엔 Item 인스턴스 또는 아이템 이름 또는 장비 인덱스가 들어와야합니다.")

    def monster_select_as_index(self, index_: int):
        index_ *= -1
        return self.enemy_list[index_ - 1]

    def select_object_as_index(self, index_: int):
        if index_ < 0:
            index_ *= -1
            return self.enemy_list[index_ - 1]
        else:
            return self.guardians[index_]

    def select_equipment_item_from_inventory(self, selected_item_index:int):
        return self.equip_inventory[selected_item_index]

    def run_character_select_option(self, using_guardian_index: int, option_: str,
                                    selected_item=None, action_target_index=None, job_name=""):
        self._assert_run_character_options(using_guardian_index=using_guardian_index, option_=option_,
                                           selected_item=selected_item, action_target_index=action_target_index)
        selected_guardian = self.guardians[using_guardian_index]
        selected_guardian: Guardian
        if selected_item is not None and isinstance(selected_item, str):
            selected_item = self.select_item_with_str_from_inventory(selected_item)
        if selected_item is not None and isinstance(selected_item, int): # equipment만 해당
            selected_item = self.select_equipment_item_from_inventory(selected_item)
            
        if option_ == '공격':
            selected_guardian.guardian_basic_attack(self.select_object_as_index(action_target_index))
        elif option_ == '스킬':
            selected_guardian.guardian_skill_attack(self.select_object_as_index(action_target_index))
        elif option_ == '아이템 사용':
            if selected_item.item_name == ItemData.tent["item_name"]:
                for g in self.guardians:
                    g.use_item(selected_item)
                self.remove_item_as_item(selected_item)
                return
            if selected_item.item_name == ItemData.job_change_scroll['item_name']:
                self._guardian_change_job(job_name, using_guardian_index)
                self.remove_item_as_item(selected_item)
                return
            if action_target_index is not None:
                target_obj = self.select_object_as_index(action_target_index)
                target_obj.use_item(selected_item)
                self.remove_item_as_item(selected_item)
                return
            elif action_target_index is None:
                selected_guardian.use_item(selected_item)
                self.remove_item_as_item(selected_item)
                return
            raise "아이템 사용을 못했음"

        elif option_ == '아이템 버리기':
            self.delete_ever_item_inventory(selected_item)
        elif option_ == '장비 장착':
            self.equip_item_with_index_from_equip_inventory(selected_item, using_guardian_index)
        elif option_ == '장비 해제':
            self.dis_equip_item_with_index_from_equip_inventory(selected_item, using_guardian_index)
        elif option_ == '도망가기':
            selected_guardian.try_run()

 

스킬이나 아이템의 경우 상대가 필요할 때도, 없을 때도 있다.

 

그에 따라 여러개의 함수로 구현하는 것보다, 하나의 함수에서 해결하도록 짜보았다.

 

 
평가

SRP에 적합한 구조는 아니지만, 우선 구현을 하기위해 덕지덕지 기능이 붙어버렸다.

 

스킬이나 아이템의 상대를 고를 때는 적일 경우엔 음수의 인덱스를, 양수일 때는 아군 인덱스를 가리키는 걸로

 

구현했다. 그러니 가리키는 상대를 찾기가 많이 쉬워졌다. 다음번에도 비슷한 로직이 있을 경우엔 더 잘 짤 수 있을 것 같다.

 

 

감사합니다.

 

 

 

+ Recent posts