모래게임 Sandrop 25
오늘 한 일
- 봇을 실수율 0퍼센트·10퍼센트·20퍼센트 세 단계로 돌려 레벨마다 난이도 프로필을 기록
- 상위 난이도에 실수 없는 봇 기준 상한을 걸어 “계획은 쉬운데 실수에만 가혹한” 판을 걸러냄
- 난이도를 축소판이 아니라 실제 판에서 재도록 통일
- 측정 반복을 8회에서 24회로 올림
- 얼음이 녹는 조건을 이웃 수로 고치고, 얼음끼리 붙지 않게 막음
- 안전망 경로가 기믹을 빠뜨리던 것을 고침
- 광고 SDK를 5.3.1에서 9.1.0으로 올리고 전면·보상형 닫기 버튼을 살림
- 전면 광고를 매 판으로, 실패 후 다시하기에도 붙임
- 500레벨 재생성
- 설정의 개인정보처리방침·이용약관을 로그스톤 샵의 이 앱 전용 페이지로 연결
- 레벨 선택에서 노드 한 줄 전체를 버튼으로
- 동생이 그려 준 케이크 도안 4종을 받아 확인
막힌 부분
최고 난이도인데 한 번에 깨졌다
500탄이 최고 난이도로 표시되는데 그냥 풀렸다. 측정 수치는 목표 안이었다.
한 숫자로 두 가지를 재려던 것이 문제였다. 지금 난이도는 “실수하는 봇이 몇 번에 한 번 깨는가”인데, 여기엔 계획이 어려워서 못 깨는 것과 한 번 삐끗하면 끝나서 못 깨는 것이 섞여 있다. 사람은 앞의 것만 어렵다고 느낀다.
실수율을 인자로 빼고 세 번 재서 레벨마다 남겼다.
g0 = _random_clear_rate(d, GREEDY_RUNS, level_id, mistake=0.0)
g10 = _random_clear_rate(d, plan.runs, level_id, mistake=0.10)
g20 = _random_clear_rate(d, plan.runs, level_id)
d["difficulty"] = {"profile": [round(g0, 2), round(g10, 2), round(g20, 2)]}
0퍼센트는 계획 난이도, 20퍼센트는 실수에 얼마나 가혹한가다. 500탄은 0퍼센트에서 절반이 깨졌다. 계획은 쉬운데 실수에만 가혹한 판이었다.
- 해결: 상위 난이도에 실수 없는 봇 기준 상한을 걸었다(어려움 0.90 / 매우 어려움 0.40 / 최고 0.25). 재생성 후 최고 난이도는 실수 없이 잘 두는 사람이 다섯 번에 한 번 성공하는 수준이 됐다
세 값이 앞뒤가 맞지 않았다
500탄 프로필이 실수 0퍼센트에서 0.50, 20퍼센트에서 0.62로 나왔다. 실수를 더 하는 쪽이 더 잘 깬다는 뜻이라 말이 안 된다.
원인은 잰 대상이 서로 달랐다는 것이다. 기존 난이도 수치는 속도 때문에 절반 해상도로 줄인 판에서 쟀는데, 새로 넣은 프로필은 실제 판에서 쟀다. 두 숫자를 나란히 놓고 비교하고 있었다.
이걸 고치면서 알게 된 게 더 컸다. 지금까지 표시되던 난이도가 전부 축소판 기준이었고, 축소판이 더 쉽게 나온다. 즉 그동안 화면에 뜨던 난이도가 실제보다 낮게 잡혀 있었다.
- 해결: 셋 다 실제 판에서 재도록 통일했다
당연히 실제 판으로 재는 줄 알았는데 축소판으로 재고 있어서, 앞으로 축소판 테스트는 금지로 못박았다.
역전이 47건이나 나왔다
실수를 더 많이 하는 봇이 더 잘 깨는 레벨이 47개였다. 진짜 그런 판이 있을 수는 있다. 함정이 있는 판이라면 정석대로 두는 쪽이 오히려 걸린다.
표본으로 8개만 골라 40회씩 다시 재보니 8개 중 6개가 다시 재면 사라졌다. 8회로는 값이 0.12와 0.35 사이에서 흔들렸다.
실수가 0이면 결정적일 거라고 생각했는데 틀렸다. 같은 점수인 수가 여럿일 때 무엇을 고르느냐가 갈림길마다 쌓여서, 실수가 없어도 결과가 크게 흔들린다.
- 해결: 측정 반복을 24회로 올렸다. 남은 역전 중 진짜는 한 자리 수였다
이웃이 남았는데 얼음이 풀렸다
옆에 아직 못 나간 바구니가 있는데 얼음이 녹았다. 얼음 강도에 상한 3이 걸려 있어서, 이웃이 넷이어도 셋만 나가면 조건을 채운 것으로 봤다.
b.iceStrength = neighbors < 1 ? 1 : neighbors;
- 해결: 상한을 없애 이웃 수를 그대로 강도로 썼다. 규칙 엔진이 파이썬에도 있어서 양쪽을 같이 고쳤다
얼음끼리 붙으면 영영 안 녹는다
위를 고치자 새 문제가 생겼다. 얼음 둘이 붙어 있으면 서로가 서로의 이웃인데 둘 다 못 나가므로 어느 쪽도 조건을 못 채운다. 424탄이 그래서 풀 수 없는 판이 됐다.
기믹을 많이 까는 후반에는 반드시 생긴다.
- 해결: 배치 단계에서 얼음끼리 이웃하지 않게 막았다
안전망이 이번엔 기믹을 빠뜨렸다
500탄은 물음표 바구니를 4분의 3으로 도배하게 설계돼 있는데 실제로는 하나도 없었다.
어제 벽이 안 깔리던 것과 같은 자리였다. 정상 경로가 실패하면 떨어지는 안전망이 있는데, 어제는 거기에 벽만 넘겨 주고 기믹 세 종류는 그대로 두고 있었다.
- 해결: 안전망도 정상 경로와 같은 인자를 받게 했다
- 어제 같은 자리를 고치면서 인자 넷 중 하나만 채운 셈이었다. 예외 경로를 고칠 때는 그 경로가 받는 것 전부를 훑어야 한다
광고에 닫기 버튼이 안 떴다
전면 광고에 X가 없어 광고를 못 닫았다. 로그에 자바스크립트 오류가 찍혀 있고 SDK가 네 개 메이저나 뒤처져 있길래 그것부터 올렸다. 안 고쳐졌다.
진짜 원인은 앱이 시스템 바를 숨기는 몰입 모드로 도는 것이었다. 광고가 안전영역을 0으로 보고 자기 UI를 화면 밖에 그린다. 타깃 API 35 이상에서 알려진 문제고 우리는 36이다.
증상과 해법이 광고 종류마다 달랐다.
- 전면은 닫기 X만 안 떴고, 광고에 몰입 모드를 알려 주는 것으로 해결됐다
- 보상형은 타이머·보상 안내·X가 통째로 안 그려졌고, 같은 방법이 안 먹혔다. 광고가 떠 있는 동안만 시스템 바를 되돌리고 닫히면 원래대로 돌리는 식으로 고쳤다
- 로그에서 눈에 띄는 오류를 원인으로 단정한 것이 오진이었다. SDK를 올린 건 그것대로 필요한 일이었지만 이 문제의 원인은 아니었다
케이크 색이 뭉갰다
동생이 일러스트레이터로 5색으로 그려 준 케이크 4종을 넣었더니 딸기가 갈색이 되고 생일초가 통째로 사라졌다.
원인을 세 번 잘못 짚었다. 색이 많아서라고 했는데 94색짜리 떡볶이는 멀쩡했다. 강조색 면적이 작아서라고 했는데 딸기는 전체의 7.6퍼센트로 작지 않았다. 32칸 격자로 그려서라고 했는데 잘 나온 기존 도안도 같은 패턴이었다.
파일을 직접 재보고서야 알았다. 5색으로 그렸다는데 파일에는 39~59색이 있었고, 여분 색이 전부 순색 두 개의 정확한 중간값이었다. 반투명 픽셀도 100개 넘게 있었다. 벡터를 PNG로 구울 때 경계를 부드럽게 깎는 옵션이 켜져 있던 것이다.
경계마다 낀 중간값까지 한 덩어리로 묶이니 평균이 갈색으로 나왔다.
- 해결: 그림은 손댈 필요가 없고 내보내기 설정에서 안티에일리어싱만 끄면 된다. 다시 받기로 했다
- 에러가 나지 않고 그냥 뭉갠 그림이 등록되므로, 눈으로 안 보면 모른다
안티에일리어싱 설정이 중요했다. 지금은 동생 preview에 설정이 안 되어 있어서 화면과 export가 살짝 다르게 보이는데, 앞으로 추가 도안 작업 때는 preview와 export 둘 다 안티에일리어싱을 적용하기로 했다.
그 밖
- 설정의 개인정보처리방침·이용약관이 “배포 전에 연결합니다” 안내로 남아 있었다
- 해결: 로그스톤 샵의 이 앱 전용 페이지로 연결했다. 앱마다 방침을 따로 두면 하나를 고칠 때 나머지가 조용히 어긋난다
- 한국어로 쓰는 중이면 국문 위치까지 붙여서 연다. 판정은 설정값이 아니라 실제 적용된 언어로 한다. 기기 언어를 따르는 설정이면 설정만 봐서는 어느 쪽인지 알 수 없다
- 레벨 선택에서 그림만 눌리고 옆의 번호·난이도는 안 눌렸다
- 해결: 노드 한 줄 전체를 하나의 버튼으로 만들었다. 그림과 라벨에 따로 걸면 겉보기엔 한 덩어리인데 사이 여백이 죽은 자리가 된다
다음에 할 일
- 케이크 도안 다시 받아 등록하고 500레벨 재생성
- 올린 난이도를 직접 확인 — 400탄대가 한 번에 안 깨지는지
- 스토어 등록물·Play Console (콘텐츠 등급·데이터 보안 양식·타겟층 설정) — 영어 등록정보도 필요
- 배포 전 디버그 모드 제거
- 레벨 동결 — 제출 전에 한다. 지금은 레벨을 다시 만들면 500개가 전부 새로 만들어져서 이미 깬 레벨의 그림까지 바뀐다