트랙
/
Lean
Lean
/
연습 문제
/
D&D 캐릭터
D&D 캐릭터

D&D 캐릭터

보통

소개

몇 주 동안이나 기다린 끝에, 친구들과 함께 첫 번째 Dungeons & Dragons (D&D) 게임을 하게 되었어요. 게임의 첫 세션이니만큼, 각 플레이어는 함께 플레이할 캐릭터를 하나씩 만들어야 해요. 캐릭터의 능력치는 6면체 주사위를 굴려서 정해져요. 그런데 그 주사위가 어디 있는 걸까요? 깜짝 놀라 보니, 친구들은 바로 _여러분_이 주사위를 가져오기를 기다리고 있었어요. 어쨌든 D&D를 하자고 한 건 여러분이니까요! 당황한 나머지 주사위를 가져오는 걸 깜빡했다는 걸 깨달아요. 그러면 D&D 게임은 못 하게 되는 셈이죠. 다행히 기본적인 코딩 실력이 있으니, 금방 해결책이 떠올라요. 주사위 굴리기를 시뮬레이션하는 프로그램을 작성하기로요.

지침

Dungeons & Dragons 게임에서는 각 플레이어가 먼저 함께 플레이할 캐릭터를 만들어요. 이 캐릭터에는 여러 가지 중에서도 여섯 가지 능력치가 있어요. 바로 근력, 민첩, 건강, 지능, 지혜, 매력이에요. 이 여섯 능력치의 점수는 무작위로 정해져요. 6면체 주사위 네 개를 굴린 뒤, 가장 큰 세 개의 합을 기록해서 정해요. 이 과정을 각 능력치마다 한 번씩, 총 여섯 번 반복해요.

캐릭터의 초기 생명점은 10 + 캐릭터의 건강 수정치예요. 건강 수정치는 캐릭터의 건강에서 10을 뺀 뒤 2로 나누고, 소수점을 버려서 구해요.

위 규칙을 따르는 무작위 캐릭터 생성기를 작성해요.

예를 들어, 주사위 네 개를 여섯 번 굴린 결과는 다음과 같을 수 있어요.

  • 5, 3, 1, 6: 1을 버리고 5 + 3 + 6 = 14를 더해서 근력에 배정해요.
  • 3, 2, 5, 3: 2를 버리고 3 + 5 + 3 = 11을 더해서 민첩에 배정해요.
  • 1, 1, 1, 1: 1을 버리고 1 + 1 + 1 = 3을 더해서 건강에 배정해요.
  • 2, 1, 6, 6: 1을 버리고 2 + 6 + 6 = 14를 더해서 지능에 배정해요.
  • 3, 5, 3, 4: 3을 버리고 5 + 3 + 4 = 12를 더해서 지혜에 배정해요.
  • 6, 6, 6, 6: 6을 버리고 6 + 6 + 6 = 18을 더해서 매력에 배정해요.

건강이 3이므로 건강 수정치는 -4이고, 생명점은 6이에요.

Note

대부분의 프로그래밍 언어에는 (의사)난수 생성기가 있지만, 주사위를 굴리도록 설계된 프로그래밍 언어는 거의 없어요. 그런 언어 중 하나가 Troll이에요.

Lean에서 의사 난수 값 생성하기

함수형 언어에서 대부분의 함수는 _순수_해요. 즉, 같은 인자 집합에 대해 항상 같은 출력을 반환하고, 그 외에는 아무것도 하지 않아요. 다시 말해, 순수 함수는 결정적이에요.

하지만 정의상 난수는 예측할 수 없고 비결정적이에요. 심지어 의사 난수성, 즉 무작위로 보이는 수열을 반환하는 것조차 순수한 맥락에서는 그리 쉽지 않아요. 의사 난수 생성기(PRNG)는 수열의 다음 수를 반환하기 위해 내부 상태를 계속 추적해야 하기 때문이에요.

Lean은 이 문제에 대해 두 가지 접근법을 제공해요:

  1. PRNG의 내부 상태를 바꿀 수 있게 해주는 모나드를 사용해요. 정확히 이 일을 하는 IO.rand라는 함수가 바로 있어요.

  2. 생성기를 인자로 받아, 생성된 의사 난수뿐만 아니라 수열의 다음 수를 위해 "준비된" 갱신된 생성기도 반환하는 순수 함수를 사용해요.

이 연습 문제는 두 번째 접근법을 사용해요. 의사 난수를 생성해야 하는 모든 함수에는 생성기가 전달되고, 그 함수는 값과 갱신된 생성기를 모두 반환해야 해요.

주어진 생성기는 결정적이라는 점에 유의해요. 즉, 항상 같은 값을 만들어요. 수열에서 다음 의사 난수를 생성하려면 갱신된 생성기를 사용해야 해요.

무작위성 검사하기

이 문제에서는 카이제곱 검정을 사용해 무작위성을 검사하는데, 유의 수준은 p < 0.0001이에요.

즉, 지침에 따라 능력치를 생성한다면, 올바른 구현이 우연히 테스트에 실패할 확률은 0.01% 미만이에요.

지침에 따르면 능력치는 _편향되지 않은 d6(6면 주사위)를 네 번 굴린 결과 중 가장 큰 세 개의 합_이라는 점에 유의해요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Lean Exercism

D&D 캐릭터 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Lean 트랙을 연습 문제 100개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.

D&D 캐릭터 깊이 살펴보기!

주사위 눈을 (겉보기에) 무작위로 만드는 방법을 살펴봐요. 시드, 의사 난수, 그리고 흔히 걸려들기 쉬운 함정에 대해 배워요. 마지막으로, 무작위 값을 반환하는 함수를 테스트할 때 속성 기반 테스트가 얼마나 유용한지 알아봐요.