ペンシルパズル on baba is you


この記事はペンシルパズルII Advent Calendar 2021 19日目の記事です。


0.まえがき?

元々は先週baba is youのエディタを初めて触ってみて、なんとなくぬりみさきの解答判定をする仕掛けが作れそうな気がしたので、それを作ったら公開するだけのつもりでした。が、興が乗って色々やってしまいました。楽しかったですね。作ったものと概要を順に説明していきます。

1.ヤジリン

作ったものの中で(おそらく)一番簡単に動くヤジリンからまず説明していきます。
今回作成したヤジリン盤面は下の画像になります
レベルコード:XRFQ-81WX
プレイ動画はこちら。puzz.linkで解く場合はこちら

無題2

まずはヤジリンのルールをbaba is youに落とし込むための前提となるルールの確認から。

1.盤面のいくつかのマスに線を引いて全体で1つの輪っかを作りましょう。また、線が通らないマスは黒くぬり、黒マスにしましょう。
2.数字は、矢印の方向に入る黒マスの数を表します。
3.数字のマスに線を引いたり、黒マスにしたりしてはいけません。
4.線は、マスの中央を通るようにタテヨコに引きます。線を交差させたり、枝分かれさせたりしてはいけません。
5.黒マスをタテヨコに連続させてはいけません。
(ニコリのページから引用)
これらのルールをプレイヤーが記入した盤面から一つ一つ判定する仕掛けを解説します。

・・・とその前に、ヤジリンの解答を盤面に入力するインターフェースを説明します。
今回の操作キャラは盤面中央付近のタイル上にいるSTICK(you)と、もう一つSPROUT(you2)があります。STICKが基本操作用、SPROUTが線の入力用です。(SPROUTの上にいるSTICKは動作のサポート用なので操作できません。)
youはアローキー、you2はWASDキーでそれぞれ操作できる仕様です。

1.黒マスと白マスの入力
黒マスと白マスは操作キャラのSTICKで入力します。
baba is youでは待機時のイベントを指定できるのでこれを利用して
タイル→黒マス→白マスと変化させます。

2.線の入力
線はSPROUT側の操作で発生させ、盤面側のSTICK側にTELEで移動させることで入力します。盤面中央上のBABA,KEKE,IT,JIJI(以降彼ら)は上にSPROUTが乗った場合だけSHIFTになります。また、彼らの上に上下左右向きの線(見た目は全てsword)が乗っていないと自動的に新しい線を再生成します。
これによって、
1.SPROUTを移動
2.SPROUT上で彼らはSHIFTになるのでSPROUTと線を中央に押し出す
3.押し出された線を盤面側にTELEで飛ばす(盤面側のSTICKは浮いているので盤面側から物が逆流してこない)
4.彼らはカラになった頭上に線を再生成
(5.同じ向きの線を二個同じ場所に飛ばすと共食いで破壊して消す)
このような仕掛けで毎ターン入力可能なインターフェースが成立しています。
また、同じswordに見えるものは内部的には向きによって別オブジェクトです。それぞれ向きが固定してあって別の意味を持つようになっています(ルールテキストはSWORD, FLOWER, FENCE, LEAFとなっています)。

・・・ここまでで1000文字超えてるって本当ですか?この先100倍くらい分量ありますけど。
・・・ということでこの先ざっくり目で行きます。
実装のアイデアベースで書くのであとは動画と画像から気合で理解をお願いします。

3.線の意味など
・ヤジリンでは破綻をSKULLで表現し、ルール違反時に生成する。
・各向きのswordはそのマスの接続先の方向を表す。
・接続先が一つあるいは三つ以上で違反(盤面右上あたり)
・上↔下、左↔右を表す線が互いに向き合っていない場合は線が途切れているとみなす。向き合っているが接続先が1マスだけの場合も線が途切れているとみなす。(LONELY GROUPで表現)
・黒マスの隣接はもちろん違反

4.ループ系の判定
・白マス(タイル)にGHOSTがぶつかるとEYEを生成し、EYEを向いているタイル上の線はEYEを生成。
・EYEはタイルをEATしながら進んでいくのでGHOSTから線をたどるようにタイルが消えていく。同時にタイルに隣接しない(次のEYEを生成できない)EYEは消える。
・ループが一周するとそのループにはTILEが残っていないためEYEが生成されなくなるが、EYEが残っていないのにタイルが残っている場合はそのタイルを小ループとみなす。

この、「次のEYEを生成できない(=その位置から発見できる新たな白マスなどのつながりのない)ものから消えていく」、とう考え方をひとつながりパズルのルール判定でも使用します。最初の起点となるマスをまず一つ見つけ、そこから辿っていけない場所があれば分断している、という考え方です。
ヤジリンの場合は白マスだけでなく線の向きも追加で判定しています。


5.数字
 数字は矢印の効果で矢印の方向をSHIFTで向くが、STILLによって位置固定。
判定時にはSTILLを消し、矢印の方向に歩いていく。
黒マスに乗るたびカウントダウンし、0で黒マスにのったり1以上残って壁に乗った場合には数字不整合とみなす。
(数字) SEEING PIXEL AND PIXEL AND ... AND PIXELのようにして数字を表現することもできますが、まぁどっちでもいいです 。数字を歩かせる方がカウント方法として汎用性が高いくらいだと思います。(移動させるとカウント条件を移動先のマスで逐一判定できる)

ヤジリンはこれだけです。簡単ですね。盤面右上でルール文を動かしていますが、動作の軽量化のためだけで特に意味はないです。


2.ぬりみさき


今回作成したぬりみさき盤面は下の画像になります。
レベルコード:D78-C2P3
プレイ動画はこちら。puzz.linkの問題はこちら

無題3

 問題の方を作りながら思ってんですけど、ぬりみさき10*10で外周ヒントのみの時、唯一解になるヒント数字の合計最小値ってどれくらいまで減るんでしょうか。これってトリビアになりませんか?(外周数字なしみさきは制約がむしろ減る傾向にあるのでカウントしない)

 ぬりみさきの分断禁や数字まわりのルールも基本的にはヤジリンと同じ考え方で作ります。
 ヤジリンにおける白マス発見者のGHOSTはこの盤面ではITになります。ぬりみさきでは上から3行目までに必ず白マスがあるので、JIJIとMEがTELEで次の行に飛ばしてくれることで必ず見つかります。必ず3行目までにある、というのは、黒マス2*2禁によって上2行にはみさきが一つ以上あり、それを3行目以降につなぐ白マスが必ず3行目までにはある、ということです。(今回はみさきを白マスとは別に扱っているため、極小サイズの盤面ではこの白マス判定ロジックは機能しないです。面倒だったので実装しませんでした)
 また、白マスにあたるROADはMOREで増やしていませんが、これは制御が面倒だからです。指定したマスだけ変えればそれで充分です。

 数字については盤面の工夫を解説。下側の氷部分がほぼ数字ルールです。基本的には5 is 5のような形で固定し、判定時だけこれをずらすことで 5 is 4 is 3 is 2 is 0と歩きながらカウントダウンさせ、数字が残っているのに白マスを向いていない、数字が0なのに白マス(タイル)を向いている、といった場合に破綻として判定しています。

 一番左上の緑背景部分が基本ルール、その下の氷部分がみさきの周囲白マス数指定や表出がないマスのみさき禁を表します。黒マス(CLIFF)と壁(CLOUD)を並列に扱うようなことはできないので、判定時にはCLOUDに一時的に黒マスを作ってもらい、終わったら消えてもらいます。並列に扱えないというのは、CLIFF AND CLOUD IS GROUPのようなルール文を作ったときGROUP IS Xという文はA OR B IS Xではなく A AND B IS Xを表します。つまり、「黒マスまたは壁が周囲に3つ」というみさきの制約を表す際にGROUPは使えません。

 2*2禁の判定は複雑ではないですがちょっと時間がかかります。注目したい領域を順に走査していって2*2禁になっていないか調べていく必要があります。2*2サイズにいるBABAが盤面を走査し、黒マスの上と白マスの上で別のサイン(ここではLAVAとWATER)を作り出します。壁際にいないBABAは同時にEYEを作り、EYEが二種類のサインのそばにいなければ破綻、という仕掛けになります。2*2のbabaのうち、一体でも壁際にいなければ判定のEYEを作るので盤面のどこでもうまく機能します。当然のことながら判定用アイテムたちはbabaが上からいなくなると順に消えます。

 さて、盤面を走査するためには壁に行き着いたBABAを次の行に飛ばしていく必要があります。そのため、飛ばしてくれるJIJIとMEも一緒に下に降りていく必要があります。ここでは、BABAが次の行に来たのをFOFOが視認すると下る→それを検知したMEが下る→それを検知したJIJIが下る、という手順になっています。横幅3以上あればMEとJIJIの移動時間ラグをBABAは追い越さないために十分なのでこのやり方は盤面サイズを問わないです(そもそも3行以下のサイズなら1回以下の飛ばしで十分なので下りが間に合う必要はなく、また、横幅3以下で縦に長い盤面を用意したとしても盤面の縦横を入れ替えれば飛ばし一回の適用条件を満たす)。 TELEの媒体を全行分用意するのはナンセンスな感じがするのでやりませんでした。(それとオブジェクト種類数制限の足枷になります)

 あとはそれぞれの判定が終わったタイミングで次に進めるように右下あたりで組まれています。

 ぬりみさきはこのくらいでしょうか。多少の工夫はありますが当然の一手という感じの流れではありますね。


3.へやわけ

今回作成したへやわけ盤面は下の画像になります。
レベルコード:41I6-M814
プレイ動画はこちら。puzz.linkの問題はこちら。結構難しい気がします。

画像3

今回領域を表すための要素には矢印を使用しています。指示先の境界に線があるとみなします。(後で出すLITSのように色分けで部屋の境界線を表現して矢印をHIDEで隠すようなこともできますが、今回は内部的なルールの見た目そのままにしています。ちょっとみにくいですが)
1*1のへや+数字とかを作ると初期盤面でタイルを置けない(初期オブジェクトの重なりは三つまで)のですが、初手MAKEでタイルを生成すれば問題ないです。

 ひとつながりと黒マス隣接禁はここまであった通りです。特に新しく解説することはありません。

 3連禁の解説をします。MEと下にいるWORMは黒マスの上にいるか黒マスが目の前にある状態以外で境界線を表す矢印に向き合うと進化します。MEは緑の右矢印、WORMはオレンジの下矢印で進化します。進化したあとに黒マスに乗ると元に戻ります(REVERT)。進化を2回連続で行うと破綻とみなします。形にしてしまえば簡単ですね。盤面下側で数字の上にある長いルール文がこれです。
 次にへやの黒マス数カウントの解説をします。ここでは不定形へやわけのようなものを考えず、部屋が長方形の場合のみを考えます。(ぬりわけを行えばLITSの項で後述する方法で不定形でもできます。)
 ざっくりいうと上に行くまで黒マスを移動、壁か下矢印にぶつかったら左に移動して緑矢印にぶつかるまで移動することで数字に重なる、といった仕掛けで領域内の黒マスを全て集めてカウントします。数字がなければそこで停止します。緑矢印は左を向いている時だけ(浮いているORBを見ている時だけ停止判定に使用されます(上に向かっているときに緑矢印の上を突き進む際は無視します。
 黒マスのカウントの方法ですが、OPENとSHUTを利用します。baba is youでOPENとSHUT以外のものを消すようなルールは、個数を無視して重なっていれば消しますが、OPENとSHUTは重なっている数だけ動作するので集めている途中で黒マスが重なることを気にせずに済みます。数字は全てSHUTされており、一度OPENされるたびにに一つ下の数字に減り、、0なのにさらにOPENされると破綻となります。(7 has 6 has 5 has... のようにして消えた際に現れる次の数字を表現)。
 どうでもいい余談ですがbaba上で数の性質を持つはオブジェクトはないのでペアノの公理の感じで帰納的に数字を表現するしかないです。見た目が数字のものはGROUPの識別記号として使えるくらいで大した意味はないということです。コンパクトに二進法を導入できればもう少し大きい数字のパズルも表現できるのかもしれませんが、今のままでは厳しいですね。(知識なしでヒエログリフの大きい桁数を表す数字を見せられても理解できないのと同じように、baba is youでもルール判定システムは数字の概念を理解していないため、何かしらの定義と使い方を与えて数字を表現してやる必要があります。)

 もっとどうでもいい余談。盤面がスカスカで余ったので右側で遊びました。BABA is NOT WONDERがすべてを悟ったbaba感があって好きです。

4.LITS

 さて、ここまではただのウォーミングアップでこのLITSが本記事のラスボスです。盤面もルールも理解できないかもしれないです。盤面を作者以外に理解できる気がしないです。そもそもルール文とオブジェクトが重なりすぎて読めないです。概要は説明するのでここまで説明した知識も総動員して理解したい人は理解しましょう。バグがあったりするのでちょいちょい自分でも理解しきれていないところがあります。

今回作成したLITS盤面は下の画像になります。
レベルコード:TR4J-9UEL
プレイ動画はこちら。puzz.linkの問題はこちら。難しいかも。
バグが残っているところがあるので動画はまた上げなおします。概要は変わらないです。

無題2

前知識
 この盤面のルールを理解するうえで4色定理が重要です。色分けで領域の境界を表現している以上に解答判定と盤面のサイズ的に大きな意味があります。ルール文は全体として色分けた領域を一領域ずつ順番に処理していく構造なのですが、4色塗分けに必要なので4色分同じルールを用意する必要があります。一つのことを表現するためだけにいちいち幅を取るといえば幅を取りますが、逆に言えば4色あれば十分なのでそれ以上は必要ないのです。5色だったら無理でした。

解説
1.形状判定のための動作
1-1.盤面走査と領域内の黒マス位置判定
 動作の順番で記載します。ぬりみさきの2*2禁で使った走査機構を使って領域を走査していきます。走査は左下2行分くらいに書いてあります。領域に2*2禁があれば破綻は変わりませんが、もう一つ役目があります。走査役のHANDと一緒に一つSHOVELがあり、SHOVELが到達したことのない区画に入ると、その領域内にshift効果のある物体X(その色の領域専用)を展開します。物体Xが黒マスに相当するPIXELに乗るとPIXELが発火し、領域内の物体をSHIFTでSHOVELの根元まで回収していきます。回収が終わるとすべての領域内PIXELが発火したとみなして形状判定を行います。(回収は到達より必ず後です。)ここまでの機構が動いている間、FLAGで走査を足止めします。回収が終わったのを合図に足止めのFLAGを破壊して再度走査を開始します。

1-2.黒マス位置判定時に使用するSHIFT効果オブジェクトの概要
 SHIFT効果を根元のSHOVELに向けるため、初期盤面でぬりわけに使ったオブジェクトは必ず隣接した物体Xの方向を向くようにしておきます。4色定理のおかげで、その領域にその時展開された物体Xの方向を必ず向き、あらぬ方向に向くことがありません。向きを変更した後で色分け自体に物体Xを作らせることで、必ず色分けオブジェクトの作った物体Xは伸びてきた根元側を向くことになります。

 基本的にここまでは盤面左上あたりのエリアに書いてあります。また、回収すべきでないPIXELなどの位置を固定するため、盤面のあちこちに固定用の文章がちりばめられています。

1-3.領域内での黒マス同士の隣接数/周囲の黒マス数を使った形状判定
 形状判定は隣接数などを使って判定します。このとき発火したPIXEL数が3個以下の場合を判定して破綻の判定を出しておきます。5個以上はスペース不足のため後で判定します。もし盤面に十分余裕があればへやわけで説明した機構を使って判定できます。(スペースの最適化が途上なので盤面変えれば収まる気もします。)形状判定を区画別で順番に行うことで隣接領域の情報との混同を防ぎます。形状判定が盤面右上あたりに書いてあります。

1-4.ひとつながりや同形禁判定の起点設置
 HANDの走査と同時に、LAMPが初めて到達したPIXELの上に置いて行かれます。同形判定やひとつながり判定の起点にLAMPを使用します。


 ここまで+LITSの10*10で盤面が四分の三くらい埋まってるのでカツカツです。ここからひとつながりや同型隣接禁があるというのに。

2.同形隣接禁判定+ひとつながり判定+盤面の空き不足の解決
2-1.同形隣接禁とSHIFT機構
 2*2禁走査と形状判定が終わると、右下のSWORD付近のぐるぐるSHIFT機構が動きます。この機構によってLAMPのある黒マスを起点に区画ごとに形状判定を行います。流れとしては、
A.区画内の隣接する黒マスの位置を確認(4ターン)
B.成長し終わったら4ターン使って各方向の別エリア隣接マスに同型がいないかを回転しながら確認(4ターン)
というABABを繰り返す流れで動きます。区画毎の黒マスは4マス以下、確認方向は上下左右の4つなので最低4ターン以上の時間のローテーションで機能します。右下のBAT(TELE)+KEKE(SHIFT)で対象判定を示すテキストをぐるぐる入れ替えつつ、左下のKEKEとJIJIが向き合ったエリアで同型判定を行っています。黒マス位置の確認中に判定を行わないための調整でITとKEKEとJIJIがいい感じにかみ合ってSHIFTするようになっています。

2-2.盤面の空き不足の解決
 さて、次にひとつながりの判定を行いたいですが。既にマスが残っていないです。(実際作成中ここで空きマスが消えました。)しかも前項で黒マスの位置確認に使っているCRYSTALは予想できないタイミングで成長が止まるため、CRYSTALをぬりみさきやへやわけで使ったひとつながり判定には流用できません。
どうしたらよいのでしょうか、困ってしまいました。
全部技術的に可能なのにテキストをこれ以上置けません。
一応ファイルをいじれば無理やり盤面を拡張できるらしいですが、やりたくありません。

・・・

悩んでいた時、天啓がおりてきました。
「テキストを置くマスがないなら今あるテキストを使えばいいのですよ」
全てを悟った私はKEKE-JIJI-IT-ぐるぐるSHIFT機構をつかって盤面を再構築することに決めました。作りたいルールを成立させるために必要な情報を考えてうまくルール文の配置を変えながら詰め、不要なルールが成立しないようにし、邪魔なテキストを破壊し、テキストを押すメンバーをテキストの下に配置し・・・そしてできました。

2-3.ひとつながり判定の構築
 流れはこうです。まず、つながりの基準点となってきたLAMPをテキストの数が多くて使いやすいFIREに変えます。FIREにかかる形状判定の余分なルールも消します。そしてFIREの位置からFOOTがひとつながり判定を行う成長を行うように中央上の文章を組み替えます。もともとは2*2禁のために複数を近くに用意していたFOOTのテキストです。ひとつながり判定をする侵食成長の終わりの判定はできませんでしたが、ぐるぐる機構を使って十分な時間を稼ぐことができます。十分な時間を稼いだ後、FOOTに侵食されていないエリアがあれば分断とみなします。このあたりの組み替えは全て中央上から右側にかけて作成されています。

2-4.同形隣接禁判定終了の確認
 同形隣接禁の判定は隣接するエリアを続けてチェックするわけではなく、色分けごとにループしてチェック済み領域に隣接していればチェックが走るという方式のため、かなり時間がかかります。これが終わるのを判定するために、ひとつながり判定が終わったあとに同型判定チェックの終わったPIXELを破壊していきます。これには同形判定済みの目印として成長していくCRYSTALに対して、CRYSTAL EAT PIXELを成立させることでPIXELを破壊していきます。すべてのPIXELが破壊し終わった時点で同形判定が終了したと判定して次の段階に進みます。

2-5.破壊的再構築PART2+1エリア5黒マス以上禁止判定
 分断禁→同形隣接禁の判定が終わると、PIXELが破壊し終わるのでそれをトリガーにして再びルールの組み替えが走り出します。(盤面中央あたりでCLOCK WITHOUT PIXEL IS SINKが組み上げられています。)
 最初に残していた同一エリア5黒マス以上禁止、これを行うため、同形隣接禁の判定のために生成して動かないように固定されていたCRYSTALの固定を解除します。これを各区画の根本にある緑色のCARTのもとに集め、5個以上重なれば禁止と判定します(もともとこの緑色のカートはSHIFT効果のある物体Xが根元で動作しないようにするための目印でした)。あとは5個以上の重なり禁止を左下で組み上げれば・・・これで誤答チェックがすべて終わりました。

2-6.最終正解判定
 あとはLEVELをWINさせるだけです。時間稼ぎに使った機構のあたりに空きマスが少しあったのでそこにWINを置き、時間稼ぎの流れの中でWINが成立するようにしました。そして、左下に、時間がたつとWINを甘受するFIREを操作キャラにする動き(FIRE IS YOU)を作り、FIREが途中で別のものに変わらないようにするためのFIRE IS FIREを右上で作り・・・ついにレベルクリアとなりました。LITSの正解判定の長い道のりが終わりました。

5.終わりに
 

 やっと解説が終わりました。全部読んでる人っているんでしょうか?長すぎてダレますよね。
 ここまでのことができるのですから複雑な形状判定などを要求されない限り大体のペンシルパズルの正当判定はBABA IS YOUで実現できそうです。作っていないだけであれはこうできるだろうというのは色々思いつくところ。例えばぬりかべは殆どLITSと同じ仕掛けの回収機構とへやわけのOPEN-SHUTカウント機構と2*2走査機構でできます。LITSより簡単ですね。CAVEのように4方向のマス数を数えるときは、行きで数えて帰りは数えないで、根元で向きを変えて移動して数えて、を繰り返す機構を作ればいいわけです。これはそれぞれのヒントマス起点でチェックできるのでヒントマス起点にやればいいので走査不要です。TAPA型のルールはヒントマスの周囲に領域展開し、それをなぞるように歩きながらカウントする機構を作ればできます。FOLLOW文の向き変更の性質を使えばよさそうです。

 BABA IS YOU は何でもできてすごい。
 みなさんも気が向いたら自分の好きなパズルの正当判定のできる仕組みを作ってみてはいかがでしょうか?

 ここまで読んでくれたり、パズルを解いてれたり、動画を見てくれたり、ありがとうございました。本当はもっといろいろ書きたいことがあったのですが。今回はこれでこの記事は終わりです。

この記事が気に入ったらサポートをしてみませんか?