
2026/01/12 7:14
このゲームは、Windows・Linux・ブラウザ上で動作する単一の13 KiBファイルです。
RSS: https://news.ycombinator.com/rss
要約▶
<|channel|>final <|constrain|>## Japanese Translation: 記事では、1つのソースファイルが「ポリグロット」バイナリを生成する方法を示しています。このバイナリには、Windows、Linux/BSD、およびブラウザ用にコンパイルされた3つの小さなプログラム(スネークゲーム)がすべて含まれており、合計13 312バイトです。コードはJustine Tunneyのcosmopolitan libcアイデアを使用し、各プラットフォームでネイティブに実行できる<16 KiBの実行ファイルを生成します。
3つのビルドが作成されます: • WinAPI用C(i686 Visual C)– 画面スクリプトとしても機能する非従来型PEヘッダーを使用。スタブはゲームを解凍して起動し、最初に再実行まで0xc0000005エラーが表示されます。 • Linux/X11用C(x86_64 clang)– lzmaデコンプレッションとシェルドロッパーを使用してファイルからELF64バイナリを抽出します。 • ブラウザ用JavaScript – ブラウザは先頭の無害なゴミを無視し、CSSで隠し、HTML/Canvasゲームがこの余白後に開始されます。
各コンパイル済み/ミニファイド版は約3–5 KiBです。3つのバイナリは順序通りに連結され、各オペレーティングシステムまたはブラウザが自分のセクションを実行します。元のゲームソースは13 772バイトでしたが、パッキングと連結後、正確に13 312バイトになります。
ゲームプレイの詳細(パッケージング物語の一部ではなく、キーポイントで言及されている)は次の通りです:
- スネークは食べ物を食べることで成長し、壁を避けます。
- 操作:矢印キー/WASDキー、ESCで終了、Rでリセット、Pで一時停止、Spacebarで開始。
- スコア:フルーツごとに+10、黄色のフルーツは+20。フルーツは一定レートで生成され、スネーク速度/長さに比例した時間が経過すると消えます。
- 10個のフルーツ後、ランダム壁を含むレベル変更が行われ、ヘッドから任意の食べ物へのパスが保証されます。初期スネーク位置はランダムですが、向いている方向に少なくとも5つの空きタイルがあります。
このプロジェクトは、複数のオペレーティングシステムとウェブブラウザ用の実行コードを1ファイルにまとめることができることを示し、小規模プログラムの軽量でプラットフォーム非依存的な展開の可能性を開きます。
本文
数年前、Justine Tunney の国際的な libc プロジェクトに気づきました。
それは C ソースコードをコンパイルして、Windows、Linux、各種 BSD(さらにブートローダーまで)でネイティブに動作する単一のバイナリへと変換できるツールキットです。
しかし当時、そのプロジェクトは GUI インターフェースをサポートせず、生成される実行ファイルがかなり肥大化していました。そこで私は同様(簡易?難解?はあなたに委ねます)な課題に挑戦することにしました:Windows、Linux、ブラウザのいずれでもネイティブに動作し、ソースコード 1 ファイルから生成できる 16 KiB 未満のビデオゲームを作成する。
ゲーム™
標準的なスネーク(Snake)ゲームで、すべてのプラットフォームで同じルールとインターフェースが使用されます。プレイヤーは食物を食べることで長くなる蛇を操作し、壁に衝突しないようにします。操作方法は矢印キーまたは WASD キーです。ESC(プラットフォームで許可されていれば)で終了、R でリセット、P で一時停止が可能です。スペースバーでゲームを開始します。
スコアは以下のように計算されます。
- 通常の食物を1個食べるごとに10点加算。
- 黄色い果実(15 % の確率で出現)は20点加算。
果物は固定レートで生成され、未取得の場合は一定時間後に消滅します。この消滅タイマーは、生成時の蛇の速度に比例し、さらにその速度は蛇の長さに比例します。
10 個の果物を食べるとゲームは次のレベルへ進み、壁の配置がランダム化されます。迷路は必ず蛇の頭から任意の食物まで道が通るように作られます。初期位置もランダムですが、常に蛇が向いている方向に少なくとも 5 マス以上空きスペースがある場所に配置されます。
ゲーム本体は 13 772 バイト でダウンロードできます。
ポリグロット™
このゲームを合計三度実装しました。
- Windows(i686 Visual C)向け WinAPI を使用した C 実装
- Linux(x86_64)向け clang と X11 を使用した C 実装
- ブラウザ用 HTML5 Canvas で書かれた JavaScript 実装
各実装はコンパイル/ミニファイ後に 約 3〜5 KiB のサイズです。
Windows 実装
圧縮スクリプトを使い、解凍スタブを先頭に付加したバイナリを作成しました。
このスタブは MZ シグネチャの後に自由に制御できる多数のバイトを持つ非常に珍しい PE ヘッダーを備えており、そこにシェルスクリプトを埋め込みます。このスクリプトはファイル残りをスキップし、Windows では有効な PE 実行可能ファイルとして動作させると同時に、Linux 上では全体が無害なシェルスクリプトとして認識され、現在のところ何も実行しません。
PE ファイルはやや扱いづらいため、Windows の apphelp 機構を利用しています。互換モードなしで初回実行すると次のメッセージが表示されます:
“The application was unable to start correctly (0xc0000005). Click OK to close the application.”
再起動後に消えるはずです。
Linux 実装
Windows と同様の手法を採用し、lzma で解凍する小さなシェルドロッパーを使用。圧縮された ELF64 バイナリを抽出し実行し、ファイルのヘッドとテールをスキップします。
HTML 実装
ブラウザは開始時に有害でないゴミデータも無理なく処理するため、この特性を悪用しました。HTML コンテンツに到達する前に余分なバイト列を挿入し、CSS を駆使してそれらを非表示/目立たないようにしています。
最終ファイル
三つの実装を適切な順序で連結した結果、13 312 バイト の単一ファイルが完成しました。各プラットフォームは自身に合った部分だけを選択して実行します。