mfst Ver 0.4 リファレンス マニュアル


目次

凡例
コメント
シナリオ
大域変数宣言
static変数番号
シーン
シーン引数, シーン内static変数宣言, シーン内変数宣言,
サブルーチン,
コマンド
write, 代入, picture, layer, eraselayer, paint, erasepaint, cls, exit, wait, loadfile,
if, for, while, do, switch, choice, break, continue, jump, call, return, goto, ラベル
rand, rand, from, id, 演算子
その他
画像のレイヤ構造, 文字列

凡例

他で定義している言葉は説明している部分へリンクを貼ってあります。 また、太い枠は切取れば実行できる例で、細い枠は部分的な例や間違った例です。
例:
この枠に囲まれた例は シナリオとして実行できます。
例:
この枠に囲まれた例は実行できません。 部分的な例や間違った例です。

コメント

コメントは「//」で始まり、その行の行末までコメントとなります。
例:
a = a + 1; // ここから先、行末までがコメントです // 先頭からコメントでも構いません a // 文字列を途中で分断しなければ、 // コメントは任意の位置に書くことができます = a + 1;

シナリオ

構文:
[ 大域変数宣言 ] [ シーン [ シーンまたはサブルーチン ... ] ]
シナリオは大域変数宣言シーンおよびサブルーチンの記述から成り立っています。 シナリオは一番最初に書かれたシーンから実行されます。
またサブルーチンの前には少なくとも1つのシーンが必要です。 (つまりシナリオの先頭がいきなりサブルーチンで始まってはいけない、ということ)。 それ以外はシーンサブルーチンの記述する順番に制約はありません。
例:
int a = 3; // 大域変数の宣言 scene 最初のシーン () { // このシーンから実行される jump 最後のシーン(); } sub サブルーチンA () { // サブルーチン } scene 最後のシーン() { call サブルーチンA(); }
悪い例:
int a = 3; // 大域変数の宣言 sub サブルーチンA () { // エラー:サブルーチンの前に1つもシーンがないのはダメ } scene 最初のシーン () { } scene 最後のシーン() { }

大域変数宣言

構文:
int 変数名 [ = ] [ , 変数名 [ = ] ... ] ;
static [ static変数番号 ] int 変数名 [ =  ] ;
シナリオの先頭で大域変数を宣言します。 大域変数は全てのシーンサブルーチンで利用できます。
変数名は、最初の1文字は英文字・漢字ひらがなで、 2文字目以降は英文字・漢字ひらがな・数字・_を利用できます。
例:
int a = 3, b; // 複数まとめて宣言できます int c = a + 3; // 初期値には他の変数も参照できます static 10 int d; // 変数番号10でdを宣言 static 6 int e = 3; // 変数番号6でeを初期値3で宣言 static int f = 4; // 変数番号はなくてもよい
悪い例:
static 10 int a, b; // 変数番号を指定する場合は1度に1つしか宣言できない

変数番号

static変数(大域変数シーン内static変数)は、 HPNV Senario Compilerにおける変数番号指定することができます。
mfstは0から順番に変数番号を使用していくので、 若い変数番号を使用するときはシナリオの先頭で定義してください。 ただし、大きい変数番号を使用すると 変数番号として利用できる数が減ってしまいます。
static変数が利用する最大の変数番号 + 最も数の多いシーン内変数の数の上限が 92個です。 (「最も数の多いシーン内変数の数」とは、例えば シーン内変数を10個利用しているシーンと、 シーン内変数を5個利用しているシーンがあるなら 「10個」ということです。10+5=15個ではありません)

シーン

構文:
scene シーン名( [ シーン引数 ] ) { [シーン内static変数宣言 ... ] [シーン内変数宣言 ... ] [ ... ] }
シーンの最後には暗黙のexitがあり、シーンの最後まで実行されると シナリオはそこで終了します。
なお、シーン内では、関数fromが使えます。 関数fromは、このシーンに来る前のシーンのid番号を返します。 シーンのid番号は関数idで調べることができます。
シーン名は、最初の1文字は英文字・漢字ひらがなで、 2文字目以降は英文字・漢字ひらがな・数字・_を利用できます。
例:
scene firstScene ( int a ) { write( "引数 a=", a ); } // ここまで来るとシナリオが終了します scene secondScene () { // 次のシーンが実行されたりはしません write( "ここには来ません" ); }

シーン引数

構文:
(何も書かない)
void
int 変数名 [, int 変数名 ... ]
シーン引数は最大で3個です(いまのところ)。
例:
scene シーン1( int a, int b, int c ) { } scene シーン2() { } scene シーン3( void ) { }
悪い例:
scene シーン4( int a, b ) { // bの前に「int」が抜けています } scene シーン5( int a=3 ) { // シーン引数に初期値は書けません }

シーン内static変数宣言

構文:
static [ static変数番号 ] int 変数名 [ = ];
大域変数と似ていますが、シーン内でしか参照できません。
初期値のはシナリオを実行開始直後に1回だけ実行されます。
大域変数との使い分けですが、 主人公の状態については大域変数を使い、 場面毎の状態(明りがついている/消えている、とか)はシーン内static変数を使うと 良いと思います。

注意: シーン内static変数はシーンの初実行時ではなく、 シナリオの最初にまとめて初期化されます。 したがって、 シーン引数を使って初期化しようとすると、めちゃくちゃな値になります。

例:
static 10 int d; // 変数番号10でdを宣言 static int e = d; // 変数番号を指定せず、eをdの値で初期化
悪い例:
static int a, b; // 変数番号を指定する場合は1度に1つしか宣言できない
悪い例:
scene AAA ( int x ) { static book = x; // コンパイルはできますが // めちゃくちゃな値で初期化されます }

シーン内変数宣言

構文:
int 変数名 [ = ];
シーン内static変数と違い、 がある場合は毎回初期化されます。 また、一度シーンを出ると変数の内容は壊れます。 C言語の自動変数(staticをつけないローカル変数)と同じです。
例:
int a, b = 10; int c = b;

サブルーチン

sub サブルーチン名( ) { [ [...] ] } サブルーチンの最後には暗黙のreturnがあり、サブルーチンの最後まで実行されると サブルーチンをcallした場所に戻ります。 サブルーチンには引数や局所変数はありません。

サブルーチン名は、最初の1文字は英文字・漢字ひらがなで、 2文字目以降は英文字・漢字ひらがな・数字・_を利用できます。

例:
scene シーン ( ) { write("まずこれが表示され"); call サブ(); write("最後にこれが表示され終了"); } scene サブ () { write( "2番目にここが表示され" ); }

コマンド

コマンドには、 write, 代入, picture, layer, eraselayer, paint, erasepaint, loadfile, cls, exit, wait があります。

write

構文:
write( 文字列 or [ , 文字列 or ... ] );
文字列や数値を表示します。 表示後、画面のタップ、またはボタンを押されるまで実行が止まります。
例:
scene aaa ( int a ) { write( "あいう", a ); // この行はすぐに表示されますが write( a * 34 ); // タップされるまでこの行は表示されません }

代入

構文:
変数 = ;
変数 += ;
変数 -= ;
変数 *= ;
変数 /= ;
変数++;
変数--;
変数に式の値を代入(演算)します。
C言語と違い、左辺は値を持ちません。
例:
a = 3; b = 2 * ( a + 5 ) * rand( 3 ); a++; a += b * 2;
悪い例:
a = b = 2; // 左辺が値を持たないので続けられません if ( a-- ) { // これも同様で、使えません write( "aにbを代入した結果が0でない"); } --b; // 前置形式はありません

picture

構文:
picture( 文字列, ) ;
picture( 文字列 ) ;
文字列で示されたBMPファイルを、 の方法で背景像を表示します。 160x120のBMPファイルを表示できます。 の値により以下のエフェクトがかかります。
-1 表示しない
0 一瞬で表示
1〜5 エフェクトをかけて表示
例:
picture( "aaa.bmp", 5 ); picture( "bbb.bmp", a - b ); picture( "ccc.bmp" );

layer

構文:
layer( 整数, 文字列, 1, 2, 3 ) ;
整数はレイヤ番号を意味し、1または2が使えます。 文字列のBMPファイルを、座標( 1, 2 )に、エフェクト 3で表示します。 エフェクトの番号の意味はpictureと同じです。 なお、BMPファイルの紫色(R=255, G=0, B=255)の部分は透明になり 下の画像が透けて見えます。
例:
for( a = 0; a < 100; a++ ) { layer( 1, "aaa.bmp", x, y, 0 ); layer( 2, "bbb.bmp", 100-x, y, 0 ); }

eraselayer

構文:
eraselayer( 整数, ) ;
整数はレイヤ番号を意味し、1または2が使えます。 で示すエフェクトを用いて、レイヤ画像を消去します。 エフェクトの番号の意味はpictureと同じです。
例:
eraselayer( 1, 4 );

paint

構文:
paint( 文字列, ) ;
で示すエフェクトで 文字列(6ケタの16進数でRGB値を表現)で示す色を使い背景画像を塗り潰します。 エフェクトの番号の意味はpictureと同じです。
例:
paint( "00FF00", 3 ); // エフェクト3で緑色に塗り潰します

erasepaint

構文:
erasepaint( );
で示すエフェクトで背景画像を消去します。 エフェクトの番号の意味はpictureと同じです。
例:
erasepaint( 4 );

cls

構文:
cls();
文字の表示領域を消去します。

exit

構文:
exit();
シナリオを終了します。シナリオファイル中にいくつ存在してもかまいません。 また、 シーンの最後には暗黙のexitが書かれているとして動作します。
例:
scene aaa () { choice ( "どうしますか?" ) { case "終了する" exit(); // ここに来るとシナリオは終了します break; case "まだ続ける" break; } write("まだ続けます"); // シーンの最後では自動的にexit()されます } scene bbb () { // したがってこのシーンは実行されません write("でもここには来ません"); }

wait

構文:
wait();
タップまたはボタンの押下を待ちます。 rand関数と組み合わせて使うと、タップした位置を知ることができます。

loadfile

構文:
loadfile( 文字列 )
他のシナリオで自動的に作成されたセーブデータを読み込みます。
static変数は同じ番号に読み込まれるので、 大域変数宣言シーン内static変数宣言で変数を宣言するとき、 static変数番号を用いて変数番号を指定すると良いでしょう。
ちなみに、セーブはできません。
例:
static 10 int age = 20; static 5 int money = 1000; scene 最初期シーン() { choice( "前作のシナリオのデータをロードしますか?" ) { case "ロードする": loadfile( "前作シナリオファイル名" ); break; case "ロードしない": break; } jump 開始シーン(); } scene 開始シーン() { write("あなたは...."); }

if, for, while, do, switch, choice, jump, call, return, goto, ラベルおよび 全てのコマンドが文です。

if

構文:
if ( ) { }
if ( ) { } else { }
if ( ) { } else if ( ) { } ...
C言語のifと似ていますが、{}を省略することはできません。 C言語と同じで、 が0以外のとき、直後のstatementを実行し、 が0の時はelse以降のstatementを実行します。
例:
if ( a == 3 ) { write( "aの値は", a, "です" ); } if ( a ) { write( "aは0以外の値です" ); }
悪い例:
if ( a == 4 ) write("あああ"); // {}は省略できません if ( write("いいい") ) { // 式ではありません write( "ううう" ); }

for

構文:
for( [コマンド [, ...]] ; ; [コマンド [, ... ]] ) { }
C言語のforと似ていますが、{}を省略することはできません。 C言語と同じで、 は0のとき偽、0以外の時真となります。
例:
scene aaa() { int a, b; for( a=0, b=2; b<10; b++ ) { // ","で区切ればコマンドを並べられます write( "a=", a, " b=", b ); // (Cと同じです) } for( ; a<10; a++ ) { // 不要ならコマンドを省略できます write( "a=", a, " b=", b ); } }

while

構文:
while( ) { }
C言語のwhileと似ていますが、{}を省略できません。 C言語と同じで、 は0のとき偽、0以外の時真となります。
例:
scene aaa () { int a = 5; while ( a ) { write("a=", a ); a--; }

do

構文:
do { } while( );
C言語のdoと似ていますが、{}を省略できません。 C言語と同じで、 は0のとき偽、0以外の時真となります。
例:
a = 10; do { a--; } while ( a > 0 );

switch

構文:
switch( ) {
case :

[ break; ]
...
default:

[ break; ] }
C言語のswitchと似ていますが、caseに値だけでなくを書くことができます。
例:
switch( a ) { case b: write("aとbは等しいです"); break; case c+4: write("aはc+4と等しいです"); // Cと同じで、breakがないと、次のcaseも実行されます case rand(10): write( "aはc+4または10以下の乱数と等しいです" ); break; default: write("その他です"); }

choice

構文:
choice( 文字列 ) {
case 文字列:
statement [ break; ] case 文字列:
statement [ break; ] [case 文字列:
statement [ break; ] ] }
2択または3択の質問するウィンドウを開き、ユーザーの選択を求めます。 最初の文字列が、質問ウィンドウのタイトルです。 caseの文字列が選択肢で、この選択肢が選ばれると case以降に書いたstatementがbreakまで実行されます。 caseは2個または3個です。1個や4個以上はエラーになります。 構文や動作ははswitchと似ています。
例:
choice ("AとBのどちらを取りますか?") { case "AとBの両方": a = 1; // breakが無ければ次のcaseも実行されます。 case "Bだけ": b = 1; break; case "どちらも取らない": jump 次のシーン(); }

break

while, for, do, switch, choiceの中で使用できます。 使用したブロックを抜けます。
例:
for( a=0; a<10; a++ ) { if ( a==4 ) { break; } }

continue

while, for, doの中で使用できます。次のループに移ります。
例:
while( a > 10 ) { if ( b < 0 ) { a++; continue; } }

jump

構文:
jump シーン名( シーン引数 );
シーンまたはラベルにジャンプします シーンにジャンプするときは、 シーン引数の数が合っていないとエラーになります。
例:
scene aaa () { a = 3; jump bbb( a ); } scene bbb ( int x ) { write( "引数の値は", x ); }
悪い例:
scene aaa () { a = 3; jump bbb( ); // シーン引数の数が合っていません } scene bbb ( int x ) { write( "引数の値は", x ); }

call

構文:
call サブルーチン名() ;
サブルーチンコールします。
()は、将来、サブルーチンに引数を作れるかもしれないので、 互換性の確保のためにつけてあります...
例:
scene A () { call 表示() ; } sub 表示 () { write("あああ"); return; }

return

構文:
return ;
サブルーチンから元に戻ります。 サブルーチンの最後には暗黙のreturnがあるので、 サブルーチンの最後のreturnは省略してもかまいません。
例:
scene A() { call subA() ; call subB() ; } sub subA() { write("サブルーチンAです"); return; } sub subB() { write("サブルーチンBです"); } // 最後のreturnは省略しても構いません

goto

構文:
goto ラベル
文字列ラベルにジャンプします。 ラベルを書けば、任意の場所にgotoできますが、 ループの中や他のシーンへのgotoは避けた方が良いでしょう (今のところスタックがないので動作はおかしくなりませんが、 変数が初期化されていないので値がヘンになります。 将来、スタックを使えるようになったら、暴走の原因になります)。

ラベル

構文:
:ラベル名
任意の場所にgotoするためのラベルです。
例:
scene aaa() { :もう一度 choice("どうする?") { case "まだやる": goto "もう一度"; case "もうやめる": exit(); } }

式(関数)

整数、変数、関数および、これらの組み合わせが式です。

rand

構文:
rand( )
0以上以下の値となる乱数を返す関数です。
例:
a = rand( 10 );

rect

構文:
rect( x1, y1, x2, y2 )
wait時にタップした座標が(x1,y1)〜(x2,y2)の中なら1を返し、 それ以外では0を返す関数です。
例:
wait(); if ( rect( 10, 10, 100, 100 ) ) { write( "(10,10)-(100,100)をタップしました"); }

from

構文:
from()
このシーンjumpしてくる前のシーンidを返す関数です。 シナリオ開始直後のシーン(どこからもjumpしてきていない)では-1を返します。 idと組み合わせて利用します。

id

構文:
id(シーン名)
シーンのidを返す関数です。idは非負の整数です。 from()と組み合わせて利用します。
例:
scene aaa () { switch( from() ) { case -1: write("シナリオ開始直後です"); case id(bbb): write("bbbから来ました"); break; case id(ccc): write("cccから来ました"); break; default: write("どこから来たか解りません"); } }

演算子

演算子には、+ , - , * , / , < , <= , == , >= , > , ! , && , ||と、()があります。 演算子の結び付きの強さは、下の表のようになっています。
最も強い ( )
  符号の-, +
  !
  *, /
  +, -
  <= , <, ==, >, >=
  &&
最も弱い ||
例:
x = a + ( b - 3 ); y = a || 2 < b && b > 10;

その他


画像レイヤ構造

画像のレイヤ構造は、一番上からレイヤ2、レイヤ1、背景となっています。

文字列

""でくくる。"自体は...表現できません。 (そういえば忘れてた)
例:
"abc" "あいう"

mfst ( MF Senario Translator ver 0.4b )
2004年1月10日
http://www.newfs.to/m_yuuki/
結城 見