BQ 점수 시스템 — 플레이어가 좌절하지 않는 하락 보호 설계
경쟁적인 게임을 해본 사람이라면 그 감정을 알 것이다. 몇 시간 동안 열심히 플레이해서 랭크를 올렸는데, 연속으로 세 판만 지면 그 진전이 순식간에 사라진다. 열두 판 이겨서 올린 점수가 세 판 지는 사이에 증발한다. 앱을 닫는다. 내일 다시 열 수도 있다. 아닐 수도 있다.
BrainFit — 6개 인지 영역에 걸친 32개 미니게임을 갖춘 두뇌 훈련 RPG — 을 만들면서, 점수 시스템이 전체 경험의 감정적 중심이 될 거라는 걸 알았다. 게임 자체도, 우주 테마 비주얼도, 가차 상점도 아닌, 점수가 핵심이다. 점수는 플레이어의 거울이기 때문이다. "나는 지금 나아지고 있는가, 퇴보하고 있는가" — 이 하나의 신호가 플레이어가 계속 할지 그만둘지를 결정한다.
나는 BQ(Brain Quotient)라는 점수 체계를 설계하는 데 몇 주를 투자했다. 비대칭 EMA 스무딩과 3단계 하락 보호를 사용해 성장은 빠르게 반영하고 하락은 완충하는 메커니즘이다. 이 글에서는 모든 설계 결정의 배경을, BrainFit의 실제 프로덕션 코드인 bq_calculator.dart와 함께 설명한다.
BQ란 무엇인가
BQ는 Brain Quotient의 약자다. BrainFit에서 플레이어에게 보여주는 실력 지표 — 프로필에 표시되고, 시간에 따라 추적하고, 친구와 비교하는 숫자다.
BQ는 6개 인지 영역으로 구성되며, 각 영역은 미니게임 카테고리에 대응한다:
| 영역 | 코드 | 게임 | |------|------|------| | 기억력 | WIS | 패턴매트릭스, 카드뒤집기, 얼굴기억, 소리순서, N-Back, 기억궁전 | | 집중력 | AGI | 색상스트룹, 스피드탭, 추적공, 이중과제, GoNoGo, 주의깜빡임 | | 논리력 | INT | 숫자사슬, 블록퍼즐, 밸런스, 패턴매칭, 매트릭스추론, 타워플래닝 | | 언어력 | CHA | 단어스크램블, 연상사슬, 빈칸채우기, 분류정렬, 언어유창성, 언어유추 | | 처리속도 | SPD | 별빛탐색, 유성정렬, 신호전환, 블랙홀회피 | | 공간인지 | SPA | 행성회전, 우주미로, 성운조립, 궤도예측 |
각 영역은 1~100 범위의 고유한 BQ 점수를 갖는다. 종합 BQ는 활성 영역 — 즉, 플레이어가 실제로 한 번이라도 플레이한 영역 — 의 평균이다. 중요한 점은, 플레이어가 기억력과 논리력 게임만 했다면, 종합 BQ는 그 두 영역의 평균이지, 플레이하지 않은 나머지 네 영역 때문에 0에 가깝게 끌려내려가지 않는다는 것이다.
실제 구현은 이렇다:
static int totalBq({
required int wis,
required int agi,
required int int_,
required int cha,
int spd = 0,
int spa = 0,
}) {
final values = [wis, agi, int_, cha, spd, spa];
final active = values.where((v) => v > 0).toList();
if (active.isEmpty) return 0;
return (active.reduce((a, b) => a + b) / active.length).round();
}
이 "활성 영역만" 설계는 의도적인 선택이다. BrainFit은 4개 핵심 영역(WIS, AGI, INT, CHA)으로 시작하고, 처리속도와 공간인지는 나중에 해금된다. 활성 영역 필터가 없다면, 새 영역 해금 시 종합 BQ가 예를 들어 65에서 약 43으로 급락할 것이다 — 새로운 콘텐츠를 탐험하는 것에 대한 벌칙인 셈이다. 끔찍한 인센티브 구조가 될 뻔했다.
Elo 기반 구조
BQ는 게임 점수로 직접 계산하지 않는다. 각 영역은 체스 랭킹에서 사용하는 것과 같은 수학적 프레임워크인 Elo 레이팅 시스템으로 플레이어의 실력을 추적한다. BQ 아래의 Elo 시스템은 이 글에서 자세히 다루므로, 여기서는 요약만 하겠다.
각 영역은 600~1800 범위의 독립적인 Elo 레이팅을 가지며, 초기값은 1000이다. 플레이어가 문제를 맞히거나 틀릴 때, Elo는 비대칭 K-factor를 적용한 표준 기대점수 공식으로 업데이트된다. K-factor는 이미 하락을 늦추도록 설계되어 있다: 오답의 K-factor는 정답의 절반이다 (초보 플레이어 기준 16 vs 32, 경험 있는 플레이어 기준 8 vs 16).
BQ는 이 Elo 범위를 1~100 스케일로 선형 매핑한 것이다:
static int eloToBq(double elo) {
final clamped = elo.clamp(EloService.minElo, EloService.maxElo);
return ((clamped - EloService.minElo) /
(EloService.maxElo - EloService.minElo) *
99 +
1)
.round()
.clamp(1, 100);
}
Elo 600은 BQ 1, Elo 1800은 BQ 100, Elo 1200(중간점)은 BQ 51로 매핑된다. 매핑은 의도적으로 선형이다 — 곡선도 없고, 임계값도 없다. Elo 시스템이 이미 실력 추정의 비선형적 역학을 처리하고 있으니까. BQ는 단지 사람이 이해하기 쉬운 스케일을 제공할 뿐이다.
그러면 Elo 레이팅을 바로 보여주면 안 되나? 두 가지 이유가 있다. 첫째, "1,247"이라는 숫자는 대부분의 플레이어에게 아무 의미가 없다. 둘째, 더 중요한 이유로, 원시 Elo는 게임 간 변동이 너무 크다. 한 판 못 했다고 1,247에서 1,231로 떨어질 수 있다. 16포인트 하락은 통계적으로는 무의미하지만, 실패처럼 느껴진다. 플레이어는 시스템이 의도하지 않은 의미를 숫자에서 읽어낸다. BQ는 Elo 위에 스무딩과 보호를 얹은 레이어 — 통계적 현실과 플레이어의 감정적 경험 사이의 완충재로 존재한다.
비대칭 스무딩의 이유: 손실 회피
BQ 설계의 핵심 심리학적 통찰은 대니얼 카너먼과 아모스 트버스키의 전망 이론에서 나온다. 그들의 연구는 손실이 동등한 이득보다 심리적으로 약 두 배 더 고통스럽다는 것을 입증했다. 10만 원을 잃는 것이 10만 원을 버는 것보다 약 두 배 더 아프다. 이 현상 — 손실 회피 — 은 행동경제학에서 가장 많이 재현된 발견 중 하나다.
두뇌 훈련 앱의 맥락에서, 손실 회피는 이런 의미를 갖는다: 3일에 걸쳐 BQ를 5점 올리고 한 번의 나쁜 세션에서 5점을 잃은 플레이어는 원점으로 돌아왔다고 느끼지 않는다. 뒤처졌다고 느낀다. 손실이 감정적 회계를 지배한다. 이런 일이 반복되면, 플레이어는 게임을 하는 것이 감정적으로 위험하다는 것을 학습하게 된다. 그 교훈에 대한 합리적 반응은 플레이를 멈추는 것이다.
이것이 BQ가 비대칭 지수 이동 평균(EMA) 스무딩을 사용하는 이유다. 핵심 아이디어는 간단하다: 플레이어의 실제 실력(Elo에서 도출된 원시 BQ)이 올라가면, 표시 BQ는 비교적 빠르게 따라간다. 내려가면, 표시 BQ는 느리게 따라간다.
구현은 이렇다:
/// 비대칭 EMA: 상승 α=0.4 (빠르게), 하락 α=0.15 (느리게).
/// 상승 시 최소 +1 보장.
static int smoothBq(int currentDisplayBq, int newRawBq) {
if (newRawBq == currentDisplayBq) return currentDisplayBq;
final alpha = newRawBq > currentDisplayBq ? 0.4 : 0.15;
final smoothed = alpha * newRawBq + (1 - alpha) * currentDisplayBq;
if (newRawBq > currentDisplayBq) {
return max(currentDisplayBq + 1, smoothed.round()).clamp(1, 100);
}
return smoothed.round().clamp(1, 100);
}
EMA 공식 자체는 표준적이다:
$$ \text = \alpha \times \text + (1 - \alpha) \times \text $$
비대칭성은 알파 값에 있다. 상승 시 알파는 0.4 — 표시 BQ가 매 업데이트마다 새 원시 값을 향해 40% 이동한다. 하락 시 알파는 0.15 — 15%만 이동한다. 즉, 상승 움직임이 하락보다 약 2.7배 빠르다.
왜 이 특정 알파 값인가?
상승에 대해 알파 = 0.4를 선택한 이유는, 성장이 반응적으로 느껴지길 원했기 때문이다. 플레이어가 열심히 노력해서 Elo가 오르고 있다면, 그것이 비교적 빨리 반영되어야 한다. 하지만 즉각적으로는 아니다 — 즉각적인 업데이트는 점수를 불안정하게 만든다. 알파 0.4는 실제 성과와 연결된 느낌을 주면서도 부드러운 상승을 제공한다. 표시 BQ 50인 플레이어가 원시 BQ 60을 달성하면, 표시 BQ의 변화는: 50 → 54 → 57.6 → 60. 세 번의 업데이트로 대부분의 차이를 좁힌다.
하락에 대해 알파 = 0.15를 선택한 이유는, 손실 회피의 역수를 근사하고 싶었기 때문이다. 손실이 두 배로 아프다면, 손실은 대략 절반의 속도로 발생해야 한다. 알파 0.15는 0.4의 정확히 절반은 아니지만, EMA가 복리로 작용한다는 점을 감안했다: 하락의 유효 반감기는 약 4.3회 업데이트 대 상승의 1.4회 — 대략 3:1 비율로, 기저의 Elo 시스템에 있는 비대칭 K-factor와 일치한다.
미묘하지만 중요한 디테일이 하나 더 있다: 상승 시 최소 증가량은 +1이다. max(currentDisplayBq + 1, smoothed.round()) 라인이다. 이 하한 없이는, 원시 BQ가 50에서 51로 올랐을 때 스무딩 값이 50.4가 되어 반올림하면 다시 50이 된다. 플레이어는 실력이 올랐지만 변화를 보지 못한다. 의욕을 꺾는 결과다. +1 최소값 보장이 실제 향상이 항상 눈에 보이도록 한다.
3단계 하락 보호
비대칭 스무딩은 일반적인 경우를 잘 처리한다: 평범한 세션에서의 점진적 하락은 완화되고, 향상은 명확히 반영된다. 하지만 스무딩만으로는 충분하지 않은 엣지 케이스가 있다. 끔찍한 날을 보내는 플레이어, 실수로 자기 수준보다 훨씬 어려운 게임을 플레이한 아이, 오랜 휴식 후 복귀하여 일시적으로 실력이 떨어진 사람 — 이런 시나리오는 어떤 스무딩으로도 완전히 흡수할 수 없는 급격하고 깊은 하락을 만들어낸다.
이런 경우를 위해 BqProtection 클래스에 3단계 하락 보호를 구축했다. 각 단계는 다른 실패 모드를 다룬다.
1단계: 연패 감쇠
/// 연패 감쇠 임계값.
static const int loseStreakThreshold = 3;
// applyProtection() 내부:
// 1. 연패: 3연패 이후 하락 -1 고정
if (consecutiveLosses >= loseStreakThreshold) {
protected = max(protected, currentBq - 1);
}
3연패 이후에는 게임당 BQ 하락이 최대 -1로 제한된다. 이것은 좌절 나선을 다룬다: 플레이어가 분명히 고전하고 있을 때, 추가적인 처벌은 도움이 되지 않는다. 아마 이미 멘탈이 흔들리고 있을 것이다. 출혈을 게임당 -1로 제한하면 자유낙하를 방지하고, 한 판만 잘 해도 회복이 시작될 수 있다.
왜 3연패인가? 1~2연패는 정상적인 분산이기 때문이다. 3연패는 무언가 체계적으로 잘못되었다는 신호다 — 난이도가 너무 높거나, 플레이어가 산만하거나, 컨디션이 안 좋은 날이거나. 그 시점에서 우선순위는 정확한 실력 추적에서 감정적 안전으로 전환된다.
왜 0이 아니라 -1인가? 연패 중 점수를 완전히 동결하면 플레이어와의 신뢰 계약이 깨지기 때문이다. BQ는 여전히 의미가 있어야 한다. 계속 지는데 BQ가 전혀 변하지 않으면, 숫자가 가짜처럼 느껴진다. 게임당 -1 하락은 좌절을 피할 만큼 작으면서도 신뢰성을 유지할 만큼 크다.
2단계: 일일 하한
/// 일일 최대 하락폭.
static const int dailyFloorDrop = 5;
// 3. 일일 하한: 오늘 시작 BQ - 5
final dailyFloor = (todayStartBq - dailyFloorDrop).clamp(1, 100);
하루 동안 무슨 일이 있어도, 플레이어의 BQ는 그날 시작 시점보다 5점 이상 떨어질 수 없다. BQ 72로 하루를 시작했다면, 그날 도달할 수 있는 최저치는 67이다.
이 단계는 폭식적 패배 시나리오를 보호한다. 일부 플레이어는 지기 시작하면 "만회하려고" 더 많은 게임을 한다 — 도박꾼에게 영향을 미치는 것과 같은 심리적 함정이다. 일일 하한 없이는 이런 플레이어가 한 번의 좌절된 세션에서 깊은 구렁텅이를 팔 수 있다. 일일 하한은 이렇게 말한다: "나쁜 날을 보낼 수 있다. 피해는 제한되어 있다. 내일 새롭게 돌아오라."
5점은 활발한 플레이어의 약 일주일 치 전형적인 성장에 해당한다. 하루에 일주일의 진전을 잃는 것은 아프지만, 회복 가능하다. 하루 안에서 점수가 의미를 가질 만큼 크면서도, 한 세션이 재앙이 되지 않을 만큼 작다.
3단계: 역대 하한
/// 역대 최고 BQ 대비 바닥 비율.
static const double historyFloorRatio = 0.8;
// 2. 역대 최고 BQ의 80% 바닥
final historyFloor =
(allTimeHighBq * historyFloorRatio).round().clamp(1, 100);
플레이어의 BQ는 역대 최고 기록의 80% 아래로 절대 떨어질 수 없다. BQ 90에 도달한 적이 있다면, 아무리 많은 나쁜 게임을 하든, 며칠이 지나든, BQ는 72(90 * 0.8 = 72) 아래로 내려가지 않는다.
이것은 최후의 보루 — 진전의 재앙적 상실을 방지하는 절대적 하한이다. 주로 복귀 플레이어를 위해 존재한다. 3개월간 매일 BrainFit을 플레이하여 BQ 85에 도달하고, 6개월 쉬었다가, 실력이 일시적으로 떨어진 상태로 돌아온 사람은 BQ가 30으로 급락하는 것을 보면 안 된다. 그들의 역사적 성취는 영구적인 인정을 받을 자격이 있다. 80% 하한은 이렇게 말한다: "한때 이 정도 할 수 있다는 것을 증명했다. 우리는 점수가 그렇지 않다고 시사하는 것을 절대 허용하지 않겠다."
왜 80%인가? 여러 임계값을 테스트했다. 90%에서는 하한이 너무 일찍 작동하여 점수가 끈적하게 느껴진다 — 플레이어가 진짜 하락하는 건지 인위적으로 받쳐주는 건지 구분하기 어렵다. 70%에서는 하한이 거의 작동하지 않아 복귀 플레이어에게 충분한 보호를 제공하지 못한다. 80%가 적정선이다: 의미 있는 단기적 변동은 허용하면서도, 과거의 노력이 헛되었다고 느끼게 만드는 깊고 의욕을 꺾는 하락은 방지한다.
세 단계가 결합되는 방식
세 보호 단계는 서로를 대체하지 않는다 — 모두 동시에 적용되며, 가장 높은 하한이 승리한다:
static int applyProtection({
required int newBq,
required int currentBq,
required int todayStartBq,
required int allTimeHighBq,
required int consecutiveLosses,
}) {
// 상승이면 보호 불필요
if (newBq >= currentBq) return newBq.clamp(1, 100);
var protected = newBq;
// 1. 연패: 3연패 이후 하락 -1 고정
if (consecutiveLosses >= loseStreakThreshold) {
protected = max(protected, currentBq - 1);
}
// 2. 역대 최고 BQ의 80% 바닥
final historyFloor =
(allTimeHighBq * historyFloorRatio).round().clamp(1, 100);
// 3. 일일 하한: 오늘 시작 BQ - 5
final dailyFloor = (todayStartBq - dailyFloorDrop).clamp(1, 100);
// 모든 바닥 중 가장 높은 값 적용
return max(protected, max(historyFloor, dailyFloor)).clamp(1, 100);
}
첫 줄에 주목하자: 새 BQ가 현재 BQ 이상이면, 보호는 완전히 우회된다. 보호는 하락 시에만 활성화된다. 보호가 향상을 방해하는 것은 절대 허용하지 않는다는 점이 중요하다.
구체적인 예를 들어보자. 어떤 플레이어의 상태가 이렇다:
- 현재 BQ: 75
- 오늘 시작 BQ: 78
- 역대 최고 BQ: 85
- 연속 패배: 5 (연패 중)
패배 후 원시 BQ 계산이 69를 산출했다. 각 단계가 하는 일:
- 연패 감쇠: 연속 패배 5회가 임계값 3을 초과하므로, 하락이 -1로 제한된다. 보호 값: max(69, 75 - 1) = 74.
- 일일 하한: 78 - 5 = 73. 오늘 BQ는 73 아래로 내려갈 수 없다.
- 역대 하한: 85 * 0.8 = 68. BQ는 절대 68 아래로 내려갈 수 없다.
가장 높은 하한은 74(연패 감쇠에서)이므로, 플레이어의 BQ는 74가 된다. 보호 없이는 69였을 것이다 — 이미 좌절스러운 연패 중에 6점 하락은 가혹하다. 보호가 있으면, 손실을 인정하되 의욕을 꺾지 않는 1점 하락이다.
레거시 마이그레이션
BrainFit이 처음부터 Elo 기반 BQ 시스템을 사용한 것은 아니다. 원래 버전은 0~999 범위의 BQ 값을 사용하는 더 단순한 점수 체계였다. Elo 기반으로 점수 시스템을 재구축할 때, 기존 플레이어를 소외시키지 않는 마이그레이션 경로가 필요했다.
마이그레이션은 구 0~999 범위를 Elo 범위인 600~1800에 선형으로 매핑한다:
/// 기존 BQ (0-999) → Elo 마이그레이션.
static double migrateToElo(int oldBq) => EloService.migrateOldBq(oldBq);
// EloService 내부:
static double migrateOldBq(int oldBq) {
assert(oldBq >= 0 && oldBq <= 999, 'oldBq must be in range 0-999');
return _minElo + (oldBq / 999) * (_maxElo - _minElo);
}
구 BQ 0은 Elo 600(새 시스템에서 BQ 1)으로, 구 BQ 999는 Elo 1800(BQ 100)으로, 구 BQ 500은 Elo 1200(BQ 51)으로 매핑된다. 선형성이 상대적 순위를 보존한다: 플레이어 A의 구 BQ가 플레이어 B보다 높았다면, 새 BQ도 A가 더 높다.
이것이 소셜 기능에서 중요하다. BrainFit에는 은하(길드), 친구 랭킹, PvP 챌린지가 있다. 상대적 순서를 뒤섞는 마이그레이션은 모든 리더보드에 혼란을 초래했을 것이다.
행성 진화: 점수를 시각적으로
가장 만족스러운 설계 결정 중 하나는 BQ를 눈에 보이는, 진화하는 행성과 연결한 것이다. BrainFit의 우주 테마에서, 각 플레이어는 BQ가 향상됨에 따라 5단계로 진화하는 행성을 가진다:
| 단계 | 이름 | Elo 범위 | 대략적 BQ | |------|------|----------|----------| | 1 | 스타더스트 | < 800 | 1-17 | | 2 | 소행성 | 800-999 | 17-34 | | 3 | 행성 | 1000-1199 | 34-51 | | 4 | 항성계 | 1200-1499 | 51-75 | | 5 | 은하 | 1500+ | 75-100 |
행성 진화 단계는 BQ가 아니라 Elo 레이팅 임계값에 연결되어 있다. 즉, BQ의 하락 보호가 진화 단계를 인위적으로 부풀리지 않는다 — 플레이어의 실제 Elo가 임계값 아래로 떨어지면, 행성은 퇴화할 수 있다. 하지만 Elo 시스템 자체에 비대칭 K-factor가 있으므로 (패배 시 Elo 변화가 승리의 절반), 기저 레이팅 시스템도 하락에 더 관대하다.
이것은 좋은 심리적 역학을 만든다. 프로필의 BQ 숫자는 강하게 보호된다 — 빠르게 떨어지는 일이 드물고, 재앙적으로 떨어지는 일은 절대 없다. 하지만 행성 비주얼은 플레이어의 현재 실력 궤적에 대해 더 솔직한 신호를 제공한다. 진짜로 하락하고 있는 플레이어는 결국 행성 단계가 내려가는 것을 보게 되며, 이는 빠르게 떨어지는 숫자의 날카로운 고통 없이 연습을 더 하라는 부드러운 넛지가 된다.
전체 파이프라인
게임 결과에서 표시 BQ까지의 전체 여정을 추적해보겠다. 모든 조각이 어떻게 맞물리는지 보면 설계 철학이 드러나기 때문이다:
- 게임 종료. 플레이어가 15문제 정답, 5문제 오답, 평균 레벨 12.
- Elo 업데이트.
EloService.updateEloForGame()이 비대칭 K-factor로 각 답을 순차 처리. WIS Elo가 1,150에서 1,167로 이동. - 원시 BQ 계산.
BqCalculator.eloToBq(1167)이 원시 BQ 48로 매핑. - 스무딩 적용. 현재 표시 WIS BQ가 45라면,
smoothBq(45, 48)이 알파 = 0.4(상승)를 사용하여 46을 산출 (+1 최소 보장 적용). - 보호 확인. 새 BQ(46)가 현재(45)보다 높으므로,
BqProtection.applyProtection()은 그대로 반환 — 보호는 하락 시에만 활성화. - 종합 BQ 재계산.
totalBq()가 모든 활성 영역 BQ를 평균. - 플레이어가 프로필에서 업데이트된 BQ를 확인. 임계값을 넘었다면 행성이 레벨업 애니메이션과 함께 빛난다.
동일한 파이프라인의 패배 버전:
- 게임 종료. 정답 5, 오답 15, 평균 레벨 12.
- Elo 업데이트. 비대칭 K(패배 시 절반)로, WIS Elo가 1,150에서 1,135로 — 15만 하락하며, 동등한 승리의 잠재적 상승 30의 절반이다.
- 원시 BQ 계산.
eloToBq(1135)= 46. - 스무딩 적용. 현재 표시 WIS BQ가 48.
smoothBq(48, 46)이 알파 = 0.15(하락)를 사용: 0.15 * 46 + 0.85 * 48 = 47.7, 반올림하면 48. 표시 BQ가 전혀 변하지 않는다. - 보호 확인. 48 >= 48이므로, 보호가 활성화되지 않는다.
시스템이 의도한 대로 작동하는 것이다. 적당한 성장 기반 대비 한 번의 나쁜 게임은 눈에 보이는 변화를 만들지 않는다. 플레이어의 실제 실력 추정치(Elo)는 적절히 조정되었지만, 플레이어에게 보이는 점수가 변동을 흡수했다. 표시 BQ가 눈에 띄게 하락하려면 지속적인 저조한 성과 — 여러 게임, 여러 세션에 걸친 — 가 필요하다. 그리고 그때에도 3단계 보호가 하락의 범위를 보장한다.
설계 원칙
BQ 시스템을 돌아보면, 모든 결정을 이끈 세 가지 원칙이 보인다:
표시 점수는 측정 도구가 아니라 커뮤니케이션 도구다. Elo가 측정이다. BQ가 커뮤니케이션이다. Elo는 통계적으로 정확해야 한다. BQ는 감정적으로 정확해야 한다. 이것은 다른 목표이며, 다른 특성을 요구한다. Elo는 보정을 유지하기 위해 빠르고 대칭적으로 업데이트해야 한다. BQ는 동기를 유지하기 위해 비대칭적으로, 보호와 함께 업데이트해야 한다.
좌절은 복리이고, 격려는 아니다. BQ 3점을 얻고 3점을 잃은 플레이어는 중립으로 느끼지 않는다 — 뒤처진 것처럼 느낀다. 3점을 얻고 유지한 플레이어는 약간 기분이 좋다. 감정적 영향의 이 비대칭성이 점수 메커니즘의 비대칭성을 정당화한다. 플레이어의 실력에 대해 거짓말하는 것이 아니다 — 기저의 Elo는 정직하다. 향상은 빠르게, 하락은 점진적으로 전달하는 것을 선택한 것이다.
안전망은 보이지 않아야 한다. 대부분의 플레이어는 보호 레이어를 의식적으로 인지하지 못할 것이다. 그들은 단순히 BQ가 "안정적이면서도 반응적"이라고 느낄 것이다 — 잘 하면 올라가고 못 하면 대충 그대로 있다. 극단적인 경우(5연패, 대규모 일일 하락)에만 안전망이 눈에 띄게 작동한다. 그때에도 플레이어는 메커니즘을 보지 않는다 — 자유낙하를 거부하는 점수만 볼 뿐이다. 그것이 목표다: 보호는 인위적이 아니라 자연스럽게 느껴져야 한다.
다르게 했을 부분
시스템이 완벽하지는 않다. 아직 고민 중인 트레이드오프 하나는 일일 하한 -5다. 하루에 20판 이상 플레이하는 매우 활발한 플레이어에게, 5점 일일 하한은 너무 관대할 수 있다 — 아무리 못해도 점수가 거의 내려갈 수 없다는 뜻이니까. 그날 플레이한 게임 수에 비례하여 일일 하한을 조정하는 것을 고려했지만, 추가된 복잡성이 아직은 그만한 가치가 있어 보이지 않는다.
또 다른 고려사항은 역대 하한 80%가 "소프트 시링" 효과를 만들 수 있다는 것이다. BQ 100에 도달한 플레이어는 절대 80 아래로 떨어질 수 없으므로, 앱을 사용하는 나머지 기간 동안 BQ 점수의 동적 범위가 줄어든다. BQ 100 도달에는 Elo가 1800에 가까워야 하므로 — 가장 숙련되고 헌신적인 플레이어만 거기에 도달한다 — 실제로는 문제가 되지 않았지만, 모니터링하고 있다.
자체 앱의 점수 시스템을 설계한다면, 핵심 시사점은 이것이다: 측정과 표시를 분리하라. 내부에서는 실력을 정확하게 추적하라. 그 다음, 그 실력을 플레이어에게 어떻게 보여줄지에 진지한 고민을 투자하라. 결국, 점수 시스템은 실력을 측정하는 것이 아니다. 플레이어가 계속 플레이하고 싶게 만드는 것이다.