SF変数を使うには~スクリプトを起動した際に、前回のデータを引き継ぐ話~

おはようございます。スクリプト研究所です。

SF変数の添え字について

2016/4/29 追記
SF変数の添え字は0-99まで使用できるのを確認しました。
ただし、たくさん使うと負荷が大きすぎるので、なるべく節約するよう提案致します。

memo

SF変数はユーザー別に、かつスクリプト単位で(つまり編集室それぞれで)値を保持します。つまり基本的には、編集室が違えば別々のSF変数を使用することになります。
ただし、同じSF変数の番号(たとえば「A_2-12345_123_01」)を指定すれば、複数の編集室で同じSF変数の値を読み書きできます。ですので、「スライドを最後まで見たらミニゲームが易しくなる」ということも可能になります。

概要

用途によっては、前回スクリプトを終了させた時点での値を引き継ぎたいとおもう変数があります。たとえばこのような値ですね。

  • どこまで読んだか? どのような選択をしたか?
  • カードやアイテムを獲得したことがあるか?
  • RPGでいうステータス値

生徒会にお願いして、(指定した編集室で)SF変数を使用できるように設定して貰うと、前回スクリプトを終了させた時点での値を引き継ぐ事が出来ます。

手順1.生徒会に「この編集室でSF変数を使用したい」旨を書いて企画を出します。本当に企画に必要かどうかよく考えて、企画を書いて応募してください。
不要だと判断されると、却下されてしまいます。

手順2.生徒会からSF変数の番号が知らされます。たとえば「A_2-12345_123_01」を使って下さい、とかですね。

手順3.スクリプトにSF変数の読み出し、書き込みの処理を追加します。

sf変数は
QUEST[A_2-12345_123_01].loadsf
で読み出して
QUEST[A_2-12345_123_01].savesf
で保存できます。
QUEST[A_2-12345_123_01].start
で自動化できますが、以前は編集室ではクエスト起動できなかったので、コマンドでloadとsaveを行なうとテストしやすいと思います。

注意事項

  • SF変数はsf[0]~sf[9]までです。つまり最大でも10個しか値を保存できません。
  • SF変数には2の31乗、つまり2 147 483 648以上の値を保存できません。なお、スクリプト研究所で実績があるのは2の30乗未満、1 073 741 823までです。
  • SF変数の保存、読み出しにはそれなりのコストがかかります。SF変数を読み書きする回数はなるだけ減らしましょう。
  • SF変数を保存した直後に、SF変数を読み出そうとすると、正しい値が読み出せません。その逆も同じです。
  • 従って、SF変数同士で直接演算しないで下さい。SF[0]=flagMult:SF[1],2などということをすると、SF変数を読み出した直後にSF変数を保存することになります。

スクリプトを起動した時点で(メニューで「はい」を選んだ後で?)SF変数を読み出し、終了直前とか章が変わった時点とかにSF変数を保存するのがよろしいかと。

その1 保存したい値が数少ない場合

保存したい値が十個以下なら素直に使えば良いのです。
QUEST[A_2-12345_123_01].loadsf
で読み出して
lf[11]=flagAdd:sf[1],0
lf[12]=flagAdd:sf[2],0
lf[13]=flagAdd:sf[3],0
lf[14]=flagAdd:sf[4],0
lf[15]=flagAdd:sf[5],0
でユーザー用の変数の値を前回終了時の値に初期化して
……(いろいろな処理を行ない)……
sf[1]=flagAdd:lf[11],0
sf[2]=flagAdd:lf[12],0
sf[3]=flagAdd:lf[13],0
sf[4]=flagAdd:lf[14],0
sf[5]=flagAdd:lf[15],0
終了時の値を保存して
->exit
で終了します。

その2 保存したい値が数多くあるが、「はい/いいえ」形式、つまり0か1である場合

SF変数はsf[0]~sf[9]までです。つまり最大でも10個しか値を保存できません。ですので、「カード100種類それぞれを拾ったことがあるかどうか保存したい」というような場合には、一工夫必要です。
カードを拾ったかどうか、がlf[101]~lf[130]に(0か1で)保存されていると仮定しますね。

読み込む処理

QUEST[A_2-12345_123_01].loadsf
lf[1]=flagAdd:sf[1],0
これで保存した値を読み込めたので…
lf[130]=flagMod:lf[1],2
lf[1]=flagSub:lf[1],lf[130]
lf[1]=flagDiv:lf[1],2
lf[129]=flagMod:lf[1],2
lf[1]=flagSub:lf[1],lf[129]
lf[1]=flagDiv:lf[1],2
lf[128]=flagMod:lf[1],2
lf[1]=flagSub:lf[1],lf[128]
lf[1]=flagDiv:lf[1],2
…(中略)…
lf[102]=flagMod:lf[1],2
lf[1]=flagSub:lf[1],lf[102]
lf[1]=flagDiv:lf[1],2
lf[101]=flagMod:lf[1],2
lf[1]=flagSub:lf[1],lf[101]
lf[1]=flagDiv:lf[1],2
という流れで解凍します。

保存する処理

lf[1]=0
と初期化して…
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[101]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[102]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[103]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[104]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[105]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[106]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[107]
…(中略)…
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[129]
lf[1]=flagMult:lf[1],2
lf[1]=flagAdd:lf[1],lf[130]
と圧縮して…
sf[1]=flagAdd:lf[1],0
QUEST[A_2-12345_123_01].savesf
で保存します。

解説

結局は二進数にして保存しているのですが…と言えば判る人は判りますが。
ABCにそれぞれ0か1が設定されているとしますね。
YにAを保存して、YからAを読み出すのは簡単です。
では、このような処理を行なったら、Yには何が入っているでしょうか?

  1. Yを0にする
  2. Yを二倍する
  3. YにAを加える

当然、YにはAが入っていますよね? では続けて…

  1. Yを二倍する
  2. YにBを加える

こうすると、Yには(A×2+B)が入っています、と、ここまでは大丈夫ですか? では続けて…

  1. Yを二倍する
  2. YにCを加える

こうすると、Yには((A×2+B)×2+C)が入っています、と。

では、ここで「Yを2で割った余り」を考えてみましょう。(A×2+B)×2 の部分は2で割り切れますので、「Yを2で割った余り」とCが等しくなります。
つまりCが1なら「Yを2で割った余り」も1で、Cが0なら「Yを2で割った余り」も0になります。

これでCが判ったので、Yには((A×2+B)×2+C)が入っている状態で、YからCを引き算してみましょう。
Yには((A×2+B)×2)が入っていますね?では続けて…

  1. Yを2で割る
  2. Yを2で割った余りを求める

こうすると、 Yには(A×2+B)が入っている状態なので「Yを2で割った余り」とBが等しくなります。
これでBが判ったので、Yには(A×2+B)が入っている状態でYからBを引き算してみましょう。
Yには(A×2)が入っていますね?では続けて…

  1. Yを2で割る
  2. Yを2で割った余りを求める

こうすると、 Yには(A)が入っている状態なので「Yを2で割った余り」とAが等しくなります。

Yに格納するときとYから読み出すときで、順序が逆になることに注意して下さいね。

その3 保存したい値が数多くあり、0~99や0~25など千差万別である場合

上記の応用です。
Aに0~2999が、Bに0~12が、Cに0~31が設定されているとします。

YにAを保存して、YからAを読み出すのは簡単です。
では、このような処理を行なったら、Yには何が入っているでしょうか?

  1. Yを0にする
  2. Yを3000倍する
  3. YにAを加える

当然、YにはAが入っていますよね? では続けて…

  1. Yを13倍する
  2. YにBを加える

こうすると、Yには(A×13+B)が入っています、と、ここまでは大丈夫ですか? では続けて…

  1. Yを32倍する
  2. YにCを加える

こうすると、Yには((A×13+B)×32+C)が入っています、と。

では、ここで「Yを32で割った余り」を考えてみましょう。(A×13+B)×32 の部分は32で割り切れますので、「Yを32で割った余り」とCが等しくなります。
つまりCが15なら「Yを32で割った余り」も15で、Cが0なら「Yを32で割った余り」も0になります。

これでCが判ったので、Yには((A×13+B)×32+C)が入っている状態で、YからCを引き算してみましょう。
Yには((A×13+B)×32)が入っていますね?では続けて…

  1. Yを32で割る
  2. Yを13で割った余りを求める

こうすると、 Yには(A×13+B)が入っている状態なので「Yを13で割った余り」とBが等しくなります。
これでBが判ったので、Yには(A×13+B)が入っている状態でYからBを引き算してみましょう。
Yには(A×13)が入っていますね?では続けて…

  1. Yを13で割る
  2. Yを3000で割った余りを求める

こうすると、 Yには(A)が入っている状態なので「Yを3000で割った余り」とAが等しくなります。

つまり、保存時には「格納したい値の最大値+1」倍しておいてから「格納したい値」を加える を繰り返します。
読み出し時には「格納したい値の最大値+1」で割った余りを求めて、その値を引き算し、「格納したい値の最大値+1」で割る を繰り返します。
Yに格納するときとYから読み出すときで、順序が逆になることに注意して下さいね。

SF変数を使うには~スクリプトを起動した際に、前回のデータを引き継ぐ話~” に対する意見

  1. ピンバック: スクリプト研究所 記事一覧(目次) | スクリプト研究所

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です