ビジュアルノベルのためのDSL

を、実は日々妄想している。

個人的にはNScripterみたいな形式が好みだ。テキストが中心と言うか、RDのおんなじノリで好きなのである。吉里吉里も非常に優れたノベルゲームエンジンだと確信してはいるが、いかんせん"タグで挟む"っていうのが非常に好かない性質なので…。

NScripterを使うかとも思うけど、変数とかラベル名とgotoによるフロー管理とか、気にしだすと気になってくるところはあるもので(贅沢な話だけど)。

NScripterとか吉里吉里のマクロ言語としてでもいいから、自分好みのノベルゲーム用スクリプトのアイディアを考えては捨て、考えては捨て…。

今回はその妄想をちょっと書いてみる。
まだテキストをクォーテーションしなきゃいけない点でNScripter的スッキリさが足りない…。

ちなみに元にしているシナリオはisbn:9784777512928ル。

# scene は namespace かトップレベルに属する
namespace "Section1" do
  
  # scene の定義
  scene "start" do
    text "- シナリオスタート -"
    text "選択肢を選んでください。"
    choice [ "選択肢A", "A" ],
           [ "選択肢B", "Section1:B" ]	# 選択肢の表示と行き先
  end
  
  # 次の scene を相対名で指定している
  scene "A", :next => "Interval:main" do
    clear
    bg "images/bg.jpg"
    wait 30
    fg "images/fg_girl.png"
    wait 30
    text "おはようございます!"
    3.times do
      wait 30
      text ""
    end
    wait 30
    text "ウェイト中です"
    wait
    text "はい!"
    text "ウェイト終了です。"
    wait 30
  end
  
  scene "B", :next => "Interval:main" do
    clear
    wait 30
    fg "images/fg_girl.png"
    wait 30
    text "こんばんは・・・。"
    wait 30
    text "ウェイト中よ!"
    wait
  end
  
  # 入れ子にできる。絶対名だと "Section1:Interval"
  namespace "Interval" do
    
    scene "main" do
      clear
      choice [ "Aへ",        "A" ],
             [ "Bへ",        "B" ],
             [ "音を鳴らす", "sound" ],
             [ "終了する",   "quit" ]
      # Section1:Interval:A がないので
      # 遡って Section1:A を見つける
    end
    
    scene "sound", :next => "main" do
      sound "sounds/crash.wav"
    end
    
    scene "quit" do
      quit
    end
    
  end
  
end

# エントリポイントとなる scene を絶対名で指定
start "Section1:start"

さてこれをどうするか。

DSL -> DSLコンパイラ -> ASTに -> インタプリタが実行
だと、エラーとか先に見つけられるけど、

DSL -> DSLインタプリタ -> 逐次実行
だと、Rubyの変数機構とか制御構文とかにタダ乗りできる。


scene の中だけ逐次実行にすればいいのかな?
DSL処理系が実行する段まで scene のブロックの評価が遅延されてればRubyのローカル変数機構や制御構文に乗っかれるわけで。
scene 間をわたって使いたい変数は、namespace で宣言できるな。こっちは予め実行されるから。トップレベルでやるとグローバル変数っぽい…
とか思ったけど、Rubyのローカル変数ってファイルスコープだった。Ruby自体のグローバル変数を使わせるのもアレなので、何か用意しないといけないな。

サプルーチンの定義とかは、Rubyのdefをまんま使うよりは、何かAPIを用意して、Procオブジェクトと名前を自力でマップしていくほうがいいかもしれない。napespace との親和性を考えると。
というか scene が引数と返り値のないサブルーチンだなぁ。