yaneuraoGameScript2000で行こう!

初心者歓迎!プロのゲームプログラマーによる、×××ツクールでは物足りない人のためのゲーム制作入門

written by やねうらお


1.多人数同時プレー

麻雀にせよ何にせよ、多人数でわいわいやるゲームは何かと楽しいものです。そこに人間的に駆け引きや、会話が存在するからかも知れません。今回は、多人数プレーのゲームについて考えます。多人数プレー、コンピュータ対戦等の基礎となる考え方ですので、しっかり学んでください。

前回までの内容は、私のホームページで参照できますので、今回から参加って人も読んでみてください。すぐに追いつけますから!

さて、今回使用するゲームスクリプト(yaneuraoGameScript2000以下、ygs2k)の最新版(1.64b)は、これです。(右クリックして対象をファイルへ保存してください)


2.多人数同時プレーのゲームは、どういったプログラムになるのか?

たとえば、4人でプレーするゲームならば、プログラムは4倍になるのか?これは、No!だと思います。
一人用のゲームと、二人用のゲームとでは、違うのか?と言われると、確かに違うと思います。二人用のゲームのほうが、プログラムが少し増大しますし、プログラムに手間がかかるのは、事実だと思います。

でも、二人用のゲームは、一人用の2倍手間がかかるかというと、そうでは無いのです。四人用のゲームは、二人用のゲームの2倍手間がかかるかというと、そうでは無いのです。

なぜでしょうか?

たとえば、対戦テトリスを考えてみましょう。二人で対戦できるので、その部分は新たにプログラムが増えています。しかし、それ以外の部分(ブロックの移動や、回転と言った部分)については、一人用が二つあるに過ぎないのです。つまり、まったく同じ処理で済むわけです。PLAYER1用の処理をコピーして、PLAYER2用の処理に書き直して追加すれば、二人用になると思ったあなた、なかなかいいセンスしてると思います。ただ、単純にコピーしてもうまく動いてくれません。

なぜでしょうか?

たとえば、PLAYER1用のブロックの座標を保持しておくのに、x と yという名前の変数を使っているとします。

PLAYER2用のブロックの座標を保持するのに、同じくx と yという変数を使おうとしたら、PLAYER1のと混同してしまいます。これを何とか切り分けなければなりません。

一つの方法としては、別の名前にしてしまうことです。PLAYER1用のブロックの座標は、x1 , y1で、PLAYER2用のブロックの座標は x2 , y2というように違う変数名にすることです。

こうやって、PLAYER1用のプログラムをコピーしてきて、x1 , y1という変数名をx2 , y2と書き換えれば、PLAYER2用のプログラムも完成するような気がしますね。やや大雑把な気もしますが、これは正しいです。

ところが、PLAYERの数が増えるごとに、プログラムもそうやって増えていくのでしょうか?それに、PLAYER1用のプログラムにバグ(プログラムの誤り)が発見されて、それを修正したら、PLAYER2用も同じように修正しなければいけません。これを忘れたりしないでしょうか?そういう意味では、何だか無駄なことをしているような気にもなります。

そこで、ここでは、配列を使ってみることにします。配列は、以前出てきましたね。つまり、

int x[2],y[2];

というように配列を用意して、PLAYER1用のブロックの座標はx[0],y[0]に格納して、PLAYER2用のブロックの座標はx[1],y[1]に格納すれば、この添え字([ ] のなかの数字)の部分だけを変更すれば、いいことになります。これには、forループが使えますね。

for ( i = 0 ; i<2 ; i++) {
 y[i] ++;
}

こうやれば、y[0]とy[1]の座標がプラス1されます。実際に1ずつ増えているところを確認してみましょう。

int x[2],y[2];

void main(){
    int i;

    TextLayerOn(0,0,0);

    loop {
        ClearSecondary();
        for (i = 0 ;i<2; i++){
            y[i]++;
        }
        sprintf(string[0],"%d %d",y[0],y[1]);
        TextOut(0,string[0]);
        halt;
    }
}

もう何度もやったので、覚えてますよね?これをテキストエディタで入力して、gamestart.cというファイル名で保存して、ygs2k本体が存在するフォルダにscriptというフォルダを作成し、そのフォルダのなかに置いたのちに、ygs2k本体をダブルクリックして実行すれば良いわけです。

sprintfで、実際にy[0] , y[1]の値を文字列として変換して、それをTextOutで表示しています。永久ループになっているので、10年間ぐらいずっと眺めていても停止はしませんので(笑)、気が済んだところでウィンドゥの右上の×印をマウスで押して終了させましょう。


3.PLAYER nの処理を関数化してしまう

次に、前回まででやった、関数を使います。関数にするメリットは、見通しが良くなることです。一つの関数があまりにも大きいと、読みにくいのです。あくまで目安ですが、だいたい、ひとつの関数は長くとも30行程度におさえるのが良いと言われています。

そして、機能単位で関数にすることにしましょう。関数を書くときは、何をする関数なのか、その機能をコメントも書いておくほうが良いです。また、引数にどんな変数をとって、その変数はどんな意味で…ということもコメントとして書いておくと良いです。自分のプログラムも3歩歩けば他人のプログラムです(笑) そういう気持ちで、丁寧にコメントを書いておきましょう。

さて。

関数呼び出しのスタイルでプログラムを書くとすれば、メインプログラムは、このようになります。

void main(){
    int i;

    OnInitialize();                     //  ゲームの初期化処理
    loop {
        ClearSecondary();
        OnInput();                      //  入力処理
        for (i = 0 ; i<4 ; i++){
            OnMovePlayer(i);            //  Player i の移動処理
        }
        for (i = 0 ; i<4 ; i++){
            OnDrawPlayer(i , i*160,0);  //  Player i の描画処理。
        }
        halt;
        if (IsEnd()) break;             //  終了条件がととのったら終了
    }
    OnTerminate();                      //  終了処理
}

4というのは、4人同時プレーだからです(笑)

ここで書いてある関数のうち、OnIntialize, OnInput , OnMovePlayer , OnDrawPlayer , IsEnd , OnTerminateは、スクリプトのマニュアルを見ても載ってませんよ。なぜなら、これらの関数は、あなたがいまから作らなくてはならない関数だからです。

何をする関数かは、コメントを見ればわかると思いますが、OnMovePlayerとOnDrawPlayerについては、説明を要するでしょう。

まず、OnMovePlayerですが、これは、ループ変数 i を引数として渡しているのを見ればわかっていただけるかも知れません。つまり、i番目のPlayer(i は0〜3)の移動処理行なう関数なのです。

次に、OnDrawPlayerですが、これは、最初の引数で指定しているのは、OnMovePlayerと同じく、i 番目のPlayer( i は0〜3)の処理を行ないなさい、という意味の i です。次の i * 160 ,0というのがクセモノですが、これは、そのPLAYER用の画面をどこに描画するか、その座標を指定できるようにするのです。画面は640×480、すなわち横幅は640ですから、縦の4画面にするならば、ひとつの横幅は160。だから、160を掛けているというわけです。

とは言っても、OnDrawPlayerの関数のなかで、この渡された座標に基づいて描画しなければ何の意味もありません。

読者のなかには、どうしてOnDrawPlayerをOnMovePlayerの直後に持ってこないのか、そうすればforは一つで済むのではないか?と言う方もおられるかも知れません。それは、それで正しいと思うのですが、移動処理と描画とは基本的には別の処理ですし、プレイヤ同士が相互干渉するゲームであれば(たとえば、PLAYER1のウィンドゥ画面に、PLAYER2が侵入してくるなどであれば)、PLAYER1の画面描画を行なうためには、他のPLAYERの位置が完全に確定している(すなわち、移動処理が終了している)必要があるのです。そこで、移動と描画は分離しています。

あと、OnInitialize/OnTerminateですが、これは、そのゲーム用の初期化/終了処理を書きます。具体的には、画像ファイルを読み込んだり、サウンドファイルを読み込んだりと、そういうことをやります。

最後に、IsEndは、終了条件のチェック用で、ブロックが積みあがったら終了なのか、どちらかが敵にやられたら終了なのか、それはいまのところ、わかりませんが(笑) ともかく、このIsEnd関数のなかで、終了条件が整ったら非0を返すようにプログラムすれば、このメインのループからbreakで抜けることとなり、ゲームが終了するというわけです。このように関数化しなくても良いのですが、終了条件は一般のゲームでは結構複雑なので、このように終了条件だけで関数化したほうが良いです。

これがすべてです。多人数同時プレーのゲームの骨格は、これがすべてなのです。

これで何のゲームが動くの?とは聞かないでください(笑) どんなゲームも動きません(笑) あくまで骨格だけなのです。これを何のゲームにするかは、すべてあなた次第なのです。そういう意味では、どんなゲームにでもなる、どんな応用も利く、非常に重要な部分だと言えるでしょう。


4.簡単なゲームを作ってみる

あのー、実に言い訳がましくなりますが、今回の講座のためにいくつかゲームを考えていたのです。Joy Stick、最大16本同時に使える、超対戦型ゲームを用意しようと思ってたんです。でも、これ、結構規模がでかいんです(笑) JoyStickのygs2k用のライブラリ作っていたら、時間がなくなってしまいました。

説明したいのは、4人同時に動く、4人同時に動かせる、の部分です。そういう意味ではキーボードでもいいのかな、と思ったのです。というか、JoyStick4本も持ってる人、そんないないですね(笑) だもんで、JoyStick対応は、読者様への宿題ということにしておきます。(私のホームページに、16本のJoyStickから入力を得るためのygs2k用ライブラリを用意しておきますので活用してみてください)

そこで、まず、キーボードで4人同時に動かす、の部分をやってみることにします。割り当てとしては、テンキーの2,4,6,8、Enterそれから、カーソルキーの上下左右,右CTRL、そして、W・Z・A・S,スペース,それに、I・M・J・K,Enterで、4人分確保ですね(笑)

とりあえず、キー入力部分と、簡単な表示部分を追加したのが、これです。解凍するとscriptフォルダが出来ると思うので、そのなかのファイルを、ygs2k本体の存在するフォルダのscriptフォルダに移動させたのちに、ygs2k本体を実行してください。

実行すると、こんな画面になるはずです。

キーボードで、それぞれのを移動させることが出来るので、それぞれが動くことを確認してみてください。

それほど目新しいことはやっていないのですが、いくつか解説せねばなりません。

// ------- キー入力アシスト関数
int IsKeyLeft(int nPlayer){
// nPlayerの左キーが押されたら非0を返す
 alt {
 case nPlayer==0 : return IsPushKey(0x1E); // DIK_A
 case nPlayer==1 : return IsPushKey(0x24); // DIK_J
 case nPlayer==2 : return IsPushKey(0xCB); // DIK_LEFT
 case nPlayer==3 : return IsPushKey(0x4B); // DIK_NUMPAD4
 };
}

これは、コメントにもあるように、あるプレイヤの左のキーに相当するキーが押されたかを判定している部分です。if 文をならべてもいいのですが、alt 〜case という選択構文(これはC言語には存在しない。ygs2k専用)がありますので、それで分岐させています。

 alt {
 case nPlayer==0 : return IsPushKey(0x1E); // DIK_A

たとえば、この部分は、nPlayerが0のときは、return IsPushKey(0x1E); を実行しなさい、という意味です。

ところで、このIsPushKeyのあとにある、0x1Eとは何でしょうか?始めてご覧になる方にとっては謎の文字列だとは思うのですが、0xで始まるのは、16進数、要するに数字の一種です。キーボードのそれぞれのキーに、それぞれの定数(=数字)が割り当てられているのです。その割り当てられている定数を指定してやれば、そのキーが押されたかどうかが判定できるのです。じゃあ、その定数表はどこを見ればわかるのか?というと、スクリプトマニュアルのほうに書いてあるのです。たとえば、DIK_A(DirectInputのKeyでAに相当するもの)ならば、0x1Eです。だから、Aのキーが押されたかどうかを判定するためには、このように0x1Eと書きます。

もう一つ、ややこしそうなところを説明します。それは、OnMovePlayerです。

void OnMovePlayer(int nPlayer){
/*
プレイヤnPlayer(0〜3)の移動処理
*/
 if ((g_anX[nPlayer]>=16) && IsKeyLeft(nPlayer)) {
  g_anX[nPlayer] = g_anX[nPlayer] - 16;
 }
 if ((g_anX[nPlayer]<=16*8) && IsKeyRight(nPlayer)) {
  g_anX[nPlayer] = g_anX[nPlayer] + 16;
 }
 if ((g_anY[nPlayer]>=32) && IsKeyUp(nPlayer)) {
  g_anY[nPlayer] = g_anY[nPlayer] - 16;
 }
 if ((g_anY[nPlayer]<=16*28) && IsKeyDown(nPlayer)) {
  g_anY[nPlayer] = g_anY[nPlayer] + 16;
 }
}

g_anX , g_anY ってのは、それぞれのプレイヤーのX座標,Y座標を保持している配列です。以前、少しだけ説明しましたが、ハンガリー記法と言って、グローバルな変数(関数のなかに無い変数)の頭には、g_ をつけるだとか、配列ならば配列だとわかるように、a ( 配列を意味するarray のaです)をつけるだけとか、整数ならば n で始めるだとか、そういうのを実践しているので、変数名が少し長いですが、こうしておけば、不意に関数内の変数名とグローバルな変数名とが重複したりする事故を招かずに済みます。(こういうバグは見つけにくいのです)

たとえば、こういうプログラムを書いたとします。

int MAX = 10;
void main( ){
 int MAX;
   ・・・
 MAX = 20;
}

MAX = 20;の部分では、グローバル変数(1行目にある)MAXに20を代入しているつもりなのに、実際は、ローカル変数(3行目にある)MAXに20が代入されてしまいます。変数を探すときには、内側のブロックにあるものが優先されるからです。そこで、こういう事態を避けるために、グローバル変数とローカル変数は何らかの区別をしたほうが良いだとか、そういう意見があるのです。

まあ、変数の命名規則は、絶対にこうしなさいというものでは無いですし、あまり固執しても仕方ないです。こういう表現の仕方もあるよ、ということで覚えておいてください。

それはともかく、先のプログラムの >= 16の部分は何をやっているのでしょうか?そうです。左へ移動するためのキーがおされたときには、X座標を16引くのですが、X座標がマイナスの領域まで行ってしまわないように、16以上でなければX座標からはマイナス16しない(すなわちXは0未満にはならない)ようにしているのです。他の3つについても同様です。移動範囲を制限するためのものです。

さて、ここから、このブロックを落ちるように変更して、テトリスやぷよぷよのような落ちモノ系のゲームにすることも出来るでしょう。

ygs2kを使えば、テトリスぐらいなら、ものの数時間で作れてしまいます。(実際に、私のホームページのygs2k関連リンクに、いろいろゲームがありますので、他の人のものも参考にしてみてください) ただ、他のゲームをパクってもあまり面白くないので、ここではちょっと変わったものを作ってみることにしましょう。


5.ライフゲーム

そのゲームとは、ライフゲームです。あまりにも有名なので、ご存知の方も結構おられると思いますが、ご存知でない方のために、簡単に説明します。ライフゲームとは、生存ゲームでして、ルールは、以下のようになっています。

ライフゲームの世界は碁盤のようにマス目が並んだものです。そのマス目は「セル」と呼ばれます。セル一つに、一つの「生命」が存在できます。だから、セルは、生命の2つの状態(生と死)があります。(普通、生きているセルのみを表示します)

この世界のなかで、進化は、時刻に従って進んでいきます。時刻 t+1 におけるセルの状態は、時刻 t の状態と、そのセルを取り囲む8つ(東、西、南、北、北東、南東、北西、および南西)のセルの状態に依存して決定します。

セルの現在の状態 周囲の■セルの数 セルの次の状態
生きている 2もしくは3 生きている
それ以外 死滅
死んでいる 3 誕生
それ以外 死滅

これは、一種の人口モデルとして周囲に人が多すぎると、食料危機で死亡し、少なすぎても死滅してしまうと、まあそういう風にもとらえることができます。この規則にしたがって、画面を表示させてみるとどうでしょうか。

試しにやってみました。これです。実行すると、さきほどの画面になりますが、スペースキー等を押せば、そのプレイヤの場所にFペントミノと呼ばれる(ときにRペントミノとも呼ばれる)、このようなパターン

を置きます。このパターンは、ライフゲームの基本パターンの一種とされているもので、ここから複雑な模様が生まれます。まあ、実際にやってみられるのが良いでしょう。一応、色分けしてあります。新たに誕生したセルは赤、周囲に2つ生存セルがあって存続して生きている場合は青、3つの場合は緑としています。画面は、世代交代を繰り返し、こんな感じになります。


6.プログラムについての解説

単純なプログラムですが、いろんなテクニックを使っているので、順番に解説します。

// フィールドを表す変数
int g_aanField[40 * 30];

フィールド(セル全体)は、40×30の大きさを持っています。画面は640×480ドットですので、ひとつのセルを16×16ドットで現すならば40×30セルというわけです。ところが、これを二次元配列

// フィールドを表す変数
int g_aanField[40][30];

として確保したいのですが、ygs2kは2次元配列をサポートしていません。まあ、言ってみれば手抜きなんですが(笑)、そこで、上のように 40 * 30だけ配列を確保して、

g_aanField[x][y]と書く代わりに、g_aanField[x + y * 40]というように書くことにします。これで、擬似的に2次元配列が実現できます。

// 8近傍の生命数を求める
n = (aanField[ ((x-1) %% 40) + ((y-1) %% 30)*40]!=0)
  + (aanField[ ((x ) %% 40) + ((y-1) %% 30)*40]!=0)
   (以下略)

8近傍のセルを調べて、生きているセルの数を足し合わせる処理をやっています。%% 40だとか、%%30というのは何でしょうか?これは、画面が右端と左端、上端と下端を擬似的に接続するためのトリックなのです。具体的には、x , y が0のとき、x - 1は-1(左端のさらに左)となってしまい、配列として用意されている外部へアクセスしてしまいます。このような、配列として用意した外へアクセスした場合、最悪の場合だとメモリエラーでプログラム自体が止まってしまいます。そこで、マイナスならば、カウントしない、という方法も考えられます。それでもいいのですが、ライフゲームは右端と左端、上端と下端がくっついているほうが面白いので、-1 は39を現すものと出来れば、これで、左右の端はつながったことになります。

スクリプトのマニュアルのほうも見ていただければ良いと思うのですが、%%は、剰余演算子で、割った余りを返します。40 %% 40 は 0 , 41 %% 40は 1 となります。逆に、マイナスの場合、 -1 %% 40 は39 , -2 %% 40 は38というように、なります。こういう処理をするのに結構便利なので、活用してみると良いでしょう。

また、!=0というのは、非0ならば1とするために書いています。というのも、セルに色をつけるため、aanFieldの値は、そのセルが生きている場合、1〜3の値をとりうるからです。8近傍の生きているセルの数をカウントしなければならないので、生きているならば、1、死んでいるならば0になって欲しいのです。そこで、!=0が必要になってくるわけです。

もちろん、この部分を見苦しいから関数化して、(x,y)にセルが存在するかを調べるような関数を作って、すっきりまとめるというのも、いいやり方です。どちらが正しいか、ということは無いと思います。ある程度の規模になってきたら関数化すると、そういう心構えでいいと思います。

あと、次の世代にする関数の冒頭で、

// フィールドをまるごとコピー
for (n = 0;n<30*40;n++){
 aanField[n] = g_aanField[n];
}

このような処理があります。これは何のために必要なのでしょうか?この手のプログラムを書いた経験がないと、わかりにくいかも知れませんが、もしバックアップ(コピー)をとらずに直接、フィールドを書き換えていくと、まずいことになるのです。

つまり、更新は、左上から右へ向かって行なっていきます。右端に到達したら1段下の左端からまた右端へ向かって、というように次の世代へと更新していくのですが、周囲8近傍を調べるときに、バックアップをとらずに直接フィールドを更新していると、そのセルの上のラインや左にあるセルは既に次の世代になっているのです。現在のセルの状態に応じて、次の世代のセルの状態が決まるゲームなのに、すでに上のラインや左にあるセルが次の世代になっているのでは困るのです。

そこで、現在のセルの状態をすべて、別の変数aanFieldにバックアップして、その変数で8近傍を調べながらg_aanFieldのほうを次の世代のセルの状態へと更新するというわけです。

この手法は、画像のフィルタ処理などでも行ないます。現在の状態に応じて、次回の状態が決まるタイプの処理では、このようにバックアップが必要なことがよくあります。


7.ゲームとして仕上げる

さて、これをどうやってゲームとして仕上げるかです。この部分を、私はこれを読んでおられるみなさんへの宿題としようと思うのです。

わわわ、待ってください。石は投げないでください(笑)

「4人同時プレー対戦型ライフゲーム」という前代未聞の名作を生み出すビッグチャンスです!!それは、あなた次第なのです。そもそも、ここは既存のゲームを遊ぶための講座ではないのです。自分で作るための講座なのです。そういう意味も含めて、ユニセフのようなやねうらお(一部、誇張あり)が、みなさんの楽しみを奪ってしまわないように、わざと画竜点睛を欠いたと、そういうことです。

しかし、いくつかのヒントをちりばめておきます

☆ スコアを導入する

対戦型ゲームであるからには、スコアがなければ何を競っていいのか、わかりません。スコアを導入してみましょう。たとえば、いままで生存していたセルの数の合計でも良いでしょう。新たに誕生したセルの数でも良いでしょう。

☆ セルの大きさを調整する

一般に、ライフゲームのセルは小さいほど華やかで綺麗なものになります。そういう意味では小さくするのは常にある一つの手段ですが、それをどうやって統御するのかということを考えると、逆に大きなほうがゲームになるということもあります。たとえばフィールドが広すぎたら、ぷよぷよというゲームは誕生していなかったでしょうし、そこを調整して始めてゲームになることも多々あるのです。

☆ 生成消滅の条件を変更できるようにする

たとえば氷河期には、食べ物がなくなるから、生存条件が厳しくなるだとか、そういう風に、季節や時代の移り変わりを導入することで、ゲームに変化が生まれてきます。また、実際に、フィールドに食べ物を導入して、食べ物のまわりでは、もっと生存条件が甘くなるだとか、そういうアイテムを導入すると面白いでしょう。

あるいは、突然変異して、通常の生存条件とは異なる変種が生まれるなどというのも面白いでしょう。それを柵などを作ってうまく誘導して、相手のフィールドに送り込むだとか、そういうことが出来るようになると、戦略性が生まれてきます。

以上は、そんなに難しくないので、実際にやってみられると良いでしょう。面白いゲームに仕上がったら、是非ともやねうらおにメールください。


一応、参考用に、セルの大きさを半分にして、スコア表示をつけたものを紹介します。

スコアは、自分のフィールドに生存しているセルの数によって増加していきますが、このへんの条件を変えてみたり、どのプレイヤかが何万点に達成したらその時点で終了するだとか、そういう部分を追加すれば競技性が生まれてくると思います。

操作性についても、押しっぱなしで移動するようにしたほうが良いように思ったので、IsPushKeyという関数の代わりにIsPressKeyという関数を呼び出すように変更してみました。こちらは、キーを押しっぱなしでも“押した”と判定されます。


8.次回予告とおまけ

その他、私のホームページのほうで、ygs2k関連のリンクで、ネットワークを扱えるライブラリなども公開されているので、そういうのも活用してみると、お手軽にネットワークゲームが作れたりします。今回の内容を応用して、やってみると良いでしょう。

ところで、次回はノベルの作りかたです。それも、サンプルごときではありません。本物です。市販品です。それを大解剖します。

PhotoShop等で絵を描いておられる方ならわかっていただけると思うのですが、画像は不透明度(α情報)を持っていることがあります。不透明度を持っている画像を、表示したりするにはどうすれば良いのでしょうか?

それぞれのゲームメーカーが、それぞれ独自の方法でやっているのだと思います。(私の方法については私のホームページのプログラム日記から抜粋した資料 があるので、興味のある人は読んでみてください。私は、この画像形式をYGA形式と呼んでいます)

それから、このYGA画像形式に対するsusieのプラグインをLuciferさんに作っていただきました。これです。

WAFFLEの作品では、『HAPPYほたる荘』(2000年12月発売)、『蒼き大地』(2001年4月発売予定)で使っています。前回の、yanePackExで圧縮データを解凍したのちに、このプラグインを利用することで…ぐふふなのです。これ以上は、私のクチからは言えませんが(笑)

次回は、ゲームスクリプトを大幅拡張し、このYGA形式の画像を表示したり、複雑なエフェクトをかけたりできるようにしますので、ご期待ください。

画面は『蒼き大地』(WAFFLE制作 2001年4月発売予定)のゲーム画面より

こんなゲームが誰でも作れるようになるんです!!しかもフリー!!使用制限一切無し!まあ、絵とシナリオは自分で描かなきゃなりませんけど^^;

他のゲーム会社に勤めるプログラマの友達連中からは「オレ、仕事あぶれるからやめてくれ」だとか、冗談とも本気ともわからないことを言われていますが(笑) ともかく、頑張りますので、ユニセフやねうらお(誰がやねん)に、決して石は投げないでください(笑)

では、今回はこのへんで。