0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Playload研究ノート #6 3KBの壁を圧縮で押してみた ― 8本中7本が小さくなったけれど、すすめはしない話

0
Last updated at Posted at 2026-11-10

はじめに

こんにちは、haruka_apps です。Playload で作品を作りながらわかったことをまとめるシリーズの6本目です。

Playload は、kitao さんが作られた「URL だけでゲームを共有できる」小さなゲームエンジンです。コードは圧縮後 3,000 バイトまで、という制限があります。

私はこの 3,000 バイトにいつも苦しんでいます。あと 50 バイトあれば音が入るのに、という場面が何度もありました。そこで今回は、作品には手を入れず、圧縮のやり方だけで余裕を作れないか を調べました。

これは、成功の記事ではありません。最初の目標(QRコード)には届かず、そのあと見つけた方法も「効く作品には 100 バイト少々効く」くらいです。それでも、どこに壁があるのかは数字ではっきり分かりました。うまくいかなかったことも含めて、道のりをそのまま残します。

  • 対象は Playload 0.9.6、私の作品が Arcade に執筆時点で載せていただいている 8 本です。
  • Playloadエンジンには一切手を入れていません。すべて、ふつうの Playload の URL として動きます。
  • 調査と計測は AI(Claude)と一緒に進めました。Chrome・Safari・スマホでの起動と、QRコードの読み取りは、私が実機で確かめています。

シリーズ目次

# タイトル URL
1 Playloadの画面は「文字のマス」と「動くキャラ」でできている https://qiita.com/haruka_apps/items/697ad6affba676620ef0
2 絵の描き方の基本 ― 内蔵文字で描く、自作文字は少しずつ書き換える https://qiita.com/haruka_apps/items/0637e72b1c5b1f73dfd4
3 3KBで3Dを描く ― Cube Maze 3D の描き方 https://qiita.com/haruka_apps/items/38af177afbb4a4fab397
4 3KBの中に8ビットコンピュータを作った ― PL-8 https://qiita.com/haruka_apps/items/e14af0ddf02e65bc521f
5 迷路を自分で覚えるAI ― td maze. https://qiita.com/haruka_apps/items/a0e0c1c5c81d943a3b83
6 3KBの壁を圧縮で押してみた ― 8本中7本が小さくなったけれど、すすめはしない話 https://qiita.com/haruka_apps/items/5b594c6323e05b86c457

この記事でわかること

  • Playload のゲームを QR コード 1 枚に入れられるのは、どの大きさまでか
  • ブラウザの圧縮より小さくできる「予測する圧縮」のしくみ
  • それを 3KB の世界に持ち込むと、なぜ簡単には勝てないのか
  • 私の 8 本で試した結果と、効く作品・効かない作品の違い
  • この方法をおすすめしない理由

先に結論

作品 今 新しい方法 差
SHOGI 9x9 2,938 2,782 −156
REVERSI 2,927 2,786 −141
td maze. 2,825 2,690 −135
PL-8 CPU 2,949 2,892 −57
reveal. 2,946 2,903 −43
Cube Maze 3D 2,921 2,892 −29
Pseudo 3D Racer 2,934 2,916 −18
minesweeper ai. 1,937 2,094 +157

(単位はバイト。エディタに表示される Payload と同じ数え方です)

図1

↑ 8 本の結果。青は小さくなった作品、オレンジは大きくなった作品です。

  • 3KB ぎりぎりの 7 本は、平均で約 83 バイト小さくなりました。
  • ソースコードは 1 文字も変えていません。
  • そのかわり、エディタで開いてもコードが読めなくなります。ここが一番大きな代償です。

きっかけは QR コードでした

展示会のチラシに QR コードを刷って、スマホのカメラで読んだらそのままゲームが始まる。そんな配り方ができたら楽しいな、と思ったのが始まりです。

条件は 1 つだけ決めました。スマホの標準カメラで読んで、kitao.dev が直接開くこと。読み取り用のページを自分で用意したり、短縮 URL を使ったりはしません。誰かのサービスが止まったら遊べなくなる、というのを避けたかったからです。

QR コード 1 枚に入る大きさ

QR コードは、いちばん大きいもの(バージョン 40、誤り訂正 L)で 2,953 文字まで入ります。Playload の URL は「書き出しの 35 文字+圧縮データを文字にしたもの」なので、逆算すると、

圧縮後およそ 2,190 バイトまでのゲームなら、QR コード 1 枚に入る

ことになります。3,000 バイトではなく 2,190 バイトなのは、URL にするときにデータが 3 分の 4 倍にふくらむからです。

私の 8 本でこの線の内側にあるのは、minesweeper ai.(1,937 バイト)だけでした。これは実際に QR コードにして、スマホのカメラから起動できることを確かめています。

残りの 7 本は 2,825〜2,949 バイトです。線まで 600 バイト以上あります。

QR に合わせて圧縮を作り変える(届かず)

QR コードには「英数字モード」という詰め方があり、大文字・数字・一部の記号だけなら 1 文字を 5.5 ビットで入れられます(ふつうは 8 ビット)。Playload の URL に使える文字のうち、大文字・数字・ハイフンの 37 種だけで URL を書ければ、同じ QR にもっと多く入るはずです。

そこで、圧縮データを文字にしたとき、なるべくこの 37 種が続くように圧縮のしかたを選ぶ という方法を作りました。圧縮には「同じ中身を表す書き方」がたくさんあるので、その中から QR に都合のよいものを選ぶわけです。

結果はこうでした。

minesweeper ai.
ふつうの圧縮で QR に使う量 2,560
QR に合わせた圧縮 2,512(−1.9%)

動きはしました。この QR コードも、スマホで読めることを確かめています。けれど 1.9% では QR の大きさは変わりません。

机上での限界も計算しました。37 種の文字しか使わない場合、どんなにうまくやっても入るのは 2,767 バイト相当までです。私の 7 本のうち 4 本は、この時点で入らないことが決まります。残りも、現実には舵を切るための損が大きく、届きませんでした。

QR コード 1 枚に入れられるのは minesweeper ai. だけ。 これが最初の結論です。

3,000 バイトの圧縮に戻る

QR はあきらめて、もとの悩みに戻りました。3,000 バイトの中に、もう少し余裕を作れないか、です。

ブラウザの圧縮がやっていること

Playload は、ブラウザに入っている圧縮(DEFLATE)を使います。この圧縮の得意技は「前に出てきた文字の並びを使い回す」ことです。String.fromCharCode が 2 回出てくれば、2 回目は「さっきのあれ」と短く書けます。

逆に言うと、使い回せるのは まったく同じ並び だけです。「for( のあとには let が来やすい」といった、ゆるい傾向は使えません。

予測する圧縮

もっと強い圧縮は、次の 1 ビットを 予測 します。

  1. 予測する: 「直前の 1 文字」「直前の 2 文字」「2 つ前と 3 つ前」など十数通りの手がかりごとに、「次は 1 になりやすいか」を記録した表を持ちます。
  2. 混ぜる: 十数個の予測を、重みをつけて 1 つにまとめます。よく当たる手がかりの重みは、読み進めるうちに自動で大きくなります。
  3. 詰める: 予測が当たったビットはほとんど場所を取らず、外れたビットだけ場所を取る書き方で記録します。
  4. 戻す: 戻すときは、まったく同じ予測をもう一度やり直しながらデータを読みます。

「次に来るものを当てる」という点では、生成 AI と同じ考え方です。こちらは表が十数枚あるだけの、とても小さなものですが。

この考え方は、JavaScript を小さくする道具として知られる Roadroller(Kang Seonghoon さん作、MIT ライセンス)で使われているものです。今回の方法は、しくみを Roadroller から学び、Playload に合わせてプログラムを書き直したものです。

ただし、戻すためのプログラムも URL に入れる

ここが 3KB の世界のつらいところです。ブラウザは「予測する圧縮」の戻し方を知りません。だから、戻すためのプログラム(復号器)も、ゲームと一緒に URL に入れる 必要があります。

図3

↑ REVERSI の中身。ゲーム本体は 560 バイトほど減りますが、復号器が 420 バイトほど増えます。

本体が 500 バイト減っても、復号器が 500 バイトあれば差し引きゼロです。つまりこれは、復号器をどこまで小さく書けるかの勝負 でした。

勝つまでの道のり

REVERSI(今は 2,927 バイト)で、工夫を 1 つずつ重ねていきました。

図2

↑ REVERSI の変化。最初は今より 159 バイトも大きくなりました。

① 最初の試作(+159)
ちゃんと元のコードに戻りましたが、復号器が 650 バイトほどあり、大負けでした。

② 復号器を短くする+文字合わせ(+13)
復号器を書き直して短くし、さらに「文字合わせ」をしました。これが今回いちばん Playload らしい工夫です。

圧縮したデータは 64 種類の文字で書きます。どの 64 種類を使うかは、実は選べます。一方、ブラウザの圧縮は「よく出る文字ほど短く書く」表を、全体で 1 つだけ作ります。そこで、データに使う文字を、復号器でよく使う文字(数字やかっこなど)に合わせました。すると復号器の文字も「よく出る文字」の仲間入りをして、短く書いてもらえます。これだけで約 80 バイト縮みました。

③ 予測の表を大きくする(−43)
表が小さいと、別々の手がかりが同じ場所にぶつかって予測が濁ります。広げたら、初めて今より小さくなりました。

④ 作品ごとに設定を探す(−109)
どの手がかりを使うか、どれくらい速く学ぶか、を作品ごとに探します。

⑤ 表の引き方を変える(−141)
手がかりの文字を数式で番号にまとめるのをやめ、文字の並びをそのまま見出しにしました。数式がいらなくなり、ぶつかりもなくなりました。

最終的な復号器は約 500 文字です。REVERSI の URL に入っている実物はこうなっています(データの部分は省略)。

// @title REVERSI
for(M=`…ここに圧縮したゲーム本体…`,B=new Uint8Array(4605),W=[],F=[],R={},C={},
K=[0,1,2,21,32,431,642,31,541],O=D=E=A=0;E<4605;B[E++]=P,A=A?P-A&&A:P==290&&P)
for(P=1;P<256;P=P*2+I){ /* 予測して、1 ビット読んで、表を直す */ }
eval(new TextDecoder().decode(B))  // 元のコードに戻して実行

うまくいかなかったこと

勝ち筋より、負けた案のほうがずっと多かったです。

試したこと 結果
QR の英数字モードに合わせた圧縮 動いたが −1.9%。QR の大きさは変わらず
Roadroller をそのまま使う コメントや空白を自動で削り、// @title も消える。コードを変えない設定では 8 本とも今より大きくなった
対数を使わない軽い計算に替える 予測が壊れて、データが 6 倍になった
場面ごとに重みを切り替える 得は 9 バイト以下。足すコードのほうが大きい
Playload の API 名を先に教えておく 7 バイトしか縮まない
よく使う書き方を先に教えておく 45 バイト縮むが、教える文を入れるのに約 125 バイトかかる

AI の見積もりも何度か外れました。「100〜350 バイト縮むはず」と出た数字が、よく調べると比べ方が公平でなかった、ということもありました。数字は必ず「同じコードで、同じ数え方で」比べる。当たり前のことですが、身にしみました。

Roadroller と比べる

元になった Roadroller をいちばん強い設定にして比べました。

REVERSI
今(ブラウザの圧縮) 2,927
Roadroller(コードを変えない設定) 2,963
Roadroller(標準。コメントや空白を削る) 2,925
今回の方法(コードを変えない) 2,786

Roadroller が劣っているという話ではありません。Roadroller は 13KB くらいの作品を想定した、何にでも使える道具です。3KB という小ささに合わせて作り直すと、そのぶんだけ得が出た、ということです。

効く作品、効かない作品

8 本の結果をもう一度見ると、きれいに分かれます。

  • よく効いた(−135〜−156): SHOGI 9x9、REVERSI、td maze.
    探索や AI など、ロジックが中心の作品です。「次に何が来るか」が当てやすいコードです。
  • 少しだけ効いた(−18〜−57): PL-8 CPU、reveal.、Cube Maze 3D、Pseudo 3D Racer
    絵や ROM を 16 進の文字列で持っている作品です。こういうデータは、ブラウザの圧縮ですでに限界近くまで詰まっています。
  • 逆に大きくなった(+157): minesweeper ai.
    もとが 1,937 バイトと小さいので、復号器の 400 バイト超がそのまま重荷になります。

Playload の知識は、圧縮には効きませんでした。 Playload の命令は cls put spr btn btnp play scr pcg の 8 個だけで、どれも 3〜4 文字です。復号器は 1 回見ればすぐ覚えるので、先に教えても 7 バイトしか変わりません。命令が少なくて短いという Playload のよさが、ここでは「工夫の余地がない」理由になっていました。

おすすめの考え方

ここまで書いておいて何ですが、私はこの方法を、ふだんの作品づくりにはおすすめしません。

  • コードが読めなくなります。 Playload は、URL を開けばコードが読めて、その場で直せるのが魅力です。この方法を使うと、エディタには暗号のような文字が並ぶだけになります。
  • エディタで直せません。 1 文字直すたびに、パソコンで詰め直す必要があります。
  • 得は 100 バイトほどです。 その 100 バイトは、たいていコードの書き方を見直せば作れます。そのほうが、作品もよくなります。

3,000 バイトという制限は、工夫を楽しむために kitao さんが決めてくださった線だと私は受け取っています。圧縮の裏技でその線を動かすより、線の内側で頭をひねるほうが Playload らしい、というのが今の気持ちです。

なので、この記事は道具の紹介ではなく、「3KB の壁はどこにあるのか」を調べた記録 として読んでいただけるとうれしいです。

つまずきやすいところ

同じことを試す方のために、気をつける点を残しておきます。

  • 比べるときは、同じコード・同じ数え方で。 圧縮の道具の中には、黙ってコメントや空白を削るものがあります。それは圧縮の力ではなく、コードを変えた分です。
  • 「ソースが短い」と「圧縮後が短い」は別です。 16 進の文字列を生のバイトに詰め直すと、ソースは 2 割短くなるのに、圧縮後は変わらないか、むしろ増えました。
  • 小数の計算はブラウザによってずれる心配があります。 復号器は対数と指数の計算を使います。今回は Chrome・Safari・スマホのどれでも起動しましたが、試すなら必ず実機で確かめてください。
  • 見えない制御文字が入ります。 データの中に、\ の代わりの見えない文字が入っています。エディタでコピーや編集をすると壊れるかもしれません。配るなら URL のままにします。
  • 起動時に、元に戻す計算が走ります。 パソコンで 0.5 秒ほどです。私のスマホでは気になりませんでしたが、古い機種では待つかもしれません。

おわりに

今回わかったことをまとめます。

  • QR コード 1 枚に入るのは、圧縮後およそ 2,190 バイトまで。私の 8 本では minesweeper ai. だけでした。
  • QR に合わせて圧縮を作り変える方法は動きましたが、効果は 1.9% でした。
  • 「予測する圧縮」を 3KB 向けに作り直すと、8 本中 7 本が小さくなりました。ロジック中心の作品で 135〜156 バイトです。
  • 勝負を決めるのは、約 500 文字の復号器でした。データに使う文字を復号器に合わせる工夫が、いちばん効きました。
  • ただし、コードが読めなくなります。ふだんの作品づくりには、おすすめしません。

届かなかった目標もありましたが、「ここまでは行ける、ここから先は行けない」という地図が手に入りました。次に 3,000 バイトで悩んだときは、裏技ではなく、コードのほうを見直そうと思います。

しくみを学ばせていただいた Roadroller の Kang Seonghoon さん、そして Playload を作ってくださった kitao さんに感謝します。

最後まで読んでいただき、ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?