プチコン3号プログラム

簡易関数電卓 QSP

初出公開日 2015年8月31日
【3DS両対応】【BIG動作可】 プチコンBIGでも特に問題なく動作します

 これはプチコン3号のQSP(WIDTH 16の1画面プログラム)で作った簡易的な関数電卓です。

 「簡易関数電卓QSP」の基本的な使い方の説明はQSPコーナーの「簡易関数電卓QSP」の項目で行っていますのでそれをご覧になってください。このページでは「簡易関数電卓QSP」の動作原理の解説や拡張関数ライブラリの使い方や自分でライブラリを作る方法などを詳しく書いていきます。





「簡易関数電卓 QSP」の動作の仕組み



 この「簡易関数電卓QSP」は式を評価する自作関数RVAL()を使うことでプチコン3号で使えるすべての演算子、関数、システム変数、定数リテラルを使った演算を可能にしています。(リスト短縮のためRVAL()関数はバラしてプログラムに内包しています)

《 プログラムリスト 》

公開キー【 ED2EM3 】、ファイル名「1GQ_CALC

《 実行時のスクリーンショット 》


《 実行時の動画 》 (※開始から40秒以降は拡張関数ライブラリの機能を使ったもの)


 RVAL()関数のリストを記しておきます。

《 RVAL()関数 ver.1.0 プログラムリスト 》



 簡易関数電卓QSPに使われているのはこのRVAL()関数 ver.1.0です。

 ちなみに最新のRVAL()関数 ver.2.1を使えば簡易関数電卓QSPのリストは現在より69文字も短く記述可能です。(実はver.1.0のままでも10文字以上短縮可能)

《 RVAL()関数 ver.2.1 プログラムリスト 》



 しかし、すでに作っているライブラリとの互換性が無くなる(戻り値がある関数はそのまま動作するけど戻り値を設定しない関数は正常に動作しなくなる)という問題を抱えてしまうため当面は簡易関数電卓QSPでは RVAL()関数 ver.1.0をベースにした現行バージョンのままとします。(ver.2.1を使用することで短縮できる59文字を互換性を保つための修正のために使うという方法もあるけどそれでも100%の互換性を保つことができないためその方法はしばらく行う予定はない)

 さて、「簡易関数電卓QSP」の核となっているRVAL()関数ですが、これは別のプログラムスロットで実際にその式を実行してその値を返すことによりプチコン3号で実行できるすべての式に対応しています。そのため入力された式をわざわざ構文解析しなくても超お手軽に演算優先順位通りの演算が可能です。
 もしも、「別のプログラムスロットで実際にその式を実行」以外の方法で式の評価を行うならば1文字ずつ文字列を読み取っていって四則演算のみに対応させるだけでも逆ポーランド記法に置き換えたりなどの処理が必要になってきます。そして関数に対応させるためには対応させる関数の分だけ条件判断を行いその関数の処理を記述していく必要があります。定数リテラルに対応させようとすれば使用可能な定数リテラルをデータ化してその中に合致しているかどうかで判断する必要があります。いずれも、言葉で説明するならば単純ですが、実際に記述するならばこのRVAL()関数と比べて数100倍は大きなプログラムになることでしょう。

 要するに、このRVAL()関数を使えば WHIILE 1:INPUT A$:?RVAL(A$):WEND とするだけで誰でも簡単に(QSPという縛りがあっても)超簡易関数電卓が作れてしまうということです。RVAL()関数はコンパクトサイズであるため凝った処理を追加しなければQSPに収めるのは非常に簡単にできる)
 「簡易関数電卓QSP」はそれに電卓としての使い勝手を上げるための工夫を追加しているだけにすぎません。

 この簡易関数電卓QSPでは上記のようにすべての演算子、関数を使った演算優先順位通りの計算を行えるというだけではなく計算結果は分かりやすく"1+1=2"のような等号で結んだ形で表示するようにしています。

《例》 2+3*4 と入力 → 2+3*4=14 と表示

 どんな関数や演算子が含まれた式でも良いのでこんな式でも計算が可能です。

《例》 SIN(RAD(30))*#L>>4 と入力 → SIN(RAD(30))*#L>>4=7 と表示

 プチコン3号で普通に演算結果の表示を行う場合は10の100乗のように大きな数は後ろに0がたくさんついて非常に見にくくなるし、0.0000000001のように小さな数は結果が丸められて0と表示されてしまいます。これでは関数電卓としてはあまり使い勝手が良くないため演算結果はSTR$()を使い文字列に変換して表示を行っています。これによって絶対値が大きな数、小さい数は自動的に指数で表示されるため見た目で分かりやすくなります。。
 このように拡張関数ライブラリ無しの純粋なQSPの状態でも関数電卓として一通り使用することが可能です。

 STR$()を使用した場合には計算結果が6桁程度に丸められてしまいますが、もっと精度が欲しいという場合は拡張関数ライブラリ3にあるPS()関数を使えば問題ありません。
 プチコン3号で実行できるすべての式に対応ということは当然自作関数に対応しています。したがって、ライブラリ(様々な自作関数)の追加で機能をどんどん追加できます。その際は簡易関数電卓QSPのリストそのものに手を加える必要はありません。(標準で戻り値のあるすべての関数に対応しているため)


拡張関数ライブラリ1 について



 拡張関数ライブラリ1によってSIND()関数、COSD()関数、TAND()関数、FACT()関数、P()関数、C()関数という6つの関数が追加されます。この拡張関数ライブラリ1そのものがQSPです。

《 プログラムリスト 》


《 実行時のスクリーンショット 》


 SIND()関数、COSD()関数、TAND()関数は「ラジアン」ではなく「度」で計算が可能な三角関数です。

《例》 SIND(30) と入力 → SIND(30)=0.5 と表示

 わざわざこんな関数を用意しなくてもSIN(RAD(30))sin 30°の値を求めることが可能です。しかし、簡易関数電卓QSPの仕様上、三角関数の値を計算する場合は常にRAD()を入力する必要があるためその必要がない「度」で計算する三角関数を用意したというわけです。
 事前にDEGREE()と入力しておけばそれ以降はすべて「度」で計算、RADIAN()と入力すれば「ラジアン」での計算になるような方法も考えましたが、そのためには入力した式の構文解析が必要になってくるためやめました。

 FACT()関数は階乗を求める関数です。

《例》 FACT(9) と入力 → FACT(9)=362880 と表示

 階乗というのは例えば「5!(5の階乗)」は1*2*3*4*5を示しています。なお0!1と定義されています。なお、引数を小数で指定した場合の例外処理は行ってないため整数値で指定してください。

 P()関数は順列を求める関数です。(順番を考慮した並び方の総数)
 P(N,R)とすることで異なるN個の中からR個を取り出したときの順列が計算できます。

《例》 P(10,4) と入力 → P(10,4)=5040 と表示

 これによって1〜10の数字が書かれたくじの中からランダムに4枚抜き出して並べたときには5040通りのパターンがあることが分かります。(5040通りというのは例えば「1,4,5,6」という順番で4枚抜き出した場合と「4,1,5,6」という順番で4枚抜き出した場合は別々のものとしたときの数字)

 C()関数は組み合わせを求める関数です。
 P(N,R)とすることで異なるN個の中からR個を取り出したときの組み合わせが計算できます。

《例》 P(10,4) と入力 → P(10,4)=210 と表示

 これによって1〜10の数字が書かれたくじの中からランダムに4枚抜き出したときにはその組み合わせは210通りになることが分かります。(210通りというのは例えば「1,4,5,6」という順番で4枚抜き出した場合と「4,1,5,6」という順番で4枚抜き出した場合は同じ4枚を抜き出したものなので同じものとしたときの数字)


拡張関数ライブラリ2 について



 拡張関数ライブラリ2によってTAXIN()関数、TAXOUT()関数、HEX()関数、BIN()関数という4つの関数が追加されます。この拡張関数ライブラリ2そのものがQSPです。

《 プログラムリスト 》


《 実行時のスクリーンショット 》


 TAXIN()関数は税込価格、TAXOUT()関数は税抜価格を求める関数です。

《例》 TAXIN(926) と入力 → TAXIN(926)=1000 と表示

 税抜926円の商品の税込価格は1000円であることが分かります。

《例》 TAXOUT(1000) と入力 → TAXOUT(1000)=926 と表示

 税込1000円の商品の税抜価格は926円であることが分かります。
 税抜価格で表示された商品を複数、税込価格で表示された商品を複数購入した際に合計の税込価格を求めたいという場合には各商品の価格のTAXIN()を求める必要はなく税抜価格の合計のTAXIN()を求めると良いです。  例えば、税抜78円、税抜198円、税抜248円、税抜480円、税込270円、税込200円の商品の合計税込価格を求めたいという場合には次のようにすると良いです。

《例》 TAXIN(78+198+248+480)+270+200 と入力 → TAXIN(78+198+248+480)+270+200=1554 と表示

 これで、合計税込価格は1554円であることが分かります。

 なお、税込価格は小数点以下切り捨て、税抜価格は小数点以下切り上げで計算しているためそれ以外の方法だと±1円の誤差が発生する可能性があります。
 税率はデフォルトでは8%となっています。税率を変えたいという場合はTAXIN()関数、TAXOUT()関数の中にあるTAX=88の部分を適当な値に変えてください。

 HEX()は10進数を16進数に変換表示する関数です。

《例》
  HEX(456+&HABC) と入力
      ↓
  HEX(456+&HABC)
  &HC84 =3204
と表示

 10進数で456に16進数でABCを加算したら16進数ではC84、10進数では3204になることが分かります。
 あくまでHEX()関数は16進数への変換表示を行う関数なので等号の先は式全体を計算した際の10進数の値になり、使用されているHEX()関数の分だけ16進数表示が行われます。(この例ではHEX()関数は1つしか使用されてないため16進数は1つしか表示されてないけど下記のBIN()関数のように複数使用した場合にはその数の分だけ表示される)
 なお、HEX()関数はプチコン3号の整数型でサポートしている範囲内-21474836482147483647すべての16進数変換表示に対応しています。

 BIN()は10進数を2進数に変換表示する関数です。

《例》
  BIN(BIN(248) AND BIN(#A)) と入力
     ↓
  BIN(BIN(248) AND BIN(#A))
  &B00000010000
  &B00011111000
  &B00000010000 =16
と表示

 これは#Aを2進数で表記したら&B00000010000248を2進数で表記したら&B00011111000になり、その2数のANDを計算したものを2進数で表記したら&B00000010000となり、それは10進数では16になるというのを意味します。
 これを使えばBUTTON()関数の値と定数リテラル等を使ってボタン入力判定を行う際にどのようになるかが見た目で分かるようになります。プチコン3号では式の評価は後ろから行われるためまずは後にあるBIN(#A)の2進数への変換表示が行われその次に先にあるBIN(248)の2進数への変換表示が行われます。
 なお、2進数の変換は11bitで固定となっています。10進数が負数の場合は補数表記の2進数になり符号が1bit、仮数が10bitとなります。プチコン3号では整数型で32bitの演算が可能なのですが、ボタン入力の計算をするために使用するならば無駄に0が多すぎて視認性が悪くなります。そのため必要最小限必要な10bit1bit11bitにしました。-10242047の範囲に対応でこれ以外の数値は動作保証対象外だけどBUTTON()関数の動作を分かりやすくするためのものとして考えれば問題ない)


拡張関数ライブラリ3 について



 拡張関数ライブラリ3によってFRAC()関数、PS()関数という2つの関数が追加されます。この拡張関数ライブラリ3そのものがQSPです。

《 プログラムリスト 》


《 実行時のスクリーンショット 》


 FRAC()関数は小数を分数に変換する関数です。

《例》 FRAC(0.12) と入力 → FRAC(0.12)=3/25 と表示

 0.12を分数に変換すると3/25(25分の3)になることが分かります。

《例》 FRAC(72/84) と入力 → FRAC(72/84)=6/7 と表示

 72/84を約分すると6/7になることが分かります。

《例》 FRAC(3/4-5/6+7/8) と入力 → FRAC(3/4-5/6+7/8)=23/24 と表示

 3/4-5/6+7/8を計算すると23/24になることが分かります。

 分数に変換できる値の上限は分母が100000、分子が2147483647です。これを超える場合には分数には変換されず小数で表示されます。
 FRAC()関数を使用する場合には式全体をFRAC()関数で囲ってください。1つの式で複数のFRAC()関数を使用することはできません。

 PS()関数は計算結果を高精度に変換する関数です。

《例》 PS(PI()) と入力 → PS(PI())=3.1415926535897931 と表示

 PS()関数を使わず普通にPI()と入力した場合には3.14159と6桁しか表示されません。これは計算結果にSTR$()を使っているためです。そこで数値を誤差ゼロで文字列に変換可能な自作関数PSTR$()を使いプチコン3号の実数型で得られるすべての桁を表示するというのがPS()関数です。(文字列に変換時の丸め誤差について詳しくは
「数値にする?それとも文字にする?」を参照)
 簡易関数電卓QSP本体のリストのSTR$()の部分をPSTR$()に書き換えてしまえば常時PSTR$()による高精度表示が可能になりますが、プチコン3号の実数型の丸め誤差まで表示される(実数型の丸め誤差については「実数型の誤差による誤動作を回避するための方法」を参照)という問題もあるためSTR$()の方が結果が分かりやすい場合も多いでしょう。PS()関数を使えば高精度で結果が欲しい時のみリストを書き換えずにPSTR$()を使用できるというメリットがあります。

《 PSTR$()関数 ver.2.0 プログラムリスト 》


簡易関数電卓QSPのフルバージョンに含まれるプログラムのうちこのPSTR$()のプログラムのみQSPではありません。
 あとはすべてQSPであり、QSPの「簡易関数電卓QSP」にQSPのプログラムをいくつか追加することで機能を増やしています。

 PS()関数を使用する場合には式全体をPS()関数で囲ってください。同じく式全体を囲う必要のあるFRAC()関数と併用する場合は PS(FRAC(計算式)) のようにFRAC()関数をPS()関数で囲ってください。これによってFRAC()関数で分数で表示されない場合は高精度の小数で表示されます。


拡張関数ライブラリ4 について



 拡張関数ライブラリ4によってTMR()関数、STW()関数という2つの関数が追加されます。この拡張関数ライブラリ4そのものがQSPです。

《 プログラムリスト 》


《 実行時のスクリーンショット 》


 TMR()関数はタイマー機能を持つ関数です。

《例》 TMR(10) と入力 → 10秒のカウントダウンタイマー

 設定は秒単位で行います。5分タイマーにしたい場合は5に60を掛けてTMR(300)もしくはTMR(5*60)としてください。
 ちなみに引数には小数にも対応しています。TMR(9.5)とすれば最初の10が0.5秒の表示、後の987654321が各1秒の表示の9.5秒タイマーになります。
 カウントダウン途中でもYボタンを押せば終了できます。

 STW()関数はストップウォッチ機能を持つ関数です。

《例》 STW(0) と入力 → 0を起点としたストップウォッチ

 Aボタンでスタート、Yボタンで停止のストップウォッチです。表示の単位は「秒」、分解能は約1/60秒となっています。
 基本的にはSTW(0)のように引数0で使用することになりますが、それ以外の引数を設定するとそれを起点としたストップウォッチになります。(例えばSTW(5.67)とすれば5.67を起点するストップウォッチになる)
 F2に前回の計測結果が入っているためそれを引数に入れると前回停止したときの時間から継続した時間を計測できます。(デフォ設定ではF2だけどBボタンやXボタンを押しながらスタートするとF3F4になる)
 引数は無しで一旦停止したら自動的に前回の計測の続きから計測というような仕様も考えましたが、それだとゼロに戻す関数が必要になりリストが長くなりQSPには収まらないという問題があるだけではなくストップウォッチ専用ソフトではなため別の処理を行っている間に「前回の計測の続き」ができない場合が発生してしまうこともあるということを考慮して引数で起点を設定という仕様にしました。


拡張関数ライブラリ5 について



 拡張関数ライブラリ5によってKEYS()関数、KEYL()関数、KEYC()関数、FN()関数という4つの関数が追加されます。この拡張関数ライブラリ5そのものがQSPです。

《 プログラムリスト 》


《 実行時のスクリーンショット 》


 KEYS()関数はファンクションキーF2F5の内容をファイル名を付けてセーブする関数です。

《例》 KEYS("ABC") と入力 → ファイル名"ABC"でセーブする

 F2〜F5の内容を1つのファイルに一括セーブします。

 KEYL()関数はファンクションキーF2F5の内容をロードする関数です。

《例》 KEYL("ABC") と入力 → ファイル名"ABC"のファイルをロードする

 ロードに対応しているのはKEYS()関数でセーブされているデータのみです。

 KEYC()関数はファイルの内容をチェックする関数です。

《例》 KEYC("ABC") と入力 → ファイル名"ABC"の内容をチェックする

 ファンクションキーにロードせずに実行画面上でファイルの中身を確認するための機能です。

 KEYS()関数でセーブされたファイルは「(F2のデータ)(F3のデータ)(F4のデータ)(F5のデータ)」という感じで1つのファイルになっています。したがって、KEYC()を使いこのようになっているかどうかを確認してやればロード可能なデータか否かが分かります。また、ロード可能なデータであってもロードしたいファイルかどうかもこれで確認できるでしょう。
 ちなみには改行コードではなく矢印となっているわけですが、これはKEYC()でチェックする際に区切りの視認性を高めるためです。

 FN()関数は任意のファンクションキーにデータを書き込む関数です。

《例》 FN(2,"2+3*4") と入力 → F2"2+3*4"を書き込む

 よく使う計算式などを書き込んでおくと便利です。F1F5の範囲で設定できますが、F1は式を入力するたびに常時書き換えられるためすぐに上書きされてしまうので注意が必要です。

《 ファンクションキーの安全性 》
F1
常に上書きされるためFN()を使った任意書き込みは無意味
F2
Bボタン、Xボタンを押してない時は上書きされる
F3
Bボタンを押している時のみ上書きされる
F4
Xボタンを押している時のみ上書きされる
F5
FN()を使わない限り基本的に上書きされない

 これを見るとF3F4は上書きで消えてしまうリスクが小さいためFN()関数は活用が十分にできるでしょう。F5FN()で書き換えるか、ファンクションキーを書き換える自作関数を作らない限りは簡易関数電卓QSPを実行中に上書きされる心配はありません。そのためF5をどのように使うかが重要になってくるかもしれません。

 1つのファンクションキーには128文字まで書き込むことが可能です。128文字超256文字以下の場合は最後の128文字分が有効です。256文字超の場合は129〜256文字目が有効です。
ファイル名"ABC"のファイルをロードする。
 正しくはファンクションキーには128文字ではなく256文字まで書き込むことができるのですが、普通にファンクションキーを押した場合には128文字しか読み出すことができない仕様になっているためです。プログラム内でA$=KEY(5)KEY 5 OUT A$のように使用する場合は最初の256文字分をすべて読み出すことが可能です。

 これら4つの関数を使用すればファイル操作を自由自在に行うことが可能になり「簡易関数電卓QSP」の汎用性が飛躍的に高まるでしょう。


ゲーム「CAVE」 について



 CAVE()関数は横スクロールゲーム「CAVE」となっています。このCAVEQSPです。

《 プログラムリスト 》


《 実行時のスクリーンショット 》


 計算式入力画面でCAVE()と入力すればゲームスタートです。左端で動いているピンクの物体が自機でこれはボタンを押すと上昇し離すと下降します。画面外に出てしまうか壁にぶつかればゲームオーバーとなりスコアを表示します。

 CAVEはいわゆる「よっぱらいゲーム」「避けゲー」に属するシンプルなゲームですが、私が作るプログラムではサンプルとして用意されることが多いです。
 初出はプチコンmkIIでのGRPによるスクロールのサンプル用(詳しくは
プチコン講座 第7回を参照)として作ったものでプチコンmkIIで試作した自作のOSもどき「Petitcom OS(仮称)」のマルチタスク動作の例(詳しくはYouTubeで公開している動画を参照)として用意しました。
 プチコン3号においては入門講座においてGRPによるスクロールのサンプルとして用意「グラフック画面をスクロールさせよう」を参照)していますが、このQSP版ではそれをさらにコンパクトにしています。

 ゲーム内容は過去に作ったものとそれほど変わらずどんどん狭くなる洞窟を進むだけ(上下に大きく動けば高得点に繋がるのも従来通りの仕様)であり、この簡易関数電卓QSP版としてはスコアをCAVE()関数の戻り値にしています。そのためCAVE()+CAVE()と入力すれば2回連続でプレイし、その合算スコアを表示可能になっています。(もちろん、CAVE()*100とすればスコアを100倍したチートスコアになる)


自分でライブラリを作る方法 1



 上記の拡張関数ライブラリ1〜5やゲーム「CAVE」を見れば自作関数を作ることでどんどん機能を追加可能なことが分かるでしょう。
 では、どのようにすれば作れるかを書いていきます。

 「簡易関数電卓QSP」では戻り値が数値1つの自作関数のみ対応しています。これさえ守れば難しいことは何もありません。普通に自作関数を作るだけです。
 ただし、作った自作関数は別スロットから呼び出すことになるためDEFではなくCOMMON DEFとしてスロットを跨いだ利用ができるようにする必要があります。

 それと基本的には簡易関数電卓QSPのシステムプログラムで使われているグローバル変数(A$B$KL)をライブラリ(自作関数)内で使用すると誤動作をしてしまう可能性があるため注意が必要です。(当然自作関数内で同名のローカル変数を使うならば何の問題もない)
 ただし、以下のグローバル変数は意図的に値を書き換えてより高度なライブラリを作ることができます。詳しくは後で説明しています。

《 ライブラリ内で使用可能なグローバル変数とその意味 》
B$

計算結果
K

結果を書き込むファンクションキー
L

結果を表示するかのフラグ
L=0ならば結果は非表示になる
※ライブラリ内でB$の値を書き換えても結果には反映されないためその元となるスロット2の1行目を直接書き換える必要がある

 対応しているのが「戻り値が数値1つの自作関数」ということで何を戻り値にするかという問題が発生しそうですが、これは
上記のCAVEのようにスコアを戻り値にすれば一般的な「スコアが表示されるゲーム」であればどのようなジャンルのゲームであってもこの簡易関数電卓QSP上で動作させることが可能になります。

《 参考 》 ゲーム「CAVE」のプログラムリスト


 スコアが戻り値なのでCAVE()+CAVE()*CAVE()ならばCAVEを3回プレイして1回目と2回目のスコアを掛けてそれに3回目のスコアを加算したものが表示されます。(プチコン3号では式の後から順番に評価されるため)
 CAVE以外にも戻り値があるゲームやツールを入力画面で一度に入力した場合には同じようにその戻り値を使って演算したものを最後に表示します。

 では、簡単に数当てゲームでも作ってみましょう。スコアは特にありませんが、戻り値は当たるまでにかかった回数にでもしましょう。

《 戻り値のある関数の作成例 》
数当てゲームを行うKAZUATE()関数



 これを簡易関数電卓QSPのリストの末尾にコピペで追加し計算式入力画面でKAZUATE()と入力することで数当てゲームが開始されます。COMMON DEFを使っているため簡易関数電卓QSPがプログラムスロット0、このKAZUATE()がプログラムスロット3に入っているならばリストをコピペしなくても簡易関数電卓QSPのリストの最初にUSE 3を追加するだけでもいい)
 内容はごくシンプルな数当てゲームでコンピュータが考えたランダムな3桁の数字(100〜999)が何かを当てるだけです。違う場合はそれより大きいか小さいかというヒントを教えてくれるため普通にプレイすれば10回以内くらいで正解させて処理を終了させることができるでしょう。
 ゲーム終了時に"正解までの回数"と表示されますがKAZUATE()関数を終了してメインに処理が戻ったときに「"="+戻り値(ここでは正解までの回数)」が表示されます。"KAZUATE()"は10文字であるためX座標10に"="が表示されています。

 CAVE()+KAZUATE()と入力すれば最初に数当てゲームを実行して次にCAVEを実行しそのスコアを加算したものを最後に表示します。
 KAZUATE()+CAVE()と入力すると先にCAVEで後から数当てゲームになるのですが、CAVEは実行前にCLSが実行され数当てゲームはCLSが実行されないためCAVEが終了時に表示される"スコア"という文字だけ残ってしまうのが気になるかもしれません。

 さて、何を戻り値に設定するのかが難しいですが、基本的にはゲームならばスコアを戻り値にすれば問題ないですね。ただし、複数入力することでその順番(入力した逆順)通りに実行が可能なのですが、計算結果においては意味のある値にはならないでしょう。これはCAVEと数当てゲームのスコアを加算したものを表示したものを見れば言わんとしていることが何かが分かると思います。
 もっとも、1回の入力で1つのゲームやツールを起動させるだけならばこの問題は起きませんが、それでも「戻り値は表示する意味のある値にする必要がある」ために戻り値を何にするかで悩んでしまうかもしれません。


自分でライブラリを作る方法 2



 戻り値が数値1つの自作関数という縛りがあるためこの簡易関数電卓QSP上で動くゲームやツールを作るのは頭を悩ませることだと思います。
 戻り値が1つあればいいのでRETURN 0としてダミーの戻り値を設定すれば「戻り値を考える必要がある」という問題は解決できますが、「意味のない数字が最後に表示される(メイン画面に戻った際に"=0"というのが画面に表示されてしまう)」という問題は解決できません。

 しかし、簡易関数電卓QSPではシステム(自作関数電卓QSPのプログラム)上で戻り値がないと判断させることが可能になる方法があります。それがグローバル変数Lの活用です。
 変数Lには入力した式の文字数が入っていてこの値が0ならば式の評価が終わった際に何も実行しないという処理が可能になります。つまり、RETURN 0のようにダミーの戻り値を設定してさらにRETURNの前にL=0を入れれば最後に"="と計算結果を表示することが無くなるというわけです。
 これによって、システム上は「戻り値を設定しない」と見なされる自作関数を作ることが可能となります。

 では、実際に戻り値を設定しない自作関数を作ってみましょう。

《 戻り値を設定しない関数の作成例 》
今日の日付や曜日を表示するTODAY()関数



 これを実行すれば"今日は10月11日(日)です"のように表示したいもののみ表示して不必要なもの("="や計算結果など)は表示されないことが分かるでしょう。
 実はこの方法は拡張関数ライブラリ5のファイル操作関係では多用されている方法です。このようにL=0:RETURN 0を使えば事実上の縛りはほぼ無くなり何でも出来るようになるわけです。

 逆に、せっかく用意されている"式=計算結果"というフォーマットを活かして作りたいという場合もあるでしょう。それについても説明しておきます。

 ランダムに"大吉"とか"凶"とか表示されるUNSEI()関数を作ってみましょう。
 "式=計算結果"というフォーマットを使って表示するためには拡張関数ライブラリ3に含まれるANS命令を使うのが便利です。このANS命令は本来「"="+計算結果」を表示するべき部分に「"="+任意の文字列」を表示する命令です。

《 ANS命令を使用した関数の作成例 》
あなたの運勢を表示するUNSEI()関数



 ちなみにANS命令の中にL=0が含まれているためUNSEI()関数内にはL=0は記述していません。
 計算式入力画面でUNSEI()と入力すればUNSEI()=大吉のように結果表示が可能になります。

 実は簡易関数電卓QSPに含まれる初期のRVAL()関数は戻り値を文字列にすることが可能(文字列である戻り値をわざわざVAL()で数値化して戻しているのでバラして内包している簡易関数電卓QSPではVAL()の処理を省略しているため「戻り値を文字列にすることが可能」というよりも事実上「文字列が戻り値」といってもいいくらい)であるためANS命令を使用しなくても普通に"大吉"などを戻り値に設定するだけで同様の動作をするUNSEI()関数を作ることが可能になります。

《 戻り値を文字列にした関数の作成例 》



 RVAL()関数 ver.1.0 では、プログラムスロット2の1行目が戻り値になっているためそこを書き換えるだけで良いです。
 ただし、これは現行の簡易関数電卓QSPが RVAL()関数 ver.1.0 ベースだからこそ可能なことであり、将来的に RVAL()関数 ver.2.x ベースになった場合には正常動作しなくなるためこのような自作関数は非推奨とします。もちろん、現状の簡易関数電卓QSPで使用するならば何ら問題はないし、RVAL()関数 ver.2.x ベースの新しい簡易関数電卓QSPを作るという保証もできないためこのような自作関数を作ったり、それを発表したりするのは自由に行って貰って構いません。

 戻り値を文字列にした場合には複数の関数を入力しても最後に記述したもののみしか実行されないためその辺にも注意が必要です。これは、1回の入力で複数のものを動作させたいのでなければ何ら問題はありません。
 その点、ANS命令を用いたUNSEI()関数はUNSEI()+UNSEI()のように複数入力すればその入力した数だけ結果を表示してくれます。ただし、2つ目以降はL=0となる関係で画面左端に結果が表示されます。

 ANS命令は簡易関数電卓QSPのフォーマットで表示する場合には便利なのですが、同じ場所に何度も表示させることはできません。そのため拡張関数ライブラリ4に含まれるTMR()関数やSTW()関数ではループに入る前に表示Y座標をCSRY-1を変数に入れて値を固定させてループ内ではX座標はL MOD 25とすることでその問題を解決しています。もちろん、L MOD 25は固定的な値であるためループに入る前に変数に入れておいても問題はありません。

 というわけで実際に私が用意した拡張関数ライブラリやCAVEのリストを見れば自分でライブラリを作るための方法は粗方分かってもらえるのではないかと思います。
 ライブラリを作る時に重要なのは無限ループにならないように気を付けるということです。プチコン3号では無限ループになっても停止ボタンでいつでも簡単に停止ができますが、無限ループが発生するとその都度停止ボタンを押す必要があるため手間がかかるというだけではなく時間がかかる処理を実行しているのか、無限ループになっているのかが実行している画面からは分からないため停止ボタンを押すタイミングが難しいというのが挙げられます。

 便利なライブラリをどんどん作っていけばこの簡易関数電卓QSPは極めて便利なツールに変わることでしょう。
 


RETURN (プチコン3号プログラムのページにもどる) RETURN *MAIN (トップページにもどる)

inserted by FC2 system