Huemill を支える技術
Huemill は、自分の工場が誰かの工場の一部になるオンラインの自動化ゲームです。そのため、シミュレーションには2つのことが求められます。サーバーがすべての島を検算できること。そして、何百もの島を動かせるくらい軽いこと。それを支える仕組みの一部を紹介します。
公正な交易:サーバーが検算する
PC がサーバーに送るのは操作だけで、結果は送りません。サーバーは島の写しを自分でも持ち、同じコードで操作を再現し、取引はすべて自分のデータベースで決済します。改造したクライアントで、アイテムやお金や時間をごまかすことはできません。
アップデートしても古いセーブが読める
セーブの形式が変わるアップデートでは、サーバーは起動する前に全員の島を新しい形式へ移します。ログインしたときに一人ずつ移すのではなく、しばらく遊んでいない人の島もブループリントも含めて、全部まとめてです。移行はデータベースの1つのトランザクションで行い、すべてのセーブが新しくなるまでサーバーは起動しません。だから、もし移行に問題があっても、それが見つかるのはアップデートを公開する前です。久しぶりに戻ってきたら島が読めなかった、ということは起きません。
「保存した」と伝えた操作は失われない
何か操作をすると、サーバーはそれをデータベースに書き込んでから応答します。サーバーが落ちても、失われうるのは、まだ受け付けたと伝えていない操作だけです。
どの PC でも同じ数字になる
サーバーが島を再現するには、どの PC でもシミュレーションの結果がぴったり一致しなければなりません。浮動小数点は使わず、整数(小数が要るところは固定小数点)と独自の乱数で計算し、1秒に20回の決まった刻みで進めます。
ベルト:1本のラインを一度に進める
同じ種類のベルトが端どうしでつながると、1本のラインにまとまります。ライン上のアイテムは一つずつ動かすのではありません。ラインはリングバッファになっていて、端を入れ替えるだけで全体が1マス進みます。そのため、ラインを進める手間は、載っているアイテムの数にもラインの長さにも左右されません。
鉄道:一度計画したら、次の出来事まで待つ
列車の位置は毎 tick 計算し直すわけではありません。区間に入るとき、その区間の走り方(加速・巡航・減速)を整数演算で一度だけ確定します。次にシミュレーションが列車を見るのは、先頭が区間の終わりに着いたときか、最後尾が区間を抜けたときです。画面のなめらかな動きも、同じ式から描いています。
信号を置く必要はありません。線路は自動で閉塞区間に区切られ、列車は進む先の区間を予約してから入ります。OpenTTD を1000時間遊んで、結局パス信号しか使わなくなったので、信号はなくしました。
水:セルではなく水の塊で扱う
水はセルごとに計算していません。つながっていて水位が同じ水は、ひとつの塊として、水量と水位を1つずつ持ちます。湧き水は低い方へ流れて川になり、海や吸い込み穴へ抜けていきます。地形を掘ったり盛ったりすると、塊はその場で分かれたり合わさったりします。1 tick の計算量を決めるのは、塊の数と、水が流れ出す場所の数です。濡れているセルの数ではありません。
地形:地中はシードから計算する
島はワールドシードから、整数と固定小数点の計算だけで生成します。同じシードなら、どの PC でも同じ地形・川・鉱脈になります。だから地中の中身はセーブに書かなくて済みます。記録するのは掘って変えた列だけで、手付かずの地中は必要なときにシードから計算し直します。