스펠 캐스팅-초당 데미지를 최적화하는 방법


23

몇 가지 주문을 아는 마법사가 있다고 상상해보십시오. 각 주문에는 3 가지 속성이 있습니다 : 데미지, 쿨 다운 시간, 시전 시간. 꽤 표준적인 RPG입니다.

재사용 대기 시간 : 주문을 다시 시전하는 데 걸리는 시간 (t)입니다. 시전이 시작되는 순간 주문이 "재사용"됩니다.

시전 시간 : 주문을 사용하는 데 걸리는 시간 (t)입니다. 마법사가 무언가를 시전하는 동안 다른 주문을 시전 할 수 없으며 취소 할 수 없습니다.

문제는 : 여러 가지 주문이 주어지면 어떻게 피해를 극대화 할 수 있습니까?

시전 시간당 최대 데미지를 쉽게 계산할 수 있습니다. 그러나 훨씬 더 높은 마법을 사용할 수있을 때 기다렸다가 피해가 적은 주문을 "고정"시키는 것이 더 좋은 상황은 어떻습니까?

예를 들어

  1. 화염 구 : 3000의 피해, 3 초의 시전 시간, 6 초의 재사용 대기 시간

  2. 동상 : 20의 피해, 4 초의 시전 시간, 4 초의 재사용 대기 시간.

  3. 화염 폭발 : 피해 3, 시전 시간 3 초, 재사용 대기 시간 3 초

이 경우 서리 볼트 대신 낮은 DPCT 주문 (화재 폭발)을 선택하면 초당 공격력이 높아집니다. 따라서 주문을 선택했을 때의 결과를 고려해야합니다. 대체 텍스트

다음 예는 "오버 캐스팅"및 "대기"의 경우입니다. 대체 텍스트


이 상황에서 왜 1-3-1을합니까? 1-2-1이 아닌 이유는 무엇입니까? 1-3-1만으로도 대상을 죽이지 않으면 1-3-1-X보다 효율적인 1-2-3-1이 아닌 이유는 무엇입니까?

@Joe Wreschnig : 지적 해 주셔서 감사합니다. 내 예에서 실수였다. 이제 2 건으로 단순화했습니다.
aaronfarr

1
탐욕, 가능한 한 가장 높은 dps 주문을 선택하십시오. 다른 논리를 무시하십시오. 기다리는.
aaronfarr

1
물을 흐릿하게하기 위해서. ∞ 데미지를 주지만 시전하는데 50 초가 걸리는 주문을 생각해보십시오. dps / dpct는 ∞이지만 50 초 이내에 다른 방법으로 대상을 처치 할 수 있다면 절대로 선택해서는 안됩니다.
deft_code

1
당신은에 속는에 연결해야합니다 math.stackexchange.com/questions/10414/...
Sparr

답변:


23

모든 AI는 검색입니다!

AI의 장에 들어가면 실제로 검색 하는 것이 얼마나 놀라운 지 놀랍습니다 .

  • state : 사용 가능한 모든 주문의 남은 재사용 대기 시간.
  • 체력 : 총 피해량
  • 비용 : 총 소요 시간
  • 분기 : 알려진 주문. 주문이 여전히 재사용 대기 상태 인 경우 해당 값을 시전 시간에 추가하십시오.
  • 목표 : 목표의 총 건강. 목표는 유한 한 양의 데미지 여야하므로 대상을 알 수없는 경우 가능한 최대의 체력을 선택하십시오.
    또는 목표를 50 초 미만으로 소비 할 수 있으며 검색에서 50 초 내에 수행 할 수있는 최대 피해를 찾을 수 있습니다.

이 매개 변수를 UCS ( Uniform Cost Search )에 연결하면 최적의 전투 계획이 보장됩니다. 휴리스틱을 찾 거나 A * 또는 IDA *를 사용하여 검색하면 훨씬 더 빠르게 동일한 답변을 얻을 수 있습니다.

UCS를 사용하면 얻을 수있는 또 다른 이점은 3 개의 변수 만 제공 한 것보다 훨씬 복잡한 상황에서 최적의 캐스트 순서를 찾을 수 있다는 것입니다. 쉽게 추가 할 수있는 몇 가지 다른 측면 :

  • 시간이 지남에 따른 피해
  • 다른 주문의 재사용 대기 시간을 줄이기 위해 주문을 새로 고침
  • 급한 주문으로 인해 다른 주문이 더 빨리 시전됩니다.
  • 다른 주문이 더 많은 데미지를 입히도록하는 데미지 부스터.

UCS는 전능하지 않습니다. 보호 주문의 이점을 모델링 할 수 없습니다. 이를 위해서는 알파-베타 검색 또는 미니 맥스로 업그레이드해야합니다.
또한 영향 영역과 그룹 싸움을 잘 처리하지 못합니다. 이러한 상황에서 합리적인 솔루션을 제공하기 위해 UCS를 조정할 수 있지만 최적의 솔루션을 찾지 못할 수도 있습니다.


2

이것은 특수한 조합 최적화 문제입니다. 주문의 수가 증가함에 따라, 주문의 최적 조합 / 패턴을 찾는 데 어려움이 크게 증가합니다. 배낭 문제에 사용 된 것과 유사한 휴리스틱 은이 문제를 해결하는 데 유용합니다.


1

예를 들어, 캐스팅 시간이 3 초이고 공격력이 3000 인 화염 구는 DPCT가 1000이됩니다.

쿨 다운을 시전하기 전에 3 초 동안 기다려야한다면, 500 DPCT (3000 데미지를 대기 시간을 포함하여 총 6 초로 나눈 값)로 감소시킵니다.

따라서 쿨 다운 대기 시간을 포함하여 각 주문의 시전 당 공격력을 결정하면됩니다. DPCT가 가장 높은 것을 선택하고 필요한 경우 기다렸다가 전송하십시오. 보스가 죽을 때까지 반복하십시오 :)


문제는 DPCT가 매우 오도 할 수 있다는 것입니다. 예를 들어 믹스 파이어 볼에 주문 2 개, 주문 3 초, 6 초 쿨 다운, DPCT : 1000 주문 # 2 : 20, 4 초 캐스트, 4 초 쿨 다운, DPCT : 5 주문 # 3 : 3 데미지, 3 초 캐스트, 3 초 쿨 다운, DPCT : 1 (주문이 시전되는 순간 쿨 다운이 시작됨을 기억하십시오) 주문 # 3의 DPCT가 낮더라도 DPS가 높아집니다 (1-3-1-3.). .)보다 주문 # 2 (1-2-1-2 ...)보다.
aaronfarr

1

귀하의 예를 사용하면 두 주문의 효과가 더 가깝기를 원하지만 다른 이점을 얻을 수 있습니다. 캐스팅 시간이 짧거나 (또는 ​​해당 재료에 대한 캐스팅 시간이없는 경우) 매우 유용하므로 손상이 적고 다시 사용하는 데 시간이 더 걸리더라도 사용할 가치가 있습니다.

방정식에 다른 요소를 항상 부과 할 수 있습니다. 마나 / 마법 포인트는 플레이어가 해당 포인트를 사용할 가치가 있는지 판단 할 수 있도록하여이 목적을 달성 할 수 있습니다.

그러나 bluescrn이 말했듯이 DPCT (또는 최고의 믹스를 추구하는 플레이어가 고도로 조정하고 논의한 많은 게임에서 DPS라고 함)는 실제로 균형을 잡고 싶은 주요 요소입니다. 특히 기술 / 스킬 트리 : 다른 플레이어가 다른 기술로 진행할 수 있지만 게임에서 주어진 위치에서 비슷한 양의 피해를 입힐 수 있습니다.


0

내 목적에 잘 맞는이 알고리즘을 알아 냈습니다.

사람들은 몇 가지 좋은 점을 제기했습니다. 궁극적 인 목표 매개 변수를 제공하면 일반 검색 알고리즘이 할 수 있습니다. 즉. t 초 안에 최적의 피해를 입히고, 최적의 시간에 x 피해를 입힌다.

내 알고리즘은 단순히 DPS가 가장 높은 일련의 주문을 반환합니다. 트래버스중인 세트의 크기를 줄이면 빠른 알고리즘이며 다른 검색 트리 기술에 대한 지식이 필요하지 않습니다.

첫 번째 단계는 시전 시간당 공격력이 가장 높은 마법을 식별하는 것입니다. 이 주문은 초당 최대 피해를 보장하기 때문에 "기준선"주문이됩니다. 즉, 다음 두 가지 조건이 충족되면 항상이 주문을 시전해야합니다. 1) 기본 주문이 가능합니다 (재사용 대기 시간 제외). 2) 현재 주문을 제출하지 않았습니다.

따라서 기준선 주문이 재사용 대기 상태 일 때 다른 주문을 채우는 문제가됩니다. (시전 시간)과 (재사용-시전 시간) 사이 그러나 일부 중복이 발생할 수 있습니다 (위의 규칙 2가 거짓).

그런 다음 두 가지 규칙을 위반하지 않는 모든 일련의 주문을 찾기 위해 기본이 아닌 모든 주문을 반복해야합니다.

DO가 겹치는 주문의 경우, 기본 주문이 수행 할 수있는 잠재적 피해 (최대 피해까지)에 대해 불이익을 주어야합니다.

예를 들어, 2 개의 주문

1 : 300의 피해, 3 초의 시전 시간, 10 초의 재사용 대기 시간

2 : 피해 290, 시전 시간 3 초, 재사용 대기 시간 3 초

가장 큰 피해는 1-2-2-2 시퀀스에서 발생합니다. 이로 인해 잠재적 인 # 1 캐스트에 2 초가 겹칩니다. 그러나 세 번째 주문 (예 : 1-2-2)을 시전하지 않으면 1 초 동안 880의 피해를 입히기 때문에 여전히 유용합니다. 여분의 # 2 주문을 시전하면 # 1의 1170-2 초를 200으로합니다. 따라서 970의 피해는 상대 피해입니다.


-2

간단한 "보안 수준"스타일 전환 사례를 수행 할 수 있습니다.

이것은 내 머리 꼭대기에 있기 때문에 피곤한 상태의 생각 수준을 넘어 논리 오류를 조심하십시오. 그러나 이것이 당신을 시작할 수 있기를 바랍니다.

시간이 블록 정수로 완료되었다고 가정하면-

// after casting spell
int remainingTime = (coolDown - castTime);
switch(spellJustCast)
{
  // assuming the cast method will have some input validation for whether the spell
  // is off cooldown or not, pass the time as a parameter
  case 3 : castSpell1(remainingTime);
           castSpell2(remainingTime);
           break;
  case 1 : castSpell2(remainingTime);
           castSpell3(remainingTime);
           break;
  case 2 : castSpell1(remainingTime);
           castSpell3(remainingTime);
           break;
  default: System.out.println("Debug!");
           break;
}

철자 시간으로 인해 일부 메소드 호출이 필요하지 않지만 항상 이런 방식으로 업데이트 할 여지가 있습니다.

편집 : 방금 깨달았습니다. 새 스펠이 캐스팅 된 후 남은 시간을 재설정해야합니다. 아마도 클래스 속성 / 필드로 만들고 castSpell 메소드 내의 호출에서 설정하는 것이 가장 좋습니다.


나는 당신이 여기에 무엇을하려고하는지 전혀 모른다. 그러나 현대 게임 엔진에는 castSpell1 및 castSpell2와 같은 기능이 없습니다.

1
@Joe Wreschnig 나는 자신의 커스텀 게임 클래스에서 자신의 메소드라는 것을 의미했습니다. 이것은 구체적인 예제가 아니라 단지 추상적 인 예입니다.
kymully

1
그렇습니다. 현대 엔진에서 철자가 작동하는 방식은 아닙니다. 파일에서 필드를 읽는 객체를 가져 오는 castSpell 함수가 하나 있습니다. 이러한 스위치 설명은 실제 엔진에서 유지 관리 할 수 ​​없으며 일종의 계획 알고리즘이 필요합니다.

@Joe Wreschnig 이해합니다. 나는 단지 문제를 해결할 수있는 방법을 제공하고 있었다. 이 예제는 엔진 또는 특정 프레임 워크 용이 아닌 Java로 작성되었습니다. 그러나 당신이 말한대로 구현 할 수 없다면 내 대답은 무효입니다.
kymully
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.