R-BASIC (Robot BASIC) 言語仕様書
本書は、ロボット建築シミュレータ (Robot Building Simulator: RBS) における自律ロボット制御用スクリプト言語 R-BASIC の完全な言語仕様を定義します。
1. 概要と実行モデル
1.1 基本コンセプト
- 行番号なし・ラベル駆動: 古典的BASICの行番号を排し、ラベル(
*labelまたはlabel:)とgoto/gosub/returnによる直感的なステートマシン制御を採用。 - 自然な数式評価: 四則演算・剰余・比較演算・論理演算・カッコ括りを備え、操車場アルゴリズム(Shunting-yard algorithm)による逆ポーランド記法スタックマシンで高速に評価。
- メモリー配列 (
mem[0..63]): ローカル変数(最大128個)に加え、番号で数値を記録・参照できる 64 要素の配列メモリmem[0..63]を標準装備。工程管理や複数データの保持に役立ちます。 - 明確な 1 Tick 行動モデル:
- ロボットは物理アクション命令(
get,put,step,turn,go,wait)を実行した瞬間に 1 Tick を消費して停止し、シミュレータに制御を戻します。 - 数式計算・変数代入・条件分岐・サブルーチン呼び出しなどの非アクション命令は同一 Tick 内で即座に評価・実行されます。
- 無限ループ防止のため、1 Tick あたり最大 500 バイトコード命令を実行すると、そのロボットの当 Tick の処理を打ち切り、警告が記録されます。次の Tick で続きを実行します。ソースの1文が複数のバイトコード命令になることがあります。
2. 構文仕様 (Syntax)
2.1 行・コメント・空白
- 1行1文: 1 行に 1 つの文を記述します。空行および空白文字は無視されます。ラベル末尾を除き、コロン
:は使用できません。 - コメント: 行内の
;、//、または単語REM以降、行末までがコメントとして扱われます。basic ; これはコメントです x = 1 // これもコメントです REM これもコメントです - ブロックブレースの無視:
{および}単体の行は無視されるため、C言語風のインデントブロック表記も視覚的に利用可能です。
2.2 ラベル
- ラベルは制御のジャンプ先を定義します。行頭に
*を置く形式、または識別子の末尾に:を置く形式のいずれも有効です。basic *main_loop loop_start: - ラベル名は大文字・小文字を区別しません(Case-insensitive)。英数字およびアンダースコア
_が使用可能です。 - 同一スクリプト内で最大 256 個まで定義できます。
2.3 変数 (Variables)
- アルファベット(
a-z,A-Z)またはアンダースコア_で始まる識別子を変数として使用できます。 - 変数は 32bit 符号付き整数として扱われます。
- 初期値はすべて
0です。 - ロボット 1 台につき最大 128 個の一意なローカル変数を保持できます。
- 変数への代入構文:
basic count = 0 step_size = count * 2 + 1
2.4 メモリー配列 (mem[])
- 番号(インデックス)を指定して数値を読み書きできる、ロボット専用の 64 要素の配列です。
mem[<式>]またはmem(<式>)の構文で読み書きします。- インデックスは
0〜63(全 64 個)です。初期値はすべて0です。 - 番号を変数で指定できるため、ループ処理でのデータ巡回や、複数の状態フラグ・工程ステップの管理に便利です。
- 範囲外のインデックスにアクセスした場合、ロボットの
lastErrorに"Memory index out of bounds: <idx>"が記録され、読み込み時は0を返します。basic mem[0] = 100 ptr = 5 mem[ptr] = mem[0] + 1 value = mem[ptr]
3. 式と演算子 (Expressions & Operators)
3.1 演算子一覧と優先順位
数式は標準的な演算子の優先順位に従って評価されます。カッコ ( ... ) を用いて優先順位を自由に変更できます。
| 優先度 | 演算子 | 種別 | 説明 | 結合性 |
|---|---|---|---|---|
| 1 (高) | ( ... ) |
グループ | カッコ | - |
| 2 | - (単項), ! (または NOT) |
単項演算子 | 符号反転(マイナス)、論理否定 | 右結合 |
| 3 | *, /, % |
算術積除 | 乗算、除算、剰余(整数演算) | 左結合 |
| 4 | +, - |
算術加減 | 加算、減算 | 左結合 |
| 5 | == (または =), != (または <>), <, <=, >, >= |
比較 | 等価・不等価・大小比較(真なら 1、偽なら 0) | 左結合 |
| 6 | && (または AND) |
論理積 | 両辺が真(非ゼロ)なら 1、それ以外は 0 | 左結合 |
| 7 (低) | \|\| (または OR) |
論理和 | いずれかが真(非ゼロ)なら 1、それ以外は 0 | 左結合 |
注意 (ゼロ除算):
/または%で除数が0の場合、エラー"Division by zero"が記録され、結果は0となります。
3.2 文字列リテラル
print以外の式では、"heavy","pillar"などのダブルクォート囲み文字列を対応する組み込み定数値に変換します。printの式では文字列として扱います(8.1参照)。basic if carrying == "heavy" then goto *found
4. 制御構文 (Control Flow)
4.1 無条件ジャンプ (goto)
指定したラベルへプログラムカウンタをジャンプさせます。ラベル名の先頭の * は省略可能です。
goto *target_label
goto next_step
4.2 サブルーチン呼出と復帰 (gosub / return)
指定ラベルへサブルーチンジャンプし、呼び出し元の次の命令アドレスをコールスタックに退避します。
return で退避されたアドレスへ復帰します。
gosub *turn_around
; ここに復帰する
*turn_around
turn RIGHT
turn RIGHT
return
- コールスタックの最大深度は 128 です。
4.3 条件分岐 (if ... then ... else ...)
条件式が真(非ゼロ)なら then 側、偽(ゼロ)なら省略可能な else 側の文を実行します。
then は必須で、それぞれの分岐には goto、gosub、代入、ロボット命令などの1文だけを記述できます。入れ子の if とコロン : による複数文は使用できません。
if carrying != NONE then goto *do_put
if units >= 4 then gosub *full_stack
if check(FRONT) == EMPTY then step else turn RIGHT
4.4 プログラム終了・スリープ (end)
ロボットのスクリプト実行を停止し、ロボットを待機(スリープ)状態にします。
end
4.5 プログラム末尾の自動ループ
プログラムの末尾行まで実行が進むと、自動的に先頭(アドレス 0)に戻ってループ実行を継続します。明示的な goto *start を記述しても構いません。
5. 組み込み定数シンボル
以下の識別子は予約定数として定義されており、式の中で直接利用できます。大文字・小文字は問いません。
定数は32bit整数の上位バイトにカテゴリ、下位24bitに表中の値を持ちます。同じ下位値でも、材料・部材・セル・マーカー・相対方向・絶対方向は異なる値です。通常の整数として加減算でき、命令が消費する時点でカテゴリと下位値の範囲を検査します。
5.1 相対方向 (Relative Direction)
| 定数名 | 下位値 | 説明 |
|---|---|---|
FRONT |
0 | ロボットの正面 |
RIGHT |
1 | ロボットの右側(時計回りに90度) |
BACK |
2 | ロボットの後方(180度) |
LEFT |
3 | ロボットの左側(反時計回りに90度) |
5.2 絶対方角 (Absolute Direction)
| 定数名 | 下位値 | 説明 |
|---|---|---|
NORTH |
0 | 北 (+Y 方向) |
EAST |
1 | 東 (+X 方向) |
SOUTH |
2 | 南 (-Y 方向) |
WEST |
3 | 西 (-X 方向) |
5.3 材料種別 (Material)
| 定数名 | 下位値 | 説明 |
|---|---|---|
NONE |
0 | 材料なし / 手ぶら |
GROUND |
1 | 地面ブロック(採取・運搬不可) |
LIGHT |
2 | 軽量材(木材系: 基礎耐震 25) |
BALANCED |
3 | 標準材(鉄骨系: 基礎耐震 35) |
HEAVY |
4 | 重量材(コンクリート系: 基礎耐震 50) |
TENSILE |
5 | 高張力材(炭素繊維・テンシル系: 基礎耐震 40) |
5.4 部材種別 (Build Part)
| 定数名 | 下位値 | 必要材料ユニット | 説明 |
|---|---|---|---|
PART_NONE |
0 | 0 | 部材なし |
PILLAR |
1 | 4 | 柱(鉛直荷重・階層支持の中核) |
FLOOR |
2 | 2 | 床(ロボットの移動面・上層建築基盤) |
WALL |
3 | 2 | 壁(横方向の耐力壁) |
STAIR |
4 | 2 | 階段(階層間の上下昇降用部材) |
5.5 セル種別 (Cell Kind)
| 定数名 | 下位値 | 説明 |
|---|---|---|
EMPTY |
0 | 空き空間 |
MATERIAL |
1 | 配置済み材料スタック |
ORDER |
2 | 建築指示(未着工セル) |
CONSTRUCTION |
3 | 施工中(一部ユニット投入済み) |
MARKER |
8 | 誘導・巡回用マーカー |
5.6 マーカー形状 (Marker Kind)
| 定数名 | 下位値 | 外観 |
|---|---|---|
MK_NONE |
0 | マーカーなし |
MK_RED_CONE |
1 | 赤色コーン |
MK_BLUE_CUBE |
2 | 青色キューブ |
MK_GREEN_SPHERE |
3 | 緑色スフィア |
MK_YELLOW_DIAMOND |
4 | 黄色ダイヤモンド |
MK_PURPLE_CYLINDER |
5 | 紫色シリンダー |
5.7 その他
TRUE: 1FALSE: 0
6. 状態変数とセンシング関数(0 Tick / 即時評価)
式の中で呼び出され、同一 Tick 内で最新のロボット環境情報を取得します。時間を消費しません。
6.1 ロボット状態変数
carrying: ロボットが現在手持ちしている材料 ID(NONE,LIGHT,BALANCED,HEAVY,TENSILE)。カッコ付きcarrying()も許容。units: 手持ち材料のユニット数(0 〜 8)。pos_x,pos_y,pos_z: ロボットの現在ワールドグリッド座標。dir: ロボットが現在向いている絶対方角(NORTH,EAST,SOUTH,WEST)。assigned_mat: UIまたはシナリオからロボットに設定された担当材料 ID。assigned_part: UIまたはシナリオからロボットに設定された担当部材 ID(PILLAR,STAIR等)。
6.2 周囲センシング関数
引数 dir には相対方向(FRONT, RIGHT, BACK, LEFT)または絶対方角を指定します。
check(dir): 指定方向のセル種別(EMPTY,MATERIAL,ORDER,CONSTRUCTION,MARKER等)を返します。material(dir): 指定方向に材料スタックがある場合、その材料 ID を返します(存在しない場合はNONE)。order(dir): 指定方向に建築指示・施工中セルがある場合、その予定部材 ID(PILLAR,FLOOR等)を返します。marker(dir): 指定方向にマーカーがある場合、そのマーカー種別 ID を返します。
6.3 目標探索関数 (find)
- 構文:
find(<target>) - 最短の対象物を幅優先探索(BFS)で検索し、発見した場合はロボット内部のナビゲーションターゲットにロックして 1 (真) を返します。到達可能な経路に対象が存在しない場合は 0 (偽) を返します。
- 引数
<target>に指定可能な識別子: - 材料:
material,light,balanced,heavy,tensile, またはassigned_mat - 建築指示:
order(またはwork),pillar,floor,wall,stair, またはassigned_part - マーカー:
markerまたはMK_RED_CONE等のマーカー種別 - 引数は式として評価されるため、対象を変数へ代入できます。対応していないカテゴリや範囲外の値は実行時エラーになります。
- 戻り値は
if文で直接判定可能です:basic target = FLOOR if find(target) then goto *walk_to_order if find(HEAVY) then goto *walk_to_mat if find(assigned_part) then goto *walk_to_order
失敗時は以前のターゲットを保持します。結果座標を読む前に戻り値を確認してください。マーカー検索はマンハッタン距離で選択し、到達性を保証しません。
6.4 座標指定ナビゲーション
| 読取専用状態値 | 意味 |
|---|---|
has_target |
目標があれば1、なければ0 |
target_x, target_y, target_z |
対象物のセル座標 |
dest_x, dest_y, dest_z |
ロボットが立つ作業位置・移動先のセル座標 |
go_result |
直前のgoの結果 |
目標未設定時の座標はすべて -1。座標系は pos_x/y/z と共通でZが高さです。履歴ではないため、保持したい座標は変数や mem[] に保存します。
target_at(x, y, z):指定セルの材料・オーダー・施工中セル・マーカーについて、到達可能な作業位置を設定します。作業位置はfindと同じ規則で選び、到着時に対象へ向きます。マーカーではそのセルへの到達性も検査します。move_to(x, y, z):歩行・到達可能な指定セルそのものを移動先に設定します。他ロボットの占有セルは指定できません。到着時の追加旋回はなく、target_*とdest_*は同じ座標になります。
両方とも3個の整数式を左から右へ評価する0 Tickの関数で、成功1・失敗0を返します。例: ok = move_to(pos_x + 2, pos_y, pos_z)。単独呼出文ではなく、代入やifの式で使用します。実際の移動は別途 go で行います。
範囲外・対象なし・到達不能では失敗し、以前の目標も解除します。成否によらず go_result を GO_NONE に戻します。既存findは成功時のみ GO_NONE に戻し、失敗時は目標と結果を保持します。
| 結果定数 | 値 | 意味 |
|---|---|---|
GO_NONE |
0 | 初期状態または目標設定後でgo未実行 |
GO_MOVED |
1 | 1歩進んだ。最後の1歩も含む |
GO_ARRIVED |
2 | go開始時に移動先におり、向き調整と目標解除を完了 |
GO_FAILED |
-1 | 移動不能または目標未設定 |
最後の1歩の次のgoで到着となり、この到着処理も1 Tick消費します。結果は次のgoまたは目標設定まで保持し、wait/get等では上書きしません。Pause・休眠では保持、Reset・プログラム適用・セッション読込で初期化します。目標と結果は保存されません。読込後の再指定に使う座標は mem[] に保存してください。
対象は予約されず、消失・置換しても保存した作業位置への移動を続けます。到着は作業成功を保証しないため、作業前にセンサーで確認してください。経路が塞がれるとgoが失敗して目標解除・右旋回し、自動再試行は行いません。
新しい状態値・結果定数・関数名は予約名で代入できません。同名の既存変数は改名が必要です。
7. 物理アクション命令(1 Tick 消費)
ロボットが実世界に対して作用する命令です。実行された時点でそのロボットの 当 Tick の行動が確定し、1 Tick 経過するまで次の命令は実行されません。
7.1 get
- 正面のセルから材料を 1 ユニット 拾い上げます。
- 足元から鉛直方向 +3 ブロック(作業高さ範囲 4 セル内)の最上部スタックから採取します。
- 既に別の材料を持っている場合は何も拾えません(失敗)。
7.2 put
- 手持ちの材料を正面のセルに投入、または設置します。
- 正面に対象部材の
ORDERまたはCONSTRUCTIONがある場合: 1 ユニット投入します。必要ユニット数(柱=4、床/壁/階段=2)を満たすと完成し、完成報酬が資金に加算されます。 - 正面が地面または完成済み床で障害物がない場合: 地面に材料スタックとして 1 ユニット配置(ドロップ)します(最大4段スタック)。
7.3 step / move
- 現在向いている方向へ 1 ブロック前進 します。
- 同一平面の移動だけでなく、1段の段差の昇降(階段の登り下り、スロープ移動)にも対応します。
- 壁や未完成ブロック、空中に阻まれた場合は移動できず、その場で 1 Tick を消費します。
7.4 turn <dir>
- 向きを転換します。
- 相対方向:
turn LEFT,turn RIGHT,turn BACK,turn FRONT - 絶対方角:
turn NORTH,turn EAST,turn SOUTH,turn WEST - 引数には変数や式も指定できます。方向定数は時計回りに並ぶため、
turn NORTH + 1は東を向きます。 - 相対・絶対方向以外のカテゴリ、または下位値が 0〜3 の範囲外なら実行時エラーになります。
7.5 go
find(...)命令によってロックされた目的地に向かって、最短経路で 1 歩前進 します。- 目的地に到着するとロックが解除されます。
- 前方が別のロボットや障害物で一時的に塞がれた場合、ターゲットを破棄して自動的に右旋回します。
7.6 wait
- その場で何もせず 1 Tick 待機 します。
- 他のロボットの作業完了を待つ場合や、巡回タイマーのウェイト調整に使用します。
8. デバッグ・ログ命令
8.1 print <式>
- 指定した式の評価結果を、そのロボットの内部実行ログ(直近20件保持)に追加し、GUIではロボットの頭上にも表示します。
- GUI のプログラムエディタ/ログビューアでリアルタイムに確認できます。
- 0 Tick で実行され、時間を消費しません。
basic print carrying print mem[0]
文字列と数値を + で連結できます。両辺が数値なら加算、どちらかが文字列なら連結です。通常の数値は符号付き10進数へ変換されますが、タグ付き定数や状態変数(HEAVY, carrying, NORTH, dir, PILLAR など)は対応するシンボル名("HEAVY", "NORTH", "PILLAR" 等)として自動的に文字列化されます。通常の優先順位に従い、+ は左から評価します。
print "材料を探しています"
print "所持数=" + units
print "位置=(" + pos_x + "," + pos_y + "," + pos_z + ")"
print "値=" + 1 + 2 ; 値=12
print "値=" + (1 + 2) ; 値=3
print 1 + 2 + "個" ; 3個
print "引用符=\" バックスラッシュ=\\"
文字列の使用はprintの式内に限定され、変数・mem[]は整数のままです。文字列の減算・乗算・比較・数値関数への引数渡しはコンパイルエラーになります。引用符は \"、バックスラッシュは \\ で表し、その他のエスケープや文字列内の改行には対応しません。引用符内の ;・//・:・= はそのまま出力できます。
print "heavy" は heavy、print HEAVY は 4 を出力します。文字列長はCP932で1,023バイトまで。リテラルと各連結段階で、日本語の文字境界を保って末尾を ... に省略します。
頭上表示は半透明の背景に白文字で最大2行。長い内容は画面上だけさらに省略され、ログでは上記上限まで確認できます。各ロボットの最新1件を実時間3秒表示し、Pause中は残り時間を停止します。速度倍率には依存しません。新しいprintで内容と残り時間を更新し、同一フレームに複数出力した場合も全件をログへ記録します。print "" は頭上表示を消し、ログへ空行を追加します。
画面外・表示階層外のロボットは非表示。建築物による遮蔽は判定せず、重なった場合は選択中ロボットのメッセージを最前面に描画します。メッセージはクリックを遮りません。Reset・セッション読込・プログラム適用で頭上表示を消し、保存にはログのみを含めます。
9. システム制限値 (Resource Limits)
| 項目 | 制限値 | 超過時の動作 |
|---|---|---|
| 最大バイトコード命令数 | 4,096 命令 | コンパイルエラー (Program exceeds maximum bytecode capacity) |
| 最大ローカル変数数 | 128 個 | コンパイルエラー (Variable limit exceeded) |
| 最大定義ラベル数 | 256 個 | コンパイルエラー |
| 式コンパイラの演算子スタック深度 | 256 | コンパイルエラー(括弧・演算子の組み合わせで消費量が変わります) |
| データスタック深度 | 256 | 満杯の場合、追加の値は保存されません |
| コールスタック深度 | 128 | サブルーチン呼出が無視されます |
メモリー配列容量 (mem[]) |
64 要素 (0..63) |
実行時エラー記録、0 を返却 |
| 1 Tick あたりバイトコード命令数 | 500 命令 | 当 Tick の実行を打ち切り、Instruction limit reached (500) を記録。次 Tick で再開 |
| GUI・インポート・保存で扱えるソースコード最大長 | 65,535 バイト(CP932変換後) | 入力を制限、または読込・保存を拒否 |