광주인력개발원

레전드 오브 복이 개발일지 - 3일차 - [2323-05-14 학습일지]

플광 2023. 5. 31. 08:27

 

근래 개발일지를 거의 올리지 못했다.

 

그동안 있던 일을 간단히 요약하면..

 

0일차 : 팀원들과 요구사항 분석 및 역할 분배

1일차 : 요구사항 문서화, 추상 클래스 설계 및 팀원에게 추상 클래스 개념, 2차원 배열, getter/setter 개념 소개

2일차 : ERD 그리기, Chracter_ABC class 70% 정도 완성, 간단한 유닛 테스트 진행함

3일차 : (계획) Item ABC, consume, equipment 구체화, user_class_abc 설계

 

매일 매일 알차게 시간을 쓰고 있음에도.. 시간이 모자라는 고달픈 상황이었다.

 

하지만, 데일리 성과를 보고, 기록이 필요하다. 아무리 바빠도 개발일지를 꼭 작성하는 습관을 들이도록 노력해야한다.

 

"""
    FILE_NAME : character_ABC.py
    최초 작성 일자 : 2023-05-12
    작성자 : 박광현
    파일 설명 :
        캐릭터 추상 클래스 설명 및 정의
"""

from abc import *


class CharacterABC(metaclass=ABCMeta):
    def __init__(self):
        pass


    @property
    @abstractmethod
    def character_name(self) -> str:
        """
        캐릭터 이름 반환 getter
        예시) 포켓몬스터 잡으면 캐릭터 이름 설정할 수 있는 것, 설정 안하면 (기본 소속 + 클래스) 정해짐
            (몬스터의 경우) 불의지역 불타는 족발, 숲의지역 은둔골램
            (수호대의 경우) 빛의 수호대 백법사
            (보스의 경우) 던전 1층보스 이동려크
            (유저 캐릭 경우)   (검사면서) 소촌동칼잡이   설정하면 사용 가능
        :return: character_name(str)
        """
        pass

    @property
    @abstractmethod
    def physical_attack(self):
        """
        물리 공격력을 리턴합니다. 레벨업 할 때마다 새로 설정이 필요합니다.
        :return:
        """
        pass

    @property
    @abstractmethod
    def magical_attack(self):
        """
        마법 공격력을 리턴합니다. 레벨업 할 때마다 새로 설정이 필요합니다.
        :return:
        """
        pass

    @property
    @abstractmethod
    def physical_defense(self):
        """
        물리 방어력을 반환합니다. 레벨업 할 때마다 설정해주세요.
        :return:
        """
        pass

    @property
    @abstractmethod
    def magical_defense(self):
        """
        마법 방어력을 반환합니다. 레벨업을 할 때마다 설정해주세요.
        :return:
        """
        pass

    @property
    @abstractmethod
    def level(self) -> int:  # getter
        """
        캐릭터 현재 레벨입니다.
        :return: level(int)
        """
        pass

    @property
    @abstractmethod
    def exp(self) -> int:
        """
        캐릭터의 현재 획득 경험치입니다.
        만약 경험치 보상을 할 예정이라면 reward_experience를 사용하십시요
        """
        pass



    @property
    @abstractmethod
    def hp(self) -> int:
        """
        캐릭터 잔여 hp를 가지고 옵니다.
        :return: hp(int)
        """
        pass

    @property
    @abstractmethod
    def max_hp(self) -> int:
        """
        캐릭터 레벨에 따른 최대 마나량입니다. mp 는 이 값을 넘을 수 없습니다.
        """
        pass



    @property
    @abstractmethod
    def buff_list(self):
        """
        현재 캐릭터에 적용된 버프 & 디버프 리스트를 리턴합니다.
        캐릭터 초기화시에만 사용하고 이후엔 add or remove buff 함수를 사용해주세요.
        """
        pass



    @abstractmethod
    def attack_(self, skill_name="기본공격", will_spend_mana=0, target=None):
        """
        공격을 시행한다면 이 함수를 실행해주세요.
        :param target: (character가 상속된) 해당 개체 의 주소 값을 넘겨주세요.
        :return:
        """
        pass



    @abstractmethod
    def reward_experience(self, value: int) -> bool:
        """
        이 개체에 경험치 보상을 시행합니다. 내부 함수 _level_up을 실행시켜주세요.
        레벨업을 할 경우 True를 반환, 레벨업을 할 경우엔 False를 반환합니다.
        :param value:
        :return:
        """
        pass

    @abstractmethod
    def character_status(self) -> list:
        """
        캐릭터의 상태(체력, 마나, 경험치, 물리 공격력, 마법 공격력, 물리방어력, 마법방어력, 전투 가능 여부)을 반환합니다.
        상태를 반환하기 전에 장비와 버프 능력치를 반영하여 반환해주세요.
        :return:
        """
        pass

    @abstractmethod
    def suffer_damage(self, dmg: int, type: str) -> bool:
        """
        데미지를 받을 경우 이 함수를 씁니다, 체력이 깍이고 만약 0이하로 떨어지면 캐릭터가 행동불능 상태에 빠집니다.
        :param dmg: 계산된 데미지를 입력합니다.
        :param type: "물리" 또는 "마법" 을 선택합니다. 디폴트는 "물리"
        :return:
        """
        pass

    @abstractmethod
    def heal_(self, heal_value: int, type_:str, how_:str ):
        """
        힐, 포션을 사용할 경우 이 함수를 써주세요.
        type 에 hp, mp, all 에 따라  체력, 마나, 전부 를 회복시킵니다.
        how_ 에 sum 또는 percent 에 따라, 고정 수치 또는 퍼센트로 회복합니다.
        :param heal_value:
        :return:
        """
        pass

    @abstractmethod
    def _applying_buff(self):
        """
        캐릭터 스테이터스를 반환하기 전에 버프를 반영합니다.
        :return:
        """
        pass


    @abstractmethod
    def add_buff(self, buff_):
        """
        buff 객체를 받으면 self._buff_list에 저장합니다.
        :param buff_:
        :return: None
        """
        pass

    @abstractmethod
    def remove_buff(self, buff_name: str):
        """
        buff_name에 해당되는 버프가 삭제됩니다.
        :param buff_name:
        :return: None
        """
        pass

    @abstractmethod
    def _assert_buff(self):
        """
        버프 적용시간 또는 턴이 유효한지 확인합니다.
        유효하지 않다면 해당 버프는 삭제합니다.
        :return: None
        """
        pass

    @abstractmethod
    def use_item(self, item_):
        """
        아이템 객체를 사용합니다.
        :param item_:
        :return: None
        """
        pass

 

CharacterABC 클래스의 일부를 발췌했다.

 

추상 클래스에서 @abstractmetho decorator를 사용하면

이 클래스를 상속 받는 클래스는 반드시 저 함수명을 재정의 해주어야한다.

 

그렇지 않으면

 

Traceback (most recent call last):
  File "C:\Users\KDT107\Desktop\learn_py\fantastic_4_project\domain\another_character.py", line 10, in <module>
    SampleCharacter()
TypeError: Can't instantiate abstract class SampleCharacter with abstract methods _applying_buff, _assert_buff, add_buff, attack_, buff_list, character_name, character_status, exp, heal_, hp, level, magical_attack, magical_defense, max_hp, physical_attack, physical_defense, remove_buff, reward_experience, suffer_damage, use_item

 

이렇게 친절하게 작성하지 않은 메소드에 대해 하나하나 알려준다.

 

큰 틀을 저렇게 구상해놓고 들어가니깐 얼추 큰 로직들이 맞춰들어가는 느낌이 드는데,

 

금방 끝날 것 같은 미세 구현들이 쉽게 끝나지 않았다.

 

또한 오늘은 같은 팀원 윤재씨와 CharacterABC 클래스에 적절하지 않은 요소들을 추리는 과정을 거쳤다.

 

plan 상 CharacterABC 클래스에서 상속 구현할 클래스는 guardian클래스와 monster 클래스가 될 것이다.

 

monster에서 쓰일 필요가 없는 property 와 method들이 CharacterABC에서 정의되고 있는 상황이라 이에 대해 정리했다.

 

또한, @classmehtod 데코레이터를 써서 개체를 create하기로 하였다. 그렇지 않으면, 또 factory class를 다시 정의해주어야할 것 같았다.

 

객체지향적인 프로그래밍이라고 해도 절대적인 할일을 줄여주진 않는 것 같다. :D

 

그래도 어제보다 더 나은 구조, 새로운 트라이를 해보고 있으니 계속 발전하고 있음을 느끼고 있다.

 

오늘도 감사합니다.