はじめに
前回の最後に、「少しだけ高度なことをする」といったな。あれは嘘だ。
(いえ、説明を書いてたら笑えない量になってしまったので、今回と次回の2回に分けただけなんですけどね、今回は触りの部分だけなので簡単です。こわくなーい)
前回までに、「キー入力でタートルを操作できるプログラム」を紹介しました。
上、上、下、下、右平行移動、左並行移動、前、前、後、後、・・・。
自在に動かすことができますね。
今回は、もっと複雑な操作もできるようにしましょう。
たとえば、「前、前、右、前」「よし。この位置だ」「穴掘りプログラム開始!」
のように外部プログラムを呼び出せたら便利ではありませんか?
穴掘りプログラムの再掲
以前の記事で、穴掘りプログラムを紹介しました。
このプログラムは、回転しながら岩盤まで直下掘りするプログラムです。 あらかじめスロット1にブロックを入れておけば、掘り終えた後に穴にフタをする機能もあります。
無線操作プログラムを使って目標位置へ移動、そして無線操作で穴掘りプログラムスタート。面白そうでしょう?
まずは、この穴掘りプログラム「boring」を受信側(タートル側)に、あらかじめダウンロードしておきましょう。
> pastebin get TFvw7usW boring
なお、このプログラムを実行するためには、スロット1にフタ用の資材ブロックを5個以上入れておく必要があります。また、燃料も念のためたっぷり補給しておきましょう。
受信側(タートル側)プログラムは前回のものをそのまま利用
msg_receiver3
http://pastebin.com/564VSbU7
送信側プログラムの修正
msg_sender3
- version 3a: テスト用コードが残っていたので修正。"z"キーで"boring"プログラムを実行するように。
インストール
> pastebin get zM0SG9Bc msg_sender3
修正は2箇所
プログラム終了操作を修正。
以前は、CTRL+Tで無理やりプログラムを終了していましたが、キー「q」の入力で終了するようにしました。
- L24) 終了する方法を画面表示
- L29) キーの名前が"q"だったらwhileループを抜けて終了。
「キー名・送信メッセージ変換表」に追加
L20, 21に、新しい項目を追加しました。
z="os.run({},'boring')", x="os.run({},'rom/programs/turtle/dance')"
"z"キーを押したら、os.run({},'boring')
というメッセージを送信します。受信したタートル側は、自分の手元にある「boring」プログラムを実行します。
"x"キーを押したら、os.run({},'rom/programs/turtle/dance')
というメッセージを送信します。受信したタートル側は、自分の手元にある「rom/programs/turtle/dance」というダンスプログラムを実行します。レッツ、ダンス!
新しく出てきたos.run()関数の説明は次のとおり(詳細はこちら)。
os.run()
- 引数で指定して、任意のプログラムを実行できる。
- 引数1(テーブル): プログラムのグローバル変数の値を指定。普段は
{}
で良い。 - 引数2(文字列): プログラム名。パスは絶対指定で指示。
- 引数3以降(文字列): プログラムに与える引数を好きなだけ
なお、外部プログラムを実行する関数としてはshell.run()
もありますが、loadstring()
は絶対パスの解決ができないための中ではパス検索しようとして必ず失敗してしまうため、今回のプログラムの中では使えません。(いただいたコメントに従い修正)
(コメントにより修正)
なお、外部プログラムを実行する関数としてはshell.run()
もありますが、現在のプログラムのままでは使えません。
この関数はos.run()のラッパー関数であり、与えたプログラム名の絶対パスを検索するという機能があるのですが、loadstring()によってコンパイルされる関数はグローバル変数テーブル(_G)を環境としているため、このままでは検索に失敗してしまうからです。
このあたり、次回の修正で解決しましょう。
おわりに
遠隔操作で、「位置調整」→「他のプログラム実行」→「位置調整」→「他のプログラム実行」……。
どうでしょうか? これ、とても便利じゃありません?
次回は、もっと複雑な動作を命令するにはどうすればよいかについて考えてみましょう。
具体的には、タートル側の受信プログラム内で定義した関数を遠隔命令で呼び出す方法です。
- たとえば、タートル側の受信プログラム内で
hevo()
という関数を定義してあるとします。 - これを呼び出そうと「hevo()」という文字列を送信しても、関数が見つからないというエラーが出てしまうのです。
- だいたい、loadstring()関数のせいw
次回はこの解決法を検討してみましょう。