記事一覧

キレイなスクリプトの書き方

スクリプトを書いていらっしゃる方が沢山来ていただいているようで、スクリプターとしては嬉しい限りです。
それに加え、スクリプトの質問をされる方も多くなってきました。
書き方のことで質問された方もいるので、いい機会に勝手ながらアドバイスをさせてもらいます。

※久しぶりに開発者よりの日記です。興味ない方ごめんなさいorz

-

最近のスクリプトを見てお気付きの方もいらっしゃると思いますが、menu・gotoなど、ラベルを使う命令を一切排除しています。
これは去年の1月からしているNo more "goto" Good bye "goto"運動(AthenaDevさんにて命名?)によるもので、スクリプトの見直し・整形を行いました。
実際に見てみると、最新のAthenaデフォルトではsampleスクリプトを除き、gotoは使われていないと思います。

なぜgotoやmenuがいけないのか、答えはswitch、selectなどで綺麗に簡潔に代用できるからです。
実際に昔のスクリプトと改修後のスクリプトを見てみると、

lou_fild01.gat,175,173,4scriptクエン ホ819,{
    if(Lou_que1 == 4) goto L_OK2;
    if(Lou_que1 == 3) goto L_OK1;
    mes "[クエン ホ]";
    mes "ここは危険だ。帰れよ。";
    close2;
    warp "lou_fild01.gat",200,174;
    end;
L_OK1:
    emotion 18;
    mes "[クエン ホ]";
    mes "どうだい、素敵だろ~。";
    mes "落ち込んだり元気がなくなると";
    mes "ここに来るんだ。";
    mes "ここからじっと景色を眺めてると";
    mes "落ち着くんだよ。";
    next;
~~~~~略~~~~~
L_OK2:
    mes "[クエン ホ]";
    mes "どうする?";
    next;
    menu "叫ぶ",-,"帰る",L_CANCEL;
    mes "[クエン ホ]";
    mes "おし、叫んでみて!";
    next;
    input @annouce$;
    announce "「"+strcharinfo(0)+"」の叫び : "+@annouce$,0x01;
    mes "["+strcharinfo(0)+"]";
    mes @annouce$;
    next;
    mes "[クエン ホ]";
    mes "どう?すっきりした?";
    mes "また叫びたくなったら来なよ。";
    close;
L_CANCEL:
    mes "[クエン ホ]";
    mes "うん、じゃあまたね。";
    close2;
    warp "lou_fild01.gat",200,174;
    end;
}

改修前の龍乃城NPC、クエン ホです。
まだフラグが少ないNPCなので何とか目で追っていけますが、もしもクエストフラグが何十にも及ぶと大変ですね。

一方改修後は

lou_fild01.gat,175,173,4scriptクエン ホ819,{
    switch(LOU_1QUE) {
    default: //3,4以外のとき
        mes "[クエン ホ]";
        mes "ここは危険だ。帰れよ。";
        close2;
        warp "lou_fild01.gat",200,174;
        end;
    case 3:
        emotion 18;
        mes "[クエン ホ]";
        mes "どうだい、素敵だろ~。";
        mes "落ち込んだり元気がなくなると";
        mes "ここに来るんだ。";
        mes "ここからじっと景色を眺めてると";
        mes "落ち着くんだよ。";
        next;
~~~~~略~~~~~
    case 4:
        mes "[クエン ホ]";
        mes "どうする?";
        next;
        if(select("叫ぶ","帰る")==2) {
            mes "[クエン ホ]";
            mes "うん、じゃあまたね。";
            close2;
            warp "lou_fild01.gat",200,174;
            end;
        }
        mes "[クエン ホ]";
        mes "おし、叫んでみて!";
        break;
    }
    next;
    input '@word$;
    announce "「"+strcharinfo(0)+"」の叫び : " +'@word$,1,0x9BFD00;
    mes "["+strcharinfo(0)+"]";
    mes '@word$;
    next;
    if(LOU_1QUE == 3) {
        mes "[クエン ホ]";
        mes "どう?すっきりしたかな?へへ。";
        mes "ここには、好きに来ていいよ。";
        mes "今日は本当にありがとう!";
        set LOU_1QUE,4;
    }
    else {
        mes "[クエン ホ]";
        mes "どう?すっきりした?";
        mes "また叫びたくなったら来なよ。";
    }
    close;
}

フラグの状況と進行具合が目で追って分かりやすいです。
breakなどによる共通部分の処理も気軽に出来る点も魅力です。
またラベルを使っていないので、衝突を意識する必要もありません。
この大改修でほとんどのスクリプトが見やすくなり、また後から手を加える人にとって大変ありがたい偉業となりました。



スクリプトを書く際少なくとも私はこの点に注意し、見た目的に分かりやすく美しく、を追求しています。
まだまだ未熟な部分もありますが・・・orz
「スクリプトなんて動けばいいじゃん」と思う方もいらっしゃるかもしれません。
ですがプログラムも然り、それを見る人・手を加える人がいる限り整合の必要性があります。

いきなりswitchやselectなんて・・・という方、私も最初はそうでしたorz
が、いざやってみるとゴチャゴチャしていた物がキレイになっていく感じで意外とハマり、無駄な処理・不要な部分という物が見えてきます。
それを排除していくことでより一層綺麗に仕上がると思います。


スクリプトを作ってる方、まずはgoto・menuの排除に挑戦してみてはいかがでしょうか。

コメント一覧

Cocoa 2007年02月14日(水)00時27分 編集・削除

スクリプト公開所の濃縮エルNPCでgoto使ってたorz
ちょっくら書き直してくるぜ!
λ=3......

らの字 2007年02月14日(水)06時08分 編集・削除

確かにswitchのほうが高性能だけど、
個人的にはmenuとラベルのように
各処理部分をはっきり分けられて
初心者にわかりやすいところが好きです。

はっきりとmenuとラベルをスクリプトから排除するより
場合によって使い分けすべきではないかと考えてます。

こより 2007年02月14日(水)17時26分 編集・削除

好みの問題だからなぁ。
ボクはswitchのほうが好き。

C寄りの考え方に慣れてくると、多分switch派になるんじゃないかなぁ。

Blaze 2007年02月15日(木)02時19分 編集・削除

個人的にラベルはイベント時やcallsub等呼び出しのみの使用と考えています。
汎用性が低いもの、例えばcancel時はラベル呼び出しよりもその条件分岐地点にぶら下げる形がスマートだと思いますので・・・

私では現状の改修後のカタチに慣れてしまいましたが、やはり人それぞれ使いやすいカタチがありますよね。
自主的な概念を強要するつもりはありませんので、人それぞれの書きやすいカタチで書いていくのも個性的でいいかもですね。

Gokismith 2007年02月17日(土)12時43分 編集・削除

swicthは便利だとは思うのですが、menuは全部排除となると躊躇します。

なぜならswicthだけだと、ラベルの全部が「CASE 数字」になってしまうので、mes文を読まないと
「これをしたのはNPCプログラムのどこだったっけ・・・?」
となってしまうから。

たとえば上のものだとLOU_1QUEが何の関数だったか忘れると一貫の終わりなわけで・・・

ラベルにそれこそLOWZENYとか具体的に書いてあればお金の足りない時の処理どうだったっけ・・・?を言葉で検索できますが、CASEだと全部読まないとムリになっちゃう。

明らかにBASIC臭い考えかただなぁと自分でも思いますけど orz

menuとラベルがAthenaから消えると自分はプログラム書くのきつくなっちゃいそうです。

elseif 2007年02月22日(木)00時54分 編集・削除

goto,menuはあまり使わない派だけど、テストNPCを書くときはmenuやgoto使います
それにAthenaのスクリプトは普通書き捨てなので、使っていってかまわないと考えています
Gokismithさんの言うように、switch,select時は戻り値が整数になるので分岐を増やすと追いかけづらくなりますしね

個人的には饒舌なNPCだとmes命令が冗長になるのと、永続キャラクター変数に何も修飾されないのが辛いです

ナナ氏 2007年03月06日(火)11時28分 編集・削除

さすがBlazeさん。
この考えはダイクストラが唱えた構造化定理の提案と同じ考えですね。
「いかなる制御を行なうプログラムも、補助的なスイッチなどを用いればgoto文のないプログラム(gotoless program)を記述できる」ていうもの。

プログラマーとしてはこの構造化定理に沿って記述していくのが筋。
「gotoの方が使い易い」という人はまだ使い熟していない証拠でしょう。

コメント投稿

投稿フォーム
名前
コメント
文字色
削除キー
投稿キー
※投稿キーには「auriga」と入力してください。