ループの利用

WORDの登録時には様々な構文が使用できます。
今回はループを使ってみます。

とりあえずの要件として、1tickごとにカウントアップし
接続しているレッドストーンランプを点滅させる、
そんな感じのものを作ってみましょう。



何はともあれループをさせてみないと何も始まりません。
ループにはBEGIN~AGAIN文を使います。


ループWORDの登録


VARIABLE X
: LOOP003
 0 X !
 BEGIN
  X @ .
  X @ 1 + X !
 AGAIN
;


とりあえずループさせるだけのWORD。
VARIABLEは変数を宣言するためのWORDです。
Xはここではループ変数として利用します。

3行目の 0 X ! は、変数Xに0を代入する、という意味です。
0からループさせたいので、最初に初期化させておきます。

4行目のBEGINからAGAINまでがループ処理。
X @ . は変数Xの値を表示します。
X @ 1 + X ! は変数Xの値を引き出し、それに1を足したものを再びXに代入する、
という処理です。1 X +! でもOKです。
実行させてみます。


ループの実行

こうなります。
1ループごとに表示・カウントアップを繰り返します。
ちなみにこれはほんとにループさせるだけで、
停止等は一切できません。無限ループです。
FORTH起動ディスク等でRESETをかけてやらないと復帰しないので、注意が必要です。


さて、ループはできたんですが制御不能のループです。
それでは使い勝手が悪いですよね。
では、とりあえず手動で止められるようにしましょう。


ループWORDの登録


VARIABLE X
: LOOP004
 0 X !
 BEGIN
  X @ .
  1 X +!
  KEY? IF
   EXIT
  THEN
 AGAIN
;


KEY? IF~THENのくだりを追加しました。
KEY?はキーが押されていればTRUE、そうでなければFALSEを返すWORDです。
IF文はTRUEかFALSEかで条件分岐するので、
KEY? IF だけで正しく動作します。
では動かしてみましょう。


ループの実行と停止

はい、どうでしょう?
今度は途中でaと入力したため、処理を途中で停止します。


ループの実行と停止

2度目の実行も問題無く行えます。0から始まってますね。

この止め方はあくまでも一例で、
IF文を使うぐらいならWHILEを使えだとか、
BEGIN UNTILがあるじゃないかとかあるかもしれませんがあくまでも一例です。
最適な構文を自分で考えるのも、プログラミングの楽しみの一つです。
(筆者がFORTH初心者であるということに突っ込んではいけない)


手動停止ができるようになったので、次はレッドストーン信号との連携です。


ループWORDの登録


: LOOP005
 0 X !
 BEGIN
  65535 IOXRST
  X @ IOXSET
  X @ . 1 X +!
  KEY? IF EXIT THEN
 AGAIN
;


まず 65535 IOXRST で全ランプを消します。
次に X @ IOXSET で該当ランプを付けます。
あとはループ制御するだけです。
改行がめんどくさくなってきたので、ループ制御の部分は2行に縮めました。

さて、これでどうなるでしょう?


ループの実行



こんな感じになりました。
表示処理より処理速度が速いせいか、白信号のランプは付きっぱなしです。
でもなんとなくこんな感じにしたかったっていうのは
お分かり頂けたのではないでしょうか。


もう少しだけ手を加えます。
白信号が点滅できていないので、処理の最高速度を10tickまで落とそうと思います。


ループWORDの登録


: LOOP006
 0 X !
 BEGIN
  65535 IOXRST
  X @ IOXSET
  10 TICKS
  X @ . 1 X +!
  KEY? IF EXIT THEN
 AGAIN
;


10 TICKS を入れただけです。
TICKSは指定tick数だけ処理を一時停止するWORDとなります。




1TICKSでも点滅しなかったので10TICKSまで落としてみましたが、
今度はちょっと遅いような気も。2~3TICKSでもよかったかもしれませんが、
まぁいいでしょう。

おまけ

ループWORDの登録


VARIABLE X
: LOOP007
 1 X !
 BEGIN
  65535 IOXRST
  X @ IOXSET
  3 TICKS
  X @ 16384 = IF
   32768 X !
  ELSE
   X @ 32768 = IF
    1 X +!
   ELSE
    X @ 1 << X !
   THEN
  THEN
  X @ 32768 > IF 1 X ! THEN
  KEY? IF EXIT THEN
 AGAIN
;




3tickごとにONにする照明を横にスライドしていくWORDです。
キモは X @ 1 << X ! です。
<< はビット演算子で、1ビット左にスライドさせます。
0000 0000 0000 0001

0000 0000 0000 0010

0000 0000 0000 0100
という具合に。
これを使ってONにする照明を左にずらしていくのですが、
16384から32768への演算でこれをやると符号ビットにひっかかって
値がマイナスになってしまいます。


値のマイナス化

そのため、16384から32768へのシフトは別途ルーチンで行わせます。
それともうひとつ。32768を超えた場合に値を1に戻す処理も行い、
処理を永続的に行うようにします。
32768からそれより大きい値にするのも別途ルーチンで。
ここらへんがスッキリできればコード量も減るのですが・・・まぁ、とりあえず。

ループと条件文を使えば、可能性は無限大です。
2012/12/28 作成

お知らせ

特にありません。