[Piet入門編]Piet入門3

どもです。

意地の連投、今日も行くぜよ。

Pietの移動ルール

前回からPietの移動ルールについて解説していました。

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

引き続き、移動ルールを中心に説明していきます。

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

前回、「移動ルール1」の「基本的な処理」は解説しました。

今回は、「例外的な処理」について説明します。

「例外的な処理」は、「Pietインタプリタが進めない場合の処理」になります。

そもそもPietインタプリタが進めない場合とは、どういう場合でしょうか。

それを「移動ルール2」として、先に説明します。

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

Pietが進めないケースは2つあります。

1つ目が、黒コーデルに進入しようとするケースです。

2つ目が、画像のフチから外に出ようとするケースです。

1:黒コーデル

Pietに使える色の紹介で、白と黒は特殊な色と説明しました。

そのうちの1つ、黒コーデルは、Pietインタプリタが通れない場所を表します。

もしPietインタプリタが移動中に黒コーデルに出会ってしまったら、

黒コーデルには入らず、その手前で一旦停止します。

2:画像の外には出られない

Pietインタプリタが進めないケースはもう一つあります。

それは画像のフチから画像の外へ出ようとする場合です。

Pietの世界は画像の内側で完結します。

また、いつかの某国民的テレビゲームのように、

マップのフチに到達すると反対のフチに出るような、

循環する世界でもありません。

Pietでは、画像の外には出られないのです。

こちらも黒コーデルと同様、外に出る前に一旦停止です。

Pietが進めなくなった時

以上、黒コーデルの中と、画像の外へは進めないと説明しました。

進めないといっても、そのまま止まり続けては困ります。

Pietには、この場合の移動ルールも規定されています。

 

もしPietインタプリタが上記の理由で進めなくなると、

Pietインタプリタの移動パラメータDP、CCを変化させて、

進める場所を探します。

ここでようやく、DP、CCが仕事をするのです。

 

進めなくなった時の移動ルールは、次の2ケースで場合分けして考えます。

  1. Pietがカラーブロックから出ようとして、黒コーデルまたは画像フチに進もうとした時
  2. Pietが白コーデル上を進行中に、黒コーデルまたは画像フチに進もうとした時

これらの処理は大まかには同じですが、若干違うので、あえて分けて書きます。

 

このうちの1つ目、

 Pietがカラーブロックから出ようとして、黒コーデルまたは画像フチに進もうとした時

が、前回のやり残し、つまり、

「移動ルール1」の「例外的な処理」に該当します。

移動ルール1(続き):カラーブロック内を進む場合

Pietインタプリタが進めない状況を理解していただいたところで、

前回の「移動ルール1」のうち、「例外的な処理」を解説します。

 

まずは、前回説明した移動ルールをおさらいします。

  1. カラーブロックのうち、最もDP方向側にある「辺」を探す。
  2. 見つけた「辺」のうち、DP方向に対してCC方向の「端点」を探す。
  3. 見つけた「端点」から、DP方向に1コーデル移動する。(カラーブロックから抜ける)
  4. もし「端点」から移動できない場合は、CCを反転し、再度1~3を実行する。
  5. それでももし「端点」から移動できない場合は、DPを時計回りに90°回転し、再度1~3を実行する。
  6. それでもなお「端点」から移動できない場合は、4と5を交互に繰り返す。
  7. 4と5を4セット繰り返してしまったらプログラムを停止する。
ステップ1〜3のおさらい

このうちステップ1〜3はすでに説明済みですが、

軽くおさらいしましょう。

1:最もDP方向にある「辺」を探す

たとえば、

f:id:y-mos:20210903002220p:plain
初期状態

この絵の例だと、

  • DP=「下」
  • CC=「右」

です。

したがって、探すべき「辺」は『最も下にある「辺」』のことですから、

f:id:y-mos:20210902224028p:plainf:id:y-mos:20210902224031p:plainf:id:y-mos:20210902224035p:plain
見つかった「辺」上のコーデルたち

この3コーデルから構成されます。

 

2:「辺」から「端点」を探す

これは運転手の見ている方向の端を「端点」に選べば良いため、

f:id:y-mos:20210902224028p:plain
見つかった「端点」
  「端点」はここです。

 

3:カラーブロックから抜ける

到達した「端点」から、DP方向に1コーデル進んで

カラーブロックから抜けます。

この時に色が変わるため、命令が実行されます。

f:id:y-mos:20210902234447p:plain
カラーブロックからの脱出と命令実行

ステップ4:「端点」から出られない!〜1回目

では、次の場合はどうでしょうか。

f:id:y-mos:20210903215237p:plain
嫌な予感がするケース その1

「明るい青」のカラーブロックの形状は今までと同じなので、

ステップ1〜2で、同じ「端点」に到達します。

f:id:y-mos:20210903215418p:plain
ステップ2まで完了

ここでステップ3の通り、DP方向に進みたいのですが、

不運なことに目の前が真っ暗、いや、真っ黒です。先に進めません。

 

さて、このような状況に見舞われたとき、

Pietの移動ルールは次のようになります。

「端点」から移動できない時は、CCを反転させて、再度ステップ1〜3を実行する。

 

わかりにくいので実際やってみましょう。

まずはとりあえず、CCを反転させてみます。

f:id:y-mos:20210903220230p:plain
CC反転(「運転手」が右を向いた)

1:最もDP方向にある「辺」を探す

いま、DPは「下」のままなので、『最も下にある「辺」』を探せば OKです。

ですが、実はそれって、先ほど探索した3コーデルと同じです。

f:id:y-mos:20210903220230p:plain f:id:y-mos:20210903220238p:plain f:id:y-mos:20210903220244p:plain
見つかった「辺」

2:「辺」から「端点」を探す

運転手の見ている方向が反転したため、先ほどとは反対の端が「端点」として選ばれます。

f:id:y-mos:20210903220244p:plain
新しい「端点」

3:カラーブロックから抜ける

こうなればPietインタプリタは前に進めそうです。

到達した「端点」から、DP方向に1コーデル進んで

カラーブロックから抜けます。

f:id:y-mos:20210903220632p:plain
カラーブロックから抜けることに成功!

このように、進めなくなったら、まずCCを反転させて、「端点」を探し直す。

これで、違う場所が「端点」として選出され、カラーブロックから脱出できます。

ステップ5:「端点」から出られない!〜2回目

しかし、なんとういうか、不運なことは続くものです。

次のケースを考えます。

f:id:y-mos:20210903221849p:plain
嫌な予感がするケース その2

なんだか悪意を感じますね。それはさておき。

 

この場合もまずはステップ1〜2を実行します。

f:id:y-mos:20210903221849p:plainf:id:y-mos:20210903222016p:plain
ステップ2まで完了

そして、ステップ3を実行しようとして「進めません」となりますので、

CCを反転して再度ステップ1〜2を実行します。

f:id:y-mos:20210903222125p:plainf:id:y-mos:20210903222132p:plain
CC反転→ステップ1〜2を実行

そして再度ステップ3を実行します。

するとどうでしょう。やはり目の前に黒コーデルがいて進めません。

 

2度目はCCを反転させても意味がありませんが、

このような場合もPietでは想定されており、次のように進路を決めます。

2度目はDPを時計回りに90°回転させて、再度ステップ1〜3を実行する。

 

実際にやってみます。まずはDPを回転します。

f:id:y-mos:20210903222631p:plain
DP回転

CCの値自体は変化しませんが、

「車(=DPの向き)」が90°回転すると、「運転手の見ている向き」も一緒に90°回転する

ので注意してください。

 

1:最もDP方向にある「辺」を探す

DPは「左」のままなので、『最も左にある「辺」』を探します。

f:id:y-mos:20210903223156p:plain f:id:y-mos:20210903223203p:plain f:id:y-mos:20210903223209p:plain
最も左にある「辺」

2:「辺」から「端点」を探す

運転手のみている方向は「下」であるため、最も下の端を「端点」とします。

f:id:y-mos:20210903223156p:plain
「端点」

3:カラーブロックから抜ける

あとは、この「端点」から、DP方向に1コーデル進んで

カラーブロックから抜ければOKです。

ステップ6:「端点」から出られない!〜3回目

ところが、残念ながら先ほどのケースでは、ステップ3は失敗します。

画像のフチという超えられない壁に出くわしてしまったからです。

 

この場合は次のようにします。

CCを反転させて、再度ステップ1〜3を実行する。

これは最初に移動できなかった時と全く同じ対処法ですが、

先ほどDPを変化させたため、ここでCCを変化させると、

これまでとは異なる点が「端点」として選ばれる可能性があります。

 

もう詳細は割愛しますが、この結果、次の図の位置が「端点」として選ばれます。

f:id:y-mos:20210903224215p:plain f:id:y-mos:20210903224223p:plain
CC反転→ステップ1〜2実行

ステップ6:「端点」から出られない!〜4回目以降

ここでステップ3を実行しようとしたのですが、

やはり画像のフチに行手を阻まれてしまいました。

 

お察しの通り、次の対処法は、

DPを時計回りに90°回転させて、再度ステップ1〜3を実行する

です。

 

もうお気づきかもしれませんが、ステップ3が失敗したら、

CC反転→DP回転→CC反転→DP回転→・・・のように、

CC反転とDP反転を交互に実行しながら、その都度ステップ1〜3を実行し

カラーブロックからの脱出を試みます。

 

パラメータCCのとりうる値は2通り、

パラメータDPのとりうる値は4通りなので、

この過程で、最大2\times{4}=8通りの「端点」を探索することになります。

途中、どこかの「端点」から外に出られれば無事終了です。

 

なお、ステップ3が失敗した場合は、パラメータは必ずCCから変化させます。

「さっきのカラーブロックではCCで終わったから、今回はDPから始めよう」

とはなりません。

 

また、この過程で変化したDPやCCの値は、

カラーブロックから無事脱出できてもリセットされません。

変えてしまったものはそのままに、次の処理へと進みます。

ステップ7:プログラムの停止

Pietインタプリタがカラーブロックから出られるまで、

ステップ4(CC反転)とステップ5(DP回転)が交互に繰り返されます。

さて、ステップ4とステップ5を、4セット繰り返すと、CCとDPが交互に8回変化します。

ここまでくると、CCとDPの状態が元に戻り、

8回目に選ばれる「端点」が、1回目に選ばれる「端点」と一致します。

 

そのあとは再び同じことを繰り返すため、

Pietインタプリタはもう、このカラーブロックから出られません。ひえー。

 

実は先ほどから例に挙げているケースも、出られなくなる例のひとつです。

選ばれた端点を順に追ってみましょう。

f:id:y-mos:20210903221849p:plainf:id:y-mos:20210903222016p:plainf:id:y-mos:20210903222132p:plain
初期状態→ステップ3失敗→1回目(CC反転)

f:id:y-mos:20210903223156p:plainf:id:y-mos:20210903224223p:plainf:id:y-mos:20210903225954p:plain
2回目(DP回転)→3回目(CC反転)→4回目(DP回転)

f:id:y-mos:20210903230007p:plainf:id:y-mos:20210903230015p:plainf:id:y-mos:20210903230022p:plain
5回目(CC反転)→6回目(DP回転)→7回目(CC反転)

そして、8回目のDP回転を実行すると、次のようになります。

f:id:y-mos:20210903222016p:plain
8回目(DP回転)

これは最初ステップ3の実行に失敗した時と、全く同じです。

 

普通に考えると、これは無限ループになるのですが、Pietでは、

ステップ4とステップ5を、4セット繰り返したら、プログラムを停止する

というルールがあります。

 

逆にいうと、Pietでは、このような脱出不可能なカラーブロックを作って、

プログラムを終了させています。

たとえば、いつぞやのカウンタ付きループのソースコード

f:id:y-mos:20210818222159p:plain
カウンタ付きループ

このソースコードでは、下辺にある次の部分が

脱出不可能なカラーブロックになっており、

プログラムを終了するブロックとして活用されています。

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

このブロックにPietインタプリタが到達すると、まず次の状態になります。

(ここでは、「そうなるものだ」と思ってください。)

f:id:y-mos:20210904000019p:plain
初期状態

ここから、8回のパラメータ変更は、次のように行われます。

f:id:y-mos:20210903232721p:plainf:id:y-mos:20210903232615p:plainf:id:y-mos:20210903232729p:plain
ステップ3失敗→1回目(CC反転)→2回目(DP回転)

f:id:y-mos:20210903232725p:plainf:id:y-mos:20210903232739p:plainf:id:y-mos:20210903232733p:plain
3回目(CC反転)→4回目(DP回転)→5回目(CC反転)

f:id:y-mos:20210903232751p:plainf:id:y-mos:20210903232744p:plainf:id:y-mos:20210903232721p:plain
6回目(DP回転)→7回目(CC反転)→8回目(DP回転)

これもCCとDPが同じ状態に戻ってしまうため、プログラムが終了します。

次回予告

さて、移動のルールは残すところあと一つ、「白コーデル上の挙動」です。

次回は白コーデルにおけるPietインタプリタの挙動を説明します。

終わりに

またしても時間かかるといっておきながら翌日更新となりました。

今回でPietルールの説明の峠は越えた感じです。

面倒なところは一通り終わったかな。

 

次回、白コーデルの話をしますが、白コーデルは割と簡単です。

ですが、これはこれで、色々注意点があるので、

また次回じっくり考えていくことにしましょう。

 

じゃ、今日はこの辺で。

では。