# Family BASIC リファレンス (LLM 向け / クリーン版)

あなたは Family BASIC (1984年、任天堂 HVC-BS) のコードを書くアシスタントです。
出力する BASIC コードは必ず Family BASIC で動く形にしてください。

## 守るべき制約 (絶対)

これらは LLM が他言語の BASIC 感覚で間違いがちな点です。**絶対に守ってください**:

- **整数 16bit** (-32768 〜 +32767)。実数 (浮動小数点) なし
- **変数名は英字 + 英数字最大 2 文字** (例: A, X1, AB)。3 文字以上不可
- **行番号は 0〜65535**、昇順
- **英文字は大文字のみ**。小文字は存在しない (`print` ではなく `PRINT`)
- **`LET` キーワードは使えない** (使うと `?SN ERROR`)
- **`NEXT` に変数を付けるな** (`NEXT I` は `?SN ERROR`、`NEXT` 単独で書く)
- **配列の添字は 0 始まり** (`DIM A(10)` は 0..10 の 11 要素)
- **真偽値は -1 (真) / 0 (偽)**、C 系の 1/0 とは異なる
- **関係演算子**: `<>` `>=` `<=` (`≠` `≧` `≦` は使えない)
- **文字列は最大 31 文字**
- **`?` は `PRINT` 略記**、**`'` は `REM` 略記**
- **`&H` は 16 進プレフィックス** (`&H7600` 等)
- **変数 × 論理演算子はスペース必須** (`NOT X` は OK、`NOTX` は誤認)
- **未初期化変数は数値=0、文字=空文字列** で読める (明示的初期化は不要)
- **STICK 値はビットフラグ**: 0=なし, 1=右, 2=左, 4=下, 8=上 (斜めは OR)
- **16×16 スプライトは 4 タイル**で構成 (`CHR$(t1)+CHR$(t2)+CHR$(t3)+CHR$(t4)`、
  順序は **左上, 右上, 左下, 右下**)。**連続する 4 コードで 1 ポーズ**
- **左右反転 (X 反転) は 2 つ両方必要**: 4 タイル並び順で L/R 列入れ替え
  (`CHR$(t2)+CHR$(t1)+CHR$(t4)+CHR$(t3)`) **+** DEF SPRITE の X 反転フラグ = 1。
  片方だけだと顔が向きと逆になる
- **未確認のキャラ・ポーズで CHR$ を当てずっぽうで選ぶな** — 崩れる。
  動作確認済の組合せ (SAMPLE_*) を使うか、**DEF MOVE で A 引数 (0-15) でキャラ種類を
  指定**して逃げる
- **DEF SPRITE の B 引数は 0 か 1 の 2 値のみ**: `0`=8×8 ドット (CHR$ 1 つ)、
  `1`=16×16 ドット (CHR$ 4 つ)。16×8 や 8×16 のような中間サイズは無い
- **弾丸 / 小さな飛び道具は 8×8 スプライト (B=0) + コード 208-213** (レーザー
  各種、よこ/たて/ななめ × 1/2 のバリエーション) を使う。
  例: `DEF SPRITE 0, (0, 0, 0, 0, 0) = CHR$(208)`
- **PLAY 文の半音記号は `#` を音名の**前**に置く** (`#C`, `#D`, `#F`, `#G`, `#A`)。
  **`C#` (後置 `#`) や `-D` (フラット) は存在しない**。フラットは等価なシャープで書く
  (例: レ♭ は `#C`)

## 各エントリの読み方

- **構文 (syntax)**: BASIC 文の書き方
- **概要 (summary)**: 1 行説明
- **詳細 (notes_for_llm)**: 動作・落とし穴・流儀

---

## 言語仕様 (spec)

### `SPEC_CHARSET`

使える文字種は数字・英文字・カナ・記号

- 漢字・ひらがなは扱えない (カナ = カタカナ)

- 英文字は **大文字のみ**。小文字は存在しない (キーボードに小文字キーが
  無く、キャラクタコード表 B も A-Z のみで a-z は欠番)
- LLM が `print "hello"` のように小文字で書いた場合、`PRINT "HELLO"` に
  補正する必要がある

*タグ*: 仕様, 文字, 制約

### `SPEC_INTEGER_RANGE`

整数の表現範囲は 16 ビット符号付き (-32768〜+32767)

- 16 進表記では &H0000〜&HFFFF
- **実数 (浮動小数点) はサポートしない** — 整数型のみ
- この範囲を超える演算結果は保証されない

*タグ*: 仕様, 制約, 数値

### `SPEC_STRING_RANGE`

文字列の長さは 0〜31 文字

- 31 文字を超える文字列は扱えない
- 文字列連結や LEFT$/RIGHT$/MID$ で 31 を超えないよう注意

*タグ*: 仕様, 制約, 文字列

### `SPEC_MULTI_STATEMENT`

マルチステートメント可能 (`:` コロンで区切る)

- 1 行に複数文を `:` で区切って書ける
- 例: `10 A=1:B=2:PRINT A,B`

*タグ*: 仕様, 構文

### `SPEC_SUBROUTINE_NESTING`

サブルーチン・ネストはメモリ範囲内で制限なし

- GOSUB のネスト数に固定上限なし — メモリで決まる
- FOR-NEXT のネストも同様

*タグ*: 仕様, 制御

### `SPEC_EDITOR`

編集機能はスクリーンエディタ

- 画面上でカーソル移動して直接編集
- LIST 後にカーソルを戻して再編集する流儀

*タグ*: 仕様, UI

### `SPEC_SCREEN_MODE`

画面モードは BG GRAPHIC 面・スプライト面・バックドロップ面の 3 層

- 重ね合わせ表示。BG GRAPHIC が背景、スプライトが手前、
  バックドロップが背景色

*タグ*: 仕様, グラフィック

### `SPEC_GRAPHICS_RESOLUTION`

バックグラウンド 28 文字 × 24 行 / スプライト 256 × 240 ドット / 1 キャラクタ 8 × 8 ドット

- **テキスト座標は 28 列 × 24 行** (LOCATE で指定する範囲)
- **ドット単位の座標は 256 × 240** (XPOS/YPOS、SPRITE 系)
- 1 キャラクタは 8×8 ドット固定

*タグ*: 仕様, グラフィック, 座標

### `SPEC_COLOR`

カラーゼネレータ 52 色発色

- 同時表示は別途パレット制約あり (PALET 文参照)
- 詳細はキャラクタテーブル / カラーチャート 参照

*タグ*: 仕様, 色

### `SPEC_SOUND`

音色・テンポ・3 重音・効果音

- **同時発音 3 音** (3 重音)
- BEEP / PLAY 文で制御

*タグ*: 仕様, 音

### `SPEC_CONTROLLER`

左右コントローラ + トリガースイッチ入力可能

- 入力読み取りは STICK / STRIG 関数

*タグ*: 仕様, 入力

### `SPEC_FILE_IO`

ファイル機能はカセットテープ (1,200 ボー)

- 補助記憶はカセットテープのみ
- SAVE / LOAD でテキスト・BG GRAPHIC を保存

*タグ*: 仕様, IO

### `SPEC_INSTRUCTION_COUNT`

命令数 基本 74

- 全予約語は機能別命令語索引参照

*タグ*: 仕様

### `SPEC_ANIME_CHARACTERS`

アニメキャラクタは既設 16 種類より選択

- DEF SPRITE / DEF MOVE で使うアニメキャラクタは **本体内蔵の 16 種類**
  から選んで使う (任意のドット絵を作って登録するわけではない)
- 16 種類の内訳 (DEF MOVE の引数 A=0〜15 順):
  - A=0  マリオ
  - A=1  レディ
  - A=2  ファイターフライ (ハエさん)
  - A=3  アキレス
  - A=4  ペンペン (ペンギンさん)
  - A=5  ファイアーボール
  - A=6  車
  - A=7  スピナー
  - A=8  スターキラー
  - A=9  スターシップ
  - A=10 爆発
  - A=11 ニタニタ
  - A=12 レーザー (8×8 単タイル)
  - A=13 シェルクリーパー (カメさん)
  - A=14 サイドステッパー (カニさん)
  - A=15 ニットピッカー (トリさん)
- 詳細は DEF MOVE の引数 A、視覚的な絵柄は
  キャラクタテーブル A 参照。完全な CHR$ マッピングは
  `SPRITE_CHARACTER_MAP` エントリ
- **ユーザがオリジナルキャラを描く方法は CGSET / BG GRAPHIC エディタ経由**
  で、こちらは「アニメキャラクタ」とは別系統

*タグ*: 仕様, スプライト

### `KEYWORD_INDEX`

全予約語の索引 (機能分類 + 略号 + 詳細ページ)

各エントリ: 命令名 (略号) — カテゴリ — 詳細ページ。
略号は `.` 終端で省略入力できる。

### システムコマンド (実行制御)
- CLEAR (CLE.) — 変数初期化
- NEW — プログラム消去
- LIST (L.) — プログラム表示
- RUN (R.) — プログラム実行
- CONT (C.) — 中断後の継続
- LOAD (LO.) — テープから読込
- SAVE (SA.) — テープへ保存
- LOAD? (LO.? または LO.P.) — SAVE 検証 (テープ書込が正しいか確認)
### 一般ステートメント (プログラム本体で使う文)
- 代入
- PRINT (?, P.) — 画面出力
- INPUT (I.) — 入力
- LINPUT (LIN.) — 行単位入力
- CLEAR (CLE.) — 変数初期化
- DIM (DI.) — 配列宣言
- GOTO (G.) — 無条件分岐
- GOSUB (GOS.) — サブルーチン呼出
- RETURN (RE.) — サブルーチン復帰
- IF~THEN (IF~T.) — 条件分岐
- FOR~TO~STEP (F.~TO~ST.) — 繰返し開始
- NEXT (N.) — 繰返し終端
- ON~ (O.) — 計算分岐
- STOP (STO.) — 停止
- END (E.) — 終了
- SWAP (SW.) — 値交換
- REM — コメント (略号は ' 単引用符でも可)
- READ (REA.) — DATA から読込
- DATA (D.) — データ定義
- RESTORE (RES.) — DATA ポインタ巻戻
- CALL (CA.) — マシン語呼出
- POKE (PO.) — メモリ書込
### 画面制御ステートメント
- LOCATE (LOC.) — カーソル位置設定
- COLOR (COL.) — 文字色設定
- CGEN (CGE.) — キャラクタジェネレータ切替
- CLS (CL.) — 画面消去
- CGSET (CG.) — キャラクタ定義
- PALET (PAL.B, PAL.S) — パレット設定
### MOVE コマンド (スプライトの自動移動)
- DEF MOVE (DE.M.) — 移動パターン定義
- MOVE (M.) — 移動開始
- CUT (CU.) — 移動停止 (即時)
- ERA (ER.) — 移動消去
- POSITION (POS.) — スプライト位置設定
- XPOS (XP.) — X 座標取得
- YPOS (YP.) — Y 座標取得
- MOVE(n) (M.(n)) — 個別スプライト移動
### 特殊ステートメント
- KEY (K.) — ファンクションキー設定
- KEYLIST (K.L.) — KEY 設定一覧表示
- PAUSE (PA.) — 一時停止
- SYSTEM (S.) — システムモード
- VIEW (V.) — 表示制御
### サウンド制御ステートメント
- BEEP (B.) — 単音発生
- PLAY (PL.) — メロディ演奏
### 関数 — 数値関数
- ABS (AB.) — 絶対値
- SGN (SG.) — 符号
- RND (RN.) — 乱数
### 関数 — 文字関数
- ASC (AS.) — 文字 → コード
- CHR$ (CH.) — コード → 文字
- VAL (VA.) — 文字列 → 数値
- STR$ (STR.) — 数値 → 文字列
- HEX$ (H.) — 数値 → 16 進文字列
- LEFT$ (LEF.) — 左部分文字列
- RIGHT$ (RI.) — 右部分文字列
- MID$ (MI.) — 中間部分文字列
- LEN (LE.) — 文字列長
### 関数 — 特殊関数
- PEEK (PE.) — メモリ読込
- POS — カーソル X 位置
- FRE (FR.) — 残メモリ取得
- STICK (STI.) — コントローラ十字キー
- STRIG (STRI.) — コントローラトリガー
- CSRLIN (CS.) — カーソル Y 位置
- SCR$ (SC.) — 画面文字取得
### 入出力用文字関数
- INKEY$ (INK.) — キーボード即時入力
### スプライト制御ステートメント
- DEF SPRITE (DE.SP.) — スプライト定義
- SPRITE (SP.) — スプライト表示
- SPRITE ON (SP.O.) — スプライト有効
- SPRITE OFF (SP.OF.) — スプライト無効
*タグ*: 予約語, 索引, 仕様

### `OP_PRECEDENCE_ARITHMETIC`

算術演算子の優先順位 (詳細は の総合優先順位を参照)

算術演算子の優先度 (高い順):
1. `*` `/` (乗算・除算)
2. `MOD` (剰余)
3. `+` `-` (加減算)

同じ優先度のものが並んだ場合は **左から順に評価**。
優先順位を変えたい場合は `( )` で囲む。

*タグ*: 演算子, 優先順位

### `OP_PRECEDENCE_FULL`

全演算子の優先順位 (高い順)

優先順位は以下の 10 段階。同じレベルなら左から評価。

1. `( )` — 括弧内
2. 関数 (ABS, RND, ASC, …)
3. `*`, `/` — 乗算・除算
4. `MOD` — 剰余
5. `-`, `+` — 加減算 (単項マイナスも可)
6. `=`, `<>`, `>`, `<`, `>=`, `<=` — 関係演算子
7. `NOT` — 否定
8. `AND` — 論理積
9. `OR` — 論理和
10. `XOR` — 排他的論理和

**算術 > 関係 > 論理** の階層。これにより
`IF X > 0 AND X < 10 THEN` のような自然な書き方が可能 (関係が先に評価される)。

*タグ*: 演算子, 優先順位, 仕様

### `META_SYNTAX_NOTATION`

文法編における命令解説の表記規則

以降の reference ページでは各命令を以下の 6 ブロックで解説:

1. **番号 (色)**: 命令の番号と分類カテゴリ
2. **文法**: 引数形式
3. **省略形**: 短縮入力形 (例: PRINT → P.)
4. **説明**: 動作の解説
5. **サンプルプログラム**: 実行例
6. **デフォルト値**: 引数省略時の値

### 構文表記の記号
- `[ ]` : 省略可能
- `( )` : 演算優先や引数の括弧
- `,...` : 繰り返し可能
- `( | )` : ハイフンで区切られた選択肢
- `《》` : メタ要素 (型・パラメタの意味)

### デフォルト値の言及
GAME BASIC モード起動直後は以下の状態 (引数省略時の挙動はこれを基準):
- CGEN2
- SPRITE OFF
- POSITION n, 120, 120
- PLAY "O3V15T4M0" 及び音程の長さ5
- カラーパレットは BG / SPRITE 用と BG 用のパレットコード1の配色となっている

*タグ*: メタ, 表記規則

### `SPEC_SOFTWARE_BUNDLED`

同梱ソフト 4 種

ファミリーベーシック ROM カートリッジには以下 4 つの「ボード」が同梱:
1. BASIC (BG GRAPHIC を含む) — GAME BASIC モード
2. カリキュレータボード (CALC) — 関数電卓
3. メッセージボード — 伝言板/グラフィック編集
4. ミュージックボード — 作曲機能

LLM がコードを書くのは主に (1) の GAME BASIC モード。
(2)-(4) は対話的 UI モードで、BASIC コードからの直接呼出は限定的。

*タグ*: 仕様, モード

### `SPEC_ROM_LAYOUT`

ROM 構成 (合計 24KB)

| 領域 | サイズ |
|------|-------|
| プログラム用 ROM | 8 ビット × 16K × 2 (= 32KB? 表記要確認) |
| キャラクタジェネレータ ROM | 8 ビット × 8K (= 8KB) |

※ 仕様欄表記が「8 ビット ×16K×2」は連結表現の可能性。
実物 ROM ファイル (`Family BASIC.nes`) は通常 32KB なので
プログラム部 32KB + CHR 8KB の慣用解釈で整合する。

*タグ*: 仕様, ROM

### `SPEC_RAM_LAYOUT`

RAM 構成 (本体 + カセット内蔵)

| 領域 | サイズ |
|------|-------|
| ワーキングメモリ用バックアップ RAM | 8 ビット × 8K (= 8KB) — **カセット側** |
| (本体内蔵 S-RAM) | 8 ビット × 2K (= 2KB) |

本体 2KB は `&H0000`-`&H07FF`、カセット 8KB は `&H7000`-`&H7FFF` 範囲を含む
(但し全部がユーザ領域ではない)。

**「ファミベは 2KB しか使えない」は本体 RAM のことを指している慣用表現**で、
実際にプログラムが入るのは BASIC カセット側 RAM の `&H7040`-`&H77FF`。

*タグ*: 仕様, RAM

### `SPEC_DISPLAY_TEXT`

文字表示能力

- **8 × 8 ドットマトリックス × 28 文字 × 24 行**
- 表示文字種: 英文字 + カタカナ + 数字 + 記号 + 特殊記号 (アイコン) + キャラクタ
- 文字数 28 列 × 24 行 = **画面 672 文字**

*タグ*: 仕様, 表示

### `SPEC_DISPLAY_SPRITE`

スプライト表示能力

- **8 × 8 ドット (但し 1 スプライトは 16 × 16 ドット = 8 × 8 を 4 枚)**
- **256 × 240 ドット** (BASIC 画面)
- スプライト ON 時の上限・色制約は別エントリで詳細

*タグ*: 仕様, 表示, スプライト

### `SPEC_SOUND_DETAIL`

サウンド機能詳細

- 2 個の効果音 (システム的に予約されている可能性)
- 1 個の効果音 (BEEP 用)
- 同時 3 重音は の SPEC_SOUND と整合

*タグ*: 仕様, 音

### `SPEC_KEYBOARD_LAYOUT`

HVC-007 キーボード配列

- 配列: ASCII 配列 (英、カタカナ 50 音配列) 準拠
- **ASCII 配列 + JIS かな** のハイブリッド
- キーの種類: 文字キー、ファンクションキー (F1-F8)、カーソルキー

*タグ*: 仕様, キーボード

### `SPEC_INTERFACE`

外部インタフェース

- カセットテープ用ピンインタフェース大入出力 — 1200 ボー
- 3.5φ プラグ READ・WRITE 接続可
- これが SAVE/LOAD で使うピンジャック

*タグ*: 仕様, IO, テープ

### `SPEC_MEMORY_BACKUP`

メモリバックアップ

- 電源断時、BASIC カセット内 RAM の内容を一定期間保持 (バックアップスイッチ)
- 詳細は phase4/memo.md の「演出ネタ: 実機の起動グリッチ再現」を参照

*タグ*: 仕様, 電源, バックアップ

### `SPEC_PHYSICAL`

外形・重量

- キーボード (HVC-007): 368 (W) × 163 (D) × 54 (H) mm
- カセット (HVC-FB): 110 (W) × 110 (D) × 17 (H) mm
- 重量: キーボード 956g / カセット 95g (電池含まず)
- 電源 / 環境: 使用湿度 35〜75 % など

*タグ*: 仕様, 物理

### `VISUAL_COLOR_CHART`

カラーチャート (パレット設定の参照表)

CGSET 文や DEF SPRITE / DEF MOVE で指定するカラーコードの参照。

構造:
- **スプライト用パレット**: 4 つのパレットセット × 各 4 色
- **バックグラウンド用パレット**: 4 つのパレットセット × 各 4 色
- 各パレットは色番号で指定され、PALETT 文で切替

### LLM 向けの留意点
- 各パレットの色番号は **52 色のマスタパレット**から選ぶ
- 同時表示できる色はスプライト 16 色 + BG 16 色程度
- 透明色 (背景色 = パレット 0) はスプライト用と BG 用で共通

*タグ*: 色, パレット, 視覚資料

## 言語仕様の制約 (constraint)

### `SPEC_VARIABLE_NAME`

変数名は英字または英字 + 数字の最大 2 文字

- 1 文字目: 英字必須
- 2 文字目: 英字または数字 (省略可)
- **3 文字以上の変数名は使えない**
- 文字列変数は末尾に `$` を付ける (例: A$, X1$)

<!-- probe-observed:start id=constraints/var-name-too-long -->
**観察例** (nesemu 実機検証):

実機では `ABC=42:PRINT ABC` がエラーにならず 42 を出力する。3 文字目以降は無視されて `AB` として扱われると推測される (両方とも `AB` を参照しているので同じ値が見える)。

```basic
10 ABC=42:PRINT ABC
```

出力:

```
   42
```
<!-- probe-observed:end -->


*タグ*: 仕様, 制約, 変数

### `SPEC_LINE_NUMBER`

行番号の範囲は 0〜65535

- **0 が下限**である点に注意 (一般 BASIC で 1 始まりが多いのと異なる)
- 上限 65535 を超える行番号は使えない (16 ビット符号なし整数の最大値)
- 行番号は昇順に並べる必要がある

*タグ*: 仕様, 制約, 行番号

### `SPEC_LINE_LENGTH`

1 行の桁数の大きさは 255 桁

- 1 行に書ける文字数の上限。マルチステートメント (`:` 連結) も含めて 255
- 長い行はこの制限に注意

*タグ*: 仕様, 制約

### `SYNTAX_OPERATOR_SPACING`

変数と論理演算子を続けて書く場合は、間にスペースが必要

規則として **変数 × 論理演算子** (NOT / AND / OR / XOR) の間のみ
スペースが必須。それ以外 (記号形、リテラル隣接、算術演算子 MOD) は
詰めて書いても動く。

- 変数と論理演算子をつづけて書く場合は、間にスペースを空ける

**安全側のルール (LLM 出力推奨)**:
- **常にスペースを入れる**のが最も安全 (可読性も上がる)
- 詰めて書くのは入力短縮目的のとき (BASIC コーディングの慣習)

<!-- probe-observed:start id=constraints/operator-spacing-mod -->
**観察例** (nesemu 実機検証):

リテラル隣接なら MOD の前後にスペース不要。

```basic
10 PRINT 10MOD3
```

出力:

```
   1
```
<!-- probe-observed:end -->

<!-- probe-observed:start id=constraints/operator-spacing-not -->
**観察例** (nesemu 実機検証):

変数 + 論理演算子の間にはスペースが必要。詰めると別の識別子扱い。

```basic
10 X=0:PRINT NOT X
```

出力:

```
  -1
```
<!-- probe-observed:end -->


*タグ*: 構文, 制約, スペース

## システムコマンド (syscommand)

### `CLEAR_SYS`

BASIC で使用するメモリ領域の最上位アドレスを指定する

**構文**: `CLEAR アドレス`

**引数**:
- `アドレス` (数値 (16bit)): メモリ領域上限アドレス。&H7AF まで (= &H77AF が上限)

- **`CLEAR` は引数有無で挙動が異なる 2 つの形がある**:
  - `CLEAR アドレス` → メモリ領域の上限を変更 (本ページ)
  - `CLEAR` (引数なし) → 変数・配列を全クリア (参照)
- マシン語プログラムを BASIC とは別領域に置きたい場合に使う
- **CLEAR を実行すると同時に変数・配列もクリアされる** (FOR-NEXT, GOSUB の
  ネスティング及び音楽・配列もクリア)
- 上限アドレスを縮めれば BASIC 領域が減り、その上の領域がマシン語等に確保される

*タグ*: システム, メモリ

### `NEW`

プログラムをすべて消去する

**構文**: `NEW`

- 略号なし (事故を防ぐため)
- 新しいプログラムを入力する前に必ず使う
- **CLEAR と異なり、メモリ上限などのシステム設定は変更しない**
- 変更後の現プログラムを失いたくない場合は、別途 SAVE してから NEW

*タグ*: システム, プログラム管理

### `LIST`

メモリ内のプログラムを画面に表示する

**構文**: `LIST [(m)] [(-n)]`

**引数**:
- `m` (数値 (行番号)) *(任意)*: 表示開始行番号
- `n` (数値 (行番号)) *(任意)*: 表示終了行番号

引数の組み合わせで以下のように使い分ける:
- `LIST` — 全プログラムを表示
- `LIST m` — m 行目のみ表示
- `LIST m-` — m 行目以降を全部表示
- `LIST m-n` — m から n までを表示
- `LIST -n` — 最初から n 行目まで表示

略号: `L.`

- **範囲指定のハイフン `-` はカンマ `,` で置き換えても動く**
  (例: `LIST 100,200` = `LIST 100-200`、連載者検証)

注意:
- **ESC キー** を押すとリスト表示を中断、`'` (シングルクォート) を押すと一時停止
- 表示中に矢印キーで停止/再開できる

<!-- probe-observed:start id=syscommand/list-program -->
**観察例** (nesemu 実機検証):

LIST はメモリ上のプログラムを画面に出力する。実機観察: 行 10/20 を入力 → LIST で `10 PRINT "FIRST"` `20 PRINT "SECOND"` が再表示 → 続けて probe_runner が付加した RUN で実行され `FIRST` `SECOND` が出る。略号は `L.`。

```basic
10 PRINT "FIRST"
20 PRINT "SECOND"
LIST
```

出力:

```
  FIRST
  SECOND
```
<!-- probe-observed:end -->


*タグ*: システム, 表示

### `RUN`

プログラムを実行する (必ず変数をクリアして開始)

**構文**: `RUN [n]`

**引数**:
- `n` (数値 (行番号)) *(任意)*: 実行開始させたい行番号 (省略時は最初から)

略号: `R.`

挙動:
- **RUN 単独**: 最初の行から実行
- **RUN n**: n 行目から実行
- **RUN は引数の有無に関わらず、必ず変数をクリアする**
- 変数をクリアせずに途中行から実行したい場合は **GOTO** か **CONT** を使う

*タグ*: システム, 実行

### `CONT`

STOP / BREAK / エラーで停止したプログラムを再開する

**構文**: `CONT`

略号: `C.`

再開可能な条件:
- STOP 文で停止
- BREAK (CTR+C) で中断
- エラー停止後、**プログラムを変更していない場合のみ**

再開不可:
- **プログラムを 1 行でも変更すると CONT は使えない** (CC エラー)
- END で終了した場合
- エラー後にプログラムを直接編集した場合

*タグ*: システム, 実行制御

### `LOAD`

カセットテープからプログラムを読み込む (← SAVE)

**構文**: `LOAD ["ファイル名"]`

**引数**:
- `ファイル名` (文字列 (16 文字以内)) *(任意)*: 読込対象のプログラム名。省略時は最初に見つかった BASIC を読込

略号: `LO.`

挙動:
- ファイル名を指定すると、テープを最初から走査して名前一致するプログラムを LOAD
- 名前指定なしの場合、テープの最初に見つかった BASIC プログラムを LOAD
- **読み込み開始時に `LOADING ファイル名` が表示される**
- **走査中にスキップしたファイルは `SKIP ファイル名` が表示される**
- 読込結果は OK で終了。失敗時は TP ERROR
- **使用方法は次ページ参照**

*タグ*: システム, IO, テープ

### `SAVE`

プログラムをカセットテープに記録する (← LOAD)

**構文**: `SAVE ["ファイル名"]`

**引数**:
- `ファイル名` (文字列 (16 文字以内)) *(任意)*: 保存時のプログラム名 (パラフレキ・オートサーション不可)

略号: `SA.`

挙動:
- 名前を指定すると、その名前でプログラムを記録
- 1 本のテープに複数プログラムを記録可能 (整理時はファイル名を 1 つずつ別にする)
- 記録中に WRITING、終了時に OK が出る
- **使用方法は次ページ参照**

*タグ*: システム, IO, テープ

### `LOAD_VERIFY`

SAVE したプログラムが正しく記録されたか検証する

**構文**: `LOAD? ["ファイル名"]`

**引数**:
- `ファイル名` (文字列 (16 文字以内)) *(任意)*: 検証対象のファイル名 (省略時は最初に見つかったプログラム)

略号: `LO.?` または `LO.P.` (TOC 表記)

動作:
- SAVE した直後にこれを実行することで、書き込みの正常性を確認
- **テープに記録されたプログラムとメモリ内のプログラムが一致するか比較**
- 一致すれば `LOADING ファイル名` の後 OK
- 不一致なら **`?TP ERROR`** (Tape read ERROR、ERROR_TP 参照)
- 検証用なので、メモリ内のプログラムを上書きしない

使い分け:
- SAVE 直後の確認に必須 (テープ媒体の信頼性が低い時代の名残)
- 連載で SAVE/LOAD を扱う場合、`SAVE "X" : LOAD? "X"` のセットで紹介推奨

*タグ*: システム, IO, テープ, 検証

## ステートメント / 文 (statement)

### `ASSIGNMENT`

変数への代入文 (LET は使えない)

**構文**: `変数 = 式`

- 文の先頭で **変数名 = 式** で代入
- 数値変数 (`A`, `X1` 等) には数値式
- 文字列変数 (末尾 `$`) には文字列式
- 型不一致は TM ERROR
- **未初期化の変数は数値 = 0、文字変数 = ヌルストリング (`""`) として
  扱われる**。明示的な初期化は不要

- **`LET` キーワードは使えない** (一般的な BASIC で許される `LET A = 10` は
  ファミベでは `?SN ERROR` (Syntax error) になる、連載者検証)
- LLM が他の BASIC 方言の感覚で `LET` を付けないよう注意

重要な制約:
- 行頭から開始 (代入文は行番号の直後に書く)
- **複数代入はできない** (`A = B = 0` は不可)
- マルチステートメント (`:`) で並べる方式: `A = 0: B = 0`

<!-- probe-observed:start id=statements/assignment -->
**観察例** (nesemu 実機検証):

代入は変数 = 式の形のみ。LET キーワードは使えない (ERROR_SN 参照)。

```basic
10 A=5:PRINT A
```

出力:

```
   5
```
<!-- probe-observed:end -->


*タグ*: 代入, 基本, 制約

### `PRINT`

画面に計算結果や数値・文字を表示

**構文**: `PRINT [式 [{,|;} 式...]] [{,|;}]`

**引数**:
- `式` (数値式 | 文字列 | 変数) *(任意)*: 表示する値。複数指定可

略号: `?` (クエスチョンマーク) または `P.`

区切り記号の挙動:
- **カンマ `,`**: 次の値を **6 文字間隔のタブ位置** に揃えて出力
- **セミコロン `;`**: 次の値を **密着** して出力
- **末尾の `,` または `;`**: **改行を抑制** する
- 末尾に区切りがなければ自動改行

出力フィールド:
- 画面幅 28 文字を **8 + 8 + 8 + 4** の 4 ブロックに分けて表示する
  — ブロック先頭は 0, 8, 16, 24

フォーマット:
- 数値は前後に 1 文字分のスペースが入る (符号用)
- PRINT (引数なし) は空行を出力

<!-- probe-observed:start id=statements/print-comma -->
**観察例** (nesemu 実機検証):

PRINT のカンマ区切りは次の値を 8 文字間隔のタブ位置に揃える (画面幅 28 = 8+8+8+4 ブロック)。

```basic
10 PRINT "A","B","C","D","E"
```

出力:

```
  A      B      C      D
  E
```
<!-- probe-observed:end -->

<!-- probe-observed:start id=statements/print-semi -->
**観察例** (nesemu 実機検証):

セミコロンは値どうしを密着して出力。

```basic
10 PRINT "A";"B";"C"
20 PRINT 1;2;3
```

出力:

```
  ABC
   1 2 3
```
<!-- probe-observed:end -->

<!-- probe-observed:start id=statements/print-string -->
**観察例** (nesemu 実機検証):

PRINT に文字列リテラルを渡すと改行付きで 1 行に表示する。

```basic
10 PRINT "HELLO"
```

出力:

```
  HELLO
```
<!-- probe-observed:end -->


*タグ*: 出力, 基本, 必須

### `INPUT`

キーボードから数値や文字を入力して変数に代入

**構文**: `INPUT ["文字列";] 変数 [, 変数...]`

**引数**:
- `文字列` (文字列リテラル) *(任意)*: プロンプトとして表示する文字列。`;` で変数と区切る
- `変数` (変数 (数値・文字列)): 入力値を受け取る変数。複数指定可 (カンマ区切りで一度に複数入力)

略号: `I.`

挙動:
- プロンプト文字列指定時、その後ろに `?` が自動表示される
- **`?` を出さないようにするには `,` (カンマ) で文字列と変数を区切る** (代わりに `:` も)
- 変数複数指定時、ユーザは `,` で区切って一度に入力する
- **入力値の数は変数の数と一致させる必要がある**
- **数値変数に文字列を入れた場合は 0 が代入される** (再入力要求にはならない)

LLM 向け:
- プロンプトに `?` が付くのは BASIC の伝統。気にしないでよい
- 数値型と文字列型を混ぜないこと

<!-- probe-observed:start id=statements/input-string -->
**観察例** (nesemu 実機検証):

INPUT は "NAME?" のプロンプトでブロッキング入力待ちになる (プロンプト文字列の後に `?` が自動付加)。inject_keys で H/E/L/L/O を順に押下し、最後に RETURN で確定 → BASIC が続行して `HI HELLO` を PRINT する。実機観察で screen に `NAME?HELLO` → `HI HELLO` が出ることを確認。

```basic
10 INPUT "NAME";A$
20 PRINT "HI ";A$
```

出力:

```
  NAME?HELLO
  HI HELLO
```
<!-- probe-observed:end -->


*タグ*: 入力, 基本

### `LINPUT`

キーボードから 1 行分の文字を入力 (改行まで)

**構文**: `LINPUT ["文字列";] 文字変数`

**引数**:
- `文字列` (文字列リテラル) *(任意)*: プロンプト
- `文字変数` (文字列変数 (`$` 付き)): 入力結果が入る変数

略号: `L.IN.`

INPUT との違い:
- **`,` や `:` をそのまま入力できる** (INPUT は区切り扱いされる)
- **末尾改行までを 1 つの文字列として取込む**
- 数値変数には使えない (文字列専用)
- メッセージや 1 行コメント入力に向く

LLM 向け:
- 「何でもよい 1 行入力」が必要なら LINPUT を選ぶ
- INPUT との使い分けは「区切り文字を入力したいか」が基準

<!-- probe-observed:start id=statements/linput-string -->
**観察例** (nesemu 実機検証):

LINPUT は改行までを 1 つの文字列として読む (INPUT と違い `,` `:` を区切り扱いしない)。INPUT との挙動差: **LINPUT はプロンプト後に `?` を自動付加しない** — 実機観察では `MSG` の直後に入力が始まり screen は `MSGTEST` となる。また `[` `]` ブラケットは **FB の表示文字セットに含まれず screen 上で空白として描画される** (PRINT "[" "]" を typing しても見た目には空白)。

```basic
10 LINPUT "MSG";A$
20 PRINT "[";A$;"]"
```

出力:

```
  20 PRINT "    ";A$;"    "
  MSGTEST
      MSGTEST
```
<!-- probe-observed:end -->


*タグ*: 入力, 文字列

### `CLEAR_VARS`

変数および配列をすべてクリア

**構文**: `CLEAR`

略号: `CLE.`

動作:
- メモリ上のすべての変数および配列をクリア (内容を Null に戻す)
- 数値型 → 0 / 文字列型 → "" (空文字列)
- **GAME BASIC モードでは、文字型のものを Null ストリング (空文字列) にする**

重要:
- **CLEAR (引数なし)** はこの動作 — 変数初期化
- **CLEAR アドレス** はメモリ上限変更 ( の CLEAR_SYS)
- **同じ命令だが引数の有無で挙動が完全に異なる** — LLM 出力時は注意

別解:
- 同等動作: `RUN` も最初から実行時は変数初期化されるが、プログラムも実行される
- 「変数だけ消したい」場合は CLEAR

<!-- probe-observed:start id=statements/clear-vars -->
**観察例** (nesemu 実機検証):

CLEAR (引数なし) は変数・配列を全部 0 / 空文字列に戻す。

```basic
10 A=99:B$="X":CLEAR:PRINT A:PRINT "["+B$+"]"
```

出力:

```
  10 A=99:B$="X":CLEAR:PRINT A
  :PRINT "    "+B$+"    "
   0
```
<!-- probe-observed:end -->


*タグ*: 初期化, 変数, 制御

### `DIM`

配列を宣言する

**構文**: `DIM 配列名(n1[, n2])[, 配列名(n1[, n2])...]`

**引数**:
- `配列名` (識別子 (英字 + 数字最大 2 文字、`$` で文字列配列)): 配列の名前。数値配列・文字列配列いずれも可
- `n1` (数値 (整数)): 1 次元目のサイズ (添字の最大値)
- `n2` (数値 (整数)) *(任意)*: 2 次元目のサイズ (省略時は 1 次元配列)

略号: `D.`

動作:
- 配列の名前と次元、サイズを指定する
- **1 つの DIM 文で複数の配列を宣言できる** (カンマ区切り)
- **DIM 時に配列要素はクリアされる** — 数値配列は 0、文字列配列は
  ヌルストリング (`""`) で初期化される
- **配列のサイズは 0 から数える** (添字 0〜n まで使える、合計 n+1 要素)
  - 例: `DIM A(10)` → A(0), A(1), ..., A(10) の 11 要素
- **2 次元配列のみサポート** (3 次元以上は不可)
- 同じ配列を 2 度 DIM すると DD ERROR (Duplicate Definition)
- 添字が範囲外なら SO ERROR (Subscript out of range)

LLM 向け:
- 配列を使う前に必ず DIM が必要
- サイズ指定は **要素数-1**ではなく **添字の最大値**
- メモリ消費に注意 (整数 1 要素 = 2 バイト)
- 初期化は不要 (DIM 直後から `A(I) = 0` 相当の値で読める)

<!-- probe-observed:start id=statements/dim -->
**観察例** (nesemu 実機検証):

DIM A(n) は A(0)〜A(n) の n+1 要素を 0 で初期化。

```basic
10 DIM A(3):A(1)=7:PRINT A(0);A(1);A(2);A(3)
```

出力:

```
   0 7 0 0
```
<!-- probe-observed:end -->


*タグ*: 配列, 宣言, 必須

### `GOTO`

指定した行番号に無条件にジャンプする

**構文**: `GOTO 行番号`

**引数**:
- `行番号` (数値 (定数のみ)): ジャンプ先の行番号

略号: `G.`

動作:
- 指定行に飛ぶ。最も基本的な制御構造
- **行番号は定数のみ** (式や変数では指定できない — 動的ジャンプは ON GOTO を使う)
- 飛び先の行が存在しない場合は UL ERROR (Undefined line Number)

使い分け:
- 単純な分岐 → GOTO
- 条件付き分岐 → IF-THEN GOTO
- 多分岐 → ON 文
- サブルーチン呼出 → GOSUB

LLM 向け:
- GOTO は使いすぎるとスパゲティになるが、ファミベ BASIC では構造化制御が
  乏しいので必須の道具

<!-- probe-observed:start id=statements/goto -->
**観察例** (nesemu 実機検証):

GOTO は指定行へジャンプ。

```basic
10 PRINT "A":GOTO 30
20 PRINT "B"
30 PRINT "C"
```

出力:

```
  A
  C
```
<!-- probe-observed:end -->


*タグ*: 分岐, 基本

### `GOSUB`

プログラムのサブルーチンを呼び出す

**構文**: `GOSUB 行番号`

**引数**:
- `行番号` (数値 (定数のみ)): サブルーチンの開始行番号

略号: `GOS.`

動作:
- 指定行にジャンプし、**RETURN 文** が実行されたら呼出元の次の文に戻る
- **メインプログラムから複数回呼出可能** — 共通処理に有用
- **ネスティング (サブルーチン内サブルーチン) 可能** — メモリ範囲内で制限なし

重要:
- サブルーチンの最後に **必ず RETURN** を書く (なければ NF / RG ERROR)
- **GOSUB 文 → メインプログラム本体終了 → サブルーチン側へ流れ込む** という
  事故を防ぐため、メイン部の最後に **STOP / END** を書くのが流儀
- サブルーチン呼出に注意をつける場合「REM」は使用できない (代わりに `'`)

伝統的な配置:
- メインプログラム: 100-999
- サブルーチン: 1000-1999, 2000-2999, ...

<!-- probe-observed:start id=statements/gosub-return -->
**観察例** (nesemu 実機検証):

GOSUB は指定行を呼出し、RETURN で呼出元の次に戻る。

```basic
10 GOSUB 100:PRINT "AFTER":END
100 PRINT "SUB":RETURN
```

出力:

```
  SUB
  AFTER
```
<!-- probe-observed:end -->


*タグ*: 分岐, サブルーチン

### `RETURN`

サブルーチンの実行を終了し、呼出元に戻る

**構文**: `RETURN [行番号]`

**引数**:
- `行番号` (数値 (定数)) *(任意)*: 戻り先の行番号 (省略時は GOSUB の次の文に戻る)

略号: `RE.`

動作:
- サブルーチンの最後に書く
- 引数なし: 通常の戻り (GOSUB の次の文へ)
- 引数あり: **指定行に戻る** (通常の戻りと違う場所へ)
- 対応する GOSUB がない状態で実行すると **RG ERROR** (RETURN without GOSUB)

LLM 向け:
- サブルーチンの末尾に必ず必要
- 引数付き RETURN は珍しい使い方 — 通常は引数なし

*タグ*: 分岐, サブルーチン

### `IF_THEN`

条件分岐

**構文**: `IF 式 THEN {行番号|文}
IF 式 GOTO 行番号
`

**引数**:
- `式` (論理式 (関係式や AND/OR の組み合わせ)): 真偽を判定する式 (真 = -1, 偽 = 0)
- `行番号 / 文` (数値 (行番号) または BASIC 文): 条件が真の場合の動作。GOTO 行番号 形式または直接文を書く

略号: `IF.-T.`

挙動:
- **式が真 (≠ 0) の場合**: THEN 以降を実行
- **式が偽 (= 0) の場合**: 同じ行の残りを実行せず、次の行へ
- **THEN 行番号** = **THEN GOTO 行番号** = **GOTO 行番号** (3 通りの書き方が等価)

例 (3 通り全部同じ意味):
```
IF X = 10 THEN 500
IF X = 10 THEN GOTO 500
IF X = 10 GOTO 500
```

THEN の後ろに直接文を書く形式:
```
IF A = 0 THEN PRINT "ZERO"
```
この場合、**ELSE 句はない** ので、否定パターンは別 IF か後続行で処理する。

LLM 向け:
- **ELSE 句がない** ので、二択は IF + GOTO + 行番号で書く
- 複合条件は AND / OR で連結 (例: `IF X > 0 AND X < 10 THEN ...`)
- 真偽値が -1/0 なので、`IF X` (X が 0 でなければ真) も使える

フローチャートで表現:
- IF の判断結果が NO → 次の行へ流れる
- IF の判断結果が YES → THEN の後を実行

<!-- probe-observed:start id=statements/if-then-false -->
**観察例** (nesemu 実機検証):

条件が偽 (= 0) のとき THEN 以降を飛ばす。

```basic
10 IF 3>5 THEN PRINT "NO":REM does nothing
20 PRINT "DONE"
```

出力:

```
  10 IF 3>5 THEN PRINT "NO":RE
  M DOES NOTHING
  DONE
```
<!-- probe-observed:end -->

<!-- probe-observed:start id=statements/if-then-true -->
**観察例** (nesemu 実機検証):

条件が真 (≠ 0) のとき THEN 以降を実行。

```basic
10 IF 5>3 THEN PRINT "YES"
```

出力:

```
  YES
```
<!-- probe-observed:end -->


*タグ*: 分岐, 条件, 必須

### `FOR_NEXT`

指定回数の繰返しループ

**構文**: `FOR i = m TO n [STEP s]
  ...
NEXT [i]
`

**引数**:
- `i` (数値変数): ループカウンタ変数
- `m` (数値式): 初期値
- `n` (数値式): 終値
- `s` (数値式) *(任意)*: 増分値 (デフォルト = 1、負数で減算)

略号: `F.-TO-ST.` (FOR-TO-STEP), `N.` (NEXT)

動作:
- i に m を代入してループ開始
- ループ末尾の NEXT に到達したら i に s を加算
- i が n を超えたらループ終了 (s が負なら下回ったら)
- **STEP 省略時は s = 1**

多重ループ (ネスト):
- 内側ループから外側ループへの飛び出しは可能だが、ネスト崩れに注意
- **NEXT に対応する FOR がないと NF ERROR** (NEXT without FOR)

- **`NEXT I` のような変数指定はできない** — `NEXT` のみで書く
  (一般的な BASIC で許される `NEXT I` はファミベでは構文エラー、
  連載者検証)
- LLM が他言語感覚で `NEXT I` を付けないよう注意

LLM 向け:
- 範囲は m ≤ n かつ STEP > 0 (または m ≥ n かつ STEP < 0) になるように
- **m と n が同じなら 1 回だけ実行**
- **m が n を初めから超えていてもループ本体は 1 回実行される** (NS-HUBASIC の挙動 — 要検証)

<!-- probe-observed:start id=statements/for-next -->
**観察例** (nesemu 実機検証):

FOR/NEXT の基本ループ。NEXT に変数指定を付けると ?SN ERROR になるので、NEXT 単独で書く。

```basic
10 FOR I=1 TO 5
20 PRINT I
30 NEXT
```

出力:

```
   1
   2
   3
   4
   5
```
<!-- probe-observed:end -->


*タグ*: 繰返し, 制御, 必須, 制約

### `True`

式の値によって複数の行番号にジャンプ (計算分岐)

**構文**: `ON 式 GOTO 行番号, 行番号, ...
ON 式 GOSUB 行番号, 行番号, ...
ON 式 RETURN 行番号, 行番号, ...
ON 式 RESTORE 行番号, 行番号, ...
`

**引数**:
- `式` (数値式 (整数)): 1 ベースのインデックス値
- `行番号` (数値 (定数のみ)): 飛び先候補 (複数指定)

略号: `O.`

動作:
- 式の値が 1 → 1 番目の行番号、2 → 2 番目、... と飛び分ける
- **式の値が 0、または範囲外 (リスト数を超える) の場合: 何も飛ばずに次の行へ進む**
- **式の値が小数の場合は整数部分を使う**
- GOTO / GOSUB / RETURN / RESTORE の 4 種類と組み合わせ可能

LLM 向け:
- **インデックスは 1 始まり** (0 でも GOTO せず次行へ)
- 多分岐 (switch / case 相当) が必要なときに使う
- C 言語の switch とは異なり、ケースは行番号でしか指定できない

等価表現:
- `ON X GOTO 1000, 2000, 3000` は以下と等価:
  ```
  IF X = 1 THEN 1000
  IF X = 2 THEN 2000
  IF X = 3 THEN 3000
  ```

<!-- probe-observed:start id=statements/on-goto -->
**観察例** (nesemu 実機検証):

ON 式 GOTO n1,n2,... は式の値で n 番目の行へ飛ぶ (1 始まり)。

```basic
10 ON 2 GOTO 100,200,300
100 PRINT "ONE":END
200 PRINT "TWO":END
300 PRINT "THREE":END
```

出力:

```
  TWO
```
<!-- probe-observed:end -->


*タグ*: 分岐, 計算分岐

### `STOP`

プログラムの実行を止める

**構文**: `STOP`

略号: `STO.`

動作:
- 実行中のプログラムを STOP の位置で停止 (BREAK と同等)
- **`BREAK IN <行番号>` のメッセージを表示**
- 停止後は **CONT で再開可能** (END とは違う)
- デバッグや一時停止に使う

LLM 向け:
- 「ここで止めて変数を見たい」場合に挿入
- END (再開不可) との使い分け
- CONT で再開できるのが特徴

<!-- probe-observed:start id=statements/stop -->
**観察例** (nesemu 実機検証):

STOP で停止すると BREAK IN <line> が表示される。

```basic
10 PRINT "BEFORE":STOP:PRINT "AFTER"
```

出力:

```
  BEFORE
  BREAK IN 10
  OK.
```
<!-- probe-observed:end -->


*タグ*: 制御, デバッグ

### `END`

プログラムの実行の終了を意味する

**構文**: `END`

略号: `E.`

動作:
- END でプログラムの実行を終了させる
- **コマンドモード (READY 表示) になる**
- **CONT による継続不可** (CC ERROR になる)
- END でプログラムを書きすぎると、どこからでも続けられなくなる
  → プログラムの最後の END で活用すること

STOP との違い:
- STOP: 一時停止、CONT で再開可能
- END: 終了、CONT 不可

LLM 向け:
- メイン部の最後に END を入れて、サブルーチンに流れ込まないようにする
- これは GOSUB の項目 と整合

<!-- probe-observed:start id=statements/end -->
**観察例** (nesemu 実機検証):

END で正常終了 (BREAK メッセージなし)。

```basic
10 PRINT "DONE":END:PRINT "NEVER"
```

出力:

```
  DONE
```
<!-- probe-observed:end -->


*タグ*: 制御, 終了

### `SWAP`

2 つの変数の内容を交換する

**構文**: `SWAP 変数A, 変数B`

**引数**:
- `変数A` (変数): 1 つ目の変数
- `変数B` (変数): 2 つ目の変数

略号: `SW.`

動作:
- 2 つの変数の内容を交換 (たとえば SWAP A, B で A と B が入れ替わる)
- **両変数の型が同じ必要** (数値同士、文字列同士)
- 異種型ペアの場合 → SWAP A, B は不可 (エラー)
- 配列要素も指定可: `SWAP A(I), A(J)`

LLM 向け:
- 古典的な「temp 経由スワップ」が不要になる便利な命令
- ソート系のアルゴリズムで重宝

<!-- probe-observed:start id=statements/swap -->
**観察例** (nesemu 実機検証):

SWAP A, B は A と B の値を入れ替える。

```basic
10 A=1:B=2:SWAP A,B:PRINT A;B
```

出力:

```
   2 1
```
<!-- probe-observed:end -->


*タグ*: 代入, 交換

### `REM`

プログラム文にコメントを入れる

**構文**: `REM コメント`

**引数**:
- `コメント` (任意の文字列) *(任意)*: 任意のコメント文 (255 文字まで、`'` での終了不可)

略号: `'` (シングルクォート) または `REM.` (R は不可だが REM. は可)

動作:
- **REM 以降、行末まではコメントとして無視される** (実行されない)
- REM の後ろに任意の文字列・255 文字以下を書ける
- **`:` で区切って後ろに別の文を書くことはできない** (REM の後ろは全部コメント)

`'` 形式:
- **シングルクォート `'` で代用可能**
- REM だと「`:`」を使ったマルチステートメントの後のコメントが書けないが、
  `'` の場合は `:` で区切って書ける場合があるかもしれない (要検証)

LLM 向け:
- プログラム冒頭にプログラム名を REM で書くのが流儀
- 行内にコメントを残したい場合は `:REM ...` または `:'...`

<!-- probe-observed:start id=statements/rem -->
**観察例** (nesemu 実機検証):

REM 以降は実行されない。

```basic
10 REM THIS IS A COMMENT
20 PRINT "X"
```

出力:

```
  X
```
<!-- probe-observed:end -->


*タグ*: コメント, 構文

### `READ`

DATA 文で用意されたデータを READ して変数に入れる

**構文**: `READ 変数 [, 変数, ...]`

**引数**:
- `変数` (数値変数 または 文字列変数): データを受け取る変数 (複数指定可)

略号: `REA.`

動作:
- **DATA 文で書かれたデータの値を順番に読む**
- 内部に「DATA ポインタ」があり、READ するたびに 1 つ進む
- 全 DATA を使い切ると **OD ERROR** (Out of DATA)
- **数値変数には数値、文字列変数には文字列を読む** (型不一致は TM ERROR)
- **DATA 文はプログラムのどこに置いてもよい** — まとめて末尾に置くのが流儀
- 読み直しは RESTORE 文 で実現

LLM 向け:
- DATA / READ ペアで初期データテーブルを実装
- 配列とは違って読み取り専用 (READ で読み出し→ 変数に格納)
- メモリ効率が良いので、テーブルデータには最適

<!-- probe-observed:start id=statements/read-data -->
**観察例** (nesemu 実機検証):

READ は DATA 文の値を順番に取り出す。

```basic
10 READ A,B,C:PRINT A;B;C
20 DATA 10,20,30
```

出力:

```
   10 20 30
```
<!-- probe-observed:end -->


*タグ*: 入力, データ

### `DATA`

READ で読み込むデータを書く

**構文**: `DATA 定数 [, 定数, ...]`

**引数**:
- `定数` (数値定数 (-32768〜+32767) または 文字列 (文字列定数)): 1 つ以上のデータ値 (カンマ区切り)

略号: `D.`

動作:
- DATA 文は実行されるステートメントではない (DATA 文に到達しても何もしない)
- **READ 文によって順番に読み込まれる** (1 つから何百でも書ける)
- 行のどこに書いてもよい (プログラム途中 or まとめて末尾)

値の表記:
- **数値**: 範囲は -32768〜+32767、文字列とは違って `"` で囲まない
- **文字列**: いくつかのことに留意:
  1. **`"` で囲む** か、または **空白なしで直接** 書く (例: `DATA ABC,DE`)
  2. **`,` (カンマ)、`:` (コロン) は使えない** (区切り記号と混同される)
  3. **「,」「:」を含めるなら `"` で囲む** (例: `DATA "ABC,DE"`)

例 (微妙な動作):
- `DATA ABC, DE, : ,F` → 4 つの文字列 `"ABC"`, `"DE"`, `""`, `"F"`
- `DATA "ABC", "DE", "" ,"F"` → 同じ意味で明示的

LLM 向け:
- **`"` 囲みなしの文字列は前後の空白がトリミングされる** (要検証)
- 数値と文字列を混在させない方が安全

*タグ*: データ, 定数

### `RESTORE`

READ で読むデータ位置を巻き戻す

**構文**: `RESTORE [行番号]`

**引数**:
- `行番号` (数値 (定数)) *(任意)*: 巻き戻す DATA 文の行番号 (省略時は最初の DATA 文)

略号: `RES.`

動作:
- DATA ポインタを指定行 (or 最初) に戻す
- これによって **同じ DATA を 2 度読める**
- 行番号を指定すると、その行以降の DATA から読み始める
- **指定行に DATA 文がなくても、その行以降の最初の DATA から読み始める**

LLM 向け:
- DATA を複数回ループで使うときに必須
- 配列を 2 回初期化したい等のケース

<!-- probe-observed:start id=statements/restore -->
**観察例** (nesemu 実機検証):

RESTORE は READ 用ポインタを先頭に戻す。

```basic
10 READ A:RESTORE:READ B:PRINT A;B
20 DATA 7
```

出力:

```
   7 7
```
<!-- probe-observed:end -->


*タグ*: データ, 巻き戻し

### `CALL`

マシン語サブルーチンを呼び出す

**構文**: `CALL アドレス`

**引数**:
- `アドレス` (数値 (16bit, アドレス値)): マシン語サブルーチンの先頭アドレス

略号: `CA.`

動作:
- 指定アドレス (`&H0000`-`&HFFFF`) に格納されたマシン語ルーチンを呼出
- 戻り値はマシン語側の責任 (BASIC は知らない)
- **マシン語サブルーチンは事前に POKE 等で配置するか、ROM 内ルーチン**
- 配置領域は CLEAR 文 (システムコマンド版) でメモリ上限を縮めて確保
- **CLEAR で指定したアドレス以下に配置すれば BASIC とは別に保護される**

LLM 向け:
- 通常の BASIC コーディングでは出番が少ない
- 高速化や PPU 直接操作が必要なときに使う上級機能
- ROM 内のサブルーチン呼出 (例: BIOS 関数) は知識が必要

*タグ*: マシン語, 上級, 呼出

### `POKE`

メモリに 1 バイトのデータを書き込む (←→ PEEK)

**構文**: `POKE アドレス, データ [, データ, ...]`

**引数**:
- `アドレス` (数値 (16bit, アドレス値)): 書き込み先のメモリアドレス
- `データ` (数値 (0〜255 = &H00〜&HFF)): 書き込む 1 バイト値 (複数指定で連続書込)

略号: `PO.`

動作:
- **メモリの指定アドレスに 1 バイト書き込む** (メモリマップ参照)
- **複数データ指定で連続バイト書込が可能** (1 つずつ POKE するより高速)
- データ値は 0〜255 (8 ビット)
- **POKE できる領域はメモリマップで「使用可能」とされた範囲のみ**
- **`&H7000`-`&H703F` のシステム予約領域は POKE 不可** (参照)
- **POKE で BASIC プログラム本体 (`&H7600`-) を上書きすると暴走の可能性**

LLM 向け:
- スプライトの直接配置、メモリ上のテーブル準備、マシン語コード書込等で使う
- メモリマップ を必ず参照
- 不明な領域への POKE は危険

<!-- probe-observed:start id=statements/poke-peek -->
**観察例** (nesemu 実機検証):

POKE addr,value でメモリ書き込み、PEEK(addr) で読み戻し。実機観察: `POKE &H7100,123` → `PEEK(&H7100)` で `123` が返る。BASIC ユーザ領域 (&H7100 付近) は安全に POKE できる。これでマシン語埋め込み / 任意メモリ操作の基盤が確認できる。

```basic
10 POKE &H7100,123
20 PRINT PEEK(&H7100)
```

出力:

```
   123
```
<!-- probe-observed:end -->


*タグ*: メモリ, 書込, 上級

### `LOCATE`

カーソルを指定位置へ移動

**構文**: `LOCATE x, y`

**引数**:
- `x` (数値 (0-27)): 水平方向 (列)
- `y` (数値 (0-23)): 垂直方向 (行)

略号: `LOC.`

動作:
- **バックグラウンド面のカーソル位置を指定**
- x = 0-27 (28 列)、y = 0-23 (24 行)。範囲外指定は無視 or エラー
- 続く PRINT 文等の出力位置がここから始まる

座標系:
- 画面サイズは 28 × 24 文字 (SPEC_GRAPHICS_RESOLUTION)
- 左上が (0, 0)、右下が (27, 23)

<!-- probe-observed:start id=statements/locate-basic -->
**観察例** (nesemu 実機検証):

LOCATE x,y はカーソルを (x,y) に動かす。x は列 (0-27)、y は行 (0-23)。

```basic
10 LOCATE 10,5:PRINT "X"
20 LOCATE 3,15:PRINT "HELLO"
```

出力:

```
            X
     HELLO
```
<!-- probe-observed:end -->


*タグ*: 画面, カーソル, 必須

### `COLOR`

バックグラウンド画面に表示する文字の配色番号と背景色を指定

**構文**: `COLOR x, y, n`

**引数**:
- `x` (数値 (0-27)): 水平方向のカラム (列)
- `y` (数値 (0-23)): 垂直方向の行
- `n` (数値 (0-3)): バックグラウンド面のカラーパレット番号 (0-3 のいずれか)

略号: `COL.`

動作:
- 指定位置 (x, y) からのキャラクタの **カラーパレット番号** を変更
- n = 0-3 のいずれか (詳細は CGSET / PALET 参照)
- 既存の文字色を変えるが、新規 PRINT 出力にも適用される

依存:
- **BG GRAPHIC 上での色は CGSET と CALR (CALR-CHART) の組合せで決まる**
- CGSET でカラーパレットを指定しても、COLOR 文でエリアごとに上書き可

色の指定範囲はエリア単位で限定:
- LOCATE で示した位置のエリアに、配色番号を指定する
- 大きな範囲 (10x10 など) を指定したい場合は、複数 COLOR を使う

例: `COLOR 10, 10, 3`
- x, y で指定した (10, 10) にあるキャラクタのカラーが 3 番カラーパレット
  (CGEN, CGSET, BG, PALET の関係で表示される) で表示される

<!-- probe-observed:start id=statements/color-fg -->
**観察例** (nesemu 実機検証):

COLOR x,y,n は (x,y) のセルに BG パレット番号 n (0-3) を割り当てる。文字色そのものではなくセル単位の配色属性を変える。色の差は video で観察。

```basic
10 CLS
20 LOCATE 5,5:PRINT "ABCD"
30 COLOR 5,5,1
40 COLOR 6,5,2
50 COLOR 7,5,3
```

出力:

```
       ABCD
```
<!-- probe-observed:end -->


*タグ*: 画面, 色, 必須

### `CGEN`

バックグラウンド面とスプライト面にキャラクタの割り当てを切り替える

**構文**: `CGEN n`

**引数**:
- `n` (数値 (0-3)): キャラクタジェネレータの組み合わせ番号 (0〜3)

略号: `CGE.`

動作:
- **キャラクタの組み合わせ (CGEN1 / CGEN2 系) を切替える**
- CGEN テーブル (キャラクタテーブルA はスプライト、B はバックグラウンド)
  の組み合わせを 4 通り (n=0,1,2,3) から選択

| n | バックグラウンド | スプライト | 説明 |
|---|----------------|-----------|------|
| 0 | A | A | 両方アニメ |
| 1 | A | B | 標準 (V3 系)|
| 2 | B | A | 入替 |
| 3 | B | B | 両方文字 |

デフォルト: **CGEN2** (起動直後の状態)
- 文字主体の表示は CGEN2 = テーブル A 文字 + テーブル B 文字 系統
- グラフィック主体: CGEN1 / CGEN3 等

注意:
- **(CTR)+(D) で CGEN は 2 の組合せに再設定される** (リセット相当)

<!-- probe-observed:start id=statements/cgen-modes -->
**観察例** (nesemu 実機検証):

CGEN n でキャラクタジェネレータを切替 (0=BG GRAPHIC、1=アルファベット、2=両方)。同じ文字でも字形が変わる (差は video で観察)。

```basic
10 CGEN 0:PRINT "A"
20 CGEN 1:PRINT "A"
30 CGEN 2:PRINT "A"
```

出力:

```
  A
  A
  A
```
<!-- probe-observed:end -->


*タグ*: 画面, キャラクタ

### `CLS`

画面をクリアする

**構文**: `CLS`

略号: `CL.`

動作:
- **バックグラウンド面 (BG GRAPHIC) を含む全部のテキスト画面をクリア**
- スプライトはクリアされない (SPRITE OFF で消す)
- **(CTR) + (L) と等価**

LLM 向け:
- 画面更新の前に CLS で初期化
- スプライトと組み合わせる場合は SPRITE OFF と組み合わせて使う

<!-- probe-observed:start id=statements/cls-clears -->
**観察例** (nesemu 実機検証):

CLS は画面を消去する。実行後は CLS 前の出力が見えなくなる。

```basic
10 PRINT "BEFORE"
20 CLS
30 PRINT "AFTER"
```

出力:

```
  AFTER
```
<!-- probe-observed:end -->


*タグ*: 画面, 初期化, 必須

### `CGSET`

BG とスプライトで使用するパレットの組合せを決める

**構文**: `CGSET [m][, n]`

**引数**:
- `m` (数値 (0-1)) *(任意)*: バックグラウンド面のパレットコード (0-1)
- `n` (数値 (0-2)) *(任意)*: スプライト (アニメキャラクタ) 用のパレットコード (0-2)

略号: `CG.`

動作:
- 表示で使用される BG とスプライトの **パレットセット** を選ぶ
- **m**: BG 用パレットの組合せ (0 or 1)
- **n**: スプライト用パレットの組合せ (0, 1, or 2)
- 両方ともデフォルトは 0、引数省略時は **m=1, n=1**

パレット階層:
- 各パレット セットは 4 つの色レジスタ (CGEN/CGSET 系) で構成
- **m, n** で大きく 2-3 種類のパレットセットを切替
- 個別の色変更は **PALET / B.PAL** 文

LLM 向け:
- 画面構築の最初に CGSET でパレット選択
- その後 PALET で個別色を調整
- DEF SPRITE / DEF MOVE で「何番のパレットを使うか」を指定して描画

*タグ*: 画面, 色, パレット

### `PALET`

配色番号の色コードを任意の色コードに設定する

**構文**: `PALET[B|S] n, C1, C2, C3, C4`

**引数**:
- `B|S` (サフィックス) *(任意)*: B=バックドロップ (背景全体), S=スプライト/アニメキャラクタ用、無印=通常
- `n` (数値 (0-3)): 配色 (パレット) 番号
- `C1, C2, C3, C4` (数値 (0-3F の色コード, 各 4 つ)): 4 つの色コード (パレット内の色 1, 中, 2, 3 に対応)

略号: `PAL.B`, `PAL.S`

動作:
- パレット n の色を C1, C2, C3, C4 で再定義
- **C1〜C4 は 0〜&H3F (52 色のマスタパレットから選択)**
- **PALET.B**: バックドロップ (全画面背景色) を変える
- **PALET.S**: スプライト用パレットを変える
- **PALET (無印)**: 通常の BG 用パレット

色コード一覧 (簡易):
| 色コード | 色 | 色コード | 色 |
|---------|----|---------|----|
| 00 | 黒 | 30 | 白 |
| 04 | 青 | 32 | 灰 |
| 06 | 紫 | 33 | (中間色) |
| 08 | 赤 | 36 | 灰青 |
| 0C | 茶 | 38 | 緑 |
| 0F | (なし) | 3F | (なし) |

(実際は 52 色 / マスタテーブル参照)

LLM 向け:
- **DEF SPRITE / DEF MOVE のパレット引数で n を指定して、その色で描画**
- 同じスプライトでも n を変えれば色違いができる
- PALET の引数は固定で 4 色 (C1, C2, C3, C4 必須)

例:
`PALET 3, &H30, &HC, &H1A, &H12`
→ パレット 3 の色を:
- C1: 白 (&H30)
- C2: 茶 (&HC)
- C3: (&H1A の色)
- C4: (&H12 の色)
として再定義

<!-- probe-observed:start id=statements/palet-bg -->
**観察例** (nesemu 実機検証):

PALETB n,C1,C2,C3,C4 は BG パレット n (0-3) の 4 色をマスタテーブルのコード (0-3F) で指定。色変化は video で観察。

```basic
10 PALETB 0,&H0F,&H16,&H27,&H30
20 PRINT "PALET SET"
```

出力:

```
  PALET SET
```
<!-- probe-observed:end -->


*タグ*: 画面, 色, パレット

### `DEF_MOVE`

アニメキャラクタの動きを定義する

**構文**: `DEF MOVE(n) = SPRITE(A, B, C, D, E, F)`

**引数**:
- `n` (数値 (0-7)): 動作番号 (0-7 の 8 通りの動きパターンを登録可)
- `A` (数値 (0-15)): アニメキャラクタの種類 (例: 0=マリオ、1=レディ、2=ファイターフライ等)
- `B` (数値 (0-8)): 動きの方向 (8 方向 + 静止)
- `C` (数値 (1-255)): 動きの速さ (1=最高速、255=最低速。0 は表示しない)
- `D` (数値 (1-255)): 動きの全体距離 (フレーム数 / ピクセル数)
- `E` (数値 (0-1)): 0=バックドロップから後ろ (背景の後ろ)、1=スプライト面 (背景の手前)
- `F` (数値 (0-3)): 配色 (パレット) 番号

略号: `DE.M.`

動作:
- **動作 n (0-7) に「アニメキャラクタの動き」を登録**
- 8 つまでの動作パターンを並行登録可能
- 各動作パターンは: キャラクタ A、方向 B、速さ C、距離 D、レイヤー E、色 F の 6 要素

アニメキャラクタの種類 (A):
| A | キャラ | A | キャラ |
|---|--------|---|--------|
| 0 | マリオ | 8 | スターキラー |
| 1 | レディ | 9 | スターシップ |
| 2 | ファイターフライ (ハエさん) | 10 | 爆発 |
| 3 | アキレス | 11 | ニタニタ |
| 4 | ペンペン (ペンギンさん) | 12 | レーザー (8×8 単タイル) |
| 5 | ファイアーボール | 13 | シェルクリーパー (カメさん) |
| 6 | 車 | 14 | サイドステッパー (カニさん) |
| 7 | スピナー | 15 | ニットピッカー (トリさん) |

詳細マッピング (キャラ × ポーズ × CHR$ コード) は
`SPRITE_CHARACTER_MAP` (16×16) と `SPRITE_8X8_LASERS` (8×8 レーザー) 参照。

動きの方向 (B):
- 8 方向 (上 / 上右 / 右 / 右下 / 下 / 左下 / 左 / 上左)
- **0=静止**

動きの速さ (C, 0-255):
- **C×1/30** 秒で動く (約 30 フレーム/秒なので、C=30 で 1 秒)
- **C=0 は表示なし** (動きが見えない)

動きの距離 (D, 1-255):
- 1 ドット = 1/255 秒 / フレーム
- **D=255 で動き続ける** (停止しない)

レイヤー (E):
- **E=0**: バックドロップ (背景) より後ろ
- **E=1**: スプライト面 (背景より手前 = 通常)

配色番号 (F, 0-3):
- パレット番号 (CGSET, PALET 系)
- スプライト用パレットから 4 つのいずれかを選ぶ

*タグ*: スプライト, MOVE, 必須

### `MOVE`

アニメキャラクタの動きを開始させる

**構文**: `MOVE n0 [, n1, n2, n3, n4, n5, n6, n7]`

**引数**:
- `n0..n7` (数値 (0-7、DEF MOVE で定義した動作番号)) *(任意)*: 動作番号。1〜8 個まで指定可

略号: `M.`

動作:
- **DEF MOVE で定義した動作番号 n0..n7 のスプライトを動かし始める**
- 同時に最大 8 個まで動かせる (n0 から n7 までを並列指定)
- **すでに SPRITE ON でスプライト表示状態にしておく必要あり**
- 動作中の SPRITE は BASIC プログラムと同時 (並列) に動く
- **MOVE 文が完了するまで処理を止めない** — つまり MOVE 後すぐに次の文が実行される

LLM 向け:
- DEF MOVE で定義 → SPRITE ON → MOVE n で動作開始
- 動作中は BASIC のメインプログラムは別の処理を走らせられる
- スプライトの位置を取りたい場合は POSITION / XPOS / YPOS 関数

<!-- probe-observed:start id=sprites/move-basic -->
**観察例** (nesemu 実機検証):

DEF MOVE(0)=SPRITE(A,B,C,D,E,F) で動作 0 を登録 (A=キャラ種, B=方向, C=速度, D=距離, E=面, F=パレット)、POSITION で初期座標、MOVE 0 で動き始める。MOVE は並列実行で次の文へすぐ進む。観察結果: (1) **B=3 = 右方向**で x が増え y は固定 100 のまま、(2) C=8 の移動速度は **30 frames あたり +4px** ≈ 1px per 8 frames で reference の「C=1 最高速、255 最低速」と整合、(3) **MOVE スプライトは OAM の i=32-35 を使用** (静的 SPRITE の i=0-3 とは別系統で衝突しない)、(4) アニメ 3 ポーズが 30 frames 毎に切替: tile 0-3 → 4-7 → 8-11 → 0-3 で歩行アニメを構成、(5) attr=112 = H反転 bit6 + 優先 bit5 + bit4 (= MOVE 由来とみられる識別ビット?) — MOVE が右方向用のタイル並べ替えと反転フラグの両方を内部処理している。

```basic
10 SPRITE ON
20 DEF MOVE(0)=SPRITE(0,3,8,100,1,0)
30 POSITION 0,50,100
40 MOVE 0
```

出力:

```
(no output)
```

アクティブスプライト: 4 個

中間スナップショット:
  - frame 0: …0,1,0) /   30 POSITION 0,50,100 /   40 MOVE 0 /   RUN /   OK
  - frame 30: …0,1,0) /   30 POSITION 0,50,100 /   40 MOVE 0 /   RUN /   OK
  - frame 60: …0,1,0) /   30 POSITION 0,50,100 /   40 MOVE 0 /   RUN /   OK
  - frame 90: …0,1,0) /   30 POSITION 0,50,100 /   40 MOVE 0 /   RUN /   OK
  - frame 120: …0,1,0) /   30 POSITION 0,50,100 /   40 MOVE 0 /   RUN /   OK

OAM スナップショット (frame → 最初のスプライトの位置):
  - frame 0: i=32 x=52 y=100 tile=5 attr=112 (active=4)
  - frame 30: i=32 x=54 y=100 tile=9 attr=112 (active=4)
  - frame 60: i=32 x=58 y=100 tile=5 attr=112 (active=4)
  - frame 90: i=32 x=62 y=100 tile=1 attr=112 (active=4)
  - frame 120: i=32 x=66 y=100 tile=9 attr=112 (active=4)
<!-- probe-observed:end -->


*タグ*: スプライト, MOVE

### `CUT`

MOVE で動き始めたアニメキャラクタの動きを止める

**構文**: `CUT n0 [, n1, n2, n3, n4, n5, n6, n7]`

**引数**:
- `n0..n7` (数値 (0-7、DEF MOVE で定義した動作番号)) *(任意)*: 停止する動作番号。複数指定可

略号: `CU.`

動作:
- MOVE で動き始めたアニメキャラクタを停止
- **CUT してもキャラクタは画面に表示される** (位置は固定)
- スプライトを完全に消す場合は **ERA** または **SPRITE OFF**

LLM 向け:
- 一時停止 → 再開する場合 CUT → MOVE で再開
- 完全に消すなら ERA / SPRITE OFF

<!-- probe-observed:start id=sprites/move-cut -->
**観察例** (nesemu 実機検証):

MOVE 開始後に CUT n でスプライト n の動きを止める文。reference は「CUT してもキャラクタは表示される」とするが、この probe の実機観察では **最終 OAM が 0 件** で ERA と区別がつかない結果になった。要追加検証 (FOR 待機時間や CUT 後の wait 量によって挙動が変わる可能性)。

```basic
10 SPRITE ON
20 DEF MOVE(0)=SPRITE(0,3,8,100,1,0)
30 POSITION 0,50,100
40 MOVE 0
50 FOR I=0 TO 300:NEXT
60 CUT 0
```

出力:

```
(no output)
```
<!-- probe-observed:end -->


*タグ*: スプライト, MOVE

### `ERA`

MOVE で動き始めたアニメキャラクタの動きを止め、スプライト面から消す

**構文**: `ERA n0 [, n1, n2, n3, n4, n5, n6, n7]`

**引数**:
- `n0..n7` (数値 (0-7、DEF MOVE で定義した動作番号)) *(任意)*: 消す動作番号。複数指定可

略号: `ER.`

動作:
- **MOVE で動いているキャラクタを停止＋スプライト面から消去**
- CUT (停止のみ) との違い: ERA は **画面からも消える**
- 画面上の位置情報は失われる

LLM 向け:
- 「もう不要なキャラクタ」を片付けるときに使う
- 一時停止だけなら CUT
- 全部消したいなら個別に ERA、または SPRITE OFF (全消去)

<!-- probe-observed:start id=sprites/move-era -->
**観察例** (nesemu 実機検証):

ERA n は停止に加えてスプライトを画面から消す。観察では最終 OAM のアクティブが 0 件で消去を確認。なお同じテストコードで CUT も最終 OAM=0 になっており、この probe ペアでは挙動の差が見えなかった (CUT が「残す」のは reference のみの記述で、実機検証が要追加)。

```basic
10 SPRITE ON
20 DEF MOVE(0)=SPRITE(0,3,8,100,1,0)
30 POSITION 0,50,100
40 MOVE 0
50 FOR I=0 TO 300:NEXT
60 ERA 0
```

出力:

```
(no output)
```
<!-- probe-observed:end -->


*タグ*: スプライト, MOVE, 削除

### `POSITION`

MOVE で動き始める前に動きの初期座標を与える

**構文**: `POSITION n, X, Y`

**引数**:
- `n` (数値 (0-7)): DEF MOVE で定義した動作番号
- `X` (数値 (0-255)): 水平方向の初期座標 (ドット単位、0-255)
- `Y` (数値 (0-255)): 垂直方向の初期座標 (ドット単位、0-255)

略号: `POS.`

動作:
- **MOVE 文で動き始めるアニメキャラクタの初期位置を指定**
- **MOVE 文の "前" に POSITION を実行する**
- 座標系は **256 × 256 ドット** (画面は 256 × 240)
- **デフォルト: X=120, Y=120** (画面中央)
- 範囲外を指定すると画面外に出る (ラップする?要確認)

実行順序:
1. DEF MOVE — 動作の定義
2. POSITION — 初期位置の指定 (省略時 120, 120)
3. SPRITE ON — スプライト表示有効化
4. MOVE — 動作開始

LLM 向け:
- **POSITION → MOVE の順** が必須
- MOVE 後に POSITION を呼んでも次の MOVE のための準備

*タグ*: スプライト, 座標

### `KEY`

ファンクションキーに対して文字列を定義する

**構文**: `KEY ファンクションキー番号, 文字列`

**引数**:
- `ファンクションキー番号` (数値 (1-8)): F1〜F8 のいずれか
- `文字列` (文字列定数 (最大 15 文字)): 当該ファンクションキー押下時に挿入される文字列

略号: `K.`

動作:
- **F1〜F8 のキーを押した時に挿入される文字列**を再定義
- GAME BASIC 起動時のデフォルト割当 (印刷 に記載):
  | F | デフォルト |
  |---|----------|
  | F1 | LOAD(M) |
  | F2 | PRINT |
  | F3 | GOTO |
  | F4 | CHR$(M) |
  | F5 | SPRITE |
  | F6 | CONT(M) |
  | F7 | LIST(M) |
  | F8 | RUN(M) |
  
  (※ `(M)` は M キー = キャリッジリターン押下相当)

LLM 向け:
- 通常は **コーディング効率化のためのショートカット**
- プログラムから KEY を変更するのは特殊用途
- 文字列に `CHR$(13)` (改行) を含めることで「自動実行マクロ」化可能

例:
- `KEY 1, "SAVE M" + CHR$(13)` → F1 で「SAVE 〇〇 + 改行」が即実行
- `KEY 5, "DEF MOVE("` → F5 で `DEF MOVE(` 入力

<!-- probe-observed:start id=statements/key-define -->
**観察例** (nesemu 実機検証):

KEY n,"文字列" で F1〜F8 のファンクションキーに任意の文字列を割り当てる。実機観察: `KEY 1,"HELLO"` の後、INPUT 待ち中に F1 を 1 回押下するだけで `HELLO` が一気に入力バッファへ展開され、続く RETURN で確定 → A$ に HELLO が入る。screen に `X?HELLO` → `HELLO` が出ることを確認。BASIC 起動時のデフォルトは F1=LOAD(M)、F2=PRINT、F3=GOTO 等 (KEY 文で上書き可)。

```basic
10 KEY 1,"HELLO"
20 INPUT "X";A$
30 PRINT A$
```

出力:

```
  X?HELLO
  HELLO
```
<!-- probe-observed:end -->


*タグ*: 入力, ファンクションキー

### `KEYLIST`

ファンクションキーの定義状態を画面に表示

**構文**: `KEYLIST`

略号: `KL.`

動作:
- 現在のファンクションキー (F1〜F8) の割当一覧を表示
- KEY で何を設定したか確認用

*タグ*: 入力, ファンクションキー

### `PAUSE`

プログラムの実行を一時停止する (時間指定可)

**構文**: `PAUSE [n]`

**引数**:
- `n` (数値 (0-32767)) *(任意)*: 停止時間。1 単位 = 約 1/60 秒。省略時は無限 (キー入力待ち)

略号: `PA.`

動作:
- 指定秒数 (約 1/60 秒単位) プログラムを停止
- **n 省略時はキー入力があるまで停止** (PRESS 待機)
- n を指定しても、その途中でキー入力があれば即解除

LLM 向け:
- **`PAUSE 60` で 約 1 秒待機**
- フレームレート同期や遅延処理に使う
- メッセージ表示後の「キー押下待ち」にも使う

<!-- probe-observed:start id=statements/pause-timed -->
**観察例** (nesemu 実機検証):

PAUSE n はおよそ n×1/60 秒プログラムを止める (途中でキーが押されると即解除)。PRE → PAUSE 30 (約 0.5 秒) → POST。observation 上は最終 screen に PRE と POST が両方並んでおり PAUSE が正常に経過したことが分かるが、snapshot_frames は probe_runner の post-run wait 中のみ撮影されるため PAUSE 中の中間状態 (PRE のみが見える状態) は直接捕捉できない (harness の制約)。動画ではブロッキング時間が見える。

```basic
10 PRINT "PRE":PAUSE 30:PRINT "POST"
```

出力:

```
  PRE
  POST
```

中間スナップショット:
  - frame 5: …E":PAUSE 30:PRIN /   T "POST" /   RUN /   PRE /   POST /   O
  - frame 15: …":PAUSE 30:PRIN /   T "POST" /   RUN /   PRE /   POST /   OK
  - frame 25: …":PAUSE 30:PRIN /   T "POST" /   RUN /   PRE /   POST /   OK
  - frame 35: …":PAUSE 30:PRIN /   T "POST" /   RUN /   PRE /   POST /   OK
  - frame 60: …":PAUSE 30:PRIN /   T "POST" /   RUN /   PRE /   POST /   OK
  - frame 100: …":PAUSE 30:PRIN /   T "POST" /   RUN /   PRE /   POST /   OK
<!-- probe-observed:end -->


*タグ*: 制御, 待機, タイミング

### `SYSTEM`

BASIC の実行モードから GAME BASIC モード画面へ戻る

**構文**: `SYSTEM`

略号: `S.`

動作:
- GAME BASIC モードで SYSTEM コマンドを入力すると、起動時のシステム画面
  (4 ボード選択画面) に戻る
- **GAME BASIC モードでは「ON CONT」や「保存」は維持されない**
- 「1 → BASIC」を選んで GAME BASIC に再入場すると、プログラムは保持されている

LLM 向け:
- 通常のコーディングでは使わない (モード切替時専用)
- プログラム内で SYSTEM を実行すると、ユーザに対話的なメニューを表示

*タグ*: モード, システム

### `VIEW`

BG GRAPHIC 面をバックグラウンド面へコピー (複写) する

**構文**: `VIEW`

略号: `V.`

動作:
- **BG GRAPHIC 画面 (BASIC で BG GRAPHIC) で書きあげた絵をバックグラウンドへコピー**
- BASIC で起動直後の状態では、バックグラウンドの絵 (BG GRAPHIC で描いた絵) は
  表示されない
- VIEW を実行すると、現在の BG GRAPHIC 内容がバックグラウンド面にコピーされて
  表示される

LLM 向け:
- BG GRAPHIC で絵を描いた後、画面表示するために実行
- **バックグラウンド面のパレットコードは 1 (CGSET 1, 1)** で表示される

<!-- probe-observed:start id=statements/view-copy -->
**観察例** (nesemu 実機検証):

VIEW は引数なし。BG GRAPHIC 面で描いた絵をバックグラウンド面へコピーする。ここでは構文エラーにならないことだけ確認 (BG GRAPHIC を描いていないので見た目の変化はない)。

```basic
10 VIEW
20 PRINT "VIEW DONE"
```

出力:

```
  VIEW DONE
```
<!-- probe-observed:end -->


*タグ*: 画面, BG GRAPHIC

### `BEEP`

単音 (ピー音) を発生

**構文**: `BEEP`

略号: `B.`

動作:
- 「ピー」という音を 1 回鳴らす
- 効果音 (システム音) として使う
- **PAUSE / IF-THEN と組み合わせると待機時の通知音として有用**

LLM 向け:
- 最も簡単な音出し
- PLAY との使い分け: 単発の確認音 → BEEP、メロディ → PLAY

<!-- probe-observed:start id=sound/beep-basic -->
**観察例** (nesemu 実機検証):

BEEP は引数なしで「ピー」と 1 回鳴る単音。実機検証では probe_runner の APU サンプリング (3 frame 間隔) がどのチャンネルの発音も捉えられなかった — BEEP は非常に短い (数フレーム以下) ためサンプル間隔で取りこぼした可能性が高い。耳では確かに鳴っているので、video の音声トラックで確認する。

```basic
10 BEEP
```

出力:

```
(no output)
```
<!-- probe-observed:end -->


*タグ*: 音, 効果音

### `PLAY`

MML 形式のストリングデータでメロディを演奏

**構文**: `PLAY ストリングデータ [, ストリングデータ, ストリングデータ]`

**引数**:
- `ストリングデータ` (文字列 (MML)): 音符・音価・音色・テンポ等を表す MML 文字列。最大 3 つで 3 重音

略号: `PL.`

動作:
- **ストリングデータで指定する文字数列を「ストリングデータ」と呼ぶ**
- 引数を **`,` (カンマ)** で区切って **3 重音 (3 チャンネル) 同時演奏** 可能
- チャンネル A、B、C の 3 つ (CSR1 のチャンネルに対応)

### MML 表記 (主要コマンド)

| コマンド | 意味 | 範囲 |
|---------|------|------|
| `T n` | テンポ設定 | T1-T255 (高い数=遅い) |
| `O n` | オクターブ設定 | O0-O5 (00=低音, 05=高音) |
| `M n` | エンベロープ MOD 設定 | M0/M1 |
| `Y n` | デューティ効果 (音色) | Y0=12.5%, Y1=25%, Y2=50%, Y3=75% |
| `V n` | ボリューム / エンベロープ長さ | V0-V15 (V0=音なし) |
| `R 音価` | 休符 | R0-R9 |
| (音名 + 音価) | 音符 | C, D, E, F, G, A, B + 音価 (0-9) |
| `#` + 音名 | **シャープ (半音上)** | (例: `#C` = ド#) |

### 音名と対応する半音 (`#` プレフィックス)

| 音程 | 指定方法 |
|------|---------|
| ド | `C` |
| ド# (= レ♭) | `#C` |
| レ | `D` |
| レ# (= ミ♭) | `#D` |
| ミ | `E` |
| ファ | `F` |
| ファ# (= ソ♭) | `#F` |
| ソ | `G` |
| ソ# (= ラ♭) | `#G` |
| ラ | `A` |
| ラ# (= シ♭) | `#A` |
| シ | `B` |

**重要**:
- **シャープは `#` を音名の前に置く** (前置 `#C`)。**`C#` (後置) は誤り**
- **フラット記号は存在しない** — フラットの音は等価なシャープで書く
  (例: レ♭ は `#C` と書く、`-D` のような書き方は不可)
- LLM が他言語 MML の感覚で `C#` や `-D` を出した場合は補正が必要

### 音価 (音の長さ)

音名の後に **0-9** をつけて長さを指定:
| 音価 | 長さ | 対応する 4 分音符 |
|------|------|-------------------|
| 0 | 32 分音符 | 1/8 |
| 1 | 16 分音符 | 1/4 |
| 2 | 8 分音符 | 1/2 |
| 3 | 付点 16 分音符 | (3/8) |
| 4 | 4 分音符 | 1 |
| 5 | 付点 4 分音符 | 3/2 |
| 6 | 2 分音符 | 2 |
| 7 | 付点 2 分音符 | 3 |
| 8 | 全音符 | 4 |
| 9 | 付点全音符 | 6 |

### 休符 (R0-R9)
- R0 (32 分休符) - R9 (付点全音符)
- 音価と同じ表
- 例: `R4` = 4 分休符

### 複数チャンネルの同期
- 3 つのストリングデータを `,` で区切ると同時演奏
- **音価指定がない場合は前と同じ音価を継続**
- **デフォルト**: T4, M0, V15, O3 (テンポ 4、波形 0、最大音量、オクターブ 3)

### LLM 向け重要事項
- **音名の記法は厳密** (大文字、`+` や `-` の位置)
- **デフォルト値**: T4, M0, V15, O3 (各チャンネル)
- 1 度 PLAY すると、再度 PLAY で動作を継続
- 各音の前に空白を入れない (詰めて書く)
- V (音量) を 0 にすると音が出ない (チャンネル無音化)

<!-- probe-observed:start id=sound/play-blocking -->
**観察例** (nesemu 実機検証):

PLAY 文はブロッキング: 発音中は次の文へ進まないため、PRE → 演奏終了 → POST の順で表示される。

```basic
10 PRINT "PRE":PLAY "CDEFG":PRINT "POST"
```

出力:

```
  PRE
  POST
```

APU 発音フレーム: ch0=144f

中間スナップショット:
  - frame 15: …0 PRINT "PRE":PLAY "CDEFG": /   PRINT "POST" /   RUN /   PRE
  - frame 30: …0 PRINT "PRE":PLAY "CDEFG": /   PRINT "POST" /   RUN /   PRE
  - frame 60: …0 PRINT "PRE":PLAY "CDEFG": /   PRINT "POST" /   RUN /   PRE
  - frame 120: …0 PRINT "PRE":PLAY "CDEFG": /   PRINT "POST" /   RUN /   PRE
  - frame 200: …AY "CDEFG": /   PRINT "POST" /   RUN /   PRE /   POST /   OK
<!-- probe-observed:end -->

<!-- probe-observed:start id=sound/play-invalid -->
**観察例** (nesemu 実機検証):

PLAY の MML 文字列に仕様外の文字を渡すとエラーになる (エラーコードは error_marker フィールドで確認)。

```basic
10 PLAY "X"
```

出力:

```
  ?SN ERROR IN 10
```

エラーマーカー: `?SN ERROR`
<!-- probe-observed:end -->

<!-- probe-observed:start id=sound/play-melody -->
**観察例** (nesemu 実機検証):

PLAY "CDEFGABO4C" で C メジャースケール (1 オクターブ上昇)。Family BASIC の MML はオクターブ変更に `>` ではなく `O n` (例: `O4`) を使う — 別言語 MML の `>` `<` 記法は ?SN ERROR になる。APU ch0 (pulse) で 8 音の発音時間を観察。

```basic
10 PLAY "CDEFGABO4C"
```

出力:

```
(no output)
```

APU 発音フレーム: ch0=240f
<!-- probe-observed:end -->

<!-- probe-observed:start id=sound/play-rest -->
**観察例** (nesemu 実機検証):

PLAY "R" はレスト (休符)。指定した長さぶん無音で時間が経過する。

```basic
10 PLAY "R"
```

出力:

```
(no output)
```
<!-- probe-observed:end -->


*タグ*: 音, MML, 音楽

### `DEF_SPRITE`

スプライト面に表示するスプライト (アニメキャラクタ) を定義する

**構文**: `DEF SPRITE n, (A, B, C, D, E) = 文字式`

**引数**:
- `n` (数値 (0-7)): スプライト番号 (8 個まで定義可)
- `A` (数値 (0-3)): パレットコード (CGSET / PALET 系の番号)
- `B` (数値 (0 or 1)): キャラクタ合成度 (0 = 8×8 ドット 1 文字、1 = 16×16 ドット 4 文字)
- `C` (数値 (0-1)): 表示優先順位 (0=バックグラウンドより後ろ、1=スプライト面 = 通常)
- `D` (数値 (0-1)): X 軸の反転 (0=通常、1=左右反転)
- `E` (数値 (0-1)): Y 軸の反転 (0=通常、1=上下反転)
- `文字式` (文字列式): スプライトを構成するキャラクタコードの並び (CHR$ 連結)

略号: `DE.SP.`

動作:
- **スプライト n (0-7) を定義**
- 5 つのパラメータ (A〜E) と、文字式 (キャラクタコード列) で構成

### スプライトサイズと文字式の関係

| B | サイズ | 文字数 | 並び順 |
|---|--------|--------|--------|
| **0** | 8×8 ドット | **1 文字** | `CHR$(n)` 単独 |
| **1** | 16×16 ドット | **4 文字** | 左上→右上→左下→右下 |

**2 サイズしかない** (16×8 や 8×16 の横/縦長スプライトはサポートされていない)。

### 文字式の作り方
- キャラクタコード番号 (キャラクタコード表 A) を **CHR$()** で
  文字に変換し、`+` で連結する
- 例: `CHR$(64) + CHR$(65) + CHR$(66) + CHR$(67)` で 16×16 スプライト
- **`"DEFG"` のように文字列リテラルでも書ける**
  (各文字のキャラクタコードが使われる)

### CGEN モードによる挙動の違い
- **CGEN0** (両方アニメ): 文字式の値はキャラクタテーブル A の絵柄
- **CGEN2** (デフォルト): スプライトはアニメ、文字式の値は A のコード番号
  `DEF SPRITE 0, (0, 1, 0, 0, 0) = CHR$(68) + CHR$(69) + CHR$(70)` で
  キャラ "DEF" が表示される

### 反転 (D, E)
- D=1: 左右反転 (X 軸)
- E=1: 上下反転 (Y 軸)
- 4 文字構成のスプライトでは反転効果が組合わせで複雑になる

LLM 向け:
- **DEF SPRITE で定義 → SPRITE で表示** の 2 段階
- DEF MOVE 系を使う場合は DEF MOVE 側で別途キャラ指定 (DEF SPRITE は不要)
- 反転で同じスプライトを左右両向きに使い回せる

<!-- probe-observed:start id=sprites/sprite-16x16 -->
**観察例** (nesemu 実機検証):

B=1 は 16×16 ドット (CHR$ 4 つ = 8×8 ハードスプライト 4 枚)。連続する 4 コードで 1 ポーズを構成。OAM 観察で 4 タイルの配置が確認できる: SPRITE 0,120,100 のとき i=0 (120,100) tile=0=左上、i=1 (128,100) tile=1=右上、i=2 (120,108) tile=2=左下、i=3 (128,108) tile=3=右下。タイル間オフセットは 8px。

```basic
10 SPRITE ON
20 DEF SPRITE 0,(0,1,1,0,0)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
30 SPRITE 0,120,100
```

出力:

```
(no output)
```

アクティブスプライト: 4 個
<!-- probe-observed:end -->

<!-- probe-observed:start id=sprites/sprite-xflip -->
**観察例** (nesemu 実機検証):

DEF SPRITE の D=1 は X (左右) 反転フラグ → OAM attr の bit6 が立つ (観察値 attr=96 = 優先 bit5 + H反転 bit6)。ただしフラグのみだと各 8×8 タイルが「その場で」反転するだけでタイルの位置 (左上/右上…) は入れ替わらないため、16×16 全体としては正しく反転しない。完全な左右反転にはタイル並べ替え (左右列の入替) + フラグの両方が必要。

```basic
10 SPRITE ON
20 DEF SPRITE 0,(0,1,1,1,0)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
30 SPRITE 0,120,100
```

出力:

```
(no output)
```

アクティブスプライト: 4 個
<!-- probe-observed:end -->

<!-- probe-observed:start id=sprites/sprite-yflip -->
**観察例** (nesemu 実機検証):

DEF SPRITE の E=1 は Y (上下) 反転フラグ → OAM attr の bit7 が立つ (観察値 attr=160 = 優先 bit5 + V反転 bit7)。X 反転 (D) と同様、フラグのみだと各タイルが「その場で」上下反転し、完全な反転には上下行のタイル並べ替えも要る。

```basic
10 SPRITE ON
20 DEF SPRITE 0,(0,1,1,0,1)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
30 SPRITE 0,120,100
```

出力:

```
(no output)
```

アクティブスプライト: 4 個
<!-- probe-observed:end -->


*タグ*: スプライト, 定義, 必須

### `SPRITE`

定義済みのスプライトを画面に表示 (または消去) する

**構文**: `SPRITE n [, x, y]`

**引数**:
- `n` (数値 (0-7)): スプライト番号 (DEF SPRITE で定義済)
- `x` (数値 (0-255)) *(任意)*: 水平方向の座標 (ドット単位、0-255 = 0-240)
- `y` (数値 (0-255)) *(任意)*: 垂直方向の座標 (5-225 範囲が表示有効)

略号: `SP.`

動作:
- **DEF SPRITE で定義済のスプライト n を画面の (x, y) に表示**
- **x, y を省略すると非表示** (SPRITE n だけで消える)
- 同じ番号の SPRITE で再度位置指定すれば移動表示

座標系:
- **x = 0-255 (横、画面の左端から右端まで 256 ドット)**
- **y = 0-255 (縦、ただし表示有効範囲は 5-225 程度)**
- スプライト面の有効描画範囲外は表示されない

BG GRAPHIC との関係:
- DEF SPRITE で C=0 を指定したスプライトは BG GRAPHIC の上に表示
- C=1 (通常) はスプライト面 (BG より手前)

LLM 向け:
- スプライトのライフサイクル:
  1. DEF SPRITE n, ... = ... — 定義
  2. SPRITE ON — 表示モード ON
  3. SPRITE n, x, y — 表示
  4. SPRITE n — 消去
- DEF MOVE 系 (POSITION → MOVE) との使い分け:
  - **静的なスプライト** (簡単な絵を 1 つ置く) → SPRITE
  - **動くスプライト** (アニメ・自動移動) → DEF MOVE + MOVE

<!-- probe-observed:start id=sprites/sprite-8x8 -->
**観察例** (nesemu 実機検証):

SPRITE ON → DEF SPRITE で定義 → SPRITE n,x,y で表示。B=0 は 8×8 ドット (CHR$ 1 つ)。OAM 観察では 1 スプライトでも 4 枠が確保され、実体は i=0 (指定座標)、残り 3 枠は (0,0) に tile=32 (空白) で駐車される — Family BASIC はスプライト番号ごとに常に 16×16 ぶん (4 ハードスプライト) を予約していることが分かる。

```basic
10 SPRITE ON
20 DEF SPRITE 0,(0,0,1,0,0)=CHR$(0)
30 SPRITE 0,120,100
```

出力:

```
(no output)
```

アクティブスプライト: 4 個
<!-- probe-observed:end -->

<!-- probe-observed:start id=sprites/sprite-hide -->
**観察例** (nesemu 実機検証):

SPRITE n を座標なしで実行するとスプライト n が非表示になる。観察では表示 → SPRITE 0 後に OAM のアクティブエントリが 0 件になり、4 枠とも画面外 (y≧0xEF) へ退避することを確認。

```basic
10 SPRITE ON
20 DEF SPRITE 0,(0,1,1,0,0)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
30 SPRITE 0,120,100
40 SPRITE 0
```

出力:

```
(no output)
```
<!-- probe-observed:end -->

<!-- probe-observed:start id=sprites/sprite-two -->
**観察例** (nesemu 実機検証):

スプライト 0 と 1 を別パレット (A=0 と A=1)・別座標で同時表示。観察では OAM に 8 エントリ (2 スプライト × 4 タイル) が出て、sprite 0 は attr=32 (pal=0)、sprite 1 は attr=33 (pal=1) と、DEF SPRITE の A 引数が attr の bit0-1 (パレット) に反映される。まとめると OAM attr = パレット(bit0-1) + 優先(bit5) + H反転(bit6) + V反転(bit7)。

```basic
10 SPRITE ON
20 DEF SPRITE 0,(0,1,1,0,0)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
30 DEF SPRITE 1,(1,1,1,0,0)=CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)
40 SPRITE 0,80,100
50 SPRITE 1,160,100
```

出力:

```
(no output)
```

アクティブスプライト: 8 個
<!-- probe-observed:end -->


*タグ*: スプライト, 表示

### `SPRITE_ON`

スプライト面の表示を有効にする

**構文**: `SPRITE ON`

略号: `SP.O.`

動作:
- **スプライト面 (バックグラウンドより前) に置かれているスプライトの表示を有効化**
- 起動直後はスプライト面 OFF (見えない状態)
- DEF SPRITE / DEF MOVE で定義しても、SPRITE ON しないと表示されない

LLM 向け:
- **画面初期化の早い段階で SPRITE ON しておく**
- 一度 ON にしたら OFF まで維持

*タグ*: スプライト, 表示制御

### `SPRITE_OFF`

スプライト面の表示をやめる (全消去)

**構文**: `SPRITE OFF`

略号: `SP.OFF.`

動作:
- スプライト面に表示されている **すべてのスプライトを非表示** にする
- スプライト定義 (DEF SPRITE) や DEF MOVE の内容自体は消えない
- SPRITE ON で再表示可

LLM 向け:
- 全スプライトを一気に消したいときに使う
- シーン切替・ゲームオーバー画面等での清掃

*タグ*: スプライト, 表示制御

## 関数 (function)

### `XPOS_FN`

アニメキャラクタの水平方向の現在座標を求める

**構文**: `XPOS(n)`

**引数**:
- `n` (数値 (0-7)): DEF MOVE で定義した動作番号

**戻り値**: 数値 (0-255)

略号: `XP.`

動作:
- 動作番号 n のスプライトの **現在の水平座標 (X) を返す**
- 動作前は POSITION で指定した値、または 120 (デフォルト)
- 動作中は MOVE の進行に応じて変化

LLM 向け:
- 衝突判定や軌跡記録に使う
- YPOS と組み合わせて (X, Y) を取得

<!-- probe-observed:start id=sprites/xpos-ypos -->
**観察例** (nesemu 実機検証):

XPOS(n) / YPOS(n) は動作番号 n のスプライトの現在座標 (0-255)。観察結果: MOVE 直後・FOR 300 ループ後ともに `80 100` が表示され、PRINT 時点では座標が更新されていない。一方で probe_runner の post_run wait (240 frames) を経た最終 OAM は x=112-120 まで動いている。**XPOS/YPOS は BASIC 文の実行タイミングだけ評価され、FOR 300 程度の短い遅延では MOVE が反映されない** ことを示唆 (MOVE の更新は VBlank で非同期に進むが、BASIC のループ内 PEEK 系には間に合わない速さ)。

```basic
10 SPRITE ON
20 DEF MOVE(0)=SPRITE(0,3,8,100,1,0)
30 POSITION 0,80,100
40 PRINT XPOS(0);YPOS(0)
50 MOVE 0
60 FOR I=0 TO 300:NEXT
70 PRINT XPOS(0);YPOS(0)
```

出力:

```
   80 100
   80 100
```

アクティブスプライト: 4 個
<!-- probe-observed:end -->


*タグ*: スプライト, 座標, 関数

### `YPOS_FN`

アニメキャラクタの垂直方向の現在座標を求める

**構文**: `YPOS(n)`

**引数**:
- `n` (数値 (0-7)): DEF MOVE で定義した動作番号

**戻り値**: 数値 (0-255)

略号: `YP.`

動作:
- 動作番号 n のスプライトの **現在の垂直座標 (Y) を返す**
- XPOS と対で使う

*タグ*: スプライト, 座標, 関数

### `MOVE_N_FN`

MOVE で動き始めた動作番号 n の動きの状況を返す

**構文**: `MOVE(n)`

**引数**:
- `n` (数値 (0-7)): DEF MOVE で定義した動作番号

**戻り値**: 数値 (0 or -1)

略号: `M.(n.)`

動作:
- 動作番号 n の動きが進行中かどうか調べる
- **動作中なら -1 (= TRUE)、終了済 / 未開始なら 0 (= FALSE)**

LLM 向け:
- **`IF MOVE(0) THEN ...`** で「動いている間だけ何かする」
- **`IF NOT MOVE(0) THEN ...`** で「動きが終わったら何かする」
- ゲームループで「弾が画面外まで行ったか」「敵が動き終わったか」を判定

注意:
- **DEF MOVE で D (距離) を 255 に設定すると永遠に動く** ので MOVE(n) は常に -1
- 距離指定時、距離分動き終わると 0 になる

*タグ*: スプライト, 状態, 関数

### `ABS_FN`

数式の絶対値を求める

**構文**: `ABS(x)`

**引数**:
- `x` (数値式 (-32768 〜 +32767)): 絶対値を求める対象

**戻り値**: 数値 (整数 0 〜 +32767)

略号: `AB.`

動作:
- **数式 x の絶対値を返す** (|x|)
- 結果は常に非負

LLM 向け:
- 距離計算、誤差処理に頻用

<!-- probe-observed:start id=functions/abs -->
**観察例** (nesemu 実機検証):

ABS(x) は x の絶対値。

```basic
10 PRINT ABS(-7):PRINT ABS(7)
```

出力:

```
   7
   7
```
<!-- probe-observed:end -->


*タグ*: 関数, 数値, 必須

### `SGN_FN`

数式の符号を返す

**構文**: `SGN(x)`

**引数**:
- `x` (数値式 (-32768 〜 +32767)): 

**戻り値**: 数値 (-1, 0, 1)

略号: `SG.`

動作:
- x > 0 → **1**
- x = 0 → **0**
- x < 0 → **-1**

LLM 向け:
- 符号判定に
- 「方向」を表現するときに -1, 0, 1 のトライナリ値で扱える

<!-- probe-observed:start id=functions/sgn -->
**観察例** (nesemu 実機検証):

SGN(x) は x の符号: 負 = -1、ゼロ = 0、正 = 1。

```basic
10 PRINT SGN(-5):PRINT SGN(0):PRINT SGN(5)
```

出力:

```
  -1
   0
   1
```
<!-- probe-observed:end -->


*タグ*: 関数, 数値

### `RND_FN`

引数未満の乱数 (整数) を発生

**構文**: `RND(x)`

**引数**:
- `x` (数値式 (整数 1 〜 32767)): 上限値 (この値未満の整数を返す)

**戻り値**: 数値 (整数 1 〜 32767)

略号: `RN.`

動作:
- **0 から x-1 の範囲の整数乱数**を返す? あるいは **1 から x の範囲**?
  → つまり **0 〜 x-1 の整数**
- **乱数の種は次のとなる** (前回の値が次の入力となる擬似乱数)

LLM 向け:
- サイコロ: `RND(6) + 1` で 1 〜 6
- 範囲指定: `RND(高 - 低 + 1) + 低` で「低〜高」の整数
- **シード初期化は仕様未明** (要検証)

<!-- probe-observed:start id=functions/rnd -->
**観察例** (nesemu 実機検証):

RND(n) は 0..n-1 の整数乱数。同じ seed なら同じ系列が出る。

```basic
10 PRINT RND(10):PRINT RND(10):PRINT RND(10)
```

出力:

```
   0
   9
   7
```
<!-- probe-observed:end -->


*タグ*: 関数, 数値, 乱数

### `ASC_FN`

文字コードを数値に変換 (CHR$ の逆)

**構文**: `ASC(文字列)`

**引数**:
- `文字列` (文字列式): 1 文字以上の文字列。**最初の 1 文字のみ**コードに変換

**戻り値**: 数値 (0-255)

略号: `AS.`

動作:
- **文字列の最初の 1 文字のキャラクタコード (0-255) を返す**
- 文字列が 2 文字以上でも先頭 1 文字のみ
- **空文字列 (`""`) の場合、ヌルストリングとして異常**

LLM 向け:
- INKEY$ で取得したキー入力をコードで判定するときに頻用
- キャラクタコード表 と組み合わせて使う

<!-- probe-observed:start id=functions/asc -->
**観察例** (nesemu 実機検証):

ASC("A") は文字 A のキャラクタコード = 65。

```basic
10 PRINT ASC("A"):PRINT ASC("0")
```

出力:

```
   65
   48
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, コード変換

### `CHR_FN`

数値をキャラクタコードとみなして文字列に変換 (ASC の逆)

**構文**: `CHR$(x)`

**引数**:
- `x` (数値式 (0-255)): キャラクタコード (0-255)

**戻り値**: 文字列 (1 文字)

略号: `CH.`

動作:
- **数値 x に対応する 1 文字の文字列を返す**
- PRINT で出力すると指定コードのキャラクタが画面に出る
- DEF SPRITE / DEF MOVE 等で **特殊コードを文字列引数に組み込む**ときに頻用

LLM 向け:
- **`CHR$(13)` = 改行**、KEY 文の自動実行マクロでよく使う
- **`CHR$(0)` = ヌル**
- キャラクタテーブル A/B のコード値 を CHR$ で文字列化
- DEF SPRITE/MOVE の引数: `(...) + CHR$(64) + CHR$(65) + ...`

<!-- probe-observed:start id=functions/chr -->
**観察例** (nesemu 実機検証):

CHR$(65) はコード 65 の文字 = "A"。

```basic
10 PRINT CHR$(65);CHR$(66);CHR$(67)
```

出力:

```
  ABC
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, コード変換, 必須

### `VAL_FN`

数字の文字列を数値に変換

**構文**: `VAL(文字列)`

**引数**:
- `文字列` (文字列式): 数字を表す文字列 (10 進または `&H` 接頭辞付き 16 進)

**戻り値**: 数値 (-32768 〜 +32767)

略号: `VA.`

動作:
- 文字列を数値に変換 (数字の部分のみ解釈)
- **`"&H"` 接頭辞があれば 16 進数として変換**
- 数字以外の文字に当たると、その手前まで変換 (例: `VAL("123ABC")` = 123)
- 完全に変換できない場合 (空文字列、文字のみ) は **0** を返す

LLM 向け:
- INPUT で文字列として受け取ってから数値に変換 (型の柔軟性確保)
- 数値リテラルが文字列内にあるときの解釈に使う

<!-- probe-observed:start id=functions/val -->
**観察例** (nesemu 実機検証):

VAL("123") は文字列の先頭を数値に変換。数字でない文字で停止。

```basic
10 PRINT VAL("123"):PRINT VAL("12X3"):PRINT VAL("XYZ")
```

出力:

```
   123
   12
   0
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 数値変換

### `STR_FN`

数式の値を文字列の数字に変換 (VAL の逆)

**構文**: `STR$(x)`

**引数**:
- `x` (数値式 (-32768 〜 +32767)): 

**戻り値**: 文字列

略号: `STR.`

動作:
- **数値を文字列に変換**
- **正の場合は先頭にスペースが 1 文字** (符号位置のため)
- 負の場合は先頭に `-`

LLM 向け:
- PRINT で `+` で連結する場合に必要 (`PRINT "X="; X` ではなく `PRINT "X=" + STR$(X)`)
- 文字列処理 (`MID$` 等) で使うときに数値を一旦文字列化
- **正の値の先頭スペース** に注意 (LEN(STR$(123)) = 4、つまり " 123")

<!-- probe-observed:start id=functions/str -->
**観察例** (nesemu 実機検証):

STR$(n) は数値を文字列化。正の数なら先頭にスペース (符号用) が入る。

```basic
10 A$=STR$(42):PRINT "["+A$+"]"
```

出力:

```
  10 A$=STR$(42):PRINT "    "+
  A$+"    "
       42
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 数値変換

### `HEX_FN`

数式を 16 進数の文字列に変換

**構文**: `HEX$(x)`

**引数**:
- `x` (数値式 (-32768 〜 +32767)): 

**戻り値**: 文字列

略号: `HE.`

動作:
- **数値を 16 進数表記の文字列に変換** (`&H` は付かない、ただの数字列)
- 例: `HEX$(255)` → `"FF"` (`&HFF` ではない)
- 例: `HEX$(0)` → `"0"`
- 負の値は 16 ビット 2 の補数表現で変換? (要検証)

LLM 向け:
- メモリダンプ表示、デバッグ出力に有用
- PEEK 結果を読みやすく表示するときに頻用

<!-- probe-observed:start id=functions/hex -->
**観察例** (nesemu 実機検証):

HEX$(255) は "FF"。負数の扱いに注意 (2 の補数)。

```basic
10 PRINT HEX$(255):PRINT HEX$(16)
```

出力:

```
  FF
  10
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 16進

### `LEFT_FN`

文字列の左側から指定した数だけ文字を取り出す

**構文**: `LEFT$(文字列, n)`

**引数**:
- `文字列` (文字列式): 
- `n` (数値 (0-255)): 取り出す文字数

**戻り値**: 文字列

略号: `LE.`

動作:
- 文字列の **左 n 文字** を返す
- n が文字列の長さより大きい場合: 全部の文字列を返す
- n = 0 の場合: 空文字列 (ヌルストリング)
- 元の文字列は変更されない (関数なので)

LLM 向け:
- 文字列の前半切り出しに使う
- 文字列長は最大 31 (SPEC_STRING_RANGE) なので n もそれ以下

<!-- probe-observed:start id=functions/left -->
**観察例** (nesemu 実機検証):

LEFT$(s, n) は左端から n 文字。

```basic
10 PRINT LEFT$("ABCDE",3)
```

出力:

```
  ABC
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 切り出し

### `RIGHT_FN`

文字列の右側から指定した数だけ文字を取り出す

**構文**: `RIGHT$(文字列, n)`

**引数**:
- `文字列` (文字列式): 
- `n` (数値 (0-255)): 取り出す文字数

**戻り値**: 文字列

略号: `R.` または `RIG.`

動作:
- 文字列の **右 n 文字** を返す
- n が文字列長より大きい場合: 全部
- n = 0 の場合: 空文字列

<!-- probe-observed:start id=functions/right -->
**観察例** (nesemu 実機検証):

RIGHT$(s, n) は右端から n 文字。

```basic
10 PRINT RIGHT$("ABCDE",3)
```

出力:

```
  CDE
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 切り出し

### `MID_FN`

文字列の中から、指定された一連の文字を取り出す

**構文**: `MID$(文字列, 開始位置, n)`

**引数**:
- `文字列` (文字列式): 
- `開始位置` (数値 (1-31)): 開始位置 (1 始まり)
- `n` (数値 (0-31)): 取り出す文字数

**戻り値**: 文字列

略号: `MI.`

動作:
- 文字列の **「開始位置」から n 文字** を返す
- **開始位置は 1 始まり** (LEFT$ や RIGHT$ と違って明示)
- 開始位置 + n が文字列長を超えた場合は、文字列の最後まで
- n = 0 の場合: 空文字列

LLM 向け:
- **開始位置 1 ベース** に注意 (LEFT$/RIGHT$ は文字数指定なので 0 ベース感覚)
- 部分文字列の取り出しに必須

<!-- probe-observed:start id=functions/mid -->
**観察例** (nesemu 実機検証):

MID$(s, m, n) は m 文字目から n 文字 (m は 1 始まり)。

```basic
10 PRINT MID$("ABCDE",2,3)
```

出力:

```
  BCD
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 切り出し

### `LEN_FN`

文字列の文字数を返す

**構文**: `LEN(文字列)`

**引数**:
- `文字列` (文字列式): 

**戻り値**: 数値 (0-31)

略号: `LE.`

動作:
- **文字列に含まれるすべての文字数を返す**
- 文字列がヌルストリング (空) のときは 0
- 空白やコントロールコードなど画面に表示されない文字も 1 文字として数える

LLM 向け:
- 文字列の長さチェック (31 文字制限の確認)
- ループ条件として使う (`FOR I = 1 TO LEN(A$)`)

<!-- probe-observed:start id=functions/len -->
**観察例** (nesemu 実機検証):

LEN(s) は文字列の長さ。

```basic
10 PRINT LEN("HELLO"):PRINT LEN("")
```

出力:

```
   5
   0
```
<!-- probe-observed:end -->


*タグ*: 関数, 文字, 長さ

### `PEEK_FN`

指定したメモリアドレスからデータを取り出す (←→ POKE)

**構文**: `PEEK(アドレス)`

**引数**:
- `アドレス` (数値 (16bit, アドレス値)): 読み込み対象のメモリアドレス

**戻り値**: 数値 (0-255)

略号: `PE.`

動作:
- **メモリの指定アドレスから 1 バイト (8 ビット) のデータを返す**
- メモリマップ で「読み込み可能」とされた範囲のみ
- 読めない領域 (`&H0800-1FFF` 等) の挙動は不定

LLM 向け:
- POKE と対で使う
- VRAM の状態取得、変数領域のデバッグ等に使う
- `&H7000` 以降のユーザ領域 + `&H8000-FFFF` の ROM が主な対象

<!-- probe-observed:start id=functions/peek -->
**観察例** (nesemu 実機検証):

PEEK(addr) は指定アドレスの 1 バイト値。

```basic
10 PRINT PEEK(&H7AF6)
```

出力:

```
   191
```
<!-- probe-observed:end -->


*タグ*: 関数, メモリ, 上級

### `POS_FN`

画面のカーソルの水平位置を返す

**構文**: `POS(0)`

**引数**:
- `0` (数値 (0 のみ)): 引数は形式的に 0 を指定 (他の値は未対応?)

**戻り値**: 数値 (0-27)

略号: なし (POS のまま)

動作:
- **カーソルの現在の水平位置 (0-27) を返す**
- 引数は **形式的に 0** を入れる (他の言語の POS との互換性のため?)
- 垂直位置は CSRLIN を使う

LLM 向け:
- PRINT 中にカーソル位置を取りたいときに
- 改行までの残り文字数を計算する用途

*タグ*: 関数, 画面, カーソル

### `FRE_FN`

ユーザメモリの未使用領域のサイズを返す

**構文**: `FRE`

**戻り値**: 数値 (バイト数)

略号: `FR.`

動作:
- **BASIC のプログラムが使っていないユーザメモリのバイト数を返す**
- **引数なし** (`FRE` 単独で使う、関数だが括弧不要)
- 通常は CLEAR や RUN の直後で確認 (大きな値)
- プログラムが書き加わると減っていく

LLM 向け:
- メモリ枯渇前のチェックに使う
- **`PRINT FRE`** で残量確認の定型
- 結果が小さくなってきたら DIM を整理する判断材料

<!-- probe-observed:start id=functions/fre -->
**観察例** (nesemu 実機検証):

FRE(0) は BASIC で使える残りバイト数。

```basic
10 PRINT FRE(0)
```

出力:

```
   1970 0
```
<!-- probe-observed:end -->


*タグ*: 関数, メモリ, 確認

### `STICK_FN`

コントローラの十字ボタンの入力値を返す (ビットフラグ)

**構文**: `STICK(x)`

**引数**:
- `x` (数値 (0 or 1)): 0 = I コントローラ、1 = II コントローラ

**戻り値**: 数値 (ビットフラグの OR 値)

略号: `ST.`

動作:
- 指定したコントローラの **十字キーの押下状態** をビットフラグで返す:

| ビット値 | 方向 |
|---------|------|
| 0 | 何も押されていない |
| 1 | 右 |
| 2 | 左 |
| 4 | 下 |
| 8 | 上 |

**斜め方向は複合ビット** (OR 値):
- 右上 = 1 + 8 = 9
- 右下 = 1 + 4 = 5
- 左上 = 2 + 8 = 10
- 左下 = 2 + 4 = 6

LLM 向け:
- **ビット単位で判定**: `IF (S AND 1) THEN PRINT "右"` のように個別検査
- **比較演算でも判定可** (単独押下なら): `IF S = 1 THEN PRINT "右"`
- 斜めも検出したい場合は AND マスクが必須 (`S AND 1` で右、`S AND 4` で下、両方真なら右下)
- **連続で取得する場合 ループでアンチチャタリングが必要**

<!-- probe-observed:start id=functions/stick-diagonal -->
**観察例** (nesemu 実機検証):

斜め押しは方向のビット OR。UP (8) + RIGHT (1) で **STICK(0) = 9 = 8|1** を確定。inner FOR J=0 TO 1500 で 1 iter ≒ 50 frames として inject 期間に複数 iter を入れ、観察では T4-T8 の 5 iter で値 9 が連続表示された。

```basic
10 FOR I=1 TO 10
20 PRINT "T";I;"=";STICK(0)
30 FOR J=0 TO 1500:NEXT
40 NEXT
```

出力:

```
  T 1= 0
  T 2= 0
  T 3= 0
  T 4= 9
  T 5= 9
  T 6= 9
  T 7= 9
  T 8= 9
  T 9= 0
  T 10= 0
```
<!-- probe-observed:end -->

<!-- probe-observed:start id=functions/stick-directions -->
**観察例** (nesemu 実機検証):

STICK(0) は 1P 十字キーの状態をビットフラグで返す。実機観察で **上=8 (bit3), 下=4 (bit2), 左=2 (bit1), 右=1 (bit0)** を確定。FOR ループ 16 回 (inner FOR J=0 TO 1500 で 1 iter ≒ 50 frames) で STICK 値を PRINT し、inject_pad で UP/RIGHT/DOWN/LEFT を 200 frame 間隔で 120 frame ずつ押下、screen に各方向の値の連続が並ぶ。

```basic
10 FOR I=1 TO 16
20 PRINT "T";I;"=";STICK(0)
30 FOR J=0 TO 1500:NEXT
40 NEXT
```

出力:

```
  T 1= 0
  T 2= 0
  T 3= 8
  T 4= 8
  T 5= 8
  T 6= 0
  T 7= 1
  T 8= 1
  T 9= 1
  T 10= 0
  T 11= 0
  T 12= 4
  T 13= 4
  T 14= 0
  T 15= 0
  T 16= 2
```
<!-- probe-observed:end -->


*タグ*: 関数, 入力, コントローラ, 必須

### `STRIG_FN`

コントローラのトリガーボタン (A/B + START/SELECT) の押下状態を返す

**構文**: `STRIG(x)`

**引数**:
- `x` (数値 (0 or 1)): 0 = I コントローラ、1 = II コントローラ

**戻り値**: 数値 (0-15 のビットフラグ)

略号: `STR.`

動作:
- **トリガーボタン (A/B/SELECT/START) の押下状態のビット和** を返す:

| 戻り値 | ボタン |
|-------|--------|
| 0 | 何も押されていない |
| 1 | A ボタン |
| 2 | B ボタン |
| 4 | SELECT (要検証) |
| 8 | START |

複数同時押しの場合: ビット和 (例: A + START = 9)

LLM 向け:
- **ビット演算で個別判定**: `IF STRIG(0) AND 1 THEN ...` で A 単独
- **比較演算でも判定可** (単独押下なら): `IF STRIG(0) = 1 THEN ...`
- **アンチチャタリング** (STICK と同様)

II コントローラ:
- II コントローラには SELECT/START がない (純正ファミコン仕様)
- II コントローラのトリガーは A/B のみ (戻り値 0/1/2/3)

<!-- probe-observed:start id=functions/strig-buttons -->
**観察例** (nesemu 実機検証):

STRIG(n) は **n 番目のコントローラ** のトリガーボタン状態 (1P=0、2P=1)。STRIG(0) と STRIG(1) は A/B 別ではない (これは想定の誤り)。観察結果: 1P で A 押下 → STRIG(0)=**8** (bit3)、B 押下 → STRIG(0)=**4** (bit2)。STICK と同じくビットフラグで、A/B が STRIG(0) の同一値の異なるビットに反映される。STRIG(1) は 2P (今回は inject していないので常に 0)。

```basic
10 FOR I=1 TO 12
20 PRINT "T";I;"A=";STRIG(0);"B=";STRIG(1)
30 FOR J=0 TO 1500:NEXT
40 NEXT
```

出力:

```
  T 1A= 0B= 0
  T 2A= 0B= 0
  T 3A= 0B= 0
  T 4A= 8B= 0
  T 5A= 8B= 0
  T 6A= 8B= 0
  T 7A= 0B= 0
  T 8A= 0B= 0
  T 9A= 4B= 0
  T 10A= 4B= 0
  T 11A= 4B= 0
  T 12A= 0B= 0
```
<!-- probe-observed:end -->


*タグ*: 関数, 入力, コントローラ, 必須

### `CSRLIN_FN`

カーソルの垂直位置を返す

**構文**: `CSRLIN`

**戻り値**: 数値 (0-23)

略号: `CSR.`

動作:
- **カーソルの現在の垂直位置 (0-23) を返す**
- **引数なし** (`POS` と違い、括弧も不要)
- 水平位置は POS(0)

LLM 向け:
- 画面の現在位置を取得 (POS と CSRLIN を組み合わせて全座標)
- PRINT 後の継続位置を確認

<!-- probe-observed:start id=functions/csrlin-pos -->
**観察例** (nesemu 実機検証):

CSRLIN は現在の行 (0-23)、POS は列 (0-27) を返す。LOCATE で動かしてから読み取ると LOCATE が反映されているかを確認できる。実機観察: `LOCATE 5,7` 後の `PRINT CSRLIN(0);POS(0)` の出力は ` 7 0 9` の 3 数字。`7` は CSRLIN (= row 7、LOCATE 5,7 と整合)、続く `0 9` は `(0);POS(0)` 部分が PRINT で 2 つの値として出ている挙動 (FB BASIC が `(0)` を独立した式として評価している可能性)。CSRLIN / POS の正しい呼び出しは引数なしの方が安全。

```basic
10 LOCATE 5,7
20 PRINT CSRLIN(0);POS(0)
```

出力:

```
        7 0 9
```
<!-- probe-observed:end -->


*タグ*: 関数, 画面, カーソル

### `SCR_FN`

BG GRAPHIC 面の指定位置の文字または絵を取り出す

**構文**: `SCR$(X, Y, Sw)`

**引数**:
- `X` (数値 (0-27)): 水平方向の位置
- `Y` (数値 (0-23)): 垂直方向の位置
- `Sw` (数値 (0 or 1)): 0 = 文字 (CHR$ 互換)、1 = 配色 (パレット番号 0-3) を取得

**戻り値**: 文字列 or 数値

略号: `SC.`

動作:
- 画面 (X, Y) 位置の **文字または配色** を取得
- **Sw=0** → その位置に表示されている文字 (CHR$ 形式の 1 文字)
- **Sw=1** → その位置のパレット番号 (0-3)
- 戻り値はカラーチャートのコードに対応

LLM 向け:
- 衝突検知 (画面上のキャラクタを読み取って判定)
- スクリーン上のキャラクタダンプ

<!-- probe-observed:start id=functions/scr-read -->
**観察例** (nesemu 実機検証):

SCR$(x, y[, sw]) は指定セルの文字を返す。実機観察: `LOCATE 3,5:PRINT "X"` で (3,5) に X を置き、`PRINT SCR$(3,5)` で読み戻すと `"X"` が返る — 書き込み・読み取りの対称性を確認。

```basic
10 LOCATE 3,5:PRINT "X"
20 PRINT SCR$(3,5)
```

出力:

```
     X
  X
```
<!-- probe-observed:end -->


*タグ*: 関数, 画面, 取得

### `INKEY_FN`

キーボードからの即時入力 (1 文字)

**構文**: `INKEY$ [(n)]`

**引数**:
- `n` (数値 (0 or 1?)) *(任意)*: 引数なし or 0/1 (詳細不明、要検証)

**戻り値**: 文字列 (0 or 1 文字)

略号: `IN.`

動作:
- **キーボードから 1 文字を即時取得** (キー押下を待たない)
- 押されていなければ **空文字列 (`""`) を返す**
- 押されていれば、その 1 文字 (CHR$ 形式)
- **キャラクタテーブル B の文字グループ A 〜 D グループ** が対応

LLM 向け:
- **`A$ = INKEY$: IF A$ = "" THEN ...`** で「キー入力待ち」の定型
- INPUT との違い: INKEY$ は **即時取得** (待たない、ノンブロッキング)
- ゲームループでのキーポーリングに必須
- 連続入力では INKEY$ ループでバッファ的に処理

<!-- probe-observed:start id=functions/inkey-basic -->
**観察例** (nesemu 実機検証):

INKEY$ は押されているキーを 1 文字返す (押されていなければ空文字列)。観察では FOR ループの **iteration 22 で A** が検出された (inject 開始 200 frame と iter ループ速度の組み合わせ)。続けて inject した B と 1 は BASIC ループ完走後に押下されたため、即時モードのプロンプトに `B1` として残った — INKEY$ のリアルタイム性とプログラム終了後にキー入力が即時モードへ流れる挙動の両方を観察できる。

```basic
10 FOR I=1 TO 30
20 A$=INKEY$
30 IF A$<>"" THEN PRINT I,A$
40 FOR J=0 TO 300:NEXT
50 NEXT
```

出力:

```
   1
   21    A
  B1
```
<!-- probe-observed:end -->


*タグ*: 関数, 入力, 必須

## 演算子 (operator)

### `OP_ADD`

加算 `+`

**構文**: `A + B`

- 整数同士の加算。結果が -32768〜+32767 の範囲を超えると保証外

<!-- probe-observed:start id=operators/op-add -->
**観察例** (nesemu 実機検証):

整数 + 整数。結果が ±32767 の範囲を超えると ?OV ERROR。

```basic
10 PRINT 2+3
```

出力:

```
   5
```
<!-- probe-observed:end -->


*タグ*: 演算子, 算術

### `OP_SUB`

減算 `-`

**構文**: `A - B`

- 二項演算 (A から B を引く)

- **単項マイナス `-A` も使える**。明記されていないが、
  `B = -5` のような書き方が実機/エミュで動作することを連載者が検証済

<!-- probe-observed:start id=operators/op-sub -->
**観察例** (nesemu 実機検証):

整数 - 整数。負数も問題なく扱える。

```basic
10 PRINT 7-3
```

出力:

```
   4
```
<!-- probe-observed:end -->


*タグ*: 演算子, 算術

### `OP_MUL`

乗算 `*`

**構文**: `A * B`

- 整数乗算。オーバーフロー注意

<!-- probe-observed:start id=operators/op-mul -->
**観察例** (nesemu 実機検証):

整数 × 整数。

```basic
10 PRINT 6*7
```

出力:

```
   42
```
<!-- probe-observed:end -->


*タグ*: 演算子, 算術

### `OP_DIV`

除算 `/`

**構文**: `A / B`

- 整数除算 — 商の整数部分のみ。小数は切り捨て
- **B = 0 は不可** (エラー)
- 余りは MOD 演算子で別途取得

<!-- probe-observed:start id=operators/op-div -->
**観察例** (nesemu 実機検証):

整数 / 整数。Family BASIC は整数のみなので結果は切り捨て (10/3=3)。

```basic
10 PRINT 20/4:PRINT 10/3
```

出力:

```
   5
   3
```
<!-- probe-observed:end -->


*タグ*: 演算子, 算術, 制約

### `OP_MOD`

剰余 `MOD`

**構文**: `A MOD B`

- A を B で割った余り
- **文法上スペースは不要** (`10MOD3` でも動く、連載者検証)
- 変数の隣に書く場合はスペースを空けるのが安全 (詳細は
  SYNTAX_OPERATOR_SPACING 参照)
- 例: 10 MOD 3 = 1

<!-- probe-observed:start id=operators/op-mod -->
**観察例** (nesemu 実機検証):

MOD は剰余を返す。リテラル隣接でも詰めて書ける。

```basic
10 PRINT 10 MOD 3
```

出力:

```
   1
```
<!-- probe-observed:end -->


*タグ*: 演算子, 算術

### `OP_EQ`

等しい `=`

**構文**: `A = B`

- **代入と等価判定で同じ記号を使う** — 文脈で区別される
- IF 文の中では等価判定: `IF A=10 THEN ...`
- 文の先頭・代入文では代入: `A=10`

<!-- probe-observed:start id=operators/op-eq -->
**観察例** (nesemu 実機検証):

比較演算子は真 = -1、偽 = 0 を返す。

```basic
10 PRINT 3=3:PRINT 3=4
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 関係

### `OP_NE`

等しくない `<>`

**構文**: `A <> B`

- **`≠` 記号は使えない** — `<>` で書く
- 代替表記なし

<!-- probe-observed:start id=operators/op-ne -->
**観察例** (nesemu 実機検証):

<> は不等で真。

```basic
10 PRINT 3<>4:PRINT 3<>3
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 関係, 制約

### `OP_GT`

大なり `>`

**構文**: `A > B`

- 左辺が右辺より大きい場合に真

<!-- probe-observed:start id=operators/op-gt -->
**観察例** (nesemu 実機検証):

より大きい

```basic
10 PRINT 5>3:PRINT 3>5
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 関係

### `OP_LT`

小なり `<`

**構文**: `A < B`

<!-- probe-observed:start id=operators/op-lt -->
**観察例** (nesemu 実機検証):

より小さい

```basic
10 PRINT 3<5:PRINT 5<3
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 関係

### `OP_GE`

以上 `>=`

**構文**: `A >= B`

- **`≧` 記号は使えない** — `>=` で書く

<!-- probe-observed:start id=operators/op-ge -->
**観察例** (nesemu 実機検証):

以上

```basic
10 PRINT 5>=5:PRINT 4>=5
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 関係, 制約

### `OP_LE`

以下 `<=`

**構文**: `A <= B`

- **`≦` 記号は使えない** — `<=` で書く

<!-- probe-observed:start id=operators/op-le -->
**観察例** (nesemu 実機検証):

以下

```basic
10 PRINT 5<=5:PRINT 6<=5
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 関係, 制約

### `OP_NOT`

否定 `NOT` (略号 NO.)

**構文**: `NOT X`

- **ビット単位の反転** (16 ビット整数全体を反転)
- 例: `NOT 11` → `B'1111 1111 1111 0100'` = `-12`
- 関係結果に対して使うと論理 NOT として機能 (関係結果は -1 or 0)
- **変数を続ける場合は要スペース** (詳細は
  SYNTAX_OPERATOR_SPACING 参照)

<!-- probe-observed:start id=operators/op-not -->
**観察例** (nesemu 実機検証):

NOT は全ビット反転。NOT 0 = -1、NOT (-1) = 0。

```basic
10 PRINT NOT 0:PRINT NOT -1
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 論理, ビット

### `OP_AND`

論理積 `AND` (略号 A.) — ビット単位の論理積

**構文**: `A AND B`

- **ビット単位** の AND
- IF 文での条件結合に頻出
- 関係式の結果 (-1 / 0) に対して AND すると論理 AND として機能

<!-- probe-observed:start id=operators/op-and -->
**観察例** (nesemu 実機検証):

AND は両方真 (-1) のとき -1。

```basic
10 PRINT (3=3) AND (5=5):PRINT (3=3) AND (3=4)
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 論理, ビット

### `OP_OR`

論理和 `OR` — ビット単位の論理和

**構文**: `A OR B`

- ビット単位の OR
- inclusive or (両方真でも真)

<!-- probe-observed:start id=operators/op-or -->
**観察例** (nesemu 実機検証):

OR はどちらか真なら -1。

```basic
10 PRINT (3=3) OR (3=4):PRINT (3=4) OR (3=5)
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 論理, ビット

### `OP_XOR`

排他的論理和 `XOR` (略号 XO.)

**構文**: `A XOR B`

- ビット単位の排他的論理和
- 「同じ値だと 0、異なるとき 1」

<!-- probe-observed:start id=operators/op-xor -->
**観察例** (nesemu 実機検証):

XOR は片方だけ真のとき -1。

```basic
10 PRINT (3=3) XOR (3=4):PRINT (3=3) XOR (5=5)
```

出力:

```
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, 論理, ビット

## エラー (error)

### `ERROR_NF`

FOR がないのに NEXT がある

**コード**: `NF`
**メッセージ**: NEXT without FOR
**原因**: NEXT 文に対応する FOR 文が見つからない。
多重ループのネスト崩れ、GOTO で FOR を飛び越えた等が典型。

**対処**: 対応する FOR-NEXT のペアを見直す

<!-- probe-observed:start id=errors/nf-next-without-for -->
**観察例** (nesemu 実機検証):

FOR 文と対応しない NEXT で ?NF ERROR。

```basic
10 NEXT
```

出力:

```
  ?NF ERROR IN 10
```

エラーマーカー: `?NF ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, ループ

### `ERROR_SN`

文法が間違っている

**コード**: `SN`
**メッセージ**: Syntax error
**原因**: 予約語の綴り違い、引数不足、引用符閉じ忘れ、`,` `;` `:` の使い違い等。
最も頻出するエラー。

**対処**: 該当行を再入力。LIST で見直す

<!-- probe-observed:start id=errors/let-keyword -->
**観察例** (nesemu 実機検証):

Family BASIC は LET キーワードをサポートしない。LET を付けた代入は ?SN ERROR (Syntax error)。

```basic
10 LET A=1
```

出力:

```
  ?SN ERROR IN 10
```

エラーマーカー: `?SN ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 構文

### `ERROR_RG`

GOSUB がないのに RETURN がある

**コード**: `RG`
**メッセージ**: RETURN without GOSUB
**原因**: GOSUB なしで RETURN を実行した。フォールスルーやスタック異常時に発生
**対処**: GOSUB / RETURN のペアを見直す

<!-- probe-observed:start id=errors/rg-return-without-gosub -->
**観察例** (nesemu 実機検証):

GOSUB と対応しない RETURN で ?RG ERROR。

```basic
10 RETURN
```

出力:

```
  ?RG ERROR IN 10
```

エラーマーカー: `?RG ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, サブルーチン

### `ERROR_OD`

READ で読むべきデータが DATA 文に用意されていない

**コード**: `OD`
**メッセージ**: Out of DATA
**原因**: DATA 文の値の数より READ の回数が多い。
RESTORE せずにループで READ を繰り返した場合等。

**対処**: DATA 文を増やすか、RESTORE で巻き戻す

<!-- probe-observed:start id=errors/od-out-of-data -->
**観察例** (nesemu 実機検証):

DATA を使い切った後でさらに READ すると ?OD ERROR。

```basic
10 READ A:READ B:READ C
20 DATA 1,2
```

出力:

```
  ?OD ERROR IN 10
```

エラーマーカー: `?OD ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, データ

### `ERROR_IL`

ステートメントや関数の呼び方が間違っている

**コード**: `IL`
**メッセージ**: Illegal function call
**原因**: 引数の型・範囲が不正。例えば負数の SQR、文字列を期待する関数に
数値を渡した、等。

**対処**: 関数の引数を見直す

*タグ*: エラー, 関数

### `ERROR_OV`

演算結果が許容範囲を超えた

**コード**: `OV`
**メッセージ**: Overflow
**原因**: 整数 16 ビット (-32768〜+32767) の範囲を超える計算結果
**対処**: 計算順序を変える、中間値を分割する

<!-- probe-observed:start id=errors/ov-overflow -->
**観察例** (nesemu 実機検証):

実機では ±32767 を超える乗算でも ?OV ERROR は発生せず、16bit で**静かに wrap**する。30000*2 = 60000 → 16bit signed で -5536。?OV は別経路 (たとえば代入時) で発生する可能性がある。

```basic
10 PRINT 30000*2
```

出力:

```
  -5536
```
<!-- probe-observed:end -->


*タグ*: エラー, 数値, 整数

### `ERROR_OM`

メモリ不足

**コード**: `OM`
**メッセージ**: Out of memory
**原因**: BASIC プログラム本体 + 変数 + DATA 等が 2KB ユーザ領域 (実質 1.95KB) を
超えた。

**対処**: コードを短縮、変数を減らす、不要な配列を削除

*タグ*: エラー, メモリ, 制約

### `ERROR_UL`

GOTO, GOSUB, IF などで指定した分岐先の番号がない

**コード**: `UL`
**メッセージ**: Undefined line Number
**原因**: 飛び先の行番号がプログラム中に存在しない
**対処**: 行番号を見直す、対象行を追加する

<!-- probe-observed:start id=errors/ul-undefined-line -->
**観察例** (nesemu 実機検証):

存在しない行番号への GOTO で ?UL ERROR。

```basic
10 GOTO 999
```

出力:

```
  ?UL ERROR IN 10
```

エラーマーカー: `?UL ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 分岐

### `ERROR_SO`

配列変数の添字が指定外である

**コード**: `SO`
**メッセージ**: Subscript out of range
**原因**: DIM で確保したサイズを超える添字でアクセスした
**対処**: DIM のサイズを増やす、添字を見直す

<!-- probe-observed:start id=errors/so-subscript-out -->
**観察例** (nesemu 実機検証):

DIM で確保した範囲外のインデックスへのアクセスは実機では ?IL ERROR (Illegal) として報告される。

```basic
10 DIM A(3):PRINT A(10)
```

出力:

```
  ?IL ERROR IN 10
```

エラーマーカー: `?IL ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 配列

### `ERROR_DD`

配列が 2 度以上定義されている

**コード**: `DD`
**メッセージ**: Duplicate Definition
**原因**: 同じ配列を DIM で 2 回宣言した
**対処**: DIM 文を 1 回にまとめる、CLEAR で初期化してから再定義

<!-- probe-observed:start id=errors/dd-duplicate-dim -->
**観察例** (nesemu 実機検証):

同じ配列を 2 度 DIM すると ?DD ERROR。

```basic
10 DIM A(3):DIM A(3)
```

出力:

```
  ?DD ERROR IN 10
```

エラーマーカー: `?DD ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 配列

### `ERROR_DZ`

0 による除算

**コード**: `DZ`
**メッセージ**: Division by zero
**原因**: `/` 除算の右辺が 0、または `MOD` の右辺が 0

**対処**: 除数が 0 にならないよう IF で事前チェック

<!-- probe-observed:start id=errors/dz-divide-by-zero -->
**観察例** (nesemu 実機検証):

0 で除算すると ?DZ ERROR。

```basic
10 PRINT 1/0
```

出力:

```
  ?DZ ERROR IN 10
```

エラーマーカー: `?DZ ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 数値

### `ERROR_TM`

変数の型が一致しない

**コード**: `TM`
**メッセージ**: Type mismatch
**原因**: 数値変数に文字列を代入、数値関数に文字列を渡した等。
`$` 付きと `$` なし変数の混同が典型。

**対処**: 変数名と用途の整合を確認

<!-- probe-observed:start id=errors/tm-type-mismatch -->
**観察例** (nesemu 実機検証):

数値変数に文字列を代入しようとすると ?TM ERROR。

```basic
10 A=1:A=A+"X"
```

出力:

```
  ?TM ERROR IN 10
```

エラーマーカー: `?TM ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 型

### `ERROR_ST`

文字列が 31 文字を超えている

**コード**: `ST`
**メッセージ**: String too long
**原因**: 連結や LEFT$/MID$ の結果が 31 文字超過
**対処**: 文字列分割、LEN で事前チェック

*タグ*: エラー, 文字列, 制約

### `ERROR_FT`

式が複雑過ぎる

**コード**: `FT`
**メッセージ**: Formula Too complex
**原因**: 式の入れ子が深すぎる、`( )` が異常に多い
**対処**: 中間変数に分割

*タグ*: エラー, 構文

### `ERROR_CC`

CONT によってプログラムの実行を続けることができない

**コード**: `CC`
**メッセージ**: Can't continue
**原因**: プログラムが編集された後、エラーで停止後にプログラム変更があった、等。
継続不可能な状態に陥った場合。

**対処**: RUN でやり直す

<!-- probe-observed:start id=errors/cc-cont-after-edit -->
**観察例** (nesemu 実機検証):

?CC ERROR は CONT 不可エラー (Cannot Continue)。実機観察: `STOP` で停止 → `BREAK IN 10` → `OK.` プロンプトで新規行 `5` を入力 (program 改変扱い) → `CONT` を打つと **`?CC ERROR`** が出る。手動で発火させづらいエラーを inject_keys 経由で確実に再現できた。発火条件は『プログラムを 1 行でも変更すると CONT は使えない』。

```basic
10 PRINT "A":STOP:PRINT "B"
```

出力:

```
  A
  BREAK IN 10
  OK.
  5
  CONT
  ?CC ERROR
```

エラーマーカー: `?CC ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 実行制御

### `ERROR_MO`

パラメータの設定がない場合に指定される

**コード**: `MO`
**メッセージ**: Missing operand
**原因**: 関数や文の必須引数が省略されている
**対処**: 引数を補う

<!-- probe-observed:start id=errors/mo-missing-operand -->
**観察例** (nesemu 実機検証):

オペランドなしの式 (`1+` で終わる) は実機では ?SN ERROR (構文エラー) として報告される。?MO は別経路で発生する可能性がある。

```basic
10 PRINT 1+
```

出力:

```
  ?SN ERROR IN 10
```

エラーマーカー: `?SN ERROR`
<!-- probe-observed:end -->


*タグ*: エラー, 構文

### `ERROR_TP`

カセットテープからデータが正しく読めない

**コード**: `TP`
**メッセージ**: Tape read ERROR
**原因**: LOAD 中にデータ破損・音量不足・速度ずれ等が検出された

**対処**: テープを巻き戻して再 LOAD、音量調整

*タグ*: エラー, IO, テープ

## メモリ (memory)

### `MEMORY_MAP`

ファミリーベーシックの物理メモリマップ

POKE/PEEK/CALL で扱うアドレス全体像。

| アドレス範囲 | 領域 | 用途 |
|-------------|------|------|
| `&H0000`-`&H07FF` | ワーク RAM (本体内蔵) | システム作業領域 (2KB) |
| `&H0800`-`&H1FFF` | 未使用 | アクセス不可 |
| `&H2000`-`&H5FFF` | システム使用 | I/O・PPU 等 |
| `&H6000`-`&H6FFF` | 未使用 | アクセス不可 |
| `&H7000`-`&H77FF` | ワーク RAM (BASIC カセット用) | 各種ボードデータまたは BASIC フリーエリア |
| `&H7800`-`&H7FFF` | 未使用 | アクセス不可 |
| `&H8000`-`&HFFFF` | プログラム ROM | ファミベ BASIC ROM 本体 |

### 重要な制約
- **`&H7000`-`&H703F` のエリアは POKE 等で個別に使用できない** — システム予約
- ユーザが自由に使えるのは事実上 `&H7040`-`&H77FF` の範囲
- 本体 RAM 0000-07FF (2KB) は内部利用が中心

### LLM 向け注意
- 「メモリ 2KB」と言うときの 2KB は本体内蔵 RAM (`&H0000`-`&H07FF`)
- BASIC プログラム本体は `&H7040`-`&H77FF` に格納される (約 1.95KB)
- これがファミベの「2KB 制約」の正体

*タグ*: メモリ, アドレス, 制約

### `MEMORY_USER_FREE_AREA`

ユーザが自由に使える RAM 領域

**アドレス**: `$7040-$77FF`
**サイズ**: 1984 バイト
**用途**: BASIC プログラム本体 + 各種ボード (BG GRAPHIC / MUSIC / MESSAGE) のデータ
**アクセス**: RW

- サイズは約 2KB だが、選択しているボードによって用途が変わる
- GAME BASIC プログラムを書く場合は実質ここがプログラム上限
- LIST 出力時の長さ感はこの領域に依存

*タグ*: メモリ, ユーザ領域

### `MEMORY_PRG_ROM`

プログラム ROM 領域

**アドレス**: `$8000-$FFFF`
**サイズ**: 32768 バイト
**用途**: ファミリーベーシック BASIC インタプリタ ROM
**アクセス**: R

- PEEK で読むとインタプリタコードが取れる
- CALL でこの領域内のサブルーチンを呼べる (アドレスは fbdasm 等で確認)

*タグ*: メモリ, ROM

## 文字コード (character_code)

### `CHARSET_SPRITE_TABLE_A`

スプライト・アニメキャラクタ用コード一覧 (0-255)

DEF SPRITE / SPRITE 文で `n` として指定するスプライトキャラクタの ID。
各 ID にプリセットのスプライト絵柄が割り当てられている。

### 主要なグループ
キャラクタテーブル A の確定マップは別エントリ `SPRITE_CHARACTER_MAP`
(v21-p115-116.md) を参照。本表は概観のみ。

| コード範囲 | キャラクタ | ポーズ数 |
|-----------|---------|---------|
| 0-27   | マリオ | 7 |
| 28-55  | レディ | 7 |
| 56-63  | ファイターフライ (ハエさん) | 2 |
| 64-87  | アキレス | 6 |
| 88-95  | ニタニタ | 2 |
| 96-111 | ペンペン (ペンギンさん) | 4 |
| 112-119| ファイアーボール | 2 |
| 120-143| 車 | 6 |
| 144-151| スピナー | 2 |
| 152-163| スターキラー | 3 |
| 164-175| スターシップ | 3 |
| 176-183| 爆発 | 2 |
| 184-191| シェルクリーパー (カメさん) | 2 |
| 192-199| サイドステッパー (カニさん) | 2 |
| 200-207| ニットピッカー (トリさん) | 2 |
| 208-213| レーザー (8×8 単タイル、別エントリ) | 6 |

### LLM 向け使い方
- DEF SPRITE 文でスプライト番号を指定するときに参照
- DEF MOVE でアニメーション系列を組むときの隣接フレーム選択に使用
- キャラごとに**ポーズ数は可変** (2〜7)、32 コード均等ではない
- 詳細な CHR$ × ポーズ対応は `SPRITE_CHARACTER_MAP` 参照
- 画像本体はキャラクタテーブル A を視覚的に参照

*タグ*: 文字コード, スプライト, アニメ

### `CHARSET_BG_KEYBOARD`

BG GRAPHIC + キーボード用キャラクタコード (主に PRINT で使用)

BASIC 上で扱う「テキスト」のコード体系。**PRINT、CHR$()、ASC() を使うときの参照**。

### コード 0-31: グラフィック領域 (CGEN1)
各コードに `(A0)`〜`(D7)` のような CGEN ID が割り当てられた小キャラクタ。
BG GRAPHIC で使うパターンセット。コード値そのものは ASCII 制御コード位置と
重なるが、**CGSET で割り当てられたグラフィックパターンとして表示される**。

### コード 32-95: ASCII 互換領域
| コード | 文字 | コード | 文字 |
|-------|------|-------|------|
| 32 ($20) | (空白) | 64 ($40) | @ |
| 33 ($21) | ! | 65 ($41) | A |
| 34 ($22) | " | 66-90 | B-Z (連続) |
| 35 ($23) | # | 91 ($5B) | [ |
| 36 ($24) | $ | 92 ($5C) | ¥ (※円記号) |
| 37 ($25) | % | 93 ($5D) | ] |
| 38 ($26) | & | 94 ($5E) | ^ |
| 39 ($27) | ' | 95 ($5F) | _ |
| 40 ($28) | ( | | |
| 41 ($29) | ) | | |
| 42 ($2A) | * | | |
| 43 ($2B) | + | | |
| 44 ($2C) | , | | |
| 45 ($2D) | - | | |
| 46 ($2E) | . | | |
| 47 ($2F) | / | | |
| 48-57 ($30-$39) | 0-9 | | |
| 58 ($3A) | : | | |
| 59 ($3B) | ; | | |
| 60 ($3C) | < | | |
| 61 ($3D) | = | | |
| 62 ($3E) | > | | |
| 63 ($3F) | ? | | |

### コード 96-127: カタカナ領域
JIS X 0201 半角カタカナ相当のコード割当。
| コード | 文字 |
|-------|------|
| 96 ($60) | ア |
| 97 ($61) | イ |
| 98 ($62) | ウ |
| 99 ($63) | エ |
| 100 ($64) | オ |
| 101 ($65) | カ |
| 102 ($66) | キ |
| 103 ($67) | ク |
| 104 ($68) | ケ |
| 105 ($69) | コ |
| 106 ($6A) | サ |
| 107 ($6B) | シ |
| 108 ($6C) | ス |
| 109 ($6D) | セ |
| 110 ($6E) | ソ |
| 111 ($6F) | タ |
| 112 ($70) | チ |
| 113 ($71) | ツ |
| 114 ($72) | テ |
| 115 ($73) | ト |
| 116 ($74) | ナ |
| 117 ($75) | ニ |
| 118 ($76) | ヌ |
| 119 ($77) | ネ |
| 120 ($78) | ノ |
| 121 ($79) | ハ |
| 122 ($7A) | ヒ |
| 123 ($7B) | フ |
| 124 ($7C) | ヘ |
| 125 ($7D) | ホ |
| 126 ($7E) | マ |
| 127 ($7F) | ミ |

### LLM 向け重要事項
- **コード 92 は `\` (バックスラッシュ) ではなく `¥` (円記号)** — JIS の慣例
- 漢字・ひらがなは扱えない (カタカナのみ)
- PRINT で英数字を出すときは ASCII 互換でほぼ問題ない
- PRINT で日本語を出すときは半角カタカナのみ。文字列は `"アイウ"` のように直接書く
- 0-31 のグラフィックは `CHR$(0)` 等で直接出力するか、CGEN/CGSET 経由

*タグ*: 文字コード, ASCII, カタカナ

### `VISUAL_CHARTABLE_B`

BG GRAPHIC 用キャラクタテーブル B (視覚版)

13 行 (A〜M) × 16 列 (0〜F) の格子で、各セルに BG GRAPHIC 用の
8×8 ドットグラフィックパターンが描かれている。

使用方法:
- BG GRAPHIC モード / CGSELECT で表示・選択する元画像
- 各セルの位置 = 「行アルファベット + 列 16 進数」が **CGEN1 ID**
  (例: A0, A1, ..., M9)
- 例: ロボット風キャラを描くなら、テーブル B の特定セル群を選んで配置

*タグ*: 文字コード, BG GRAPHIC, 視覚資料

### `VISUAL_CHARTABLE_A`

スプライト用キャラクタテーブル A (視覚版)

スプライトとして使えるアニメキャラクタの絵柄一覧 (見開き 1 ページ)。
各キャラごとに**ポーズ数は可変** (8×8 単タイルのレーザーまで含めて合計 256 コード)。

主要キャラクタ (DEF MOVE の A 引数 = 0〜15 順):

- A=0  マリオ (7 ポーズ)
- A=1  レディ (7 ポーズ)
- A=2  ファイターフライ / ハエさん (2 ポーズ)
- A=3  アキレス (6 ポーズ)
- A=4  ペンペン / ペンギンさん (4 ポーズ)
- A=5  ファイアーボール (2 ポーズ)
- A=6  車 (6 ポーズ)
- A=7  スピナー (2 ポーズ)
- A=8  スターキラー (3 ポーズ)
- A=9  スターシップ (3 ポーズ)
- A=10 爆発 (2 ポーズ)
- A=11 ニタニタ (2 ポーズ)
- A=12 レーザー (8×8 単タイル、6 種)
- A=13 シェルクリーパー / カメさん (2 ポーズ)
- A=14 サイドステッパー / カニさん (2 ポーズ)
- A=15 ニットピッカー / トリさん (2 ポーズ)

詳細マップは `SPRITE_CHARACTER_MAP` (16×16) と `SPRITE_8X8_LASERS` (8×8) 参照。

*タグ*: 文字コード, スプライト, 視覚資料

### `SPRITE_8X8_LASERS`

8×8 単タイルスプライト (コード 208-213, レーザー各種、弾丸・projectile に使える)

キャラクタテーブル A の末尾 (コード **208〜213** の 6 個) は、**8×8 ドット単タイル**
のスプライト。レーザーの**向き × バリエーション**で構成:

| コード | 内容 |
|-------|---------------------|
| 208 | レーザー (よこ 1) |
| 209 | レーザー (よこ 2) |
| 210 | レーザー (ななめ 1) |
| 211 | レーザー (ななめ 2) |
| 212 | レーザー (たて 1) |
| 213 | レーザー (たて 2) |

(向き 3 種 × バリエーション 2)。**上下左右反転**を組合せると 8 方向の表現に拡張可能。

### 使い方

8×8 単タイルなので **DEF SPRITE の B 引数 = 0** + **CHR$ 1 つ** で定義する
(16×16 用の 4 連結とは異なる):

- 既設キャラとしては「レーザー」と分類されているだけだが、**弾丸 / projectile /
  銃弾 / ミサイル / 小さな飛び道具** の表現に最適 (8×8 = 1 タイルで軽い)
- 16×16 スプライトと違って 4 タイル組合せが不要なので、**LLM が単純に 1 つ
  の CHR$ コードを指定するだけで完成**する。「ボールが画面を跳ね返る」のような
  課題で **弾代わりとして使うのが正解**
- 縦シューティングなら 210 or 211 (たて) を、横シューティングなら 208 or 209
  (よこ) を使い分けると視覚的に正しい

### 注意点

- **16×16 スプライト (マリオ等) と混在可能**、それぞれ DEF SPRITE で B=0/B=1 を
  適切に指定すれば OK
- 同時表示できるスプライトは 8 個まで (`n = 0-7`、16×16 と 8×8 の合計)
- 8×8 スプライトに対して X 反転 (D=1) や Y 反転 (E=1) も指定可能、
  4 タイル並び替えのような複雑な操作は不要 (単純にビット反転される)

*タグ*: 文字コード, スプライト, 8x8, 弾丸, 必須

### `SPRITE_CHARACTER_MAP`

キャラクタテーブル A の 16×16 スプライト全マップ (キャラ × ポーズ × CHR$)

キャラクタテーブル A の全 16 種類のキャラについて、CHR$ コードと
ポーズの対応を網羅したマップ。**キャラごとにポーズ数は可変** (2〜7) で、
32 コード均等ではない点に注意。

8×8 単タイルのレーザー (208-213) は別エントリ `SPRITE_8X8_LASERS` 参照。
左右反転の規則は `SPRITE_COMPOSITION_RULE` 参照。

### 全体マップ (キャラ → コード範囲)

| コード範囲 | キャラクタ | ポーズ数 | DEF MOVE `A` |
|-----------|---------|---------|-------------|
| 0-27   | マリオ | 7 | 0 |
| 28-55  | レディ | 7 | 1 |
| 56-63  | ファイターフライ (ハエさん) | 2 | 2 |
| 64-87  | アキレス | 6 | 3 |
| 88-95  | ニタニタ | 2 | 11 |
| 96-111 | ペンペン (ペンギンさん) | 4 | 4 |
| 112-119| ファイアーボール | 2 | 5 |
| 120-143| 車 | 6 | 6 |
| 144-151| スピナー | 2 | 7 |
| 152-163| スターキラー | 3 | 8 |
| 164-175| スターシップ | 3 | 9 |
| 176-183| 爆発 | 2 | 10 |
| 184-191| シェルクリーパー (カメさん) | 2 | 13 |
| 192-199| サイドステッパー (カニさん) | 2 | 14 |
| 200-207| ニットピッカー (トリさん) | 2 | 15 |
| 208-213| レーザー (8×8 単タイル、別エントリ参照) | 6 | 12 |

### マリオ (7 ポーズ、コード 0-27)

全ポーズの元向きは**左向き**。右向きは L/R 列入れ替え + X 反転フラグ
(`SPRITE_COMPOSITION_RULE` 参照)。

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| WALK1 | `CHR$(0)+CHR$(1)+CHR$(2)+CHR$(3)`     | 立ち |
| WALK2 | `CHR$(4)+CHR$(5)+CHR$(6)+CHR$(7)`     | 歩き 1 |
| WALK3 | `CHR$(8)+CHR$(9)+CHR$(10)+CHR$(11)`   | 歩き 2 |
| JUMP  | `CHR$(12)+CHR$(13)+CHR$(14)+CHR$(15)` | ジャンプ |
| スリップ | `CHR$(16)+CHR$(17)+CHR$(18)+CHR$(19)` | 転倒/滑り |
| はしご | `CHR$(20)+CHR$(21)+CHR$(22)+CHR$(23)` | 右手が上 |
| DOWN  | `CHR$(24)+CHR$(25)+CHR$(26)+CHR$(27)` | 下向き |

- **歩行アニメ**: WALK1 → WALK2 → WALK3 → WALK1 ... の順で表示
- **はしご**: 左右反転と交互で昇降演出
- **DOWN**: 左右反転して向き変えに使える

### レディ (7 ポーズ、コード 28-55)

マリオと同じ構成。

| ポーズ | CHR$ 並び |
|-------|----------|
| WALK1 | `CHR$(28)+CHR$(29)+CHR$(30)+CHR$(31)` |
| WALK2 | `CHR$(32)+CHR$(33)+CHR$(34)+CHR$(35)` |
| WALK3 | `CHR$(36)+CHR$(37)+CHR$(38)+CHR$(39)` |
| JUMP  | `CHR$(40)+CHR$(41)+CHR$(42)+CHR$(43)` |
| スリップ | `CHR$(44)+CHR$(45)+CHR$(46)+CHR$(47)` |
| はしご | `CHR$(48)+CHR$(49)+CHR$(50)+CHR$(51)` |
| DOWN  | `CHR$(52)+CHR$(53)+CHR$(54)+CHR$(55)` |

### ファイターフライ (ハエさん) — 2 ポーズ、コード 56-63

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) 羽が開 | `CHR$(56)+CHR$(57)+CHR$(58)+CHR$(59)` | |
| (2) 羽が閉 | `CHR$(60)+CHR$(61)+CHR$(62)+CHR$(63)` | |

- 1 と 2 を交互に表示すると羽ばたきアニメ
- 左右反転で向き変え (差は少ない)

### アキレス — 6 ポーズ、コード 64-87

車と同じ 3 方向 × 2 バリエーション構成。

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (左 1)   | `CHR$(64)+CHR$(65)+CHR$(66)+CHR$(67)` | 左向き |
| (左 2)   | `CHR$(68)+CHR$(69)+CHR$(70)+CHR$(71)` | 左向き |
| (左上 1) | `CHR$(72)+CHR$(73)+CHR$(74)+CHR$(75)` | 左上向き |
| (左上 2) | `CHR$(76)+CHR$(77)+CHR$(78)+CHR$(79)` | 左上向き |
| (上 1)   | `CHR$(80)+CHR$(81)+CHR$(82)+CHR$(83)` | 上向き |
| (上 2)   | `CHR$(84)+CHR$(85)+CHR$(86)+CHR$(87)` | 上向き |

- 各方向で 1 と 2 を交互に表示すると動きアニメ
- 上下左右反転で 8 方向に拡張可能

### ニタニタ — 2 ポーズ、コード 88-95

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) 口が開 | `CHR$(88)+CHR$(89)+CHR$(90)+CHR$(91)` | |
| (2) 口が閉 | `CHR$(92)+CHR$(93)+CHR$(94)+CHR$(95)` | |

- 1 と 2 を交互で口パクアニメ
- 左右反転で向き変え (差は少ない)

### ペンペン (ペンギンさん) — 4 ポーズ、コード 96-111

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (左歩 1) 足下げ | `CHR$(96)+CHR$(97)+CHR$(98)+CHR$(99)`     | 左向き |
| (左歩 2) 足上げ | `CHR$(100)+CHR$(101)+CHR$(102)+CHR$(103)` | 左向き |
| (正面) | `CHR$(104)+CHR$(105)+CHR$(106)+CHR$(107)` | 正面 |
| (後ろ) | `CHR$(108)+CHR$(109)+CHR$(110)+CHR$(111)` | 後ろ |

- 左歩 1 と 2 を交互で歩行アニメ
- 正面・後ろは左右反転と交互で動きの表現

### ファイアーボール — 2 ポーズ、コード 112-119

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) 火の粉あり | `CHR$(112)+CHR$(113)+CHR$(114)+CHR$(115)` | 左向き |
| (2) 火の粉なし | `CHR$(116)+CHR$(117)+CHR$(118)+CHR$(119)` | 左向き |

- 1 と 2 を交互で揺らめき
- 左右反転で進行方向に合わせる

### 車 — 6 ポーズ、コード 120-143

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (左 1) | `CHR$(120)+CHR$(121)+CHR$(122)+CHR$(123)` | 左向き |
| (左 2) | `CHR$(124)+CHR$(125)+CHR$(126)+CHR$(127)` | 左向き |
| (左上 1) | `CHR$(128)+CHR$(129)+CHR$(130)+CHR$(131)` | 左上向き |
| (左上 2) | `CHR$(132)+CHR$(133)+CHR$(134)+CHR$(135)` | 左上向き |
| (上 1)   | `CHR$(136)+CHR$(137)+CHR$(138)+CHR$(139)` | 上向き |
| (上 2)   | `CHR$(140)+CHR$(141)+CHR$(142)+CHR$(143)` | 上向き |

- 各方向で 1 と 2 を交互で走行アニメ
- 上下左右反転で 8 方向に拡張

### スピナー — 2 ポーズ、コード 144-151

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) ＋型 | `CHR$(144)+CHR$(145)+CHR$(146)+CHR$(147)` | クロス |
| (2) ×型 | `CHR$(148)+CHR$(149)+CHR$(150)+CHR$(151)` | バツ |

- 1 と 2 を交互で回転アニメ
- 反転しても見た目はほぼ同じ

### スターキラー — 3 ポーズ、コード 152-163

| ポーズ | CHR$ 並び |
|-------|----------|
| (1) 左 | `CHR$(152)+CHR$(153)+CHR$(154)+CHR$(155)` |
| (2) 左上 | `CHR$(156)+CHR$(157)+CHR$(158)+CHR$(159)` |
| (3) 上 | `CHR$(160)+CHR$(161)+CHR$(162)+CHR$(163)` |

- 上下左右反転で 8 方向に拡張

### スターシップ — 3 ポーズ、コード 164-175

| ポーズ | CHR$ 並び |
|-------|----------|
| (1) 左 | `CHR$(164)+CHR$(165)+CHR$(166)+CHR$(167)` |
| (2) 左上　| `CHR$(168)+CHR$(169)+CHR$(170)+CHR$(171)` |
| (3) 上　| `CHR$(172)+CHR$(173)+CHR$(174)+CHR$(175)` |

- 上下左右反転で 8 方向に拡張

### 爆発 — 2 ポーズ、コード 176-183

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) 小 | `CHR$(176)+CHR$(177)+CHR$(178)+CHR$(179)` | 小爆発 |
| (2) 大 | `CHR$(180)+CHR$(181)+CHR$(182)+CHR$(183)` | 大爆発 |

- 1 → 2 と順に表示すれば爆発演出

### シェルクリーパー (カメさん) — 2 ポーズ、コード 184-191

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) 口が開 | `CHR$(184)+CHR$(185)+CHR$(186)+CHR$(187)` | 左向き |
| (2) 口が閉 | `CHR$(188)+CHR$(189)+CHR$(190)+CHR$(191)` | 左向き |

- 1 と 2 を交互で動きアニメ
- 左右反転で向き変え

### サイドステッパー (カニさん) — 2 ポーズ、コード 192-199

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) | `CHR$(192)+CHR$(193)+CHR$(194)+CHR$(195)` | 左向き |
| (2) | `CHR$(196)+CHR$(197)+CHR$(198)+CHR$(199)` | 左向き |

- 1 と 2 を交互で動きアニメ
- 左右反転で向き変え

### ニットピッカー (トリさん) — 2 ポーズ、コード 200-207

| ポーズ | CHR$ 並び | 備考 |
|-------|----------|------|
| (1) 口が閉 | `CHR$(200)+CHR$(201)+CHR$(202)+CHR$(203)` | 左向き |
| (2) 口が開 | `CHR$(204)+CHR$(205)+CHR$(206)+CHR$(207)` | 左向き |

- 1 と 2 を交互で口パクアニメ
- 左右反転で向き変え

### レーザー — 6 種、コード 208-213 (8×8 単タイル)

8×8 単タイルなので **B=0 + CHR$ 1 つ** で定義 (16×16 用の 4 連結ではない)。
詳細な使い方は別エントリ `SPRITE_8X8_LASERS` 参照。

| ポーズ | CHR$ |
|-------|------|
| (1) よこ | `CHR$(208)` |
| (2) よこ | `CHR$(209)` |
| (3) ななめ | `CHR$(210)` |
| (4) ななめ | `CHR$(211)` |
| (5) たて | `CHR$(212)` |
| (6) たて | `CHR$(213)` |

- 上下左右反転で 8 方向に拡張可能
- 弾丸・projectile としても使える

### LLM 向け重要指示

- **動作確認済の組合せ (上記表)** をそのまま使う
- **左右反転は両操作必須** (L/R 列入れ替え + X 反転フラグ)、`SPRITE_COMPOSITION_RULE`
  参照
- **未確認のキャラ・ポーズ** を使うときは `DEF MOVE(n) = SPRITE(A, B, C, D, E, F)`
  で `A=0〜15` を指定して自動描画に任せる方が安全:
  *タグ*: 記号, 構文

### `SYM_COMMA`

カンマ `,` でオペランドを区切る

- PRINT, INPUT, DATA 等で複数値を区切る
- PRINT で `,` を使うと **次の出力ブロックの先頭に揃えて**出力
  (画面幅 28 文字を 8+8+8+4 の 4 ブロックに分割、先頭は 0, 8, 16, 24)
- DATA 文では値の区切り

*タグ*: 記号, 構文

### `SYM_COLON`

コロン `:` でマルチステートメントを区切る

- 1 行内で複数文を並べるときに使う
- 条件分岐内のブロック相当の代用
- 1 行 255 桁制限内で詰め込む手段

*タグ*: 記号, 構文

### `SYM_SEMICOLON`

セミコロン `;` で PRINT の出力を密着連結

- PRINT 文で値を **密着** して出力 (タブ揃えしない)
- 末尾 `;` で改行抑制
- INPUT 文ではプロンプト文字列と入力欄の区切り

*タグ*: 記号, 構文

### `SYM_QUESTION_PRINT`

クエスチョンマーク `?` は PRINT の代用

- **`?` 単独で PRINT として機能する**
- キー入力短縮の常套手段
- LIST すると `PRINT` に展開されて表示される (実装によるが BASIC 一般の流儀)

*タグ*: 記号, 構文, 略記

### `SYM_AMP_HEX`

`&H` 接頭辞で 16 進数リテラルを表す

- **`&H` で始まる数値リテラルは 16 進数**
- それ以外は 10 進数として解釈
- 範囲は &H0000〜&HFFFF (16 ビット符号なしと等価)
- メモリアドレス、ビットマスク等で頻用

*タグ*: 記号, リテラル, 16進

### `CTRL_CODES_TABLE`

CTRL+キー組み合わせの制御コード一覧

`CTR + X` の操作 (INS キーを押しながら X キー)。プログラム中で
CHR$() で送出することもできる場合がある (要確認)。

| キー | 機能 |
|------|------|
| CTR+A | INS モード ON/OFF スイッチ |
| CTR+C | BREAK (実行中プログラムを中断) |
| CTR+D | 起動設定: CGEN2, SPRITE OFF |
| CTR+E | カラーパレットをスプライト面/バックグラウンド面/バックドロップ面でリセット |
| CTR+F | カーソル位置 1 行分の消去 |
| CTR+G | BEEP 音を出す |
| CTR+H | DEL と同じ機能 |
| CTR+I | ラインフィード (行送り) (TAB キーと同等) |
| CTR+K | カーソルキーの上 (↑) と同じ |
| CTR+L | 画面クリア |
| CTR+M | 1 行入力させる (キャリッジリターン) |
| CTR+R | INS と同じ機能 |
| CTR+S | カナキーロック |
| CTR+W | 英・数字を制御 |
| CTR+Z | カーソル位置以降画面下までクリア |

*タグ*: 制御コード, キーボード

## イディオム / 実用パターン (idiom)

### `IDIOM_RELATIONAL_AS_VALUE`

関係演算子の結果を数値として使う流儀 (真 = -1, 偽 = 0)

- **関係式は真のとき -1、偽のとき 0 を返す** (整数として)
- これを使ってトリッキーな代入が可能
- 例: `A = X - (X>0)` で「X>0 なら A=X-(-1)=X+1, X<=0 なら A=X-0=X」
- LLM 出力としては可読性が低いので、IF-THEN を優先することを推奨

<!-- probe-observed:start id=idioms/relational-as-value -->
**観察例** (nesemu 実機検証):

比較式は -1 (真) または 0 (偽) を返すので、乗算で条件付き加算を表現できる。

```basic
10 PRINT (5>3)*10:PRINT (3>5)*10
```

出力:

```
  -10
   0
```
<!-- probe-observed:end -->


*タグ*: 演算子, イディオム, 関係

### `IDIOM_BOOLEAN_VALUES`

真偽値は -1 (真) / 0 (偽) の 16 ビット整数

- 関係式の結果は **-1 (= 0xFFFF) または 0**
- NOT は全ビット反転なので NOT(-1) = 0, NOT(0) = -1 (= 0xFFFF) になる
- これによりビット論理演算子がそのまま「論理演算子」として使える
- 一般的な BASIC 同様の流儀 (C 系の 1/0 と異なる点に注意)

<!-- probe-observed:start id=idioms/boolean-values -->
**観察例** (nesemu 実機検証):

Family BASIC の真偽値は -1 (真) と 0 (偽)。

```basic
10 PRINT -1:PRINT 0:PRINT 5>3:PRINT 5<3
```

出力:

```
  -1
   0
  -1
   0
```
<!-- probe-observed:end -->


*タグ*: イディオム, 論理, 真偽値

### `SPRITE_COMPOSITION_RULE`

16×16 スプライトの 4 タイル組み立てルール (LLM 必須知識)

**DEF SPRITE で 16×16 スプライトを作るときの 4 タイル並び順**:

```
DEF SPRITE n, (A, B, C, D, E) = CHR$(t1) + CHR$(t2) + CHR$(t3) + CHR$(t4)
                                      ↓        ↓        ↓        ↓
                                   左上     右上     左下     右下
```

- **B 引数 = 1** (16×16 サイズ) で、4 つの 8×8 タイルを 2×2 に並べる
- **連続する 4 コード** (例: 0,1,2,3) が **1 つのポーズ** を構成する
- キャラクタテーブル A の各セルが「コード範囲 + 絵柄」を示す

### 左右反転 (X 反転) のルール — LLM が間違えやすい中核

同じキャラを左右両向きで使いたい場合、**2 つの操作が両方必要**:

1. **4 タイルの L/R 列を入れ替える**:
   `CHR$(t1)+CHR$(t2)+CHR$(t3)+CHR$(t4)` (右向き)
   → `CHR$(t2)+CHR$(t1)+CHR$(t4)+CHR$(t3)` (左向き)
2. **DEF SPRITE の D 引数 (X 反転フラグ) を 1 に設定**:
   `DEF SPRITE n, (A, B, C, 1, E) = ...`

両方やらないと:
- **L/R 入れ替えだけ**: タイル位置は左右逆になるが、各タイル内部の絵は右向きのまま
  → 顔が後ろを向いた変な絵
- **X 反転フラグだけ**: 各タイル内部は反転するが、配置は元のまま
  → 顔が左にあるが体が右側を向いた、つなぎ目がずれた絵

### 例 (マリオ立ち、SAMPLE_WALK_ANIM より)

*タグ*: スプライト, 構成ルール, 必須

### `SAMPLE_POSE_MARIO`

マリオの 6 種類のポーズをスプライト面に並べる (DEF SPRITE 入門)

16×16 ドットのスプライトを定義して画面に配置する基本パターン。

要点:
- **`CGSET 1, 0`** でキャラクタセットを選択 (キャラクタテーブル A を使う)
- **`DEF SPRITE n, (パレット, サイズ, 優先度, X反転, Y反転) = CHR$(...)`**
- サイズ `0` = 8×8 (CHR$ × 1 個)、サイズ `1` = 16×16 (CHR$ × 4 個)
  - 4 個の並びは「左上、右上、左下、右下」
- X 反転 `= 1` で左右反転 (歩行アニメの左向きに使える)
- **SPRITE n, X, Y** で画面に配置 (省略すれば非表示)

*タグ*: サンプル, スプライト, マリオ

### `SAMPLE_PAD_LR_MOVE`

コントローラでマリオを左右に動かす (STICK 入力ループ)

STICK(0) でコントローラの方向を取得し、スプライト座標を更新するメインループ。

要点:
- **STICK の値はビットフラグ**: 0=なし, 1=右, 2=左, 4=下, 8=上
- **画面端の処理 (ワープ)** を忘れずに (X > 250 / X < 5)
- メインループは **GOTO で回す**
- 押されていない (`S = 0`) ときは更新しない (`IF S = 0 THEN 60`)

*タグ*: サンプル, コントローラ, ループ

### `SAMPLE_WALK_ANIM`

コントローラでマリオを歩かせる (SWAP + 複数 DEF SPRITE で歩行アニメ)

6 つのスプライト定義を切り替えて歩行アニメーションを実現する完全なゲームループ。

要点:
- **SPRITE ON** で画面にスプライトを表示開始
- 複数の DEF SPRITE で歩行パターン (右向き 2 フレーム + 左向き 2 フレーム + 立ち) を定義
- **SWAP 命令でスプライト番号を入れ替えてアニメーション**
- **PAUSE 5** で 5 フレーム待ってアニメーション速度を調整
- 右方向と左方向で異なるスプライトセットを使い分ける
- **SPRITE n (座標なし) でそのスプライトを非表示** にする

*タグ*: サンプル, スプライト, アニメ, ループ

### `SAMPLE_MOVE_8DIR`

DEF MOVE で 8 方向に動かす (MOVE 命令の基本)

**DEF MOVE は 16 種類のプリセットキャラクタを自動アニメーション付きで動かす命令**。
DEF SPRITE より簡単にキャラクタを表示・移動できる。

要点:
- **DEF MOVE(n) = SPRITE(A, B, C, D, E, F)** でキャラクタの種類と動きを定義
  - n: 動作番号 (0〜7)
  - A: キャラクタ種類 (0〜15、プリセット)
  - B: 方向 (0=静止, 1〜8=8 方向)
  - C: 速さ (1=最高速, 255=最低速)
  - D: 全移動量 (1〜255、0 だと表示されない)
  - E: 配色番号 (0〜3)
  - F: 表示の優先度 (0=BG の手前, 1=BG の後ろ)
- **MOVE n[, n, ...]** で動作を開始。同時に 8 個まで
- **MOVE(n) 関数**: `-1` = 動作中, `0` = 停止中

*タグ*: サンプル, スプライト, MOVE

### `SAMPLE_MOVE_PAD_CTRL`

コントローラで MOVE キャラクタを操作 (方向切替パターン)

STICK(0) で方向を取得し、DEF MOVE の方向を動的に切り替える。

要点:
- **方向ごとに DEF MOVE を事前定義**し、入力に応じて切り替える
- **ERA M でキャラクタを消し、POSITION + MOVE で新しい方向に再配置**
- **MOVE(M) = -1 で動作完了を待つ**
- **XPOS(n), YPOS(n) で現在座標を取得**
- STICK 値 1=右, 2=左, 4=下, 8=上 → 対応する DEF MOVE 番号にマップ

*タグ*: サンプル, スプライト, MOVE, コントローラ

### `SAMPLE_JUMP_CHAIN`

マリオをジャンプさせる (複数 MOVE 連鎖でジャンプ軌道)

複数の MOVE を連鎖してジャンプ軌道を表現する。

要点:
- **方向 3 (右) → 方向 2 (右上) → 方向 4 (右下) を連鎖** してジャンプ軌道を作る
- 各 MOVE の完了を `MOVE(n) = -1` で待ってから次の MOVE に引き継ぐ
- **ERA → POSITION → MOVE の 3 ステップ** でキャラクタを引き継ぐ
- 同じスプライト番号を使わず、複数の動作番号を渡り歩く

*タグ*: サンプル, スプライト, MOVE, ジャンプ
