Salmonholic 생존 모드를 붙인 하루: 20시드 자동 주행으로 중앙값 11분 52초에 맞추기
10인 배틀로얄 게임에 혼자 15분 버티는 생존 모드를 붙였다. 기존 캐릭터·무기를 그대로 쓰고, 자동 주행 20판의 생존 시간 중앙값을 목표 8~12분 안으로 넣은 과정과 공개 순서를 정리했다.

Salmonholic은 고양이 10마리가 연어 떼를 잡으며 마지막 한 마리를 가리는 배틀로얄이다. 9월 28일 하루 동안 여기에 두 번째 모드를 붙였다. 혼자 들어가서 점점 거세지는 연어 떼를 15분 동안 버티는 생존 모드다. 그날 올린 버전은 세 개였다. 0.22.1(커밋 20b93dc)에 기능 플래그 뒤로 숨겨서 넣었고, 0.23.0(338f8a3)에서 공개했고, 0.24.0(6401c6c)에서 결과 화면 진입과 기본 모드 실험을 더했다. 이 글은 그 순서와 난이도를 맞춘 숫자의 기록이다.
새로 만든 것은 파일 하나였다
처음부터 정한 원칙은 “있는 것을 다시 쓴다”였다. 캐릭터 16종, 무기 24종, 진화, 레벨업 카드, 초밥, 외형, 미션과 업적까지 배틀로얄의 것을 그대로 쓴다. 적도 새로 그리지 않았다. 거대 연어는 기존 큰 연어를 두 배 크기로 그린 것이다. 대신 생존 경로에서는 로비, 방 서버, 다른 고양이와의 대전, 줄어드는 구역을 전부 쓰지 않는다. 로컬 플레이어 한 명만 살아 있고 네트워크 요청도 나가지 않는다.
모드의 시간·파도·보상 규칙은 survival_mode.gd 한 파일에 모았다. 배틀로얄 경로에서는 이 파일을 아예 호출하지 않는다. 그래서 기존 모드의 결정론 검사(같은 시드면 같은 결과가 나오는지 보는 골든 테스트)는 세 버전 모두 기존 기준 파일과 그대로 일치했다. 골든 파일은 한 번도 고치지 않았다.
규칙은 이렇다.
| 항목 | 값 |
|---|---|
| 목표 | 15분 생존, 성공하면 보상을 받고 끝내거나 무한으로 계속 |
| 시작 | 연어 14마리를 주위에 둥글게 배치 |
| 일반 연어 체력 | 시간과 상관없이 1(첫 타격에 쓰러짐) |
| 정예 무리 | 150초마다 |
| 거대 연어 | 300초마다(5·10·15분) |
| 보상 | 버틴 시간에 비례, 랭크는 바뀌지 않음 |
적이 강해지는 방식은 체력이 아니라 숫자와 속도다. 출현량과 이동 속도가 분 단위로 오른다.
var minutes: float = g.t_match / 60.0
g.mon_spd_mult = minf(3.6, 0.60 + minutes * 0.16)
g.spawn_acc += dt * minf(180.0, 3.0 + minutes * 8.0
+ pow(maxf(0.0, minutes - 4.0), 2.0) * 2.0)
속도는 0.6배에서 시작해 1분에 0.16씩 오르고, 출현량은 4분이 지나면 제곱으로 가팔라진다. 첫 10초 검사에서 레벨 4까지 오르고 연어 31마리를 잡았다. 시작하자마자 무언가를 잡고 크는 느낌은 CrazyGames 반려 뒤 첫 90초를 고친 글에서 가장 신경 쓴 부분이라 여기서도 그대로 지켰다.
왼쪽은 시작 12초(레벨 4, 무기 4칸), 오른쪽은 같은 모드 7분 6초(레벨 56, 무기와 패시브 10칸). 둘 다 QA 검토용으로 녹화한 영상의 한 장면이다.
목표는 “중앙값 8~12분”
15분짜리 모드라고 해서 대부분이 15분을 버티면 안 된다고 봤다. 너무 쉬우면 끝까지 가는 긴장이 없고, 너무 어려우면 초반에 튕겨 나간다. 그래서 기준을 두 개로 정했다. 자동으로 조작하는 고양이를 20개 시드로 돌렸을 때 생존 시간 중앙값이 8~12분 사이일 것, 그리고 첫 60초 안에 죽는 판이 0일 것.
자동 주행은 시드 스윕과 골든 게이트 글에서 쓰던 도구를 그대로 이었다. 다만 7분 시점 화면을 녹화로 확인하려면 7분을 실제로 기다려야 하는 문제가 있었다. 그래서 워밍업 옵션을 만들었다. 렌더와 소리 없이 같은 60Hz 게임 로직만 먼저 돌리는 방식이다. 첫 검증에서 게임 시간 420초까지 3.7초가 걸렸고, 레벨 55와 진화 6개에 도달해 있었다. 워밍업을 쓴 실행과 처음부터 돌린 실행의 시간 외 지표가 전부 일치하는 것도 확인했다.
세 번 돌린 스윕
각 점이 시드 한 판이다. 초록 띠가 목표 구간이고 흰 선이 중앙값이다.
| 회차 | 판 수 | 중앙값 | 최소 | 15분 완주 | 첫 60초 사망 |
|---|---|---|---|---|---|
| 조정 전 | 8 | 14분 2초 | 10분 4초 | 2 | 0 |
| 중간 조정 | 20 | 12분 55초 | 9분 19초 | 2 | 0 |
| 최종 | 20 | 11분 52초 | 9분 29초 | 1 | 0 |
조정 전 8판은 절반이 14분을 넘겼다. 8판 중 2판은 15분을 채웠다. 한 번 조정한 뒤 시드를 20개로 늘린 판도 중앙값이 12분 55초라 목표를 못 넘었다. 이 결과는 QA 기록에 “목표 미통과”로 따로 남겨 두었다. 마지막 20판에서 중앙값 712.2초, 11분 52초로 목표 안에 들어왔다. 가장 짧은 판은 569초, 15분 완주는 20판 중 1판이었다. 끝날 때 진화는 5~6개, 동시에 떠 있던 연어는 최대 303마리로 상한 800 안이었다.
성능도 10분 지점에서 따로 쟀다. 시드 6을 600초까지 워밍업하고 30초를 측정했더니 프레임당 시뮬레이션 처리 시간은 평균 0.43ms, 99번째 백분위가 0.58ms였다. 헤드리스 CPU 측정이라 브라우저의 실제 프레임 속도는 아니다. 그래서 보고서에도 “GPU 렌더 시간이 아니다”라고 적었다.
공개는 세 단계로 나눴다
0.22.1에서는 코드만 넣고 주소에 플래그를 붙여야만 생존 모드가 보이게 했다. 개발자 승인 전까지는 기본 흐름을 건드리지 않는다는 조건이었다.
0.23.0에서 기본으로 켰다. 여기서 가장 조심한 것은 배틀로얄의 빠른 진입이었다. 이 게임은 다운로드하는 동안 미리 매칭 자리를 잡아 두고, 로딩이 끝나면 바로 경기로 들어간다. 생존 모드가 이 흐름을 방해하면 안 됐다. 그래서 타이틀의 큰 버튼은 늘 배틀로얄이고, 생존 버튼은 옆의 작은 버튼에 “NEW” 배지를 달았다. 처음 들어올 때의 자동 진입과 친구 초대 링크는 저장된 선호와 상관없이 배틀로얄로 간다. 생존을 고르는 순간 잡아 둔 매칭 자리를 취소한다. 이 취소는 대기 중, 예약 완료, 응답 지연의 세 경우를 나눠 10번 검사해 모두 통과했다.
0.24.0에서는 결과 화면에 생존 버튼을 넣었다. 5위 이하로 끝났거나, 90초 안에 탈락했거나, 첫 1~3판인 사람에게는 버튼을 더 크게 보여 준다. 반대로 생존 결과 화면에서는 멀티플레이 대전으로 돌아가는 버튼을 둔다. 같이 기본 모드 실험도 켰다. 처음 설치한 프로필만 익명 식별자로 반반 나누고, 한쪽은 지금처럼 배틀로얄로, 다른 쪽은 첫 실행을 생존 모드로 시작한다. 테스트 식별자 1만 개로 돌렸을 때 5,002 대 4,998로 나뉘었다. 이미 경기 기록이 있는 사람은 실험에 넣지 않는다.
아직 모르는 것
실험 결과는 아직 없다. 어느 쪽이 1분 넘게 플레이하는 비율이 높은지, 다시 돌아오는 비율이 어떤지는 집계가 쌓여야 안다. 20시드 중앙값도 자동 조작 기준이다. 사람은 카드를 다르게 고르고 더 일찍 겁먹는다. 그래서 첫 60초 사망 0이라는 기준을 중앙값만큼 중요하게 봤다.
생존 모드에서 어떤 무기와 진화가 오래 버티는지는 레벨업 카드와 진화 조건 글을 참고하면 된다. 게임 소개와 바로 하기 링크는 Salmonholic 게임 페이지에 있다.


