본문 바로가기

블로그 / 개발일지

10인 방의 빈자리는 봇이 채운다 — 매치메이킹과 봇 지능 10단계

사람이 적은 신작 웹게임에서 10인 배틀로얄을 굴리기 위해 만든 입장 대기열, 빈자리 봇, 1~10등급 봇 지능, 첫 세 판 보호 규칙을 실제 측정값과 함께 정리했다.

Salmonholic ·· 5분 읽기

Salmonholic 경기 화면. 가운데 흰 고양이와 오른쪽 아래 미니맵에 다른 참가자 아홉 명이 색 점으로 보인다.

Salmonholic은 한 판에 열 명이 들어가는 배틀로얄이다. 문제는 출시 직후의 신작 웹게임에 동시에 열 명이 모일 일이 거의 없다는 점이다. 그래서 처음부터 “사람이 한 명이어도 판은 열 명으로 시작한다”를 원칙으로 잡았다. 빈자리는 봇이 채운다. 이 글은 그 봇과 매치메이킹을 며칠 동안 고친 기록이다.

로비는 짧게, 빈자리는 봇으로

서버 규칙 파일에는 인원 10, 로비 6.5초, 혼자일 때 로비 1.5초, 카운트다운 3초가 적혀 있다. 혼자 들어오면 1.5초 동안만 다른 사람을 기다렸다가 바로 카운트다운에 들어간다. 그 1.5초 안에 두 번째 사람이 들어오면 로비를 한 번만 6.5초로 늘린다. 0.15.2 커밋 메시지의 “solo lobby starts in ~4.5 s”가 이 계산(1.5초+3초)이다.

경기 중에 사람이 나가도 자리는 비지 않는다. 입력이 20초 없으면 그 자리를 봇 AI가 대신 움직이고, 연결이 끊긴 사람은 15초 안에 돌아오면 자기 고양이를 다시 잡는다. 결과 화면에는 봇에 “(봇)” 표시를 달아서 누가 사람이었는지 숨기지 않았다.

결과 화면. 10명 순위 중 몇 명에게 봇 표시가 붙어 있다 결과 화면에서는 봇 이름 옆에 (봇)을 붙인다. 순위표 절반 가까이가 봇인 판이 흔하다.

서버가 꽉 찼을 때의 입장 대기열

반대 상황도 대비해야 했다. 방 서버가 가득 차면 예전에는 그냥 거절했다. 9월 24일 0.11.3에서 입장 대기열을 넣었다. 요청이 몰리면 서버는 거절 대신 순번, 예상 대기 시간, 한 번만 쓸 수 있는 입장표를 돌려준다. 먼저 받은 표가 먼저 자리를 받는 FIFO이고, 한 로비에 10명까지 예약한 뒤 들어오지 않은 자리는 최대 30초 뒤 봇으로 채운다. 대기열 상한은 200명이다.

입장 대기 화면. 대기 순번과 예상 시간, 계속 기다리기와 다른 서버로 바로 플레이 버튼 로컬 서버로 재현한 대기 화면. 자체 웹에서는 20초, 게임 포털에서는 8초가 지나면 다른 서버로 가는 선택지가 켜진다.

포털 쪽을 8초로 짧게 잡은 건 포털 이용자가 기다리지 않고 다른 게임으로 넘어가기 때문이다. 대기가 300초 넘게 이어지면 서버 상태 응답에 경보 플래그가 켜지도록 했다. 이후 0.16.3(RL4)에서는 게임 파일을 내려받는 동안 셸이 먼저 로비 자리를 잡아 두고, 엔진이 준비되면 그 예약을 넘겨받게 바꿨다.

좌우로 떠는 봇 고치기

같은 0.11.3 작업에서 모바일로 직접 해 보다가 봇이 제자리에서 좌우로 떠는 걸 봤다. 원인은 서버 봇의 “파밍 목표” 선택이었다. 봇은 0.22초마다 12방향×2거리 후보의 몬스터 밀도를 다시 평가했는데, 비슷한 값끼리 동점이 나면서 매번 반대쪽 목표를 골랐다. 시드 16에서 목표가 초당 약 3.7번 바뀌고 있었다.

목표를 도착할 때까지 유지하고, 직전 진행 방향에 최대 10% 가산점을 주고, 목표 근처에서는 감속하도록 바꿨다. 측정 결과는 이렇다.

서버 시드 16 수정 전 수정 후
초당 방향 역전 2.809회 0.045회
초당 좌우 반전 2.641회 0.182회
1초 순변위 ÷ 이동 거리 30.5% 95.9%

봇 지능을 10등급으로 나누다

0.14.5(커밋 33eba88, RB3)에서 봇을 1~10등급으로 나눴다. 1등급이 예전 봇, 10등급이 가장 강한 봇이다. 등급별로 반응 시간이 1초에서 0.22초까지 줄고, 카드 선택 실수 확률이 10%에서 0%로 줄고, 전술 판단 비중이 0에서 1로 오른다. 하위 등급은 교전 중 당황하거나 카드에 과투자하고, 상위 등급은 마지막 두 명이 남았을 때 회복과 마무리를 구분한다.

지키려고 한 규칙은 공정성이다. 봇은 자기 중심 620×340 시야 안의 상대 체력과 위치만 읽는다. 화면 밖 상대는 플레이어도 보는 미니맵 수준인 32픽셀 칸으로만 안다. 봇 전용 체력·피해·속도·경험치 보너스는 없고, 봇이 몬스터를 잡는 양도 사람과 같은 제한을 받는다.

등급별 우승률 막대그래프. 13등급은 1.53%, 10등급은 31% 1~10등급을 한 명씩 섞은 서버 시뮬레이션 200판. 등급이 오를수록 평균 순위도 6.83위에서 3.00위로 좋아졌다.

솔직히 적자면 이 측정은 봇끼리의 강약 검증이다. 사람 대리로 쓴 테스트 봇이 단순한 대리보다도 약해서, “숙련자 승률 20~30%, 초보 10% 이하”라는 원래 목표를 이 자료로 확정하지는 못했다.

처음 세 판은 봐준다

등급을 나누고 나니 첫 판부터 10등급 봇을 만나는 사람이 생겼다. 0.15.0(RB4)에서 완료한 판이 3판 미만인 신입을 따로 대했다. 첫 판 봇 구성은 1~3등급만, 둘째·셋째 판은 최대 6등급이다. 처음 90초 동안은 봇이 신입을 공격 대상으로 고르지 않는다. 일반 로비는 [1,1,2,2,3,4,5,6,8]로 낮추고 다섯 판에 한 번만 10등급을 넣었다. 탈락하면 1.5초 뒤 바로 “한 판 더” 버튼이 뜬다.

실제 게임 코드 30시드 생존 중앙값 상위 3위 우승
변경 전(모든 판) 194.5초 56.67% 30.00%
변경 후 첫 판 209.97초 76.67% 53.33%
변경 후 일반 로비 207.3초 56.67% 20.00%

오프라인에서는 됐는데 온라인 신입 방은 여전히 짧게 끝났다. 서버 기준 첫 판 경기 중앙값이 144초 안팎이었다. 0.16.0(RB5)에서 원인을 찾았다. 저등급 봇은 상대가 사거리에 들어오면 원 중앙으로 달려가는데, 안전지대 여백 계산까지 겹쳐 좁은 공간에 몰려 서로 싸우다 판이 빨리 끝났다. 신입 방에서는 사냥 단계 전까지 보이는 상대와 거리를 벌리는 쪽으로 움직이게 했다. 두 서버 런타임에서 총 1,200판을 돌려 첫 판 중앙값이 143.87초에서 190.80초로 늘었고, 일반 방 결과는 한 자리도 바뀌지 않았다.

남은 숙제

봇은 사람의 빈자리를 채우는 장치지만, 결국 사람이 재미를 느껴야 한다. 같은 보고서에 적힌 최근 24시간 라이브 집계에서 한국 서버 8명 중 6명이 죽기 전에 나갔다. 표본이 너무 작아서 원인을 단정할 수는 없다. 이후 0.21.0에서 모바일 첫 30초와 결과 화면의 “다음 목표” 안내를 손본 것도 같은 고민에서 나왔다. 봇 수치를 어떻게 검증했는지는 밸런스 시뮬레이션 글에, 게임 소개는 Salmonholic 게임 페이지에 정리해 두었다.

#매치메이킹#봇AI#배틀로얄#게임밸런스#서버

함께 읽으면 좋은 글

전체 글 →