[작성중/교양 프로그래밍] 발악데미지 원리 추측

대연.

·

2021. 7. 7. 01:12

개요

민속놀이 스타크래프트에는 몇몇 기괴한 현상이 일어난다. 그 중 하나인 럴커의 발악데미지에 대한 뇌피셜을 풀어본다. 발악데미지란, 럴커가 발사한 가시가 끝에 도달하기 전에 럴커가 죽으면 엄청난 데미지를 뿜어내는 버그성 현상이다. 자주 챙겨보는 열사 운장이형의 럴커는 죽을 때도 데미지를 입힌다는 점 알고 계셨나요? 영상에서 가설을 세우고 실험을 통해 증명하는 모습을 보면서, 현상보다 더 깊이 있는 코딩에 대한

럴커의 디자인

가시 발사는 럴커가 1회 공격하였을 때, 가시는 1회의 공격에서 시각적으로 보이는 각각의 가시 1개를 말하겠다.

기획자는 럴커 가시 범위 내의 유닛에게 한 번의 데미지를 주기를 원하였을 것이다. 실제로도 럴커가 죽지 않고 공격을 수행한다면, 의도대로 한 번의 가시 발사에 한 번의 데미지밖에 입지 않는다. 그런데...

문제의 가시 범위

한 번의 럴커 공격에서 나오는 각 가시의 피격 판정은 생각보다 넓어보인다. 아래 그림을 참고하자.

보이는 것 보다 피격판정이 크다.

과장되게 그림을 그렸지만, 실제 보이는 가시보다 피격판정이 크다고 체감된다. 여기서 생기는 문제는, 만약 각 가시의 범위에 겹친다면 어떤 일이 벌어질까?

각 가시가 독립적으로 데미지를 주도록 구현이 되어있다면, 두 개의 가시 범위에 겹치는 유닛은 2번의 데미지를 받을 것이다. 이는 기획자의 의도에 벗어난 구현일 것이고, 이를 방지하기 위해서 추가적인 아이디어가 필요했을 것이다.

중복 피격 방지하기

* 여기서부턴 뇌피셜의 영역입니다. 가볍게 읽어주시길 바랍니다.

럴커가 살아있을 경우 이미 발사된 가시들은 id=25인 럴커가 발사했다는 정보를 담고 있을 것이고, 어떤 유닛이 1회 피격 시 특정 시간 동안에는 같은 럴커가 발사한 다른 가시에 데미지를 받지 않도록 구현할 수 있을 것이다. 실제로 럴커가 살아 있을 때에는 잘 작동하고, 20년 스타 역사에 수천,수만 프로 경기를 치러오면서도 문제가 되지 않았음을 알 수 있다.

문제는 럴커의 가시 발사가 끝나지 않았는데 럴커가 죽은 경우이다.

발악 데미지 상황에서의 동작

럴커가 데미지를 받아 사망하면, 게임 내에서 모종의 처리가 이루어질 것이다. id=25인 럴커는 사망하였기 때문에 더 이상 게임 내에서 유효한 유닛이 아니게 될 것이고, 럴커의 정보를 담은 객체는 소멸할 것이다. 각 가시를 구현한 객체가 럴커 객체에 의존하고 있다면, 그리고 해당 객체가 존재했던 메모리 공간이 초기화되거나 다른 객체가 덮어 쓸 경우 기존 럴커의 id를 참조하려고 메모리에 접근하지만 엉뚱한 값이 나오게 될 것이다. 럴커 사망 후 올라오는 가시들에 대해서는 발사한 럴커의 id가 25가 아닌 다른 값이 되어서 2회 피격 판정을 받아 사망하는 경우라고 볼 수 있을 것이다.

관측으로 뇌피셜 검증하기

가시에 정통으로 피격된 마린은 살아남고, 가시 사이에 낀 마린들은 20*2의 데미지를 입어 죽는 모습이다.

매달린 포인터 (dangling pointer)

-- 차차 작성하기

가비지 콜렉터

메모리 할당기

lazy free / nullify

참고자료 및 출처

[Youtube #01]러커의 발악데미지 그 강함은 어디까지? by Bono

6개의 댓글

  • 개굴

    2021.08.13 18:23

    흑운장 영상에서 봤던 기억이 납니다

    • 대연.

      2021.08.16 01:04 신고

      비공개 글이라 생각했었는데 공개되어 있었군요...(•_•)

      저도 흑운장 영상에서 봤었습니다. 개발자 취준생으로써 보고 있으면 운장이형은 참 똑똑한 것 같아요.

  • 사로로

    2021.09.11 23:12

    스타크래프트 코드를 보니 발악뎀 원리는 다름과 같았습니다

    간단히 원리를 보자면

    ※무기 타입이 러커무기(109번)일때
    ※※무기를 쓴 유닛(cunit)이 존재할 때
    ※※※러커 피격된 유닛이 정보에 없을 때(있으면 넘어감)
    ※※※러커 피격된 정보 기록(공격한 유닛 포인터(cunit) 공격당한 유닛(cunit))
    ※※※무기 딜
    ※※그냥 무기딜


    이런식으로 되어 있어 러커가 죽을 때 쏜 가시는 원천 유닛의 포인터가 사라져 발악데미지가 터집니다

    심지어 러커 가시 범위도 하드코딩으로 되어 있어서 가시 주변 범위에서만 데미지를 줍니다

    • 대연.

      2021.09.12 19:16 신고

      감사합니다. 얼추 비슷하겐 맞췄네요. 소스코드를 확인하셨나요 아님 리버스 엔지니어링으로 확인하셨나요?

    • 대연.

      2021.09.12 19:16 신고

      덕분에 더 알차게 글 완성할 수 있을 것 같네요. 감사합니다.

    • 사로로

      2021.09.12 20:55

      https://github.com/OpenBW/openbw/blob/master/bwgame.h

      여기 참고하시면 될거 같습니다