<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>GRstory Blog</title>
    <link>https://aratino5165.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 17 Jul 2026 07:51:30 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>GRstory</managingEditor>
    <image>
      <title>GRstory Blog</title>
      <url>https://tistory1.daumcdn.net/tistory/7304181/attach/2a2cc920967543a6bc9d825d901bf547</url>
      <link>https://aratino5165.tistory.com</link>
    </image>
    <item>
      <title>Unreal Gameplay Ability System 기초</title>
      <link>https://aratino5165.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Gameplay Ability System (GAS)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GAS란? 스킬, 속성, 상태 이상 효과 등을 체계적으로 구현하기 위한 언리얼 엔진의 프레임워크.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터가 수행할 수 있는 행동, 캐릭터가 가진 수치, 그 수치와 상태를 변화시키는 요인 등을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 동기화를 지원해 클라이언트의 예측과 서버의 검증이 있고 스킬, 버프, 데미지 공식이 서로 다른 객체와 데이터로 구분되어 있어 모듈화 및 재사용성이 좋다. 기존에 모든것을 상속 - BP로 만들어야 하는 구조와 다르게 Data-Driven 한 설계를 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 클래스:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UAbilitySystemComponent&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액터 컴포넌트. 어빌리티의 활성화, 이펙트 적용, 태그 관리 등을 지원한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FGameplayTag&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;계층을 가진 이름표.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;태그의 유무를 통해 캐릭터의 상태 / 물체의 상태 등을 판별해 어빌리티 실행 여부를 통제한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UGameplayAbility&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터가 실행할 수 있는 단일 스킬/행동을 정의한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몽타주 재생, 투사체 생성, 타겟팅 처리 등을 수행하며 쿨타임, 소모 자원 등의 조건 설정이 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;492&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OzDOw/dJMcajiDlfd/xEksBe63BiZCYeDYeRH4V1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OzDOw/dJMcajiDlfd/xEksBe63BiZCYeDYeRH4V1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OzDOw/dJMcajiDlfd/xEksBe63BiZCYeDYeRH4V1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOzDOw%2FdJMcajiDlfd%2FxEksBe63BiZCYeDYeRH4V1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1041&quot; height=&quot;492&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;492&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FGameplayAbilitySpec&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASC에 GA가 부여될 때 생성되는 데이터이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어빌리티의 레벨, 활성화 상태 등을 관리한다.&lt;/p&gt;
&lt;pre id=&quot;code_1783863758647&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct GAMEPLAYABILITIES_API FGameplayAbilitySpec : public FFastArraySerializerItem
{
	FGameplayAbilitySpecHandle Handle; //int32 프로퍼티를 가지고 있는 스펙을 식별하기 위한 ID
    TObjectPtr&amp;lt;UGameplayAbility&amp;gt; Ability; // 인스턴스화된 GA 객체를 가리키는 포인터
    int32	Level; //어빌리티의 레벨
    int32	InputID; //  키보드/마우스와 매핑하기 위한 값
}

// 1레벨, 0번 입력키를 가진 어빌리티 스펙 구조체를 생성한다.
FGameplayAbilitySpec AbilitySpec(MyAbilityClass, 1, 0);

// 생성된 스펙을 ASC에 부여한다.
AbilitySystemComponent-&amp;gt;GiveAbility(AbilitySpec);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UAbilityTask&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GA는 단일 프레임에서 적용, 종료되는것을 확장하기 위해 종료 대기, 입력 대기 등 비동기 흐름 제어용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UArributeSet&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체력, 이동속도, 방어력 등 캐릭터가 가지는 수치 데이터의 집합이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값이 변경될 때 발생하는 이벤트를 정의하고 관리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UGameplayEffect&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Attribute를 변경하거나 타겟에게 태그를 부여하는 클래스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉발형 데미지, 버프, 디버프, 패시브 등을 구현할 수 있고, 이를 태그 기반으로 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GameplayEffect는 여러개의 Moditfier을 가질 수 있는데,&amp;nbsp; 대상 어트리뷰트, 연산 방식, 값으로 구성되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값(Modifier)을 결정하는 방식은 4가지이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.4186%;&quot;&gt;Scalable Float&lt;/td&gt;
&lt;td style=&quot;width: 75.5814%;&quot;&gt;DataTable에서 지정하는 구조체 값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.4186%;&quot;&gt;Attribute Based&lt;/td&gt;
&lt;td style=&quot;width: 75.5814%;&quot;&gt;EffectSpec을 만든 주체/ 타겟의 CurrentValue / EffectSpec을 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.4186%;&quot;&gt;Custom Calculation Class&lt;/td&gt;
&lt;td style=&quot;width: 75.5814%;&quot;&gt;MMC 클래스를 사용해 커스텀으로 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 24.4186%;&quot;&gt;Set By Caller&lt;/td&gt;
&lt;td style=&quot;width: 75.5814%;&quot;&gt;런타임에 Ability / EffectSpec 생성할 때 값 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GameplayEffect는 3가지의 지속시간 타입을 가진다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 167px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 10.7752%; height: 17px;&quot;&gt;Duration&lt;/td&gt;
&lt;td style=&quot;width: 14.2635%; height: 17px;&quot;&gt;GameplayCue&lt;/td&gt;
&lt;td style=&quot;width: 74.9612%; height: 17px;&quot;&gt;Usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 43px;&quot;&gt;
&lt;td style=&quot;width: 10.7752%; height: 43px;&quot;&gt;Instant&lt;/td&gt;
&lt;td style=&quot;width: 14.2635%; height: 43px;&quot;&gt;Execute&lt;/td&gt;
&lt;td style=&quot;width: 74.9612%; height: 43px;&quot;&gt;Attribute의 BaseValue에 즉각적이고 영구적인 변화를 줄 때 사용합니다. 이 경우 GameplayTag는 적용되지 않으며, 한 프레임 동안조차도 존재하지 않습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 43px;&quot;&gt;
&lt;td style=&quot;width: 10.7752%; height: 43px;&quot;&gt;Duration&lt;/td&gt;
&lt;td style=&quot;width: 14.2635%; height: 43px;&quot;&gt;Add / Remove&lt;/td&gt;
&lt;td style=&quot;width: 74.9612%; height: 43px;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;Attribute&lt;/span&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;의 CurrentValue를 일시적으로 변경하거나 특정 기간 동안 GameplayTag를 적용할 때 사용합니다. 해당 기간은 UGameplayEffect 클래스 또는 블루프린트에서 정의됩니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 64px;&quot;&gt;
&lt;td style=&quot;width: 10.7752%; height: 64px;&quot;&gt;Infinite&lt;/td&gt;
&lt;td style=&quot;width: 14.2635%; height: 64px;&quot;&gt;Add / Remove&lt;/td&gt;
&lt;td style=&quot;width: 74.9612%; height: 64px;&quot;&gt;Attribute의 CurrentValue를 일시적으로 변경하거나 무한으로 GameplayTag를 적용할 때 사용합니다. 해당 Effect는 스스로 만료되지 않으며, 반드시 Ability나 ASC(Ability System Component)를 통해 수동으로 제거해야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GameplayEffect는 다양한 방법으로 적용이 가능한데, GA의 함수나 ASC의 함수로 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GE를 직접 넘기는 방식은 블루프린트에 설정된 정적인 데이터만 적용 가능하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런타임에 데미지 수치를 계산하는 등의 &lt;b&gt;데이터 조작이 필요한 경우에는 Spec&lt;/b&gt;을 만들어 적용해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1783869414037&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ApplyGameplayEffectToSelf: 자신에게 GE 클래스를 직접 적용한다.
ApplyGameplayEffectToTarget: 특정 대상에게 GE 클래스를 직접 적용한다.
ApplyGameplayEffectSpecToSelf: 자신에게 동적으로 설정된 GE 스펙(Spec)을 적용한다.
ApplyGameplayEffectSpecToTarget: 특정 대상에게 동적으로 설정된 GE 스펙을 적용한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; FGameplayEffectSpec &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GE를 타겟에게 적용시키기 전에, FGameplayEffectContextHandle, Level, Period, Duration, Dynamic Gameplay Tag를 넣어 생성한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; FGameplayEffectContextHandle &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FGameplayEffectSpec 구조체 안에 포함되어있는 정보로 FGameplayEffectContext 를 가리킨다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;FGameplayEffectContext는 시전자, 충돌 정보 등을 담고있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1783866166115&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1. 컨텍스트 생성 (상황 정보 캡처)
FGameplayEffectContextHandle ContextHandle = AbilitySystemComponent-&amp;gt;MakeEffectContext();

필요 시 컨텍스트에 추가 정보 주입 (예: 타격 위치 정보)
ContextHandle.AddHitResult(MyHitResult);

// 2. 스펙 생성 (클래스 + 레벨 + 컨텍스트 결합)
FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent-&amp;gt;MakeOutgoingSpec(DamageEffectClass, 1.0f, ContextHandle);

동적 데이터 주입 (예: Set By Caller 수치 설정)
if (SpecHandle.IsValid())
{
    SpecHandle.Data.Get()-&amp;gt;SetSetByCallerMagnitude(FGameplayTag::RequestGameplayTag(FName(&quot;Data.Damage&quot;)), 50.0f);
}

// 3. 타겟에게 적용
if (SpecHandle.IsValid() &amp;amp;&amp;amp; TargetASC)
{
    AbilitySystemComponent-&amp;gt;ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), TargetASC);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Unreal</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/40</guid>
      <comments>https://aratino5165.tistory.com/40#entry40comment</comments>
      <pubDate>Mon, 13 Jul 2026 01:11:39 +0900</pubDate>
    </item>
    <item>
      <title>무기 시스템 - 1</title>
      <link>https://aratino5165.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;UnrealEngine으로 신규 프로젝트를 진행중, 무기 시스템을 개발하고 있다.&lt;br /&gt;무기 시스템은 보더랜드식 접두사, 접미사 모듈이 있으며 모듈에 따라 무기의 능력이 일부 바뀌어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 발사 방법, 투사체 종류, 발사시 효과, 명중시 효과 등등이 무기마다 다 다르기 때문에 최대한 설계를 잘 해야 한다는 어려움이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 무기는 액터로, 무기 정보는 데이터 에셋, 인스턴스로&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무기는 맵에 스폰 및 장착을 해야하니 액터를 상속해야 하지만, 인벤토리에 넣을 수 있어야 하기 때문에 무기 정보만을 위한 인스턴스 클래스가 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무기의 데이터 자체는 UPrimaryDataAsset을 상속해 데미지, 발사 속도 등의 데이터를 넣고 런타임 인스턴스 클래스에는 이 DataAsset과 런타임에서 붙는 여러 모듈등으로 계산 후 출력하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적 데이터: UGSItemData / UGSWeaponData / UGSWeaponData_gun&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;런타임 인스턴스: UGSItemInstanceData/UGSWeaponInstanceData&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액터: UGSWeapon/UGSWeapon_Gun/UGSWeaponMelee&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 무기는 공격 방식이 다양하니 Strategy 패턴을 사용한다.&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무기는 대부분은 총이니 Projectile 을 사용하겠지만, 근접무기의 경우는 다르다. 따라서 Strategy 클래스를 만들고 (EditInineNew) 프로퍼티를 통해 클래스를 골라서 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 발사 전략은 무기 발사 시에, 어떻게 탄을 발사하는가 를 담당하고, 쏠 수 있는가, 언제 쏘는가, 어떻게 쏘는가는 Ability가 담당한다. (차지 무기의 경우, 발사 가능 여부 등등은 Strategy 클래스가 담당하기에는 좀 버거워서)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;발사 전략: UGSFireStrategy / UGSFireStrategy_Projectile, UGSFireStrategy_Hitscan&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. GAS 연결&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GAS의 SpecHandle들을 가지고 있는 구조체를 만들어 전달한다. 데미지, 사용자에게 적용할 핸들, 타겟에게 적용할 핸들 등을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 GameplayTag는 다음과 같이 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UGSWeaponAffix::DamageTypeTags &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;//데미지 타입&lt;/span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;UGSItemData::ItemTag //아이템 종류 (인벤토리)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;투사체는 OnHit 함수에서 피격자 ASC에게 DamageSpec을 넘겨주는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스펙에는 SetByCallserTagMagnitudes로 지정한 태그와 데미지 원본 수치,&amp;nbsp;&lt;br /&gt;DynamicAssetTags로 추가한 데미지 타입을 건네준다.&lt;br /&gt;&lt;br /&gt;만약 도트딜 등등이 필요하다면 SetByCaller에 태그와 value를 더 주면 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플레이어가 GAS를 이용해서 상호작용 / 무기 발사 를 해야 하기때문에 GAS에 대한 공부를 더 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Unreal</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/39</guid>
      <comments>https://aratino5165.tistory.com/39#entry39comment</comments>
      <pubDate>Sun, 12 Jul 2026 21:51:24 +0900</pubDate>
    </item>
    <item>
      <title>[Dx] 실습 1</title>
      <link>https://aratino5165.tistory.com/38</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Dx3D의 초기화는 장치, 컨텍스트를 생성하는 것.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ID3D11Device: GPU 리소스(버퍼, 쉐이더, 텍스쳐 등) 생성하는 팩토리&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ID3D11DeviceContext: GPU에게 명령을 내리는 인터페이스&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. D3DClass&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1783521013545&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;InitializeGraphicsHW(screenWidth, screenHeight, vsync);
InitializeSwapBuffer(screenWidth, screenHeight, hwnd, fullscreen);
InitializeDepthStencilBuffer(screenWidth, screenHeight);
InitializeRasterizer();
InitializeViewport(screenWidth, screenHeight);

m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth);
m_worldMatrix = XMMatrixIdentity();
m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;InitializeGraphicsHW(): 모니터 해상도, 주사율을 로드해 VSync 설정&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;InitializeSwapBuffer():&amp;nbsp;D3D11CreateDeviceAndSwapChain()으로 Device, DeviceContext, Swapchain 생성&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;InitializeDepthStencilBuffer(): Z버퍼 생성,&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;InitializeRasterizer(): 폴리곤 뒷면 컬링( &lt;span style=&quot;text-align: start;&quot;&gt;D3D11_CULL_BACK&lt;/span&gt; ), 폴리곤 채워서 그리기( &lt;span style=&quot;text-align: start;&quot;&gt;D3D11_FILL_SOLID&lt;/span&gt; )&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;InitializeViewport(): 뷰포트 사이즈 설정(화면 전체)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;투영 행렬, 월드 행렬 계산.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. CameraClass&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1783521503386&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void CameraClass::Render()
{
	XMVECTOR up, position, lookAt;
	float yaw, pitch, roll;
	XMMATRIX rotationMatrix;

	up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	position = XMLoadFloat3(&amp;amp;m_position);

	lookAt = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);

	pitch = m_rotation.x * 0.0174532925f;
	yaw   = m_rotation.y * 0.0174532925f;
	roll  = m_rotation.z * 0.0174532925f;

	rotationMatrix = XMMatrixRotationRollPitchYaw(pitch, yaw, roll);

	lookAt = XMVector3TransformCoord(lookAt, rotationMatrix);
	up = XMVector3TransformCoord(up, rotationMatrix);

	lookAt = position + lookAt;

	m_viewMatrix = XMMatrixLookAtLH(position, lookAt, up);

	return;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;up 벡터 설정으로 Z+ 방향 보도록 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rotation 값을 Deg2Rad 값 곱해서 라디안 값으로 변환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. ColorShaderClass&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HLSL 쉐이더는 VS가 컴파일 하는게 아니라 D3DCompileFromFile로 직접 컴파일 해야함.&lt;/p&gt;
&lt;pre id=&quot;code_1783521921346&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result = D3DCompileFromFile(fileName, NULL, NULL, &quot;ColorVertexShader&quot;, &quot;vs_5_0&quot;, 
	D3D10_SHADER_ENABLE_STRICTNESS, 0, &amp;amp;vertexShaderBuffer, &amp;amp;errorMessage);
    
result = D3DCompileFromFile(fileName, NULL, NULL, &quot;ColorPixelShader&quot;, &quot;ps_5_0&quot;,
	D3D10_SHADER_ENABLE_STRICTNESS, 0, &amp;amp;pixelShaderBuffer, &amp;amp;errorMessage);
    
result = device-&amp;gt;CreateVertexShader(vertexShaderBuffer-&amp;gt;GetBufferPointer(), 
	vertexShaderBuffer-&amp;gt;GetBufferSize(), NULL, &amp;amp;m_vertexShader);

result = device-&amp;gt;CreatePixelShader(pixelShaderBuffer-&amp;gt;GetBufferPointer(), 
	pixelShaderBuffer-&amp;gt;GetBufferSize(), NULL, &amp;amp;m_pixelShader);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dx3D의 정점은 위치 정보 + 추가적인 정보를 가질 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 추가 정보를 가지고 싶다면, 구조체를 정의 해야 하는데, Dx3D에게 알려주기 위해&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D3D11_INPUT_ELEMENT_DESC&lt;/b&gt; 구조체들로 이루어진 배열로 &lt;b&gt;ID3D11InputLayout&lt;/b&gt; 형식의 객체를 만들어야 함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783522693278&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;D3D11_INPUT_ELEMENT_DESC polygonLayout[2];

polygonLayout[0].SemanticName = &quot;POSITION&quot;;
polygonLayout[0].SemanticIndex = 0;
polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[0].InputSlot = 0;
polygonLayout[0].AlignedByteOffset = 0;
polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[0].InstanceDataStepRate = 0;

polygonLayout[1].SemanticName = &quot;COLOR&quot;;
polygonLayout[1].SemanticIndex = 0;
polygonLayout[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
polygonLayout[1].InputSlot = 0;
polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[1].InstanceDataStepRate = 0;

//ColorShader.hlsl
struct VertexInputType
{
    float4 position : POSITION;
    float4 color : COLOR;
};

//D3D11_INPUT_ELEMENT_DESC: GPU 버퍼에 넣은 데이터를 쉐이더가 이해할 수 있는 구조체로 해석하는 방법을 알려주는 매핑 테이블
//SemanticName: 이 성분이 뭔지 알려줌. 이름은 중요하지 않은데 시맨틱 태그 이름은 모두 같아야 함.
//SemanticIndex: 같은 종류가 여러 개일 때 구분용 번호
//Format: 이 성분이 메모리에서 몇바이트인지, 어떤 타입인지
//InputSlot: 어느 정점 버퍼에서 이 데이터를 가져올지 (정점 버퍼는 최대 16개)
//AlignedByteOffset: 몇 바이트부터 시작하는지 (position은 시작이니 0,  color은 자동 계산)
//InputSlotClass: 이 데이터가 정점마다 바뀌는지(D3D11_INPUT_PER_VERTEX_DATA), 인스턴스인지(D3D11_INPUT_PER_INSTANCE_DATA)
//InstanceDataStepRate: 인스턴싱용 옵션

//여기서 polygonLayout 배열과 쉐이더의 VertexInputType구조체 비교 후 이름, 개수, 순서 가 안맞으면 false
result = device-&amp;gt;CreateInputLayout(polygonLayout, numElements, 
	vertexShaderBuffer-&amp;gt;GetBufferPointer(), vertexShaderBuffer-&amp;gt;GetBufferSize(), &amp;amp;m_layout);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 렌더링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BeginScene(): 프레임/Z 버퍼 초기화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Camera.Render(): 뷰 행렬 계산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Model.Render(): 정점/인덱스 버퍼를 바인딩&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ColorShader.Render(): Wolrd, View,Projection 행렬 로드, 쉐이더 작동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EndScene(): 스왑체인 후 화면에 표시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 전체 구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DirectX</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/38</guid>
      <comments>https://aratino5165.tistory.com/38#entry38comment</comments>
      <pubDate>Thu, 9 Jul 2026 00:01:18 +0900</pubDate>
    </item>
    <item>
      <title>[Dx] 렌더링 파이프라인</title>
      <link>https://aratino5165.tistory.com/37</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 렌더링 파이프라인&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3D 씬 &amp;gt; CPU (Application) &amp;gt; GPU(Geometry, Rasterizer) &amp;gt; Image&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Application: 렌더링 할 그래픽 데이터 로드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Geometry: 정점별 연산 수행 (메쉬 / 카메라 이동, 폴리곤의 빛 연산, 투영, 클리핑)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Lighting: 정점별 색을 계산한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Projection: 3D 메쉬를 2D 평면에 매핑한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Clipping: 프로젝션 후 화면 밖으로 벗어나는 영역을 자른다. depth 정보와 함께 다음 단계로 이동.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;모델 좌표 &amp;gt; 월드 좌표 &amp;gt; 카메라 좌표 &amp;gt; 빛 계산 &amp;gt; 프로젝션 &amp;gt; 클리핑 &amp;gt; 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Rasterizer: 픽셀별 연산 수행 (보간, 텍스쳐링, Z-버퍼링)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Double Buffering (Swap chain): 프레임버퍼를 2개 사용해서 티어링 방지.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1783519687073&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DXGI_SWAP_CHAIN_DESC* //스왑체인 생성시 필요한 데이터 구조체
D3D11CreateDeviceAndSwapChain() &amp;rarr; m_swapChain(IDXGISwapChain*) 생성
m_swapChain-&amp;gt;GetBuffer() &amp;rarr; 백버퍼 텍스처(ID3D11Texture2D*) 획득
device-&amp;gt;CreateRenderTargetView() &amp;rarr; m_renderTargetView(ID3D11RenderTargetView*) 생성

ClearRenderTargetView(m_renderTargetView)
//그리기
m_swapChain-&amp;gt;Present() //스왑&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Z-Buffering&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴리곤 변환시 Z값 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴리곤 계산시 현재 화면의 Z값이랑 비교 후 현재 값보다 작으면 컬러버퍼 교체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Coloring &amp;amp; Texturing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴리곤 내부 색상 보간, UV좌표에 맞춰 텍스쳐링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. DirectX 렌더링 파이프라인&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;679&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k8G0Y/dJMcagMZVgk/3Kt9SgV0Ickc32KawKK0lK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k8G0Y/dJMcagMZVgk/3Kt9SgV0Ickc32KawKK0lK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k8G0Y/dJMcagMZVgk/3Kt9SgV0Ickc32KawKK0lK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk8G0Y%2FdJMcagMZVgk%2F3Kt9SgV0Ickc32KawKK0lK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;687&quot; height=&quot;408&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;679&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정점 쉐이더: 정점 위치를 모델 공간에서 클립 공간으로 변환, 정점별 빛 연산, Skeletal 메쉬 스키닝&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헐 쉐이더:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테셀레이터: 헐 쉐이더에서 지정된 테셀레이션 계수에 따라 테셀레이션 결정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 쉐이더:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지오메트리 쉐이더:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스트림 출력: 기본 데이터를 GPU 메모리로 이동함. 이 데이터는 다시 렌더링 파이프라인으로 들어와 다른 쉐이더에서 사용 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;래스터라이저: 뷰 프로스텀으로 자르고, 컬링 수행, 폴리곤의 면 보간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;픽셀 쉐이더: 정점별 값을 이용해 픽셀별 색상 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉐이더: GPU에서 실행되는, 3D 장면의 밝기 등의 색상을 계산하는 프로그램&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HLSL(Dx), GLSL(OpenGL)&lt;/p&gt;</description>
      <category>DirectX</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/37</guid>
      <comments>https://aratino5165.tistory.com/37#entry37comment</comments>
      <pubDate>Wed, 8 Jul 2026 23:26:29 +0900</pubDate>
    </item>
    <item>
      <title>[Dx] 컴퓨터 그래픽스 기초</title>
      <link>https://aratino5165.tistory.com/36</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 래스터 그래픽&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;래스터 그래픽: 2차원 이미지를 정사각형 픽셀 형태로 표현하는 방법.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;래스터라이제이션: 도형을 래스터 이미지로 변환하는 작업.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Frame buffer&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프레임 버퍼는 디스플레이에 표시될 모든 픽셀의 색상 값을 나타내는 데이터를 저장하는 메모리 버퍼를 의미함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPU가 연산을 통해 렌더링한 화면 데이터를 디스플레이로 전송하기 직전에 저장함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더블 버퍼링: 티어링 등을 방지하기 위해 두개의 버퍼(프론트, 백)를 사용한다. 렌더링이 완료되면 두 버퍼를 교환해 부드러운 화면을 보여줄 수 있음.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Refresh rate &amp;amp; Frame rate&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Refresh rate는 디스플레이가 1초동안 화면 갱신하는 횟수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Frame rate는 GPU가 1초동안 렌더링하여 생성하는 프레임의 수&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. Polygon&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버텍스와 엣지의 모음. 보통 3개(트라이앵글), 4개(쿼드)로 이루어져 있음.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 폴리곤을 구성하는 정점들은 순서가 있고, 순서에 따라 앞면인지, 뒷면인지 결정된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctGD30/dJMb99NH7wg/LGgUmwJy6aBCyaYbkS03DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctGD30/dJMb99NH7wg/LGgUmwJy6aBCyaYbkS03DK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctGD30/dJMb99NH7wg/LGgUmwJy6aBCyaYbkS03DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctGD30%2FdJMb99NH7wg%2FLGgUmwJy6aBCyaYbkS03DK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;416&quot; height=&quot;240&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버텍스 리스트: 모든 버텍스의 정보를 담아두는 배열이다. 공간상의 위치 뿐 아니라 노멀벡터, UV좌표, 색상 값 등 버텍스의 정보를 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스 리스트: 버텍스 리스트의 버텍스들을 어떤 순서로 연결해 폴리곤을 만들지 인덱스 정보만 기록한 정수 배열이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cui2Yp/dJMcaixcA0x/ttPeZAWM6eazAGmlw1DoLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cui2Yp/dJMcaixcA0x/ttPeZAWM6eazAGmlw1DoLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cui2Yp/dJMcaixcA0x/ttPeZAWM6eazAGmlw1DoLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcui2Yp%2FdJMcaixcA0x%2FttPeZAWM6eazAGmlw1DoLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;534&quot; height=&quot;319&quot; data-origin-width=&quot;1035&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 테셀레이션&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테셀레이션: 기존의 메쉬를 폴리곤 단위로 쪼개는것. 메쉬 위에 Bump맵 같은걸 씌웠을때 하는듯.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LOD: 3D 객체가 카메라로부터 멀어질 때 메쉬의 정밀도를 조절하는 기법.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LbTkk/dJMcabkz1LK/Whz870J8M6KmtNoSpB9KT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LbTkk/dJMcabkz1LK/Whz870J8M6KmtNoSpB9KT1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LbTkk/dJMcabkz1LK/Whz870J8M6KmtNoSpB9KT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLbTkk%2FdJMcabkz1LK%2FWhz870J8M6KmtNoSpB9KT1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;519&quot; height=&quot;223&quot; data-origin-width=&quot;845&quot; data-origin-height=&quot;363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 윈도우 프로그래밍&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Win32 프로그래밍은 WinMain 함수에서 시작함.&lt;/p&gt;
&lt;pre id=&quot;code_1783346445501&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow)
{
	SystemClass* System;
	bool result;
	
	
	// Create the system object.
	System = new SystemClass;
	if(!System)
	{
		return 0;
	}

	// Initialize and run the system object.
	result = System-&amp;gt;Initialize();
	if(result)
	{
		System-&amp;gt;Run();
	}

	// Shutdown and release the system object.
	System-&amp;gt;Shutdown();
	delete System;
	System = 0;

	return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>DirectX</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/36</guid>
      <comments>https://aratino5165.tistory.com/36#entry36comment</comments>
      <pubDate>Mon, 6 Jul 2026 23:01:37 +0900</pubDate>
    </item>
    <item>
      <title>LLM을 이용한 행동트리 학습 가능성에 대한 연구</title>
      <link>https://aratino5165.tistory.com/35</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;이 글에서 공개하는 내용은 개인적으로 진행했지만, 논문 작성까지 가지 않은 개인 연구 입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;본 원고는 학회에 게재되거나 발표되지 않았으며, 정식 심사를 거치지 않았습니다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;0. Abstract&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;게임 인공지능 분야에서 행동 트리&lt;/span&gt;&lt;span&gt;(BT)&lt;/span&gt;&lt;span&gt;는 높은 해석 가능성과 모듈성을 제공하지만&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;복잡한 환경에 대응하기 위해서는 전문가의 수동 설계가 필수적이라는 한계가 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;최근 대규모 언어 모델&lt;/span&gt;&lt;span&gt;(LLM)&lt;/span&gt;&lt;span&gt;을 활용한 에이전트 연구가 활발하나&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;실시간 추론 비용과 속도로 인해 게임 런타임에 직접 적용하기에는 제약이 따른다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;본 연구에서는 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;을 실시간 컨트롤러가 아닌&lt;/span&gt;&lt;span&gt;, BT&lt;/span&gt;&lt;span&gt;를 설계하고 수정하는 프레임워크를 제안한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;1. 서론&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;게임 인공지능 분야에서 에이전트의 의사결정 모델을 설계하는 것은 크게 규칙 기반과 학습 기반의 두 가지로 구분된다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;전통적인 유한 상태 기계&lt;/span&gt;&lt;span&gt;(FSM)&lt;/span&gt;&lt;span&gt;나 행동 트리&lt;/span&gt;&lt;span&gt;(BT)&lt;/span&gt;&lt;span&gt;와 같은 규칙 기반 시스템은 개발자가 의도를 명확히 파악할 수 있고 디버깅이 용이하나 복잡한 게임 환경의 모든 상태를 사전에 정의해야 하는 확장성의 한계가 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;반면 강화학습은 고차원 상태 공간에서 최적의 전략을 찾을 수 있으나 학습 과정에 많은 자원이 소요되며 결과물인 정책이 블랙박스 형태여서 해석과 수정이 불가능하다는 단점이 있다&lt;/span&gt;&lt;span&gt;[1].&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;최근 대규모 언어 모델&lt;/span&gt;&lt;span&gt;(LLM)&lt;/span&gt;&lt;span&gt;의 등장으로 텍스트 기반의 추론 능력을 활용하여 게임 플레이 로그를 분석하고 전략을 생성하는 접근방법이 가능해졌다&lt;/span&gt;&lt;span&gt;[2]. &lt;/span&gt;&lt;span&gt;그러나 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;이 게임 컨트롤에 실시간으로 개입하는 것은 추론 시간과 비용 등으로 인해 비효율적이다&lt;/span&gt;&lt;span&gt;[3]. &lt;/span&gt;&lt;span&gt;따라서 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;을 실시간 컨트롤러가 아닌 기존의 신뢰성 있는 제어 구조인 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 생성하고 수정하는 설계자로서 활용하는 방법론이 주목받고 있다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;본 연구에서는 턴제 텍스트 &lt;/span&gt;&lt;span&gt;RPG &lt;/span&gt;&lt;span&gt;전투 환경에서 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;이 전투 로그를 분석하여 플레이어의 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 점진적으로 개선하는 프레임워크를 제안한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이 시스템은 전투 수행&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;로그 분석&lt;/span&gt;&lt;span&gt;, BT &lt;/span&gt;&lt;span&gt;수정의 반복적인 사이클을 통해 사람의 개입 없이 전략을 최적화할 수 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;2. 관련 연구&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;2.1 BehaviourTree 자동 생성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; BT&lt;/span&gt;&lt;span&gt;는 모듈화와 재사용성이 뛰어나 게임 업계의 표준적인 &lt;/span&gt;&lt;span&gt;AI &lt;/span&gt;&lt;span&gt;아키텍쳐로 자리 잡았다&lt;/span&gt;&lt;span&gt;[4]. &lt;/span&gt;&lt;span&gt;기존 연구에서는 유전 알고리즘을 사용하여 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 진화시키려는 시도가 있었으나&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;이는 적합도 함수 설계가 까다롭고 생성된 트리의 가독성이 떨어지는 경향이 있다&lt;/span&gt;&lt;span&gt;[5]. &lt;/span&gt;&lt;span&gt;본 연구는 무작위 변이에 의존하는 진화 연산 대신 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;의 추론 능력을 활용하여 전투 로그의 인과 관계를 분석하고 목적 지향적으로 트리를 수정한다는 점에서 차별화된다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;2.2 게임 에이전트로서의 LLM&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;기존 연구는 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;이 텍스트 피드백을 통해 마인크래프트 같은 시뮬레이션 환경에서 장기적인 계획을 수립할 수 있음을 입증했다&lt;/span&gt;&lt;span&gt;[6]. &lt;/span&gt;&lt;span&gt;그러나 이러한 방식은 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;이 매 틱마다 호출되거나 자연어 형태의 계획을 수행하므로 연산 비용이 높고 실시간성이 요구되는 전투 환경에 부적합 한 문제가 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;본 연구는 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;을 최적화 도구로만 사용하고 생성된 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 오프라인 환경에서 실행해 실행 효율성과 성능을 동시에 추구한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;3. 실험 방법&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.1 게임 환경 및 제약 조건&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;실험 환경은 &lt;/span&gt;&lt;span&gt;35&lt;/span&gt;&lt;span&gt;턴의 제한이 있는 &lt;/span&gt;&lt;span&gt;1:1 &lt;/span&gt;&lt;span&gt;턴제 전투이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;플레이어와 적은 각각 &lt;/span&gt;&lt;span&gt;HP, MP, &lt;/span&gt;&lt;span&gt;공격력&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;방어력 등의 스탯을 가지며&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;화염과 얼음 속성 간의 상성 시스템이 적용된다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;모든 전투 정보는 텍스트의 로그 형태로 기록되며 이는 &lt;/span&gt;&lt;span&gt;Critic LLM&lt;/span&gt;&lt;span&gt;의 입력 데이터로 활용된다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.1.1 &lt;/span&gt;&lt;span&gt;플레이어&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;플레이어는 &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;의 체력과 &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;의 &lt;/span&gt;&lt;span&gt;MP&lt;/span&gt;&lt;span&gt;를 가지며 다음과 같은 &lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;개의 액션 공간을 가진다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;공격 및 스킬&lt;/span&gt;&lt;span&gt;: Attack, Charge, FireSpell, IceSpell&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;방어 및 보조&lt;/span&gt;&lt;span&gt;: Defend, Heal, Cleanse&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;는 이러한 액션들을 노드로 가지며&lt;/span&gt;&lt;span&gt;, Sequence, Selector &lt;/span&gt;&lt;span&gt;등의 제어 노드를 통해 로직을 구성한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;각 액션은 조건 노드와 결합하여 상황에 맞는 전략을 실행한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;조건 노드는 &lt;/span&gt;&lt;span&gt;IsPlayerHPLow, HasMP, HasStatus, EnemyIsTelegraphing, EnemyHasElement &lt;/span&gt;&lt;span&gt;등이 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;액션의 자세한 설명은 다음과 같다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Attack: 9 &lt;/span&gt;&lt;span&gt;데미지&lt;/span&gt;&lt;span&gt;, MP 10 &lt;/span&gt;&lt;span&gt;회복&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Charge: 7 &lt;/span&gt;&lt;span&gt;데미지&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;다음 턴 &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;배 데미지의 &lt;/span&gt;&lt;span&gt;Charged &lt;/span&gt;&lt;span&gt;상태 부여&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;FireSpell: 20MP &lt;/span&gt;&lt;span&gt;소모&lt;/span&gt;&lt;span&gt;, 7&lt;/span&gt;&lt;span&gt;데미지&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;약점 공격시 데미지 &lt;/span&gt;&lt;span&gt;1.5&lt;/span&gt;&lt;span&gt;배&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;IceSpell: 20MP &lt;/span&gt;&lt;span&gt;소모&lt;/span&gt;&lt;span&gt;, 10&lt;/span&gt;&lt;span&gt;데미지&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;약점 공격시 데미지 &lt;/span&gt;&lt;span&gt;1.5&lt;/span&gt;&lt;span&gt;배&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Defend: &lt;/span&gt;&lt;span&gt;받는 데미지 &lt;/span&gt;&lt;span&gt;50% &lt;/span&gt;&lt;span&gt;감소&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Heal: 30MP &lt;/span&gt;&lt;span&gt;소모&lt;/span&gt;&lt;span&gt;, HP40 &lt;/span&gt;&lt;span&gt;회복&lt;/span&gt;&lt;span&gt;, 3&lt;/span&gt;&lt;span&gt;턴 쿨타임&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Cleanse: 25MP&lt;/span&gt;&lt;span&gt;소모&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;상태 이상 제거&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.1.2 &lt;/span&gt;&lt;span&gt;적대적 개체&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;시스템을 검증하기 위해 서로 다른 전략을 요구하는 두 가지 타입의 적을 설계한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;FireGolem: 상태 기반 패턴 변화&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;180&lt;/span&gt;&lt;span&gt;의 체력과 &lt;/span&gt;&lt;span&gt;40MP&lt;/span&gt;&lt;span&gt;를 가지며 두 개의 체력 기반 상태&lt;/span&gt;&lt;span&gt;(Phase)&lt;/span&gt;&lt;span&gt;를 가지며 상태 &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;에서는 &lt;/span&gt;&lt;span&gt;Fire &lt;/span&gt;&lt;span&gt;속성을 부여받는다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;특수 능력으로 플레이어에게 입힌 데미지의 &lt;/span&gt;&lt;span&gt;20%&lt;/span&gt;&lt;span&gt;를 회복하고 턴 당 &lt;/span&gt;&lt;span&gt;8MP&lt;/span&gt;&lt;span&gt;를 회복한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;사용하는 액션과 확률은 다음과 같다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Phase1: Slam(60%), HeavySlam(40%)&lt;/li&gt;
&lt;li&gt;Phase2: FireStrike(70%), HeavySlam(30%)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;각 액션의 자세한 정보는 다음과 같다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;액션의 정보는 액션 이름&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;소모 &lt;/span&gt;&lt;span&gt;MP, &lt;/span&gt;&lt;span&gt;기본 데미지&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;특수 능력으로 구성된다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Slam: 10MP 소모, Dmg21&lt;/li&gt;
&lt;li&gt;HeavySlam: 30MP 소모, Dmg45&lt;/li&gt;
&lt;li&gt;FireStrike:20MP 소모, Dmg15, 플레이어게게 3턴동안 10의 데미지를 주는 디버프를 부여한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 2. IceWraith: 상호작용 기반 동적 속성 변화&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;의 체력과 &lt;/span&gt;&lt;span&gt;100MP&lt;/span&gt;&lt;span&gt;를 가지며 &lt;/span&gt;&lt;span&gt;FrostBlast &lt;/span&gt;&lt;span&gt;스킬을 사용시 &lt;/span&gt;&lt;span&gt;Ice &lt;/span&gt;&lt;span&gt;속성을 &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;턴동안 부여받으며 &lt;/span&gt;&lt;span&gt;FireGolem&lt;/span&gt;&lt;span&gt;보다 세부적인 &lt;/span&gt;&lt;span&gt;Phase&lt;/span&gt;&lt;span&gt;를 가지고 있다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Phase1: FrostTouch(80%), FlostBlast(20%)&lt;/li&gt;
&lt;li&gt;Phase2: FrostTouch(45%), FlostBlast(20%), Debuff(20%), DefensiveStance(15%)&lt;/li&gt;
&lt;li&gt;Phase3: FlostBlast(45%), FrostTouch(35%), Debuff(20%)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;각 액션의 자세한 정보는 다음과 같다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FrostTouch: 10MP, Dmg18&lt;/li&gt;
&lt;li&gt;FrostBlast: 20MP, Dmg28, 사용시 Ice 속성을 3턴동안 부여받는다.&lt;/li&gt;
&lt;li&gt;Debuff: 20MP, 플레이어에게 1턴동안 공격력 20% 감소 디버프를 부여한다.&lt;/li&gt;
&lt;li&gt;DefensiveStance: 15MP, 방어력이 25% 증가한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.2 시스템 아키텍쳐&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;본 시스템은 전투 로그를 분석하고 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 개선하기 위해 두 단계의 &lt;/span&gt;&lt;span&gt;LLM &lt;/span&gt;&lt;span&gt;파이프라인을 사용한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.2.1 Critic&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;전투가 종료되면 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트는 전체 전투 로그를 입력받는다&lt;/span&gt;&lt;span&gt;. Critic&lt;/span&gt;&lt;span&gt;은 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;의 문법을 수정하지 않고&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;오직 전략적 결함만을 자연어로 지적한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이 단계에서는 많은 토큰을 효율적으로 처리하기 위해 &lt;/span&gt;&lt;span&gt;Gemma3:4b &lt;/span&gt;&lt;span&gt;모델을 사용하였다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;3.2.2 Generator&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Generator &lt;/span&gt;&lt;span&gt;에이전트는 현재의 &lt;/span&gt;&lt;span&gt;BT DSL&lt;/span&gt;&lt;span&gt;과 &lt;/span&gt;&lt;span&gt;Critic&lt;/span&gt;&lt;span&gt;의 피드백을 입력받고 개선된 &lt;/span&gt;&lt;span&gt;BT DSL&lt;/span&gt;&lt;span&gt;을 생성성한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;복잡한 제어 로직을 구성하고 문법적 정확도를 유지해야 하므로 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트보다 높은 코딩 성능을 보유한 &lt;/span&gt;&lt;span&gt;Gemini 2.0 Flash &lt;/span&gt;&lt;span&gt;모델을 사용하였다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;생성한 &lt;/span&gt;&lt;span&gt;BT DSL&lt;/span&gt;&lt;span&gt;은 문법 오류&lt;/span&gt;&lt;span&gt;, Fallback &lt;/span&gt;&lt;span&gt;액션&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;존재하지 않은 조건&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;액션을 사용하는지 검증하고 실패시 이전 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 다시 사용한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;실험은 다음과 같은 반복 루프로 수행된다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기화: 플레이어는 매우 단순한 초기 BT로 게임을 플레이한다.&lt;/li&gt;
&lt;li&gt;실행: 현재 BT로 랜덤한 적과 전투를 수행하고 로그를 생성한다. 승리하거나 최대 턴을 초과하면 종료된다.&lt;/li&gt;
&lt;li&gt;평가: 남은 HP, 소요 턴 수, 승패 유무 등을 기록하고 추가로 두 적과 20회씩 전투 후 승률을 기록한다.&lt;/li&gt;
&lt;li&gt;최적화: Critic-Generator 파이프라인을 가동하여 새로운 BT를 생성한다.&lt;/li&gt;
&lt;li&gt;반복: 생성된 BT로 2단계로 돌아가 재전투를 수행한다. 이 과정은 정해진 횟수 또는 목표 승률 도달까지 반복한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;4. 실험 결과&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;4.1 실패사례 분석&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image01.png&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfjhEG/dJMcaglNMhl/rNLq93HNVZIKjoR7ay0L1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfjhEG/dJMcaglNMhl/rNLq93HNVZIKjoR7ay0L1k/img.png&quot; data-alt=&quot;[그림 1]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfjhEG/dJMcaglNMhl/rNLq93HNVZIKjoR7ay0L1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfjhEG%2FdJMcaglNMhl%2FrNLq93HNVZIKjoR7ay0L1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;429&quot; height=&quot;343&quot; data-filename=&quot;image01.png&quot; data-origin-width=&quot;899&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[그림 1]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;실험 과정에서 &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;그림 &lt;/span&gt;&lt;span&gt;1]&lt;/span&gt;&lt;span&gt;과 같은 에이전트가 최적 전략에 도달하지 못하고 성능이 정체되는 현상이 자주 관찰되었다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이러한 실패사례를 분석한 결과&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;주로 &lt;/span&gt;&lt;span&gt;Generator &lt;/span&gt;&lt;span&gt;에이전트의 보수적 성향과 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트의 추론 오류에 기인함을 확인하였다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Generator &lt;/span&gt;&lt;span&gt;에이전트가 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트의 피드백을 반영하는 과정에서&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;새로운 노드를 추가하거나 제어 노드를 변경해야 하는 상황에서 기존 노드의 순서만 바꾸거나 수치만을 조절해 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;의 논리 구조를 근본적으로 재설계하지 못하는 경향이 보였다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트는 전투 로그의 방대한 텍스트 내에서 패배의 결정적 원인을 식별하지 못하는 경우가 확인되었다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;예를 들어&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;패배의 원인이 &lt;/span&gt;&lt;span&gt;&amp;lsquo;&lt;/span&gt;&lt;span&gt;과거 턴의 디버프 해제 실패&lt;/span&gt;&lt;span&gt;&amp;rsquo; &lt;/span&gt;&lt;span&gt;임에도 단순히 &lt;/span&gt;&lt;span&gt;&amp;lsquo;&lt;/span&gt;&lt;span&gt;전투 종료 직전의 &lt;/span&gt;&lt;span&gt;HP &lt;/span&gt;&lt;span&gt;회복 실패&lt;/span&gt;&lt;span&gt;&amp;rsquo;&lt;/span&gt;&lt;span&gt;를 문제 삼는 등 시간적 인과 관계를 완전히 파악하지 못하는 문제가 있었다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이는 경량화 모델의 한계로 인해 긴 시퀀스 내에서의 맥락을 완전히 파악하지 못했고&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;복합적인 게임 규칙을 완전히 이해하지 못한 것으로 보인다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;4.2 성공사례 분석&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image02.png&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ym7Sv/dJMcaiYazn0/l8IF13MsxjnjeAkL6hKyr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ym7Sv/dJMcaiYazn0/l8IF13MsxjnjeAkL6hKyr0/img.png&quot; data-alt=&quot;[그림 2]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ym7Sv/dJMcaiYazn0/l8IF13MsxjnjeAkL6hKyr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fym7Sv%2FdJMcaiYazn0%2Fl8IF13MsxjnjeAkL6hKyr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;583&quot; height=&quot;217&quot; data-filename=&quot;image02.png&quot; data-origin-width=&quot;907&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[그림 2]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;개선에 성공한 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;들을 분석한 결과&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;에이전트는 게임의 매커니즘 중 일부를 이해하고 더 나은 전략 패턴을 사용했다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;구체적으로는 적의 속성 상태를 조건부로 판단하여 성성 우위에 있는 액션을 선택하거나&lt;/span&gt;&lt;span&gt;, Charge &lt;/span&gt;&lt;span&gt;상태에서 기본 공격 대신 고위력 기술을 연계하여 &lt;/span&gt;&lt;span&gt;DPS&lt;/span&gt;&lt;span&gt;를 올리는 공격 시퀀스가 있었다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;또한&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;적의 강력한 공격이 예고되어있는 텔레그래프를 감지하였을 때는 적절히 방어나 힐을 사용하는 등 생존성을 확보하고&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;디버프가 부여된 경우에는 &lt;/span&gt;&lt;span&gt;Cleanse &lt;/span&gt;&lt;span&gt;액션을 통해 디버프를 해제하는 모습을 보였다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;5. 결과&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;본 연구에서는 턴제 텍스트 &lt;/span&gt;&lt;span&gt;RPG &lt;/span&gt;&lt;span&gt;전투 로그를 분석하여 플레이어의 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 자동으로 최적화하는 프레임워크를 제안하였다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이 시스템은 경량화된 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트와 고성능 &lt;/span&gt;&lt;span&gt;Generator &lt;/span&gt;&lt;span&gt;에이전트의 &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;단계 파이프라인을 통해 텍스트데이터로부터 승리 전략을 만들어 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;를 생성하는 과정을 자동화 하였다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;실험 결과&lt;/span&gt;&lt;span&gt;, Generator &lt;/span&gt;&lt;span&gt;에이전트가 생성하는 &lt;/span&gt;&lt;span&gt;BT&lt;/span&gt;&lt;span&gt;의 구조적 고착과 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;모델의 인과 관계 추론 오류로 인해 대다수의 실험에서 최적의 전략에 수렴하지 못하는 한계가 드러났다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;그러나 간헐적으로 생성된 개선 사례에서 에이전트가 속성 상성&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;텔레그래프 대응&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;스킬 연계와 같은 고수준 전략을 명시적인 &lt;/span&gt;&lt;span&gt;BT &lt;/span&gt;&lt;span&gt;형태로 구현하였음을 확인하였다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이는 불완전한 시스템에도 불구하고 &lt;/span&gt;&lt;span&gt;LLM&lt;/span&gt;&lt;span&gt;이 학습 없이 게임 매커니즘을 이해하고 논리적인 전략을 수립할 수 있음을 시사한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;향후 연구에서는 이러한 한계를 극복하기 위해 &lt;/span&gt;&lt;span&gt;Critic &lt;/span&gt;&lt;span&gt;에이전트의 추론 정확도를 확보할 수 있도록 게임 로그의 품질을 개선할 것이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;또한&lt;/span&gt;&lt;span&gt;, Generator &lt;/span&gt;&lt;span&gt;에이전트의 구조적 문제를 해결하기 위해 유망한 후보를 선별하는 &lt;/span&gt;&lt;span&gt;Beam Search &lt;/span&gt;&lt;span&gt;알고리즘을 도입하고 이전에 실패했거나 성능이 저조했던 노드 패턴을 프롬프트에 추가하여 구조적 변이를 유도할 계획이다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;6. REFERENCE&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[1]: Puiutta, Erika, and Eric MSP Veith. &quot;Explainable reinforcement learning: A survey,&quot; in International Cross-Domain Conference for Machine Learning and Knowledge Extraction, Cham: Springer International Publishing, 2020, pp. 77&lt;/span&gt;&lt;span&gt;&amp;ndash;&lt;/span&gt;&lt;span&gt;95.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[2]: Shinn, Noah, et al. &quot;Reflexion: Language agents with verbal reinforcement learning,&quot; in Advances in Neural Information Processing Systems, vol. 36, 2023, pp. 8634&lt;/span&gt;&lt;span&gt;&amp;ndash;&lt;/span&gt;&lt;span&gt;8652.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[3]:Park, Joon Sung, et al. &quot;Generative agents: Interactive simulacra of human behavior.&quot; Proceedings of the 36th annual acm symposium on user interface software and technology. 2023.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[4]: Isla, Damian. &quot;Managing complexity in the halo2 ai.&quot; Game Developer's Conference Proceedings, 2005. 2005.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[5]: Perez, Diego, et al. &quot;Evolving behaviour trees for the mario ai competition using grammatical evolution.&quot; European Conference on the Applications of Evolutionary Computation. Berlin, Heidelberg: Springer Berlin Heidelberg, 2011.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;[6]: Wang, Guanzhi, et al. &quot;Voyager: An open-ended embodied agent with large language models.&quot; arXiv preprint arXiv:2305.16291, 2023.&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/35</guid>
      <comments>https://aratino5165.tistory.com/35#entry35comment</comments>
      <pubDate>Mon, 6 Jul 2026 22:22:44 +0900</pubDate>
    </item>
    <item>
      <title>개인용 클로드 멀티에이전트 오케스트레이션 환경 구축</title>
      <link>https://aratino5165.tistory.com/33</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;0. 클로드 설치&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. Claude OMC 플러그인 설치&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; 멀티 에이전트 오케스트레이션을 구성하기 위해 클로드 OMC 플러그인을 설치한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/README.ko.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/README.ko.md&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. 스킬 플러그인 및 프로젝트 MCP 설정&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;프로젝트 진행 시 토큰 최적화 및 지식 관리를 자동화하기 위해 플러그인을 설치하고 규칙을 명시한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;설치하는 플러그인: rtk, graphify, llm-wiki&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;설치용 프롬프트: /rtk, /graphify, /llm-wiki 설치해. 매 프롬프트마다 /rtk로 토큰을 압축하고, /graphify 지식그래프로 정제하여 /llm-wiki에 적재하고 참조하면서 발전시켜나가는 것을 규칙으로 적용하고 기억해.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. 유니티 MCP 설치&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;유니티 MCP 패키지 설치&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://github.com/IvanMurzak/Unity-MCP&quot;&gt;https://github.com/IvanMurzak/Unity-MCP&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. 유니티 MCP 연동&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;5. 대화 시작&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt; /ooo interview /deepinit [내 프롬프트 내용 입력] ultrateam4를 사용해. &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>ETC</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/33</guid>
      <comments>https://aratino5165.tistory.com/33#entry33comment</comments>
      <pubDate>Mon, 11 May 2026 23:23:44 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 다음 큰 숫자</title>
      <link>https://aratino5165.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 2진수에서 1의 개수를 세며 1씩 더해 맞을때까지 while문을 돌리는거는 비효율적이라고 생각해 패턴을 찾았음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패턴: 0111 &amp;gt; 1000, 오른쪽부터 봤을 때 1 다음에 나오는 첫 0을 1로 바꾸고 비트를 오른쪽으로 밀어버리는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;string으로 코드를 만들었는데 통과하지만 효율 테스트에서 걸러짐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 비트연산으로 나오면 비직관적이라서 생각이 안드는듯 하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n=0111,0000 이라고 가정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bit연산으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n &amp;amp; -n = 최하위 비트 찾기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0111,0000 &amp;amp; 1001,0000 = 0001,0000&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n + (n &amp;amp; -n) = 아까 말했던 첫번째 패턴&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0111,0000 &amp;nbsp;+ 0001,0000 = 1000,0000&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n ^ (n + (n &amp;amp; -n)) = 원본과 첫번째 패턴과 다른 비트 수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0111,0000 &amp;nbsp;^ 1000,0000 = 1111,0000&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n ^ (n + (n &amp;amp; -n))&amp;nbsp; / (n &amp;amp; -n)여기서 비트를 오른쪽으로 밀어야 하니까, 최하위 비트로 나누어 주면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1111,0000 / 0001,0000 = 0000,1111&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 첫번째 패턴을 만들때 0이 1이 되었기 때문에 최하위 비트 1, 원래부터 연속되었던 1 3개로 1이 4개가 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 연속된 3개중에서 사용해야 할것은 2개이니까&amp;nbsp; 비트 2개를 밀어줘야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n ^ (n + (n &amp;amp; -n))&amp;nbsp; / (n &amp;amp; -n) &amp;gt;&amp;gt; 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0000,1111 &amp;gt;&amp;gt; 2 = 0000,0011&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거를 첫번째 패턴이랑 더하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000,0000 + 0000,0011 = 1000,0011&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1776517501254&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;

class Solution 
{
    public int solution(int n) 
   {
        int answer = 0;
        int upBit = n &amp;amp; -n;
        int mid = n + upBit;
        
        int post = ((n ^ mid) / upBit) &amp;gt;&amp;gt; 2;
        answer = post | mid;
            
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래머스</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/32</guid>
      <comments>https://aratino5165.tistory.com/32#entry32comment</comments>
      <pubDate>Sat, 18 Apr 2026 22:05:44 +0900</pubDate>
    </item>
    <item>
      <title>강화학습 - IMPALA</title>
      <link>https://aratino5165.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분산 강화학습의 필요성&lt;span&gt;: &lt;/span&gt;멀티태스킹이 가능함&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp;학습의 속도&lt;/li&gt;
&lt;li&gt;&amp;nbsp;학습과 데이터를 동시에 얻는 등 리소스 절약&lt;/li&gt;
&lt;li&gt;같은 환경으로부터 다양한 데이터를 얻어 일반화 가능&lt;/li&gt;
&lt;li&gt;다른 환경, 변수를 주어 일반화 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;Actor - Critic (A2C)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정책과 가치를 동시에 학습함&lt;/li&gt;
&lt;li&gt;Gt는 시간 t에서의 누적 보상&lt;/li&gt;
&lt;li&gt;Q함수는 특정 상태 s에서 행동 a를 했을 때 기대되는 누적 보상&lt;/li&gt;
&lt;li&gt;Critic은 상태 가치 V(St)를 학습함&lt;/li&gt;
&lt;li&gt;Gt는 에피소드가 종료되어야 결과가 나와 분산 학습에 적합하지 않음. 반면 IMPALA는 가치 예측 신경망 V(s)로 근사값을 예측함.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;IMPALA: A2C&lt;/span&gt;와 유사하지만&lt;span&gt; V-trace&lt;/span&gt;라는 타겟 밸류 계산법을 사용함&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;속도에서 이점이 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;A2C&lt;/span&gt;는&lt;span&gt; OnPolicy&lt;/span&gt;메소드라서 이전&lt;span&gt; Policy&lt;/span&gt;가 생산한 데이터를 학습하지 못한다&lt;/b&gt;&lt;span&gt;&lt;b&gt;?&lt;/b&gt;&lt;span&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Behaviour Policy &amp;mu;: Action을 선택하고 데이터를 얻을 때 사용하는 Policy&lt;/li&gt;
&lt;li&gt;Target Policy &amp;pi;: 평가하고 업데이트 하는 Policy&lt;/li&gt;
&lt;li&gt;On-Policy: 행동 Policy = 타겟 Policy&lt;/li&gt;
&lt;li&gt;Actor가 Action중일 때 현재 정책 기반으로 데이터를 얻고 학습한다.&lt;/li&gt;
&lt;li&gt;Off-Policy는 과거의 정책에서 나온 데이터를 학습 가능하다&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;IMPALA의 Learner: &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 에피소드 시작 시 Actor은 Learner의 최신 정책으로 업데이트하고 n단계 실행&lt;/li&gt;
&lt;li&gt;n단계 후 trajectory (상태, 행동, 보상과 정책 분포, 초기 LSTM 상태) 를 Learner에게 큐로 전달&lt;/li&gt;
&lt;li&gt;Learner은 수집된 정보들로 정책을 V-trace로 업데이트&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;V-trace:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Leaner가 학습하는 사이 actor들은 데이터 수집중. (actor의 액션과 Leaner의 액션이 다르기 때문에 off-Policy)&lt;/li&gt;
&lt;li&gt;Actor은 최신 데이터를 수집하지만 Leaner은 구형 데이터를 사용하는데, 이를 해소하기 위해 V-trace 사용&lt;/li&gt;
&lt;li&gt;Actor가 선택한 행동의 확률과 leaner의 최신 정책 (구형)에서 선택할 비율을 계산해 학습 보상을 조정함&lt;/li&gt;
&lt;li&gt;만약 &amp;pi; = &amp;mu; 라면 이 비율은 1이 되고 V(xt) = rt + &amp;gamma;V(xt + 1), On-Policy와 동일하게 됨&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분산 A2C와 IMPALA 비교&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u3eLX/btsLPrX2fB7/iAynemTZy27tSw597pHBn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u3eLX/btsLPrX2fB7/iAynemTZy27tSw597pHBn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u3eLX/btsLPrX2fB7/iAynemTZy27tSw597pHBn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu3eLX%2FbtsLPrX2fB7%2FiAynemTZy27tSw597pHBn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;940&quot; height=&quot;427&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;a&amp;gt;b&amp;gt;c&lt;/span&gt;로 진화 한것처럼 보임&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;좌측은 각각 step, trajectory를 동기화 하지만 결국 모든 액터의 에피소드가 끝나야 하기에 기다려야함.&lt;/li&gt;
&lt;li&gt;&lt;u&gt;step 동기화는 무슨 의미?&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;trajectory 동기화는 에피소드가 끝나야 &lt;u&gt;trajectory를 leaner에게 전해주니 에피소드 자체를 동기화 하는듯?&lt;/u&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;우측의 경우에는 역전파시 에피소드가 채 끝나지 않은 액터의 trajectory도 사용해 학습하는것 처럼 보임&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;IMPALA&lt;/span&gt;의&lt;span&gt; Learner&lt;/span&gt;은 에피소드가 끝나지 않은 액터의 이전&lt;span&gt; trajectory&lt;/span&gt;와 다른 액터의 새로운 &lt;span&gt;trajectory&lt;/span&gt;를 얻어&lt;span&gt; V-trace&lt;/span&gt;로 근사치를 구한다&lt;span&gt;. &lt;/span&gt;이는 행동 정책&lt;span&gt;(&lt;/span&gt;액터가 행동하려는&lt;span&gt;, &lt;/span&gt;점수를 얻으려는 정책&lt;span&gt;)&lt;/span&gt;과 목표 정책&lt;span&gt;()&lt;/span&gt;의 차이를 보정하려고 하기 위함이다&lt;span&gt;. &lt;/span&gt;이때 목표 정책은 최적화된 행동 정책이라고 봐도 된다&lt;span&gt;? &lt;/span&gt;왜나면&lt;span&gt;, &lt;/span&gt;일부 액터들을 기다리기 때문에&lt;span&gt;, &lt;/span&gt;모든 최신&lt;span&gt; trajectory&lt;/span&gt;로 학습하지 않았으니까&lt;span&gt;, &lt;/span&gt;이런 액터들의 행동 정책과&lt;span&gt; leaner&lt;/span&gt;의 정책에는 차이가 있을텐데 이게&lt;span&gt; Off-Policy &lt;/span&gt;방식인가&lt;span&gt;? &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니까&lt;span&gt;, &lt;/span&gt;목표 정책은 행동 정책이 목표로 하는 완성된 행동 정책인가&lt;span&gt;?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;V-trace&lt;/span&gt;는 예측한 누적가치합과 현재 상태에서 예측되는 누적 가치합의 차이를 중요도 샘플링을 사용해 최소화한다&lt;span&gt;. &lt;/span&gt;그렇다면&lt;span&gt;, &amp;lsquo;&lt;/span&gt;누적&lt;span&gt;&amp;rsquo; &lt;/span&gt;이니까&lt;span&gt; LSTM&lt;/span&gt;을 사용하게 된다&lt;span&gt;?&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/31</guid>
      <comments>https://aratino5165.tistory.com/31#entry31comment</comments>
      <pubDate>Thu, 16 Jan 2025 01:46:59 +0900</pubDate>
    </item>
    <item>
      <title>사칙연산 / C++</title>
      <link>https://aratino5165.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/1843&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/1843&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1735925360851&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/1843&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/TQ5Qd/hyXWCGjXUt/WdlRwDWezjOJ2ZlAw2zKZk/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/03fUz/hyXWuVLCQR/mwRCvMKl0YFp12kj0moeI0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/1843&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/1843&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/TQ5Qd/hyXWCGjXUt/WdlRwDWezjOJ2ZlAw2zKZk/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/03fUz/hyXWuVLCQR/mwRCvMKl0YFp12kj0moeI0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 주어진 숫자와 부호를 똑같이 취급했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex. 1 + (-3) = -2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex. -3 + 5 = -(3 + 5) = -8&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[i][j] 에서 색상 라인으로 뻗어나간 두 노드를 탐색해 더 큰 수만 저장하는 방식으로 생각했는데, 오답이 너무 많이 나왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;160&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFTr6H/btsLCDy0t3l/O9paaOyfVKitQLylSSYA7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFTr6H/btsLCDy0t3l/O9paaOyfVKitQLylSSYA7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFTr6H/btsLCDy0t3l/O9paaOyfVKitQLylSSYA7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFTr6H%2FbtsLCDy0t3l%2FO9paaOyfVKitQLylSSYA7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;160&quot; height=&quot;184&quot; data-origin-width=&quot;160&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간중간 오류를 보완하는 코드를 넣었지만 반례가 너무 많아 접근 방식이 틀렸다고 인정하고 아이디어를 바꿨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서는 구간의 최댓값만 사용한다. 하지만 부호가 음수일경우, 구간 - 구간 일 경우에는 뒷 구간은 최솟값이어야 최대값이 출력된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부호가 양수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대값: 최대 + 최대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소값: 최소 + 최소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부호가 음수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대값: 최대값 - 최소값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소값: 최소값 - 최대값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미리 저장해놓은 dp[][] 배열에서 좌측 구간과 우측 구간 연산시 해당 연산자의 부호에 따라 점화식이 바뀐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이해하기 쉽게 이미지를 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1399&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wxdSu/btsLDKDXFlH/Sq34PnQAm7Yyms9N6xMcN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wxdSu/btsLDKDXFlH/Sq34PnQAm7Yyms9N6xMcN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wxdSu/btsLDKDXFlH/Sq34PnQAm7Yyms9N6xMcN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwxdSu%2FbtsLDKDXFlH%2FSq34PnQAm7Yyms9N6xMcN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1399&quot; height=&quot;737&quot; data-origin-width=&quot;1399&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i가 의미하는것은 계산할 총 구간의 길이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;s가 의미하는것은 구간의 시작 노드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 구간의 끝 노드는 s + i - 1 이 될것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 - 1 - 1 + 5 - 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에서 i = 2, s = 2 라면 e = 3 이다. 1 + 5 구간.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 연산자 o의 위치는 2번 밖에 없다. [2] 1, [3] 5 사이에는 + 밖에 없으니까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;o = 2 &amp;gt;&amp;gt; (1) + (5) &amp;gt;&amp;gt; dp[2][2] 와 dp[3][3] 을 계산.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지를 보면 최대값 6, 최소값 6&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i = 3, s = 0 이라면 e = 2 다. 0, 1, 2 번 노드를 계산한다. 1 - 1 - 1 구간.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;o = 0 &amp;gt;&amp;gt; 1 - (1 - 1)&amp;nbsp; &amp;gt;&amp;gt; dp[0][0] 와 dp[1][2] 을 계산.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;o = 1 &amp;gt;&amp;gt; (1 - 1) - 1&amp;nbsp; &amp;gt;&amp;gt; dp[0][1] 와 dp[2][2] 을 계산.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 부호는 음수니까 위에서 말한대로 최대값과 최소값을 구해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 끝까지 계산해주고 최대값을 리턴하면 끝.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1735925363295&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;vector&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;lt;algorithm&amp;gt;

using namespace std;

pair&amp;lt;int, int&amp;gt; dp[205][205];
int is[205];
int solution(vector&amp;lt;string&amp;gt; arr)
{
    int size = arr.size() / 2 + 1;
    for (int i = 0; i &amp;lt; size; i++)
    {
        for (int j = 0; j &amp;lt; size; j++)
        {
            dp[i][j].first = -1e9;
            dp[i][j].second = 1e9;
        }
    }

    for (int i = 0; i &amp;lt; size; i++)
    {
        dp[i][i].first = stoi(arr[i * 2]);
        dp[i][i].second = stoi(arr[i * 2]);
    }
    for (int i = 0; i &amp;lt; size - 1; i++)
    {
        if (arr[i * 2 + 1] == &quot;-&quot;)
        {
            is[i] = true;
        }
    }

    for (int i = 2; i &amp;lt;= size; i++) //사이즈
    {
        for (int s = 0; s + i - 1 &amp;lt; size; s++)
        {
            for (int o = s; o &amp;lt; s + i - 1; o++)
            {
                //cout &amp;lt;&amp;lt; &quot;start: &quot; &amp;lt;&amp;lt; s &amp;lt;&amp;lt; &quot;, end: &quot; &amp;lt;&amp;lt; s + i - 1 &amp;lt;&amp;lt; &quot;, operator: &quot; &amp;lt;&amp;lt; o &amp;lt;&amp;lt; endl;
                if (is[o])
                {
                    dp[s][s + i - 1].first = max(dp[s][s + i - 1].first, dp[s][o].first - dp[o + 1][s + i - 1].second);
                    dp[s][s + i - 1].second = min(dp[s][s + i - 1].second, dp[s][o].second - dp[o + 1][s + i - 1].first);
                }
                else
                {
                    dp[s][s + i - 1].first = max(dp[s][s + i - 1].first, dp[s][o].first + dp[o + 1][s + i - 1].first);
                    dp[s][s + i - 1].second = min(dp[s][s + i - 1].second, dp[s][o].second + dp[o + 1][s + i - 1].second);
                }
            }
        }
    }


    return dp[0][size - 1].first;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래머스</category>
      <author>GRstory</author>
      <guid isPermaLink="true">https://aratino5165.tistory.com/30</guid>
      <comments>https://aratino5165.tistory.com/30#entry30comment</comments>
      <pubDate>Sat, 4 Jan 2025 02:42:21 +0900</pubDate>
    </item>
  </channel>
</rss>