リリース v0.8.0

SAGBAL
(サグバル) — a stratum on Kimetron Isle

移動の仲裁層。
物理の真実は下に、行き先の意味は上に。

GitHub リポジトリを開く

その間に、層がなかった。

Kimetron Isle が面倒を見るのは「ここに置けるか」「何と重なったか」 ——配置と衝突の、物理の真実だけです。絶対条件として、 Kimetron には「目的地」も「門」も「優先度」も教えていません。

でもアプリが本当に知りたいのは、その先です。誰が先に通るか、 いま詰まっているのか、道を譲ったのか、爆発寸前なのか—— 移動という「事象」です。この二つの間に何もないままでは、 意味づけを全部アプリに書くか、物理エンジンに意味を教え込むかの 二択になってしまいます。

SAGBAL は真ん中に置く層です。Kimetron の真実の上に積み、 毎ティックの「この1歩を取りたい」という意図を集めて、 重なりを競り、行き詰まりを検出し、詰まりをほぐす—— 移動の現象を組み立てて、上へ事実として返します。

事実は上へ、指示は下へ

App ──API──▶ SAGBAL ──API──▶ Kimetron。 それぞれの層が持つものははっきり分かれています。

  • App — 意味 行き先・優先度・迂回経路。「門」や「街路」「袋小路」が何かを知るのはこの層だけ。経路は Goal.via の列として層に渡します
  • SAGBAL — 事象 意図の登録、競り(スコア・オークション)、譲りヒステリシス、閉路(deadlock)検出と相互退避、完全閉塞からの拡散、混雑の事実出力
  • Kimetron — 真実 配置・衝突・占有の物理。ユニットが重なれるか、壁を通れるかはここだけが決めます。すべての移動は最終的に tryMove を通るので、真実は全員に同一です

生のエンジンイベントは層で飲み込まず App まで素通しさせます。 SAGBAL が返すのは「より濃い事実」であって、解釈の押し付けでは ありません。

層の中で起きていること

  • 意図と「総意」 毎ティック、全ユニットの「この1歩」を収集。行き先が重なればスコアで競ります——総意は優先度の表現であって、物理を曲げません
  • 譲りヒステリシス 競り負けた側はしばらく抑制され、一歩後ろへ下がります。勝者はその隙間を通る
  • 右側通行(世界規約) 行き詰まった2体は、それぞれ自分の進行方向に対して決まった側へ逸れます。ペアごとの交渉ではなく世界の通行規則になるので、対向する流れは自然にレーンへ分かれます(Policy.keepSide)
  • 正面衝突も多数決 互いの場所を取り合う閉路も、オークションをバイパスさせず総意で決着。スコアに差があれば負けた方だけが逸れ、同点なら両方が脇へ退避します
  • 完全閉塞は拡散 動きたいのに四方すべて塞がったユニットは「動けません」と周囲へ発信(boxed)。信号を受けた近くのユニットは、距離減衰の斥力で少しずつ離れていきます(diffuse)
  • 混雑の事実 局所密度が上がると crowded、解消不能なら full の事実を返します。事実をどう使うかは App の仕事です
  • プレイヤーも競りの参加者 ドラッグ中の移動は setIntent で意図として登録され、徘徊者たちは他のユニットと同じように道を譲ります。層が外部の手を直接動かすことはありません
  • ストレスと爆発 詰まり続けたユニットはストレスを溜め、閾値で「爆発」します——スコア+100の意気込みで、次の競りを必ず押し通します。進めばストレスは減り、爆発も再武装します
  • 個別の歩幅 移動は全員同速ではありません。Goal.step を渡せば、その目的を追うユニットは自分の歩幅で動きます。負傷・荷役・高齢——「遅い理由」は App の語彙で、層は数値を運ぶだけ。意図・退避・拡散の押し出しまで、自分の歩幅を基準に動かします

街路網のデモ

3×3 の建物ブロックが作る街路網を、スライム6体が目的地ポストを 巡って行き来します。廊下での対面衝突、辻での譲り合い、袋小路での 拡散——右のイベントログには、3色に分かれた事象がそのまま流れます。

SAGBAL デモ:街路網を巡るスライムと3色のイベントログ

動画の後半では、プレイヤー P を街の真ん中にドラッグして駐機させ ています。徘徊者たちは「手」を他の移動体と同じように扱い、 uE blocked by uP が連発——避けきれずに爆発した ユニットが押し通る様子も見られます。

名前の由来

SAGBAL はシュメール語の sag (前・先)と bal(交差・移し替え)の合成語です。 「先に通るもの」を「交差」させる層——行き違いそのものが字面に 内蔵されています。

Kimetron が ki(場)と metron(尺度)で「測る場」なら、 SAGBAL はその場の上で起きる交差の層。島(Isle)の上に積む 地層(stratum)という位置づけです。

正直な現状

v0.8.0 は「移動の仲裁層」としては実用域ですが、ゲームエンジン ではありません。残っている余地も正直に書きます。

  • 描画・入力・経路探索は App 領分 層が持つのは仲裁と事象の組み立てだけ。デモの局所経路(辻まで数キャラ分のロールアウト)は App 側の実装です
  • 実測は数百体規模まで 競合・密度の走査は空間グリッドで近傍限定に(v0.7.0——起床ラッシュのフレーム停止を解消)。ただし一点への全員密集は局所二次が残り、数百体の実運用はまだ限定的です
  • 掃引衝突は入れません 着地地点の検査は Kimetron の正解なので、1ティックに体より大きく動く移動体は壁をトンネルし得ます——仕様です
  • npm 未公開 現状はリポジトリ同梱(vendored)のみ。公開整備は需要を見てから

ソースコード

MIT ライセンスで公開しています。TypeScript + React 製、 フレームワーク非依存の中間層です。

github.com/cuculhart/sagbal