文章を書くときは「です・ます調」か「である・だ調」のどちらに統一するか,あらかじめ決めてかからなければいけない。ちなみに,この日記は「である・だ調」だが,日経ソフトウエア誌に連載している「C言語で始めるプログラミングの基礎」は「です・ます調」を使っている。しかし,「である・だ調」を使っていても,読者に語りかける部分だけが無意識に「です」になったり,間違った使い方かもしれないが「です・ます調」のなかに「だ」を使って,「ダ,ダ,ダー」といきおいをつけるたくなることもある。

 さて,こうしろうの妹,ほのちゃんは11月3日で5歳になるのだが,「です・ます」がまだうまく言えない。「す」の音で空気が抜けて,「ふ」になってしまうのである。さすがにもう5歳だから,ふざけてやっているのかと思い「ちゃんと,ですって言ってごらん」と試してみたが,やっぱりたまに「でふ」になってしまう。これを我が家では「でふ・まふ調」と呼んでいる。こうしろうがかずに問題を出し「でふ・まふ調で答えなさい」などと使ったりする。私も一度試してみたが「でふ・まふ調」で何かを説明するのはえらく難しい。

 前回,紹介したように私とこうしろうは地元のIT推進をアシストするNAT(ITネットワークアシストたかおか)というボランティア団体に所属している。そのNATが11月16日に開催するITフェスタという催し物の中でマインドストームによるロボットコンテストを行うことになり,当然こうしろうもエントリした。

 こうしろうのロボットはハロウィンおばさんという名前で,小さな子供を見つけ飴を配るというシナリオだった。しかし,テストを重ねると,飴は袋が引っかかったり斜めになったりするので,キャラメルを配るように変更した。


 キャラメルは四角いので安定供給できる。

 プログラムは,NQC言語で作った。私が居ると,横からごちゃごちゃ口を出されると思ったのか,こうしうろうは私が家にいない間にプログラムを作っていた。
-------------------------------------------------------------------
#define HENKA 100
int lastlevel;

task main(){
 SetSensorType(SENSOR_2,SENSOR_TYPE_LIGHT);
 SetSensorMode(SENSOR_2,SENSOR_MODE_RAW);
 SetSensorType(SENSOR_1,SENSOR_TYPE_TOUCH);
 SetSensorType(SENSOR_3,SENSOR_TYPE_TOUCH);
 SetPower(OUT_B+OUT_C,7);
 start go_around;
 start send_signal;
 start check_signal;
 start check_touch;
}
-------------------------------------------------------------------
 NQC(Not Quite C)は,C言語に似た文法を持つ言語である。プログラムはtask main()から実行される。SetSensorTypeとSetSensorModeコマンドでセンサーのタイプとモードを設定し,SetPowerでキャタピラを動かすモーターのパワーを7(最大)に設定している。そのわりに歩みが遅いのはロボットの重さというか,高さのせいだろう。他のtask(タスク:仕事や役割)を実行するにはstart タスク名とする。go_around,send_signal,check_signal,check_touchの四つのタスクをスタートさせている。
 各タスクは,順に実行されるのではなく,同時に実行される。タスクを止めるにはstopタスク名とする。NQCの文法はマルチタスクを実感しやすい。
-------------------------------------------------------------------
task go_around(){
 while(true){
  OnFwd(OUT_B+OUT_C);
  Wait(700);
  if(Random(1) == 0){
   OnFwd(OUT_B);
   OnRev(OUT_C);
  }
  else{
   OnFwd(OUT_C);
   OnRev(OUT_B);
  }
  Wait(300);
 }
}
task send_signal(){
 while(true){
  SendMessage(0);
  Wait(5);
 }
}
task check_touch(){
 while(true){
  if(SENSOR_1+SENSOR_3 > 0){
   OnRev(OUT_B+OUT_C);
   Wait(250);
   if(Random(1) == 0){
    OnFwd(OUT_B);
    OnRev(OUT_C);
   }
   else{
    OnFwd(OUT_C);
    OnRev(OUT_B);
   }
   Wait(300);
  }
 }
}
-------------------------------------------------------------------
 go_aroundは動き回るタスク,しばらく前進すると向きを変える。send_signalは赤外線出力,check_touch はステージの端にぶつかったことを検知して後退し方向を変えるタスクである。
-------------------------------------------------------------------
task check_signal(){
 while(true){
  lastlevel = SENSOR_2;
  SetPower(OUT_A,3);
  if(SENSOR_2 > lastlevel + HENKA){
   stop go_around;
   Off(OUT_B+OUT_C);
   PlaySound(3);
   Wait(10);
   OnFwd(OUT_A);
   Wait(100);
   Off(OUT_A);
   Wait(250);
   OnRev(OUT_A);
   Wait(100);
   Off(OUT_A);
   if(Random(1) == 0){
    OnFwd(OUT_B);
    OnRev(OUT_C);
   }
   else{
    OnFwd(OUT_C);
    OnRev(OUT_B);
   }
   Wait(300);
   start go_around;
  }
 }
}
-------------------------------------------------------------------
 check_signalは赤外線の反射をライトセンサーで読み取り,変数lastlevelに保存しておいたライトセンサーの戻り値と現在の戻り値の間に,#defineで定義した定数HENKAの値(100)以上の差が発生したら,誰かが前にいると判断してキャラメルを差し出す。キャラメルを取ってくれるまで,しばらく待ち,また動きだす。


 このタスクが処理の中心であるが,全体のコードの行数のわりに,このタスクだけ行数が多いのでキャラメルを載せたプレートを前後させる処理を別タスクにすればスッキリするだろう。
 などと,横で見ていなくてついつい口を出したくなる父である。

 さてコンテストで,このロボットは首尾よく子供にキャラメルを差し出しことができるのであろうか。