# エントリーシーンとエンディング

## エントリーシーン {#entry-scenes}

```kix
enum Ending { NormalEnd, AzusaEnd }

#[scene]
#[entry]
pushdown fn Main(cleared_azusa: bool) -> Ending {
    …
    if ROUTE == Route::Azusa {
        return Ending::AzusaEnd;
    }
    Ending::NormalEnd
}
```

**エントリーシーン**とは、`#[entry]` も付けたシーンです。システムが物語を開始できる場所であり、チューリング完全なコードから物語に入る唯一の入口です。

- ゲームには少なくとも 1 つのエントリーシーンがあります。追加の章、アフターストーリー、シーンの回想は、さらに別のエントリーシーンです。
- 引数と戻り値の型は有限で（`E3008`）、`Text` を含めることはできません（`E3009`）。`fn` のコードは実行時にテキストを作れるので、システムから来た `Text` はプログラムの定数テキストとは限らないからです。
- `#[scene]` のない `#[entry]` は `E3018` です。それ以外の点では、エントリーシーンは普通のシーンであり、他のシーンから呼ぶこともできます。
- エントリーシーンは物語のすべての解析の根です。どのエントリーシーンからも到達できないシーンやステップは報告されます（`W5008`、`W5009`）。

## 物語の開始 {#starting-the-story}

システムは `fn` のコードから `nav::start` で物語を開始します。

```kix
button!{on_click = || nav::start(story::Main, (CLEARED_AZUSA.get(),), on_ending), t!["Start"]}

fn on_ending(ending: story::Ending) {
    match ending {
        story::Ending::AzusaEnd => { CLEARED_AZUSA.set(true); nav::goto(Credits) }
        story::Ending::NormalEnd => nav::goto(Credits),
    }
}
```

`nav::start` は、エントリーシーン、その引数、終了ハンドラを受け取ります。これが物語に入る唯一の方法です。

- `story::Main` は `#[entry]` シーンを指す `scene fn(P1, …, Pn) -> R` ポインタで、引数はタプル `(P1, …, Pn)`、終了ハンドラは `Fn(R)` です。合わない呼び出しは `E2027` です。
- 引数はエントリーシーンの有限な引数の型を持ち、セーブに記録されます。

システム側は[ゲームシステム](./system.md)と、STD リファレンスの [`std::system::nav`](../../std/system-nav.md) で説明しています。

## 引数 {#arguments}

エントリーの引数は、以前のプレイでクリアしたエンディングのような、プレイをまたぐ状態を物語が読むための手段です。システムがメタを読み、物語を開始するときにその値を渡します。引数はトレースと一緒にセーブに保存されるので、その後メタが変わっていても、読み込み時には同じ値でリプレイされます。コンパイラは引数を自由なものとして扱います。すべての解析は、引数のすべての値について成り立ちます。

## エンディング {#the-ending}

エントリーシーンが戻ると物語は終わり、制御はシステムに戻ります。戻り値はどのエンディングに到達したかをシステムに伝え、システムの終了ハンドラが、スタッフロールを流すかタイトルに戻るかなど、次に何をするかを決めます。渡るのは値だけで、システムは物語変数を見られません。ハンドラがどこにも遷移しない場合、モードスタックは開始ページにリセットされます。

`Main` のすべての経路は `Ending` を返さなければならないので、エンディングを返し忘れた経路は型エラーです。終了ハンドラは網羅的な `match` なので、システムが処理しないエンディングもコンパイルエラーです。

## メタの書き込み {#writing-meta}

```kix
CLEARED_AZUSA.write(true);
```

物語は、`Meta<T>` の `pushdown fn` メソッドである `write` でメタを書きます。

| メソッド | 種別 | 用途 |
| -------- | ---- | ---- |
| `get()` | `fn` | システムのコードが読む |
| `set(v)` | `fn` | システムのコードが書く |
| `write(v)` | `pushdown fn` | 物語が書く。物語は読み返せない |

物語からのメタは**書き込み専用**です。読むのは `fn` だけで、`const fn` のコードはメタを名指すこともできません（`E3013`）。物語が読み返せない書き込みは物語の制御フローを変えられないので、物語の解析には影響しません。書き込みはロードや巻き戻しで元に戻りません。解放したものは解放されたままです。メタが物語に届くのは、開始時のエントリーシーンの引数を通してだけです。

エクストラ画面からのシーンの**回想**は、別の `#[entry]` シーンの `nav::start` です。物語がそのシーンを初めて通ったときに書く `Meta<bool>` で解放します。
