[Piet入門編]Piet入門2

どもです。

時間かかると言った割には早く書き上げることができました()

前回、Pietの概説と、色と命令の関係を説明しました。

今回は、Piet入門編の2回目です。

 

本日のメニューはこちら

目次入れるとわかりやすくていいですね。(自画自賛

Pietの移動ルール

今回はPietインタプリタの移動ルールについて説明します。

Piet用語:カラーブロック

説明に入る前に、移動ルールに関するPiet用語「カラーブロック」の説明をします。

 

カラーブロックとは、同色のコーデルのかたまりのことです。

ここでいう「かたまり」とは「4連結1」、つまり、辺同士で繋がっているものです。

頂点が接触しているだけでは、同一のカラーブロックにはなりません。

たとえば、

f:id:y-mos:20210828232603p:plain
カラーブロックの数え方(1)

この図には以下の4つのカラーブロックがあります。

  • 右上の横一文字の領域(ピンク色)
  • 右下の縦一文字領域(水色)
  • 左上のL字の領域(ピンク色)
  • 右下の長方形領域(ピンク色)

最初の2つはわかりやすいと思いますが、後の2つの領域もそれぞれ独立したカラーブロックです。

後の2つの領域は角で接触していますが、角だけで接触している場合は別のカラーブロックとして考えます。

 

同様に考えると、以下の図には2つのカラーブロックがあることもわかります。

f:id:y-mos:20210828232709p:plain
カラーブロックの数え方(2)

ちなみに、白色のかたまりはカラーブロックとは呼びません。

移動に関するパラメータ

カラーブロックについて説明したところで、

ここからはPietの移動ルールに関係する

2つのパラメータDP、CCについて説明します。

パラメータその1:DP

まず一つ目のパラメータはDP(Direction Pointer)です。

これは、Pietインタプリタの進行方向を表します。

DPのとる値は、「左」、「下」、「右」、「上」の4つです。

パラメータその2:CC

次に二つ目のパラメータ、CC(Codel Chooser)です。

これは、今の時点では説明が難しいのですが、

Pietインタプリタがカラーブロックのどこから出ていくかを決めます。

 

CCのとる値は、「左」、「右」の2つです。

これは、画像上での「左」、「右」ではなく、

DP方向を「前」とした時に、「左」か「右」か、という意味合いとなります。

DPとCCのイメージ

以上2つのパラメータですが、特にCCがややこしいです。

そこで私は「車に乗った人」というイメージで考えています。

つまり、

  • DP : 画像の上を走る「車」
  • CC : 車の「運転手の見ている向き」

というイメージです。

 

たとえば、DP=「右」、CC=「左」の場合の

イメージを絵で描くとこんな感じです。

f:id:y-mos:20210902220826p:plain
DP(車)とCC(運転手)のイメージ

なんだかファンシーですね。

 

青いホームベース型のものが「車」を表しています。

尖っている方向が進行方向(=DPの方向)を表します。

 

また、中央の丸が運転手の頭を上から見た様子を表しています。

よく見ると鼻がついていて、運転手の見ている方向がわかります。

(この例では、上方向を向いています。)

 

CC=「左」ではありますが、運転手は「上」方向を見ています。

その理由は次の通りです。

車の進行方向(=DP方向)は「右」であり、運転手にとってはこちらが前です。

それに対し、運転手の見ている方向(=CC)が「左」であるので、

結局運転手は画像の「上」方向を向いていることになります。

 

他にもいくつか例を挙げておきます。

DP、CC、運転手の顔の向き。この3つの関係を確認してみて下さい。

f:id:y-mos:20210902221737p:plain
DP=「下」CC=「右」

f:id:y-mos:20210902221742p:plain
DP=「左」CC=「左」

f:id:y-mos:20210902221747p:plain
DP=「上」CC=「左」

Pietの移動ルール解説!

ではいよいよ具体的な説明をします。

初期状態

まず、Pietインタプリタは、画像の左上の角のコーデルから出発します。

パラメータの初期状態は次の通りです。

  • DP=「右」
  • CC=「左」

つまり、Pietインタプリタは、画像の左上コーデルから左に出発します。

f:id:y-mos:20210902220826p:plain
DPとCCの初期状態

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

まず、Pietインタプリタがカラーブロックに入った時の移動ルールを説明します。

移動ルールは次の通りです。

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

 

ね?簡単でしょ?

 

まぁ、そんなわけないのは私もよくわかっているので、

解説していきますだ。

 

さて、このフローは大きく2つに分けることができます。

  1. 基本的な処理(ステップ1〜3)
  2. 例外的な処理(ステップ4〜7)

 

ステップ1〜3は基本的な処理です。

基本的にはステップ1〜3のみで移動が完結します。

 

一方で、ステップ4〜7は例外的な処理です。

ステップ1〜3を実行した結果、Pietインタプリタが先に進めないときに実行します。

 

今回はまず、基本的な処理であるステップ1〜3を説明したいと思います。

ステップ1:DP方向の「辺」を探索する

早速ですが、難解ポイントその1です。

おそらくなんとなく言っていることはわかると思うのですが、

ここは正確に理解する必要があります。

 

ここで使う移動パラメータはDPだけです。

このステップでは、いま居るカラーブロックのみに着目し、

カラーブロック内の最もDP方向にあるコーデルを全て探します。

それが探索すべき「辺」です。

 

たとえば次のPietソースコード画像を考えます。しれっと車も待機しています。

f:id:y-mos:20210902223031p:plain
例1

今の状態を整理します。

  • Pietインタプリタの位置:「明るい赤」カラーブロックの左上
  • DP:右
  • CC:左

このとき、探索すべき「辺」とは、

最もDP方向にある(つまり、最も右にある)、次の3コーデルです。

f:id:y-mos:20210902223523p:plainf:id:y-mos:20210902223530p:plainf:id:y-mos:20210902223535p:plain
最もDP方向にある「辺」

 

また、別の例も考えてみます。

f:id:y-mos:20210903002220p:plain
例2

今の状態を整理します。

  • Pietインタプリタの位置:「明るい青」カラーブロックの上辺
  • DP:下
  • CC:右

このとき、探索すべき「辺」とは、

最もDP方向にある(つまり、最も下にある)、次の3コーデルです。

f:id:y-mos:20210902224028p:plainf:id:y-mos:20210902224031p:plainf:id:y-mos:20210902224035p:plain
最もDP方向にある「辺」

『「辺」を探しているのに白コーデルで分離されているけどいいのか』

と思われるかもしれませんが、「辺」の探索方法は、あくまで、

「同じカラーブロックの中から、最もDP方向にあるコーデルを全て探す」ことです。

その条件を満たすコーデルは、全て「辺」のひとつです。

「辺」と言うのは、あくまで説明のために便宜上つけた名前です。

 

また、

『PietインタプリタがDP方向に直進したら右端のくぼみに入るため、

左の2つの図のようにはならないのではないか』と思われるかもしれません。

 

しかし、このステップで行なっているのは、

DP方向に最も離れた場所を見つけることであり、

DP方向に直進することではありません。

言い換えれば、Pietインタプリタ

カラーブロックの形状全体を見ているのであって、

真正面だけ見ているわけではないのです。

 

もう一つ例です。

f:id:y-mos:20210902224611p:plain
例3

今の状態を整理します。

  • Pietインタプリタの位置:「明るいマゼンタ」カラーブロックの右辺
  • DP:左
  • CC:左

このとき、探索すべき「辺」はどこでしょうか?

答えは次の1コーデルだけです。

f:id:y-mos:20210902224728p:plain
最もDP方向にあるコーデル

形状が複雑ですが、「辺」の探索手順、すなわち、

「同じカラーブロックの中から、最もDP方向にあるコーデルを探す」

に忠実に従うと、この1コーデルのみが「辺」に該当します。

 

なお、以上はあくまで、カラーブロック内でのPietインタプリタの挙動であり、

白色領域内ではPietインタプリタの挙動が変わります。

白色領域については次回以降に説明します。

ステップ2:「辺」の中からCC方向の「端点」を探す

「辺」が見つかったら次は「端点」を探します。

「辺」が正しく見つけられれば、このステップは簡単です。

 

この段階で使う移動パラメータはCCだけです。

ここでは、先ほど見つけた「辺」のうち、

「DP方向に対するCC方向」(=運転手の見ている方向)の端を探し、

そのコーデルを「端点」とします。

 

たとえば例1の場合は、運転手が上を見ていたので、

端点はここです。

f:id:y-mos:20210902223523p:plain
例1の端点

例2だと、運転手は左を見ていましたので、

端点は次の位置になります。

f:id:y-mos:20210902224028p:plain
例2の端点

例3は、そもそも「辺」に含まれるコーデルが1つしかないので、

問答無用で次の位置が端点です。

f:id:y-mos:20210902224728p:plain
例3の端点

ステップ3:カラーブロック脱出 

Pietインタプリタは、先ほど選ばれた「端点」に到達すると、

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

 

ここでは移動パラメータのDPのみを使います。

脱出する際には、「端点」からDP方向に1コーデル進みます。

首尾よく脱出できた場合、

Pietインタプリタが異なるカラーブロックに進入するため、

色の変化が生じますので、命令が実行されます。

 

たとえば例1の場合は、

明るさ変化2、色味変化2でnot命令が実行されます。

f:id:y-mos:20210902223523p:plainf:id:y-mos:20210902234441p:plain
not命令(明るさ変化2、色味変化2)

例2の場合は、明るさ変化0、色味変化2でdiv命令と解釈されます。

f:id:y-mos:20210902224028p:plainf:id:y-mos:20210902234447p:plain
div命令(明るさ変化0、色味変化2)

例3では、明るさ変化0、色味変化3でgt命令となります。

f:id:y-mos:20210902224728p:plainf:id:y-mos:20210902234454p:plain
gt命令(明るさ変化0、色味変化3)

カラーブロックを脱出したPietインタプリタは、

多くの場合、また別のカラーブロックに入ります。

次のカラーブロックでも上記ステップ1〜3を繰り返して、

次々に命令を実行していくのです。

次回予告

次回は今回説明できなかった「例外的な処理」であるステップ4〜7を中心に解説します。

あわせて、黒コーデルや画像フチにおけるPietインタプリタの挙動、

Pietインタプリタを停止する方法についても、次回解説したいと思います。

おわりに

前回は完全にモチベ不足で更新が遅れましたが、

今回はなぜかモチベが回復して、ほぼ翌日更新に漕ぎ着けました。

なんということでしょう!読者に対する裏切りですよ、これは!

まあ今回の場合は、良い方に裏切ったのでいいかもしれませんが。

 

前回の予告通り、やはり移動ルールの解説は、

2部構成または3部構成になりそうです。

結構重たいですが、Piet理解の要なので、

次回もしっかり書いていこうと思います。

 

じゃ、今回はこの辺で。

では。


  1. 「4連結」とついになる用語は「8連結」です。「8連結」は、辺が接触していなくても、角だけが接触していれば同じ「かたまり」とみなすことを言います。