[Piet入門編]Piet入門4

どもです。

今回もPiet入門編です。

前回の最後に、「次回で完結」とかいっていましたが、

よく考えたら、pointer命令とswitch命令の説明をしていなかったので、

命令の説明がてら、もう1〜2回は入門編が必要ですね。むむむ。

 

では本日のメニューを。

Pietの移動ルール

今回は説明の第3弾です。

残りの移動ルールを説明します。

Pietの移動ルール解説!(続き)

前回までに、

  • 移動ルール1:カラーブロック内を進む場合
  • 移動ルール2:Pietインタプリタが進めない場合

を説明しました。

 

今回はまだ説明していない、白コーデルの役割を、

「移動ルール3」として説明します。

 

また、白コーデル内で進めなくなった場合の処理を、

「移動ルール2」に追記する形で、説明します。

移動ルール3:白コーデル

今回の主役は白コーデルです。

Pietでは、黒・白コーデルは特別な役割を持っていました。

白コーデルの基本的な性質は次の3点です。

  • Pietインタプリタ白コーデル内を通行可能。
  • 白コーデル内ではPietインタプリタDP方向に直進する。
  • 白コーデルでは命令が実行されない。

順に解説していきます。

白コーデル内は通行可能

Pietインタプリタは白コーデル内部を通行可能です。

しかし、Pietインタプリタの移動ルールは、通常のカラーブロックとは異なります。

白コーデル内は直進

Pietインタプリタ白コーデル内ではDP方向に直進します。

カラーブロックや黒コーデル・画像フチの、ひとつ手前の白コーデルまで進みます。

そして、

  • カラーブロックに到達したら、DP方向に1コーデル進んでカラーブロックに入ります。
  • 黒コーデル・画像フチに到達した場合は、後ほど説明します。

たとえば次のケースです。

f:id:y-mos:20210904113325p:plain
 

このあとのPietインタプリタの動きを追ってみると、

白コーデル内ではPietインタプリタはDP方向に直進するため、

次の図の位置に到達します。

f:id:y-mos:20210904113954p:plain
白コーデル内を移動した後の様子

これだけです。

 

もし、今までのカラーブロックの理屈を当てはめるなら、

CCを考慮して次の位置に来るはずです。

f:id:y-mos:20210904114137p:plain
白コーデル内の移動結果(※これは誤り!)

しかし、これは誤りです。

白コーデル内では、CCの挙動は関係ありません。

DP方向にただ直進すればOKです。

これが通常のカラーブロックと、白コーデルとの違いです。

 

なお、白コーデルを進行中にカラーブロックに突き当たったら

そのままDP方向に進行してカラーブロックに入っていきます。

f:id:y-mos:20210904113954p:plainf:id:y-mos:20210904135540p:plain
白コーデルからカラーブロックに入る様子

白コーデルでは命令が実行されない

さて、白コーデルからカラーブロックに入るときも色が変化するので、

ここでも命令が実行されそうです。

しかしPietでは、変化前後の色のどちらかが白であれば、命令は実行されません。

したがって、先ほどの図のように、

白コーデルから「明るいシアン」のカラーブロックに進入した時は、

命令が実行されません。

 

逆に、カラーブロックから脱出した先が白コーデルだった場合も、

同様に命令が実行されません。

たとえば、次の図のように移動したときも、命令は実行されません。

f:id:y-mos:20210904140001p:plainf:id:y-mos:20210904113325p:plain
カラーブロックから白コーデルに出る時:命令は実行されない

移動ルール2(追加):Pietインタプリタが進めない場合

白コーデルの説明をしたので、

白コーデル内でPietインタプリタが進めなくなった場合の説明をします。

白コーデル内で進めなくなったとき

白コーデルを進行中に、黒コーデルや画像のフチに到達した場合は、

次のような挙動となります。

  • CCを反転させる。
  • その後すぐにDPを90°時計回りに回転させる。

その上で再び白コーデル内での移動ルールにしたがって、Pietインタプリタを移動させます。

CCを反転させてから、すぐにDPを回転させるのは、

白コーデル内での移動ルール上、CCが変化しても影響はなく、

DPが変化しないと行き先が変化しないからです。

 

たとえば、次のケースを考えます。

f:id:y-mos:20210904143908p:plain
 

まず、DP方向に直進します。

f:id:y-mos:20210904144312p:plain
黒コーデルに突き当たる

黒コーデルに突き当たったので、CCを反転させ、DPを回転させます。

そして、DP方向に直進します。

f:id:y-mos:20210904144312p:plainf:id:y-mos:20210904144518p:plainf:id:y-mos:20210904144524p:plainf:id:y-mos:20210904144628p:plain
初期状態→CC反転→DP回転→DP方向に直進

しかし、この結果またしても黒コーデルに突き当たるので、

さらに、CCを反転させ、DPを回転させ、そして、DP方向に直進します。

f:id:y-mos:20210904144628p:plainf:id:y-mos:20210904144828p:plainf:id:y-mos:20210904144836p:plainf:id:y-mos:20210904144841p:plain
黒コーデルに遭遇→CC反転→DP回転→DP方向に直進

すると無事カラーブロックに突き当たるので、そのまま進入します。

(もちろんこの時、命令は実行されません。)

f:id:y-mos:20210904144841p:plainf:id:y-mos:20210904145154p:plain
カラーブロックに遭遇→進入

白コーデル内で無限ループになった時:プログラム停止

さて、カラーブロックの移動ルールを説明したときに、

黒コーデルや画像フチに何度も遭遇して

無限ループになる時があることを説明しました。

 

白コーデル内を移動中にも同様に、黒コーデルや画像フチに何度も遭遇し、

無限ループに入る可能性があります。その時の移動ルールは次の通りです。

  • 白コーデル内を移動中に、全く同じルートを再度通ったらPietインタプリタが停止する。

・・・らしいです。

 

「らしいです」というのは、Pietのインタプリタであるnpietで、

その動作が確認できなかったから。

試しに次のコードを作ってみて、

f:id:y-mos:20210904150529p:plain
白コーデル内でのプログラム停止試験コード

npietにかけてみました。

トレース画像は次の通りです。

f:id:y-mos:20210904150802p:plain
試験コードのトレース画像

黒い線が、Pietインタプリタの進んだ軌跡です。

形状は複雑ですが、一応同じところをぐるぐる回るコードになっています。

 

しかし、結果としては、npietは停止しませんでした。

右端の縦ラインに入ったところで全く同じルートに入るので、

停止してくれないかなと期待していたのですが。。。

 

なお、Pietの白コーデル内の挙動に関しては、当初若干混乱があったようで、

Pietの公式でも補足説明がされています。

(Syntax Elementsの下、White Blocksの中の、イタリック体以降のところ)

 

私が解釈を間違えているのか、もしくは、この辺の説明がnpietに反映されていないのか。

いずれにしても、プログラムを止めるなら、前回解説したような、

「脱出不能なカラーブロック」を作る方が確実なようです。

f:id:y-mos:20210903232354p:plain
「脱出不能なカラーブロック」の例

おわりに

今回は比較的さっぱり終えることができました。

毎度こんな感じならいいのですが、

中途半端に「続きは次回!」みたいな展開が個人的には好きではないので、

非効率とは思いつつ毎度毎度長くなってしまうのですが。。。

 

次回はPietの命令について解説します。

本当は「自作のGridPietGeneratorの命令解説を見てください」と

お茶を濁そうと思ったのですが、ちょっと不親切な気もするので

もう一度解説しようかと思います。

 

じゃ、今回はこの辺で。

では。