選択肢を使いこなす

 KAG で、選択肢によって変化するシナリオを管理する場合、ちょっと見ただけで気の狂いそうなシナリオになってしまうことがあります。例えば、以下のようなコードです。

; first.ks -----------------------------
*スタート|
@cm

好きな食べ物はなんですか?[r]
@r
[link target=*好きな食べ物→カレー]カレー[endlink][r]
[link target=*好きな食べ物→ハンバーグ]ハンバーグ[endlink][r]

@s
;---------------------------------------
*好きな食べ物→カレー|
@cm

では、特に好きなカレーの種類を教えてください。[r]
@r
[link target=*好きな食べ物→カレー→カツカレー]カツカレー[endlink][r]
[link target=*好きな食べ物→カレー→納豆カレー]納豆カレー[endlink][r]

@s
;---------------------------------------
*好きな食べ物→カレー→カツカレー|
@cm

好きな食べ物 : カレー[r]
好きな種類 : カツカレー[r]

@s
;---------------------------------------
*好きな食べ物→カレー→納豆カレー|
@cm

好きな食べ物 : カレー[r]
好きな種類 : 納豆カレー[r]

@s
;---------------------------------------
*好きな食べ物→ハンバーグ|
@cm

では、和風・洋風ではどちらが好きですか?[r]
@r
[link target=*好きな食べ物→ハンバーグ→和風ハンバーグ]和風ハンバーグ[endlink][r]
[link target=*好きな食べ物→ハンバーグ→洋風ハンバーグ]洋風ハンバーグ[endlink][r]

@s
;---------------------------------------
*好きな食べ物→ハンバーグ→和風ハンバーグ|
@cm

好きな食べ物 : ハンバーグ[r]
好きな種類 : 和風ハンバーグ[r]

@s
;---------------------------------------
*好きな食べ物→ハンバーグ→洋風ハンバーグ|
@cm

好きな食べ物 : ハンバーグ[r]
好きな種類 : 洋風ハンバーグ[r]

@s
;---------------------------------------

 これだけならまだマシなのですが、これが複雑に絡まり合うシナリオになってくると、もうお手上げです。

 さて、このようなシナリオは、変数とマクロを用いることにより、ある程度分かりやすくまとめることができます。私が直してみたところ、以下のようなシナリオになりました。

; first.ks -----------------------------

;---------------------------------------
; 選択肢用マクロ
;---------------------------------------
; 属性
;   text : 表示させたい文字
;   flag : 変数名
;   label: ラベル名(指定しなかった場合は、*変数名となる)
;
; 例えば、[select text=カレー flag=好きな食べ物]と書いた場合、その選択肢が選ばれると、
; 1、「f.好きな食べ物」という変数に "カレー" が入る。
; 2、「*好きな食べ物」というラベルに飛ぶ。
;---------------------------------------
@macro name=select
@eval exp="mp.label = '*' + mp.flag" cond="mp.label === void"
@link target="&mp.label" exp="&'f.'+ mp.flag + '=' + '\'' + mp.text + '\''"
@emb exp=mp.text
@endlink
@r
@endmacro
;---------------------------------------


; ---------------------------------------
*スタート|
@cm

好きな食べ物はなんですか?[r]
@r
@select text=カレー flag=好きな食べ物
@select text=ハンバーグ flag=好きな食べ物

@s
; ---------------------------------------
*好きな食べ物
@cm

; ◆カレーの場合
@if exp="f.好きな食べ物 == 'カレー'"
では、特に好きなカレーの種類を教えてください。[r]
@r
@select text=カツカレー flag=好きな種類 label=*結果
@select text=納豆カレー flag=好きな種類 label=*結果
@endif

; ◆ハンバーグの場合
@if exp="f.好きな食べ物 == 'ハンバーグ'"
では、和風・洋風ではどちらが好きですか?[r]
@r
@select text=和風ハンバーグ flag=好きな種類 label=*結果
@select text=洋風ハンバーグ flag=好きな種類 label=*結果
@endif

@s
; ---------------------------------------
*結果
@cm

好きな食べ物 : [emb exp="f.好きな食べ物"][r]
好きな種類 : [emb exp="f.好きな種類"][r]

@s
; ---------------------------------------

 マクロの部分が分かりにくいと思いますので、説明しておきます。

 まず、

@eval exp="mp.label = '*' + mp.flag" cond="mp.label === void"

の部分では、「label 属性が指定されなかった場合、flag 属性に指定された文字をラベルとして扱う」ということをやっています。

cond="mp.label === void"

というのが、「label 属性が指定されなかった場合」という意味になります。このように、マクロに指定された属性は、マクロ内で書き換えてしまうことができます。

 次に、

@link target="&mp.label" exp="&'f.'+ mp.flag + '=' + '\'' + mp.text + '\''"

の部分ですが、これはさらに難しいと思います。まず、

@link target="&mp.label"

までは大丈夫でしょう。これすらあやういという人は、KAG リファレンスのエンティティの部分で学んできてください。さて、問題は、

exp="&'f.'+ mp.flag + '=' + '\'' + mp.text + '\''"

の部分です。まず、link タグの exp 属性は、クリックされたときに初めて解釈されます。このため、単純に、

@link exp="f[mp.flag] = mp.text"

と書いたのでは、エラーになってしまいます。これは、選択肢をクリックする時点では、すでに mp ( マクロに与えられる属性変数 ) は、クリアされてしまっているからです。このために、クリックされるまでにあらかじめ、mp の中身を展開しておく必要があります。そこで、

exp="&'f.'+ mp.flag + '=' + '\'' + mp.text + '\''"

という記述が必要になるわけです。

 多分、これで「分かった〜!」という人は少ないでしょう。しかし、無理をして使っていく内に、「あ、そういうことか!」と分かる日が来るはずです。


 さて、選択肢を管理する場合、このように、色々と工夫をすると KAG の勉強にもなり、シナリオも見やすくなり、一石二鳥だと思います。皆さんも、自分なりの分かりやすいやり方を見つけてみてください。