randomize

2016/05/01

Killzone KidのArmaスクリプト講座:遅延評価の作り方

(訳注:プログラムに馴染みのない方にはやや見慣れない「評価」という言葉は「式から答えを取り出す」ことを意味する。かくいう私も知りませんでした。また、このポストはスクリプトのパフォーマンス向上に関する話で、正直初心者向けではありません。)
あなたがArmaのエンジンについて知っておくべきことの一つは、自ら勝手に仕事を増やし実行していくということ。そして意図的な休みを入れないかぎり実行は止まらない。何が言いたいかって、trueまたはfalseを返す式の話だ。基本例を見てみよう。

if (a && b && c) then {
    //実行
};

もしabcがすべてtrueなら、演算の結果()内はtrueとなり、{}の中身が実行される。基本的に式をtrueと評価させるためには、全ての変数をtrueにする必要がある。()内の演算は左から右に実行されていくため、もしafalseならばbcの演算は行わないのが道理というものだ。しかしArmaのエンジンは違う考えを持っているらしく、)に当たるまで全てチェックする。

スクリプトを書くこととこの事実はどう関係するか?つまり複数のif構文を活用することにより処理速度を上げられるということだ。従って上のスクリプトは次のように書くことで処理速度を上げられる。

if (a) then {
    if (b) then {
        if (c) then {
            //実行
        };
    };
};

この場合afalseだった場合{}内を無視するため、即座に次のタスクに移れる。幸運にも(訳注:このような回りくどい書き方をしなくても)BETA 93632で遅延評価モード(並行して評価するのではなく、順番が来るまで待機する評価)が追加された。
[93632] New: Lazy evaluation variants of scripting functions and / or.
(訳注:ソースはこちら

このモードを実行するためには通常とは異なる書き方をする必要がある。通常の演算の場合には次のような構文である。
  • boolean [and/or] boolean [and/or] boolean … [and/or] boolean
遅延評価のコードと比べてみよう。
  • boolean [and/or] code [and/or] code … [and/or] code
この時最初に一回だけbooleanを使い、その後codeを使う必要がある。式をtruefalseに評価するにはcodeをbooleanのように使おう。つまり遅延評価を行う場合、最初の例を次のように書き換える必要がある。

if (a && {b} && {c}) then {
    //実行
};

すべてcodeならば分かりやすいかもしれないが、これでよいのだ。この構文は(訳注:if構文に限らず)switchwhilewaitUntilでも可能である。

private ["_result","_step","_c"];   
_result = "is false";  
a = {
    _step = "1";  
    true;
};  
b = {  
    _step = "2";  
    false;
};  
_c = {  
    _step = "3";  
    true;
};
scopeName "main";
while {call a && b && _c} do {
    _result = "is true";
    breakTo "main";
};
hintSilent format ["Expression %1, quit at step %2", _result, _step];

上の例の評価はExpression is false, quit at step 2.となる。というわけで、以上がArma向け遅延評価の講座だ。

Enjoy,
KK



補足

恐らく読者の皆さんはつまらない座学でも聞いているような気分で読みきったと思うんですけど(私もそうです)、この講座をより深く理解するためには構文の負荷を測定する必要があります。
Escでポーズして出てくるデバッグコンソールのExecuteの欄、左下のメーターのアイコンを押すことで今Executeに入力されている構文を10000回実行してその負荷を測定してくれます。
これを利用して例文を入力し、aとbとcの状態を変えながら負荷を観察すると遅延評価の特徴と意義が分かってくるかもしれません(あえてここでは解説しません)。
また、andorの"Alternative Syntax"や"Examples"に書いてある例も読むと理解がしやすいかもしれません。
a、b、cの状態を変えるには、Watchの部分に
a = true
などと書き込めば実行してくれ、大変便利です。

なお、構文を実行して測定しているため、高負荷の構文(createVehicleやhintのような)を実行しようとするとゲームがフリーズする危険があります。
この負荷テストではフリーズの危険がある構文はある程度自動で中断してくれますが、念のためあまり危険なことはしないようにしましょう。

ちなみに、この負荷テストは以下の構文でも可能です。
["(実行する構文)"] call BIS_fnc_codePerformance;

0 件のコメント :

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。