2023年10月7日土曜日

[セカンドライフ:lsl]複数のフラグを一つのint型で格納し、bit演算で判定する。の話。


 
 どうも、まあやです。ひっさびさのブログ投稿です。
 今回のお話はセカンドライフのスクリプトであるLSLの関する話となります。



複数のフラグを扱う場合に、
    integer i_flag01;
    integer i_flag02;
    integer i_flag03;
    integer i_flag04;
    integer i_flag05;
の様に変数を用意し、
    if(i_flag01 == TRUE){};
と判定を行うと思います。

これを、
    integer i_flag;
の変数だけを用意し、
    if(i_flag & 2){}
等として判定します。

 i_flagの中には、00000から11111の二進数でフラグを格納します。
例えば1個目のフラグを1桁目、2個目のフラグを2桁目~とするならば、2個目のフラグだけTRUEの際には、i_flagは00010、十進数では2となります。
これを
 if(i_flag & 2){}
とする事で、ANDで判定しif文の中が実行されるわけです。

 この判定の仕方には利点があって、複数のフラグを判定したい場合、個別のintgerにフラグを格納しているのならば、
    if(i_flag02 == TRUE){
        if(i_flag03 == TRUE){
        }
    }
であったり、
    if( (i_flag02 == TRUE) && (ifi_flag03 == TRUE) ){};
となりますが、一個のintgerに格納し、例えば2個目と3個目のフラグがTRUEの場合としたいのなら、二進数で00110である十進数の6、
    if( i_flag & 6){}
で判定が出来ます。

 この処理には利点もありデメリットもあるのですが、例えば
    if(i_flag & 6){}
の際に、i_flagが二進数00110である十進数で6の時も、二進数で00111である十進数7の時も、2桁目と3桁目は1の為、どちらもTRUEとなる事です。
 TRUEの部分があってさえいれば良いというのであればこれで良いのですが、FALSEの部分はFALSEであって欲しい場合に困ってしまいます。そこでどうするかというと、
    if(i_flag == 6){}
としちゃう。bit演算にこだわり過ぎない。
 じゃあ全部==でいいのではと思うかもしれませんが、&でビット演算の方がわずかにメモリや処理が良いのと判定の緩さが出るので。

 それではフラグの格納の仕方です。個別に変数を用意しフラグを格納する場合は、
    i_flag01 = 1;
等と中身を考えずに放りこむ事がわけですが、一つにまとめた場合はこうはいきません。
 例えば2個目のフラグをTRUEにしたい場合は、
    if(i_flag & 2){
        //そもそもTRUEなので何もしない。
    }else{
        i_flag += 2;
    }
とし、逆にFALSEにしたい時は
    if(i_flag & 2){
        i_flag -= 2;
    }else{
        //そもそもFALSEなので何もしない。
    }
となります。これだと処理が増えてしまってるじゃないかと思うでしょうが、実際に使う際はフラグの判定ー>行いたい処理の実行ー>フラグの格納となるので、増えずに済みます。


 結局のところ、フラグを一個の変数に格納する。bit演算する。これらは有効ではある物のメリットを感じれるだけの物になるのかという問題はあります。スクリプトの規模や内容は作るものによってかなり変わるので。ですので書く際、メンテ、使用時でどう描くと良いのかを試し、手法の一つとして身に着けておくと役には立つかなと思います。


#secondlife #sljp #lsl