<?xml version="1.0" encoding="UTF-8" ?><rdf:RDF 
  xmlns="http://purl.org/rss/1.0/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xml:lang="ja">
  <channel rdf:about="http://w.atwiki.jp/instead/">
    <title>INSTEAD @ wiki</title>
    <link>http://w.atwiki.jp/instead/</link>
    <atom:link href="https://w.atwiki.jp/instead/rss10.xml" rel="self" type="application/rss+xml" />
    <atom:link rel="hub" href="https://pubsubhubbub.appspot.com" />
    <description>INSTEAD @ wiki</description>

    <dc:language>ja</dc:language>
    <dc:date>2012-01-16T21:05:07+09:00</dc:date>
    <utime>1326715507</utime>

    <items>
      <rdf:Seq>
                <rdf:li rdf:resource="https://w.atwiki.jp/instead/pages/19.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/instead/pages/18.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/instead/pages/17.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/instead/pages/15.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/instead/pages/14.html" />
              </rdf:Seq>
    </items>
	
		
    
  </channel>
    <item rdf:about="https://w.atwiki.jp/instead/pages/19.html">
    <title>19. テーマ</title>
    <link>https://w.atwiki.jp/instead/pages/19.html</link>
    <description>
      <![CDATA[<!--@@@@@--><h2 id="id_da93b100">19 sdl-instead用のテーマ</h2>
<div>
sdl-insteadなどのグラフィックインタプリタはテーマの機能を持っています。テーマは“theme.ini”ファイルのあるディレクトリにあります。

</div>
<br />
<div>
insteadにはすくなくとも“default”テーマが必要です。このテーマは常に最初のロード時に読み込まれます。ほかのテーマは“default”テーマを継承して、引数を部分的にあるいはすべてをオーバーライドします。ユーザーは設定メニューからテーマを選択できますが、ゲーム自体で自前のテーマを含むこともできます。ゲーム自前のテーマを使う場合はゲームのディレクトリに“theme.ini”ファイルが必要です。

</div>
<br />
<div>
ユーザーはゲームのテーマを変更できますが、作者の意図したデザインが変更されることになるのでインタプリタは警告を表示します。

</div>
<br />
<div>
“theme.ini”は非常にシンプルな文法で構成されています。

</div>
<br />
<pre>&lt;引数&gt; = &lt;値&gt;
; コメント
</pre>
<br />
<div>
使用可能な値は文字列、色、数字です。色については#RGBの16進数表記になります。いくつかの色は名前を利用できます。たとえば“yellow”、“green”、“violet”などです。

</div>
<br />
<div>
使用可能な引数のリスト：

</div>
<br />
<ul><li>scr.w = ゲーム表示エリアの幅ピクセル数</li>
<li>scr.h = ゲーム表示エリアの高さピクセル数</li>
<li>scr.col.bg = 背景色</li>
<li>scr.gfx.bg = 背景画像のファイルパス（文字列）</li>
<li>scr.gfx.cursor.x = マウスポインタの中央位置のX座標（数字）バージョン0.8.9以降</li>
<li>scr.gfx.cursor.y = マウスポインタの中央位置のY座標（数字）バージョン0.8.9以降</li>
<li>scr.gfx.cursor.normal = マウスポインタ画像ファイルパス（文字列）バージョン0.8.9以降</li>
<li>scr.gfx.cursor.use = インベントリの“use”マウスポインタ画像のファイルパス（文字列）バージョン0.8.9以降</li>
<li>scr.gfx.use = インベントリの“use”マウスポインタ画像のファイルパス（文字列）バージョン0.8.9未満</li>
<li>scr.gfx.pad = スクロールバーとメニューの間隔（数字）</li>
<li>scr.gfx.x, scr.gfx.y, scr.gfx.w, scr.gfx.h = シーンで表示される画像エリアの幅と高さの座標。レイアウトモードに依存（数字）</li>
<li>win.gfx.h - scr.gfx.hと同じ機能（バージョン互換性のため）</li>
<li>scr.gfx.mode = レイアウトモードの指定（値は“fixed”、“embedded”、“float”）。画像を表示するための設定。“embedded”にすると画像はメインウィンドウの一部になる。“scr.gfx.x”、“scr.gfx.y”、“scr.gfx.w”の値は無効になる。“float”が指定された場合は画像は指定された座標上（“scr.gfx.x”と“scr.gfx.y”）に表示され、大きい場合は“scr.gfx.w”と“scr.gfx.h”のサイズに縮小される。“fixed”が指定された場合は“embedded”と同じくメインウィンドウの一部として表示されるが、テキストの上部に固定表示され、スクロールはしない。</li></ul>
<br />
<ul><li>win.x, win.y, win.w, win.h = メインウィンドウの幅と高さを表す座標。シーンの説明文が表示されるエリア（数字）</li>
<li>win.fnt.name = フォントファイルのファイルパス（文字列）</li>
<li>win.fnt.size = メインウィンドウのフォントサイズ（数字）</li>
<li>win.fnt.height = 小数点数で指定する1行の高さ（デフォルト値1.0）</li>
<li>win.gfx.up, win.gfx.down = メインウィンドウの縦スクロールバーの画像のファイルパス（文字列）</li>
<li>win.up.x, win.up.y, win.down.x, win.down.y = スクロールバーの座標（位置または-1）</li>
<li>win.col.fg = メインウィンドウのフォント色（16進か色名）</li>
<li>win.col.link = メインウィンドウのリンク文字列の色（16進か色名）</li>
<li>win.col.alink = メインウィンドウのアクティブなリンク文字列の色（16進か色名）</li></ul>
<br />
<ul><li>inv.x, inv.y, inv.w, inv.h = インベントリの幅と高さの座標（数字）</li>
<li>inv.mode = インベントリのモード指定（“horizontal”または“vertical”）。horizontalモードではいくつかのアイテムは同じ行に表示される。verticalモードでは1行につき1個のアイテムが表示される。</li>
<li>inv.col.fg = インベントリの文字列の色（16進か色名）</li>
<li>inv.col.link = インベントリのリンク文字列色（16進か色名）</li>
<li>inv.col.alink = インベントリのアクティブリンク文字列色（16進か色名）</li>
<li>inv.fnt.name = インベントリ用のフォントのファイルパス（文字列）</li>
<li>inv.fnt.size = インベントリのフォントサイズ（数字）</li>
<li>inv.fnt.height = 小数点数で指定するインベントリの1行の高さ（デフォルト値1.0）</li>
<li>inv.gfx.up, inv.gfx.down = インベントリのスクロールバーの画像のファイルパス（文字列）</li>
<li>inv.up.x, inv.up.y, inv.down.x, inv.down.y = インベントリのスクロールバーの座標（位置か-1）</li></ul>
<br />
<ul><li>menu.col.bg = 設定メニューの背景色（16進か色名）</li>
<li>menu.col.fg = 設定メニューの文字列色（16進か色名）</li>
<li>menu.col.link = 設定メニューのリンク文字列色（16進か色名）</li>
<li>menu.col.alink = 設定メニューのアクティブなリンク文字列色（16進か色名）</li>
<li>menu.col.alpha = 設定メニューの透過色（0から255の数字）</li>
<li>menu.col.border = 設定メニューの枠線の色（16進か色名）</li>
<li>menu.bw = 設定メニューの枠線の幅（16進か色名）</li>
<li>menu.fnt.name = 設定メニューのフォントファイルパス（文字列）</li>
<li>menu.fnt.size = 設定メニューのフォントサイズ（数字）</li>
<li>menu.fnt.height = 小数点数で指定する設定メニューの1行の高さ（デフォルト値1.0）</li>
<li>menu.gfx.button = メニューアイコンのファイルパス（文字列）</li>
<li>menu.button.x, menu.button.y = メニューアイコンボタンの座標（数字）</li></ul>
<br />
<ul><li>snd.click = マウスクリック音のサウンドファイルパス（文字列）</li></ul>
<br />
<ul><li>include = テーマ名の指定。ディレクトリパスの最後の部分（文字列）</li></ul>
<br />
<div>
テーマヘッダにはコメントタグが含まれます。現在のところ使えるタグは“$Name:”のみで、テーマ名に使える文字コードはUTF-8です。たとえば次のようになります：

</div>
<br />
<pre>; $Name:New theme$
; Bookテーマをベースにした修正版
include = book
scr.gfx.h = 500
</pre>
<br />
<div>
インタプリタは“themes”ディレクトリからテーマファイルを検索します。UNIX版では“~/.instead/themes/”ディレクトリも検索します。バージョン0.8.7以降のWindows版では“Documents and Settings/ユーザー名/Local Settings/Application Data/instead/themes”を検索します。

</div>
<br />
<hr />
<br />
<div>
露英訳： vopros＠pochta.ru
</div>]]>    </description>
    <dc:date>2012-01-16T21:05:07+09:00</dc:date>
    <utime>1326715507</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/instead/pages/18.html">
    <title>18. アドバイス</title>
    <link>https://w.atwiki.jp/instead/pages/18.html</link>
    <description>
      <![CDATA[<!--@@@@@--><h2 id="id_c91810dc">18. アドバイス</h2>
<br />
<h3 id="id_7efd05bb">ゲームファイルの分割</h3>
<div>
“dofile”関数を使って、分割されたソースコードをインクルードできます。“dofile”はグローバルな関数として使い、“main.lua”がパースされる際に分割されたソースコードをロードします。次のようなコードになります：

</div>
<br />
<pre>-- main.lua
dofile &quot;episode1.lua&quot;
dofile &quot;npc.lau&quot;
dofile &quot;start.lua&quot;
</pre>
<br />
<div>
動的にインクルードする（現在のオブジェクトとシーンの再定義を可能にする）ためのコードは“gamefile”関数を使います。以下のようになります：

</div>
<br />
<pre>...
act = code [[ gamefile (&quot;episode2.lua&quot;); ]]
...
</pre>
<br />
<div>
以前にロードされたファイルのために確保されたメモリを気にすることなく、新しいファイルをロードして新しいゲームのように実行できます。

</div>
<br />
<pre>...
act = code [[ gamefile (&quot;episode3.lua&quot;, true); ]]
...
</pre>
<br />
<h3 id="id_54141062">モジュール</h3>
<div>
バージョン1.2.0以降では“require”関数でモジュールを呼び出せます。現在のところ以下のようなモジュールが使えます：

</div>
<br />
<ul><li>dbg　デバッグ用モジュール（デバッガを有効にします）。</li>
<li>walk　goの代わりにシーンを移動するために改善されたモジュールです。</li>
<li>xact　オブジェクトへの参照を返します。</li>
<li>input　キーボード入力を補助するためのものです。</li>
<li>click　シーンの画像上でのマウスクリックを捕捉します。</li>
<li>vars　変数の定義をします。</li>
<li>prefs　参照を扱います。</li>
<li>snapshots　スナップショットを取ります。</li>
<li>format　指定した書式で文字列を表示します。</li>
<li>object　改善されたオブジェクトです。</li>
<li>theme　ゲーム自身でテーマを適用するためのモジュールです。</li></ul>
<br />
<div>
モジュールはたとえば次のように使います：

</div>
<br />
<pre>--$Name: My game!$
instead_version &quot;1.2.0&quot;
require &quot;para&quot;
require &quot;dbg&quot;
...
</pre>
<br />
<div>
バージョン1.2.0以降では“vars”、“object”、“walk”が自動的に読み込まれます。

</div>
<br />
<div>
“prefs”オブジェクト（“prefs”モジュール内のオブジェクトも含めて）はゲームへの参照を保持できます。たとえばプレイヤーの進捗状況や実行回数を数えるのに役に立ちます。

</div>
<br />
<pre>require &quot;prefs&quot;
...
    prefs.counter = 0
...
    exit = function(s)
        prefs.counter = prefs.counter + 1
        prefs:store()
    end
...
    enter = function(s)
        return &#039;あなたがこのゲームをプレイするのは、これで&#039;..prefs.counter..&#039;回目。&#039;;
    end
...
    act = function(s)
        prefs:purge()
        return &quot;設定がクリアされました。&quot;
    end
</pre>
<br />
<div>
“xact”モジュールは、ほかのオブジェクトやリアクション、また“life”関数などからオブジェクトを参照するときに使います。これらの参照の記述は“{object:string}”です。

</div>
<br />
<pre>...
    act = [[私はテーブルの下に{myknife:ナイフ}があることに気付いた。]]
...
</pre>
<br />
<div>
“object”の参照の一部にはオブジェクトの値かオブジェクトの名前が使えます。このモジュールは“xact”と“xdsc”オブジェクトでも定義されています。

</div>
<br />
<div>
“xact”は簡単なリアクションのためのオブジェクトです。たとえば次のようなコードになります：

</div>
<br />
<pre>main = room {
    forcedsc = true;
    dsc = [[作者のコメント：私はこのゲームを{note1:かかって}作った。]];
    obj = {
        xact(&#039;note1&#039;, [[十年以上]]);
    }
}
</pre>
<br />
<div>
リアクションは以下のようなコードを含むことができます：

</div>
<br />
<pre>       xact(&#039;note1&#039;, code [[p &quot;十年以上&quot;]]);
</pre>
<br />
<div>
“xdsc”を使うとオブジェクトリストに複数の説明文を挿入できます。

</div>
<br />
<pre>main = room {
    forcedsc = true;
    dsc = [[私は今部屋の中にいる。]];
    xdsc = [[{anapple:リンゴ}と{aknife:ナイフ}がある。]];
    other = [[それから{achain:チェーン}と{atool:ノコギリ}もある。]];
    obj = {
        xdsc(), -- &#039;xdsc関数のデフォルト&#039;
        xdsc(&#039;other&#039;),
        &#039;apple&#039;, &#039;knife&#039;, &#039;chain&#039;, &#039;tool&#039;,
    }
}
</pre>
<br />
<div>
“xroom”オブジェクトも使えます：

</div>
<br />
<pre>main = xroom {
    forcedsc = true;
    dsc = [[私は今部屋の中にいる。]];
    xdsc = [[{anapple:リンゴ}と{aknife:ナイフ}がある。]];
    obj = {
        &#039;apple&#039;, &#039;knife&#039;, &#039;chain&#039;, &#039;tool&#039;,
    }
}
</pre>
<br />
<div>
“input”モジュールは簡単な文字入力の枠を実装するのに使います。“click”モジュールはシーンに表示されている画像をユーザーがマウスクリックした場合をフォローするのに使います。

</div>
<br />
<div>
“para”モジュールは文章にインデントを追加して段落を作ります。

</div>
<br />
<div>
“format”モジュールは文字列の出力を整形します。デフォルトではすべて無効になっています：

</div>
<br />
<ul><li>format.para = false　段落にインデントを追加します。</li>
<li>format.dash = false　引用符のダッシュを2つに変更します。</li>
<li>format.quotes = false　&lt;&lt; &gt;&gt;で囲まれた引用を変更します。</li>
<li>format.filter = nil ユーザーが指定するテキストの整形です。</li></ul>
<br />
<div>
それぞれの機能を使うには“para/dash/quotes”モジュールを有効にする必要があります。

</div>
<br />
<h3 id="id_d31ac841">テキストの整形</h3>
<div>
関数で簡単なテキストのフォーマットを指定できます：

</div>
<br />
<ul><li>txtc()　中央寄せ</li>
<li>txtr()　右詰め</li>
<li>txtl()　左詰め</li>
<li>txttop()　上詰め</li>
<li>txtbottom()　下詰め</li>
<li>txtmiddle()　行の中心（デフォルト）</li></ul>
<br />
<div>
たとえば以下のようになります：

</div>
<br />
<pre>main = room {
  nam = &#039;Intro&#039;,
  dsc = txtc(&#039;ようこそ！&#039;),
}
</pre>
<br />
<div>
以下のようなテキスト表示のスタイルを指定できます：

</div>
<br />
<ul><li>txtb()　ボールド</li>
<li>txtem()　エンボス</li>
<li>txtu()　下線付き</li>
<li>txtst()　取り消し線付き</li></ul>
<br />
<div>
たとえば次のようになります：

</div>
<br />
<pre>main = room {
  nam = &#039;イントロ&#039;,
  dsc = &#039;あなたは今&#039;..txtb(&#039;メイン&#039;)..&#039;ルームの中にいる。&#039;,
}
</pre>
<br />
<div>
バージョン1.1.0以降では“txtnb()”関数を使い、ラップされていない文字列を表示できます。

</div>
<br />
<div>
たとえば：

</div>
<br />
<pre>main = room {
  nam = &#039;イントロ&#039;,
  dsc = &#039;あなたは今&#039;..txtnb(&#039;メイン&#039;)..&#039;ルームの中にいる。&#039;,
}
</pre>
<br />
<h3 id="id_b7a6c500">メニュー</h3>
<div>
メニューコンストラクタと使ってインベントリのエリアにメニューを表示できます。menuハンドラはマウスが1回クリックされた後に呼ばれます。ハンドラに文字列が返されない場合はなにも変化しません。ポケットの中身を表現すると、たとえば次のようなコードになります：

</div>
<br />
<pre>pocket = menu {
  State = false,
  nam = function(s)
    if s.State then
      return txtu(&#039;ポケット&#039;);
    end
    return &#039;ポケット&#039;;
  end,
  gen = function(s)
    if s.State then
      s:enable_all();
    else
      s:disable_all();
    end 
  end,
  menu = function(s)
    if s.State then
      s.State = false;
    else
      s.State = true;
    end 
    s:gen();
  end,
};

knife = obj {
  nam = &#039;ナイフ&#039;,
  inv = &#039;これはナイフ。&#039;,
};

function init()
    inv():add(pocket);
    put(knife, pocket);
    pocket:gen();
end

main = room {
  nam = &#039;テスト&#039;,
};
</pre>
<br />
<h3 id="id_1a6ef205">プレイヤーステータス</h3>
<div>
以下はインベントリのようにプレイヤーステータスの表示を実装したものです。この文字列はアイテムのようには使えません。

</div>
<br />
<pre>global {
    life = 10;
    power = 10;
}

status = stat {
  nam = function(s)
    p (&#039;ライフゲージ: &#039;, life, &#039;パワー: &#039;, power)
  end
};
function init()
    inv():add(&#039;ステータス&#039;);
end
</pre>
<br />
<h3 id="id_c03c6d59">“exit”と“enter”ハンドラから“walk”する</h3>
<div>
“exit”と“enter”ハンドラから“walk”ができます。

</div>
<br />
<h3 id="id_288c653f">参照を動的に作る</h3>
<div>
参照を動的に作るにはいくつかの方法があります。以下の例では“vway”オブジェクトを使って参照を追加しています：

</div>
<br />
<pre>objs(home):add(vway(&#039;道&#039;, &#039;私は森に続く{道}が伸びていることに気付いた。&#039;, &#039;forest&#039;));
</pre>
<br />
<div>
参照を削除するには“del”関数を使います。

</div>
<br />
<pre>objs(home):del(&#039;道&#039;);
</pre>
<br />
<div>
シーン内で参照が存在するかどうか“srch”関数でチェックできます。

</div>
<br />
<pre>if not objs(home):srch(&#039;道&#039;) then
  objs(home):add(vway(&#039;道&#039;,
            &#039;私は森に続く{道}が伸びていることに気付いた。&#039;, &#039;forest&#039;));
end
</pre>
<br />
<div>
動的な参照を“enter”ハンドラ内で作るかまたはゲームソースの任意の場所で作るかですが、それが要求されている場所で作れるので非常に便利です。現在のシーン内に作る場合のサンプルコードは以下のようになります：

</div>
<br />
<pre>if not seen(&#039;道&#039;) then
  objs():add(vway(&#039;道&#039;,
         &#039;私は森に続く{道}が伸びていることに気付いた。&#039;, &#039;forest&#039;));
end
</pre>
<br />
<div>
また“enable()”と“disable()”で参照の有効化と無効化をする場合は以下のようになります：

</div>
<br />
<pre>  seen(&#039;道&#039;, home):disable();
        exist(&#039;道&#039;, home):enable();
</pre>
<br />
<div>
“vobj”と“vway”を無効化するには：

</div>
<br />
<pre> obj = {vway(&#039;道&#039;,
          &#039;私は森に続く{道}が伸びていることに気付いた。&#039;, &#039;forest&#039;):disable()},
</pre>
<br />
<div>
それから“obj”配列のインデックスを使って参照を有効化するか、または“srch”か“seen/exist”を使って探し出し有効化します。次のようになります：

</div>
<br />
<pre>objs()[1]:enable();
</pre>
<br />
<h3 id="id_d926e850">ゲームソースをエンコードする（バージョン0.9.3以降）</h3>
<div>
ゲームのソースコードを見せたくない場合はコマンドラインからエンコードできます。

</div>
<br />
<pre>sdl-instead -encode &lt;入力ファイル名&gt; [出力ファイル名]
</pre>
<br />
<div>
エンコードされたファイルをロードするには“doencfile”を使います。つまり最初にロードされる“main.lua”だけはエンコードしないプレーンテキストである必要があります。エンコードされたソースのロードは次のようになります（ゲームのファイル名はgame.luaです）：

</div>
<br />
<pre>main.lua

-- $Name: 秘密のソースコード！$
doencfile(&quot;game&quot;);
</pre>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>luac（Luaコンパイラ）はプラットフォームのコードに依存しているので使わないでください。しかしゲームのコンパイル時のメッセージはゲームコード中のバグを発見するのには役に立ちます。

</div>
<br />
<h3 id="id_c4c6605b">ゲームのリソースをidfファイルにパッケージ化する（バージョン1.4.0以降）</h3>
<div>
画像や音、テーマなど、ゲームのすべてのリソースを1個の拡張子idfのファイルにパッケージ化できます。リソースのファイルをすべて“data”ディレクトリに配置し、以下のコマンドを実行します。

</div>
<br />
<pre>instead -idf &lt;dataディレクトリのパス&gt;
</pre>
<br />
<div>
カレントディレクトリに data.idf ファイルが生成されます。このファイルをゲームのディレクトリに置き、ほかのリソースファイルを削除します。

</div>
<br />
<div>
以下のコマンドでゲーム全体をidfパッケージにできます：

</div>
<br />
<pre>instead -idf &lt;ゲームのパス&gt;
</pre>
<br />
<div>
idfフォーマットのゲームファイルは、パッケージされていないゲームと同じようにコマンドラインから直接実行できます：

</div>
<br />
<pre>instead game.idf
</pre>
<br />
<h3 id="id_4466208f">プレイヤーを切り替える</h3>
<div>
ゲーム内にいくつかのキャラクタを用意して互いに切り替えることができます（“change_pl”を参照のこと）。同じ方法でキャラクタごとにインベントリを使い分けることもできます。

</div>
<br />
<h3 id="id_cc0c0a2e">ハンドラの1つ目の引数を使う</h3>
<div>
たとえば以下のようなコードがあります：

</div>
<br />
<pre>stone = obj {
  nam = &#039;石&#039;,
  dsc = &#039;崖っぷちに{石}があります。&#039;,
  act = function()
    objs():del(&#039;stone&#039;);
    return &#039;私が石を押すと下に転がり落ちていった。&#039;;
  end
</pre>
<br />
<div>
“act”ハンドラの使い方は簡単です。たとえば以下のようになります：

</div>
<br />
<pre>  act = function(s)
    objs():del(s);
    return &#039;私が石を押すと下に転がり落ちていった。&#039;;
  end
</pre>
<br />
<h3 id="id_cd2aa930">“set_music”関数を使う</h3>
<div>
サウンドを再生するために“set_music”の2つ目の引数を使うことができます。この引数はサウンドファイルの連続再生を何回繰り返すかを指定します。

</div>
<br />
<div>
liveオブジェクトから自前のサウンドプレイヤーを記述することができます。たとえば次のようになります：

</div>
<br />
<div>
コード

</div>
<pre>-- 2回目からランダムな順番で音楽のトラックを再生する
tracks = {&quot;mus/astro2.mod&quot;,
          &quot;mus/aws_chas.xm&quot;,
          &quot;mus/dmageofd.xm&quot;,
          &quot;mus/doomsday.s3m&quot;}
mplayer = obj {
  nam = &#039;メディアプレイヤー&#039;,
  life = function(s)
    local n = get_music();
    local v = get_music_loop();
    if not n or not v then
      set_music(tracks[2], 1);
    elseif v == -1 then
      local n = get_music();
      while get_music() == n do
        n = tracks[rnd(4)]
      end
      set_music(n, 1);
    end
  end,
};
lifeon(&#039;mplayer&#039;);
</pre>
<br />
<div>
“get_music_loop”と“get_music”関数を使って最後に再生されたサウンドを取得でき、また再度再生できます。たとえば次のようなコードです：

</div>
<br />
<pre>function save_music(s)
  s._oldMusic = get_music();
  s._oldMusicLoop = get_music_loop();
end

function restore_music(s)
  set_music(s._oldMusic, s._oldMusicLoop);
end

-- ....
enter = function(s)
  save_music(s);
end,
exit = function(s)
  restore_music(s);
end,
-- ....
</pre>
<br />
<div>
バージョン0.8.5以降では“save_music”と“restore_music”を使うことができます。

</div>
<br />
<h3 id="id_690f5f3d">liveオブジェクト</h3>
<div>
たとえば主人公に友達を作りたいとします。方法のひとつはキャラクタに“life”関数を使い、プレイヤーのいる場所に常にその友達オブジェクトを置くことです。

</div>
<br />
<pre>horse = obj {
  nam = &#039;馬&#039;,
  dsc = &#039;おれの隣に{馬}が立っている。&#039;,
  life = function(s)
    if not seen(&#039;horse&#039;) then
      move(&#039;horse&#039;, here(), s.__where);
      s.__where = pl.where;
    end
  end,
};
function init()
    lifeon(&#039;horse&#039;);
end
</pre>
<br />
<h3 id="id_2ee9abd8">タイマー</h3>
<div>
INSTEADのバージョン1.1以降ではタイマーオブジェクトが用意されています（SDLバージョンのみ）。タイマーはタイマーオブジェクトを管理します。

</div>
<br />
<ul><li>timer:set(ms)　ミリ秒単位でタイマーの発動する間隔を指定します</li>
<li>timer:stop()　タイマーを止めます</li>
<li>timer.callback(s)　コールバックです。タイマーの間隔に達したら呼ばれます</li></ul>
<br />
<div>
タイマー関数はsteadインターフェイスのコマンドを返します。コールバックの実行後に呼ばれる必要があります。たとえば次のようなコードになります:

</div>
<br />
<pre>timer.callback = function(s)
  main._time = main._time + 1;  
  return &quot;look&quot;;
end
timer:set(100);
main = room {
  _time = 1,
  forcedsc = true,
  nam = &#039;タイマー&#039;,
  dsc = function(s)
  return &#039;Example: &#039;..tostring(s._time);
  end
};
</pre>
<br />
<h3 id="id_7bd5bfbd">キーボード操作</h3>
<div>
INSTEADバージョン1.1.0以降ではキーボード入力をサポートしています（SDLバージョンのみ）。これで入力オブジェクトを使うことができます。

</div>
<br />
<ul><li>input.key(s, pressed, key)　キーボードハンドラ。第2引数は“pressed”または“release”のイベント。“key”はキーの名前</li></ul>
<br />
<div>
ハンドラはsteadインターフェイスのコマンドを返します。この例ではインタプリタはキーを扱いません。たとえば次のようなコードです：

</div>
<br />
<pre>input.key = function(s, pr, key)
  if not pr or key == &quot;escape&quot; then 
    return
  elseif key == &#039;space&#039; then 
    key = &#039; &#039;
  elseif key == &#039;return&#039; then
    key = &#039;^&#039;;
  end
  if key:len() &gt; 1 then return end 
  main._txt = main._txt:gsub(&#039;_$&#039;,&#039;&#039;);
  main._txt = main._txt..key..&#039;_&#039;;
  return &quot;look&quot;;
end

main = room {
  _txt = &#039;_&#039;,
  forcedsc = true,
  nam = &#039;キーボード&#039;,
  dsc = function(s)
    return &#039;例： &#039;..tostring(s._txt);
  end 
};
</pre>
<br />
<h3 id="id_8d62410b">マウス操作</h3>
<div>
INSTEADバージョン1.1.5以降ではマウスクリックの検知をサポートします（SDLバージョンのみ）。これで入力オブジェクトを使うことができます。

</div>
<br />
<div>
input.click(s, pressed, mb, x, y, px, py)　マウスクリックハンドラ。イベントは“press”か“release”。“mb”はマウスボタンのインデックス（1が左）を表す。“x”と“y”はカーソルの位置をウィンドウの左上からの座標で表す。“px”と“py”は画像がクリックされた場合の座標。マウスカーソルの位置を画像の左上からの座標で表す。

</div>
<br />
<div>
ハンドラはsteadインターフェイスのコマンドを返します。この例ではインタプリタはキーを扱いません。次のようなコードです：

</div>
<br />
<pre>input.click = function(s, press, mb, x, y, px, py)
  if press and px then
    click.x = px;
    click.y = py;
    click:enable();
    return &quot;look&quot;
  end
end

click = obj {
  nam = &#039;クリック&#039;,
  x = 0,
  y = 0,
  dsc = function(s)
    return &quot;あなたは画像をクリックしました。座標： &quot;..s.x..&#039;,&#039;..s.y..&#039;.&#039;;
  end
}:disable();

main = room {
  nam = &#039;テスト&#039;,
  pic =&#039;picture.png&#039;,
  dsc = &#039;サンプルコード。&#039;,
  obj = { &#039;click&#039; },
};
</pre>
<br />
<div>
以下は、現在のシーンに表示された1つの画像がクリックされたときの、階層化されたクリック関数の呼び出しを実装したコードです：

</div>
<br />
<pre>input.click = function(s, press, mb, x, y, px, py)
  if press and px then
    return &quot;click &quot;..px..&#039;,&#039;..py;
  end
end

game.action = function(s, cmd, x, y)
  if cmd == &#039;click&#039; then
    return call(here(), &#039;click&#039;, x, y);
  end
end
----------------------------------------------------------------------
main = room {
  nam = &#039;テスト&#039;,
  pic =&#039;picture.png&#039;,
  dsc = &#039;サンプルコード。&#039;,
  click = function(s, x, y)
    return &quot;あなたは画像をクリックしました。座標： &quot;..x..&#039;,&#039;..y..&#039;.&#039;;
  end
};
</pre>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>バージョン1.2.0以降ではclickモジュールが必要です。

</div>
<br />
<h3 id="id_1be6816e">ダイナミックオブジェクトを作る</h3>
<div>
“new”と“delete”関数でダイナミックオブジェクトを作り、また削除することができます。たとえば以下のようなコードです：

</div>
<br />
<pre>new (&quot;obj { nam = &#039;テスト&#039;, act = &#039;test&#039; }&quot;)
put(new [[obj {nam = &#039;テスト&#039; } ]]);
put(new(&#039;myconstructor()&#039;);
n = new(&#039;myconstructor()&#039;);
delete(n)
</pre>
<br />
<div>
“new”関数はオブジェクトのコンストラクタのように文字列の引数を扱います。コンストラクタはオブジェクトを1つ返します。文字列の引数はコンストラクタの関数呼び出しを含んでいます。次のようなコードになります：

</div>
<br />
<pre>function myconstructor()
  local v = {}
  v.nam = &#039;テストオブジェクト&#039;,
  v.act = &#039;test feedback&#039;,
  return obj(v);
end
</pre>
<br />
<div>
このオブジェクトはゲームがセーブされるたびにセーブされます。new()関数はオブジェクトの実体を返します。オブジェクト名を得るためには“deref”関数が使えます。

</div>
<br />
<pre>o_name = deref(new(&#039;myconstructor()&#039;));
delete(o_name);
</pre>
<br />
<h3 id="id_a3998755">イベントハンドラからの複雑な出力</h3>
<div>
プログラマはときどき、いくつかの条件に依存するいくつかの部品からの、イベントハンドラの出力を整形する必要が生じることがあります。このような例では“p()”関数と“pn()”関数を使うことができます。これらの関数は文字列をハンドラが持つ内部的なバッファに追加します。このバッファの中身はハンドラから返されます。

</div>
<br />
<pre>dsc = function(s)
  p &quot;床の上に{樽}が置いてある。&quot;
  if s._opened then
    p &quot;樽のフタがそばに落ちている。&quot;
  end
end
</pre>
<br />
<div>
“pn()”関数はテキストに改行を追加しバッファに出力します。p()関数はそれと同じ機能を持ちますが改行の代わりに空白を1個追加します。

</div>
<br />
<div>
バージョン1.1.6以降では“pr()”関数が使えますが、これは出力される文字列の最後に何も追加しません。

</div>
<br />
<div>
バッファをクリアするためには“pclr()”関数が使えます。ユーザーアクションのステータスを文字列で返すためには“pget()”関数を使うか、または単に“return”で戻り値を返します。

</div>
<br />
<pre>use = function(s, w)
  if w == apple then
    p &#039;私はリンゴの皮を剥いた。&#039;;
    apple._peeled = true
    return
  end
  p &#039;それは使えない！&#039;
  return false; -- またはpget(), falseを返す
end
</pre>
<br />
<h3 id="id_94f2b0ed">デバッグ</h3>
<div>
エラーが出た場合のLuaのスタックを見るには、sdl-insteadに“-debug”パラメタをつけて起動します。Windows版ではデバッグコンソールが表示されます。INSTEADを使わずにゲームをデバッグするには、次のようなコード“game.lua”を記述します：

</div>
<br />
<pre>dofile(&quot;/usr/share/games/stead/stead.lua&quot;); -- stead.luaの絶対パス
dofile(&quot;main.lua&quot;); -- ゲームのメインソース
game:ini();
iface:shell();
</pre>
<br />
<div>
次にコマンドライン“lua game.lua”でゲームを起動します。この起動方法ではゲームは簡易シェルの環境で実行されます。使えるコマンドは、“ls”、“go”、“act”、“use”などがあります。

</div>
<br />
<div>
ゲーム内でデバッガを使うには次のコードを挿入してください：

</div>
<br />
<pre>require &quot;dbg&quot;
</pre>
<br />
<div>
これは“main.lua”内のバージョン指定行の直後に記述します。F7キーでデバッガを呼び出せます。

</div>
<br />
<hr />
<div>
19. <a href="http://w.atwiki.jp/instead/pages/19.html"  title="19. テーマ (5263d)">テーマ</a>へ
</div>]]>    </description>
    <dc:date>2012-01-16T21:14:09+09:00</dc:date>
    <utime>1326716049</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/instead/pages/17.html">
    <title>トラブルシュート</title>
    <link>https://w.atwiki.jp/instead/pages/17.html</link>
    <description>
      <![CDATA[<!--@@@@@--><div>
このページでは再現性のあるトラブルを解決するヒントを紹介します。

</div>
<br />
<h4 id="id_b0b8e55e">メニューが文字化けて読めない</h4>
<div>
日本語テーマファイルを読み込む前に言語設定が日本語になると、この症状が起こります。テーマとフォントの両方が日本語になっていないのが原因です。INSETADのデフォルトフォントが英文字のLiberation Sansになっているためです。（この問題は1.6.0で解決されました）

</div>
<br />

<picture><source media="(max-width: 320px)" srcset="https://img.atwiki.jp/instead/attach/17/21/t/trouble001.jpg"><source media="(max-width: 480px)" srcset="https://img.atwiki.jp/instead/attach/17/21/m/trouble001.jpg"><img class="atwiki_plugin_ref" loading="lazy" width="400" height="311" style="aspect-ratio: 400/311;" src="https://img.atwiki.jp/instead/attach/17/21/trouble001.jpg"></picture>

<div>
メニューの上から3番目が“テーマを選択”になっています。3番目をクリックします。
<br />
<br />

</div>
<br />

<picture><source media="(max-width: 320px)" srcset="https://img.atwiki.jp/instead/attach/17/22/t/trouble002.jpg"><source media="(max-width: 480px)" srcset="https://img.atwiki.jp/instead/attach/17/22/m/trouble002.jpg"><img class="atwiki_plugin_ref" loading="lazy" width="400" height="311" style="aspect-ratio: 400/311;" src="https://img.atwiki.jp/instead/attach/17/22/trouble002.jpg"></picture>

<div>
テーマからJapaneseを選択します。
<br />
<br />

</div>
<br />
<h4 id="id_61dba49c">音が割れる</h4>
<div>
環境によってはノイズが入ることがあるようです。設定メニューのサウンドからサンプリングを44100Hz以上にしてみてください。

</div>
<br />
<h4 id="id_9c80d601">説明文に余分な空白が入る</h4>
<div>
この空白は元々、英語環境で行をカーニングするために入れられているものだということです。日本語や中国語、また韓国語では必要ないので、以下のコードをゲームのソース main.lua の最後に追加してください。

</div>
<br />
<pre>stead.space_delim = &#039;&#039;;
</pre>
<br />
<div>
stead.space_delimはINSTEAD\stead\stead.luaで宣言されています。

</div>
<br />
<h4 id="id_caace2d5">古いゲームのプレイ中にリンクで不具合が出る</h4>
<div>
バージョン1.5.3ではLua5.2のリリースに合わせて、以下のコードが変更されました：

</div>
<br />
<ul><li>goto → walk</li>
<li>goin → walkin</li>
<li>goout → walkout</li>
<li>goback → walkback</li></ul>
<br />
<div>
アイテムをクリックしても拾えない、次に進めないなどの場合はこれが原因になっている場合があります。適宜修正してください。

</div>
<br />
<hr />]]>    </description>
    <dc:date>2011-12-22T16:26:04+09:00</dc:date>
    <utime>1324538764</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/instead/pages/15.html">
    <title>ドキュメント</title>
    <link>https://w.atwiki.jp/instead/pages/15.html</link>
    <description>
      <![CDATA[<!--@@@@@--><div>
このテキストは公式のデベロップメントドキュメントを翻訳したものです。原文は以下にあります：
<br />
<a href="http://instead.syscall.ru/wiki/en/gamedev/documentation" rel="nofollow">http://instead.syscall.ru/wiki/en/gamedev/documentation</a>

</div>
<br />
<h2 id="id_751f5a25">0. <a id="generalinfo" name="generalinfo"></a>一般情報</h2>
<div>
STEAD用のゲームコードはLua(5.1)で書かれておりLua言語の仕様を知っておくと便利ですが、かならずしも必要ではありません。Luaエンジンのコードはおよそ3000行もの長さがあります。それこそが最良のドキュメントだと言えます。（訳注：INSTEAD 1.5.3ではLua 5.2になりました）

</div>
<br />
<div>
メインのゲームウィンドウには、シーンの静的または動的なパーツ、アクティブなイベント、シーンを切り替えられる画像（INSTEADのようなグラフィックインタプリタの場合）などが含まれます。

</div>
<br />
<div>
静的なパーツはプレイヤーがシーンに入ったときに一度だけ表示されます。同じくlookコマンド（グラフィックインタプリタではシーン名をクリックしたとき）で繰り返し表示されます。

</div>
<br />
<div>
シーンの動的なパーツはシーンのオブジェクトを説明する文章から構成されます。これは常時表示されます。

</div>
<br />
<div>
インベントリにはプレイヤーがシーン内でアクセスできるオブジェクトが含まれます。プレイヤーはインベントリオブジェクトを操作したり、持っているオブジェクトをシーンやインベントリにあるほかのオブジェクトに使ったりできます。

</div>
<br />
<table>
<tr class="atwiki_tr_odd atwiki_tr_1" >		<!--0-0--><td style=""><picture><source media="(max-width: 320px)" srcset="https://img.atwiki.jp/instead/attach/15/20/t/info.png"><source media="(max-width: 480px)" srcset="https://img.atwiki.jp/instead/attach/15/20/m/info.png"><img class="atwiki_plugin_ref" loading="lazy" width="24" height="24" style="aspect-ratio: 24/24;" src="https://img.atwiki.jp/instead/attach/15/20/info.png"></picture></td>
		<!--0-1--><td style="">“inventory”はどちらかといえば曖昧な定義です。オブジェクトに対して適応できるコマンドは、たとえば“open”、“examine(調べる)”、“use”のようなものがあります。</td></tr>
</table>
<br />
<div>
プレイヤーが操作可能なアクションは以下のようなものです：

</div>
<ul><li>シーンを見る</li>
<li>シーンのオブジェクトを使う</li>
<li>インベントリのオブジェクトを使う</li>
<li>インベントリのオブジェクトをシーンのオブジェクトに対して使う</li>
<li>インベントリのオブジェクトをインベントリのオブジェクトに対して使う</li>
<li>シーンのオブジェクトをシーンのオブジェクトに対して使う（scene_useモード）</li>
<li>シーンのオブジェクトをインベントリのオブジェクトに対して使う（scene_useモード）</li>
<li>ほかのシーンへ移動する</li></ul>
<br />
<div>
どのゲームも main.lua スクリプトがディレクトリに存在します。ほかのゲームリソース（Luaスクリプト、画像、音楽）はこのディレクトリ以下に存在しなければなりません。すべてのリソースを参照するときはこのゲームディレクトリからの相対位置になります。

</div>
<br />
<div>
main.lua を実行するにはヘッダを記述する必要があります。いくつかのタグが含まれます。どのヘッダタグもLuaプログラミングでののコメントを表すハイフン“-”の記号ではじまります。現在のところヘッダの種類は“$Name:”のみ使用できます。これはゲームのタイトルになり、UTF-8の文字コードで書きます。たとえば以下のようなコードになります：

</div>
<br />
<pre>-- $Name: すごく面白いゲーム！$
</pre>
<br />
<div>
バージョン1.2.0以降のヘッダーではSTEAD APIバージョンを定義するようになっています。現在は“1.6.0”です。

</div>
<br />
<pre>instead_version &quot;1.6.0&quot;
</pre>
<br />
<table>
<tr class="atwiki_tr_odd atwiki_tr_1" >		<!--0-0--><td style=""><picture><source media="(max-width: 320px)" srcset="https://img.atwiki.jp/instead/attach/15/19/t/important.png"><source media="(max-width: 480px)" srcset="https://img.atwiki.jp/instead/attach/15/19/m/important.png"><img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/15/19/important.png"></picture></td>
		<!--0-1--><td style="">この行がない場合、STEAD APIは互換モード（レガシーモード）になります。</td></tr>
</table>
<br />
<div>
ゲームの初期化ではinit関数のように定義します。たとえば次のようになります：

</div>
<br />
<pre>function init()
    me()._know_truth = false
    take(knife);
    take(paper);
end
</pre>
<br />
<div>
グラフィックインタプリタは有効なゲームをゲームディレクトリから検索します。UNIX版では“~/.instead/games”になります。0.8.7以降のWindows版では“C:\Documents and Settings/[ユーザー名]/Local Settings/Application Data/instead/games”になります。

</div>
<br />
<div>
Windows版とUNIX版の1.2.0以降では“./appdata/games”が存在するとそのディレクトリを検索します。

</div>
<br />
<h2 id="id_d5595a09">1. <a id="scene" name="scene"></a>シーン</h2>
<div>
シーンはゲーム内の単位です。その中では、プレイヤーがシーンのすべてのオブジェクトとアクションを調べることができます。ゲームはすくなくとも1個の“main”シーンを含みます。

</div>
<br />
<pre>main = room {
	nam = &#039;メインルーム&#039;,
	dsc = &#039;あなたは広い部屋にいます。&#039;,
};
</pre>
<br />
<div>
各フィールドはroom型のmainオブジェクトの構成要素です。すべてのオブジェクトは属性とハンドラを持ちます。たとえばnam属性（name）はどのオブジェクトにも必須の属性です。

</div>
<br />
<div>
シーンで使うnam属性はプレイ時に表示されるシーン名になります。シーン名はシーンを移動する際にもそれを識別するために使用されます。

</div>
<br />
<div>
dsc属性はシーンの静的なパーツとして表示される説明文です。プレイヤーがシーンに入ったとき、または明示的にlookコマンド（訳注：シーンのタイトルをクリックしたとき）を使用したときに表示されます。

</div>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>シーン内の記述では要素の区切りに“;”を使ってください。次のようなコードになります：

</div>
<br />
<pre>main = room {
	nam = &#039;メインルーム&#039;;
	dsc = &#039;あなたは大きな部屋にいます。&#039;;
};
</pre>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>ゲームコードで説明文を常に表示したい場合は“forcedsc”の引数をコードの先頭に使ってください。

</div>
<br />
<pre>game.forcedsc = true;
</pre>
<br />
<div>
または“forcedsc”の引数を必要なシーンに記述してください。

</div>
<br />
<div>
長い説明文を書くときは以下のようなフォーマットを使うのが便利です：

</div>
<br />
<pre>dsc = [[ と　て　も　長　い　説　明　文... ]],
</pre>
<br />
<div>
このフォーマットでは改行が無視されます。段落を分けたい場合は文末に記号“^”を記述します。2つ重ねると1行空きで表示されます。

</div>
<br />
<pre>dsc = [[ 最初の段落。 ^^
次の段落。^^
　
3つ目の段落。^
新しい行。]],
</pre>
<br />
<h2 id="id_3987501c">2. <a id="object" name="object"></a>オブジェクト</h2>
<div>
オブジェクトはシーン内の単位であり、プレイヤーが操作するものです。

</div>
<br />
<pre>tabl = obj {
	nam = &#039;テーブル&#039;,
	dsc = &#039;部屋の中に{テーブル}があります。&#039;,
	act = &#039;うーん……ただのテーブルのようです。&#039;,
};
</pre>
<br />
<div>
オブジェクト名“nam”はオブジェクトがインベントリに入ったとき、またテキストインタープリタではオブジェクトを処理するときに使用されます。

</div>
<br />
<div>
“dsc”は説明文のオブジェクトです。シーンの動的パーツとして表示されます。パーレン記号“{ }”で囲まれた文字はグラフィックインタプリタのリンクを表しています。

</div>
<br />
<div>
“act”はハンドラであり、プレイヤーがシーンのオブジェクトを使うときに呼ばれます。これは文字列を返す必要があり、シーン内のイベントパーツかブール値になります（5.属性と関数ハンドラを参照）。

</div>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>Lua名前空間でいくつかの文字列は（オブジェクトテーブルで）予約されているものがあります。たとえば“table”、“io”、“string”などのオブジェクトを作る場合は注意が必要です。例として“tabl”はすでに使われています（INSTEADの最近のバージョンではこの問題は解決されています）。

</div>
<br />
<h2 id="id_b338a90b">3. <a id="addingobject" name="addingobject"></a>シーンへのオブジェクトの追加</h2>
<div>
オブジェクトを参照するにはそれが作られたときの名前の文字列を使います。たとえば“tabl”は“tabl”オブジェクトを参照します。

</div>
<br />
<div>
シーンにオブジェクトを配置するためにオブジェクトへの参照の配列“obj”を定義します：

</div>
<br />
<pre>main = room {
	nam = &#039;メインルーム&#039;,
	dsc = &#039;あなたは大きな部屋にいます。&#039;,
	obj = { &#039;tabl&#039; },
};
</pre>
<br />
<div>
こうするとシーンが表示されたときプレイヤーは動的パーツのテーブルオブジェクトを見ることになります。

</div>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>オブジェクトがそれを使いたい場所より前に定義されている場合は、引用符なしでオブジェクトへの参照を記述することもできます。しかし構文としては引用符で囲むほうが安全です。

</div>
<br />
<h2 id="id_5a728982">4. <a id="objectreference" name="objectreference"></a>オブジェクト間の参照</h2>
<div>
オブジェクトには“obj”属性を入れ子にすることができます。これでリストを連続的に展開できます。たとえばテーブルの上にリンゴを置いてみます。

</div>
<br />
<pre>aple = obj {
	nam = &#039;リンゴ&#039;,
	dsc = &#039;テーブルの上に{リンゴ}があります。&#039;,
	act = &#039;取るべきでしょうかね？&#039;,
};
</pre>
<br />
<pre>tabl = obj {
	nam = &#039;テーブル&#039;,
	dsc = &#039;部屋の中に{テーブル}があります。&#039;,
	act = &#039;うーん……ただのテーブルのようです。&#039;,
	obj = { &#039;aple&#039; },
};
</pre>
<br />
<div>
このシーンでの説明文は、“aple”オブジェクトはtablによって参照されているので“テーブル”と“リンゴ”の説明文になります。
<br />
/* 翻訳者ノート：英語版のドキュメントではaple.namの値“apple”を“aple”と区別しています。 */

</div>
<br />
<h2 id="id_2f776e4b">5. <a id="attribute_function_handler" name="attribute_function_handler"></a>属性と関数ハンドラ</h2>
<div>
ほとんどの属性とハンドラは関数のように機能します。たとえば：

</div>
<br />
<pre>nam = function()
	return &#039;リンゴ&#039;;
end,
</pre>
<br />
<div>
これは以下のコードと同じです。

</div>
<br />
<pre>nam = &#039;リンゴ&#039;;
</pre>
<br />
<div>
ハンドラは必ず文字列を返します。以下のようなもっと便利な関数もあります：

</div>
<br />
<ul><li>p (&quot;text&quot;)　空白つきで出力します。</li>
<li>pn (&quot;text&quot;)　新しい行として表示します。</li>
<li>pr (&quot;text&quot;)　そのまま表示します。</li></ul>
<br />
<div>
これらの関数で引数が1個の文字列だけの場合はパーレン記号“{ }”を省略できます。パーレンを使うか、あるいは文字列の連結を使うことができます。たとば：

</div>
<br />
<pre>pn &quot;パーレンなし&quot;;
pn (&quot;これは文字列1で&quot;..&quot; これは文字列2です&quot;);
pn (&quot;これは文字列位置で&quot;, &quot;これは文字列2です&quot;);
</pre>
<br />
<div>
関数はSTEADの能力を強力にします。たとえば：

</div>
<br />
<pre>aple = obj {
	nam = &#039;リンゴ&#039;,
	dsc = function(s)
		if not s._seen then
			p &#039;テーブルの上に{なにか}があります。&#039;;
		else
			p &#039;テーブルの上に{リンゴ}があります。&#039;;
		end
	end,
	act = function(s)
		if s._seen then
			p &#039;リンゴでした！&#039;;
		else
			s._seen = true;
			p &#039;うーん、でもそれはリンゴでした！&#039;;
		end
	end,
};
</pre>
<br />
<div>
属性またはハンドラが関数のように並んでいる場合は、最初の引数 (s) それ自身がオブジェクトになります。サンプルコードでは動的パーツが文字列“テーブルの上になにかがあります。”を含んでいます。もしプレイヤーが“なにか”を使うと、“リンゴ”オブジェクトの変数‘seen’の値が“true”に設定されます。プレイヤーはそれがリンゴであることを知ります。

</div>
<br />
<div>
‘s._seen’とは変数‘_seen’がオブジェクト“s”（このケースでは“リンゴ”）に配置されていることを意味します。アンダースコア“_”は、この値がゲームのセーブファイルに保存されることを意味しています。

</div>
<br />
<div>
バージョン1.2.0以降では以下のような変数の定義ができます：

</div>
<br />
<pre>global {
    global_var = 1;
}
main = room {
    var {
        i = &quot;a&quot;;
        z = &quot;b&quot;;
    };
    nam = &#039;最初の部屋&#039;;
    var {
        new_var = 3;
    };
    dsc = function(s)
        p (&quot;i == &quot;, s.i);
        p (&quot;new_var == &quot;, s.new_var);
        p (&quot;global_var == &quot;, global_var);
    end;
</pre>
<br />
<div>
バージョン1.2.0以降では関数の定義を以下のように記述できます：

</div>
<br />
<pre>	dsc = code [[
		if not self._seen then
			p &#039;テーブルの上に{なにか}があります。&#039;;
		else
			p &#039;テーブルの上に{リンゴ}があります。&#039;;
		end
	]],
</pre>
<br />
<div>
code の実行中は、オブジェクトはそれ自身が書かれた“self”の変数になります。arg1からarg9のargs[]配列はすべての引数を保持します。

</div>
<br />
<div>
注意：変数のうち、room、game、obj、player、globalで定義されているものはすべてセーブファイルに保存されます。アンダースコアではじまる変数またはvar/globalで定義されている変数も保存されます。

</div>
<br />
<div>
以下のような変数の型が保存されます：

</div>
<br />
<ul><li>文字列</li>
<li>ブール値</li>
<li>数</li>
<li>オブジェクトへのリンク</li>
<li>構造体</li></ul>
<br />
<div>
説明文を一切表示しないでなにかをしようとする場合ハンドラが必要になります。たとえば以下のようなコードです：

</div>
<br />
<pre>button = obj {
	nam = &quot;ボタン&quot;,
	dsc = &quot;部屋の壁に{ボタン}がある。&quot;,
	act = function (s)
		here()._dynamic_dsc = [[ボタンを押したら部屋の様子が一変した。
			テーブルセットのそばにあった本棚が消え、
			奇妙なデバイスがそこに現れた。]];
		return true;
	end,
}
r12 = room {
	nam = &#039;部屋&#039;,
	_dynamic_dsc = &#039;部屋の中にいる。&#039;,
	dsc = function (s) return s._dynamic_dsc end,
	obj = {&#039;button&#039;}
}
</pre>
<br />
<div>
このケースではactハンドラが部屋の説明文を変更するのに使われていますが、説明文を後ろに追加することは想定されていません。これを実行するためにはハンドラからtrueを返す必要があります。この戻り値はこのアクションが成功したことを意味しますが、追加の説明文を表示することは要求できません。

</div>
<br />
<div>
プレイヤーのアクションが無理であることを示したい場合は、ただハンドラから何も返しません。このケースではデフォルトの説明文がこのアクションのために表示されます。デフォルトのアクションはgame.actハンドラに設定します。デフォルトのアクションは一般的に不可能なアクションのための説明文として利用されます。

</div>
<br />
<div>
上記のサンプルコードの中で、動的に表示される説明文として使われている新しい変数 _dynamic_dsc に注意してください。これは新しい説明文がセーブデータに保存されることを保証します。シーン名‘dsc’は先頭にアンダースコアを付けず、必ず小文字にします。

</div>
<br />
<div>
以上の結果、サンプルコードは次のようになります：

</div>
<br />
<pre>button = obj {
	nam = &quot;ボタン&quot;;
	dsc = &quot;部屋の壁に赤い大きな{ボタン}がある。&quot;;
	act = function (s)
		here().dsc = &quot;部屋は妙な様子だ……&quot;;
		p [[ボタンを押すと部屋の様子が一変した。
			テーブルセットのそばにあった本棚が消え、
			奇妙なデバイスがそこに現れた。]];
	end
}
r12 = room {
        forcedsc = true;
	nam = &#039;部屋&#039;;
        var {
	    dsc = &#039;私は今部屋の中にいる。&#039;;
        };
	obj = {&#039;button&#039;}
}
</pre>
<br />
<h2 id="id_ace49ed1">6. <a id="inventory" name="inventory"></a>インベントリ</h2>
<div>
プレイヤーが取ることができるオブジェクトを作るもっとも簡単な方法は“tak”ハンドラを定義することです。

</div>
<br />
<div>
たとえば次のようなコードになります：

</div>
<br />
<pre>aple = obj {
	nam = &#039;リンゴ&#039;,
	dsc = &#039;テーブルの上に{リンゴ}があります。&#039;,
	inv = function(s)
		inv():del(s);
		return &#039;リンゴを食べました。&#039;;
	end,
	tak = &#039;リンゴを取りました。&#039;,
};
</pre>
<br />
<div>
上記のコードではプレイヤーが“リンゴ”オブジェクトを使用したとき、リンゴはシーンから取り除かれインベントリに追加されます。プレイヤーがインベントリを使用すると“inv”ハンドラが呼ばれます。

</div>
<br />
<div>
サンプルコードではプレイヤーがインベントリ内のリンゴを使用すると、リンゴを食べたことになります。

</div>
<br />
<h2 id="id_2c304af6">7. <a id="scene_transition" name="scene_transition"></a>シーンの遷移</h2>
<br />
<div>
ひとつのシーンからほかのシーンへ移るには“way”属性のリストを使います。

</div>
<br />
<pre>room2 = room {
	nam = &#039;ホール&#039;,
	dsc = &#039;あなたは広いホールにいます。&#039;,
	way = { &#039;main&#039; },
};

main = room {
	nam = &#039;メインルーム&#039;,
	dsc = &#039;あなたは広い部屋の中にいます。&#039;,
	obj = { &#039;tabl&#039; },
	way = { &#039;room2&#039; },
};
</pre>
<br />
<div>
このコードでは“main”と“room2”シーンの間を移動します。前述のとおり、“nam”は関数で作ることも可能で、シーン名を動的に生成できます。たとえば、プレイヤーがそこに入るまでシーン名を知らせたくないような場合です。

</div>
<br />
<div>
2つのシーンを切り替えるときゲームエンジンは現在のシーンから“exit”ハンドラを呼び、次に行き先のシーンで“enter”ハンドラを呼びます。たとえば次にのようなコードになります：

</div>
<br />
<pre>room2 = room {
	enter = &#039;あなたはホールに入りました。&#039;,
	nam = &#039;ホール&#039;,
	dsc = &#039;あなたは広いホールにいます。&#039;,
	way = { &#039;main&#039; },
	exit = &#039;あなたはホールを出ました。&#039;,
};
</pre>
<br />
<div>
“exit”と“enter”の文字列は関数から生成することもできます。最初の引数はオブジェクト自身で、2番目の引数はプレイヤーが行こうとする部屋（“exit”のために）か、プレイヤーが去ろうとする部屋（“enter”のため）になります。たとえば次のようになります：

</div>
<br />
<pre>room2 = room {
	enter = function(s, f)
		if f == main then
			return &#039;あなたは部屋から来ました。&#039;;
		end
	end,
	nam = &#039;ホール&#039;,
	dsc = &#039;あなたは広いホールにいます。&#039;,
	way = { &#039;main&#039; },
	exit = function(s, t)
		if t == main then
			return &#039;戻りたくないよ！&#039;, false
		end
	end,
};
</pre>
<br />
<div>
ご覧のようにハンドラは2つの値を返すことができます。文字列とステータスです。このサンプルコードでは、プレイヤーがホールから“main”に戻ろうとしたとき、“exit”関数が“false”を返します。“false”はプレイヤーがシーンに移れないことを意味します。同じロジックを“enter”と“tak”でも使えます。

</div>
<br />
<div>
p/pn/prを使ってステータスを返すこともできます。次のようなコードになります：

</div>
<br />
<pre>room2 = room {
	enter = function(s, f)
		if f == main then
			p &#039;あなたは部屋から来ました。&#039;;
		end
	end,
	nam = &#039;ホール&#039;,
	dsc = &#039;あなたは広いホールにいます。&#039;,
	way = { &#039;main&#039; },
	exit = function(s, t)
		if t == main then
			p &#039;戻りたくないよ！&#039;
                        return false
		end
	end,
};
</pre>
<br />
<div>
シーンを移る瞬間の“enter”ハンドラの呼び出しでは、現在のシーンが変更されない場合があることに注意してください。バージョン1.2.0では2つのアクションハンドラが追加されました。“left”と“entered”です。これらは遷移の直後に呼ばれ、遷移が禁止されないケースでの使用が推奨されています。

</div>
<br />
<h2 id="id_de6e8501">8 <a id="use_object" name="use_object"></a>オブジェクトの操作</h2>
<div>
プレイヤーはインベントリにあるオブジェクトをほかのオブジェクトに対して使うことができます。ここでは“use”ハンドラがインベントリのオブジェクトから呼ばれて、ほかのオブジェクトから“used”されるケースを扱います。たとえば次のようになります：

</div>
<br />
<pre>knife = obj {
	nam = &#039;ナイフ&#039;,
	dsc = &#039;テーブルの上に{ナイフ}があります。&#039;,
	inv = &#039;鋭い！&#039;,
	tak = &#039;ナイフを取りました！&#039;,
	use = &#039;あなたはナイフを使おうとしました。&#039;,
};

tabl = obj {
	nam = &#039;テーブル&#039;,
	dsc = &#039;部屋の中に{テーブル}があります。&#039;,
	act = &#039;うーん、ただのテーブルのようです。&#039;,
	obj = { &#039;aple&#039;, &#039;knife&#039; },
	used = &#039;あなたはテーブルになにかをしようとしました。&#039;,
};
</pre>
<br />
<div>
プレイヤーがナイフを取ってテーブルに対して使おうとすると、“use”と“used”ハンドラの文字列が表示されます。“use”と“used”には関数を与えることもできます。最初の引数はそれ自身のオブジェクトになります。2つめの引数は“use”のためのものでアクションの対象となるオブジェクトであり、“used”はアクションを実行したオブジェクトになります。

</div>
<br />
<div>
“use”が“false”ステータスを返すと“used”は呼ばれません（それが存在すればですが）。“used”ステータスは無視されます。

</div>
<br />
<div>
たとえば次のようになります：

</div>
<br />
<pre>knife = obj {
	nam = &#039;ナイフ&#039;,
	dsc = &#039;テーブルの上に{ナイフ}があります。&#039;,
	inv = &#039;鋭い！&#039;,
	tak = &#039;ナイフを取りました！&#039;,
	use = function(s, w)
		if w ~= tabl then
			p &#039;それには切りつけたくない。&#039;
                        return false
		else
			p &#039;あなたはテーブルに自分のイニシャルを掘りました。&#039;;
		end
};
</pre>
<br />
<div>
プレイヤーはナイフをテーブルのみに使うことができます。

</div>
<br />
<h2 id="id_67814048">9. <a id="player_object" name="player_object"></a>プレイヤーオブジェクト</h2>
<br />
<div>
STEADの内部ではプレイヤーは“pl”オブジェクトで表されます。オブジェクトの型は“player”です。エンジン内部では次のように生成されます：

</div>
<br />
<pre>pl = player {
	nam = &quot;Incognito&quot;,
	where = &#039;main&#039;,
	obj = { }
};
</pre>
<br />
<div>
“obj”属性はプレイヤーのインベントリを表します。

</div>
<br />
<h2 id="id_cfee98e8">10. <a id="game_object" name="game_object"></a>gameオブジェクト</h2>
<div>
ゲームもまた“game”型の“game”オブジェクトによって表されます。エンジン内部では次のように定義されています：

</div>
<br />
<pre>game = game {
	nam = &quot;INSTEAD -- シンプルテキストアドベンチャー インタプリタ v&quot;..version..
             &quot; &#039;2009 by Peter Kosyh&quot;,
	dsc = [[
コマンド:^
    look(あるいはenter), act &lt;モノ&gt; (あるいは何), use &lt;何&gt; [何に], go &lt;場所&gt;,^
    back, inv, way, obj, quit, save &lt;ファイル名&gt;, load &lt;ファイル名&gt;.]],
	pl =&#039;pl&#039;,
	showlast = true,
};
</pre>
<br />
<div>
このようにオブジェクトは現在のプレイヤーオブジェクト‘pl’への参照と引数を保持します。たとえばゲームソースの先頭にテキストのエンコードの種類を設定できます：

</div>
<br />
<pre>game.codepage=&quot;UTF-8&quot;; 
</pre>
<br />
<div>
エンコードの種類の指定は、すべてのバージョンのUNIX版インタプリタとWindows版0.7.7以降でサポートされています。

</div>
<br />
<div>
さらに“game”オブジェクトはデフォルトのハンドラを持っています。“act”、“inv”、“use”などです。これらはプレイヤーのアクションに対応するハンドラがほかに見つからない場合にデフォルトで呼び出されます。

</div>
<br />
<pre>game.act = &#039;それは無理です。&#039;;
game.inv = &#039;うーん、それは常軌を逸脱しています。&#039;;
game.use = &#039;使えませんでした。&#039;;
</pre>
<br />
<h2 id="id_e976f352">11. <a id="attribute_list" name="attribute_list"></a>属性リスト</h2>
<div>
属性（“way”や“obj”などのような）リストは、それら自身が動的に定義されたシーン同士の接続、ライブオブジェクトなどを実装することを可能にします。

</div>
<br />
<div>
リストを操作するメソッドは“add”、“del”、“look”、“srch”、“purge”、“replace”があります。もっともよく使われるものは“add”と“del”です。

</div>
<br />
<div>
“add”はリストに追加し、“del”はリストから削除します。“purge”は削除しオブジェクトを無効にします。“srch”は検索です。“replace”はオブジェクトを置換します。“del”、“purge”、“replace”、“srch”はオブジェクト自身または識別子の引数として使用できます。またオブジェクト名にもできます。

</div>
<br />
<div>
バージョン0.8以降では、オブジェクト自身を“add”の引数として使用できます。このバージョンからはリスト中の位置を示す2つめの引数がオプションとして追加されています。“set”を使ってインデックスを指定しリストを修正できます。次のようなコードになります：

</div>
<br />
<pre>objs():set(&#039;knife&#039;,1);
</pre>
<br />
<div>
上記のサンプルコード“ inv():del(&#039;aple&#039;);”にあるとおり、リンゴを食べるコードで使われています。

</div>
<br />
<div>
“inv()”は関数であり、インベントリのリストを返します。“:”の後の“del”は関数であり、インベントリの要素を1個削除します。

</div>
<br />
<div>
同様に“tak”は次のように実装されます：

</div>
<br />
<pre>knife = obj {
	nam = &#039;ナイフ&#039;,
	dsc = &#039;テーブルの上に{ナイフ}がある。,
	inv = &#039;鋭い！&#039;,
	act = function(s)
		objs():del(s);
		inv():add(s);
	end,
};
</pre>
<br />
<div>
オブジェクトリストの追加と削除とは別に、“enable()”と“disable()”を使ってオンとオフを切り替えることができます。たとえば“knife:disable()”のような使い方になります。これは“knife”オブジェクトがシーンの説明文から消えることを意味します。後で“knife:enable()”に切り替えることもできます。

</div>
<br />
<div>
バージョン0.9.1以降で追加された“enable_all()”と“disable_all()”は入れ子のオブジェクトに使えます。

</div>
<br />
<div>
バージョン0.9.1以降の“zap”と“cat”も使用できます。zap()はすべての要素を削除し、cat(b, [pos])はリストbのすべての要素を現在のリストの位置[pos]に追加します。

</div>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>現在のところ、オブジェクトとインベントリの操作には put/get/take/drop/remove/seen/have などの高レベルの関数を使うことが推奨されています。

</div>
<br />
<h2 id="id_689b5b05">12. <a id="return_object_function" name="return_object_function"></a>オブジェクトを返す関数</h2>
<div>
STEADで定義されているいくつかの関数は、オブジェクトを返すときにたびたび使われます。たとえば次のようなものがあります：

</div>
<br />
<ul><li>inv() インベントリのリストを返します。</li>
<li>objs() 現在のシーンのオブジェクトのリストを返します（バージョン0.8.5以降はオプションの引数が1個あります。シーンのオブジェクトを返すための引数です）。</li>
<li>ways() 現在のシーンから移動できるシーンのリストを返します（バージョン0.8.5以降はオプションの引数が1個あります。シーンのリストを返すための引数です）。</li>
<li>me() プレイヤーオブジェクトを返します。</li>
<li>here() 現在のシーンを返します（バージョン0.8.5以降ではほかに、オブジェクトがどのシーンにあるかを返すwhere(obj)関数があります。これを使えるのはput/drop/moveで設定されたオブジェクトが存在する場合のみです）。</li>
<li>from() 直前のシーン名を返します。</li>
<li>seen(obj, [scene]) シーン内に存在する場合、あるいはdisable()で無効にされていない場合にオブジェクトを1個返します。</li>
<li>have(obj, [scene]) インベントリ内に存在する場合オブジェクトを1個返します。</li>
<li>exist(obj, [scene]) シーン内に存在する場合オブジェクトを1個返します。</li>
<li>live(obj) （訳注：有効な？）lifeの中に存在すればオブジェクトを1個返します。</li>
<li>path(obj,[where]) オブジェクトの検索をします。無効化されたアイテムに対しても有効です。</li></ul>
<br />
<div>
これらの関数と“add”、“del”を組み合わせて動的にシーンを変えることができます。たとえば以下のような使い方があります：

</div>
<br />
<ul><li>ways():add(&#039;nexroom&#039;); --次に進むシーンへの選択肢を追加します。</li>
<li>objs():add(&#039;chair&#039;); 現在のシーンにオブジェクトを1個追加します。</li></ul>
<br />
<div>
ref()関数はオブジェクトへの参照からオブジェクトを取得します：

</div>
<br />
<div>
たとえば‘home’シーンにオブジェクトに追加できます：

</div>
<br />
<pre>ref(&#039;home&#039;).obj:add(&#039;chair&#039;);
</pre>
<br />
<div>
これは短くすると次のコードと同等です：

</div>
<br />
<pre>home.obj:add(&#039;chair&#039;);
</pre>
<br />
<div>
あるいは0.8.5以降では：

</div>
<br />
<pre>objs(&#039;home&#039;):add(&#039;chair&#039;);
</pre>
<br />
<div>
さらに：

</div>
<br />
<pre>put(&#039;chair&#039;, &#039;home&#039;);
</pre>
<br />
<div>
以下のコードも同じです：

</div>
<br />
<pre>put(chair, home);
</pre>
<br />
<div>
バージョン0.8.5以降のderef(o)はオブジェクトへの参照文字列を1個返します。

</div>
<br />
<h2 id="id_188d2a83">13. <a id="aux_functions" name="aux_functions"></a>補助関数群</h2>
<div>
STEADには高レベルの関数がいくつかあります。ゲームを書くときに非常に便利です。

</div>
<br />
<ul><li>have() オブジェクトがインベントリにあるかどうかチェックします。オブジェクトの“nam”属性を使うかまたは参照を使います。たとえば次のようなコードです：</li></ul>
<br />
<pre>...
act = function(s)
	if have(&#039;knife&#039;) then
		return &#039;ナイフを入手した！&#039;;
	end
end
...
</pre>
<br />
<div>
次のサンプルコードは等しく動作します。

</div>
<br />
<pre>...
	if have &#039;knife&#039; then
...
	if have (knife) then
...
</pre>
<br />
<div>
次のサンプルコードはアドレスモード以上で使います。

</div>
<br />
<ul><li>move(o, w) 現在のシーンから別のシーンへオブジェクトを移動させます。たとえば：</li></ul>
<br />
<pre>move(&#039;mycat&#039;,&#039;inmycar&#039;);
</pre>
<br />
<div>
任意のシーンからオブジェクトを移動させたい場合は、“del”で元のシーンにあるオブジェクトを削除する必要があります。オブジェクトを作るのは複雑な手順になりますが、オブジェクトの位置（room）を保存する関数と元のシーンからオブジェクトを削除する関数をそれぞれ書く必要があります。“move”の3つ目の引数で初期の位置（room）を設定できます。

</div>
<br />
<pre>move(&#039;mycat&#039;,&#039;inmycar&#039;, &#039;forest&#039;); 
</pre>
<br />
<div>
バージョン0.8以降では“move”に似た機能を持つ“movef”関数が用意されています。この関数はリストの先頭にオブジェクトを追加します。

</div>
<br />
<ul><li>seen(o) 現在のシーンに存在しているオブジェクトを返します：</li></ul>
<br />
<pre>	if seen(&#039;mycat&#039;) then
		move(&#039;mycat&#039;,&#039;inmycar&#039;);
	end
</pre>
<br />
<div>
バージョン0.8.6以降ではシーン名を指定する2つ目の引数がオプションとしてあります。

</div>
<br />
<ul><li>drop(o) インベントリにあるオブジェクトをシーンに捨てます。</li></ul>
<br />
<pre>drop(&#039;knife&#039;);
</pre>
<br />
<div>
バージョン0.8以降では“drop”に似た“dropf”関数があります。これはリストの先頭にオブジェクトを追加します。バージョン0.8.5以降ではオプションで2つ目の引数があります。オブジェクトを置くシーン名です。また0.8.5以降には似た関数で“put/putf”があります。これらの関数はインベントリからオブジェクトを削除しません。

</div>
<br />
<div>
バージョン0.8.9以降では“remove(o, [from])”関数があります。これは現在のシーン、または2つ目の引数で指定したシーンからオブジェクトを削除します。

</div>
<br />
<ul><li>take(o) オブジェクトを取ります。インベントリに追加されます。</li></ul>
<br />
<pre>take(&#039;knife&#039;);
</pre>
<br />
<div>
バージョン0.8.5以降ではオプションで2つ目の引数があります。オブジェクトを取るシーン名です。

</div>
<br />
<ul><li>taken(o) オブジェクトがすでに取られている場合 true を返します（“tak”または“take()”で取られたオブジェクト）。</li></ul>
<br />
<ul><li>rnd(m) 1からmまでの乱数を生成します。</li></ul>
<br />
<div>
walk(w) 指定したシーンwに移動します。文字列の表示に“p/pn/pr”関数を使っていない場合、ハンドラは“walk”が返す値を返します。たとえば次のようなコードになります：

</div>
<br />
<pre>act = code [[
        pn &quot;次の部屋に行きます……。&quot;
        walk (nextroom);
]]
...
act = code [[
        return cat(&#039;次の部屋に行きます……。&#039;, walk (nextroom));
]]
</pre>
<br />
<div>
<span style="font-weight: bold;"><!--@@@@@-->注意：</span>walk 関数で呼び出した後、ハンドラはハンドラの end または return が来るまで実行を続けます。

</div>
<br />
<ul><li>change_pl(p) プレイヤーを切り替えます（インベントリと現在の位置が別のプレイヤーのものになります）。関数は新しいプレイヤーのシーンの説明文とハンドラから渡された戻り値を返します（“walk()”の項目を参照）。</li></ul>
<br />
<pre>mycar = obj {
	nam = &#039;自分の車&#039;,
	dsc = &#039;小屋の前にトヨタの{ピックアップトラック}が停めてある。&#039;,
	act = function(s)
		return walk(&#039;inmycar&#039;);
	end
};
</pre>
<br />
<ul><li>walkback() 直前のシーンに戻ります。</li>
<li>back() 直前のシーンに戻ります。キャラクタとの会話からシーンに戻るケースでは、シーンの“dsc/enter/entered”関数は呼ばれません。会話のシーン内部で使ってください。</li>
<li>walkin(room) シーンを移動します。現在のシーンの“exit/left”は呼ばれません。</li>
<li>walkout() 直前のシーンの戻ります。そのシーンの“enter/entered”は呼ばれません。</li>
<li>time() 現在のゲームでプレイヤーが移動した回数を返します。</li>
<li>cat(…) 文字列または連結された文字列を返します。最初の引数が nil の場合は nil を返します。</li>
<li>par(…) 文字列または最初の引数文字列で分割された文字列を返します。</li>
<li>disable/enable/disable_all/enable_all それぞれオブジェクトを有効化/無効化します。</li>
<li>visited([where]) シーンに訪れた回数を返します（nilになります）。</li>
<li>path(obj,[where]) オブジェクトがどのシーンにあるか検索します。オブジェクトが無効化されていても機能します。</li>
<li>nameof(obj) オブジェクト名（nam属性）を取得します。</li>
<li>purge (obj, [where]) remove と同じ機能でオブジェクトを削除します。無効化されたオブジェクトにも機能します。</li>
<li>replace (obj, onobj, [where]) オブジェクトを置き換えます。</li>
<li>disabled(obj) オブジェクトが無効化されていれば true を返します。</li></ul>
<br />
<h2 id="id_52aefca6">14. <a id="dialog" name="dialog"></a>ダイアログ</h2>
<div>
ダイアログは会話シーンなどに用いられ、オブジェクトの選択肢を表示します。シンプルなものは以下のようなコードです：

</div>
<br />
<pre>povardlg = dlg {
	nam = &#039;キッチンにて&#039;,
	dsc = &#039;白いシェフ帽をかぶった太めの女性が疲れた視線でこっちを見た。&#039;,

	obj = {
	[1] = phr(&#039;「その緑色のやつ……ください。そう、その豆も！」&#039;,
	&#039;「あいよ！」&#039;),

	[2] = phr(&#039;「プライドポテトとベーコンください！」&#039;,
	&#039;「ボナペティ！」&#039;),

	[3] = phr(&#039;「ガーリックスープを2つ！」&#039;,
	&#039;「シェフの自信作ですよ！」&#039;),

	[4] = phr(&#039;「なんでもいいから、柔らかくて食べやすいものをください。\
	俺って胃が悪くて……。」&#039;, &#039;「オートミールいっちょ！」&#039;),
	},
};
</pre>
<br />
<div>
“phr”で各セリフを用意します。セリフには質問と答え、リアクションが含まれます（サンプルにはリアクションがありません）。プレイヤーがセリフの1つを選択すると、それは一度無効化されます。すべてのセリフが無効になるとダイアログは終了します。リアクションは1行で書かれたLuaのコードであり、セリフが無効化されたときに実行されます。たとえば次のようなコードになります：

</div>
<br />
<pre>food = obj {
	nam = &#039;食べ物&#039;,
	inv = function (s)
		inv():del(&#039;food&#039;);
		return &#039;I eat.&#039;;
	end
};

gotfood = function(w)
	inv():add(&#039;food&#039;);
	food._num = w;
	back();
end

povardlg = dlg {
	nam = &#039;キッチンにて&#039;,
	dsc = &#039;白いシェフ帽をかぶった太めの女性が疲れた視線でこっちを見た。&#039;,
	obj = {

	[1] = phr(&#039;「その緑色のやつ……ください。そう、その豆も！」&#039;,
	&#039;「あいよ！」&#039;, [[pon(); gotfood(1);]]),

	[2] = phr(&#039;「フライドポテトとベーコンをください！」&#039;,
	&#039;「ボナペティ！」&#039;, [[pon(); gotfood(2);]]),

	[3] = phr(&#039;「ガーリックスープを2つ！」&#039;,
	&#039;「シェフの自信作ですよ！」, [[pon(); gotfood(3);]]),

	[4] = phr(&#039;「なんでもいいから、柔らかくて食べやすいものをください。\
	俺って胃が悪くて……。」&#039;, &#039;「オートミールいっちょ！」&#039;,
	[[pon(); gotfood(4);]]),
	},
};
</pre>
<br />
<div>
上記のサンプルコードではプレイヤーがディナーを選択しています。メニューを受け取った後（選択した“food._num”の値が記録されます）、プレイヤーはダイアログからシーンに戻ります。

</div>
<br />
<div>
リアクションにはLuaのコードを記述します、STEADにはあらかじめ定義された便利な関数が用意されています。

</div>
<br />
<ul><li>pon(n..) n番のセリフを有効にします（サンプルコードでは同じメニューを何度も受け取れます）。</li>
<li>poff(n…) n番のセリフを無効にします。</li>
<li>prem(n…) n番のセリフを削除します（削除されたセリフは“pon()”で再有効化できません）。</li>
<li>pseen(n…) n番のセリフが可視化されていればtrueを返します。</li>
<li>punseen(n..) n番のセリフが不可視であればtrueを返します。</li></ul>
<br />
<div>
引数がない場合は現在のセリフに対して機能します。

</div>
<br />
<div>
プレイヤーはシーンに入ったときダイアログに入ります：

</div>
<br />
<pre>povar = obj {
	nam = &#039;シェフ&#039;,
	dsc = &#039;{シェフ}がいる。&#039;,
	act = function()
		return walk(&#039;povardlg&#039;);
	end,
};
</pre>
<br />
<div>
1つのダイアログからほかのダイアログに移動することができます。またダイアログを階層化することもできます。

</div>
<br />
<div>
ダイアログを初期化する際にセリフを隠し、一定の条件で表示させることができます。

</div>
<br />
<pre>facectrl = dlg {
	nam = &#039;顔認証システム&#039;,
	dsc = &#039;感じの悪い、あからさまに意地の悪そうな顔をした太った警備員がいる。&#039;,

	obj = {
	[1] = phr(&#039;「ベリン氏の講義を聞きに来たんだが。」&#039;, 
	&#039;“「見ない顔だな。お前は誰だ？」^警備員はニヤリと笑った。^\
	「まともなやつしか中に入れないようにと言われてるんでな」”&#039;,
	[[pon(2);]]),

	[2] = _phr(&#039;「俺は招待状を持ってるぞ！」&#039;, 
	&#039;「知ったことか！自分の姿を鏡で見てみろ！ベリン氏の講義を聞きに来ただと？」^\
	警備員はベリンの名前を口にして一瞬だけ迷ったが、^「ともかく出て行け！」&#039;,
	[[pon(3,4)]]),

	[3] = _phr(&#039; 「お前の顔に蹴りを入れてやる！」&#039;,
	 &#039;「へえ。やってみろ」^
	力強い腕が俺をつかんで廊下に放り出した。バラバラにされなかったのはラッキーかもしれん。&#039;,
	[[poff(4)]]),

	[4] = _phr(&#039;「このイボイノシシ野郎！招待状を持ってるって言ってるだろうが。」&#039;,
	&#039;「なんだとお!?」警備員の目が充血してきた。^\
	強力なキックで廊下に蹴り出された。最悪だ……。&#039;,
	[[poff(3)]]),
	},
	exit = function(s,w)
		s:pon(1);
	end,
};
</pre>
<br />
<div>
“_phr”は無効化されたセリフを表し、後で有効化できます。サンプルコードではダイアログに“pon”、“poff”、“prem”関数を使っています（“exit”も参照のこと）。

</div>
<br />
<div>
現在のダイアログに対してだけでなく、任意のダイアログオブジェクトに対して有効化・無効化・削除・チェックができます。“pon”、“poff”、“prem”、“pseen”、“pusneen”関数を使用します。たとえば以下のような使い方です：

</div>
<br />
<pre>shopman:pon(5);
</pre>
<br />
<h2 id="id_b60419e9">15. <a id="lightweight_object" name="lightweight_object"></a>軽量オブジェクト</h2>
<div>
ゲームに表現力を持たせるには限界があり、そのためにシーンは複雑なコードで埋め尽くされることが多々あります。それを改善するために軽量のオブジェクトを使うことができます。たとえば以下のようなコードになります：

</div>
<br />
<pre>sside = room {
  nam = &#039;南側&#039;,
  dsc = [[研究施設の南側の壁に来ている。]],
  act = function(s, w)
    if w == &quot;玄関&quot; then
      ways():add(&#039;stolcorridor&#039;);
      p &quot;俺は玄関に向かって歩いていった。ドアには食堂と書かれている。^\
          ほう……ここから入れそうだな。&quot;;
    elseif w == &quot;人々&quot; then
      p &#039;ひとり出て行ったがなんだか満足そうな表情だ。&#039;;
    end
  end,
  obj = { vobj(&quot;玄関&quot;, &quot;東の隅に小さな{玄関}がある。&quot;),
    vobj(&quot;人々&quot;, &quot;ときどき玄関のドアから{人々}が出入りしている。&quot;)},
};
</pre>
<br />
<div>
上記のコードにあるように“vobj”は、プレイヤーが操作可能な軽量の静的オブジェクトを作ることができます（シーン内の“act”ハンドラの定義はオブジェクト名をチェックします）。“vobj”は3つ目の引数で“used”関数を呼び出します。これはオブジェクトが仮想オブジェクトのように機能します。

</div>
<br />
<div>
“vobj”の構文は“vobj(オブジェクト名, 説明文);”です。2つ目の引数にはシーンの“act”と“used”ハンドラに渡すキーワードが含まれます。

</div>
<br />
<div>
“vway”は“vobj”オブジェクトが修正されたものです。これは参照を作るためのものです。“vway”の構文は“vway(オブジェクト名, 説明文, 行き先のシーン名);”です。たとえば次のようなコードになります：

</div>
<br />
<pre>  obj = { vway(&quot;次へ&quot;, &quot;{ここ}をクリックしてください。&quot;, &#039;nextroom&#039;) }
</pre>
<br />
<div>
“vobj”と“vway”オブジェクトはシーン内で動的に設定できます。“add”と“del”関数を使います。たとえば次のようなコードです：

</div>
<br />
<pre>  objs(home):add(vway(&quot;次へ&quot;, &quot;{次へ}。&quot;, &#039;next_room&#039;));
-- ここになにかコードを書く
  home.obj:del(&quot;次へ&quot;);
</pre>
<br />
<div>
シンプルなシーン“vroom”も使えます。構文は“vroom(行き先の表示, 行き先のシーン名)”になります。次のようなコードです：

</div>
<br />
<pre>  home.way:add(vroom(&quot;西へ行く&quot;, &#039;mountains&#039;);
</pre>
<br />
<h2 id="id_39f0add7">16. <a id="dynamic_event" name="dynamic_event"></a>動的なイベント</h2>
<div>
実行するたびに配列のインデックスを増加させるようなハンドラを定義できます。たとえば次のようなコードになります：

</div>
<br />
<pre>mycat = obj {
  nam = &#039;バルシク&#039;,
  lf = {
    [1] = &#039;バルシクがボストンバックの中でもぞもぞと動いている。&#039;,
    [2] = &#039;バルシクがボストンバックの中から様子をうかがっている。&#039;,
    [3] = &#039;バルシクがボストンバックの中でのどをゴロゴロと鳴らしている。&#039;,
    [4] = &#039;バルシクがボストンバックの中で震えている。&#039;,
    [5] = &#039;俺はボストンバックの中にいるバルシクの体温を感じた。&#039;,
    [6] = &#039;バルシクがボストンバックの中から顔を出してまわりを見回した。&#039;,
  },
  life = function(s)
    local r = rnd(6);
    if r &gt; 2 then
      return;
    end
    r = rnd(6);
    return s.lf[r];
  end,
....

profdlg2 = dlg {
  nam = &#039;ベリン&#039;,
  dsc = &#039;ベリンは顔色が悪い。呆然と俺のショットガンを凝視している。&#039;,
  obj = {
    [1] = phr(&#039;「俺は猫を取り返しに来たんだ」&#039;,
  &#039;俺はベリンの手からバルシクをひったくってボストンバックに押し込んだ。&#039;,
    [[inv():add(&#039;mycat&#039;); lifeon(&#039;mycat&#039;)]]),
....

</pre>
<div>
オブジェクトまたはシーンは“life”ハンドラを持つことができます。これはオブジェクトまたはシーンに、“lifeon”によって“生きている”オブジェクトのリストに追加された場合、ゲームが進行するたびに呼ばれます。この“生きている”オブジェクトが必要でなくなったら“lifeoff”関数で削除することを忘れないようにしてください。たとえば“exit”ハンドラ内などで行います。

</div>
<br />
<div>
“life”は文字列を返します。この文字列はシーン内の最後に表示されます。

</div>
<br />
<div>
バージョン0.9.1以降では2つ目のブール値の戻り値があります。たとえば次のようになります：

</div>
<br />
<pre>return &#039;警備員が部屋に入ってきた。&#039;, true
-- このイベントはオブジェクトの説明文の前に表示されます。
</pre>
<br />
<div>
または：

</div>
<br />
<pre>p &#039;警備員が部屋に入ってきた。&#039;
return true
-- このイベントはオブジェクトの説明文の前に表示されます。
</pre>
<br />
<h2 id="id_a602bd2d">17. <a id="graphic_sound" name="graphic_sound"></a>グラフィックとサウンド</h2>
<div>
グラフィックインタプリタは、シーンに“pic”属性を持ち画像ファイルへのパスを保持しています。たとえば次のようなコードです：

</div>
<br />
<pre>home = room {
  pic = &#039;gfx/home.png&#039;,
  nam = &#039;自宅&#039;,
  dsc = &#039;俺は今家にいる。&#039;,
};
</pre>
<br />
<div>
もちろん“pic”は関数としても使えます。これは開発者の能力を大きく補強します。現在のシーンに“pic”属性が定義されていない場合は、“game.pic”属性が代わりに使われます。“game.pic”が定義されていない場合は画像は表示されません。

</div>
<br />
<div>
バージョン0.9.2以降ではアニメーションGIFを表示できます。

</div>
<br />
<div>
バージョン0.9.2以降では“img”関数を使って説明文などのテキストやインベントリなどにも画像を配置できます。たとえば次のようなコードになります：

</div>
<br />
<pre>knife = obj {
  nam = &#039;Knife&#039;..img(&#039;img/knife.png&#039;),
}
</pre>
<br />
<div>
バージョン1.3.0以降ではテキストの回りこみに対応しています。“imgl/imgr”関数を使い右と左に画像を配置できます。画像にはリンクはできません。

</div>
<br />
<div>
画像のまわりに隙間を空けるには“pad:”を使います。たとえば：

</div>
<br />
<pre>imgl &#039;pad:16,picture.png&#039; -- 16ピクセル;
imgl &#039;pad:0 16 16 4,picture.png&#039;
                    -- 上0ピクセル, 右16ピクセル, 下16ピクセル, 左4ピクセル
imgl &#039;pad:0 16,picture.png&#039;
                    -- 上0ピクセル, 右16ピクセル, 下0ピクセル, 左16ピクセル
</pre>
<br />
<div>
次のように空の画像を配置できます：

</div>
<br />
<pre>dsc = img &#039;blank:32x32&#039;..[[ブランクイメージの線。]];
dsc = img &#039;box:32x32,red,128&#039;..[[赤い半透過の正方形と線。]];
</pre>
<br />
<div>
現在のバージョンでは“disp”属性を使うことができます：

</div>
<br />
<pre>knife = obj {
  nam = &#039;ナイフ&#039;;
        disp = &#039;ナイフ&#039;..img(&#039;img/knife.png&#039;),
}
</pre>
<br />
<div>
インタプリタは“set_music(ファイル名)”関数で定義されたサウンドファイルをループ再生できます。

</div>
<br />
<div>
次のようなコードになります：

</div>
<br />
<pre>street = room {
  pic = &#039;gfx/street.png&#039;,
  enter = function()
    set_music(&#039;mus/rain.ogg&#039;);
  end,
  nam = &#039;通りの真ん中&#039;,
  dsc = &#039;雨が降っている。,
};
</pre>
<br />
<div>
バージョン1.0.0以降では基本となる画像とオーバーレイから新しい画像を作って表示できます：

</div>
<br />
<pre>pic = &#039;gfx/mycat.png;gfx/milk.png@120,25;gfx/fish.png@32,32&#039;
</pre>
<br />
<div>
get_music() 現在のサウンドのトラック名を返します。

</div>
<br />
<div>
バージョン0.7.7以降では“set_music()”関数で再生回数を指定できる引数が追加されています。“get_music_loop()”関数で現在の再生回数を取得できます。戻り値が-1の場合は再生がすでに終了したことを意味します。

</div>
<br />
<div>
バージョン0.9.2以降では“set_sound()”関数でサウンドファイルを再生できます。“get_sound()”関数は再生されたファイル名を返します。

</div>
<br />
<div>
再生を止めるには“stop_music()”関数を使います。バージョン1.0.0以降で使えます。

</div>
<br />
<div>
“is_music()”関数は現在再生中かをブール値で返します。バージョン1.0.0以降で使えます。

</div>
<br />
<hr />
<div>
18. <a href="http://w.atwiki.jp/instead/pages/18.html"  title="18. アドバイス (5263d)">アドバイス</a>へ
</div>]]>    </description>
    <dc:date>2012-01-16T21:13:25+09:00</dc:date>
    <utime>1326716005</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/instead/pages/14.html">
    <title>インストール</title>
    <link>https://w.atwiki.jp/instead/pages/14.html</link>
    <description>
      <![CDATA[<!--@@@@@--><h3 id="id_c276138d">インストール方法</h3>
<div>
INSTEADをインストールして日本語を表示する方法を説明します。一部のスクリーンショットは開発中のものを使用しています。

</div>
<br />
<div>
以下のURLからWindows版インストールパッケージ instead-x.x.x-CJK.exe をダウンロードします。CJKパッケージには日本語フォントと日本語表示のテーマ、さらにゲーム「シュレーディンガーの猫を探して」が同梱されています。
<br />
<a href="http://instead-games.googlecode.com/files/instead-1.6.0-CJK.exe" rel="nofollow">http://instead-games.googlecode.com/files/instead-1.6.0-CJK.exe</a>

</div>
<br />
<div>
日本語テーマにはIPA明朝フォント、IPAゴシックフォントが使用されています。IPAフォントはIPAライセンスに基づいて配布されています。

</div>
<br />
<div>
ダウンロードした instead-x.x.x-CJK.exe のインストールパッケージを実行し、インストーラのダイアログにしたがってインストールします。インストール先はデフォルトのまま進めます。日本語のフォルダ名にするとゲームファイルを読み取れない不具合があるようです（1.6.0現在）。

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" width="400" height="308" style="aspect-ratio: 400/308;" src="https://img.atwiki.jp/instead/attach/14/4/install001.jpg"/>

<div>
<br />

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/5/install002.jpg"/>

<div>
<br />

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/8/install005.jpg"/>

<div>
<br />

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/9/install006.jpg"/>

<div>
<br />

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/24/install014.jpg"/>

<br />
<div>
最初の起動時には“Select Game to Play”メニューが表示されます。ここで一旦、日本語環境の設定をします。Backをクリックします。

</div>
<br />
<h3 id="id_a5d92afb">日本語の表示設定</h3>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/25/install015.jpg"/>

<div>
“Settings”をクリックします。

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/26/install016.jpg"/>

<div>
“Other”→“Language:”から&lt;&lt;Japanese&gt;&gt;を選択します。

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/27/install017.jpg"/>

<div>
メニューが日本語表示になります。“適用”をクリックします。

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/28/install018.jpg"/>

<div>
“ゲームを選択”をクリックします。

</div>
<br />

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/29/install019.jpg"/>

<div>
チュートリアルを試してみてください。

</div>
<br />
<h3 id="id_9cf72203">ほかのゲームのインストール</h3>
<div>
ゲームファイルをダウンロードして展開し、INSTEADのgamesフォルダにコピーします。デフォルトでは &quot;C:\Program Files\Pinebrush games\INSTEAD\games&quot; になります。

</div>
<br />
<div>
ゲームファイルを開くにはメニューから &quot;ゲームの選択&quot; をクリックします。ゲームが開始されます。

</div>
<br />
<div>
公式の日本語のゲームは2011年12月現在のところ「シュレーディンガーの猫を探して」のみです。

</div>
<br />
<h3 id="id_4b75bbf1">カスタムテーマの日本語化の方法</h3>

<img class="atwiki_plugin_ref" loading="lazy" src="https://img.atwiki.jp/instead/attach/14/16/install013.jpg"/>

<div>
<br />
<br />
INSTEADではTrueTypeフォントが使用できます。自作のテーマを作るときは、テーマファイル &quot;theme.ini&quot; に日本語フォントを指定するディレクティブを記述します。メインウィンドウ、インベントリ、メニューで使用するフォントを指定できます。次の例ではIPAフォントを指定しています。ノーマル、ボールド、イタリックの順に並んでいます。

</div>
<br />
<blockquote><div>
win.fnt.name = {ipam,ipam,ipam}.ttc
<br />
inv.fnt.name = {ipag,ipag,ipag}.ttc
<br />
menu.fnt.name = {ipag,ipag,ipag}.ttc

</div>
</blockquote>
<br />
<br />
<div>
各テーマフォルダにそれぞれフォントファイルのコピーが必要ですが、ほかのフォルダにあるフォントを相対パスで指定することもできます。次の例では他のテーマフォルダにあるフォントファイルを指定しています。

</div>
<br />
<blockquote><div>
win.fnt.name = {../jp/ipam, ../jp/ipam, ../jp/ipam}.ttc
<br />
inv.fnt.name = {../jp/ipag, ../jp/ipag, ../jp/ipag}.ttc
<br />
menu.fnt.name = {../jp/ipag, ../jp/ipag, ../jp/ipag}.ttc

</div>
</blockquote>
<br />
<div>
win.fnt.nameが空白の場合、Windowsのシステムフォント（MS UIゴシック）が使用されます。inv.fnt.name（インベントリ）とmenu.fnt.name（メニュー）が空白の場合は文字化けするようです。

</div>
<br />
<h3 id="id_b951b769">設定ファイルなど</h3>
<ul><li>日本語メニューは &quot;C:\Program Files\Pinebrush games\INSTEAD\lang\jp.ini&quot; になります。将来メニューがアップデートされた場合などはこのファイルを編集してください。</li>
<li>ユーザーの設定やセーブデータなどは &quot;C:\Documents and Settings\[ユーザー名]\Local Settings\Application Data\instead&quot; 以下にあります。ゲームをデバッグする際にはセーブデータを参照するとよいでしょう。</li></ul>
<br />
<hr />]]>    </description>
    <dc:date>2012-03-04T13:01:45+09:00</dc:date>
    <utime>1330833705</utime>
  </item>
  </rdf:RDF>
