小分けにせず、まとめて1回で届ける
ふつうのWebゲームは、部品集(ライブラリ)・画像・音楽・データなどを、たくさんのファイルに分けて届けます。
80億分の1は、ゲーム本体を1つのファイル(4.7MB)にまとめて、最初に1回で届けます。届いたあとは、ほとんど通信せずに一生の最後まで遊べます。
あとから届くのは、文字の形のデータ(フォント)の小さなかけらだけです。くわしくは「文字」の章で説明します。
非公式の解説ページです。ゲーム「80億分の1」の作者とは関係ありません。ゲーム本体は 1in8b.life で遊べます。
「80億分の1」は、ブラウザで遊べる人生シミュレーションゲームです。今日生まれる赤ちゃんの一人になって、172か国の本物の統計の中で一生を送ります。このページでは、その中身を開けて、どんな技術で動いているのかを図と動きで説明します。プログラムの知識はいりません。
ふつうのWebゲームは、部品集(ライブラリ)・画像・音楽・データなどを、たくさんのファイルに分けて届けます。
80億分の1は、ゲーム本体を1つのファイル(4.7MB)にまとめて、最初に1回で届けます。届いたあとは、ほとんど通信せずに一生の最後まで遊べます。
あとから届くのは、文字の形のデータ(フォント)の小さなかけらだけです。くわしくは「文字」の章で説明します。
ファイルを開いて、何にどれだけ場所を使っているかを測りました。ゲームのルールと並んで大きいのが、日本語に置き換えるための辞書です。
作者は文章を韓国語で書いていて、韓国語の文字だけで約41万字あります。文庫本なら3〜4冊分の文章量です。
帯や項目を押すと説明が出ます。全体は4.67MBで、プログラムの中の名前をもとに分類した、おおよその内訳です。
韓国語の原文を日本語に置き換えるための辞書です。言語ごとに別のページがあり、それぞれに自分の言語の辞書が1冊ずつ入っています。
ゲームの場面は、横192×縦60ドットの小さな「画用紙」(キャンバスという機能)に描かれます。画像ファイルは使っていません。
「この位置にこの色の点」という命令を順番に実行して描き、最後に画面いっぱいまで拡大します。拡大するときににじませない設定にしているので、くっきりしたドット絵になります。
右の図で「ぼかして拡大」を押すと、この設定がないとどう見えるかを比べられます。
音楽ファイルもありません。ブラウザに最初から入っているシンセサイザー機能を使い、音の高さと長さをプログラムで決めて鳴らします。
曲を作るときは、人物の名前などをタネ(シード)にします。タネが同じなら、毎回まったく同じ曲になります。タネから決まった順番で数字を取り出す「合言葉つきのサイコロ」のような仕組みです。
右のデモで名前を変えると曲が変わり、同じ名前に戻すと同じ曲に戻ります。音が出るので音量に気をつけてください。
最初の「生まれる」ボタンを押すと、国ごとの1年の出生数に比例した確率で、生まれる国が決まります。
インドに生まれる確率は17.6%です。日本は0.57%で、およそ176人に1人です。
右のボタンで、ゲームと同じ割合の抽選を試せます。何回で日本が出るか数えてみてください。
国連・WHO・世界銀行の統計をもとにした数字が、ファイルの中に直接書き込まれています。データを取りに行く通信はありません。
病気や事故、進学、収入などの出来事が起きる確率は、生まれた国のこの数字で変わります。同じ日に生まれても、国によって一生の形が大きく変わるのはこのためです。
上の20項目は、ゲームのコードにある統計表の名前をそのまま使いました。下の10項目の名前は、コードでの使われ方から判断しました。平均寿命と喫煙率は男女別の値を持つので、元のデータは1か国あたり32項目です。
作者は、画面に出す文章を韓国語で書いています。その文章には「翻訳する」という目印がついていて、目印はプログラムの中に12,226か所あります。
日本語版では、文章を画面に出す直前に辞書を引いて、日本語に置き換えます。英語、繁体字中国語、ベトナム語、フランス語も同じ仕組みです。
言語ごとに専用のページ(/ja/、/en/ など)があり、それぞれのページに自分の言語の辞書だけが入っています。
生まれてから亡くなるまでの計算は、すべてあなたのスマホやパソコンの中で行われます。セーブデータも、ブラウザの中にある保存場所に入ります。
インターネットの向こう側(サーバー)を使うのは、みんなと共有する機能だけです。たとえば、亡くなった人生を残す「追悼」の掲示板、投稿への反応、匿名のプレイ統計、それに有料機能の支払いです。
サーバー側の受付窓口(API)は24種類ありました。配信とこの窓口は Cloudflare、支払いは Stripe が担当しています。
日本語の漢字や韓国語のハングルは種類がとても多く、文字の形のデータ(フォント)が大きくなります。
そこでフォントを568個のグループに分けておき、画面に出てくる文字が入ったグループだけを取りに行きます。調査でプレイを始めた時点で読み込まれていたのは55グループで、全体の約1割でした。
プログラムのいちばん最後に、window.claude.hot という名前を使う数行があります。これは、Claude が作ったページ(アーティファクト)を表示する画面のための仕組みです。
役割は「しおり」です。ページを作り直して新しい版に入れ替えるとき、遊んでいる途中の状態を挟んでおき、新しい版でもその続きから再開できるようにします。開発中に Claude へ修正を頼むたび、赤ちゃんからやり直さずに続きを確かめられたはずです。
公開中のサイトには window.claude がないので、この数行は何もせず、ゲームはふつうに始まります。Claude Code で作られたという話と一致しますが、どの Claude 製品を使ったかまではコードから決められません。
// 今の人生(S)と設定を「しおり」に挟む if (window.claude && window.claude.hot && window.claude.hot.snapshot) window.claude.hot.snapshot(() => ({ S, prefs: UI.prefs })); // しおりがあれば、そこからゲームを始める if (window.claude && window.claude.hot && window.claude.hot.ready) window.claude.hot.ready(start); else start(...);
このサイトは、自分のサイト以外から来たプログラムを動かさない設定(CSP)をしています。悪いプログラムが紛れ込んでも動かないようにするための鍵です。
調べている途中で、鍵が効きすぎている場面も見つかりました。
自分で調べたいときや、エンジニアと話すときのための対応表です。
| このページでの言い方 | 技術の名前 | ゲームでの使い道 |
|---|---|---|
| 全部を1つのファイルに | 単一HTML(JS・CSSを埋め込み) | ゲーム本体を1回で届ける |
| 部品集を使わない | Vanilla JavaScript(フレームワークなし) | React などを使わず、素の JavaScript で書く |
| 画用紙 | Canvas 2D API | ドット絵、世界地図、共有用カードを描く |
| にじませない拡大 | image-rendering: pixelated | 小さく描いた絵をくっきり拡大する |
| シンセサイザー機能 | Web Audio API | BGMをその場で作曲して演奏する |
| 合言葉つきのサイコロ | シード付き疑似乱数(PRNG) | 同じタネから同じ曲や人生を再現する |
| 翻訳の目印と辞書 | 自作の多言語化(タグ付きテンプレート) | 韓国語の原文を6言語で表示する |
| 文字の小分け | Webフォントのサブセット化(unicode-range, woff2) | 必要な文字の形だけを読み込む |
| ブラウザの保存場所 | localStorage / IndexedDB | セーブ、設定、過去の人生 |
| データの圧縮 | CompressionStream(gzip) | 別の端末へ引っ越すためのコード |
| 動画の書き出し | MediaRecorder / captureStream | 人生の振り返り動画を作る |
| ホーム画面に置ける | PWA(Web App Manifest) | アプリのように起動する |
| 配る・預かる | Cloudflare(配信と API) | ファイル配信、追悼の掲示板、統計 |
| 支払い | Stripe(Link) | 有料機能「keep」 |
| 鍵 | Content Security Policy / HSTS | 外から来たプログラムを動かさない |
| しおり | window.claude.hot | 開発中、更新しても続きから遊べる |
window.claude.hot が残っている