Data Science!/프로젝트

[수학] 확률론 - 파이썬으로 짜는 부루마불 시뮬레이터 (난이도 : 중상)

양국남자 2021. 9. 15. 08:45

모든 수업은 파이썬 (Python 3 이상) 으로 진행됩니다. Pycharm 등 IDE 사용도 좋지만, Jupyter Notebook 이나 Google Colab 사용을 더욱 권장드립니다. Google Colab 에 있는 전체 컴필레이션은 확률편 마지막 강의에 올릴 예정입니다.

 

저도 게임 좋아했고, 이 글 읽으시는 분들도 IT에 관심 있고 게임과 완전 거리가 머실 분들은 아니시기 때문에 오늘은 게임 썰 한번 풀어봅시다. 

 

리그 오브 레전드나, 배틀그라운드, 둠 이터널, 워해머 3 이런 좀 복잡한 최신 게임 말고... 남녀노소라면 다 아실 부루마불이요!

 

확률론을 배웠으니까, 우리는 주사위를 n 번 던지면 다음에는 어느칸에 있을지 시뮬레이팅 하는 프로그램을 짜 볼 예정입니다

 

추억의 게임 부루마불입니다.

 

아시다시피 주사위는 등기 확률입니다. 어떤 나쁜사람이 주사위에 몹쓸 마개조를 하지 않는이상, 모든 면의 확률이 1/6 으로 같습니다. 하지만, 사실 주사위를 두개 던지기 때문에, 부루마불의 주사위 던지기는 비등기 확률을 따릅니다.

 

이건... 다른 의미에서 비등기 확률이고요.

잘 와닿지 않으신다면, 부루마불에서 주사위를 두개 던져서 2가 나오는 경우는 1+1 하나뿐이고, 1/36의 확률을 가지고 있습니다. 하지만 6 이 나오는 경우는 어떨까요? 1+5, 2+4, 3+3, 4+2, 5+1 해서 5개가 나옵니다. 부루마불을 할 때 나올 수 있는 모든 경우의 수는 다음과 같은 확률을 따릅니다.

 

이동 확률
2 1/36
3 2/36
4 3/36
5 4/36
6 5/36
7 6/36
8 5/36
9 4/36
10 3/36
11 2/36
12 1/36

주로 반 이상의 경우에 5,6,7,8 칸을 이동하게 된다는 거네요. 부루마불 보드의 배치도는 이 점을 염두에 두고 짜여진걸까요? 뭐 파이썬으로 코드 짜서 시뮬레이션 해보면 알 거 같네요.

 

이 배치에 숨겨진 의도가 있을까요?

일단, 파이썬 코드로 부루마불 게임을 만들어 봤습니다. 1강에서 트럼프 카드 나올때 나왔던 random 을 import 해주세요. 카드뽑기 등도 다 구현했습니다. 이 포스팅 따라오시는 분들이라면 다 확률에 대한 지식이 있으시기 때문에, 큰 어려움 없이 짜실 수 있다 생각합니다.

 

부루마불의 배치를 보면 시작점 앞에는 타이페이, 베이징, 싱가폴 등 비교적 '똥땅'이 배치되어있고, 반바퀴 돌아 시작점으로 갈수록 최종병기 서울을 비롯해 뉴욕, 도쿄, 로마 등 비교적 '꿀땅'들이 배치되어 있습니다. 이 배치에 기획 의도가 있는걸까요?

 

우주여행은 너무 변수가 많아서 과감히 제외했습니다. 다 서울 달리거나 꿀땅 살거면서...

 

#1강에서 random 을 import 하지 않았을 경우 해주세요.
import random

from collections import deque as Deck # 파이썬의 데크 모듈입니다. 스택처럼 쓸 수도, 큐처럼 쓸 수도 있어요.
#스택, 큐 관련 이야기는 나중에 하고, 이건 일단 모음을 만들기 위해 임포트한 모듈입니다.

# 부루마블 보드입니다
(시작,   타이페이, 황금열쇠1, 베이징,  마닐라, 제주도, 황금열쇠2,  싱가폴, 카이로, 이스탄불,
 무인도, 아테네, 황금열쇠3,  코펜하겐,  스톡홀름, 콩코드여객기, 베른,  황금열쇠4, 베를린, 오타와, 
 사회복지기금수령처,   부에노스아이레스, 황금열쇠5, 상파올루,  시드니, 부산, 하와이,  리스본,  퀸엘리자베스, 마드리드, 
 우주여행, 도쿄,  콜롬비아호, 파리,  로마, 황금열쇠6, 런던, 뉴욕, 사회복지기금접수처,  서울) = board = range(40)

# 황금열쇠. 제가 아는 선에서는 31개중 19개는 위치에 변함이 없고, 12개정도는 위치에 변함이 있습니다.
#제자리로 돌아오는건 위치 변함 없는거기 때문에 None 처리했습니다.
GK_deck = Deck([시작, 무인도, 타이페이, 베이징, 부산, 제주도, 서울, -3,-2, 사회복지기금접수처, 우주여행, 우주여행]+ 19 * [None])

def blue_marble(rolls):

    #부루마불 게임에서 주사위를 n 번 던진 결과를 시뮬레이팅 한 뒤에 모든 위치를 몇번 방문했는지 출력하는 함수
    counts = [0] * len(board)
    doubles = 0 # 
    random.shuffle(GK_deck)
    goto(시작)
    for _ in range(rolls):
        d1, d2 = random.randint(1, 6), random.randint(1, 6)
        doubles = (doubles + 1 if d1 == d2 else 0)
        goto(here + d1 + d2)
        if here in (황금열쇠1, 황금열쇠2, 황금열쇠3,황금열쇠4,황금열쇠5):
            do_card(GK_deck)
        counts[here] += 1
    return counts

def goto(square):
    #이동을 담당하는 코드입니다.
    global here
    here = square % len(board)        

def do_card(deck):
    #카드 뽑기입니다.
    card = deck.popleft()       # 맨 윗장
    deck.append(card)           # 맨 윗장 카드를 아래로
    if card == None:            # 움직임 없음
        pass
    elif card == -2:            # 2칸 뒤로
        goto(here - 2)
    elif card == -3:            # 3칸 뒤로
        goto(here - 3)
    else:                       # 카드에 적힌곳으로
        goto(card)

보드를 만들었고, 컴퓨터도 좋은 거 있으니 한 100만번은 돌려봅시다.

 

#주사위 백만번
counts = blue_marble(10**6)

 

이제 결과를 출력해줍시다.

 

#보드의 위치명들입니다.
property_names = """
 시작,   타이페이, 황금열쇠1, 베이징,  마닐라, 제주도, 황금열쇠2,  싱가폴, 카이로, 이스탄불,
 무인도, 아테네, 황금열쇠3,  코펜하겐,  스톡홀름, 콩코드여객기, 베른,  황금열쇠4, 베를린, 오타와, 
 사회복지기금수령처,   부에노스아이레스, 황금열쇠5, 상파올루,  시드니, 부산, 하와이,  리스본,  퀸엘리자베스, 마드리드, 
 우주여행, 도쿄,  콜롬비아호, 파리,  로마, 황금열쇠6, 런던, 뉴욕, 사회복지기금접수처,  서울""".replace(',', ' ').split()

#확률을 높은 순서대로 정리한 뒤에 출력해봅시다
for (c, n) in sorted(zip(counts, property_names), reverse=True):
    print('{:4} {:.2%}'.format(n, c / sum(counts)))

 

결과는 이렇게 나오네요. 여러분도 Google Colab 에 직접 짜보시거나, 아니면 최종 확률 컴필레이션을 신중히 기다려 주시길 바랍니다 ^^

 

 

여러분이 돌릴때는 또 다르게 나올 수 있어요.

 

우주여행과 무인도가 비슷한 확률로 나오고, 그 뒤를 베이징, 시작, 제주도, 타이페이 등 비교적 똥땅들과 함정인 사회복지기금 접수처가 잇고 있습니다. 그리고 최종 격전지인 서울이 꽤 상위권이고, 로마, 파리, 도쿄,뉴욕, 런던 등 꿀땅들은 좀 낮으며, 황금열쇠는 다 밑에 깔려 있네요. 운을 최소화 하려는 시도인가요?

 

이번 시뮬레이션만으로 판단하기는 이르지만, 꽤 부루마불의 배치 자체가 의도적이라는 생각이 들기는 하네요. 뭐 잘 만든 게임인거에는 이유가 다 있겠죠. 운에 맡기는 주사위 게임이지만 운요소를 많이 줄이려는 의도가 보이긴 합니다.