人生シミュレーションゲームは、たいていキャラクター作成から始まります。国を選んで、家族を選んで、ステータスを最適化する。
私はその逆がやりたかったんです。現実の人生は選べません。国も、家族も、身体も、「実際にその場所で生まれる赤ちゃんの数」に応じた確率で配られます。そこで、その"配布"そのものをゲームにしました:1 in 8 Billion(1in8b.dev)。ボタンを1つ押すと、実際の出生数に比例した確率で地球上のどこかに生まれます。あとはその国の統計のままに、1年ずつ人生を生きて、統計が「もう終わり」と言うまで続けます。
データ層の話
ゲーム全体が、172の国と地域の公開統計の上で動いています。
- 国連 World Population Prospects:生命表と出生数
- WHO / 世界銀行の指標:平均寿命、5歳未満死亡率、所得(一人当たりGDP・PPP)、都市化率、出生率
- 国別の死因分布:ラゴスで人が亡くなる理由と、大阪で亡くなる理由は違います
最後の死因分布が、思った以上に効きました。データセットの平均寿命は 54.5歳(ナイジェリア)から85.5歳(香港) まで開いています。31年の差が、出生地の旗だけでほぼ決まってしまう。この差を無視したシミュレーションはただのサイコロですが、使うと別物になります。プレイするたびに、「人生の結果のどれだけが、選択の前に配布で決まっているか」を少しだけ学ぶゲームになりました。
仕組みとしては、ゲーム内の1年ごとに、その国の生存曲線、死因プロファイル、そしてマイルストーン(進学、就職、移住、家族)の抽選を行います。マイルストーンの確率は国の統計に応じて変わるので、先進国の人生と途上国の人生は、終わる年齢が違うだけではなく、人生の"形"そのものが違います。
実装で面白かった2点
1. 9言語をランタイム切替ではなく静的ルートにした
各言語が独立したビルド済みページ(/ja/、/ko/、/fr/ …)で、それぞれ固有のタイトル、説明文、canonical URLを持ちます。アプリはパスから言語を判定します。重複のコストはかかりましたが、得たものは大きいです。各言語版が独立にインデックスされ、初回描画の時点でもう正しい言語になっています。
2. 国名こそ本当のi18n問題だった
UIの文言テーブルは簡単な部分です。でもこのゲームには、172すべての国の名前が全言語分必要で、地域名も要ります。当初データにあったのは中国語・英語・韓国語だけで、残り6言語ではフランス人やタイ人のプレイヤーに中国語の国名が表示されていました。
修正は、不足分を CLDR データ(Intl.DisplayNames)で補い、countryName() ヘルパー1つに集約すること。そして、文言テーブルを素通りしていた約250件のハードコードされた二言語文字列の監査でした。「9言語対応」を謳うアプリが実際に未対応なのは、たいていテーブル外のこのロングテールです。
遊んでみてください
無料、登録不要、ブラウザでそのまま動きます。
まずは生まれた国のままに1回生きてみて、次にもう1回抽選してみてください。「もう一人の自分」にいちばん考えさせられるのは、たいてい2回目です。
技術構成:バニラJSの静的サイト(フレームワークなし、バックエンドなし、アカウントなし)。データはすべてJSONで配信され、シミュレーションはブラウザ内で完結します。